Cantr Enhanced

Some useful enhancements: events grouping and coloring names, objects grouping, clean objects list, buildings&vehicles highlighting

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name          Cantr Enhanced
// @namespace     http://www.cantr-mmorpg.pl/scripts
// @description   Some useful enhancements: events grouping and coloring names, objects grouping, clean objects list, buildings&vehicles highlighting
// @include       http://www.cantr.net/*
// @include       http://cantr.net/*
// @include       https://cantr.net/*
// @include       https://www.cantr.net/*
// @include       cantr.net/*
// @include       http://test.cantr.net/*
// @grant         none
// @exclude       http://cantr.net/*?page=login*
// @include       www.cantr.net/*
// @version       2.5.0
// ==/UserScript==

var VER = '2.5.0';

/*

version 2.5.0
 - make CE work after the major layout changes

version 2.4.0b
 - nothing changes, it's just made available on greasefork instead of dead userscripts

version 2.4.0
 - CE options available again on player page

version 2.3.0
 - compatibility with new events page changes

version 2.2.0
 - removed [all] button for objects&inventory pages

version 2.1.0
 - support for Finnish characters
 - buildings&vehicles bookmarks works again
 - removed grouping of vehicles by type (it's already done by the game)

version 2.0.0
 - ajax based object taking/dropping
 - fixed operations on many notes for taking notes from envelope

version 1.8.5
 - most of modules now work for Spanish and German characters, but interface is not translated

version 1.8.3
 - whisper receivers list is remembered between page loads
 - name on receivers list is updated when changing character name using ajax char renaming

version 1.8.2
 - fixed bug with renaming chars on events page

version 1.8.1
 - fixed bugs from 1.8.0
   - it's possible to submit text on events page using [ENTER]
   - on chrome works significantly faster
   - removing character from whisper list no longer causes issues

version 1.8.0 UNSTABLE
 - events page performance fix
 - added ajax whisper on events page
 - added rename character on events page
 - added line which shows unread events (when browser was not focused)
 - it's easier to select English language in CE options
 - removed summer time, because server will always use UTC
 - removed unused features (note preview, repair time autofill, object labels)

version 1.5.1
 - added https support

version 1.5.0
 - added import/export of private settings to text in CE options

version 1.4.1
 - events grouping a bit faster
 - change in Portuguese translation

version 1.4.0
 - fixed "select language" box on the player page

version 1.3.01
 - fix for turn time left

version 1.3.0
 - works with new cantr appearance
 - "talk to" popup works again

version 1.05.0
 - fixed notes checker, because I need it

version 1.00.5
 - fixed buildings and vehicles bookmarks

version 1.00.0
 - object and inventory pages things adjusted to new inventory and objects page

version 0.99.7
 - fixed "last 4 digits of char id" function, now character related data is saved properly

version 0.99.5
 - repair time autofill revived

version 0.99.0
 - script is revived

version 0.98.0
 - script is dead, managed to revive events page options

version 0.97.0
 - some events-related things works, events filtering will be provided by the game. Autorefreshed events are not coloured etc.


version 0.92.0
 - notes checker bugfix

version 0.90.0
 - options are on the main page, not in shop (which will be deleted soon)

version 0.79.0+1
 - take and drop all ultimate (+0.0.1 max amount to take bugfix)

version 0.76.0
 - names colors (+0.01 bugfix) (+0.02 names shortening + lesser opacity of names)

version 0.75.0
 - popup talk button on the events page (language independent)
 - new (autorefreshed) events are filtered by the script

version 0.70.32
 - roll die PL and tiny bugfix (destructive objects pulling)
 - bum bum, calculator bugfix (after some changes suggested by ProgD)
 - moar pretty [max] buttons when taking/giving resources

version 0.70.1
 - grouping events misc bugfix

version 0.70.0
 - grouping events SHOULD work for English (but I can't guarantee that)
 - summer time option in the Shop (disable it to have proper ticks information if something's wrong)

version 0.69.1
 - grouping events bugfix

version 0.69.0 
 - grouping events (works only for PL for now, very professional translation needed) i.e. (x drops y.", "x drops z." => "x drops y, z."

version 0.66.1
 - more quotations for Events Filter in English

version 0.66.0
 - language selection when you use that script first time
 - improved RegExp (most of them should work also on Opera)

version 0.60.0
 - objects list on the OBJECTS page
 - grouping objects (machines) on the OBJECTS page

version 0.59.0
 - (almost) works for German version
 - English version should work fine (except of events filter)

version 0.55.0
 - nothing (I just need better version number)

version 0.52.3
 - dynamic calculator is more dynamic now

version 0.52.1
 - display bugfix (description in options panel)

version 0.52.0
 - labels are now only for containers

version 0.51.4
 - some bugfixes
 - characters count when editing notes (unfortunately doesn't count regional characters as 2)

version 0.51.3
 - more minor bugfixes

version 0.51.2
 - some minor bugfixes

version 0.51.1
 - notes autochecking (all, none, duplicates, opposite)
 - name highlight in event filter bugfix (now script is searching for only first word of name)

version 0.50.1
 - clock bugfix (visible on every page)

version 0.50.0
 - clock improvement (instead of "remains 108:8 ..." there is "remains 1:48:08...")
 - replacement of "exits" panel on the "location" page
 - English translation (but not everything works fine - I don't have any English character to check some quotations)
 
version 0.49.0
 - dynamic clock with turn alert (but needs extra connection with Cantr Server, so it is visible that you are using it) - needs improve
 - bookmark favourites buildings and vehicles

version 0.48.1
 - critical bugfix - syntax error

version 0.48.0
 - dynamic clock (turn alert will be added soon)
 - some improvements
 - nice "enhanced" title next to "Cantr II" on the top

version 0.46.0
 - language selection in option "shop" page (but still works only pl - en needs translation)

version 0.45.0
 - possibility of adding new languages (though currently there is no option of changing language)

version 0.42.0
 - max button on "give resources" page

version 0.41.0 and 0.41.1 and 0.41.2
 - events filtering enhancement (more and more)

version 0.40.0
 - events filtering (wow!) (only PL, need fixes)
 - grouping bugfix (now titleBars are being shown only when there is at least 1 vehicle or ship)

version 0.36.1
 - when you set empty ("") string as a label of an object, the label is entirely removed

version 0.36.0
 - land vehicles and ships grouping on "Buildings and Vehicles" page (oonly PL)

version 0.35.0
 - dynamic amount of resources for projects needed (only PL)

version 0.3
 - options on "shop" page - you can enable or disable some functions (only PL)
 - labels on "put into container" page (only PL)

version 0.29
 - note preview on "edit note" page (only PL)

version 0.20 and older
 - labels for objects (PL and EN)
 - 'taking as much as you can' button om "pick up resources" page (only PL)

*/

	// stałe
	var MAXCAP = 15000; // udźwig maksymalny w gramach
	var NOTE_MAXLENGTH = 65535;
	var GROUPEVENTS_MAX_MIN_DIFF = 2; // amount of minutes between first and last grouped event possible
	

	var ln = getLanguage(); // language - will be en as default but not yet
	var lang = [];
	
	
	
	
	/*#############################
				LANGUAGES
	  #############################*/

	var activeText = [];
	var pageObjects = [];
	var pageInventory = [];
	var pageBuildingsAndVehicles = [];
	var pageBuildingsAndVehiclesInside = [];
	var pageEvents = [];
	var pageTakingInfo = [];
	var pageWriteNote = [];
	var pageShop = [];
	var pageStorageResources = [];
	var pageSelAmountToProject = [];
	var pageGiveResources = [];
	var pageRepair = [];
	var pageLocation = [];
	var pageEmptyEnvelope = [];
	var pageMainPage = [];
	var pageRetrieveFromContainer = [];
	
	
	
	
	
	/*
	POLISH
	*/
	lang['pl'] = [];
	
	// labels
	lang['pl']['setLabel'] = "[set]";
	lang['pl']['setPromptInfo'] = 'Podaj identyfikator dla tego obiektu';
	// max button - pick up resources
	lang['pl']['maxButton'] = 'max';
	// note preview
	lang['pl']['previewButton'] = '<b>[podgląd]</b>';
	lang['pl']['previewCharLeft'] = 'Pozostało znaków:';
	lang['pl']['previewExceedsLimit'] = 'UWAGA! LICZBA ZNAKÓW W NOTATCE PRZEKROCZONA!!!';
	// project size
	lang['pl']['timeInDays'] = 'Dokładny czas w dniach (w nawiasie realny): ';
	// ships and land vehicles grouping
	lang['pl']['groupingCheckBoxDesc'] = ' grupowanie pojazdów lądowych i morskich';
	lang['pl']['landVehicles'] = 'Pojazdy lądowe:';
	lang['pl']['ships'] = 'Statki:';
	// events filter
	lang['pl']['filters'] = '<b>Filtry:</b>';
	lang['pl']['sayFilter'] = 'rozmowy';
	lang['pl']['wichtigFilter'] = 'ważne';
	lang['pl']['whisperFilter'] = 'antyVlo'; // enabling and disabling whispers
	lang['pl']['radioFilter'] = 'radio';
	lang['pl']['travelFilter'] = 'podróż';
	lang['pl']['resourcesFilter'] = 'surowce';
	lang['pl']['tap_danceFilter'] = 'tuptanie'; // moving inside buildings, vehicles etc.
	lang['pl']['miscFilter'] = 'inne'; // everything else: hunting, eating...
	// ajax whisper
	lang['pl']['ajaxEventsToEveryone'] = 'Do wszystkich';
	lang['pl']['ajaxEventsWhisperButton'] = 'Szepcz';
	lang['pl']['ajaxEventsYouTalkingTo'] = 'Wybierz do kogo mówić:';
	// rename character on events page
	lang['pl']['eventsRenameChar'] = 'Podaj nowe imię dla postaci';
	// clock
	lang['pl']['clockTimeLeft'] = 'pozostało';
	lang['pl']['clockUntil'] = 'do';
	lang['pl']['clockTicksailing'] = 'przeliczenia podróży morskich';
	lang['pl']['clockTicktravel'] = 'przeliczenia podróży lądowych';
	lang['pl']['clockTickproject'] = 'przeliczenia projektów';
	// bookmark
	lang['pl']['bmVehTitle'] = 'WYRÓŻNIONE POJAZDY'; 
	lang['pl']['bmBuildTitle'] = 'WYRÓŻNIONE BUDYNKI'; 
	lang['pl']['bottomPanelCharacterMenu'] = 'MENU POSTACI'; 
	// "location" page's panels replacement
	lang['pl']['replaceLocationExits'] = 'WYJŚCIA';
	lang['pl']['replaceCheckBoxDesc'] = 'zamiana paneli';
	// notes checker
	lang['pl']['notesChbTitle'] = 'Autozaznaczanie notatek';
	lang['pl']['notesChbAll'] = 'wszystkie';
	lang['pl']['notesChbNo'] = 'żadne';
	lang['pl']['notesChbDupl'] = 'duplikaty';
	lang['pl']['notesChbOpp'] = 'odwrotność';
	// list objects
	lang['pl']['listObjectsTitle'] = 'LISTA';
	lang['pl']['listObjectsNotesCB'] = 'notatki';
	lang['pl']['listObjectsResourcesCB'] = 'surowce';
	lang['pl']['listObjectsOthersCB'] = 'inne';
	// group objects
	lang['pl']['groupObjectsUsedFirst'] = '<i>(używane ';
	lang['pl']['groupObjectsUsedOf'] = ' z ';
	lang['pl']['groupObjectsUsedEnd'] = ')</i>';
	// language selection
	lang['pl']['langSelectionTextBefore'] = 'Wybierz język. Wystarczy wybrać go z listy i odświeżyć stronę, a zostanie on zapisany na stałe.';
	lang['pl']['langSelectionTextAfter'] = 'Jeśli zechcesz zmienić później język skryptu lub wyłączyć niektóre moduły skryptu to znajdziesz tę możliwość na stronie "SKLEP"';
	
	
	// other
	lang['pl']['shipNames'] = ['łódka', 'darter', 'dłubanka', 'prom', 'trzcinowa łódź', 'łódź wiosłowa', 'galeon', 'szabrownik', 'slup', 'tratwa', 'długa łódź', 'szkuner', 'kajak', 'soarer']; // MUST BE LOWERCASE
	lang['pl']['itemNote'] = 'notatka';
	lang['pl']['itemEnvelope'] = 'Koperta';
	lang['pl']['grams'] = 'gram';
	lang['pl']['pieces'] = ' sztuk ';
	lang['pl']['optionsButton'] = 'opcje Cantr Enhanced';
	lang['pl']['groupObjectsInUse'] = ' <i>(w użyciu)</i>';

  // since 2.1
  lang['pl']['vehCategoryLandVehicles'] = 'POJAZDY LĄDOWE';
	lang['pl']['vehCategoryShips'] = 'STATKI';
	lang['pl']['vehCategoryConstructions'] = 'KONSTRUKCJE';
	lang['pl']['categoryBuildingsOutside'] = 'BUDYNKI';
	lang['pl']['categoryBuildingsInside'] = 'POMIESZCZENIA';
		
	// events grouping - be careful, it's quite hard to translate
	 lang['pl']['groupEventsSbUse'] = />(?:.*)>(.*) używa(?: trochę)* (.*)( na )(.*)/;
	lang['pl']['groupEventsSbHunt'] = />(?:.*)>(.*) zwierzę znane jako (.*)(, używając )(.*)/;
	lang['pl']['groupEventsSbPoke'] = />(?:.*)>(.*) szturcha (.*)\./;
	lang['pl']['groupEventsSbTake'] = />(?:.*)>(.*) bierze (?:trochę )*(.*)\./;
	lang['pl']['groupEventsSbDrop'] = />(?:.*)>(.*)(?: upuszcza | odkłada )(?:trochę )*(.*)\./;
	lang['pl']['groupEventsSbGive'] = />(?:.*)>(.* podaje do .*)> (?:trochę |coś wyglądającego jak )*(.*)\./;
	lang['pl']['groupEventsSbDragRes'] = /(Widzisz,* że ktoś przeciągnął )(?:trochę )*(.*)()( z centralnego obszaru .* do .*| z <.* do .*| do .* z .*)/;
	lang['pl']['groupEventsSbThrowDie'] = /(Widzisz, że .* rzuca czymś wyglądającym jak .*\.)( Wypada )(.*)\./;
  lang['pl']['groupPreEventsYouSay'] = 'Mówisz';
  lang['pl']['groupPreEventsSbSay'] = ' mówi:';
  lang['pl']['groupPreEventsSbWhisper'] = ' mówi do ';
  lang['pl']['groupPreEventsSbUse'] = ' używa ';
	lang['pl']['groupPreEventsSbHunt'] = 'zwierzę znane jako';
	lang['pl']['groupPreEventsSbPoke'] = ' szturcha ';
	lang['pl']['groupPreEventsSbTake'] = ' bierze ';
	lang['pl']['groupPreEventsSbDrop'] = '';
	lang['pl']['groupPreEventsSbGive'] = ' podaje do ';
	lang['pl']['groupPreEventsSbDragRes'] = ' że ktoś przeciągnął ';
	lang['pl']['groupPreEventsSbThrowDie'] = ' rzuca czymś wyglądającym jak ';
	
	
	// options on "shop" page (enabling and disabling options, language change etc.)
	lang['pl']['optionsTitle'] = "<i>Cantr Enhanced v. " + VER + " - PANEL KONFIGURACYJNY </i> <br><br>";
	lang['pl']['optionsLabel'] = "etykiety dla obiektów w zakładkach OBIEKTY oraz INWENTARZ";
	lang['pl']['optionsNotePre'] = "podgląd edytowanej notatki";
	lang['pl']['optionsAllButt'] = "przycisk podnoszenia i podawania\"ile się da\"";
	lang['pl']['optionsIntoContainer'] = "etykiety dla pojemników na stronie WŁÓŻ SUROWIEC DO POJEMNIKA";
	lang['pl']['optionsProjectSize'] = "dane co do ilości potrzebnych surowców generowane (mądre słowo) w czasie rzeczywistym (jeszcze mądrzejsze)";
	lang['pl']['optionsGroupBuildingVehicles'] = "grupowanie pojazdów lądowych i morskich na stronie BUDYNKI I POJAZDY";
	lang['pl']['optionsEventsFilter'] = "filtrowanie zdarzeń";
	lang['pl']['optionsGroupEvents'] = "grupowanie zdarzeń (wymaga włączonego filtrowania)";
	lang['pl']['optionsColorNames'] = "kolorowanie imion (wymaga włączonego wyskakującego okienka rozmawiaj (tm))";
	lang['pl']['optionsShortNames'] = "skracanie nieznanych imion (np. dwudziestoletni mężczyzna -> dwudziestolatek)";
	lang['pl']['optionsClock'] = 'ruchomy zegarek i powiadamianie o turach';
	lang['pl']['optionsSummerTime'] = 'czas letni (dostosuj do cantryjskiej rzeczywistości)';
	lang['pl']['optionsPopupButtons'] = 'Wyskakujące okienko rozmawiaj<s>/przeciągaj/atakuj</s> na stronie zdarzeń (wymaga włączonego filtrowania)';
	lang['pl']['optionsClickInsteadOfHover'] = 'Klikanie na imię postaci zamiast najechania na nie (uniemożliwia korzystanie z linka w imieniu)';
	lang['pl']['optionsAjaxWhisper'] = 'Szeptanie na stronie zdarzeń jak "Mów do wszystkich" (AJAX). Wyskakujące okienko "Rozmawiaj" musi być włączone';
	lang['pl']['optionsBookmarkBuildingsVehicles'] = 'wyróżnione budynki i pojazdy';
	lang['pl']['optionsLocationPanelsReplacement'] = 'zamiana kolejności paneli w stronie Miejsce';
	lang['pl']['optionsNotesCheckBox'] = 'autozaznaczanie notatek na stronach OPERACJE NA WIELU NOTATKACH i OPRÓŻNIJ KOPERTĘ';
	lang['pl']['optionsListObjects'] = 'wysuwalne menu na dole strony OBIEKTY, wyświetlające listę obiektów do skopiowania';
	lang['pl']['optionsGroupObjects'] = 'grupowanie maszyn tego samego typu w zakładce OBIEKTY';
	lang['pl']['optionsTakeAllUltimate'] = 'przycisk podnoszenia wszystkiego na stronie obiektów';
	lang['pl']['optionsLineEventsNotFocused'] = 'linia pokazująca zdarzenia wyświetlone gdy przeglądarka była nieaktywna';
	lang['pl']['optionsCharMenuToolbar'] = 'Przyciski menu postaci (buduj itp) po prawej stronie głównych okien';
	
	// QUOTATIONS
	/*
	!!!CAUTION!!! Remember that you shouldn't translate this text, but check how it is named in your language - no mistakes allowed or script will not load
	*/
	
	// most important quotation
	activeText['pl'] = 'graczy było aktywnych w ciągu ostatnich 15 minut.';
	
	pageObjects.push('OBIEKTY'); // opened objects panel titlebar
	pageInventory.push('INWENTARZ'); // opened inventory panel titlebar
	pageBuildingsAndVehicles.push(lang['pl']['vehCategoryLandVehicles']);// opened vehicles panel titlebar
	pageBuildingsAndVehicles.push(lang['pl']['vehCategoryShips']);
	pageBuildingsAndVehicles.push(lang['pl']['vehCategoryConstructions']);
	pageBuildingsAndVehicles.push(lang['pl']['categoryBuildingsOutside']);
	pageBuildingsAndVehiclesInside.push(lang['pl']['categoryBuildingsInside']);
	pageEvents.push('ZDARZENIA'); // opened events panel titlebar
	pageTakingInfo.push('INFORMACJA O ZABIERANIU'); // page where you type how much resources do you want to pick up
	pageWriteNote.push('NAPISZ NOTATKĘ'); // write note page
	pageShop.push('EKSTRA CZAS ZA KREDYTKI'); // shop page (credits etc)
	pageStorageResources.push('PRZECHOWYWANIE SUROWCÓW'); // how much resources do you want to put into container
	pageSelAmountToProject.push('WYBIERZ ILOŚĆ DO TEGO PROJEKTU'); // when you create project and you type how much do you want to get (in projects like refining iron ore)
	pageGiveResources.push('INFORMACJA O DAWANIU'); //  how much resources do you want to give to sb
	pageRepair.push('Naprawa - '); /*  de on pageGiveResources - because there are two pages with similar name */
	pageLocation.push(': OPIS'); // how to recognise LOCATION page? :D
	pageEmptyEnvelope.push('OPRÓŻNIANIE KOPERTY');
	pageMainPage.push('PROFIL GRACZA');
	pageRetrieveFromContainer.push('POZYSKAJ ZE SKŁADU');
	
	/*
	ENGLISH
	*/
	
	lang['en'] = [];
	
	// labels
	lang['en']['setLabel'] = "[set]";
	lang['en']['setPromptInfo'] = 'Insert identifier of this object';
	// max button - pick up resources
	lang['en']['maxButton'] = 'max';
	// note preview
	lang['en']['previewButton'] = '<b>[preview]</b>';
	lang['en']['previewCharLeft'] = 'Characters left:';
	lang['en']['previewExceedsLimit'] = 'WARNING! NOTE CAPACITY REACHED!!!';
	// project size
	lang['en']['timeInDays'] = 'Strict time in days (real in brackets): ';
	// ships and land vehicles grouping
	lang['en']['groupingCheckBoxDesc'] = ' grouping of land vehicles and ships';
	lang['en']['landVehicles'] = 'Land vehicles:';
	lang['en']['ships'] = 'Ships:';
	// events filter
	lang['en']['filters'] = '<b>Filters:</b>';
	lang['en']['sayFilter'] = 'talking';
	lang['en']['wichtigFilter'] = 'important';
	lang['en']['whisperFilter'] = 'whispers'; // enabling and disabling whispers
	lang['en']['radioFilter'] = 'radio';
	lang['en']['travelFilter'] = 'movement';
	lang['en']['resourcesFilter'] = 'resources';
	lang['en']['tap_danceFilter'] = 'in/out'; // moving inside buildings, vehicles etc.
	lang['en']['miscFilter'] = 'misc'; // everything else: hunting, eating...
	// ajax whisper
	lang['en']['ajaxEventsToEveryone'] = 'To everyone';
	lang['en']['ajaxEventsWhisperButton'] = 'Whisper';
	lang['en']['ajaxEventsYouTalkingTo'] = 'Who are you talking to:';
	// rename character on events page
	lang['en']['eventsRenameChar'] = 'Enter new name for a character';
	// clock
	lang['en']['clockTimeLeft'] = '';
	lang['en']['clockUntil'] = 'until';
	lang['en']['clockTicksailing'] = 'sailing tick';
	lang['en']['clockTicktravel'] = 'travelling tick';
	lang['en']['clockTickproject'] = 'projects tick';
	// bookmark
	lang['en']['bmVehTitle'] = 'BOOKMARKED VEHICLES'; 
	lang['en']['bmBuildTitle'] = 'BOOKMARKED BUILDINGS';
	lang['en']['bottomPanelCharacterMenu'] = 'CHARACTER MENU'; // bottom menu with buttons like create note, manufacture etc - must be exactly like panel in the game
	// "location" page's panels replacement
	lang['en']['replaceLocationExits'] = 'EXITS';
	lang['en']['replaceCheckBoxDesc'] = 'panels replacement';
	// notes checker
	lang['en']['notesChbTitle'] = 'Autochecker:';
	lang['en']['notesChbAll'] = 'all';
	lang['en']['notesChbNo'] = 'no';
	lang['en']['notesChbDupl'] = 'duplicates';
	lang['en']['notesChbOpp'] = 'opposite';
	// list objects
	lang['en']['listObjectsTitle'] = 'LIST';
	lang['en']['listObjectsNotesCB'] = 'notes';
	lang['en']['listObjectsResourcesCB'] = 'resources';
	lang['en']['listObjectsOthersCB'] = 'others';
	// group objects
	lang['en']['groupObjectsUsedFirst'] = '<i>(';
	lang['en']['groupObjectsUsedOf'] = ' out of ';
	lang['en']['groupObjectsUsedEnd'] = ' in use)</i>';
	// language selection
	lang['en']['langSelectionTextBefore'] = 'Select language. It is enough to select it from the list, refresh page and it will be saved.';
	lang['en']['langSelectionTextAfter'] = 'If you would like to change language in the future or disable some modules you can click on the text [Cantr Enhanced options] below.';
	// other
	lang['en']['itemNote'] = 'Note';
	lang['en']['itemEnvelope'] = 'Envelope';
	lang['en']['grams'] = 'grams';
	lang['en']['pieces'] = ' pieces of ';
	lang['en']['optionsButton'] = 'Cantr Enhanced options';
	lang['en']['groupObjectsInUse'] = ' <i>(in use)</i>';

  // since 2.1
  lang['en']['vehCategoryLandVehicles'] = 'LAND VEHICLES';
	lang['en']['vehCategoryShips'] = 'SHIPS';
	lang['en']['vehCategoryConstructions'] = 'CONSTRUCTIONS';
	lang['en']['categoryBuildingsOutside'] = 'BUILDINGS';
	lang['en']['categoryBuildingsInside'] = 'OTHER ROOMS';
	
	lang['en']['shipNames'] = ['raft', 'kayak', 'dugout canoe', 'reed boat', 'dinghy', 'rowing boat', 'sloop', 'darter', 'longboat', 'soarer', 'ferry', 'raker', 'skimmer', 'galleon']; // MUST BE LOWERCASE

	// events grouping - be careful, it's quite hard to translate
	lang['en']['groupEventsSbUse'] = />(?:.*)>(.*) use(?: some)* (.*)( on )(.*)/;
	lang['en']['groupEventsSbHunt'] = />(?:.*)>(.*) hurt (.*)( using )(.*)/;
	lang['en']['groupEventsSbPoke'] = />(?:.*)>(.*) poke (.*)\./;
	lang['en']['groupEventsSbTake'] = />(?:.*)>(.*) take (?:some )*(.*)\./;
	lang['en']['groupEventsSbDrop'] = />(?:.*)>(.*) drop (?:some )*(.*)\./;
	lang['en']['groupEventsSbGive'] = />(?:.*)>(.*) give (?:some )*(.*)( to )(.*)\./;
	lang['en']['groupEventsSbDragRes'] = /(You see )(?:some )*(.*)()( being pulled from .* to .*| being pulled to .*, coming from .*)/;
	lang['en']['groupEventsSbThrowDie'] = /doesn work/;
  lang['en']['groupPreEventsYouSay'] = 'You say';
  lang['en']['groupPreEventsSbSay'] = ' says:';
  lang['en']['groupPreEventsSbWhisper'] = ' talking to ';
  lang['en']['groupPreEventsSbUse'] = ' use ';
	lang['en']['groupPreEventsSbHunt'] = ' hurt ';
	lang['en']['groupPreEventsSbPoke'] = ' poke ';
	lang['en']['groupPreEventsSbTake'] = ' take ';
	lang['en']['groupPreEventsSbDrop'] = ' drop ';
	lang['en']['groupPreEventsSbGive'] = ' give ';
	lang['en']['groupPreEventsSbDragRes'] = ' being pulled from ';
	lang['en']['groupPreEventsSbThrowDie'] = ' roll a ';

		
	// options on "shop" page (enabling and disabling options, language change etc.)
	lang['en']['optionsTitle'] = "<i>Cantr Enhanced v. " + VER + " - Config panel </i> <br><br>";
	lang['en']['optionsLabel'] = "labels for objects on OBJECTS, INVENTORY pages";
	lang['en']['optionsNotePre'] = "preview of edited note";
	lang['en']['optionsAllButt'] = "\'take as much as you can\' button when picking up and giving resources";
	lang['en']['optionsIntoContainer'] = "labels on \'put resource into\' page";
	lang['en']['optionsProjectSize'] = "resources needed for a project calculator";
	lang['en']['optionsGroupBuildingVehicles'] = "grouping of land vehicles and ships on OBJECTS AND VEHICLES page";
	lang['en']['optionsEventsFilter'] = "events filtering (not 100% working)";
	lang['en']['optionsGroupEvents'] = "grouping events (events filtering must be enabled)";
	lang['en']['optionsColorNames'] = "name colors (popup talk window must be enabled)";
	lang['en']['optionsShortNames'] = "shortening names (i.e. a man in his twenties -> 20 year-old-man)";
	lang['en']['optionsClock'] = 'dynamic clock and turns notifier';
	lang['en']['optionsSummerTime'] = 'summer time';
	lang['en']['optionsPopupButtons'] = 'Popup talk window on the events page (events filtering must be enabled)';
	lang['en']['optionsClickInsteadOfHover'] = 'Click on character name instead of hovering (makes entering name link impossible)';
	lang['en']['optionsAjaxWhisper'] = 'Whisper form on events page like "talk to all" (AJAX). popup buttons must be enabled';
	lang['en']['optionsBookmarkBuildingsVehicles'] = 'bookmark buildings and vehicles';
	lang['en']['optionsLocationPanelsReplacement'] = 'replacement of panels on LOCATION page';
	lang['en']['optionsNotesCheckBox'] = 'autochecking notes on the "empty envelope" and "many notes operations"';
	lang['en']['optionsListObjects'] = 'menu on OBJECTS page which shows list of objects easy to copy/paste';
	lang['en']['optionsGroupObjects'] = 'grouping of machines of the same type on OBJECTS page';
	lang['en']['optionsTakeAllUltimate'] = 'take all button on the OBJECTS page';
	lang['en']['optionsLineEventsNotFocused'] = 'Line which shows events which took place when browser was not focued';
	lang['en']['optionsCharMenuToolbar'] = 'Charmenu buttons on right side of the screen on main game pages';
	
	
	// QUOTATIONS
	/*
	!!!CAUTION!!! Remember that you shouldn't write translated text, but check how it is named in your language - no mistakes allowed or script will not load
	*/

	// most important quotation
	activeText['en'] = ' users were active in the last 15 minutes.';
	pageObjects.push('OBJECTS'); // opened objects panel titlebar
	pageInventory.push('INVENTORY'); // opened inventory panel titlebar
	pageBuildingsAndVehicles.push(lang['en']['vehCategoryLandVehicles']);// opened vehicles panel titlebar
	pageBuildingsAndVehicles.push(lang['en']['vehCategoryShips']);
	pageBuildingsAndVehicles.push(lang['en']['vehCategoryConstructions']);
	pageBuildingsAndVehicles.push(lang['en']['categoryBuildingsOutside']);
	pageBuildingsAndVehiclesInside.push(lang['en']['categoryBuildingsInside']);
	pageEvents.push('EVENTS'); // opened events panel titlebar
	pageTakingInfo.push('TAKE INFO'); // page where you type how much resources do you want to pick up
	pageWriteNote.push('WRITE A NOTE'); // write note page
	pageShop.push('SHOPPING WITH CREDITS'); // shop page (credits etc)
	pageStorageResources.push('STORE RAW MATERIAL'); // how much resources do you want to put into container
	pageSelAmountToProject.push('SELECT AMOUNT FOR THIS PROJECT'); // when you create project and you type how much do you want to get (in projects like refining iron ore)
	pageGiveResources.push('<B>GIVE INFO</B>'); //  how much resources do you want to give to sb
	pageRepair.push('Repairing'); /*  de on pageGiveResources - because there are two pages with similar name */
	pageLocation.push(': DESCRIPTION'); // how to recognise LOCATION page? :D
	pageEmptyEnvelope.push('EMPTY ENVELOPE'); // when taking notes out of envelope - titlebar
	pageMainPage.push('PLAYER INFO');
	
	
	/*
	DEUTSCH
	*/

	// QUOTATIONS
/*
	!!!CAUTION!!! Remember that you shouldn't write translated text, but check how it is named in your language - no mistakes allowed or script will not load
	*/
	
	lang['de'] = [];
	
	// other
	lang['de']['itemNote'] = 'Zettel';
	lang['de']['itemEnvelope'] = 'Briefumschlag';
	lang['de']['grams'] = 'Gramm';
	lang['de']['pieces'] = 'Stück';
	lang['de']['shipNames'] = ['floß', 'fellboot', 'einbaumkanu', 'schilfboot', 'jolle', 'ruderboot', 'slup', 'darter', 'langboot', 'soarer', 'fähre', 'raker', 'skimmer', 'galleone']; // MUST BE LOWERCASE
	lang['de']['groupObjectsInUse'] = ' <i>(wird benutzt)</i>';

  // since 2.1
  lang['de']['vehCategoryLandVehicles'] = 'LAND VEHICLES';
	lang['de']['vehCategoryShips'] = 'SHIPS';
	lang['de']['vehCategoryConstructions'] = 'CONSTRUCTIONS';
	lang['de']['categoryBuildingsOutside'] = 'BUILDINGS';
	lang['de']['categoryBuildingsInside'] = 'ANDERE RÄUME';
	
	// events grouping - be careful, it's quite hard to translate
	lang['de']['groupEventsSbUse'] = />(?:.*)>(.*) (?:ein\/einen|etwas) (.*)( für )(?:das Projekt )*(.*) (?:benutzen|verwenden)\./;
	lang['de']['groupEventsSbHunt'] = />(?:.*)>(.*) (?:ein|eine|einen) (.*)( mit )(.*) verwunden\./;
	lang['de']['groupEventsSbPoke'] = />(?:.*)>(.*) ein\/einen (.*) stoßen\./;
	lang['de']['groupEventsSbTake'] = />(?:.*)>(.*) (?:etwas )?(.*) nehmen\./;
	lang['de']['groupEventsSbDrop'] = />(?:.*)>(.*) etwas (.*) fallen lässt\./;
	lang['de']['groupEventsSbGive'] = />doesnt workI@UDAWSd/;
	lang['de']['groupEventsSbDragRes'] = /(Du siehst wie )(?:etwas )*(.*)()( aus .* ins .* geschleppt wird\.)/;
	lang['de']['groupEventsSbThrowDie'] = /doesnt!#@$ work/;
	lang['de']['groupPreEventsYouSay'] = 'Du sagst:';
	lang['de']['groupPreEventsSbSay'] = ' sagt:';
	lang['de']['groupPreEventsSbWhisper'] = ' reden.';
	lang['de']['groupPreEventsSbUse'] = ' ';
	lang['de']['groupPreEventsSbHunt'] = ' verwunden.';
	lang['de']['groupPreEventsSbPoke'] = ' stoßen.';
	lang['de']['groupPreEventsSbTake'] = ' nehmen.';
	lang['de']['groupPreEventsSbDrop'] = ' fallen l';
	lang['de']['groupPreEventsSbGive'] = ' doesnt work1234';
	lang['de']['groupPreEventsSbDragRes'] = ' geschleppt wird.';
	lang['de']['groupPreEventsSbThrowDie'] = ' doesnt work1234s';
	
	// most important quotation
	activeText['de'] = 'Spieler waren in den letzten 15 Minuten aktiv.';
	
	pageObjects.push('OBJEKTE'); // opened objects panel titlebar
	pageInventory.push('INVENTAR'); // opened inventory panel titlebar
	pageBuildingsAndVehicles.push(lang['de']['vehCategoryLandVehicles']);// opened vehicles panel titlebar
	pageBuildingsAndVehicles.push(lang['de']['vehCategoryShips']);
	pageBuildingsAndVehicles.push(lang['de']['vehCategoryConstructions']);
	pageBuildingsAndVehicles.push(lang['de']['categoryBuildingsOutside']);
	pageBuildingsAndVehiclesInside.push(lang['de']['categoryBuildingsInside']);
	pageEvents.push('EREIGNISSE'); // opened events panel titlebar
	pageTakingInfo.push('INFO NEHMEN'); // page where you type how much resources do you want to pick up
	pageWriteNote.push('EINE NOTIZ SCHREIBEN'); // write note page
	pageShop.push('EINKAUFEN MIT CREDITS'); // shop page (credits etc)
	pageStorageResources.push('ROHMATERIAL LAGERN'); // how much resources do you want to put into container
	pageSelAmountToProject.push('WÄHLE MENGE FÜR DIESES PROJEKT'); // when you create project and you type how much do you want to get (in projects like refining iron ore)
	pageGiveResources.push('INFO GEBEN</B>'); //  how much resources do you want to give to sb
	pageRepair.push('repariert '); /*  de on pageGiveResources - because there are two pages with similar name */
	pageLocation.push(': BESCHREIBUNG'); // how to recognise LOCATION page? :D
	pageEmptyEnvelope.push('LEERER BRIEFUMSCHLAG');
	
	/*
	Português
	*/
	
	lang['pt'] = [];
	
	// other
	lang['pt']['itemNote'] = 'nota';
	lang['pt']['itemEnvelope'] = 'envelope';
	lang['pt']['grams'] = 'gramas';
	lang['pt']['pieces'] = 'doesnt exist leixi9I(@!UI(JF';
	lang['pt']['shipNames'] = ['jangada', 'caiaque', 'canoa de tora', 'barco de junco', 'bote', 'barco a remos', 'eslópe', 'patacho', 'bote longo', 'catamarão', 'balsa', 'brigue', 'escuna', 'galeão']; // MUST BE LOWERCASE
	lang['pt']['groupObjectsInUse'] = ' <i>(em uso)</i>';
	
  // since 2.1
  lang['pt']['vehCategoryLandVehicles'] = 'LAND VEHICLES';
	lang['pt']['vehCategoryShips'] = 'SHIPS';
	lang['pt']['vehCategoryConstructions'] = 'CONSTRUCTIONS';
	lang['pt']['categoryBuildingsOutside'] = 'CONSTRUÇÕES';
	lang['pt']['categoryBuildingsInside'] = 'OTHER ROOMS';
	
	// QUOTATIONS
	/*
	!!!CAUTION!!! Remember that you shouldn't write translated text, but check how it is named in your language - no mistakes allowed or script will not load
	*/
	activeText['pt'] = 'usuários estiveram ativos durante os últimos 15 minutos.';
	
	pageObjects.push('OBJETOS'); // opened objects panel titlebar
	pageInventory.push('INVENTÁRIO'); // opened inventory panel titlebar
	pageBuildingsAndVehicles.push(lang['pt']['vehCategoryLandVehicles']);// opened vehicles panel titlebar
	pageBuildingsAndVehicles.push(lang['pt']['vehCategoryShips']);
	pageBuildingsAndVehicles.push(lang['pt']['vehCategoryConstructions']);
	pageBuildingsAndVehicles.push(lang['pt']['categoryBuildingsOutside']);
	pageBuildingsAndVehiclesInside.push(lang['pt']['categoryBuildingsInside']);
	pageEvents.push('ACONTECIMENTOS'); // opened events panel titlebar
	pageTakingInfo.push('PEGUE INFORMAÇÃO'); // page where you type how much resources do you want to pick up
	pageWriteNote.push('ESCREVER UMA NOTA'); // write note page
	pageShop.push('COMPRAS COM OS CRÉDITOS'); // shop page (credits etc)
	pageStorageResources.push('ARMAZENAR MATERIAL EM ESTADO BRUTO'); // how much resources do you want to put into container
	pageSelAmountToProject.push('SELECIONA A QUANTIDADE PARA ESTE PROJETO'); // when you create project and you type how much do you want to get (in projects like refining iron ore)
	pageGiveResources.push('<B>DAR INFORMAÇÃO</B>'); //  how much resources do you want to give to sb
	pageRepair.push('Reparando'); /*  de on pageGiveResources - because there are two pages with similar name */
	pageLocation.push(': DESCRIÇÃO'); // how to recognise LOCATION page? :D
	pageEmptyEnvelope.push('ESVAZIAR ENVELOPE'); // when taking notes out of envelope - titlebar
	
	/*
	SPANISH
	*/

	// QUOTATIONS
	/*
	!!!CAUTION!!! Remember that you shouldn't write translated text, but check how it is named in your language - no mistakes allowed or script will not load
	*/
	
	lang['es'] = [];
	
	// other
	lang['es']['itemNote'] = 'nota';
	lang['es']['itemEnvelope'] = 'Sobre';
	lang['es']['grams'] = 'gramos de';
	lang['es']['pieces'] = 'peça(s) de';
	lang['es']['shipNames'] = ['balsa', 'kayak', 'canoa', 'bote de cañas', 'esquife', 'bote de remos', 'balandra', 'patache', 'chalupa', 'catamarán', 'transbordador', 'bergantín', 'nao', 'galeón']; // MUST BE LOWERCASE
	lang['es']['groupObjectsInUse'] = ' <i>(en uso)</i>';

  // since 2.1
  lang['es']['vehCategoryLandVehicles'] = 'LAND VEHICLES';
	lang['es']['vehCategoryShips'] = 'SHIPS';
	lang['es']['vehCategoryConstructions'] = 'CONSTRUCTIONS';
	lang['es']['categoryBuildingsOutside'] = 'BUILDINGS';
	lang['es']['categoryBuildingsInside'] = 'OTRAS HABITACIONES';

	// most important quotation
	activeText['es'] = 'usuarios activos en los últimos 15 minutos.';
	
	pageObjects.push('OBJETOS'); // opened objects panel titlebar
	pageInventory.push('INVENTARIO'); // opened inventory panel titlebar
	pageBuildingsAndVehicles.push(lang['es']['vehCategoryLandVehicles']);// opened vehicles panel titlebar
	pageBuildingsAndVehicles.push(lang['es']['vehCategoryShips']);
	pageBuildingsAndVehicles.push(lang['es']['vehCategoryConstructions']);
	pageBuildingsAndVehicles.push(lang['es']['categoryBuildingsOutside']);
	pageBuildingsAndVehiclesInside.push(lang['es']['categoryBuildingsInside']);
	pageEvents.push('ACONTECIMIENTOS'); // opened events panel titlebar
	pageTakingInfo.push('INFORMACIÓN SOBRE LO QUE COJE'); // page where you type how much resources do you want to pick up
	pageWriteNote.push('ESCRIBE UNA NOTA'); // write note page
	pageShop.push('NO LONGER EXIST dkoawjid'); // shop page (credits etc)
	pageStorageResources.push('ALMACENAR MATERIAS PRIMAS '); // how much resources do you want to put into container
	pageSelAmountToProject.push('SELECCIONAR CANTIDAD PARA ESTE PROYECTO'); // when you create project and you type how much do you want to get (in projects like refining iron ore)
	pageGiveResources.push('INFORMACIÓN SOBRE LO QUE VA A ENTREGAR'); //  how much resources do you want to give to sb
	pageRepair.push('reparando '); /*  de on pageGiveResources - because there are two pages with similar name */
	pageLocation.push(': DESCRIPCIÓN'); // how to recognise LOCATION page? :D
	pageEmptyEnvelope.push('SOBRE1234 DOESNT WORK');


	/*
	 * FINNISH
	 */

	lang['fi'] = [];

  // since 2.1
  lang['fi']['vehCategoryLandVehicles'] = 'LAND VEHICLES';
	lang['fi']['vehCategoryShips'] = 'SHIPS';
	lang['fi']['vehCategoryConstructions'] = 'CONSTRUCTIONS';
	lang['fi']['categoryBuildingsOutside'] = 'RAKENNUKSET';
	lang['fi']['categoryBuildingsInside'] = 'MUUT HUONEET';

	
  // other
	lang['fi']['itemNote'] = 'Viestilappu';
	lang['fi']['itemEnvelope'] = 'Kirjekuori';
	lang['fi']['grams'] = 'grammaa';
	lang['fi']['pieces'] = ' kappaletta ';
	lang['fi']['optionsButton'] = 'Cantr Enhanced vaihtoehdot';
	lang['fi']['groupObjectsInUse'] = ' <i>(käytössä)</i>';

	// most important quotation
	activeText['fi'] = 'käyttäjää on ollut aktivisena viimeisen 15 minuutin sisään.';
	pageObjects.push('ESINEET'); // opened objects panel titlebar
	pageInventory.push('OMAT TAVARAT'); // opened inventory panel titlebar
	pageBuildingsAndVehicles.push(lang['fi']['vehCategoryLandVehicles']);// opened vehicles panel titlebar
	pageBuildingsAndVehicles.push(lang['fi']['vehCategoryShips']);
	pageBuildingsAndVehicles.push(lang['fi']['vehCategoryConstructions']);
	pageBuildingsAndVehicles.push(lang['fi']['categoryBuildingsOutside']);
	pageBuildingsAndVehiclesInside.push(lang['fi']['categoryBuildingsInside']);
	pageEvents.push('TAPAHTUMAT'); // opened events panel titlebar
	pageTakingInfo.push('OTTO - TIEDOT'); // page where you type how much resources do you want to pick up
	pageWriteNote.push('KIRJOITA VIESTI'); // write note page
	pageShop.push('OSTOKSET KREDIITEILLÄ'); // shop page (credits etc)
	pageStorageResources.push('LAITA VARASTOON'); // how much resources do you want to put into container
	pageSelAmountToProject.push('VALITSE MÄÄRÄ PROJEKTILLE'); // when you create project and you type how much do you want to get (in projects like refining iron ore)
	pageGiveResources.push('<B>ANNA</B>'); //  how much resources do you want to give to sb
	pageRepair.push('Korjataan'); /*  de on pageGiveResources - because there are two pages with similar name */
	pageLocation.push(': KUVAUS'); // how to recognise LOCATION page? :D
	pageEmptyEnvelope.push('TYHJENNÄ KIRJEKUORI'); // when taking notes out of envelope - titlebar
	pageMainPage.push('PELAAJAINFO');
	
	// ustawianie języka postaci
	var chLn = getCharacterLanguage();
	
	
	
	
	
	/*#############################
			  LANGUAGES END
	  #############################*/
	
	//////
	////// POCZĄTEK LISTA OBIEKTÓW
	////// 
	
	function listObjects(){
		var node = document.body;
		var mainNode = node.getElementsByClassName('page')[1];
		var TRs = mainNode.getElementsByTagName('tr');
		var list = [];
		var dummySpan = document.createElement('span');
		for (var ind=0;ind<TRs.length;ind++){
			if(TRs[ind].getElementsByTagName('table').length > 0){ // because there is outer TR and inner TR (in table), we want only outer TRs
				var tabNode = TRs[ind].getElementsByTagName('table')[0];
				var TDs = tabNode.getElementsByTagName('td');
				var lastTD = TDs[TDs.length-1];
				dummySpan.innerHTML = lastTD.innerHTML.replace(">", "> ");
				list.push(trim(dummySpan.textContent));
			}
		}
		var listOuterDiv = document.createElement('div');
		mainNode.appendChild(listOuterDiv);
		var headerDiv = createHeaderTitle(lang[ln]['listObjectsTitle'], 12);
		headerDiv.style.marginBottom = '10px';
		var listDiv = document.createElement('div');
		// na początku lista jest ukryta
		var listVisible = false;
		listDiv.style.display = 'none';
		// ukrywanie i odkrywanie listy po wciśnięciu nagłówka
		headerDiv.addEventListener('click', function(){
			listVisible = !listVisible;
			if (listVisible)
				listDiv.style.display = 'block';
			else 
				listDiv.style.display = 'none';
		}, true);
		
		

		var chBoxes = document.createElement('div');
		var chNotes = addListCheckBox(lang[ln]['listObjectsNotesCB']);
		var chRes = addListCheckBox(lang[ln]['listObjectsResourcesCB']);
		var chOther = addListCheckBox(lang[ln]['listObjectsOthersCB']);
		
		listDiv.appendChild(chBoxes);
		
		var listTArea = document.createElement('textarea');
		listTArea.cols = 83;
		listTArea.rows = 5;
		listDiv.appendChild(listTArea);
		
		rebuildList();
		
		var noteCB = document.createElement('input');
		
		listOuterDiv.appendChild(headerDiv);
		listOuterDiv.appendChild(listDiv);
		
		function rebuildList(){
		console.log('rebuilding');
		listTArea.innerHTML = '';
			for (var index=0;index<list.length;index++){
				if (list[index].indexOf(lang[chLn]['itemNote']) >= 0 || list[index].indexOf(lang[chLn]['itemEnvelope']) >= 0){
					if (chNotes.checked)
						listTArea.innerHTML += list[index] + '\n';
				}
				else if (list[index].indexOf(lang[chLn]['grams']) >= 0 ){
					if (chRes.checked)
						listTArea.innerHTML += list[index] + '\n';
				}
				else if (chOther.checked){
					listTArea.innerHTML += list[index] + '\n';
				}
			}
		}
		
		
		function addListCheckBox(spanName){
			var chBox = document.createElement('input');
			chBox.type = 'checkbox';
			chBox.checked = true;
			chBoxes.appendChild(chBox);
			var capSpan = document.createElement('span');
			capSpan.innerHTML = spanName;
			chBox.addEventListener('click', function(){ rebuildList();}, true);
			chBoxes.appendChild(capSpan);
			return chBox;
		}
    
    function trim (str){
      return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
    }
	}
	
	
	//////
	////// KONIEC LISTA OBIEKTÓW
	////// POCZĄTEK GRUPOWANIE OBIEKTÓW
	//////
	
	function groupObjects(){
		var node = document.body;
		var centerNode = node.getElementsByClassName('page')[1];
		var TRs = centerNode.getElementsByTagName('tr');
		var list = [];
		for (var ind=0;ind<TRs.length;ind++){
			if(TRs[ind].getElementsByTagName('table').length > 0){ // because there is outer TR and inner TR (in table), we want only outer TRs
				var tabNode = TRs[ind].getElementsByTagName('table')[0];
				var TDs = tabNode.getElementsByTagName('td');
				
				for (var tdind=0;tdind<TDs.length;tdind++){
					if (TDs[tdind].innerHTML.indexOf('button_small_use.gif') >= 0){ // sprawdza czy jest to maszyna
						var nameTD = TDs[TDs.length-1];
						var projectTD = TDs[tdind];
						var allTR = TRs[ind];
						var infoSpan = document.createElement('span');
						var used = false;
						if (nameTD.innerHTML.indexOf(lang[chLn]['groupObjectsInUse']) >= 0){
							used = true;
						}
						nameTD.innerHTML = nameTD.innerHTML.replace(lang[chLn]['groupObjectsInUse'], '');
						var hash = nameTD.innerHTML.hashCode();
						if (list[hash] == null || list[hash] == undefined){ // gdy znalazło po raz pierwszy
							list[hash] = [];
							nameTD.appendChild(infoSpan);
							list[hash]['name'] = nameTD;
							list[hash]['project'] = projectTD;
							list[hash]['info'] = infoSpan;
							list[hash]['num'] = 1;
							list[hash]['used'] = 0;
							if (used){
								list[hash]['used'] = 1;
								list[hash]['info'].innerHTML = lang[chLn]['groupObjectsInUse'];
								}
						}
						else { // po raz kolejny wystąpiło
							list[hash]['num']++;
							if (used){
								list[hash]['used']++;
							}
							else {
								list[hash]['project'].innerHTML = projectTD.innerHTML;
							}
							list[hash]['info'].innerHTML = ' ' + lang[ln]['groupObjectsUsedFirst'] + list[hash]['used'] + lang[ln]['groupObjectsUsedOf'] +  list[hash]['num'] + lang[ln]['groupObjectsUsedEnd'];
							TRs[ind].innerHTML = '';
							// TRs[ind].parentNode.removeChild(TRs[ind]);
						}
						
					}
				}
				
				
			}
		}
		
	}
	
	//////
	////// KONIEC GRUPOWANIE OBIEKTÓW
	////// POCZĄTEK AUTOZAZNACZANIE NOTATEK
	//////
	
	function notesCheckBoxInventory(){
		var node = document.body;
		var inputs = node.getElementsByTagName('input');
		
		// storage of informations about TR checkbox and TR in which is located
		var noteName = [];
		var noteCB = [];
		
		for (var i=0;i<inputs.length;i++){
		var currInput = inputs[i];
			if (currInput.type == 'checkbox' && currInput.name == 'notes[]'){
				var label = currInput.parentNode;
        var rx1 = new RegExp('('+lang[chLn]['itemNote']+')(.*)', "m");

			var parts = rx1.exec(label.innerHTML);
			var text = "";
			if (parts){
				text = parts[0];
			}
				if (text.indexOf(lang[chLn]['itemNote']) >= 0){
					noteName.push(text);
					noteCB.push(currInput);
				}
			}
		}
		if (noteCB.length > 0){
      console.log('number of notes: ' + noteCB.length);
			var optionsCenter = node.getElementsByTagName('center')[2];
      var forPanel = document.createElement('div');
      optionsCenter.insertBefore(forPanel, optionsCenter.firstChild);
			notesCheckBoxIn(noteCB, noteName, forPanel);
		}
	}
	
	
	function notesCheckBoxEnvelopes() {
		var node = document.body.getElementsByTagName('center')[0];
		var inputs = node.getElementsByTagName('input');
		
		var noteName = [];
		var noteCB = [];
		for (var i=0;i<inputs.length;i++) {
			var currInput = inputs[i];
			if (currInput.type == 'checkbox' && currInput.name.indexOf('note') == 0){
				noteCB.push(currInput);
				// i tu się zaczyna głupia sprawa z nazwą, bo jej potrzebuję
				var noteNameNode = currInput.parentNode.nextSibling.nextSibling;
				var currCode = noteNameNode.innerHTML;
				var currName = currCode.split('<br>', 1)[0];
				noteName.push(currName);
			}
		}
		
		if (noteCB.length > 0){
      console.log('number of notes: ' + noteCB.length);
			var optionsCenter = document.body.getElementsByTagName('center')[0];
			var forDiv = document.createElement('div');
      optionsCenter.insertBefore(forDiv, optionsCenter.firstChild);
			notesCheckBoxIn(noteCB, noteName, forDiv);
		}
		
	}
	
	
	function notesCheckBoxIn(notesArr, nameArr, options){
		var infoSpan = document.createElement('span');
		infoSpan.innerHTML = lang[ln]['notesChbTitle'] + ': ';
		
		var allNotes = document.createElement('span');
		allNotes.innerHTML = ' [' + lang[ln]['notesChbAll'] + '] ';
		allNotes.addEventListener('click', function(){
			for (var i=0;i<notesArr.length;i++)
				notesArr[i].checked = true;
		}, true);
		
		var noNotes = document.createElement('span');
		noNotes.innerHTML = ' [' + lang[ln]['notesChbNo'] + '] ';
		noNotes.addEventListener('click', function(){
			for (var i=0;i<notesArr.length;i++)
				notesArr[i].checked = false;
		}, true);
		
		var duplNotes = document.createElement('span');
		duplNotes.innerHTML = ' [' + lang[ln]['notesChbDupl'] + '] ';
		duplNotes.addEventListener('click', function(){
			var hashTab = [];
			for (var i=0;i<notesArr.length;i++){
				var currHash = nameArr[i].hashCode();
				if (hashTab[currHash] != 1){ // jeśli nie istnieje taki element
					hashTab[currHash] = 1;
					notesArr[i].checked = false;
				}
				else { // jeśli już wcześniej taki znaleziono
					notesArr[i].checked = true;
				}
			}
		}, true);
		
		var oppositeNotes = document.createElement('span');
		oppositeNotes.innerHTML = ' [' + lang[ln]['notesChbOpp'] + '] ';
		oppositeNotes.addEventListener('click', function(){
			for (var i=0;i<notesArr.length;i++)
				notesArr[i].checked = !notesArr[i].checked;
		}, true);
		
		
		options.appendChild(infoSpan);
		options.appendChild(allNotes);
		options.appendChild(noNotes);
		options.appendChild(duplNotes);
		options.appendChild(oppositeNotes);
	}
	
	
	//////
	////// KONIEC AUTOZAZNACZANIE NOTATEK
	////// POCZĄTEK WYRÓŻNIONE BUDYNKI/POJAZDY
	//////
	
	function bookmarkBuildingsVehicles(){
		var char4digits = get4digits();
		
		var hlDiv = document.createElement('div');
    hlDiv.style.width = '700px';
    hlDiv.style.margin = 'auto';
    hlDiv.style.marginTop = "10px";
    hlDiv.style.background = 'rgba(0, 58, 0, 0.86)';
    hlDiv.style.boxShadow = '3px 3px 10px #004000, -3px -3px 10px #003A00, 3px -3px 10px #003000';

		var titleBars = document.getElementsByClassName('titlebar txt-title');
		
		var isVehBar = false;
		var isBuildBar = false;
		var sumVeh = 0; // sum of bookmarked vehicles
		var sumBuild = 0; // sum of bookmarked buildings
		
		for (var i=0; i < titleBars.length; i++) {
			var currBar = titleBars[i];
			if (
				(currBar.textContent.indexOf(lang[chLn]['vehCategoryLandVehicles']) >= 0) ||
				(currBar.textContent.indexOf(lang[chLn]['vehCategoryShips']) >= 0) ||
				(currBar.textContent.indexOf(lang[chLn]['vehCategoryConstructions']) >= 0)
			) { // add to veh
				if (!isVehBar) {
					isVehBar = true;
					var vehTitle = createHeaderTitle(lang[ln]['bmVehTitle'], 8);
					hlDiv.appendChild(vehTitle);
				}
				var ourCenter = skipIfNotCenter(currBar.nextSibling);
				sumVeh += addToHighlightList(ourCenter);
			} else if (
				(currBar.textContent.indexOf(lang[chLn]['categoryBuildingsOutside']) >= 0) ||
				(currBar.textContent.indexOf(lang[chLn]['categoryBuildingsInside']) >= 0)
			) { // add to buildings
				if (!isBuildBar) {
					isBuildBar = true;
					var buildTitle = createHeaderTitle(lang[ln]['bmBuildTitle'], 8);
					hlDiv.appendChild(buildTitle);
				}
				var ourCenter = skipIfNotCenter(currBar.nextSibling);
				
				sumBuild += addToHighlightList(ourCenter);
			}
		}

		if (isVehBar || isBuildBar) {
			if ((sumVeh == 0) && (vehTitle != null)) {
				vehTitle.parentNode.removeChild(vehTitle);
			}
			if ((sumBuild == 0) && (buildTitle != null)) {
				buildTitle.parentNode.removeChild(buildTitle);
			}
			titleBars[1].parentNode.insertBefore(hlDiv, titleBars[1]);
		}

		function skipIfNotCenter(node) {
			if (node.tagName != "CENTER") {
				return node.nextSibling;
			}
			return node;
		}
		
		function addToHighlightList(selObjects){
		var count = 0;
		var objList = selObjects.getElementsByTagName('tr');
			for (var obID=0;obID<objList.length;obID++){
				var objID = '';
				var currObj = objList[obID];
				var currObjTDs = currObj.getElementsByTagName('td'); // TR zawierający informacje o pojeździe. Należy uważać, żeby nic nie popsuć
				
				var lineDiv = document.createElement('div');
				var lastElement;
				for (var tdi = 0; tdi<currObjTDs.length; tdi++){
					var currTD = currObjTDs[tdi];
					var inputNode = currTD.getElementsByTagName('input')[0];
					if (inputNode != null && objID == '')
						objID = inputNode.value;
					var currDiv = document.createElement('div');
					currDiv.innerHTML = currObjTDs[tdi].innerHTML;
					currDiv.style.display = 'inline';
					currDiv.style.verticalAlign = 'top';
					
					// usuwanie stylu dla dodatkowych znaków
					var pe = currDiv.getElementsByTagName('p');
					for (var idx = 0;idx<pe.length;idx++)
						pe[idx].style.display = 'none';
							
					lineDiv.appendChild(currDiv);
					lastElement = currDiv;
				}
				if (itemExists(char4digits, objID)){   // todo
					count++;

					hlDiv.appendChild(lineDiv);
				}
				var selectionTD = document.createElement('td');
				if (!itemExists(char4digits, objID))
					setEnable(selectionTD);
				else setDisable(selectionTD);
				
				setChangeListener(selectionTD, char4digits, objID);
				
				currObj.insertBefore(selectionTD, currObjTDs[currObjTDs.length-1]); // dodajemy gwiazdkę tuż przed ostatnim elementem - tekstem
			}
			return count;
		}
	}
	
	

	
	function setChangeListener(master, digits, idek){
		master.addEventListener('click', function(){
			if (!itemExists(digits, idek)){ // gdy taki wpis nie istniał
				itemSet(digits, idek);
				// todo set localStorage że to ma być wyróżnione
				setDisable(master);
			}
			else {
				itemRemove(digits, idek);
				setEnable(master);
			}
		}, true);
	}
	
	function itemExists(dgt, obi){
		return localStorage.getItem('CE_hl_' + dgt + '_' + obi);
	}
	
	function itemSet(dgt, obi){
		localStorage.setItem('CE_hl_' + dgt + '_' + obi, 'yes');
	}
	
	function itemRemove(dgt, obi){
		localStorage.removeItem('CE_hl_' + dgt + '_' + obi);
	}
	
	function setEnable(tnode){
		tnode.innerHTML = '(+)';
	}
	function setDisable(tnode){
		tnode.innerHTML = '[-]';
	}
	
	
	//////
	////// KONIEC WYRÓŻNIONE BUDYNKI/POJAZDY
	////// POCZĄTEK OPERACJE NA STRONIE ZDARZEŃ
	//////
	
	function eventsFilter(){
		var ID4digits = get4digits();
		
		// łączenie komunikatów tego samego typu - pod warunkiem zaznaczenia pewnej opcji w wiadomo czym
		if (enabledInStorage('GroupEvents') && lang[chLn]){

		    var types = [
				{
					'id': 1,
          'pretext': lang[chLn]['groupPreEventsSbUse'],
					'regexp': lang[chLn]['groupEventsSbUse'],
					'f1':function(fst,snd, p, arg0, perf){
						if (p[1] == perf && p[4] == arg0){
							fst.innerHTML = fst.innerHTML.substr(0, fst.innerHTML.indexOf(p[3])) + ', '  + p[2] + fst.innerHTML.substr(fst.innerHTML.indexOf(p[3]));
							snd.innerHTML = '';
							return true;
						}
						return false;
					}
				},
				{
					'id': 2,
          'pretext': lang[chLn]['groupPreEventsSbHunt'],
					'regexp': lang[chLn]['groupEventsSbHunt'],
					'f1':function(fst,snd, p, arg0, perf){
						if (p[1] == perf && p[4] == arg0){
							fst.innerHTML = fst.innerHTML.substr(0, fst.innerHTML.indexOf(p[3])) + ', '  + p[2] + fst.innerHTML.substr(fst.innerHTML.indexOf(p[3]));
							snd.innerHTML = '';
							return true;
						}
						return false;
					}
				},
				{
					'id': 3,
          'pretext': lang[chLn]['groupPreEventsSbPoke'],
					'regexp': lang[chLn]['groupEventsSbPoke'],
					'f1':function(fst,snd, p, arg0, perf){
						if (p[1] == perf){
							fst.innerHTML = fst.innerHTML.substr(0, fst.innerHTML.lastIndexOf('.')) + ', '  + p[2] + fst.innerHTML.substr(fst.innerHTML.lastIndexOf('.'));
							snd.innerHTML = '';
							return true;
						}
						return false;
					}
				},
				{
					'id': 4,
          'pretext': lang[chLn]['groupPreEventsSbTake'],
					'regexp': lang[chLn]['groupEventsSbTake'],
					'f1':function(fst,snd, p, arg0, perf){
						if (p[1] == perf){
							fst.innerHTML = fst.innerHTML.substr(0, fst.innerHTML.lastIndexOf('.')) + ', '  + p[2] + fst.innerHTML.substr(fst.innerHTML.lastIndexOf('.'));
							snd.innerHTML = '';
							return true;
						}
						return false;
					}
				},
				{
					'id': 5,
          'pretext': lang[chLn]['groupPreEventsSbDrop'],
					'regexp': lang[chLn]['groupEventsSbDrop'],
					'f1':function(fst,snd, p, arg0, perf){
						if (p[1] == perf){
							fst.innerHTML = fst.innerHTML.substr(0, fst.innerHTML.lastIndexOf('.')) + ', '  + p[2] + fst.innerHTML.substr(fst.innerHTML.lastIndexOf('.'));
							snd.innerHTML = '';
							return true;
						}
						return false;
					}
				},
				{
					'id': 6,
          'pretext': lang[chLn]['groupPreEventsSbGive'],
					'regexp': lang[chLn]['groupEventsSbGive'],
					'f1':function(fst,snd, p, arg0, perf){
						if (p[1] == perf){
							fst.innerHTML = fst.innerHTML.substr(0, fst.innerHTML.lastIndexOf('.')) + ', '  + p[2] + fst.innerHTML.substr(fst.innerHTML.lastIndexOf('.'));
							snd.innerHTML = '';
							return true;
						}
						return false;
					}
				},
				{
					'id': 7,
          'pretext': lang[chLn]['groupPreEventsSbDragRes'],
					'regexp': lang[chLn]['groupEventsSbDragRes'],
					'f1':function(fst,snd, p, arg0, perf){
						if (arg0 == p[4]){
							var firstP = fst.innerHTML.substr(0, fst.innerHTML.indexOf(p[4]));
							var secP = fst.innerHTML.substr(fst.innerHTML.indexOf(p[4]));
							fst.innerHTML =  firstP + ', '  + p[2] + secP;
							snd.innerHTML = '';
							return true;
						}
						return false;
					}
				},
				{
					'id': 8,
          'pretext': lang[chLn]['groupPreEventsSbThrowDie'],
					'regexp': lang[chLn]['groupEventsSbThrowDie'],
					'f1':function(fst,snd, p, arg0, perf){
						if (arg0 == p[1]) {
							var firstP = fst.innerHTML.substr(0, fst.innerHTML.lastIndexOf('.'));
							var secP = fst.innerHTML.substr(fst.innerHTML.lastIndexOf('.'));
							fst.innerHTML =  firstP + ', '  + p[3] + secP;
							snd.innerHTML = '';
							return true;
						}
						return false;
					}
				}
			];
			
      var eventNode = document.getElementById("eventsList");
      
			var divs = eventNode.getElementsByTagName('div');
			var timexp = /(\d+)-(\d+)\.<small>(\d+)<\/small>/; // time regexp
			var startTime = new Date().getTime();

			var arrtime = [];
			var lastType = 0;
			var first = 0;
			var sub = '';
			var perf = '';
			
			for (var i=0;i<divs.length;i++) {
				var tdiv = divs[i];
					
				if ((tdiv.innerHTML.indexOf(lang[chLn]['groupPreEventsYouSay']) == -1) &&
					(tdiv.innerHTML.indexOf(lang[chLn]['groupPreEventsSbSay']) == -1) &&
					(tdiv.innerHTML.indexOf(lang[chLn]['groupPreEventsSbWhisper']) == -1)
				) {
					
					var ctime = timexp.exec(tdiv.innerHTML); // zakładam, że zawsze będzie pasować
					var matched = false;
					for (var u=0;u<types.length && !matched;u++) {
						var type = types[u];
						if (tdiv.innerHTML.indexOf(type.pretext) == -1) {
							continue;
						}
						var rexp = type.regexp;
						
						var parts = rexp.exec(tdiv.innerHTML);
						if (parts) {
							matched = true;
							
							if ((lastType != type.id) || !isnear(ctime, arrtime) ||
								!type.f1(first, tdiv, parts, sub, perf)
							) { // mimo tego samego typu nie udalo sie skleic, bo roznia sie szczegoly; zaczynamy od poczatku
								first = tdiv;
								lastType = type.id;
								sub = parts[4];
								perf = parts[1];
								arrtime = ctime;
							}
            }
					}
					if (!matched) {
						lastType = 0;
					}
				} else {
					lastType = 0;
				}
			}
		}
		console.log("Event grouping time: " + (new Date().getTime() - startTime));
		// funkcja sprawdzająca odległość czasową
		
		function isnear(tab1, tab2){ // sprawdza czy pierwsza komórka jest taka sama a druga +- 1 min taka sama
			var t1 = tab1[1]*8*36+tab1[2]*36+tab1[3];
			var t2 = tab2[1]*8*36+tab2[2]*36+tab2[3];
			
			return Math.abs(t2-t1) <= GROUPEVENTS_MAX_MIN_DIFF;
		}
		
		var divp = document.createElement('div');
		
		/*
			pobieranie numeru postaci
		*/
		
		var charID = getCharId();
		
		/*
		 Popup do szeptów
		 */

		
		function popupstart(nnd) {
			
			if (enabledInStorage('ShortNames') && chLn == 'pl') {
				switch (nnd.innerHTML){
					case 'dwudziestoletni mężczyzna': nnd.innerHTML = 'dwudziestolatek'; break;
					case 'trzydziestoletni mężczyzna': nnd.innerHTML = 'trzydziestolatek'; break;
					case 'czterdziestoletni mężczyzna': nnd.innerHTML = 'czterdziestolatek'; break;
					case 'pięćdziesięcioletni mężczyzna': nnd.innerHTML = 'pięćdziesięciolatek'; break;
					case 'sześćdziesięcioletni mężczyzna': nnd.innerHTML = 'sześćdziesięciolatek'; break;
					case 'siedemdziesięcioletni mężczyzna': nnd.innerHTML = 'siedemdziesięciolatek'; break;
					case 'osiemdziesięcioletni mężczyzna': nnd.innerHTML = 'osiemdziesięciolatek'; break;
					
					case 'dwudziestoletnia kobieta': nnd.innerHTML = 'dwudziestolatka'; break;
					case 'trzydziestoletnia kobieta': nnd.innerHTML = 'trzydziestolatka'; break;
					case 'czterdziestoletnia kobieta': nnd.innerHTML = 'czterdziestolatka'; break;
					case 'pięćdziesięcioletnia kobieta': nnd.innerHTML = 'pięćdziesięciolatka'; break;
					case 'sześćdziesięcioletnia kobieta': nnd.innerHTML = 'sześćdziesięciolatka'; break;
					case 'siedemdziesięcioletnia kobieta': nnd.innerHTML = 'siedemdziesięciolatka'; break;
					case 'osiemdziesięcioletnia kobieta': nnd.innerHTML = 'osiemdziesięciolatka'; break;
				}
			}
			
			if (enabledInStorage('ColorNames')){
				var colors = ['#eeeeee', '#3dc5cc', '#fefefe', '#ffec77', '#e8ff8b', '#000080', '#333333', '#330033', '#4b2500', '#004000'];
				
				var name = nnd.innerHTML;
				var k = Math.abs(name.hashCode());
				var e = k%5;
				k = Math.floor(k/10);
				var o = k%5;
				if (e < 5)
					o = o+5;

				var spanNode = document.createElement('span');
				spanNode.style.backgroundColor = colors[o];
				spanNode.style.color = colors[e];
				spanNode.style.opacity = "0.6";
				spanNode.innerHTML = name;
				nnd.innerHTML = "";
				nnd.appendChild(spanNode);
			}
		}
	
			var startTime = new Date().getTime();
			var divs = eventNode.children;
			for (var i=0;i<divs.length;i++){
				var aNodes = divs[i].getElementsByClassName('character');
				for (var k=0;k<aNodes.length;k++){
					popupstart(aNodes[k]);
				}
			}
			console.log("Character name matching time: " + (new Date().getTime() - startTime));
		
		/*
			NEW EVENTS
		*/

		var eventsNumber = divs.length;
		
		function refreshEvents() {
			return function() {
				var newEvents = divs.length - eventsNumber;
				for (var i = 0; i < newEvents; i++) {
					var aNodes = divs[i].getElementsByClassName('character');
					for (var k=0;k<aNodes.length;k++) {
						var nnode = aNodes[k];
						popupstart(nnode);
					}
				}
				eventsNumber = divs.length;
			};
		}

		setInterval(refreshEvents(), 1000);

		/*
		* KRESKA POKAZUJACA DOKAD SIE DOCZYTALO ZDARZENIA
		*/

		if (enabledInStorage('LineEventsNotFocused')) {
			var eventsFocus = divs.length;
			var lastUnderlinedNode = null;
			
			function onFocus() {
				var diff = divs.length - eventsFocus;
				if (diff > 0) {
					if (lastUnderlinedNode != null) {
						lastUnderlinedNode.style.borderBottom = "none";
					}
					lastUnderlinedNode = divs[diff-1];
					lastUnderlinedNode.style.borderBottom = "1px dashed #820";
				}
			}

			function onBlur() {
				eventsFocus = divs.length;
			}
			
			window.onfocus = onFocus;
			window.onblur = onBlur;
		}
	}
	
	//////
	////// KONIEC OPERACJE NA STRONIE ZDARZEŃ
	////// POCZĄTEK ZEGAREK
	//////
	
	
	function cantrClock(){
		var client = new XMLHttpRequest();
		var result = 0;
		client.open("OPTIONS", "*", true);
		client.send();
		client.onreadystatechange = function() {
			if(this.readyState == 2) {
				var regEx =  new RegExp(/^(.*?), (\d+) (.*?) (\d+) (\d+:\d+:\d+)(.*?)$/); // RegExp gets hour min and sec section from string like: "Thu, 11 Aug 2011 23:53:13 GMT"
				var dateParts = regEx.exec(client.getResponseHeader("Date"));
				//console.log('time: ' + dateParts[0]);
					var dens = dateParts[5].split(':');
					result = dens[0]*3600;
					result += dens[1]*60;
					result += +dens[2]*1;
					cantrClockWithTime(result);
			}
		}
	}
	
	function cantrClockWithTime(serverTime){
		var node = document.body;
		var datespan = node.getElementsByClassName('tiny-top')[0];

		console.log('serverTime = ' + serverTime);
    
    var startDate = document.getElementById('datetime').innerHTML;
    
		// wyłuszczanie dnia i godziny z tego tekstu
		var rx1 = /^(.*)(\d+)(.*?)(\d+:\d+:\d+)(.*)$/; // regexp który wycina z treści w stylu "Day 3338 Time: 0:35:27"
		var parts = rx1.exec(startDate);
		// [1] "day:", [2] dayCount (i.e. '3333'), [3] "time", [4] timeCount(i.e. '3:06:05')
		var day = parts[2];
		var time = parts[4];
		var timeSplit = time.split(':');
		var hour = timeSplit[0];
		var min = timeSplit[1];
		var sec = timeSplit[2];
		
		var ticks = [];

		ticks[0] = addTick('sailing', 0, 44, 0);
		ticks[1] = addTick('travel', 1, 10, 0);
		ticks[2] = addTick('project', 1, 40, 0);
		 
    var x = 0;
		var systemTime = Math.floor(new Date().getTime()/1000);
		setInterval(function (){clockTick();}, 500);
		
		function clockTick() {
			var newTime = Math.floor(new Date().getTime()/1000);
			if (newTime == systemTime) {
				return;
			}
			systemTime = newTime;
		
			var to0 = (((ticks[0]['min']*1+36)-min)*60+ticks[0]['sec']*1-sec)%(36*60); // 10:20    -> 14:00
			var to1 = (((ticks[1]['min']*1+36)-min)*60+ticks[1]['sec']*1-sec)%(36*60);
			var to2 = (((ticks[2]['min']*1+36)-min)*60+ticks[2]['sec']*1-sec)%(36*60);
			var used = 0;
			if (to0 < to1){
				if(to2 < to0)
					used = 2;
			}
			else {
				if (to1 < to2)
					used = 1;
				else used = 2;
			}
			toTick = ((ticks[used]['min']*60+ticks[used]['sec']+36*60-min*60-sec)*5-x)%(3600*3);
			// migający alarm gdy tura się zbliża
			if (toTick*1 < 10*60){
				datespan.style.background = '#' + (Math.round(toTick)%2 ? 'AA':'FF') + '0000'; // miganie komunikatu
			} else {
				datespan.style.background = 'none';
			}
			
			var hoursLeft = '';
			var minsLeft = Math.floor(toTick/60);
			var secsLeft = Math.round(toTick%60);
			if (minsLeft >=60){
				hoursLeft =  Math.floor((minsLeft/60)) + ':';
				minsLeft %= 60;
			}
			if (minsLeft < 10 && hoursLeft != '')
				minsLeft = '0' + minsLeft;
			if (secsLeft < 10)
				secsLeft = '0' + secsLeft;
			
			var timeLeft = hoursLeft + minsLeft + ':' + secsLeft;
			datespan.innerHTML = lang[ln]['clockTimeLeft']+ ' <b>' + timeLeft + '</b> ' + lang[ln]['clockUntil'] + ' ' + lang[ln]['clockTick' + ticks[used]['name']];
      
    
			// refresh every second, but second in cantr is 5 times longer
			x++;
			if (x < 5)
				return;
			x = 0;
			
			sec++;
			if (sec >= 60){
				sec = 0;
				min++;
					if (min >= 36){
						min = 0;
						hour++;
						if (hour >= 8){
							day++;
						}
					}
				}
			// setTime();
      
		}
		
		

		
		
		function addTick(tickName, tickHour, tickMin, tickSec){
			//console.log(tickHour + ' ' + tickMin + ' ' + tickSec);
			var s_tickTime = tickHour*3600;
			s_tickTime += tickMin*60;
			s_tickTime = s_tickTime + tickSec*1;
			// tymczasowo
			//console.log('tickName: ' + tickName);
			//console.log('serverTime: ' + serverTime + ' s_tickTime: ' + s_tickTime);
			var rlSecondsToNextTick = ((s_tickTime+24*60*60 - serverTime)%(3600*3)); // czas do najbliższego ticku w sekundach
			var cantrSecsToNextTick = rlSecondsToNextTick/5;
			//console.log('cantrSecsToNextTick ' + cantrSecsToNextTick);
			var cantrMinsToNextTick = Math.floor(cantrSecsToNextTick/60);
			cMin = (min*1+cantrMinsToNextTick*1)%36;
			cSec = Math.round(sec*1+cantrSecsToNextTick*1%60);
			if (cSec >= 60){ // if na wypadek gdyby sec+reszta z dzielenia SecsToNextTick dawała razem pełną minutę
				cSec -= 60;
				cMin++;
			}
			
			var resArr = [];
			//console.log('cantrTime ' + cMin + ' ' + cSec);
			resArr['min'] = cMin;
			resArr['sec'] = cSec;
			resArr['name'] = tickName;
			return resArr;
		}
		
		
	}
	
	//////
	////// KONIEC ZEGAREK
	////// POCZĄTEK PASEK NARZĘDZI POSTACI
	//////

	function charMenuToolbar() {
		var toolbar = document.createElement('div');
		toolbar.style.display = "block";
		toolbar.style.width = "60px";
		toolbar.style.backgroundColor = "#040";
		toolbar.style.padding = "3px";
		toolbar.style.position = "fixed";
    var width = window.innerWidth || d.documentElement.clientWidth || d.body.clientWidth;
    var pos = width/2 + 350 + 60;
		toolbar.style.top = "20px";
		toolbar.style.left = pos + "px";

		var oldCharMenu = document.getElementById('character_menu');
		var els = oldCharMenu.getElementsByTagName('a');
		for (var i=0; i < els.length; i++) {
			var newEl = els[i].cloneNode(true);
			toolbar.appendChild(newEl);
		}
		var backToPlayer = document.getElementById('player_menu').getElementsByTagName('a')[0];
		toolbar.appendChild(backToPlayer.cloneNode(true));
		
		document.body.appendChild(toolbar);
	}

	//////
	////// KONIEC PASEK NARZĘDZI POSTACI
	////// POCZĄTEK WYBORU JĘZYKA ZA PIERWSZYM RAZEM
	//////
	
	function langSelection() {
		var cent = document.body.getElementsByClassName('playerTopBar')[0];

    var trForBox = document.createElement('div');
		var langSpanBefore = document.createElement('p');
		var langSpanAfter = document.createElement('p');
    langSpanBefore.style.margin = '3px';
    langSpanAfter.style.margin = '3px';
		var langDiv = document.createElement('div');
    langDiv.colSpan = 2;
		langDiv.style.backgroundColor = '#008800';
		langDiv.style.padding = '2px';
		langSpanBefore.innerHTML = lang[ln]['langSelectionTextBefore'];
		langSpanAfter.innerHTML = lang[ln]['langSelectionTextAfter'];
    trForBox.appendChild(langDiv);
		cent.appendChild(trForBox);
    
		langDiv.appendChild(langSpanBefore);
		langDiv.appendChild(languageNode());
		langDiv.appendChild(langSpanAfter);
	}
	
	//////
	////// KONIEC WYBORU JĘZYKA ZA PIERWSZYM RAZEM
	////// POCZĄTEK OPCJE
	//////
	
	function optionPanel(){
		var node = document.body;
		node = node.getElementsByClassName('playerTopBar')[0]; // node - wszystkie elementy z <center>
		optionsDiv = document.createElement('div');
		
		var optionTD = document.createElement('div');
		var showOptions = document.createElement('p');
		showOptions.innerHTML = '[' + lang[ln]['optionsButton'] + ']';
		optionsDiv.appendChild(showOptions);
		optionsDiv.appendChild(optionTD);
		
		node.appendChild(optionsDiv);
		
		showOptions.style.textAlign = 'right';
		
		showOptions.addEventListener("click", function() {
			if (optionTD.style.display == 'none')
				optionTD.style.display = 'block';
			else optionTD.style.display = 'none';
		}, true);
		
		
		var CE_Desc = document.createElement('span');
		CE_Desc.style.fontSize = "21px";
		CE_Desc.innerHTML = lang[ln]['optionsTitle'];
		
		
		optionTD.appendChild(CE_Desc);
		
		var oForm = document.createElement('form');
		optionTD.appendChild(oForm);
		optionTD.style.display = 'none';
		optionTD.style.textAlign = 'left';
		optionTD.style.background = "#006600";
		
		
		addCheckbox(oForm, "EventsFilter", lang[ln]['optionsEventsFilter']);
		addCheckbox(oForm, "GroupEvents", lang[ln]['optionsGroupEvents']);
		addCheckbox(oForm, "ColorNames", lang[ln]['optionsColorNames']);
		addCheckbox(oForm, "ShortNames", lang[ln]['optionsShortNames']);
		addCheckbox(oForm, "Clock", lang[ln]['optionsClock']);
		addCheckbox(oForm, "HighlightedBuildingsVehicles", lang[ln]['optionsBookmarkBuildingsVehicles']);
		addCheckbox(oForm, "NotesCheckBox", lang[ln]['optionsNotesCheckBox']);
		addCheckbox(oForm, "List", lang[ln]['optionsListObjects']);
		addCheckbox(oForm, "GroupObjects", lang[ln]['optionsGroupObjects']);
		addCheckbox(oForm, "LineEventsNotFocused", lang[ln]['optionsLineEventsNotFocused']);
		addCheckbox(oForm, "CharMenuToolbar", lang[ln]['optionsCharMenuToolbar']);
		
		optionTD.appendChild(languageNode());
		
		optionTD.appendChild(createImportExportArea());
				
		function addCheckbox(upForm, optionName, descText){
			var enableOption = document.createElement('input');
			enableOption.type = 'checkbox';
			enableOption.name = "CE_enable" + optionName;
			var optionDesc = document.createElement('span');
			optionDesc.innerHTML = descText + "<br>";
			enableOption.checked = true;
			if (localStorage.getItem('CE_enable' + optionName) != null && localStorage.getItem('CE_enable' + optionName) == 'false')
				enableOption.checked = false;
				
			enableOption.addEventListener("click", function(){
				localStorage.setItem('CE_enable' + optionName, enableOption.checked);
			}, true);
			
			upForm.appendChild(enableOption);
			upForm.appendChild(optionDesc);
		}
		
		function createImportExportArea() {
			var importExportDiv = document.createElement('div');
			var ietextArea = document.createElement('textarea');
			ietextArea.cols = 83;
			ietextArea.rows = 5;
			
			var importButt = document.createElement('input');
			importButt.type = 'button';
			importButt.value = "import";
			var exportButt = document.createElement('input');
			exportButt.type = 'button';
			exportButt.value = "export";
			
			exportButt.addEventListener("click", function() {
				var values = {};
				for (var i=0;i<localStorage.length;i++) {
					var valueName = localStorage.key(i);
					values[valueName] = localStorage.getItem(valueName);
				}
				ietextArea.value = JSON.stringify(values);
			}, true);
			
			importButt.addEventListener("click", function() {
				try {
					var values = JSON.parse(ietextArea.value);
				} catch (e) { // input is invalid
					return;
				}
				for (idx in values) {
					if (localStorage.getItem(idx) === null) { // item doesn't exist so import
						localStorage.setItem(idx, values[idx]);
					}
				}
			}, true);
			
			importExportDiv.appendChild(ietextArea);
			importExportDiv.appendChild(importButt);
			importExportDiv.appendChild(exportButt);
			return importExportDiv;
		}
		
		
	}
	
	function languageNode(){
		var selectNode = document.createElement('select');
		var noOp = addLangOption("--");
		var enOp = addLangOption('en');
		var plOp = addLangOption('pl');
		// var deOp = addOption('de');
		
		selectNode.addEventListener("change", function(){
				ln = selectNode.options[selectNode.selectedIndex].value;
				setLanguage(ln);
			}, true);
		
		function addLangOption(language){
			var optionNode = document.createElement('option');
			optionNode.name = language;
			optionNode.innerHTML = language;
			optionNode.value = language;
			if (language == getLanguage())
				optionNode.selected = true;
			selectNode.appendChild(optionNode);
			return optionNode;
		}
		return selectNode;
	}
	
	//////
	////// KONIEC OPCJE
	//////
	
		/*
			posX posY functions - to get global absolute position of the tag
		*/
		function posX(obj){
		var curleft = 0;
		if(obj.offsetParent)
			while(1){
			  curleft += obj.offsetLeft;
			  if(!obj.offsetParent)
				break;
			  obj = obj.offsetParent;
			}
		else if(obj.x)
			curleft += obj.x;
		return curleft;
		}

		function posY(obj){
		var curtop = 0;
		if(obj.offsetParent)
			while(1){
			  curtop += obj.offsetTop;
			  if(!obj.offsetParent)
				break;
			  obj = obj.offsetParent;
			}
		else if(obj.y)
			curtop += obj.y;
		return curtop;
		}

	
	
	function get4digits(){
		var ownCharIdNode = document.getElementById('ownCharId'); // center nr 1 - tu jest belka postaci
		return (ownCharIdNode.value)%10000; // only last 4 digits for safety reasons, ya know
	}
	
	function createHeaderTitle(title, pts){
		var titleDiv = document.createElement('div');
		titleDiv.innerHTML = '<b>' + title + '</b>';
		titleDiv.style.background = '#008800';
		titleDiv.style.fontSize = pts + 'pt';
		titleDiv.style.textAlign = 'center';
		return titleDiv;
	}
	
	String.prototype.hashCode = function(){
		var hash = 0;
		if (this.length == 0) return hash;
		for (i = 0; i < this.length; i++) {
			char = this.charCodeAt(i);
			hash = ((hash<<5)-hash)+char;
			hash = hash & hash; // Convert to 32bit integer
		}
		return hash;
	}
	
	
	/*
	*	SPRAWDZANIE NA KTÓREJ STRONIE SIĘ ZNAJDUJESZ
	*/
	
	function isWrit(tresc, arr){
		var isW = false;
		for (idx=0; idx < arr.length;idx++){
				if (tresc.indexOf(arr[idx]) >= 0)
					isW = true;
		}
		return isW;
	}
	
	function cInput(itype, iname, ivalue){
		var ci = document.createElement('input');
		ci.type = itype;
		ci.name = iname;
		ci.value = ivalue;
		return ci;
	}

	
	
	function checkStrona(){
	var node = document.body;
	node = node.getElementsByClassName("titlebar"); // node - wszystkie elementy z <div>
	if (node.length > 0){ // czy istnieje pierwszy div
		for (var i = 0; i < node.length; i++) {
			if (isWrit(node[i].innerHTML, pageMainPage)) {
				return ('main_page');
			}
		}
	}
	
	if(node.length > 1){ // czy w ogóle istnieje czwart center
	var code = node[1].innerHTML; // kod <center> nr 4 czyli tego z belką w której jest nazwana podstrona	
	
	if(isWrit(code, pageObjects))
		return ('objects');
	if(isWrit(code, pageLocation))
		return ('location');
	if(isWrit(code, pageInventory))
		return ('inventory');
	if(isWrit(code, pageBuildingsAndVehicles))
		return ('building_vehicles');
	if(isWrit(code, pageBuildingsAndVehiclesInside))
		return ('inside_building');
	if(isWrit(code, pageEvents))
		return ('events_page');
	}
	
	var header = node[0];
	if (header != null){
	var code = header.innerHTML;
		// gdy coś podnosisz
		if (isWrit(code, pageTakingInfo)){
			return ('take_resources');
		}
		if (isWrit(code, pageEmptyEnvelope)){
			return ('empty_envelope');
		}
		if (isWrit(code, pageWriteNote)){
			return ('write_note');
		}
		if (isWrit(code, pageRetrieveFromContainer)){
			return ('retrieve_from_container');
		}
		if (isWrit(code, pageShop)){
			return ('shop');
		}
		if (isWrit(code, pageStorageResources)){
			return ('into_container');
		}
		if (isWrit(code, pageSelAmountToProject)){
			return ('project_size');
		}
		if (isWrit(code, pageGiveResources)){
			return ('give_resources');
		}
		if (isWrit(code, pageRepair)){
			return ('repair');
		}
	// jeśli żadnej nas interesującej nie znajdzie
	}
	
	return ('no');
}

function changeName(){
	var cantrTitle = document.body.getElementsByTagName('p')[0];
	cantrTitle.innerHTML = 'Cantr II<span style="font-size:10px;text-shadow: -1px 0 #444444, 0 1px #444444, 1px 0 #444444, 0 -1px #444444;"> enhanced</span>';
}

function getCap(){
	var cnode = document.body.getElementsByTagName('center')[0];
	var capTD = cnode.getElementsByTagName('tr')[4].getElementsByTagName('td')[1];
	var capRexp = /\d+/;
	var capText = capRexp.exec(capTD.innerHTML);
	if (capText)
		return capText[0];
	else return 0;
}

function enabledInStorage(itemName) {
	if (enabledInStorage.items === undefined) {
		enabledInStorage.items = [];
	}
	
	if (enabledInStorage.items[itemName] !== undefined) {
		return enabledInStorage.items[itemName];
	} else {
		var value = localStorage.getItem('CE_enable' + itemName);
		var result = (value == null || value == 'true');
		enabledInStorage.items[itemName] = result;
		return result;
	}
}

function getLanguage(){
	var langResult = localStorage.getItem('CE_language');
	if (langResult != null)
		return langResult;
	return 'en';
}

function setLanguage(setLan) {
	if (lang[setLan] === undefined) {
		setLan = "en";
	}
	localStorage.setItem('CE_language', setLan);
}


// pobieranie języka POSTACI

function getCharacterLanguage(){
	var tab = document.body.getElementsByTagName('table')[0];
	var activeReceivedText = tab.getElementsByTagName('td')[1].getElementsByTagName('span')[0]
	// tekst ile osób było aktywnych w ciągu ostatnich x minut
	
	for (var index in activeText){
		if (activeReceivedText.innerHTML.indexOf(activeText[index]) >= 0){
			return index;
		}
	}
	return 'en'; // default
}

function getCharId() {
	return document.getElementById('ownCharId').value;
}


// tu zaczyna działać tak naprawdę po raz pierwszy

var scriptStartTime = new Date().getTime();

var strona = checkStrona(); // sprawdzamy czy znajdujemy się na której ze stron "znaczących" - takich na których skrypt ma coś robić

changeName();


if (strona == 'objects' && enabledInStorage('ListObjects')){
	listObjects();
}

if (strona == 'objects' && enabledInStorage('GroupObjects')){
	groupObjects();
}

if (strona == 'inventory' && enabledInStorage('NotesCheckBox')){
	notesCheckBoxInventory();
}

if (strona == 'empty_envelope' && enabledInStorage('NotesCheckBox')){
	notesCheckBoxEnvelopes();
}

if (strona == 'write_note' && enabledInStorage('NotePre')){
	notePreview();
}

if (strona == 'main_page' && localStorage.getItem('CE_language') == null)
	langSelection();

if (strona == 'main_page'){
	optionPanel();
}

if ((strona == 'building_vehicles' || strona == 'inside_building') && enabledInStorage('BookmarkBuildingsVehicles')){
	bookmarkBuildingsVehicles();
}

if (strona == 'events_page' && enabledInStorage('EventsFilter')){
	eventsFilter();
}

if (enabledInStorage('Clock')){
	cantrClock();
}

if (['objects', 'location', 'inventory', 'building_vehicles', 'inside_building',
	'events_page'].indexOf(strona) != -1 && enabledInStorage('CharMenuToolbar')) {
	charMenuToolbar();
}

console.log("Cantr Enhanced execution time: " + (new Date().getTime() - scriptStartTime));