Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/simulation/ai/petra/gameTypeManager.js
var PETRA = function(m) | var PETRA = function(m) | ||||
{ | { | ||||
/** | /** | ||||
* Handle events that are important to specific gameTypes | * Handle events that are important to specific victory conditions. | ||||
* In regicide, train and manage healer guards and military guards for the hero. | * In regicide, train and manage healer guards and military guards for the hero. | ||||
*/ | */ | ||||
m.GameTypeManager = function(Config) | m.GameTypeManager = function(Config) | ||||
{ | { | ||||
this.Config = Config; | this.Config = Config; | ||||
this.criticalEnts = new Map(); | this.criticalEnts = new Map(); | ||||
// Holds ids of all ents who are (or can be) guarding and if the ent is currently guarding | // Holds ids of all ents who are (or can be) guarding and if the ent is currently guarding | ||||
this.guardEnts = new Map(); | this.guardEnts = new Map(); | ||||
this.healersPerCriticalEnt = 2 + Math.round(this.Config.personality.defensive * 2); | this.healersPerCriticalEnt = 2 + Math.round(this.Config.personality.defensive * 2); | ||||
this.tryCaptureGaiaRelic = false; | this.tryCaptureGaiaRelic = false; | ||||
this.tryCaptureGaiaRelicLapseTime = -1; | this.tryCaptureGaiaRelicLapseTime = -1; | ||||
this.tryCaptureGaiaRelicLocal = false; | this.tryCaptureGaiaRelicLocal = false; | ||||
this.tryCaptureGaiaRelicLocalLapseTime = -1; | this.tryCaptureGaiaRelicLocalLapseTime = -1; | ||||
// Gaia relics which we are targeting currently and have not captured yet | // Gaia relics which we are targeting currently and have not captured yet | ||||
this.targetedGaiaRelics = new Set(); | this.targetedGaiaRelics = new Set(); | ||||
}; | }; | ||||
/** | /** | ||||
* Cache the ids of any inital gameType-critical entities. | * Cache the ids of any inital victoryCondition-critical entities. | ||||
* In regicide, these are the inital heroes that the player starts with. | * In regicide, these are the inital heroes that the player starts with. | ||||
*/ | */ | ||||
m.GameTypeManager.prototype.init = function(gameState) | m.GameTypeManager.prototype.init = function(gameState) | ||||
{ | { | ||||
if (gameState.getGameType() === "wonder") | if (gameState.getVictoryConditions().indexOf("wonder") != -1) | ||||
{ | { | ||||
for (let wonder of gameState.getOwnEntitiesByClass("Wonder", true).values()) | for (let wonder of gameState.getOwnEntitiesByClass("Wonder", true).values()) | ||||
this.criticalEnts.set(wonder.id(), { "guardsAssigned": 0, "guards": new Map() }); | this.criticalEnts.set(wonder.id(), { "guardsAssigned": 0, "guards": new Map() }); | ||||
} | } | ||||
if (gameState.getGameType() === "regicide") | if (gameState.getVictoryConditions().indexOf("regicide") != -1) | ||||
{ | { | ||||
for (let hero of gameState.getOwnEntitiesByClass("Hero", true).values()) | for (let hero of gameState.getOwnEntitiesByClass("Hero", true).values()) | ||||
{ | { | ||||
let defaultStance = hero.hasClass("Soldier") ? "aggressive" : "passive"; | let defaultStance = hero.hasClass("Soldier") ? "aggressive" : "passive"; | ||||
if (hero.getStance() !== defaultStance) | if (hero.getStance() !== defaultStance) | ||||
hero.setStance(defaultStance); | hero.setStance(defaultStance); | ||||
this.criticalEnts.set(hero.id(), { | this.criticalEnts.set(hero.id(), { | ||||
"garrisonEmergency": false, | "garrisonEmergency": false, | ||||
"healersAssigned": 0, | "healersAssigned": 0, | ||||
"guardsAssigned": 0, // for non-healer guards | "guardsAssigned": 0, // for non-healer guards | ||||
"guards": new Map() // ids of ents who are currently guarding this hero | "guards": new Map() // ids of ents who are currently guarding this hero | ||||
}); | }); | ||||
} | } | ||||
} | } | ||||
}; | }; | ||||
/** | /** | ||||
* In regicide mode, if the hero has less than 70% health, try to garrison it in a healing structure | * In regicide mode, if the hero has less than 70% health, try to garrison it in a healing structure | ||||
* If it is less than 40%, try to garrison in the closest possible structure | * If it is less than 40%, try to garrison in the closest possible structure | ||||
* If the hero cannot garrison, retreat it to the closest base | * If the hero cannot garrison, retreat it to the closest base | ||||
*/ | */ | ||||
m.GameTypeManager.prototype.checkEvents = function(gameState, events) | m.GameTypeManager.prototype.checkEvents = function(gameState, events) | ||||
{ | { | ||||
if (gameState.getGameType() === "wonder") | if (gameState.getVictoryConditions().indexOf("wonder") != -1) | ||||
{ | { | ||||
for (let evt of events.Create) | for (let evt of events.Create) | ||||
{ | { | ||||
let ent = gameState.getEntityById(evt.entity); | let ent = gameState.getEntityById(evt.entity); | ||||
if (!ent || !ent.isOwn(PlayerID) || ent.foundationProgress() === undefined || | if (!ent || !ent.isOwn(PlayerID) || ent.foundationProgress() === undefined || | ||||
!ent.hasClass("Wonder")) | !ent.hasClass("Wonder")) | ||||
continue; | continue; | ||||
Show All 15 Lines | for (let evt of events.ConstructionFinished) | ||||
continue; | continue; | ||||
let ent = gameState.getEntityById(evt.newentity); | let ent = gameState.getEntityById(evt.newentity); | ||||
if (ent && ent.isOwn(PlayerID) && ent.hasClass("Wonder")) | if (ent && ent.isOwn(PlayerID) && ent.hasClass("Wonder")) | ||||
this.criticalEnts.set(ent.id(), { "guardsAssigned": 0, "guards": new Map() }); | this.criticalEnts.set(ent.id(), { "guardsAssigned": 0, "guards": new Map() }); | ||||
} | } | ||||
} | } | ||||
if (gameState.getGameType() === "regicide") | if (gameState.getVictoryConditions().indexOf("regicide") != -1) | ||||
{ | { | ||||
for (let evt of events.Attacked) | for (let evt of events.Attacked) | ||||
{ | { | ||||
if (!this.criticalEnts.has(evt.target)) | if (!this.criticalEnts.has(evt.target)) | ||||
continue; | continue; | ||||
let target = gameState.getEntityById(evt.target); | let target = gameState.getEntityById(evt.target); | ||||
if (!target || !target.position() || target.healthLevel() > this.Config.garrisonHealthLevel.high) | if (!target || !target.position() || target.healthLevel() > this.Config.garrisonHealthLevel.high) | ||||
▲ Show 20 Lines • Show All 166 Lines • ▼ Show 20 Lines | for (let evt of events.OwnershipChanged) | ||||
} | } | ||||
if (evt.from === 0 && this.targetedGaiaRelics.has(evt.entity)) | if (evt.from === 0 && this.targetedGaiaRelics.has(evt.entity)) | ||||
this.targetedGaiaRelics.delete(evt.entity); | this.targetedGaiaRelics.delete(evt.entity); | ||||
if (evt.to !== PlayerID) | if (evt.to !== PlayerID) | ||||
continue; | continue; | ||||
let ent = gameState.getEntityById(evt.entity); | let ent = gameState.getEntityById(evt.entity); | ||||
if (ent && (gameState.getGameType() === "wonder" && ent.hasClass("Wonder") || | if (ent && (gameState.getVictoryConditions().indexOf("wonder") != -1 && ent.hasClass("Wonder") || | ||||
gameState.getGameType() === "capture_the_relic" && ent.hasClass("Relic"))) | gameState.getVictoryConditions().indexOf("capture_the_relic") != -1 && ent.hasClass("Relic"))) | ||||
{ | { | ||||
this.criticalEnts.set(ent.id(), { "guardsAssigned": 0, "guards": new Map() }); | this.criticalEnts.set(ent.id(), { "guardsAssigned": 0, "guards": new Map() }); | ||||
// Move captured relics to the closest base | // Move captured relics to the closest base | ||||
if (ent.hasClass("Unit")) | if (ent.hasClass("Unit")) | ||||
{ | { | ||||
this.pickCriticalEntRetreatLocation(gameState, ent, false); | this.pickCriticalEntRetreatLocation(gameState, ent, false); | ||||
if (evt.from === 0) | if (evt.from === 0) | ||||
gameState.ai.HQ.attackManager.cancelAttacksAgainstPlayer(gameState, evt.from); | gameState.ai.HQ.attackManager.cancelAttacksAgainstPlayer(gameState, evt.from); | ||||
▲ Show 20 Lines • Show All 245 Lines • ▼ Show 20 Lines | |||||
m.GameTypeManager.prototype.update = function(gameState, events, queues) | m.GameTypeManager.prototype.update = function(gameState, events, queues) | ||||
{ | { | ||||
// Wait a turn for trigger scripts to spawn any critical ents (i.e. in regicide) | // Wait a turn for trigger scripts to spawn any critical ents (i.e. in regicide) | ||||
if (gameState.ai.playedTurn === 1) | if (gameState.ai.playedTurn === 1) | ||||
this.init(gameState); | this.init(gameState); | ||||
this.checkEvents(gameState, events); | this.checkEvents(gameState, events); | ||||
if (gameState.getGameType() === "wonder" && gameState.ai.playedTurn % 10 === 0) | if (gameState.getVictoryConditions().indexOf("wonder") != -1 && gameState.ai.playedTurn % 10 === 0) | ||||
mimo: these changes and following won't work as for example this.manageCriticalEntGuards should be… | |||||
{ | { | ||||
gameState.ai.HQ.buildWonder(gameState, queues, true); | gameState.ai.HQ.buildWonder(gameState, queues, true); | ||||
this.manageCriticalEntGuards(gameState); | this.manageCriticalEntGuards(gameState); | ||||
} | } | ||||
if (gameState.getGameType() === "regicide" && gameState.ai.playedTurn % 10 === 0) | if (gameState.getVictoryConditions().indexOf("regicide") != -1 && gameState.ai.playedTurn % 10 === 0) | ||||
{ | { | ||||
for (let [id, data] of this.criticalEnts) | for (let [id, data] of this.criticalEnts) | ||||
{ | { | ||||
let ent = gameState.getEntityById(id); | let ent = gameState.getEntityById(id); | ||||
if (ent && ent.healthLevel() > this.Config.garrisonHealthLevel.high && ent.hasClass("Soldier") && | if (ent && ent.healthLevel() > this.Config.garrisonHealthLevel.high && ent.hasClass("Soldier") && | ||||
ent.getStance() !== "aggressive") | ent.getStance() !== "aggressive") | ||||
ent.setStance("aggressive"); | ent.setStance("aggressive"); | ||||
if (data.healersAssigned < this.healersPerCriticalEnt && | if (data.healersAssigned < this.healersPerCriticalEnt && | ||||
this.guardEnts.size < Math.min(gameState.getPopulationMax() / 10, gameState.getPopulation() / 4)) | this.guardEnts.size < Math.min(gameState.getPopulationMax() / 10, gameState.getPopulation() / 4)) | ||||
this.trainCriticalEntHealer(gameState, queues, id); | this.trainCriticalEntHealer(gameState, queues, id); | ||||
} | } | ||||
this.manageCriticalEntGuards(gameState); | this.manageCriticalEntGuards(gameState); | ||||
} | } | ||||
if (gameState.getGameType() === "capture_the_relic" && gameState.ai.playedTurn % 10 === 0) | if (gameState.getVictoryConditions().indexOf("capture_the_relic") != -1 && gameState.ai.playedTurn % 10 === 0) | ||||
{ | { | ||||
this.manageCriticalEntGuards(gameState); | this.manageCriticalEntGuards(gameState); | ||||
if (!this.tryCaptureGaiaRelic && gameState.ai.elapsedTime > this.tryCaptureGaiaRelicLapseTime) | if (!this.tryCaptureGaiaRelic && gameState.ai.elapsedTime > this.tryCaptureGaiaRelicLapseTime) | ||||
this.tryCaptureGaiaRelic = true; | this.tryCaptureGaiaRelic = true; | ||||
// Look for some relic that may be on our territory at game-start or if our territory boundaries change | // Look for some relic that may be on our territory at game-start or if our territory boundaries change | ||||
if (!this.tryCaptureGaiaRelicLocal && gameState.ai.elapsedTime > this.tryCaptureGaiaRelicLocalLapseTime) | if (!this.tryCaptureGaiaRelicLocal && gameState.ai.elapsedTime > this.tryCaptureGaiaRelicLocalLapseTime) | ||||
{ | { | ||||
Show All 40 Lines |
Wildfire Games · Phabricator
these changes and following won't work as for example this.manageCriticalEntGuards should be only called once, even if multiple victory conditions.