Greasy Fork is available in English.

Cantr Enhanced

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

// ==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));