BuildingAI style fixes, refs #3763.

Remove a duplicate targetUnits-, some useless length-checks and unneeded
comments.

This was SVN commit r17783.
This commit is contained in:
elexis
2016-02-22 16:44:57 +00:00
parent 8f630789e6
commit 94ccb153a6
2 changed files with 75 additions and 102 deletions
@@ -51,20 +51,23 @@ function damageTypeDetails(dmg)
function attackRateDetails(entState, type)
{
// Either one arrow shot by UnitAI,
let time = entState.attack[type].repeatTime / 1000;
let timeString = sprintf(translatePlural("%(time)s %(second)s", "%(time)s %(second)s", time), {
"time": time,
"second": g_TooltipTextFormats.unit[0] + translatePlural("second", "seconds", time) + g_TooltipTextFormats.unit[1]
});
// or multiple arrows shot by BuildingAI
if (!entState.buildingAI)
return timeString;
let arrows = Math.max(entState.buildingAI.arrowCount, entState.buildingAI.defaultArrowCount);
let arrows = entState.buildingAI.arrowCount;
let arrowString = sprintf(translatePlural("%(arrowcount)s %(arrow)s", "%(arrowcount)s %(arrow)s", arrows), {
"arrowcount": arrows,
"arrow": g_TooltipTextFormats.unit[0] + translatePlural("arrow", "arrows", arrows) + g_TooltipTextFormats.unit[1]
});
return sprintf(translate("%(arrowString)s / %(timeString)s"), {
"arrowString": arrowString,
"timeString": timeString
@@ -17,22 +17,16 @@ BuildingAI.prototype.Schema =
BuildingAI.prototype.MAX_PREFERENCE_BONUS = 2;
/**
* Initialize BuildingAI Component
*/
BuildingAI.prototype.Init = function()
{
this.currentRound = 0;
//Arrows left to fire
this.arrowsLeft = 0;
this.targetUnits = [];
};
BuildingAI.prototype.OnOwnershipChanged = function(msg)
{
// Remove current targets, to prevent them from being added twice
this.targetUnits = [];
this.SetupRangeQuery();
this.SetupGaiaRangeQuery();
};
@@ -48,20 +42,17 @@ BuildingAI.prototype.OnDiplomacyChanged = function(msg)
this.SetupGaiaRangeQuery();
};
/**
* Cleanup on destroy
*/
BuildingAI.prototype.OnDestroy = function()
{
if (this.timer)
{
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
cmpTimer.CancelTimer(this.timer);
this.timer = undefined;
}
// Clean up range queries
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
if (this.enemyUnitsQuery)
cmpRangeManager.DestroyActiveQuery(this.enemyUnitsQuery);
if (this.gaiaUnitsQuery)
@@ -101,20 +92,20 @@ BuildingAI.prototype.SetupRangeQuery = function()
if (!cmpPlayer)
return;
var players = [];
var enemies = [];
var numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers();
for (var i = 1; i < numPlayers; ++i)
{ // Exclude gaia, allies, and self
// TODO: How to handle neutral players - Special query to attack military only?
for (let i = 1; i < numPlayers; ++i)
if (cmpPlayer.IsEnemy(i))
players.push(i);
}
enemies.push(i);
if (!players.length)
if (!enemies.length)
return;
var range = cmpAttack.GetRange(attackType);
this.enemyUnitsQuery = cmpRangeManager.CreateActiveParabolicQuery(this.entity, range.min, range.max, range.elevationBonus, players, IID_DamageReceiver, cmpRangeManager.GetEntityFlagMask("normal"));
this.enemyUnitsQuery = cmpRangeManager.CreateActiveParabolicQuery(
this.entity, range.min, range.max, range.elevationBonus,
enemies, IID_DamageReceiver, cmpRangeManager.GetEntityFlagMask("normal"));
cmpRangeManager.EnableActiveQuery(this.enemyUnitsQuery);
};
@@ -140,7 +131,10 @@ BuildingAI.prototype.SetupGaiaRangeQuery = function()
var range = cmpAttack.GetRange(attackType);
// This query is only interested in Gaia entities that can attack.
this.gaiaUnitsQuery = cmpRangeManager.CreateActiveParabolicQuery(this.entity, range.min, range.max, range.elevationBonus, [0], IID_Attack, cmpRangeManager.GetEntityFlagMask("normal"));
this.gaiaUnitsQuery = cmpRangeManager.CreateActiveParabolicQuery(
this.entity, range.min, range.max, range.elevationBonus,
[0], IID_Attack, cmpRangeManager.GetEntityFlagMask("normal"));
cmpRangeManager.EnableActiveQuery(this.gaiaUnitsQuery);
};
@@ -154,40 +148,28 @@ BuildingAI.prototype.OnRangeUpdate = function(msg)
if (!cmpAttack)
return;
// Target enemy units except non-dangerous animals
if (msg.tag == this.gaiaUnitsQuery)
{
const filter = function(e) {
var cmpUnitAI = Engine.QueryInterface(e, IID_UnitAI);
return (cmpUnitAI && (!cmpUnitAI.IsAnimal() || cmpUnitAI.IsDangerousAnimal()));
};
if (msg.added.length)
msg.added = msg.added.filter(filter);
// Removed entities may not have cmpUnitAI.
for (var i = 0; i < msg.removed.length; ++i)
if (this.targetUnits.indexOf(msg.removed[i]) == -1)
msg.removed.splice(i--, 1);
msg.added = msg.added.filter(e => {
let cmpUnitAI = Engine.QueryInterface(e, IID_UnitAI);
return cmpUnitAI && (!cmpUnitAI.IsAnimal() || cmpUnitAI.IsDangerousAnimal());
});
}
else if (msg.tag != this.enemyUnitsQuery)
return;
if (msg.added.length > 0)
// Add new targets
for (let entity of msg.added)
if (cmpAttack.CanAttack(entity))
this.targetUnits.push(entity);
// Remove targets outside of vision-range
for (let entity of msg.removed)
{
for each (var entity in msg.added)
{
if (cmpAttack.CanAttack(entity))
this.targetUnits.push(entity);
}
}
if (msg.removed.length > 0)
{
for each (var entity in msg.removed)
{
var index = this.targetUnits.indexOf(entity);
if (index > -1)
this.targetUnits.splice(index, 1);
}
let index = this.targetUnits.indexOf(entity);
if (index > -1)
this.targetUnits.splice(index, 1);
}
if (this.targetUnits.length)
@@ -205,7 +187,9 @@ BuildingAI.prototype.StartTimer = function()
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
var attackTimers = cmpAttack.GetTimers(attackType);
this.timer = cmpTimer.SetInterval(this.entity, IID_BuildingAI, "FireArrows", attackTimers.prepare, attackTimers.repeat / roundCount, null);
this.timer = cmpTimer.SetInterval(this.entity, IID_BuildingAI, "FireArrows",
attackTimers.prepare, attackTimers.repeat / roundCount, null);
};
BuildingAI.prototype.GetDefaultArrowCount = function()
@@ -235,12 +219,12 @@ BuildingAI.prototype.GetGarrisonArrowClasses = function()
*/
BuildingAI.prototype.GetArrowCount = function()
{
var count = this.GetDefaultArrowCount();
var cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder);
let count = this.GetDefaultArrowCount();
let cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder);
if (cmpGarrisonHolder)
{
count += Math.round(cmpGarrisonHolder.GetGarrisonedArcherCount(this.GetGarrisonArrowClasses()) * this.GetGarrisonArrowMultiplier());
}
return count;
};
@@ -252,7 +236,8 @@ BuildingAI.prototype.SetUnitAITarget = function(ent)
};
/**
* Fires arrows. Called 'roundCount' times every 'RepeatTime' seconds when there are units in the range
* Fire arrows with random temporal distribution on prefered targets.
* Called 'roundCount' times every 'RepeatTime' seconds when there are units in the range.
*/
BuildingAI.prototype.FireArrows = function()
{
@@ -261,91 +246,76 @@ BuildingAI.prototype.FireArrows = function()
if (!this.timer)
return;
// stop the timer
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
cmpTimer.CancelTimer(this.timer);
this.timer = undefined;
return;
}
var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
let cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
if (!cmpAttack)
return;
var arrowsToFire = 0;
if (this.currentRound > (roundCount - 1))
{
//Reached end of rounds. Reset count
if (this.currentRound > roundCount - 1)
this.currentRound = 0;
}
if (this.currentRound == 0)
{
//First round. Calculate arrows to fire
this.arrowsLeft = this.GetArrowCount();
}
if (this.currentRound == (roundCount - 1))
{
//Last round. Need to fire all left-over arrows
let arrowsToFire = 0;
if (this.currentRound == roundCount - 1)
arrowsToFire = this.arrowsLeft;
}
else
{
//Fire N arrows, 0 <= N <= Number of arrows left
arrowsToFire = Math.min(
Math.round(2*Math.random() * this.GetArrowCount()/roundCount),
Math.round(2 * Math.random() * this.GetArrowCount() / roundCount),
this.arrowsLeft
);
}
if (arrowsToFire <= 0)
{
this.currentRound++;
++this.currentRound;
return;
}
// add targets to a weighted list, to allow preferences
var targets = new WeightedList();
var maxPreferenceBonus = this.MAX_PREFERENCE_BONUS;
var addTarget = function(target)
// Add targets to a weighted list, to allow preferences
let targets = new WeightedList();
let addTarget = function(target)
{
var preference = cmpAttack.GetPreference(target);
var weight = 1;
if (preference !== null && preference !== undefined)
{
// Lower preference scores indicate a higher preference so they
// should result in a higher weight.
weight = 1 + maxPreferenceBonus / (1 + preference);
}
targets.push(target, weight);
let preference = cmpAttack.GetPreference(target);
let weight = 1;
if (preference !== null && preference !== undefined)
weight += this.MAX_PREFERENCE_BONUS / (1 + preference);
targets.push(target, weight);
};
// add the unit ai target separately, as the UnitMotion and RangeManager
// implementations differ
// Add the UnitAI target separately, as the UnitMotion and RangeManager implementations differ
if (this.unitAITarget && this.targetUnits.indexOf(this.unitAITarget) == -1)
addTarget(this.unitAITarget);
for (let target of this.targetUnits)
addTarget(target);
for (var i = 0;i < arrowsToFire;i++)
for (let i = 0; i < arrowsToFire; ++i)
{
var selectedIndex = targets.randomIndex();
var selectedTarget = targets.itemAt(selectedIndex);
let selectedIndex = targets.randomIndex();
let selectedTarget = targets.itemAt(selectedIndex);
if (selectedTarget && this.CheckTargetVisible(selectedTarget))
{
cmpAttack.PerformAttack(attackType, selectedTarget);
PlaySound("attack", this.entity);
continue;
}
else
// Could not attack target, retry
targets.removeAt(selectedIndex);
--i;
if (!targets.length())
{
targets.removeAt(selectedIndex);
i--; // one extra arrow left to fire
if(targets.length() < 1)
{
this.arrowsLeft += arrowsToFire;
// no targets found in this round, save arrows and go to next round
break;
}
this.arrowsLeft += arrowsToFire;
break;
}
}
@@ -367,8 +337,8 @@ BuildingAI.prototype.CheckTargetVisible = function(target)
if (cmpFogging && cmpFogging.IsMiraged(cmpOwnership.GetOwner()))
return true;
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
// Either visible directly, or visible in fog
let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
return cmpRangeManager.GetLosVisibility(target, cmpOwnership.GetOwner()) != "hidden";
};