mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-06-22 01:46:34 +00:00
petra: react to more capture events and some tweaks on attacks
This was SVN commit r16559.
This commit is contained in:
@@ -64,7 +64,7 @@ m.AttackPlan = function(gameState, Config, uniqueID, type, data)
|
||||
// priority of the queues we'll create.
|
||||
var priority = 70;
|
||||
|
||||
// priority is relative. If all are 0, the only relevant criteria is "currentsize/targetsize".
|
||||
// unitStat priority is relative. If all are 0, the only relevant criteria is "currentsize/targetsize".
|
||||
// if not, this is a "bonus". The higher the priority, the faster this unit will get built.
|
||||
// Should really be clamped to [0.1-1.5] (assuming 1 is default/the norm)
|
||||
// Eg: if all are priority 1, and the siege is 0.5, the siege units will get built
|
||||
@@ -470,6 +470,16 @@ m.AttackPlan.prototype.updatePreparation = function(gameState)
|
||||
if (this.canBuildUnits)
|
||||
{
|
||||
// We still have time left to recruit units and do stuffs.
|
||||
if (!this.unitStat["Siege"])
|
||||
{
|
||||
var numSiegeBuilder = 0;
|
||||
if (gameState.civ() !== "mace" && gameState.civ() !== "maur")
|
||||
numSiegeBuilder += gameState.getOwnEntitiesByClass("Fortress", true).filter(API3.Filters.isBuilt()).length;
|
||||
if (gameState.civ() === "mace" || gameState.civ() === "maur" || gameState.civ() === "rome")
|
||||
numSiegeBuilder += gameState.countEntitiesByType(this.bAdvanced[0], true);
|
||||
if (numSiegeBuilder > 0)
|
||||
this.addSiegeUnits(gameState);
|
||||
}
|
||||
this.trainMoreUnits(gameState);
|
||||
// may happen if we have no more training facilities and build orders are canceled
|
||||
if (this.buildOrder.length == 0)
|
||||
@@ -1385,9 +1395,16 @@ m.AttackPlan.prototype.update = function(gameState, events)
|
||||
targetClassesUnit = {"attack": ["Unit", "Structure"], "avoid": ["Fortress", "StoneWall"], "vetoEntities": veto};
|
||||
}
|
||||
if (this.target.hasClass("Structure"))
|
||||
targetClassesSiege = {"attack": ["Structure"], "vetoEntities": veto};
|
||||
targetClassesSiege = {"attack": ["Structure"], "avoid": [], "vetoEntities": veto};
|
||||
else
|
||||
targetClassesSiege = {"attack": ["Unit", "Structure"], "vetoEntities": veto};
|
||||
targetClassesSiege = {"attack": ["Unit", "Structure"], "avoid": [], "vetoEntities": veto};
|
||||
|
||||
// do not loose time destroying buildings which do not help enemy's defense and can be easily captured later
|
||||
if (this.target.getDefaultArrow() || this.target.getArrowMultiplier())
|
||||
{
|
||||
targetClassesUnit.avoid = targetClassesUnit.avoid.concat("House", "Storehouse", "Farmstead", "Field", "Blacksmith");
|
||||
targetClassesSiege.avoid = targetClassesSiege.avoid.concat("House", "Storehouse", "Farmstead", "Field", "Blacksmith");
|
||||
}
|
||||
|
||||
if (this.unitCollUpdateArray === undefined || this.unitCollUpdateArray.length == 0)
|
||||
this.unitCollUpdateArray = this.unitCollection.toIdArray();
|
||||
@@ -1509,7 +1526,7 @@ m.AttackPlan.prototype.update = function(gameState, events)
|
||||
{
|
||||
if (!ent.hasClass("Ranged"))
|
||||
{
|
||||
let targetClasses = {"attack": targetClassesSiege.attack, "avoid": ["Ship"], "vetoEntities": veto};
|
||||
let targetClasses = {"attack": targetClassesSiege.attack, "avoid": targetClassesSiege.avoid.concat("Ship"), "vetoEntities": veto};
|
||||
ent.attackMove(this.targetPos[0], this.targetPos[1], targetClasses);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -110,21 +110,24 @@ m.BaseManager.prototype.checkEvents = function (gameState, events, queues)
|
||||
if (ent.resourceDropsiteTypes() && !ent.hasClass("Elephant"))
|
||||
this.removeDropsite(gameState, ent);
|
||||
if (evt.metadata[PlayerID]["baseAnchor"] && evt.metadata[PlayerID]["baseAnchor"] === true)
|
||||
{
|
||||
// sounds like we lost our anchor. Let's reaffect our units and buildings
|
||||
this.anchor = undefined;
|
||||
this.anchorId = undefined;
|
||||
this.neededDefenders = 0;
|
||||
let bestbase = m.getBestBase(ent, gameState);
|
||||
this.newbaseID = bestbase.ID;
|
||||
for (let entity of this.units.values())
|
||||
bestbase.assignEntity(gameState, entity);
|
||||
for (let entity of this.buildings.values())
|
||||
bestbase.assignEntity(gameState, entity);
|
||||
}
|
||||
this.anchorLost(gameState, ent);
|
||||
}
|
||||
}
|
||||
|
||||
let captureEvents = events["OwnershipChanged"];
|
||||
for (let evt of captureEvents)
|
||||
{
|
||||
if (evt.from !== PlayerID)
|
||||
continue;
|
||||
let ent = gameState.getEntityById(evt.entity);
|
||||
if (!ent || ent.getMetadata(PlayerID, "base") !== this.ID)
|
||||
continue;
|
||||
if (ent.resourceDropsiteTypes() && !ent.hasClass("Elephant"))
|
||||
this.removeDropsite(gameState, ent);
|
||||
if (ent.getMetadata(PlayerID, "baseAnchor") === true)
|
||||
this.anchorLost(gameState, ent);
|
||||
}
|
||||
|
||||
for (var evt of cFinishedEvents)
|
||||
{
|
||||
if (!evt || !evt.newentity)
|
||||
@@ -163,6 +166,20 @@ m.BaseManager.prototype.checkEvents = function (gameState, events, queues)
|
||||
}
|
||||
};
|
||||
|
||||
/* we lost our anchor. Let's reaffect our units and buildings */
|
||||
m.BaseManager.prototype.anchorLost = function (gameState, ent)
|
||||
{
|
||||
this.anchor = undefined;
|
||||
this.anchorId = undefined;
|
||||
this.neededDefenders = 0;
|
||||
let bestbase = m.getBestBase(ent, gameState);
|
||||
this.newbaseID = bestbase.ID;
|
||||
for (let entity of this.units.values())
|
||||
bestbase.assignEntity(gameState, entity);
|
||||
for (let entity of this.buildings.values())
|
||||
bestbase.assignEntity(gameState, entity);
|
||||
};
|
||||
|
||||
/**
|
||||
* Assign the resources around the dropsites of this basis in three areas according to distance, and sort them in each area.
|
||||
* Moving resources (animals) and buildable resources (fields) are treated elsewhere.
|
||||
|
||||
@@ -289,6 +289,9 @@ m.HQ.prototype.OnCityPhase = function(gameState)
|
||||
if (this.Config.difficulty > 2 && this.femaleRatio > 0.3)
|
||||
this.femaleRatio = 0.3;
|
||||
|
||||
// increase the priority of defense buildings to free this queue for our first fortress
|
||||
gameState.ai.queueManager.changePriority("defenseBuilding", 2*this.Config.priorities.defenseBuilding);
|
||||
|
||||
this.phaseStarted = 3;
|
||||
};
|
||||
|
||||
@@ -1249,50 +1252,34 @@ m.HQ.prototype.buildNewBase = function(gameState, queues, resource)
|
||||
// Deals with building fortresses and towers along our border with enemies.
|
||||
m.HQ.prototype.buildDefenses = function(gameState, queues)
|
||||
{
|
||||
if (this.saveResources)
|
||||
if (this.saveResources || queues.defenseBuilding.length() !== 0)
|
||||
return;
|
||||
|
||||
if (gameState.currentPhase() > 2 || gameState.isResearching(gameState.cityPhase()))
|
||||
{
|
||||
// try to build fortresses
|
||||
var fortressType = "structures/{civ}_fortress";
|
||||
if (queues.defenseBuilding.length() == 0 && this.canBuild(gameState, fortressType))
|
||||
if (this.canBuild(gameState, "structures/{civ}_fortress"))
|
||||
{
|
||||
var numFortresses = gameState.getOwnEntitiesByClass("Fortress", true).length;
|
||||
if (gameState.ai.elapsedTime > (1 + 0.10*numFortresses)*this.fortressLapseTime + this.fortressStartTime)
|
||||
let numFortresses = gameState.getOwnEntitiesByClass("Fortress", true).length;
|
||||
if ((numFortresses == 0 || gameState.ai.elapsedTime > (1 + 0.10*numFortresses)*this.fortressLapseTime + this.fortressStartTime)
|
||||
&& gameState.getOwnFoundationsByClass("Fortress").length < 2)
|
||||
{
|
||||
this.fortressStartTime = gameState.ai.elapsedTime;
|
||||
queues.defenseBuilding.addItem(new m.ConstructionPlan(gameState, fortressType));
|
||||
if (numFortresses == 0)
|
||||
gameState.ai.queueManager.changePriority("defenseBuilding", 2*this.Config.priorities.defenseBuilding);
|
||||
let plan = new m.ConstructionPlan(gameState, "structures/{civ}_fortress");
|
||||
plan.onStart = function(gameState) { gameState.ai.queueManager.changePriority("defenseBuilding", gameState.ai.Config.priorities.defenseBuilding); };
|
||||
queues.defenseBuilding.addItem(plan);
|
||||
}
|
||||
}
|
||||
|
||||
// let's add a siege building plan to the current attack plan if there is none currently.
|
||||
var numSiegeBuilder = 0;
|
||||
if (gameState.civ() !== "mace" && gameState.civ() !== "maur")
|
||||
numSiegeBuilder += gameState.getOwnEntitiesByClass("Fortress", true).filter(API3.Filters.isBuilt()).length;
|
||||
if (gameState.civ() === "mace" || gameState.civ() === "maur" || gameState.civ() === "rome")
|
||||
numSiegeBuilder += gameState.countEntitiesByType(this.bAdvanced[0], true);
|
||||
if (numSiegeBuilder > 0)
|
||||
{
|
||||
var attack = undefined;
|
||||
// There can only be one upcoming attack
|
||||
if (this.attackManager.upcomingAttacks["Attack"].length != 0)
|
||||
attack = this.attackManager.upcomingAttacks["Attack"][0];
|
||||
else if (this.attackManager.upcomingAttacks["HugeAttack"].length != 0)
|
||||
attack = this.attackManager.upcomingAttacks["HugeAttack"][0];
|
||||
|
||||
if (attack && !attack.unitStat["Siege"])
|
||||
attack.addSiegeUnits(gameState);
|
||||
}
|
||||
}
|
||||
|
||||
if (gameState.currentPhase() < 2
|
||||
|| queues.defenseBuilding.length() != 0
|
||||
|| !this.canBuild(gameState, "structures/{civ}_defense_tower"))
|
||||
if (gameState.currentPhase() < 2 || !this.canBuild(gameState, "structures/{civ}_defense_tower"))
|
||||
return;
|
||||
|
||||
var numTowers = gameState.getOwnEntitiesByClass("DefenseTower", true).length;
|
||||
if (gameState.ai.elapsedTime > (1 + 0.10*numTowers)*this.towerLapseTime + this.towerStartTime)
|
||||
let numTowers = gameState.getOwnEntitiesByClass("DefenseTower", true).length;
|
||||
if ((numTowers == 0 || gameState.ai.elapsedTime > (1 + 0.10*numTowers)*this.towerLapseTime + this.towerStartTime)
|
||||
&& gameState.getOwnFoundationsByClass("DefenseTower").length < 3)
|
||||
{
|
||||
this.towerStartTime = gameState.ai.elapsedTime;
|
||||
queues.defenseBuilding.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_defense_tower"));
|
||||
|
||||
@@ -322,7 +322,7 @@ m.TradeManager.prototype.checkEvents = function(gameState, events)
|
||||
}
|
||||
}
|
||||
|
||||
// if one market is destroyed or built, we may have to look for a better route
|
||||
// if one market is destroyed or built (i.e. its foundation is destroyed), we should look for a better route
|
||||
let destroyEvents = events["Destroy"];
|
||||
for (let evt of destroyEvents)
|
||||
{
|
||||
@@ -331,13 +331,21 @@ m.TradeManager.prototype.checkEvents = function(gameState, events)
|
||||
let ent = evt.entityObj;
|
||||
if (!ent || !ent.hasClass("Market") || !gameState.isPlayerAlly(ent.owner()))
|
||||
continue;
|
||||
if (this.Config.debug > 1)
|
||||
{
|
||||
if (evt.SuccessfulFoundation)
|
||||
API3.warn("new market build ... checking routes");
|
||||
else
|
||||
API3.warn("one market (or foundation) has been destroyed ... checking routes");
|
||||
}
|
||||
this.routeProspection = true;
|
||||
gameState.ai.HQ.restartBuild(gameState, "structures/{civ}_market");
|
||||
gameState.ai.HQ.restartBuild(gameState, "structures/{civ}_dock");
|
||||
return true;
|
||||
}
|
||||
|
||||
// same thing for captured markets
|
||||
let capturedEvents = events["OwnershipChanged"];
|
||||
for (let evt of capturedEvents)
|
||||
{
|
||||
if (!gameState.isPlayerAlly(evt.from) && !gameState.isPlayerAlly(evt.to))
|
||||
continue;
|
||||
let ent = gameState.getEntityById(evt.entity);
|
||||
if (!ent || !ent.hasClass("Market"))
|
||||
continue;
|
||||
this.routeProspection = true;
|
||||
gameState.ai.HQ.restartBuild(gameState, "structures/{civ}_market");
|
||||
gameState.ai.HQ.restartBuild(gameState, "structures/{civ}_dock");
|
||||
|
||||
Reference in New Issue
Block a user