Ticket #1432: entitylimits_single_hero_maegereg.diff
File entitylimits_single_hero_maegereg.diff, 27.4 KB (added by , 12 years ago) |
---|
-
binaries/data/mods/public/simulation/components/ProductionQueue.js
212 212 if (!cmpPlayer.TrySubtractResources(totalCosts)) 213 213 return; 214 214 215 //Update player's entity limits to reflect queued units 216 var cmpEntityLimits = QueryOwnerInterface(this.entity, IID_EntityLimits); 217 for (var i = 0; i < count; ++i) 218 { 219 cmpEntityLimits.AddUnitByTemplate(template); 220 } 221 215 222 this.queue.push({ 216 223 "id": this.nextID++, 217 224 "player": cmpPlayer.GetPlayerID(), … … 305 312 306 313 var cmpPlayer = QueryPlayerIDInterface(item.player, IID_Player); 307 314 315 var cmpEntityLimits = QueryOwnerInterface(this.entity, IID_EntityLimits); 316 var cmpTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); 317 cmpEntityLimits.RemoveUnitByTemplate(cmpTempMan.GetTemplate(item.unitTemplate), true); 318 308 319 // Refund the resource cost for this batch 309 320 var totalCosts = {}; 310 321 for each (var r in ["food", "wood", "stone", "metal"]) … … 414 425 // so only create them once and use as needed 415 426 for (var i = 0; i < count; ++i) 416 427 { 417 this.entityCache.push(Engine.AddEntity(templateName)); 428 var ent = Engine.AddEntity(templateName); 429 430 //Remove the virtual unit from the unit count that represented this unit in the queue- it will be replaced by the actual unit being spawned 431 var cmpEntityLimits = QueryOwnerInterface(this.entity, IID_EntityLimits); 432 cmpEntityLimits.RemoveUnit(ent, true); 433 434 this.entityCache.push(ent); 418 435 } 419 436 } 420 437 -
binaries/data/mods/public/simulation/components/EntityLimit.js
1 function EntityLimit() {} 2 3 EntityLimit.prototype.Schema = 4 "<a:help>Specifies the number of this unit that can be build, and the categories of units that count toward the limit</a:help>" + 5 "<a:example>" + 6 "<ConcurrentLimit>" + 7 "<Limit>" + 8 "5" + 9 "</Limit>" + 10 "<Classes> Hero </Classes>" + 11 "</ConcurrentLimit>" + 12 "</a:example>" + 13 "<interleave>" + 14 "<optional>" + 15 "<element name='ConcurrentLimit' a:help='A limit on the number of this unit that can be built by a player at any one time.'>"+ 16 "<interleave>" + 17 "<element name='Limit'>" + 18 "<data type='positiveInteger' />" + 19 "</element>" + 20 "<optional>" + 21 "<element name='Classes'>" + 22 "<attribute name='datatype'>" + 23 "<value>tokens</value>" + 24 "</attribute>" + 25 "<text/>" + 26 "</element>" + 27 "</optional>" + 28 "</interleave>" + 29 "</element>" + 30 "</optional>" + 31 "<optional>" + 32 "<element name='TotalLimit' a:help='A limit on the total number of this unit that can be built by a player during a game.'>" + 33 "<interleave>" + 34 "<element name='Limit'>" + 35 "<data type='positiveInteger' />" + 36 "</element>" + 37 "<optional>"+ 38 "<element name='Classes' a:help='See Classes under ConcurrentLimit'>" + 39 "<attribute name='datatype'>" + 40 "<value>tokens</value>" + 41 "</attribute>" + 42 "<text />" + 43 "</element>" + 44 "</optional>" + 45 "</interleave>" + 46 "</element>" + 47 "</optional>" + 48 "</interleave>"; 49 50 EntityLimit.prototype.Init = function() 51 { 52 }; 53 54 /* 55 Return value of 0 indicates no limit 56 */ 57 EntityLimit.prototype.GetConcurrentLimit = function() 58 { 59 if(this.template.ConcurrentLimit) 60 { 61 return this.template.ConcurrentLimit.Limit; 62 } 63 return 0; 64 } 65 66 /* 67 Empty list return value indicates no classes 68 */ 69 EntityLimit.prototype.GetConcurrentLimitClasses = function() 70 { 71 if(this.template.ConcurrentLimit && this.template.ConcurrentLimit.Classes && "_string" in this.template.ConcurrentLimit.Classes) 72 { 73 var string = this.template.ConcurrentLimit.Classes._string; 74 return string.split(/\s+/); 75 } 76 return []; 77 } 78 79 /* 80 Return value of 0 indicates no limit 81 */ 82 EntityLimit.prototype.GetTotalLimit = function() 83 { 84 if(this.template.TotalLimit) 85 { 86 return this.template.TotalLimit.Limit; 87 } 88 return 0; 89 } 90 91 /* 92 Empty list return value indicates no classes 93 */ 94 EntityLimit.prototype.GetTotalLimitClasses = function() 95 { 96 if(this.template.TotalLimit && this.template.TotalLimit.Classes && "_string" in this.template.TotalLimit.Classes) 97 { 98 var string = this.template.TotalLimit.Classes._string; 99 return string.split(/\s+/); 100 } 101 return []; 102 } 103 104 Engine.RegisterComponentType(IID_EntityLimit, "EntityLimit", EntityLimit); 105 No newline at end of file -
binaries/data/mods/public/simulation/components/GuiInterface.js
122 122 return ret; 123 123 }; 124 124 125 GuiInterface.prototype.AllowedToBuild = function(player, template) 126 { 127 var cmpPlayerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager); 128 var cmpEntityLimits = Engine.QueryInterface(cmpPlayerMan.GetPlayerByID(player), IID_EntityLimits); 129 return cmpEntityLimits.AllowedToBuild(template); 130 }; 131 125 132 GuiInterface.prototype.GetRenamedEntities = function(player) 126 133 { 127 134 return this.renamedEntities; … … 385 392 if (template.Cost.PopulationBonus) ret.cost.populationBonus = GetTechModifiedProperty(techMods, template, "Cost/PopulationBonus", +template.Cost.PopulationBonus); 386 393 } 387 394 395 if (template.EntityLimit) 396 { 397 ret.entityLimit = {}; 398 if (template.EntityLimit.ConcurrentLimit) 399 { 400 ret.EntityLimit = template.EntityLimit; 401 } 402 } 403 388 404 if (template.Footprint) 389 405 { 390 406 ret.footprint = {"height": template.Footprint.Height}; … … 442 458 ret.icon = template.Identity.Icon; 443 459 ret.tooltip = template.Identity.Tooltip; 444 460 ret.requiredTechnology = template.Identity.RequiredTechnology; 461 if(template.Identity.Classes) 462 { 463 ret.classes = template.Identity.Classes; 464 } 445 465 } 446 466 447 467 if (template.UnitMotion) … … 1571 1585 1572 1586 "GetSimulationState": 1, 1573 1587 "GetExtendedSimulationState": 1, 1588 "AllowedToBuild": 1, 1574 1589 "GetRenamedEntities": 1, 1575 1590 "ClearRenamedEntities": 1, 1576 1591 "GetEntityState": 1, -
binaries/data/mods/public/simulation/components/Identity.js
87 87 return this.template.Civ; 88 88 }; 89 89 90 Identity.prototype.GetGenericName = function() 91 { 92 return this.template.GenericName; 93 }; 94 90 95 Identity.prototype.GetRank = function() 91 96 { 92 97 return (this.template.Rank || ""); -
binaries/data/mods/public/simulation/components/EntityLimits.js
1 function EntityLimits() {} 2 3 EntityLimits.prototype.schema = 4 "<a:help>Tracks limits on numbers of certain units that can be built</a:help>" + 5 "<a:component type='system'/><empty/>"; 6 7 EntityLimits.prototype.Init = function() 8 { 9 this.CurrentClassCounts = {}; 10 this.TotalClassCounts = {}; 11 this.CurrentEntityCounts = {}; 12 this.TotalEntityCounts = {}; 13 }; 14 15 /*Add a newly created unit to the counts via its entity*/ 16 EntityLimits.prototype.AddUnit = function(entity) 17 { 18 var cmpIdentity = Engine.QueryInterface(entity, IID_Identity); 19 if(cmpIdentity) 20 { 21 var classes = cmpIdentity.GetClassesList(); 22 var entityName = cmpIdentity.GetGenericName(); 23 this.Add(entityName, classes); 24 } 25 }; 26 27 /*Remove a unit from the counts via its entity 28 removeTotals should be true to force the unit to be removed from Total count tables. 29 Normally this is not desired- we want to keep track of all the units that have ever 30 been built in those tables. Only set it to true if the unit is being replaced (as in 31 the production queue). Do not include the parameter if you don't want to remove from totals.*/ 32 EntityLimits.prototype.RemoveUnit = function(entity, removeTotals) 33 { 34 var cmpIdentity = Engine.QueryInterface(entity, IID_Identity); 35 if(cmpIdentity) 36 { 37 var classes = cmpIdentity.GetClassesList(); 38 var entityName = cmpIdentity.GetGenericName(); 39 this.Remove(entityName, classes); 40 if (removeTotals) 41 { 42 this.RemoveTotals(entityName, classes); 43 } 44 } 45 }; 46 47 /*Adds a unit based on its template. Can either use the gui interface template, or the actual template*/ 48 EntityLimits.prototype.AddUnitByTemplate = function(template) 49 { 50 var classes = []; 51 if (template.classes && template.classes._string) 52 { 53 classes = template.classes._string.split(/\s/); 54 } 55 else if (template.Identity && template.Identity.Classes && template.Identity.Classes._string) 56 { 57 classes = template.Identity.Classes._string.split(/\s/); 58 } 59 if (template.name) 60 { 61 var entityName = template.name.generic; 62 } 63 else if (template.Identity) 64 { 65 var entityName = template.Identity.GenericName; 66 } 67 this.Add(entityName, classes); 68 }; 69 70 /*Removed a unit based on its template. Can either use the gui interface template, or the actual template 71 removeTotals- see the same parameter on RemoveUnit*/ 72 EntityLimits.prototype.RemoveUnitByTemplate = function(template, removeTotals) 73 { 74 var classes = []; 75 if (template.classes && template.classes._string) 76 { 77 classes = template.classes._string.split(/\s/); 78 } 79 else if (template.Identity && template.Identity.Classes && template.Identity.Classes._string) 80 { 81 classes = template.Identity.Classes._string.split(/\s/); 82 } 83 if (template.name) 84 { 85 var entityName = template.name.generic; 86 } 87 else if (template.Identity) 88 { 89 var entityName = template.Identity.GenericName; 90 } 91 this.Remove(entityName, classes); 92 if (removeTotals) 93 { 94 this.RemoveTotals(entityName, classes); 95 } 96 } 97 98 /*Internal function for adding a unit. Do not call directly.*/ 99 EntityLimits.prototype.Add = function(entityName, classes) 100 { 101 if (!(entityName in this.CurrentEntityCounts) || (isNaN(this.CurrentEntityCounts[entityName]))) 102 { 103 this.CurrentEntityCounts[entityName] = 1; 104 } 105 else 106 { 107 ++this.CurrentEntityCounts[entityName]; 108 } 109 if (!(entityName in this.TotalEntityCounts) || (isNaN(this.TotalEntityCounts[entityName]))) 110 { 111 this.TotalEntityCounts[entityName] = 1; 112 } 113 else 114 { 115 ++this.TotalEntityCounts[entityName]; 116 } 117 for (var i = 0; i<classes.length; ++i) 118 { 119 var entityClass = classes[i]; 120 if (!(entityClass in this.CurrentClassCounts) || (isNaN(this.CurrentClassCounts[entityClass]))) 121 { 122 this.CurrentClassCounts[entityClass] = 1; 123 } 124 else 125 { 126 ++this.CurrentClassCounts[entityClass]; 127 } 128 if (!(entityClass in this.TotalClassCounts) || (isNaN(this.TotalClassCounts[entityClass]))) 129 { 130 this.TotalClassCounts[entityClass] = 1; 131 } 132 else 133 { 134 ++this.TotalClassCounts[entityClass]; 135 } 136 } 137 }; 138 139 /*Internal function for removing a unit. Do not call directly.*/ 140 EntityLimits.prototype.Remove = function(entityName, classes) 141 { 142 if (!(entityName in this.CurrentEntityCounts) || (isNaN(this.CurrentEntityCounts[entityName]))) 143 { 144 this.CurrentEntityCounts[entityName] = 0; 145 } 146 else 147 { 148 --this.CurrentEntityCounts[entityName]; 149 } 150 for (var i = 0; i<classes.length; ++i) 151 { 152 var entityClass = classes[i]; 153 if (!(entityClass in this.CurrentClassCounts) || (isNaN(this.CurrentClassCounts[entityClass]))) 154 { 155 this.CurrentClassCounts[entityClass] = 0; 156 } 157 else 158 { 159 --this.CurrentClassCounts[entityClass]; 160 } 161 } 162 }; 163 164 /*Internal function for removing a unit from the total counts. Do not call directly.*/ 165 EntityLimits.prototype.RemoveTotals= function(entityName, classes) 166 { 167 if (!(entityName in this.TotalEntityCounts) || (isNaN(this.TotalEntityCounts[entityName]))) 168 { 169 this.TotalEntityCounts[entityName] = 0; 170 } 171 else 172 { 173 --this.TotalEntityCounts[entityName]; 174 } 175 for (var i = 0; i<classes.length; ++i) 176 { 177 var entityClass = classes[i]; 178 if (!(entityClass in this.TotalClassCounts) || (isNaN(this.TotalClassCounts[entityClass]))) 179 { 180 this.TotalClassCounts[entityClass] = 0; 181 } 182 else 183 { 184 --this.TotalClassCounts[entityClass]; 185 } 186 } 187 }; 188 189 EntityLimits.prototype.GetCurrentEntityCount = function(entityName) 190 { 191 if (entityName in this.CurrentEntityCounts) 192 { 193 return this.CurrentEntityCounts[entityName]; 194 } 195 return 0; 196 }; 197 198 EntityLimits.prototype.GetCurrentClassCount = function(className) 199 { 200 if (className in this.CurrentClassCounts) 201 { 202 return this.CurrentClassCounts[className]; 203 } 204 return 0; 205 }; 206 207 EntityLimits.prototype.GetTotalEntityCount = function(entityName) 208 { 209 if (entityName in this.TotalEntityCounts) 210 { 211 return this.TotalEntityCounts[entityName]; 212 } 213 return 0; 214 }; 215 216 EntityLimits.prototype.GetTotalClassCount = function(className) 217 { 218 if (className in this.TotalClassCounts) 219 { 220 return this.TotalClassCounts[className]; 221 } 222 return 0; 223 }; 224 225 /*Checks if the unit can be built, based on a gui-interface template. It would be relatively trivial to change this to work on actual templates too. 226 Will return false if a unit cannot be built because its limits are currently exceeded.*/ 227 EntityLimits.prototype.AllowedToBuild = function(template) 228 { 229 if (template.EntityLimit){ 230 /*Total limits are placed first because if both total and concurrent limits are present, total limits are more likely to be exceeded*/ 231 var entityName = template.name.generic; 232 if (template.EntityLimit.TotalLimit) 233 { 234 var totalLimit = template.EntityLimit.TotalLimit.Limit; 235 if (this.GetTotalEntityCount(entityName) >= totalLimit) 236 { 237 return false; 238 } 239 if (template.EntityLimit.TotalLimit.Classes && "_string" in template.EntityLimit.TotalLimit.Classes) 240 { 241 var limitClasses = template.EntityLimit.TotalLimit.Classes._string.split(/\s/); 242 var entityClasses = []; 243 if (template.classes && "_string" in template.classes) 244 { 245 entityClasses = template.classes._string.split(/\s/); 246 } 247 var intersections = 0; 248 var curNumber = this.GetTotalEntityCount(entityName); 249 for (var i =0; i<limitClasses.length; ++i) 250 { 251 curNumber = curNumber+this.GetTotalClassCount(limitClasses[i]); 252 if (entityClasses.indexOf(limitClasses[i]) != -1) 253 { 254 ++intersections; 255 } 256 } 257 curNumber = curNumber - intersections*this.GetTotalEntityCount(entityName); 258 if (curNumber >= totalLimit) 259 { 260 return false; 261 } 262 } 263 } 264 if (template.EntityLimit.ConcurrentLimit) 265 { 266 var concurrentLimit = template.EntityLimit.ConcurrentLimit.Limit; 267 var entityName = template.name.generic; 268 if (this.GetCurrentEntityCount(entityName) >= concurrentLimit) 269 { 270 return false; 271 } 272 if (template.EntityLimit.ConcurrentLimit.Classes && "_string" in template.EntityLimit.ConcurrentLimit.Classes) 273 { 274 var limitClasses = template.EntityLimit.ConcurrentLimit.Classes._string.split(/\s/); 275 var entityClasses = []; 276 if (template.classes && "_string" in template.classes) 277 { 278 entityClasses = template.classes._string.split(/\s/); 279 } 280 var intersections = 0; 281 var curNumber = this.GetCurrentEntityCount(entityName); 282 for (var i =0; i<limitClasses.length; ++i) 283 { 284 curNumber = curNumber+this.GetCurrentClassCount(limitClasses[i]); 285 if (entityClasses.indexOf(limitClasses[i]) != -1) 286 { 287 ++intersections; 288 } 289 } 290 curNumber = curNumber - intersections*this.GetCurrentEntityCount(entityName); 291 if (curNumber >= concurrentLimit) 292 { 293 return false; 294 } 295 } 296 } 297 } 298 return true; 299 }; 300 301 /* 302 Does not prevent ownership change, even if the change would exceed limits 303 */ 304 EntityLimits.prototype.OnGlobalOwnershipChanged = function(msg) 305 { 306 var playerID = Engine.QueryInterface(this.entity, IID_Player).GetPlayerID(); 307 if (msg.from == playerID) 308 { 309 this.RemoveUnit(msg.entity); 310 } 311 else if (msg.to == playerID) 312 { 313 this.AddUnit(msg.entity); 314 } 315 }; 316 317 Engine.RegisterComponentType(IID_EntityLimits, "EntityLimits", EntityLimits); 318 No newline at end of file -
binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_swordsman.xml
48 48 </Bonuses> 49 49 </Charge> 50 50 </Attack> 51 <EntityLimit> 52 <ConcurrentLimit> 53 <Limit>1</Limit> 54 <Classes datatype="tokens">Hero</Classes> 55 </ConcurrentLimit> 56 </EntityLimit> 51 57 <Identity> 52 58 <Classes datatype="tokens">Melee Sword</Classes> 53 59 <GenericName>Hero Swordsman</GenericName> -
binaries/data/mods/public/simulation/templates/template_unit_hero_infantry.xml
27 27 <metal>200</metal> 28 28 </Resources> 29 29 </Cost> 30 <EntityLimit> 31 <ConcurrentLimit> 32 <Limit>1</Limit> 33 <Classes datatype="tokens">Hero</Classes> 34 </ConcurrentLimit> 35 </EntityLimit> 30 36 <Footprint> 31 37 <Circle radius="2.0"/> 32 38 <Height>2.5</Height> -
binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_archer.xml
44 44 <Max>500</Max> 45 45 <RegenRate>0.5</RegenRate> 46 46 </Health> 47 <EntityLimit> 48 <ConcurrentLimit> 49 <Limit>1</Limit> 50 <Classes>Hero</Classes> 51 </ConcurrentLimit> 52 </EntityLimit> 47 53 <Identity> 48 54 <Classes datatype="tokens">Hero Bow -Javelin</Classes> 49 55 <GenericName>Hero Cavalry Archer</GenericName> -
binaries/data/mods/public/simulation/templates/template_structure_defense_defense_tower.xml
32 32 <stone>100</stone> 33 33 </Resources> 34 34 </Cost> 35 <EntityLimit> 36 <ConcurrentLimit> 37 <Limit> 38 25 39 </Limit> 40 </ConcurrentLimit> 41 </EntityLimit> 35 42 <Footprint> 36 43 <Square width="10.0" depth="10.0"/> 37 44 <Height>15.0</Height> -
binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_javelinist.xml
28 28 <metal>75</metal> 29 29 </Resources> 30 30 </Cost> 31 <EntityLimit> 32 <ConcurrentLimit> 33 <Limit>1</Limit> 34 <Classes>Hero</Classes> 35 </ConcurrentLimit> 36 </EntityLimit> 31 37 <Footprint> 32 38 <Circle radius="3.0"/> 33 39 <Height>3.0</Height> -
binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry.xml
29 29 <metal>250</metal> 30 30 </Resources> 31 31 </Cost> 32 <EntityLimit> 33 <ConcurrentLimit> 34 <Limit>1</Limit> 35 <Classes datatype="tokens">Hero </Classes> 36 </ConcurrentLimit> 37 </EntityLimit> 32 38 <Footprint> 33 39 <Circle radius="3.0"/> 34 40 <Height>3.0</Height> -
binaries/data/mods/public/simulation/templates/special/player.xml
8 8 <Fortress>10</Fortress> 9 9 </Limits> 10 10 </BuildLimits> 11 <EntityLimits /> 11 12 <Player/> 12 13 <StatisticsTracker/> 13 14 <TechnologyManager/> -
binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_javelinist.xml
34 34 <wood>200</wood> 35 35 </Resources> 36 36 </Cost> 37 <EntityLimit> 38 <ConcurrentLimit> 39 <Limit>1</Limit> 40 <Classes datatype="tokens">Hero</Classes> 41 </ConcurrentLimit> 42 </EntityLimit> 37 43 <Footprint> 38 44 <Circle radius="2.0"/> 39 45 <Height>2.5</Height> -
binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml
33 33 <stone>650</stone> 34 34 </Resources> 35 35 </Cost> 36 <EntityLimit> 37 <ConcurrentLimit> 38 <Limit>10</Limit> 39 </ConcurrentLimit> 40 </EntityLimit> 36 41 <Footprint> 37 42 <Square width="30.0" depth="30.0"/> 38 43 <Height>8.0</Height> -
binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_spearman.xml
23 23 </Bonuses> 24 24 </Charge> 25 25 </Attack> 26 <EntityLimit> 27 <ConcurrentLimit> 28 <Limit>1</Limit> 29 <Classes datatype="tokens">Hero</Classes> 30 </ConcurrentLimit> 31 </EntityLimit> 26 32 <Identity> 27 33 <Classes datatype="tokens">Melee Spear</Classes> 28 34 <GenericName>Hero Spearman</GenericName> -
binaries/data/mods/public/simulation/templates/template_unit_hero.xml
29 29 <metal>250</metal> 30 30 </Resources> 31 31 </Cost> 32 <EntityLimit> 33 <ConcurrentLimit> 34 <Limit>1</Limit> 35 <Classes datatype="tokens">Hero</Classes> 36 </ConcurrentLimit> 37 </EntityLimit> 32 38 <Health> 33 39 <Max>400</Max> 34 40 <RegenRate>0.5</RegenRate> -
binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_spearman.xml
61 61 <PreferredClasses datatype="tokens">Organic Siege</PreferredClasses> 62 62 </Charge> 63 63 </Attack> 64 <EntityLimit> 65 <ConcurrentLimit> 66 <Limit>1</Limit> 67 <Classes>Hero</Classes> 68 </ConcurrentLimit> 69 </EntityLimit> 64 70 <Identity> 65 71 <Classes datatype="tokens">Melee Spear</Classes> 66 72 <GenericName>Hero Cavalry Spearman</GenericName> -
binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_pikeman.xml
30 30 </Bonuses> 31 31 </Charge> 32 32 </Attack> 33 <EntityLimit> 34 <ConcurrentLimit> 35 <Limit>1</Limit> 36 <Classes datatype="tokens">Hero</Classes> 37 </ConcurrentLimit> 38 </EntityLimit> 33 39 <Identity> 34 40 <Classes datatype="tokens">Melee Spear</Classes> 35 41 <GenericName>Hero Pikeman</GenericName> -
binaries/data/mods/public/simulation/templates/template_unit_hero_ranged.xml
24 24 <wood>500</wood> 25 25 </Resources> 26 26 </Cost> 27 <EntityLimit> 28 <ConcurrentLimit> 29 <Limit>1</Limit> 30 <Classes datatype="tokens">Hero</Classes> 31 </ConcurrentLimit> 32 </EntityLimit> 27 33 <Health> 28 34 <Max>400</Max> 29 35 <RegenRate>0.2</RegenRate> -
binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_archer.xml
28 28 <wood>200</wood> 29 29 </Resources> 30 30 </Cost> 31 <EntityLimit> 32 <ConcurrentLimit> 33 <Limit>1</Limit> 34 <Classes datatype="tokens">Hero</Classes> 35 </ConcurrentLimit> 36 </EntityLimit> 31 37 <Footprint> 32 38 <Circle radius="2.0"/> 33 39 <Height>2.5</Height> -
binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_swordsman.xml
48 48 <PreferredClasses datatype="tokens">Organic Siege</PreferredClasses> 49 49 </Charge> 50 50 </Attack> 51 <EntityLimit> 52 <ConcurrentLimit> 53 <Limit>1</Limit> 54 <Classes>Hero</Classes> 55 </ConcurrentLimit> 56 </EntityLimit> 51 57 <Identity> 52 58 <Classes datatype="tokens">Sword</Classes> 53 59 <GenericName>Hero Cavalry Swordsman</GenericName> -
binaries/data/mods/public/gui/session/unit_commands.js
538 539 button.tooltip += "\nRequires " + techName; 539 540 grayscale = "grayscale:"; 540 541 } 541 542 if (guiName == TRAINING && template.EntityLimit) 543 { 544 if (!Engine.GuiInterfaceCall("AllowedToBuild", template)) 545 { 546 grayscale = "grayscale:"; 547 button.enabled = false; 548 button.tooltip += "\nLimit Reached: No more can be produced"; 549 } 550 } 542 551 if (guiName == RESEARCH && !Engine.GuiInterfaceCall("CheckTechnologyRequirements", entType)) 543 552 { 544 553 button.enabled = false;