1
0
forked from mirrors/0ad

Petra: fix a case where the AI loose control of its units (they become only driven by UnitAI)

Reviewed By: Sandarac
Differential Revision: https://code.wildfiregames.com/D545
This was SVN commit r19655.
This commit is contained in:
mimo
2017-05-25 20:26:22 +00:00
parent a2d87af95d
commit d5dcb0c61e
2 changed files with 73 additions and 7 deletions
@@ -280,8 +280,69 @@ m.Army.prototype.clear = function (gameState)
{
while (this.foeEntities.length > 0)
this.removeFoe(gameState,this.foeEntities[0]);
// Go back to our territory, using the nearest (defensive if any) structure.
let armyPos = [0, 0];
let npos = 0;
for (let entId of this.ownEntities)
{
let ent = gameState.getEntityById(entId);
if (!ent)
continue;
let pos = ent.position();
if (!pos || gameState.ai.HQ.territoryMap.getOwner(pos) === PlayerID)
continue;
armyPos[0] += pos[0];
armyPos[1] += pos[1];
++npos;
}
let nearestStructurePos;
let defensiveFound;
let distmin;
let radius;
if (npos > 0)
{
armyPos[0] /= npos;
armyPos[1] /= npos;
let armyAccess = gameState.ai.accessibility.getAccessValue(armyPos);
for (let struct of gameState.getOwnStructures().values())
{
let pos = struct.position();
if (!pos || gameState.ai.HQ.territoryMap.getOwner(pos) !== PlayerID)
continue;
if (m.getLandAccess(gameState, struct) !== armyAccess)
continue;
let defensiveStruct = struct.hasDefensiveFire();
if (defensiveFound && !defensiveStruct)
continue;
let dist = API3.SquareVectorDistance(armyPos, pos);
if (distmin && dist > distmin && (defensiveFound || !defensiveStruct))
continue;
if (defensiveStruct)
defensiveFound = true;
distmin = dist;
nearestStructurePos = pos;
radius = struct.obstructionRadius();
}
}
while (this.ownEntities.length > 0)
this.removeOwn(gameState,this.ownEntities[0]);
{
let entId = this.ownEntities[0];
this.removeOwn(gameState, entId);
let ent = gameState.getEntityById(entId);
if (ent)
{
if (!ent.position() ||
ent.healthLevel() < this.Config.garrisonHealthLevel.low &&
gameState.ai.HQ.defenseManager.garrisonAttackedUnit(gameState, ent))
continue;
if (nearestStructurePos && gameState.ai.HQ.territoryMap.getOwner(ent.position()) !== PlayerID)
ent.moveToRange(nearestStructurePos[0], nearestStructurePos[1], radius, radius+5);
else
ent.stopMoving();
}
}
this.assignedAgainst = {};
this.assignedTo = {};
@@ -566,18 +566,18 @@ m.DefenseManager.prototype.garrisonUnitsInside = function(gameState, target, dat
let minGarrison = data.min ? data.min : target.garrisonMax();
let typeGarrison = data.type ? data.type : "protection";
if (gameState.ai.HQ.garrisonManager.numberOfGarrisonedUnits(target) >= minGarrison)
return;
return false;
if (target.hitpoints() < target.garrisonEjectHealth() * target.maxHitpoints())
return;
return false;
if (data.attacker)
{
let attackTypes = target.attackTypes();
if (!attackTypes || attackTypes.indexOf("Ranged") === -1)
return;
return false;
let dist = API3.SquareVectorDistance(data.attacker.position(), target.position());
let range = target.attackRange("Ranged").max;
if (dist >= range*range)
return;
return false;
}
let index = gameState.ai.accessibility.getAccessValue(target.position());
let garrisonManager = gameState.ai.HQ.garrisonManager;
@@ -592,6 +592,7 @@ m.DefenseManager.prototype.garrisonUnitsInside = function(gameState, target, dat
else
allowMelee = true;
}
let ret = false;
for (let ent of units.values())
{
if (garrisonManager.numberOfGarrisonedUnits(target) >= minGarrison)
@@ -623,7 +624,9 @@ m.DefenseManager.prototype.garrisonUnitsInside = function(gameState, target, dat
if (army)
army.removeOwn(gameState, ent.id());
garrisonManager.garrison(gameState, ent, target, typeGarrison);
ret = true;
}
return ret;
};
/** garrison a attacked siege ranged unit inside the nearest fortress */
@@ -650,6 +653,7 @@ m.DefenseManager.prototype.garrisonSiegeUnit = function(gameState, unit)
});
if (nearest)
garrisonManager.garrison(gameState, unit, nearest, "protection");
return nearest !== undefined;
};
/**
@@ -683,17 +687,18 @@ m.DefenseManager.prototype.garrisonAttackedUnit = function(gameState, unit, emer
nearest = ent;
}
if (!nearest)
return;
return false;
if (!emergency)
{
garrisonManager.garrison(gameState, unit, nearest, "protection");
return;
return true;
}
if (garrisonManager.numberOfGarrisonedUnits(nearest) >= nearest.garrisonMax()) // make room for this ent
nearest.unload(nearest.garrisoned()[0]);
garrisonManager.garrison(gameState, unit, nearest, nearest.buffHeal() ? "protection" : "emergency");
return true;
};
/**