Ticket #3: technology_19-04-12.diff
File technology_19-04-12.diff, 156.3 KB (added by , 12 years ago) |
---|
-
source/simulation2/system/ComponentManager.h
233 233 static int Script_AddLocalEntity(void* cbdata, std::string templateName); 234 234 static void Script_DestroyEntity(void* cbdata, int ent); 235 235 static CScriptVal Script_ReadJSONFile(void* cbdata, std::wstring fileName); 236 static std::vector<std::string> Script_FindAllTechnologyTemplates(void* cbdata); 236 237 237 238 CMessage* ConstructMessage(int mtid, CScriptVal data); 238 239 void SendGlobalMessage(entity_id_t ent, const CMessage& msg) const; -
source/simulation2/system/ComponentManager.cpp
81 81 m_ScriptInterface.RegisterFunction<int, std::string, CComponentManager::Script_AddLocalEntity> ("AddLocalEntity"); 82 82 m_ScriptInterface.RegisterFunction<void, int, CComponentManager::Script_DestroyEntity> ("DestroyEntity"); 83 83 m_ScriptInterface.RegisterFunction<CScriptVal, std::wstring, CComponentManager::Script_ReadJSONFile> ("ReadJSONFile"); 84 m_ScriptInterface.RegisterFunction<std::vector<std::string>, CComponentManager::Script_FindAllTechnologyTemplates> ("FindAllTechnologyTemplates"); 84 85 } 85 86 86 87 // Define MT_*, IID_* as script globals, and store their names … … 944 945 945 946 return componentManager->GetScriptInterface().ReadJSONFile(path).get(); 946 947 } 948 949 static Status AddToTechnologyTemplates(const VfsPath& pathname, const FileInfo& UNUSED(fileInfo), const uintptr_t cbData) 950 { 951 std::vector<std::string>& templates = *(std::vector<std::string>*)cbData; 952 953 // Strip the .json extension 954 VfsPath pathstem = pathname.ChangeExtension(L""); 955 // Strip the root from the path 956 std::wstring name = pathstem.string().substr(ARRAY_SIZE("simulation/data/technologies/")-1); 957 958 templates.push_back(std::string(name.begin(), name.end())); 959 return INFO::OK; 960 } 961 962 std::vector<std::string> CComponentManager::Script_FindAllTechnologyTemplates(void* cbdata) 963 { 964 std::vector<std::string> templates; 965 966 Status ok; 967 968 // Find all the technology template files 969 ok = vfs::ForEachFile(g_VFS, "simulation/data/technologies/", AddToTechnologyTemplates, (uintptr_t)&templates, L"*.json", vfs::DIR_RECURSIVE); 970 WARN_IF_ERR(ok); 971 972 return templates; 973 } -
source/simulation2/Simulation2.cpp
125 125 LOAD_SCRIPTED_COMPONENT("GuiInterface"); 126 126 LOAD_SCRIPTED_COMPONENT("PlayerManager"); 127 127 LOAD_SCRIPTED_COMPONENT("Timer"); 128 LOAD_SCRIPTED_COMPONENT("TechnologyTemplateManager"); 128 129 129 130 #undef LOAD_SCRIPTED_COMPONENT 130 131 } -
binaries/data/mods/internal/simulation/templates/campaigns/campaign_religious_test.xml
20 20 <Radius>100</Radius> 21 21 <Weight>65536</Weight> 22 22 </TerritoryInfluence> 23 < TrainingQueue disable=""/>23 <ProductionQueue disable=""/> 24 24 <VisualActor> 25 25 <Actor>structures/hellenes/temple_new.xml</Actor> 26 26 </VisualActor> -
binaries/data/mods/internal/simulation/templates/campaigns/campaign_city_test.xml
35 35 <Radius>300</Radius> 36 36 <Weight>35000</Weight> 37 37 </TerritoryInfluence> 38 < TrainingQueue>38 <ProductionQueue> 39 39 <Entities datatype="tokens"> 40 40 -units/{civ}_support_female_citizen 41 41 campaigns/army_mace_hero_alexander 42 42 campaigns/army_mace_standard 43 43 units/{civ}_support_trader 44 44 </Entities> 45 </ TrainingQueue>45 </ProductionQueue> 46 46 <VisualActor> 47 47 <Actor>campaigns/structures/hellenes/settlement_curtainwall.xml</Actor> 48 48 </VisualActor> -
binaries/data/mods/internal/simulation/templates/campaigns/campaign_city_minor_test.xml
35 35 <Radius>150</Radius> 36 36 <Weight>35000</Weight> 37 37 </TerritoryInfluence> 38 < TrainingQueue>38 <ProductionQueue> 39 39 <Entities datatype="tokens"> 40 40 -units/{civ}_support_female_citizen 41 41 campaigns/army_mace_hero_alexander 42 42 campaigns/army_mace_standard 43 43 </Entities> 44 </ TrainingQueue>44 </ProductionQueue> 45 45 <VisualActor> 46 46 <Actor>campaigns/structures/hellenes/settlement_curtainwall.xml</Actor> 47 47 </VisualActor> -
binaries/data/mods/internal/simulation/templates/structures/mace_corral.xml
18 18 <Obstruction> 19 19 <Static width="14.0" depth="14.0"/> 20 20 </Obstruction> 21 < TrainingQueue>21 <ProductionQueue> 22 22 <Entities datatype="tokens"> 23 23 gaia/fauna_goat 24 24 </Entities> 25 </ TrainingQueue>25 </ProductionQueue> 26 26 <VisualActor> 27 27 <Actor>structures/hellenes/corral.xml</Actor> 28 28 <FoundationActor>structures/fndn_3x3.xml</FoundationActor> -
binaries/data/mods/internal/simulation/templates/structures/mace_barracks.xml
15 15 <SpecificName>Stratēgeîon</SpecificName> 16 16 <History>The Stratigeion was the main military headquarters, where important decisions were taken and plans for battles discussed by the Hellene Generals, or "Strategoi".</History> 17 17 </Identity> 18 < TrainingQueue>18 <ProductionQueue> 19 19 <Entities datatype="tokens"> 20 20 units/mace_infantry_spearman_b 21 21 units/mace_infantry_javelinist_b … … 24 24 units/mace_cavalry_spearman_b 25 25 units/mace_cavalry_javelinist_b 26 26 </Entities> 27 </ TrainingQueue>27 </ProductionQueue> 28 28 <VisualActor> 29 29 <Actor>structures/hellenes/barracks.xml</Actor> 30 30 </VisualActor> -
binaries/data/mods/internal/simulation/templates/structures/spart_corral.xml
18 18 <Obstruction> 19 19 <Static width="14.0" depth="14.0"/> 20 20 </Obstruction> 21 < TrainingQueue>21 <ProductionQueue> 22 22 <Entities datatype="tokens"> 23 23 gaia/fauna_goat 24 24 </Entities> 25 </ TrainingQueue>25 </ProductionQueue> 26 26 <VisualActor> 27 27 <Actor>structures/hellenes/corral.xml</Actor> 28 28 <FoundationActor>structures/fndn_3x3.xml</FoundationActor> -
binaries/data/mods/internal/simulation/templates/structures/mace_fortress.xml
19 19 <Obstruction> 20 20 <Static width="24.0" depth="26.0"/> 21 21 </Obstruction> 22 < TrainingQueue>22 <ProductionQueue> 23 23 <Entities datatype="tokens"> 24 24 units/mace_hero_philip 25 25 units/mace_hero_alexander … … 30 30 units/mace_mechanical_siege_lithobolos 31 31 units/mace_mechanical_siege_tower 32 32 </Entities> 33 </ TrainingQueue>33 </ProductionQueue> 34 34 <VisualActor> 35 35 <Actor>structures/hellenes/fortress_new.xml</Actor> 36 36 </VisualActor> -
binaries/data/mods/internal/simulation/templates/structures/spart_barracks.xml
15 15 <SpecificName>Stratēgeîon</SpecificName> 16 16 <History>The Stratigeion was the main military headquarters, where important decisions were taken and plans for battles discussed by the Hellene Generals, or "Strategoi".</History> 17 17 </Identity> 18 < TrainingQueue>18 <ProductionQueue> 19 19 <Entities datatype="tokens"> 20 20 units/spart_infantry_spearman_b 21 21 units/spart_champion_infantry_sword 22 22 units/spart_infantry_javelinist_b 23 23 units/spart_cavalry_javelinist_b 24 24 </Entities> 25 </ TrainingQueue>25 </ProductionQueue> 26 26 <VisualActor> 27 27 <Actor>structures/hellenes/barracks.xml</Actor> 28 28 </VisualActor> -
binaries/data/mods/internal/simulation/templates/structures/spart_syssiton.xml
33 33 <death>attack/destruction/building_collapse_large.xml</death> 34 34 </SoundGroups> 35 35 </Sound> 36 < TrainingQueue>36 <ProductionQueue> 37 37 <Entities datatype="tokens"> 38 38 units/hele_hero_leonidas 39 39 units/spart_champion_infantry_spear 40 40 </Entities> 41 </ TrainingQueue>41 </ProductionQueue> 42 42 <VisualActor> 43 43 <Actor>structures/hellenes/gymnasion.xml</Actor> 44 44 <FoundationActor>structures/fndn_6x6.xml</FoundationActor> -
binaries/data/mods/internal/simulation/templates/structures/spart_fortress.xml
19 19 <Obstruction> 20 20 <Static width="24.0" depth="26.0"/> 21 21 </Obstruction> 22 < TrainingQueue>22 <ProductionQueue> 23 23 <Entities datatype="tokens"> 24 24 units/spart_mechanical_siege_ram 25 25 </Entities> 26 </ TrainingQueue>26 </ProductionQueue> 27 27 <VisualActor> 28 28 <Actor>structures/hellenes/fortress_new.xml</Actor> 29 29 </VisualActor> -
binaries/data/mods/internal/simulation/templates/structures/mace_civil_centre.xml
11 11 <SpecificName>Agorā́</SpecificName> 12 12 <History>The most important place in most Classical Greek poleis, the Agora served many purposes; it was a place for public speeches and was the stage for civic life and commercial interests.</History> 13 13 </Identity> 14 < TrainingQueue>14 <ProductionQueue> 15 15 <Entities datatype="tokens"> 16 16 units/mace_infantry_spearman_b 17 17 units/mace_infantry_javelinist_b 18 18 units/mace_cavalry_spearman_b 19 19 </Entities> 20 </ TrainingQueue>20 </ProductionQueue> 21 21 <VisualActor> 22 22 <Actor>structures/hellenes/civic_centre_new.xml</Actor> 23 23 </VisualActor> -
binaries/data/mods/internal/simulation/templates/structures/mace_dock.xml
11 11 <SpecificName>Limḗn</SpecificName> 12 12 <History>Greece is a sea country, which is why some of the greatest Hellenic and Hellenistic cities like Ephesus, Corinth, Alexandria and Antioch were built by the sea. It should also be noted that all colonies during the Great Colonisation were thriving port centres, which traded with the local population.</History> 13 13 </Identity> 14 < TrainingQueue>14 <ProductionQueue> 15 15 <Entities datatype="tokens"> 16 16 units/hele_ship_bireme 17 17 units/hele_ship_trireme 18 18 </Entities> 19 </ TrainingQueue>19 </ProductionQueue> 20 20 <VisualActor> 21 21 <Actor>structures/hellenes/dock.xml</Actor> 22 22 </VisualActor> -
binaries/data/mods/internal/simulation/templates/structures/spart_civil_centre.xml
11 11 <SpecificName>Agorā́</SpecificName> 12 12 <History>The most important place in most Classical Greek poleis, the Agora served many purposes; it was a place for public speeches and was the stage for civic life and commercial interests.</History> 13 13 </Identity> 14 < TrainingQueue>14 <ProductionQueue> 15 15 <Entities datatype="tokens"> 16 16 units/spart_infantry_spearman_b 17 17 units/spart_infantry_javelinist_b 18 18 units/spart_cavalry_javelinist_b 19 19 </Entities> 20 </ TrainingQueue>20 </ProductionQueue> 21 21 <VisualActor> 22 22 <Actor>structures/hellenes/civic_centre_new.xml</Actor> 23 23 </VisualActor> -
binaries/data/mods/internal/simulation/templates/structures/spart_gerousia.xml
34 34 <death>attack/destruction/building_collapse_large.xml</death> 35 35 </SoundGroups> 36 36 </Sound> 37 < TrainingQueue>37 <ProductionQueue> 38 38 <Entities datatype="tokens"> 39 39 units/hele_hero_leonidas 40 40 </Entities> 41 </ TrainingQueue>41 </ProductionQueue> 42 42 <VisualActor> 43 43 <Actor>structures/hellenes/tholos.xml</Actor> 44 44 </VisualActor> -
binaries/data/mods/internal/simulation/templates/structures/spart_dock.xml
11 11 <SpecificName>Limḗn</SpecificName> 12 12 <History>Greece is a sea country, which is why some of the greatest Hellenic and Hellenistic cities like Ephesus, Corinth, Alexandria and Antioch were built by the sea. It should also be noted that all colonies during the Great Colonisation were thriving port centres, which traded with the local population.</History> 13 13 </Identity> 14 < TrainingQueue>14 <ProductionQueue> 15 15 <Entities datatype="tokens"> 16 16 units/spart_ship_bireme 17 17 units/spart_ship_trireme 18 18 </Entities> 19 </ TrainingQueue>19 </ProductionQueue> 20 20 <VisualActor> 21 21 <Actor>structures/hellenes/dock.xml</Actor> 22 22 </VisualActor> -
binaries/data/mods/public/gui/session/session.xml
727 727 </object> 728 728 729 729 <object name="unitResearchPanel" 730 style="TranslucentPanelThinBorder" 731 size="0 100%-56 100% 100%" 732 type="text" 730 size="14 100%-56 100% 100%" 733 731 > 734 732 <object size="0 0 100% 100%"> 733 <repeat count="8"> 734 <object name="unitResearchButton[n]" hidden="true" style="iconButton" type="button" size="0 0 46 46" tooltip_style="sessionToolTipBottom"> 735 <object name="unitResearchIcon[n]" type="image" ghost="true" size="3 3 43 43"/> 736 </object> 737 </repeat> 738 </object> 735 739 [research commands] 736 740 </object> 737 741 -
binaries/data/mods/public/gui/session/input.js
764 764 case "hotkeyup": 765 765 if (ev.hotkey == "session.batchtrain") 766 766 { 767 flushTraining QueueBatch();767 flushTrainingBatch(); 768 768 inputState = INPUT_NORMAL; 769 769 } 770 770 break; … … 1202 1202 var batchTrainingCount; 1203 1203 const batchIncrementSize = 5; 1204 1204 1205 function flushTraining QueueBatch()1205 function flushTrainingBatch() 1206 1206 { 1207 1207 Engine.PostNetworkCommand({"type": "train", "entity": batchTrainingEntity, "template": batchTrainingType, "count": batchTrainingCount}); 1208 1208 } 1209 1209 1210 1210 // Called by GUI when user clicks training button 1211 function addT oTrainingQueue(entity, trainEntType)1211 function addTrainingToQueue(entity, trainEntType) 1212 1212 { 1213 1213 if (Engine.HotkeyIsPressed("session.batchtrain")) 1214 1214 { … … 1223 1223 // Otherwise start a new one 1224 1224 else 1225 1225 { 1226 flushTraining QueueBatch();1226 flushTrainingBatch(); 1227 1227 // fall through to create the new batch 1228 1228 } 1229 1229 } … … 1239 1239 } 1240 1240 } 1241 1241 1242 // Called by GUI when user clicks training button 1243 function addResearchToQueue(entity, trainEntType) 1244 { 1245 Engine.PostNetworkCommand({"type": "research", "entity": entity, "template": trainEntType}); 1246 } 1247 1242 1248 // Returns the number of units that will be present in a batch if the user clicks 1243 1249 // the training button with shift down 1244 function getTraining QueueBatchStatus(entity, trainEntType)1250 function getTrainingBatchStatus(entity, trainEntType) 1245 1251 { 1246 1252 if (inputState == INPUT_BATCHTRAINING && batchTrainingEntity == entity && batchTrainingType == trainEntType) 1247 1253 return [batchTrainingCount, batchIncrementSize]; … … 1250 1256 } 1251 1257 1252 1258 // Called by GUI when user clicks production queue item 1253 function removeFrom TrainingQueue(entity, id)1259 function removeFromProductionQueue(entity, id) 1254 1260 { 1255 Engine.PostNetworkCommand({"type": "stop- train", "entity": entity, "id": id});1261 Engine.PostNetworkCommand({"type": "stop-production", "entity": entity, "id": id}); 1256 1262 } 1257 1263 1258 1264 // Called by unit selection buttons -
binaries/data/mods/public/gui/session/unit_commands.js
4 4 const GARRISON = "Garrison"; 5 5 const FORMATION = "Formation"; 6 6 const TRAINING = "Training"; 7 const RESEARCH = "Research"; 7 8 const CONSTRUCTION = "Construction"; 8 9 const COMMAND = "Command"; 9 10 const STANCE = "Stance"; … … 23 24 const BARTER_ACTIONS = ["Sell", "Buy"]; 24 25 25 26 // The number of currently visible buttons (used to optimise showing/hiding) 26 var g_unitPanelButtons = {"Selection": 0, "Queue": 0, "Formation": 0, "Garrison": 0, "Training": 0, " Barter": 0, "Trading": 0, "Construction": 0, "Command": 0, "Stance": 0};27 var g_unitPanelButtons = {"Selection": 0, "Queue": 0, "Formation": 0, "Garrison": 0, "Training": 0, "Research": 0, "Barter": 0, "Trading": 0, "Construction": 0, "Command": 0, "Stance": 0}; 27 28 28 29 // Unit panels are panels with row(s) of buttons 29 30 var g_unitPanels = ["Selection", "Queue", "Formation", "Garrison", "Training", "Barter", "Trading", "Construction", "Research", "Stance", "Command"]; … … 163 164 if (numberOfItems > 24) 164 165 numberOfItems = 24; 165 166 break; 167 168 case RESEARCH: 169 if (numberOfItems > 8) 170 numberOfItems = 8; 171 break; 166 172 167 173 case CONSTRUCTION: 168 174 if (numberOfItems > 24) … … 183 189 for (i = 0; i < numberOfItems; i++) 184 190 { 185 191 var item = items[i]; 186 var entType = ((guiName == "Queue")? item.template : item); 192 193 // If a tech has been researched it leaves an empty slot 194 if (guiName == RESEARCH && !item) 195 { 196 getGUIObjectByName("unit"+guiName+"Button["+i+"]").hidden = true; 197 continue; 198 } 199 200 // Get the entity type and load the template for that type if necessary 201 var entType; 187 202 var template; 188 if (guiName != "Formation" && guiName != "Command" && guiName != "Stance")203 switch (guiName) 189 204 { 190 template = GetTemplateData(entType); 191 if (!template) 192 continue; // ignore attempts to use invalid templates (an error should have been reported already) 205 case QUEUE: 206 // The queue can hold both technologies and units so we need to use the correct code for 207 // loading the templates 208 if (item.unitTemplate) 209 { 210 entType = item.unitTemplate; 211 template = GetTemplateData(entType); 212 } 213 else if (item.technologyTemplate) 214 { 215 entType = item.technologyTemplate; 216 template = GetTechnologyData(entType); 217 } 218 219 if (!template) 220 continue; // ignore attempts to use invalid templates (an error should have been 221 // reported already) 222 break; 223 case RESEARCH: 224 entType = item; 225 template = GetTechnologyData(entType); 226 if (!template) 227 continue; // ignore attempts to use invalid templates (an error should have been 228 // reported already) 229 break; 230 case SELECTION: 231 case GARRISON: 232 case TRAINING: 233 case CONSTRUCTION: 234 entType = item; 235 template = GetTemplateData(entType); 236 if (!template) 237 continue; // ignore attempts to use invalid templates (an error should have been 238 // reported already) 239 break; 193 240 } 194 241 195 242 switch (guiName) … … 233 280 if (template.tooltip) 234 281 tooltip += "\n[font=\"serif-13\"]" + template.tooltip + "[/font]"; 235 282 236 var [batchSize, batchIncrement] = getTraining QueueBatchStatus(unitEntState.id, entType);283 var [batchSize, batchIncrement] = getTrainingBatchStatus(unitEntState.id, entType); 237 284 var trainNum = batchSize ? batchSize+batchIncrement : batchIncrement; 238 285 239 286 tooltip += "\n" + getEntityCost(template); … … 250 297 tooltip += "\n\n[font=\"serif-bold-13\"]Shift-click[/font][font=\"serif-13\"] to train " + trainNum + ".[/font]"; 251 298 252 299 break; 300 301 case RESEARCH: 302 var tooltip = getEntityNameWithGenericType(template); 253 303 304 if (template.tooltip) 305 tooltip += "\n[font=\"serif-13\"]" + template.tooltip + "[/font]"; 306 307 tooltip += "\n" + getEntityCost(template); 308 break; 309 254 310 case CONSTRUCTION: 255 311 var tooltip = getEntityNameWithGenericType(template); 256 312 if (template.tooltip) … … 352 408 } 353 409 else if (template.icon) 354 410 { 355 icon.sprite = "stretched:session/portraits/" + template.icon; 411 var grayscale = ""; 412 button.enabled = true; 413 414 if (template.requiredTechnology && !Engine.GuiInterfaceCall("IsTechnologyResearched", template.requiredTechnology)) 415 { 416 button.enabled = false; 417 var techName = getEntityName(GetTechnologyData(template.requiredTechnology)); 418 button.tooltip += "\nRequires " + techName; 419 grayscale = "grayscale:"; 420 } 421 422 if (guiName == RESEARCH && !Engine.GuiInterfaceCall("CheckTechnologyRequirements", entType)) 423 { 424 button.enabled = false; 425 button.tooltip += "\n" + GetTechnologyData(entType).requirementsTooltip; 426 grayscale = "grayscale:"; 427 } 428 429 icon.sprite = "stretched:" + grayscale + "session/portraits/" + template.icon; 356 430 } 357 431 else 358 432 { … … 537 611 { 538 612 setupUnitPanel("Construction", usedPanels, entState, entState.buildEntities, startBuildingPlacement); 539 613 } 540 541 if (entState. training && entState.training.entities.length)614 615 if (entState.production && entState.production.entities.length) 542 616 { 543 setupUnitPanel("Training", usedPanels, entState, entState. training.entities,544 function (trainEntType) { addT oTrainingQueue(entState.id, trainEntType); } );617 setupUnitPanel("Training", usedPanels, entState, entState.production.entities, 618 function (trainEntType) { addTrainingToQueue(entState.id, trainEntType); } ); 545 619 } 620 621 if (entState.production && entState.production.technologies.length) 622 { 623 setupUnitPanel("Research", usedPanels, entState, entState.production.technologies, 624 function (researchType) { addResearchToQueue(entState.id, researchType); } ); 625 } 546 626 547 if (entState. training && entState.training.queue.length)548 setupUnitPanel("Queue", usedPanels, entState, entState. training.queue,549 function (item) { removeFrom TrainingQueue(entState.id, item.id); } );627 if (entState.production && entState.production.queue.length) 628 setupUnitPanel("Queue", usedPanels, entState, entState.production.queue, 629 function (item) { removeFromProductionQueue(entState.id, item.id); } ); 550 630 551 631 if (entState.trader) 552 632 { -
binaries/data/mods/public/gui/session/session.js
15 15 16 16 // Indicate when one of the current player's training queues is blocked 17 17 // (this is used to support population counter blinking) 18 var g_IsTraining QueueBlocked = false;18 var g_IsTrainingBlocked = false; 19 19 20 20 // Cache EntityStates 21 21 var g_EntityStates = {}; // {id:entState} … … 53 53 return g_TemplateData[templateName]; 54 54 } 55 55 56 // Cache TechnologyData 57 var g_TechnologyData = {}; // {id:template} 58 59 function GetTechnologyData(technologyName) 60 { 61 if (!(technologyName in g_TechnologyData)) 62 { 63 var template = Engine.GuiInterfaceCall("GetTechnologyData", technologyName); 64 g_TechnologyData[technologyName] = template; 65 } 66 67 return g_TechnologyData[technologyName]; 68 } 69 56 70 // Init 57 71 function init(initData, hotloadData) 58 72 { … … 206 220 global.music.updateTimer(); 207 221 208 222 // When training is blocked, flash population (alternates colour every 500msec) 209 if (g_IsTraining QueueBlocked && (Date.now() % 1000) < 500)223 if (g_IsTrainingBlocked && (Date.now() % 1000) < 500) 210 224 getGUIObjectByName("resourcePop").textcolor = POPULATION_ALERT_COLOR; 211 225 else 212 226 getGUIObjectByName("resourcePop").textcolor = DEFAULT_POPULATION_COLOR; … … 257 271 g_Selection.dirty = false; 258 272 g_EntityStates = {}; 259 273 g_TemplateData = {}; 274 g_TechnologyData = {}; 260 275 261 276 var simState = Engine.GuiInterfaceCall("GetSimulationState"); 262 277 … … 345 360 getGUIObjectByName("resourceMetal").caption = playerState.resourceCounts.metal; 346 361 getGUIObjectByName("resourcePop").caption = playerState.popCount + "/" + playerState.popLimit; 347 362 348 g_IsTraining QueueBlocked = playerState.trainingQueueBlocked;363 g_IsTrainingBlocked = playerState.trainingBlocked; 349 364 } 350 365 351 366 function updateTimeElapsedCounter(simState) -
binaries/data/mods/public/simulation/helpers/Commands.js
135 135 // Verify that the building can be controlled by the player 136 136 if (CanControlUnit(cmd.entity, player, controlAllUnits)) 137 137 { 138 var queue = Engine.QueryInterface(cmd.entity, IID_TrainingQueue); 139 if (queue) 140 queue.AddBatch(cmd.template, +cmd.count, cmd.metadata); 138 var cmpTechMan = QueryOwnerInterface(cmd.entity, IID_TechnologyManager); 139 // TODO: Enable this check once the AI gets technology support 140 if (cmpTechMan.CanProduce(cmd.template) || true) 141 { 142 var queue = Engine.QueryInterface(cmd.entity, IID_ProductionQueue); 143 if (queue) 144 queue.AddBatch(cmd.template, "unit", +cmd.count, cmd.metadata); 145 } 146 else if (g_DebugCommands) 147 { 148 warn("Invalid command: training requires unresearched technology: " + uneval(cmd)); 149 } 141 150 } 142 151 else if (g_DebugCommands) 143 152 { … … 145 154 } 146 155 break; 147 156 148 case " stop-train":157 case "research": 149 158 // Verify that the building can be controlled by the player 150 159 if (CanControlUnit(cmd.entity, player, controlAllUnits)) 151 160 { 152 var queue = Engine.QueryInterface(cmd.entity, IID_TrainingQueue); 161 var cmpTechMan = QueryOwnerInterface(cmd.entity, IID_TechnologyManager); 162 // TODO: Enable this check once the AI gets technology support 163 if (cmpTechMan.CanResearch(cmd.template) || true) 164 { 165 var queue = Engine.QueryInterface(cmd.entity, IID_ProductionQueue); 166 if (queue) 167 queue.AddBatch(cmd.template, "technology"); 168 } 169 else if (g_DebugCommands) 170 { 171 warn("Invalid command: Requirements to research technology are not met: " + uneval(cmd)); 172 } 173 } 174 else if (g_DebugCommands) 175 { 176 warn("Invalid command: research building cannot be controlled by player "+player+": "+uneval(cmd)); 177 } 178 break; 179 180 case "stop-production": 181 // Verify that the building can be controlled by the player 182 if (CanControlUnit(cmd.entity, player, controlAllUnits)) 183 { 184 var queue = Engine.QueryInterface(cmd.entity, IID_ProductionQueue); 153 185 if (queue) 154 186 queue.RemoveBatch(cmd.id); 155 187 } 156 188 else if (g_DebugCommands) 157 189 { 158 warn("Invalid command: trainingbuilding cannot be controlled by player "+player+": "+uneval(cmd));190 warn("Invalid command: production building cannot be controlled by player "+player+": "+uneval(cmd)); 159 191 } 160 192 break; 161 193 … … 233 265 Engine.DestroyEntity(ent); 234 266 break; 235 267 } 268 269 var cmpTechMan = QueryPlayerIDInterface(player, IID_TechnologyManager); 270 // TODO: Enable this check once the AI gets technology support 271 if (!cmpTechMan.CanProduce(cmd.template) && false) 272 { 273 if (g_DebugCommands) 274 { 275 warn("Invalid command: required technology check failed for player "+player+": "+uneval(cmd)); 276 } 236 277 278 var cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 279 cmpGuiInterface.PushNotification({ "player": player, "message": "Building's technology requirements are not met." }); 280 281 // Remove the foundation because the construction was aborted 282 Engine.DestroyEntity(ent); 283 } 284 237 285 // TODO: AI has no visibility info 238 286 if (!cmpPlayer.IsAI()) 239 287 { -
binaries/data/mods/public/simulation/components/GuiInterface.js
66 66 "popLimit": cmpPlayer.GetPopulationLimit(), 67 67 "popMax": cmpPlayer.GetMaxPopulation(), 68 68 "resourceCounts": cmpPlayer.GetResourceCounts(), 69 "training QueueBlocked": cmpPlayer.IsTrainingQueueBlocked(),69 "trainingBlocked": cmpPlayer.IsTrainingBlocked(), 70 70 "state": cmpPlayer.GetState(), 71 71 "team": cmpPlayer.GetTeam(), 72 72 "phase": cmpPlayer.GetPhase(), … … 177 177 ret.buildEntities = cmpBuilder.GetEntitiesList(); 178 178 } 179 179 180 var cmp TrainingQueue = Engine.QueryInterface(ent, IID_TrainingQueue);181 if (cmp TrainingQueue)180 var cmpProductionQueue = Engine.QueryInterface(ent, IID_ProductionQueue); 181 if (cmpProductionQueue) 182 182 { 183 ret.training = { 184 "entities": cmpTrainingQueue.GetEntitiesList(), 185 "queue": cmpTrainingQueue.GetQueue(), 183 ret.production = { 184 "entities": cmpProductionQueue.GetEntitiesList(), 185 "technologies": cmpProductionQueue.GetTechnologiesList(), 186 "queue": cmpProductionQueue.GetQueue(), 186 187 }; 187 188 } 188 189 … … 346 347 }; 347 348 ret.icon = template.Identity.Icon; 348 349 ret.tooltip = template.Identity.Tooltip; 350 ret.requiredTechnology = template.Identity.RequiredTechnology; 349 351 } 350 352 351 353 if (template.UnitMotion) … … 359 361 return ret; 360 362 }; 361 363 364 GuiInterface.prototype.GetTechnologyData = function(player, name) 365 { 366 var cmpTechTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TechnologyTemplateManager); 367 var template = cmpTechTempMan.GetTemplate(name); 368 369 if (!template) 370 { 371 warn("tried to get data for invaalid technology: " + name); 372 return null; 373 } 374 375 var ret = {}; 376 377 var cmpPlayer = QueryPlayerIDInterface(player, IID_Player); 378 var specific = template.specificName; 379 if (template["specificName_" + cmpPlayer.GetCiv()]) 380 specific = template["specificName_" + cmpPlayer.GetCiv()]; 381 382 ret.name = { 383 "specific": specific, 384 "generic": template.genericName, 385 }; 386 ret.icon = template.icon; 387 ret.cost = { 388 "food": +template.cost.food, 389 "wood": +template.cost.wood, 390 "metal": +template.cost.metal, 391 "stone": +template.cost.stone, 392 } 393 ret.tooltip = template.tooltip; 394 395 if (template.requirementsTooltip) 396 ret.requirementsTooltip = template.requirementsTooltip; 397 else 398 ret.requirementsTooltip = ""; 399 400 ret.description = template.description; 401 402 return ret; 403 }; 404 405 GuiInterface.prototype.IsTechnologyResearched = function(player, tech) 406 { 407 var cmpTechMan = QueryPlayerIDInterface(player, IID_TechnologyManager); 408 409 if (!cmpTechMan) 410 return false; 411 412 return cmpTechMan.IsTechnologyResearched(tech); 413 } 414 415 // Checks whether the requirements for this technology have been met 416 GuiInterface.prototype.CheckTechnologyRequirements = function(player, tech) 417 { 418 var cmpTechMan = QueryPlayerIDInterface(player, IID_TechnologyManager); 419 420 if (!cmpTechMan) 421 return false; 422 423 return cmpTechMan.CanResearch(tech); 424 } 425 362 426 GuiInterface.prototype.PushNotification = function(notification) 363 427 { 364 428 this.notifications.push(notification); … … 812 876 "ClearRenamedEntities": 1, 813 877 "GetEntityState": 1, 814 878 "GetTemplateData": 1, 879 "GetTechnologyData": 1, 880 "IsTechnologyResearched": 1, 881 "CheckTechnologyRequirements": 1, 815 882 "GetNextNotification": 1, 816 883 817 884 "GetFormationRequirements": 1, -
binaries/data/mods/public/simulation/components/interfaces/TrainingQueue.js
1 Engine.RegisterInterface("TrainingQueue");2 3 // Message of the form { } (use GetQueue if you want the current details),4 // sent to the current entity whenever the training queue changes.5 Engine.RegisterMessageType("TrainingQueueChanged");6 7 // Message of the form { entities: [id, ...], metadata: ... }8 // sent to the current entity whenever a unit has been trained.9 Engine.RegisterMessageType("TrainingFinished"); -
binaries/data/mods/public/simulation/components/interfaces/TechnologyManager.js
1 Engine.RegisterInterface("TechnologyManager"); 2 3 // Message of the form { "component": "Attack", "player": 3 } 4 // Sent when a new technology is researched which modifies a component 5 Engine.RegisterMessageType("TechnologyModificationChange"); -
binaries/data/mods/public/simulation/components/interfaces/ProductionQueue.js
1 Engine.RegisterInterface(" TrainingQueue");1 Engine.RegisterInterface("ProductionQueue"); 2 2 3 3 // Message of the form { } (use GetQueue if you want the current details), 4 4 // sent to the current entity whenever the training queue changes. 5 Engine.RegisterMessageType(" TrainingQueueChanged");5 Engine.RegisterMessageType("ProductionQueueChanged"); 6 6 7 7 // Message of the form { entities: [id, ...], metadata: ... } 8 8 // sent to the current entity whenever a unit has been trained. -
binaries/data/mods/public/simulation/components/interfaces/TechnologyTemplateManager.js
1 Engine.RegisterInterface("TechnologyTemplateManager"); 2 No newline at end of file -
binaries/data/mods/public/simulation/components/ResourceGatherer.js
125 125 return undefined; 126 126 }; 127 127 128 // Remove any cached template data which is based on technology data 129 ResourceGatherer.prototype.OnTechnologyModificationChange = function(msg) 130 { 131 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 132 if (!cmpOwnership) 133 return; 134 135 var player = cmpOwnership.GetOwner(); 136 137 if (msg.component === "ResourceGatherer" && msg.player === player) 138 delete this.gatherRatesCache; 139 }; 140 128 141 ResourceGatherer.prototype.GetGatherRates = function() 129 142 { 130 var ret = {}; 131 for (var r in this.template.Rates) 132 ret[r] = this.template.Rates[r] * this.template.BaseSpeed; 133 return ret; 143 if (!this.gatherRatesCache){ 144 this.gatherRatesCache = {}; 145 var cmpTechManager = QueryOwnerInterface(this.entity, IID_TechnologyManager); 146 var baseSpeed = cmpTechManager.ApplyModifications("ResourceGatherer/BaseSpeed", this.template.BaseSpeed, this.entity); 147 for (var r in this.template.Rates) 148 { 149 var rate = cmpTechManager.ApplyModifications("ResourceGatherer/Rates/" + r, this.template.Rates[r], this.entity); 150 this.gatherRatesCache[r] = rate * baseSpeed; 151 } 152 } 153 154 return this.gatherRatesCache; 134 155 }; 135 156 136 157 ResourceGatherer.prototype.GetRange = function() 137 158 { 138 159 return { "max": +this.template.MaxDistance, "min": 0 }; 139 160 // maybe this should depend on the unit or target or something? 140 } 161 }; 141 162 142 163 /** 143 164 * Try to gather treasure … … 223 244 var type = cmpResourceSupply.GetType(); 224 245 225 246 var rate; 226 if (type.specific && this. template.Rates[type.generic+"."+type.specific])227 rate = this. template.Rates[type.generic+"."+type.specific];247 if (type.specific && this.GetGatherRates()[type.generic+"."+type.specific]) 248 rate = this.GetGatherRates()[type.generic+"."+type.specific]; 228 249 else 229 rate = this. template.Rates[type.generic];250 rate = this.GetGatherRates()[type.generic]; 230 251 231 return (rate || 0) * this.template.BaseSpeed;232 } 252 return (rate || 0); 253 }; 233 254 234 255 /** 235 256 * Returns whether this unit can carry more of the given type of resource. -
binaries/data/mods/public/simulation/components/TrainingQueue.js
1 var g_ProgressInterval = 1000;2 const MAX_QUEUE_SIZE = 16;3 4 function TrainingQueue() {}5 6 TrainingQueue.prototype.Schema =7 "<a:help>Allows the building to train new units.</a:help>" +8 "<a:example>" +9 "<Entities datatype='tokens'>" +10 "\n units/{civ}_support_female_citizen\n units/{civ}_support_trader\n units/celt_infantry_spearman_b\n " +11 "</Entities>" +12 "</a:example>" +13 "<element name='Entities' a:help='Space-separated list of entity template names that this building can train. The special string \"{civ}\" will be automatically replaced by the building's four-character civ code'>" +14 "<attribute name='datatype'>" +15 "<value>tokens</value>" +16 "</attribute>" +17 "<text/>" +18 "</element>";19 20 TrainingQueue.prototype.Init = function()21 {22 this.nextID = 1;23 24 this.queue = [];25 // Queue items are:26 // {27 // "id": 1,28 // "player": 1, // who paid for this batch; we need this to cope with refunds cleanly29 // "template": "units/example",30 // "count": 10,31 // "resources": { "wood": 100, ... }, // resources per unit, multiply by count to get total32 // "population": 1, // population per unit, multiply by count to get total33 // "trainingStarted": false, // true iff we have reserved population34 // "timeTotal": 15000, // msecs35 // "timeRemaining": 10000, // msecs36 // }37 38 this.timer = undefined; // g_ProgressInterval msec timer, active while the queue is non-empty39 40 this.entityCache = [];41 this.spawnNotified = false;42 };43 44 /*45 * Returns list of entities that can be trained by this building.46 */47 TrainingQueue.prototype.GetEntitiesList = function()48 {49 var string = this.template.Entities._string;50 51 // Replace the "{civ}" codes with this entity's civ ID52 var cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity);53 if (cmpIdentity)54 string = string.replace(/\{civ\}/g, cmpIdentity.GetCiv());55 56 return string.split(/\s+/);57 };58 59 /*60 * Adds a new batch of identical units to the training queue.61 */62 TrainingQueue.prototype.AddBatch = function(templateName, count, metadata)63 {64 // TODO: there should probably be a limit on the number of queued batches65 // TODO: there should be a way for the GUI to determine whether it's going66 // to be possible to add a batch (based on resource costs and length limits)67 var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);68 69 if (this.queue.length < MAX_QUEUE_SIZE)70 {71 // Find the template data so we can determine the build costs72 var cmpTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);73 var template = cmpTempMan.GetTemplate(templateName);74 if (!template)75 return;76 77 // Apply a time discount to larger batches.78 // TODO: work out what equation we should use here.79 var timeMult = Math.pow(count, 0.7);80 81 var time = timeMult * template.Cost.BuildTime;82 83 var totalCosts = {};84 for each (var r in ["food", "wood", "stone", "metal"])85 totalCosts[r] = Math.floor(count * template.Cost.Resources[r]);86 87 var population = template.Cost.Population;88 89 // TrySubtractResources should report error to player (they ran out of resources)90 if (!cmpPlayer.TrySubtractResources(totalCosts))91 return;92 93 this.queue.push({94 "id": this.nextID++,95 "player": cmpPlayer.GetPlayerID(),96 "template": templateName,97 "count": count,98 "metadata": metadata,99 "resources": deepcopy(template.Cost.Resources), // need to copy to avoid serialization problems100 "population": population,101 "trainingStarted": false,102 "timeTotal": time*1000,103 "timeRemaining": time*1000,104 });105 Engine.PostMessage(this.entity, MT_TrainingQueueChanged, { });106 107 // If this is the first item in the queue, start the timer108 if (!this.timer)109 {110 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);111 this.timer = cmpTimer.SetTimeout(this.entity, IID_TrainingQueue, "ProgressTimeout", g_ProgressInterval, {});112 }113 }114 else115 {116 var notification = {"player": cmpPlayer.GetPlayerID(), "message": "The training queue is full."};117 var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);118 cmpGUIInterface.PushNotification(notification);119 }120 };121 122 /*123 * Removes an existing batch of units from the training queue.124 * Refunds resource costs and population reservations.125 */126 TrainingQueue.prototype.RemoveBatch = function(id)127 {128 // Destroy any cached entities (those which didn't spawn for some reason)129 for (var i = 0; i < this.entityCache.length; ++i)130 {131 Engine.DestroyEntity(this.entityCache[i]);132 }133 this.entityCache = [];134 135 for (var i = 0; i < this.queue.length; ++i)136 {137 var item = this.queue[i];138 if (item.id != id)139 continue;140 141 // Now we've found the item to remove142 143 var cmpPlayer = QueryPlayerIDInterface(item.player, IID_Player);144 145 // Refund the resource cost for this batch146 var totalCosts = {};147 for each (var r in ["food", "wood", "stone", "metal"])148 totalCosts[r] = Math.floor(item.count * item.resources[r]);149 150 cmpPlayer.AddResources(totalCosts);151 152 // Remove reserved population slots if necessary153 if (item.trainingStarted)154 cmpPlayer.UnReservePopulationSlots(item.population * item.count);155 156 // Remove from the queue157 // (We don't need to remove the timer - it'll expire if it discovers the queue is empty)158 this.queue.splice(i, 1);159 Engine.PostMessage(this.entity, MT_TrainingQueueChanged, { });160 161 return;162 }163 };164 165 /*166 * Returns basic data from all batches in the training queue.167 */168 TrainingQueue.prototype.GetQueue = function()169 {170 var out = [];171 for each (var item in this.queue)172 {173 out.push({174 "id": item.id,175 "template": item.template,176 "count": item.count,177 "progress": 1-(item.timeRemaining/item.timeTotal),178 "metadata": item.metadata,179 });180 }181 return out;182 };183 184 /*185 * Removes all existing batches from the queue.186 */187 TrainingQueue.prototype.ResetQueue = function()188 {189 // Empty the training queue and refund all the resource costs190 // to the player. (This is to avoid players having to micromanage their191 // buildings' queues when they're about to be destroyed or captured.)192 193 while (this.queue.length)194 this.RemoveBatch(this.queue[0].id);195 };196 197 TrainingQueue.prototype.OnOwnershipChanged = function(msg)198 {199 if (msg.from != -1)200 {201 // Unset flag that previous owner's training queue may be blocked202 var cmpPlayer = QueryPlayerIDInterface(msg.from, IID_Player);203 if (cmpPlayer && this.queue.length > 0)204 cmpPlayer.UnBlockTrainingQueue();205 }206 207 // Reset the training queue whenever the owner changes.208 // (This should prevent players getting surprised when they capture209 // an enemy building, and then loads of the enemy's civ's soldiers get210 // created from it. Also it means we don't have to worry about211 // updating the reserved pop slots.)212 this.ResetQueue();213 };214 215 TrainingQueue.prototype.OnDestroy = function()216 {217 // Reset the queue to refund any resources218 this.ResetQueue();219 220 if (this.timer)221 {222 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);223 cmpTimer.CancelTimer(this.timer);224 }225 };226 227 /*228 * This function creates the entities and places them in world if possible.229 * returns the number of successfully spawned entities.230 */231 TrainingQueue.prototype.SpawnUnits = function(templateName, count, metadata)232 {233 var cmpFootprint = Engine.QueryInterface(this.entity, IID_Footprint);234 var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);235 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);236 var cmpRallyPoint = Engine.QueryInterface(this.entity, IID_RallyPoint);237 238 var spawnedEnts = [];239 240 if (this.entityCache.length == 0)241 {242 // We need entities to test spawning, but we don't want to waste resources,243 // so only create them once and use as needed244 for (var i = 0; i < count; ++i)245 {246 this.entityCache.push(Engine.AddEntity(templateName));247 }248 }249 250 for (var i = 0; i < count; ++i)251 {252 var ent = this.entityCache[0];253 var pos = cmpFootprint.PickSpawnPoint(ent);254 if (pos.y < 0)255 {256 // Fail: there wasn't any space to spawn the unit257 break;258 }259 else260 {261 // Successfully spawned262 var cmpNewPosition = Engine.QueryInterface(ent, IID_Position);263 cmpNewPosition.JumpTo(pos.x, pos.z);264 // TODO: what direction should they face in?265 266 var cmpNewOwnership = Engine.QueryInterface(ent, IID_Ownership);267 cmpNewOwnership.SetOwner(cmpOwnership.GetOwner());268 269 var cmpPlayerStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker);270 cmpPlayerStatisticsTracker.IncreaseTrainedUnitsCounter();271 272 // Play a sound, but only for the first in the batch (to avoid nasty phasing effects)273 if (spawnedEnts.length == 0)274 PlaySound("trained", ent);275 276 this.entityCache.shift();277 spawnedEnts.push(ent);278 }279 }280 281 if (spawnedEnts.length > 0)282 {283 // If a rally point is set, walk towards it (in formation) using a suitable command based on where the284 // rally point is placed.285 if (cmpRallyPoint)286 {287 var rallyPos = cmpRallyPoint.GetPosition();288 if (rallyPos)289 {290 ProcessCommand(cmpOwnership.GetOwner(), GetRallyPointCommand(cmpRallyPoint, spawnedEnts));291 }292 }293 294 Engine.PostMessage(this.entity, MT_TrainingFinished, {295 "entities": spawnedEnts,296 "owner": cmpOwnership.GetOwner(),297 "metadata": metadata,298 });299 }300 301 return spawnedEnts.length;302 };303 304 /*305 * Increments progress on the first batch in the training queue, and blocks the306 * queue if population limit is reached or some units failed to spawn.307 */308 TrainingQueue.prototype.ProgressTimeout = function(data)309 {310 // Allocate the 1000msecs to as many queue items as it takes311 // until we've used up all the time (so that we work accurately312 // with items that take fractions of a second)313 var time = g_ProgressInterval;314 var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);315 316 while (time > 0 && this.queue.length)317 {318 var item = this.queue[0];319 if (!item.trainingStarted)320 {321 // Batch's training hasn't started yet.322 // Try to reserve the necessary population slots323 if (!cmpPlayer.TryReservePopulationSlots(item.population * item.count))324 {325 // No slots available - don't train this batch now326 // (we'll try again on the next timeout)327 328 // Set flag that training queue is blocked329 cmpPlayer.BlockTrainingQueue();330 break;331 }332 333 // Unset flag that training queue is blocked334 cmpPlayer.UnBlockTrainingQueue();335 336 item.trainingStarted = true;337 }338 339 // If we won't finish the batch now, just update its timer340 if (item.timeRemaining > time)341 {342 item.timeRemaining -= time;343 break;344 }345 346 var numSpawned = this.SpawnUnits(item.template, item.count, item.metadata);347 if (numSpawned == item.count)348 {349 // All entities spawned, this batch finished350 cmpPlayer.UnReservePopulationSlots(item.population * numSpawned);351 time -= item.timeRemaining;352 this.queue.shift();353 // Unset flag that training queue is blocked354 cmpPlayer.UnBlockTrainingQueue();355 this.spawnNotified = false;356 Engine.PostMessage(this.entity, MT_TrainingQueueChanged, { });357 }358 else359 {360 if (numSpawned > 0)361 {362 // Only partially finished363 cmpPlayer.UnReservePopulationSlots(item.population * numSpawned);364 item.count -= numSpawned;365 Engine.PostMessage(this.entity, MT_TrainingQueueChanged, { });366 }367 368 // Some entities failed to spawn369 // Set flag that training queue is blocked370 cmpPlayer.BlockTrainingQueue();371 372 if (!this.spawnNotified)373 {374 var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);375 var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Can't find free space to spawn trained units" };376 var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);377 cmpGUIInterface.PushNotification(notification);378 this.spawnNotified = true;379 }380 break;381 }382 }383 384 // If the queue's empty, delete the timer, else repeat it385 if (this.queue.length == 0)386 {387 this.timer = undefined;388 389 // Unset flag that training queue is blocked390 // (This might happen when the player unqueues all batches)391 cmpPlayer.UnBlockTrainingQueue();392 }393 else394 {395 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);396 this.timer = cmpTimer.SetTimeout(this.entity, IID_TrainingQueue, "ProgressTimeout", g_ProgressInterval, data);397 }398 }399 400 Engine.RegisterComponentType(IID_TrainingQueue, "TrainingQueue", TrainingQueue); -
binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js
12 12 Engine.LoadComponentScript("interfaces/ResourceDropsite.js"); 13 13 Engine.LoadComponentScript("interfaces/ResourceGatherer.js"); 14 14 Engine.LoadComponentScript("interfaces/ResourceSupply.js"); 15 Engine.LoadComponentScript("interfaces/ TrainingQueue.js");15 Engine.LoadComponentScript("interfaces/ProductionQueue.js"); 16 16 Engine.LoadComponentScript("interfaces/Trader.js") 17 17 Engine.LoadComponentScript("interfaces/Timer.js"); 18 18 Engine.LoadComponentScript("interfaces/StatisticsTracker.js"); … … 58 58 GetPopulationLimit: function() { return 20; }, 59 59 GetMaxPopulation: function() { return 200; }, 60 60 GetResourceCounts: function() { return { food: 100 }; }, 61 IsTraining QueueBlocked: function() { return false; },61 IsTrainingBlocked: function() { return false; }, 62 62 GetState: function() { return "active"; }, 63 63 GetTeam: function() { return -1; }, 64 64 GetDiplomacy: function() { return [-1, 1]; }, … … 105 105 GetPopulationLimit: function() { return 30; }, 106 106 GetMaxPopulation: function() { return 300; }, 107 107 GetResourceCounts: function() { return { food: 200 }; }, 108 IsTraining QueueBlocked: function() { return false; },108 IsTrainingBlocked: function() { return false; }, 109 109 GetState: function() { return "active"; }, 110 110 GetTeam: function() { return -1; }, 111 111 GetDiplomacy: function() { return [-1, 1]; }, … … 157 157 popLimit: 20, 158 158 popMax: 200, 159 159 resourceCounts: { food: 100 }, 160 training QueueBlocked: false,160 trainingBlocked: false, 161 161 state: "active", 162 162 team: -1, 163 163 phase: "", … … 174 174 popLimit: 30, 175 175 popMax: 300, 176 176 resourceCounts: { food: 200 }, 177 training QueueBlocked: false,177 trainingBlocked: false, 178 178 state: "active", 179 179 team: -1, 180 180 phase: "village", … … 198 198 popLimit: 20, 199 199 popMax: 200, 200 200 resourceCounts: { food: 100 }, 201 training QueueBlocked: false,201 trainingBlocked: false, 202 202 state: "active", 203 203 team: -1, 204 204 phase: "", … … 231 231 popLimit: 30, 232 232 popMax: 300, 233 233 resourceCounts: { food: 200 }, 234 training QueueBlocked: false,234 trainingBlocked: false, 235 235 state: "active", 236 236 team: -1, 237 237 phase: "village", -
binaries/data/mods/public/simulation/components/Identity.js
68 68 "<element name='Icon'>" + 69 69 "<text/>" + 70 70 "</element>" + 71 "</optional>" + 72 "<optional>" + 73 "<element name='RequiredTechnology' a:help='Optional name of a technology which must be researched before the entity can be produced'>" + 74 "<text/>" + 75 "</element>" + 71 76 "</optional>"; 72 77 73 78 … … 126 131 Identity.prototype.GetSelectionGroupName = function() 127 132 { 128 133 return (this.template.SelectionGroupName || ""); 129 } 134 }; 130 135 131 136 Engine.RegisterComponentType(IID_Identity, "Identity", Identity); -
binaries/data/mods/public/simulation/components/AIProxy.js
119 119 this.changes.unitAIOrderData = msg.to; 120 120 }; 121 121 122 AIProxy.prototype.On TrainingQueueChanged = function(msg)122 AIProxy.prototype.OnProductionQueueChanged = function(msg) 123 123 { 124 124 this.NotifyChange(); 125 125 126 var cmp TrainingQueue = Engine.QueryInterface(this.entity, IID_TrainingQueue);127 this.changes.trainingQueue = cmp TrainingQueue.GetQueue();126 var cmpProductionQueue = Engine.QueryInterface(this.entity, IID_ProductionQueue); 127 this.changes.trainingQueue = cmpProductionQueue.GetQueue(); 128 128 }; 129 129 130 130 AIProxy.prototype.OnGarrisonedUnitsChanged = function(msg) … … 206 206 ret.unitAIOrderData = cmpUnitAI.GetOrderData(); 207 207 } 208 208 209 var cmp TrainingQueue = Engine.QueryInterface(this.entity, IID_TrainingQueue);210 if (cmp TrainingQueue)209 var cmpProductionQueue = Engine.QueryInterface(this.entity, IID_ProductionQueue); 210 if (cmpProductionQueue) 211 211 { 212 // Updated by On TrainingQueueChanged213 ret.trainingQueue = cmp TrainingQueue.GetQueue();212 // Updated by OnProductionQueueChanged 213 ret.trainingQueue = cmpProductionQueue.GetQueue(); 214 214 } 215 215 216 216 var cmpFoundation = Engine.QueryInterface(this.entity, IID_Foundation); -
binaries/data/mods/public/simulation/components/Player.js
12 12 this.popUsed = 0; // population of units owned or trained by this player 13 13 this.popBonuses = 0; // sum of population bonuses of player's entities 14 14 this.maxPop = 300; // maximum population 15 this.training QueueBlocked = false; // indicates whether any training queue is currently blocked15 this.trainingBlocked = false; // indicates whether any training queue is currently blocked 16 16 this.resourceCount = { 17 17 "food": 1000, 18 18 "wood": 1000, … … 104 104 return this.maxPop; 105 105 }; 106 106 107 Player.prototype.IsTraining QueueBlocked = function()107 Player.prototype.IsTrainingBlocked = function() 108 108 { 109 return this.training QueueBlocked;109 return this.trainingBlocked; 110 110 }; 111 111 112 Player.prototype.BlockTraining Queue= function()112 Player.prototype.BlockTraining = function() 113 113 { 114 this.training QueueBlocked = true;114 this.trainingBlocked = true; 115 115 }; 116 116 117 Player.prototype.UnBlockTraining Queue= function()117 Player.prototype.UnBlockTraining = function() 118 118 { 119 this.training QueueBlocked = false;119 this.trainingBlocked = false; 120 120 }; 121 121 122 122 Player.prototype.SetResourceCounts = function(resources) -
binaries/data/mods/public/simulation/components/TechnologyManager.js
1 function TechnologyManager() {} 2 3 TechnologyManager.prototype.Schema = 4 "<a:component type='system'/><empty/>"; 5 6 TechnologyManager.prototype.Init = function () 7 { 8 var cmpTechTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TechnologyTemplateManager); 9 this.allTechs = cmpTechTempMan.GetAllTechs(); 10 this.researchedTechs = {}; // technologies which have been researched 11 this.inProgressTechs = {}; // technologies which are being researched currently 12 13 // This stores the modifications to unit stats from researched technologies 14 // Example data: {"ResourceGatherer/Rates/food.grain": [ {"multiplier": 1.15, "affects": ["Female", "Infantry Swordsman"]}, 15 // {"add": 2} ]} 16 this.modifications = {}; 17 18 this.typeCounts = {}; // stores the number of entities of each type 19 this.classCounts = {}; // stores the number of entities of each Class 20 this.typeCountsByClass = {}; // stores the number of entities of each type for each class i.e. 21 // {"someClass": {"unit/spearman": 2, "unit/cav": 5} "someOtherClass":...} 22 23 // Some technologies are automatically researched when their conditions are met. They have no cost and are 24 // researched instantly. This allows civ bonuses and more complicated technologies. 25 this.autoResearchTech = {}; 26 for (var key in this.allTechs) 27 { 28 if (this.allTechs[key].autoResearch) 29 this.autoResearchTech[key] = this.allTechs[key]; 30 } 31 32 this._UpdateAutoResearch(); 33 }; 34 35 // This function checks if the requirements of any autoresearch techs are met and if they are it researches them 36 TechnologyManager.prototype._UpdateAutoResearch = function () 37 { 38 for (var key in this.autoResearchTech) 39 { 40 if (this.CanResearch(key)) 41 { 42 delete this.autoResearchTech[key]; 43 this.ResearchTechnology(key); 44 return; // We will have recursively handled any knock-on effects so can just return 45 } 46 } 47 } 48 49 TechnologyManager.prototype.GetTechnologyTemplate = function (tech) 50 { 51 return this.allTechs[tech]; 52 }; 53 54 // This function checks an entity template to see if it's technology requirements have been met 55 TechnologyManager.prototype.CanProduce = function (templateName) 56 { 57 var cmpTempManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); 58 var template = cmpTempManager.GetTemplate(templateName); 59 60 if (template.Identity && template.Identity.RequiredTechnology) 61 return this.IsTechnologyResearched(template.Identity.RequiredTechnology); 62 else 63 return true; // If there is no required technology then this entity can be produced 64 }; 65 66 TechnologyManager.prototype.IsTechnologyResearched = function (tech) 67 { 68 return (this.researchedTechs[tech] !== undefined); 69 }; 70 71 // Checks the requirements for a technology to see if it can be researched at the current time 72 TechnologyManager.prototype.CanResearch = function (tech) 73 { 74 var template = this.GetTechnologyTemplate(tech); 75 if (!template) 76 { 77 warn("Technology \"" + tech + "\" does not exist"); 78 return false; 79 } 80 81 var ret = true; 82 83 // The technology which this technology supercedes is required 84 if (template.supercedes) 85 ret = ret && this.IsTechnologyResearched(template.supercedes); 86 87 ret = ret && this._CheckTechnologyRequirements(template.requirements); 88 89 return ret; 90 }; 91 92 TechnologyManager.prototype._CheckTechnologyRequirements = function (reqs) 93 { 94 // If there are no requirements then all requirements are met 95 if (!reqs) 96 return true; 97 98 if (reqs.tech) 99 { 100 return this.IsTechnologyResearched(reqs.tech); 101 } 102 else if (reqs.all) 103 { 104 var ret = true; 105 for (var i = 0; i < reqs.all.length; i++) 106 { 107 ret = ret && this._CheckTechnologyRequirements(reqs.all[i]); 108 } 109 return ret; 110 } 111 else if (reqs.any) 112 { 113 for (var i = 0; i < reqs.any.length; i++) 114 { 115 if (this._CheckTechnologyRequirements(reqs.any[i])) 116 return true; 117 } 118 return false 119 } 120 else if (reqs["class"]) 121 { 122 return (reqs.numberOfTypes <= Object.keys(this.typeCountsByClass[reqs["class"]]).length); 123 } 124 125 // The technologies requirements are not a recognised format 126 error("Bad requirements " + uneval(reqs)); 127 return false; 128 }; 129 130 TechnologyManager.prototype.OnGlobalOwnershipChanged = function (msg) 131 { 132 // This automatically updates typeCounts, classCounts and typeCountsByClass 133 var playerID = (Engine.QueryInterface(this.entity, IID_Player)).GetPlayerID(); 134 if (msg.to == playerID) 135 { 136 var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); 137 var template = cmpTemplateManager.GetCurrentTemplateName(msg.entity); 138 139 this.typeCounts[template] = this.typeCounts[template] || 0; 140 this.typeCounts[template] += 1; 141 142 // don't use foundations for the class counts 143 if (Engine.QueryInterface(msg.entity, IID_Foundation)) 144 return; 145 146 var cmpIdentity = Engine.QueryInterface(msg.entity, IID_Identity); 147 if (cmpIdentity) 148 { 149 var classes = cmpIdentity.GetClassesList(); 150 for (var i in classes) 151 { 152 this.classCounts[classes[i]] = this.classCounts[classes[i]] || 0; 153 this.classCounts[classes[i]] += 1; 154 155 this.typeCountsByClass[classes[i]] = this.typeCountsByClass[classes[i]] || {}; 156 this.typeCountsByClass[classes[i]][template] = this.typeCountsByClass[classes[i]][template] || 0; 157 this.typeCountsByClass[classes[i]][template] += 1; 158 } 159 } 160 } 161 if (msg.from == playerID) 162 { 163 var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); 164 var template = cmpTemplateManager.GetCurrentTemplateName(msg.entity); 165 166 this.typeCounts[template] -= 1; 167 168 // don't use foundations for the class counts 169 if (Engine.QueryInterface(msg.entity, IID_Foundation)) 170 return; 171 172 var cmpIdentity = Engine.QueryInterface(msg.entity, IID_Identity); 173 if (cmpIdentity) 174 { 175 var classes = cmpIdentity.GetClassesList(); 176 for (var i in classes) 177 { 178 this.classCounts[classes[i]] -= 1; 179 180 this.typeCountsByClass[classes[i]][template] -= 1; 181 } 182 } 183 } 184 }; 185 186 // Marks a technology as researched. Note that this does not verify that the requirements are met. 187 TechnologyManager.prototype.ResearchTechnology = function (tech) 188 { 189 this.StoppedResearch(tech); // The tech is no longer being currently researched 190 191 var template = this.GetTechnologyTemplate(tech); 192 if (template) 193 { 194 var modifiedComponents = {}; 195 this.researchedTechs[tech] = template; 196 // store the modifications in an easy to access structure 197 if (template.modifications) 198 { 199 var affects = []; 200 if (template.affects && template.affects.length > 0) 201 { 202 for (var i in template.affects) 203 { 204 // Put the list of classes into an array for convenient access 205 affects.push(template.affects[i].split(" ")); 206 } 207 } 208 else 209 { 210 affects.push([]); 211 } 212 213 // We add an item to this.modifications for every 214 for (var i in template.modifications) 215 { 216 var modification = template.modifications[i]; 217 if (!this.modifications[modification.value]) 218 this.modifications[modification.value] = []; 219 220 var mod = {"affects": affects}; 221 // copy the modification data into our new data structure 222 for (var j in modification) 223 if (j !== "value") 224 mod[j] = modification[j] 225 226 this.modifications[modification.value].push(mod); 227 modifiedComponents[modification.value.split("/")[0]] = true; 228 } 229 } 230 231 var cmpPlayer = Engine.QueryInterface(this.entity, IID_Player); 232 var player = cmpPlayer.GetPlayerID(); 233 234 for (var component in modifiedComponents) 235 Engine.BroadcastMessage(MT_TechnologyModificationChange, { "component": component, "player": player }); 236 237 this._UpdateAutoResearch(); 238 } 239 else 240 { 241 error("Tried to research invalid techonology: " + uneval(tech)); 242 } 243 }; 244 245 TechnologyManager.prototype.ApplyModifications = function(valueName, curValue, ent) 246 { 247 // Get all modifications to this value 248 var modifications = this.modifications[valueName]; 249 if (!modifications) // no modifications so return the orignal value 250 return curValue; 251 252 // Get the classes which this entity belongs to 253 var cmpIdentity = Engine.QueryInterface(ent, IID_Identity); 254 var classes = cmpIdentity.GetClassesList(); 255 256 var retValue = +curValue; 257 258 for (var i in modifications) 259 { 260 var modification = modifications[i]; 261 var applies = false; 262 // See if any of the lists of classes matches this entity 263 for (var j in modification.affects) 264 { 265 var hasAllClasses = true; 266 // Check each 267 for (var k in modification.affects[j]) 268 hasAllClasses = hasAllClasses && (classes.indexOf(modification.affects[j][k]) !== -1); 269 270 if (hasAllClasses) 271 { 272 applies = true; 273 break; 274 } 275 } 276 277 // Nothing is cumulative so that ordering doesn't matter as much as possible 278 if (modification.multiplier) 279 retValue += (modification.multiplier - 1) * +curValue; 280 else if (modification.add) 281 retValue += modification.add; 282 else if (modification.replace) // This will depend on ordering because there is no choice 283 retValue = modification.replace; 284 else 285 warn("modification format not recognised (modifying " + valueName + "): " + uneval(modification)); 286 } 287 288 return retValue; 289 }; 290 291 // Marks a technology as being currently researched 292 TechnologyManager.prototype.StartedResearch = function (tech) 293 { 294 this.inProgressTechs[tech] = true; 295 }; 296 297 // Marks a technology as not being currently researched 298 TechnologyManager.prototype.StoppedResearch = function (tech) 299 { 300 delete this.inProgressTechs[tech]; 301 }; 302 303 // Checks whether a technology is being currently researched 304 TechnologyManager.prototype.IsInProgress = function(tech) 305 { 306 if (this.inProgressTechs[tech]) 307 return true; 308 else 309 return false; 310 }; 311 312 Engine.RegisterComponentType(IID_TechnologyManager, "TechnologyManager", TechnologyManager); -
binaries/data/mods/public/simulation/components/ProductionQueue.js
1 1 var g_ProgressInterval = 1000; 2 2 const MAX_QUEUE_SIZE = 16; 3 3 4 function TrainingQueue() {}4 function ProductionQueue() {} 5 5 6 TrainingQueue.prototype.Schema =7 "<a:help>Allows the building to train new units .</a:help>" +6 ProductionQueue.prototype.Schema = 7 "<a:help>Allows the building to train new units and research technologies.</a:help>" + 8 8 "<a:example>" + 9 9 "<Entities datatype='tokens'>" + 10 10 "\n units/{civ}_support_female_citizen\n units/{civ}_support_trader\n units/celt_infantry_spearman_b\n " + 11 11 "</Entities>" + 12 12 "</a:example>" + 13 "<element name='Entities' a:help='Space-separated list of entity template names that this building can train. The special string \"{civ}\" will be automatically replaced by the building's four-character civ code'>" + 14 "<attribute name='datatype'>" + 15 "<value>tokens</value>" + 16 "</attribute>" + 17 "<text/>" + 18 "</element>"; 13 "<optional>" + 14 "<element name='Entities' a:help='Space-separated list of entity template names that this building can train. The special string \"{civ}\" will be automatically replaced by the building's four-character civ code'>" + 15 "<attribute name='datatype'>" + 16 "<value>tokens</value>" + 17 "</attribute>" + 18 "<text/>" + 19 "</element>" + 20 "</optional>" + 21 "<optional>" + 22 "<element name='Technologies' a:help='Space-separated list of technology names that this building can research.'>" + 23 "<attribute name='datatype'>" + 24 "<value>tokens</value>" + 25 "</attribute>" + 26 "<text/>" + 27 "</element>" + 28 "</optional>"; 19 29 20 TrainingQueue.prototype.Init = function()30 ProductionQueue.prototype.Init = function() 21 31 { 22 32 this.nextID = 1; 23 33 … … 26 36 // { 27 37 // "id": 1, 28 38 // "player": 1, // who paid for this batch; we need this to cope with refunds cleanly 29 // " template": "units/example",39 // "unitTemplate": "units/example", 30 40 // "count": 10, 31 41 // "resources": { "wood": 100, ... }, // resources per unit, multiply by count to get total 32 42 // "population": 1, // population per unit, multiply by count to get total 33 // " trainingStarted": false, // true iff we have reserved population43 // "productionStarted": false, // true iff we have reserved population 34 44 // "timeTotal": 15000, // msecs 35 45 // "timeRemaining": 10000, // msecs 36 46 // } 47 // 48 // { 49 // "id": 1, 50 // "player": 1, // who paid for this research; we need this to cope with refunds cleanly 51 // "technologyTemplate": "example_tech", 52 // "resources": { "wood": 100, ... }, // resources needed for research 53 // "productionStarted": false, // true iff production has started 54 // "timeTotal": 15000, // msecs 55 // "timeRemaining": 10000, // msecs 56 // } 37 57 38 58 this.timer = undefined; // g_ProgressInterval msec timer, active while the queue is non-empty 39 59 … … 44 64 /* 45 65 * Returns list of entities that can be trained by this building. 46 66 */ 47 TrainingQueue.prototype.GetEntitiesList = function()67 ProductionQueue.prototype.GetEntitiesList = function() 48 68 { 69 if (!this.template.Entities) 70 return []; 71 49 72 var string = this.template.Entities._string; 50 73 51 74 // Replace the "{civ}" codes with this entity's civ ID … … 57 80 }; 58 81 59 82 /* 60 * Adds a new batch of identical units to the training queue.83 * Returns list of technologies that can be researched by this building. 61 84 */ 62 TrainingQueue.prototype.AddBatch = function(templateName, count, metadata)85 ProductionQueue.prototype.GetTechnologiesList = function() 63 86 { 87 if (!this.template.Technologies) 88 return []; 89 90 var string = this.template.Technologies._string; 91 92 var cmpTechMan = QueryOwnerInterface(this.entity, IID_TechnologyManager); 93 if (!cmpTechMan) 94 return []; 95 96 var techs = string.split(/\s+/); 97 var ret = []; 98 var superceded = {}; // Stores the tech which supercedes the key 99 100 // Add any top level technologies to an array which corresponds to the displayed icons 101 // Also store the "children" for the superceding, 102 for (var i in techs) 103 { 104 var tech = techs[i]; 105 var template = cmpTechMan.GetTechnologyTemplate(tech); 106 if (!template.supercedes || techs.indexOf(template.supercedes) === -1) 107 ret.push(tech); 108 else 109 superceded[template.supercedes] = tech; 110 } 111 112 // Now make researched/in progress techs invisible 113 for (var i in ret) 114 { 115 var tech = ret[i]; 116 while (cmpTechMan.IsTechnologyResearched(tech) || cmpTechMan.IsInProgress(tech)) 117 { 118 tech = superceded[tech]; 119 } 120 121 122 ret[i] = tech; 123 } 124 125 return ret; 126 }; 127 128 /* 129 * Adds a new batch of identical units to train or a technology to research to the production queue. 130 */ 131 ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadata) 132 { 64 133 // TODO: there should probably be a limit on the number of queued batches 65 134 // TODO: there should be a way for the GUI to determine whether it's going 66 135 // to be possible to add a batch (based on resource costs and length limits) … … 68 137 69 138 if (this.queue.length < MAX_QUEUE_SIZE) 70 139 { 71 // Find the template data so we can determine the build costs 72 var cmpTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); 73 var template = cmpTempMan.GetTemplate(templateName); 74 if (!template) 75 return; 140 141 if (type == "unit") 142 { 143 // Find the template data so we can determine the build costs 144 var cmpTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); 145 var template = cmpTempMan.GetTemplate(templateName); 146 if (!template) 147 return; 148 149 // Apply a time discount to larger batches. 150 // TODO: work out what equation we should use here. 151 var timeMult = Math.pow(count, 0.7); 76 152 77 // Apply a time discount to larger batches. 78 // TODO: work out what equation we should use here. 79 var timeMult = Math.pow(count, 0.7); 153 var time = timeMult * template.Cost.BuildTime; 80 154 81 var time = timeMult * template.Cost.BuildTime; 155 var totalCosts = {}; 156 for each (var r in ["food", "wood", "stone", "metal"]) 157 totalCosts[r] = Math.floor(count * template.Cost.Resources[r]); 82 158 83 var totalCosts = {}; 84 for each (var r in ["food", "wood", "stone", "metal"]) 85 totalCosts[r] = Math.floor(count * template.Cost.Resources[r]); 159 var population = template.Cost.Population; 160 161 // TrySubtractResources should report error to player (they ran out of resources) 162 if (!cmpPlayer.TrySubtractResources(totalCosts)) 163 return; 86 164 87 var population = template.Cost.Population; 88 89 // TrySubtractResources should report error to player (they ran out of resources) 90 if (!cmpPlayer.TrySubtractResources(totalCosts)) 165 this.queue.push({ 166 "id": this.nextID++, 167 "player": cmpPlayer.GetPlayerID(), 168 "unitTemplate": templateName, 169 "count": count, 170 "metadata": metadata, 171 "resources": deepcopy(template.Cost.Resources), // need to copy to avoid serialization problems 172 "population": population, 173 "productionStarted": false, 174 "timeTotal": time*1000, 175 "timeRemaining": time*1000, 176 }); 177 } 178 else if (type == "technology") 179 { 180 // Load the technology template 181 var cmpTechTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TechnologyTemplateManager); 182 var template = cmpTechTempMan.GetTemplate(templateName); 183 if (!template) 184 return; 185 186 var time = template.researchTime; 187 188 var cost = {}; 189 for each (var r in ["food", "wood", "stone", "metal"]) 190 cost[r] = Math.floor(template.cost[r]); 191 192 // TrySubtractResources should report error to player (they ran out of resources) 193 if (!cmpPlayer.TrySubtractResources(cost)) 194 return; 195 196 // Tell the technology manager that we have started researching this so that people can't research the same 197 // thing twice. 198 var cmpTechMan = QueryOwnerInterface(this.entity, IID_TechnologyManager); 199 cmpTechMan.StartedResearch(templateName); 200 201 this.queue.push({ 202 "id": this.nextID++, 203 "player": cmpPlayer.GetPlayerID(), 204 "count": 1, 205 "technologyTemplate": templateName, 206 "resources": deepcopy(template.cost), // need to copy to avoid serialization problems 207 "productionStarted": false, 208 "timeTotal": time*1000, 209 "timeRemaining": time*1000, 210 }); 211 } 212 else 213 { 214 warn("Tried to add invalid item of type \"" + type + "\" and template \"" + templateName + "\" to a production queue"); 91 215 return; 216 } 217 218 Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { }); 92 219 93 this.queue.push({94 "id": this.nextID++,95 "player": cmpPlayer.GetPlayerID(),96 "template": templateName,97 "count": count,98 "metadata": metadata,99 "resources": deepcopy(template.Cost.Resources), // need to copy to avoid serialization problems100 "population": population,101 "trainingStarted": false,102 "timeTotal": time*1000,103 "timeRemaining": time*1000,104 });105 Engine.PostMessage(this.entity, MT_TrainingQueueChanged, { });106 107 220 // If this is the first item in the queue, start the timer 108 221 if (!this.timer) 109 222 { 110 223 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 111 this.timer = cmpTimer.SetTimeout(this.entity, IID_ TrainingQueue, "ProgressTimeout", g_ProgressInterval, {});224 this.timer = cmpTimer.SetTimeout(this.entity, IID_ProductionQueue, "ProgressTimeout", g_ProgressInterval, {}); 112 225 } 113 226 } 114 227 else 115 228 { 116 var notification = {"player": cmpPlayer.GetPlayerID(), "message": "The trainingqueue is full."};229 var notification = {"player": cmpPlayer.GetPlayerID(), "message": "The production queue is full."}; 117 230 var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 118 231 cmpGUIInterface.PushNotification(notification); 119 232 } 120 233 }; 121 234 122 235 /* 123 * Removes an existing batch of units from the trainingqueue.236 * Removes an existing batch of units from the production queue. 124 237 * Refunds resource costs and population reservations. 125 238 */ 126 TrainingQueue.prototype.RemoveBatch = function(id)239 ProductionQueue.prototype.RemoveBatch = function(id) 127 240 { 128 241 // Destroy any cached entities (those which didn't spawn for some reason) 129 242 for (var i = 0; i < this.entityCache.length; ++i) … … 139 252 continue; 140 253 141 254 // Now we've found the item to remove 142 255 143 256 var cmpPlayer = QueryPlayerIDInterface(item.player, IID_Player); 144 257 145 258 // Refund the resource cost for this batch 146 259 var totalCosts = {}; 147 260 for each (var r in ["food", "wood", "stone", "metal"]) 148 261 totalCosts[r] = Math.floor(item.count * item.resources[r]); 149 262 150 263 cmpPlayer.AddResources(totalCosts); 151 264 152 265 // Remove reserved population slots if necessary 153 if (item. trainingStarted)266 if (item.productionStarted && item.unitTemplate) 154 267 cmpPlayer.UnReservePopulationSlots(item.population * item.count); 155 268 269 // Mark the research as stopped if we cancel it 270 if (item.technologyTemplate) 271 { 272 var cmpTechMan = QueryOwnerInterface(this.entity, IID_TechnologyManager); 273 cmpTechMan.StoppedResearch(item.technologyTemplate); 274 } 275 156 276 // Remove from the queue 157 277 // (We don't need to remove the timer - it'll expire if it discovers the queue is empty) 158 278 this.queue.splice(i, 1); 159 Engine.PostMessage(this.entity, MT_ TrainingQueueChanged, { });279 Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { }); 160 280 161 281 return; 162 282 } 163 283 }; 164 284 165 285 /* 166 * Returns basic data from all batches in the trainingqueue.286 * Returns basic data from all batches in the production queue. 167 287 */ 168 TrainingQueue.prototype.GetQueue = function()288 ProductionQueue.prototype.GetQueue = function() 169 289 { 170 290 var out = []; 171 291 for each (var item in this.queue) 172 292 { 173 293 out.push({ 174 294 "id": item.id, 175 "template": item.template, 295 "unitTemplate": item.unitTemplate, 296 "technologyTemplate": item.technologyTemplate, 176 297 "count": item.count, 177 298 "progress": 1-(item.timeRemaining/item.timeTotal), 178 299 "metadata": item.metadata, … … 184 305 /* 185 306 * Removes all existing batches from the queue. 186 307 */ 187 TrainingQueue.prototype.ResetQueue = function()308 ProductionQueue.prototype.ResetQueue = function() 188 309 { 189 // Empty the trainingqueue and refund all the resource costs310 // Empty the production queue and refund all the resource costs 190 311 // to the player. (This is to avoid players having to micromanage their 191 312 // buildings' queues when they're about to be destroyed or captured.) 192 313 … … 194 315 this.RemoveBatch(this.queue[0].id); 195 316 }; 196 317 197 TrainingQueue.prototype.OnOwnershipChanged = function(msg)318 ProductionQueue.prototype.OnOwnershipChanged = function(msg) 198 319 { 199 320 if (msg.from != -1) 200 321 { 201 // Unset flag that previous owner's training queuemay be blocked322 // Unset flag that previous owner's training may be blocked 202 323 var cmpPlayer = QueryPlayerIDInterface(msg.from, IID_Player); 203 324 if (cmpPlayer && this.queue.length > 0) 204 cmpPlayer.UnBlockTraining Queue();325 cmpPlayer.UnBlockTraining(); 205 326 } 206 327 207 // Reset the trainingqueue whenever the owner changes.328 // Reset the production queue whenever the owner changes. 208 329 // (This should prevent players getting surprised when they capture 209 330 // an enemy building, and then loads of the enemy's civ's soldiers get 210 331 // created from it. Also it means we don't have to worry about … … 212 333 this.ResetQueue(); 213 334 }; 214 335 215 TrainingQueue.prototype.OnDestroy = function()336 ProductionQueue.prototype.OnDestroy = function() 216 337 { 217 338 // Reset the queue to refund any resources 218 339 this.ResetQueue(); … … 228 349 * This function creates the entities and places them in world if possible. 229 350 * returns the number of successfully spawned entities. 230 351 */ 231 TrainingQueue.prototype.SpawnUnits = function(templateName, count, metadata)352 ProductionQueue.prototype.SpawnUnits = function(templateName, count, metadata) 232 353 { 233 354 var cmpFootprint = Engine.QueryInterface(this.entity, IID_Footprint); 234 355 var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); … … 302 423 }; 303 424 304 425 /* 305 * Increments progress on the first batch in the trainingqueue, and blocks the426 * Increments progress on the first batch in the production queue, and blocks the 306 427 * queue if population limit is reached or some units failed to spawn. 307 428 */ 308 TrainingQueue.prototype.ProgressTimeout = function(data)429 ProductionQueue.prototype.ProgressTimeout = function(data) 309 430 { 310 431 // Allocate the 1000msecs to as many queue items as it takes 311 432 // until we've used up all the time (so that we work accurately … … 316 437 while (time > 0 && this.queue.length) 317 438 { 318 439 var item = this.queue[0]; 319 if (!item. trainingStarted)440 if (!item.productionStarted) 320 441 { 321 // Batch's training hasn't started yet. 322 // Try to reserve the necessary population slots 323 if (!cmpPlayer.TryReservePopulationSlots(item.population * item.count)) 442 // If the item is a unit then do population checks 443 if (item.unitTemplate) 324 444 { 325 // No slots available - don't train this batch now 326 // (we'll try again on the next timeout) 445 // Batch's training hasn't started yet. 446 // Try to reserve the necessary population slots 447 if (item.unitTemplate && !cmpPlayer.TryReservePopulationSlots(item.population * item.count)) 448 { 449 // No slots available - don't train this batch now 450 // (we'll try again on the next timeout) 327 451 328 // Set flag that training queue is blocked 329 cmpPlayer.BlockTrainingQueue(); 330 break; 452 // Set flag that training is blocked 453 cmpPlayer.BlockTraining(); 454 break; 455 } 456 457 // Unset flag that training is blocked 458 cmpPlayer.UnBlockTraining(); 331 459 } 332 460 333 // Unset flag that training queue is blocked 334 cmpPlayer.UnBlockTrainingQueue(); 335 336 item.trainingStarted = true; 461 item.productionStarted = true; 337 462 } 338 463 339 464 // If we won't finish the batch now, just update its timer … … 343 468 break; 344 469 } 345 470 346 var numSpawned = this.SpawnUnits(item.template, item.count, item.metadata); 347 if (numSpawned == item.count) 471 if (item.unitTemplate) 348 472 { 349 // All entities spawned, this batch finished 350 cmpPlayer.UnReservePopulationSlots(item.population * numSpawned); 351 time -= item.timeRemaining; 352 this.queue.shift(); 353 // Unset flag that training queue is blocked 354 cmpPlayer.UnBlockTrainingQueue(); 355 this.spawnNotified = false; 356 Engine.PostMessage(this.entity, MT_TrainingQueueChanged, { }); 357 } 358 else 359 { 360 if (numSpawned > 0) 473 var numSpawned = this.SpawnUnits(item.unitTemplate, item.count, item.metadata); 474 if (numSpawned == item.count) 361 475 { 362 // Only partiallyfinished476 // All entities spawned, this batch finished 363 477 cmpPlayer.UnReservePopulationSlots(item.population * numSpawned); 364 item.count -= numSpawned; 365 Engine.PostMessage(this.entity, MT_TrainingQueueChanged, { }); 478 time -= item.timeRemaining; 479 this.queue.shift(); 480 // Unset flag that training is blocked 481 cmpPlayer.UnBlockTraining(); 482 this.spawnNotified = false; 483 Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { }); 366 484 } 485 else 486 { 487 if (numSpawned > 0) 488 { 489 // Only partially finished 490 cmpPlayer.UnReservePopulationSlots(item.population * numSpawned); 491 item.count -= numSpawned; 492 Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { }); 493 } 367 494 368 // Some entities failed to spawn 369 // Set flag that training queue is blocked 370 cmpPlayer.BlockTrainingQueue(); 371 372 if (!this.spawnNotified) 373 { 374 var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); 375 var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Can't find free space to spawn trained units" }; 376 var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 377 cmpGUIInterface.PushNotification(notification); 378 this.spawnNotified = true; 495 // Some entities failed to spawn 496 // Set flag that training is blocked 497 cmpPlayer.BlockTraining(); 498 499 if (!this.spawnNotified) 500 { 501 var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); 502 var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Can't find free space to spawn trained units" }; 503 var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 504 cmpGUIInterface.PushNotification(notification); 505 this.spawnNotified = true; 506 } 507 break; 379 508 } 380 break;381 509 } 510 else if (item.technologyTemplate) 511 { 512 var cmpTechnologyManager = QueryOwnerInterface(this.entity, IID_TechnologyManager); 513 cmpTechnologyManager.ResearchTechnology(item.technologyTemplate); 514 515 this.queue.shift(); 516 Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { }); 517 } 382 518 } 383 519 384 520 // If the queue's empty, delete the timer, else repeat it … … 386 522 { 387 523 this.timer = undefined; 388 524 389 // Unset flag that training queueis blocked525 // Unset flag that training is blocked 390 526 // (This might happen when the player unqueues all batches) 391 cmpPlayer.UnBlockTraining Queue();527 cmpPlayer.UnBlockTraining(); 392 528 } 393 529 else 394 530 { 395 531 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 396 this.timer = cmpTimer.SetTimeout(this.entity, IID_ TrainingQueue, "ProgressTimeout", g_ProgressInterval, data);532 this.timer = cmpTimer.SetTimeout(this.entity, IID_ProductionQueue, "ProgressTimeout", g_ProgressInterval, data); 397 533 } 398 534 } 399 535 400 Engine.RegisterComponentType(IID_ TrainingQueue, "TrainingQueue", TrainingQueue);536 Engine.RegisterComponentType(IID_ProductionQueue, "ProductionQueue", ProductionQueue); -
binaries/data/mods/public/simulation/components/TechnologyTemplateManager.js
1 /** 2 * System component which loads the technology data files 3 */ 4 function TechnologyTemplateManager() {} 5 6 TechnologyTemplateManager.prototype.Schema = 7 "<a:component type='system'/><empty/>"; 8 9 TechnologyTemplateManager.prototype.Init = function() 10 { 11 this.allTechs = {}; 12 var techNames = this.ListAllTechs(); 13 for (i in techNames) 14 this.GetTemplate(techNames[i]); 15 }; 16 17 TechnologyTemplateManager.prototype.GetTemplate = function(template) 18 { 19 if (!this.allTechs[template]) 20 { 21 this.allTechs[template] = Engine.ReadJSONFile("technologies/" + template + ".json"); 22 if (! this.allTechs[template]) 23 error("Failed to load technology \"" + template + "\""); 24 } 25 26 return this.allTechs[template]; 27 }; 28 29 TechnologyTemplateManager.prototype.ListAllTechs = function() 30 { 31 return Engine.FindAllTechnologyTemplates(); 32 } 33 34 TechnologyTemplateManager.prototype.GetAllTechs = function() 35 { 36 return this.allTechs; 37 } 38 39 Engine.RegisterComponentType(IID_TechnologyTemplateManager, "TechnologyTemplateManager", TechnologyTemplateManager); 40 No newline at end of file -
binaries/data/mods/public/simulation/ai/common-api/base.js
43 43 // CCmpTemplateManager::CopyFoundationSubset and only includes components 44 44 // that our EntityTemplate class currently uses.) 45 45 var g_FoundationForbiddenComponents = { 46 " TrainingQueue": 1,46 "ProductionQueue": 1, 47 47 "ResourceSupply": 1, 48 48 "ResourceDropsite": 1, 49 49 "GarrisonHolder": 1, -
binaries/data/mods/public/simulation/ai/common-api/entity.js
126 126 }, 127 127 128 128 trainableEntities: function() { 129 if (!this._template. TrainingQueue)129 if (!this._template.ProductionQueue) 130 130 return undefined; 131 131 var civ = this.civ(); 132 var templates = this._template. TrainingQueue.Entities._string.replace(/\{civ\}/g, civ).split(/\s+/);132 var templates = this._template.ProductionQueue.Entities._string.replace(/\{civ\}/g, civ).split(/\s+/); 133 133 return templates; 134 134 }, 135 135 -
binaries/data/mods/public/simulation/ai/common-api-v2/base.js
44 44 // CCmpTemplateManager::CopyFoundationSubset and only includes components 45 45 // that our EntityTemplate class currently uses.) 46 46 var g_FoundationForbiddenComponents = { 47 " TrainingQueue": 1,47 "ProductionQueue": 1, 48 48 "ResourceSupply": 1, 49 49 "ResourceDropsite": 1, 50 50 "GarrisonHolder": 1, -
binaries/data/mods/public/simulation/ai/common-api-v2/entity.js
127 127 }, 128 128 129 129 trainableEntities: function() { 130 if (!this._template. TrainingQueue)130 if (!this._template.ProductionQueue) 131 131 return undefined; 132 132 var civ = this.civ(); 133 var templates = this._template. TrainingQueue.Entities._string.replace(/\{civ\}/g, civ).split(/\s+/);133 var templates = this._template.ProductionQueue.Entities._string.replace(/\{civ\}/g, civ).split(/\s+/); 134 134 return templates; 135 135 }, 136 136 -
binaries/data/mods/public/simulation/data/technologies/town_phase.json
1 { 2 "genericName": "Town Phase", 3 "description": "Advances from a small village to a bustling town, ready to expand rapidly.", 4 "cost": { "food": 100, "wood": 100, "stone": 0, "metal": 50 }, 5 "requirements": { "class": "Village", "numberOfTypes": 2 }, 6 "requirementsTooltip": "Requires two village structures", 7 "supercedes": "village_phase", 8 "icon": "technologies/town_phase.png", 9 "researchTime": 10, 10 "tooltip": "Advance to Town Phase" 11 } -
binaries/data/mods/public/simulation/data/technologies/city_phase.json
1 { 2 "genericName": "City Phase", 3 "specificName": "Generic Specific City Name", 4 "specificName_hele": "Greek City", 5 "description": "Advances from a bustling town to a veritable metropolis, full of the wonders of modern technology.", 6 "cost": {"food": 0, "wood": 0, "stone": 50, "metal": 0}, 7 "supercedes": "town_phase", 8 "icon": "technologies/city_phase.png", 9 "researchTime": 10, 10 "tooltip": "Advance to City Phase" 11 } -
binaries/data/mods/public/simulation/data/technologies/plough.json
1 { 2 "genericName": "Plough", 3 "description": "A horse drawn instrument to turn the sod", 4 "cost": {"food": 0, "wood": 0, "stone": 0, "metal": 0}, 5 "requirements": {"tech": "town_phase"}, 6 "requirementsTooltip": "Requires Town Phase", 7 "icon": "technologies/plough.png", 8 "researchTime": 10, 9 "tooltip": "Discover the Plough", 10 "modifications": [{"value": "ResourceGatherer/Rates/food.grain", "multiplier": 15}], 11 "affects": ["Female"] 12 } -
binaries/data/mods/public/simulation/data/technologies/village_phase.json
1 { 2 "genericName": "Village Phase", 3 "description": "Advances from a small village to a bustling town, ready to expand rapidly.", 4 "autoResearch": true, 5 "icon": "technologies/town_phase.png", 6 "researchTime": 10, 7 "tooltip": "Advance to Town Phase" 8 } -
binaries/data/mods/public/simulation/templates/special/player.xml
10 10 </BuildLimits> 11 11 <Player/> 12 12 <StatisticsTracker/> 13 <TechnologyManager/> 13 14 </Entity> -
binaries/data/mods/public/simulation/templates/structures/celt_dock.xml
15 15 <Obstruction> 16 16 <Static width="10.0" depth="22.0"/> 17 17 </Obstruction> 18 < TrainingQueue>18 <ProductionQueue> 19 19 <Entities datatype="tokens"> 20 20 units/celt_ship_trireme 21 21 </Entities> 22 </ TrainingQueue>22 </ProductionQueue> 23 23 <VisualActor> 24 24 <Actor>structures/celts/dock_new.xml</Actor> 25 25 <FoundationActor>structures/fndn_celt_dock.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/structures/rome_army_camp.xml
68 68 <HealthDecayRate>5</HealthDecayRate> 69 69 </TerritoryDecay> 70 70 <TerritoryInfluence disable=""/> 71 < TrainingQueue>71 <ProductionQueue> 72 72 <Entities datatype="tokens"> 73 73 units/rome_infantry_swordsman_b 74 74 units/rome_infantry_spearman_a … … 78 78 units/rome_mechanical_siege_scorpio 79 79 units/rome_mechanical_siege_ram 80 80 </Entities> 81 </ TrainingQueue>81 </ProductionQueue> 82 82 <Vision> 83 83 <Range>60</Range> 84 84 </Vision> … … 86 86 <FoundationActor>structures/fndn_8x8.xml</FoundationActor> 87 87 <Actor>structures/romans/camp.xml</Actor> 88 88 </VisualActor> 89 </Entity> 90 No newline at end of file 89 </Entity> -
binaries/data/mods/public/simulation/templates/structures/hele_civil_centre.xml
11 11 <SpecificName>Agorā́</SpecificName> 12 12 <History>The most important place in most Classical Greek poleis, the Agora served many purposes; it was a place for public speeches and was the stage for civic life and commercial interests.</History> 13 13 </Identity> 14 < TrainingQueue>14 <ProductionQueue> 15 15 <Entities datatype="tokens"> 16 16 units/hele_infantry_spearman_b 17 17 units/hele_infantry_javelinist_b 18 18 units/hele_cavalry_javelinist_b 19 19 </Entities> 20 </ TrainingQueue>20 </ProductionQueue> 21 21 <VisualActor> 22 22 <Actor>structures/hellenes/civic_centre_new.xml</Actor> 23 23 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/mace_barracks.xml
15 15 <SpecificName>Stratēgeîon</SpecificName> 16 16 <History>The Stratigeion was the main military headquarters, where important decisions were taken and plans for battles discussed by the Hellene Generals, or "Strategoi".</History> 17 17 </Identity> 18 < TrainingQueue>18 <ProductionQueue> 19 19 <Entities datatype="tokens"> 20 20 units/mace_infantry_spearman_b 21 21 units/mace_infantry_javelinist_b … … 24 24 units/mace_cavalry_spearman_b 25 25 units/mace_cavalry_javelinist_b 26 26 </Entities> 27 </ TrainingQueue>27 </ProductionQueue> 28 28 <VisualActor> 29 29 <Actor>structures/hellenes/barracks.xml</Actor> 30 30 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/pers_apadana.xml
32 32 <Root>true</Root> 33 33 <Radius>38</Radius> 34 34 </TerritoryInfluence> 35 < TrainingQueue>35 <ProductionQueue> 36 36 <Entities datatype="tokens"> 37 37 units/pers_hero_cyrus 38 38 units/pers_hero_darius 39 39 units/pers_hero_xerxes 40 40 units/pers_champion_infantry 41 41 </Entities> 42 </ TrainingQueue>42 </ProductionQueue> 43 43 <VisualActor> 44 44 <Actor>structures/persians/sb1_new.xml</Actor> 45 45 <FoundationActor>structures/fndn_6x6.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/structures/iber_corral.xml
12 12 <Obstruction> 13 13 <Static width="14.0" depth="14.0"/> 14 14 </Obstruction> 15 < TrainingQueue>15 <ProductionQueue> 16 16 <Entities datatype="tokens"> 17 17 gaia/fauna_goat 18 18 </Entities> 19 </ TrainingQueue>19 </ProductionQueue> 20 20 <VisualActor> 21 21 <Actor>structures/iberians/corral.xml</Actor> 22 22 <FoundationActor>structures/fndn_4x4.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/structures/pers_stables.xml
25 25 <Obstruction> 26 26 <Static width="18.0" depth="16.0"/> 27 27 </Obstruction> 28 < TrainingQueue>28 <ProductionQueue> 29 29 <Entities datatype="tokens"> 30 30 units/pers_cavalry_spearman_b 31 31 units/pers_cavalry_swordsman_b 32 32 units/pers_cavalry_javelinist_b 33 33 units/pers_cavalry_archer_b 34 34 </Entities> 35 </ TrainingQueue>35 </ProductionQueue> 36 36 <VisualActor> 37 37 <Actor>structures/persians/stables.xml</Actor> 38 38 <FoundationActor>structures/fndn_4x4.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/structures/rome_civil_centre.xml
12 12 <Obstruction> 13 13 <Static width="37.0" depth="37.0"/> 14 14 </Obstruction> 15 < TrainingQueue>15 <ProductionQueue> 16 16 <Entities datatype="tokens"> 17 17 units/rome_infantry_swordsman_b 18 18 units/rome_infantry_javelinist_b 19 19 units/rome_cavalry_spearman_b 20 20 </Entities> 21 </ TrainingQueue>21 </ProductionQueue> 22 22 <VisualActor> 23 23 <FoundationActor>structures/fndn_8x8.xml</FoundationActor> 24 24 <Actor>structures/romans/civic_centre.xml</Actor> -
binaries/data/mods/public/simulation/templates/structures/spart_corral.xml
18 18 <Obstruction> 19 19 <Static width="14.0" depth="14.0"/> 20 20 </Obstruction> 21 < TrainingQueue>21 <ProductionQueue> 22 22 <Entities datatype="tokens"> 23 23 gaia/fauna_goat 24 24 </Entities> 25 </ TrainingQueue>25 </ProductionQueue> 26 26 <VisualActor> 27 27 <Actor>structures/hellenes/corral.xml</Actor> 28 28 <FoundationActor>structures/fndn_3x3.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/structures/athen_dock.xml
11 11 <SpecificName>Limḗn</SpecificName> 12 12 <History>Greece is a sea country, which is why some of the greatest Hellenic and Hellenistic cities like Ephesus, Corinth, Alexandria and Antioch were built by the sea. It should also be noted that all colonies during the Great Colonisation were thriving port centres, which traded with the local population.</History> 13 13 </Identity> 14 < TrainingQueue>14 <ProductionQueue> 15 15 <Entities datatype="tokens"> 16 16 units/athen_ship_bireme 17 17 units/athen_ship_trireme 18 18 </Entities> 19 </ TrainingQueue>19 </ProductionQueue> 20 20 <VisualActor> 21 21 <Actor>structures/athenians/dock.xml</Actor> 22 22 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/rome_corral.xml
12 12 <Obstruction> 13 13 <Static width="14" depth="20"/> 14 14 </Obstruction> 15 < TrainingQueue>15 <ProductionQueue> 16 16 <Entities datatype="tokens"> 17 17 gaia/fauna_goat 18 18 gaia/fauna_sheep 19 19 </Entities> 20 </ TrainingQueue>20 </ProductionQueue> 21 21 <VisualActor> 22 22 <FoundationActor>structures/fndn_2x4.xml</FoundationActor> 23 23 <Actor>structures/romans/corral.xml</Actor> -
binaries/data/mods/public/simulation/templates/structures/spart_syssiton.xml
33 33 <death>attack/destruction/building_collapse_large.xml</death> 34 34 </SoundGroups> 35 35 </Sound> 36 < TrainingQueue>36 <ProductionQueue> 37 37 <Entities datatype="tokens"> 38 38 units/hele_hero_leonidas 39 39 units/spart_champion_infantry_spear 40 40 </Entities> 41 </ TrainingQueue>41 </ProductionQueue> 42 42 <VisualActor> 43 43 <Actor>structures/hellenes/gymnasion.xml</Actor> 44 44 <FoundationActor>structures/fndn_6x6.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/structures/cart_super_dock.xml
46 46 </Sound> 47 47 <TerritoryDecay disable=""/> 48 48 <TerritoryInfluence disable=""/> 49 < TrainingQueue>49 <ProductionQueue> 50 50 <Entities datatype="tokens"> 51 51 units/cart_ship_bireme 52 52 units/cart_ship_trireme 53 53 units/cart_ship_quinquereme 54 54 </Entities> 55 </ TrainingQueue>55 </ProductionQueue> 56 56 <Vision> 57 57 <Range>100</Range> 58 58 </Vision> -
binaries/data/mods/public/simulation/templates/structures/iber_fortress.xml
19 19 <Obstruction> 20 20 <Static width="27.0" depth="27.0"/> 21 21 </Obstruction> 22 < TrainingQueue>22 <ProductionQueue> 23 23 <Entities datatype="tokens"> 24 24 units/iber_hero_caros 25 25 units/iber_hero_indibil … … 28 28 units/iber_champion_cavalry 29 29 units/iber_mechanical_siege_ram 30 30 </Entities> 31 </ TrainingQueue>31 </ProductionQueue> 32 32 <VisualActor> 33 33 <Actor>structures/iberians/fortress.xml</Actor> 34 34 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/pers_corral.xml
18 18 <Obstruction> 19 19 <Static width="17.0" depth="11.0"/> 20 20 </Obstruction> 21 < TrainingQueue>21 <ProductionQueue> 22 22 <Entities datatype="tokens"> 23 23 gaia/fauna_goat 24 24 </Entities> 25 </ TrainingQueue>25 </ProductionQueue> 26 26 <VisualActor> 27 27 <Actor>structures/persians/corral.xml</Actor> 28 28 <FoundationActor>structures/fndn_4x2.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/structures/celt_fortress_b.xml
29 29 <death>attack/destruction/building_collapse_large.xml</death> 30 30 </SoundGroups> 31 31 </Sound> 32 < TrainingQueue>32 <ProductionQueue> 33 33 <Entities datatype="tokens"> 34 34 units/celt_hero_boudicca 35 35 units/celt_hero_caratacos … … 38 38 units/celt_champion_infantry_brit 39 39 units/celt_mechanical_siege_ram 40 40 </Entities> 41 </ TrainingQueue>41 </ProductionQueue> 42 42 <Vision> 43 43 <Range>100</Range> 44 44 </Vision> -
binaries/data/mods/public/simulation/templates/structures/spart_fortress.xml
19 19 <Obstruction> 20 20 <Static width="24.0" depth="26.0"/> 21 21 </Obstruction> 22 < TrainingQueue>22 <ProductionQueue> 23 23 <Entities datatype="tokens"> 24 24 units/spart_mechanical_siege_ram 25 25 </Entities> 26 </ TrainingQueue>26 </ProductionQueue> 27 27 <VisualActor> 28 28 <Actor>structures/hellenes/fortress_new.xml</Actor> 29 29 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/athen_gymnasion.xml
33 33 <death>attack/destruction/building_collapse_large.xml</death> 34 34 </SoundGroups> 35 35 </Sound> 36 < TrainingQueue>36 <ProductionQueue> 37 37 <Entities datatype="tokens"> 38 38 units/athen_champion_infantry 39 39 units/athen_champion_ranged 40 40 </Entities> 41 </ TrainingQueue>41 </ProductionQueue> 42 42 <VisualActor> 43 43 <Actor>structures/athenians/gymnasion.xml</Actor> 44 44 <FoundationActor>structures/fndn_6x6.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/structures/cart_corral.xml
12 12 <Obstruction> 13 13 <Static width="16.0" depth="14.5"/> 14 14 </Obstruction> 15 < TrainingQueue>15 <ProductionQueue> 16 16 <Entities datatype="tokens"> 17 17 gaia/fauna_goat 18 18 </Entities> 19 </ TrainingQueue>19 </ProductionQueue> 20 20 <VisualActor> 21 21 <Actor>structures/carthaginians/corral.xml</Actor> 22 22 <FoundationActor>structures/fndn_3x3.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/structures/pers_fortress.xml
12 12 <History>The Susa Chateau was a fortress in the administrative capital of Susa, which was reconstructed by a French archaeologist in 1890 with the use of original building material.</History> 13 13 <Tooltip>Train Champion Units and Construct Siege Rams.</Tooltip> 14 14 </Identity> 15 < TrainingQueue>15 <ProductionQueue> 16 16 <Entities datatype="tokens"> 17 17 units/pers_champion_cavalry 18 18 units/pers_mechanical_siege_ram 19 19 </Entities> 20 </ TrainingQueue>20 </ProductionQueue> 21 21 <VisualActor> 22 22 <Actor>structures/persians/fortress.xml</Actor> 23 23 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/mace_dock.xml
11 11 <SpecificName>Limḗn</SpecificName> 12 12 <History>Greece is a sea country, which is why some of the greatest Hellenic and Hellenistic cities like Ephesus, Corinth, Alexandria and Antioch were built by the sea. It should also be noted that all colonies during the Great Colonisation were thriving port centres, which traded with the local population.</History> 13 13 </Identity> 14 < TrainingQueue>14 <ProductionQueue> 15 15 <Entities datatype="tokens"> 16 16 units/hele_ship_bireme 17 17 units/hele_ship_trireme 18 18 </Entities> 19 </ TrainingQueue>19 </ProductionQueue> 20 20 <VisualActor> 21 21 <Actor>structures/hellenes/dock.xml</Actor> 22 22 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/iber_civil_centre.xml
5 5 <SpecificName>Oppidum</SpecificName> 6 6 <History>The Oppidum, plural Oppida (oh-PEE-dah), has a long history in the Iberian Peninsula. They were walled towns, dating back to even before the time period of the game and expanding greatly during it. They were usually built upon heights for better defensive purposes but sometimes right out on the plains, especially in the east where there may not have been heights at desirable locations near meandering rivers. This concept drawing is derived from an actual archeological site that has been excavated in the northeast of Spain having belonged to the Ilergete (ee-layer-HAY-tay) tribe as shown in the figure below and from the virtual reconstruction of the site at the museum located adjacent to it.</History> 7 7 </Identity> 8 < TrainingQueue>8 <ProductionQueue> 9 9 <Entities datatype="tokens"> 10 10 units/iber_infantry_swordsman_b 11 11 units/iber_infantry_javelinist_b 12 12 units/iber_cavalry_javelinist_b 13 13 </Entities> 14 </ TrainingQueue>14 </ProductionQueue> 15 15 <VisualActor> 16 16 <Actor>structures/iberians/civil_centre.xml</Actor> 17 17 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/spart_civil_centre.xml
11 11 <SpecificName>Agorā́</SpecificName> 12 12 <History>The most important place in most Classical Greek poleis, the Agora served many purposes; it was a place for public speeches and was the stage for civic life and commercial interests.</History> 13 13 </Identity> 14 < TrainingQueue>14 <ProductionQueue> 15 15 <Entities datatype="tokens"> 16 16 units/spart_infantry_spearman_b 17 17 units/spart_infantry_javelinist_b 18 18 units/spart_cavalry_javelinist_b 19 19 </Entities> 20 </ TrainingQueue>20 </ProductionQueue> 21 21 <VisualActor> 22 22 <Actor>structures/hellenes/civic_centre_new.xml</Actor> 23 23 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/cart_fortress.xml
13 13 <Obstruction> 14 14 <Static width="26.0" depth="28.0"/> 15 15 </Obstruction> 16 < TrainingQueue>16 <ProductionQueue> 17 17 <Entities datatype="tokens"> 18 18 units/cart_hero_hamilcar 19 19 units/cart_hero_hannibal … … 22 22 units/cart_mechanical_siege_ballista 23 23 units/cart_mechanical_siege_oxybeles 24 24 </Entities> 25 </ TrainingQueue>25 </ProductionQueue> 26 26 <VisualActor> 27 27 <Actor>structures/carthaginians/fortress.xml</Actor> 28 28 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/hele_barracks.xml
15 15 <SpecificName>Stratēgeîon</SpecificName> 16 16 <History>The Stratigeion was the main military headquarters, where important decisions were taken and plans for battles discussed by the Hellene Generals, or "Strategoi".</History> 17 17 </Identity> 18 < TrainingQueue>18 <ProductionQueue> 19 19 <Entities datatype="tokens"> 20 20 units/hele_infantry_spearman_b 21 21 units/hele_infantry_javelinist_b … … 24 24 units/hele_cavalry_swordsman_b 25 25 units/hele_cavalry_javelinist_b 26 26 </Entities> 27 </ TrainingQueue>27 </ProductionQueue> 28 28 <VisualActor> 29 29 <Actor>structures/hellenes/barracks.xml</Actor> 30 30 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/pers_civil_centre.xml
12 12 <SpecificName>Xsacapava</SpecificName> 13 13 <History>Possibly of Median origin, the word 'satrapy' means province. Soon after coming to the throne, Darius the Great carried out a vast administrative reform, dividing the huge empire into 20 satrapies governed by satraps.</History> 14 14 </Identity> 15 < TrainingQueue>15 <ProductionQueue> 16 16 <Entities datatype="tokens"> 17 17 units/pers_infantry_spearman_b 18 18 units/pers_infantry_archer_b 19 19 units/pers_cavalry_javelinist_b 20 20 </Entities> 21 </ TrainingQueue>21 </ProductionQueue> 22 22 <VisualActor> 23 23 <Actor>structures/persians/civil_centre.xml</Actor> 24 24 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/hele_gymnasion.xml
33 33 <death>attack/destruction/building_collapse_large.xml</death> 34 34 </SoundGroups> 35 35 </Sound> 36 < TrainingQueue>36 <ProductionQueue> 37 37 <Entities datatype="tokens"> 38 38 units/hele_champion_cavalry_mace 39 39 units/hele_champion_infantry_mace 40 40 units/hele_champion_infantry_polis 41 41 units/hele_champion_swordsman_polis 42 42 </Entities> 43 </ TrainingQueue>43 </ProductionQueue> 44 44 <VisualActor> 45 45 <Actor>structures/hellenes/gymnasion.xml</Actor> 46 46 <FoundationActor>structures/fndn_6x6.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/structures/cart_embassy_iberian.xml
17 17 <Obstruction> 18 18 <Static width="16.0" depth="16.0"/> 19 19 </Obstruction> 20 < TrainingQueue>20 <ProductionQueue> 21 21 <Entities datatype="tokens"> 22 22 units/cart_infantry_javelinist_b 23 23 units/cart_infantry_slinger_b 24 24 units/cart_cavalry_swordsman_b 25 25 </Entities> 26 </ TrainingQueue>26 </ProductionQueue> 27 27 <VisualActor> 28 28 <Actor>structures/carthaginians/embassy_iberian.xml</Actor> 29 29 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/cart_embassy_italiote.xml
20 20 <Obstruction> 21 21 <Static width="11.0" depth="14.0"/> 22 22 </Obstruction> 23 < TrainingQueue>23 <ProductionQueue> 24 24 <Entities datatype="tokens"> 25 25 units/cart_infantry_swordsman_2_b 26 26 units/cart_cavalry_spearman_b 27 27 </Entities> 28 </ TrainingQueue>28 </ProductionQueue> 29 29 <VisualActor> 30 30 <Actor>structures/carthaginians/embassy_italiote.xml</Actor> 31 31 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/celt_civil_centre.xml
12 12 <Obstruction> 13 13 <Static width="25.0" depth="25.0"/> 14 14 </Obstruction> 15 < TrainingQueue>15 <ProductionQueue> 16 16 <Entities datatype="tokens"> 17 17 units/celt_infantry_spearman_b 18 18 units/celt_infantry_javelinist_b 19 19 units/celt_cavalry_javelinist_b 20 20 </Entities> 21 </ TrainingQueue>21 </ProductionQueue> 22 22 <VisualActor> 23 23 <Actor>structures/celts/civic_centre.xml</Actor> 24 24 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/cart_civil_centre.xml
5 5 <SpecificName>Merkāz</SpecificName> 6 6 <History>Carthiginian's History</History> 7 7 </Identity> 8 < TrainingQueue>8 <ProductionQueue> 9 9 <Entities datatype="tokens"> 10 10 units/cart_infantry_spearman_b 11 11 units/cart_infantry_archer_b 12 12 units/cart_cavalry_javelinist_b 13 13 </Entities> 14 </ TrainingQueue>14 </ProductionQueue> 15 15 <VisualActor> 16 16 <Actor>structures/carthaginians/civil_centre.xml</Actor> 17 17 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/athen_fortress.xml
19 19 <Obstruction> 20 20 <Static width="24.0" depth="26.0"/> 21 21 </Obstruction> 22 < TrainingQueue>22 <ProductionQueue> 23 23 <Entities datatype="tokens"> 24 24 units/athen_mechanical_siege_oxybeles 25 25 units/athen_mechanical_siege_lithobolos 26 26 </Entities> 27 </ TrainingQueue>27 </ProductionQueue> 28 28 <VisualActor> 29 29 <Actor>structures/athenians/fortress.xml</Actor> 30 30 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/rome_fortress.xml
5 5 <SpecificName>Castellum</SpecificName> 6 6 <History>Fortified auxillary camp.</History> 7 7 </Identity> 8 < TrainingQueue>8 <ProductionQueue> 9 9 <Entities datatype="tokens"> 10 10 units/rome_hero_marcellus 11 11 units/rome_hero_maximus … … 16 16 units/rome_mechanical_siege_scorpio 17 17 units/rome_mechanical_siege_ram 18 18 </Entities> 19 </ TrainingQueue>19 </ProductionQueue> 20 20 <VisualActor> 21 21 <Actor>structures/romans/fortress.xml</Actor> 22 22 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/mace_corral.xml
18 18 <Obstruction> 19 19 <Static width="14.0" depth="14.0"/> 20 20 </Obstruction> 21 < TrainingQueue>21 <ProductionQueue> 22 22 <Entities datatype="tokens"> 23 23 gaia/fauna_goat 24 24 </Entities> 25 </ TrainingQueue>25 </ProductionQueue> 26 26 <VisualActor> 27 27 <Actor>structures/hellenes/corral.xml</Actor> 28 28 <FoundationActor>structures/fndn_3x3.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/structures/hele_dock.xml
11 11 <SpecificName>Limḗn</SpecificName> 12 12 <History>Greece is a sea country, which is why some of the greatest Hellenic and Hellenistic cities like Ephesus, Corinth, Alexandria and Antioch were built by the sea. It should also be noted that all colonies during the Great Colonisation were thriving port centres, which traded with the local population.</History> 13 13 </Identity> 14 < TrainingQueue>14 <ProductionQueue> 15 15 <Entities datatype="tokens"> 16 16 units/hele_ship_bireme 17 17 units/hele_ship_trireme 18 18 </Entities> 19 </ TrainingQueue>19 </ProductionQueue> 20 20 <VisualActor> 21 21 <Actor>structures/hellenes/dock.xml</Actor> 22 22 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/pers_sb2.xml
40 40 <Root>false</Root> 41 41 <Radius>38</Radius> 42 42 </TerritoryInfluence> 43 < TrainingQueue>43 <ProductionQueue> 44 44 <Entities datatype="tokens"> 45 45 units/pers_kardakes_hoplite 46 46 units/pers_kardakes_skirmisher 47 47 units/pers_war_elephant 48 48 </Entities> 49 </ TrainingQueue>49 </ProductionQueue> 50 50 <VisualActor> 51 51 <Actor>structures/persians/sb2.xml</Actor> 52 52 <FoundationActor>structures/fndn_6x6.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/structures/athen_civil_centre.xml
11 11 <SpecificName>Agorā́</SpecificName> 12 12 <History>The most important place in most Classical Greek poleis, the Agora served many purposes; it was a place for public speeches and was the stage for civic life and commercial interests.</History> 13 13 </Identity> 14 < TrainingQueue>14 <ProductionQueue> 15 15 <Entities datatype="tokens"> 16 16 units/athen_infantry_spearman_b 17 17 units/athen_infantry_slinger_b 18 18 units/athen_cavalry_javelinist_b 19 19 </Entities> 20 </ TrainingQueue>20 </ProductionQueue> 21 21 <VisualActor> 22 22 <Actor>structures/athenians/civic_centre_new.xml</Actor> 23 23 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/iber_barracks.xml
11 11 <SpecificName>Cuartel</SpecificName> 12 12 <History>To the best of our knowledge, the Iberians did not have standing armies in the sense that we know of them elsewhere or of today, it is doubtful that they had specific structures designated as military centres; however as a game construct we show a modest structure wherein military related activities take place.</History> 13 13 </Identity> 14 < TrainingQueue>14 <ProductionQueue> 15 15 <Entities datatype="tokens"> 16 16 units/iber_infantry_spearman_b 17 17 units/iber_infantry_swordsman_b … … 20 20 units/iber_cavalry_spearman_b 21 21 units/iber_cavalry_javelinist_b 22 22 </Entities> 23 </ TrainingQueue>23 </ProductionQueue> 24 24 <VisualActor> 25 25 <Actor>structures/iberians/barracks.xml</Actor> 26 26 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/mace_fortress.xml
19 19 <Obstruction> 20 20 <Static width="24.0" depth="26.0"/> 21 21 </Obstruction> 22 < TrainingQueue>22 <ProductionQueue> 23 23 <Entities datatype="tokens"> 24 24 units/mace_hero_philip 25 25 units/mace_hero_alexander … … 30 30 units/mace_mechanical_siege_lithobolos 31 31 units/mace_mechanical_siege_tower 32 32 </Entities> 33 </ TrainingQueue>33 </ProductionQueue> 34 34 <VisualActor> 35 35 <Actor>structures/hellenes/fortress_new.xml</Actor> 36 36 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/spart_barracks.xml
15 15 <SpecificName>Stratēgeîon</SpecificName> 16 16 <History>The Stratigeion was the main military headquarters, where important decisions were taken and plans for battles discussed by the Hellene Generals, or "Strategoi".</History> 17 17 </Identity> 18 < TrainingQueue>18 <ProductionQueue> 19 19 <Entities datatype="tokens"> 20 20 units/spart_infantry_spearman_b 21 21 units/spart_champion_infantry_sword 22 22 units/spart_infantry_javelinist_b 23 23 units/spart_cavalry_javelinist_b 24 24 </Entities> 25 </ TrainingQueue>25 </ProductionQueue> 26 26 <VisualActor> 27 27 <Actor>structures/hellenes/barracks.xml</Actor> 28 28 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/rome_dock.xml
12 12 <Obstruction> 13 13 <Static width="20.0" depth="24.0"/> 14 14 </Obstruction> 15 < TrainingQueue>15 <ProductionQueue> 16 16 <Entities datatype="tokens"> 17 17 units/rome_ship_bireme 18 18 units/rome_ship_trireme 19 19 units/rome_ship_quinquereme 20 20 </Entities> 21 </ TrainingQueue>21 </ProductionQueue> 22 22 <VisualActor> 23 23 <Actor>structures/romans/dock.xml</Actor> 24 24 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/pers_barracks.xml
17 17 <Tooltip>Levy citizen-infantry units.</Tooltip> 18 18 <Icon>structures/pers_barracks.png</Icon> 19 19 </Identity> 20 < TrainingQueue>20 <ProductionQueue> 21 21 <Entities datatype="tokens"> 22 22 units/pers_infantry_spearman_b 23 23 units/pers_infantry_javelinist_b 24 24 units/pers_infantry_archer_b 25 25 </Entities> 26 </ TrainingQueue>26 </ProductionQueue> 27 27 <VisualActor> 28 28 <Actor>structures/persians/barracks.xml</Actor> 29 29 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/celt_kennel.xml
40 40 <Radius>20</Radius> 41 41 <Weight>65536</Weight> 42 42 </TerritoryInfluence> 43 < TrainingQueue>43 <ProductionQueue> 44 44 <Entities datatype="tokens"> 45 45 units/celt_war_dog_b 46 46 </Entities> 47 </ TrainingQueue>47 </ProductionQueue> 48 48 <VisualActor> 49 49 <Actor>structures/celts/kennel.xml</Actor> 50 50 <FoundationActor>structures/fndn_2x2.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/structures/celt_fortress_g.xml
16 16 <death>attack/destruction/building_collapse_large.xml</death> 17 17 </SoundGroups> 18 18 </Sound> 19 < TrainingQueue>19 <ProductionQueue> 20 20 <Entities datatype="tokens"> 21 21 units/celt_hero_brennus 22 22 units/celt_hero_britomartus … … 25 25 units/celt_champion_infantry_gaul 26 26 units/celt_mechanical_siege_ram 27 27 </Entities> 28 </ TrainingQueue>28 </ProductionQueue> 29 29 <VisualActor> 30 30 <Actor>structures/celts/fortress_gallic.xml</Actor> 31 31 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/celt_corral.xml
12 12 <Obstruction> 13 13 <Static width="10.0" depth="20.0"/> 14 14 </Obstruction> 15 < TrainingQueue>15 <ProductionQueue> 16 16 <Entities datatype="tokens"> 17 17 gaia/fauna_sheep 18 18 </Entities> 19 </ TrainingQueue>19 </ProductionQueue> 20 20 <VisualActor> 21 21 <Actor>structures/celts/plot_corral.xml</Actor> 22 22 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/mace_civil_centre.xml
11 11 <SpecificName>Agorā́</SpecificName> 12 12 <History>The most important place in most Classical Greek poleis, the Agora served many purposes; it was a place for public speeches and was the stage for civic life and commercial interests.</History> 13 13 </Identity> 14 < TrainingQueue>14 <ProductionQueue> 15 15 <Entities datatype="tokens"> 16 16 units/mace_infantry_spearman_b 17 17 units/mace_infantry_javelinist_b 18 18 units/mace_cavalry_spearman_b 19 19 </Entities> 20 </ TrainingQueue>20 </ProductionQueue> 21 21 <VisualActor> 22 22 <Actor>structures/hellenes/civic_centre_new.xml</Actor> 23 23 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/celt_barracks.xml
14 14 <Obstruction> 15 15 <Static width="20.0" depth="20.0"/> 16 16 </Obstruction> 17 < TrainingQueue>17 <ProductionQueue> 18 18 <Entities datatype="tokens"> 19 19 units/celt_infantry_spearman_b 20 20 units/celt_infantry_javelinist_b … … 22 22 units/celt_cavalry_swordsman_b 23 23 units/celt_cavalry_javelinist_b 24 24 </Entities> 25 </ TrainingQueue>25 </ProductionQueue> 26 26 <VisualActor> 27 27 <Actor>structures/celts/barracks_new.xml</Actor> 28 28 <FoundationActor>structures/fndn_5x5.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/structures/cart_barracks.xml
19 19 <Obstruction> 20 20 <Static width="22.0" depth="23.0"/> 21 21 </Obstruction> 22 < TrainingQueue>22 <ProductionQueue> 23 23 <Entities datatype="tokens"> 24 24 units/cart_infantry_spearman_b 25 25 units/cart_infantry_archer_b 26 26 units/cart_cavalry_javelinist_b 27 27 </Entities> 28 </ TrainingQueue>28 </ProductionQueue> 29 29 <VisualActor> 30 30 <Actor>structures/carthaginians/barracks.xml</Actor> 31 31 <FoundationActor>structures/fndn_5x5.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/structures/hele_corral.xml
18 18 <Obstruction> 19 19 <Static width="14.0" depth="14.0"/> 20 20 </Obstruction> 21 < TrainingQueue>21 <ProductionQueue> 22 22 <Entities datatype="tokens"> 23 23 gaia/fauna_goat 24 24 </Entities> 25 </ TrainingQueue>25 </ProductionQueue> 26 26 <VisualActor> 27 27 <Actor>structures/hellenes/corral.xml</Actor> 28 28 <FoundationActor>structures/fndn_3x3.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/structures/iber_dock.xml
12 12 <Obstruction> 13 13 <Static width="14.0" depth="24.0"/> 14 14 </Obstruction> 15 < TrainingQueue>15 <ProductionQueue> 16 16 <Entities datatype="tokens"> 17 17 units/iber_ship_fire 18 18 </Entities> 19 </ TrainingQueue>19 </ProductionQueue> 20 20 <VisualActor> 21 21 <Actor>structures/iberians/dock.xml</Actor> 22 22 <FoundationActor>structures/fndn_dock_iber.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/structures/hele_prytaneion.xml
34 34 <death>attack/destruction/building_collapse_large.xml</death> 35 35 </SoundGroups> 36 36 </Sound> 37 < TrainingQueue>37 <ProductionQueue> 38 38 <Entities datatype="tokens"> 39 39 units/hele_hero_alexander 40 40 units/hele_hero_demetrius … … 43 43 units/hele_hero_themistocles 44 44 units/hele_hero_xenophon 45 45 </Entities> 46 </ TrainingQueue>46 </ProductionQueue> 47 47 <VisualActor> 48 48 <Actor>structures/hellenes/tholos.xml</Actor> 49 49 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/spart_gerousia.xml
34 34 <death>attack/destruction/building_collapse_large.xml</death> 35 35 </SoundGroups> 36 36 </Sound> 37 < TrainingQueue>37 <ProductionQueue> 38 38 <Entities datatype="tokens"> 39 39 units/hele_hero_leonidas 40 40 </Entities> 41 </ TrainingQueue>41 </ProductionQueue> 42 42 <VisualActor> 43 43 <Actor>structures/hellenes/tholos.xml</Actor> 44 44 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/spart_dock.xml
11 11 <SpecificName>Limḗn</SpecificName> 12 12 <History>Greece is a sea country, which is why some of the greatest Hellenic and Hellenistic cities like Ephesus, Corinth, Alexandria and Antioch were built by the sea. It should also be noted that all colonies during the Great Colonisation were thriving port centres, which traded with the local population.</History> 13 13 </Identity> 14 < TrainingQueue>14 <ProductionQueue> 15 15 <Entities datatype="tokens"> 16 16 units/spart_ship_bireme 17 17 units/spart_ship_trireme 18 18 </Entities> 19 </ TrainingQueue>19 </ProductionQueue> 20 20 <VisualActor> 21 21 <Actor>structures/hellenes/dock.xml</Actor> 22 22 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/cart_temple.xml
18 18 <Obstruction> 19 19 <Static width="17.0" depth="30.0"/> 20 20 </Obstruction> 21 < TrainingQueue>21 <ProductionQueue> 22 22 <Entities datatype="tokens"> 23 23 units/cart_champion_infantry 24 24 </Entities> 25 </ TrainingQueue>25 </ProductionQueue> 26 26 <VisualActor> 27 27 <Actor>structures/carthaginians/temple_big.xml</Actor> 28 28 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/cart_embassy_celtic.xml
24 24 <Obstruction> 25 25 <Static width="15.0" depth="12.0"/> 26 26 </Obstruction> 27 < TrainingQueue>27 <ProductionQueue> 28 28 <Entities datatype="tokens"> 29 29 units/cart_infantry_swordsman_b 30 30 units/cart_cavalry_swordsman_2_b 31 31 </Entities> 32 </ TrainingQueue>32 </ProductionQueue> 33 33 <VisualActor> 34 34 <Actor>structures/carthaginians/embassy_celtic.xml</Actor> 35 35 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/athen_corral.xml
18 18 <Obstruction> 19 19 <Static width="14.0" depth="14.0"/> 20 20 </Obstruction> 21 < TrainingQueue>21 <ProductionQueue> 22 22 <Entities datatype="tokens"> 23 23 gaia/fauna_goat 24 24 </Entities> 25 </ TrainingQueue>25 </ProductionQueue> 26 26 <VisualActor> 27 27 <Actor>structures/athenians/corral.xml</Actor> 28 28 <FoundationActor>structures/fndn_3x3.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/structures/hele_fortress.xml
19 19 <Obstruction> 20 20 <Static width="24.0" depth="26.0"/> 21 21 </Obstruction> 22 < TrainingQueue>22 <ProductionQueue> 23 23 <Entities datatype="tokens"> 24 24 units/hele_mechanical_siege_oxybeles 25 25 units/hele_mechanical_siege_lithobolos 26 26 units/hele_mechanical_siege_tower 27 27 </Entities> 28 </ TrainingQueue>28 </ProductionQueue> 29 29 <VisualActor> 30 30 <Actor>structures/hellenes/fortress_new.xml</Actor> 31 31 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/athen_barracks.xml
15 15 <SpecificName>Stratēgeîon</SpecificName> 16 16 <History>The Stratigeion was the main military headquarters, where important decisions were taken and plans for battles discussed by the Hellene Generals, or "Strategoi".</History> 17 17 </Identity> 18 < TrainingQueue>18 <ProductionQueue> 19 19 <Entities datatype="tokens"> 20 20 units/athen_infantry_spearman_b 21 21 units/athen_infantry_javelinist_b … … 23 23 units/athen_cavalry_swordsman_b 24 24 units/athen_cavalry_javelinist_b 25 25 </Entities> 26 </ TrainingQueue>26 </ProductionQueue> 27 27 <VisualActor> 28 28 <Actor>structures/athenians/barracks.xml</Actor> 29 29 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/athen_prytaneion.xml
34 34 <death>attack/destruction/building_collapse_large.xml</death> 35 35 </SoundGroups> 36 36 </Sound> 37 < TrainingQueue>37 <ProductionQueue> 38 38 <Entities datatype="tokens"> 39 39 units/athen_hero_themistocles 40 40 units/athen_hero_pericles 41 41 units/athen_hero_xenophon 42 42 </Entities> 43 </ TrainingQueue>43 </ProductionQueue> 44 44 <VisualActor> 45 45 <Actor>structures/athenians/prytaneion.xml</Actor> 46 46 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/pers_dock.xml
18 18 <Obstruction> 19 19 <Static width="23.0" depth="15.0"/> 20 20 </Obstruction> 21 < TrainingQueue>21 <ProductionQueue> 22 22 <Entities datatype="tokens"> 23 23 units/pers_ship_bireme 24 24 units/pers_ship_trireme 25 25 </Entities> 26 </ TrainingQueue>26 </ProductionQueue> 27 27 <VisualActor> 28 28 <Actor>structures/persians/dock.xml</Actor> 29 29 </VisualActor> -
binaries/data/mods/public/simulation/templates/structures/rome_barracks.xml
18 18 <Obstruction> 19 19 <Static width="24.0" depth="24.0"/> 20 20 </Obstruction> 21 < TrainingQueue>21 <ProductionQueue> 22 22 <Entities datatype="tokens"> 23 23 units/rome_infantry_swordsman_b 24 24 units/rome_infantry_spearman_a 25 25 units/rome_infantry_javelinist_b 26 26 units/rome_cavalry_spearman_b 27 27 </Entities> 28 </ TrainingQueue>28 </ProductionQueue> 29 29 <VisualActor> 30 30 <FoundationActor>structures/fndn_5x5.xml</FoundationActor> 31 31 <Actor>structures/romans/barracks.xml</Actor> -
binaries/data/mods/public/simulation/templates/structures/cart_embassy.xml
21 21 <Obstruction> 22 22 <Static width="28.0" depth="28.0"/> 23 23 </Obstruction> 24 < TrainingQueue>24 <ProductionQueue> 25 25 <Entities datatype="tokens"> 26 26 units/cart_infantry_swordsman_b 27 27 units/cart_infantry_javelinist_b … … 29 29 units/cart_cavalry_swordsman_b 30 30 units/cart_cavalry_spearman_b 31 31 </Entities> 32 </ TrainingQueue>32 </ProductionQueue> 33 33 <VisualActor> 34 34 <Actor>structures/carthaginians/embassy.xml</Actor> 35 35 <FoundationActor>structures/fndn_5x5.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml
62 62 CivCentre 63 63 </Classes> 64 64 <Icon>structures/civic_centre.png</Icon> 65 <RequiredTechnology>town_phase</RequiredTechnology> 65 66 </Identity> 66 67 <Loot> 67 68 <xp>200</xp> … … 89 90 <Radius>180</Radius> 90 91 <Weight>65536</Weight> 91 92 </TerritoryInfluence> 92 < TrainingQueue>93 <ProductionQueue> 93 94 <Entities datatype="tokens"> 94 95 units/{civ}_support_female_citizen 95 96 </Entities> 96 </TrainingQueue> 97 <Technologies datatype="tokens"> 98 town_phase 99 city_phase 100 plough 101 </Technologies> 102 </ProductionQueue> 97 103 <Vision> 98 104 <Range>90</Range> 99 105 </Vision> -
binaries/data/mods/public/simulation/templates/units/pers_infantry_spearman_b.xml
23 23 <SpecificName>Mada Sparabara</SpecificName> 24 24 <Icon>units/pers_infantry_spearman.png</Icon> 25 25 <History>Mede Shieldbearers comprised the main infantry regiment of the Persians during this period, especially in the reign of Xerxes. First under the Medes and later the Achaemenids these soldiers were the bread and butter infantry for hand-to-hand engagement. Within the Satabam, the basic tactical unit of the Achamenid army, the shieldbearers formed the first two ranks, protecting the arhcers and also serving as a way to keep the enemy pinned down until the cavalry could act. While well known for tenacity the shieldbearers were not equipped to last long in an extended melee with heavy infantry, like hoplites. </History> 26 <RequiredTechnology>town_phase</RequiredTechnology> 26 27 </Identity> 27 28 <Promotion> 28 29 <Entity>units/pers_infantry_spearman_a</Entity> -
binaries/data/mods/public/simulation/templates/units/pers_hero_cyrus.xml
9 9 Hero Aura: "Lead from the Front." Boosts attack of nearby cavalry units.</Tooltip> 10 10 <History>(559 BC - 530 BC) The son of a Median princess and the ruler of Anshan; justly called the 'Father of the Empire', Cyrus the Great conquered Media, Lydia, Babylonia and Bactria, thereby establishing the Persian Empire. He was also renown as a benevolent conqueror. Technically the second ruler of the Persians by that name, and so appears as Kurush II on his documents and coins. Kurush I was his grandfather.</History> 11 11 </Identity> 12 < TrainingQueue>12 <ProductionQueue> 13 13 <Entities datatype="tokens"> 14 14 units/pers_champion_infantry 15 15 </Entities> 16 </ TrainingQueue>16 </ProductionQueue> 17 17 <VisualActor> 18 18 <Actor>units/persians/hero_cyrus.xml</Actor> 19 19 </VisualActor> -
binaries/data/mods/public/simulation/templates/units/athen_ship_trireme.xml
9 9 <History>The first Triremes were built circa 650BC, and by 500BC the Trireme was the most widely used heavy warship of the Greek city-states. In the Trireme the outriggers were now an integral part of the ship's hull. The Trireme also had a partial or full fighting deck above the rowers. The length of the Trireme remained approximately 35-38 meters, and the beam was approximately 3.5 metres. A Trireme carried 170 oarsmen, plus twenty sailors and fourteen marines in Greek navies. The top speed of a Trireme was approximately 11.5 knots. Some Triremes may have been able to reach higher speeds in short bursts. A Trireme travelling from Athens to Mitylene in 427BC made the 350 kilometre trip in only 24 hours, averaging eight knots (14.6 km/h). The Trireme could accelerate much faster than a Bireme or Penteconter, and was much more manoeuvrable. This gave the Trireme an advantage in combat, where higher speed and manoeuvrability meant a better chance of victory.</History> 10 10 <Icon>units/hele_ship_trireme.png</Icon> 11 11 </Identity> 12 < TrainingQueue>12 <ProductionQueue> 13 13 <Entities datatype="tokens"> 14 14 units/athen_champion_marine 15 15 </Entities> 16 </ TrainingQueue>16 </ProductionQueue> 17 17 <VisualActor> 18 18 <Actor>structures/athenians/trireme.xml</Actor> 19 19 </VisualActor> -
binaries/data/mods/public/simulation/templates/template_structure_economic_market.xml
49 49 <Radius>40</Radius> 50 50 <Weight>65536</Weight> 51 51 </TerritoryInfluence> 52 < TrainingQueue>52 <ProductionQueue> 53 53 <Entities datatype="tokens"> 54 54 units/{civ}_support_trader 55 55 </Entities> 56 </ TrainingQueue>56 </ProductionQueue> 57 57 <Vision> 58 58 <Range>32</Range> 59 59 </Vision> -
binaries/data/mods/public/simulation/templates/other/celt_homestead.xml
35 35 <ResourceDropsite> 36 36 <Types>food wood stone metal</Types> 37 37 </ResourceDropsite> 38 < TrainingQueue>38 <ProductionQueue> 39 39 <Entities datatype="tokens"> 40 40 units/celt_cavalry_javelinist_b 41 41 units/celt_infantry_javelinist_b 42 42 units/celt_infantry_spearman_b 43 43 </Entities> 44 </ TrainingQueue>44 </ProductionQueue> 45 45 <TerritoryInfluence> 46 46 <Radius>100</Radius> 47 47 <Weight>65536</Weight> -
binaries/data/mods/public/simulation/templates/other/celt_tavern.xml
39 39 <Radius>32</Radius> 40 40 <Weight>65536</Weight> 41 41 </TerritoryInfluence> 42 < TrainingQueue>42 <ProductionQueue> 43 43 <Entities datatype="tokens"> 44 44 units/celt_fanatic 45 45 </Entities> 46 </ TrainingQueue>46 </ProductionQueue> 47 47 <VisualActor> 48 48 <Actor>structures/celts/tavern.xml</Actor> 49 49 <FoundationActor>structures/fndn_4x4.xml</FoundationActor> -
binaries/data/mods/public/simulation/templates/other/pers_inn.xml
21 21 <TerritoryInfluence> 22 22 <Radius>26</Radius> 23 23 </TerritoryInfluence> 24 < TrainingQueue>24 <ProductionQueue> 25 25 <Entities datatype="tokens"> 26 26 units/{civ}_support_female_citizen 27 27 </Entities> 28 </ TrainingQueue>28 </ProductionQueue> 29 29 <VisualActor> 30 30 <Actor>props/structures/persians/alt_building_04.xml</Actor> 31 31 </VisualActor> -
binaries/data/mods/public/simulation/templates/other/hellenic_royal_stoa.xml
48 48 <Radius>40</Radius> 49 49 <Weight>65536</Weight> 50 50 </TerritoryInfluence> 51 < TrainingQueue>51 <ProductionQueue> 52 52 <Entities datatype="tokens"> 53 53 units/thrace_black_cloak 54 54 units/mace_thorakites 55 55 units/mace_thureophoros 56 56 </Entities> 57 </ TrainingQueue>57 </ProductionQueue> 58 58 <Vision> 59 59 <Range>40</Range> 60 60 <RetainInFog>true</RetainInFog> -
binaries/data/mods/public/simulation/templates/other/pers_apartment_block.xml
21 21 <TerritoryInfluence> 22 22 <Radius>25</Radius> 23 23 </TerritoryInfluence> 24 < TrainingQueue>24 <ProductionQueue> 25 25 <Entities datatype="tokens"> 26 26 units/{civ}_support_female_citizen 27 27 </Entities> 28 </ TrainingQueue>28 </ProductionQueue> 29 29 <VisualActor> 30 30 <Actor>props/structures/persians/alt_building_03.xml</Actor> 31 31 </VisualActor> -
binaries/data/mods/public/simulation/templates/other/cart_tophet.xml
34 34 <Static width="22.0" depth="24.0"/> 35 35 </Obstruction> 36 36 <TerritoryDecay disable=""/> 37 < TrainingQueue>37 <ProductionQueue> 38 38 <Entities datatype="tokens"> 39 39 units/cart_sacred_band_cavalry 40 40 </Entities> 41 </ TrainingQueue>41 </ProductionQueue> 42 42 <Vision> 43 43 <Range>40</Range> 44 44 </Vision> -
binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml
63 63 <Radius>40</Radius> 64 64 <Weight>65536</Weight> 65 65 </TerritoryInfluence> 66 < TrainingQueue>66 <ProductionQueue> 67 67 <Entities datatype="tokens"> 68 68 units/{civ}_support_healer_b 69 69 </Entities> 70 </ TrainingQueue>70 </ProductionQueue> 71 71 <Vision> 72 72 <Range>40</Range> 73 73 </Vision> -
binaries/data/mods/public/simulation/templates/template_structure_military_dock.xml
57 57 </SoundGroups> 58 58 </Sound> 59 59 <TerritoryDecay disable=""/> 60 < TrainingQueue>60 <ProductionQueue> 61 61 <Entities datatype="tokens"> 62 62 units/{civ}_ship_fishing 63 63 units/{civ}_ship_merchant 64 64 </Entities> 65 </ TrainingQueue>65 </ProductionQueue> 66 66 <Vision> 67 67 <Range>40</Range> 68 68 </Vision>