[PetraAI] - Use enum-like variables instead of magic values. -- [1]
Improved readability. Easier find-and-replace. This commit is focused on: - BaseManager - AttackPlan - GarrisonManager Patch by: @JCWasmx86 Differential revision: https://code.wildfiregames.com/D4334 Refs. #6256 Comments by: @Silier, @Stan This was SVN commit r26029.
This commit is contained in:
parent
5a7aa37cd1
commit
5d3902498f
@ -9,8 +9,18 @@ PETRA.AttackManager = function(Config)
|
||||
this.attackNumber = 0;
|
||||
this.rushNumber = 0;
|
||||
this.raidNumber = 0;
|
||||
this.upcomingAttacks = { "Rush": [], "Raid": [], "Attack": [], "HugeAttack": [] };
|
||||
this.startedAttacks = { "Rush": [], "Raid": [], "Attack": [], "HugeAttack": [] };
|
||||
this.upcomingAttacks = {
|
||||
[PETRA.AttackPlan.TYPE_RUSH]: [],
|
||||
[PETRA.AttackPlan.TYPE_RAID]: [],
|
||||
[PETRA.AttackPlan.TYPE_DEFAULT]: [],
|
||||
[PETRA.AttackPlan.TYPE_HUGE_ATTACK]: []
|
||||
};
|
||||
this.startedAttacks = {
|
||||
[PETRA.AttackPlan.TYPE_RUSH]: [],
|
||||
[PETRA.AttackPlan.TYPE_RAID]: [],
|
||||
[PETRA.AttackPlan.TYPE_DEFAULT]: [],
|
||||
[PETRA.AttackPlan.TYPE_HUGE_ATTACK]: []
|
||||
};
|
||||
this.bombingAttacks = new Map();// Temporary attacks for siege units while waiting their current attack to start
|
||||
this.debugTime = 0;
|
||||
this.maxRushes = 0;
|
||||
@ -63,7 +73,7 @@ PETRA.AttackManager.prototype.checkEvents = function(gameState, events)
|
||||
{
|
||||
for (let attack of this.upcomingAttacks[attackType])
|
||||
{
|
||||
if (attack.state === "completing")
|
||||
if (attack.state === PETRA.AttackPlan.STATE_COMPLETING)
|
||||
{
|
||||
if (attack.targetPlayer === targetPlayer)
|
||||
available += attack.unitCollection.length;
|
||||
@ -85,7 +95,7 @@ PETRA.AttackManager.prototype.checkEvents = function(gameState, events)
|
||||
{
|
||||
for (let attack of this.upcomingAttacks[attackType])
|
||||
{
|
||||
if (attack.state === "completing" ||
|
||||
if (attack.state === PETRA.AttackPlan.STATE_COMPLETING ||
|
||||
attack.targetPlayer !== targetPlayer ||
|
||||
attack.unitCollection.length < 3)
|
||||
continue;
|
||||
@ -252,8 +262,12 @@ PETRA.AttackManager.prototype.update = function(gameState, queues, events)
|
||||
}
|
||||
|
||||
this.checkEvents(gameState, events);
|
||||
|
||||
let unexecutedAttacks = { "Rush": 0, "Raid": 0, "Attack": 0, "HugeAttack": 0 };
|
||||
const unexecutedAttacks = {
|
||||
[PETRA.AttackPlan.TYPE_RUSH]: 0,
|
||||
[PETRA.AttackPlan.TYPE_RAID]: 0,
|
||||
[PETRA.AttackPlan.TYPE_DEFAULT]: 0,
|
||||
[PETRA.AttackPlan.TYPE_HUGE_ATTACK]: 0
|
||||
};
|
||||
for (let attackType in this.upcomingAttacks)
|
||||
{
|
||||
for (let i = 0; i < this.upcomingAttacks[attackType].length; ++i)
|
||||
@ -266,20 +280,20 @@ PETRA.AttackManager.prototype.update = function(gameState, queues, events)
|
||||
|
||||
let updateStep = attack.updatePreparation(gameState);
|
||||
// now we're gonna check if the preparation time is over
|
||||
if (updateStep == 1 || attack.isPaused())
|
||||
if (updateStep === PETRA.AttackPlan.PREPARATION_KEEP_GOING || attack.isPaused())
|
||||
{
|
||||
// just chillin'
|
||||
if (attack.state == "unexecuted")
|
||||
if (attack.state === PETRA.AttackPlan.STATE_UNEXECUTED)
|
||||
++unexecutedAttacks[attackType];
|
||||
}
|
||||
else if (updateStep == 0)
|
||||
else if (updateStep === PETRA.AttackPlan.PREPARATION_FAILED)
|
||||
{
|
||||
if (this.Config.debug > 1)
|
||||
API3.warn("Attack Manager: " + attack.getType() + " plan " + attack.getName() + " aborted.");
|
||||
attack.Abort(gameState);
|
||||
this.upcomingAttacks[attackType].splice(i--, 1);
|
||||
}
|
||||
else if (updateStep == 2)
|
||||
else if (updateStep === PETRA.AttackPlan.PREPARATION_START)
|
||||
{
|
||||
if (attack.StartAttack(gameState))
|
||||
{
|
||||
@ -321,30 +335,32 @@ PETRA.AttackManager.prototype.update = function(gameState, queues, events)
|
||||
let barracksNb = gameState.getOwnEntitiesByClass("Barracks", true).filter(API3.Filters.isBuilt()).length;
|
||||
if (this.rushNumber < this.maxRushes && barracksNb >= 1)
|
||||
{
|
||||
if (unexecutedAttacks.Rush === 0)
|
||||
if (unexecutedAttacks[PETRA.AttackPlan.TYPE_RUSH] === 0)
|
||||
{
|
||||
// we have a barracks and we want to rush, rush.
|
||||
let data = { "targetSize": this.rushSize[this.rushNumber] };
|
||||
let attackPlan = new PETRA.AttackPlan(gameState, this.Config, this.totalNumber, "Rush", data);
|
||||
const attackPlan = new PETRA.AttackPlan(gameState, this.Config, this.totalNumber, PETRA.AttackPlan.TYPE_RUSH, data);
|
||||
if (!attackPlan.failed)
|
||||
{
|
||||
if (this.Config.debug > 1)
|
||||
API3.warn("Military Manager: Rushing plan " + this.totalNumber + " with maxRushes " + this.maxRushes);
|
||||
this.totalNumber++;
|
||||
attackPlan.init(gameState);
|
||||
this.upcomingAttacks.Rush.push(attackPlan);
|
||||
this.upcomingAttacks[PETRA.AttackPlan.TYPE_RUSH].push(attackPlan);
|
||||
}
|
||||
this.rushNumber++;
|
||||
}
|
||||
}
|
||||
else if (unexecutedAttacks.Attack == 0 && unexecutedAttacks.HugeAttack == 0 &&
|
||||
this.startedAttacks.Attack.length + this.startedAttacks.HugeAttack.length < Math.min(2, 1 + Math.round(gameState.getPopulationMax()/100)) &&
|
||||
(this.startedAttacks.Attack.length + this.startedAttacks.HugeAttack.length == 0 || gameState.getPopulationMax() - gameState.getPopulation() > 12))
|
||||
else if (unexecutedAttacks[PETRA.AttackPlan.TYPE_DEFAULT] == 0 && unexecutedAttacks[PETRA.AttackManager.TYPE_HUGE_ATTACK] == 0 &&
|
||||
this.startedAttacks[PETRA.AttackPlan.TYPE_DEFAULT].length + this.startedAttacks[PETRA.AttackManager.TYPE_HUGE_ATTACK].length <
|
||||
Math.min(2, 1 + Math.round(gameState.getPopulationMax() / 100)) &&
|
||||
(this.startedAttacks[PETRA.AttackPlan.TYPE_DEFAULT].length + this.startedAttacks[PETRA.AttackManager.TYPE_HUGE_ATTACK].length == 0 ||
|
||||
gameState.getPopulationMax() - gameState.getPopulation() > 12))
|
||||
{
|
||||
if (barracksNb >= 1 && (gameState.currentPhase() > 1 || gameState.isResearching(gameState.getPhaseName(2))) ||
|
||||
!gameState.ai.HQ.hasPotentialBase()) // if we have no base ... nothing else to do than attack
|
||||
{
|
||||
let type = this.attackNumber < 2 || this.startedAttacks.HugeAttack.length > 0 ? "Attack" : "HugeAttack";
|
||||
const type = this.attackNumber < 2 || this.startedAttacks[PETRA.AttackPlan.TYPE_HUGE_ATTACK].length > 0 ? PETRA.AttackPlan.TYPE_DEFAULT : PETRA.AttackPlan.TYPE_HUGE_ATTACK;
|
||||
let attackPlan = new PETRA.AttackPlan(gameState, this.Config, this.totalNumber, type);
|
||||
if (attackPlan.failed)
|
||||
this.attackPlansEncounteredWater = true; // hack
|
||||
@ -360,7 +376,7 @@ PETRA.AttackManager.prototype.update = function(gameState, queues, events)
|
||||
}
|
||||
}
|
||||
|
||||
if (unexecutedAttacks.Raid === 0 && gameState.ai.HQ.defenseManager.targetList.length)
|
||||
if (unexecutedAttacks[PETRA.AttackPlan.TYPE_RAID] === 0 && gameState.ai.HQ.defenseManager.targetList.length)
|
||||
{
|
||||
let target;
|
||||
for (let targetId of gameState.ai.HQ.defenseManager.targetList)
|
||||
@ -465,7 +481,7 @@ PETRA.AttackManager.prototype.getEnemyPlayer = function(gameState, attack)
|
||||
for (let i in this.defeated)
|
||||
veto[i] = true;
|
||||
// No rush if enemy too well defended (i.e. iberians)
|
||||
if (attack.type == "Rush")
|
||||
if (attack.type === PETRA.AttackPlan.TYPE_RUSH)
|
||||
{
|
||||
for (let i = 1; i < gameState.sharedScript.playersData.length; ++i)
|
||||
{
|
||||
@ -484,7 +500,7 @@ PETRA.AttackManager.prototype.getEnemyPlayer = function(gameState, attack)
|
||||
|
||||
// then if not a huge attack, continue attacking our previous target as long as it has some entities,
|
||||
// otherwise target the most accessible one
|
||||
if (attack.type != "HugeAttack")
|
||||
if (attack.type !== PETRA.AttackPlan.TYPE_HUGE_ATTACK)
|
||||
{
|
||||
if (attack.targetPlayer === undefined && this.currentEnemyPlayer !== undefined &&
|
||||
!this.defeated[this.currentEnemyPlayer] &&
|
||||
@ -507,7 +523,7 @@ PETRA.AttackManager.prototype.getEnemyPlayer = function(gameState, attack)
|
||||
continue;
|
||||
if (!gameState.isPlayerEnemy(enemycc.owner()))
|
||||
continue;
|
||||
if (access != PETRA.getLandAccess(gameState, enemycc))
|
||||
if (access !== PETRA.getLandAccess(gameState, enemycc))
|
||||
continue;
|
||||
let dist = API3.SquareVectorDistance(ourPos, enemycc.position());
|
||||
if (distmin && dist > distmin)
|
||||
@ -640,7 +656,7 @@ PETRA.AttackManager.prototype.cancelAttacksAgainstPlayer = function(gameState, p
|
||||
PETRA.AttackManager.prototype.raidTargetEntity = function(gameState, ent)
|
||||
{
|
||||
let data = { "target": ent };
|
||||
let attackPlan = new PETRA.AttackPlan(gameState, this.Config, this.totalNumber, "Raid", data);
|
||||
const attackPlan = new PETRA.AttackPlan(gameState, this.Config, this.totalNumber, PETRA.AttackPlan.TYPE_RAID, data);
|
||||
if (attackPlan.failed)
|
||||
return null;
|
||||
if (this.Config.debug > 1)
|
||||
@ -648,7 +664,7 @@ PETRA.AttackManager.prototype.raidTargetEntity = function(gameState, ent)
|
||||
this.raidNumber++;
|
||||
this.totalNumber++;
|
||||
attackPlan.init(gameState);
|
||||
this.upcomingAttacks.Raid.push(attackPlan);
|
||||
this.upcomingAttacks[PETRA.AttackPlan.TYPE_RAID].push(attackPlan);
|
||||
return attackPlan;
|
||||
};
|
||||
|
||||
@ -686,7 +702,7 @@ PETRA.AttackManager.prototype.switchDefenseToAttack = function(gameState, target
|
||||
}
|
||||
let attackData = data.uniqueTarget ? { "uniqueTargetId": target.id() } : undefined;
|
||||
let pos = target.position();
|
||||
let attackType = "Attack";
|
||||
const attackType = PETRA.AttackPlan.TYPE_DEFAULT;
|
||||
let attackPlan = new PETRA.AttackPlan(gameState, this.Config, this.totalNumber, attackType, attackData);
|
||||
if (attackPlan.failed)
|
||||
return false;
|
||||
@ -733,7 +749,7 @@ PETRA.AttackManager.prototype.switchDefenseToAttack = function(gameState, target
|
||||
attackPlan.targetPlayer = target.owner();
|
||||
attackPlan.targetPos = pos;
|
||||
attackPlan.target = target;
|
||||
attackPlan.state = "arrived";
|
||||
attackPlan.state = PETRA.AttackPlan.STATE_ARRIVED;
|
||||
return true;
|
||||
};
|
||||
|
||||
|
@ -4,13 +4,12 @@
|
||||
* To making sure units are built, and pushing elements to the queue manager otherwise
|
||||
* It also handles the actual attack, though much work is needed on that.
|
||||
*/
|
||||
|
||||
PETRA.AttackPlan = function(gameState, Config, uniqueID, type, data)
|
||||
PETRA.AttackPlan = function(gameState, Config, uniqueID, type = PETRA.AttackPlan.TYPE_DEFAULT, data)
|
||||
{
|
||||
this.Config = Config;
|
||||
this.name = uniqueID;
|
||||
this.type = type || "Attack";
|
||||
this.state = "unexecuted";
|
||||
this.type = type;
|
||||
this.state = PETRA.AttackPlan.STATE_UNEXECUTED;
|
||||
this.forced = false; // true when this attacked has been forced to help an ally
|
||||
|
||||
if (data && data.target)
|
||||
@ -114,7 +113,7 @@ PETRA.AttackPlan = function(gameState, Config, uniqueID, type, data)
|
||||
this.unitStat = {};
|
||||
|
||||
// neededShips is the minimal number of ships which should be available for transport
|
||||
if (type == "Rush")
|
||||
if (type === PETRA.AttackPlan.TYPE_RUSH)
|
||||
{
|
||||
priority = 250;
|
||||
this.unitStat.Infantry = { "priority": 1, "minSize": 10, "targetSize": 20, "batchSize": 2, "classes": ["Infantry"],
|
||||
@ -125,14 +124,14 @@ PETRA.AttackPlan = function(gameState, Config, uniqueID, type, data)
|
||||
this.unitStat.Infantry.targetSize = data.targetSize;
|
||||
this.neededShips = 1;
|
||||
}
|
||||
else if (type == "Raid")
|
||||
else if (type === PETRA.AttackPlan.TYPE_RAID)
|
||||
{
|
||||
priority = 150;
|
||||
this.unitStat.FastMoving = { "priority": 1, "minSize": 3, "targetSize": 4, "batchSize": 2, "classes": ["FastMoving+CitizenSoldier"],
|
||||
"interests": [ ["strength", 1] ] };
|
||||
this.neededShips = 1;
|
||||
}
|
||||
else if (type == "HugeAttack")
|
||||
else if (type === PETRA.AttackPlan.TYPE_HUGE_ATTACK)
|
||||
{
|
||||
priority = 90;
|
||||
// basically we want a mix of citizen soldiers so our barracks have a purpose, and champion units.
|
||||
@ -216,7 +215,7 @@ PETRA.AttackPlan = function(gameState, Config, uniqueID, type, data)
|
||||
// each array is [ratio, [associated classes], associated EntityColl, associated unitStat, name ]
|
||||
this.buildOrders = [];
|
||||
this.canBuildUnits = gameState.ai.HQ.canBuildUnits;
|
||||
this.siegeState = 0; // 0 = not yet tested, 1 = not yet any siege trainer, 2 = siege added in build orders
|
||||
this.siegeState = PETRA.AttackPlan.SIEGE_NOT_TESTED;
|
||||
|
||||
// some variables used during the attack
|
||||
this.position5TurnsAgo = [0, 0];
|
||||
@ -227,6 +226,27 @@ PETRA.AttackPlan = function(gameState, Config, uniqueID, type, data)
|
||||
return true;
|
||||
};
|
||||
|
||||
PETRA.AttackPlan.PREPARATION_FAILED = 0;
|
||||
PETRA.AttackPlan.PREPARATION_KEEP_GOING = 1;
|
||||
PETRA.AttackPlan.PREPARATION_START = 2;
|
||||
|
||||
PETRA.AttackPlan.SIEGE_NOT_TESTED = 0;
|
||||
PETRA.AttackPlan.SIEGE_NO_TRAINER = 1;
|
||||
|
||||
/**
|
||||
* Siege added in build orders
|
||||
*/
|
||||
PETRA.AttackPlan.SIEGE_ADDED = 2;
|
||||
|
||||
PETRA.AttackPlan.STATE_UNEXECUTED = "unexecuted";
|
||||
PETRA.AttackPlan.STATE_COMPLETING = "completing";
|
||||
PETRA.AttackPlan.STATE_ARRIVED = "arrived";
|
||||
|
||||
PETRA.AttackPlan.TYPE_DEFAULT = "Attack";
|
||||
PETRA.AttackPlan.TYPE_HUGE_ATTACK = "HugeAttack";
|
||||
PETRA.AttackPlan.TYPE_RAID = "Raid";
|
||||
PETRA.AttackPlan.TYPE_RUSH = "Rush";
|
||||
|
||||
PETRA.AttackPlan.prototype.init = function(gameState)
|
||||
{
|
||||
this.queue = gameState.ai.queues["plan_" + this.name];
|
||||
@ -262,7 +282,7 @@ PETRA.AttackPlan.prototype.getType = function()
|
||||
|
||||
PETRA.AttackPlan.prototype.isStarted = function()
|
||||
{
|
||||
return this.state !== "unexecuted" && this.state !== "completing";
|
||||
return this.state !== PETRA.AttackPlan.STATE_UNEXECUTED && this.state !== PETRA.AttackPlan.STATE_COMPLETING;
|
||||
};
|
||||
|
||||
PETRA.AttackPlan.prototype.isPaused = function()
|
||||
@ -316,7 +336,7 @@ PETRA.AttackPlan.prototype.mustStart = function()
|
||||
if (MaxReachedEverywhere)
|
||||
return true;
|
||||
if (MinReachedEverywhere)
|
||||
return this.type == "Raid" && this.target && this.target.foundationProgress() &&
|
||||
return this.type === PETRA.AttackPlan.TYPE_RAID && this.target && this.target.foundationProgress() &&
|
||||
this.target.foundationProgress() > 50;
|
||||
return false;
|
||||
};
|
||||
@ -364,7 +384,7 @@ PETRA.AttackPlan.prototype.addBuildOrder = function(gameState, name, unitStats,
|
||||
|
||||
PETRA.AttackPlan.prototype.addSiegeUnits = function(gameState)
|
||||
{
|
||||
if (this.siegeState == 2 || this.state !== "unexecuted")
|
||||
if (this.siegeState === PETRA.AttackPlan.SIEGE_ADDED || this.state !== PETRA.AttackPlan.STATE_UNEXECUTED)
|
||||
return false;
|
||||
|
||||
let civ = gameState.getPlayerCiv();
|
||||
@ -397,13 +417,13 @@ PETRA.AttackPlan.prototype.addSiegeUnits = function(gameState)
|
||||
i = ++i % classes.length;
|
||||
}
|
||||
|
||||
this.siegeState = 2;
|
||||
this.siegeState = PETRA.AttackPlan.SIEGE_ADDED;
|
||||
let targetSize;
|
||||
if (this.Config.difficulty < 3)
|
||||
targetSize = this.type == "HugeAttack" ? Math.max(this.Config.difficulty, 1) : Math.max(this.Config.difficulty - 1, 0);
|
||||
targetSize = this.type === PETRA.AttackPlan.TYPE_HUGE_ATTACK ? Math.max(this.Config.difficulty, 1) : Math.max(this.Config.difficulty - 1, 0);
|
||||
else
|
||||
targetSize = this.type == "HugeAttack" ? this.Config.difficulty + 1 : this.Config.difficulty - 1;
|
||||
targetSize = Math.max(Math.round(this.Config.popScaling * targetSize), this.type == "HugeAttack" ? 1 : 0);
|
||||
targetSize = this.type === PETRA.AttackPlan.TYPE_HUGE_ATTACK ? this.Config.difficulty + 1 : this.Config.difficulty - 1;
|
||||
targetSize = Math.max(Math.round(this.Config.popScaling * targetSize), this.type === PETRA.AttackPlan.TYPE_HUGE_ATTACK ? 1 : 0);
|
||||
if (!targetSize)
|
||||
return true;
|
||||
// no minsize as we don't want the plan to fail at the last minute though.
|
||||
@ -418,23 +438,23 @@ PETRA.AttackPlan.prototype.updatePreparation = function(gameState)
|
||||
{
|
||||
// the completing step is used to return resources and regroup the units
|
||||
// so we check that we have no more forced order before starting the attack
|
||||
if (this.state == "completing")
|
||||
if (this.state === PETRA.AttackPlan.STATE_COMPLETING)
|
||||
{
|
||||
// if our target was destroyed, go back to "unexecuted" state
|
||||
if (this.targetPlayer === undefined || !this.target || !gameState.getEntityById(this.target.id()))
|
||||
{
|
||||
this.state = "unexecuted";
|
||||
this.state = PETRA.AttackPlan.STATE_UNEXECUTED;
|
||||
this.target = undefined;
|
||||
}
|
||||
else
|
||||
{
|
||||
// check that all units have finished with their transport if needed
|
||||
if (this.waitingForTransport())
|
||||
return 1;
|
||||
return PETRA.AttackPlan.PREPARATION_KEEP_GOING;
|
||||
// bloqued units which cannot finish their order should not stop the attack
|
||||
if (gameState.ai.elapsedTime < this.maxCompletingTime && this.hasForceOrder())
|
||||
return 1;
|
||||
return 2;
|
||||
return PETRA.AttackPlan.PREPARATION_KEEP_GOING;
|
||||
return PETRA.AttackPlan.PREPARATION_START;
|
||||
}
|
||||
}
|
||||
|
||||
@ -443,11 +463,11 @@ PETRA.AttackPlan.prototype.updatePreparation = function(gameState)
|
||||
|
||||
// if we need a transport, wait for some transport ships
|
||||
if (this.overseas && !gameState.ai.HQ.navalManager.seaTransportShips[this.overseas].length)
|
||||
return 1;
|
||||
return PETRA.AttackPlan.PREPARATION_KEEP_GOING;
|
||||
|
||||
if (this.type != "Raid" || !this.forced) // Forced Raids have special purposes (as relic capture)
|
||||
if (this.type !== PETRA.AttackPlan.TYPE_RAID || !this.forced) // Forced Raids have special purposes (as relic capture)
|
||||
this.assignUnits(gameState);
|
||||
if (this.type != "Raid" && gameState.ai.HQ.attackManager.getAttackInPreparation("Raid") !== undefined)
|
||||
if (this.type !== PETRA.AttackPlan.TYPE_RAID && gameState.ai.HQ.attackManager.getAttackInPreparation(PETRA.AttackPlan.TYPE_RAID) !== undefined)
|
||||
this.reassignFastUnit(gameState); // reassign some fast units (if any) to fasten raid preparations
|
||||
|
||||
// Fasten the end game.
|
||||
@ -481,16 +501,16 @@ PETRA.AttackPlan.prototype.updatePreparation = function(gameState)
|
||||
if (this.Config.debug > 1)
|
||||
{
|
||||
let am = gameState.ai.HQ.attackManager;
|
||||
API3.warn(" attacks upcoming: raid " + am.upcomingAttacks.Raid.length +
|
||||
" rush " + am.upcomingAttacks.Rush.length +
|
||||
" attack " + am.upcomingAttacks.Attack.length +
|
||||
" huge " + am.upcomingAttacks.HugeAttack.length);
|
||||
API3.warn(" attacks started: raid " + am.startedAttacks.Raid.length +
|
||||
" rush " + am.startedAttacks.Rush.length +
|
||||
" attack " + am.startedAttacks.Attack.length +
|
||||
" huge " + am.startedAttacks.HugeAttack.length);
|
||||
API3.warn(" attacks upcoming: raid " + am.upcomingAttacks[PETRA.AttackPlan.TYPE_RAID].length +
|
||||
" rush " + am.upcomingAttacks[PETRA.AttackPlan.TYPE_RUSH].length +
|
||||
" attack " + am.upcomingAttacks[PETRA.AttackPlan.TYPE_DEFAULT].length +
|
||||
" huge " + am.upcomingAttacks[PETRA.AttackPlan.TYPE_HUGE_ATTACK].length);
|
||||
API3.warn(" attacks started: raid " + am.startedAttacks[PETRA.AttackPlan.TYPE_RAID].length +
|
||||
" rush " + am.startedAttacks[PETRA.AttackPlan.TYPE_RUSH].length +
|
||||
" attack " + am.startedAttacks[PETRA.AttackPlan.TYPE_DEFAULT].length +
|
||||
" huge " + am.startedAttacks[PETRA.AttackPlan.TYPE_HUGE_ATTACK].length);
|
||||
}
|
||||
return 0;
|
||||
return PETRA.AttackPlan.PREPARATION_FAILED;
|
||||
}
|
||||
}
|
||||
else if (this.mustStart())
|
||||
@ -499,7 +519,7 @@ PETRA.AttackPlan.prototype.updatePreparation = function(gameState)
|
||||
{
|
||||
// keep on while the units finish being trained, then we'll start
|
||||
this.emptyQueues();
|
||||
return 1;
|
||||
return PETRA.AttackPlan.PREPARATION_KEEP_GOING;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -507,30 +527,31 @@ PETRA.AttackPlan.prototype.updatePreparation = function(gameState)
|
||||
if (this.canBuildUnits)
|
||||
{
|
||||
// We still have time left to recruit units and do stuffs.
|
||||
if (this.siegeState == 0 || this.siegeState == 1 && gameState.ai.playedTurn % 5 == 0)
|
||||
if (this.siegeState === PETRA.AttackPlan.SIEGE_NOT_TESTED ||
|
||||
this.siegeState === PETRA.AttackPlan.SIEGE_NO_TRAINER && gameState.ai.playedTurn % 5 == 0)
|
||||
this.addSiegeUnits(gameState);
|
||||
this.trainMoreUnits(gameState);
|
||||
// may happen if we have no more training facilities and build orders are canceled
|
||||
if (!this.buildOrders.length)
|
||||
return 0; // will abort the plan
|
||||
return PETRA.AttackPlan.PREPARATION_FAILED; // will abort the plan
|
||||
}
|
||||
return 1;
|
||||
return PETRA.AttackPlan.PREPARATION_KEEP_GOING;
|
||||
}
|
||||
|
||||
// if we're here, it means we must start
|
||||
this.state = "completing";
|
||||
this.state = PETRA.AttackPlan.STATE_COMPLETING;
|
||||
|
||||
// Raids have their predefined target
|
||||
if (!this.target && !this.chooseTarget(gameState))
|
||||
return 0;
|
||||
return PETRA.AttackPlan.PREPARATION_FAILED;
|
||||
if (!this.overseas)
|
||||
this.getPathToTarget(gameState);
|
||||
|
||||
if (this.type == "Raid")
|
||||
if (this.type === PETRA.AttackPlan.TYPE_RAID)
|
||||
this.maxCompletingTime = this.forced ? 0 : gameState.ai.elapsedTime + 20;
|
||||
else
|
||||
{
|
||||
if (this.type == "Rush" || this.forced)
|
||||
if (this.type === PETRA.AttackPlan.TYPE_RUSH || this.forced)
|
||||
this.maxCompletingTime = gameState.ai.elapsedTime + 40;
|
||||
else
|
||||
this.maxCompletingTime = gameState.ai.elapsedTime + 60;
|
||||
@ -576,7 +597,7 @@ PETRA.AttackPlan.prototype.updatePreparation = function(gameState)
|
||||
|
||||
// reset all queued units
|
||||
this.removeQueues(gameState);
|
||||
return 1;
|
||||
return PETRA.AttackPlan.PREPARATION_KEEP_GOING;
|
||||
};
|
||||
|
||||
PETRA.AttackPlan.prototype.trainMoreUnits = function(gameState)
|
||||
@ -681,7 +702,7 @@ PETRA.AttackPlan.prototype.assignUnits = function(gameState)
|
||||
return added;
|
||||
}
|
||||
|
||||
if (this.type == "Raid")
|
||||
if (this.type === PETRA.AttackPlan.TYPE_RAID)
|
||||
{
|
||||
// Raids are quick attacks: assign all FastMoving soldiers except some for hunting.
|
||||
let num = 0;
|
||||
@ -727,7 +748,7 @@ PETRA.AttackPlan.prototype.assignUnits = function(gameState)
|
||||
|
||||
let num = 0;
|
||||
const numbase = {};
|
||||
let keep = this.type != "Rush" ?
|
||||
let keep = this.type !== PETRA.AttackPlan.TYPE_RUSH ?
|
||||
6 + 4 * gameState.getNumPlayerEnemies() + 8 * this.Config.personality.defensive : 8;
|
||||
keep = Math.round(this.Config.popScaling * keep);
|
||||
for (const ent of gameState.getOwnEntitiesByRole("worker", true).values())
|
||||
@ -745,7 +766,7 @@ PETRA.AttackPlan.prototype.assignUnits = function(gameState)
|
||||
}
|
||||
if (num++ < keep || numbase[baseID] < 5)
|
||||
continue;
|
||||
if (this.type != "Rush" && ent.getMetadata(PlayerID, "subrole") != "idle")
|
||||
if (this.type !== PETRA.AttackPlan.TYPE_RUSH && ent.getMetadata(PlayerID, "subrole") != "idle")
|
||||
continue;
|
||||
ent.setMetadata(PlayerID, "plan", plan);
|
||||
this.unitCollection.updateEnt(ent);
|
||||
@ -775,7 +796,7 @@ PETRA.AttackPlan.prototype.reassignFastUnit = function(gameState)
|
||||
continue;
|
||||
if (!ent.hasClasses(["FastMoving", "CitizenSoldier"]))
|
||||
continue;
|
||||
let raid = gameState.ai.HQ.attackManager.getAttackInPreparation("Raid");
|
||||
const raid = gameState.ai.HQ.attackManager.getAttackInPreparation(PETRA.AttackPlan.TYPE_RAID);
|
||||
ent.setMetadata(PlayerID, "plan", raid.name);
|
||||
this.unitCollection.updateEnt(ent);
|
||||
raid.unitCollection.updateEnt(ent);
|
||||
@ -887,9 +908,9 @@ PETRA.AttackPlan.prototype.getNearestTarget = function(gameState, position, same
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.type == "Raid")
|
||||
if (this.type === PETRA.AttackPlan.TYPE_RAID)
|
||||
targets = this.raidTargetFinder(gameState);
|
||||
else if (this.type == "Rush" || this.type == "Attack")
|
||||
else if (this.type === PETRA.AttackPlan.TYPE_RUSH || this.type === PETRA.AttackPlan.TYPE_DEFAULT)
|
||||
{
|
||||
targets = this.rushTargetFinder(gameState, this.targetPlayer);
|
||||
if (!targets.hasEntities() && (this.hasSiegeUnits() || this.forced))
|
||||
@ -914,7 +935,7 @@ PETRA.AttackPlan.prototype.getNearestTarget = function(gameState, position, same
|
||||
continue;
|
||||
let dist = API3.SquareVectorDistance(ent.position(), position);
|
||||
// In normal attacks, disfavor fields
|
||||
if (this.type != "Rush" && this.type != "Raid" && ent.hasClass("Field"))
|
||||
if (this.type !== PETRA.AttackPlan.TYPE_RUSH && this.type !== PETRA.AttackPlan.TYPE_RAID && ent.hasClass("Field"))
|
||||
dist += 100000;
|
||||
if (dist < minDist)
|
||||
{
|
||||
@ -1034,7 +1055,7 @@ PETRA.AttackPlan.prototype.rushTargetFinder = function(gameState, playerEnemy)
|
||||
if (target)
|
||||
targets.addEnt(target);
|
||||
|
||||
if (!targets.hasEntities() && this.type == "Rush" && playerEnemy)
|
||||
if (!targets.hasEntities() && this.type === PETRA.AttackPlan.TYPE_RUSH && playerEnemy)
|
||||
targets = this.rushTargetFinder(gameState);
|
||||
|
||||
return targets;
|
||||
@ -1285,7 +1306,7 @@ PETRA.AttackPlan.prototype.update = function(gameState, events)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this.state == "arrived")
|
||||
if (this.state === PETRA.AttackPlan.STATE_ARRIVED)
|
||||
{
|
||||
// let's proceed on with whatever happens now.
|
||||
this.state = "";
|
||||
@ -1294,7 +1315,7 @@ PETRA.AttackPlan.prototype.update = function(gameState, events)
|
||||
ent.stopMoving();
|
||||
ent.setMetadata(PlayerID, "subrole", "attacking");
|
||||
});
|
||||
if (this.type == "Rush") // try to find a better target for rush
|
||||
if (this.type === PETRA.AttackPlan.TYPE_RUSH) // try to find a better target for rush
|
||||
{
|
||||
let newtarget = this.getNearestTarget(gameState, this.position);
|
||||
if (newtarget)
|
||||
@ -1450,7 +1471,7 @@ PETRA.AttackPlan.prototype.update = function(gameState, events)
|
||||
|
||||
let targetClassesUnit;
|
||||
let targetClassesSiege;
|
||||
if (this.type == "Rush")
|
||||
if (this.type === PETRA.AttackPlan.TYPE_RUSH)
|
||||
targetClassesUnit = { "attack": ["Unit", "Structure"], "avoid": ["Palisade", "Wall", "Tower", "Fortress"], "vetoEntities": veto };
|
||||
else
|
||||
{
|
||||
@ -1767,7 +1788,7 @@ PETRA.AttackPlan.prototype.UpdateTransporting = function(gameState, events)
|
||||
|
||||
if (done)
|
||||
{
|
||||
this.state = "arrived";
|
||||
this.state = PETRA.AttackPlan.STATE_ARRIVED;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1818,7 +1839,7 @@ PETRA.AttackPlan.prototype.UpdateWalking = function(gameState, events)
|
||||
{
|
||||
if (gameState.ai.HQ.territoryMap.getOwner(this.position) === this.targetPlayer || attackedNB > 3)
|
||||
{
|
||||
this.state = "arrived";
|
||||
this.state = PETRA.AttackPlan.STATE_ARRIVED;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1858,7 +1879,7 @@ PETRA.AttackPlan.prototype.UpdateWalking = function(gameState, events)
|
||||
{
|
||||
if (this.Config.debug > 1)
|
||||
API3.warn("Attack Plan " + this.type + " " + this.name + " has met walls and is not happy.");
|
||||
this.state = "arrived";
|
||||
this.state = PETRA.AttackPlan.STATE_ARRIVED;
|
||||
return true;
|
||||
}
|
||||
// abort plan
|
||||
@ -1876,7 +1897,7 @@ PETRA.AttackPlan.prototype.UpdateWalking = function(gameState, events)
|
||||
{
|
||||
if (this.Config.debug > 1)
|
||||
API3.warn("Attack Plan " + this.type + " " + this.name + " has arrived to destination.");
|
||||
this.state = "arrived";
|
||||
this.state = PETRA.AttackPlan.STATE_ARRIVED;
|
||||
return true;
|
||||
}
|
||||
else if (this.path.length && API3.SquareVectorDistance(this.position, this.path[0]) < 1600)
|
||||
@ -1888,7 +1909,7 @@ PETRA.AttackPlan.prototype.UpdateWalking = function(gameState, events)
|
||||
{
|
||||
if (this.Config.debug > 1)
|
||||
API3.warn("Attack Plan " + this.type + " " + this.name + " has arrived to destination.");
|
||||
this.state = "arrived";
|
||||
this.state = PETRA.AttackPlan.STATE_ARRIVED;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -2052,7 +2073,7 @@ PETRA.AttackPlan.prototype.checkEvents = function(gameState, events)
|
||||
{
|
||||
if (!this.target || this.target.id() != evt.entity)
|
||||
continue;
|
||||
if (this.type == "Raid" && !this.isStarted())
|
||||
if (this.type === PETRA.AttackPlan.TYPE_RAID && !this.isStarted())
|
||||
this.target = undefined;
|
||||
else
|
||||
this.target = gameState.getEntityById(evt.newentity);
|
||||
@ -2072,7 +2093,7 @@ PETRA.AttackPlan.prototype.checkEvents = function(gameState, events)
|
||||
this.target = undefined;
|
||||
}
|
||||
|
||||
if (!this.overseas || this.state !== "unexecuted")
|
||||
if (!this.overseas || this.state !== PETRA.AttackPlan.STATE_UNEXECUTED)
|
||||
return;
|
||||
// let's check if an enemy has built a structure at our access
|
||||
for (let evt of events.Create)
|
||||
|
@ -35,11 +35,29 @@ PETRA.BaseManager = function(gameState, basesManager)
|
||||
this.timeNextIdleCheck = 0;
|
||||
};
|
||||
|
||||
|
||||
PETRA.BaseManager.STATE_WITH_ANCHOR = "anchored";
|
||||
|
||||
/**
|
||||
* New base with a foundation anchor.
|
||||
*/
|
||||
PETRA.BaseManager.STATE_UNCONSTRUCTED = "unconstructed";
|
||||
|
||||
/**
|
||||
* Captured base with an anchor.
|
||||
*/
|
||||
PETRA.BaseManager.STATE_CAPTURED = "captured";
|
||||
|
||||
/**
|
||||
* Anchorless base, currently with dock.
|
||||
*/
|
||||
PETRA.BaseManager.STATE_ANCHORLESS = "anchorless";
|
||||
|
||||
PETRA.BaseManager.prototype.init = function(gameState, state)
|
||||
{
|
||||
if (state == "unconstructed")
|
||||
if (state === PETRA.BaseManager.STATE_UNCONSTRUCTED)
|
||||
this.constructing = true;
|
||||
else if (state != "captured")
|
||||
else if (state !== PETRA.BaseManager.STATE_CAPTURED)
|
||||
this.neededDefenders = 0;
|
||||
this.workerObject = new PETRA.Worker(this);
|
||||
// entitycollections
|
||||
@ -66,12 +84,12 @@ PETRA.BaseManager.prototype.init = function(gameState, state)
|
||||
|
||||
PETRA.BaseManager.prototype.reset = function(gameState, state)
|
||||
{
|
||||
if (state == "unconstructed")
|
||||
if (state === PETRA.BaseManager.STATE_UNCONSTRUCTED)
|
||||
this.constructing = true;
|
||||
else
|
||||
this.constructing = false;
|
||||
|
||||
if (state != "captured" || this.Config.difficulty < 3)
|
||||
if (state !== PETRA.BaseManager.STATE_CAPTURED || this.Config.difficulty < 3)
|
||||
this.neededDefenders = 0;
|
||||
else
|
||||
this.neededDefenders = 3 + 2 * (this.Config.difficulty - 3);
|
||||
@ -122,7 +140,7 @@ PETRA.BaseManager.prototype.setAnchorlessEntity = function(gameState, ent)
|
||||
API3.warn("Error: Petra base " + this.ID + " has been assigned " + ent.templateName() + " as origin.");
|
||||
this.accessIndex = PETRA.getLandAccess(gameState, ent);
|
||||
}
|
||||
else if (this.accessIndex != PETRA.getLandAccess(gameState, ent))
|
||||
else if (this.accessIndex !== PETRA.getLandAccess(gameState, ent))
|
||||
API3.warn(" Error: Petra base " + this.ID + " with access " + this.accessIndex +
|
||||
" has been assigned " + ent.templateName() + " with access" + PETRA.getLandAccess(gameState, ent));
|
||||
|
||||
|
@ -25,14 +25,14 @@ PETRA.BasesManager.prototype.init = function(gameState)
|
||||
this.basesMap = new API3.Map(gameState.sharedScript, "territory");
|
||||
|
||||
this.noBase = new PETRA.BaseManager(gameState, this);
|
||||
this.noBase.init(gameState);
|
||||
this.noBase.init(gameState, PETRA.BaseManager.STATE_WITH_ANCHOR);
|
||||
this.noBase.accessIndex = 0;
|
||||
|
||||
for (const cc of gameState.getOwnStructures().filter(API3.Filters.byClass("CivCentre")).values())
|
||||
if (cc.foundationProgress() === undefined)
|
||||
this.createBase(gameState, cc);
|
||||
this.createBase(gameState, cc, PETRA.BaseManager.STATE_WITH_ANCHOR);
|
||||
else
|
||||
this.createBase(gameState, cc, "unconstructed");
|
||||
this.createBase(gameState, cc, PETRA.BaseManager.STATE_UNCONSTRUCTED);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -65,12 +65,8 @@ PETRA.BasesManager.prototype.postinit = function(gameState)
|
||||
* If an existing one without anchor already exist, use it.
|
||||
* Otherwise create a new one.
|
||||
* TODO when buildings, criteria should depend on distance
|
||||
* allowedType: undefined => new base with an anchor
|
||||
* "unconstructed" => new base with a foundation anchor
|
||||
* "captured" => captured base with an anchor
|
||||
* "anchorless" => anchorless base, currently with dock
|
||||
*/
|
||||
PETRA.BasesManager.prototype.createBase = function(gameState, ent, type)
|
||||
PETRA.BasesManager.prototype.createBase = function(gameState, ent, type = PETRA.BaseManager.STATE_WITH_ANCHOR)
|
||||
{
|
||||
const access = PETRA.getLandAccess(gameState, ent);
|
||||
let newbase;
|
||||
@ -78,9 +74,9 @@ PETRA.BasesManager.prototype.createBase = function(gameState, ent, type)
|
||||
{
|
||||
if (base.accessIndex != access)
|
||||
continue;
|
||||
if (type != "anchorless" && base.anchor)
|
||||
if (type !== PETRA.BaseManager.STATE_ANCHORLESS && base.anchor)
|
||||
continue;
|
||||
if (type != "anchorless")
|
||||
if (type !== PETRA.BaseManager.STATE_ANCHORLESS)
|
||||
{
|
||||
// TODO we keep the first one, we should rather use the nearest if buildings
|
||||
// and possibly also cut on distance
|
||||
@ -116,7 +112,7 @@ PETRA.BasesManager.prototype.createBase = function(gameState, ent, type)
|
||||
else
|
||||
newbase.reset(type);
|
||||
|
||||
if (type != "anchorless")
|
||||
if (type !== PETRA.BaseManager.STATE_ANCHORLESS)
|
||||
newbase.setAnchor(gameState, ent);
|
||||
else
|
||||
newbase.setAnchorlessEntity(gameState, ent);
|
||||
@ -172,7 +168,7 @@ PETRA.BasesManager.prototype.checkEvents = function(gameState, events)
|
||||
if (ent.getMetadata(PlayerID, "base") == -1) // Standard base around a cc
|
||||
{
|
||||
// Okay so let's try to create a new base around this.
|
||||
const newbase = this.createBase(gameState, ent, "unconstructed");
|
||||
const newbase = this.createBase(gameState, ent, PETRA.BaseManager.STATE_UNCONSTRUCTED);
|
||||
// Let's get a few units from other bases there to build this.
|
||||
const builders = this.bulkPickWorkers(gameState, newbase, 10);
|
||||
if (builders !== false)
|
||||
@ -186,7 +182,7 @@ PETRA.BasesManager.prototype.checkEvents = function(gameState, events)
|
||||
}
|
||||
else if (ent.getMetadata(PlayerID, "base") == -2) // anchorless base around a dock
|
||||
{
|
||||
const newbase = this.createBase(gameState, ent, "anchorless");
|
||||
const newbase = this.createBase(gameState, ent, PETRA.BaseManager.STATE_ANCHORLESS);
|
||||
// Let's get a few units from other bases there to build this.
|
||||
const builders = this.bulkPickWorkers(gameState, newbase, 4);
|
||||
if (builders != false)
|
||||
@ -250,10 +246,10 @@ PETRA.BasesManager.prototype.checkEvents = function(gameState, events)
|
||||
{
|
||||
let newbase;
|
||||
if (ent.foundationProgress() !== undefined)
|
||||
newbase = this.createBase(gameState, ent, "unconstructed");
|
||||
newbase = this.createBase(gameState, ent, PETRA.BaseManager.STATE_UNCONSTRUCTED);
|
||||
else
|
||||
{
|
||||
newbase = this.createBase(gameState, ent, "captured");
|
||||
newbase = this.createBase(gameState, ent, PETRA.BaseManager.STATE_CAPTURED);
|
||||
addBase = true;
|
||||
}
|
||||
newbase.assignEntity(gameState, ent);
|
||||
@ -263,7 +259,7 @@ PETRA.BasesManager.prototype.checkEvents = function(gameState, events)
|
||||
let base;
|
||||
// If dropsite on new island, create a base around it
|
||||
if (!ent.decaying() && ent.resourceDropsiteTypes())
|
||||
base = this.createBase(gameState, ent, "anchorless");
|
||||
base = this.createBase(gameState, ent, PETRA.BaseManager.STATE_ANCHORLESS);
|
||||
else
|
||||
base = PETRA.getBestBase(gameState, ent) || this.noBase;
|
||||
base.assignEntity(gameState, ent);
|
||||
@ -582,7 +578,7 @@ PETRA.BasesManager.prototype.assignEntity = function(gameState, ent, territoryIn
|
||||
if (!bestbase) // entity outside our territory
|
||||
{
|
||||
if (ent.hasClass("Structure") && !ent.decaying() && ent.resourceDropsiteTypes())
|
||||
bestbase = this.createBase(gameState, ent, "anchorless");
|
||||
bestbase = this.createBase(gameState, ent, PETRA.BaseManager.STATE_ANCHORLESS);
|
||||
else
|
||||
bestbase = PETRA.getBestBase(gameState, ent) || this.noBase;
|
||||
bestbase.assignEntity(gameState, ent);
|
||||
@ -775,7 +771,7 @@ PETRA.BasesManager.prototype.Deserialize = function(gameState, data)
|
||||
|
||||
this.noBase = new PETRA.BaseManager(gameState, this);
|
||||
this.noBase.Deserialize(gameState, data.noBase);
|
||||
this.noBase.init(gameState);
|
||||
this.noBase.init(gameState, PETRA.BaseManager.STATE_WITH_ANCHOR);
|
||||
this.noBase.Deserialize(gameState, data.noBase);
|
||||
|
||||
this.baseManagers = [];
|
||||
@ -784,7 +780,7 @@ PETRA.BasesManager.prototype.Deserialize = function(gameState, data)
|
||||
// The first call to deserialize set the ID base needed by entitycollections.
|
||||
const newbase = new PETRA.BaseManager(gameState, this);
|
||||
newbase.Deserialize(gameState, basedata);
|
||||
newbase.init(gameState);
|
||||
newbase.init(gameState, PETRA.BaseManager.STATE_WITH_ANCHOR);
|
||||
newbase.Deserialize(gameState, basedata);
|
||||
this.baseManagers.push(newbase);
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ PETRA.chatLaunchAttack = function(gameState, player, type)
|
||||
{
|
||||
Engine.PostCommand(PlayerID, {
|
||||
"type": "aichat",
|
||||
"message": "/allies " + pickRandom(this.launchAttackMessages[type === "HugeAttack" ? "hugeAttack" : "other"]),
|
||||
"message": "/allies " + pickRandom(this.launchAttackMessages[type === PETRA.AttackPlan.TYPE_HUGE_ATTACK ? "hugeAttack" : "other"]),
|
||||
"translateMessage": true,
|
||||
"translateParameters": ["_player_"],
|
||||
"parameters": { "_player_": player }
|
||||
|
@ -606,7 +606,7 @@ PETRA.DefenseManager.prototype.checkEvents = function(gameState, events)
|
||||
if (plan !== undefined && plan >= 0)
|
||||
{
|
||||
let attack = gameState.ai.HQ.attackManager.getPlan(plan);
|
||||
if (attack && attack.state != "unexecuted")
|
||||
if (attack && attack.state != PETRA.AttackPlan.STATE_UNEXECUTED)
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -752,7 +752,7 @@ PETRA.DefenseManager.prototype.garrisonUnitsInside = function(gameState, target,
|
||||
let access = PETRA.getLandAccess(gameState, target);
|
||||
let garrisonManager = gameState.ai.HQ.garrisonManager;
|
||||
let garrisonArrowClasses = target.getGarrisonArrowClasses();
|
||||
let typeGarrison = data.type || "protection";
|
||||
const typeGarrison = data.type || PETRA.GarrisonManager.TYPE_PROTECTION;
|
||||
let allowMelee = gameState.ai.HQ.garrisonManager.allowMelee(target);
|
||||
if (allowMelee === undefined)
|
||||
{
|
||||
@ -767,7 +767,7 @@ PETRA.DefenseManager.prototype.garrisonUnitsInside = function(gameState, target,
|
||||
return false;
|
||||
if (!ent.hasClasses(garrisonArrowClasses))
|
||||
return false;
|
||||
if (typeGarrison != "decay" && !allowMelee && ent.attackTypes().indexOf("Melee") != -1)
|
||||
if (typeGarrison !== PETRA.GarrisonManager.TYPE_DECAY && !allowMelee && ent.attackTypes().indexOf("Melee") != -1)
|
||||
return false;
|
||||
if (ent.getMetadata(PlayerID, "transport") !== undefined)
|
||||
return false;
|
||||
@ -778,7 +778,7 @@ PETRA.DefenseManager.prototype.garrisonUnitsInside = function(gameState, target,
|
||||
{
|
||||
let subrole = ent.getMetadata(PlayerID, "subrole");
|
||||
// When structure decaying (usually because we've just captured it in enemy territory), also allow units from an attack plan.
|
||||
if (typeGarrison != "decay" && subrole && (subrole == "completing" || subrole == "walking" || subrole == "attacking"))
|
||||
if (typeGarrison !== PETRA.GarrisonManager.TYPE_DECAY && subrole && (subrole == "completing" || subrole == "walking" || subrole == "attacking"))
|
||||
return false;
|
||||
}
|
||||
if (PETRA.getLandAccess(gameState, ent) != access)
|
||||
@ -832,7 +832,7 @@ PETRA.DefenseManager.prototype.garrisonSiegeUnit = function(gameState, unit)
|
||||
nearest = ent;
|
||||
}
|
||||
if (nearest)
|
||||
garrisonManager.garrison(gameState, unit, nearest, "protection");
|
||||
garrisonManager.garrison(gameState, unit, nearest, PETRA.GarrisonManager.TYPE_PROTECTION);
|
||||
return nearest !== undefined;
|
||||
};
|
||||
|
||||
@ -873,13 +873,13 @@ PETRA.DefenseManager.prototype.garrisonAttackedUnit = function(gameState, unit,
|
||||
|
||||
if (!emergency)
|
||||
{
|
||||
garrisonManager.garrison(gameState, unit, nearest, "protection");
|
||||
garrisonManager.garrison(gameState, unit, nearest, PETRA.GarrisonManager.TYPE_PROTECTION);
|
||||
return true;
|
||||
}
|
||||
if (garrisonManager.numberOfGarrisonedSlots(nearest) >= nearest.garrisonMax()) // make room for this ent
|
||||
nearest.unload(nearest.garrisoned()[0]);
|
||||
|
||||
garrisonManager.garrison(gameState, unit, nearest, nearest.buffHeal() ? "protection" : "emergency");
|
||||
garrisonManager.garrison(gameState, unit, nearest, nearest.buffHeal() ? PETRA.GarrisonManager.TYPE_PROTECTION : PETRA.GarrisonManager.TYPE_EMERGENCY);
|
||||
return true;
|
||||
};
|
||||
|
||||
|
@ -13,6 +13,12 @@ PETRA.GarrisonManager = function(Config)
|
||||
this.decayingStructures = new Map();
|
||||
};
|
||||
|
||||
PETRA.GarrisonManager.TYPE_FORCE = "force";
|
||||
PETRA.GarrisonManager.TYPE_TRADE = "trade";
|
||||
PETRA.GarrisonManager.TYPE_PROTECTION = "protection";
|
||||
PETRA.GarrisonManager.TYPE_DECAY = "decay";
|
||||
PETRA.GarrisonManager.TYPE_EMERGENCY = "emergency";
|
||||
|
||||
PETRA.GarrisonManager.prototype.update = function(gameState, events)
|
||||
{
|
||||
// First check for possible upgrade of a structure
|
||||
@ -194,7 +200,7 @@ PETRA.GarrisonManager.prototype.update = function(gameState, events)
|
||||
if (!ent || ent.owner() !== PlayerID)
|
||||
this.decayingStructures.delete(id);
|
||||
else if (this.numberOfGarrisonedSlots(ent) < gmin)
|
||||
gameState.ai.HQ.defenseManager.garrisonUnitsInside(gameState, ent, { "min": gmin, "type": "decay" });
|
||||
gameState.ai.HQ.defenseManager.garrisonUnitsInside(gameState, ent, { "min": gmin, "type": PETRA.GarrisonManager.TYPE_DECAY });
|
||||
}
|
||||
};
|
||||
|
||||
@ -284,11 +290,11 @@ PETRA.GarrisonManager.prototype.keepGarrisoned = function(ent, holder, around)
|
||||
{
|
||||
switch (ent.getMetadata(PlayerID, "garrisonType"))
|
||||
{
|
||||
case 'force': // force the ungarrisoning
|
||||
case PETRA.GarrisonManager.TYPE_FORCE: // force the ungarrisoning
|
||||
return false;
|
||||
case 'trade': // trader garrisoned in ship
|
||||
case PETRA.GarrisonManager.TYPE_TRADE: // trader garrisoned in ship
|
||||
return true;
|
||||
case 'protection': // hurt unit for healing or infantry for defense
|
||||
case PETRA.GarrisonManager.TYPE_PROTECTION: // hurt unit for healing or infantry for defense
|
||||
if (holder.buffHeal() && ent.isHealable() && ent.healthLevel() < this.Config.garrisonHealthLevel.high)
|
||||
return true;
|
||||
let capture = ent.capturePoints();
|
||||
@ -309,9 +315,9 @@ PETRA.GarrisonManager.prototype.keepGarrisoned = function(ent, holder, around)
|
||||
if (PETRA.isSiegeUnit(ent))
|
||||
return around.meleeSiege;
|
||||
return holder.buffHeal() && ent.needsHeal();
|
||||
case 'decay':
|
||||
case PETRA.GarrisonManager.TYPE_DECAY:
|
||||
return this.decayingStructures.has(holder.id());
|
||||
case 'emergency': // f.e. hero in regicide mode
|
||||
case PETRA.GarrisonManager.TYPE_EMERGENCY: // f.e. hero in regicide mode
|
||||
if (holder.buffHeal() && ent.isHealable() && ent.healthLevel() < this.Config.garrisonHealthLevel.high)
|
||||
return true;
|
||||
if (around.unit || around.defenseStructure || around.meleeSiege ||
|
||||
@ -324,7 +330,7 @@ PETRA.GarrisonManager.prototype.keepGarrisoned = function(ent, holder, around)
|
||||
API3.warn("unknown type in garrisonManager " + ent.getMetadata(PlayerID, "garrisonType") +
|
||||
" for " + ent.genericName() + " id " + ent.id() +
|
||||
" inside " + holder.genericName() + " id " + holder.id());
|
||||
ent.setMetadata(PlayerID, "garrisonType", "protection");
|
||||
ent.setMetadata(PlayerID, "garrisonType", PETRA.GarrisonManager.TYPE_PROTECTION);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -210,7 +210,7 @@ PETRA.HQ.prototype.checkEvents = function(gameState, events)
|
||||
if (plan !== undefined && plan >= 0)
|
||||
{
|
||||
let attack = this.attackManager.getPlan(plan);
|
||||
if (!attack || attack.state != "unexecuted")
|
||||
if (!attack || attack.state !== PETRA.AttackPlan.STATE_UNEXECUTED)
|
||||
ent.setMetadata(PlayerID, "plan", -1);
|
||||
}
|
||||
}
|
||||
@ -441,7 +441,7 @@ PETRA.HQ.prototype.trainMoreWorkers = function(gameState, queues)
|
||||
let alpha = 0.85;
|
||||
if (!gameState.isTemplateAvailable(gameState.applyCiv("structures/{civ}/field")))
|
||||
supportRatio = Math.min(this.supportRatio, 0.1);
|
||||
if (this.attackManager.rushNumber < this.attackManager.maxRushes || this.attackManager.upcomingAttacks.Rush.length)
|
||||
if (this.attackManager.rushNumber < this.attackManager.maxRushes || this.attackManager.upcomingAttacks[PETRA.AttackPlan.TYPE_RUSH].length)
|
||||
alpha = 0.7;
|
||||
if (gameState.isCeasefireActive())
|
||||
alpha += (1 - alpha) * Math.min(Math.max(gameState.ceasefireTimeRemaining - 120, 0), 180) / 180;
|
||||
@ -1869,7 +1869,7 @@ PETRA.HQ.prototype.trainEmergencyUnits = function(gameState, positions)
|
||||
}
|
||||
let metadata = { "role": "worker", "base": nearestAnchor.getMetadata(PlayerID, "base"), "plan": -1, "trainer": nearestAnchor.id() };
|
||||
if (autogarrison)
|
||||
metadata.garrisonType = "protection";
|
||||
metadata.garrisonType = PETRA.GarrisonManager.TYPE_PROTECTION;
|
||||
gameState.ai.queues.emergency.addPlan(new PETRA.TrainingPlan(gameState, templateFound[0], metadata, 1, 1));
|
||||
return true;
|
||||
};
|
||||
|
@ -679,7 +679,7 @@ PETRA.VictoryManager.prototype.captureGaiaRelic = function(gameState, relic)
|
||||
if (plan !== undefined && plan >= 0)
|
||||
{
|
||||
let attack = gameState.ai.HQ.attackManager.getPlan(plan);
|
||||
if (attack && (attack.state != "unexecuted" || attack.type == "Raid"))
|
||||
if (attack && (attack.state !== PETRA.AttackPlan.STATE_UNEXECUTED || attack.type === PETRA.AttackPlan.TYPE_RAID))
|
||||
return false;
|
||||
}
|
||||
if (PETRA.getLandAccess(gameState, ent) != access)
|
||||
|
Loading…
Reference in New Issue
Block a user