forked from mirrors/0ad
petra: rework the management of siege units in attacks, to remove some civ hardcodings + some cleanup
This was SVN commit r20260.
This commit is contained in:
@@ -701,7 +701,7 @@ m.GameState.prototype.findTrainableUnits = function(classes, anticlasses)
|
||||
{
|
||||
let allTrainable = [];
|
||||
let civ = this.playerData.civ;
|
||||
this.getOwnStructures().forEach(function(ent) {
|
||||
this.getOwnTrainingFacilities().forEach(function(ent) {
|
||||
let trainable = ent.trainableEntities(civ);
|
||||
if (!trainable)
|
||||
return;
|
||||
@@ -719,28 +719,10 @@ m.GameState.prototype.findTrainableUnits = function(classes, anticlasses)
|
||||
let template = this.getTemplate(trainable);
|
||||
if (!template || !template.available(this))
|
||||
continue;
|
||||
|
||||
let okay = true;
|
||||
for (let clas of classes)
|
||||
{
|
||||
if (template.hasClass(clas))
|
||||
continue;
|
||||
okay = false;
|
||||
break;
|
||||
}
|
||||
if (!okay)
|
||||
if (classes.some(c => !template.hasClass(c)))
|
||||
continue;
|
||||
|
||||
for (let clas of anticlasses)
|
||||
{
|
||||
if (!template.hasClass(clas))
|
||||
continue;
|
||||
okay = false;
|
||||
break;
|
||||
}
|
||||
if (!okay)
|
||||
if (anticlasses.some(c => template.hasClass(c)))
|
||||
continue;
|
||||
|
||||
let category = template.trainingCategory();
|
||||
if (category && limits[category] && current[category] >= limits[category])
|
||||
continue;
|
||||
|
||||
@@ -336,8 +336,9 @@ m.AttackManager.prototype.update = function(gameState, queues, events)
|
||||
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)))
|
||||
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))
|
||||
{
|
||||
if (barracksNb >= 1 && (gameState.currentPhase() > 1 || gameState.isResearching(gameState.getPhaseName(2))) ||
|
||||
!gameState.ai.HQ.baseManagers[1]) // if we have no base ... nothing else to do than attack
|
||||
|
||||
@@ -195,6 +195,7 @@ m.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
|
||||
|
||||
// some variables used during the attack
|
||||
this.position5TurnsAgo = [0,0];
|
||||
@@ -334,18 +335,49 @@ m.AttackPlan.prototype.addBuildOrder = function(gameState, name, unitStats, rese
|
||||
|
||||
m.AttackPlan.prototype.addSiegeUnits = function(gameState)
|
||||
{
|
||||
if (this.unitStat.Siege || this.state !== "unexecuted")
|
||||
if (this.siegeState == 2 || this.state !== "unexecuted")
|
||||
return false;
|
||||
|
||||
let playerCiv = gameState.getPlayerCiv();
|
||||
let classes = [[ "Siege", "Melee"], ["Siege", "Ranged"], ["Elephant", "Melee", "Champion"]];
|
||||
let hasTrainer = [false, false, false];
|
||||
for (let ent of gameState.getOwnTrainingFacilities().values())
|
||||
{
|
||||
let trainables = ent.trainableEntities(playerCiv);
|
||||
if (!trainables)
|
||||
continue;
|
||||
for (let trainable of trainables)
|
||||
{
|
||||
if (gameState.isTemplateDisabled(trainable))
|
||||
continue;
|
||||
let template = gameState.getTemplate(trainable);
|
||||
if (!template || !template.available(gameState))
|
||||
continue;
|
||||
for (let i = 0; i < classes.length; ++i)
|
||||
if (classes[i].every(c => template.hasClass(c)))
|
||||
hasTrainer[i] = true;
|
||||
}
|
||||
}
|
||||
if (hasTrainer.every(e => !e))
|
||||
return false;
|
||||
let i = this.name % classes.length;
|
||||
for (let k = 0; k < classes.length; ++k)
|
||||
{
|
||||
if (hasTrainer[i])
|
||||
break;
|
||||
i = ++i % classes.length;
|
||||
}
|
||||
|
||||
this.siegeState = 2;
|
||||
let targetSize = this.type == "HugeAttack" ? 6 : 4;
|
||||
if (this.Config.difficulty < 3)
|
||||
targetSize = this.Config.difficulty;
|
||||
targetSize = Math.round(this.Config.popScaling * targetSize);
|
||||
if (!targetSize)
|
||||
return true;
|
||||
// no minsize as we don't want the plan to fail at the last minute though.
|
||||
let stat = { "priority": 1, "minSize": 0, "targetSize": 4, "batchSize": 2, "classes": ["Siege"],
|
||||
"interests": [ ["siegeStrength", 3] ] };
|
||||
if (gameState.getPlayerCiv() === "maur")
|
||||
stat.classes = ["Elephant", "Champion"];
|
||||
if (this.Config.difficulty < 2)
|
||||
stat.targetSize = 1;
|
||||
else if (this.Config.difficulty < 3)
|
||||
stat.targetSize = 2;
|
||||
stat.targetSize = Math.round(this.Config.popScaling * stat.targetSize);
|
||||
let stat = { "priority": 1, "minSize": 0, "targetSize": targetSize, "batchSize": Math.min(targetSize, 2),
|
||||
"classes": classes[i], "interests": [ ["siegeStrength", 3] ] };
|
||||
this.addBuildOrder(gameState, "Siege", stat, true);
|
||||
return true;
|
||||
};
|
||||
@@ -428,17 +460,8 @@ m.AttackPlan.prototype.updatePreparation = function(gameState)
|
||||
if (this.canBuildUnits)
|
||||
{
|
||||
// We still have time left to recruit units and do stuffs.
|
||||
if (!this.unitStat.Siege)
|
||||
{
|
||||
let numSiegeBuilder = 0;
|
||||
let playerCiv = gameState.getPlayerCiv();
|
||||
if (playerCiv !== "mace" && playerCiv !== "maur")
|
||||
numSiegeBuilder += gameState.getOwnEntitiesByClass("Fortress", true).filter(API3.Filters.isBuilt()).length;
|
||||
if (playerCiv === "mace" || playerCiv === "maur" || playerCiv === "rome")
|
||||
numSiegeBuilder += gameState.countEntitiesByType(gameState.ai.HQ.bAdvanced[0], true);
|
||||
if (numSiegeBuilder > 0)
|
||||
this.addSiegeUnits(gameState);
|
||||
}
|
||||
if (this.siegeState == 0 || this.siegeState == 1 && 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)
|
||||
@@ -558,13 +581,12 @@ m.AttackPlan.prototype.trainMoreUnits = function(gameState)
|
||||
{
|
||||
// find the actual queue we want
|
||||
let queue = this.queue;
|
||||
if (firstOrder[3].classes.indexOf("Siege") !== -1 ||
|
||||
gameState.getPlayerCiv() == "maur" && firstOrder[3].classes.indexOf("Elephant") !== -1 &&
|
||||
firstOrder[3].classes.indexOf("Champion") !== -1)
|
||||
if (firstOrder[3].classes.indexOf("Siege") != -1 || firstOrder[3].classes.indexOf("Elephant") != -1 &&
|
||||
firstOrder[3].classes.indexOf("Melee") != -1 && firstOrder[3].classes.indexOf("Champion") != -1)
|
||||
queue = this.queueSiege;
|
||||
else if (firstOrder[3].classes.indexOf("Hero") !== -1)
|
||||
else if (firstOrder[3].classes.indexOf("Hero") != -1)
|
||||
queue = this.queueSiege;
|
||||
else if (firstOrder[3].classes.indexOf("Champion") !== -1)
|
||||
else if (firstOrder[3].classes.indexOf("Champion") != -1)
|
||||
queue = this.queueChamp;
|
||||
|
||||
if (queue.length() <= 5)
|
||||
@@ -2052,6 +2074,7 @@ m.AttackPlan.prototype.Serialize = function()
|
||||
"maxCompletingTime": this.maxCompletingTime,
|
||||
"neededShips": this.neededShips,
|
||||
"unitStat": this.unitStat,
|
||||
"siegeState": this.siegeState,
|
||||
"position5TurnsAgo": this.position5TurnsAgo,
|
||||
"lastPosition": this.lastPosition,
|
||||
"position": this.position,
|
||||
|
||||
@@ -4,7 +4,7 @@ var PETRA = function(m)
|
||||
/** returns true if this unit should be considered as a siege unit */
|
||||
m.isSiegeUnit = function(ent)
|
||||
{
|
||||
return ent.hasClass("Siege") || ent.hasClass("Elephant") && ent.hasClass("Champion");
|
||||
return ent.hasClass("Siege") || ent.hasClass("Elephant") && ent.hasClass("Melee") && ent.hasClass("Champion");
|
||||
};
|
||||
|
||||
/** returns some sort of DPS * health factor. If you specify a class, it'll use the modifiers against that class too. */
|
||||
|
||||
Reference in New Issue
Block a user