diff --git a/binaries/data/mods/public/simulation/ai/common-api/entity.js b/binaries/data/mods/public/simulation/ai/common-api/entity.js index 73fdab498e..9a0da27cb2 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/entity.js +++ b/binaries/data/mods/public/simulation/ai/common-api/entity.js @@ -329,15 +329,16 @@ m.Template = m.Class({ return templates; // TODO: map to Entity? }, - trainableEntities: function() { + trainableEntities: function(civ) { if (!this.get("ProductionQueue/Entities/_string")) return undefined; - var civ = this.civ(); var templates = this.get("ProductionQueue/Entities/_string").replace(/\{civ\}/g, civ).split(/\s+/); return templates; }, - researchableTechs: function() { + researchableTechs: function(civ) { + if (this.civ() !== civ) // techs can only be researched in structure from the player civ + return undefined; if (!this.get("ProductionQueue/Technologies/_string")) return undefined; var templates = this.get("ProductionQueue/Technologies/_string").split(/\s+/); @@ -865,9 +866,9 @@ m.Entity = m.Class({ return this; }, - train: function(type, count, metadata, promotedTypes) + train: function(civ, type, count, metadata, promotedTypes) { - var trainable = this.trainableEntities(); + var trainable = this.trainableEntities(civ); if (!trainable) { error("Called train("+type+", "+count+") on non-training entity "+this); diff --git a/binaries/data/mods/public/simulation/ai/common-api/filters.js b/binaries/data/mods/public/simulation/ai/common-api/filters.js index 5c6f7942b5..2d09335b02 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/filters.js +++ b/binaries/data/mods/public/simulation/ai/common-api/filters.js @@ -115,9 +115,9 @@ m.Filters = { }, "dynamicProperties": ['trainingQueue']}; }, - byResearchAvailable: function(){ + byResearchAvailable: function(civ){ return {"func" : function(ent){ - return ent.researchableTechs() !== undefined; + return ent.researchableTechs(civ) !== undefined; }, "dynamicProperties": []}; }, diff --git a/binaries/data/mods/public/simulation/ai/common-api/gamestate.js b/binaries/data/mods/public/simulation/ai/common-api/gamestate.js index 15f8b8c658..5d2cc8e313 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/gamestate.js +++ b/binaries/data/mods/public/simulation/ai/common-api/gamestate.js @@ -460,7 +460,7 @@ m.GameState.prototype.getOwnTrainingFacilities = function(){ }; m.GameState.prototype.getOwnResearchFacilities = function(){ - return this.updatingGlobalCollection("" + this.player + "-research-facilities", m.Filters.byResearchAvailable(), this.getOwnEntities()); + return this.updatingGlobalCollection("" + this.player + "-research-facilities", m.Filters.byResearchAvailable(this.playerData.civ), this.getOwnEntities()); }; @@ -565,11 +565,12 @@ m.GameState.prototype.getFishableSupplies = function(){ m.GameState.prototype.findTrainableUnits = function(classes, anticlasses) { var allTrainable = []; + var civ = this.playerData.civ; this.getOwnStructures().forEach(function(ent) { - var trainable = ent.trainableEntities(); + var trainable = ent.trainableEntities(civ); if (!trainable) return; - for (var unit of trainable) + for (let unit of trainable) if (allTrainable.indexOf(unit) === -1) allTrainable.push(unit); }); @@ -580,7 +581,7 @@ m.GameState.prototype.findTrainableUnits = function(classes, anticlasses) { let template = this.getTemplate(trainable); - if (!template.available(this)) + if (!template || !template.available(this)) continue; if (this.isDisabledTemplates(trainable)) continue; @@ -620,9 +621,10 @@ m.GameState.prototype.findTrainableUnits = function(classes, anticlasses) // If there are pairs, both techs are returned. m.GameState.prototype.findAvailableTech = function() { - let allResearchable = []; + var allResearchable = []; + var civ = this.playerData.civ; this.getOwnEntities().forEach(function(ent) { - let searchable = ent.researchableTechs(); + let searchable = ent.researchableTechs(civ); if (!searchable) return; for (let tech of searchable) @@ -650,13 +652,13 @@ m.GameState.prototype.findAvailableTech = function() }; /** - * Find buildings that are capable of training said template. - * Getting the best is up to the AI. + * Find buildings that are capable of training that template. */ m.GameState.prototype.findTrainers = function(template) { + var civ = this.playerData.civ; return this.getOwnTrainingFacilities().filter(function(ent) { - let trainable = ent.trainableEntities(); + let trainable = ent.trainableEntities(civ); if (!trainable || trainable.indexOf(template) == -1) return false; return true; @@ -685,9 +687,10 @@ m.GameState.prototype.findResearchers = function(templateName, noRequirementChec var template = this.getTemplate(templateName); var self = this; + var civ = this.playerData.civ; return this.getOwnResearchFacilities().filter(function(ent) { - var techs = ent.researchableTechs(); + var techs = ent.researchableTechs(civ); for (let tech of techs) { let thisTemp = self.getTemplate(tech); diff --git a/binaries/data/mods/public/simulation/ai/petra/headquarters.js b/binaries/data/mods/public/simulation/ai/petra/headquarters.js index 9455cc65b9..84df1c28b2 100644 --- a/binaries/data/mods/public/simulation/ai/petra/headquarters.js +++ b/binaries/data/mods/public/simulation/ai/petra/headquarters.js @@ -1408,6 +1408,7 @@ m.HQ.prototype.trainEmergencyUnits = function(gameState, positions) if (gameState.ai.queues.emergency.countQueuedUnits() !== 0) return false; + var civ = gameState.civ(); // find nearest base anchor var distcut = 20000; var nearestAnchor = undefined; @@ -1422,7 +1423,7 @@ m.HQ.prototype.trainEmergencyUnits = function(gameState, positions) continue; if (base.anchor.getMetadata(PlayerID, "access") !== access) continue; - if (!base.anchor.trainableEntities()) // base still in construction + if (!base.anchor.trainableEntities(civ)) // base still in construction continue; let queue = base.anchor._entity.trainingQueue if (queue) @@ -1462,7 +1463,7 @@ m.HQ.prototype.trainEmergencyUnits = function(gameState, positions) var total = gameState.getResources(); var templateFound = undefined; - var trainables = nearestAnchor.trainableEntities(); + var trainables = nearestAnchor.trainableEntities(civ); var garrisonArrowClasses = nearestAnchor.getGarrisonArrowClasses(); for (let trainable of trainables) { diff --git a/binaries/data/mods/public/simulation/ai/petra/navalManager.js b/binaries/data/mods/public/simulation/ai/petra/navalManager.js index 68b3eafcba..1a022eea25 100644 --- a/binaries/data/mods/public/simulation/ai/petra/navalManager.js +++ b/binaries/data/mods/public/simulation/ai/petra/navalManager.js @@ -637,9 +637,10 @@ m.NavalManager.prototype.buildNavalStructures = function(gameState, queues) // goal can be either attack (choose ship with best arrowCount) or transport (choose ship with best capacity) m.NavalManager.prototype.getBestShip = function(gameState, sea, goal) { + var civ = gameState.civ(); var trainableShips = []; gameState.getOwnTrainingFacilities().filter(API3.Filters.byMetadata(PlayerID, "sea", sea)).forEach(function(ent) { - var trainables = ent.trainableEntities(); + var trainables = ent.trainableEntities(civ); for (var trainable of trainables) { if (gameState.isDisabledTemplates(trainable)) diff --git a/binaries/data/mods/public/simulation/ai/petra/queueplan-training.js b/binaries/data/mods/public/simulation/ai/petra/queueplan-training.js index db7cd86750..95abf9fdb4 100644 --- a/binaries/data/mods/public/simulation/ai/petra/queueplan-training.js +++ b/binaries/data/mods/public/simulation/ai/petra/queueplan-training.js @@ -45,7 +45,7 @@ m.TrainingPlan.prototype.start = function(gameState) metadata[key] = this.metadata[key]; var trainer = gameState.getEntityById(this.metadata.trainer); if (trainer) - trainer.train(this.type, this.number, metadata, this.promotedTypes(gameState)); + trainer.train(gameState.civ(), this.type, this.number, metadata, this.promotedTypes(gameState)); this.onStart(gameState); return; } @@ -104,7 +104,7 @@ m.TrainingPlan.prototype.start = function(gameState) }); if (this.metadata && this.metadata.base !== undefined && this.metadata.base == 0) this.metadata.base = trainers[0].getMetadata(PlayerID, "base"); - trainers[0].train(this.type, this.number, this.metadata, this.promotedTypes(gameState)); + trainers[0].train(gameState.civ(), this.type, this.number, this.metadata, this.promotedTypes(gameState)); } else if (gameState.ai.Config.debug > 1) warn(" no trainers for this queue " + this.type); diff --git a/binaries/data/mods/public/simulation/ai/petra/startingStrategy.js b/binaries/data/mods/public/simulation/ai/petra/startingStrategy.js index 2f95c97be5..dd60f08a55 100644 --- a/binaries/data/mods/public/simulation/ai/petra/startingStrategy.js +++ b/binaries/data/mods/public/simulation/ai/petra/startingStrategy.js @@ -139,9 +139,10 @@ m.HQ.prototype.regionAnalysis = function(gameState) } if (!landIndex) { + var civ = gameState.civ(); for (let ent of gameState.getOwnEntities().values()) { - if (!ent.position() || (!ent.hasClass("Unit") && !ent.trainableEntities())) + if (!ent.position() || (!ent.hasClass("Unit") && !ent.trainableEntities(civ))) continue; let land = accessibility.getAccessValue(ent.position()); if (land > 1)