From 77bb9494112c87d5bf97b42ab96b8e23e243af92 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Mon, 28 Dec 2009 12:40:00 +1300 Subject: [PATCH] autoheal split from autotarget; it's fairly different. --- OpenRa.Game/OpenRa.Game.csproj | 1 + OpenRa.Game/Traits/AutoHeal.cs | 64 ++++++++++++++++++++++++++++++++++ units.ini | 2 +- 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 OpenRa.Game/Traits/AutoHeal.cs diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj index 3ea793d682..9540200910 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -172,6 +172,7 @@ + diff --git a/OpenRa.Game/Traits/AutoHeal.cs b/OpenRa.Game/Traits/AutoHeal.cs new file mode 100644 index 0000000000..2015140ccd --- /dev/null +++ b/OpenRa.Game/Traits/AutoHeal.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OpenRa.Game.Traits +{ + class AutoHeal : ITick + { + public AutoHeal(Actor self) { } + + void AttackTarget(Actor self, Actor target) + { + var attack = self.traits.WithInterface().First(); + if (target != null) + attack.ResolveOrder(self, new Order("Attack", self, target, int2.Zero, null)); + } + + float GetMaximumRange(Actor self) + { + return new[] { self.Info.Primary, self.Info.Secondary } + .Where(w => w != null) + .Max(w => Rules.WeaponInfo[w].Range); + } + + bool NeedsNewTarget(Actor self) + { + var attack = self.traits.WithInterface().First(); + var range = GetMaximumRange(self); + + if (attack.target == null) + return true; // he's dead. + if ((attack.target.Location - self.Location).LengthSquared > range * range + 2) + return true; // wandered off faster than we could follow + if (attack.target.Health == attack.target.Info.Strength) + return true; // fully healed + + return false; + } + + public void Tick(Actor self) + { + if (!self.IsIdle) return; + + var attack = self.traits.WithInterface().First(); + var range = GetMaximumRange(self); + + if (NeedsNewTarget(self)) + AttackTarget(self, ChooseTarget(self, range)); + } + + Actor ChooseTarget(Actor self, float range) + { + var inRange = Game.FindUnitsInCircle(self.CenterLocation, Game.CellSize * range); + + return inRange + .Where(a => a.Owner == self.Owner) /* todo: one day deal with friendly players */ + .Where(a => Combat.HasAnyValidWeapons(self, a)) + .Where(a => a.Health < a.Info.Strength) + .OrderBy(a => (a.Location - self.Location).LengthSquared) + .FirstOrDefault(); + } + } +} diff --git a/units.ini b/units.ini index 2644c3a949..633e89a442 100755 --- a/units.ini +++ b/units.ini @@ -569,7 +569,7 @@ LongDesc=Elite commando infantry, armed with \ndual pistols and C4.\n Strong vs [MEDI] Description=Medic Voice=MedicVoice -Traits=Unit, Mobile, RenderInfantry, AttackBase, TakeCover, Infantry, AutoTarget +Traits=Unit, Mobile, RenderInfantry, AttackBase, TakeCover, Infantry, AutoHeal LongDesc=Heals nearby infantry.\n Strong vs Nothing\n Weak vs Everything