From 32c73fa72fccddb7e9397e1d12e898078df80903 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Sun, 2 May 2010 13:18:13 +1200 Subject: [PATCH] heli separation --- OpenRA.Game/Traits/Activities/HeliAttack.cs | 36 +++++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/OpenRA.Game/Traits/Activities/HeliAttack.cs b/OpenRA.Game/Traits/Activities/HeliAttack.cs index da2f24a891..6b3360cbc3 100644 --- a/OpenRA.Game/Traits/Activities/HeliAttack.cs +++ b/OpenRA.Game/Traits/Activities/HeliAttack.cs @@ -19,6 +19,7 @@ #endregion using System; +using System.Linq; using OpenRA.GameRules; namespace OpenRA.Traits.Activities @@ -27,6 +28,7 @@ namespace OpenRA.Traits.Activities { Actor target; const int CruiseAltitude = 20; + const int AvoidDist = 80; public HeliAttack( Actor target ) { this.target = target; } public IActivity NextActivity { get; set; } @@ -54,17 +56,37 @@ namespace OpenRA.Traits.Activities var desiredFacing = Util.GetFacing(dist, unit.Facing); Util.TickFacing(ref unit.Facing, desiredFacing, self.Info.Traits.Get().ROT); - if (!float2.WithinEpsilon(float2.Zero, dist, range * Game.CellSize)) - { - var rawSpeed = .2f * Util.GetEffectiveSpeed(self, UnitMovementType.Fly); - self.CenterLocation += (rawSpeed / dist.Length) * dist; - self.Location = ((1 / 24f) * self.CenterLocation).ToInt2(); - } + var rawSpeed = .2f * Util.GetEffectiveSpeed(self, UnitMovementType.Fly); + + if (!float2.WithinEpsilon(float2.Zero, dist, range * Game.CellSize)) + self.CenterLocation += (rawSpeed / dist.Length) * dist; + + var otherHelis = self.World.FindUnitsInCircle(self.CenterLocation, AvoidDist) + .Where(a => a.traits.Contains()); + + var f = otherHelis + .Select(h => GetRepulseForce(self, h)) + .Aggregate(float2.Zero, (a, b) => a + b); + + self.CenterLocation += rawSpeed * f; + + self.Location = ((1 / 24f) * self.CenterLocation).ToInt2(); - /* todo: maintain seperation wrt other helis */ return this; } + const float Epsilon = .5f; + float2 GetRepulseForce(Actor self, Actor h) + { + if (self == h) + return float2.Zero; + var d = self.CenterLocation - h.CenterLocation; + if (d.LengthSquared < Epsilon) + return float2.FromAngle((float)self.World.SharedRandom.NextDouble() * 3.14f); + + return (2 / d.LengthSquared) * d; + } + public void Cancel(Actor self) { target = null; NextActivity = null; } } }