Ignore damage modifiers when killing a unit via actor.Kill(). Fixes surrender desync (#460); Fixes invulnerable actors surviving in situations where they should be killed (bridge death, losing/surrender, etc).
This commit is contained in:
@@ -70,18 +70,19 @@ namespace OpenRA.Traits
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InflictDamage(Actor self, Actor attacker, int damage, WarheadInfo warhead)
|
public void InflictDamage(Actor self, Actor attacker, int damage, WarheadInfo warhead, bool ignoreModifiers)
|
||||||
{
|
{
|
||||||
if (IsDead) return; /* overkill! don't count extra hits as more kills! */
|
if (IsDead) return; /* overkill! don't count extra hits as more kills! */
|
||||||
|
|
||||||
var oldState = this.DamageState;
|
var oldState = this.DamageState;
|
||||||
|
|
||||||
/* apply the damage modifiers, if we have any. */
|
/* apply the damage modifiers, if we have any. */
|
||||||
var modifier = (float)self.TraitsImplementing<IDamageModifier>()
|
var modifier = (float)self.TraitsImplementing<IDamageModifier>()
|
||||||
.Concat(self.Owner.PlayerActor.TraitsImplementing<IDamageModifier>())
|
.Concat(self.Owner.PlayerActor.TraitsImplementing<IDamageModifier>())
|
||||||
.Select(t => t.GetDamageModifier(attacker, warhead)).Product();
|
.Select(t => t.GetDamageModifier(attacker, warhead)).Product();
|
||||||
|
|
||||||
|
if (!ignoreModifiers)
|
||||||
damage = damage > 0 ? (int)(damage * modifier) : damage;
|
damage = damage > 0 ? (int)(damage * modifier) : damage;
|
||||||
|
|
||||||
hp = Exts.Clamp(hp - damage, 0, MaxHP);
|
hp = Exts.Clamp(hp - damage, 0, MaxHP);
|
||||||
|
|
||||||
var ai = new AttackInfo
|
var ai = new AttackInfo
|
||||||
@@ -175,16 +176,14 @@ namespace OpenRA.Traits
|
|||||||
{
|
{
|
||||||
var health = self.TraitOrDefault<Health>();
|
var health = self.TraitOrDefault<Health>();
|
||||||
if (health == null) return;
|
if (health == null) return;
|
||||||
health.InflictDamage(self, attacker, damage, warhead);
|
health.InflictDamage(self, attacker, damage, warhead, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Kill(this Actor self, Actor attacker)
|
public static void Kill(this Actor self, Actor attacker)
|
||||||
{
|
{
|
||||||
var health = self.TraitOrDefault<Health>();
|
var health = self.TraitOrDefault<Health>();
|
||||||
if (health == null) return;
|
if (health == null) return;
|
||||||
|
health.InflictDamage(self, attacker, health.MaxHP, null, true);
|
||||||
/* hack. Fix for proper */
|
|
||||||
health.InflictDamage(self, attacker, int.MaxValue, null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,8 +34,16 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
if( !target.Trait<IOccupySpace>().OccupiedCells().Any( x => x.First == self.Location ) )
|
if( !target.Trait<IOccupySpace>().OccupiedCells().Any( x => x.First == self.Location ) )
|
||||||
return NextActivity;
|
return NextActivity;
|
||||||
|
|
||||||
self.World.AddFrameEndTask(w => w.Add(new DelayedAction(delay,
|
self.World.AddFrameEndTask(w => w.Add(new DelayedAction(delay, () =>
|
||||||
() => { if (target.IsInWorld) target.Kill(self); })));
|
{
|
||||||
|
// Invulnerable actors can't be demolished
|
||||||
|
var modifier = (float)target.TraitsImplementing<IDamageModifier>()
|
||||||
|
.Concat(self.Owner.PlayerActor.TraitsImplementing<IDamageModifier>())
|
||||||
|
.Select(t => t.GetDamageModifier(self, null)).Product();
|
||||||
|
|
||||||
|
if (target.IsInWorld && modifier > 0)
|
||||||
|
target.Kill(self);
|
||||||
|
})));
|
||||||
return NextActivity;
|
return NextActivity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user