Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/binaries/data/mods/public/simulation/ai/petra/baseManager.js
/** | /** | ||||
* Base Manager | * Base Manager | ||||
* Handles lower level economic stuffs. | * Handles lower level economic stuffs. | ||||
* Some tasks: | * Some tasks: | ||||
* -tasking workers: gathering/hunting/building/repairing?/scouting/plans. | * -tasking workers: gathering/hunting/building/repairing?/scouting/plans. | ||||
* -giving feedback/estimates on GR | * -giving feedback/estimates on GR | ||||
* -achieving building stuff plans (scouting/getting ressource/building) or other long-staying plans. | * -achieving building stuff plans (scouting/getting ressource/building) or other long-staying plans. | ||||
* -getting good spots for dropsites | * -getting good spots for dropsites | ||||
* -managing dropsite use in the base | * -managing dropsite use in the base | ||||
* -updating whatever needs updating, keeping track of stuffs (rebuilding needs…) | * -updating whatever needs updating, keeping track of stuffs (rebuilding needs…) | ||||
*/ | */ | ||||
PETRA.BaseManager = function(gameState, Config) | PETRA.BaseManager = function(gameState, basesManager) | ||||
{ | { | ||||
this.Config = Config; | this.Config = basesManager.Config; | ||||
this.ID = gameState.ai.uniqueIDs.bases++; | this.ID = gameState.ai.uniqueIDs.bases++; | ||||
this.basesManager = basesManager; | |||||
// anchor building: seen as the main building of the base. Needs to have territorial influence | // anchor building: seen as the main building of the base. Needs to have territorial influence | ||||
this.anchor = undefined; | this.anchor = undefined; | ||||
this.anchorId = undefined; | this.anchorId = undefined; | ||||
this.accessIndex = undefined; | this.accessIndex = undefined; | ||||
// Maximum distance (from any dropsite) to look for resources | // Maximum distance (from any dropsite) to look for resources | ||||
// 3 areas are used: from 0 to max/4, from max/4 to max/2 and from max/2 to max | // 3 areas are used: from 0 to max/4, from max/4 to max/2 and from max/2 to max | ||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
if (!anchorEntity.hasClass("CivCentre")) | if (!anchorEntity.hasClass("CivCentre")) | ||||
API3.warn("Error: Petra base " + this.ID + " has been assigned " + ent.templateName() + " as anchor."); | API3.warn("Error: Petra base " + this.ID + " has been assigned " + ent.templateName() + " as anchor."); | ||||
else | else | ||||
{ | { | ||||
this.anchor = anchorEntity; | this.anchor = anchorEntity; | ||||
this.anchorId = anchorEntity.id(); | this.anchorId = anchorEntity.id(); | ||||
this.anchor.setMetadata(PlayerID, "baseAnchor", true); | this.anchor.setMetadata(PlayerID, "baseAnchor", true); | ||||
gameState.ai.HQ.resetBaseCache(); | this.basesManager.resetBaseCache(); | ||||
} | } | ||||
anchorEntity.setMetadata(PlayerID, "base", this.ID); | anchorEntity.setMetadata(PlayerID, "base", this.ID); | ||||
this.buildings.updateEnt(anchorEntity); | this.buildings.updateEnt(anchorEntity); | ||||
this.accessIndex = PETRA.getLandAccess(gameState, anchorEntity); | this.accessIndex = PETRA.getLandAccess(gameState, anchorEntity); | ||||
return true; | return true; | ||||
}; | }; | ||||
/* we lost our anchor. Let's reassign our units and buildings */ | /* we lost our anchor. Let's reassign our units and buildings */ | ||||
PETRA.BaseManager.prototype.anchorLost = function(gameState, ent) | PETRA.BaseManager.prototype.anchorLost = function(gameState, ent) | ||||
{ | { | ||||
this.anchor = undefined; | this.anchor = undefined; | ||||
this.anchorId = undefined; | this.anchorId = undefined; | ||||
this.neededDefenders = 0; | this.neededDefenders = 0; | ||||
gameState.ai.HQ.resetBaseCache(); | this.basesManager.resetBaseCache(); | ||||
}; | }; | ||||
/** Set a building of an anchorless base */ | /** Set a building of an anchorless base */ | ||||
PETRA.BaseManager.prototype.setAnchorlessEntity = function(gameState, ent) | PETRA.BaseManager.prototype.setAnchorlessEntity = function(gameState, ent) | ||||
{ | { | ||||
if (!this.buildings.hasEntities()) | if (!this.buildings.hasEntities()) | ||||
{ | { | ||||
if (!PETRA.getBuiltEntity(gameState, ent).resourceDropsiteTypes()) | if (!PETRA.getBuiltEntity(gameState, ent).resourceDropsiteTypes()) | ||||
Show All 22 Lines | if (this.dropsites[dropsite.id()]) | ||||
return; | return; | ||||
} | } | ||||
let accessIndex = this.accessIndex; | let accessIndex = this.accessIndex; | ||||
let dropsitePos = dropsite.position(); | let dropsitePos = dropsite.position(); | ||||
let dropsiteId = dropsite.id(); | let dropsiteId = dropsite.id(); | ||||
this.dropsites[dropsiteId] = true; | this.dropsites[dropsiteId] = true; | ||||
if (this.ID == gameState.ai.HQ.baseManagers[0].ID) | if (this.ID == this.basesManager.baselessBase().ID) | ||||
accessIndex = PETRA.getLandAccess(gameState, dropsite); | accessIndex = PETRA.getLandAccess(gameState, dropsite); | ||||
let maxDistResourceSquare = this.maxDistResourceSquare; | let maxDistResourceSquare = this.maxDistResourceSquare; | ||||
for (let type of dropsite.resourceDropsiteTypes()) | for (let type of dropsite.resourceDropsiteTypes()) | ||||
{ | { | ||||
let resources = gameState.getResourceSupplies(type); | let resources = gameState.getResourceSupplies(type); | ||||
if (!resources.length) | if (!resources.length) | ||||
continue; | continue; | ||||
▲ Show 20 Lines • Show All 192 Lines • ▼ Show 20 Lines | PETRA.BaseManager.prototype.findBestDropsiteLocation = function(gameState, resource, templateName) | ||||
if (bestVal <= 0) | if (bestVal <= 0) | ||||
return { "quality": bestVal, "pos": [0, 0] }; | return { "quality": bestVal, "pos": [0, 0] }; | ||||
let x = (bestIdx % obstructions.width + 0.5) * obstructions.cellSize; | let x = (bestIdx % obstructions.width + 0.5) * obstructions.cellSize; | ||||
let z = (Math.floor(bestIdx / obstructions.width) + 0.5) * obstructions.cellSize; | let z = (Math.floor(bestIdx / obstructions.width) + 0.5) * obstructions.cellSize; | ||||
return { "quality": bestVal, "pos": [x, z] }; | return { "quality": bestVal, "pos": [x, z] }; | ||||
}; | }; | ||||
PETRA.BaseManager.prototype.getResourceLevel = function(gameState, type, nearbyOnly = false) | PETRA.BaseManager.prototype.getResourceLevel = function(gameState, type, distances = ["nearby", "medium", "faraway"]) | ||||
{ | { | ||||
let count = 0; | let count = 0; | ||||
let check = {}; | let check = {}; | ||||
for (let supply of this.dropsiteSupplies[type].nearby) | for (const proxim of distances) | ||||
for (const supply of this.dropsiteSupplies[type][proxim]) | |||||
{ | { | ||||
if (check[supply.id]) // avoid double counting as same resource can appear several time | if (check[supply.id]) // avoid double counting as same resource can appear several time | ||||
continue; | continue; | ||||
check[supply.id] = true; | check[supply.id] = true; | ||||
count += supply.ent.resourceSupplyAmount(); | count += supply.ent.resourceSupplyAmount(); | ||||
} | } | ||||
if (nearbyOnly) | |||||
return count; | |||||
for (let supply of this.dropsiteSupplies[type].medium) | |||||
{ | |||||
if (check[supply.id]) | |||||
continue; | |||||
check[supply.id] = true; | |||||
count += 0.6*supply.ent.resourceSupplyAmount(); | |||||
} | |||||
return count; | return count; | ||||
}; | }; | ||||
/** check our resource levels and react accordingly */ | /** check our resource levels and react accordingly */ | ||||
PETRA.BaseManager.prototype.checkResourceLevels = function(gameState, queues) | PETRA.BaseManager.prototype.checkResourceLevels = function(gameState, queues) | ||||
{ | { | ||||
for (let type of Resources.GetCodes()) | for (let type of Resources.GetCodes()) | ||||
{ | { | ||||
if (type == "food") | if (type == "food") | ||||
{ | { | ||||
const prox = ["nearby"]; | |||||
if (gameState.currentPhase() < 2) | |||||
prox.push("medium"); | |||||
if (gameState.ai.HQ.canBuild(gameState, "structures/{civ}/field")) // let's see if we need to add new farms. | if (gameState.ai.HQ.canBuild(gameState, "structures/{civ}/field")) // let's see if we need to add new farms. | ||||
{ | { | ||||
let count = this.getResourceLevel(gameState, type, gameState.currentPhase() > 1); // animals are not accounted | const count = this.getResourceLevel(gameState, type, prox); // animals are not accounted | ||||
let numFarms = gameState.getOwnStructures().filter(API3.Filters.byClass("Field")).length; // including foundations | let numFarms = gameState.getOwnStructures().filter(API3.Filters.byClass("Field")).length; // including foundations | ||||
let numQueue = queues.field.countQueuedUnits(); | let numQueue = queues.field.countQueuedUnits(); | ||||
// TODO if not yet farms, add a check on time used/lost and build farmstead if needed | // TODO if not yet farms, add a check on time used/lost and build farmstead if needed | ||||
if (numFarms + numQueue == 0) // starting game, rely on fruits as long as we have enough of them | if (numFarms + numQueue == 0) // starting game, rely on fruits as long as we have enough of them | ||||
{ | { | ||||
if (count < 600) | if (count < 600) | ||||
{ | { | ||||
Show All 13 Lines | if (type == "food") | ||||
else if (gameState.ai.HQ.needCorral && !gameState.getOwnEntitiesByClass("Corral", true).hasEntities() && | else if (gameState.ai.HQ.needCorral && !gameState.getOwnEntitiesByClass("Corral", true).hasEntities() && | ||||
!queues.corral.hasQueuedUnits() && gameState.ai.HQ.canBuild(gameState, "structures/{civ}/corral")) | !queues.corral.hasQueuedUnits() && gameState.ai.HQ.canBuild(gameState, "structures/{civ}/corral")) | ||||
queues.corral.addPlan(new PETRA.ConstructionPlan(gameState, "structures/{civ}/corral", { "favoredBase": this.ID })); | queues.corral.addPlan(new PETRA.ConstructionPlan(gameState, "structures/{civ}/corral", { "favoredBase": this.ID })); | ||||
continue; | continue; | ||||
} | } | ||||
if (!gameState.getOwnEntitiesByClass("Corral", true).hasEntities() && | if (!gameState.getOwnEntitiesByClass("Corral", true).hasEntities() && | ||||
!queues.corral.hasQueuedUnits() && gameState.ai.HQ.canBuild(gameState, "structures/{civ}/corral")) | !queues.corral.hasQueuedUnits() && gameState.ai.HQ.canBuild(gameState, "structures/{civ}/corral")) | ||||
{ | { | ||||
let count = this.getResourceLevel(gameState, type, gameState.currentPhase() > 1); // animals are not accounted | const count = this.getResourceLevel(gameState, type, prox); // animals are not accounted | ||||
if (count < 900) | if (count < 900) | ||||
{ | { | ||||
queues.corral.addPlan(new PETRA.ConstructionPlan(gameState, "structures/{civ}/corral", { "favoredBase": this.ID })); | queues.corral.addPlan(new PETRA.ConstructionPlan(gameState, "structures/{civ}/corral", { "favoredBase": this.ID })); | ||||
gameState.ai.HQ.needCorral = true; | gameState.ai.HQ.needCorral = true; | ||||
} | } | ||||
} | } | ||||
continue; | continue; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 122 Lines • ▼ Show 20 Lines | for (let i = mostNeeded.length-1; i > 0; --i) | ||||
let lessNeed = mostNeeded[i]; | let lessNeed = mostNeeded[i]; | ||||
for (let j = 0; j < i; ++j) | for (let j = 0; j < i; ++j) | ||||
{ | { | ||||
let moreNeed = mostNeeded[j]; | let moreNeed = mostNeeded[j]; | ||||
let lastFailed = gameState.ai.HQ.lastFailedGather[moreNeed.type]; | let lastFailed = gameState.ai.HQ.lastFailedGather[moreNeed.type]; | ||||
if (lastFailed && gameState.ai.elapsedTime - lastFailed < 20) | if (lastFailed && gameState.ai.elapsedTime - lastFailed < 20) | ||||
continue; | continue; | ||||
// Ensure that the most wanted resource is not exhausted | // Ensure that the most wanted resource is not exhausted | ||||
if (moreNeed.type != "food" && gameState.ai.HQ.isResourceExhausted(moreNeed.type)) | if (moreNeed.type != "food" && this.basesManager.isResourceExhausted(moreNeed.type)) | ||||
{ | { | ||||
if (lessNeed.type != "food" && gameState.ai.HQ.isResourceExhausted(lessNeed.type)) | if (lessNeed.type != "food" && this.basesManager.isResourceExhausted(lessNeed.type)) | ||||
continue; | continue; | ||||
// And if so, move the gatherer to the less wanted one. | // And if so, move the gatherer to the less wanted one. | ||||
nb = this.switchGatherer(gameState, moreNeed.type, lessNeed.type, nb); | nb = this.switchGatherer(gameState, moreNeed.type, lessNeed.type, nb); | ||||
if (nb == 0) | if (nb == 0) | ||||
return; | return; | ||||
} | } | ||||
// If we assume a mean rate of 0.5 per gatherer, this diff should be > 1 | // If we assume a mean rate of 0.5 per gatherer, this diff should be > 1 | ||||
// but we require a bit more to avoid too frequent changes | // but we require a bit more to avoid too frequent changes | ||||
if (scale*moreNeed.wanted - moreNeed.current - scale*lessNeed.wanted + lessNeed.current > 1.5 || | if (scale*moreNeed.wanted - moreNeed.current - scale*lessNeed.wanted + lessNeed.current > 1.5 || | ||||
lessNeed.type != "food" && gameState.ai.HQ.isResourceExhausted(lessNeed.type)) | lessNeed.type != "food" && this.basesManager.isResourceExhausted(lessNeed.type)) | ||||
{ | { | ||||
nb = this.switchGatherer(gameState, lessNeed.type, moreNeed.type, nb); | nb = this.switchGatherer(gameState, lessNeed.type, moreNeed.type, nb); | ||||
if (nb == 0) | if (nb == 0) | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
}; | }; | ||||
Show All 19 Lines | if (num == 0) | ||||
return num; | return num; | ||||
if (!ent.canGather(to)) | if (!ent.canGather(to)) | ||||
continue; | continue; | ||||
if (only && !ent.hasClass(only)) | if (only && !ent.hasClass(only)) | ||||
continue; | continue; | ||||
--num; | --num; | ||||
ent.stopMoving(); | ent.stopMoving(); | ||||
ent.setMetadata(PlayerID, "gather-type", to); | ent.setMetadata(PlayerID, "gather-type", to); | ||||
gameState.ai.HQ.AddTCResGatherer(to); | this.basesManager.AddTCResGatherer(to); | ||||
} | } | ||||
return num; | return num; | ||||
}; | }; | ||||
PETRA.BaseManager.prototype.reassignIdleWorkers = function(gameState, idleWorkers) | PETRA.BaseManager.prototype.reassignIdleWorkers = function(gameState, idleWorkers) | ||||
{ | { | ||||
// Search for idle workers, and tell them to gather resources based on demand | // Search for idle workers, and tell them to gather resources based on demand | ||||
if (!idleWorkers) | if (!idleWorkers) | ||||
Show All 19 Lines | if (ent.hasClass("Worker")) | ||||
let mostNeeded = gameState.ai.HQ.pickMostNeededResources(gameState); | let mostNeeded = gameState.ai.HQ.pickMostNeededResources(gameState); | ||||
for (let needed of mostNeeded) | for (let needed of mostNeeded) | ||||
{ | { | ||||
if (!ent.canGather(needed.type)) | if (!ent.canGather(needed.type)) | ||||
continue; | continue; | ||||
let lastFailed = gameState.ai.HQ.lastFailedGather[needed.type]; | let lastFailed = gameState.ai.HQ.lastFailedGather[needed.type]; | ||||
if (lastFailed && gameState.ai.elapsedTime - lastFailed < 20) | if (lastFailed && gameState.ai.elapsedTime - lastFailed < 20) | ||||
continue; | continue; | ||||
if (needed.type != "food" && gameState.ai.HQ.isResourceExhausted(needed.type)) | if (needed.type != "food" && this.basesManager.isResourceExhausted(needed.type)) | ||||
continue; | continue; | ||||
ent.setMetadata(PlayerID, "subrole", "gatherer"); | ent.setMetadata(PlayerID, "subrole", "gatherer"); | ||||
ent.setMetadata(PlayerID, "gather-type", needed.type); | ent.setMetadata(PlayerID, "gather-type", needed.type); | ||||
gameState.ai.HQ.AddTCResGatherer(needed.type); | this.basesManager.AddTCResGatherer(needed.type); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
else if (PETRA.isFastMoving(ent) && ent.canGather("food") && ent.canAttackClass("Animal")) | else if (PETRA.isFastMoving(ent) && ent.canGather("food") && ent.canAttackClass("Animal")) | ||||
ent.setMetadata(PlayerID, "subrole", "hunter"); | ent.setMetadata(PlayerID, "subrole", "hunter"); | ||||
else if (ent.hasClass("FishingBoat")) | else if (ent.hasClass("FishingBoat")) | ||||
ent.setMetadata(PlayerID, "subrole", "fisher"); | ent.setMetadata(PlayerID, "subrole", "fisher"); | ||||
▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | workers.forEach(ent => { | ||||
ent.stopMoving(); | ent.stopMoving(); | ||||
ent.setMetadata(PlayerID, "target-foundation", tID); | ent.setMetadata(PlayerID, "target-foundation", tID); | ||||
} | } | ||||
}); | }); | ||||
} | } | ||||
if (workers.length < 3) | if (workers.length < 3) | ||||
{ | { | ||||
let fromOtherBase = gameState.ai.HQ.bulkPickWorkers(gameState, this, 2); | const fromOtherBase = this.basesManager.bulkPickWorkers(gameState, this, 2); | ||||
if (fromOtherBase) | if (fromOtherBase) | ||||
{ | { | ||||
let baseID = this.ID; | let baseID = this.ID; | ||||
fromOtherBase.forEach(worker => { | fromOtherBase.forEach(worker => { | ||||
worker.setMetadata(PlayerID, "base", baseID); | worker.setMetadata(PlayerID, "base", baseID); | ||||
worker.setMetadata(PlayerID, "subrole", "builder"); | worker.setMetadata(PlayerID, "subrole", "builder"); | ||||
workers.updateEnt(worker); | workers.updateEnt(worker); | ||||
builderWorkers.updateEnt(worker); | builderWorkers.updateEnt(worker); | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | for (let target of foundations.values()) | ||||
if (target.getMetadata(PlayerID, "baseAnchor") == true || | if (target.getMetadata(PlayerID, "baseAnchor") == true || | ||||
target.hasClass("Wonder") && gameState.getVictoryConditions().has("wonder")) | target.hasClass("Wonder") && gameState.getVictoryConditions().has("wonder")) | ||||
{ | { | ||||
targetNB = 15; | targetNB = 15; | ||||
maxTotalBuilders = Math.max(maxTotalBuilders, 15); | maxTotalBuilders = Math.max(maxTotalBuilders, 15); | ||||
} | } | ||||
// if no base yet, everybody should build | if (!this.basesManager.hasActiveBase()) | ||||
if (gameState.ai.HQ.numActiveBases() == 0) | |||||
{ | { | ||||
targetNB = workers.length; | targetNB = workers.length; | ||||
maxTotalBuilders = targetNB; | maxTotalBuilders = targetNB; | ||||
} | } | ||||
if (assigned >= targetNB) | if (assigned >= targetNB) | ||||
continue; | continue; | ||||
idleBuilderWorkers.forEach(function(ent) { | idleBuilderWorkers.forEach(function(ent) { | ||||
▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Lines | nearestNonBuilders.forEach(function(ent) { | ||||
ent.setMetadata(PlayerID, "target-foundation", target.id()); | ent.setMetadata(PlayerID, "target-foundation", target.id()); | ||||
}); | }); | ||||
} | } | ||||
}; | }; | ||||
/** Return false when the base is not active (no workers on it) */ | /** Return false when the base is not active (no workers on it) */ | ||||
PETRA.BaseManager.prototype.update = function(gameState, queues, events) | PETRA.BaseManager.prototype.update = function(gameState, queues, events) | ||||
{ | { | ||||
if (this.ID == gameState.ai.HQ.baseManagers[0].ID) // base for unaffected units | if (this.ID == this.basesManager.baselessBase().ID) | ||||
{ | { | ||||
// if some active base, reassigns the workers/buildings | // if some active base, reassigns the workers/buildings | ||||
// otherwise look for anything useful to do, i.e. treasures to gather | // otherwise look for anything useful to do, i.e. treasures to gather | ||||
if (gameState.ai.HQ.numActiveBases() > 0) | if (this.basesManager.hasActiveBase()) | ||||
{ | { | ||||
for (let ent of this.units.values()) | for (let ent of this.units.values()) | ||||
{ | { | ||||
let bestBase = PETRA.getBestBase(gameState, ent); | let bestBase = PETRA.getBestBase(gameState, ent); | ||||
if (bestBase.ID != this.ID) | if (bestBase.ID != this.ID) | ||||
bestBase.assignEntity(gameState, ent); | bestBase.assignEntity(gameState, ent); | ||||
} | } | ||||
for (let ent of this.buildings.values()) | for (let ent of this.buildings.values()) | ||||
{ | { | ||||
let bestBase = PETRA.getBestBase(gameState, ent); | let bestBase = PETRA.getBestBase(gameState, ent); | ||||
if (!bestBase) | if (!bestBase) | ||||
{ | { | ||||
if (ent.hasClass("Dock")) | if (ent.hasClass("Dock")) | ||||
API3.warn("Petra: dock in baseManager[0]. It may be useful to do an anchorless base for " + ent.templateName()); | API3.warn("Petra: dock in 'noBase' baseManager. It may be useful to do an anchorless base for " + ent.templateName()); | ||||
continue; | continue; | ||||
} | } | ||||
if (ent.resourceDropsiteTypes()) | if (ent.resourceDropsiteTypes()) | ||||
this.removeDropsite(gameState, ent); | this.removeDropsite(gameState, ent); | ||||
bestBase.assignEntity(gameState, ent); | bestBase.assignEntity(gameState, ent); | ||||
} | } | ||||
} | } | ||||
else if (gameState.ai.HQ.canBuildUnits) | else if (gameState.ai.HQ.canBuildUnits) | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | if(owner != 0 && !gameState.isPlayerAlly(owner)) | ||||
let ccEnts = gameState.updatingGlobalCollection("allCCs", API3.Filters.byClass("CivCentre")); | let ccEnts = gameState.updatingGlobalCollection("allCCs", API3.Filters.byClass("CivCentre")); | ||||
for (let cc of ccEnts.values()) | for (let cc of ccEnts.values()) | ||||
{ | { | ||||
if (cc.owner() != owner) | if (cc.owner() != owner) | ||||
continue; | continue; | ||||
if (API3.SquareVectorDistance(cc.position(), this.anchor.position()) > 8000) | if (API3.SquareVectorDistance(cc.position(), this.anchor.position()) > 8000) | ||||
continue; | continue; | ||||
this.anchor.destroy(); | this.anchor.destroy(); | ||||
gameState.ai.HQ.resetBaseCache(); | this.basesManager.resetBaseCache(); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
else if (this.neededDefenders && gameState.ai.HQ.trainEmergencyUnits(gameState, [this.anchor.position()])) | else if (this.neededDefenders && gameState.ai.HQ.trainEmergencyUnits(gameState, [this.anchor.position()])) | ||||
--this.neededDefenders; | --this.neededDefenders; | ||||
if (gameState.ai.elapsedTime > this.timeNextIdleCheck && | if (gameState.ai.elapsedTime > this.timeNextIdleCheck && | ||||
(gameState.currentPhase() > 1 || gameState.ai.HQ.phasing == 2)) | (gameState.currentPhase() > 1 || gameState.ai.HQ.phasing == 2)) | ||||
this.setWorkersIdleByPriority(gameState); | this.setWorkersIdleByPriority(gameState); | ||||
this.assignRolelessUnits(gameState); | this.assignRolelessUnits(gameState); | ||||
this.reassignIdleWorkers(gameState); | this.reassignIdleWorkers(gameState); | ||||
// check if workers can find something useful to do | // check if workers can find something useful to do | ||||
for (let ent of this.workers.values()) | for (let ent of this.workers.values()) | ||||
this.workerObject.update(gameState, ent); | this.workerObject.update(gameState, ent); | ||||
for (let ent of this.mobileDropsites.values()) | for (let ent of this.mobileDropsites.values()) | ||||
this.workerObject.moveToGatherer(gameState, ent, false); | this.workerObject.moveToGatherer(gameState, ent, false); | ||||
Engine.ProfileStop(); | Engine.ProfileStop(); | ||||
return true; | return true; | ||||
}; | }; | ||||
PETRA.BaseManager.prototype.AddTCGatherer = function(supplyID) | |||||
{ | |||||
return this.basesManager.AddTCGatherer(supplyID); | |||||
}; | |||||
PETRA.BaseManager.prototype.RemoveTCGatherer = function(supplyID) | |||||
{ | |||||
this.basesManager.RemoveTCGatherer(supplyID); | |||||
}; | |||||
PETRA.BaseManager.prototype.GetTCGatherer = function(supplyID) | |||||
{ | |||||
return this.basesManager.GetTCGatherer(supplyID); | |||||
}; | |||||
PETRA.BaseManager.prototype.Serialize = function() | PETRA.BaseManager.prototype.Serialize = function() | ||||
{ | { | ||||
return { | return { | ||||
"ID": this.ID, | "ID": this.ID, | ||||
"anchorId": this.anchorId, | "anchorId": this.anchorId, | ||||
"accessIndex": this.accessIndex, | "accessIndex": this.accessIndex, | ||||
"maxDistResourceSquare": this.maxDistResourceSquare, | "maxDistResourceSquare": this.maxDistResourceSquare, | ||||
"constructing": this.constructing, | "constructing": this.constructing, | ||||
Show All 14 Lines |
Wildfire Games · Phabricator