Remove passing the warheads from DamageWarhead to AttackInfo.

Added a Damage class to pass damage value and damage(types) instead.
This removes a great amount of overhead and longterm opens possibilities to have damagetypes without warheads.
This commit is contained in:
Zimmermann Gyula
2016-06-24 13:18:15 +02:00
parent 6342b40bfd
commit cf8fff2b99
30 changed files with 69 additions and 64 deletions

View File

@@ -317,12 +317,12 @@ namespace OpenRA
return (health == null) ? DamageState.Undamaged : health.DamageState; return (health == null) ? DamageState.Undamaged : health.DamageState;
} }
public void InflictDamage(Actor attacker, int damage, IWarhead warhead) public void InflictDamage(Actor attacker, Damage damage)
{ {
if (Disposed || health == null) if (Disposed || health == null)
return; return;
health.InflictDamage(this, attacker, damage, warhead, false); health.InflictDamage(this, attacker, damage, false);
} }
public void Kill(Actor attacker) public void Kill(Actor attacker)

View File

@@ -41,7 +41,7 @@ namespace OpenRA.Traits
int DisplayHP { get; } int DisplayHP { get; }
bool IsDead { get; } bool IsDead { get; }
void InflictDamage(Actor self, Actor attacker, int damage, IWarhead warhead, bool ignoreModifiers); void InflictDamage(Actor self, Actor attacker, Damage damage, bool ignoreModifiers);
void Kill(Actor self, Actor attacker); void Kill(Actor self, Actor attacker);
} }
@@ -82,13 +82,30 @@ namespace OpenRA.Traits
public class AttackInfo public class AttackInfo
{ {
public int Damage; public Damage Damage;
public Actor Attacker; public Actor Attacker;
public IWarhead Warhead;
public DamageState DamageState; public DamageState DamageState;
public DamageState PreviousDamageState; public DamageState PreviousDamageState;
} }
public class Damage
{
public readonly int Value;
public readonly HashSet<string> DamageTypes;
public Damage(int damage, HashSet<string> damageTypes)
{
Value = damage;
DamageTypes = damageTypes;
}
public Damage(int damage)
{
Value = damage;
DamageTypes = new HashSet<string>();
}
}
public interface ITick { void Tick(Actor self); } public interface ITick { void Tick(Actor self); }
public interface ITickRender { void TickRender(WorldRenderer wr, Actor self); } public interface ITickRender { void TickRender(WorldRenderer wr, Actor self); }
public interface IRender { IEnumerable<IRenderable> Render(Actor self, WorldRenderer wr); } public interface IRender { IEnumerable<IRenderable> Render(Actor self, WorldRenderer wr); }
@@ -249,7 +266,7 @@ namespace OpenRA.Traits
} }
public interface IRenderModifier { IEnumerable<IRenderable> ModifyRender(Actor self, WorldRenderer wr, IEnumerable<IRenderable> r); } public interface IRenderModifier { IEnumerable<IRenderable> ModifyRender(Actor self, WorldRenderer wr, IEnumerable<IRenderable> r); }
public interface IDamageModifier { int GetDamageModifier(Actor attacker, IWarhead warhead); } public interface IDamageModifier { int GetDamageModifier(Actor attacker, Damage damage); }
public interface ISpeedModifier { int GetSpeedModifier(); } public interface ISpeedModifier { int GetSpeedModifier(); }
public interface IFirepowerModifier { int GetFirepowerModifier(); } public interface IFirepowerModifier { int GetFirepowerModifier(); }
public interface IReloadModifier { int GetReloadModifier(); } public interface IReloadModifier { int GetReloadModifier(); }

View File

@@ -112,7 +112,7 @@ namespace OpenRA.Mods.Cnc.Traits
} }
} }
public int GetDamageModifier(Actor attacker, IWarhead warhead) public int GetDamageModifier(Actor attacker, Damage damage)
{ {
return state == PopupState.Closed ? info.ClosedDamageMultiplier : 100; return state == PopupState.Closed ? info.ClosedDamageMultiplier : 100;
} }

View File

@@ -69,7 +69,7 @@ namespace OpenRA.Mods.Common.Activities
else else
{ {
var damage = health.MaxHP * capturesInfo.SabotageHPRemoval / 100; var damage = health.MaxHP * capturesInfo.SabotageHPRemoval / 100;
actor.InflictDamage(self, damage, null); actor.InflictDamage(self, new Damage(damage));
} }
self.Dispose(); self.Dispose();

View File

@@ -71,7 +71,7 @@ namespace OpenRA.Mods.Common.Activities
return this; return this;
} }
self.InflictDamage(self, -hpToRepair, null); self.InflictDamage(self, new Damage(-hpToRepair));
foreach (var depot in host.TraitsImplementing<INotifyRepair>()) foreach (var depot in host.TraitsImplementing<INotifyRepair>())
depot.Repairing(host, self); depot.Repairing(host, self);

View File

@@ -36,7 +36,7 @@ namespace OpenRA.Mods.Common.Activities
if (health.DamageState == DamageState.Undamaged) if (health.DamageState == DamageState.Undamaged)
return; return;
target.InflictDamage(self, -health.MaxHP, null); target.InflictDamage(self, new Damage(-health.MaxHP));
} }
} }
} }

View File

@@ -29,7 +29,7 @@ namespace OpenRA.Mods.Common.Scripting
public int Health public int Health
{ {
get { return health.HP; } get { return health.HP; }
set { health.InflictDamage(Self, Self, health.HP - value, null, true); } set { health.InflictDamage(Self, Self, new Damage(health.HP - value), true); }
} }
[Desc("Maximum health of the actor.")] [Desc("Maximum health of the actor.")]
@@ -38,7 +38,7 @@ namespace OpenRA.Mods.Common.Scripting
[Desc("Kill the actor.")] [Desc("Kill the actor.")]
public void Kill() public void Kill()
{ {
health.InflictDamage(Self, Self, health.MaxHP, null, true); health.InflictDamage(Self, Self, new Damage(health.MaxHP), true);
} }
} }
} }

View File

@@ -113,7 +113,7 @@ namespace OpenRA.Mods.Common.Traits
return; return;
// don't retaliate against healers // don't retaliate against healers
if (e.Damage < 0) if (e.Damage.Value < 0)
return; return;
Aggressor = attacker; Aggressor = attacker;

View File

@@ -292,7 +292,7 @@ namespace OpenRA.Mods.Common.Traits
KillUnitsOnBridge(); KillUnitsOnBridge();
} }
else else
health.InflictDamage(self, repairer, -health.MaxHP, null, true); health.InflictDamage(self, repairer, new Damage(-health.MaxHP), true);
if (direction < 0 ? neighbours[0] == null && neighbours[1] == null : Hut != null || neighbours[direction] == null) if (direction < 0 ? neighbours[0] == null && neighbours[1] == null : Hut != null || neighbours[direction] == null)
onComplete(); // Done if single or reached other hut onComplete(); // Done if single or reached other hut
}); });

View File

@@ -129,7 +129,7 @@ namespace OpenRA.Mods.Common.Traits
// activePlayers won't cause IndexOutOfRange because we capped the max amount of players // activePlayers won't cause IndexOutOfRange because we capped the max amount of players
// to the length of the array // to the length of the array
self.InflictDamage(self, -(hpToRepair * Info.RepairBonuses[activePlayers - 1] / 100), null); self.InflictDamage(self, new Damage(-(hpToRepair * Info.RepairBonuses[activePlayers - 1] / 100)));
if (health.DamageState == DamageState.Undamaged) if (health.DamageState == DamageState.Undamaged)
{ {

View File

@@ -44,7 +44,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
if (--ticks <= 0) if (--ticks <= 0)
{ {
self.InflictDamage(self, info.Damage, null); self.InflictDamage(self, new Damage(info.Damage));
ticks = info.Interval; ticks = info.Interval;
} }
} }

View File

@@ -116,14 +116,14 @@ namespace OpenRA.Mods.Common.Traits
public void Damaged(Actor self, AttackInfo e) public void Damaged(Actor self, AttackInfo e)
{ {
if (devMode == null || !devMode.ShowCombatGeometry || e.Damage == 0) if (devMode == null || !devMode.ShowCombatGeometry || e.Damage.Value == 0)
return; return;
if (healthInfo == null) if (healthInfo == null)
return; return;
var maxHP = healthInfo.HP > 0 ? healthInfo.HP : 1; var maxHP = healthInfo.HP > 0 ? healthInfo.HP : 1;
var damageText = "{0} ({1}%)".F(-e.Damage, e.Damage * 100 / maxHP); var damageText = "{0} ({1}%)".F(-e.Damage.Value, e.Damage.Value * 100 / maxHP);
self.World.AddFrameEndTask(w => w.Add(new FloatingText(self.CenterPosition, e.Attacker.Owner.Color.RGB, damageText, 30))); self.World.AddFrameEndTask(w => w.Add(new FloatingText(self.CenterPosition, e.Attacker.Owner.Color.RGB, damageText, 30)));
} }

View File

@@ -10,6 +10,7 @@
#endregion #endregion
using System.Linq; using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
@@ -28,7 +29,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
foreach (var healable in collector.World.ActorsWithTrait<Health>().Where(tp => tp.Actor.Owner == collector.Owner)) foreach (var healable in collector.World.ActorsWithTrait<Health>().Where(tp => tp.Actor.Owner == collector.Owner))
if (!healable.Trait.IsDead) if (!healable.Trait.IsDead)
healable.Trait.InflictDamage(healable.Actor, healable.Actor, -(healable.Trait.MaxHP - healable.Trait.HP), null, true); healable.Trait.InflictDamage(healable.Actor, healable.Actor, new Damage(-(healable.Trait.MaxHP - healable.Trait.HP)), true);
base.Activate(collector); base.Activate(collector);
} }

View File

@@ -67,7 +67,7 @@ namespace OpenRA.Mods.Common.Traits
// Actors start with maximum damage applied // Actors start with maximum damage applied
var delta = health.HP - damageThreshold; var delta = health.HP - damageThreshold;
if (delta > 0) if (delta > 0)
health.InflictDamage(self, self.World.WorldActor, delta, null, false); health.InflictDamage(self, self.World.WorldActor, new Damage(delta), false);
} }
public void Tick(Actor self) public void Tick(Actor self)

View File

@@ -69,8 +69,7 @@ namespace OpenRA.Mods.Common.Traits
if (self.World.SharedRandom.Next(100) > info.Chance) if (self.World.SharedRandom.Next(100) > info.Chance)
return; return;
var warhead = e.Warhead as DamageWarhead; if (info.DeathTypes.Count > 0 && !e.Damage.DamageTypes.Overlaps(info.DeathTypes))
if (info.DeathTypes.Count > 0 && warhead != null && !warhead.DamageTypes.Overlaps(info.DeathTypes))
return; return;
var weapon = ChooseWeaponForExplosion(self); var weapon = ChooseWeaponForExplosion(self);

View File

@@ -66,8 +66,7 @@ namespace OpenRA.Mods.Common.Traits
if (!info.ValidStances.HasStance(e.Attacker.Owner.Stances[self.Owner])) if (!info.ValidStances.HasStance(e.Attacker.Owner.Stances[self.Owner]))
return; return;
var warhead = e.Warhead as DamageWarhead; if (info.DeathTypes.Count > 0 && !e.Damage.DamageTypes.Overlaps(info.DeathTypes))
if (info.DeathTypes.Count > 0 && warhead != null && !warhead.DamageTypes.Overlaps(info.DeathTypes))
return; return;
var cost = self.GetSellValue(); var cost = self.GetSellValue();

View File

@@ -112,10 +112,9 @@ namespace OpenRA.Mods.Common.Traits
var ai = new AttackInfo var ai = new AttackInfo
{ {
Attacker = repairer, Attacker = repairer,
Damage = -MaxHP, Damage = new Damage(-MaxHP),
DamageState = DamageState, DamageState = DamageState,
PreviousDamageState = DamageState.Dead, PreviousDamageState = DamageState.Dead,
Warhead = null,
}; };
foreach (var nd in self.TraitsImplementing<INotifyDamage>() foreach (var nd in self.TraitsImplementing<INotifyDamage>()
@@ -131,7 +130,7 @@ namespace OpenRA.Mods.Common.Traits
nd.AppliedDamage(repairer, self, ai); nd.AppliedDamage(repairer, self, ai);
} }
public void InflictDamage(Actor self, Actor attacker, int damage, IWarhead warhead, bool ignoreModifiers) public void InflictDamage(Actor self, Actor attacker, Damage damage, bool ignoreModifiers)
{ {
// Overkill! Don't count extra hits as more kills! // Overkill! Don't count extra hits as more kills!
if (IsDead) if (IsDead)
@@ -140,16 +139,16 @@ namespace OpenRA.Mods.Common.Traits
var oldState = DamageState; var oldState = DamageState;
// Apply any damage modifiers // Apply any damage modifiers
if (!ignoreModifiers && damage > 0) if (!ignoreModifiers && damage.Value > 0)
{ {
var modifiers = self.TraitsImplementing<IDamageModifier>() var modifiers = self.TraitsImplementing<IDamageModifier>()
.Concat(self.Owner.PlayerActor.TraitsImplementing<IDamageModifier>()) .Concat(self.Owner.PlayerActor.TraitsImplementing<IDamageModifier>())
.Select(t => t.GetDamageModifier(attacker, warhead)); .Select(t => t.GetDamageModifier(attacker, damage));
damage = Util.ApplyPercentageModifiers(damage, modifiers); damage = new Damage(Util.ApplyPercentageModifiers(damage.Value, modifiers), damage.DamageTypes);
} }
hp = (hp - damage).Clamp(0, MaxHP); hp = (hp - damage.Value).Clamp(0, MaxHP);
var ai = new AttackInfo var ai = new AttackInfo
{ {
@@ -157,7 +156,6 @@ namespace OpenRA.Mods.Common.Traits
Damage = damage, Damage = damage,
DamageState = DamageState, DamageState = DamageState,
PreviousDamageState = oldState, PreviousDamageState = oldState,
Warhead = warhead,
}; };
foreach (var nd in self.TraitsImplementing<INotifyDamage>() foreach (var nd in self.TraitsImplementing<INotifyDamage>()
@@ -191,7 +189,7 @@ namespace OpenRA.Mods.Common.Traits
public void Kill(Actor self, Actor attacker) public void Kill(Actor self, Actor attacker)
{ {
InflictDamage(self, attacker, MaxHP, null, true); InflictDamage(self, attacker, new Damage(MaxHP), true);
} }
public void Tick(Actor self) public void Tick(Actor self)

View File

@@ -78,7 +78,7 @@ namespace OpenRA.Mods.Common.Traits
public void Damaged(Actor self, AttackInfo e) public void Damaged(Actor self, AttackInfo e)
{ {
if (e.Damage > 0) if (e.Damage.Value > 0)
Panic(); Panic();
} }

View File

@@ -56,8 +56,7 @@ namespace OpenRA.Mods.Common.Traits
public void Damaged(Actor self, AttackInfo e) public void Damaged(Actor self, AttackInfo e)
{ {
var warhead = e.Warhead as DamageWarhead; if (e.Damage.Value <= 0 || !e.Damage.DamageTypes.Overlaps(info.DamageTriggers))
if (e.Damage <= 0 || warhead == null || !warhead.DamageTypes.Overlaps(info.DamageTriggers))
return; return;
if (!IsProne) if (!IsProne)
@@ -79,16 +78,15 @@ namespace OpenRA.Mods.Common.Traits
get { return true; } get { return true; }
} }
public int GetDamageModifier(Actor attacker, IWarhead warhead) public int GetDamageModifier(Actor attacker, Damage damage)
{ {
if (!IsProne) if (!IsProne)
return 100; return 100;
var damageWh = warhead as DamageWarhead; if (damage.DamageTypes.Count == 0)
if (damageWh == null)
return 100; return 100;
var modifierPercentages = info.DamageModifiers.Where(x => damageWh.DamageTypes.Contains(x.Key)).Select(x => x.Value); var modifierPercentages = info.DamageModifiers.Where(x => damage.DamageTypes.Contains(x.Key)).Select(x => x.Value);
return Util.ApplyPercentageModifiers(100, modifierPercentages); return Util.ApplyPercentageModifiers(100, modifierPercentages);
} }

View File

@@ -41,10 +41,9 @@ namespace OpenRA.Mods.Common.Traits
this.self = self; this.self = self;
} }
public int GetDamageModifier(Actor attacker, IWarhead warhead) public int GetDamageModifier(Actor attacker, Damage damage)
{ {
var damageWh = warhead as DamageWarhead; if (attacker.Owner.IsAlliedWith(self.Owner) && damage.Value < 0 && !Info.ModifyHealing)
if (attacker.Owner.IsAlliedWith(self.Owner) && (damageWh != null && damageWh.Damage < 0) && !Info.ModifyHealing)
return FullDamage; return FullDamage;
var world = self.World; var world = self.World;

View File

@@ -26,6 +26,6 @@ namespace OpenRA.Mods.Common.Traits
public DamageMultiplier(DamageMultiplierInfo info, string actorType) public DamageMultiplier(DamageMultiplierInfo info, string actorType)
: base(info, "DamageMultiplier", actorType) { } : base(info, "DamageMultiplier", actorType) { }
public int GetDamageModifier(Actor attacker, IWarhead warhead) { return GetModifier(); } public int GetDamageModifier(Actor attacker, Damage damage) { return GetModifier(); }
} }
} }

View File

@@ -65,7 +65,7 @@ namespace OpenRA.Mods.Common.Traits
if (!self.Info.HasTraitInfo<BuildingInfo>()) if (!self.Info.HasTraitInfo<BuildingInfo>())
return; return;
if (e.Attacker.Owner.IsAlliedWith(self.Owner) && e.Damage <= 0) if (e.Attacker.Owner.IsAlliedWith(self.Owner) && e.Damage.Value <= 0)
return; return;
if (self.World.WorldTick - lastAttackTime > info.NotifyInterval * 25) if (self.World.WorldTick - lastAttackTime > info.NotifyInterval * 25)
@@ -85,4 +85,4 @@ namespace OpenRA.Mods.Common.Traits
lastAttackTime = self.World.WorldTick; lastAttackTime = self.World.WorldTick;
} }
} }
} }

View File

@@ -55,12 +55,11 @@ namespace OpenRA.Mods.Common.Traits.Render
public void Damaged(Actor self, AttackInfo e) public void Damaged(Actor self, AttackInfo e)
{ {
var warhead = e.Warhead as DamageWarhead; if (info.DamageTypes.Count > 0 && !e.Damage.DamageTypes.Overlaps(info.DamageTypes))
if (info.DamageTypes.Count > 0 && (warhead != null && !warhead.DamageTypes.Overlaps(info.DamageTypes)))
return; return;
if (isSmoking) return; if (isSmoking) return;
if (e.Damage < 0) return; /* getting healed */ if (e.Damage.Value < 0) return; /* getting healed */
if (e.DamageState < info.MinimumDamageState) return; if (e.DamageState < info.MinimumDamageState) return;
if (e.DamageState > info.MaximumDamageState) return; if (e.DamageState > info.MaximumDamageState) return;

View File

@@ -84,7 +84,7 @@ namespace OpenRA.Mods.Common.Traits.Render
palette += self.Owner.InternalName; palette += self.Owner.InternalName;
// Killed by some non-standard means // Killed by some non-standard means
if (e.Warhead == null || !(e.Warhead is DamageWarhead)) if (e.Damage.DamageTypes.Count == 0)
{ {
if (Info.FallbackSequence != null) if (Info.FallbackSequence != null)
SpawnDeathAnimation(self, self.CenterPosition, rs.GetImage(self), Info.FallbackSequence, palette); SpawnDeathAnimation(self, self.CenterPosition, rs.GetImage(self), Info.FallbackSequence, palette);
@@ -95,8 +95,7 @@ namespace OpenRA.Mods.Common.Traits.Render
var sequence = Info.DeathSequence; var sequence = Info.DeathSequence;
if (Info.UseDeathTypeSuffix) if (Info.UseDeathTypeSuffix)
{ {
var warhead = e.Warhead as DamageWarhead; var damageType = Info.DeathTypes.Keys.FirstOrDefault(e.Damage.DamageTypes.Contains);
var damageType = Info.DeathTypes.Keys.FirstOrDefault(warhead.DamageTypes.Contains);
if (damageType == null) if (damageType == null)
return; return;

View File

@@ -55,13 +55,13 @@ namespace OpenRA.Mods.Common.Traits
if (--ticks <= 0) if (--ticks <= 0)
{ {
ticks = Info.Delay; ticks = Info.Delay;
self.InflictDamage(self, -Info.Step, null); self.InflictDamage(self, new Damage(-Info.Step));
} }
} }
public void Damaged(Actor self, AttackInfo e) public void Damaged(Actor self, AttackInfo e)
{ {
if (e.Damage > 0) if (e.Damage.Value > 0)
damageTicks = Info.DamageCooldown; damageTicks = Info.DamageCooldown;
} }
} }

View File

@@ -39,11 +39,8 @@ namespace OpenRA.Mods.Common.Traits.Sound
public void Killed(Actor self, AttackInfo e) public void Killed(Actor self, AttackInfo e)
{ {
var warhead = e.Warhead as DamageWarhead; if (info.DeathTypes.Count == 0 || e.Damage.DamageTypes.Overlaps(info.DeathTypes))
// If the warhead is null, the actor was killed by some non-standard means
if (info.DeathTypes.Count == 0 || (warhead != null && warhead.DamageTypes.Overlaps(info.DeathTypes)))
self.PlayVoiceLocal(info.Voice, info.VolumeMultiplier); self.PlayVoiceLocal(info.Voice, info.VolumeMultiplier);
} }
} }
} }

View File

@@ -72,8 +72,7 @@ namespace OpenRA.Mods.Common.Traits
if (self.World.SharedRandom.Next(100) > info.Probability) if (self.World.SharedRandom.Next(100) > info.Probability)
return; return;
var warhead = e.Warhead as DamageWarhead; if (info.DeathType != null && !e.Damage.DamageTypes.Contains(info.DeathType))
if (info.DeathType != null && (warhead == null || !warhead.DamageTypes.Contains(info.DeathType)))
return; return;
self.World.AddFrameEndTask(w => self.World.AddFrameEndTask(w =>

View File

@@ -70,7 +70,7 @@ namespace OpenRA.Mods.Common.Warheads
return; return;
var damage = Util.ApplyPercentageModifiers(Damage, damageModifiers.Append(DamageVersus(victim))); var damage = Util.ApplyPercentageModifiers(Damage, damageModifiers.Append(DamageVersus(victim)));
victim.InflictDamage(firedBy, damage, this); victim.InflictDamage(firedBy, new Damage(damage, DamageTypes));
} }
} }
} }

View File

@@ -52,7 +52,7 @@ namespace OpenRA.Mods.Common.Warheads
// Damage is measured as a percentage of the target health // Damage is measured as a percentage of the target health
var damage = Util.ApplyPercentageModifiers(healthInfo.HP, damageModifiers.Append(Damage, DamageVersus(victim))); var damage = Util.ApplyPercentageModifiers(healthInfo.HP, damageModifiers.Append(Damage, DamageVersus(victim)));
victim.InflictDamage(firedBy, damage, this); victim.InflictDamage(firedBy, new Damage(damage, DamageTypes));
} }
} }
} }

View File

@@ -95,7 +95,7 @@ namespace OpenRA.Mods.RA.Traits
{ {
// Damage is inflicted by the chronosphere // Damage is inflicted by the chronosphere
if (!self.Disposed) if (!self.Disposed)
self.InflictDamage(chronosphere, int.MaxValue, null); self.InflictDamage(chronosphere, new Damage(int.MaxValue));
}); });
return true; return true;
} }