Ticket #3934: resource_agnostic-v7.diff
File resource_agnostic-v7.diff, 100.5 KB (added by , 8 years ago) |
---|
-
new file inaries/data/mods/public/globalscripts/Resources.js
diff --git a/binaries/data/mods/public/globalscripts/Resources.js b/binaries/data/mods/public/globalscripts/Resources.js new file mode 100644 index 0000000..04c3056
- + 1 2 /** 3 * Resources Global 4 * 5 * Engine.FindJSONFiles only exists within the session context 6 * Engine.BuildDirEntList only exists within the gui context 7 * The AI and test contexts have no access to any JSON file access functions 8 */ 9 function Resources() 10 { 11 let jsonFiles = []; 12 if (Engine.FindJSONFiles) 13 { 14 jsonFiles = Engine.FindJSONFiles("resources", false); 15 for (let file in jsonFiles) 16 jsonFiles[file] = "resources/" + jsonFiles[file] + ".json"; 17 } 18 else if (Engine.BuildDirEntList) 19 jsonFiles = Engine.BuildDirEntList("simulation/data/resources/", "*.json", false); 20 else 21 { 22 warn("Resources: No JSON access functions are unavailable"); 23 return; 24 } 25 26 this.resourceData = []; 27 this.resourceCodes = []; 28 29 for (let filename of jsonFiles) 30 { 31 let data = Engine.ReadJSONFile(filename); 32 if (!data) 33 continue; 34 35 data.subtypeNames = data.subtypes; 36 data.subtypes = Object.keys(data.subtypes); 37 38 this.resourceData.push(data); 39 if (data.enabled) 40 this.resourceCodes.push(data.code); 41 } 42 }; 43 44 Resources.prototype.GetData = function() 45 { 46 return this.resourceData.filter(resource => resource.enabled); 47 }; 48 49 Resources.prototype.GetResource = function(type) 50 { 51 let lType = type.toLowerCase(); 52 return this.GetData().find(resource => resource.code == lType); 53 }; 54 55 Resources.prototype.GetCodes = function() 56 { 57 return this.resourceCodes; 58 }; 59 60 /** 61 * Returns an object containing untranslated resource names mapped to 62 * resource codes. Includes subtypes. 63 */ 64 Resources.prototype.GetNames = function() 65 { 66 let names = {}; 67 for (let res of this.GetData()) 68 { 69 names[res.code] = res.name; 70 for (let subres of res.subtypes) 71 names[subres] = res.subtypeNames[subres] 72 } 73 return names; 74 }; 75 76 /** 77 * Builds a RelaxRNG schema based on currently valid elements. 78 * 79 * To prevent validation errors, disabled resources are included in the schema. 80 * 81 * @param datatype The datatype of the element 82 * @param additional Array of additional data elements. Time, xp, treasure, etc. 83 * @param subtypes If true, resource subtypes will be included as well. 84 * @return RelaxNG schema string 85 */ 86 Resources.prototype.BuildSchema = function(datatype, additional = [], subtypes = false) 87 { 88 if (!datatype) 89 return ""; 90 91 switch (datatype) 92 { 93 case "decimal": 94 case "nonNegativeDecimal": 95 case "positiveDecimal": 96 datatype = "<ref name='" + datatype + "'/>"; 97 break; 98 99 default: 100 datatype = "<data type='" + datatype + "'/>"; 101 } 102 103 let resCodes = this.resourceData.map(resource => resource.code); 104 let schema = "<interleave>"; 105 for (let res of resCodes.concat(additional)) 106 schema += 107 "<optional>" + 108 "<element name='" + res + "'>" + 109 datatype + 110 "</element>" + 111 "</optional>"; 112 113 if (!subtypes) 114 return schema + "</interleave>"; 115 116 for (let res of this.resourceData) 117 for (let subtype of res.subtypes) 118 schema += 119 "<optional>" + 120 "<element name='" + res.code + "." + subtype + "'>" + 121 datatype + 122 "</element>" + 123 "</optional>"; 124 125 if (additional.indexOf("treasure") !== -1) 126 for (let res of resCodes) 127 schema += 128 "<optional>" + 129 "<element name='" + "treasure." + res + "'>" + 130 datatype + 131 "</element>" + 132 "</optional>"; 133 134 return schema + "</interleave>"; 135 } 136 137 /** 138 * Builds the value choices for a RelaxNG `<choice></choice>` object, based on currently valid resources. 139 * 140 * @oaram subtypes If set to true, the choices returned will be resource subtypes, rather than main types 141 * @param treasure If set to true, the pseudo resource 'treasure' (or its subtypes) will be included 142 * @return String of RelaxNG Schema `<choice/>` values. 143 */ 144 Resources.prototype.BuildChoicesSchema = function(subtypes = false, treasure = false) 145 { 146 let schema = "<choice>"; 147 148 if (!subtypes) 149 { 150 let resCodes = this.resourceData.map(resource => resource.code); 151 for (let res of resCodes.concat(treasure ? [ "treasure" ] : [])) 152 schema += "<value>" + res + "</value>"; 153 } 154 else 155 for (let res of this.resourceData) 156 { 157 for (let subtype of res.subtypes) 158 schema += "<value>" + res.code + "." + subtype + "</value>"; 159 if (treasure) 160 schema += "<value>" + "treasure." + res.code + "</value>"; 161 } 162 163 return schema + "</choice>"; 164 } -
binaries/data/mods/public/gui/common/functions_utility.js
diff --git a/binaries/data/mods/public/gui/common/functions_utility.js b/binaries/data/mods/public/gui/common/functions_utility.js index 9984cb0..9e89efd 100644
a b function formatPlayerInfo(playerDataArray, playerStates) 416 416 417 417 return teamDescription.join("\n\n"); 418 418 } 419 420 /** 421 * Horizontally fit objects within a parent. 422 * 423 * @param margin - The gap, in px, between the repeated objects 424 * @param limit - The number of elements to fit 425 */ 426 function horizontallyDistributeObjects(parentName, margin = 0, limit = undefined) 427 { 428 let objects = Engine.GetGUIObjectByName(parentName).children; 429 if (limit !== undefined) 430 objects = objects.splice(0, limit); 431 432 for (let i in objects) 433 { 434 i = +i; 435 let size = objects[i].size; 436 size.rleft = 100 / objects.length * i; 437 size.rright = 100 / objects.length * (i + 1); 438 size.right = -margin; 439 objects[i].size = size; 440 } 441 } 442 443 /** 444 * Hide all children after a certain index 445 * 446 * @param prefix - The part of the element name preceeding the index 447 * @param idx - The index from which to start 448 * @param prefix - The part of the element name after the index 449 */ 450 function hideRemaining(prefix, idx, suffix) 451 { 452 while (true) 453 { 454 let obj = Engine.GetGUIObjectByName(prefix + idx + suffix); 455 if (!obj) 456 return; 457 obj.hidden = true; 458 ++idx; 459 } 460 } -
binaries/data/mods/public/gui/common/l10n.js
diff --git a/binaries/data/mods/public/gui/common/l10n.js b/binaries/data/mods/public/gui/common/l10n.js index 53c16c2..3fd4570 100644
a b 1 const localisedResourceNames = {2 "firstWord": {3 // Translation: Word as used at the beginning of a sentence or as a single-word sentence.4 "food": translateWithContext("firstWord", "Food"),5 // Translation: Word as used at the beginning of a sentence or as a single-word sentence.6 "meat": translateWithContext("firstWord", "Meat"),7 // Translation: Word as used at the beginning of a sentence or as a single-word sentence.8 "metal": translateWithContext("firstWord", "Metal"),9 // Translation: Word as used at the beginning of a sentence or as a single-word sentence.10 "ore": translateWithContext("firstWord", "Ore"),11 // Translation: Word as used at the beginning of a sentence or as a single-word sentence.12 "rock": translateWithContext("firstWord", "Rock"),13 // Translation: Word as used at the beginning of a sentence or as a single-word sentence.14 "ruins": translateWithContext("firstWord", "Ruins"),15 // Translation: Word as used at the beginning of a sentence or as a single-word sentence.16 "stone": translateWithContext("firstWord", "Stone"),17 // Translation: Word as used at the beginning of a sentence or as a single-word sentence.18 "treasure": translateWithContext("firstWord", "Treasure"),19 // Translation: Word as used at the beginning of a sentence or as a single-word sentence.20 "tree": translateWithContext("firstWord", "Tree"),21 // Translation: Word as used at the beginning of a sentence or as a single-word sentence.22 "wood": translateWithContext("firstWord", "Wood"),23 // Translation: Word as used at the beginning of a sentence or as a single-word sentence.24 "fruit": translateWithContext("firstWord", "Fruit"),25 // Translation: Word as used at the beginning of a sentence or as a single-word sentence.26 "grain": translateWithContext("firstWord", "Grain"),27 // Translation: Word as used at the beginning of a sentence or as a single-word sentence.28 "fish": translateWithContext("firstWord", "Fish"),29 },30 "withinSentence": {31 // Translation: Word as used in the middle of a sentence (which may require using lowercase for your language).32 "food": translateWithContext("withinSentence", "Food"),33 // Translation: Word as used in the middle of a sentence (which may require using lowercase for your language).34 "meat": translateWithContext("withinSentence", "Meat"),35 // Translation: Word as used in the middle of a sentence (which may require using lowercase for your language).36 "metal": translateWithContext("withinSentence", "Metal"),37 // Translation: Word as used in the middle of a sentence (which may require using lowercase for your language).38 "ore": translateWithContext("withinSentence", "Ore"),39 // Translation: Word as used in the middle of a sentence (which may require using lowercase for your language).40 "rock": translateWithContext("withinSentence", "Rock"),41 // Translation: Word as used in the middle of a sentence (which may require using lowercase for your language).42 "ruins": translateWithContext("withinSentence", "Ruins"),43 // Translation: Word as used in the middle of a sentence (which may require using lowercase for your language).44 "stone": translateWithContext("withinSentence", "Stone"),45 // Translation: Word as used in the middle of a sentence (which may require using lowercase for your language).46 "treasure": translateWithContext("withinSentence", "Treasure"),47 // Translation: Word as used in the middle of a sentence (which may require using lowercase for your language).48 "tree": translateWithContext("withinSentence", "Tree"),49 // Translation: Word as used in the middle of a sentence (which may require using lowercase for your language).50 "wood": translateWithContext("withinSentence", "Wood"),51 // Translation: Word as used in the middle of a sentence (which may require using lowercase for your language).52 "fruit": translateWithContext("withinSentence", "Fruit"),53 // Translation: Word as used in the middle of a sentence (which may require using lowercase for your language).54 "grain": translateWithContext("withinSentence", "Grain"),55 // Translation: Word as used in the middle of a sentence (which may require using lowercase for your language).56 "fish": translateWithContext("withinSentence", "Fish"),57 }58 };59 1 60 function getLocalizedResourceName(resource Code, context)2 function getLocalizedResourceName(resourceName, context) 61 3 { 62 if (!localisedResourceNames[context]) 63 { 64 warn("Internationalization: Unexpected context for resource type localization found: ‘" + context + "’. This context is not supported."); 65 return resourceCode; 66 } 67 if (!localisedResourceNames[context][resourceCode]) 68 { 69 warn("Internationalization: Unexpected resource type found with code ‘" + resourceCode + ". This resource type must be internationalized."); 70 return resourceCode; 71 } 72 return localisedResourceNames[context][resourceCode]; 4 return translateWithContext(context, resourceName); 73 5 } 74 6 75 7 /** … … function getLocalizedResourceAmounts(resources) 81 13 .filter(type => resources[type] > 0) 82 14 .map(type => sprintf(translate("%(amount)s %(resourceType)s"), { 83 15 "amount": resources[type], 84 "resourceType": getLocalizedResourceName(type, "withinSentence")16 "resourceType": translateWithContext("withinSentence", type) 85 17 })); 86 18 87 19 if (amounts.length > 1) -
binaries/data/mods/public/gui/common/tooltips.js
diff --git a/binaries/data/mods/public/gui/common/tooltips.js b/binaries/data/mods/public/gui/common/tooltips.js index ada0ca7..0fe4e0b 100644
a b function getEntityCostComponentsTooltipString(template, trainNum, entity) 342 342 343 343 return costs; 344 344 } 345 345 346 function getGatherTooltip(template) 346 347 { 347 348 if (!template.gather) -
binaries/data/mods/public/gui/session/diplomacy_window.xml
diff --git a/binaries/data/mods/public/gui/session/diplomacy_window.xml b/binaries/data/mods/public/gui/session/diplomacy_window.xml index 1708159..9a531f6 100644
a b 11 11 </object> 12 12 13 13 <object name="diplomacyHeader" size="32 32 100%-32 64"> 14 <object name="diplomacyHeaderName" size="0 0 1 50 100%" type="text" style="chatPanel" ghost="true">14 <object name="diplomacyHeaderName" size="0 0 140 100%" type="text" style="chatPanel" ghost="true" text_align="center"> 15 15 <translatableAttribute id="caption">Name</translatableAttribute> 16 16 </object> 17 17 <object name="diplomacyHeaderCiv" size="150 0 250 100%" type="text" style="chatPanel" ghost="true"> … … 23 23 <object name="diplomacyHeaderTheirs" size="300 0 360 100%" type="text" style="chatPanel" ghost="true"> 24 24 <translatableAttribute id="caption">Theirs</translatableAttribute> 25 25 </object> 26 <object name="diplomacyHeaderAlly" size=" 100%-180 0 100%-160 100%" type="text" style="chatPanel" tooltip_style="sessionToolTipBold">26 <object name="diplomacyHeaderAlly" size="360 0 380 100%" type="text" style="chatPanel" tooltip_style="sessionToolTipBold"> 27 27 <translatableAttribute id="caption">A</translatableAttribute> 28 28 <translatableAttribute id="tooltip">Ally</translatableAttribute> 29 29 </object> 30 <object name="diplomacyHeaderNeutral" size=" 100%-160 0 100%-140 100%" type="text" style="chatPanel" tooltip_style="sessionToolTipBold">30 <object name="diplomacyHeaderNeutral" size="380 0 400 100%" type="text" style="chatPanel" tooltip_style="sessionToolTipBold"> 31 31 <translatableAttribute id="caption">N</translatableAttribute> 32 32 <translatableAttribute id="tooltip">Neutral</translatableAttribute> 33 33 </object> 34 <object name="diplomacyHeaderEnemy" size=" 100%-140 0 100%-120 100%" type="text" style="chatPanel" tooltip_style="sessionToolTipBold">34 <object name="diplomacyHeaderEnemy" size="400 0 420 100%" type="text" style="chatPanel" tooltip_style="sessionToolTipBold"> 35 35 <translatableAttribute id="caption">E</translatableAttribute> 36 36 <translatableAttribute id="tooltip">Enemy</translatableAttribute> 37 37 </object> 38 <object name="diplomacyHeaderTribute" size=" 100%-110 0 100% 100%" type="text" style="chatPanel">38 <object name="diplomacyHeaderTribute" size="430 0 100%-30 100%" type="text" style="chatPanel" text_align="center"> 39 39 <translatableAttribute id="caption">Tribute</translatableAttribute> 40 40 </object> 41 41 </object> … … 48 48 <object name="diplomacyPlayerTheirs[n]" size="300 0 360 100%" type="text" style="chatPanel" ghost="true"/> 49 49 50 50 <!-- Diplomatic stance - selection --> 51 <object name="diplomacyPlayerAlly[n]" size=" 100%-180 0 100%-160 100%" type="button" style="StoneButton" hidden="true"/>52 <object name="diplomacyPlayerNeutral[n]" size=" 100%-160 0 100%-140 100%" type="button" style="StoneButton" hidden="true"/>53 <object name="diplomacyPlayerEnemy[n]" size=" 100%-140 0 100%-120 100%" type="button" style="StoneButton" hidden="true"/>51 <object name="diplomacyPlayerAlly[n]" size="360 0 380 100%" type="button" style="StoneButton" hidden="true"/> 52 <object name="diplomacyPlayerNeutral[n]" size="380 0 400 100%" type="button" style="StoneButton" hidden="true"/> 53 <object name="diplomacyPlayerEnemy[n]" size="400 0 420 100%" type="button" style="StoneButton" hidden="true"/> 54 54 55 55 <!-- Tribute --> 56 <object name="diplomacyPlayerTributeFood[n]" size="100%-110 0 100%-90 100%" type="button" style="iconButton" tooltip_style="sessionToolTipBold" hidden="true"> 57 <object name="diplomacyPlayerTributeFoodImage[n]" type="image" size="0 0 100% 100%" sprite="stretched:session/icons/resources/food.png" ghost="true"/> 58 </object> 59 <object name="diplomacyPlayerTributeWood[n]" size="100%-90 0 100%-70 100%" type="button" style="iconButton" tooltip_style="sessionToolTipBold" hidden="true"> 60 <object name="diplomacyPlayerTributeWoodImage[n]" type="image" size="0 0 100% 100%" sprite="stretched:session/icons/resources/wood.png" ghost="true"/> 61 </object> 62 <object name="diplomacyPlayerTributeStone[n]" size="100%-70 0 100%-50 100%" type="button" style="iconButton" tooltip_style="sessionToolTipBold" hidden="true"> 63 <object name="diplomacyPlayerTributeStoneImage[n]" type="image" size="0 0 100% 100%" sprite="stretched:session/icons/resources/stone.png" ghost="true"/> 64 </object> 65 <object name="diplomacyPlayerTributeMetal[n]" size="100%-50 0 100%-30 100%" type="button" style="iconButton" tooltip_style="sessionToolTipBold" hidden="true"> 66 <object name="diplomacyPlayerTributeMetalImage[n]" type="image" size="0 0 100% 100%" sprite="stretched:session/icons/resources/metal.png" ghost="true"/> 56 <object size="430 0 100%-40 100%"> 57 <repeat count="8" var="r"> 58 <object name="diplomacyPlayer[n]_tribute[r]" size="0 0 20 100%" type="button" style="iconButton" tooltip_style="sessionToolTipBold" hidden="true"> 59 <object name="diplomacyPlayer[n]_tribute[r]_image" type="image" size="0 0 100% 100%" ghost="true"/> 60 </object> 61 </repeat> 67 62 </object> 68 63 69 64 <object name="diplomacyAttackRequest[n]" size="100%-20 0 100% 100%" type="button" style="iconButton" tooltip_style="sessionToolTipBold" hidden="true"> -
binaries/data/mods/public/gui/session/menu.js
diff --git a/binaries/data/mods/public/gui/session/menu.js b/binaries/data/mods/public/gui/session/menu.js index 494bd14..99bfd5e 100644
a b const INITIAL_MENU_POSITION = "100%-164 " + MENU_TOP + " 100% " + MENU_BOTTOM; 22 22 // Number of pixels per millisecond to move 23 23 const MENU_SPEED = 1.2; 24 24 25 // Available resources in trade and tribute menu26 const RESOURCES = ["food", "wood", "stone", "metal"];27 28 25 // Trade menu: step for probability changes 29 26 const STEP = 5; 30 27 … … function openDiplomacy() 237 234 g_IsDiplomacyOpen = true; 238 235 239 236 let isCeasefireActive = GetSimState().ceasefireActive; 237 let resCodes = g_ResourceData.GetCodes(); 240 238 241 239 // Get offset for one line 242 240 let onesize = Engine.GetGUIObjectByName("diplomacyPlayer[0]").size; … … function openDiplomacy() 255 253 diplomacyFormatAttackRequestButton(i, myself || playerInactive || isCeasefireActive || !hasAllies || !g_Players[i].isEnemy[g_ViewedPlayer]); 256 254 } 257 255 258 Engine.GetGUIObjectByName("diplomacyDialogPanel").hidden = false; 256 let dialog = Engine.GetGUIObjectByName("diplomacyDialogPanel"); 257 let size = dialog.size; 258 let width = 260 + resCodes.length * 10; 259 size.left = -width; 260 size.right = width; 261 dialog.size = size; 262 dialog.hidden = false; 259 263 } 260 264 261 265 function diplomacySetupTexts(i, rowsize) … … function diplomacyFormatStanceButtons(i, hidden) 305 309 306 310 function diplomacyFormatTributeButtons(i, hidden) 307 311 { 308 for (let resource of RESOURCES) 312 let resNames = g_ResourceData.GetNames(); 313 let resCodes = g_ResourceData.GetCodes(); 314 let r = 0; 315 for (let resCode of resCodes) 309 316 { 310 let button = Engine.GetGUIObjectByName("diplomacyPlayerTribute"+resource[0].toUpperCase()+resource.substring(1)+"["+(i-1)+"]"); 317 let button = Engine.GetGUIObjectByName("diplomacyPlayer["+(i-1)+"]_tribute["+r+"]"); 318 Engine.GetGUIObjectByName("diplomacyPlayer["+(i-1)+"]_tribute["+r+"]_image").sprite = "stretched:session/icons/resources/"+resCode+".png"; 311 319 button.hidden = hidden; 320 setPanelObjectPosition(button, r, 8, 0); 321 ++r; 312 322 if (hidden) 313 323 continue; 314 324 315 325 button.enabled = controlsPlayer(g_ViewedPlayer); 316 button.tooltip = formatTributeTooltip(i, res ource, 100);317 button.onpress = (function(i, res ource, button) {326 button.tooltip = formatTributeTooltip(i, resNames[resCode], 100); 327 button.onpress = (function(i, resCode, button) { 318 328 // Shift+click to send 500, shift+click+click to send 1000, etc. 319 329 // See INPUT_MASSTRIBUTING in input.js 320 330 let multiplier = 1; … … function diplomacyFormatTributeButtons(i, hidden) 327 337 } 328 338 329 339 let amounts = {}; 330 for (let type of RESOURCES)331 amounts[ type] = 0;332 amounts[res ource] = 100 * multiplier;340 for (let res of resCodes) 341 amounts[res] = 0; 342 amounts[resCode] = 100 * multiplier, 333 343 334 button.tooltip = formatTributeTooltip(i, res ource, amounts[resource]);344 button.tooltip = formatTributeTooltip(i, resNames[resCode], amounts[resCode]); 335 345 336 346 // This is in a closure so that we have access to `player`, `amounts`, and `multiplier` without some 337 347 // evil global variable hackery. 338 348 g_FlushTributing = function() { 339 349 Engine.PostNetworkCommand({ "type": "tribute", "player": i, "amounts": amounts }); 340 350 multiplier = 1; 341 button.tooltip = formatTributeTooltip(i, res ource, 100);351 button.tooltip = formatTributeTooltip(i, resNames[resCode], 100); 342 352 }; 343 353 344 354 if (!isBatchTrainPressed) 345 355 g_FlushTributing(); 346 356 }; 347 })(i, res ource, button);357 })(i, resCode, button); 348 358 } 349 359 } 350 360 … … function openTrade() 398 408 } 399 409 }; 400 410 401 var proba = Engine.GuiInterfaceCall("GetTradingGoods", g_ViewedPlayer); 402 var button = {}; 403 var selec = RESOURCES[0]; 404 for (var i = 0; i < RESOURCES.length; ++i) 411 let proba = Engine.GuiInterfaceCall("GetTradingGoods", g_ViewedPlayer); 412 let button = {}; 413 let resCodes = g_ResourceData.GetCodes(); 414 let selec = resCodes[0]; 415 hideRemaining("tradeResource[", resCodes.length, "]"); 416 417 for (let i = 0; i < resCodes.length; ++i) 405 418 { 406 var buttonResource = Engine.GetGUIObjectByName("tradeResource["+i+"]"); 407 if (i > 0) 408 { 409 var size = Engine.GetGUIObjectByName("tradeResource["+(i-1)+"]").size; 410 var width = size.right - size.left; 411 size.left += width; 412 size.right += width; 413 Engine.GetGUIObjectByName("tradeResource["+i+"]").size = size; 414 } 415 var resource = RESOURCES[i]; 416 proba[resource] = (proba[resource] ? proba[resource] : 0); 417 var buttonResource = Engine.GetGUIObjectByName("tradeResourceButton["+i+"]"); 418 var icon = Engine.GetGUIObjectByName("tradeResourceIcon["+i+"]"); 419 icon.sprite = "stretched:session/icons/resources/" + resource + ".png"; 420 var label = Engine.GetGUIObjectByName("tradeResourceText["+i+"]"); 421 var buttonUp = Engine.GetGUIObjectByName("tradeArrowUp["+i+"]"); 422 var buttonDn = Engine.GetGUIObjectByName("tradeArrowDn["+i+"]"); 423 var iconSel = Engine.GetGUIObjectByName("tradeResourceSelection["+i+"]"); 424 button[resource] = { "up": buttonUp, "dn": buttonDn, "label": label, "sel": iconSel }; 419 let buttonResource = Engine.GetGUIObjectByName("tradeResource["+i+"]"); 420 setPanelObjectPosition(buttonResource, i, 8); 421 let resCode = resCodes[i]; 422 proba[resCode] = (proba[resCode] ? proba[resCode] : 0); 423 buttonResource = Engine.GetGUIObjectByName("tradeResourceButton["+i+"]"); 424 let icon = Engine.GetGUIObjectByName("tradeResourceIcon["+i+"]"); 425 icon.sprite = "stretched:session/icons/resources/" + resCode + ".png"; 426 let label = Engine.GetGUIObjectByName("tradeResourceText["+i+"]"); 427 let buttonUp = Engine.GetGUIObjectByName("tradeArrowUp["+i+"]"); 428 let buttonDn = Engine.GetGUIObjectByName("tradeArrowDn["+i+"]"); 429 let iconSel = Engine.GetGUIObjectByName("tradeResourceSelection["+i+"]"); 430 button[resCode] = { "up": buttonUp, "dn": buttonDn, "label": label, "sel": iconSel }; 425 431 426 432 buttonResource.enabled = controlsPlayer(g_ViewedPlayer); 427 433 buttonResource.onpress = (function(resource){ 428 434 return function() { 429 435 if (Engine.HotkeyIsPressed("session.fulltradeswap")) 430 436 { 431 for ( var ress of RESOURCES)437 for (let ress of resCodes) 432 438 proba[ress] = 0; 433 439 proba[resource] = 100; 434 440 Engine.PostNetworkCommand({"type": "set-trading-goods", "tradingGoods": proba}); … … function openTrade() 436 442 selec = resource; 437 443 updateButtons(); 438 444 }; 439 })(res ource);445 })(resCode); 440 446 441 447 buttonUp.enabled = controlsPlayer(g_ViewedPlayer); 442 448 buttonUp.onpress = (function(resource){ … … function openTrade() 446 452 Engine.PostNetworkCommand({"type": "set-trading-goods", "tradingGoods": proba}); 447 453 updateButtons(); 448 454 }; 449 })(res ource);455 })(resCode); 450 456 451 457 buttonDn.enabled = controlsPlayer(g_ViewedPlayer); 452 458 buttonDn.onpress = (function(resource){ … … function openTrade() 456 462 Engine.PostNetworkCommand({"type": "set-trading-goods", "tradingGoods": proba}); 457 463 updateButtons(); 458 464 }; 459 })(res ource);465 })(resCode); 460 466 } 461 467 updateButtons(); 462 468 … … function openTrade() 464 470 Engine.GetGUIObjectByName("landTraders").caption = getIdleLandTradersText(traderNumber); 465 471 Engine.GetGUIObjectByName("shipTraders").caption = getIdleShipTradersText(traderNumber); 466 472 467 Engine.GetGUIObjectByName("tradeDialogPanel").hidden = false; 473 let dialog = Engine.GetGUIObjectByName("tradeDialogPanel"); 474 let size = dialog.size; 475 let wid = resCodes.length * (58/2); 476 size.left = -(134 + wid); 477 size.right = (134 + wid); 478 dialog.size = size; 479 dialog.hidden = false; 468 480 } 469 481 470 482 function getIdleLandTradersText(traderNumber) -
binaries/data/mods/public/gui/session/selection_details.js
diff --git a/binaries/data/mods/public/gui/session/selection_details.js b/binaries/data/mods/public/gui/session/selection_details.js index 29acc09..36fa2a6 100644
a b function layoutSelectionMultiple() 13 13 function getResourceTypeDisplayName(resourceType) 14 14 { 15 15 let resourceCode = resourceType.generic; 16 if (resourceCode == "treasure") 17 return getLocalizedResourceName(resourceType.specific, "firstWord"); 18 else 19 return getLocalizedResourceName(resourceCode, "firstWord"); 16 let resourceName = g_ResourceData.GetNames()[(resourceCode == "treasure" ? resourceType.specific : resourceCode)] 17 return getLocalizedResourceName(resourceName, "firstWord"); 20 18 } 21 19 22 20 // Updates the health bar of garrisoned units -
binaries/data/mods/public/gui/session/selection_panels.js
diff --git a/binaries/data/mods/public/gui/session/selection_panels.js b/binaries/data/mods/public/gui/session/selection_panels.js index c21fc4f..ceae7a9 100644
a b let g_FormationsInfo = new Map(); 34 34 35 35 let g_SelectionPanels = {}; 36 36 37 let g_BarterSell; 38 37 39 g_SelectionPanels.Alert = { 38 40 "getMaxNumberOfItems": function() 39 41 { … … g_SelectionPanels.Alert = { 87 89 g_SelectionPanels.Barter = { 88 90 "getMaxNumberOfItems": function() 89 91 { 90 return 4;92 return 8; 91 93 }, 92 94 "rowLength": 4, 93 95 "getItems": function(unitEntState, selection) 94 96 { 95 97 if (!unitEntState.barterMarket) 96 98 return []; 97 // ["food", "wood", "stone", "metal"] 98 return BARTER_RESOURCES; 99 return g_ResourceData.GetCodes(); 99 100 }, 100 101 "setupButton": function(data) 101 102 { … … g_SelectionPanels.Barter = { 115 116 if (Engine.HotkeyIsPressed("session.massbarter")) 116 117 amountToSell *= BARTER_BUNCH_MULTIPLIER; 117 118 119 if (!g_BarterSell) 120 g_BarterSell = g_ResourceData.GetCodes()[0]; 121 118 122 amount.Sell.caption = "-" + amountToSell; 119 123 let prices = data.unitEntState.barterMarket.prices; 120 124 amount.Buy.caption = "+" + Math.round(prices.sell[g_BarterSell] / prices.buy[data.item] * amountToSell); 121 125 122 let resource = getLocalizedResourceName( data.item, "withinSentence");126 let resource = getLocalizedResourceName(g_ResourceData.GetNames()[data.item], "firstWord"); 123 127 button.Buy.tooltip = sprintf(translate("Buy %(resource)s"), { "resource": resource }); 124 128 button.Sell.tooltip = sprintf(translate("Sell %(resource)s"), { "resource": resource }); 125 129 … … g_SelectionPanels.Barter = { 164 168 button.Sell.hidden = false; 165 169 selectionIcon.hidden = !isSelected; 166 170 167 setPanelObjectPosition(button.Sell, data.i, data.rowLength); 168 setPanelObjectPosition(button.Buy, data.i + data.rowLength, data.rowLength); 171 let sellPos = data.i + (data.i >= data.rowLength ? data.rowLength : 0); 172 let buyPos = data.i + data.rowLength * (data.i >= data.rowLength ? 2 : 1); 173 setPanelObjectPosition(button.Sell, sellPos, data.rowLength); 174 setPanelObjectPosition(button.Buy, buyPos, data.rowLength); 169 175 return true; 170 176 } 171 177 }; -
binaries/data/mods/public/gui/session/selection_panels_helpers.js
diff --git a/binaries/data/mods/public/gui/session/selection_panels_helpers.js b/binaries/data/mods/public/gui/session/selection_panels_helpers.js index fc0e7a6..46976f9 100644
a b 1 1 const BARTER_RESOURCE_AMOUNT_TO_SELL = 100; 2 2 const BARTER_BUNCH_MULTIPLIER = 5; 3 const BARTER_RESOURCES = ["food", "wood", "stone", "metal"];4 3 const BARTER_ACTIONS = ["Sell", "Buy"]; 5 4 const GATE_ACTIONS = ["lock", "unlock"]; 6 5 7 // upgrade constants8 6 const UPGRADING_NOT_STARTED = -2; 9 7 const UPGRADING_CHOSEN_OTHER = -1; 10 8 11 // ==============================================12 // BARTER HELPERS13 // Resources to sell on barter panel14 var g_BarterSell = "food";15 16 9 function canMoveSelectionIntoFormation(formationTemplate) 17 10 { 18 11 if (!(formationTemplate in g_canMoveIntoFormation)) -
binaries/data/mods/public/gui/session/selection_panels_left/barter_panel.xml
diff --git a/binaries/data/mods/public/gui/session/selection_panels_left/barter_panel.xml b/binaries/data/mods/public/gui/session/selection_panels_left/barter_panel.xml index f32e117..717efce 100644
a b 1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <object name="unitBarterPanel" 3 size=" 6 36100% 100%"3 size="24 12 100% 100%" 4 4 hidden="true" 5 5 > 6 <object ghost="true" style="resourceText" type="text" size="0 0 100% 20"> 7 <translatableAttribute id="tooltip">Exchange resources:</translatableAttribute>8 </object> 9 <object size="0 32 100% 124">10 < repeat count="4">11 < !-- sell -->12 <object name="unitBarterSell Button[n]" style="iconButton" type="button" size="0 0 46 46" tooltip_style="sessionToolTipBottomBold">13 <object name="unitBarterSellIcon[n]" type="image" ghost="true" size="3 3 43 43"/>14 <object name="unitBarterSellAmount[n]" ghost="true" style="resourceText" type="text" size="0 0 100% 50%"/>15 <object name="unitBarterSellSelection[n]" hidden="true" type="image" ghost="true" size="3 3 43 43" sprite="stretched:session/icons/corners.png"/> 16 </object>17 <!-- buy -->18 <object name="unitBarterBuy Button[n]" style="iconButton" type="button" size="0 0 46 46" tooltip_style="sessionToolTipBottomBold">19 <object name="unitBarterBuyIcon[n]" type="image" ghost="true" size="3 3 43 43"/>20 <object name="unitBarterBuyAmount[n]" ghost="true" style="resourceText" type="text" size="0 0 100% 50%"/>21 </object> 22 23 </object> 6 7 <repeat count="8"> 8 9 <!-- Sell --> 10 <object name="unitBarterSellButton[n]" style="iconButton" type="button" size="0 0 36 36" tooltip_style="sessionToolTipBottomBold" hidden="true"> 11 <object name="unitBarterSellIcon[n]" type="image" ghost="true" size="3 3 33 33"/> 12 <object name="unitBarterSellAmount[n]" ghost="true" style="resourceText" type="text" size="0 0 100% 50%"/> 13 <object name="unitBarterSellSelection[n]" hidden="true" type="image" ghost="true" size="3 3 33 33" sprite="stretched:session/icons/corners.png"/> 14 </object> 15 16 <!-- Buy --> 17 <object name="unitBarterBuyButton[n]" style="iconButton" type="button" size="0 0 36 36" tooltip_style="sessionToolTipBottomBold" hidden="true"> 18 <object name="unitBarterBuyIcon[n]" type="image" ghost="true" size="3 3 33 33"/> 19 <object name="unitBarterBuyAmount[n]" ghost="true" style="resourceText" type="text" size="0 0 100% 50%"/> 20 </object> 21 22 </repeat> 23 24 24 </object> -
binaries/data/mods/public/gui/session/session.js
diff --git a/binaries/data/mods/public/gui/session/session.js b/binaries/data/mods/public/gui/session/session.js index 35af7a7..af267cb 100644
a b var g_EntityStates = {}; 122 122 var g_TemplateData = {}; 123 123 var g_TemplateDataWithoutLocalization = {}; 124 124 var g_TechnologyData = {}; 125 var g_ResourceData = new Resources(); 125 126 126 127 /** 127 128 * Top coordinate of the research list. … … function updateTopPanel() 463 464 let viewPlayer = Engine.GetGUIObjectByName("viewPlayer"); 464 465 viewPlayer.hidden = !g_IsObserver && !g_DevSettings.changePerspective; 465 466 466 Engine.GetGUIObjectByName("food").hidden = !isPlayer; 467 Engine.GetGUIObjectByName("wood").hidden = !isPlayer; 468 Engine.GetGUIObjectByName("stone").hidden = !isPlayer; 469 Engine.GetGUIObjectByName("metal").hidden = !isPlayer; 467 let resCodes = g_ResourceData.GetCodes(); 468 let resNames = g_ResourceData.GetNames(); 469 let r = 0; 470 for (let res of resCodes) 471 { 472 Engine.GetGUIObjectByName("resource["+r+"]_icon").sprite = "stretched:session/icons/resources/" + res + ".png"; 473 Engine.GetGUIObjectByName("resource["+r+"]").hidden = !isPlayer; 474 ++r; 475 } 476 horizontallyDistributeObjects("resourceCounts", 0, r); 477 hideRemaining("resource[", r, "]"); 478 470 479 Engine.GetGUIObjectByName("population").hidden = !isPlayer; 471 480 Engine.GetGUIObjectByName("diplomacyButton1").hidden = !isPlayer; 472 481 Engine.GetGUIObjectByName("tradeButton1").hidden = !isPlayer; … … function leaveGame(willRejoin) 547 556 "disconnected": g_Disconnected, 548 557 "isReplay": g_IsReplay, 549 558 "replayDirectory": !g_HasRejoined && replayDirectory, 550 "replaySelectionData": g_ReplaySelectionData 559 "replaySelectionData": g_ReplaySelectionData, 560 "resources": GetSimState().resources 551 561 } 552 562 }); 553 563 } … … function getAllyStatTooltip(resource) 947 957 948 958 function updatePlayerDisplay() 949 959 { 950 let playerState = GetSimState().players[g_ViewedPlayer]; 960 let simState = GetSimState(); 961 let playerState = simState.players[g_ViewedPlayer]; 951 962 if (!playerState) 952 963 return; 953 964 954 for (let res of RESOURCES) 965 let resCodes = g_ResourceData.GetCodes(); 966 let resNames = g_ResourceData.GetNames(); 967 for (let r = 0; r < resCodes.length; ++r) 955 968 { 956 Engine.GetGUIObjectByName("resource_" + res).caption = Math.floor(playerState.resourceCounts[res]); 957 Engine.GetGUIObjectByName(res).tooltip = getLocalizedResourceName(res, "firstWord") + getAllyStatTooltip(res); 969 let res = resCodes[r]; 970 Engine.GetGUIObjectByName("resource["+r+"]").tooltip = getLocalizedResourceName(resNames[res], "firstWord") + getAllyStatTooltip(res); 971 Engine.GetGUIObjectByName("resource["+r+"]_count").caption = Math.floor(playerState.resourceCounts[res]); 958 972 } 959 973 960 974 Engine.GetGUIObjectByName("resourcePop").caption = sprintf(translate("%(popCount)s/%(popLimit)s"), playerState); -
deleted file binaries/data/mods/public/gui/session/top_panel/resource_food.xml
diff --git a/binaries/data/mods/public/gui/session/top_panel/resource_food.xml b/binaries/data/mods/public/gui/session/top_panel/resource_food.xml deleted file mode 100644 index 4d84ca7..0000000
+ - 1 <?xml version="1.0" encoding="utf-8"?>2 <object name="food" size="10 0 100 100%" type="image" style="resourceCounter" tooltip_style="sessionToolTipBold">3 <object size="0 -4 40 36" type="image" sprite="stretched:session/icons/resources/food.png" ghost="true"/>4 <object size="32 0 100% 100%-2" type="text" style="resourceText" name="resource_food"/>5 </object> -
deleted file binaries/data/mods/public/gui/session/top_panel/resource_metal.xml
diff --git a/binaries/data/mods/public/gui/session/top_panel/resource_metal.xml b/binaries/data/mods/public/gui/session/top_panel/resource_metal.xml deleted file mode 100644 index 4edba79..0000000
+ - 1 <?xml version="1.0" encoding="utf-8"?>2 <object name="metal" size="280 0 370 100%" type="image" style="resourceCounter" tooltip_style="sessionToolTipBold">3 <object size="0 -4 40 36" type="image" sprite="stretched:session/icons/resources/metal.png" ghost="true"/>4 <object size="32 0 100% 100%-2" type="text" style="resourceText" name="resource_metal"/>5 </object> -
binaries/data/mods/public/gui/session/top_panel/resource_population.xml
diff --git a/binaries/data/mods/public/gui/session/top_panel/resource_population.xml b/binaries/data/mods/public/gui/session/top_panel/resource_population.xml index 9c9dcc2..9d66e40 100644
a b 1 1 <?xml version="1.0" encoding="utf-8"?> 2 <object name="population" size=" 370 0 460100%" type="image" style="resourceCounter" tooltip_style="sessionToolTipBold">2 <object name="population" size="50%-90-52 0 50%-52 100%" type="image" style="resourceCounter" tooltip_style="sessionToolTipBold"> 3 3 <object size="0 -4 40 34" type="image" sprite="stretched:session/icons/resources/population.png" ghost="true"/> 4 4 <object size="32 0 100% 100%-2" type="text" style="resourceText" name="resourcePop"/> 5 5 </object> -
deleted file binaries/data/mods/public/gui/session/top_panel/resource_stone.xml
diff --git a/binaries/data/mods/public/gui/session/top_panel/resource_stone.xml b/binaries/data/mods/public/gui/session/top_panel/resource_stone.xml deleted file mode 100644 index 6133acc..0000000
+ - 1 <?xml version="1.0" encoding="utf-8"?>2 <object name="stone" size="190 0 280 100%" type="image" style="resourceCounter" tooltip_style="sessionToolTipBold">3 <object size="0 -4 40 36" type="image" sprite="stretched:session/icons/resources/stone.png" ghost="true"/>4 <object size="32 0 100% 100%-2" type="text" style="resourceText" name="resource_stone"/>5 </object> -
deleted file binaries/data/mods/public/gui/session/top_panel/resource_wood.xml
diff --git a/binaries/data/mods/public/gui/session/top_panel/resource_wood.xml b/binaries/data/mods/public/gui/session/top_panel/resource_wood.xml deleted file mode 100644 index f020979..0000000
+ - 1 <?xml version="1.0" encoding="utf-8"?>2 <object name="wood" size="100 0 190 100%" type="image" style="resourceCounter" tooltip_style="sessionToolTipBold">3 <object size="0 -4 40 36" type="image" sprite="stretched:session/icons/resources/wood.png" ghost="true"/>4 <object size="32 0 100% 100%-2" type="text" style="resourceText" name="resource_wood"/>5 </object> -
new file inaries/data/mods/public/gui/session/top_panel/resources.xml
diff --git a/binaries/data/mods/public/gui/session/top_panel/resources.xml b/binaries/data/mods/public/gui/session/top_panel/resources.xml new file mode 100644 index 0000000..520aa35
- + 1 <?xml version="1.0" encoding="utf-8"?> 2 3 <object size="10 0 50%-90-52 100%" name="resourceCounts"> 4 <repeat count="8"> 5 <object name="resource[n]" size="0 0 90 100%" type="image" style="resourceCounter" tooltip_style="sessionToolTipBold"> 6 <object size="0 -4 40 36" type="image" name="resource[n]_icon" ghost="true"/> 7 <object size="32 0 100% 100%-2" type="text" style="resourceText" name="resource[n]_count"/> 8 </object> 9 </repeat> 10 </object> -
binaries/data/mods/public/gui/session/trade_window.xml
diff --git a/binaries/data/mods/public/gui/session/trade_window.xml b/binaries/data/mods/public/gui/session/trade_window.xml index 80b226c..0862bc1 100644
a b 16 16 </object> 17 17 18 18 <object size="180 0 100% 100%"> 19 <repeat count=" 4">19 <repeat count="8"> 20 20 <object name="tradeResource[n]" size="0 0 58 32"> 21 21 <object name="tradeResourceButton[n]" size="4 0 36 100%" type="button" style="StoneButton"> 22 22 <object name="tradeResourceIcon[n]" type="image" ghost="true"/> -
binaries/data/mods/public/gui/structree/draw.js
diff --git a/binaries/data/mods/public/gui/structree/draw.js b/binaries/data/mods/public/gui/structree/draw.js index 92c60ce..ee15fb3 100644
a b function getPositionOffset(idx) 235 235 return size; 236 236 } 237 237 238 function hideRemaining(prefix, idx, suffix)239 {240 let obj = Engine.GetGUIObjectByName(prefix + idx + suffix);241 while (obj)242 {243 obj.hidden = true;244 ++idx;245 obj = Engine.GetGUIObjectByName(prefix + idx + suffix);246 }247 }248 249 250 238 /** 251 239 * Positions certain elements that only need to be positioned once 252 240 * (as <repeat> does not reposition automatically). -
binaries/data/mods/public/gui/structree/load.js
diff --git a/binaries/data/mods/public/gui/structree/load.js b/binaries/data/mods/public/gui/structree/load.js index 534747b..006de1b 100644
a b 5 5 */ 6 6 function getGatherRates(templateName) 7 7 { 8 // TODO: It would be nice to use the gather rates present in the templates 9 // instead of hard-coding the possible rates here. 10 11 // We ignore ruins here, as those are not that common and would skew the results 12 var types = { 13 "food": ["food", "food.fish", "food.fruit", "food.grain", "food.meat", "food.milk"], 14 "wood": ["wood", "wood.tree"], 15 "stone": ["stone", "stone.rock"], 16 "metal": ["metal", "metal.ore"] 17 }; 18 var rates = {}; 8 let rates = {}; 19 9 20 for (let type in types)10 for (let resource of g_ResourceData.GetData()) 21 11 { 12 let types = [resource.code]; 13 for (let subtype of resource.subtypes) 14 // We ignore ruins as those are not that common and skew the results 15 if (subtype !== "ruins") 16 types.push(resource.code + "." + subtype); 17 22 18 let count, rate; 23 [rate, count] = types [type].reduce(function(sum, t) {19 [rate, count] = types.reduce(function(sum, t) { 24 20 let r = +fetchValue(templateName, "ResourceGatherer/Rates/"+t); 25 21 return [sum[0] + (r > 0 ? r : 0), sum[1] + (r > 0 ? 1 : 0)]; 26 22 }, [0, 0]); 27 23 28 24 if (rate > 0) 29 rates[ type] = Math.round(rate / count * 100) / 100;25 rates[resource.code] = Math.round(rate / count * 100) / 100; 30 26 } 31 27 32 28 if (!Object.keys(rates).length) -
binaries/data/mods/public/gui/structree/structree.js
diff --git a/binaries/data/mods/public/gui/structree/structree.js b/binaries/data/mods/public/gui/structree/structree.js index 65bfd9e..fcb6a9c 100644
a b var g_Lists = {}; 9 9 var g_CivData = {}; 10 10 var g_SelectedCiv = ""; 11 11 var g_CallbackSet = false; 12 var g_ResourceData = new Resources(); 12 13 13 14 /** 14 15 * Initialize the dropdown containing all the available civs -
binaries/data/mods/public/gui/summary/counters.js
diff --git a/binaries/data/mods/public/gui/summary/counters.js b/binaries/data/mods/public/gui/summary/counters.js index 562e3bb..1823b67 100644
a b function calculateUnits(playerState, position) 250 250 251 251 function calculateResources(playerState, position) 252 252 { 253 let type = g_Resource sTypes[position];253 let type = g_ResourceData.GetCodes()[position]; 254 254 255 255 return formatIncome( 256 256 playerState.statistics.resourcesGathered[type], … … function calculateTotalResources(playerState) 262 262 let totalGathered = 0; 263 263 let totalUsed = 0; 264 264 265 for (let type of g_Resource sTypes)265 for (let type of g_ResourceData.GetCodes()) 266 266 { 267 267 totalGathered += playerState.statistics.resourcesGathered[type]; 268 268 totalUsed += playerState.statistics.resourcesUsed[type] - playerState.statistics.resourcesSold[type]; … … function calculateResourcesTeam(counters) 330 330 331 331 function calculateResourceExchanged(playerState, position) 332 332 { 333 let type = g_Resource sTypes[position];333 let type = g_ResourceData.GetCodes()[position]; 334 334 335 335 return formatIncome( 336 336 playerState.statistics.resourcesBought[type], -
binaries/data/mods/public/gui/summary/layout.js
diff --git a/binaries/data/mods/public/gui/summary/layout.js b/binaries/data/mods/public/gui/summary/layout.js index 7feeb45..bd9962c 100644
a b var g_ScorePanelsData = { 92 92 "resources": { 93 93 "headings": [ 94 94 { "caption": translate("Player name"), "yStart": 26, "width": 200 }, 95 { "caption": translate("Food"), "yStart": 34, "width": 100 },96 { "caption": translate("Wood"), "yStart": 34, "width": 100 },97 { "caption": translate("Stone"), "yStart": 34, "width": 100 },98 { "caption": translate("Metal"), "yStart": 34, "width": 100 },99 95 { "caption": translate("Total"), "yStart": 34, "width": 110 }, 100 96 { 101 97 "caption": sprintf(translate("Tributes \n(%(sent)s / %(received)s)"), … … var g_ScorePanelsData = { 121 117 }, // width = 510 122 118 ], 123 119 "counters": [ 124 { "width": 100, "fn": calculateResources, "verticalOffset": 12 },125 { "width": 100, "fn": calculateResources, "verticalOffset": 12 },126 { "width": 100, "fn": calculateResources, "verticalOffset": 12 },127 { "width": 100, "fn": calculateResources, "verticalOffset": 12 },128 120 { "width": 110, "fn": calculateTotalResources, "verticalOffset": 12 }, 129 121 { "width": 121, "fn": calculateTributeSent, "verticalOffset": 12 }, 130 122 { "width": 100, "fn": calculateTreasureCollected, "verticalOffset": 12 }, … … var g_ScorePanelsData = { 135 127 "market": { 136 128 "headings": [ 137 129 { "caption": translate("Player name"), "yStart": 26, "width": 200 }, 138 { "caption": translate("Food exchanged"), "yStart": 16, "width": 100 },139 { "caption": translate("Wood exchanged"), "yStart": 16, "width": 100 },140 { "caption": translate("Stone exchanged"), "yStart": 16, "width": 100 },141 { "caption": translate("Metal exchanged"), "yStart": 16, "width": 100 },142 130 { "caption": translate("Barter efficiency"), "yStart": 16, "width": 100 }, 143 131 { "caption": translate("Trade income"), "yStart": 16, "width": 100 } 144 132 ], 145 133 "titleHeadings": [], 146 134 "counters": [ 147 { "width": 100, "fn": calculateResourceExchanged, "verticalOffset": 12 },148 { "width": 100, "fn": calculateResourceExchanged, "verticalOffset": 12 },149 { "width": 100, "fn": calculateResourceExchanged, "verticalOffset": 12 },150 { "width": 100, "fn": calculateResourceExchanged, "verticalOffset": 12 },151 135 { "width": 100, "fn": calculateBarterEfficiency, "verticalOffset": 12 }, 152 136 { "width": 100, "fn": calculateTradeIncome, "verticalOffset": 12 } 153 137 ], -
binaries/data/mods/public/gui/summary/summary.js
diff --git a/binaries/data/mods/public/gui/summary/summary.js b/binaries/data/mods/public/gui/summary/summary.js index 51e5577..f4da805 100644
a b 1 const g_MaxHeadingTitle= 8;1 const g_MaxHeadingTitle= 12; 2 2 3 3 // const for filtering long collective headings 4 4 const g_LongHeadingWidth = 250; … … const g_CapturedColor = '[color="255 255 157"]'; 17 17 18 18 const g_BuildingsTypes = [ "total", "House", "Economic", "Outpost", "Military", "Fortress", "CivCentre", "Wonder" ]; 19 19 const g_UnitsTypes = [ "total", "Infantry", "Worker", "Cavalry", "Champion", "Hero", "Ship", "Trader" ]; 20 const g_ResourcesTypes = [ "food", "wood", "stone", "metal" ];21 20 22 21 // Colors used for gathered and traded resources 23 22 const g_IncomeColor = '[color="201 255 200"]'; … … var g_PlayerCount = 0; 34 33 // Count players without team (or all if teams are not displayed) 35 34 var g_WithoutTeam = 0; 36 35 var g_GameData; 36 var g_ResourceData = new Resources(); 37 37 38 38 function selectPanel(panel) 39 39 { … … function init(data) 242 242 else 243 243 g_Teams = false; 244 244 245 // Resource names and counters 246 let resHeads = []; 247 let tradeHeads = []; 248 let resPanel = g_ScorePanelsData.resources; 249 let tradePanel = g_ScorePanelsData.market; 250 let resNames = g_ResourceData.GetNames(); 251 let resCodes = g_ResourceData.GetCodes(); 252 for (let code of resCodes) 253 { 254 resHeads.push({ 255 "caption": translateWithContext("firstWord", resNames[code]), 256 "yStart": 34, 257 "width": 100 258 }); 259 260 resPanel.counters.unshift({ 261 "width": 100, 262 "fn": calculateResources, 263 "verticalOffset": 12 264 }); 265 266 tradeHeads.push({ 267 "caption": sprintf( 268 translate("%(resource)s exchanged"), { 269 "resource": translateWithContext("withinSentence", resNames[code]) 270 }), 271 "yStart": 16, 272 "width": 100 273 }); 274 275 tradePanel.counters.unshift({ 276 "width": 100, 277 "fn": calculateResourceExchanged, 278 "verticalOffset": 12 279 }); 280 } 281 resPanel.headings.splice.apply(resPanel.headings, [1, 0].concat(resHeads)); 282 resPanel.titleHeadings[0].width = (100 * resCodes.length) + 110; 283 tradePanel.headings.splice.apply(tradePanel.headings, [1, 0].concat(tradeHeads)); 284 245 285 // Erase teams data if teams are not displayed 246 286 if (!g_Teams) 247 287 { -
binaries/data/mods/public/gui/summary/summary.xml
diff --git a/binaries/data/mods/public/gui/summary/summary.xml b/binaries/data/mods/public/gui/summary/summary.xml index 2c47f16..015638f 100644
a b 103 103 <object name="playerNameHeading" type="text" style="ModernLeftTabLabelText"> 104 104 <translatableAttribute id="caption">Player name</translatableAttribute> 105 105 </object> 106 <repeat var="x" count=" 8">106 <repeat var="x" count="12"> 107 107 <object name="titleHeading[x]" type="text" style="ModernTabLabelText"> 108 108 </object> 109 109 </repeat> 110 <repeat var="x" count=" 8">110 <repeat var="x" count="12"> 111 111 <object name="Heading[x]" type="text" style="ModernTabLabelText"> 112 112 </object> 113 113 </repeat> … … 124 124 </object> 125 125 <object name="playerNamet[i][n]" type="text" size="40 2 208 100%" style="ModernLeftLabelText"/> 126 126 <object name="civIcont[i][n]" type="image" size="208 5 240 37" /> 127 <repeat var="x" count=" 8">127 <repeat var="x" count="12"> 128 128 <object name="valueDataTeam[i][n][x]" type="text" style="ModernTabLabelText"> 129 129 </object> 130 130 </repeat> … … 132 132 </repeat> 133 133 </object> 134 134 <object name="teamHeadingt[i]" type="text" style="ModernLeftTabLabelText"/> 135 <repeat var="x" count=" 8">135 <repeat var="x" count="12"> 136 136 <object name="valueDataTeam[i][x]" type="text" style="ModernTabLabelText"> 137 137 </object> 138 138 </repeat> … … 147 147 </object> 148 148 <object name="playerName[n]" type="text" size="40 2 208 100%" style="ModernLeftLabelText"/> 149 149 <object name="civIcon[n]" type="image" size="208 5 240 37"/> 150 <repeat var="x" count=" 8">150 <repeat var="x" count="12"> 151 151 <object name="valueData[n][x]" type="text" style="ModernTabLabelText"> 152 152 </object> 153 153 </repeat> -
binaries/data/mods/public/l10n/messages.json
diff --git a/binaries/data/mods/public/l10n/messages.json b/binaries/data/mods/public/l10n/messages.json index 188e3cc..34bd751 100644
a b 289 289 } 290 290 } 291 291 }, 292 292 { 293 293 "extractor": "json", 294 294 "filemasks": [ 295 295 "gui/credits/texts/**.json" … … 562 562 "description" 563 563 ] 564 564 } 565 }, 566 { 567 "extractor": "json", 568 "filemasks": [ 569 "simulation/data/resources/**.json" 570 ], 571 "options": { 572 "keywords": [ 573 "name", 574 "subtypes" 575 ], 576 "context": "firstWord" 577 } 578 }, 579 { 580 "extractor": "json", 581 "filemasks": [ 582 "simulation/data/resources/**.json" 583 ], 584 "options": { 585 "keywords": [ 586 "name", 587 "subtypes" 588 ], 589 "context": "withinSentence" 590 } 565 591 } 566 592 ] 567 593 }, -
binaries/data/mods/public/simulation/ai/common-api/resources.js
diff --git a/binaries/data/mods/public/simulation/ai/common-api/resources.js b/binaries/data/mods/public/simulation/ai/common-api/resources.js index 8130676..b6fe84b 100644
a b m.Resources = function(amounts = {}, population = 0) 9 9 this.population = population > 0 ? population : 0; 10 10 }; 11 11 12 m.Resources.prototype.types = []; // This array will be filled in SharedScript.init 12 // This array will be filled in SharedScript.init 13 m.Resources.prototype.types = []; 13 14 14 15 m.Resources.prototype.reset = function() 15 16 { -
binaries/data/mods/public/simulation/ai/common-api/shared.js
diff --git a/binaries/data/mods/public/simulation/ai/common-api/shared.js b/binaries/data/mods/public/simulation/ai/common-api/shared.js index 68ab45d..0e7b6c5 100644
a b m.SharedScript.prototype.init = function(state, deserialization) 180 180 this.accessibility.init(state, this.terrainAnalyzer); 181 181 182 182 // Setup resources 183 this.resourceTypes = { "food": 0, "wood": 1, "stone": 2, "metal": 2 }; 184 this.resourceList = []; 185 for (let res in this.resourceTypes) 186 this.resourceList.push(res); 187 m.Resources.prototype.types = this.resourceList; 183 this.resourceInfo = state.resources; 184 m.Resources.prototype.types = state.resources.codes; 188 185 // Resource types: 0 = not used for resource maps 189 // 1 = ab ondant resource with small amount each186 // 1 = abundant resource with small amount each 190 187 // 2 = spare resource, but huge amount each 191 188 // The following maps are defined in TerrainAnalysis.js and are used for some building placement (cc, dropsites) 192 189 // They are updated by checking for create and destroy events for all resources … … m.SharedScript.prototype.init = function(state, deserialization) 197 194 this.ccResourceMaps = {}; // Contains maps showing the density of resources, optimized for CC placement. 198 195 this.createResourceMaps(); 199 196 200 /** Keep in sync with gui/common/l10n.js */201 this.resourceNames = {202 // Translation: Word as used in the middle of a sentence (which may require using lowercase for your language).203 "food": markForTranslationWithContext("withinSentence", "Food"),204 // Translation: Word as used in the middle of a sentence (which may require using lowercase for your language).205 "wood": markForTranslationWithContext("withinSentence", "Wood"),206 // Translation: Word as used in the middle of a sentence (which may require using lowercase for your language).207 "metal": markForTranslationWithContext("withinSentence", "Metal"),208 // Translation: Word as used in the middle of a sentence (which may require using lowercase for your language).209 "stone": markForTranslationWithContext("withinSentence", "Stone"),210 };211 212 197 this.gameState = {}; 213 198 for (let i in this._players) 214 199 { -
binaries/data/mods/public/simulation/ai/common-api/terrain-analysis.js
diff --git a/binaries/data/mods/public/simulation/ai/common-api/terrain-analysis.js b/binaries/data/mods/public/simulation/ai/common-api/terrain-analysis.js index 04633dc..7d79317 100644
a b m.Accessibility.prototype.floodFill = function(startIndex, value, onWater) 383 383 /** creates a map of resource density */ 384 384 m.SharedScript.prototype.createResourceMaps = function() 385 385 { 386 for (let resource of this.resource List)386 for (let resource of this.resourceInfo.codes) 387 387 { 388 if (this.resource Types[resource] !== 1 && this.resourceTypes[resource] !== 2)388 if (this.resourceInfo.aiInfluenceGroups[resource] === 0) 389 389 continue; 390 390 // if there is no resourceMap create one with an influence for everything with that resource 391 391 if (this.resourceMaps[resource]) … … m.SharedScript.prototype.createResourceMaps = function() 405 405 let cellSize = this.resourceMaps[resource].cellSize; 406 406 let x = Math.floor(ent.position()[0] / cellSize); 407 407 let z = Math.floor(ent.position()[1] / cellSize); 408 let type = this.resourceTypes[resource];409 let strength = Math.floor(ent.resourceSupplyMax()/this.normalizationFactor[ type]);410 this.resourceMaps[resource].addInfluence(x, z, this.influenceRadius[ type]/cellSize, strength/2, "constant");411 this.resourceMaps[resource].addInfluence(x, z, this.influenceRadius[ type]/cellSize, strength/2);412 this.ccResourceMaps[resource].addInfluence(x, z, this.ccInfluenceRadius[ type]/cellSize, strength, "constant");408 let grp = this.resourceInfo.aiInfluenceGroups[resource]; 409 let strength = Math.floor(ent.resourceSupplyMax()/this.normalizationFactor[grp]); 410 this.resourceMaps[resource].addInfluence(x, z, this.influenceRadius[grp]/cellSize, strength/2, "constant"); 411 this.resourceMaps[resource].addInfluence(x, z, this.influenceRadius[grp]/cellSize, strength/2); 412 this.ccResourceMaps[resource].addInfluence(x, z, this.ccInfluenceRadius[grp]/cellSize, strength, "constant"); 413 413 } 414 414 }; 415 415 … … m.SharedScript.prototype.createResourceMaps = function() 420 420 */ 421 421 m.SharedScript.prototype.updateResourceMaps = function(events) 422 422 { 423 for (let resource of this.resource List)423 for (let resource of this.resourceInfo.codes) 424 424 { 425 if (this.resource Types[resource] !== 1 && this.resourceTypes[resource] !== 2)425 if (this.resourceInfo.aiInfluenceGroups[resource] === 0) 426 426 continue; 427 427 // if there is no resourceMap create one with an influence for everything with that resource 428 428 if (this.resourceMaps[resource]) … … m.SharedScript.prototype.updateResourceMaps = function(events) 447 447 let cellSize = this.resourceMaps[resource].cellSize; 448 448 let x = Math.floor(ent.position()[0] / cellSize); 449 449 let z = Math.floor(ent.position()[1] / cellSize); 450 let type = this.resourceTypes[resource];451 let strength = -Math.floor(ent.resourceSupplyMax()/this.normalizationFactor[ type]);452 this.resourceMaps[resource].addInfluence(x, z, this.influenceRadius[ type]/cellSize, strength/2, "constant");453 this.resourceMaps[resource].addInfluence(x, z, this.influenceRadius[ type]/cellSize, strength/2);454 this.ccResourceMaps[resource].addInfluence(x, z, this.ccInfluenceRadius[ type]/cellSize, strength, "constant");450 let grp = this.resourceInfo.aiInfluenceGroups[resource]; 451 let strength = -Math.floor(ent.resourceSupplyMax()/this.normalizationFactor[grp]); 452 this.resourceMaps[resource].addInfluence(x, z, this.influenceRadius[grp]/cellSize, strength/2, "constant"); 453 this.resourceMaps[resource].addInfluence(x, z, this.influenceRadius[grp]/cellSize, strength/2); 454 this.ccResourceMaps[resource].addInfluence(x, z, this.ccInfluenceRadius[grp]/cellSize, strength, "constant"); 455 455 } 456 456 for (let e of events.Create) 457 457 { … … m.SharedScript.prototype.updateResourceMaps = function(events) 466 466 let cellSize = this.resourceMaps[resource].cellSize; 467 467 let x = Math.floor(ent.position()[0] / cellSize); 468 468 let z = Math.floor(ent.position()[1] / cellSize); 469 let type = this.resourceTypes[resource];470 let strength = Math.floor(ent.resourceSupplyMax()/this.normalizationFactor[ type]);471 this.resourceMaps[resource].addInfluence(x, z, this.influenceRadius[ type]/cellSize, strength/2, "constant");472 this.resourceMaps[resource].addInfluence(x, z, this.influenceRadius[ type]/cellSize, strength/2);473 this.ccResourceMaps[resource].addInfluence(x, z, this.ccInfluenceRadius[ type]/cellSize, strength, "constant");469 let grp = this.resourceInfo.aiInfluenceGroups[resource]; 470 let strength = Math.floor(ent.resourceSupplyMax()/this.normalizationFactor[grp]); 471 this.resourceMaps[resource].addInfluence(x, z, this.influenceRadius[grp]/cellSize, strength/2, "constant"); 472 this.resourceMaps[resource].addInfluence(x, z, this.influenceRadius[grp]/cellSize, strength/2); 473 this.ccResourceMaps[resource].addInfluence(x, z, this.ccInfluenceRadius[grp]/cellSize, strength, "constant"); 474 474 } 475 475 }; 476 476 -
binaries/data/mods/public/simulation/ai/petra/baseManager.js
diff --git a/binaries/data/mods/public/simulation/ai/petra/baseManager.js b/binaries/data/mods/public/simulation/ai/petra/baseManager.js index f1b338f..1c823c7 100644
a b m.BaseManager.prototype.init = function(gameState, state) 55 55 this.dropsites = {}; 56 56 this.dropsiteSupplies = {}; 57 57 this.gatherers = {}; 58 for (let res of gameState.sharedScript.resource List)58 for (let res of gameState.sharedScript.resourceInfo.codes) 59 59 { 60 60 this.dropsiteSupplies[res] = { "nearby": [], "medium": [], "faraway": [] }; 61 61 this.gatherers[res] = { "nextCheck": 0, "used": 0, "lost": 0 }; … … m.BaseManager.prototype.getResourceLevel = function (gameState, type, nearbyOnly 434 434 /** check our resource levels and react accordingly */ 435 435 m.BaseManager.prototype.checkResourceLevels = function (gameState, queues) 436 436 { 437 for (let type of gameState.sharedScript.resource List)437 for (let type of gameState.sharedScript.resourceInfo.codes) 438 438 { 439 439 if (type === "food") 440 440 { -
binaries/data/mods/public/simulation/ai/petra/chatHelper.js
diff --git a/binaries/data/mods/public/simulation/ai/petra/chatHelper.js b/binaries/data/mods/public/simulation/ai/petra/chatHelper.js index 60999e8..d50232f 100644
a b m.chatRequestTribute = function(gameState, resource) 91 91 "message": message, 92 92 "translateMessage": true, 93 93 "translateParameters": {"resource": "withinSentence"}, 94 "parameters": {"resource": gameState.sharedScript.resource Names[resource]}94 "parameters": {"resource": gameState.sharedScript.resourceInfo.names[resource]} 95 95 }); 96 96 }; 97 97 -
binaries/data/mods/public/simulation/ai/petra/config.js
diff --git a/binaries/data/mods/public/simulation/ai/petra/config.js b/binaries/data/mods/public/simulation/ai/petra/config.js index d5dc6b3..b0f5e7f 100644
a b m.Config = function(difficulty) 103 103 "defensive": 0.5 104 104 }; 105 105 106 this.resources = ["food", "wood", "stone", "metal"]; 106 // See m.QueueManager.prototype.wantedGatherRates() 107 this.queues = 108 { 109 "firstTurn": { 110 "food": 10, 111 "wood": 10, 112 "default": 0 113 }, 114 "short": { 115 "food": 200, 116 "wood": 200, 117 "default": 100 118 }, 119 "medium": { 120 "default": 0 121 }, 122 "long": { 123 "default": 0 124 } 125 }; 107 126 }; 108 127 109 128 m.Config.prototype.setConfig = function(gameState) -
binaries/data/mods/public/simulation/ai/petra/headquarters.js
diff --git a/binaries/data/mods/public/simulation/ai/petra/headquarters.js b/binaries/data/mods/public/simulation/ai/petra/headquarters.js index 3e67da9..871035f 100644
a b m.HQ.prototype.init = function(gameState, queues) 69 69 this.navalMap = false; 70 70 this.navalRegions = {}; 71 71 72 for (let res of gameState.sharedScript.resource List)72 for (let res of gameState.sharedScript.resourceInfo.codes) 73 73 { 74 74 this.wantedRates[res] = 0; 75 75 this.currentRates[res] = 0; … … m.HQ.prototype.bulkPickWorkers = function(gameState, baseRef, number) 653 653 m.HQ.prototype.getTotalResourceLevel = function(gameState) 654 654 { 655 655 let total = {}; 656 for (let res of gameState.sharedScript.resource List)656 for (let res of gameState.sharedScript.resourceInfo.codes) 657 657 total[res] = 0; 658 658 for (let base of this.baseManagers) 659 659 for (let res in total) -
binaries/data/mods/public/simulation/ai/petra/queueManager.js
diff --git a/binaries/data/mods/public/simulation/ai/petra/queueManager.js b/binaries/data/mods/public/simulation/ai/petra/queueManager.js index 4691d11..671131d 100644
a b m.QueueManager.prototype.wantedGatherRates = function(gameState) 84 84 if (gameState.ai.playedTurn === 0) 85 85 { 86 86 let ret = {}; 87 for (let res of gameState.sharedScript.resource List)88 ret[res] = (res === "food" || res === "wood" ) ? 10 : 0;87 for (let res of gameState.sharedScript.resourceInfo.codes) 88 ret[res] = this.Config.queues.firstTurn[res] || this.Config.queues.firstTurn.default; 89 89 return ret; 90 90 } 91 91 … … m.QueueManager.prototype.wantedGatherRates = function(gameState) 97 97 let totalShort = {}; 98 98 let totalMedium = {}; 99 99 let totalLong = {}; 100 for (let res of gameState.sharedScript.resource List)100 for (let res of gameState.sharedScript.resourceInfo.codes) 101 101 { 102 totalShort[res] = (res === "food" || res === "wood" ) ? 200 : 100;103 totalMedium[res] = 0;104 totalLong[res] = 0;102 totalShort[res] = this.Config.queues.short[res] || this.Config.queues.short.default; 103 totalMedium[res] = this.Config.queues.medium[res] || this.Config.queues.medium.default; 104 totalLong[res] = this.Config.queues.long[res] || this.Config.queues.long.default; 105 105 } 106 106 let total; 107 107 //queueArrays because it's faster. … … m.QueueManager.prototype.wantedGatherRates = function(gameState) 133 133 // global rates 134 134 let rates = {}; 135 135 let diff; 136 for (let res of gameState.sharedScript.resource List)136 for (let res of gameState.sharedScript.resourceInfo.codes) 137 137 { 138 138 if (current[res] > 0) 139 139 { -
binaries/data/mods/public/simulation/ai/petra/researchManager.js
diff --git a/binaries/data/mods/public/simulation/ai/petra/researchManager.js b/binaries/data/mods/public/simulation/ai/petra/researchManager.js index f169b39..8e409a1 100644
a b m.ResearchManager.prototype.researchWantedTechs = function(gameState, techs) 100 100 let cost = template.cost; 101 101 let costMax = 0; 102 102 for (let res in cost) 103 costMax = Math.max(costMax, Math.max(cost[res]-available[res], 0)); 103 if (gameState.sharedScript.resourceInfo.codes.indexOf(res)) 104 costMax = Math.max(costMax, Math.max(cost[res]-available[res], 0)); 104 105 if (10*numWorkers < costMax) 105 106 continue; 106 107 } -
binaries/data/mods/public/simulation/components/Barter.js
diff --git a/binaries/data/mods/public/simulation/components/Barter.js b/binaries/data/mods/public/simulation/components/Barter.js index 24c39a4..106d1e3 100644
a b 1 // T rue price of 100 units of resource (for case if some resource is more worth).1 // The "true price" is a base price of 100 units of resource (for the case of some resources being of more worth than others). 2 2 // With current bartering system only relative values makes sense 3 3 // so if for example stone is two times more expensive than wood, 4 4 // there will 2:1 exchange rate. 5 const TRUE_PRICES = { "food": 100, "wood": 100, "stone": 100, "metal": 100 }; 6 5 // 7 6 // Constant part of price difference between true price and buy/sell price. 8 7 // In percents. 9 8 // Buy price equal to true price plus constant difference. … … const DIFFERENCE_RESTORE = 0.5; 21 20 // Interval of timer which slowly restore prices after deals 22 21 const RESTORE_TIMER_INTERVAL = 5000; 23 22 24 // Array of resource names25 const RESOURCES = ["food", "wood", "stone", "metal"];26 27 23 function Barter() {} 28 24 29 25 Barter.prototype.Schema = … … Barter.prototype.Schema = 32 28 Barter.prototype.Init = function() 33 29 { 34 30 this.priceDifferences = {}; 35 for ( var resource of RESOURCES)31 for (let resource of Resources.GetCodes()) 36 32 this.priceDifferences[resource] = 0; 37 33 this.restoreTimer = undefined; 38 34 }; … … Barter.prototype.Init = function() 40 36 Barter.prototype.GetPrices = function() 41 37 { 42 38 var prices = { "buy": {}, "sell": {} }; 43 for ( var resource of RESOURCES)39 for (let resource of Resources.GetCodes()) 44 40 { 45 prices["buy"][resource] = TRUE_PRICES[resource] * (100 + CONSTANT_DIFFERENCE + this.priceDifferences[resource]) / 100; 46 prices["sell"][resource] = TRUE_PRICES[resource] * (100 - CONSTANT_DIFFERENCE + this.priceDifferences[resource]) / 100; 41 let truePrice = Resources.GetResource(resource).truePrice; 42 prices.buy[resource] = truePrice * (100 + CONSTANT_DIFFERENCE + this.priceDifferences[resource]) / 100; 43 prices.sell[resource] = truePrice * (100 - CONSTANT_DIFFERENCE + this.priceDifferences[resource]) / 100; 47 44 } 48 45 return prices; 49 46 }; … … Barter.prototype.ExchangeResources = function(playerEntity, resourceToSell, reso 71 68 warn("ExchangeResources: incorrect amount: " + uneval(amount)); 72 69 return; 73 70 } 74 if (RESOURCES.indexOf(resourceToSell) == -1) 71 let availResources = Resources.GetCodes(); 72 if (availResources.indexOf(resourceToSell) == -1) 75 73 { 76 74 warn("ExchangeResources: incorrect resource to sell: " + uneval(resourceToSell)); 77 75 return; 78 76 } 79 if ( RESOURCES.indexOf(resourceToBuy) == -1)77 if (availResources.indexOf(resourceToBuy) == -1) 80 78 { 81 79 warn("ExchangeResources: incorrect resource to buy: " + uneval(resourceToBuy)); 82 80 return; … … Barter.prototype.ExchangeResources = function(playerEntity, resourceToSell, reso 123 121 Barter.prototype.ProgressTimeout = function(data) 124 122 { 125 123 var needRestore = false; 126 for ( var resource of RESOURCES)124 for (let resource of Resources.GetCodes()) 127 125 { 128 126 // Calculate value to restore, it should be limited to [-DIFFERENCE_RESTORE; DIFFERENCE_RESTORE] interval 129 127 var differenceRestore = Math.min(DIFFERENCE_RESTORE, Math.max(-DIFFERENCE_RESTORE, this.priceDifferences[resource])); -
binaries/data/mods/public/simulation/components/Cost.js
diff --git a/binaries/data/mods/public/simulation/components/Cost.js b/binaries/data/mods/public/simulation/components/Cost.js index b3196a6..bf33b60 100644
a b 1 1 function Cost() {} 2 2 3 Cost.prototype.ResourcesSchema = Resources.BuildSchema("nonNegativeDecimal"); 4 3 5 Cost.prototype.Schema = 4 6 "<a:help>Specifies the construction/training costs of this entity.</a:help>" + 5 7 "<a:example>" + … … Cost.prototype.Schema = 19 21 "<element name='PopulationBonus' a:help='Population cap increase while this entity exists'>" + 20 22 "<data type='nonNegativeInteger'/>" + 21 23 "</element>" + 22 "<element name='BuildTime' a:help='Time taken to construct/train this unit(in seconds)'>" +24 "<element name='BuildTime' a:help='Time taken to construct/train this entity (in seconds)'>" + 23 25 "<ref name='nonNegativeDecimal'/>" + 24 26 "</element>" + 25 "<element name='Resources' a:help='Resource costs to construct/train this unit'>" + 26 "<interleave>" + 27 "<element name='food'><ref name='nonNegativeDecimal'/></element>" + 28 "<element name='wood'><ref name='nonNegativeDecimal'/></element>" + 29 "<element name='stone'><ref name='nonNegativeDecimal'/></element>" + 30 "<element name='metal'><ref name='nonNegativeDecimal'/></element>" + 31 "</interleave>" + 27 "<element name='Resources' a:help='Resource costs to construct/train this entity'>" + 28 Cost.prototype.ResourcesSchema + 32 29 "</element>"; 33 30 34 31 Cost.prototype.Init = function() … … Cost.prototype.GetResourceCosts = function(owner) 70 67 let entityTemplate = cmpTemplateManager.GetTemplate(entityTemplateName); 71 68 72 69 let costs = {}; 73 for (let r in this.template.Resources) 74 costs[r] = ApplyValueModificationsToTemplate("Cost/Resources/"+r, +this.template.Resources[r], owner, entityTemplate); 70 let resCodes = Resources.GetCodes(); 71 72 for (let res in this.template.Resources) 73 { 74 let cost = +this.template.Resources[res]; 75 if (resCodes.indexOf(res) < 0) 76 continue; 77 costs[res] = ApplyValueModificationsToTemplate("Cost/Resources/"+res, cost, owner, entityTemplate); 78 } 79 75 80 return costs; 76 81 }; 77 82 -
binaries/data/mods/public/simulation/components/GuiInterface.js
diff --git a/binaries/data/mods/public/simulation/components/GuiInterface.js b/binaries/data/mods/public/simulation/components/GuiInterface.js index aaa7855..1b89b40 100644
a b GuiInterface.prototype.GetSimulationState = function() 152 152 let cmpBarter = Engine.QueryInterface(SYSTEM_ENTITY, IID_Barter); 153 153 ret.barterPrices = cmpBarter.GetPrices(); 154 154 155 // Add Resource Codes, untranslated names and AI Analysis 156 ret.resources = { 157 "codes": Resources.GetCodes(), 158 "names": Resources.GetNames(), 159 "aiInfluenceGroups": {} 160 }; 161 for (let res of ret.resources.codes) 162 ret.resources.aiInfluenceGroups[res] = Resources.GetResource(res).aiAnalysisInfluenceGroup || 0; 163 155 164 // Add basic statistics to each player 156 165 for (let i = 0; i < numPlayers; ++i) 157 166 { … … GuiInterface.prototype.SetWallPlacementPreview = function(player, cmd) 1269 1278 1270 1279 let result = { 1271 1280 "pieces": [], 1272 "cost": { " food": 0, "wood": 0, "stone": 0, "metal": 0, "population": 0, "populationBonus": 0, "time": 0 },1281 "cost": { "population": 0, "populationBonus": 0, "time": 0 }, 1273 1282 }; 1283 for (let res of Resources.GetCodes()) 1284 result.cost[res] = 0; 1274 1285 1275 1286 let previewEntities = []; 1276 1287 if (end.pos) … … GuiInterface.prototype.SetWallPlacementPreview = function(player, cmd) 1545 1556 // copied over, so we need to fetch it from the template instead). 1546 1557 // TODO: we should really use a Cost object or at least some utility functions for this, this is mindless 1547 1558 // boilerplate that's probably duplicated in tons of places. 1548 result.cost.food += tplData.cost.food; 1549 result.cost.wood += tplData.cost.wood; 1550 result.cost.stone += tplData.cost.stone; 1551 result.cost.metal += tplData.cost.metal; 1552 result.cost.population += tplData.cost.population; 1553 result.cost.populationBonus += tplData.cost.populationBonus; 1554 result.cost.time += tplData.cost.time; 1559 let entries = Resources.GetCodes().concat("population", "populationBonus", "time"); 1560 for (let res of entries) 1561 result.cost[res] = tplData.cost[res]; 1555 1562 } 1556 1563 1557 1564 let canAfford = true; -
binaries/data/mods/public/simulation/components/Loot.js
diff --git a/binaries/data/mods/public/simulation/components/Loot.js b/binaries/data/mods/public/simulation/components/Loot.js index 3161340..2d0939c 100644
a b 1 1 function Loot() {} 2 2 3 Loot.prototype.ResourcesSchema = Resources.BuildSchema("nonNegativeInteger", [ "xp" ]); 4 3 5 Loot.prototype.Schema = 4 "<optional>" + 5 "<element name='xp'><data type='nonNegativeInteger'/></element>" + 6 "</optional>" + 7 "<optional>" + 8 "<element name='food'><data type='nonNegativeInteger'/></element>" + 9 "</optional>" + 10 "<optional>" + 11 "<element name='wood'><data type='nonNegativeInteger'/></element>" + 12 "</optional>" + 13 "<optional>" + 14 "<element name='stone'><data type='nonNegativeInteger'/></element>" + 15 "</optional>" + 16 "<optional>" + 17 "<element name='metal'><data type='nonNegativeInteger'/></element>" + 18 "</optional>"; 6 "<a:help>Specifies the loot credited when this entity is killed.</a:help>" + 7 "<a:example>" + 8 "<xp>35</xp>" + 9 "<metal>10</metal>" + 10 "</a:example>" + 11 Loot.prototype.ResourcesSchema; 19 12 20 13 Loot.prototype.Serialize = null; // we have no dynamic state to save 21 14 … … Loot.prototype.GetXp = function() 26 19 27 20 Loot.prototype.GetResources = function() 28 21 { 29 return { 30 "food": +(this.template.food || 0), 31 "wood": +(this.template.wood || 0), 32 "metal": +(this.template.metal || 0), 33 "stone": +(this.template.stone || 0) 34 }; 22 let ret = {}; 23 for (let res of Resources.GetCodes()) 24 ret[res] = +(this.template[res] || 0); 25 26 return ret; 35 27 }; 36 28 37 29 Engine.RegisterComponentType(IID_Loot, "Loot", Loot); -
binaries/data/mods/public/simulation/components/Player.js
diff --git a/binaries/data/mods/public/simulation/components/Player.js b/binaries/data/mods/public/simulation/components/Player.js index cb137dd..51236ce 100644
a b Player.prototype.Init = function() 18 18 this.popBonuses = 0; // sum of population bonuses of player's entities 19 19 this.maxPop = 300; // maximum population 20 20 this.trainingBlocked = false; // indicates whether any training queue is currently blocked 21 this.resourceCount = { 22 "food": 300, 23 "wood": 300, 24 "metal": 300, 25 "stone": 300 26 }; 27 // goods for next trade-route and its proba in % (the sum of probas must be 100) 28 this.tradingGoods = [ 29 { "goods": "wood", "proba": 30 }, 30 { "goods": "stone", "proba": 35 }, 31 { "goods": "metal", "proba": 35 }, 32 ]; 21 this.resourceCount = {}; 22 this.tradingGoods = []; // goods for next trade-route and its proba in % (the sum of probas must be 100) 33 23 this.team = -1; // team number of the player, players on the same team will always have ally diplomatic status - also this is useful for team emblems, scoring, etc. 34 24 this.teamsLocked = false; 35 25 this.state = "active"; // game state - one of "active", "defeated", "won" … … Player.prototype.Init = function() 44 34 this.cheatsEnabled = false; 45 35 this.cheatTimeMultiplier = 1; 46 36 this.heroes = []; 47 this.resourceNames = { 48 "food": markForTranslation("Food"), 49 "wood": markForTranslation("Wood"), 50 "metal": markForTranslation("Metal"), 51 "stone": markForTranslation("Stone"), 52 }; 37 this.resourceNames = {}; 53 38 this.disabledTemplates = {}; 54 39 this.disabledTechnologies = {}; 55 40 this.startingTechnologies = []; 41 42 // Initial resources and trading goods probability in steps of 5 43 let resCodes = Resources.GetCodes(); 44 let quotient = Math.floor(20 / resCodes.length); 45 let remainder = 20 % resCodes.length; 46 for (let i in resCodes) 47 { 48 let res = resCodes[i]; 49 this.resourceCount[res] = 300; 50 this.resourceNames[res] = Resources.GetResource(res).name; 51 this.tradingGoods.push({ 52 "goods": res, 53 "proba": 5 * (quotient + (+i < remainder ? 1 : 0)) 54 }); 55 } 56 56 }; 57 57 58 58 Player.prototype.SetPlayerID = function(id) … … Player.prototype.UnBlockTraining = function() 197 197 198 198 Player.prototype.SetResourceCounts = function(resources) 199 199 { 200 if (resources.food !== undefined) 201 this.resourceCount.food = resources.food; 202 if (resources.wood !== undefined) 203 this.resourceCount.wood = resources.wood; 204 if (resources.stone !== undefined) 205 this.resourceCount.stone = resources.stone; 206 if (resources.metal !== undefined) 207 this.resourceCount.metal = resources.metal; 200 for (let res in resources) 201 if (this.resourceCount[res]) 202 this.resourceCount[res] = resources[res]; 208 203 }; 209 204 210 205 Player.prototype.GetResourceCounts = function() … … Player.prototype.SubtractResourcesOrNotify = function(amounts) 297 292 298 293 // Subtract the resources 299 294 for (var type in amounts) 300 this.resourceCount[type] -= amounts[type]; 295 if (this.resourceCount[type]) 296 this.resourceCount[type] -= amounts[type]; 301 297 302 298 return true; 303 299 }; … … Player.prototype.SetTradingGoods = function(tradingGoods) 346 342 if (sumProba != 100) // consistency check 347 343 { 348 344 error("Player.js SetTradingGoods: " + uneval(tradingGoods)); 349 tradingGoods = { "food": 20, "wood":20, "stone":30, "metal":30 }; 345 let first = true; 346 for (let res of Resources.GetCodes()) 347 if (first) 348 { 349 tradingGoods[res] = 100; 350 first = false; 351 } 352 else 353 tradingGoods[res] = 0; 350 354 } 351 355 352 356 this.tradingGoods = []; -
binaries/data/mods/public/simulation/components/ProductionQueue.js
diff --git a/binaries/data/mods/public/simulation/components/ProductionQueue.js b/binaries/data/mods/public/simulation/components/ProductionQueue.js index 6c72202..447b0ff 100644
a b const MAX_QUEUE_SIZE = 16; 3 3 4 4 function ProductionQueue() {} 5 5 6 ProductionQueue.prototype.ResourceSchema = Resources.BuildSchema("nonNegativeDecimal", [ "time" ]); 7 6 8 ProductionQueue.prototype.Schema = 7 9 "<a:help>Allows the building to train new units and research technologies</a:help>" + 8 10 "<a:example>" + … … ProductionQueue.prototype.Schema = 31 33 "</element>" + 32 34 "</optional>" + 33 35 "<element name='TechCostMultiplier' a:help='Multiplier to modify ressources cost and research time of technologies searched in this building.'>" + 34 "<interleave>" + 35 "<element name='food'><ref name='nonNegativeDecimal'/></element>" + 36 "<element name='wood'><ref name='nonNegativeDecimal'/></element>" + 37 "<element name='stone'><ref name='nonNegativeDecimal'/></element>" + 38 "<element name='metal'><ref name='nonNegativeDecimal'/></element>" + 39 "<element name='time'><ref name='nonNegativeDecimal'/></element>" + 40 "</interleave>" + 36 ProductionQueue.prototype.ResourceSchema + 41 37 "</element>"; 42 38 43 39 ProductionQueue.prototype.Init = function() … … ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadat 260 256 // TODO: there should probably be a limit on the number of queued batches 261 257 // TODO: there should be a way for the GUI to determine whether it's going 262 258 // to be possible to add a batch (based on resource costs and length limits) 263 var cmpPlayer = QueryOwnerInterface(this.entity); 259 let cmpPlayer = QueryOwnerInterface(this.entity); 260 let resCodes = Resources.GetCodes(); 264 261 265 262 if (this.queue.length < MAX_QUEUE_SIZE) 266 263 { … … ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadat 293 290 var buildTime = ApplyValueModificationsToTemplate("Cost/BuildTime", +template.Cost.BuildTime, cmpPlayer.GetPlayerID(), template); 294 291 var time = timeMult * buildTime; 295 292 296 for ( var rin template.Cost.Resources)293 for (let res in template.Cost.Resources) 297 294 { 298 costs[r] = ApplyValueModificationsToTemplate("Cost/Resources/"+r, +template.Cost.Resources[r], cmpPlayer.GetPlayerID(), template); 299 totalCosts[r] = Math.floor(count * costs[r]); 295 let cost = +template.Cost.Resources[res]; 296 if (resCodes.indexOf(res) < 0) 297 continue; 298 costs[res] = ApplyValueModificationsToTemplate("Cost/Resources/"+res, cost, cmpPlayer.GetPlayerID(), template); 299 totalCosts[res] = Math.floor(count * costs[res]); 300 300 } 301 301 302 302 var population = ApplyValueModificationsToTemplate("Cost/Population", +template.Cost.Population, cmpPlayer.GetPlayerID(), template); … … ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadat 341 341 let techCostMultiplier = this.GetTechCostMultiplier(); 342 342 let time = techCostMultiplier.time * template.researchTime * cmpPlayer.GetCheatTimeMultiplier(); 343 343 344 varcost = {};344 let cost = {}; 345 345 for (let res in template.cost) 346 cost[res] = Math.floor(techCostMultiplier[res] * template.cost[res]); 346 { 347 if (resCodes.indexOf(res) < 0) 348 continue; 349 cost[res] = Math.floor((techCostMultiplier[res] ? techCostMultiplier[res] : 1) * template.cost[res]); 350 } 347 351 348 352 // TrySubtractResources should report error to player (they ran out of resources) 349 353 if (!cmpPlayer.TrySubtractResources(cost)) … … ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadat 361 365 "player": cmpPlayer.GetPlayerID(), 362 366 "count": 1, 363 367 "technologyTemplate": templateName, 364 "resources": deepcopy(template.cost), // need to copy to avoid serialization problems368 "resources": cost, 365 369 "productionStarted": false, 366 370 "timeTotal": time*1000, 367 371 "timeRemaining": time*1000, … … ProductionQueue.prototype.RemoveBatch = function(id) 433 437 // Refund the resource cost for this batch 434 438 var totalCosts = {}; 435 439 var cmpStatisticsTracker = QueryPlayerIDInterface(item.player, IID_StatisticsTracker); 436 for each (var r in ["food", "wood", "stone", "metal"])440 for (let r of Resources.GetCodes()) 437 441 { 442 if (!item.resources[r]) 443 continue; 438 444 totalCosts[r] = Math.floor(item.count * item.resources[r]); 439 445 if (cmpStatisticsTracker) 440 446 cmpStatisticsTracker.IncreaseResourceUsedCounter(r, -totalCosts[r]); -
binaries/data/mods/public/simulation/components/ResourceDropsite.js
diff --git a/binaries/data/mods/public/simulation/components/ResourceDropsite.js b/binaries/data/mods/public/simulation/components/ResourceDropsite.js index 819807c..a14ddaf 100644
a b 1 1 function ResourceDropsite() {} 2 2 3 ResourceDropsite.prototype.ResourceChoiceSchema = Resources.BuildChoicesSchema(); 4 3 5 ResourceDropsite.prototype.Schema = 4 6 "<element name='Types'>" + 5 7 "<list>" + 6 8 "<zeroOrMore>" + 7 "<choice>" + 8 "<value>food</value>" + 9 "<value>wood</value>" + 10 "<value>stone</value>" + 11 "<value>metal</value>" + 12 "</choice>" + 9 ResourceDropsite.prototype.ResourceChoiceSchema + 13 10 "</zeroOrMore>" + 14 11 "</list>" + 15 12 "</element>" + … … ResourceDropsite.prototype.Init = function() 24 21 }; 25 22 26 23 /** 27 * Returns the list of resource types accepted by this dropsite. 24 * Returns the list of resource types accepted by this dropsite, 25 * as defined by it being referred to in the template and the resource being enabled. 28 26 */ 29 27 ResourceDropsite.prototype.GetTypes = function() 30 28 { 31 29 let types = ApplyValueModificationsToEntity("ResourceDropsite/Types", this.template.Types, this.entity); 32 return types ? types.split(/\s+/) : []; 30 let resources = Resources.GetCodes(); 31 return types.split(/\s+/).filter(type => resources.indexOf(type.toLowerCase()) > -1); 33 32 }; 34 33 35 34 /** -
binaries/data/mods/public/simulation/components/ResourceGatherer.js
diff --git a/binaries/data/mods/public/simulation/components/ResourceGatherer.js b/binaries/data/mods/public/simulation/components/ResourceGatherer.js index acd5fbd..52f0b44 100644
a b 1 1 function ResourceGatherer() {} 2 2 3 ResourceGatherer.prototype.ResourcesSchema = Resources.BuildSchema("positiveDecimal", [ "treasure" ], true); 4 ResourceGatherer.prototype.CapacitiesSchema = Resources.BuildSchema("positiveDecimal"); 5 3 6 ResourceGatherer.prototype.Schema = 4 7 "<a:help>Lets the unit gather resources from entities that have the ResourceSupply component.</a:help>" + 5 8 "<a:example>" + … … ResourceGatherer.prototype.Schema = 25 28 "<ref name='positiveDecimal'/>" + 26 29 "</element>" + 27 30 "<element name='Rates' a:help='Per-resource-type gather rate multipliers. If a resource type is not specified then it cannot be gathered by this unit'>" + 28 "<interleave>" + 29 "<optional><element name='food' a:help='Food gather rate (may be overridden by \"food.*\" subtypes)'><ref name='positiveDecimal'/></element></optional>" + 30 "<optional><element name='wood' a:help='Wood gather rate'><ref name='positiveDecimal'/></element></optional>" + 31 "<optional><element name='stone' a:help='Stone gather rate'><ref name='positiveDecimal'/></element></optional>" + 32 "<optional><element name='metal' a:help='Metal gather rate'><ref name='positiveDecimal'/></element></optional>" + 33 "<optional><element name='treasure' a:help='Treasure gather rate (only presense on value makes sense, size is only used to determine the delay before gathering, so it should be set to 1)'><ref name='positiveDecimal'/></element></optional>" + 34 "<optional><element name='food.fish' a:help='Fish gather rate (overrides \"food\")'><ref name='positiveDecimal'/></element></optional>" + 35 "<optional><element name='food.fruit' a:help='Fruit gather rate (overrides \"food\")'><ref name='positiveDecimal'/></element></optional>" + 36 "<optional><element name='food.grain' a:help='Grain gather rate (overrides \"food\")'><ref name='positiveDecimal'/></element></optional>" + 37 "<optional><element name='food.meat' a:help='Meat gather rate (overrides \"food\")'><ref name='positiveDecimal'/></element></optional>" + 38 "<optional><element name='food.milk' a:help='Milk gather rate (overrides \"food\")'><ref name='positiveDecimal'/></element></optional>" + 39 "<optional><element name='wood.tree' a:help='Tree gather rate (overrides \"wood\")'><ref name='positiveDecimal'/></element></optional>" + 40 "<optional><element name='wood.ruins' a:help='Tree gather rate (overrides \"wood\")'><ref name='positiveDecimal'/></element></optional>" + 41 "<optional><element name='stone.rock' a:help='Rock gather rate (overrides \"stone\")'><ref name='positiveDecimal'/></element></optional>" + 42 "<optional><element name='stone.ruins' a:help='Rock gather rate (overrides \"stone\")'><ref name='positiveDecimal'/></element></optional>" + 43 "<optional><element name='metal.ore' a:help='Ore gather rate (overrides \"metal\")'><ref name='positiveDecimal'/></element></optional>" + 44 "<optional><element name='treasure.food' a:help='Food treasure gather rate (overrides \"treasure\")'><ref name='positiveDecimal'/></element></optional>" + 45 "<optional><element name='treasure.wood' a:help='Wood treasure gather rate (overrides \"treasure\")'><ref name='positiveDecimal'/></element></optional>" + 46 "<optional><element name='treasure.stone' a:help='Stone treasure gather rate (overrides \"treasure\")'><ref name='positiveDecimal'/></element></optional>" + 47 "<optional><element name='treasure.metal' a:help='Metal treasure gather rate (overrides \"treasure\")'><ref name='positiveDecimal'/></element></optional>" + 48 "</interleave>" + 31 ResourceGatherer.prototype.ResourcesSchema + 49 32 "</element>" + 50 33 "<element name='Capacities' a:help='Per-resource-type maximum carrying capacity'>" + 51 "<interleave>" + 52 "<element name='food' a:help='Food capacity'><ref name='positiveDecimal'/></element>" + 53 "<element name='wood' a:help='Wood capacity'><ref name='positiveDecimal'/></element>" + 54 "<element name='stone' a:help='Stone capacity'><ref name='positiveDecimal'/></element>" + 55 "<element name='metal' a:help='Metal capacity'><ref name='positiveDecimal'/></element>" + 56 "</interleave>" + 34 ResourceGatherer.prototype.CapacitiesSchema + 57 35 "</element>"; 58 36 59 37 ResourceGatherer.prototype.Init = function() … … ResourceGatherer.prototype.RecalculateGatherRatesAndCapacities = function() 137 115 this.rates = {}; 138 116 for (let r in this.template.Rates) 139 117 { 118 let type = r.split("."); 119 let res = Resources.GetResource(type[0]); 120 121 if (!res && type[0] !== "treasure" || (type.length > 1 && res.subtypes.indexOf(type[1]) < 0)) 122 continue; 123 140 124 let rate = ApplyValueModificationsToEntity("ResourceGatherer/Rates/" + r, +this.template.Rates[r], this.entity); 141 125 this.rates[r] = rate * this.baseSpeed; 142 126 } … … ResourceGatherer.prototype.GetRange = function() 174 158 175 159 /** 176 160 * Try to gather treasure 177 * @return 'true' if treasure is successfully gathered and 'false' i n the other case161 * @return 'true' if treasure is successfully gathered and 'false' if not 178 162 */ 179 163 ResourceGatherer.prototype.TryInstantGather = function(target) 180 164 { -
binaries/data/mods/public/simulation/components/ResourceSupply.js
diff --git a/binaries/data/mods/public/simulation/components/ResourceSupply.js b/binaries/data/mods/public/simulation/components/ResourceSupply.js index 04e95da..7cc580b 100644
a b 1 1 function ResourceSupply() {} 2 2 3 ResourceSupply.prototype.ResourceChoiceSchema = Resources.BuildChoicesSchema(true, true); 4 3 5 ResourceSupply.prototype.Schema = 4 6 "<a:help>Provides a supply of one particular type of resource.</a:help>" + 5 7 "<a:example>" + … … ResourceSupply.prototype.Schema = 12 14 "<element name='Amount' a:help='Amount of resources available from this entity'>" + 13 15 "<choice><data type='nonNegativeInteger'/><value>Infinity</value></choice>" + 14 16 "</element>" + 15 "<element name='Type' a:help='Type of resources'>" + 16 "<choice>" + 17 "<value>wood.tree</value>" + 18 "<value>wood.ruins</value>" + 19 "<value>stone.rock</value>" + 20 "<value>stone.ruins</value>" + 21 "<value>metal.ore</value>" + 22 "<value>food.fish</value>" + 23 "<value>food.fruit</value>" + 24 "<value>food.grain</value>" + 25 "<value>food.meat</value>" + 26 "<value>food.milk</value>" + 27 "<value>treasure.wood</value>" + 28 "<value>treasure.stone</value>" + 29 "<value>treasure.metal</value>" + 30 "<value>treasure.food</value>" + 31 "</choice>" + 17 "<element name='Type' a:help='Type and Subtype of resource available from this entity'>" + 18 ResourceSupply.prototype.ResourceChoiceSchema + 32 19 "</element>" + 33 20 "<element name='MaxGatherers' a:help='Amount of gatherers who can gather resources from this entity at the same time'>" + 34 21 "<data type='nonNegativeInteger'/>" + … … ResourceSupply.prototype.Init = function() 45 32 this.amount = this.GetMaxAmount(); 46 33 47 34 this.gatherers = []; // list of IDs for each players 48 varcmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager); // system component so that's safe.49 varnumPlayers = cmpPlayerManager.GetNumPlayers();50 for ( vari = 0; i <= numPlayers; ++i) // use "<=" because we want Gaia too.35 let cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager); // system component so that's safe. 36 let numPlayers = cmpPlayerManager.GetNumPlayers(); 37 for (let i = 0; i <= numPlayers; ++i) // use "<=" because we want Gaia too. 51 38 this.gatherers.push([]); 52 39 53 40 this.infinite = !isFinite(+this.template.Amount); 54 41 55 [this.type,this.subType] = this.template.Type.split('.'); 56 this.cachedType = { "generic" : this.type, "specific" : this.subType }; 42 [this.type, this.subtype] = this.template.Type.split('.'); 43 let resData = Resources.GetResource(this.type); 44 if (this.type === "treasure") 45 resData = { "subtypes": Resources.GetCodes() }; 46 47 // Remove entity from gameworld if the resource supplied by this entity is disabled or not valid. 48 if (!resData || resData.subtypes.indexOf(this.subtype) === -1) 49 Engine.DestroyEntity(this.entity); 57 50 51 this.cachedType = { "generic" : this.type, "specific" : this.subtype }; 58 52 }; 59 53 60 54 ResourceSupply.prototype.IsInfinite = function() -
binaries/data/mods/public/simulation/components/ResourceTrickle.js
diff --git a/binaries/data/mods/public/simulation/components/ResourceTrickle.js b/binaries/data/mods/public/simulation/components/ResourceTrickle.js index 5c554e7..7bed918 100644
a b 1 1 function ResourceTrickle() {} 2 2 3 ResourceTrickle.prototype.ResourcesSchema = Resources.BuildSchema("nonNegativeDecimal"); 4 3 5 ResourceTrickle.prototype.Schema = 4 6 "<a:help>Controls the resource trickle ability of the unit.</a:help>" + 5 7 "<element name='Rates' a:help='Trickle Rates'>" + 6 "<interleave>" + 7 "<optional>" + 8 "<element name='food' a:help='Food given to the player every interval'>" + 9 "<ref name='nonNegativeDecimal'/>" + 10 "</element>" + 11 "</optional>" + 12 "<optional>" + 13 "<element name='wood' a:help='Wood given to the player every interval'>" + 14 "<ref name='nonNegativeDecimal'/>" + 15 "</element>" + 16 "</optional>" + 17 "<optional>" + 18 "<element name='stone' a:help='Stone given to the player every interval'>" + 19 "<ref name='nonNegativeDecimal'/>" + 20 "</element>" + 21 "</optional>" + 22 "<optional>" + 23 "<element name='metal' a:help='Metal given to the player every interval'>" + 24 "<ref name='nonNegativeDecimal'/>" + 25 "</element>" + 26 "</optional>" + 27 "</interleave>" + 8 ResourceTrickle.prototype.ResourcesSchema + 28 9 "</element>" + 29 10 "<element name='Interval' a:help='Number of miliseconds must pass for the player to gain the next trickle.'>" + 30 11 "<ref name='nonNegativeDecimal'/>" + … … ResourceTrickle.prototype.GetTimer = function() 45 26 46 27 ResourceTrickle.prototype.GetRates = function() 47 28 { 48 var rates = {}; 49 for (var resource in this.template.Rates) 29 let rates = {}; 30 let resCodes = Resources.GetCodes(); 31 for (let resource in this.template.Rates) 32 { 33 if (resCodes.indexOf(resource) < 0) 34 continue; 50 35 rates[resource] = ApplyValueModificationsToEntity("ResourceTrickle/Rates/"+resource, +this.template.Rates[resource], this.entity); 36 } 51 37 52 38 return rates; 53 39 }; … … ResourceTrickle.prototype.GetRates = function() 55 41 // Do the actual work here 56 42 ResourceTrickle.prototype.Trickle = function(data, lateness) 57 43 { 58 var cmpPlayer = QueryOwnerInterface(this.entity); 59 if (!cmpPlayer) 60 return; 61 62 var rates = this.GetRates(); 63 for (var resource in rates) 64 cmpPlayer.AddResource(resource, rates[resource]); 44 let cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); 45 if (cmpPlayer) 46 cmpPlayer.AddResources(this.GetRates()); 65 47 }; 66 48 67 49 Engine.RegisterComponentType(IID_ResourceTrickle, "ResourceTrickle", ResourceTrickle); -
binaries/data/mods/public/simulation/components/StatisticsTracker.js
diff --git a/binaries/data/mods/public/simulation/components/StatisticsTracker.js b/binaries/data/mods/public/simulation/components/StatisticsTracker.js index 3bc1f79..482502d 100644
a b StatisticsTracker.prototype.Init = function() 105 105 this.buildingsCapturedValue = 0; 106 106 107 107 this.resourcesGathered = { 108 "food": 0,109 "wood": 0,110 "metal": 0,111 "stone": 0,112 108 "vegetarianFood": 0 113 109 }; 114 this.resourcesUsed = { 115 "food": 0, 116 "wood": 0, 117 "metal": 0, 118 "stone": 0 119 }; 120 this.resourcesSold = { 121 "food": 0, 122 "wood": 0, 123 "metal": 0, 124 "stone": 0 125 }; 126 this.resourcesBought = { 127 "food": 0, 128 "wood": 0, 129 "metal": 0, 130 "stone": 0 131 }; 110 this.resourcesUsed = {}; 111 this.resourcesSold = {}; 112 this.resourcesBought = {}; 113 for (let res of Resources.GetCodes()) 114 { 115 this.resourcesGathered[res] = 0; 116 this.resourcesUsed[res] = 0; 117 this.resourcesSold[res] = 0; 118 this.resourcesBought[res] = 0; 119 } 132 120 133 121 this.tributesSent = 0; 134 122 this.tributesReceived = 0; … … StatisticsTracker.prototype.IncreaseResourceGatheredCounter = function(type, amo 347 335 */ 348 336 StatisticsTracker.prototype.IncreaseResourceUsedCounter = function(type, amount) 349 337 { 350 this.resourcesUsed[type] += amount; 338 if (typeof this.resourcesUsed[type] === "number") 339 this.resourcesUsed[type] += amount; 351 340 }; 352 341 353 342 StatisticsTracker.prototype.IncreaseTreasuresCollectedCounter = function() -
binaries/data/mods/public/simulation/components/Trader.js
diff --git a/binaries/data/mods/public/simulation/components/Trader.js b/binaries/data/mods/public/simulation/components/Trader.js index 735778d..771a814 100644
a b 4 4 // Additional gain for ships for each garrisoned trader, in percents 5 5 const GARRISONED_TRADER_ADDITION = 20; 6 6 7 // Array of resource names8 const RESOURCES = ["food", "wood", "stone", "metal"];9 10 7 function Trader() {} 11 8 12 9 Trader.prototype.Schema = -
binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js
diff --git a/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js b/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js index 6ae026e..7e7f2d2 100644
a b Engine.LoadComponentScript("interfaces/Upgrade.js"); 33 33 Engine.LoadComponentScript("interfaces/BuildingAI.js"); 34 34 Engine.LoadComponentScript("GuiInterface.js"); 35 35 36 Resources = { 37 "GetCodes": function() { return [ "food", "metal", "stone", "wood" ] }, 38 "GetNames": function() { return { "food": "Food", "metal": "Metal", "stone": "Stone", "wood": "Wood" } }, 39 "GetResource": function() { return {}; }, 40 }; 41 36 42 var cmp = ConstructComponent(SYSTEM_ENTITY, "GuiInterface"); 37 43 38 44 … … TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulationState(), { 330 336 circularMap: false, 331 337 timeElapsed: 0, 332 338 gameType: "conquest", 333 barterPrices: {buy: {food: 150}, sell: {food: 25}} 339 barterPrices: {buy: {food: 150}, sell: {food: 25}}, 340 resources: { 341 codes: [ "food", "metal", "stone", "wood" ], 342 names: { 343 "food": "Food", 344 "metal": "Metal", 345 "stone": "Stone", 346 "wood": "Wood", 347 }, 348 aiInfluenceGroups: { 349 "food": 0, 350 "metal": 0, 351 "stone": 0, 352 "wood": 0, 353 } 354 }, 334 355 }); 335 356 336 357 TS_ASSERT_UNEVAL_EQUALS(cmp.GetExtendedSimulationState(), { … … TS_ASSERT_UNEVAL_EQUALS(cmp.GetExtendedSimulationState(), { 449 470 circularMap: false, 450 471 timeElapsed: 0, 451 472 gameType: "conquest", 452 barterPrices: {buy: {food: 150}, sell: {food: 25}} 473 barterPrices: {buy: {food: 150}, sell: {food: 25}}, 474 resources: { 475 codes: [ "food", "metal", "stone", "wood" ], 476 names: { 477 "food": "Food", 478 "metal": "Metal", 479 "stone": "Stone", 480 "wood": "Wood", 481 }, 482 aiInfluenceGroups: { 483 "food": 0, 484 "metal": 0, 485 "stone": 0, 486 "wood": 0, 487 } 488 }, 453 489 }); 454 490 455 491 -
binaries/data/mods/public/simulation/components/tests/test_Player.js
diff --git a/binaries/data/mods/public/simulation/components/tests/test_Player.js b/binaries/data/mods/public/simulation/components/tests/test_Player.js index 4191a68..7cba52a 100644
a b Engine.LoadComponentScript("Timer.js") 9 9 ConstructComponent(SYSTEM_ENTITY, "EndGameManager"); 10 10 ConstructComponent(SYSTEM_ENTITY, "Timer"); 11 11 12 Resources = { 13 "GetCodes": function() { return [ "food", "metal", "stone", "wood" ] }, 14 "GetResource": function() { return {}; }, 15 }; 16 12 17 var cmpPlayer = ConstructComponent(10, "Player"); 13 18 14 19 TS_ASSERT_EQUALS(cmpPlayer.GetPopulationCount(), 0); -
new file inaries/data/mods/public/simulation/data/resources/food.json
diff --git a/binaries/data/mods/public/simulation/data/resources/food.json b/binaries/data/mods/public/simulation/data/resources/food.json new file mode 100644 index 0000000..67c85e7
- + 1 { 2 "code": "food", 3 "name": "Food", 4 "subtypes": { 5 "fish": "Fish", 6 "fruit": "Fruit", 7 "grain": "Grain", 8 "meat": "Meat", 9 "milk": "Milk" 10 }, 11 "truePrice": 100, 12 "aiAnalysisInfluenceGroup": 0, 13 "enabled": true 14 } -
new file inaries/data/mods/public/simulation/data/resources/metal.json
diff --git a/binaries/data/mods/public/simulation/data/resources/metal.json b/binaries/data/mods/public/simulation/data/resources/metal.json new file mode 100644 index 0000000..2a8b590
- + 1 { 2 "code": "metal", 3 "name": "Metal", 4 "subtypes": { 5 "ore": "Ore" 6 }, 7 "truePrice": 100, 8 "aiAnalysisInfluenceGroup": 2, 9 "enabled": true 10 } -
new file inaries/data/mods/public/simulation/data/resources/stone.json
diff --git a/binaries/data/mods/public/simulation/data/resources/stone.json b/binaries/data/mods/public/simulation/data/resources/stone.json new file mode 100644 index 0000000..034783e
- + 1 { 2 "code": "stone", 3 "name": "Stone", 4 "subtypes": { 5 "rock": "Rock", 6 "ruins": "Ruins" 7 }, 8 "truePrice": 100, 9 "aiAnalysisInfluenceGroup": 2, 10 "enabled": true 11 } -
new file inaries/data/mods/public/simulation/data/resources/wood.json
diff --git a/binaries/data/mods/public/simulation/data/resources/wood.json b/binaries/data/mods/public/simulation/data/resources/wood.json new file mode 100644 index 0000000..9e5a904
- + 1 { 2 "code": "wood", 3 "name": "Wood", 4 "subtypes": { 5 "tree": "Tree", 6 "ruins": "Ruins" 7 }, 8 "truePrice": 100, 9 "aiAnalysisInfluenceGroup": 1, 10 "enabled": true 11 } -
new file inaries/data/mods/public/simulation/helpers/Resources.js
diff --git a/binaries/data/mods/public/simulation/helpers/Resources.js b/binaries/data/mods/public/simulation/helpers/Resources.js new file mode 100644 index 0000000..af6f747
- + 1 2 Resources = new Resources();