Greasy Fork is available in English.

Ikariam Enhanced UI

Enhancements for the user interface of Ikariam.

  1. // ==UserScript==
  2. // @name Ikariam Enhanced UI
  3. // @description Enhancements for the user interface of Ikariam.
  4. // @namespace Tobbe
  5. // @author Tobbe
  6. // @version 4.2
  7. // @license MIT License
  8. //
  9. // @name:de Ikariam Enhanced UI
  10. // @description:de Verbesserungen der Oberfläche von Ikariam.
  11. //
  12. // @run-at document-idle
  13. //
  14. //
  15. // @include /https?:\/\/s[0-9]*-[a-z]{2}\.ikariam\.gameforge\.com\/.*/
  16. //
  17. // @require https://greatest.deepsurf.us/scripts/5574-ikariam-core/code/Ikariam%20Core.js?version=669395
  18. //
  19. // @connect greatest.deepsurf.us
  20. //
  21. // @grant unsafeWindow
  22. // @grant GM_setValue
  23. // @grant GM.setValue
  24. // @grant GM_getValue
  25. // @grant GM.getValue
  26. // @grant GM_deleteValue
  27. // @grant GM.deleteValue
  28. // @grant GM_listValues
  29. // @grant GM.listValues
  30. // @grant GM_getResourceText
  31. // @grant GM.getResourceText
  32. // @grant GM_xmlhttpRequest
  33. // @grant GM.xmlHttpRequest
  34. //
  35. // @bug Opera & Chrome Zooming with the mouse is not possible with "Shift" as access key.
  36. // @bug Opera & Chrome No updating of the missing resources is possible due to a missing modification listener.
  37. // @bug All The selected island is not centered in world view.
  38. // @bug All If you are zooming to more than 100%, the view is not centered correctly after a page reload.
  39. //
  40. // @history 4.2 Release: 10.02.2019
  41. // @history 4.2 Core: Update to Version 3.2.1 - Greasy Fork prohibits update check intervals smaller than 24 hours
  42. // @history 4.2 Core: Update to Version 3.2.1 - Include all translations in the script and remove external dependencies for translations
  43. // @history 4.2 Language: Include all translations in the script and remove external dependencies for translations
  44. // @history 4.2 Language: Update Russian translation
  45. //
  46. // @history 4.1.0.1 Release: 14.11.2017
  47. // @history 4.1.0.1 Core: Update to Version 3.1.0.1 - Fix issue with Greasemonkey 4.0 and incorrect link to translation files
  48. // @history 4.1.0.1 Language: Update Greek translation
  49. //
  50. // @history 4.1 Release: 12.11.2017
  51. // @history 4.1 Core: Update to Version 3.1 - Support translations in Greasemonkey 4.0
  52. //
  53. // @history 4.0 Release: 10.11.2017
  54. // @history 4.0 Core: Update to Version 3.0 - Adjust to work with Greasemonkey 4.0 and Firefox 57
  55. // @history 4.0 Change: Adjust the script to work with Greasemonkey 4.0 and Firefox 57.
  56. // @history 4.0 Bugfix: Global messages break embedded messages preview.
  57. // @history 4.0 Bugfix: Formatting of income table was changed.
  58. //
  59. // @history 3.4 Release: 19.02.2017
  60. // @history 3.4 Core: Update to Version 2.3.3 - Bug fix (crew conversion broken)
  61. // @history 3.4 Feature: Up to 60 characters of messages are displayed in the message overview.
  62. // @history 3.4 Feature: Link barracks / shipyard from troop overview / dismiss units screen.
  63. // @history 3.4 Bugfix: No jumping header bar anymore due to MMO links.
  64. // @history 3.4 Bugfix: Troop information was displayed incorrectly.
  65. //
  66. // @history 3.3 Release: 05.06.2016
  67. // @history 3.3 Feature: Add @connect information to avoid requests from Tampermonkey.
  68. // @history 3.3 Feature: Daily expenses in resource information if amount is negative.
  69. // @history 3.3 Bugfix: Tooltip formatting for resource information broken.
  70. // @history 3.3 Bugfix: Formatting of direct tooltip in military advisor broken.
  71. // @history 3.3 Bugfix: Foreign troops are incorrect displayed in troop information.
  72. //
  73. // @history 3.2.2 Release: 02.02.2016
  74. // @history 3.2.2 Core: Update to Version 2.3.2 - Bug fix (permanent reload of crew conversion)
  75. //
  76. // @history 3.2.1 Release: 27.01.2016
  77. // @history 3.2.1 Core: Update to Version 2.3.1 - Bug fixes
  78. //
  79. // @history 3.2 Release: 27.01.2016
  80. // @history 3.2 Core: Update to Version 2.3 - Bug fixes
  81. // @history 3.2 Feature: Let the script also run on SSL encripted Ikariam page.
  82. // @history 3.2 Bugfix: In very rare cases it was possible that the script was to fast and thus did not work.
  83. // @history 3.2 Language: French translation added (incomplete).
  84. //
  85. // @history 3.1 Release: 14.10.2015
  86. // @history 3.1 Core: Update to Version 2.2 - Bug fixes and user specific options
  87. // @history 3.1 Feature: Player specific signatures in messages.
  88. // @history 3.1 Change: Remove easy circular message functionality as it is implemented directly in Ikariam now.
  89. // @history 3.1 Language: Turkish translation added (incomplete).
  90. //
  91. // @history 3.0.3 Release: 20.03.2015
  92. // @history 3.0.3 Bugfix: Town name in unit information incorrect.
  93. //
  94. // @history 3.0.2 Release: 08.03.2015
  95. // @history 3.0.2 Bugfix: Wrong time display for last reset of highscore information.
  96. // @history 3.0.2 Bugfix: Start piracy raid icon was resized.
  97. //
  98. // @history 3.0.1 Release: 07.03.2015
  99. // @history 3.0.1 Language: Updated Greek translation.
  100. // @history 3.0.1 Bugfix: Language key in message options.
  101. // @history 3.0.1 Bugfix: Alliance member data stored at same place for all alliance members.
  102. //
  103. // @history 3.0 Release: 05.03.2015
  104. // @history 3.0 Language: Russian translation added (incomplete).
  105. // @history 3.0 Language: Italian translation added (incomplete).
  106. // @history 3.0 Language: Greek translation added (incomplete).
  107. // @history 3.0 Change: Implementation of Ikariam Core - rewrote the complete code.
  108. // @history 3.0 Change: Cleared the update history to use the Ikariam Core labels.
  109. // @history 3.0 Bugfix: Diverse graphic errors.
  110. // @history 3.0 Bugfix: Broken in Firefox and Chrome.
  111. // @history 3.0 Due to rename of script: Manually deleting old script necessary.
  112. //
  113. // @history 2.6 Release: 12.10.2014
  114. // @history 2.6 Bugfix: Script options were broken.
  115. //
  116. // @history 2.6 Release: 19.08.2014
  117. // @history 2.5 Bugfix: Game language is recognized again.
  118. // @history 2.5 Bugfix: Works now in Greasemonkey 2.0+
  119. // @history 2.5 Change: Checks now for updates on Greasy Fork.
  120. // @history 2.5 Removed code parts for mobile version.
  121. // @history 2.5 Removed alliance page improvement, as fixed in Ikariam v0.5.13
  122. //
  123. // @history 2.6 Release: 11.09.2013
  124. // @history 2.4 Bugfix: New Ikariam domain -> script can now be used with this domain
  125. //
  126. // @history 2.3 Release: 12.04.2013
  127. // @history 2.3 Feature: Formatting troop lists for posting in forums / personal messages.
  128. // @history 2.3 Feature: Filling level of warehouse as bar in town view.
  129. // @history 2.3 Feature: Link to mines / town hall when clicking on resources / citizens.
  130. // @history 2.3 Change: New versioning system.
  131. // @history 2.3 Bugfix: Some characters in links were not decoded correctly.
  132. // @history 2.3 Bugfix: Watching a foreign city causes a abortion of the script.
  133. // @history 2.3 Bugfix: The city dropdown sometimes was zoomed in world view.
  134. // @history 2.3 Bugfix: Removed obsolete CSS styles for Firefox.
  135. // @history 2.3 Adjustments in the language files.
  136. // @history 2.3 Violent Monkey brings Greasemonkey functions to Opera.
  137. //
  138. // @history 2.2.1 Release: 11.10.2012
  139. // @history 2.2.1 Feature: Smaller icons in direct military tooltip.
  140. // @history 2.2.1 Bugfix: Problems with update check and version numbers >= 10.
  141. // @history 2.2.1 Bugfix: Problems with another script.
  142. // @history 2.2.1 Bugfix: Problems with a wrong style in island view.
  143. //
  144. // @history 2.2 Release: 10.10.2012
  145. // @history 2.2 Feature: Message signature can be set.
  146. // @history 2.2 Feature: Button for faster sending of circular messages.
  147. // @history 2.2 Feature: Make links in messages clickable.
  148. // @history 2.2 Feature: Show town information of colonizing cities.
  149. // @history 2.2 Feature: Information about cargo / fleets is displayed directly in military view.
  150. // @history 2.2 Feature: Script options: Sections on the script tab can be folded.
  151. // @history 2.2 Bugfix: Tooltips with mouseover were not clickable anymore.
  152. // @history 2.2 Changes in code for better overview.
  153. //
  154. // @history 2.1.1 Release: 01.10.2012
  155. // @history 2.1.1 Feature: Different styles for income in town view.
  156. // @history 2.1.1 Feature: Remaining resources after upgrade.
  157. // @history 2.1.1 Feature: Improved style for external alliance pages.
  158. // @history 2.1.1 Feature: Refresh the missing / remaining resources in construction view automatically.
  159. //
  160. // @history 2.1 Release: 23.09.2012
  161. // @history 2.1 Feature: Show the missing resources in construction view.
  162. // @history 2.1 Feature: Show the hourly income directly in town view and add the daily production as popup.
  163. // @history 2.1 Feature: Don't center town information in the town advisor.
  164. // @history 2.1 Feature: Save the highscore data of alliance members and compare it with the actual value.
  165. // @history 2.1 Bugfix: There was an error with a missing language package and seperators.
  166. // @history 2.1 Bugfix: Some things in worldview were not resized correctly.
  167. // @history 2.1 Prevent more than one script execution.
  168. // @history 2.1 Prevent more than one script option panel (the script option panel now is usable for other scripts, too).
  169. //
  170. // @history 2.0.1 Release: 27.08.2012
  171. // @history 2.0.1 Bugfix: Zooming was broken.
  172. // @history 2.0.1 Bugfix: Dropdown menus created by the script were broken.
  173. // @history 2.0.1 Bugfix: Tooltips in in Alliance / Military view were not shown correctly.
  174. //
  175. // @history 2.0 Release: 18.07.2012
  176. // @history 2.0 Language: Latvian translation
  177. // @history 2.0 Feature: Cross-browser compatibility.
  178. // @history 2.0 Feature: Possibility to hide the update hint for a new script version.
  179. // @history 2.0 Bugfix: Resizing the owner state in world view was broken.
  180. // @history 2.0 Some changes in the code for easier copying of functions which should be used by more than one script.
  181. //
  182. // @history 1.7 Release: 12.06.2012
  183. // @history 1.7 Feature: Resizing banners when zooming is possible in city view, too.
  184. // @history 1.7 Feature: The zoom buttons are available in world view, too.
  185. // @history 1.7 Feature: Zooming with the mouse scroll is possible again (now with key, standard is ctrl).
  186. // @history 1.7 Change: Changes in the option panel due to the new zooming function features.
  187. // @history 1.7 Bugfix: If resizing is enabled, zooming with the buttons will resize the banners, too.
  188. // @history 1.7 Bugfix: The chat will not cause to much executions of script functions.
  189. // @history 1.7 The language texts are integrated as resources, so that there is shorter code.
  190. // @history 1.7 Replace the GM_* functions by myGM.* to expand them easy and add new.
  191. //
  192. // @history 1.6 Release: 05.06.2012
  193. // @history 1.6 Feature: Possibility to hide only the bird swarm animation.
  194. // @history 1.6 Feature: Easier upkeep reduction table.
  195. // @history 1.6 Feature: Enhanced zoom function using the Ikariam zoom function.
  196. // @history 1.6 Due to the use of Ikariam functions the code could be reduced.
  197. // @history 1.6 Code enhancements for shorter code.
  198. //
  199. // @history 1.5.1.1 Release: 25.05.2012
  200. // @history 1.5.1.1 Bugfix: Not all occurrences of hidden were changed.
  201. //
  202. // @history 1.5.1 Release: 24.05.2012
  203. // @history 1.5.1 Bugfix: Name of a class (hidden) is used by GF.
  204. //
  205. // @history 1.5 Release: 24.05.2012
  206. // @history 1.5 Feature: Options panel to enable/disable funtions and set settings.
  207. // @history 1.5 Feature: Update interval can be set.
  208. // @history 1.5 Feature: Manually check for updates.
  209. // @history 1.5 Feature: Zoom function without resizing the whole view.
  210. // @history 1.5 Feature: Move loading circle to another position.
  211. // @history 1.5 Feature: Show tooltip in alliance / military view on mouseover.
  212. // @history 1.5 Change: Code better commented. More comments, so that it is easier to understand.
  213. // @history 1.5 Bugfix: Changed *.gif to *.png.
  214. // @history 1.5 Version numbers adjusted.
  215. //
  216. // @history 1.4.1 Release: 01.05.2012
  217. // @history 1.4.1 Feature: Support for mobile interface.
  218. // @history 1.4.1 Bugfix: Fixed bug with scrollbar in finances view.
  219. //
  220. // @history 1.4 Release: 20.04.2012
  221. // @history 1.4 Feature: Ready for 0.5.0, but also supports 0.4.5 furthermore.
  222. // @history 1.4 Feature: Implemented support for different languages.
  223. // @history 1.4 Feature: Enhanced script updater.
  224. // @history 1.4 Change: Cleaned up code.
  225. // @history 1.4 Change: Rename the script to "Enhanced UI".
  226. // @history 1.4 Change: Change the namespace to "Tobbe".
  227. // @history 1.4 Because of the change of namespace and name you have to delete the old script manually!
  228. //
  229. // @history 1.3.3 Release: 11.04.2011
  230. // @history 1.3.3 Bugfix: Problem with negative numbers and 0.4.2.4 fixed.
  231. //
  232. // @history 1.3.2 Release: 15.01.2011
  233. // @history 1.3.2 Feature: Own script updater.
  234. // @history 1.3.2 Change: Remove everything what refered to other scripts.
  235. //
  236. // @history 1.3.1 Release: 15.01.2011
  237. // @history 1.3.1 Change: New script updater.
  238. //
  239. // @history 1.3 Release: 14.01.2011
  240. // @history 1.3 Change: Remove the script updater (Because of the problem with Greasemonkey scripts).
  241. //
  242. // @history 1.2.1 Release: 28.12.2010
  243. // @history 1.2.1 Change: New style of update panel.
  244. // @history 1.2.1 Bugfix: Bug with ',' as seperator fixed.
  245. //
  246. // @history 1.2 Release: 09.10.2010
  247. // @history 1.2 Feature: Income in 24h added.
  248. // @history 1.2 Change: Cleaned up code.
  249. //
  250. // @history 1.1 Release: 13.04.2010
  251. // @history 1.1 Feature: Update check implemented.
  252. //
  253. // @history 1.0 Release: 12.04.2010
  254. // @history 1.0 Initial release.
  255. // ==/UserScript==
  256.  
  257. /**
  258. * Instantiate a new set of enhancement functions.
  259. * {@link https://greatest.deepsurf.us/scripts/4369-ikariam-enhanced-ui Script on Greasy Fork}
  260. * {@link https://github.com/IkaScripts/IkariamEnhancedUI Script on GitHub}
  261. *
  262. * @version 4.2
  263. * @author Tobbe <ikascripts@tobbexiv.de>
  264. *
  265. * @global
  266. *
  267. * @class
  268. * @classdesc Enhancements for the user interface of Ikariam.
  269. *
  270. * @param {IkariamCore} $
  271. * An instance of the Ikariam Core.
  272. */
  273. function EnhancedUI(IC) {
  274. /**
  275. * Script toolbar.
  276. *
  277. * @type {element}
  278. */
  279. var ge_toolbar = IC.myGM.addElement('div', IC.myGM.$('#GF_toolbar'), { 'id': 'toolbar' }, true, IC.myGM.$('#GF_toolbar ul'));
  280. IC.myGM.addStyle(
  281. '#GF_toolbar > ul { width: auto !important; text-align: center !important; pointer-events: none; } \
  282. #GF_toolbar > ul > * { pointer-events: auto; } \
  283. #GF_toolbar #mmoNewsticker { display: inline-block !important; position: relative !important; } \
  284. #GF_toolbar #mmoNewsticker > ul { width: 300px !important; } \
  285. #' + IC.myGM.prefix + 'toolbar { float: right; } \
  286. #' + IC.myGM.prefix + 'toolbar > div { display: inline-block; position: relative; float: right; margin: 0px 5px; }',
  287. 'scriptToolbar'
  288. );
  289. IC.Options.addWrapper('diverseOptions', IC.Language.$('diverse.options.wrapperTitle'));
  290. IC.con.groupCollapsed('IkariamEnhancedUI initalization ...');
  291. IC.con.logTimeStamp('IkariamEnhancedUI: toolbar and general styles created');
  292. // General functions to enhance the view.
  293. (function() {
  294. IC.Options.addWrapper('enhancedView', IC.Language.$('view.options.wrapperTitle'));
  295. // Move the loading circle to the breadcrumb area.
  296. IC.Options.addCheckbox('moveLoadingCircle', 'enhancedView', 1, true, IC.Language.$('view.options.moveLoadingCircle'), {
  297. changeCallback: function(ib_newValue) {
  298. if(ib_newValue === true) {
  299. IC.myGM.addStyle(
  300. '#js_worldBread { margin-left: 16px !important; } \
  301. #loadingPreview { transform: scale(0.5); -webkit-transform: scale(0.5); left: 35px !important; top: 141px !important; }',
  302. 'enhancedView_moveLoadingCircle'
  303. );
  304. return;
  305. }
  306. IC.myGM.removeStyle('enhancedView_moveLoadingCircle');
  307. }
  308. });
  309. // Hide the flying bird swarm.
  310. IC.Options.addCheckbox('hideBirds', 'enhancedView', 1, true, IC.Language.$('view.options.hideBirds'), {
  311. changeCallback: function(ib_newValue) {
  312. if(ib_newValue === true) {
  313. IC.myGM.addStyle(
  314. '.bird_swarm { display: none; }',
  315. 'enhancedView_hideBirds'
  316. );
  317. return;
  318. }
  319. IC.myGM.removeStyle('enhancedView_hideBirds');
  320. }
  321. });
  322. // Bind the town name and date to the top of the row in the town advisor.
  323. IC.Options.addCheckbox('noVerticalCenterInTownAdvisor', 'enhancedView', 1, true, IC.Language.$('view.options.noVerticalCenterInTownAdvisor'), {
  324. changeCallback: function(ib_newValue) {
  325. if(ib_newValue === true) {
  326. IC.myGM.addStyle(
  327. '#inboxCity td { vertical-align: top !important; }',
  328. 'enhancedView_noVerticalCenterInTownAdvisor'
  329. );
  330. return;
  331. }
  332. IC.myGM.removeStyle('enhancedView_noVerticalCenterInTownAdvisor');
  333. }
  334. });
  335. })();
  336. IC.con.logTimeStamp('IkariamEnhancedUI: view functions created');
  337. // Functions for the island view.
  338. (function() {
  339. /**
  340. * Storage for the colonizing city info functions.
  341. *
  342. * @type {object}
  343. */
  344. var _go_colonizingCityInfo = new function() {
  345. /**
  346. * Add the link to show the colonizing city information.
  347. */
  348. var _lf_doShowColonizingCityInfo = function() {
  349. var la_colonizingCities = IC.myGM.$$('.level0');
  350. la_colonizingCities.forEach(function(le_colonizingCity) {
  351. var ls_locationId = le_colonizingCity.id.replace(/\D/g, '');
  352. var ls_cityId = IC.ika.getScreen().data.cities[ls_locationId].id;
  353. IC.myGM.$('#js_cityLocation' + ls_locationId + 'Link').href = '?view=cityDetails&destinationCityId=' + ls_cityId;
  354. });
  355. };
  356. /**
  357. * Remove the link to show the colonizing city information.
  358. */
  359. var _lf_doHideColonizingCityInfo = function() {
  360. var la_colonizingCityLinks = IC.myGM.$$('.level0 .link_img');
  361. la_colonizingCityLinks.forEach(function(le_colonizingCityLink) {
  362. le_colonizingCityLink.href = '';
  363. });
  364. };
  365. /**
  366. * Update the settings to execute the callback or delete the handler.
  367. *
  368. * @param {boolean} ib_showColonizingCityInfo
  369. * If the user selected the checkbox to show the colonizing city info.
  370. */
  371. this.updateSettings = function(ib_showColonizingCityInfo) {
  372. if(IC.Ikariam.view !== 'island')
  373. return;
  374. if(ib_showColonizingCityInfo === true) {
  375. IC.RefreshHandler.add('*', 'showColonizingCityInfo', _lf_doShowColonizingCityInfo);
  376. _lf_doShowColonizingCityInfo();
  377. return;
  378. }
  379. IC.RefreshHandler.remove('*', 'showColonizingCityInfo');
  380. _lf_doHideColonizingCityInfo();
  381. };
  382. };
  383. // Retrieve information about colonies during colonization.
  384. IC.Options.addCheckbox('showColonizingCityInfo', 'diverseOptions', 1, true, IC.Language.$('island.options.showColonizingCityInfo'), { changeCallback: _go_colonizingCityInfo.updateSettings });
  385. // Add a divider line.
  386. IC.Options.addLine('diverseOptions', 1);
  387. })();
  388. IC.con.logTimeStamp('IkariamEnhancedUI: island functions created');
  389. // Functions for the finance popup.
  390. (function(){
  391. /**
  392. * Some general functions for the finance view enhancements.
  393. *
  394. * @type {object}
  395. */
  396. var _go_generalFunctions = new function() {
  397. /**
  398. * Extract the current income in the finance popup.
  399. *
  400. * @return {int}
  401. * The current income.
  402. */
  403. this.getIncome = function() {
  404. var le_incomeCell = IC.myGM.$$('.hidden')[IC.myGM.$$('.hidden').length - 1];
  405. while(le_incomeCell.firstChild.firstChild)
  406. le_incomeCell = le_incomeCell.firstChild;
  407. return IC.Ikariam.getInt(le_incomeCell.innerHTML);
  408. };
  409. /**
  410. * Create a new table row.
  411. *
  412. * @param {element} ie_parentTable
  413. * The table to add the row to.
  414. * @param {string[]} ia_classes
  415. * The class(es) of the table row. Set to null if no class should be set.
  416. * @param {object[]} ia_cells
  417. * The data for the table cells. Both properties of each cell are optional. If the cell object is empty, an empty cell is created.
  418. * Signature: <code>[{ className: ['class1', 'class2', ...], text: 'cellContent' }]</code>
  419. * @param {boolean} ib_isTableHeadRow
  420. * If the cells should be table header cells (th).
  421. *
  422. * @return {element}
  423. * The created row.
  424. */
  425. this.createTableRow = function(ie_parentTable, ia_classes, ia_cells, ib_isTableHeadRow) {
  426. var re_newRow = IC.myGM.addElement('tr', ie_parentTable, { classes: ia_classes });
  427. var ls_cellType = 'td';
  428. if(!!ib_isTableHeadRow)
  429. ls_cellType = 'th';
  430. for(var i = 0; i < ia_cells.length; i++) {
  431. var lo_options = {
  432. 'classes': ia_cells[i].className
  433. };
  434. if(!!ia_cells[i].text === true)
  435. lo_options['innerHTML'] = ia_cells[i].text;
  436. IC.myGM.addElement(ls_cellType, re_newRow, lo_options);
  437. }
  438. return re_newRow;
  439. };
  440. };
  441. /**
  442. * Storage for the income on top functions.
  443. *
  444. * @type {object}
  445. */
  446. var _go_incomeOnTop = new function() {
  447. /**
  448. * Callback to show the income on top.
  449. */
  450. var _lf_doShowIncomeOnTop = function() {
  451. var le_summaryTable = IC.myGM.$('.table01 tbody');
  452. var li_income = _go_generalFunctions.getIncome();
  453. var la_incomeCells = [
  454. { className: ['sigma'], text: IC.Language.$('finance.income.perHour') },
  455. { className: ['nowrap', 'res'], text: IC.Ikariam.formatToIkaNumber(li_income) }
  456. ];
  457. _go_generalFunctions.createTableRow(le_summaryTable, [], la_incomeCells);
  458. la_incomeCells[0].text = IC.Language.$('finance.income.perDay');
  459. la_incomeCells[1].text = IC.Ikariam.formatToIkaNumber(li_income * 24);
  460. _go_generalFunctions.createTableRow(le_summaryTable, [], la_incomeCells);
  461. var le_premiumCell = IC.myGM.$('.premiumOffer', le_summaryTable);
  462. le_premiumCell.rowSpan = le_premiumCell.rowSpan + 2;
  463. // Adjust the size of the Scrollbar.
  464. IC.ika.controller.adjustSizes();
  465. };
  466. /**
  467. * Update the settings to execute the callback or delete the handler.
  468. *
  469. * @param {boolean} ib_showIncomeOnTop
  470. * If the user selected the checkbox to show the income on top.
  471. */
  472. this.updateSettings = function(ib_showIncomeOnTop) {
  473. if(ib_showIncomeOnTop === true) {
  474. IC.RefreshHandler.add('finances', 'showIncomeOnTop', _lf_doShowIncomeOnTop);
  475. return;
  476. }
  477. IC.RefreshHandler.remove('finances', 'showIncomeOnTop');
  478. };
  479. };
  480. /**
  481. * Storage for the short upkeep reduction table functions.
  482. *
  483. * @type {object}
  484. */
  485. var _go_shortUpkeepReductionTable = new function() {
  486. /**
  487. * Extract the data from the old tables.
  488. *
  489. * @param {element[]} ia_oldUpkeepReductionTables
  490. * The old upkeep tables to collapse.
  491. *
  492. * @return {object[]}
  493. * The data for the table rows.
  494. * Signature:
  495. * <code>[{
  496. * rows: [
  497. * { reason : 'reason', basicUpkeep: int, supplyUpkeep: int, result: int }
  498. * ]
  499. * priorToReduction: int
  500. * income: int
  501. * }]</code>
  502. */
  503. var _lf_getData = function(ia_oldUpkeepReductionTables) {
  504. var ro_data = {
  505. rows: [],
  506. priorToReduction: IC.Ikariam.getInt(IC.myGM.$('td.hidden', ia_oldUpkeepReductionTables[2]).innerHTML),
  507. income: _go_generalFunctions.getIncome()
  508. };
  509. // Get the data for the troops and ships redution rows.
  510. for(var i = 0; i < 3; i++) {
  511. var le_basicUpkeepCell = IC.myGM.$$('.alt.bottomLine td.hidden, .result td.hidden', ia_oldUpkeepReductionTables[0])[i];
  512. var le_supplyUpkeepCell = IC.myGM.$$('.alt.bottomLine td.hidden, .result td.hidden', ia_oldUpkeepReductionTables[1])[i];
  513. var li_basicUpkeep = IC.Ikariam.getInt(le_basicUpkeepCell.innerHTML);
  514. var li_supplyUpkeep = IC.Ikariam.getInt(le_supplyUpkeepCell.innerHTML);
  515. var lo_row = {
  516. reason: IC.Language.$('finance.upkeep.reason.' + i),
  517. basicUpkeep: li_basicUpkeep,
  518. supplyUpkeep: li_supplyUpkeep,
  519. result: li_basicUpkeep + li_supplyUpkeep
  520. };
  521. ro_data.rows.push(lo_row);
  522. }
  523. return ro_data;
  524. };
  525. /**
  526. * Prepare the table rows for easy adding to the new table.
  527. *
  528. * @param {element[]} ia_oldUpkeepReductionTables
  529. * The old upkeep tables to collapse.
  530. *
  531. * @return {object[]}
  532. * The data for the table rows.
  533. * Signature:
  534. * <code>[{
  535. * classes: 'class' || ['class1', 'class2', ...]
  536. * isHeadRow: true || false
  537. * cells: [
  538. * { className: 'class' || ['class1', 'class2', ...], text: 'cellContent' (optional) }
  539. * ]
  540. * }]</code>
  541. */
  542. var _lf_prepareTableRows = function(ia_oldUpkeepReductionTables) {
  543. var lo_data = _lf_getData(ia_oldUpkeepReductionTables);
  544. var ra_tableRows = [];
  545. // Header
  546. ra_tableRows.push({
  547. classes: [],
  548. isHeadRow: true,
  549. cells: [
  550. { className: ['city', 'left'] },
  551. { className: ['left'], text: IC.Language.$('finance.upkeep.basic') },
  552. { className: ['left'], text: IC.Language.$('finance.upkeep.supply') },
  553. { className: ['left'], text: IC.Language.$('finance.upkeep.result') }
  554. ]
  555. });
  556. // Income without reduction
  557. ra_tableRows.push({
  558. classes: ['alt', 'bottomLine'],
  559. isHeadRow: false,
  560. cells: [
  561. { className: ['city', 'left'], text: IC.Language.$('finance.income.start') },
  562. { className: ['nowrap', 'res'] },
  563. { className: ['nowrap', 'res'] },
  564. { className: ['nowrap', 'res'], text: IC.Ikariam.formatToIkaNumber(lo_data.priorToReduction) }
  565. ]
  566. });
  567. // Income reduction
  568. lo_data.rows.forEach(function(io_row, ii_index) {
  569. var trClass = [];
  570. if(ii_index % 2 === 1)
  571. trClass = ['alt', 'bottomLine'];
  572. ra_tableRows.push({
  573. classes: trClass,
  574. isHeadRow: false,
  575. cells: [
  576. { className: ['city', 'left'], text: io_row.reason },
  577. { className: ['nowrap', 'res'], text: IC.Ikariam.formatToIkaNumber(-io_row.basicUpkeep) },
  578. { className: ['nowrap', 'res'], text: IC.Ikariam.formatToIkaNumber(-io_row.supplyUpkeep) },
  579. { className: ['nowrap', 'res'], text: IC.Ikariam.formatToIkaNumber(-io_row.result) }
  580. ]
  581. });
  582. });
  583. // Result
  584. ra_tableRows.push({
  585. classes: ['result'],
  586. isHeadRow: false,
  587. cells: [
  588. { className: ['sigma', 'left'], text: '<img alt="Summe" src="skin/layout/sigma.png">' },
  589. { className: ['nowrap', 'res'] },
  590. { className: ['nowrap', 'res'] },
  591. { className: ['nowrap', 'res'], text: IC.Ikariam.formatToIkaNumber(lo_data.income) }
  592. ]
  593. });
  594. return ra_tableRows;
  595. };
  596. /**
  597. * Create the new upkeep reduction table.
  598. *
  599. * @param {element[]} ia_oldUpkeepReductionTables
  600. * The old upkeep tables.
  601. */
  602. var _lf_createNewTable = function(ia_oldUpkeepReductionTables) {
  603. var le_shortTable = IC.myGM.addElement('table', ia_oldUpkeepReductionTables[0].parentNode, {
  604. 'id': 'balance',
  605. 'classes': ['table01', 'border']
  606. }, null, ia_oldUpkeepReductionTables[0]);
  607. var la_tableRows = _lf_prepareTableRows(ia_oldUpkeepReductionTables);
  608. la_tableRows.forEach(function(io_rowData) {
  609. _go_generalFunctions.createTableRow(le_shortTable, io_rowData.classes, io_rowData.cells, io_rowData.isHeadRow);
  610. });
  611. IC.myGM.addElement('hr', ia_oldUpkeepReductionTables[0].parentNode, {}, null, ia_oldUpkeepReductionTables[0]);
  612. };
  613. /**
  614. * Toggle the status of an old upkeep table (collapsed / non-collapsed).
  615. */
  616. var _lf_toggleUpkeepReductionTable = function() {
  617. IC.myGM.toggleShowHideButton(this);
  618. var la_rows = IC.myGM.$$('tr:not(:first-child)', this.parentNode.parentNode.parentNode);
  619. la_rows.forEach(function(ie_row) {
  620. ie_row.classList.toggle('invisible');
  621. });
  622. // Adjust the size of the Scrollbar.
  623. IC.ika.controller.adjustSizes();
  624. };
  625. /**
  626. * Minimize the old upkeep tables and make them collapsable.
  627. *
  628. * @param {element[]} ia_oldUpkeepReductionTables
  629. * The old upkeep tables to collapse.
  630. */
  631. var _lf_minimizeOldTables = function(ia_oldUpkeepReductionTables) {
  632. for(var i = 0; i < ia_oldUpkeepReductionTables.length; i++) {
  633. var la_rows = IC.myGM.$$('tr', ia_oldUpkeepReductionTables[i]);
  634. la_rows.forEach(function(ie_row, ii_index) {
  635. if(ii_index !== 0)
  636. ie_row.classList.add('invisible');
  637. });
  638. var le_buttonParent = IC.myGM.$('th', la_rows[0]);
  639. IC.myGM.addElement('div', le_buttonParent, {
  640. 'class': 'maximizeImg',
  641. 'style': [['cssFloat', 'left']],
  642. 'title': IC.Language.$('general.expand'),
  643. 'click': _lf_toggleUpkeepReductionTable
  644. }, null, le_buttonParent.firstChild);
  645. }
  646. };
  647. /**
  648. * Callback to show the short upkeep reduction table.
  649. */
  650. var _lf_doShowShortTable = function() {
  651. var la_oldUpkeepReductionTables = IC.myGM.$$('.upkeepReductionTable');
  652. _lf_createNewTable(la_oldUpkeepReductionTables);
  653. _lf_minimizeOldTables(la_oldUpkeepReductionTables);
  654. // Adjust the size of the Scrollbar.
  655. IC.ika.controller.adjustSizes();
  656. };
  657. /**
  658. * Update the settings to execute the callback or delete the handler.
  659. *
  660. * @param {boolean} ib_showShortTable
  661. * If the user selected the checkbox to show the short upkeep reduction table.
  662. */
  663. this.updateSettings = function(ib_showShortTable) {
  664. if(ib_showShortTable === true) {
  665. IC.RefreshHandler.add('finances', 'shortUpkeepReductionTable', function() { _lf_doShowShortTable(); });
  666. return;
  667. }
  668. IC.RefreshHandler.remove('finances', 'shortUpkeepReductionTable');
  669. };
  670. };
  671. // Show the income also on top in finance popup.
  672. IC.Options.addCheckbox('showIncomeOnTop', 'diverseOptions', 1, true, IC.Language.$('finance.options.showIncomeOnTop'), { changeCallback: _go_incomeOnTop.updateSettings });
  673. // Short overview upkeep reduction table in finance popup.
  674. IC.Options.addCheckbox('shortUpkeepReductionTable', 'diverseOptions', 1, true, IC.Language.$('finance.options.shortUpkeepReductionTable'), { changeCallback: _go_shortUpkeepReductionTable.updateSettings });
  675. // Add a divider line.
  676. IC.Options.addLine('diverseOptions', 1);
  677. })();
  678. IC.con.logTimeStamp('IkariamEnhancedUI: finance functions created');
  679. // Functions for missing resources.
  680. (function() {
  681. /**
  682. * Storage for the missing ressources functions.
  683. *
  684. * @type {object}
  685. */
  686. var _go_showMissingResources = new function() {
  687. /**
  688. * Update the information in the missing resources wrappers.
  689. *
  690. * @param {boolean} ib_isUpdateView
  691. * If the update is in the update view.
  692. */
  693. var _lf_updateInformation = function(ib_isUpdateView) {
  694. var la_currentResources = [
  695. IC.ika.getModel().currentResources.resource, // Wood.
  696. IC.ika.getModel().currentResources[1], // Wine.
  697. IC.ika.getModel().currentResources[2], // Marble.
  698. IC.ika.getModel().currentResources[3], // Crystal.
  699. IC.ika.getModel().currentResources[4] // Sulfur.
  700. ];
  701. var lb_showPositiveNumbers = IC.Options.getOption('missingResources', 'showPositive') === true && ib_isUpdateView === true;
  702. var lb_showMissingColoured = IC.Options.getOption('missingResources', 'showColoured');
  703. var ls_resourcesPattern = '%resources%';
  704. if(ib_isUpdateView !== true)
  705. ls_resourcesPattern = ' (' + ls_resourcesPattern + ')';
  706. for(var i = 0; i < IC.Ikariam.resourceNames.length; i++) {
  707. var la_missingWrappers = IC.myGM.$$('.' + IC.myGM.prefix + 'missingResources' + IC.Ikariam.resourceNames[i]);
  708. if(!!la_missingWrappers) {
  709. for(var k = 0; k < la_missingWrappers.length; k++) {
  710. var le_neededWrapper = la_missingWrappers[k].previousSibling;
  711. var li_missing = la_currentResources[i] - IC.Ikariam.getInt(le_neededWrapper.nodeValue);
  712. if(li_missing < 0 || lb_showPositiveNumbers === true) {
  713. var ls_formattedMissingValue = IC.Ikariam.formatToIkaNumber(li_missing, lb_showMissingColoured, true);
  714. la_missingWrappers[k].innerHTML = ls_resourcesPattern.replace(/\%resources\%/, ls_formattedMissingValue);
  715. } else {
  716. la_missingWrappers[k].innerHTML = '';
  717. }
  718. }
  719. }
  720. }
  721. };
  722. /**
  723. * Add the missing resources wrappers.
  724. *
  725. * @param {boolean} ib_isUpdateView
  726. * If the wrappers are added to the update view.
  727. */
  728. var _lf_addMissingWrappers = function(ib_isUpdateView) {
  729. var ls_wrapperSelector = '#buildingGround .resources';
  730. if(ib_isUpdateView === true)
  731. ls_wrapperSelector = '#sidebar .resources';
  732. var la_wrappers = IC.myGM.$$(ls_wrapperSelector);
  733. for(var i = 0; i < la_wrappers.length; i++) {
  734. for(var k = 0; k < IC.Ikariam.resourceNames.length; k++) {
  735. var le_resourceNode = IC.myGM.$('.' + IC.Ikariam.resourceNames[k], la_wrappers[i]);
  736. if(!!le_resourceNode) {
  737. IC.myGM.addElement('span', le_resourceNode, { 'classes': ['missingResources', 'missingResources' + IC.Ikariam.resourceNames[k]] }, true);
  738. }
  739. }
  740. }
  741. _lf_updateInformation(ib_isUpdateView);
  742. };
  743. /**
  744. * Update the missing resources in building ground popup.
  745. */
  746. var _lf_doUpdateInBuildingView = function() {
  747. if(!IC.myGM.$('#buildingGround_c')) {
  748. IC.Observer.remove('missingResourcesBuilding');
  749. return;
  750. }
  751.  
  752. _lf_updateInformation(false);
  753. };
  754. /**
  755. * Update the missing resources in update view.
  756. */
  757. var _lf_doUpdateInUpdateView = function() {
  758. if(!IC.myGM.$('#buildingUpgrade')) {
  759. IC.Observer.remove('missingResourcesUpdate');
  760. return;
  761. }
  762.  
  763. _lf_updateInformation(true);
  764. };
  765. /**
  766. * Show the missing resources in building ground popup.
  767. */
  768. var _lf_doShowInBuildingGround = function() {
  769. _lf_addMissingWrappers(false);
  770. IC.Observer.add('missingResourcesBuilding', IC.myGM.$('#cityResources'), { childList: true, subtree: true }, _lf_doUpdateInBuildingView, _lf_doUpdateInBuildingView);
  771. };
  772. /**
  773. * Show the missing resources in update view.
  774. */
  775. var _lf_doShowInUpdateView = function() {
  776. if(!IC.myGM.$('#buildingUpgrade') || IC.myGM.$$('.' + IC.myGM.prefix + 'missingResources').length > 0)
  777. return;
  778. _lf_addMissingWrappers(true);
  779. IC.Observer.add('missingResourcesUpgrade', IC.myGM.$('#cityResources'), { childList: true, subtree: true }, _lf_doUpdateInUpdateView, _lf_doUpdateInUpdateView);
  780. };
  781. /**
  782. * Update the settings to execute the callback or delete the handler.
  783. *
  784. * @param {boolean} ib_showMissingResources
  785. * If the user selected the checkbox to show the missing resources info.
  786. */
  787. this.updateSettings = function(ib_showMissingResources) {
  788. if(ib_showMissingResources === true) {
  789. IC.RefreshHandler.add('buildingGround', 'showMissingResources', _lf_doShowInBuildingGround);
  790. IC.RefreshHandler.add('%', 'showMissingResources', _lf_doShowInUpdateView);
  791. IC.myGM.addStyle(
  792. '#sidebar #buildingUpgrade ul.resources li { width: 120px; } \
  793. #sidebar #buildingUpgrade ul.resources li.time { width: 60px !important; } \
  794. #sidebar .' + IC.myGM.prefix + 'missingResources { float: right; }',
  795. 'showMissingResources'
  796. );
  797. return;
  798. }
  799. IC.RefreshHandler.remove('buildingGround', 'showMissingResources');
  800. IC.RefreshHandler.remove('%', 'showMissingResources');
  801. IC.myGM.removeStyle('showMissingResources');
  802. };
  803. };
  804. IC.Options.addWrapper('missingResources', IC.Language.$('missingResources.options.wrapperTitle'));
  805. // Show missing resources in upgrade / building view.
  806. IC.Options.addCheckbox('show', 'missingResources', 1, true, IC.Language.$('missingResources.options.show'), { changeCallback: _go_showMissingResources.updateSettings });
  807. // Disable coloring of the missing resources.
  808. IC.Options.addCheckbox('showPositive', 'missingResources', 2, true, IC.Language.$('missingResources.options.showPositive'), {});
  809. // Show only missing ressources, not also remaining.
  810. IC.Options.addCheckbox('showColoured', 'missingResources', 2, true, IC.Language.$('missingResources.options.showColoured'), {});
  811. })();
  812. IC.con.logTimeStamp('IkariamEnhancedUI: missing resource functions created');
  813. // Functions for tooltips.
  814. (function() {
  815. /**
  816. * Storage for the autoshow tootips functions.
  817. *
  818. * @type {object}
  819. */
  820. var _go_autoshowTooltips = new function() {
  821. /**
  822. * General function for autowhow.
  823. *
  824. * @param {string} onclickWrapperClass
  825. * The class of the wrapper which has the onclik attribute set.
  826. */
  827. var _lf_autoshowTooltipsGeneral = function(onclickWrapperClass) {
  828. IC.myGM.$$('.' + onclickWrapperClass).forEach(function(onclickWrapper) {
  829. var onclickFunction = onclickWrapper.onclick;
  830. onclickWrapper.onclick = 'return false;';
  831. var newHandler = IC.myGM.$('.magnify_icon', onclickWrapper);
  832. if(!newHandler)
  833. newHandler = onclickWrapper;
  834. newHandler.addEventListener('mouseover', function(e) { IC.ika.controller.captureMousePosition(e); onclickFunction(e); }, true);
  835. });
  836. IC.myGM.$('.templateView .mainContent').addEventListener('click', function() { IC.win.$(document).trigger("closeExclusiveInfo"); }, true);
  837. };
  838. /**
  839. * Autmatically show tooltips in alliance member lists.
  840. */
  841. var _lf_doAutoshowTooltipsAlliance = function() {
  842. _lf_autoshowTooltipsGeneral('cityInfo');
  843. };
  844. /**
  845. * Autmatically show tooltips in military advisor.
  846. */
  847. var _lf_doAutoshowTooltipsMilitaryAdvisor = function() {
  848. if(IC.Options.getOption('moduleOptions', 'showDirectMilitaryTooltips') === true)
  849. return;
  850. _lf_autoshowTooltipsGeneral('spyMilitary');
  851. };
  852. /**
  853. * Update the settings to execute the callback or delete the handler.
  854. *
  855. * @param {boolean} autoshowTooltips
  856. * If the user selected the checkbox to autoshow tooltips.
  857. */
  858. this.updateSettings = function(autoshowTooltips) {
  859. var alliancePopupIds = ['diplomacyAllyMemberlist', 'embassy'];
  860. if(autoshowTooltips === true) {
  861. IC.RefreshHandler.add('militaryAdvisor', 'autoshowTooltips', _lf_doAutoshowTooltipsMilitaryAdvisor);
  862. IC.RefreshHandler.add(alliancePopupIds, 'autoshowTooltips', _lf_doAutoshowTooltipsAlliance);
  863. return;
  864. }
  865. IC.RefreshHandler.remove('militaryAdvisor', 'autoshowTooltips');
  866. IC.RefreshHandler.remove(alliancePopupIds, 'autoshowTooltips');
  867. };
  868. };
  869. /**
  870. * Storage for the direct military tooltip functions.
  871. *
  872. * @type {object}
  873. */
  874. var _go_directMilitaryTooltips = new function() {
  875. /**
  876. * Storage for the class ids and their corresponding translations. Each class is a property of the object with the translation stored in it.
  877. *
  878. * @type {object}
  879. */
  880. var _lo_idTranslation = {};
  881. /**
  882. * Fill the id translation object.
  883. */
  884. var _lf_fillIdTranslation = function() {
  885. if(_lo_idTranslation.length === 0)
  886. return;
  887. var la_troops = ['swordsman', 'phalanx', 'archer', 'marksman', 'mortar', 'slinger', 'catapult', 'ram', 'steamgiant', 'bombardier', 'cook', 'medic', 'gyrocopter', 'spearman', 'spartan'];
  888. var la_ships = ['balliasta', 'catapult', 'flamethrower', 'mortar', 'ram', 'steamboat', 'rocketship', 'submarine', 'paddlespeedship', 'balloncarrier', 'tender', 'transport', 'premium_transport'];
  889. var la_resources = IC.Ikariam.resourceNames;
  890. la_resources.push('gold');
  891. la_troops.forEach(function(is_troopName) {
  892. _lo_idTranslation[is_troopName] = IC.Language.$('diverse.name.unit.' + is_troopName);
  893. });
  894. la_ships.forEach(function(is_shipName) {
  895. _lo_idTranslation['ship_' + is_shipName] = IC.Language.$('diverse.name.ship.' + is_shipName.replace('premium_', ''));
  896. });
  897. la_resources.forEach(function(is_resourceName) {
  898. _lo_idTranslation[is_resourceName] = IC.Language.$('diverse.name.resource.' + is_resourceName);
  899. });
  900. };
  901. /**
  902. * Hide the number of ships for the own peaceful missions (trade / transport).
  903. */
  904. var _lf_hideShipNumberOwnPeacefulMissions = function() {
  905. var la_ownEventTableRows = IC.myGM.$$('#js_MilitaryMovementsFleetMovementsTable .military_event_table tr.own');
  906. la_ownEventTableRows.forEach(function(ie_tableRow) {
  907. var le_missionDiv = IC.myGM.$('td:nth-child(1) div.mission_icon', ie_tableRow);
  908. var lb_peacefulMission = le_missionDiv.classList.contains('transport') || le_missionDiv.classList.contains('trade');
  909. if(lb_peacefulMission === true) {
  910. IC.myGM.$('td:nth-child(4) div', ie_tableRow).classList.add('invisible');
  911. }
  912. });
  913. };
  914. /**
  915. * Show the military tooltips directly.
  916. */
  917. var _lf_doShowDirectMilitaryTooltips = function() {
  918. _lf_fillIdTranslation();
  919. _lf_hideShipNumberOwnPeacefulMissions();
  920. IC.myGM.$$('.spyMilitary').forEach(function(ie_movementWrapper) {
  921. ie_movementWrapper.onclick = 'return false;';
  922. });
  923. var le_movementsTable = IC.myGM.$('#js_MilitaryMovementsFleetMovementsTable');
  924. IC.myGM.forEach(_lo_idTranslation, function(is_classId, is_translation) {
  925. IC.myGM.$$('.icon40.' + is_classId, le_movementsTable).forEach(function(ie_detailIcon) {
  926. ie_detailIcon.title = is_translation;
  927. });
  928. });
  929. };
  930. /**
  931. * Update the settings to execute the callback or delete the handler.
  932. *
  933. * @param {boolean} ib_showDirectMilitaryTooltips
  934. * If the user selected the checkbox to show the military tooltips directly.
  935. */
  936. this.updateSettings = function(ib_showDirectMilitaryTooltips) {
  937. if(ib_showDirectMilitaryTooltips === true) {
  938. IC.RefreshHandler.add('militaryAdvisor', 'showDirectMilitaryTooltips', _lf_doShowDirectMilitaryTooltips);
  939. IC.myGM.addStyle(
  940. '#js_MilitaryMovementsFleetMovementsTable .military_event_table .magnify_icon { background-image: none; cursor: default; width: 240px; } \
  941. #js_MilitaryMovementsFleetMovementsTable .military_event_table .magnify_icon .infoTip { display: inline; position: relative; padding: 0px; border: none; top: 0px; } \
  942. #js_MilitaryMovementsFleetMovementsTable .military_event_table .magnify_icon .infoTip h5 { display: none; } \
  943. #js_MilitaryMovementsFleetMovementsTable .military_event_table .icon40 { background-size: 25px 25px; background-color: transparent; padding: 26px 3px 0px 3px; width: 30px; } \
  944. #js_MilitaryMovementsFleetMovementsTable .military_event_table .icon40.resource_icon { background-size: 20px 16px; }',
  945. 'showDirectMilitaryTooltips'
  946. );
  947. return;
  948. }
  949. IC.RefreshHandler.remove('militaryAdvisor', 'showDirectMilitaryTooltips');
  950. IC.myGM.removeStyle('showDirectMilitaryTooltips');
  951. };
  952. };
  953. // Show alliance / military tooltips directly.
  954. IC.Options.addCheckbox('autoshowTooltips', 'diverseOptions', 1, true, IC.Language.$('tooltips.options.autoshow'), { changeCallback: _go_autoshowTooltips.updateSettings });
  955. // Show military tooltips directly.
  956. IC.Options.addCheckbox('showDirectMilitaryTooltips', 'diverseOptions', 1, false, IC.Language.$('tooltips.options.showDirectInMilitaryAdvisor'), { changeCallback: _go_directMilitaryTooltips.updateSettings });
  957. // Add a divider line.
  958. IC.Options.addLine('diverseOptions', 1);
  959. })();
  960. IC.con.logTimeStamp('IkariamEnhancedUI: tooltip functions created');
  961. // Zoom function.
  962. (function() {
  963. /**
  964. * Storage for the zoom functions.
  965. *
  966. * @type {object}
  967. */
  968. var _go_zoomView = new function() {
  969. /**
  970. * Storage for the minimum zoom factor.
  971. *
  972. * @type {int}
  973. */
  974. var _li_minZoom = 55;
  975. /**
  976. * Storage for the maximum zoom factor.
  977. *
  978. * @type {int}
  979. */
  980. var _li_maxZoom = 150;
  981. /**
  982. * Storage for the zoom step size.
  983. *
  984. * @type {int}
  985. */
  986. var _li_zoomStep = 5;
  987. /**
  988. * Storage for the actual mousewheel callback.
  989. *
  990. * @type {function}
  991. */
  992. var _lf_mousewheelCallbackStorage = IC.ika.getController().mouseScrollHandle;
  993. /**
  994. * Getter for the minimum zoom factor.
  995. *
  996. * @return {int}
  997. * The minimum zoom factor.
  998. */
  999. this.__defineGetter__('minZoom', function() { return _li_minZoom; });
  1000. /**
  1001. * Getter for the maximum zoom factor.
  1002. *
  1003. * @return {int}
  1004. * The maximum zoom factor.
  1005. */
  1006. this.__defineGetter__('maxZoom', function() { return _li_maxZoom; });
  1007. /**
  1008. * Getter for the zoom step size.
  1009. *
  1010. * @return {int}
  1011. * The zoom step size.
  1012. */
  1013. this.__defineGetter__('zoomStep', function() { return _li_zoomStep; });
  1014. /**
  1015. * Initialize the zoom bounds (min and max zoom).
  1016. */
  1017. var _lf_initBounds = function() {
  1018. var li_minZoom = Math.round(IC.ika.worldview_scale_min * 100);
  1019. if(li_minZoom % 5 != 0)
  1020. li_minZoom = li_minZoom + (5 - (li_minZoom % 5));
  1021.  
  1022. _li_minZoom = li_minZoom;
  1023. IC.ika.worldview_scale_min = _li_minZoom / 100;
  1024. IC.ika.worldview_scale_max = _li_maxZoom / 100;
  1025. };
  1026. /**
  1027. * Zoom the world view, as there is no function provided by Ikariam.
  1028. *
  1029. * @param {decimal} in_zoomFactor
  1030. * The zoom factor as decimal number (1 =^= 100%)
  1031. */
  1032. var _lf_zoomWorldView = function(in_zoomFactor) {
  1033. var li_translateXY = (100 - 100 / in_zoomFactor) / 2;
  1034. var ls_heightWidth = (100 / in_zoomFactor) + '% !important';
  1035. var ls_transformString = 'scale(' + in_zoomFactor + ') translate(' + li_translateXY + '%, ' + li_translateXY + '%)';
  1036. IC.myGM.addStyle(
  1037. '#scrollcover { transform: ' + ls_transformString + '; -webkit-transform: ' + ls_transformString + '; height: ' + ls_heightWidth + '; width: ' + ls_heightWidth + '; }',
  1038. 'zoomWorld', true
  1039. );
  1040. var le_map = IC.myGM.$('#map1');
  1041. le_map.style.top = '0px';
  1042. le_map.style.left = '0px';
  1043. };
  1044. /**
  1045. * Rescale the badges and symbols.
  1046. *
  1047. * @param {decimal} in_zoomFactorNumber
  1048. * The zoom factor as decimal number (1 =^= 100%)
  1049. */
  1050. var _lf_scaleChildren = function(in_zoomFactorNumber) {
  1051. var ls_transformString = 'transform: scale(' + 1 / in_zoomFactorNumber + '); -webkit-transform: scale(' + 1 / in_zoomFactorNumber + ');';
  1052. var ls_style = '';
  1053. if(IC.Ikariam.view == 'world') {
  1054. var ls_ownerState = '';
  1055. if(in_zoomFactorNumber < 1)
  1056. ls_ownerState = ', .ownerState';
  1057. ls_style = '.islandTile .wonder, .islandTile .tradegood, .islandTile .cities, .islandTile .piracyInRange' + ls_ownerState + ' { ' + ls_transformString + ' } \
  1058. .islandTile .cities { bottom: 10px !important; }';
  1059. }
  1060. if(IC.Ikariam.view == 'island') {
  1061. var ls_movePiracy = 'transform: translate(0px, -' + (1 - in_zoomFactorNumber) * 20 + 'px) scale(' + 1 / in_zoomFactorNumber + ');';
  1062. ls_style = '.cityLocation .scroll_img, .cityLocationScroll .scroll_img { ' + ls_transformString + ' } \
  1063. .cityLocation .piracyRaid { ' + ls_movePiracy + ' }';
  1064. }
  1065. if(IC.Ikariam.view == 'town')
  1066. ls_style = '.timetofinish { ' + ls_transformString + ' }';
  1067. IC.myGM.addStyle(ls_style, 'scaleChildren', true);
  1068. };
  1069. /**
  1070. * Update the zoom in and zoom out button and the percentage in the middle.
  1071. *
  1072. * @param {int} ii_zoomFactor
  1073. * The zoom factor as percentage.
  1074. */
  1075. var _lf_updateZoomButtons = function(ii_zoomFactor) {
  1076. var le_zoomFactorDiv = IC.myGM.$('#' + IC.myGM.prefix + 'zoomFactor');
  1077. var le_zoomIn = IC.myGM.$('#' + IC.myGM.prefix + 'zoomIn');
  1078. var le_zoomOut = IC.myGM.$('#' + IC.myGM.prefix + 'zoomOut');
  1079. if(!!le_zoomFactorDiv) {
  1080. le_zoomFactorDiv.innerHTML = ii_zoomFactor + '%';
  1081. }
  1082. if(!!le_zoomIn) {
  1083. le_zoomIn.style.visibility = '';
  1084. if(ii_zoomFactor >= _li_maxZoom)
  1085. le_zoomIn.style.visibility = 'hidden';
  1086. }
  1087. if(!!le_zoomOut) {
  1088. le_zoomOut.style.visibility = '';
  1089. if(ii_zoomFactor <= _li_minZoom)
  1090. le_zoomOut.style.visibility = 'hidden';
  1091. }
  1092. };
  1093. /**
  1094. * Calculate the zoom factor as decimal number and execute the zoom function. If it is requestet, call also the rescale function for child elements.
  1095. *
  1096. * @param {int} ii_zoomFactor
  1097. * The zoom factor as percentage.
  1098. */
  1099. var _lf_zoomView = function(ii_zoomFactor) {
  1100. var ln_zoomFactorNumber = ii_zoomFactor / 100.0;
  1101. var li_scale = 0;
  1102. if(IC.Ikariam.view == 'island')
  1103. li_scale = IC.ika.worldview_scale_island;
  1104. if(IC.Ikariam.view == 'town')
  1105. li_scale = IC.ika.worldview_scale_city;
  1106. if(IC.Ikariam.view == 'world') {
  1107. _lf_zoomWorldView(ln_zoomFactorNumber);
  1108. } else {
  1109. var li_stepNumber = Math.round((ln_zoomFactorNumber - li_scale) / .05);
  1110. var le_worldview = IC.myGM.$('#worldview');
  1111. var li_posX = le_worldview.offsetLeft + le_worldview.offsetWidth / 2;
  1112. var li_posY = le_worldview.offsetTop + le_worldview.offsetHeight / 2;
  1113. IC.ika.controller.scaleWorldMap(li_stepNumber, li_posX, li_posY);
  1114. }
  1115. if(IC.Options.getOption('zoom', IC.Ikariam.view + 'ScaleChildren') === true)
  1116. _lf_scaleChildren(ln_zoomFactorNumber);
  1117. };
  1118. /**
  1119. * Ensure that the requested zoom factor is in the bounds and update the view.
  1120. *
  1121. * @param {int} ii_zoomFactor
  1122. * The zoom factor as percentage.
  1123. */
  1124. var _lf_zoom = function(ii_zoomFactor) {
  1125. if(ii_zoomFactor > _li_maxZoom)
  1126. ii_zoomFactor = _li_maxZoom;
  1127. if(ii_zoomFactor < _li_minZoom)
  1128. ii_zoomFactor = _li_minZoom;
  1129. IC.Options.setOption('zoom', IC.Ikariam.view + 'Factor', ii_zoomFactor);
  1130. _lf_updateZoomButtons(ii_zoomFactor);
  1131. _lf_zoomView(ii_zoomFactor);
  1132. };
  1133. /**
  1134. * Zoom one step in.
  1135. */
  1136. var _lf_zoomIn = function() {
  1137. var li_factor = IC.Ikariam.getInt(IC.Options.getOption('zoom', IC.Ikariam.view + 'Factor', 100)) + _li_zoomStep;
  1138. _lf_zoom(li_factor);
  1139. };
  1140. /**
  1141. * Zoom one step out.
  1142. */
  1143. var _lf_zoomOut = function() {
  1144. var li_factor = IC.Options.getOption('zoom', IC.Ikariam.view + 'Factor', 100) - _li_zoomStep;
  1145. _lf_zoom(li_factor);
  1146. };
  1147. /**
  1148. * Add the zoom buttons.
  1149. */
  1150. var _lf_addZoomButtons = function() {
  1151. var le_zoomWrapper = IC.myGM.addElement('div', ge_toolbar, { 'id': 'zoomWrapper' });
  1152. IC.myGM.addElement('div', le_zoomWrapper, {
  1153. 'id': 'zoomIn',
  1154. 'class': 'maximizeImg',
  1155. 'title': IC.Language.$('zoom.zoomIn'),
  1156. 'click': _lf_zoomIn
  1157. });
  1158. IC.myGM.addElement('div', le_zoomWrapper, {
  1159. 'id': 'zoomFactor',
  1160. 'title': IC.Language.$('zoom.factor')
  1161. });
  1162. IC.myGM.addElement('div', le_zoomWrapper, {
  1163. 'id': 'zoomOut',
  1164. 'class': 'minimizeImg',
  1165. 'title': IC.Language.$('zoom.zoomOut'),
  1166. 'click': _lf_zoomOut
  1167. });
  1168. IC.myGM.addStyle(
  1169. '#' + IC.myGM.prefix + 'zoomWrapper { width: 72px; margin: 0px -5px !important; transform: scale(0.75); scale(0.75); -webkit-transform: scale(0.75); } \
  1170. #' + IC.myGM.prefix + 'zoomWrapper > div { display: inline-block; position: relative; } \
  1171. #' + IC.myGM.prefix + 'zoomFactor { top: -4px; width: 35px; text-align: center; }',
  1172. 'zoomButtons'
  1173. );
  1174. };
  1175. /**
  1176. * Set the zoom to 100% if in world view or if it was bigger than 100% and remove the zoom buttons and all styles for the zoom.
  1177. */
  1178. var _lf_resetZoom = function() {
  1179. if((IC.Ikariam.view == 'island' && IC.ika.worldview_scale_island > 1) || (IC.Ikariam.view == 'town' && IC.ika.worldview_scale_city > 1) || IC.Ikariam.view == 'world')
  1180. _lf_zoomView(100);
  1181. IC.ika.worldview_scale_max = 1;
  1182. IC.myGM.removeElement(IC.myGM.$('#' + IC.myGM.prefix + 'zoomWrapper'));
  1183. IC.myGM.removeStyle('zoomButtons');
  1184. IC.myGM.removeStyle('zoomWorld');
  1185. IC.myGM.removeStyle('scaleChildren');
  1186. };
  1187. /**
  1188. * Check, if the key are pressed which are required to zoom with the mouse.
  1189. *
  1190. * @param {object} io_event
  1191. * The "event object" with information about the mouse scroll and pressed keys.
  1192. *
  1193. * @return {boolean}
  1194. * If the correct keys were pressed.
  1195. */
  1196. var _lf_keysOK = function(io_event) {
  1197. var lb_ctrlOK = !!io_event.ctrlKey;
  1198. if(IC.Options.getOption('zoom', 'ctrlAsAccessKey') === false)
  1199. lb_ctrlOK = true;
  1200. var lb_altOK = !!io_event.altKey;
  1201. if(IC.Options.getOption('zoom', 'altAsAccessKey') === false)
  1202. lb_altOK = true;
  1203. var lb_shiftOK = !!io_event.shiftKey;
  1204. if(IC.Options.getOption('zoom', 'shiftAsAccessKey') === false)
  1205. lb_shiftOK = true;
  1206. return lb_ctrlOK && lb_altOK && lb_shiftOK;
  1207. };
  1208. /**
  1209. * Calculate the delta the mousewheel was turned.
  1210. *
  1211. * @param {object} io_event
  1212. * The "event object" with information about the mouse scroll and pressed keys.
  1213. *
  1214. * @return {int}
  1215. * The delta the mousewheel was moved.
  1216. */
  1217. var _lf_calculateDelta = function(io_event) {
  1218. var ri_stepNumber = 0;
  1219.  
  1220. // Get the number of steps to scroll.
  1221. if(io_event.wheelDelta)
  1222. ri_stepNumber = io_event.wheelDelta / 120;
  1223.  
  1224. if (io_event.detail)
  1225. ri_stepNumber = -io_event.detail / 3;
  1226.  
  1227. if (io_event.wheelDeltaY !== undefined)
  1228. ri_stepNumber = io_event.wheelDeltaY / 120;
  1229. // If the number is between -1 and 0, set it to -1.
  1230. if(ri_stepNumber < 0)
  1231. ri_stepNumber = ri_stepNumber > -1 ? -1 : Math.round(ri_stepNumber);
  1232.  
  1233. // If the number is between 0 and 1, set it to 1.
  1234. else
  1235. ri_stepNumber = ri_stepNumber < 1 ? 1 : Math.round(ri_stepNumber);
  1236. return ri_stepNumber;
  1237. };
  1238. /**
  1239. * Handler for mousescroll to zoom.
  1240. *
  1241. * @param {object} io_event
  1242. * The "event object" with information about the mouse scroll and pressed keys.
  1243. *
  1244. * @return false
  1245. * If the prevent default method is not available to prevent the default action.
  1246. */
  1247. var _lf_mouseScroll = function(io_event) {
  1248. if(_lf_keysOK(io_event) === true) {
  1249. // If the scrolling is horizontally return.
  1250. if(io_event.axis !== undefined && io_event.axis === io_event.HORIZONTAL_AXIS)
  1251. return;
  1252. var li_factor = IC.Ikariam.getInt(IC.Options.getOption('zoom', IC.Ikariam.view + 'Factor')) + _li_zoomStep * _lf_calculateDelta(io_event);
  1253. _lf_zoom(li_factor);
  1254. // Prevent the default event.
  1255. if(io_event.preventDefault)
  1256. io_event.preventDefault();
  1257. else
  1258. return false;
  1259. }
  1260. };
  1261. /**
  1262. * Change the mousewheel listener to a new callback.
  1263. *
  1264. * @param {function} if_newCallback
  1265. * The new callback for the mousewheel listener.
  1266. */
  1267. var _lf_changeMouseWheelListener = function(if_newCallback) {
  1268. if(_lf_mousewheelCallbackStorage == if_newCallback)
  1269. return;
  1270. var ls_scrollDivId = '#worldmap';
  1271. if(IC.Ikariam.view == 'world')
  1272. ls_scrollDivId = '#map1';
  1273. if(_lf_mousewheelCallbackStorage == IC.ika.getController().mouseScrollHandle) {
  1274. // Remove the ikariam mouse wheel listener and add the own. (with the use of Ikariam-jQuery)
  1275. IC.win.$(ls_scrollDivId).unbind('mousewheel');
  1276. var scrollDiv = IC.myGM.$(ls_scrollDivId);
  1277. scrollDiv.addEventListener('DOMMouseScroll', if_newCallback, false);
  1278. scrollDiv.addEventListener('mousewheel', if_newCallback, false);
  1279. } else {
  1280. var scrollDiv = IC.myGM.$(ls_scrollDivId);
  1281. scrollDiv.removeEventListener('DOMMouseScroll', _lf_mousewheelCallbackStorage, false);
  1282. scrollDiv.removeEventListener('mousewheel', _lf_mousewheelCallbackStorage, false);
  1283. IC.win.$(ls_scrollDivId).on('mousewheel', if_newCallback);
  1284. }
  1285. _lf_mousewheelCallbackStorage = if_newCallback;
  1286. };
  1287. /**
  1288. * Update the settings to execute the callback or delete the handler.
  1289. *
  1290. * @param {boolean} ib_zoomView
  1291. * If the user selected the checkbox to zoom.
  1292. */
  1293. this.updateSettings = function(ib_zoomView) {
  1294. _lf_initBounds();
  1295. _go_zoomOptions.renewFactorSelects();
  1296. if(ib_zoomView === true) {
  1297. _lf_addZoomButtons();
  1298. _lf_changeMouseWheelListener(_lf_mouseScroll);
  1299. _lf_zoom(IC.Options.getOption('zoom', IC.Ikariam.view + 'Factor'));
  1300. return;
  1301. }
  1302. _lf_resetZoom();
  1303. _lf_changeMouseWheelListener(IC.ika.getController().mouseScrollHandle);
  1304. };
  1305. };
  1306. /**
  1307. * Storage for the option creation functions.
  1308. *
  1309. * @type {object}
  1310. */
  1311. var _go_zoomOptions = new function() {
  1312. /**
  1313. * If the zoom wrapper is already created.
  1314. */
  1315. var _lb_zoomWrapperCreated = false;
  1316. /**
  1317. * Add the select fields for the zoom factors.
  1318. */
  1319. var _lf_addFactorSelects = function(ib_replace) {
  1320. var la_options = [];
  1321. for(var i = _go_zoomView.minZoom; i <= _go_zoomView.maxZoom; i = i + _go_zoomView.zoomStep) {
  1322. la_options.push({ value: i, label: i + '%' });
  1323. }
  1324. IC.Ikariam.viewNames.forEach(function(is_view, ii_index) {
  1325. IC.Options.addSelect(is_view + 'Factor', 'zoom', 'factors', 100, IC.Language.$('zoom.options.factor.' + is_view), la_options, { replace: !!ib_replace });
  1326. });
  1327. };
  1328. /**
  1329. * Add the checkboxes fields for rescaling the badges and icons.
  1330. */
  1331. var _lf_addScaleChildrenCheckboxes = function() {
  1332. IC.Options.addHTML('scaleChildrenDescription', 'zoom', 'scale', { html: '<p>' + IC.Language.$('zoom.options.scaleChildren.label') + '</p>' });
  1333. IC.Ikariam.viewNames.forEach(function(is_view) {
  1334. IC.Options.addCheckbox(is_view + 'ScaleChildren', 'zoom', 'scale', true, IC.Language.$('zoom.options.scaleChildren.' + is_view), {});
  1335. });
  1336. };
  1337. /**
  1338. * Add the checkboxes for the access keys.
  1339. */
  1340. var _lf_addAccessKeyCheckboxes = function() {
  1341. IC.Options.addHTML('accessKeyDescription', 'zoom', 'accessKeys', { html: '<p>' + IC.Language.$('zoom.options.accessKeyLabel') + '</p>' });
  1342. var la_accessKeys = ['ctrl', 'alt', 'shift'];
  1343. la_accessKeys.forEach(function(is_accessKey) {
  1344. var lb_defaultEnabled = (is_accessKey == 'ctrl');
  1345. IC.Options.addCheckbox(is_accessKey + 'AsAccessKey', 'zoom', 'accessKeys', lb_defaultEnabled, IC.Language.$('general.' + is_accessKey), {});
  1346. });
  1347. };
  1348. /**
  1349. * Create the zoom options wrapper and add the option elements.
  1350. */
  1351. this.create = function() {
  1352. _lf_addFactorSelects();
  1353. _lf_addScaleChildrenCheckboxes();
  1354. _lf_addAccessKeyCheckboxes();
  1355. _lb_zoomWrapperCreated = true;
  1356. };
  1357. /**
  1358. * Recreate the select fields for the zoom factor (and keep the old zoom factor).
  1359. */
  1360. this.renewFactorSelects = function() {
  1361. if(_lb_zoomWrapperCreated === false)
  1362. return;
  1363. _lf_addFactorSelects(true);
  1364. };
  1365. };
  1366. IC.Options.addWrapper('zoom', IC.Language.$('zoom.options.wrapperTitle'));
  1367. // Show missing resources in upgrade / building view.
  1368. IC.Options.addCheckbox('view', 'zoom', 'general', true, IC.Language.$('zoom.options.zoomView'), { changeCallback: _go_zoomView.updateSettings });
  1369. // Add the zoom function settings.
  1370. _go_zoomOptions.create();
  1371. })();
  1372. IC.con.logTimeStamp('IkariamEnhancedUI: zoom functions created');
  1373. // Ressource information.
  1374. (function() {
  1375. /**
  1376. * Storage for the style functions for the capacity bar and the direct income.
  1377. *
  1378. * @type {object}
  1379. */
  1380. var _go_styleFunctions = new function() {
  1381. /**
  1382. * Get the style for the #js_GlobalMenu_ elements.
  1383. *
  1384. * @param {string} is_incomeStyle
  1385. * How the income is styled.
  1386. *
  1387. * @return {string}
  1388. * The style string.
  1389. */
  1390. var _lf_getGlobalMenuStyle = function(is_incomeStyle) {
  1391. if(is_incomeStyle != 'alignLeft')
  1392. return '#js_GlobalMenu_wood, #js_GlobalMenu_wine, #js_GlobalMenu_marble, #js_GlobalMenu_crystal, #js_GlobalMenu_sulfur { padding-right: 4px; } ';
  1393. return '';
  1394. };
  1395. /**
  1396. * Gets the style for the separation of the resource values.
  1397. *
  1398. * @param {string} is_incomeStyle
  1399. * How the income is styled.
  1400. *
  1401. * @return {string}
  1402. * The style string.
  1403. */
  1404. var _lf_getSeparationStyle = function(is_incomeStyle) {
  1405. if(is_incomeStyle == 'withSeparation')
  1406. return '#resources_wood, #resources_wine, #resources_marble, #resources_glass { border-right: 1px dotted #542C0F; } ';
  1407. return '';
  1408. };
  1409. /**
  1410. * Get styles which are independent of the activation of the cpacity bar or direct income.
  1411. *
  1412. * @param {string} is_incomeStyle
  1413. * How the income is styled.
  1414. *
  1415. * @return {string}
  1416. * The style string.
  1417. */
  1418. var _lf_getGeneralStyles = function(is_incomeStyle) {
  1419. var ls_globalMenuStyle = _lf_getGlobalMenuStyle(is_incomeStyle);
  1420. var ls_separationStyle = _lf_getSeparationStyle(is_incomeStyle);
  1421. return ls_globalMenuStyle + ls_separationStyle;
  1422. };
  1423. /**
  1424. * Get the style for the capacity bar "wrapper".
  1425. *
  1426. * @param {string} is_capacityBarOrientation
  1427. * The orientation of the capacity bar.
  1428. * @param {string} is_incomeStyle
  1429. * How the income is styled.
  1430. *
  1431. * @return {string}
  1432. * The style string.
  1433. */
  1434. var _lf_getCapacityBarStyle = function(is_capacityBarOrientation, is_incomeStyle) {
  1435. var ls_height = 'height: 4px; ';
  1436. var ls_width = 'width: 79px;';
  1437. var ls_right = 'right: 4px; ';
  1438. var ls_marginLeft = '';
  1439. if(is_capacityBarOrientation == 'horizontal')
  1440. ls_width = 'width: 50px; ';
  1441. if(is_capacityBarOrientation == 'vertical') {
  1442. ls_height = 'height: 21px; ';
  1443. ls_width = 'width: 4px; ';
  1444. ls_right = '';
  1445. if(is_incomeStyle == 'alignLeft')
  1446. ls_marginLeft = 'margin-left: -7px; ';
  1447. }
  1448. return '.' + IC.myGM.prefix + 'capacityInformation { position: absolute; bottom: 4px; ' + ls_height + ls_width + ls_right + ls_marginLeft + '} ';
  1449. };
  1450. /**
  1451. * Get the style for the capacity bar with a border.
  1452. *
  1453. * @param {string} is_capacityBarOrientation
  1454. * The orientation of the capacity bar.
  1455. *
  1456. * @return {string}
  1457. * The style string.
  1458. */
  1459. var _lf_getCapacityBarWithBorderStyle = function(is_capacityBarOrientation) {
  1460. var ls_height = 'height: 3px; ';
  1461. var ls_width = 'width: 78px; ';
  1462. var ls_right = 'right: 3px; ';
  1463. if(is_capacityBarOrientation == 'horizontal')
  1464. ls_width = 'width: 50px; ';
  1465. if(is_capacityBarOrientation == 'vertical') {
  1466. ls_height = 'height: 20px; ';
  1467. ls_width = 'width: 3px; ';
  1468. ls_right = '';
  1469. }
  1470. return '.' + IC.myGM.prefix + 'capacityInformation.' + IC.myGM.prefix + 'border { border: 1px inset #906646; bottom: 3px; ' + ls_height + ls_width + ls_right + '} ';
  1471. };
  1472. /**
  1473. * Get the style for the capacity bar.
  1474. *
  1475. * @param {string} is_capacityBarOrientation
  1476. * The orientation of the capacity bar.
  1477. * @param {string} is_incomeStyle
  1478. * How the income is styled.
  1479. *
  1480. * @return {string}
  1481. * The style string.
  1482. */
  1483. var _lf_getCapacityStyle = function(is_capacityBarOrientation, is_incomeStyle) {
  1484. var ls_prefix = IC.myGM.prefix;
  1485. var ls_barStyle = '.' + ls_prefix + 'bar { height: 100%; width: 100%; bottom: 0px; position: absolute; } \
  1486. .' + ls_prefix + 'bar.' + ls_prefix + 'red { background-color: #AA0000; } \
  1487. .' + ls_prefix + 'bar.' + ls_prefix + 'yellow { background-color: #FFD700; } \
  1488. .' + ls_prefix + 'bar.' + ls_prefix + 'green { background-color: #669900; }';
  1489. var ls_capacityStyle = _lf_getCapacityBarStyle(is_capacityBarOrientation, is_incomeStyle);
  1490. var ls_capacityBorderStyle = _lf_getCapacityBarWithBorderStyle(is_capacityBarOrientation);
  1491. return ls_barStyle + ls_capacityStyle + ls_capacityBorderStyle;
  1492. };
  1493. /**
  1494. * Get the style for the direct hourly income in the town view.
  1495. *
  1496. * @param {boolean} ib_capacityBarActive
  1497. * If the capacity bar is shown.
  1498. * @param {string} is_capacityBarOrientation
  1499. * The orientation of the capacity bar.
  1500. * @param {string} is_incomeStyle
  1501. * How the income is styled.
  1502. *
  1503. * @return {string}
  1504. * The style string.
  1505. */
  1506. var _lf_getHourlyIncomeStyle = function(ib_capacityBarActive, is_capacityBarOrientation, is_incomeStyle) {
  1507. var ls_display = 'display: block; ';
  1508. var ls_fontSize = 'font-size: 11px; ';
  1509. var ls_paddingRight = 'padding-right: 4px; ';
  1510. if(ib_capacityBarActive === true && is_capacityBarOrientation !== 'horizontalFull')
  1511. ls_fontSize = 'font-size: 9px; ';
  1512. if(is_incomeStyle == 'alignLeft')
  1513. ls_paddingRight = '';
  1514. return '.' + IC.myGM.prefix + 'hourlyIncomeResource { ' + ls_display + ls_fontSize + ls_paddingRight + '} ';
  1515. };
  1516. /**
  1517. * Get some resource styles which are only set if the capacity bar is active.
  1518. *
  1519. * @param {boolean} ib_directIncomeActive
  1520. * If the direct income is shown.
  1521. * @param {string} is_capacityBarOrientation
  1522. * The orientation of the capacity bar.
  1523. * @param {string} is_incomeStyle
  1524. * How the income is styled.
  1525. *
  1526. * @return {string}
  1527. * The style string.
  1528. */
  1529. var _lf_getResourceStyleCapacityActive = function(ib_directIncomeActive, is_capacityBarOrientation, is_incomeStyle) {
  1530. var ls_height = '';
  1531. var ls_top = '';
  1532. var ls_paddingLeft = '';
  1533. var ls_fontSize = '';
  1534. if(is_capacityBarOrientation == 'horizontalFull') {
  1535. ls_height = 'height: 32px !important; ';
  1536. ls_top = 'top: -2px !important; ';
  1537. }
  1538. if(is_capacityBarOrientation == 'vertical' && is_incomeStyle == 'alignLeft')
  1539. ls_paddingLeft = 'padding-left: 38px !important; ';
  1540. if(is_capacityBarOrientation == 'vertical' || (ib_directIncomeActive === true && is_capacityBarOrientation != 'horizontalFull'))
  1541. ls_fontSize = 'font-size: 11px; ';
  1542. return ls_height + ls_top + ls_paddingLeft + ls_fontSize;
  1543. };
  1544. /**
  1545. * Get the line height for the sored resources.
  1546. *
  1547. * @param {boolean} ib_capacityBarActive
  1548. * If the capacity bar is shown.
  1549. * @param {boolean} ib_directIncomeActive
  1550. * If the direct income is shown.
  1551. * @param {string} is_capacityBarOrientation
  1552. * The orientation of the capacity bar.
  1553. *
  1554. * @return {string}
  1555. * The style string.
  1556. */
  1557. var _lf_getResourceStyleLineHeigth = function(ib_capacityBarActive, ib_directIncomeActive, is_capacityBarOrientation) {
  1558. if(ib_directIncomeActive === true) {
  1559. if(ib_capacityBarActive === true && is_capacityBarOrientation == 'horizontal')
  1560. return 'line-height: 9px !important; ';
  1561. return 'line-height: 11px !important; ';
  1562. }
  1563. if(is_capacityBarOrientation == 'horizontal')
  1564. return 'line-height: 12px !important; ';
  1565. if(is_capacityBarOrientation == 'vertical')
  1566. return 'line-height: 24px !important; ';
  1567. return '';
  1568. };
  1569. /**
  1570. * Get the style for the resource fields.
  1571. *
  1572. * @param {boolean} ib_capacityBarActive
  1573. * If the capacity bar is shown.
  1574. * @param {boolean} ib_directIncomeActive
  1575. * If the direct income is shown.
  1576. * @param {string} is_capacityBarOrientation
  1577. * The orientation of the capacity bar.
  1578. * @param {string} is_incomeStyle
  1579. * How the income is styled.
  1580. *
  1581. * @return {string}
  1582. * The style string.
  1583. */
  1584. var _lf_getResourceStyle = function(ib_capacityBarActive, ib_directIncomeActive, is_capacityBarOrientation, is_incomeStyle) {
  1585. var ls_align = 'text-align: right; ';
  1586. var ls_capacityActive = '';
  1587. var ls_lineHeight = _lf_getResourceStyleLineHeigth(ib_capacityBarActive, ib_directIncomeActive, is_capacityBarOrientation);
  1588. if(is_incomeStyle == 'alignLeft')
  1589. ls_align = '';
  1590. if(ib_capacityBarActive === true)
  1591. ls_capacityActive = _lf_getResourceStyleCapacityActive(ib_directIncomeActive, is_capacityBarOrientation, is_incomeStyle);
  1592. return '#resources_wood, #resources_wine, #resources_marble, #resources_glass, #resources_sulfur { ' + ls_align + ls_lineHeight + ls_capacityActive + ' } ';
  1593. };
  1594. /**
  1595. * Set the styles for the direct income and the capacity bar.
  1596. */
  1597. this.setStyles = function() {
  1598. var lb_capacityBarActive = IC.Options.getOption('resourceInformation', 'showCapacityBar');
  1599. var lb_directIncomeActive = IC.Options.getOption('resourceInformation', 'showDirectIncome');
  1600. // If not both of the checkboxes have been defined yet, do nothing!
  1601. if(lb_capacityBarActive === null || lb_directIncomeActive === null)
  1602. return;
  1603. if(lb_capacityBarActive === false && lb_directIncomeActive === false) {
  1604. IC.myGM.removeStyle('resourceInformation');
  1605. return;
  1606. }
  1607. var ls_capacityBarOrientation = IC.Options.getOption('resourceInformation', 'capacityBarOrientation');
  1608. var ls_incomeStyle = IC.Options.getOption('resourceInformation', 'incomeStyle');
  1609. var ls_incomeStyleString = _lf_getGeneralStyles(ls_incomeStyle)
  1610. + _lf_getResourceStyle(lb_capacityBarActive, lb_directIncomeActive, ls_capacityBarOrientation, ls_incomeStyle);
  1611. if(lb_capacityBarActive === true)
  1612. ls_incomeStyleString += _lf_getCapacityStyle(ls_capacityBarOrientation, ls_incomeStyle);
  1613. if(lb_directIncomeActive === true)
  1614. ls_incomeStyleString += _lf_getHourlyIncomeStyle(lb_capacityBarActive, ls_capacityBarOrientation, ls_incomeStyle);
  1615. IC.myGM.addStyle(ls_incomeStyleString, 'resourceInformation', true);
  1616. };
  1617. };
  1618. /**
  1619. * Storage for the functions for the capacity bar.
  1620. *
  1621. * @type {object}
  1622. */
  1623. var _go_capacityInformation = new function() {
  1624. /**
  1625. * Update the capacity information bars.
  1626. */
  1627. var _lf_updateFields = function() {
  1628. if(IC.ika.model.isOwnCity === false)
  1629. return;
  1630. var la_capacityInformation = [];
  1631. var la_resourceIdentifiers = ['resource', 1, 2, 3, 4];
  1632. la_resourceIdentifiers.forEach(function(im_identifier, ii_index) {
  1633. la_capacityInformation.push({
  1634. warehouse: IC.Ikariam.getInt(IC.ika.getModel().maxResources[im_identifier]),
  1635. branchOffice: IC.Ikariam.getInt(IC.ika.getModel().branchOfficeResources[im_identifier]),
  1636. current: IC.Ikariam.getInt(IC.ika.getModel().currentResources[im_identifier])
  1637. });
  1638. });
  1639. var ls_prefix = '#' + IC.myGM.prefix;
  1640. var ls_styleToChange = 'width';
  1641. if(IC.Options.getOption('resourceInformation', 'capacityBarOrientation') == 'vertical')
  1642. ls_styleToChange = 'height';
  1643. la_capacityInformation.forEach(function(io_capacity, ii_index) {
  1644. var ls_resource = IC.Ikariam.resourceNames[ii_index];
  1645. var li_warehousePercentage = 100;
  1646. var li_resourcePercentage = io_capacity.current / io_capacity.warehouse * 100;
  1647. if(IC.Options.getOption('resourceInformation', 'capacityBarShowBranchOfficeResources') === true) {
  1648. var li_maximumCapacity = io_capacity.warehouse + io_capacity.branchOffice;
  1649. li_warehousePercentage = io_capacity.warehouse / li_maximumCapacity * 100;
  1650. li_resourcePercentage = io_capacity.current / li_maximumCapacity * 100;
  1651. }
  1652. IC.myGM.$(ls_prefix + 'maxCapacity' + ls_resource).style[ls_styleToChange] = '100%';
  1653. IC.myGM.$(ls_prefix + 'warehouseCapacity' + ls_resource).style[ls_styleToChange] = li_warehousePercentage + '%';
  1654. IC.myGM.$(ls_prefix + 'currentResource' + ls_resource).style[ls_styleToChange] = li_resourcePercentage + '%';
  1655. });
  1656. };
  1657. /**
  1658. * Add the capacity information bars.
  1659. */
  1660. var _lf_addFields = function() {
  1661. var la_classes = ['capacityInformation'];
  1662. if(IC.Options.getOption('resourceInformation', 'capacityBarHasBorder') === true)
  1663. la_classes.push('border');
  1664. IC.Ikariam.resourceNames.forEach(function(is_resource) {
  1665. var le_wrapper = IC.myGM.addElement('div', IC.myGM.$('#resources_' + is_resource), { 'id': 'capacityInfo' + is_resource, 'classes': la_classes }, true);
  1666. IC.myGM.addElement('div', le_wrapper, { 'id': 'maxCapacity' + is_resource, 'classes': ['bar', 'yellow'] }, true);
  1667. IC.myGM.addElement('div', le_wrapper, { 'id': 'warehouseCapacity' + is_resource, 'classes': ['bar', 'green'] }, true);
  1668. IC.myGM.addElement('div', le_wrapper, { 'id': 'currentResource' + is_resource, 'classes': ['bar', 'red'] }, true);
  1669. });
  1670. _lf_updateFields();
  1671. };
  1672. /**
  1673. * Remove the capacity information bars.
  1674. */
  1675. var _lf_removeFields = function() {
  1676. IC.myGM.removeElement(IC.myGM.$$('.' + IC.myGM.prefix + 'capacityInformation'));
  1677. };
  1678. /**
  1679. * Update the settings to execute the callback or delete the handler.
  1680. *
  1681. * @param {boolean} ib_showCapacityBar
  1682. * If the user selected the checkbox to show the capacity information.
  1683. */
  1684. this.updateSettings = function(ib_showCapacityBar) {
  1685. _go_styleFunctions.setStyles();
  1686. if(ib_showCapacityBar === true) {
  1687. _lf_addFields();
  1688. IC.Observer.add('updateCapacityBar', IC.myGM.$('#cityResources'), { childList: true, subtree: true }, _lf_updateFields, _lf_updateFields);
  1689. return;
  1690. }
  1691. IC.Observer.remove('updateCapacityBar');
  1692. _lf_removeFields();
  1693. };
  1694. };
  1695. /**
  1696. * Storage for the functions for the direct income.
  1697. *
  1698. * @type {object}
  1699. */
  1700. var _go_directIncome = new function() {
  1701. /**
  1702. * Storage for the tradegood of the last town selected.
  1703. *
  1704. * @type {int}
  1705. */
  1706. var _li_lastTradegood = null;
  1707. /**
  1708. * Delete the data of the tradegood of the last town selected.
  1709. *
  1710. * @param {string} is_hourlyPrefix
  1711. * The prefix for the hourly income wrapper selector.
  1712. * @param {string} is_dailyPrefix
  1713. * The prefix for the daily income wrapper selector.
  1714. */
  1715. var _lf_deleteLastTradegoodData = function(is_hourlyPrefix, is_dailyPrefix) {
  1716. IC.myGM.$(is_hourlyPrefix + IC.Ikariam.resourceNames[_li_lastTradegood]).innerHTML = '';
  1717. IC.myGM.$(is_dailyPrefix + IC.Ikariam.resourceNames[_li_lastTradegood]).innerHTML = '';
  1718. if(_li_lastTradegood !== 1) {
  1719. IC.myGM.$(is_hourlyPrefix + IC.Ikariam.resourceNames[_li_lastTradegood]).classList.add('invisible');
  1720. IC.myGM.$(is_dailyPrefix + 'Wrapper' + IC.Ikariam.resourceNames[_li_lastTradegood]).classList.add('invisible');
  1721. }
  1722. };
  1723. /**
  1724. * Update the direct icome fields.
  1725. *
  1726. * @param {boolean} ib_firstRun
  1727. * If this is the first run after adding the fields.
  1728. */
  1729. var _lf_updateFields = function(ib_firstRun) {
  1730. if(IC.ika.model.isOwnCity === false)
  1731. return;
  1732. var ls_hourlyPrefix = '#' + IC.myGM.prefix + 'hourlyIncomeResource';
  1733. var ls_dailyPrefix = '#' + IC.myGM.prefix + 'dailyIncomeResource';
  1734. if(_li_lastTradegood !== null)
  1735. _lf_deleteLastTradegoodData(ls_hourlyPrefix, ls_dailyPrefix);
  1736. var li_producedTradegood = IC.Ikariam.getInt(IC.ika.getModel().producedTradegood);
  1737. var li_tradegoodProduction = IC.ika.getModel().tradegoodProduction * 3600 + 0.001;
  1738. var li_woodProduction = IC.ika.getModel().resourceProduction * 3600 + 0.001;
  1739. var li_wineSpending = IC.ika.getModel().wineSpendings;
  1740. var li_producesWine = IC.ika.getModel().cityProducesWine;
  1741. var ls_tradegoodName = IC.Ikariam.resourceNames[li_producedTradegood];
  1742. IC.myGM.$(ls_hourlyPrefix + IC.Ikariam.resourceNames[0]).innerHTML = IC.Ikariam.formatToIkaNumber(Math.floor(li_woodProduction), true, true);
  1743. IC.myGM.$(ls_dailyPrefix + IC.Ikariam.resourceNames[0]).innerHTML = IC.Ikariam.formatToIkaNumber(Math.floor(li_woodProduction * 24), false);
  1744. IC.myGM.$(ls_hourlyPrefix + IC.Ikariam.resourceNames[1]).innerHTML = IC.Ikariam.formatToIkaNumber(Math.floor(-1 * li_wineSpending), true, true);
  1745. IC.myGM.$(ls_dailyPrefix + IC.Ikariam.resourceNames[1]).innerHTML = IC.Ikariam.formatToIkaNumber(Math.floor(-1 * li_wineSpending * 24), false);
  1746. IC.myGM.$(ls_dailyPrefix + 'Label' + IC.Ikariam.resourceNames[1]).innerHTML = IC.Language.$('resourceInformation.dailyExpenses', [IC.Language.$('diverse.name.resource.' + IC.Ikariam.resourceNames[1])]);
  1747. if(li_producesWine === true)
  1748. li_tradegoodProduction = li_tradegoodProduction - li_wineSpending;
  1749. if(li_tradegoodProduction >= 0)
  1750. IC.myGM.$(ls_dailyPrefix + 'Label' + ls_tradegoodName).innerHTML = IC.Language.$('resourceInformation.dailyProduction', [IC.Language.$('diverse.name.resource.' + ls_tradegoodName)]);
  1751. else
  1752. IC.myGM.$(ls_dailyPrefix + 'Label' + ls_tradegoodName).innerHTML = IC.Language.$('resourceInformation.dailyExpenses', [IC.Language.$('diverse.name.resource.' + ls_tradegoodName)]);
  1753. IC.myGM.$(ls_hourlyPrefix + ls_tradegoodName).innerHTML = IC.Ikariam.formatToIkaNumber(Math.floor(li_tradegoodProduction), true, true);
  1754. IC.myGM.$(ls_dailyPrefix + ls_tradegoodName).innerHTML = IC.Ikariam.formatToIkaNumber(Math.floor(li_tradegoodProduction * 24), false);
  1755. IC.myGM.$(ls_hourlyPrefix + ls_tradegoodName).classList.remove('invisible');
  1756. IC.myGM.$(ls_dailyPrefix + 'Wrapper' + ls_tradegoodName).classList.remove('invisible');
  1757. _li_lastTradegood = li_producedTradegood;
  1758. };
  1759. /**
  1760. * Add the direct income fields.
  1761. */
  1762. var _lf_addFields = function() {
  1763. if(!IC.myGM.$('js_GlobalMenu_production_container_wood') === true) {
  1764. var le_woodProductionContainer = IC.myGM.$('#js_GlobalMenu_resourceProduction').parentNode;
  1765. le_woodProductionContainer.id = 'js_GlobalMenu_production_container_wood';
  1766. }
  1767. IC.Ikariam.resourceNames.forEach(function(is_resource, ii_index) {
  1768. var ls_resourceParent = is_resource === 'glass' ? 'crystal' : is_resource;
  1769. var la_hourlyClasses = [IC.myGM.prefix + 'hourlyIncomeResource'];
  1770. var la_dailyClasses = ['altTooltip', IC.myGM.prefix + 'dailyIncomeResourceWrapper'];
  1771.  
  1772. if(ii_index >= 2) {
  1773. la_hourlyClasses.push('invisible');
  1774. la_dailyClasses.push('invisible');
  1775. }
  1776. IC.myGM.addElement('span', IC.myGM.$('#resources_' + is_resource), { 'id': 'hourlyIncomeResource' + is_resource, 'classes': la_hourlyClasses });
  1777. var le_dailyIncomeParent = IC.myGM.$('#js_GlobalMenu_' + ls_resourceParent + '_tooltip tbody');
  1778. var le_dailyIncomeInsertBefore = IC.myGM.$('#js_GlobalMenu_production_container_' + ls_resourceParent + ' + tr');
  1779. var le_dailyIncomeWrapper = IC.myGM.addElement('tr', le_dailyIncomeParent, {
  1780. 'id': 'dailyIncomeResourceWrapper' + is_resource,
  1781. 'classes': la_dailyClasses,
  1782. }, null, le_dailyIncomeInsertBefore);
  1783. IC.myGM.addElement('td', le_dailyIncomeWrapper, {
  1784. 'id': 'dailyIncomeResourceLabel' + is_resource,
  1785. 'class': 'smallFont',
  1786. 'innerHTML': IC.Language.$('resourceInformation.dailyProduction', [IC.Language.$('diverse.name.resource.' + is_resource)])
  1787. });
  1788. IC.myGM.addElement('td', le_dailyIncomeWrapper, {
  1789. 'id': 'dailyIncomeResource' + is_resource,
  1790. 'class': 'rightText'
  1791. });
  1792. });
  1793. _lf_updateFields(true);
  1794. };
  1795. /**
  1796. * Remove the direct income fields.
  1797. */
  1798. var _lf_removeFields = function() {
  1799. IC.myGM.removeElement(IC.myGM.$$('.' + IC.myGM.prefix + 'hourlyIncomeResource' + ', .' + IC.myGM.prefix + 'dailyIncomeResourceWrapper'));
  1800. };
  1801. /**
  1802. * Update the settings to execute the callback or delete the handler.
  1803. *
  1804. * @param {boolean} ib_showDirectIncome
  1805. * If the user selected the checkbox to show the income directly in town view.
  1806. */
  1807. this.updateSettings = function(ib_showDirectIncome) {
  1808. _go_styleFunctions.setStyles();
  1809. if(ib_showDirectIncome === true) {
  1810. _lf_addFields();
  1811. IC.RefreshHandler.add('*', 'directIncome', _lf_updateFields);
  1812. return;
  1813. }
  1814. IC.RefreshHandler.remove('*', 'directIncome');
  1815. _lf_removeFields();
  1816. };
  1817. };
  1818. /**
  1819. * Storage for the functions for the resource quicklinks enhancements.
  1820. *
  1821. * @type {object}
  1822. */
  1823. var _go_resourceQuicklinkEnhancements = new function() {
  1824. /**
  1825. * Open the town hall of the selected town.
  1826. */
  1827. var _lf_openTownHall = function() {
  1828. var ls_selectedCity = IC.ika.getModel().relatedCityData.selectedCity;
  1829. var ls_cityId = IC.ika.getModel().relatedCityData[ls_selectedCity].id;
  1830. if(IC.Ikariam.view == 'town') {
  1831. IC.win.ajaxHandlerCall('?view=townHall&cityId=' + ls_cityId + '&position=0');
  1832. return;
  1833. }
  1834. IC.win.ajaxHandlerCall('?view=city&dialog=townHall&cityId=' + ls_cityId + '&position=0');
  1835. };
  1836. /**
  1837. * Update the css to hover only the resources which are clickable.
  1838. */
  1839. var _lf_updateCSS = function() {
  1840. var ls_activeResource = IC.Ikariam.resourceNames[IC.ika.getModel().producedTradegood];
  1841. IC.myGM.addStyle(
  1842. '#resources_population:hover, #resources_wood:hover, #resources_' + ls_activeResource + ':hover { text-shadow: 2px 2px 2px #666; cursor: pointer; color: #333; }',
  1843. 'resourceQuicklinkEnhancements', true
  1844. );
  1845. };
  1846. /**
  1847. * Update the settings to execute the callback or delete the handler.
  1848. *
  1849. * @param {boolean} ib_enhanceResourceQuicklinks
  1850. * If the user selected the checkbox to enhance the resource quicklinks.
  1851. */
  1852. this.updateSettings = function(ib_enhanceResourceQuicklinks) {
  1853. if(ib_enhanceResourceQuicklinks === true) {
  1854. IC.myGM.$('#resources_population').addEventListener('click', _lf_openTownHall, true);
  1855. IC.RefreshHandler.add('*', 'resourceQuicklinkEnhancements', _lf_updateCSS);
  1856. return;
  1857. }
  1858. IC.RefreshHandler.remove('*', 'resourceQuicklinkEnhancements');
  1859. IC.myGM.$('#resources_population').removeEventListener('click', _lf_openTownHall, true);
  1860. IC.myGM.removeStyle('resourceQuicklinkEnhancements');
  1861. };
  1862. };
  1863. IC.Options.addWrapper('resourceInformation', IC.Language.$('resourceInformation.options.wrapperTitle'));
  1864. // Option to show the income directly in town view.
  1865. IC.Options.addCheckbox('showDirectIncome', 'resourceInformation', 1, true, IC.Language.$('resourceInformation.options.directIncome.show'), { changeCallback: _go_directIncome.updateSettings });
  1866. // Option to enhance the resource quicklinks and add one to population.
  1867. IC.Options.addCheckbox('resourceQuicklinkEnhancements', 'resourceInformation', 1, true, IC.Language.$('resourceInformation.options.resourceQuicklinkEnhancements'), { changeCallback: _go_resourceQuicklinkEnhancements.updateSettings });
  1868. // Option to show the capacity information.
  1869. IC.Options.addCheckbox('showCapacityBar', 'resourceInformation', 2, true, IC.Language.$('resourceInformation.options.capacityBar.show'), { changeCallback: _go_capacityInformation.updateSettings });
  1870. // Option to show the capacity bar with border.
  1871. IC.Options.addCheckbox('capacityBarHasBorder', 'resourceInformation', 2, true, IC.Language.$('resourceInformation.options.capacityBar.hasBorder'), {});
  1872. // Option to show also branch office ressources.
  1873. IC.Options.addCheckbox('capacityBarShowBranchOfficeResources', 'resourceInformation', 2, true, IC.Language.$('resourceInformation.options.capacityBar.showBranchOfficeResources'), {});
  1874. // Style of the resources in warehouse / daily income.
  1875. IC.Options.addSelect('incomeStyle', 'resourceInformation', 3, 'alignRight', IC.Language.$('resourceInformation.options.directIncome.style.label'), [
  1876. { value: 'alignRight', label: IC.Language.$('resourceInformation.options.directIncome.style.alignRight') },
  1877. { value: 'alignLeft', label: IC.Language.$('resourceInformation.options.directIncome.style.alignLeft') },
  1878. { value: 'withSeparation', label: IC.Language.$('resourceInformation.options.directIncome.style.withSeparation') }
  1879. ], {});
  1880. // Style of the capacity bar.
  1881. IC.Options.addSelect('capacityBarOrientation', 'resourceInformation', 3, 'vertical', IC.Language.$('resourceInformation.options.capacityBar.orientation.label'), [
  1882. { value: 'vertical', label: IC.Language.$('resourceInformation.options.capacityBar.orientation.vertical') },
  1883. { value: 'horizontal', label: IC.Language.$('resourceInformation.options.capacityBar.orientation.horizontal') },
  1884. { value: 'horizontalFull', label: IC.Language.$('resourceInformation.options.capacityBar.orientation.horizontalFull') }
  1885. ], {});
  1886. })();
  1887. IC.con.logTimeStamp('IkariamEnhancedUI: resource information functions created');
  1888. // Member information in highscore view.
  1889. (function() {
  1890. /**
  1891. * Storage for the member information functions.
  1892. *
  1893. * @type {object}
  1894. */
  1895. var _go_memberInformation = new function() {
  1896. /**
  1897. * Storage for the member data.
  1898. *
  1899. * @type {object}
  1900. */
  1901. var _lo_data = null;
  1902. /**
  1903. * Key for the storage of the member information.
  1904. *
  1905. * @type {string}
  1906. */
  1907. var _ls_dataKey = '';
  1908. /**
  1909. * Key for the storage of the last reset date.
  1910. *
  1911. * @type {string}
  1912. */
  1913. var _ls_timeKey = '';
  1914. /**
  1915. * Show the data.
  1916. */
  1917. var _lf_clickShow = function() {
  1918. IC.myGM.setValue('memberInfo_infoLinkClicked', true).then(function() {
  1919. IC.myGM.$('#tab_highscore input[name="searchUser"]').value = '';
  1920. IC.myGM.$('#searchOnlyFriends').checked = false;
  1921. IC.myGM.$('#searchOnlyAllies').checked = true;
  1922. IC.myGM.$('#tab_highscore input[type="submit"]').click();
  1923. });
  1924. };
  1925. /**
  1926. * Reset the stored data.
  1927. */
  1928. var _lf_clickReset = function() {
  1929. IC.myGM.setValue(_ls_dataKey, _lo_data).then(function() {
  1930. return IC.myGM.setValue(_ls_timeKey, (new Date).getTime());
  1931. }).then(function() {
  1932. _lf_clickShow();
  1933. });
  1934. };
  1935. /**
  1936. * Add the button to show the data.
  1937. */
  1938. var _lf_addShowButton = function() {
  1939. var le_button = IC.myGM.addButton(IC.myGM.$('#tab_highscore .centerButton'), IC.Language.$('highscore.memberInformation.show'), _lf_clickShow, true);
  1940. le_button.id = IC.myGM.prefix + 'showInfo';
  1941. };
  1942. /**
  1943. * Add the button to reset the stored data.
  1944. */
  1945. var _lf_addResetButton = function() {
  1946. var le_button = IC.myGM.addButton(IC.myGM.$('#tab_highscore .content p'), IC.Language.$('highscore.memberInformation.reset'), _lf_clickReset, true);
  1947. le_button.id = IC.myGM.prefix + 'resetInfo';
  1948. };
  1949. /**
  1950. * Get the own data and show the differences to the last stored data.
  1951. *
  1952. * @param {object} io_oldMemberInfo
  1953. * The last stored data.
  1954. *
  1955. * @return {object}
  1956. * The own data.
  1957. */
  1958. var _lf_getOwnDataShowDifference = function(io_oldMemberInfo) {
  1959. var le_ownRow = IC.myGM.$('table.highscore tr.own');
  1960. var ro_ownData = {
  1961. 'place': IC.Ikariam.getInt(IC.myGM.$('.place', le_ownRow).innerHTML),
  1962. 'score': IC.Ikariam.getInt(IC.myGM.$('.score', le_ownRow).innerHTML)
  1963. };
  1964. var ls_placeDifference = '-';
  1965. var ls_scoreDifference = '-';
  1966. if(!!io_oldMemberInfo === true && !!io_oldMemberInfo['own'] === true) {
  1967. ls_placeDifference = IC.Ikariam.formatToIkaNumber(io_oldMemberInfo['own']['place'] - ro_ownData['place'], true, true);
  1968. ls_scoreDifference = IC.Ikariam.formatToIkaNumber(ro_ownData['score'] - io_oldMemberInfo['own']['score'], true, true);
  1969. }
  1970. IC.myGM.addElement('span', IC.myGM.$('.place', le_ownRow), { 'innerHTML': ls_placeDifference });
  1971. IC.myGM.addElement('span', IC.myGM.$('.score', le_ownRow), { 'innerHTML': ls_scoreDifference });
  1972. return ro_ownData;
  1973. };
  1974. /**
  1975. * Get the data and show the differences to the last stored data.
  1976. *
  1977. * @return {Promise}
  1978. * A Promise which resolves to the member data.
  1979. */
  1980. var _lf_getDataShowDifference = async function() {
  1981. var ro_memberInfo = {};
  1982. var lo_oldMemberInfo = await IC.myGM.getValue(_ls_dataKey, null);
  1983. var la_allyMemberRows = IC.myGM.$$('table.highscore tr.ownally');
  1984. la_allyMemberRows.forEach(function(ie_allyMemberRow) {
  1985. var ls_actionLink = IC.myGM.$('.action a', ie_allyMemberRow).href;
  1986. var ls_memberId = ls_actionLink.match(/receiverId=([0-9]*)/i)[1];
  1987. ro_memberInfo[ls_memberId] = {
  1988. 'place': IC.Ikariam.getInt(IC.myGM.$('.place', ie_allyMemberRow).innerHTML),
  1989. 'score': IC.Ikariam.getInt(IC.myGM.$('.score', ie_allyMemberRow).innerHTML)
  1990. };
  1991. var ls_placeDifference = '-';
  1992. var ls_scoreDifference = '-';
  1993. if(!!lo_oldMemberInfo === true && !!lo_oldMemberInfo[ls_memberId] === true) {
  1994. ls_placeDifference = IC.Ikariam.formatToIkaNumber(lo_oldMemberInfo[ls_memberId]['place'] - ro_memberInfo[ls_memberId]['place'], true, true);
  1995. ls_scoreDifference = IC.Ikariam.formatToIkaNumber(ro_memberInfo[ls_memberId]['score'] - lo_oldMemberInfo[ls_memberId]['score'], true, true);
  1996. }
  1997. IC.myGM.addElement('span', IC.myGM.$('.place', ie_allyMemberRow), { 'innerHTML': ls_placeDifference });
  1998. IC.myGM.addElement('span', IC.myGM.$('.score', ie_allyMemberRow), { 'innerHTML': ls_scoreDifference });
  1999. });
  2000. ro_memberInfo['own'] = _lf_getOwnDataShowDifference(lo_oldMemberInfo);
  2001. return Promise.resolve(ro_memberInfo);
  2002. };
  2003. /**
  2004. * Add the span with the time of the last reset.
  2005. *
  2006. * @return {Promise}
  2007. * A Promise which resolves once the last reset time is added.
  2008. */
  2009. var _lf_addLastResetTime = async function() {
  2010. var li_lastResetTime = await IC.myGM.getValue(_ls_timeKey, 0);
  2011. var li_differenceInSec = ((new Date()).getTime() - li_lastResetTime) / 1000;
  2012. var ls_lastReset = IC.Language.$('highscore.memberInformation.noReset');
  2013. if(li_lastResetTime > 0) {
  2014. var li_days = Math.floor(li_differenceInSec / 86400);
  2015. var li_hours = Math.floor(li_differenceInSec / 3600) % 24;
  2016. var li_minutes = Math.floor(li_differenceInSec / 60) % 60;
  2017. ls_lastReset = li_days + 'd ' + li_hours + 'h ' + li_minutes + 'min';
  2018. }
  2019. IC.myGM.addElement('br', IC.myGM.$('#tab_highscore .content p'));
  2020. IC.myGM.addElement('span', IC.myGM.$('#tab_highscore .content p'), {
  2021. 'classes': ['bold', 'brown'],
  2022. 'innerHTML': IC.Language.$('highscore.memberInformation.lastReset', [ls_lastReset])
  2023. });
  2024. };
  2025. /**
  2026. * Prepare the highscore popup to show the data and show the data if requested.
  2027. *
  2028. * @return {Promise}
  2029. * A Promise which resolves once the popup is prepared.
  2030. */
  2031. var _lf_doPreparePopup = async function() {
  2032. _ls_dataKey = IC.Ikariam.serverCode + '_' + IC.ika.getModel().avatarAllyId + '_memberInfo_data_' + IC.myGM.getSelectValue('js_highscoreType', true, true);
  2033. _ls_timeKey = IC.Ikariam.serverCode + '_' + IC.ika.getModel().avatarAllyId + '_memberInfo_time_' + IC.myGM.getSelectValue('js_highscoreType', true, true);
  2034. _lf_addShowButton();
  2035. var lb_linkClicked = await IC.myGM.getValue('memberInfo_infoLinkClicked', false);
  2036. if(lb_linkClicked === true) {
  2037. await IC.myGM.deleteValue('memberInfo_infoLinkClicked');
  2038. _lo_data = await _lf_getDataShowDifference();
  2039. _lf_addResetButton();
  2040. _lf_addLastResetTime();
  2041. }
  2042. };
  2043. /**
  2044. * Update the settings to execute the callback or delete the handler.
  2045. *
  2046. * @param {boolean} ib_showMemberInformation
  2047. * If the user selected the checkbox to show the member information.
  2048. */
  2049. this.updateSettings = function(ib_showMemberInformation) {
  2050. if(ib_showMemberInformation === true) {
  2051. IC.RefreshHandler.add('highscore', 'memberInformation', _lf_doPreparePopup);
  2052. IC.myGM.addStyle(
  2053. '#' + IC.myGM.prefix + "resetInfo { float: right; margin-top: -6px; margin-right: 6px; } \
  2054. .highscore .score span { float: right; text-align: right; width: 70px; } \
  2055. .highscore .place span { float: right; text-align: right; width: 30px; } \
  2056. .highscore th:nth-child(4) { width: 30% !important; } \
  2057. .highscore th:nth-child(5) { width: 10% !important; } \
  2058. #tab_highscore .centerButton { margin: 10px 0px; }",
  2059. 'memberInformation', true
  2060. );
  2061. return;
  2062. }
  2063. IC.RefreshHandler.remove('highscore', 'memberInformation');
  2064. IC.myGM.removeStyle('memberInformation');
  2065. };
  2066. };
  2067. // Show the member information.
  2068. IC.Options.addCheckbox('showMemberInformation', 'diverseOptions', 1, false, IC.Language.$('highscore.options.showMemberInformation'), { changeCallback: _go_memberInformation.updateSettings });
  2069. })();
  2070. IC.con.logTimeStamp('IkariamEnhancedUI: highscore functions created');
  2071. // Message enhancements.
  2072. (function() {
  2073. /**
  2074. * Storage for the url replacement functions.
  2075. *
  2076. * @type {object}
  2077. */
  2078. var _go_replaceURL = new function() {
  2079. /**
  2080. * Show a warning when a replaced link is clicked.
  2081. */
  2082. var _lf_showNotification = function() {
  2083. var ls_urlToOpen = this.innerHTML.IC.decodeHTML();
  2084. var lo_notificationText = {
  2085. header: IC.Language.$('message.replacedUrl.notification.header'),
  2086. body: IC.Language.$('message.replacedUrl.notification.text', ['<span class="bold red">"' + ls_urlToOpen + '"</span>']),
  2087. confirm: IC.Language.$('general.yes'),
  2088. abort: IC.Language.$('general.no')
  2089. };
  2090. var lo_notificationCallback = {
  2091. confirm: function() { IC.win.open(ls_urlToOpen); },
  2092. abort: function() { /* Only set to show the abort button */ }
  2093. };
  2094. IC.myGM.notification(lo_notificationText, lo_notificationCallback);
  2095. };
  2096. /**
  2097. * Replace the links.
  2098. */
  2099. var _lf_doReplace = function() {
  2100. var la_messageBodys = IC.myGM.$$('.msgText');
  2101. la_messageBodys.forEach(function(ie_messageBody) {
  2102. var ls_text = ie_messageBody.innerHTML;
  2103. ie_messageBody.innerHTML = ls_text.replace(/(?:^|\s)(http(s?)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,4}(\/[^<\s]*)?)/g, ' <span class="' + IC.myGM.prefix + 'replacedUrl" title="$1">$1</span> ');
  2104. });
  2105. var la_replacedURLs = IC.myGM.$$('.' + IC.myGM.prefix + 'replacedUrl');
  2106. la_replacedURLs.forEach(function(ie_replacedURL) {
  2107. ie_replacedURL.addEventListener('click', _lf_showNotification, true);
  2108. });
  2109. };
  2110. /**
  2111. * Update the settings to execute the callback or delete the handler.
  2112. *
  2113. * @param {boolean} ib_replaceURL
  2114. * If the user selected the checkbox to replace the url.
  2115. */
  2116. this.updateSettings = function(ib_replaceURL) {
  2117. var la_postboxes = ['diplomacyAdvisor', 'diplomacyAdvisorOutBox', 'diplomacyAdvisorArchive', 'diplomacyAdvisorArchiveOutBox'];
  2118. if(ib_replaceURL === true) {
  2119. IC.RefreshHandler.add(la_postboxes, 'replaceURL', _lf_doReplace);
  2120. IC.myGM.addStyle(
  2121. '.' + IC.myGM.prefix + 'replacedUrl { font-weight: bold; font-style: italic; } \
  2122. .' + IC.myGM.prefix + 'replacedUrl:hover { text-decoration: underline; cursor: pointer; }',
  2123. 'replaceURL', true
  2124. );
  2125. return;
  2126. }
  2127. IC.RefreshHandler.remove(la_postboxes, 'replaceURL');
  2128. IC.myGM.removeStyle('replaceURL');
  2129. };
  2130. };
  2131. /**
  2132. * Storage for the inline message functions.
  2133. *
  2134. * @type {object}
  2135. */
  2136. var _go_inlineMessage = new function() {
  2137. /**
  2138. * Replace the links.
  2139. */
  2140. var _lf_doShowInline = function() {
  2141. var la_messageRows = IC.myGM.$$('#deleteMessages tr.entry');
  2142. var li_displayMaxCharacters = 60;
  2143. la_messageRows.forEach(function(ie_messageRow) {
  2144. var le_subject = IC.myGM.$('.subject', ie_messageRow);
  2145. var ls_typePrefix = /gmessage/.test(ie_messageRow.id) === true ? 'g' : '';
  2146. var ls_id = ie_messageRow.id.replace(ls_typePrefix + 'message', '');
  2147. var le_text = IC.myGM.$('#tbl_' + ls_typePrefix + 'mail' + ls_id + ' .msgText');
  2148. var ls_inlineText = le_text.innerHTML.replace(/<br>/gi, ' ').replace(/\s+/gi, ' ');
  2149. if(ls_inlineText.length > li_displayMaxCharacters)
  2150. ls_inlineText = ls_inlineText.substring(0, li_displayMaxCharacters - 6) + ' (...)';
  2151. le_subject.innerHTML += '<br><sub>' + ls_inlineText + '</sub>';
  2152. });
  2153. // Adjust the size of the Scrollbar.
  2154. IC.ika.controller.adjustSizes();
  2155. };
  2156. /**
  2157. * Update the settings to execute the callback or delete the handler.
  2158. *
  2159. * @param {boolean} ib_displayInlineMessage
  2160. * If the user selected the checkbox to display inline messages.
  2161. */
  2162. this.updateSettings = function(ib_displayInlineMessage) {
  2163. var la_postboxes = ['diplomacyAdvisor', 'diplomacyAdvisorOutBox', 'diplomacyAdvisorArchive', 'diplomacyAdvisorArchiveOutBox'];
  2164. if(ib_displayInlineMessage === true) {
  2165. IC.RefreshHandler.add(la_postboxes, 'inlineMessage', _lf_doShowInline);
  2166. return;
  2167. }
  2168. IC.RefreshHandler.remove(la_postboxes, 'inlineMessage');
  2169. };
  2170. };
  2171. /**
  2172. * Storage for the message signature functions.
  2173. *
  2174. * @type {object}
  2175. */
  2176. var _go_messageSignature = new function() {
  2177. /**
  2178. * Add the signature to a new message.
  2179. */
  2180. var _lf_addSignature = function() {
  2181. var ls_signature = '';
  2182. switch(IC.Options.getOption('messages', 'useMessageSignature')) {
  2183. case IC.Options.SpecificityLevel.GLOBAL:
  2184. ls_signature = IC.Options.getOption('messages', 'globalSignature');
  2185. break;
  2186. case IC.Options.SpecificityLevel.SERVER:
  2187. ls_signature = IC.Options.getOption('messages', 'serverSignature');
  2188. break;
  2189. case IC.Options.SpecificityLevel.PLAYER:
  2190. ls_signature = IC.Options.getOption('messages', 'playerSignature');
  2191. break;
  2192. }
  2193. if(ls_signature === '')
  2194. return;
  2195. var le_textarea = IC.myGM.$('#js_msgTextConfirm');
  2196. var ls_text = le_textarea.value;
  2197. if(IC.Options.getOption('messages', 'signaturePlacementTop'))
  2198. ls_text = '\n\n' + ls_signature + ls_text;
  2199. else
  2200. ls_text = ls_text + '\n\n' + ls_signature;
  2201. le_textarea.value = ls_text;
  2202. le_textarea.setSelectionRange(0,0);
  2203. le_textarea.focus();
  2204. };
  2205. /**
  2206. * Update the settings to execute the callback or delete the handler.
  2207. *
  2208. * @param {boolean} ib_addMessageSignature
  2209. * If the user selected the checkbox to add signatures to messages.
  2210. */
  2211. this.updateSettings = function(is_useMessageSignature) {
  2212. if(is_useMessageSignature === IC.Options.SpecificityLevel.GLOBAL
  2213. || is_useMessageSignature === IC.Options.SpecificityLevel.SERVER
  2214. || is_useMessageSignature === IC.Options.SpecificityLevel.PLAYER) {
  2215. IC.RefreshHandler.add('sendIKMessage', 'addMessageSignature', _lf_addSignature);
  2216. return;
  2217. }
  2218. IC.RefreshHandler.remove('sendIKMessage', 'addMessageSignature');
  2219. };
  2220. };
  2221. IC.Options.addWrapper('messages', IC.Language.$('message.options.wrapperTitle'));
  2222. // Replace urls.
  2223. IC.Options.addCheckbox('replaceURL', 'messages', 1, true, IC.Language.$('message.options.replaceURL'), { changeCallback: _go_replaceURL.updateSettings });
  2224. // Display message text teaser in overview.
  2225. IC.Options.addCheckbox('inlineMessage', 'messages', 1, true, IC.Language.$('message.options.inlineMessage'), { changeCallback: _go_inlineMessage.updateSettings });
  2226. // Player specific signatures.
  2227. var la_options = [
  2228. { value: 'none', label: IC.Language.$('message.options.signature.use.none') },
  2229. { value: IC.Options.SpecificityLevel.GLOBAL, label: IC.Language.$('message.options.signature.use.global') },
  2230. { value: IC.Options.SpecificityLevel.SERVER, label: IC.Language.$('message.options.signature.use.server') },
  2231. { value: IC.Options.SpecificityLevel.PLAYER, label: IC.Language.$('message.options.signature.use.player') }
  2232. ];
  2233. IC.Options.addSelect('useMessageSignature', 'messages', 2, IC.Options.SpecificityLevel.GLOBAL, IC.Language.$('message.options.signature.use.description'), la_options, { changeCallback: _go_messageSignature.updateSettings, 'specificity': IC.Options.SpecificityLevel.PLAYER });
  2234. // Place the signature on top.
  2235. IC.Options.addCheckbox('signaturePlacementTop', 'messages', 2, true, IC.Language.$('message.options.signature.placementTop'), {});
  2236. // Define a global signature.
  2237. IC.Options.addTextArea('globalSignature', 'messages', 3, '', IC.Language.$('message.options.signature.global'), {});
  2238. // Define a server specific signature.
  2239. IC.Options.addTextArea('serverSignature', 'messages', 4, '', IC.Language.$('message.options.signature.server'), { 'specificity': IC.Options.SpecificityLevel.SERVER });
  2240. // Define a server specific signature.
  2241. IC.Options.addTextArea('playerSignature', 'messages', 4, '', IC.Language.$('message.options.signature.player'), { 'specificity': IC.Options.SpecificityLevel.PLAYER });
  2242. })();
  2243. IC.con.logTimeStamp('IkariamEnhancedUI: message functions created');
  2244. // Troop information.
  2245. (function() {
  2246. /**
  2247. * Provider for data storages.
  2248. *
  2249. * @type {object}
  2250. */
  2251. var _go_storageProvider = new function() {
  2252. /**
  2253. * Constructor for troop list.
  2254. */
  2255. var _lf_troopList = function() {
  2256. /**
  2257. * Storage for troop information.
  2258. *
  2259. * @type {lf_troop[]}
  2260. */
  2261. var la_troopList = [];
  2262. /**
  2263. * Troop information storage.
  2264. *
  2265. * @param {string} is_name
  2266. * The name of the troop.
  2267. * @param {int} ii_number
  2268. * The number of the troop.
  2269. */
  2270. var lf_troop = function(is_name, ii_number) {
  2271. var ls_name = is_name;
  2272. var li_number = ii_number;
  2273. this.toString = function() {
  2274. return '\n' + ls_name + ': ' + li_number;
  2275. };
  2276. };
  2277. /**
  2278. * If the troop list contains no entries.
  2279. *
  2280. * @return {boolean}
  2281. * If the troop list is empty.
  2282. */
  2283. this.__defineGetter__('isEmpty', function() {
  2284. return la_troopList.length < 1;
  2285. });
  2286. /**
  2287. * Add a new troop to the troop list.
  2288. *
  2289. * @param {string} is_name
  2290. * The name of the troop.
  2291. * @param {int} ii_number
  2292. * The number of the troop.
  2293. */
  2294. this.addTroop = function(is_name, ii_number) {
  2295. la_troopList.push(new lf_troop(is_name, ii_number));
  2296. };
  2297. /**
  2298. * Transform the troop list to a string.
  2299. *
  2300. * @return {string}
  2301. * The string representation of the troop list.
  2302. */
  2303. this.toString = function() {
  2304. return la_troopList.join('');
  2305. };
  2306. };
  2307. /**
  2308. * Constructor for troop list of foreign player.
  2309. *
  2310. * @param {string} is_playerName
  2311. * The name of the player who owns the troops.
  2312. */
  2313. var _lf_foreignTroopList = function(is_playerName) {
  2314. /**
  2315. * The name of the player who owns the troops.
  2316. *
  2317. * @type {string}
  2318. */
  2319. var ls_playerName = is_playerName;
  2320. /**
  2321. * Storage for troop information.
  2322. *
  2323. * @type {_lf_troopList[]}
  2324. */
  2325. var lo_troopList = new _lf_troopList();
  2326. /**
  2327. * If the troop list contains no entries.
  2328. *
  2329. * @return {boolean}
  2330. * If the troop list is empty.
  2331. */
  2332. this.__defineGetter__('isEmpty', function() {
  2333. return lo_troopList.isEmpty;
  2334. });
  2335. /**
  2336. * Add a new troop to the troop list.
  2337. *
  2338. * @param {string} is_name
  2339. * The name of the troop.
  2340. * @param {int} ii_number
  2341. * The number of the troop.
  2342. */
  2343. this.addTroop = function(is_name, ii_number) {
  2344. lo_troopList.addTroop(is_name, ii_number);
  2345. };
  2346. /**
  2347. * Transform the troop list to a string.
  2348. *
  2349. * @return {string}
  2350. * The string representation of the troop list.
  2351. */
  2352. this.toString = function() {
  2353. return '\n* ' + ls_playerName + ' *' + lo_troopList;
  2354. };
  2355. };
  2356. /**
  2357. * Storage for multiple troop lists.
  2358. *
  2359. * @param {string} is_type
  2360. * The type of the troops (units / ships)
  2361. * @param {string} is_status
  2362. * The status of the troops (own / friends / enemies)
  2363. */
  2364. var _lf_troopListStorage = function(is_type, is_status) {
  2365. /**
  2366. * The type of the troops (units / ships).
  2367. *
  2368. * @type {string}
  2369. */
  2370. var ls_type = is_type;
  2371. /**
  2372. * The status of the troops (own / friends / enemies).
  2373. *
  2374. * @type {string}
  2375. */
  2376. var ls_status = is_status;
  2377. /**
  2378. * The troop lists.
  2379. *
  2380. * @type {(_lf_troopList||_lf_foreignTroopList)[]}
  2381. */
  2382. var la_troopLists = [];
  2383. /**
  2384. * The status of the troop lists (own / friends / enemies).
  2385. *
  2386. * @return {boolean}
  2387. * The status of the lists.
  2388. */
  2389. this.__defineGetter__('status', function() {
  2390. return ls_status;
  2391. });
  2392. /**
  2393. * Add a new troop list to the storage.
  2394. *
  2395. * @param {_lf_troopList||_lf_foreignTroopList} io_troopList
  2396. * The troop list to add.
  2397. */
  2398. this.addTroopList = function(io_troopList) {
  2399. la_troopLists.push(io_troopList);
  2400. };
  2401. /**
  2402. * Transform the troop list storage to a string.
  2403. *
  2404. * @return {string}
  2405. * The string representation of the troop list storage.
  2406. */
  2407. this.toString = function() {
  2408. return '\n--- ' + IC.Language.$('troopInformation.' + ls_type + '.' + ls_status) + ' ---' + la_troopLists.join('\n');
  2409. };
  2410. };
  2411. /**
  2412. * Storage for data of all troops of one type.
  2413. *
  2414. * @param {string} is_type
  2415. * The type of the troops (units / ships)
  2416. */
  2417. var _lf_troopData = function(is_type) {
  2418. /**
  2419. * The type of the troops (units / ships).
  2420. *
  2421. * @type {string}
  2422. */
  2423. var ls_type = is_type;
  2424. /**
  2425. * The troop list storages.
  2426. *
  2427. * @type {_lf_troopListStorage[]}
  2428. */
  2429. var la_listStorages = [];
  2430. /**
  2431. * If the troop list contains no entries.
  2432. *
  2433. * @return {boolean}
  2434. * If the troop list is empty.
  2435. */
  2436. this.__defineGetter__('isEmpty', function() {
  2437. return la_listStorages.length < 1;
  2438. });
  2439. /**
  2440. * Add a new troop list to the storage.
  2441. *
  2442. * @param {string} is_status
  2443. * The status of the troop list.
  2444. * @param {_lf_troopList||_lf_foreignTroopList} io_troopList
  2445. * The troop list to add.
  2446. */
  2447. this.addTroopList = function(is_status, io_troopList) {
  2448. for(var i = 0; i < la_listStorages.length; i++) {
  2449. if(la_listStorages[i].status === is_status) {
  2450. la_listStorages[i].addTroopList(io_troopList);
  2451. return;
  2452. }
  2453. }
  2454. var lo_listStorage = new _lf_troopListStorage(ls_type, is_status);
  2455. lo_listStorage.addTroopList(io_troopList);
  2456. la_listStorages.push(lo_listStorage);
  2457. };
  2458. /**
  2459. * Transform the troop data to a string.
  2460. *
  2461. * @param {string} is_townInformation
  2462. * The information about the town for which the troop data is displayed.
  2463. *
  2464. * @return {string}
  2465. * The string representation of the troop data.
  2466. */
  2467. this.getString = function(is_townInformation) {
  2468. return '===== ' + IC.Language.$('troopInformation.' + ls_type + '.label', [is_townInformation]) + ' =====' + la_listStorages.join('\n\n');
  2469. };
  2470. };
  2471. /**
  2472. * Get a new troop list representation for own troops.
  2473. *
  2474. * @return {_lf_troopList}
  2475. * The troop list.
  2476. */
  2477. this.ownTroopList = function() {
  2478. return new _lf_troopList();
  2479. };
  2480. /**
  2481. * Get a new troop list representation for foreign troops.
  2482. *
  2483. * @param {string} is_playerName
  2484. * The name of the player who owns the troops.
  2485. *
  2486. * @return {_lf_foreignTroopList}
  2487. * The troop list.
  2488. */
  2489. this.foreignTroopList = function(is_playerName) {
  2490. return new _lf_foreignTroopList(is_playerName);
  2491. };
  2492. /**
  2493. * Get a new troop data storage representation for all troops of one type.
  2494. *
  2495. * @param {string} is_type
  2496. * The type of the troops (units / ships).
  2497. *
  2498. * @return {_lf_troopData}
  2499. * The troop data storage.
  2500. */
  2501. this.troopData = function(is_type) {
  2502. return new _lf_troopData(is_type);
  2503. };
  2504. };
  2505. /**
  2506. * Storage for the dta extraction functions.
  2507. *
  2508. * @type {object}
  2509. */
  2510. var _go_dataExtractor = new function() {
  2511. /**
  2512. * Extract own troops from a wrapper.
  2513. *
  2514. * @param {element} ie_wrapper
  2515. * The wrapper to extract the troops from.
  2516. *
  2517. * @return {_go_storageProvider.ownTroopList[]}
  2518. * The extracted troops.
  2519. */
  2520. var _lf_extractOwnTroops = function(ie_wrapper) {
  2521. var la_nameCells = IC.myGM.$$('.table01 .title_img_row th .tooltip', ie_wrapper);
  2522. var la_numberCells = IC.myGM.$$('.table01 .count td', ie_wrapper);
  2523. var ro_troops = _go_storageProvider.ownTroopList();
  2524. for(var i = 0; i < la_nameCells.length; i++) {
  2525. var li_number = IC.Ikariam.getInt(la_numberCells[i].innerHTML);
  2526. if(li_number > 0)
  2527. ro_troops.addTroop(la_nameCells[i].innerHTML, li_number);
  2528. }
  2529. return ro_troops;
  2530. };
  2531. /**
  2532. * Extract foreign troops from a wrapper.
  2533. *
  2534. * @param {element} ie_wrapper
  2535. * The wrapper to extract the troops from.
  2536. *
  2537. * @return {_go_storageProvider.foreignTroopList[]}
  2538. * The extracted troops.
  2539. */
  2540. var _lf_extractForeignTroops = function(ie_wrapper) {
  2541. var la_nameCells = IC.myGM.$$('.table01 .title_img_row th:not(:first-child) .tooltip', ie_wrapper);
  2542. var la_numberRows = IC.myGM.$$('.table01 tr:not(.title_img_row)', ie_wrapper);
  2543. var lo_numberCells = {};
  2544. for(var i = 0; i < la_numberRows.length; i++) {
  2545. var ls_playerName = IC.myGM.$('td a', la_numberRows[i]).innerHTML.trim();
  2546. if(!lo_numberCells[ls_playerName]) {
  2547. lo_numberCells[ls_playerName] = [];
  2548. }
  2549. lo_numberCells[ls_playerName] = lo_numberCells[ls_playerName].concat(IC.myGM.$$('td:not(:first-child)', la_numberRows[i]));
  2550. }
  2551. var ra_troops = [];
  2552. IC.myGM.forEach(lo_numberCells, function (is_playerName, ia_numberCells) {
  2553. var lo_playerTroops = _go_storageProvider.foreignTroopList(is_playerName);
  2554. for(var i = 0; i < la_nameCells.length; i++) {
  2555. var li_number = IC.Ikariam.getInt(ia_numberCells[i].innerHTML);
  2556. if(li_number > 0)
  2557. lo_playerTroops.addTroop(la_nameCells[i].innerHTML, li_number);
  2558. }
  2559. if(lo_playerTroops.isEmpty === false)
  2560. ra_troops.push(lo_playerTroops);
  2561. });
  2562. return ra_troops;
  2563. };
  2564. /**
  2565. * Extract all troop of one type.
  2566. *
  2567. * @param {string} is_type
  2568. * The type of the troops to extract (units / ships).
  2569. * @param {string} is_wrapperTabId
  2570. * The id of the tab which contains the wrappers.
  2571. *
  2572. * @return {_go_storageProvider.troopData}
  2573. * The extracted data.
  2574. */
  2575. var _lf_extractTroops = function(is_type, is_wrapperTabId) {
  2576. var ro_return = _go_storageProvider.troopData(is_type);
  2577. var la_wrappers = IC.myGM.$$('#' + is_wrapperTabId + ' .contentBox01h');
  2578. var lo_ownTroops = _lf_extractOwnTroops(la_wrappers[0]);
  2579. if(lo_ownTroops.isEmpty === false)
  2580. ro_return.addTroopList('own', lo_ownTroops);
  2581. var la_foreignStatus = ['friends', 'enemies'];
  2582. for(var i = 0; i < la_foreignStatus.length; i++) {
  2583. var la_foreignTroops = _lf_extractForeignTroops(la_wrappers[i + 2]);
  2584. for(var j = 0; j < la_foreignTroops.length; j++) {
  2585. ro_return.addTroopList(la_foreignStatus[i], la_foreignTroops[j]);
  2586. }
  2587. }
  2588. return ro_return;
  2589. };
  2590. /**
  2591. * Extract all troop from the popup.
  2592. *
  2593. * @return {object}
  2594. * All extracted troops.
  2595. * Signature: { units: <_go_storageProvider.troopData>, ships: <_go_storageProvider.troopData> }
  2596. */
  2597. this.extract = function() {
  2598. return {
  2599. units: _lf_extractTroops('units', 'tabUnits'),
  2600. ships: _lf_extractTroops('ships', 'tabShips')
  2601. };
  2602. };
  2603. };
  2604. /**
  2605. * Storage for the troop information functions.
  2606. *
  2607. * @type {object}
  2608. */
  2609. var _go_troopInformation = new function() {
  2610. /**
  2611. * Show the troop information popup.
  2612. *
  2613. * @param {object} io_data
  2614. * All extracted troop.
  2615. * Signature: { units: <_go_storageProvider.troopData>, ships: <_go_storageProvider.troopData> }
  2616. */
  2617. var _ls_showPopup = function(io_data) {
  2618. var la_output = [];
  2619. var ls_townInformation = (function() {
  2620. var lo_allTowns = IC.ika.getModel().relatedCityData;
  2621. var lo_selectedTown = lo_allTowns[lo_allTowns.selectedCity];
  2622. return lo_selectedTown.name + ' ' + lo_selectedTown.coords;
  2623. })();
  2624. if(!!io_data === true) {
  2625. if(!!io_data.units.isEmpty === false)
  2626. la_output.push(io_data.units.getString(ls_townInformation));
  2627. if(!!io_data.ships.isEmpty === false)
  2628. la_output.push(io_data.ships.getString(ls_townInformation));
  2629. }
  2630. var ls_output = la_output.join('\n\n-------------------------------------------------------------------------------------\n\n');
  2631. if(ls_output.length === 0)
  2632. ls_output = IC.Language.$('troopInformation.noTroops', [ls_townInformation]);
  2633. var lo_text = {
  2634. header: IC.Language.$('troopInformation.header', [ls_townInformation]),
  2635. body: ls_output
  2636. };
  2637. IC.myGM.notification(lo_text, null, { textarea: true, readonly: true, autoselect: true });
  2638. };
  2639. /**
  2640. * Extract the data and show the popup.
  2641. */
  2642. var _lf_showInformation = function() {
  2643. _ls_showPopup(_go_dataExtractor.extract());
  2644. };
  2645. /**
  2646. * Show the troop information link.
  2647. */
  2648. var _lf_doShowTroopInformationLink = function() {
  2649. var le_button = IC.myGM.addButton(IC.myGM.$('#cityMilitary_c .buildingDescription'), IC.Language.$('troopInformation.button'), _lf_showInformation, true);
  2650. var la_cssRules = [['position', 'absolute'], ['top', '5px'], ['right', '20px']];
  2651. for(var i = 0; i < la_cssRules.length; i++) {
  2652. le_button.style[la_cssRules[i][0]] = la_cssRules[i][1];
  2653. }
  2654. };
  2655. /**
  2656. * Update the settings to execute the callback or delete the handler.
  2657. *
  2658. * @param {boolean} ib_enableTroopInformation
  2659. * If the user selected the checkbox to show the troop information.
  2660. */
  2661. this.updateSettings = function(ib_enableTroopInformation) {
  2662. if(ib_enableTroopInformation === true) {
  2663. IC.RefreshHandler.add('cityMilitary', 'troopInformation', _lf_doShowTroopInformationLink);
  2664. return;
  2665. }
  2666. IC.RefreshHandler.remove('cityMilitary', 'troopInformation');
  2667. };
  2668. };
  2669. /**
  2670. * Storage for the link barracks and shipyard functions.
  2671. *
  2672. * @type {object}
  2673. */
  2674. var _go_linkBarrackShipyard = new function() {
  2675. /**
  2676. * Adds a link to the container.
  2677. *
  2678. * @param {String} is_type
  2679. * The link type (units / fleet).
  2680. * @param {Element} ie_container
  2681. * The element which should be container for the link.
  2682. */
  2683. var _lf_addLink = function(is_type, ie_container) {
  2684. var lo_data = IC.ika.getScreen().data;
  2685. var ls_linkText = is_type === 'units' ? IC.Language.$('troopInformation.link.gotoBarracks') : IC.Language.$('troopInformation.link.gotoShipyard');
  2686. ls_linkText = '(' + ls_linkText + ')';
  2687. var ls_buildingType = is_type === 'units' ? 'barracks' : 'shipyard';
  2688. var li_position = -1;
  2689. for(var i = 0; i < lo_data.position.length; i++) {
  2690. if(lo_data.position[i].building === ls_buildingType) {
  2691. li_position = i;
  2692. break;
  2693. }
  2694. }
  2695. if(li_position >= 0) {
  2696. var ls_href = '?view=%building%&cityId=%cityId%&position=%position%'
  2697. .replace(/%building%/gi, ls_buildingType)
  2698. .replace(/%cityId%/gi, lo_data.id)
  2699. .replace(/%position%/gi, li_position);
  2700. IC.myGM.addElement('a', ie_container, {
  2701. innerHTML: ls_linkText,
  2702. href: ls_href,
  2703. onclick: 'ajaxHandlerCall(this.href);return false;',
  2704. style: [['margin-left', '5px']]
  2705. });
  2706. }
  2707. };
  2708. /**
  2709. * Link barack and shipyard from troop overview screen.
  2710. */
  2711. var _lf_doLinkBarrackShipyardOverview = function() {
  2712. var le_container = IC.myGM.$('.header', IC.myGM.$('#tabUnits'));
  2713. _lf_addLink('units', le_container);
  2714. le_container = IC.myGM.$('.header', IC.myGM.$('#tabShips'));
  2715. _lf_addLink('fleet', le_container);
  2716. };
  2717. /**
  2718. * Link barrack and shipyard in dismiss units screen.
  2719. */
  2720. var _lf_doLinkBarrackShipyardDismiss = function() {
  2721. var ls_type = IC.myGM.$('#js_garrisonEditForm input[name=function]').value.replace(/fire/gi, '').toLowerCase();
  2722. var le_container = IC.myGM.$('#js_garrisonEditForm .header');
  2723. _lf_addLink(ls_type, le_container);
  2724. };
  2725. /**
  2726. * Update the settings to execute the callback or delete the handler.
  2727. *
  2728. * @param {boolean} ib_linkBarrackShipyard
  2729. * If the user selected the checkbox to link barrackand shipyard.
  2730. */
  2731. this.updateSettings = function(ib_linkBarrackShipyard) {
  2732. if(ib_linkBarrackShipyard === true) {
  2733. IC.RefreshHandler.add('cityMilitary', 'linkBarrackShipyardOverview', _lf_doLinkBarrackShipyardOverview);
  2734. IC.RefreshHandler.add('garrisonEdit', 'linkBarrackShipyardDismiss', _lf_doLinkBarrackShipyardDismiss);
  2735. return;
  2736. }
  2737. IC.RefreshHandler.remove('cityMilitary', 'linkBarrackShipyardOverview');
  2738. IC.RefreshHandler.remove('garrisonEdit', 'linkBarrackShipyardDismiss');
  2739. };
  2740. };
  2741. IC.Options.addCheckbox('showTroopInformation', 'diverseOptions', 1, true, IC.Language.$('troopInformation.options.show'), { changeCallback: _go_troopInformation.updateSettings });
  2742. IC.Options.addCheckbox('linkBarrackShipyard', 'diverseOptions', 1, true, IC.Language.$('troopInformation.options.linkBarrackShipyard'), { changeCallback: _go_linkBarrackShipyard.updateSettings });
  2743. })();
  2744. IC.con.logTimeStamp('IkariamEnhancedUI: troop information functions created');
  2745. IC.con.groupEnd();
  2746. }
  2747.  
  2748. /**
  2749. * Main function of the script.<br>
  2750. * Inits the Ikariam Core and calls the script functions.<br>
  2751. * Must be called with <pre>setTimeout(main, 0)</pre> for correct setting of some core variables.
  2752. */
  2753. async function main() {
  2754. // Get the Ikariam core.
  2755. var IC = new IkariamCore('4.2', 4369, 'Ikariam Enhanced UI', 'Tobbe', false);
  2756. if(IC.myGM.alreadyExecuted === true)
  2757. return;
  2758. await IC.Language.setDefaultLanguage('en');
  2759. var la_language = [
  2760. { code: 'de', translations: {"view": {"options": {"wrapperTitle": "Anzeige","moveLoadingCircle": "Ladekreis in Positionsleiste verschieben","hideBirds": "Den Vogelschwarm nicht anzeigen","noVerticalCenterInTownAdvisor": "Städteinformationen im Städteberater vertikal nicht zentrieren"}},"island": {"options": {"showColonizingCityInfo": "Informationen über kolonisierende Städte anzeigen"}},"finance": {"options": {"showIncomeOnTop": "Einkommen in der Bilanz auch oben anzeigen","shortUpkeepReductionTable": "Eine gekürzte Version der Einkommensreduktion anzeigen"},"income": {"perHour": "Einkommen pro Stunde","perDay": "Einkommen pro Tag","start": "Einkommen ohne Abzüge"},"upkeep": {"reason": {"0": "Truppen","1": "Schiffe","2": "Truppen & Schiffe"},"basic": "Grundkosten","supply": "Versorgungskosten","result": "Gesamtkosten"}},"missingResources": {"options": {"wrapperTitle": "Fehlende Ressourcen","show": "Fehlende Ressourcen anzeigen","showPositive": "Auch die nach einem Upgrade noch verbleibenden Ressourcen anzeigen","showColoured": "Die verbleibenden Ressourcen farbig anzeigen"}},"tooltips": {"options": {"autoshow": "Tooltips in Allianzmitgliederliste und Militärberater automatisch anzeigen","showDirectInMilitaryAdvisor": "Informationen über Ladungen / Flotten im Militärberater ohne Tooltip anzeigen"}},"zoom": {"options": {"wrapperTitle": "Zoom Funktion","zoomView": "Zoomen in Weltansicht, Inselansicht und Stadtansicht aktivieren","factor": {"world": "Zoom in der Weltkarte:","island": "Zoom in der Inselansicht:","town": "Zoom in der Stadtansicht:"},"scaleChildren": {"label": "Beschriftungen und Symbole beim Zoomen in folgenden Ansichten in Normalgröße belassen:","world": "Weltkarte","island": "Inselansicht","town": "Stadtansicht"},"accessKeyLabel": "Folgende Tasten müssen gedrückt sein, um mit der Maus zoomen zu können:"},"zoomIn": "Reinzoomen","factor": "Zoom Faktor","zoomOut": "Rauszoomen"},"resourceInformation": {"options": {"wrapperTitle": "Einkommen in Stadtansicht","resourceQuicklinkEnhancements": "Ressourcenanzahl zu Rathaus und Minen verlinken","directIncome": {"show": "Tageseinkommen in der Stadtansicht anzeigen","style": {"label": "Darstellung des Einkommens in der Stadtansicht:","alignRight": "Rechtsbündig","alignLeft": "Linksbündig","withSeparation": "Rechtsbündig & Separator"}},"capacityBar": {"show": "Informationsbalken für Lagerhausfüllstand anzeigen","hasBorder": "Mit Rahmen","showBranchOfficeResources": "Auch Ressourcen in Kontor anzeigen","orientation": {"label": "Orientierung des Balkens","vertical": "Vertikal","horizontal": "Horizontal","horizontalFull": "Horizontal, volle Länge"}}},"dailyProduction": "Tagesproduktion %$1:","dailyExpenses": "Tägliche Ausgaben %$1:"},"highscore": {"options": {"showMemberInformation": "Speichern von Highscoreständen von Allianzmitgliedern ermöglichen"},"memberInformation": {"show": "Alli Infos","reset": "Zurücksetzen","lastReset": "Zeit seit dem letzten Zurücksetzen: %$1","noReset": "Bisher nicht zurückgesetzt."}},"message": {"options": {"wrapperTitle": "Nachrichten","replaceURL": "Links in Nachrichten anklickbar machen","inlineMessage": "Bette die ersten Zeichen einer Nachricht direkt in der Nachrichtenübersicht ein","signature": {"use": {"description": "Diese Signatur verwenden:","none": "Keine Signatur","global": "Globale Signatur","server": "Server Signatur","player": "Spieler Signatur"},"placementTop": "Signatur oberhalb von Zitaten einfügen","global": "Globale Signatur, die auf allen Welten verwendet werden kann:","server": "Server Signatur, welcher nur auf dieser Welt genutzt wird:","player": "Spieler Signatur, welche nur für diesen Spieler genutzt wird:"}},"replacedUrl": {"notification": {"header": "Achtung!","text": "Du bist dabei, den Link %$1 zu öffnen. Das öffnen dieses Links erfolgt auf eigenes Risiko. Trotzdem fortfahren?"}}},"troopInformation": {"options": {"show": "Truppeninformationen anzeigen","linkBarrackShipyard": "Kaserne und Kriegswerft in Truppenübersicht und Einheiten entlassen verlinken"},"link": {"gotoBarracks": "zur Kaserne","gotoShipyard": "zur Kriegswerft"},"units": {"label": "Einheiten in %$1","own": "Eigene Einheiten","friends": "Befreundete Einheiten","enemies": "Feindliche Einheiten"},"ships": {"label": "Schiffe in %$1","own": "Eigene Schiffe","friends": "Befreundete Schiffe","enemies": "Feindliche Schiffe"},"button": "Truppeninformationen","header": "Truppen in %$1","noTroops": "Es befinden sich keine Truppen in %$1"},"diverse": {"options": {"wrapperTitle": "Verschiedenes"},"name": {"resource": {"gold": "Gold","wood": "Baumaterial","wine": "Wein","marble": "Marmor","glass": "Kristallglas","sulfur": "Schwefel"},"unit": {"swordsman": "Schwertkämpfer","phalanx": "Hoplit","archer": "Bogenschütze","marksman": "Schwefelbüchsen-Schütze","mortar": "Mörser","slinger": "Steinschleuderer","catapult": "Katapult","ram": "Rammbock","steamgiant": "Dampfgigant","bombardier": "Ballon-Bombardier","cook": "Koch","medic": "Arzt","girocopter": "Gyrokopter","spearman": "Speerträger","spartan": "Spartaner"},"ship": {"ballista": "Ballistaschiff","catapult": "Katapultschiff","flamethrower": "Feuerschiff","mortar": "Mörserschiff","ram": "Rammschiff","steamboat": "Dampframme","rocketship": "Raketenschiff","submarine": "Tauchboot","paddlespeedship": "Schaufelschnellboot","ballooncarrier": "Ballonträger","tender": "Tender","transport": "Handelsschiff"}}}} },
  2761. { code: 'gr', translations: {"view": {"options": {"wrapperTitle": "Προβολή","moveLoadingCircle": "Μετακίνηση κύκλου φόρτωσης στη γραμμή θέσης","hideBirds": "Απόκρυψη του σμήνους πουλιών","noVerticalCenterInTownAdvisor": "Μη κεντράρισμα πληροφοριών πόλης στον σύμβουλο πόλης"}},"island": {"options": {"showColonizingCityInfo": "Προβολή πληροφοριών για τον αποικισμό πόλεων"}},"finance": {"options": {"showIncomeOnTop": "Προβολή εισοδήματος στην κορυφή στο παράθυρο ισοζυγίου","shortUpkeepReductionTable": "Προβολή μιας μικρής έκδοσης της μείωσης κόστους"},"income": {"perHour": "Εισόδημα ανά ώρα","perDay": "Εισόδημα ανά ημέρα","start": "Εισόδημα χωρίς μείωση"},"upkeep": {"reason": {"0": "Μονάδες στρατού","1": "Πλοία","2": "Μονάδες Στρατού και Πλοία"},"basic": "Βασικά Κόστη","supply": "Κόστη Προμήθειας","result": "Συνολικά Κόστη"}},"missingResources": {"options": {"wrapperTitle": "Χαμένοι Πόροι","show": "Προβολή χαμένων πόρων στην προβολή κατασκευής","showPositive": "Προβολή επίσης των απομένοντων πόρων μετά από αναβάθμιση","showColoured": "Προβολή των απομένοντων πόρων χρωματισμένων"}},"tooltips": {"options": {"autoshow": "Προβολή επεξηγήσεων στο παράθυρο προβολής μελών της συμμαχίας και στον στρατιωτικό σύμβουλο αυτόματα","showDirectInMilitaryAdvisor": "Προβολή πληροφοριών για εμπορικές μεταφορές / μεταγωγές στο παράθυρο στρατού χωρίς επεξηγήσεις"}},"zoom": {"options": {"wrapperTitle": "Λειτουργία εστίασης","zoomView": "Ενεργοποιήση εστίασης σε παγκόσμια, νησιωτική και αστική προβολή","factor": {"world": "Εστίαση παγκόσμιου χάρτη:","island": "Εστίαση νησιωτικής προβολής:","town": "Εστίαση στην αστική προβολή:"},"scaleChildren": {"label": "Διατήρηση διαφημίσεων και συμβόλων σε κανονικό μέγεθος κατά την εστίαση σε αυτή την προβολή:","world": "Παγκόσμιος χάρτης","island": "Νησιωτική προβολή","town": "Αστική προβολή"},"accessKeyLabel": "Αυτά τα κλειδιά πρέπει να πατιούνται για εστίαση με το ποντίκι:"},"zoomIn": "Μεγέθυνση","factor": "Συντελεστής εστίασης","zoomOut": "Σμίκρυνση"},"resourceInformation": {"options": {"wrapperTitle": "Πληροφορίες πόρου","resourceQuicklinkEnhancements": "Σύνδεση αριθμού πόρου στο δημαρχείο / ορυχεία","directIncome": {"show": "Προβολή του ωριαίου εισοδήματος άμεσα στην αστική προβολή","style": {"label": "Στυλ του ωριαίου εισοδήματος στην αστική προβολή:","alignRight": "Δεξιά ευθυγράμμιση","alignLeft": "Αριστερή ευθυγράμμιση","withSeparation": "Δεξιά ευθυγράμμιση με διαχωρισμό"}},"capacityBar": {"show": "Προβολή γραμμής πληροφοριών για τη χωρητικότητα της αποθήκης","hasBorder": "Έχει όριο","showBranchOfficeResources": "Προβολή πόρων στο εμπορικό ανταλλακτήριο","orientation": {"label": "Προσανατολισμός της γραμμής","vertical": "Κάθετος","horizontal": "Οριζόντιος","horizontalFull": "Οριζόντιος, πλήρες μήκος"}}},"dailyProduction": "Ημερήσια παραγωγή %$1:","dailyExpenses": "Ημερήσιες δαπάνες %$1:"},"highscore": {"options": {"showMemberInformation": "Ενεργοποίηση της πιθανότητας αποθήκευσης δεδομένων βαθμολογίας των μελών της συμμαχίας"},"memberInformation": {"show": "Πληροφορίες συμμαχίας","reset": "Επαναφορά","lastReset": "Χρόνος από την τελευταία επαναφορά: %$1","noReset": "Καμιά επαναφορά μέχρι στιγμής."}},"message": {"options": {"wrapperTitle": "Μηνύματα","replaceURL": "Δημιουργία ενεργών συνδέσμων στα μηνύματα","inlineMessage": "Ενσωμάτωση των πρώτων λίγων χαρακτήρων σε κάθε μήνυμα στην επισκόπηση μηνυμάτων","signature": {"use": {"description": "Χρήση αυτής της υπογραφής:","none": "Χωρίς υπογραφή","global": "Καθολική υπογραφή","server": "Υπογραφή διακομιστή","player": "Υπογραφή παίκτη"},"placementTop": "Εισαγωγή υπογραφής πάνω από τα συνημμένα μηνύματα","global": "Καθολική υπογραφή, που θα χρησιμοποιείται σε κάθε κόσμο:","server": "Υπογραφή διακομιστή, που θα χρησιμοποιείται μόνο σε αυτόν τον κόσμο:","player": "Υπογραφή παίκτη, που θα χρησιμοποιείται μόνο για αυτόν τον παίκτη:"}},"replacedUrl": {"notification": {"header": "Προσοχή!","text": "Πρόκειται να ανοίξετε τον σύνδεσμο %$1. Αυτό θα συνεχίσει με δική σας ευθύνη. Συνέχεια;"}}},"troopInformation": {"options": {"show": "Πληροφορίες πληροφοριών στρατού","linkBarrackShipyard": "Σύνδεσμοι του στρατώνα και του ναυπηγείου στις οθόνες επισκόπησης στρατού και απόλυσης μονάδων"},"link": {"gotoBarracks": "μετάβαση στο στρατώνα","gotoShipyard": "μετάβαση στο ναυπηγείο"},"units": {"label": "Μονάδες στην πόλη %$1","own": "Οι δικές μου μονάδες","friends": "Μονάδες συμμαχίας","enemies": "Μονάδες εχθρού"},"ships": {"label": "Πλοία στην πόλη %$1","own": "Τα δικά μου πλοία","friends": "Συμμαχικά πλοία","enemies": "Εχθρικά πλοία"},"button": "Πληροφορίες στρατού","header": "Στρατός στην πόλη %$1","noTroops": "Δεν υπάρχουν μονάδες στρατού στην πόλη %$1"},"diverse": {"options": {"wrapperTitle": "Διαφοροποίηση"},"name": {"resource": {"gold": "Χρυσός","wood": "Ξύλο","wine": "Κρασί","marble": "Μάρμαρο","glass": "Κρύσταλλο","sulfur": "Θείο"},"unit": {"swordsman": "Ξιφομάχος","phalanx": "Οπλίτης","archer": "Τοξότης","marksman": "Πυροβολιτής θείου","mortar": "Κανόνι","slinger": "Εκτοξευτής","catapult": "Καταπέλτης","ram": "Κριός","steamgiant": "Ατμογίγαντας","bombardier": "Βομβαρδιστικό Αερόστατο","cook": "Μάγειρας","medic": "Ιατρός","girocopter": "Γυροκόπτερο","spearman": "Λογχοφόρος","spartan": "Σπαρτιάτης"},"ship": {"ballista": "Βαλιστροφόρο","catapult": "Καταπελτοφόρο","flamethrower": "Φλογοβόλο","mortar": "Κανονιοφόρο","ram": "Σκάφος-Έμβολο","steamboat": "Έμβολο Ατμού","rocketship": "Πυραυλάκατος","submarine": "Βάρκα κατάδυσης","paddlespeedship": "Κωπήλατη Τορπιλάκατος","ballooncarrier": "Μεταφορικό Αερόστατων","tender": "Βοηθητικό σκάφος","transport": "Εμπορικό Πλοίο"}}}} },
  2762. { code: 'en', translations: {"view": {"options": {"wrapperTitle":"View","moveLoadingCircle":"Move loading circle to position bar","hideBirds":"Hide the bird swarm","noVerticalCenterInTownAdvisor":"Don't center town information in the town advisor"}},"island": {"options": {"showColonizingCityInfo":"Show information about colonizing cities"}},"finance": {"options": {"showIncomeOnTop":"Show income on top in balance view","shortUpkeepReductionTable":"Show a short version of the upkeep reduction"},"income": {"perHour":"Income per hour","perDay":"Income per day","start":"Income without reduction"},"upkeep": {"reason": {"0":"Troops","1":"Ships","2":"Troops & Ships"},"basic":"Basic Costs","supply":"Supply Costs","result":"Total Costs"}},"missingResources": {"options": {"wrapperTitle":"Missing Resources","show":"Show missing resources in construction view","showPositive":"Show also the remaining resources after an upgrade","showColoured":"Show the remaining resources coloured"}},"tooltips": {"options": {"autoshow":"Show tooltips in alliance mebers view and military advisor automatically","showDirectInMilitaryAdvisor":"Show information about cargo / fleets in military view without tooltips"}},"zoom": {"options": {"wrapperTitle":"Zoom function","zoomView":"Activate zoom in world view, island view, town view","factor": {"world":"Zoom worldmap:","island":"Zoom island view:","town":"Zoom town view:"},"scaleChildren": {"label":"Let banners and symbols in normal size when zooming when zooming in this view:","world":"Worldmap","island":"Island view","town":"Town view"},"accessKeyLabel":"This keys must be pressed to zoom with the mouse:"},"zoomIn":"Zoom in","factor":"Zoom factor","zoomOut":"Zoom out"},"resourceInformation": {"options": {"wrapperTitle":"Resource Information","resourceQuicklinkEnhancements":"Link resource number to town hall / mines","directIncome": {"show":"Show the hourly income directly in town view","style": {"label":"Style of the hourly income in town view:","alignRight":"Right align","alignLeft":"Left align","withSeparation":"Right align with separation"}},"capacityBar": {"show":"Show info bar for warehouse capacity","hasBorder":"Has border","showBranchOfficeResources":"Show resources in trading post","orientation": {"label":"Orientation of the bar","vertical":"Vertical","horizontal":"Horizontal","horizontalFull":"Horizontal, full length"}}},"dailyProduction":"Daily production %$1:","dailyExpenses":"Daily expenses %$1:"},"highscore": {"options": {"showMemberInformation":"Enable the possibility to save highscore data of alliance members"},"memberInformation": {"show":"Alliance info","reset":"Reset","lastReset":"Time since the last reset: %$1","noReset":"No reset so far."}},"message": {"options": {"wrapperTitle":"Messages","replaceURL":"Make links in messages clickable","inlineMessage":"Embed the first few characters of each message in the messages overview","signature": {"use": {"description":"Use this signature:","none":"No signature","global":"Global signature","server":"Server signature","player":"Player signature"},"placementTop":"Insert signature above cited messages","global":"Global signature, which would be used on every world:","server":"Server signature, which only would be used on this world:","player":"Player signature, which only would be used for this player:"}},"replacedUrl": {"notification": {"header":"Attention!","text":"You're going to open the link %$1. This happens on your own risk. Proceed?"}}},"troopInformation": {"options": {"show":"Show troop info","linkBarrackShipyard":"Link barracks and shipyard from troop overview and dismiss units screen"},"link": {"gotoBarracks":"goto barracks","gotoShipyard":"goto shipyard"},"units": {"label":"Units in %$1","own":"Own units","friends":"Allied units","enemies":"Enemy units"},"ships": {"label":"Ships in %$1","own":"Own ships","friends":"Allied ships","enemies":"Enemy ships"},"button":"Troop information","header":"Troops in %$1","noTroops":"There are no troops in %$1"},"diverse": {"options": {"wrapperTitle":"Diverse"},"name": {"resource": {"gold":"Gold","wood":"Building Material","wine":"Wine","marble":"Marble","glass":"Crystal Glass","sulfur":"Sulphur"},"unit": {"swordsman":"Swordsman","phalanx":"Hoplite","archer":"Archer","marksman":"Sulphur Carabineer","mortar":"Mortar","slinger":"Slinger","catapult":"Catapult","ram":"Battering Ram","steamgiant":"Steam Giant","bombardier":"Balloon-Bombardier","cook":"Cook","medic":"Doctor","girocopter":"Gyrocopter","spearman":"Spearman","spartan":"Spartan"},"ship": {"ballista":"Ballista Ship","catapult":"Catapult Ship","flamethrower":"Fire Ship","mortar":"Mortar Ship","ram":"Ram Ship","steamboat":"Steam Ram","rocketship":"Rocket Ship","submarine":"Diving Boat","paddlespeedship":"Paddle Speedboat","ballooncarrier":"Balloon Carrier","tender":"Tender","transport":"Merchant Ship"}}}} },
  2763. { code: 'fr', translations: {"view": {"options": {"wrapperTitle": "","moveLoadingCircle": "","hideBirds": "","noVerticalCenterInTownAdvisor": ""}},"island": {"options": {"showColonizingCityInfo": ""}},"finance": {"options": {"showIncomeOnTop": "","shortUpkeepReductionTable": ""},"income": {"perHour": "","perDay": "","start": ""},"upkeep": {"reason": {"0": "","1": "","2": ""},"basic": "","supply": "","result": ""}},"missingResources": {"options": {"wrapperTitle": "","show": "","showPositive": "","showColoured": ""}},"tooltips": {"options": {"autoshow": "","showDirectInMilitaryAdvisor": ""}},"zoom": {"options": {"wrapperTitle": "","zoomView": "","factor": {"world": "","island": "","town": ""},"scaleChildren": {"label": "","world": "","island": "","town": ""},"accessKeyLabel": ""},"zoomIn": "","factor": "","zoomOut": ""},"resourceInformation": {"options": {"wrapperTitle": "","resourceQuicklinkEnhancements": "","directIncome": {"show": "","style": {"label": "","alignRight": "","alignLeft": "","withSeparation": ""}},"capacityBar": {"show": "","hasBorder": "","showBranchOfficeResources": "","orientation": {"label": "","vertical": "","horizontal": "","horizontalFull": ""}}},"dailyProduction": "","dailyExpenses": ""},"highscore": {"options": {"showMemberInformation": ""},"memberInformation": {"show": "","reset": "","lastReset": "","noReset": ""}},"message": {"options": {"wrapperTitle": "","replaceURL": "","inlineMessage": "","signature": {"use": {"description": "","none": "","global": "","server": "","player": ""},"placementTop": "","global": "","server": "","player": ""}},"replacedUrl": {"notification": {"header": "","text": ""}}},"troopInformation": {"options": {"show": "","linkBarrackShipyard": ""},"link": {"gotoBarracks": "","gotoShipyard": ""},"units": {"label": "","own": "","friends": "","enemies": ""},"ships": {"label": "","own": "","friends": "","enemies": ""},"button": "","header": "","noTroops": ""},"diverse": {"options": {"wrapperTitle": ""},"name": {"resource": {"gold": "","wood": "","wine": "","marble": "","glass": "","sulfur": ""},"unit": {"swordsman": "","phalanx": "","archer": "","marksman": "","mortar": "","slinger": "","catapult": "","ram": "","steamgiant": "","bombardier": "","cook": "","medic": "","girocopter": "","spearman": "","spartan": ""},"ship": {"ballista": "","catapult": "","flamethrower": "","mortar": "","ram": "","steamboat": "","rocketship": "","submarine": "","paddlespeedship": "","ballooncarrier": "","tender": "","transport": ""}}}} },
  2764. { code: 'it', translations: {"view": {"options": {"wrapperTitle": "","moveLoadingCircle": "","hideBirds": "","noVerticalCenterInTownAdvisor": ""}},"island": {"options": {"showColonizingCityInfo": ""}},"finance": {"options": {"showIncomeOnTop": "","shortUpkeepReductionTable": ""},"income": {"perHour": "","perDay": "","start": ""},"upkeep": {"reason": {"0": "","1": "","2": ""},"basic": "","supply": "","result": ""}},"missingResources": {"options": {"wrapperTitle": "","show": "","showPositive": "","showColoured": ""}},"tooltips": {"options": {"autoshow": "","showDirectInMilitaryAdvisor": ""}},"zoom": {"options": {"wrapperTitle": "","zoomView": "","factor": {"world": "","island": "","town": ""},"scaleChildren": {"label": "","world": "","island": "","town": ""},"accessKeyLabel": ""},"zoomIn": "","factor": "","zoomOut": ""},"resourceInformation": {"options": {"wrapperTitle": "","resourceQuicklinkEnhancements": "","directIncome": {"show": "","style": {"label": "","alignRight": "","alignLeft": "","withSeparation": ""}},"capacityBar": {"show": "","hasBorder": "","showBranchOfficeResources": "","orientation": {"label": "","vertical": "","horizontal": "","horizontalFull": ""}}},"dailyProduction": "","dailyExpenses": ""},"highscore": {"options": {"showMemberInformation": ""},"memberInformation": {"show": "","reset": "","lastReset": "","noReset": ""}},"message": {"options": {"wrapperTitle": "","replaceURL": "","inlineMessage": "","signature": {"use": {"description": "","none": "","global": "","server": "","player": ""},"placementTop": "","global": "","server": "","player": ""}},"replacedUrl": {"notification": {"header": "","text": ""}}},"troopInformation": {"options": {"show": "","linkBarrackShipyard": ""},"link": {"gotoBarracks": "","gotoShipyard": ""},"units": {"label": "","own": "","friends": "","enemies": ""},"ships": {"label": "","own": "","friends": "","enemies": ""},"button": "","header": "","noTroops": ""},"diverse": {"options": {"wrapperTitle": ""},"name": {"resource": {"gold": "","wood": "","wine": "","marble": "","glass": "","sulfur": ""},"unit": {"swordsman": "","phalanx": "","archer": "","marksman": "","mortar": "","slinger": "","catapult": "","ram": "","steamgiant": "","bombardier": "","cook": "","medic": "","girocopter": "","spearman": "","spartan": ""},"ship": {"ballista": "","catapult": "","flamethrower": "","mortar": "","ram": "","steamboat": "","rocketship": "","submarine": "","paddlespeedship": "","ballooncarrier": "","tender": "","transport": ""}}}} },
  2765. { code: 'lv', translations: {"view": {"options": {"wrapperTitle": "Skats","moveLoadingCircle": "Pārvietot uz augšējo joslu apli, kas parādās pie procesu apstrādes","hideBirds": "Paslēpt putnu baru","noVerticalCenterInTownAdvisor": "Necentrēt pilsētas informāciju pilsētas padomdevējā"}},"island": {"options": {"showColonizingCityInfo": "Rādīt informāciju par topošajām kolonijām"}},"finance": {"options": {"showIncomeOnTop": "Rādīt ienākumus bilances pārskata augšdaļā","shortUpkeepReductionTable": "Rādīt apgādes samazinājumu īso versiju"},"income": {"perHour": "Ienākumi stundā","perDay": "Ienākumi dienā","start": "Ienākumi bez samazinājumiem"},"upkeep": {"reason": {"0": "Kareivji","1": "Kara kuģi","2": "Kareivji & Kara kuģi"},"basic": "Pamata izmaksas","supply": "Apgādes izmaksas","result": "Kopējās izmaksas"}},"missingResources": {"options": {"wrapperTitle": "Informācija par resursiem","show": "Rādīt trūkstošos resursus celtniecības skatā","showPositive": "Rādīt atlikušos resursus arī pēc uzlabojuma","showColoured": "Rādīt atlikušos resursus ar izkrāsojumu"}},"tooltips": {"options": {"autoshow": "Rādīt uznirstošos lodziņus alianses biedru skatā un karaspēka padomdevējā automātiski","showDirectInMilitaryAdvisor": "Rādīt informāciju par kravu floti karaspēka pārskatā bez uznirstošajiem logiem"}},"zoom": {"options": {"wrapperTitle": "Zoom funkcija","zoomView": "Aktivizēt zoom funkciju pasaules skatā, salas skatā, pilsētas skatā","factor": {"world": "Zoom pasaules skatā:","island": "Zoom salas skatā:","town": "Zoom pilsētas skatā:"},"scaleChildren": {"label": "Atstāt banerus un simbolus normālā izmērā, kad izmanto zoom funkciju šajā skatā:","world": "Pasaules skats","island": "Salas skats","town": "Pilsētas skats"},"accessKeyLabel": "Lai veiktu zoom funkciju ar peli, ir jāpietur taustiņš:"},"zoomIn": "Samazināt","factor": "Mērogs","zoomOut": "Palielināt"},"resourceInformation": {"options": {"wrapperTitle": "Trūkstošie resursi","resourceQuicklinkEnhancements": "Saite no resursu daudzuma uz rātsnamu / raktuvēm","directIncome": {"show": "Rādīt ikstundas resursu produkciju pilsētas skatā","style": {"label": "Ik stundas ienākumu noformējums pilsētas skatā:","alignRight": "Centrēt pa labi","alignLeft": "Centrēt pa kreisi","withSeparation": "Centrēt pa labi ar sadalījumu"}},"capacityBar": {"show": "Rādīt informāciju par noliktavas ietilpību","hasBorder": "Ir rāmītis","showBranchOfficeResources": "Rādīt resursus tirgū","orientation": {"label": "Joslas novietojums","vertical": "Vertikāli","horizontal": "Horizontāli","horizontalFull": "Horizontāli, pilns garums"}}},"dailyProduction": "Ikdienas %$1 produkcija:","dailyExpenses": ""},"highscore": {"options": {"showMemberInformation": "Ieslēgt iespēju saglabāt TOP listes datus par alianses biedriem"},"memberInformation": {"show": "Alianses info","reset": "Notīrīt","lastReset": "Laiks kopš pēdējās notīrīšanas: %$1","noReset": "Pagaidām nav veikta tīrīšana."}},"message": {"options": {"wrapperTitle": "Vēstules","replaceURL": "Pārveidot saites vēstulēs klikšķināmas","inlineMessage": "","signature": {"use": {"description": "","none": "","global": "","server": "","player": ""},"placementTop": "Ievietot parakstu vēstulēs virs citātiem","global": "Globāls paraksts, kuru var lietot katrā serverī:","server": "","player": ""}},"replacedUrl": {"notification": {"header": "Uzmanību!","text": "Jūs grasāties atvērt saiti %$1. Tas notiek uz Jūsu paša atbildību. Turpināt?"}}},"troopInformation": {"options": {"show": "Rādīt informāciju par vienībām","linkBarrackShipyard": ""},"link": {"gotoBarracks": "","gotoShipyard": ""},"units": {"label": "Kareivji %$1","own": "Paša kareivji","friends": "Sabiedroto kareivji","enemies": "Ienaidnieku kareivji"},"ships": {"label": "Kara kuģi %$1","own": "Paša kuģi","friends": "Sabiedroto kuģi","enemies": "Ienaidnieku kuģi"},"button": "Informācija par vienībām","header": "Vienības %$1","noTroops": "Pašlaik nav vienību %$1"},"diverse": {"options": {"wrapperTitle": "Dažādi"},"name": {"resource": {"gold": "Zelts","wood": "Kokmateriāli","wine": "Vīns","marble": "Marmors","glass": "Kristāls","sulfur": "Sērs"},"unit": {"swordsman": "Paukotājs","phalanx": "Šķēpnesis","archer": "Lokšāvējs","marksman": "Šāvējs","mortar": "Mīnemtējs","slinger": "Metējs","catapult": "Katapulta","ram": "Tarāns","steamgiant": "Tvaika milzis","bombardier": "Balons bombardieris","cook": "Pavārs","medic": "Ārsts","girocopter": "Helikopters","spearman": "Pīķnesis","spartan": "Spartietis"},"ship": {"ballista": "Ballistiskais kugis","catapult": "Katapultas kuģis","flamethrower": "Ugunsmetējs","mortar": "Mīnmetēja kuģis","ram": "Tarāna kuģis","steamboat": "Dzenrata kuģis","rocketship": "Raķešu kuģis","submarine": "Zemūdene","paddlespeedship": "Tvaikonis","ballooncarrier": "Balonu bāzes kuģis","tender": "Atbalsta kuģis","transport": "Tirdzniecības kuģis"}}}} },
  2766. { code: 'ru', translations: {"view": {"options": {"wrapperTitle": "Обзор","moveLoadingCircle": "Переместить индикатор загрузки на строку навигации","hideBirds": "Не показывать пролетающих птиц","noVerticalCenterInTownAdvisor": "Не центровать информацию о городе в окне городского советника"}},"island": {"options": {"showColonizingCityInfo": "Показать информацию о колонизации городов"}},"finance": {"options": {"showIncomeOnTop": "Показать доходы вверху окна просмотра баланса","shortUpkeepReductionTable": "Показать краткий вариант экономии содержания"},"income": {"perHour": "Доход в час","perDay": "Доход в день","start": "Доход без скидок"},"upkeep": {"reason": {"0": "Войска","1": "Флоты","2": "Войска & Флоты"},"basic": "Базовое снабжение войск","supply": "Снабжение войск в походе","result": "Всего"}},"missingResources": {"options": {"wrapperTitle": "Недостающие ресурсы","show": "Показать недостающие ресурсы в окне строительстве","showPositive": "Показывать ресурсы, которые останутся после запуска строительства","showColoured": "Выделять цветом остаток ресурсов"}},"tooltips": {"options": {"autoshow": "Автоматически показывать подсказки в обзоре членов альянса и окне военного советника","showDirectInMilitaryAdvisor": "Показать информацию о грузе / флотов в окне военного советника"}},"zoom": {"options": {"wrapperTitle": "Функция масштабирования","zoomView": "Активировать увеличение в обзоре мира, острова, города","factor": {"world": "Увеличить карту мира:","island": "Увеличить карту острова:","town": "Увеличить обзор города:"},"scaleChildren": {"label": "Не изменять размер букв и символов при масштабировании:","world": "Карты мира","island": "Обзор острова","town": "Обзора города"},"accessKeyLabel": "Это клавиши нужно нажимать, чтобы изменить масштаб с помощью мыши:"},"zoomIn": "Увеличить","factor": "Коэффициент увеличения","zoomOut": "Уменьшить"},"resourceInformation": {"options": {"wrapperTitle": "Информация о ресурсах","resourceQuicklinkEnhancements": "Интерактивные значки ресурсов и населения с посыланиями на шахты и ратушу","directIncome": {"show": "Показать почасовую прибыль непосредственно в обзоре города","style": {"label": "Представление доходов в обзоре города:","alignRight": "выравнивать по правому краю","alignLeft": "выравнивать по левому краю","withSeparation": "выравнивать по правому краю с с разделителем"}},"capacityBar": {"show": "Показать информационную строку для складских площадей","hasBorder": "Имеет границы","showBranchOfficeResources": "Показывать ресурсы в торговом посту","orientation": {"label": "Ориентация бара","vertical": "Вертикальный","horizontal": "Горизонтальный","horizontalFull": "Горизонтальный, полная длина"}}},"dailyProduction": "Ежедневное производство %$1:","dailyExpenses": "Ежедневные расходы %$1:"},"highscore": {"options": {"showMemberInformation": "Включить возможность сохранения информации о рекордах членов альянса"},"memberInformation": {"show": "Информация о альянсе","reset": "Сброс","lastReset": "Время с момента последнего сброса: %$1","noReset": "Повременить со сбросом."}},"message": {"options": {"wrapperTitle": "Сообщения","replaceURL": "Сделать ссылки в сообщениях интерактивными","inlineMessage": "Показывать первые несколько символов каждого сообщения в обзоре сообщений","signature": {"use": {"description": "Использовать следующую подпись:","none": "Без подписи","global": "Глобальная подпись","server": "Серверная подпись","player": "Подпись игрока"},"placementTop": "Ставить подпись више цитаты","global": "Глобальная подпись, которую можно использован в каждом мире:","server": "Серверная подпись, будет использована только в этом мире: ","player": "Подпись игрока, будет использована только для этого игрока:"}},"replacedUrl": {"notification": {"header": "Внимание!","text": "Вы собираетесь открыть ссылку %$1. Вы делаете это на свой ​​страх и риск. Продолжать?"}}},"troopInformation": {"options": {"show": "Показать информацию о войсках","linkBarrackShipyard": "Добавить ссылки на переход в казарму и верфь в окне обзора войск и окне исчезнувших войск"},"link": {"gotoBarracks": "перейти в казарму","gotoShipyard": "перейти в верфь"},"units": {"label": "Количество %$1","own": "Собственные подразделения","friends": "Подразделения союзников","enemies": "Вражеские подразделения"},"ships": {"label": "Флоты %$1","own": "Собственные флоты","friends": "Флоты союзников","enemies": "Вражеские флоты"},"button": "Информация о войсках","header": "Войска %$1","noTroops": "Нет войск в %$1"},"diverse": {"options": {"wrapperTitle": "Другое"},"name": {"resource": {"gold": "Золото","wood": "Строительные материалы","wine": "Виноград","marble": "Мрамор","glass": "Хрусталь","sulfur": "Сера"},"unit": {"swordsman": "Мечник","phalanx": "Гоплит","archer": "Лучник","marksman": "Стрелок","mortar": "Мортира","slinger": "Пращник","catapult": "Катапульта","ram": "Таран","steamgiant": "Паровой гигант","bombardier": "Бомбардировщик","cook": "Повар","medic": "Доктор","girocopter": "Гирокоптер","spearman": "Копейщик","spartan": "Спартанец"},"ship": {"ballista": "Корабль с баллистой","catapult": "Корабль с катапультой","flamethrower": "Огнеметный корабль","mortar": "Корабль с мортирой","ram": "Корабль с тараном","steamboat": "Паровой таран","rocketship": "Ракетоносец","submarine": "Подводная лодка","paddlespeedship": "Пароход","ballooncarrier": "Авианосец","tender": "Плавучая база","transport": "Торговое судно"}}}} },
  2767. { code: 'tr', translations: {"view": {"options": {"wrapperTitle": "Görüntüle","moveLoadingCircle": "Yüklenme dairesini pozisyon barına sürükle","hideBirds": "","noVerticalCenterInTownAdvisor": ""}},"island": {"options": {"showColonizingCityInfo": "Şehirleri kolonileştirme hakkında bilgi göster"}},"finance": {"options": {"showIncomeOnTop": "","shortUpkeepReductionTable": ""},"income": {"perHour": "Saat başına düşen gelir","perDay": "Gün başına düşen gelir","start": ""},"upkeep": {"reason": {"0": "Birlikler","1": "Gemiler","2": "Birlikler & Gemiler"},"basic": "","supply": "","result": "Toplam Maaliyet"}},"missingResources": {"options": {"wrapperTitle": "Eksik Kaynaklar","show": "","showPositive": "","showColoured": ""}},"tooltips": {"options": {"autoshow": "","showDirectInMilitaryAdvisor": ""}},"zoom": {"options": {"wrapperTitle": "","zoomView": "","factor": {"world": "Dünya haritasını yakınlaştır:","island": "Ada görünümüne yakınlaştır:","town": "Köy görünümüne yakınlaştır:"},"scaleChildren": {"label": "","world": "Dünya haritası","island": "Ada görünümü","town": ""},"accessKeyLabel": ""},"zoomIn": "Yakınlaştır","factor": "","zoomOut": "Uzaklaştır"},"resourceInformation": {"options": {"wrapperTitle": "Kaynak Bilgisi","resourceQuicklinkEnhancements": "","directIncome": {"show": "","style": {"label": "","alignRight": "","alignLeft": "","withSeparation": ""}},"capacityBar": {"show": "","hasBorder": "","showBranchOfficeResources": "","orientation": {"label": "","vertical": "","horizontal": "","horizontalFull": ""}}},"dailyProduction": "","dailyExpenses": ""},"highscore": {"options": {"showMemberInformation": ""},"memberInformation": {"show": "","reset": "","lastReset": "","noReset": ""}},"message": {"options": {"wrapperTitle": "Mesajlar","replaceURL": "","inlineMessage": "","signature": {"use": {"description": "","none": "İmza yok","global": "","server": "","player": ""},"placementTop": "","global": "","server": "","player": ""}},"replacedUrl": {"notification": {"header": "Dikkat!","text": ""}}},"troopInformation": {"options": {"show": "Birlik bilgisini göster","linkBarrackShipyard": ""},"link": {"gotoBarracks": "","gotoShipyard": ""},"units": {"label": "","own": "","friends": "","enemies": ""},"ships": {"label": "","own": "","friends": "","enemies": "Düşman gemileri"},"button": "Birlik bilgileri","header": "","noTroops": ""},"diverse": {"options": {"wrapperTitle": ""},"name": {"resource": {"gold": "Altın","wood": "İnşaa Malzemeleri","wine": "Şarap","marble": "","glass": "Kristal Bardak","sulfur": "Sülfür"},"unit": {"swordsman": "Kılıç ustası","phalanx": "","archer": "Okçu","marksman": "","mortar": "Havan","slinger": "","catapult": "Mancınık","ram": "","steamgiant": "","bombardier": "","cook": "Pişir","medic": "Doktor Who?","girocopter": "","spearman": "Mızrakçı","spartan": "Spartalı"},"ship": {"ballista": "","catapult": "Mancınık Gemisi","flamethrower": "Ateş Gemisi","mortar": "Havan Gemisi","ram": "","steamboat": "","rocketship": "","submarine": "Dalış Botu","paddlespeedship": "","ballooncarrier": "","tender": "İhale","transport": ""}}}} }
  2768. ];
  2769. for(var i = 0; i < la_language.length; i++) {
  2770. await IC.Language.addLanguageText(la_language[i].code, la_language[i].translations);
  2771. }
  2772. // Instantiate the ui script.
  2773. setTimeout(function() { new EnhancedUI(IC); }, 100);
  2774. }
  2775.  
  2776. // Call the main function of the script.
  2777. setTimeout(main, 0);