Index: binaries/data/mods/public/simulation/ai/common-api/entity.js =================================================================== --- binaries/data/mods/public/simulation/ai/common-api/entity.js +++ binaries/data/mods/public/simulation/ai/common-api/entity.js @@ -50,8 +50,10 @@ "matchLimit": function() { if (!this.get("TrainingRestrictions")) - return undefined; - return this.get("TrainingRestrictions/MatchLimit"); + return this.get("TrainingRestrictions/MatchLimit"); + if (!this.get("BuildRestrictions")) + return this.get("BuildRestrictions/MatchLimit"); + return undefined; }, "classes": function() { @@ -454,7 +456,10 @@ "walkSpeed": function() { return +this.get("UnitMotion/WalkSpeed"); }, - "trainingCategory": function() { return this.get("TrainingRestrictions/Category"); }, + "limitCategory": function() { + return this.get("TrainingRestrictions/Category") || + this.get("BuildRestrictions/Category"); + }, "buildTime": function(productionQueue) { let time = +this.get("Cost/BuildTime"); @@ -463,8 +468,6 @@ return time; }, - "buildCategory": function() { return this.get("BuildRestrictions/Category"); }, - "buildDistance": function() { let distance = this.get("BuildRestrictions/Distance"); if (!distance) Index: binaries/data/mods/public/simulation/ai/common-api/filters.js =================================================================== --- binaries/data/mods/public/simulation/ai/common-api/filters.js +++ binaries/data/mods/public/simulation/ai/common-api/filters.js @@ -77,6 +77,11 @@ "dynamicProperties": [] }), + "byBuildableEntities": (civ) => ({ + "func": ent => ent.buildableEntities(civ), + "dynamicProperties": [] + }), + "byCanAttackClass": aClass => ({ "func": ent => ent.canAttackClass(aClass), "dynamicProperties": [] Index: binaries/data/mods/public/simulation/ai/common-api/gamestate.js =================================================================== --- binaries/data/mods/public/simulation/ai/common-api/gamestate.js +++ binaries/data/mods/public/simulation/ai/common-api/gamestate.js @@ -587,6 +587,11 @@ return this.updatingGlobalCollection("player-" + this.player + "-research-facilities", m.Filters.byResearchAvailable(this, this.playerData.civ), this.getOwnEntities()); }; +m.GameState.prototype.getOwnBuilders = function() +{ + return this.updatingGlobalCollection("player-" + this.player + "-builders", m.Filters.byBuildableEntities(this.playerData.civ), this.getOwnEntities()); +}; + m.GameState.prototype.countEntitiesByType = function(type, maintain) { @@ -700,45 +705,57 @@ }; /** This returns only units from buildings. */ -m.GameState.prototype.findTrainableUnits = function(classes, anticlasses) +m.GameState.prototype.findCreatableEntities = function(unit, classes, anticlasses) { - let allTrainable = []; + let allCreatable = []; let civ = this.playerData.civ; - this.getOwnTrainingFacilities().forEach(function(ent) { - let trainable = ent.trainableEntities(civ); - if (!trainable) + (unit ? this.getOwnTrainingFacilities() : this.getOwnBuilders()).forEach(function(ent) { + let creatable = unit ? ent.trainableEntities(civ) : ent.buildableEntities(civ); + if (!creatable) return; - for (let unit of trainable) - if (allTrainable.indexOf(unit) === -1) - allTrainable.push(unit); + for (let entity of creatable) + if (allCreatable.indexOf(entity) === -1) + allCreatable.push(entity); }); let ret = []; let limits = this.getEntityLimits(); let current = this.getEntityCounts(); let matchCounts = this.getEntityMatchCounts(); - for (let trainable of allTrainable) + for (let creatable of allCreatable) { - if (this.isTemplateDisabled(trainable)) + if (this.isTemplateDisabled(creatable)) continue; - let template = this.getTemplate(trainable); + let template = this.getTemplate(creatable); if (!template || !template.available(this)) continue; let limit = template.matchLimit(); - if (matchCounts && limit && matchCounts[trainable] >= limit) + if (matchCounts && limit && matchCounts[creatable] >= limit) continue; if (classes.some(c => !template.hasClass(c))) continue; if (anticlasses.some(c => template.hasClass(c))) continue; - let category = template.trainingCategory(); + let category = template.limitCategory(); if (category && limits[category] && current[category] >= limits[category]) continue; - ret.push([trainable, template]); + ret.push([creatable, template]); } return ret; }; +/** This returns only units from buildings. */ +m.GameState.prototype.findTrainableUnits = function(classes, anticlasses) +{ + return this.findCreatableEntities(true, classes, anticlasses); +}; + +/** This returns only structures from units. */ +m.GameState.prototype.findBuildableStructures = function(classes, anticlasses) +{ + return this.findCreatableEntities(false, classes, anticlasses); +}; + /** * Return all techs which can currently be researched * Does not factor cost. Index: binaries/data/mods/public/simulation/ai/petra/headquarters.js =================================================================== --- binaries/data/mods/public/simulation/ai/petra/headquarters.js +++ binaries/data/mods/public/simulation/ai/petra/headquarters.js @@ -2216,7 +2216,7 @@ // build limits let limits = gameState.getEntityLimits(); - let category = template.buildCategory(); + let category = template.limitCategory(); if (category && limits[category] !== undefined && gameState.getEntityCounts()[category] >= limits[category]) { this.buildManager.setUnbuildable(gameState, type, 90, "limit"); Index: binaries/data/mods/public/simulation/ai/petra/navalManager.js =================================================================== --- binaries/data/mods/public/simulation/ai/petra/navalManager.js +++ binaries/data/mods/public/simulation/ai/petra/navalManager.js @@ -791,7 +791,7 @@ if (!template.available(gameState)) continue; - let category = template.trainingCategory(); + let category = template.limitCategory(); if (category && limits[category] && current[category] >= limits[category]) continue;