Ticket #3: technology_20-03-12.2.diff
File technology_20-03-12.2.diff, 116.1 KB (added by , 12 years ago) |
---|
-
source/scriptinterface/ScriptInterface.cpp
1023 1023 return ParseJSON(content); 1024 1024 } 1025 1025 1026 static Status AddToTemplates(const VfsPath& pathname, const FileInfo& UNUSED(fileInfo), const uintptr_t cbData) 1027 { 1028 std::vector<std::string>& templates = *(std::vector<std::string>*)cbData; 1029 1030 // Strip the .json extension 1031 VfsPath pathstem = pathname.ChangeExtension(L""); 1032 // Strip the root from the path 1033 std::wstring name = pathstem.string().substr(ARRAY_SIZE("simulation/data/technologies/")-1); 1034 1035 templates.push_back(std::string(name.begin(), name.end())); 1036 return INFO::OK; 1037 } 1038 1039 std::vector<std::string> ScriptInterface::FindAllTechnologyTemplates() 1040 { 1041 // TODO: eventually this should probably read all the template files and look for flags to 1042 // determine which should be displayed in the editor (and in what categories etc); for now we'll 1043 // just return all the files 1044 1045 std::vector<std::string> templates; 1046 1047 Status ok; 1048 1049 // Find all the normal entity templates first 1050 ok = vfs::ForEachFile(g_VFS, "simulation/data/technologies/", AddToTemplates, (uintptr_t)&templates, L"*.json", vfs::DIR_RECURSIVE); 1051 WARN_IF_ERR(ok); 1052 1053 return templates; 1054 } 1055 1026 1056 struct Stringifier 1027 1057 { 1028 1058 static JSBool callback(const jschar* buf, uint32 len, void* data) -
source/scriptinterface/ScriptInterface.h
230 230 * Read a JSON file. Returns the undefined value on error. 231 231 */ 232 232 CScriptValRooted ReadJSONFile(const VfsPath& path); 233 234 std::vector<std::string> FindAllTechnologyTemplates(); 233 235 234 236 /** 235 237 * Stringify to a JSON string, UTF-8 encoded. Returns an empty string on error. -
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 std::vector<std::string> CComponentManager::Script_FindAllTechnologyTemplates(void* cbdata) 950 { 951 CComponentManager* componentManager = static_cast<CComponentManager*> (cbdata); 952 953 return componentManager->GetScriptInterface().FindAllTechnologyTemplates(); 954 } -
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/public/gui/session/session.xml
730 730 </object> 731 731 732 732 <object name="unitResearchPanel" 733 style="TranslucentPanelThinBorder" 734 size="0 100%-56 100% 100%" 735 type="text" 733 size="14 100%-56 100% 100%" 736 734 > 737 <object size="-5 -2 59 62" type="image" sprite="snIconSheetTab" tooltip_style="sessionToolTipBottom" 738 cell_id="1" tooltip="Research"/> 739 740 [research commands] 735 <object size="0 0 100% 100%"> 736 <repeat count="8"> 737 <object name="unitResearchButton[n]" hidden="true" style="iconButton" type="button" size="0 0 46 46" tooltip_style="sessionToolTipBottom"> 738 <object name="unitResearchIcon[n]" type="image" ghost="true" size="3 3 43 43"/> 739 </object> 740 </repeat> 741 </object> 741 742 </object> 742 743 743 744 <object name="unitTrainingPanel" -
binaries/data/mods/public/gui/session/input.js
737 737 case "hotkeyup": 738 738 if (ev.hotkey == "session.batchtrain") 739 739 { 740 flushTraining QueueBatch();740 flushTrainingBatch(); 741 741 inputState = INPUT_NORMAL; 742 742 } 743 743 break; … … 1169 1169 var batchTrainingCount; 1170 1170 const batchIncrementSize = 5; 1171 1171 1172 function flushTraining QueueBatch()1172 function flushTrainingBatch() 1173 1173 { 1174 1174 Engine.PostNetworkCommand({"type": "train", "entity": batchTrainingEntity, "template": batchTrainingType, "count": batchTrainingCount}); 1175 1175 } 1176 1176 1177 1177 // Called by GUI when user clicks training button 1178 function addT oTrainingQueue(entity, trainEntType)1178 function addTrainingToQueue(entity, trainEntType) 1179 1179 { 1180 1180 if (Engine.HotkeyIsPressed("session.batchtrain")) 1181 1181 { … … 1190 1190 // Otherwise start a new one 1191 1191 else 1192 1192 { 1193 flushTraining QueueBatch();1193 flushTrainingBatch(); 1194 1194 // fall through to create the new batch 1195 1195 } 1196 1196 } … … 1206 1206 } 1207 1207 } 1208 1208 1209 // Called by GUI when user clicks training button 1210 function addResearchToQueue(entity, trainEntType) 1211 { 1212 Engine.PostNetworkCommand({"type": "research", "entity": entity, "template": trainEntType}); 1213 } 1214 1209 1215 // Returns the number of units that will be present in a batch if the user clicks 1210 1216 // the training button with shift down 1211 function getTraining QueueBatchStatus(entity, trainEntType)1217 function getTrainingBatchStatus(entity, trainEntType) 1212 1218 { 1213 1219 if (inputState == INPUT_BATCHTRAINING && batchTrainingEntity == entity && batchTrainingType == trainEntType) 1214 1220 return [batchTrainingCount, batchIncrementSize]; … … 1217 1223 } 1218 1224 1219 1225 // Called by GUI when user clicks production queue item 1220 function removeFrom TrainingQueue(entity, id)1226 function removeFromProductionQueue(entity, id) 1221 1227 { 1222 Engine.PostNetworkCommand({"type": "stop- train", "entity": entity, "id": id});1228 Engine.PostNetworkCommand({"type": "stop-production", "entity": entity, "id": id}); 1223 1229 } 1224 1230 1225 1231 // 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"]; … … 172 173 if (numberOfItems > 24) 173 174 numberOfItems = 24; 174 175 break; 176 177 case RESEARCH: 178 if (numberOfItems > 8) 179 numberOfItems = 8; 180 break; 175 181 176 182 case CONSTRUCTION: 177 183 if (numberOfItems > 24) … … 192 198 for (i = 0; i < numberOfItems; i++) 193 199 { 194 200 var item = items[i]; 195 var entType = ((guiName == "Queue")? item.template : item); 201 202 // If a tech has been researched it leaves an empty slot 203 if (guiName == RESEARCH && !item) 204 { 205 getGUIObjectByName("unit"+guiName+"Button["+i+"]").hidden = true; 206 continue; 207 } 208 196 209 var template; 197 if (guiName != "Formation" && guiName != "Command" && guiName != "Stance") 210 var entType; 211 if (guiName == QUEUE) 198 212 { 199 template = GetTemplateData(entType); 213 // The queue can hold both technologies and units so we need to use the correct code for loading the templates 214 if (item.unitTemplate) 215 { 216 entType = item.unitTemplate; 217 template = GetTemplateData(entType); 218 } 219 else if (item.technologyTemplate) 220 { 221 entType = item.technologyTemplate; 222 template = GetTechnologyData(entType); 223 } 224 200 225 if (!template) 201 continue; // ignore attempts to use invalid templates (an error should have been reported already)226 continue; // ignore attempts to use invalid templates (an error should have been reported already) 202 227 } 228 else 229 { 230 entType = item; 231 if (guiName != FORMATION && guiName != COMMAND && guiName != STANCE && guiName != RESEARCH) 232 { 233 template = GetTemplateData(entType); 234 if (!template) 235 continue; // ignore attempts to use invalid templates (an error should have been reported already) 236 } 237 238 if (guiName == RESEARCH) 239 { 240 template = GetTechnologyData(entType); 241 if (!template) 242 continue; // TODO: should make some kind of warning happen somewhere in the code 243 } 244 } 203 245 204 246 switch (guiName) 205 247 { … … 242 284 if (template.tooltip) 243 285 tooltip += "\n[font=\"serif-13\"]" + template.tooltip + "[/font]"; 244 286 245 var [batchSize, batchIncrement] = getTraining QueueBatchStatus(unitEntState.id, entType);287 var [batchSize, batchIncrement] = getTrainingBatchStatus(unitEntState.id, entType); 246 288 var trainNum = batchSize ? batchSize+batchIncrement : batchIncrement; 247 289 248 290 tooltip += "\n" + getEntityCost(template); … … 259 301 tooltip += "\n\n[font=\"serif-bold-13\"]Shift-click[/font][font=\"serif-13\"] to train " + trainNum + ".[/font]"; 260 302 261 303 break; 304 305 case RESEARCH: 306 var tooltip = getEntityNameWithGenericType(template); 262 307 308 if (template.tooltip) 309 tooltip += "\n[font=\"serif-13\"]" + template.tooltip + "[/font]"; 310 311 tooltip += "\n" + getEntityCost(template); 312 break; 313 263 314 case CONSTRUCTION: 264 315 var tooltip = getEntityNameWithGenericType(template); 265 316 if (template.tooltip) … … 344 395 } 345 396 else if (template.icon) 346 397 { 347 icon.sprite = "stretched:session/portraits/" + template.icon; 398 var grayscale = ""; 399 button.enabled = true; 400 401 if (template.requiredTechnology && !Engine.GuiInterfaceCall("IsTechnologyResearched", template.requiredTechnology)) 402 { 403 button.enabled = false; 404 var techName = getEntityName(GetTechnologyData(template.requiredTechnology)); 405 button.tooltip += "\nRequires " + techName; 406 grayscale = "grayscale:"; 407 } 408 409 if (guiName == RESEARCH && !Engine.GuiInterfaceCall("CheckTechnologyRequirements", entType)) 410 { 411 button.enabled = false; 412 button.tooltip += "\n" + GetTechnologyData(entType).requirementsTooltip; 413 grayscale = "grayscale:"; 414 } 415 416 icon.sprite = "stretched:" + grayscale + "session/portraits/" + template.icon; 348 417 } 349 418 else 350 419 { … … 539 608 setupUnitPanel("Construction", usedPanels, entState, entState.buildEntities, startBuildingPlacement); 540 609 // isInvisible = false; 541 610 } 542 543 if (entState. training && entState.training.entities.length)611 612 if (entState.production && entState.production.entities.length) 544 613 { 545 setupUnitPanel("Training", usedPanels, entState, entState. training.entities,546 function (trainEntType) { addT oTrainingQueue(entState.id, trainEntType); } );614 setupUnitPanel("Training", usedPanels, entState, entState.production.entities, 615 function (trainEntType) { addTrainingToQueue(entState.id, trainEntType); } ); 547 616 // isInvisible = false; 548 617 } 618 619 if (entState.production && entState.production.technologies.length) 620 { 621 setupUnitPanel("Research", usedPanels, entState, entState.production.technologies, 622 function (researchType) { addResearchToQueue(entState.id, researchType); } ); 623 // isInvisible = false; 624 } 549 625 550 if (entState. training && entState.training.queue.length)551 setupUnitPanel("Queue", usedPanels, entState, entState. training.queue,552 function (item) { removeFrom TrainingQueue(entState.id, item.id); } );626 if (entState.production && entState.production.queue.length) 627 setupUnitPanel("Queue", usedPanels, entState, entState.production.queue, 628 function (item) { removeFromProductionQueue(entState.id, item.id); } ); 553 629 554 630 if (entState.trader) 555 631 { -
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
121 121 // Verify that the building can be controlled by the player 122 122 if (CanControlUnit(cmd.entity, player, controlAllUnits)) 123 123 { 124 var queue = Engine.QueryInterface(cmd.entity, IID_TrainingQueue); 125 if (queue) 126 queue.AddBatch(cmd.template, +cmd.count, cmd.metadata); 124 var cmpTechMan = QueryOwnerInterface(cmd.entity, IID_TechnologyManager); 125 // TODO: Enable this check once the AI gets technology support 126 if (cmpTechMan.CanProduce(cmd.template) || true) 127 { 128 var queue = Engine.QueryInterface(cmd.entity, IID_ProductionQueue); 129 if (queue) 130 queue.AddBatch(cmd.template, "unit", +cmd.count, cmd.metadata); 131 } 132 else if (g_DebugCommands) 133 { 134 warn("Invalid command: training requires unresearched technology: " + uneval(cmd)); 135 } 127 136 } 128 137 else if (g_DebugCommands) 129 138 { … … 131 140 } 132 141 break; 133 142 134 case " stop-train":143 case "research": 135 144 // Verify that the building can be controlled by the player 136 145 if (CanControlUnit(cmd.entity, player, controlAllUnits)) 137 146 { 138 var queue = Engine.QueryInterface(cmd.entity, IID_TrainingQueue); 147 var cmpTechMan = QueryOwnerInterface(cmd.entity, IID_TechnologyManager); 148 // TODO: Enable this check once the AI gets technology support 149 if (cmpTechMan.CanResearch(cmd.template) || true) 150 { 151 var queue = Engine.QueryInterface(cmd.entity, IID_ProductionQueue); 152 if (queue) 153 queue.AddBatch(cmd.template, "technology"); 154 } 155 else if (g_DebugCommands) 156 { 157 warn("Invalid command: Requirements to research technology are not met: " + uneval(cmd)); 158 } 159 } 160 else if (g_DebugCommands) 161 { 162 warn("Invalid command: research building cannot be controlled by player "+player+": "+uneval(cmd)); 163 } 164 break; 165 166 case "stop-production": 167 // Verify that the building can be controlled by the player 168 if (CanControlUnit(cmd.entity, player, controlAllUnits)) 169 { 170 var queue = Engine.QueryInterface(cmd.entity, IID_ProductionQueue); 139 171 if (queue) 140 172 queue.RemoveBatch(cmd.id); 141 173 } 142 174 else if (g_DebugCommands) 143 175 { 144 warn("Invalid command: trainingbuilding cannot be controlled by player "+player+": "+uneval(cmd));176 warn("Invalid command: production building cannot be controlled by player "+player+": "+uneval(cmd)); 145 177 } 146 178 break; 147 179 … … 219 251 Engine.DestroyEntity(ent); 220 252 break; 221 253 } 254 255 var cmpTechMan = QueryPlayerIDInterface(player, IID_TechnologyManager); 256 // TODO: Enable this check once the AI gets technology support 257 if (!cmpTechMan.CanProduce(cmd.template) && false) 258 { 259 if (g_DebugCommands) 260 { 261 warn("Invalid command: required technology check failed for player "+player+": "+uneval(cmd)); 262 } 222 263 264 var cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 265 cmpGuiInterface.PushNotification({ "player": player, "message": "Building's technology requirements are not met." }); 266 267 // Remove the foundation because the construction was aborted 268 Engine.DestroyEntity(ent); 269 } 270 223 271 // TODO: AI has no visibility info 224 272 if (!cmpPlayer.IsAI()) 225 273 { -
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(), … … 176 176 ret.buildEntities = cmpBuilder.GetEntitiesList(); 177 177 } 178 178 179 var cmp TrainingQueue = Engine.QueryInterface(ent, IID_TrainingQueue);180 if (cmp TrainingQueue)179 var cmpProductionQueue = Engine.QueryInterface(ent, IID_ProductionQueue); 180 if (cmpProductionQueue) 181 181 { 182 ret.training = { 183 "entities": cmpTrainingQueue.GetEntitiesList(), 184 "queue": cmpTrainingQueue.GetQueue(), 182 ret.production = { 183 "entities": cmpProductionQueue.GetEntitiesList(), 184 "technologies": cmpProductionQueue.GetTechnologiesList(), 185 "queue": cmpProductionQueue.GetQueue(), 185 186 }; 186 187 } 187 188 … … 336 337 }; 337 338 ret.icon = template.Identity.Icon; 338 339 ret.tooltip = template.Identity.Tooltip; 340 ret.requiredTechnology = template.Identity.RequiredTechnology; 339 341 } 340 342 341 343 if (template.UnitMotion) … … 349 351 return ret; 350 352 }; 351 353 354 GuiInterface.prototype.GetTechnologyData = function(player, name) 355 { 356 var cmpTechTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TechnologyTemplateManager); 357 var template = cmpTechTempMan.GetTemplate(name); 358 359 if (!template) 360 return null; 361 362 var ret = {}; 363 364 ret.name = { 365 "specific": template.specificName, 366 "generic": template.genericName, 367 }; 368 ret.icon = template.icon; 369 ret.cost = { 370 "food": +template.cost.food, 371 "wood": +template.cost.wood, 372 "metal": +template.cost.metal, 373 "stone": +template.cost.stone, 374 } 375 ret.tooltip = template.tooltip; 376 377 if (template.requirementsTooltip) 378 ret.requirementsTooltip = template.requirementsTooltip; 379 else 380 ret.requirementsTooltip = ""; 381 382 ret.description = template.description; 383 384 return ret; 385 }; 386 387 GuiInterface.prototype.IsTechnologyResearched = function(player, tech) 388 { 389 var cmpTechMan = QueryPlayerIDInterface(player, IID_TechnologyManager); 390 391 if (!cmpTechMan) 392 return false; 393 394 return cmpTechMan.IsTechnologyResearched(tech); 395 } 396 397 // Checks whether the requirements for this technology have been met 398 GuiInterface.prototype.CheckTechnologyRequirements = function(player, tech) 399 { 400 var cmpTechMan = QueryPlayerIDInterface(player, IID_TechnologyManager); 401 402 if (!cmpTechMan) 403 return false; 404 405 return cmpTechMan.CanResearch(tech); 406 } 407 352 408 GuiInterface.prototype.PushNotification = function(notification) 353 409 { 354 410 this.notifications.push(notification); … … 781 837 "ClearRenamedEntities": 1, 782 838 "GetEntityState": 1, 783 839 "GetTemplateData": 1, 840 "GetTechnologyData": 1, 841 "IsTechnologyResearched": 1, 842 "CheckTechnologyRequirements": 1, 784 843 "GetNextNotification": 1, 785 844 786 845 "CanMoveEntsIntoFormation": 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"); -
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/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
11 11 Engine.LoadComponentScript("interfaces/ResourceDropsite.js"); 12 12 Engine.LoadComponentScript("interfaces/ResourceGatherer.js"); 13 13 Engine.LoadComponentScript("interfaces/ResourceSupply.js"); 14 Engine.LoadComponentScript("interfaces/ TrainingQueue.js");14 Engine.LoadComponentScript("interfaces/ProductionQueue.js"); 15 15 Engine.LoadComponentScript("interfaces/Trader.js") 16 16 Engine.LoadComponentScript("interfaces/Timer.js"); 17 17 Engine.LoadComponentScript("interfaces/StatisticsTracker.js"); … … 57 57 GetPopulationLimit: function() { return 20; }, 58 58 GetMaxPopulation: function() { return 200; }, 59 59 GetResourceCounts: function() { return { food: 100 }; }, 60 IsTraining QueueBlocked: function() { return false; },60 IsTrainingBlocked: function() { return false; }, 61 61 GetState: function() { return "active"; }, 62 62 GetTeam: function() { return -1; }, 63 63 GetDiplomacy: function() { return [-1, 1]; }, … … 104 104 GetPopulationLimit: function() { return 30; }, 105 105 GetMaxPopulation: function() { return 300; }, 106 106 GetResourceCounts: function() { return { food: 200 }; }, 107 IsTraining QueueBlocked: function() { return false; },107 IsTrainingBlocked: function() { return false; }, 108 108 GetState: function() { return "active"; }, 109 109 GetTeam: function() { return -1; }, 110 110 GetDiplomacy: function() { return [-1, 1]; }, … … 156 156 popLimit: 20, 157 157 popMax: 200, 158 158 resourceCounts: { food: 100 }, 159 training QueueBlocked: false,159 trainingBlocked: false, 160 160 state: "active", 161 161 team: -1, 162 162 phase: "", … … 173 173 popLimit: 30, 174 174 popMax: 300, 175 175 resourceCounts: { food: 200 }, 176 training QueueBlocked: false,176 trainingBlocked: false, 177 177 state: "active", 178 178 team: -1, 179 179 phase: "village", … … 197 197 popLimit: 20, 198 198 popMax: 200, 199 199 resourceCounts: { food: 100 }, 200 training QueueBlocked: false,200 trainingBlocked: false, 201 201 state: "active", 202 202 team: -1, 203 203 phase: "", … … 230 230 popLimit: 30, 231 231 popMax: 300, 232 232 resourceCounts: { food: 200 }, 233 training QueueBlocked: false,233 trainingBlocked: false, 234 234 state: "active", 235 235 team: -1, 236 236 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
105 105 this.changes.idle = msg.idle; 106 106 }; 107 107 108 AIProxy.prototype.On TrainingQueueChanged = function(msg)108 AIProxy.prototype.OnProductionQueueChanged = function(msg) 109 109 { 110 110 this.NotifyChange(); 111 111 112 var cmp TrainingQueue = Engine.QueryInterface(this.entity, IID_TrainingQueue);113 this.changes.trainingQueue = cmp TrainingQueue.GetQueue();112 var cmpProductionQueue = Engine.QueryInterface(this.entity, IID_ProductionQueue); 113 this.changes.trainingQueue = cmpProductionQueue.GetQueue(); 114 114 } 115 115 116 116 AIProxy.prototype.OnGarrisonedUnitsChanged = function(msg) … … 170 170 ret.idle = cmpUnitAI.IsIdle(); 171 171 } 172 172 173 var cmp TrainingQueue = Engine.QueryInterface(this.entity, IID_TrainingQueue);174 if (cmp TrainingQueue)173 var cmpProductionQueue = Engine.QueryInterface(this.entity, IID_ProductionQueue); 174 if (cmpProductionQueue) 175 175 { 176 // Updated by On TrainingQueueChanged177 ret.trainingQueue = cmp TrainingQueue.GetQueue();176 // Updated by OnProductionQueueChanged 177 ret.trainingQueue = cmpProductionQueue.GetQueue(); 178 178 } 179 179 180 180 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.allTech = cmpTechTempMan.GetAllTechs(); 10 this.researchedTech = {}; // technologies which have been researched 11 this.inProgressTech = {}; // technologies which are being ersearched currently 12 13 // Some technologies are automatically researched when their conditions are met. They have no cost and are 14 // researched instantly 15 this.autoResearchTech = {}; 16 for (var key in this.allTech) 17 { 18 if (this.allTech[key].autoResearch) 19 this.autoResearchTech[key] = this.allTech[key]; 20 } 21 22 this._UpdateAutoResearch(); 23 }; 24 25 // This fnuction checks if the requirements of any autoresearch techs are met and if they are it researches then 26 TechnologyManager.prototype._UpdateAutoResearch = function () 27 { 28 for (var key in this.autoResearchTech) 29 { 30 if (this.CanResearch(key)) 31 { 32 delete this.autoResearchTech[key]; 33 this.ResearchTechnology(key); 34 return; // We will have recursively handled any knock-on effects so can just return 35 } 36 } 37 } 38 39 TechnologyManager.prototype.GetTechnologyTemplate = function (tech) 40 { 41 return this.allTech[tech]; 42 }; 43 44 // This function checks an entity template to see if it's technology requirements have been met 45 TechnologyManager.prototype.CanProduce = function (templateName) 46 { 47 var cmpTempManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); 48 var template = cmpTempManager.GetTemplate(templateName); 49 50 if (template.Identity && template.Identity.RequiredTechnology) 51 return this.IsTechnologyResearched(template.Identity.RequiredTechnology); 52 else 53 return true; // If there is no required technology then this entity can be produced 54 }; 55 56 TechnologyManager.prototype.IsTechnologyResearched = function (tech) 57 { 58 return (this.researchedTech[tech] !== undefined); 59 }; 60 61 // Checks the requirements for a technology to see if it can be researched at the current time 62 TechnologyManager.prototype.CanResearch = function (tech) 63 { 64 var template = this.GetTechnologyTemplate(tech); 65 if (!template) 66 return false; 67 68 var ret = true; 69 70 // The technology which this tech supercedes is required 71 if (template.supercedes) 72 ret = ret && this.IsTechnologyResearched(template.supercedes); 73 74 ret = ret && this._CheckTechnologyRequirements(template.requirements); 75 76 return ret; 77 }; 78 79 TechnologyManager.prototype._CheckTechnologyRequirements = function (reqs) 80 { 81 // If there are no requirements then they are all met 82 if (!reqs) 83 return true; 84 85 if (reqs.tech) 86 { 87 return this.IsTechnologyResearched(reqs.tech); 88 } 89 else if (reqs.all) 90 { 91 var ret = true; 92 for (var i = 0; i < reqs.all.length; i++) 93 { 94 ret = ret && this._CheckTechnologyRequirements(reqs.all[i]); 95 } 96 return ret; 97 } 98 99 // The technologies requirements are not a recognised format 100 error("Bad requirements " + uneval(reqs)); 101 return false; 102 }; 103 104 // Marks a technology as researched. Note that this does not verify that the requirements are met. 105 TechnologyManager.prototype.ResearchTechnology = function (tech) 106 { 107 this.StoppedResearch(tech); // The tech is no longer being currently researched 108 109 var template = this.GetTechnologyTemplate(tech); 110 if (template) 111 { 112 this.researchedTech[tech] = template; 113 } 114 else 115 { 116 error("Tried to research invalid techonology: " + uneval(tech)); 117 } 118 119 this._UpdateAutoResearch(); 120 }; 121 122 // Marks a technology as being currently researched 123 TechnologyManager.prototype.StartedResearch = function (tech) 124 { 125 this.inProgressTech[tech] = true; 126 }; 127 128 // Marks a technology as not being currently researched 129 TechnologyManager.prototype.StoppedResearch = function (tech) 130 { 131 delete this.inProgressTech[tech]; 132 }; 133 134 // Checks whether a technology is being currently researched 135 TechnologyManager.prototype.IsInProgress = function(tech) 136 { 137 if (this.inProgressTech[tech]) 138 return this.inProgressTech[tech]; 139 else 140 return false; 141 } 142 143 Engine.RegisterComponentType(IID_TechnologyManager, "TechnologyManager", TechnologyManager); 144 No newline at end of file -
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'>" +13 "<optional><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 14 "<attribute name='datatype'>" + 15 15 "<value>tokens</value>" + 16 16 "</attribute>" + 17 17 "<text/>" + 18 "</element>"; 18 "</element></optional>" + 19 "<optional><element name='Technologies' a:help='Space-separated list of technology names that this building can research.'>" + 20 "<attribute name='datatype'>" + 21 "<value>tokens</value>" + 22 "</attribute>" + 23 "<text/>" + 24 "</element></optional>"; 19 25 20 TrainingQueue.prototype.Init = function()26 ProductionQueue.prototype.Init = function() 21 27 { 22 28 this.nextID = 1; 23 29 … … 26 32 // { 27 33 // "id": 1, 28 34 // "player": 1, // who paid for this batch; we need this to cope with refunds cleanly 29 // " template": "units/example",35 // "unitTemplate": "units/example", 30 36 // "count": 10, 31 37 // "resources": { "wood": 100, ... }, // resources per unit, multiply by count to get total 32 38 // "population": 1, // population per unit, multiply by count to get total 33 // " trainingStarted": false, // true iff we have reserved population39 // "productionStarted": false, // true iff we have reserved population 34 40 // "timeTotal": 15000, // msecs 35 41 // "timeRemaining": 10000, // msecs 36 42 // } 43 // 44 // { 45 // "id": 1, 46 // "player": 1, // who paid for this batch; we need this to cope with refunds cleanly 47 // "technologyTemplate": "example_tech", 48 // "resources": { "wood": 100, ... }, // resources per unit, multiply by count to get total 49 // "productionStarted": false, // true iff production has started 50 // "timeTotal": 15000, // msecs 51 // "timeRemaining": 10000, // msecs 52 // } 37 53 38 54 this.timer = undefined; // g_ProgressInterval msec timer, active while the queue is non-empty 39 55 … … 44 60 /* 45 61 * Returns list of entities that can be trained by this building. 46 62 */ 47 TrainingQueue.prototype.GetEntitiesList = function()63 ProductionQueue.prototype.GetEntitiesList = function() 48 64 { 65 if (!this.template.Entities) 66 return []; 67 49 68 var string = this.template.Entities._string; 50 69 51 70 // Replace the "{civ}" codes with this entity's civ ID … … 57 76 }; 58 77 59 78 /* 60 * Adds a new batch of identical units to the training queue.79 * Returns list of technologies that can be researched by this building. 61 80 */ 62 TrainingQueue.prototype.AddBatch = function(templateName, count, metadata)81 ProductionQueue.prototype.GetTechnologiesList = function() 63 82 { 83 if (!this.template.Technologies) 84 return []; 85 86 var string = this.template.Technologies._string; 87 88 var cmpTechMan = QueryOwnerInterface(this.entity, IID_TechnologyManager); 89 if (!cmpTechMan) 90 return []; 91 92 var techs = string.split(/\s+/); 93 var ret = []; 94 var superceded = {}; // Stores the tech which supercedes the key 95 96 // Add any top level technologies to an array which corresponds to the displayed icons 97 // Also store the "children" for the superceding, 98 for (var i in techs) 99 { 100 var tech = techs[i]; 101 var template = cmpTechMan.GetTechnologyTemplate(tech); 102 if (!template.supercedes || techs.indexOf(template.supercedes) === -1) 103 ret.push(tech); 104 else 105 superceded[template.supercedes] = tech; 106 } 107 108 // Now make researched/in progress techs invisible 109 for (var i in ret) 110 { 111 var tech = ret[i]; 112 while (cmpTechMan.IsTechnologyResearched(tech) || cmpTechMan.IsInProgress(tech)) 113 tech = superceded[tech]; 114 115 ret[i] = tech; 116 } 117 118 return ret; 119 }; 120 121 /* 122 * Adds a new batch of identical units to train or a technology to research to the production queue. 123 */ 124 ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadata) 125 { 64 126 // TODO: there should probably be a limit on the number of queued batches 65 127 // TODO: there should be a way for the GUI to determine whether it's going 66 128 // to be possible to add a batch (based on resource costs and length limits) … … 68 130 69 131 if (this.queue.length < MAX_QUEUE_SIZE) 70 132 { 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; 133 134 if (type == "unit") 135 { 136 // Find the template data so we can determine the build costs 137 var cmpTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); 138 var template = cmpTempMan.GetTemplate(templateName); 139 if (!template) 140 return; 141 142 // Apply a time discount to larger batches. 143 // TODO: work out what equation we should use here. 144 var timeMult = Math.pow(count, 0.7); 76 145 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); 146 var time = timeMult * template.Cost.BuildTime; 80 147 81 var time = timeMult * template.Cost.BuildTime; 148 var totalCosts = {}; 149 for each (var r in ["food", "wood", "stone", "metal"]) 150 totalCosts[r] = Math.floor(count * template.Cost.Resources[r]); 82 151 83 var totalCosts = {}; 84 for each (var r in ["food", "wood", "stone", "metal"]) 85 totalCosts[r] = Math.floor(count * template.Cost.Resources[r]); 152 var population = template.Cost.Population; 153 154 // TrySubtractResources should report error to player (they ran out of resources) 155 if (!cmpPlayer.TrySubtractResources(totalCosts)) 156 return; 86 157 87 var population = template.Cost.Population; 88 89 // TrySubtractResources should report error to player (they ran out of resources) 90 if (!cmpPlayer.TrySubtractResources(totalCosts)) 158 this.queue.push({ 159 "id": this.nextID++, 160 "player": cmpPlayer.GetPlayerID(), 161 "unitTemplate": templateName, 162 "count": count, 163 "metadata": metadata, 164 "resources": deepcopy(template.Cost.Resources), // need to copy to avoid serialization problems 165 "population": population, 166 "productionStarted": false, 167 "timeTotal": time*1000, 168 "timeRemaining": time*1000, 169 }); 170 } 171 else if (type == "technology") 172 { 173 // Load the technology template 174 var cmpTechTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TechnologyTemplateManager); 175 var template = cmpTechTempMan.GetTemplate(templateName); 176 if (!template) 177 return; 178 179 var time = template.researchTime; 180 181 var cost = {}; 182 for each (var r in ["food", "wood", "stone", "metal"]) 183 cost[r] = Math.floor(template.cost[r]); 184 185 // TrySubtractResources should report error to player (they ran out of resources) 186 if (!cmpPlayer.TrySubtractResources(cost)) 187 return; 188 189 // Tell the technology manager that we have started researching this so that people can't research the same 190 // thing twice. 191 var cmpTechMan = QueryOwnerInterface(this.entity, IID_TechnologyManager); 192 cmpTechMan.StartedResearch(templateName); 193 194 this.queue.push({ 195 "id": this.nextID++, 196 "player": cmpPlayer.GetPlayerID(), 197 "count": 1, 198 "technologyTemplate": templateName, 199 "resources": deepcopy(template.cost), // need to copy to avoid serialization problems 200 "productionStarted": false, 201 "timeTotal": time*1000, 202 "timeRemaining": time*1000, 203 }); 204 } 205 else 206 { 91 207 return; 208 } 209 210 Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { }); 92 211 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 212 // If this is the first item in the queue, start the timer 108 213 if (!this.timer) 109 214 { 110 215 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 111 this.timer = cmpTimer.SetTimeout(this.entity, IID_ TrainingQueue, "ProgressTimeout", g_ProgressInterval, {});216 this.timer = cmpTimer.SetTimeout(this.entity, IID_ProductionQueue, "ProgressTimeout", g_ProgressInterval, {}); 112 217 } 113 218 } 114 219 else 115 220 { 116 var notification = {"player": cmpPlayer.GetPlayerID(), "message": "The trainingqueue is full."};221 var notification = {"player": cmpPlayer.GetPlayerID(), "message": "The production queue is full."}; 117 222 var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 118 223 cmpGUIInterface.PushNotification(notification); 119 224 } 120 225 }; 121 226 122 227 /* 123 * Removes an existing batch of units from the trainingqueue.228 * Removes an existing batch of units from the production queue. 124 229 * Refunds resource costs and population reservations. 125 230 */ 126 TrainingQueue.prototype.RemoveBatch = function(id)231 ProductionQueue.prototype.RemoveBatch = function(id) 127 232 { 128 233 // Destroy any cached entities (those which didn't spawn for some reason) 129 234 for (var i = 0; i < this.entityCache.length; ++i) … … 139 244 continue; 140 245 141 246 // Now we've found the item to remove 142 247 143 248 var cmpPlayer = QueryPlayerIDInterface(item.player, IID_Player); 144 249 145 250 // Refund the resource cost for this batch 146 251 var totalCosts = {}; 147 252 for each (var r in ["food", "wood", "stone", "metal"]) 148 253 totalCosts[r] = Math.floor(item.count * item.resources[r]); 149 254 150 255 cmpPlayer.AddResources(totalCosts); 151 256 152 257 // Remove reserved population slots if necessary 153 if (item. trainingStarted)258 if (item.productionStarted && item.unitTemplate) 154 259 cmpPlayer.UnReservePopulationSlots(item.population * item.count); 155 260 261 // Mark the research as stopped if we cancel it 262 if (item.technologyTemplate) 263 { 264 var cmpTechMan = QueryOwnerInterface(this.entity, IID_TechnologyManager); 265 cmpTechMan.StoppedResearch(item.technologyTemplate); 266 } 267 156 268 // Remove from the queue 157 269 // (We don't need to remove the timer - it'll expire if it discovers the queue is empty) 158 270 this.queue.splice(i, 1); 159 Engine.PostMessage(this.entity, MT_ TrainingQueueChanged, { });271 Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { }); 160 272 161 273 return; 162 274 } 163 275 }; 164 276 165 277 /* 166 * Returns basic data from all batches in the trainingqueue.278 * Returns basic data from all batches in the production queue. 167 279 */ 168 TrainingQueue.prototype.GetQueue = function()280 ProductionQueue.prototype.GetQueue = function() 169 281 { 170 282 var out = []; 171 283 for each (var item in this.queue) 172 284 { 173 285 out.push({ 174 286 "id": item.id, 175 "template": item.template, 287 "unitTemplate": item.unitTemplate, 288 "technologyTemplate": item.technologyTemplate, 176 289 "count": item.count, 177 290 "progress": 1-(item.timeRemaining/item.timeTotal), 178 291 "metadata": item.metadata, … … 184 297 /* 185 298 * Removes all existing batches from the queue. 186 299 */ 187 TrainingQueue.prototype.ResetQueue = function()300 ProductionQueue.prototype.ResetQueue = function() 188 301 { 189 // Empty the trainingqueue and refund all the resource costs302 // Empty the production queue and refund all the resource costs 190 303 // to the player. (This is to avoid players having to micromanage their 191 304 // buildings' queues when they're about to be destroyed or captured.) 192 305 … … 194 307 this.RemoveBatch(this.queue[0].id); 195 308 }; 196 309 197 TrainingQueue.prototype.OnOwnershipChanged = function(msg)310 ProductionQueue.prototype.OnOwnershipChanged = function(msg) 198 311 { 199 312 if (msg.from != -1) 200 313 { 201 // Unset flag that previous owner's training queuemay be blocked314 // Unset flag that previous owner's training may be blocked 202 315 var cmpPlayer = QueryPlayerIDInterface(msg.from, IID_Player); 203 316 if (cmpPlayer && this.queue.length > 0) 204 cmpPlayer.UnBlockTraining Queue();317 cmpPlayer.UnBlockTraining(); 205 318 } 206 319 207 // Reset the trainingqueue whenever the owner changes.320 // Reset the production queue whenever the owner changes. 208 321 // (This should prevent players getting surprised when they capture 209 322 // an enemy building, and then loads of the enemy's civ's soldiers get 210 323 // created from it. Also it means we don't have to worry about … … 212 325 this.ResetQueue(); 213 326 }; 214 327 215 TrainingQueue.prototype.OnDestroy = function()328 ProductionQueue.prototype.OnDestroy = function() 216 329 { 217 330 // Reset the queue to refund any resources 218 331 this.ResetQueue(); … … 228 341 * This function creates the entities and places them in world if possible. 229 342 * returns the number of successfully spawned entities. 230 343 */ 231 TrainingQueue.prototype.SpawnUnits = function(templateName, count, metadata)344 ProductionQueue.prototype.SpawnUnits = function(templateName, count, metadata) 232 345 { 233 346 var cmpFootprint = Engine.QueryInterface(this.entity, IID_Footprint); 234 347 var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); … … 302 415 }; 303 416 304 417 /* 305 * Increments progress on the first batch in the trainingqueue, and blocks the418 * Increments progress on the first batch in the production queue, and blocks the 306 419 * queue if population limit is reached or some units failed to spawn. 307 420 */ 308 TrainingQueue.prototype.ProgressTimeout = function(data)421 ProductionQueue.prototype.ProgressTimeout = function(data) 309 422 { 310 423 // Allocate the 1000msecs to as many queue items as it takes 311 424 // until we've used up all the time (so that we work accurately … … 316 429 while (time > 0 && this.queue.length) 317 430 { 318 431 var item = this.queue[0]; 319 if (!item. trainingStarted)432 if (!item.productionStarted) 320 433 { 321 // Batch's training hasn't started yet. 322 // Try to reserve the necessary population slots 323 if (!cmpPlayer.TryReservePopulationSlots(item.population * item.count)) 434 // If the item is a unit then do population checks 435 if (item.unitTemplate) 324 436 { 325 // No slots available - don't train this batch now 326 // (we'll try again on the next timeout) 437 // Batch's training hasn't started yet. 438 // Try to reserve the necessary population slots 439 if (item.unitTemplate && !cmpPlayer.TryReservePopulationSlots(item.population * item.count)) 440 { 441 // No slots available - don't train this batch now 442 // (we'll try again on the next timeout) 327 443 328 // Set flag that training queue is blocked 329 cmpPlayer.BlockTrainingQueue(); 330 break; 444 // Set flag that training is blocked 445 cmpPlayer.BlockTraining(); 446 break; 447 } 448 449 // Unset flag that training is blocked 450 cmpPlayer.UnBlockTraining(); 331 451 } 332 452 333 // Unset flag that training queue is blocked 334 cmpPlayer.UnBlockTrainingQueue(); 335 336 item.trainingStarted = true; 453 item.productionStarted = true; 337 454 } 338 455 339 456 // If we won't finish the batch now, just update its timer … … 343 460 break; 344 461 } 345 462 346 var numSpawned = this.SpawnUnits(item.template, item.count, item.metadata); 347 if (numSpawned == item.count) 463 if (item.unitTemplate) 348 464 { 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) 465 var numSpawned = this.SpawnUnits(item.unitTemplate, item.count, item.metadata); 466 if (numSpawned == item.count) 361 467 { 362 // Only partiallyfinished468 // All entities spawned, this batch finished 363 469 cmpPlayer.UnReservePopulationSlots(item.population * numSpawned); 364 item.count -= numSpawned; 365 Engine.PostMessage(this.entity, MT_TrainingQueueChanged, { }); 470 time -= item.timeRemaining; 471 this.queue.shift(); 472 // Unset flag that training is blocked 473 cmpPlayer.UnBlockTraining(); 474 this.spawnNotified = false; 475 Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { }); 366 476 } 477 else 478 { 479 if (numSpawned > 0) 480 { 481 // Only partially finished 482 cmpPlayer.UnReservePopulationSlots(item.population * numSpawned); 483 item.count -= numSpawned; 484 Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { }); 485 } 367 486 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; 487 // Some entities failed to spawn 488 // Set flag that training is blocked 489 cmpPlayer.BlockTraining(); 490 491 if (!this.spawnNotified) 492 { 493 var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); 494 var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Can't find free space to spawn trained units" }; 495 var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 496 cmpGUIInterface.PushNotification(notification); 497 this.spawnNotified = true; 498 } 499 break; 379 500 } 380 break;381 501 } 502 else if (item.technologyTemplate) 503 { 504 var cmpTechnologyManager = QueryOwnerInterface(this.entity, IID_TechnologyManager); 505 cmpTechnologyManager.ResearchTechnology(item.technologyTemplate); 506 507 this.queue.shift(); 508 Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { }); 509 } 382 510 } 383 511 384 512 // If the queue's empty, delete the timer, else repeat it … … 386 514 { 387 515 this.timer = undefined; 388 516 389 // Unset flag that training queueis blocked517 // Unset flag that training is blocked 390 518 // (This might happen when the player unqueues all batches) 391 cmpPlayer.UnBlockTraining Queue();519 cmpPlayer.UnBlockTraining(); 392 520 } 393 521 else 394 522 { 395 523 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 396 this.timer = cmpTimer.SetTimeout(this.entity, IID_ TrainingQueue, "ProgressTimeout", g_ProgressInterval, data);524 this.timer = cmpTimer.SetTimeout(this.entity, IID_ProductionQueue, "ProgressTimeout", g_ProgressInterval, data); 397 525 } 398 526 } 399 527 400 Engine.RegisterComponentType(IID_ TrainingQueue, "TrainingQueue", TrainingQueue);528 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/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 "supercedes": "village_phase", 6 "icon": "technologies/town_phase.png", 7 "researchTime": 10, 8 "tooltip": "Advance to Town Phase" 9 } -
binaries/data/mods/public/simulation/data/technologies/city_phase.json
1 { 2 "genericName": "City Phase", 3 "description": "Advances from a bustling town to a veritable metropolis, full of the wonders of modern technology.", 4 "cost": {"food": 0, "wood": 0, "stone": 50, "metal": 0}, 5 "supercedes": "town_phase", 6 "icon": "technologies/city_phase.png", 7 "researchTime": 10, 8 "tooltip": "Advance to City Phase" 9 } -
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": 100, "wood": 100, "stone": 0, "metal": 50}, 5 "requirements": {"tech": "town_phase"}, 6 "requirementsTooltip": "Requires Town Phase", 7 "icon": "technologies/plough.png", 8 "researchTime": 10, 9 "tooltip": "Discover the Plough" 10 } -
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_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/rome_army_camp.xml
67 67 <HealthDecayRate>5</HealthDecayRate> 68 68 </TerritoryDecay> 69 69 <TerritoryInfluence disable=""/> 70 < TrainingQueue>70 <ProductionQueue> 71 71 <Entities datatype="tokens"> 72 72 units/rome_infantry_swordsman_b 73 73 units/rome_infantry_spearman_a … … 77 77 units/rome_mechanical_siege_scorpio 78 78 units/rome_mechanical_siege_ram 79 79 </Entities> 80 </ TrainingQueue>80 </ProductionQueue> 81 81 <Vision> 82 82 <Range>60</Range> 83 83 </Vision> … … 85 85 <FoundationActor>structures/fndn_8x8.xml</FoundationActor> 86 86 <Actor>structures/romans/camp.xml</Actor> 87 87 </VisualActor> 88 </Entity> 89 No newline at end of file 88 </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/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_apadana.xml
31 31 <Root>true</Root> 32 32 <Radius>38</Radius> 33 33 </TerritoryInfluence> 34 < TrainingQueue>34 <ProductionQueue> 35 35 <Entities datatype="tokens"> 36 36 units/pers_hero_cyrus 37 37 units/pers_hero_darius 38 38 units/pers_hero_xerxes 39 39 units/pers_champion_infantry 40 40 </Entities> 41 </ TrainingQueue>41 </ProductionQueue> 42 42 <VisualActor> 43 43 <Actor>structures/persians/sb1_new.xml</Actor> 44 44 <FoundationActor>structures/fndn_6x6.xml</FoundationActor> -
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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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 <Obstruction> 67 68 <Static width="30.0" depth="30.0"/> … … 81 82 <Radius>180</Radius> 82 83 <Weight>65536</Weight> 83 84 </TerritoryInfluence> 84 < TrainingQueue>85 <ProductionQueue> 85 86 <Entities datatype="tokens"> 86 87 units/{civ}_support_female_citizen 87 88 </Entities> 88 </TrainingQueue> 89 <Technologies datatype="tokens"> 90 town_phase 91 city_phase 92 plough 93 </Technologies> 94 </ProductionQueue> 89 95 <Vision> 90 96 <Range>90</Range> 91 97 </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/template_structure_economic_market.xml
42 42 <Radius>40</Radius> 43 43 <Weight>65536</Weight> 44 44 </TerritoryInfluence> 45 < TrainingQueue>45 <ProductionQueue> 46 46 <Entities datatype="tokens"> 47 47 units/{civ}_support_trader 48 48 </Entities> 49 </ TrainingQueue>49 </ProductionQueue> 50 50 <Vision> 51 51 <Range>32</Range> 52 52 </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/thebes_sacred_band_hoplitai 54 54 units/thespian_melanochitones … … 57 57 units/mace_thorakites 58 58 units/mace_thureophoros 59 59 </Entities> 60 </ TrainingQueue>60 </ProductionQueue> 61 61 <Vision> 62 62 <Range>40</Range> 63 63 <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
56 56 <Radius>40</Radius> 57 57 <Weight>65536</Weight> 58 58 </TerritoryInfluence> 59 < TrainingQueue>59 <ProductionQueue> 60 60 <Entities datatype="tokens"> 61 61 units/{civ}_support_healer_b 62 62 </Entities> 63 </ TrainingQueue>63 </ProductionQueue> 64 64 <Vision> 65 65 <Range>40</Range> 66 66 </Vision> -
binaries/data/mods/public/simulation/templates/template_structure_military_dock.xml
50 50 </SoundGroups> 51 51 </Sound> 52 52 <TerritoryDecay disable=""/> 53 < TrainingQueue>53 <ProductionQueue> 54 54 <Entities datatype="tokens"> 55 55 units/{civ}_ship_fishing 56 56 units/{civ}_ship_merchant 57 57 </Entities> 58 </ TrainingQueue>58 </ProductionQueue> 59 59 <Vision> 60 60 <Range>40</Range> 61 61 </Vision>