1
0
forked from 0ad/0ad

Let entity react on target death directly.

Don't let entities waste a repeat time when they've killed their target.
Done by storing a list of attackers in cmpResistance (since that cmp is
obligatory anyway).

Differential revision: https://code.wildfiregames.com/D2129
Comments by: @Angen, @wraitii
This was SVN commit r25368.
This commit is contained in:
Freagarach 2021-05-04 05:18:11 +00:00
parent 34b1920e7b
commit 738b200dda
4 changed files with 39 additions and 6 deletions

View File

@ -455,6 +455,10 @@ Attack.prototype.StartAttacking = function(target, type, callerIID)
if (!this.CanAttack(target, [type]))
return false;
let cmpResistance = Engine.QueryInterface(target, IID_Resistance);
if (!cmpResistance || !cmpResistance.AddAttacker(this.entity))
return false;
let timings = this.GetTimers(type);
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
@ -496,6 +500,10 @@ Attack.prototype.StopAttacking = function(reason)
cmpTimer.CancelTimer(this.timer);
delete this.timer;
let cmpResistance = Engine.QueryInterface(this.target, IID_Resistance);
if (cmpResistance)
cmpResistance.RemoveAttacker(this.entity);
delete this.target;
let cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
@ -539,10 +547,7 @@ Attack.prototype.Attack = function(type, lateness)
this.PerformAttack(type, this.target);
if (!this.target)
{
this.StopAttacking("TargetInvalidated");
return;
}
// We check the range after the attack to facilitate chasing.
if (!this.IsTargetInRange(this.target, type))

View File

@ -73,6 +73,7 @@ Resistance.prototype.Schema =
Resistance.prototype.Init = function()
{
this.invulnerable = false;
this.attackers = new Set();
};
Resistance.prototype.IsInvulnerable = function()
@ -80,6 +81,28 @@ Resistance.prototype.IsInvulnerable = function()
return this.invulnerable;
};
/**
* @param {number} attacker - The entity ID of the attacker to add.
* @return {boolean} - Whether the attacker was added sucessfully.
*/
Resistance.prototype.AddAttacker = function(attacker)
{
if (this.attackers.has(attacker))
return false;
this.attackers.add(attacker);
return true;
};
/**
* @param {number} attacker - The entity ID of the attacker to remove.
* @return {boolean} - Whether the attacker was attacking us previously.
*/
Resistance.prototype.RemoveAttacker = function(attacker)
{
return this.attackers.delete(attacker);
};
Resistance.prototype.SetInvulnerability = function(invulnerability)
{
this.invulnerable = invulnerability;
@ -151,4 +174,11 @@ Resistance.prototype.GetResistanceOfForm = function(entityForm)
return ret;
};
Resistance.prototype.OnOwnershipChanged = function(msg)
{
if (msg.to === INVALID_PLAYER)
for (let attacker of this.attackers)
Engine.QueryInterface(attacker, IID_Attack)?.StopAttacking("TargetInvalidated");
};
Engine.RegisterComponentType(IID_Resistance, "Resistance", Resistance);

View File

@ -2156,9 +2156,6 @@ UnitAI.prototype.UnitFsmSpec = {
this.SetNextState("FINDINGNEWTARGET");
},
// TODO: respond to target deaths immediately, rather than waiting
// until the next Timer event
"Attacked": function(msg) {
if (this.order.data.attackType == "Capture" && (this.GetStance().targetAttackersAlways || !this.order.data.force) &&
this.order.data.target != msg.data.attacker && this.GetBestAttackAgainst(msg.data.attacker, true) != "Capture")

View File

@ -24,6 +24,7 @@
<OverlayRenderer merge=""/>
<Ownership merge=""/>
<Position merge=""/>
<Resistance merge=""/>
<Selectable merge=""/>
<StatusBars merge=""/>
<Visibility merge=""/>