Created IHealth interface and cleanup.

To decouple the Health trait from OpenRA.Traits.
DisplayHp renamed to DisplayHP and HealthExts moved
moved next to Actor.Kill() for consistency.
This commit is contained in:
Huw Pascoe
2015-10-11 01:12:08 +01:00
parent a79b71c608
commit 5a81d5dfa7
4 changed files with 53 additions and 40 deletions

View File

@@ -71,7 +71,7 @@ namespace OpenRA
IOccupySpace occupySpace; IOccupySpace occupySpace;
readonly IFacing facing; readonly IFacing facing;
readonly Health health; readonly IHealth health;
readonly IRenderModifier[] renderModifiers; readonly IRenderModifier[] renderModifiers;
readonly IRender[] renders; readonly IRender[] renders;
readonly IDisable[] disables; readonly IDisable[] disables;
@@ -103,7 +103,7 @@ namespace OpenRA
VisualBounds = DetermineVisualBounds(); VisualBounds = DetermineVisualBounds();
EffectiveOwner = TraitOrDefault<IEffectiveOwner>(); EffectiveOwner = TraitOrDefault<IEffectiveOwner>();
facing = TraitOrDefault<IFacing>(); facing = TraitOrDefault<IFacing>();
health = TraitOrDefault<Health>(); health = TraitOrDefault<IHealth>();
renderModifiers = TraitsImplementing<IRenderModifier>().ToArray(); renderModifiers = TraitsImplementing<IRenderModifier>().ToArray();
renders = TraitsImplementing<IRender>().ToArray(); renders = TraitsImplementing<IRender>().ToArray();
disables = TraitsImplementing<IDisable>().ToArray(); disables = TraitsImplementing<IDisable>().ToArray();
@@ -281,12 +281,28 @@ namespace OpenRA
}); });
} }
public void Kill(Actor attacker) public DamageState GetDamageState()
{ {
if (health == null) if (Disposed)
return DamageState.Dead;
return (health == null) ? DamageState.Undamaged : health.DamageState;
}
public void InflictDamage(Actor attacker, int damage, IWarhead warhead)
{
if (Disposed || health == null)
return; return;
health.InflictDamage(this, attacker, health.MaxHP, null, true); health.InflictDamage(this, attacker, damage, warhead, false);
}
public void Kill(Actor attacker)
{
if (Disposed || health == null)
return;
health.Kill(this, attacker);
} }
public bool IsDisabled() public bool IsDisabled()

View File

@@ -74,7 +74,7 @@ namespace OpenRA.Graphics
wlr.DrawLine(start + r, z + r, barColor2); wlr.DrawLine(start + r, z + r, barColor2);
} }
Color GetHealthColor(Health health) Color GetHealthColor(IHealth health)
{ {
var player = actor.World.RenderPlayer ?? actor.World.LocalPlayer; var player = actor.World.RenderPlayer ?? actor.World.LocalPlayer;
@@ -104,7 +104,7 @@ namespace OpenRA.Graphics
health.DamageState == DamageState.Heavy ? Color.Yellow : Color.LimeGreen; health.DamageState == DamageState.Heavy ? Color.Yellow : Color.LimeGreen;
} }
void DrawHealthBar(WorldRenderer wr, Health health, float2 start, float2 end) void DrawHealthBar(WorldRenderer wr, IHealth health, float2 start, float2 end)
{ {
if (health == null || health.IsDead) if (health == null || health.IsDead)
return; return;
@@ -133,7 +133,7 @@ namespace OpenRA.Graphics
wlr.DrawLine(start + q, z + q, healthColor); wlr.DrawLine(start + q, z + q, healthColor);
wlr.DrawLine(start + r, z + r, healthColor2); wlr.DrawLine(start + r, z + r, healthColor2);
if (health.DisplayHp != health.HP) if (health.DisplayHP != health.HP)
{ {
var deltaColor = Color.OrangeRed; var deltaColor = Color.OrangeRed;
var deltaColor2 = Color.FromArgb( var deltaColor2 = Color.FromArgb(
@@ -141,7 +141,7 @@ namespace OpenRA.Graphics
deltaColor.R / 2, deltaColor.R / 2,
deltaColor.G / 2, deltaColor.G / 2,
deltaColor.B / 2); deltaColor.B / 2);
var zz = float2.Lerp(start, end, (float)health.DisplayHp / health.MaxHP); var zz = float2.Lerp(start, end, (float)health.DisplayHP / health.MaxHP);
wlr.DrawLine(z + p, zz + p, deltaColor2); wlr.DrawLine(z + p, zz + p, deltaColor2);
wlr.DrawLine(z + q, zz + q, deltaColor); wlr.DrawLine(z + q, zz + q, deltaColor);
@@ -155,7 +155,7 @@ namespace OpenRA.Graphics
if (!actor.IsInWorld || actor.IsDead) if (!actor.IsInWorld || actor.IsDead)
return; return;
var health = actor.TraitOrDefault<Health>(); var health = actor.TraitOrDefault<IHealth>();
var screenPos = wr.ScreenPxPosition(pos); var screenPos = wr.ScreenPxPosition(pos);
var bounds = actor.VisualBounds; var bounds = actor.VisualBounds;

View File

@@ -26,15 +26,13 @@ namespace OpenRA.Traits
public virtual object Create(ActorInitializer init) { return new Health(init, this); } public virtual object Create(ActorInitializer init) { return new Health(init, this); }
} }
public enum DamageState { Undamaged, Light, Medium, Heavy, Critical, Dead } public class Health : IHealth, ISync, ITick
public class Health : ISync, ITick
{ {
public readonly HealthInfo Info; public readonly HealthInfo Info;
[Sync] int hp; [Sync] int hp;
public int DisplayHp { get; private set; } public int DisplayHP { get; private set; }
public Health(ActorInitializer init, HealthInfo info) public Health(ActorInitializer init, HealthInfo info)
{ {
@@ -43,11 +41,11 @@ namespace OpenRA.Traits
hp = init.Contains<HealthInit>() ? init.Get<HealthInit, int>() * MaxHP / 100 : MaxHP; hp = init.Contains<HealthInit>() ? init.Get<HealthInit, int>() * MaxHP / 100 : MaxHP;
DisplayHp = hp; DisplayHP = hp;
} }
public int HP { get { return hp; } } public int HP { get { return hp; } }
public int MaxHP; public int MaxHP { get; private set; }
public bool IsDead { get { return hp <= 0; } } public bool IsDead { get { return hp <= 0; } }
public bool RemoveOnDeath = true; public bool RemoveOnDeath = true;
@@ -162,13 +160,18 @@ namespace OpenRA.Traits
} }
} }
public void Kill(Actor self, Actor attacker)
{
InflictDamage(self, attacker, MaxHP, null, true);
}
public void Tick(Actor self) public void Tick(Actor self)
{ {
if (hp > DisplayHp) if (hp > DisplayHP)
DisplayHp = hp; DisplayHP = hp;
if (DisplayHp > hp) if (DisplayHP > hp)
DisplayHp = (2 * DisplayHp + hp) / 3; DisplayHP = (2 * DisplayHP + hp) / 3;
} }
} }
@@ -191,24 +194,4 @@ namespace OpenRA.Traits
return value; return value;
} }
} }
public static class HealthExts
{
public static DamageState GetDamageState(this Actor self)
{
if (self.Disposed)
return DamageState.Dead;
var health = self.TraitOrDefault<Health>();
return (health == null) ? DamageState.Undamaged : health.DamageState;
}
public static void InflictDamage(this Actor self, Actor attacker, int damage, IWarhead warhead)
{
if (self.Disposed) return;
var health = self.TraitOrDefault<Health>();
if (health == null) return;
health.InflictDamage(self, attacker, damage, warhead, false);
}
}
} }

View File

@@ -19,6 +19,20 @@ using OpenRA.Primitives;
namespace OpenRA.Traits namespace OpenRA.Traits
{ {
public enum DamageState { Undamaged, Light, Medium, Heavy, Critical, Dead }
public interface IHealth
{
DamageState DamageState { get; }
int HP { get; }
int MaxHP { get; }
int DisplayHP { get; }
bool IsDead { get; }
void InflictDamage(Actor self, Actor attacker, int damage, IWarhead warhead, bool ignoreModifiers);
void Kill(Actor self, Actor attacker);
}
// depends on the order of pips in WorldRenderer.cs! // depends on the order of pips in WorldRenderer.cs!
public enum PipType { Transparent, Green, Yellow, Red, Gray, Blue, Ammo, AmmoEmpty } public enum PipType { Transparent, Green, Yellow, Red, Gray, Blue, Ammo, AmmoEmpty }
public enum TagType { None, Fake, Primary } public enum TagType { None, Fake, Primary }