From a5d8dc5861c579fbdf34c7056c0d6e3ff50dcefd Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 29 Dec 2009 17:40:35 +1300 Subject: [PATCH 01/10] planes attacking works; post-attack glitches though --- OpenRa.Game/OpenRa.Game.csproj | 2 ++ OpenRa.Game/Traits/Activities/Circle.cs | 13 +++----- OpenRa.Game/Traits/Activities/FlyAttack.cs | 31 ++++++++++++++++++ OpenRa.Game/Traits/AttackPlane.cs | 38 ++++++++++++++++++++++ OpenRa.Game/Traits/AttackTurreted.cs | 2 +- OpenRa.Game/Traits/Util.cs | 7 ++++ units.ini | 4 +-- 7 files changed, 85 insertions(+), 12 deletions(-) create mode 100644 OpenRa.Game/Traits/Activities/FlyAttack.cs create mode 100644 OpenRa.Game/Traits/AttackPlane.cs diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj index 57c74ffc8b..87e964d61f 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -113,6 +113,7 @@ + @@ -174,6 +175,7 @@ + diff --git a/OpenRa.Game/Traits/Activities/Circle.cs b/OpenRa.Game/Traits/Activities/Circle.cs index 6f8eaefffd..be4bf96765 100644 --- a/OpenRa.Game/Traits/Activities/Circle.cs +++ b/OpenRa.Game/Traits/Activities/Circle.cs @@ -16,15 +16,10 @@ namespace OpenRa.Game.Traits.Activities public IActivity Tick(Actor self) { if (isCanceled) return NextActivity; - var unit = self.traits.Get(); - return new Fly(Util.CenterOfCell(Cell)) - { - NextActivity = - new FlyTimed(50, 20) - { - NextActivity = this - } - }; + return Util.SequenceActivities( + new Fly(Util.CenterOfCell(Cell)), + new FlyTimed(50, 20), + this); } public void Cancel(Actor self) { isCanceled = true; NextActivity = null; } diff --git a/OpenRa.Game/Traits/Activities/FlyAttack.cs b/OpenRa.Game/Traits/Activities/FlyAttack.cs new file mode 100644 index 0000000000..0d47d92685 --- /dev/null +++ b/OpenRa.Game/Traits/Activities/FlyAttack.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OpenRa.Game.Traits.Activities +{ + class FlyAttack : IActivity + { + public IActivity NextActivity { get; set; } + Actor Target; + + public FlyAttack(Actor target) { Target = target; } + + public IActivity Tick(Actor self) + { + if (Target == null || Target.IsDead) return NextActivity; + + var limitedAmmo = self.traits.GetOrDefault(); + if (limitedAmmo != null && !limitedAmmo.HasAmmo()) + return NextActivity; + + return Util.SequenceActivities( + new Fly(Target.CenterLocation), + new FlyTimed(50, 20), + this); + } + + public void Cancel(Actor self) { Target = null; NextActivity = null; } + } +} diff --git a/OpenRa.Game/Traits/AttackPlane.cs b/OpenRa.Game/Traits/AttackPlane.cs new file mode 100644 index 0000000000..47a51d61b2 --- /dev/null +++ b/OpenRa.Game/Traits/AttackPlane.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using OpenRa.Game.Traits.Activities; + +namespace OpenRa.Game.Traits +{ + // yet another ugly trait that does two things: + // - plane-specific attack order dispatch + // - forward-facing attack with a tolerance + + class AttackPlane : AttackBase + { + const int facingTolerance = 20; + + public AttackPlane(Actor self) : base(self) { } + + public override void Tick(Actor self) + { + base.Tick(self); + + if (target == null) return; + + var unit = self.traits.Get(); + var facingToTarget = Util.GetFacing(target.CenterLocation - self.CenterLocation, unit.Facing); + + if (Math.Abs(facingToTarget - unit.Facing) % 256 < facingTolerance) + DoAttack(self); + } + + protected override void QueueAttack(Actor self, Order order) + { + self.QueueActivity(new FlyAttack(order.TargetActor)); + target = order.TargetActor; + } + } +} diff --git a/OpenRa.Game/Traits/AttackTurreted.cs b/OpenRa.Game/Traits/AttackTurreted.cs index 3d9d40bd9d..256bd25379 100755 --- a/OpenRa.Game/Traits/AttackTurreted.cs +++ b/OpenRa.Game/Traits/AttackTurreted.cs @@ -41,7 +41,7 @@ namespace OpenRa.Game.Traits self.QueueActivity( new Traits.Activities.Follow( order.TargetActor, Math.Max( 0, (int)Rules.WeaponInfo[ weapon ].Range - RangeTolerance ) ) ); - self.traits.Get().target = order.TargetActor; + target = order.TargetActor; } bool buildComplete = false; diff --git a/OpenRa.Game/Traits/Util.cs b/OpenRa.Game/Traits/Util.cs index 8809c86d90..b578fa3ff6 100755 --- a/OpenRa.Game/Traits/Util.cs +++ b/OpenRa.Game/Traits/Util.cs @@ -2,6 +2,7 @@ using System.Linq; using OpenRa.Game.GameRules; using OpenRa.Game.Graphics; +using OpenRa.Game.Traits.Activities; namespace OpenRa.Game.Traits { @@ -135,5 +136,11 @@ namespace OpenRa.Game.Traits .Product(); return mi.Speed * modifier; } + + public static IActivity SequenceActivities(params IActivity[] acts) + { + return acts.Reverse().Aggregate((IActivity)null, + (next, a) => { a.NextActivity = next; return a; }); + } } } diff --git a/units.ini b/units.ini index 0457488a27..da6a29918e 100755 --- a/units.ini +++ b/units.ini @@ -165,13 +165,13 @@ HIND [MIG] Description=Mig Attack Plane BuiltAt=afld -Traits=Unit, Plane, RenderUnit, WithShadow, LimitedAmmo +Traits=Unit, AttackPlane, Plane, RenderUnit, WithShadow, LimitedAmmo InitialFacing=192 LongDesc=Fast Ground-Attack Plane.\n Strong vs Buildings\n Weak vs Infantry, Light Vehicles [YAK] Description=Yak Attack Plane BuiltAt=afld -Traits=Unit, Plane, RenderUnit, WithShadow, LimitedAmmo +Traits=Unit, AttackPlane, Plane, RenderUnit, WithShadow, LimitedAmmo InitialFacing=192 LongDesc=Anti-Tanks & Anti-Infantry Plane.\n Strong vs Infantry, Tanks\n Weak vs Buildings [TRAN] From 8a71bf36c34eb130f12085c95776296855afa94b Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 29 Dec 2009 19:47:08 +1300 Subject: [PATCH 02/10] planes return to base after attacking --- OpenRa.Game/Traits/Activities/FlyAttack.cs | 3 ++- OpenRa.Game/Traits/Activities/ReturnToBase.cs | 25 ++++++++++++++++++- OpenRa.Game/Traits/AttackPlane.cs | 4 ++- OpenRa.Game/Traits/Plane.cs | 2 +- OpenRa.Game/Traits/Util.cs | 2 +- 5 files changed, 31 insertions(+), 5 deletions(-) diff --git a/OpenRa.Game/Traits/Activities/FlyAttack.cs b/OpenRa.Game/Traits/Activities/FlyAttack.cs index 0d47d92685..21baf5cba4 100644 --- a/OpenRa.Game/Traits/Activities/FlyAttack.cs +++ b/OpenRa.Game/Traits/Activities/FlyAttack.cs @@ -14,7 +14,8 @@ namespace OpenRa.Game.Traits.Activities public IActivity Tick(Actor self) { - if (Target == null || Target.IsDead) return NextActivity; + if (Target == null || Target.IsDead) + return NextActivity; var limitedAmmo = self.traits.GetOrDefault(); if (limitedAmmo != null && !limitedAmmo.HasAmmo()) diff --git a/OpenRa.Game/Traits/Activities/ReturnToBase.cs b/OpenRa.Game/Traits/Activities/ReturnToBase.cs index ee7af24ef4..991bd37f3f 100644 --- a/OpenRa.Game/Traits/Activities/ReturnToBase.cs +++ b/OpenRa.Game/Traits/Activities/ReturnToBase.cs @@ -7,14 +7,37 @@ namespace OpenRa.Game.Traits.Activities { class ReturnToBase : IActivity { + // todo: defer decision-making until we are first scheduled! public IActivity NextActivity { get; set; } bool isCanceled; readonly float2 w1, w2, w3; /* tangent points to turn circles */ readonly float2 landPoint; - public ReturnToBase(Actor self, float2 landPos) + public ReturnToBase(Actor self) + : this( self, null ) {} + + Actor ChooseAirfield(Actor self) { + // todo: handle reservations + + var airfield = Game.world.Actors + .Where(a => a.Info == Rules.UnitInfo["AFLD"] + && a.Owner == self.Owner) + .FirstOrDefault(); + + if (airfield == null) + throw new NotImplementedException("nowhere to land; what to do?"); + + return airfield; + } + + public ReturnToBase(Actor self, Actor dest) + { + if (dest == null) + dest = ChooseAirfield(self); + + var landPos = dest.CenterLocation; var unit = self.traits.Get(); var speed = .2f * Util.GetEffectiveSpeed(self); var approachStart = landPos - new float2(unit.Altitude * speed, 0); diff --git a/OpenRa.Game/Traits/AttackPlane.cs b/OpenRa.Game/Traits/AttackPlane.cs index 47a51d61b2..0c2d0e0553 100644 --- a/OpenRa.Game/Traits/AttackPlane.cs +++ b/OpenRa.Game/Traits/AttackPlane.cs @@ -31,8 +31,10 @@ namespace OpenRa.Game.Traits protected override void QueueAttack(Actor self, Order order) { - self.QueueActivity(new FlyAttack(order.TargetActor)); + self.CancelActivity(); target = order.TargetActor; + self.QueueActivity(new FlyAttack(order.TargetActor)); + self.QueueActivity(new ReturnToBase(self)); } } } diff --git a/OpenRa.Game/Traits/Plane.cs b/OpenRa.Game/Traits/Plane.cs index 064662ee06..aca90b5998 100644 --- a/OpenRa.Game/Traits/Plane.cs +++ b/OpenRa.Game/Traits/Plane.cs @@ -36,7 +36,7 @@ namespace OpenRa.Game.Traits if (order.OrderString == "Enter") { self.CancelActivity(); - self.QueueActivity(new ReturnToBase(self, order.TargetActor.CenterLocation)); + self.QueueActivity(new ReturnToBase(self, order.TargetActor)); } } diff --git a/OpenRa.Game/Traits/Util.cs b/OpenRa.Game/Traits/Util.cs index b578fa3ff6..fa918b337d 100755 --- a/OpenRa.Game/Traits/Util.cs +++ b/OpenRa.Game/Traits/Util.cs @@ -139,7 +139,7 @@ namespace OpenRa.Game.Traits public static IActivity SequenceActivities(params IActivity[] acts) { - return acts.Reverse().Aggregate((IActivity)null, + return acts.Reverse().Aggregate( (next, a) => { a.NextActivity = next; return a; }); } } From b5d9c9e6508f6a3ea03425a83c60c6a494953b4b Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 29 Dec 2009 19:51:36 +1300 Subject: [PATCH 03/10] defer landing decision until needed --- OpenRa.Game/Traits/Activities/ReturnToBase.cs | 42 ++++++++++--------- OpenRa.Game/Traits/AttackPlane.cs | 2 +- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/OpenRa.Game/Traits/Activities/ReturnToBase.cs b/OpenRa.Game/Traits/Activities/ReturnToBase.cs index 991bd37f3f..20a746fac4 100644 --- a/OpenRa.Game/Traits/Activities/ReturnToBase.cs +++ b/OpenRa.Game/Traits/Activities/ReturnToBase.cs @@ -7,15 +7,14 @@ namespace OpenRa.Game.Traits.Activities { class ReturnToBase : IActivity { - // todo: defer decision-making until we are first scheduled! public IActivity NextActivity { get; set; } + bool isCanceled; + bool isCalculated; + Actor dest; - readonly float2 w1, w2, w3; /* tangent points to turn circles */ - readonly float2 landPoint; - - public ReturnToBase(Actor self) - : this( self, null ) {} + float2 w1, w2, w3; /* tangent points to turn circles */ + float2 landPoint; Actor ChooseAirfield(Actor self) { @@ -32,10 +31,9 @@ namespace OpenRa.Game.Traits.Activities return airfield; } - public ReturnToBase(Actor self, Actor dest) + void Calculate(Actor self) { - if (dest == null) - dest = ChooseAirfield(self); + if (dest == null) dest = ChooseAirfield(self); var landPos = dest.CenterLocation; var unit = self.traits.Get(); @@ -67,22 +65,26 @@ namespace OpenRa.Game.Traits.Activities w2 = c2 + f; w3 = approachStart; landPoint = landPos; + + isCalculated = true; + } + + public ReturnToBase(Actor self, Actor dest) + { + this.dest = dest; } public IActivity Tick(Actor self) { if (isCanceled) return NextActivity; - var unit = self.traits.Get(); - return new Fly(w1) - { - NextActivity = new Fly(w2) - { - NextActivity = new Fly(w3) - { - NextActivity = new Land(landPoint) - } - } - }; + if (!isCalculated) + Calculate(self); + + return Util.SequenceActivities( + new Fly(w1), + new Fly(w2), + new Fly(w3), + new Land(landPoint)); } public void Cancel(Actor self) { isCanceled = true; NextActivity = null; } diff --git a/OpenRa.Game/Traits/AttackPlane.cs b/OpenRa.Game/Traits/AttackPlane.cs index 0c2d0e0553..427096b62b 100644 --- a/OpenRa.Game/Traits/AttackPlane.cs +++ b/OpenRa.Game/Traits/AttackPlane.cs @@ -34,7 +34,7 @@ namespace OpenRa.Game.Traits self.CancelActivity(); target = order.TargetActor; self.QueueActivity(new FlyAttack(order.TargetActor)); - self.QueueActivity(new ReturnToBase(self)); + self.QueueActivity(new ReturnToBase(self, null)); } } } From 77e1b5ba8c340a5153da1595fbb5f31f14e8add0 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 29 Dec 2009 19:59:22 +1300 Subject: [PATCH 04/10] update progress --- doc/progress.txt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/doc/progress.txt b/doc/progress.txt index aedf15ccfb..bf39fb74c7 100644 --- a/doc/progress.txt +++ b/doc/progress.txt @@ -36,12 +36,13 @@ Helicopters - Repair/rearm doesn't work TRAN Cargo doesn't work -Planes - - Edge cases in landing code - - Circle behavior needs to be able to work with a unit - - -YAK Weapons don't work -MIG Weapons don't work +Planes + - AFLD reservations don't work + - Rearm doesn't work (should happen when on AFLD) + - Repair at FIX doesn't work [fix doesn't work?] + - Planes damage themselves (should never happen; these are AG weapons) +YAK Ammo/ROF are funky +MIG Ammo/ROF are funky Ships From b3ec936497f089181b4c89047ba393981f5b4760 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 29 Dec 2009 20:21:44 +1300 Subject: [PATCH 05/10] move action has return-to-base --- OpenRa.Game/Traits/Plane.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/OpenRa.Game/Traits/Plane.cs b/OpenRa.Game/Traits/Plane.cs index aca90b5998..f0accf7995 100644 --- a/OpenRa.Game/Traits/Plane.cs +++ b/OpenRa.Game/Traits/Plane.cs @@ -8,9 +8,7 @@ namespace OpenRa.Game.Traits { class Plane : IOrder, IMovement { - public Plane(Actor self) - { - } + public Plane(Actor self) {} public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor) { @@ -30,7 +28,8 @@ namespace OpenRa.Game.Traits if (order.OrderString == "Move") { self.CancelActivity(); - self.QueueActivity(new Circle(order.TargetLocation)); + self.QueueActivity(new Fly(Util.CenterOfCell(order.TargetLocation))); + self.QueueActivity(new ReturnToBase(self, null)); } if (order.OrderString == "Enter") From 76a59a10268ef86c983b458be7a7a0c51874ab9d Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 29 Dec 2009 20:21:58 +1300 Subject: [PATCH 06/10] removing redundant Circle activity --- OpenRa.Game/OpenRa.Game.csproj | 1 - OpenRa.Game/Traits/Activities/Circle.cs | 27 ------------------------- 2 files changed, 28 deletions(-) delete mode 100644 OpenRa.Game/Traits/Activities/Circle.cs diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj index 87e964d61f..9fe3375de5 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -110,7 +110,6 @@ - diff --git a/OpenRa.Game/Traits/Activities/Circle.cs b/OpenRa.Game/Traits/Activities/Circle.cs deleted file mode 100644 index be4bf96765..0000000000 --- a/OpenRa.Game/Traits/Activities/Circle.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace OpenRa.Game.Traits.Activities -{ - class Circle : IActivity - { - public IActivity NextActivity { get; set; } - bool isCanceled; - readonly int2 Cell; - - public Circle(int2 cell) { Cell = cell; } - - public IActivity Tick(Actor self) - { - if (isCanceled) return NextActivity; - return Util.SequenceActivities( - new Fly(Util.CenterOfCell(Cell)), - new FlyTimed(50, 20), - this); - } - - public void Cancel(Actor self) { isCanceled = true; NextActivity = null; } - } -} From 8fc8d0d9c7422451029070708cc5dde97237b05d Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 29 Dec 2009 20:47:06 +1300 Subject: [PATCH 07/10] new heli movement --- OpenRa.Game/OpenRa.Game.csproj | 2 + OpenRa.Game/Traits/Activities/HeliFly.cs | 49 ++++++++++++++++ OpenRa.Game/Traits/Activities/HeliLand.cs | 32 +++++++++++ OpenRa.Game/Traits/Helicopter.cs | 70 +++-------------------- OpenRa.Game/Traits/Production.cs | 4 -- 5 files changed, 92 insertions(+), 65 deletions(-) create mode 100644 OpenRa.Game/Traits/Activities/HeliFly.cs create mode 100644 OpenRa.Game/Traits/Activities/HeliLand.cs diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj index 57c74ffc8b..da4ca11ed3 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -114,6 +114,8 @@ + + diff --git a/OpenRa.Game/Traits/Activities/HeliFly.cs b/OpenRa.Game/Traits/Activities/HeliFly.cs new file mode 100644 index 0000000000..c27de496f1 --- /dev/null +++ b/OpenRa.Game/Traits/Activities/HeliFly.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OpenRa.Game.Traits.Activities +{ + class HeliFly : IActivity + { + const int CruiseAltitude = 20; + readonly float2 Dest; + public HeliFly(float2 dest) + { + Dest = dest; + } + + public IActivity NextActivity { get; set; } + bool isCanceled; + + public IActivity Tick(Actor self) + { + if (isCanceled) + return NextActivity; + + var unit = self.traits.Get(); + + if (unit.Altitude != CruiseAltitude) + { + unit.Altitude += Math.Sign(CruiseAltitude - unit.Altitude); + return this; + } + + var dist = Dest - self.CenterLocation; + if (float2.WithinEpsilon(float2.Zero, dist, 10)) + return NextActivity; + + var desiredFacing = Util.GetFacing(dist, unit.Facing); + Util.TickFacing(ref unit.Facing, desiredFacing, self.Info.ROT); + + var rawSpeed = .2f * Util.GetEffectiveSpeed(self); + self.CenterLocation += (rawSpeed / dist.Length) * dist; + self.Location = ((1 / 24f) * self.CenterLocation).ToInt2(); + + return this; + } + + public void Cancel(Actor self) { isCanceled = true; NextActivity = null; } + } +} diff --git a/OpenRa.Game/Traits/Activities/HeliLand.cs b/OpenRa.Game/Traits/Activities/HeliLand.cs new file mode 100644 index 0000000000..eea8171415 --- /dev/null +++ b/OpenRa.Game/Traits/Activities/HeliLand.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OpenRa.Game.Traits.Activities +{ + class HeliLand : IActivity + { + public HeliLand(bool requireSpace) { this.requireSpace = requireSpace; } + + bool requireSpace; + bool isCanceled; + public IActivity NextActivity { get; set; } + + public IActivity Tick(Actor self) + { + if (isCanceled) return NextActivity; + var unit = self.traits.Get(); + if (unit.Altitude == 0) + return NextActivity; + + if (requireSpace && !Game.IsCellBuildable(self.Location, UnitMovementType.Foot)) + return this; // fail to land if no space + + --unit.Altitude; + return this; + } + + public void Cancel(Actor self) { isCanceled = true; NextActivity = null; } + } +} diff --git a/OpenRa.Game/Traits/Helicopter.cs b/OpenRa.Game/Traits/Helicopter.cs index 400456f832..0c1d5b1a82 100644 --- a/OpenRa.Game/Traits/Helicopter.cs +++ b/OpenRa.Game/Traits/Helicopter.cs @@ -1,19 +1,13 @@ using System; using System.Linq; using OpenRa.Game.GameRules; +using OpenRa.Game.Traits.Activities; namespace OpenRa.Game.Traits { - class Helicopter : ITick, IOrder, IMovement + class Helicopter : IOrder, IMovement { - public int2 targetLocation; - - const int CruiseAltitude = 20; - - public Helicopter(Actor self) - { - targetLocation = self.Location; - } + public Helicopter(Actor self) {} public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor) { @@ -27,61 +21,15 @@ namespace OpenRa.Game.Traits public void ResolveOrder( Actor self, Order order ) { - if( order.OrderString == "Move" ) + if (order.OrderString == "Move") { - targetLocation = order.TargetLocation; - - var attackBase = self.traits.WithInterface().FirstOrDefault(); - if( attackBase != null ) - attackBase.target = null; /* move cancels attack order */ + self.CancelActivity(); + self.QueueActivity(new HeliFly(Util.CenterOfCell(order.TargetLocation))); + self.QueueActivity(new HeliLand(true)); } } - public void Tick(Actor self) - { - var unit = self.traits.Get(); - - if (self.Location != targetLocation) - { - var dist = Util.CenterOfCell(targetLocation) - self.CenterLocation; - var desiredFacing = Util.GetFacing(dist, unit.Facing); - Util.TickFacing(ref unit.Facing, desiredFacing, - self.Info.ROT); - - var rawSpeed = .2f * Util.GetEffectiveSpeed(self); - var angle = (unit.Facing - desiredFacing) / 128f * Math.PI; - var scale = .4f + .6f * (float)Math.Cos(angle); - - if (unit.Altitude > CruiseAltitude / 2) // do some movement. - { - self.CenterLocation += (rawSpeed * scale / dist.Length) * dist; - self.CenterLocation += (1f - scale) * rawSpeed - * float2.FromAngle((float)angle); - self.Location = ((1 / 24f) * self.CenterLocation).ToInt2(); - } - - if (unit.Altitude < CruiseAltitude) - { - ++unit.Altitude; - return; - } - } - else if (unit.Altitude > 0 && - Game.IsCellBuildable( self.Location, UnitMovementType.Foot )) - { - --unit.Altitude; - } - - /* todo: bob slightly when hovering */ - } - public UnitMovementType GetMovementType() - { - return UnitMovementType.Fly; - } - - public bool CanEnterCell(int2 location) - { - return true; // Planes can go anywhere (?) - } + public UnitMovementType GetMovementType() { return UnitMovementType.Fly; } + public bool CanEnterCell(int2 location) { return true; } } } diff --git a/OpenRa.Game/Traits/Production.cs b/OpenRa.Game/Traits/Production.cs index f916f05dc5..c4d1413f39 100755 --- a/OpenRa.Game/Traits/Production.cs +++ b/OpenRa.Game/Traits/Production.cs @@ -33,10 +33,6 @@ namespace OpenRa.Game.Traits var mobile = newUnit.traits.GetOrDefault(); if( mobile != null ) newUnit.QueueActivity( new Activities.Move( rp.rallyPoint, 1 ) ); - - var heli = newUnit.traits.GetOrDefault(); - if (heli != null) - heli.targetLocation = rp.rallyPoint; // TODO: make Activity.Move work for helis. } var bi = self.Info as BuildingInfo; From f061c82f4ca2aeb0e06b58232d7c0056d620e541 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 29 Dec 2009 21:08:23 +1300 Subject: [PATCH 08/10] wired up so it actually works --- OpenRa.Game/OpenRa.Game.csproj | 2 + OpenRa.Game/Traits/Activities/HeliAttack.cs | 52 +++++++++++++++++++++ OpenRa.Game/Traits/AttackHeli.cs | 35 ++++++++++++++ units.ini | 4 +- 4 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 OpenRa.Game/Traits/Activities/HeliAttack.cs create mode 100644 OpenRa.Game/Traits/AttackHeli.cs diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj index da4ca11ed3..bee3b6d805 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -114,6 +114,7 @@ + @@ -175,6 +176,7 @@ + diff --git a/OpenRa.Game/Traits/Activities/HeliAttack.cs b/OpenRa.Game/Traits/Activities/HeliAttack.cs new file mode 100644 index 0000000000..28eeab1210 --- /dev/null +++ b/OpenRa.Game/Traits/Activities/HeliAttack.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OpenRa.Game.Traits.Activities +{ + class HeliAttack : IActivity + { + Actor target; + const int CruiseAltitude = 20; + public HeliAttack( Actor target ) { this.target = target; } + + public IActivity NextActivity { get; set; } + + public IActivity Tick(Actor self) + { + if (target == null || target.IsDead) + return NextActivity; + + var limitedAmmo = self.traits.GetOrDefault(); + if (limitedAmmo != null && !limitedAmmo.HasAmmo()) + return NextActivity; + + var unit = self.traits.Get(); + + if (unit.Altitude != CruiseAltitude) + { + unit.Altitude += Math.Sign(CruiseAltitude - unit.Altitude); + return this; + } + + var range = Rules.WeaponInfo[ self.Info.Primary ].Range; + var dist = target.CenterLocation - self.CenterLocation; + + var desiredFacing = Util.GetFacing(dist, unit.Facing); + Util.TickFacing(ref unit.Facing, desiredFacing, self.Info.ROT); + + if (!float2.WithinEpsilon(float2.Zero, dist, range * Game.CellSize)) + { + var rawSpeed = .2f * Util.GetEffectiveSpeed(self); + self.CenterLocation += (rawSpeed / dist.Length) * dist; + self.Location = ((1 / 24f) * self.CenterLocation).ToInt2(); + } + + /* todo: maintain seperation wrt other helis */ + return this; + } + + public void Cancel(Actor self) { target = null; NextActivity = null; } + } +} diff --git a/OpenRa.Game/Traits/AttackHeli.cs b/OpenRa.Game/Traits/AttackHeli.cs new file mode 100644 index 0000000000..093870a0dd --- /dev/null +++ b/OpenRa.Game/Traits/AttackHeli.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using OpenRa.Game.Traits.Activities; + +namespace OpenRa.Game.Traits +{ + class AttackHeli : AttackBase + { + public AttackHeli(Actor self) : base(self) { } + + const int facingTolerance = 20; + public override void Tick(Actor self) + { + base.Tick(self); + + if (target == null) return; + + var unit = self.traits.Get(); + var facingToTarget = Util.GetFacing(target.CenterLocation - self.CenterLocation, unit.Facing); + + if (Math.Abs(facingToTarget - unit.Facing) % 256 < facingTolerance) + DoAttack(self); + } + + protected override void QueueAttack(Actor self, Order order) + { + self.CancelActivity(); + self.QueueActivity(new HeliAttack(order.TargetActor)); + target = order.TargetActor; + // todo: fly home + } + } +} diff --git a/units.ini b/units.ini index 0457488a27..5382f0eec9 100755 --- a/units.ini +++ b/units.ini @@ -185,14 +185,14 @@ LongDesc=Fast Infantry Transport Helicopter.\n Unarmed [HELI] Description=Longbow BuiltAt=hpad -Traits=Unit, Helicopter, RenderUnitRotor, WithShadow, LimitedAmmo +Traits=Unit, AttackHeli, Helicopter, RenderUnitRotor, WithShadow, LimitedAmmo PrimaryOffset=0,0,0,-2 InitialFacing=20 LongDesc=Helicopter Gunship with AG Missiles.\n Strong vs Buildings, Tanks\n Weak vs Infantry [HIND] Description=Hind BuiltAt=hpad -Traits=Unit, Helicopter, RenderUnitRotor, WithShadow, LimitedAmmo +Traits=Unit, AttackHeli, Helicopter, RenderUnitRotor, WithShadow, LimitedAmmo InitialFacing=20 LongDesc=Helicopter Gunship with Chainguns.\n Strong vs Infantry, Light Vehicles.\n Weak vs Tanks From a02836b19e5c0cba24016d35dbeb2e6dd580b1e0 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 29 Dec 2009 21:13:06 +1300 Subject: [PATCH 09/10] heli range hack --- OpenRa.Game/Traits/Activities/HeliAttack.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenRa.Game/Traits/Activities/HeliAttack.cs b/OpenRa.Game/Traits/Activities/HeliAttack.cs index 28eeab1210..65c6f44ef3 100644 --- a/OpenRa.Game/Traits/Activities/HeliAttack.cs +++ b/OpenRa.Game/Traits/Activities/HeliAttack.cs @@ -30,7 +30,7 @@ namespace OpenRa.Game.Traits.Activities return this; } - var range = Rules.WeaponInfo[ self.Info.Primary ].Range; + var range = Rules.WeaponInfo[ self.Info.Primary ].Range - 1; var dist = target.CenterLocation - self.CenterLocation; var desiredFacing = Util.GetFacing(dist, unit.Facing); From be783e768383a8c4ffaf32edb3dfa8058f1483db Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 29 Dec 2009 21:14:18 +1300 Subject: [PATCH 10/10] updating progress --- doc/progress.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/progress.txt b/doc/progress.txt index aedf15ccfb..2ec616eb41 100644 --- a/doc/progress.txt +++ b/doc/progress.txt @@ -31,10 +31,10 @@ HARV Works ARTY Works Helicopters - - Weapons don't work, - - hover while attacking doesn't work, - Repair/rearm doesn't work TRAN Cargo doesn't work +HELI Weapon offsets wrong +HIND Weapon offsets wrong Planes - Edge cases in landing code