From 56da57bc09b2719adba87730d9fcd149ed7c7019 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 20 Jul 2013 19:04:09 +1200 Subject: [PATCH 01/26] Return WVec.LengthSquared as a long to avoid overflow. --- OpenRA.FileFormats/WVec.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenRA.FileFormats/WVec.cs b/OpenRA.FileFormats/WVec.cs index 7b450d9d57..e792a75ae6 100644 --- a/OpenRA.FileFormats/WVec.cs +++ b/OpenRA.FileFormats/WVec.cs @@ -36,7 +36,7 @@ namespace OpenRA public static bool operator !=(WVec me, WVec other) { return !(me == other); } public static int Dot(WVec a, WVec b) { return a.X * b.X + a.Y * b.Y + a.Z * b.Z; } - public int LengthSquared { get { return X * X + Y * Y + Z * Z; } } + public long LengthSquared { get { return (long)X * X + (long)Y * Y + (long)Z * Z; } } public int Length { get { return (int)Math.Sqrt(LengthSquared); } } public WVec Rotate(WRot rot) From f18994f800b41d0a95e2b77e4dceccf3f513aa4b Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 20 Jul 2013 19:04:19 +1200 Subject: [PATCH 02/26] Add WVec.HorizontalLengthSquared to simplify range checks. --- OpenRA.FileFormats/WVec.cs | 1 + OpenRA.Game/Traits/Target.cs | 7 +------ OpenRA.Mods.RA/Air/Land.cs | 14 ++++++++++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/OpenRA.FileFormats/WVec.cs b/OpenRA.FileFormats/WVec.cs index e792a75ae6..ab96bea054 100644 --- a/OpenRA.FileFormats/WVec.cs +++ b/OpenRA.FileFormats/WVec.cs @@ -38,6 +38,7 @@ namespace OpenRA public static int Dot(WVec a, WVec b) { return a.X * b.X + a.Y * b.Y + a.Z * b.Z; } public long LengthSquared { get { return (long)X * X + (long)Y * Y + (long)Z * Z; } } public int Length { get { return (int)Math.Sqrt(LengthSquared); } } + public long HorizontalLengthSquared { get { return (long)X * X + (long)Y * Y; } } public WVec Rotate(WRot rot) { diff --git a/OpenRA.Game/Traits/Target.cs b/OpenRA.Game/Traits/Target.cs index 2bd84ffd11..39d0153123 100644 --- a/OpenRA.Game/Traits/Target.cs +++ b/OpenRA.Game/Traits/Target.cs @@ -91,12 +91,7 @@ namespace OpenRA.Traits // Target ranges are calculated in 2D, so ignore height differences var rangeSquared = range.Range*range.Range; - return Positions.Any(t => - { - var dx = (long)(t.X - origin.X); - var dy = (long)(t.Y - origin.Y); - return dx*dx + dy*dy <= rangeSquared; - }); + return Positions.Any(t => (t - origin).HorizontalLengthSquared <= rangeSquared); } } diff --git a/OpenRA.Mods.RA/Air/Land.cs b/OpenRA.Mods.RA/Air/Land.cs index eb5d41f398..42ac37f569 100755 --- a/OpenRA.Mods.RA/Air/Land.cs +++ b/OpenRA.Mods.RA/Air/Land.cs @@ -25,13 +25,19 @@ namespace OpenRA.Mods.RA.Air if (!Target.IsValid) Cancel(self); - if (IsCanceled) return NextActivity; - - var d = Target.CenterPosition - self.CenterPosition; - if (d.LengthSquared < 256*256) // close enough (1/4 cell) + if (IsCanceled) return NextActivity; var aircraft = self.Trait(); + var d = Target.CenterPosition - self.CenterPosition; + + // close enough (1/16 cell) + // TODO: TickMove may overshoot if the aircraft speed is too high + if (d.HorizontalLengthSquared < 4096) + { + aircraft.SetPxPosition(self, PPos.FromWPos(Target.CenterPosition)); + return NextActivity; + } if (aircraft.Altitude > 0) --aircraft.Altitude; From a0706295718deb0d87a230844bf2c79e3b5d8b49 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 20 Jul 2013 19:06:15 +1200 Subject: [PATCH 03/26] Convert plane activities to world coords. --- OpenRA.Mods.RA/Air/Fly.cs | 28 +++++------ OpenRA.Mods.RA/Air/FlyAttack.cs | 2 +- OpenRA.Mods.RA/Air/Land.cs | 6 +-- OpenRA.Mods.RA/Air/Plane.cs | 2 +- OpenRA.Mods.RA/Air/ReturnToBase.cs | 79 ++++++++++++++++-------------- 5 files changed, 62 insertions(+), 55 deletions(-) diff --git a/OpenRA.Mods.RA/Air/Fly.cs b/OpenRA.Mods.RA/Air/Fly.cs index 09f2ca2d81..bd900f72b9 100755 --- a/OpenRA.Mods.RA/Air/Fly.cs +++ b/OpenRA.Mods.RA/Air/Fly.cs @@ -16,25 +16,25 @@ namespace OpenRA.Mods.RA.Air { public class Fly : Activity { - public readonly PPos Pos; + readonly WPos pos; - Fly(PPos px) { Pos = px; } + Fly(WPos pos) { this.pos = pos; } - public static Fly ToPx( PPos px ) { return new Fly( px ); } - public static Fly ToCell(CPos pos) { return new Fly(Util.CenterOfCell(pos)); } + public static Fly ToPos(WPos pos) { return new Fly(pos); } + public static Fly ToCell(CPos pos) { return new Fly(pos.CenterPosition); } public override Activity Tick(Actor self) { - var cruiseAltitude = self.Info.Traits.Get().CruiseAltitude; + if (IsCanceled) + return NextActivity; - if (IsCanceled) return NextActivity; - - var d = Pos - self.CenterLocation; - if (d.LengthSquared < 50) /* close enough */ + // Close enough (ported from old code which checked length against sqrt(50) px) + var d = pos - self.CenterPosition; + if (d.HorizontalLengthSquared < 91022) return NextActivity; var aircraft = self.Trait(); - + var cruiseAltitude = self.Info.Traits.Get().CruiseAltitude; var desiredFacing = Util.GetFacing(d, aircraft.Facing); if (aircraft.Altitude == cruiseAltitude) aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT); @@ -46,18 +46,18 @@ namespace OpenRA.Mods.RA.Air return this; } - public override IEnumerable GetTargets( Actor self ) + public override IEnumerable GetTargets(Actor self) { - yield return Target.FromPos(Pos); + yield return Target.FromPos(pos); } } public static class FlyUtil { - public static void Fly(Actor self, int desiredAltitude ) + public static void Fly(Actor self, int desiredAltitude) { var aircraft = self.Trait(); - aircraft.TickMove( PSubPos.PerPx * aircraft.MovementSpeed, aircraft.Facing ); + aircraft.TickMove(PSubPos.PerPx * aircraft.MovementSpeed, aircraft.Facing); aircraft.Altitude += Math.Sign(desiredAltitude - aircraft.Altitude); } } diff --git a/OpenRA.Mods.RA/Air/FlyAttack.cs b/OpenRA.Mods.RA/Air/FlyAttack.cs index 43cc94fa9c..780bc77fb4 100755 --- a/OpenRA.Mods.RA/Air/FlyAttack.cs +++ b/OpenRA.Mods.RA/Air/FlyAttack.cs @@ -36,7 +36,7 @@ namespace OpenRA.Mods.RA.Air if( IsCanceled ) return NextActivity; inner = Util.SequenceActivities( - Fly.ToPx(Target.CenterLocation), + Fly.ToPos(Target.CenterPosition), new FlyTimed(50)); } inner = Util.RunActivity( self, inner ); diff --git a/OpenRA.Mods.RA/Air/Land.cs b/OpenRA.Mods.RA/Air/Land.cs index 42ac37f569..cedd99ebdb 100755 --- a/OpenRA.Mods.RA/Air/Land.cs +++ b/OpenRA.Mods.RA/Air/Land.cs @@ -31,9 +31,9 @@ namespace OpenRA.Mods.RA.Air var aircraft = self.Trait(); var d = Target.CenterPosition - self.CenterPosition; - // close enough (1/16 cell) - // TODO: TickMove may overshoot if the aircraft speed is too high - if (d.HorizontalLengthSquared < 4096) + // The next move would overshoot, so just set the final position + var moveDist = aircraft.MovementSpeed * 7 * 1024 / (Game.CellSize * 32); + if (d.HorizontalLengthSquared < moveDist*moveDist) { aircraft.SetPxPosition(self, PPos.FromWPos(Target.CenterPosition)); return NextActivity; diff --git a/OpenRA.Mods.RA/Air/Plane.cs b/OpenRA.Mods.RA/Air/Plane.cs index 6a877be1ed..0d07f8a657 100755 --- a/OpenRA.Mods.RA/Air/Plane.cs +++ b/OpenRA.Mods.RA/Air/Plane.cs @@ -21,7 +21,7 @@ namespace OpenRA.Mods.RA.Air public class Plane : Aircraft, IResolveOrder, ITick, ISync { - [Sync] public PVecInt RTBPathHash; + [Sync] public WPos RTBPathHash; public Plane( ActorInitializer init, PlaneInfo info ) : base( init, info ) { } diff --git a/OpenRA.Mods.RA/Air/ReturnToBase.cs b/OpenRA.Mods.RA/Air/ReturnToBase.cs index 22a06df9b7..4fddcdf466 100755 --- a/OpenRA.Mods.RA/Air/ReturnToBase.cs +++ b/OpenRA.Mods.RA/Air/ReturnToBase.cs @@ -19,8 +19,7 @@ namespace OpenRA.Mods.RA.Air { bool isCalculated; Actor dest; - - PPos w1, w2, w3; /* tangent points to turn circles */ + WPos w1, w2, w3; public static Actor ChooseAirfield(Actor self, bool unreservedOnly) { @@ -35,11 +34,14 @@ namespace OpenRA.Mods.RA.Air void Calculate(Actor self) { - if (dest == null || Reservable.IsReserved(dest)) dest = ChooseAirfield(self, true); + if (dest == null || Reservable.IsReserved(dest)) + dest = ChooseAirfield(self, true); - if (dest == null) return; + if (dest == null) + return; var plane = self.Trait(); + var planeInfo = self.Info.Traits.Get(); var res = dest.TraitOrDefault(); if (res != null) { @@ -47,41 +49,46 @@ namespace OpenRA.Mods.RA.Air plane.reservation = res.Reserve(dest, self, plane); } - var landPos = dest.CenterLocation; - var aircraft = self.Trait(); + var landPos = dest.CenterPosition; + var speed = plane.MovementSpeed * 1024 / Game.CellSize / 5; - var speed = .2f * aircraft.MovementSpeed; + // Distance required for descent. + // TODO: Generalize this for arbitrary flight pitches + var landDistance = planeInfo.CruiseAltitude * speed; + var altitude = planeInfo.CruiseAltitude * 1024 / Game.CellSize; - /* if the aircraft is on the ground, it will take off to the cruise altitude first before approaching */ - var altitude = aircraft.Altitude; - if (altitude == 0) altitude = self.Info.Traits.Get().CruiseAltitude; + // Land towards the east + var approachStart = landPos + new WVec(-landDistance, 0, altitude); - var approachStart = landPos.ToInt2() - new float2(altitude * speed, 0); - var turnRadius = (128f / self.Info.Traits.Get().ROT) * speed / (float)Math.PI; + // Add 10% to the turning radius to ensure we have enough room + var turnRadius = (int)(141 * speed / planeInfo.ROT / (float)(Math.PI)); - /* work out the center points */ - var fwd = -float2.FromAngle(aircraft.Facing / 128f * (float)Math.PI); - var side = new float2(-fwd.Y, fwd.X); /* rotate */ + // Find the center of the turning circles for clockwise and counterclockwise turns + var angle = WAngle.FromFacing(plane.Facing); + var fwd = -new WVec(angle.Sin(), angle.Cos(), 0); + + // Work out whether we should turn clockwise or counter-clockwise for approach + var side = new WVec(-fwd.Y, fwd.X, fwd.Z); + var approachDelta = self.CenterPosition - approachStart; var sideTowardBase = new[] { side, -side } - .OrderBy(a => float2.Dot(a, self.CenterLocation.ToInt2() - approachStart)) + .OrderBy(a => WVec.Dot(a, approachDelta)) .First(); - var c1 = self.CenterLocation.ToInt2() + turnRadius * sideTowardBase; - var c2 = approachStart + new float2(0, turnRadius * Math.Sign(self.CenterLocation.Y - approachStart.Y)); // above or below start point + // Calculate the tangent line that joins the turning circles at the current and approach positions + var cp = self.CenterPosition + turnRadius * sideTowardBase / 1024; + var posCenter = new WPos(cp.X, cp.Y, altitude); + var approachCenter = approachStart + new WVec(0, turnRadius * Math.Sign(self.CenterPosition.Y - approachStart.Y), 0); + var tangentDirection = approachCenter - posCenter; + var tangentOffset = new WVec(-tangentDirection.Y, tangentDirection.X, 0) * turnRadius / tangentDirection.Length; - /* work out tangent points */ - var d = c2 - c1; - var e = (turnRadius / d.Length) * d; - var f = new float2(-e.Y, e.X); /* rotate */ + // TODO: correctly handle CCW <-> CW turns + if (tangentOffset.X > 0) + tangentOffset = -tangentOffset; - /* TODO: support internal tangents, too! */ - - if (f.X > 0) f = -f; - - w1 = (PPos)(c1 + f).ToInt2(); - w2 = (PPos)(c2 + f).ToInt2(); - w3 = (PPos)(approachStart).ToInt2(); - plane.RTBPathHash = (PVecInt)w1 + (PVecInt)w2 + (PVecInt)w3; + w1 = posCenter + tangentOffset; + w2 = approachCenter + tangentOffset; + w3 = approachStart; + plane.RTBPathHash = w1 + (WVec)w2 + (WVec)w3; isCalculated = true; } @@ -93,12 +100,12 @@ namespace OpenRA.Mods.RA.Air public override Activity Tick(Actor self) { - if (IsCanceled) - return NextActivity; - if (self.IsDead()) + if (IsCanceled || self.IsDead()) return NextActivity; + if (!isCalculated) Calculate(self); + if (dest == null) { var nearestAfld = ChooseAirfield(self, false); @@ -111,9 +118,9 @@ namespace OpenRA.Mods.RA.Air } return Util.SequenceActivities( - Fly.ToPx(w1), - Fly.ToPx(w2), - Fly.ToPx(w3), + Fly.ToPos(w1), + Fly.ToPos(w2), + Fly.ToPos(w3), new Land(Target.FromActor(dest)), NextActivity); } From b92aa760d2940c2dfd0b6ab7f7a7f1a3036866df Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 20 Jul 2013 19:27:45 +1200 Subject: [PATCH 04/26] FlyAttack style fixes. --- OpenRA.Mods.RA/Air/FlyAttack.cs | 36 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/OpenRA.Mods.RA/Air/FlyAttack.cs b/OpenRA.Mods.RA/Air/FlyAttack.cs index 780bc77fb4..1e577804f4 100755 --- a/OpenRA.Mods.RA/Air/FlyAttack.cs +++ b/OpenRA.Mods.RA/Air/FlyAttack.cs @@ -14,43 +14,41 @@ namespace OpenRA.Mods.RA.Air { public class FlyAttack : Activity { - readonly Target Target; + readonly Target target; Activity inner; - public FlyAttack(Target target) { Target = target; } + public FlyAttack(Target target) { this.target = target; } public override Activity Tick(Actor self) { - if( !Target.IsValid ) - Cancel( self ); + if (!target.IsValid) + Cancel(self); + var limitedAmmo = self.TraitOrDefault(); - if( limitedAmmo != null && !limitedAmmo.HasAmmo() ) - Cancel( self ); + if (limitedAmmo != null && !limitedAmmo.HasAmmo()) + Cancel(self); var attack = self.TraitOrDefault(); if (attack != null) - attack.DoAttack( self, Target ); + attack.DoAttack(self, target); - if( inner == null ) + if (inner == null) { - if( IsCanceled ) + if (IsCanceled) return NextActivity; - inner = Util.SequenceActivities( - Fly.ToPos(Target.CenterPosition), - new FlyTimed(50)); + + inner = Util.SequenceActivities(Fly.ToPos(target.CenterPosition), new FlyTimed(50)); } - inner = Util.RunActivity( self, inner ); + + inner = Util.RunActivity(self, inner); return this; } - public override void Cancel( Actor self ) + public override void Cancel(Actor self) { - if( !IsCanceled ) - { - if( inner != null ) - inner.Cancel( self ); - } + if (!IsCanceled && inner != null) + inner.Cancel(self); // NextActivity must always be set to null: base.Cancel(self); From 712e13b1e7387070e7c01f7e90e40e065a611319 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 20 Jul 2013 19:21:16 +1200 Subject: [PATCH 05/26] Remove some duplication against WorldUtils.ClosestTo. --- OpenRA.Mods.RA/Missions/Allies04Script.cs | 2 +- OpenRA.Mods.RA/Missions/FortLonestarScript.cs | 5 ++--- OpenRA.Mods.RA/Missions/MissionUtils.cs | 2 +- OpenRA.Mods.RA/Missions/Soviet01ClassicScript.cs | 3 +-- OpenRA.Mods.RA/Missions/Survival01Script.cs | 5 ++--- 5 files changed, 7 insertions(+), 10 deletions(-) diff --git a/OpenRA.Mods.RA/Missions/Allies04Script.cs b/OpenRA.Mods.RA/Missions/Allies04Script.cs index dbe480c86b..e66a5335fd 100644 --- a/OpenRA.Mods.RA/Missions/Allies04Script.cs +++ b/OpenRA.Mods.RA/Missions/Allies04Script.cs @@ -150,7 +150,7 @@ namespace OpenRA.Mods.RA.Missions var enemies = world.Actors.Where(u => u.Owner == creeps && u.HasTrait() && ((u.HasTrait() && !u.HasTrait() && !u.HasTrait()) || u.HasTrait()) && !u.IsDead() && u.IsInWorld); - var enemy = enemies.OrderBy(u => (attacker.CenterPosition - u.CenterPosition).LengthSquared).FirstOrDefault(); + var enemy = enemies.ClosestTo(attacker); if (enemy != null) attacker.QueueActivity(new AttackMove.AttackMoveActivity(attacker, new Attack(Target.FromActor(enemy), WRange.FromCells(3)))); else diff --git a/OpenRA.Mods.RA/Missions/FortLonestarScript.cs b/OpenRA.Mods.RA/Missions/FortLonestarScript.cs index 4134054f37..bc4360879a 100644 --- a/OpenRA.Mods.RA/Missions/FortLonestarScript.cs +++ b/OpenRA.Mods.RA/Missions/FortLonestarScript.cs @@ -79,11 +79,10 @@ namespace OpenRA.Mods.RA.Missions { var enemies = world.Actors.Where(u => u.IsInWorld && !u.IsDead() && (u.Owner == multi0) && ((u.HasTrait() && !u.HasTrait()))); - var targetEnemy = enemies.OrderBy(u => (self.CenterPosition - u.CenterPosition).LengthSquared).FirstOrDefault(); + + var targetEnemy = enemies.ClosestTo(self); if (targetEnemy != null) - { self.QueueActivity(new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(targetEnemy), WRange.FromCells(6)))); - } } void SendVehicles() diff --git a/OpenRA.Mods.RA/Missions/MissionUtils.cs b/OpenRA.Mods.RA/Missions/MissionUtils.cs index e397de1dad..e5976235a5 100644 --- a/OpenRA.Mods.RA/Missions/MissionUtils.cs +++ b/OpenRA.Mods.RA/Missions/MissionUtils.cs @@ -212,7 +212,7 @@ namespace OpenRA.Mods.RA.Missions var enemies = self.World.Actors.Where(u => u.AppearsHostileTo(self) && u.Owner == enemyPlayer && ((u.HasTrait() && !u.HasTrait()) || (u.HasTrait() && !u.HasTrait())) && u.IsInWorld && !u.IsDead()); - var enemy = enemies.OrderBy(u => (self.CenterPosition - u.CenterPosition).LengthSquared).FirstOrDefault(); + var enemy = enemies.ClosestTo(self); if (enemy != null) self.QueueActivity(queued, new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(enemy), WRange.FromCells(3)))); } diff --git a/OpenRA.Mods.RA/Missions/Soviet01ClassicScript.cs b/OpenRA.Mods.RA/Missions/Soviet01ClassicScript.cs index 7971850508..b910b948e9 100644 --- a/OpenRA.Mods.RA/Missions/Soviet01ClassicScript.cs +++ b/OpenRA.Mods.RA/Missions/Soviet01ClassicScript.cs @@ -126,8 +126,7 @@ namespace OpenRA.Mods.RA.Missions { var bridge = world.Actors .Where(a => a.HasTrait() && !a.IsDead()) - .OrderBy(a => (startJeep.CenterPosition - a.CenterPosition).LengthSquared) - .First(); + .ClosestTo(startJeep); Combat.DoExplosion(bridge, "Demolish", bridge.CenterPosition); world.WorldActor.Trait().AddEffect(15, bridge.CenterPosition, 6); bridge.Kill(bridge); diff --git a/OpenRA.Mods.RA/Missions/Survival01Script.cs b/OpenRA.Mods.RA/Missions/Survival01Script.cs index 7b37bf0fdc..9ca1de8e66 100644 --- a/OpenRA.Mods.RA/Missions/Survival01Script.cs +++ b/OpenRA.Mods.RA/Missions/Survival01Script.cs @@ -211,11 +211,10 @@ namespace OpenRA.Mods.RA.Missions { var enemies = world.Actors.Where(u => u.IsInWorld && !u.IsDead() && (u.Owner == allies) && ((u.HasTrait() && !u.HasTrait()) || u.HasTrait())); - var targetEnemy = enemies.OrderBy(u => (self.CenterPosition - u.CenterPosition).LengthSquared).FirstOrDefault(); + + var targetEnemy = enemies.ClosestTo(self); if (targetEnemy != null) - { self.QueueActivity(new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(targetEnemy), WRange.FromCells(3)))); - } } void ManageSovietUnits() From 179f97a59846974c5d5fc6880f51925c5413db4a Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 20 Jul 2013 19:49:39 +1200 Subject: [PATCH 06/26] Convert helicopter activities to world coords. --- OpenRA.Mods.RA/Air/HeliFly.cs | 25 ++++----- OpenRA.Mods.RA/Air/HeliReturn.cs | 7 +-- OpenRA.Mods.RA/Air/Helicopter.cs | 51 ++++++++++--------- .../Missions/DesertShellmapScript.cs | 7 +-- OpenRA.Mods.RA/Missions/MissionUtils.cs | 8 +-- OpenRA.Mods.RA/Production.cs | 2 +- 6 files changed, 53 insertions(+), 47 deletions(-) diff --git a/OpenRA.Mods.RA/Air/HeliFly.cs b/OpenRA.Mods.RA/Air/HeliFly.cs index b0962801dd..041edd6256 100755 --- a/OpenRA.Mods.RA/Air/HeliFly.cs +++ b/OpenRA.Mods.RA/Air/HeliFly.cs @@ -16,15 +16,14 @@ namespace OpenRA.Mods.RA.Air { class HeliFly : Activity { - public readonly PPos Dest; - public HeliFly(PPos dest) - { - Dest = dest; - } + readonly WPos pos; + public HeliFly(WPos pos) { this.pos = pos; } + public HeliFly(CPos pos) { this.pos = pos.CenterPosition; } public override Activity Tick(Actor self) { - if (IsCanceled) return NextActivity; + if (IsCanceled) + return NextActivity; var info = self.Info.Traits.Get(); var aircraft = self.Trait(); @@ -35,23 +34,25 @@ namespace OpenRA.Mods.RA.Air return this; } - var dist = Dest - aircraft.PxPosition; - if (Math.Abs(dist.X) < 2 && Math.Abs(dist.Y) < 2) + // The next move would overshoot, so just set the final position + var dist = pos - self.CenterPosition; + var moveDist = aircraft.MovementSpeed * 7 * 1024 / (Game.CellSize * 32); + if (dist.HorizontalLengthSquared < moveDist*moveDist) { - aircraft.SubPxPosition = Dest.ToPSubPos(); + aircraft.SubPxPosition = PPos.FromWPos(pos).ToPSubPos(); return NextActivity; } var desiredFacing = Util.GetFacing(dist, aircraft.Facing); aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT); - aircraft.TickMove( PSubPos.PerPx * aircraft.MovementSpeed, desiredFacing ); + aircraft.TickMove(PSubPos.PerPx * aircraft.MovementSpeed, desiredFacing); return this; } - public override IEnumerable GetTargets( Actor self ) + public override IEnumerable GetTargets(Actor self) { - yield return Target.FromPos(Dest); + yield return Target.FromPos(pos); } } } diff --git a/OpenRA.Mods.RA/Air/HeliReturn.cs b/OpenRA.Mods.RA/Air/HeliReturn.cs index 6481786ca5..96969ccb6a 100755 --- a/OpenRA.Mods.RA/Air/HeliReturn.cs +++ b/OpenRA.Mods.RA/Air/HeliReturn.cs @@ -42,7 +42,7 @@ namespace OpenRA.Mods.RA.Air if (nearestHpad == null) return Util.SequenceActivities(new Turn(initialFacing), new HeliLand(true, 0), NextActivity); else - return Util.SequenceActivities(new HeliFly(Util.CenterOfCell(nearestHpad.Location))); + return Util.SequenceActivities(new HeliFly(nearestHpad.CenterPosition)); } var res = dest.TraitOrDefault(); @@ -51,10 +51,11 @@ namespace OpenRA.Mods.RA.Air heli.reservation = res.Reserve(dest, self, heli); var exit = dest.Info.Traits.WithInterface().FirstOrDefault(); - var offset = exit != null ? exit.SpawnOffsetVector : PVecInt.Zero; + var offset = (exit == null) ? WVec.Zero : + new WVec(exit.SpawnOffsetVector.X, exit.SpawnOffsetVector.Y, 0) * 1024 / Game.CellSize; return Util.SequenceActivities( - new HeliFly(dest.Trait().PxPosition + offset), + new HeliFly(dest.CenterPosition + offset), new Turn(initialFacing), new HeliLand(false, 0), new Rearm(self), diff --git a/OpenRA.Mods.RA/Air/Helicopter.cs b/OpenRA.Mods.RA/Air/Helicopter.cs index 103dfb971f..a5bc21bd51 100755 --- a/OpenRA.Mods.RA/Air/Helicopter.cs +++ b/OpenRA.Mods.RA/Air/Helicopter.cs @@ -17,7 +17,7 @@ namespace OpenRA.Mods.RA.Air { class HelicopterInfo : AircraftInfo { - public readonly int IdealSeparation = 40; + public readonly WRange IdealSeparation = new WRange(1706); public readonly bool LandWhenIdle = true; public readonly int MinimalLandAltitude = 0; @@ -48,7 +48,7 @@ namespace OpenRA.Mods.RA.Air self.SetTargetLine(Target.FromCell(target), Color.Green); self.CancelActivity(); - self.QueueActivity(new HeliFly(Util.CenterOfCell(target))); + self.QueueActivity(new HeliFly(target)); if (Info.LandWhenIdle) { @@ -71,12 +71,13 @@ namespace OpenRA.Mods.RA.Air reservation = res.Reserve(order.TargetActor, self, this); var exit = order.TargetActor.Info.Traits.WithInterface().FirstOrDefault(); - var offset = exit != null ? exit.SpawnOffsetVector : PVecInt.Zero; + var offset = (exit == null) ? WVec.Zero : + new WVec(exit.SpawnOffsetVector.X, exit.SpawnOffsetVector.Y, 0) * 1024 / Game.CellSize; self.SetTargetLine(Target.FromActor(order.TargetActor), Color.Green); self.CancelActivity(); - self.QueueActivity(new HeliFly(order.TargetActor.Trait().PxPosition + offset)); + self.QueueActivity(new HeliFly(order.TargetActor.CenterPosition + offset)); self.QueueActivity(new Turn(Info.InitialFacing)); self.QueueActivity(new HeliLand(false, Info.MinimalLandAltitude)); self.QueueActivity(new ResupplyAircraft()); @@ -110,38 +111,40 @@ namespace OpenRA.Mods.RA.Air ReserveSpawnBuilding(); } - /* repulsion only applies when we're flying */ - if (Altitude <= 0) return; + // Repulsion only applies when we're flying! + if (Altitude != Info.CruiseAltitude) + return; - var separation = new WRange(Info.IdealSeparation * 1024 / Game.CellSize); - var otherHelis = self.World.FindActorsInCircle(self.CenterPosition, separation) + var otherHelis = self.World.FindActorsInCircle(self.CenterPosition, Info.IdealSeparation) .Where(a => a.HasTrait()); var f = otherHelis .Select(h => GetRepulseForce(self, h)) - .Aggregate(PSubVec.Zero, (a, b) => a + b); + .Aggregate(WVec.Zero, (a, b) => a + b); - // FIXME(jsd): not sure which units GetFacing accepts; code is unclear to me. - int repulsionFacing = Util.GetFacing( f.ToInt2(), -1 ); - if( repulsionFacing != -1 ) + int repulsionFacing = Util.GetFacing(f, -1); + if (repulsionFacing != -1) TickMove(PSubPos.PerPx * MovementSpeed, repulsionFacing); } - // Returns a vector in subPx units - public PSubVec GetRepulseForce(Actor self, Actor h) + public WVec GetRepulseForce(Actor self, Actor other) { - if (self == h) - return PSubVec.Zero; - if( h.Trait().Altitude < Altitude ) - return PSubVec.Zero; - var d = self.CenterLocation - h.CenterLocation; + if (self == other || other.Trait().Altitude < Altitude) + return WVec.Zero; - if (d.Length > Info.IdealSeparation) - return PSubVec.Zero; + var d = self.CenterPosition - other.CenterPosition; + var dlSq = d.HorizontalLengthSquared; + if (dlSq > Info.IdealSeparation.Range*Info.IdealSeparation.Range) + return WVec.Zero; - if (d.LengthSquared < 1) - return Util.SubPxVector[self.World.SharedRandom.Next(255)]; - return (5 * d.ToPSubVec()) / d.LengthSquared; + if (dlSq < 1) + { + var yaw = self.World.SharedRandom.Next(0, 1023); + var rot = new WRot(WAngle.Zero, WAngle.Zero, new WAngle(yaw)); + return new WVec(1024, 0, 0).Rotate(rot); + } + + return (d * 1024 * 8) / (int)dlSq; } } } diff --git a/OpenRA.Mods.RA/Missions/DesertShellmapScript.cs b/OpenRA.Mods.RA/Missions/DesertShellmapScript.cs index 277eae9720..deef2f2ffe 100644 --- a/OpenRA.Mods.RA/Missions/DesertShellmapScript.cs +++ b/OpenRA.Mods.RA/Missions/DesertShellmapScript.cs @@ -217,14 +217,15 @@ namespace OpenRA.Mods.RA.Missions cargo.Load(chinook, world.CreateActor(false, ChinookCargo.Random(world.SharedRandom), allies, null, null)); var exit = lz.Info.Traits.WithInterface().FirstOrDefault(); - var offset = exit != null ? exit.SpawnOffsetVector : PVecInt.Zero; + var offset = (exit == null) ? WVec.Zero : + new WVec(exit.SpawnOffsetVector.X, exit.SpawnOffsetVector.Y, 0) * 1024 / Game.CellSize; - chinook.QueueActivity(new HeliFly(lz.CenterLocation + offset)); // no reservation of hpad but it's not needed + chinook.QueueActivity(new HeliFly(lz.CenterPosition + offset)); // no reservation of hpad but it's not needed chinook.QueueActivity(new Turn(0)); chinook.QueueActivity(new HeliLand(false, 0)); chinook.QueueActivity(new UnloadCargo(true)); chinook.QueueActivity(new Wait(150)); - chinook.QueueActivity(new HeliFly(Util.CenterOfCell(entry))); + chinook.QueueActivity(new HeliFly(entry)); chinook.QueueActivity(new RemoveSelf()); } diff --git a/OpenRA.Mods.RA/Missions/MissionUtils.cs b/OpenRA.Mods.RA/Missions/MissionUtils.cs index e5976235a5..cdb15634c3 100644 --- a/OpenRA.Mods.RA/Missions/MissionUtils.cs +++ b/OpenRA.Mods.RA/Missions/MissionUtils.cs @@ -45,12 +45,12 @@ namespace OpenRA.Mods.RA.Missions public static Actor ExtractUnitWithChinook(World world, Player owner, Actor unit, CPos entry, CPos lz, CPos exit) { var chinook = world.CreateActor("tran", new TypeDictionary { new OwnerInit(owner), new LocationInit(entry) }); - chinook.QueueActivity(new HeliFly(Util.CenterOfCell(lz))); + chinook.QueueActivity(new HeliFly(lz)); chinook.QueueActivity(new Turn(0)); chinook.QueueActivity(new HeliLand(true, 0)); chinook.QueueActivity(new WaitFor(() => chinook.Trait().Passengers.Contains(unit))); chinook.QueueActivity(new Wait(150)); - chinook.QueueActivity(new HeliFly(Util.CenterOfCell(exit))); + chinook.QueueActivity(new HeliFly(exit)); chinook.QueueActivity(new RemoveSelf()); return chinook; } @@ -60,13 +60,13 @@ namespace OpenRA.Mods.RA.Missions var unit = world.CreateActor(false, unitName, new TypeDictionary { new OwnerInit(owner) }); var chinook = world.CreateActor("tran", new TypeDictionary { new OwnerInit(owner), new LocationInit(entry) }); chinook.Trait().Load(chinook, unit); - chinook.QueueActivity(new HeliFly(Util.CenterOfCell(lz))); + chinook.QueueActivity(new HeliFly(lz)); chinook.QueueActivity(new Turn(0)); chinook.QueueActivity(new HeliLand(true, 0)); chinook.QueueActivity(new UnloadCargo(true)); chinook.QueueActivity(new CallFunc(() => afterUnload(unit))); chinook.QueueActivity(new Wait(150)); - chinook.QueueActivity(new HeliFly(Util.CenterOfCell(exit))); + chinook.QueueActivity(new HeliFly(exit)); chinook.QueueActivity(new RemoveSelf()); return Pair.New(chinook, unit); } diff --git a/OpenRA.Mods.RA/Production.cs b/OpenRA.Mods.RA/Production.cs index d8718b08f9..60782adb4a 100755 --- a/OpenRA.Mods.RA/Production.cs +++ b/OpenRA.Mods.RA/Production.cs @@ -104,7 +104,7 @@ namespace OpenRA.Mods.RA var helicopter = newUnit.TraitOrDefault(); if (helicopter != null) { - newUnit.QueueActivity(new HeliFly(Util.CenterOfCell(rp.rallyPoint))); + newUnit.QueueActivity(new HeliFly(rp.rallyPoint)); return rp.rallyPoint; } From 031c17ab9c600d6ee1c5bd4a30b65c82ed5a4fd4 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 20 Jul 2013 22:24:04 +1200 Subject: [PATCH 07/26] Helicopter style fixes. --- OpenRA.Mods.RA/Air/Helicopter.cs | 39 ++++++++++++++++---------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/OpenRA.Mods.RA/Air/Helicopter.cs b/OpenRA.Mods.RA/Air/Helicopter.cs index a5bc21bd51..7830abc8ac 100755 --- a/OpenRA.Mods.RA/Air/Helicopter.cs +++ b/OpenRA.Mods.RA/Air/Helicopter.cs @@ -21,17 +21,18 @@ namespace OpenRA.Mods.RA.Air public readonly bool LandWhenIdle = true; public readonly int MinimalLandAltitude = 0; - public override object Create( ActorInitializer init ) { return new Helicopter( init, this); } + public override object Create(ActorInitializer init) { return new Helicopter(init, this); } } class Helicopter : Aircraft, ITick, IResolveOrder { - HelicopterInfo Info; + HelicopterInfo info; bool firstTick = true; - public Helicopter( ActorInitializer init, HelicopterInfo info) : base( init, info ) + public Helicopter(ActorInitializer init, HelicopterInfo info) + : base(init, info) { - Info = info; + this.info = info; } public void ResolveOrder(Actor self, Order order) @@ -50,10 +51,10 @@ namespace OpenRA.Mods.RA.Air self.CancelActivity(); self.QueueActivity(new HeliFly(target)); - if (Info.LandWhenIdle) + if (info.LandWhenIdle) { - self.QueueActivity(new Turn(Info.InitialFacing)); - self.QueueActivity(new HeliLand(true, Info.MinimalLandAltitude)); + self.QueueActivity(new Turn(info.InitialFacing)); + self.QueueActivity(new HeliLand(true, info.MinimalLandAltitude)); } } @@ -78,8 +79,8 @@ namespace OpenRA.Mods.RA.Air self.CancelActivity(); self.QueueActivity(new HeliFly(order.TargetActor.CenterPosition + offset)); - self.QueueActivity(new Turn(Info.InitialFacing)); - self.QueueActivity(new HeliLand(false, Info.MinimalLandAltitude)); + self.QueueActivity(new Turn(info.InitialFacing)); + self.QueueActivity(new HeliLand(false, info.MinimalLandAltitude)); self.QueueActivity(new ResupplyAircraft()); } } @@ -87,17 +88,17 @@ namespace OpenRA.Mods.RA.Air if (order.OrderString == "ReturnToBase") { self.CancelActivity(); - self.QueueActivity( new HeliReturn() ); + self.QueueActivity(new HeliReturn()); } if (order.OrderString == "Stop") { self.CancelActivity(); - if (Info.LandWhenIdle) + if (info.LandWhenIdle) { - self.QueueActivity(new Turn(Info.InitialFacing)); - self.QueueActivity(new HeliLand(true, Info.MinimalLandAltitude)); + self.QueueActivity(new Turn(info.InitialFacing)); + self.QueueActivity(new HeliLand(true, info.MinimalLandAltitude)); } } } @@ -112,10 +113,10 @@ namespace OpenRA.Mods.RA.Air } // Repulsion only applies when we're flying! - if (Altitude != Info.CruiseAltitude) + if (Altitude != info.CruiseAltitude) return; - var otherHelis = self.World.FindActorsInCircle(self.CenterPosition, Info.IdealSeparation) + var otherHelis = self.World.FindActorsInCircle(self.CenterPosition, info.IdealSeparation) .Where(a => a.HasTrait()); var f = otherHelis @@ -133,18 +134,18 @@ namespace OpenRA.Mods.RA.Air return WVec.Zero; var d = self.CenterPosition - other.CenterPosition; - var dlSq = d.HorizontalLengthSquared; - if (dlSq > Info.IdealSeparation.Range*Info.IdealSeparation.Range) + var distSq = d.HorizontalLengthSquared; + if (distSq > info.IdealSeparation.Range * info.IdealSeparation.Range) return WVec.Zero; - if (dlSq < 1) + if (distSq < 1) { var yaw = self.World.SharedRandom.Next(0, 1023); var rot = new WRot(WAngle.Zero, WAngle.Zero, new WAngle(yaw)); return new WVec(1024, 0, 0).Rotate(rot); } - return (d * 1024 * 8) / (int)dlSq; + return (d * 1024 * 8) / (int)distSq; } } } From 8a988e5e02edbbd2a60adf4064e02b9a239fd6de Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 09:55:38 +1200 Subject: [PATCH 08/26] Clean up HarvesterDockSequence. --- .../Activities/HarvesterDockSequence.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/OpenRA.Mods.Cnc/Activities/HarvesterDockSequence.cs b/OpenRA.Mods.Cnc/Activities/HarvesterDockSequence.cs index 337438a7fc..b0a27be2cd 100644 --- a/OpenRA.Mods.Cnc/Activities/HarvesterDockSequence.cs +++ b/OpenRA.Mods.Cnc/Activities/HarvesterDockSequence.cs @@ -20,7 +20,8 @@ namespace OpenRA.Mods.Cnc { public class HarvesterDockSequence : Activity { - enum State { Wait, Turn, DragIn, Dock, Loop, Undock, DragOut }; + enum State { Wait, Turn, DragIn, Dock, Loop, Undock, DragOut } + static readonly WVec DockOffset = new WVec(-640, 341, 0); readonly Actor proc; readonly Harvester harv; @@ -34,8 +35,8 @@ namespace OpenRA.Mods.Cnc state = State.Turn; harv = self.Trait(); ru = self.Trait(); - startDock = self.Trait().PxPosition.ToWPos(0); - endDock = (proc.Trait().PxPosition + new PVecInt(-15,8)).ToWPos(0); + startDock = self.CenterPosition; + endDock = proc.CenterPosition + DockOffset; } public override Activity Tick(Actor self) @@ -51,7 +52,7 @@ namespace OpenRA.Mods.Cnc state = State.Dock; return Util.SequenceActivities(new Drag(startDock, endDock, 12), this); case State.Dock: - ru.PlayCustomAnimation(self, "dock", () => {ru.PlayCustomAnimRepeating(self, "dock-loop"); state = State.Loop;}); + ru.PlayCustomAnimation(self, "dock", () => { ru.PlayCustomAnimRepeating(self, "dock-loop"); state = State.Loop; }); state = State.Wait; return this; case State.Loop: @@ -65,6 +66,7 @@ namespace OpenRA.Mods.Cnc case State.DragOut: return Util.SequenceActivities(new Drag(endDock, startDock, 12), NextActivity); } + throw new InvalidOperationException("Invalid harvester dock state"); } @@ -73,10 +75,9 @@ namespace OpenRA.Mods.Cnc state = State.Undock; } - public override IEnumerable GetTargets( Actor self ) + public override IEnumerable GetTargets(Actor self) { yield return Target.FromActor(proc); } } -} - +} \ No newline at end of file From 200fde77b1b8435b70ad598b7210a62e903c87bf Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 10:01:39 +1200 Subject: [PATCH 09/26] Remove unnecessary IHasLocation checks in HackyAI. Existing checks for ITargetable / Building / etc make these redundant. --- OpenRA.Mods.RA/AI/HackyAI.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/OpenRA.Mods.RA/AI/HackyAI.cs b/OpenRA.Mods.RA/AI/HackyAI.cs index 394510ae82..430811ce58 100644 --- a/OpenRA.Mods.RA/AI/HackyAI.cs +++ b/OpenRA.Mods.RA/AI/HackyAI.cs @@ -1028,7 +1028,7 @@ namespace OpenRA.Mods.RA.AI { var allEnemyUnits = world.Actors .Where(unit => p.Stances[unit.Owner] == Stance.Enemy && !unit.HasTrait() && - unit.HasTrait() && unit.HasTrait()).ToList(); + unit.HasTrait()).ToList(); if (allEnemyUnits.Count > 0) return allEnemyUnits.ClosestTo(pos); @@ -1048,14 +1048,14 @@ namespace OpenRA.Mods.RA.AI List FindEnemyConstructionYards() { - var bases = world.Actors.Where(a => p.Stances[a.Owner] == Stance.Enemy && a.HasTrait() - && !a.Destroyed && a.HasTrait() && !a.HasTrait()).ToList(); + var bases = world.Actors.Where(a => p.Stances[a.Owner] == Stance.Enemy && !a.Destroyed + && a.HasTrait() && !a.HasTrait()).ToList(); return bases != null ? bases : new List(); } Actor FindEnemyBuildingClosestToPos(WPos pos) { - var closestBuilding = world.Actors.Where(a => p.Stances[a.Owner] == Stance.Enemy && a.HasTrait() + var closestBuilding = world.Actors.Where(a => p.Stances[a.Owner] == Stance.Enemy && !a.Destroyed && a.HasTrait()).ClosestTo(pos); return closestBuilding; } @@ -1424,12 +1424,12 @@ namespace OpenRA.Mods.RA.AI aggro[e.Attacker.Owner].Aggro += e.Damage; //protected harvesters or building - if (self.HasTrait() || self.HasTrait()) - if (e.Attacker.HasTrait() && (p.Stances[e.Attacker.Owner] == Stance.Enemy)) - { - defenseCenter = e.Attacker.Location; - ProtectOwn(e.Attacker); - } + if ((self.HasTrait() || self.HasTrait()) && + p.Stances[e.Attacker.Owner] == Stance.Enemy) + { + defenseCenter = e.Attacker.Location; + ProtectOwn(e.Attacker); + } } } } From ac3f63b59c143aff1e9a74ada2fec4ba9d8eff5f Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 10:03:48 +1200 Subject: [PATCH 10/26] Remove IHasLocation lookup from Target. --- OpenRA.Game/Traits/Target.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/OpenRA.Game/Traits/Target.cs b/OpenRA.Game/Traits/Target.cs index 39d0153123..6dd8031a0a 100644 --- a/OpenRA.Game/Traits/Target.cs +++ b/OpenRA.Game/Traits/Target.cs @@ -45,8 +45,7 @@ namespace OpenRA.Traits } public bool IsValid { get { return valid && (actor == null || (actor.IsInWorld && !actor.IsDead() && actor.Generation == generation)); } } - public PPos PxPosition { get { return IsActor ? actor.Trait().PxPosition : PPos.FromWPos(pos); } } - public PPos CenterLocation { get { return PxPosition; } } + public PPos CenterLocation { get { return IsActor ? actor.CenterLocation : PPos.FromWPos(pos); } } public Actor Actor { get { return IsActor ? actor : null; } } // TODO: This should return true even if the actor is destroyed From 36a45d1a3fd19ef893b6e9a0b98b1ba1fbad442e Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 10:08:48 +1200 Subject: [PATCH 11/26] Change Exit.SpawnOffsetVector to WVec. --- OpenRA.Mods.RA/Air/HeliReturn.cs | 3 +-- OpenRA.Mods.RA/Air/Helicopter.cs | 3 +-- OpenRA.Mods.RA/Missions/DesertShellmapScript.cs | 3 +-- OpenRA.Mods.RA/Production.cs | 10 ++++++---- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/OpenRA.Mods.RA/Air/HeliReturn.cs b/OpenRA.Mods.RA/Air/HeliReturn.cs index 96969ccb6a..b1638bcace 100755 --- a/OpenRA.Mods.RA/Air/HeliReturn.cs +++ b/OpenRA.Mods.RA/Air/HeliReturn.cs @@ -51,8 +51,7 @@ namespace OpenRA.Mods.RA.Air heli.reservation = res.Reserve(dest, self, heli); var exit = dest.Info.Traits.WithInterface().FirstOrDefault(); - var offset = (exit == null) ? WVec.Zero : - new WVec(exit.SpawnOffsetVector.X, exit.SpawnOffsetVector.Y, 0) * 1024 / Game.CellSize; + var offset = (exit != null) ? exit.SpawnOffsetVector : WVec.Zero; return Util.SequenceActivities( new HeliFly(dest.CenterPosition + offset), diff --git a/OpenRA.Mods.RA/Air/Helicopter.cs b/OpenRA.Mods.RA/Air/Helicopter.cs index 7830abc8ac..a0a8529355 100755 --- a/OpenRA.Mods.RA/Air/Helicopter.cs +++ b/OpenRA.Mods.RA/Air/Helicopter.cs @@ -72,8 +72,7 @@ namespace OpenRA.Mods.RA.Air reservation = res.Reserve(order.TargetActor, self, this); var exit = order.TargetActor.Info.Traits.WithInterface().FirstOrDefault(); - var offset = (exit == null) ? WVec.Zero : - new WVec(exit.SpawnOffsetVector.X, exit.SpawnOffsetVector.Y, 0) * 1024 / Game.CellSize; + var offset = (exit != null) ? exit.SpawnOffsetVector : WVec.Zero; self.SetTargetLine(Target.FromActor(order.TargetActor), Color.Green); diff --git a/OpenRA.Mods.RA/Missions/DesertShellmapScript.cs b/OpenRA.Mods.RA/Missions/DesertShellmapScript.cs index deef2f2ffe..ed185f1ed0 100644 --- a/OpenRA.Mods.RA/Missions/DesertShellmapScript.cs +++ b/OpenRA.Mods.RA/Missions/DesertShellmapScript.cs @@ -217,8 +217,7 @@ namespace OpenRA.Mods.RA.Missions cargo.Load(chinook, world.CreateActor(false, ChinookCargo.Random(world.SharedRandom), allies, null, null)); var exit = lz.Info.Traits.WithInterface().FirstOrDefault(); - var offset = (exit == null) ? WVec.Zero : - new WVec(exit.SpawnOffsetVector.X, exit.SpawnOffsetVector.Y, 0) * 1024 / Game.CellSize; + var offset = (exit != null) ? exit.SpawnOffsetVector : WVec.Zero; chinook.QueueActivity(new HeliFly(lz.CenterPosition + offset)); // no reservation of hpad but it's not needed chinook.QueueActivity(new Turn(0)); diff --git a/OpenRA.Mods.RA/Production.cs b/OpenRA.Mods.RA/Production.cs index 60782adb4a..3a516b6bb8 100755 --- a/OpenRA.Mods.RA/Production.cs +++ b/OpenRA.Mods.RA/Production.cs @@ -31,13 +31,15 @@ namespace OpenRA.Mods.RA public class ExitInfo : TraitInfo { public readonly int2 SpawnOffset = int2.Zero; // in px relative to CenterLocation - public readonly int2 ExitCell = int2.Zero; // in cells relative to TopLeft + public readonly int2 ExitCell = int2.Zero; // in cells relative to TopLeft public readonly int Facing = -1; - public PVecInt SpawnOffsetVector { get { return (PVecInt)SpawnOffset; } } + // TODO: Push this conversion into the yaml + public WVec SpawnOffsetVector { get { return new WVec(SpawnOffset.X, SpawnOffset.Y, 0) * 1024 / Game.CellSize; } } public CVec ExitCellVector { get { return (CVec)ExitCell; } } } - public class Exit {} + + public class Exit { } public class Production { @@ -50,7 +52,7 @@ namespace OpenRA.Mods.RA public void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo) { var exit = self.Location + exitinfo.ExitCellVector; - var spawn = (self.Trait().PxPosition + exitinfo.SpawnOffsetVector).ToWPos(0); + var spawn = self.CenterPosition + exitinfo.SpawnOffsetVector; var to = exit.CenterPosition; var fi = producee.Traits.Get(); From ecc119cb29e1af627cf471713319566e76195714 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 10:44:07 +1200 Subject: [PATCH 12/26] Combine IHasLocation -> IOccupySpace, IMove -> ITeleportable. --- OpenRA.Game/Actor.cs | 23 +++++-------------- OpenRA.Game/Traits/TraitsInterfaces.cs | 11 +++++---- OpenRA.Game/Traits/Waypoint.cs | 1 + OpenRA.Game/Traits/World/SpatialBins.cs | 2 +- OpenRA.Mods.Cnc/Missions/Gdi01Script.cs | 2 +- OpenRA.Mods.Cnc/Missions/Nod01Script.cs | 6 ++--- OpenRA.Mods.RA/AI/HackyAI.cs | 6 ++--- OpenRA.Mods.RA/Air/Aircraft.cs | 4 ++-- OpenRA.Mods.RA/Air/EjectOnDeath.cs | 2 +- OpenRA.Mods.RA/Armament.cs | 6 ++--- OpenRA.Mods.RA/Attack/AttackBase.cs | 6 ++--- OpenRA.Mods.RA/Attack/AttackLoyalty.cs | 3 +-- OpenRA.Mods.RA/Bridge.cs | 2 +- OpenRA.Mods.RA/Buildings/Building.cs | 1 + OpenRA.Mods.RA/Cargo.cs | 8 +++---- OpenRA.Mods.RA/CarpetBomb.cs | 2 +- OpenRA.Mods.RA/ChronoshiftDeploy.cs | 2 +- OpenRA.Mods.RA/Crate.cs | 3 ++- OpenRA.Mods.RA/Effects/Missile.cs | 4 ++-- OpenRA.Mods.RA/Husk.cs | 1 + OpenRA.Mods.RA/Mine.cs | 1 + OpenRA.Mods.RA/Minelayer.cs | 4 ++-- OpenRA.Mods.RA/Missions/Allies02Script.cs | 6 ++--- OpenRA.Mods.RA/Missions/MissionUtils.cs | 2 +- OpenRA.Mods.RA/Missions/Survival01Script.cs | 2 +- OpenRA.Mods.RA/Missions/Survival02Script.cs | 2 +- OpenRA.Mods.RA/Move/Mobile.cs | 2 +- .../Orders/SetChronoTankDestination.cs | 2 +- OpenRA.Mods.RA/Player/PlayerStatistics.cs | 2 +- OpenRA.Mods.RA/Render/WithRotor.cs | 2 +- OpenRA.Mods.RA/Render/WithShadow.cs | 6 ++--- 31 files changed, 61 insertions(+), 65 deletions(-) diff --git a/OpenRA.Game/Actor.cs b/OpenRA.Game/Actor.cs index a559931c26..e93c8cacca 100755 --- a/OpenRA.Game/Actor.cs +++ b/OpenRA.Game/Actor.cs @@ -26,8 +26,6 @@ namespace OpenRA public readonly uint ActorID; Lazy occupySpace; - IHasLocation HasLocation; - Lazy Move; Lazy Facing; public Cached Bounds; @@ -37,21 +35,13 @@ namespace OpenRA public CPos Location { get { return occupySpace.Value.TopLeft; } } - public PPos CenterLocation - { - get - { - if (HasLocation == null) - HasLocation = Trait(); - return HasLocation.PxPosition; - } - } + public PPos CenterLocation { get { return occupySpace.Value.PxPosition; } } public WPos CenterPosition { get { - var altitude = Move.Value != null ? Move.Value.Altitude : 0; + var altitude = occupySpace.Value != null ? occupySpace.Value.Altitude : 0; return CenterLocation.ToWPos(altitude); } } @@ -93,7 +83,6 @@ namespace OpenRA AddTrait(trait.Create(init)); } - Move = Lazy.New(() => TraitOrDefault()); Facing = Lazy.New(() => TraitOrDefault()); Size = Lazy.New(() => @@ -152,13 +141,13 @@ namespace OpenRA loc += new PVecInt(si.Bounds[2], si.Bounds[3]); } - var move = Move.Value; - if (move != null) + var ios = occupySpace.Value; + if (ios != null) { - loc -= new PVecInt(0, move.Altitude); + loc -= new PVecInt(0, ios.Altitude); if (useAltitude) - size = new PVecInt(size.X, size.Y + move.Altitude); + size = new PVecInt(size.X, size.Y + ios.Altitude); } return new Rectangle(loc.X, loc.Y, size.X, size.Y); diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 56ec0c1f01..4e1457d89d 100755 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -96,12 +96,16 @@ namespace OpenRA.Traits public interface IVisibilityModifier { bool IsVisible(Actor self, Player byPlayer); } public interface IRadarColorModifier { Color RadarColorOverride(Actor self); } - public interface IHasLocation { PPos PxPosition { get; } } - public interface IOccupySpace : IHasLocation + public interface IOccupySpace { + PPos PxPosition { get; } CPos TopLeft { get; } IEnumerable> OccupiedCells(); + + // TODO: We shouldn't expose the setter here + // This will be going away soon, so isn't a big deal + int Altitude { get; set; } } public static class IOccupySpaceExts @@ -134,7 +138,7 @@ namespace OpenRA.Traits public interface ITags { IEnumerable GetTags(); } public interface ISelectionBar { float GetValue(); Color GetColor(); } - public interface ITeleportable : IHasLocation /* crap name! */ + public interface ITeleportable : IOccupySpace { bool CanEnterCell(CPos location); void SetPosition(Actor self, CPos cell); @@ -142,7 +146,6 @@ namespace OpenRA.Traits void AdjustPxPosition(Actor self, PPos px); /* works like SetPxPosition, but visual only */ } - public interface IMove : ITeleportable { int Altitude { get; set; } } public interface INotifyBlockingMove { void OnNotifyBlockingMove(Actor self, Actor blocking); } public interface IFacing diff --git a/OpenRA.Game/Traits/Waypoint.cs b/OpenRA.Game/Traits/Waypoint.cs index 96b29fb8f5..d60b8079cd 100644 --- a/OpenRA.Game/Traits/Waypoint.cs +++ b/OpenRA.Game/Traits/Waypoint.cs @@ -31,5 +31,6 @@ namespace OpenRA.Traits public IEnumerable> OccupiedCells() { yield break; } public PPos PxPosition { get { return Util.CenterOfCell(location); } } + public int Altitude { get { return 0; } set { } } } } diff --git a/OpenRA.Game/Traits/World/SpatialBins.cs b/OpenRA.Game/Traits/World/SpatialBins.cs index 563311cf6e..a6b17a508c 100644 --- a/OpenRA.Game/Traits/World/SpatialBins.cs +++ b/OpenRA.Game/Traits/World/SpatialBins.cs @@ -45,7 +45,7 @@ namespace OpenRA.Traits for (var i = 0; i <= bins.GetUpperBound(0); i++) bins[i, j].Clear(); - foreach (var a in self.World.ActorsWithTrait()) + foreach (var a in self.World.ActorsWithTrait()) { var bounds = a.Actor.ExtendedBounds.Value; diff --git a/OpenRA.Mods.Cnc/Missions/Gdi01Script.cs b/OpenRA.Mods.Cnc/Missions/Gdi01Script.cs index 35b81831e8..4b1e8276e6 100644 --- a/OpenRA.Mods.Cnc/Missions/Gdi01Script.cs +++ b/OpenRA.Mods.Cnc/Missions/Gdi01Script.cs @@ -205,7 +205,7 @@ namespace OpenRA.Mods.Cnc.Missions { if (b.Destroyed) return; w2.Add(b); - b.TraitsImplementing().FirstOrDefault().SetPosition(b, a.Location); + b.TraitsImplementing().FirstOrDefault().SetPosition(b, a.Location); b.QueueActivity(mobile.MoveTo(unload, 2)); }); } diff --git a/OpenRA.Mods.Cnc/Missions/Nod01Script.cs b/OpenRA.Mods.Cnc/Missions/Nod01Script.cs index 1f23828606..d0f8c6d517 100644 --- a/OpenRA.Mods.Cnc/Missions/Nod01Script.cs +++ b/OpenRA.Mods.Cnc/Missions/Nod01Script.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2012 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -135,7 +135,7 @@ namespace OpenRA.Mods.Cnc.Missions IEnumerable UnitsNearActor(Actor actor, int range) { return world.FindActorsInCircle(actor.CenterPosition, WRange.FromCells(range)) - .Where(a => a.IsInWorld && a != world.WorldActor && !a.Destroyed && a.HasTrait() && !a.Owner.NonCombatant); + .Where(a => a.IsInWorld && a != world.WorldActor && !a.Destroyed && a.HasTrait() && !a.Owner.NonCombatant); } void NODReinforceNthA() @@ -198,4 +198,4 @@ namespace OpenRA.Mods.Cnc.Missions Media.PlayFMVFullscreen(w, "nod1.vqa", afterFMV))); } } -} +} diff --git a/OpenRA.Mods.RA/AI/HackyAI.cs b/OpenRA.Mods.RA/AI/HackyAI.cs index 430811ce58..f759199a26 100644 --- a/OpenRA.Mods.RA/AI/HackyAI.cs +++ b/OpenRA.Mods.RA/AI/HackyAI.cs @@ -763,7 +763,7 @@ namespace OpenRA.Mods.RA.AI if (!buildableThings.Any()) return null; var myUnits = p.World - .ActorsWithTrait() + .ActorsWithTrait() .Where(a => a.Actor.Owner == p) .Select(a => a.Actor.Info.Name).ToArray(); @@ -783,7 +783,7 @@ namespace OpenRA.Mods.RA.AI int CountUnits(string unit, Player owner) { - return world.ActorsWithTrait().Where(a => a.Actor.Owner == owner && a.Actor.Info.Name == unit).Count(); + return world.ActorsWithTrait().Where(a => a.Actor.Owner == owner && a.Actor.Info.Name == unit).Count(); } int? CountBuildingByCommonName(string commonName, Player owner) @@ -1145,7 +1145,7 @@ namespace OpenRA.Mods.RA.AI void FindNewUnits(Actor self) { - var newUnits = self.World.ActorsWithTrait() + var newUnits = self.World.ActorsWithTrait() .Where(a => a.Actor.Owner == p && !a.Actor.HasTrait() && !activeUnits.Contains(a.Actor)) .Select(a => a.Actor).ToArray(); diff --git a/OpenRA.Mods.RA/Air/Aircraft.cs b/OpenRA.Mods.RA/Air/Aircraft.cs index 7c8f0f8feb..f105538e3c 100755 --- a/OpenRA.Mods.RA/Air/Aircraft.cs +++ b/OpenRA.Mods.RA/Air/Aircraft.cs @@ -36,7 +36,7 @@ namespace OpenRA.Mods.RA.Air public int GetInitialFacing() { return InitialFacing; } } - public class Aircraft : IMove, IFacing, IOccupySpace, ISync, INotifyKilled, IIssueOrder, IOrderVoice + public class Aircraft : IFacing, ITeleportable, ISync, INotifyKilled, IIssueOrder, IOrderVoice { public IDisposable reservation; @@ -77,7 +77,7 @@ namespace OpenRA.Mods.RA.Air public Actor GetActorBelow() { - if (self.Trait().Altitude != 0) + if (self.Trait().Altitude != 0) return null; // not on the ground. return self.World.FindActorsInBox(self.CenterPosition, self.CenterPosition) diff --git a/OpenRA.Mods.RA/Air/EjectOnDeath.cs b/OpenRA.Mods.RA/Air/EjectOnDeath.cs index 74cf19de12..879aebc631 100644 --- a/OpenRA.Mods.RA/Air/EjectOnDeath.cs +++ b/OpenRA.Mods.RA/Air/EjectOnDeath.cs @@ -30,7 +30,7 @@ namespace OpenRA.Mods.RA var pilot = self.World.CreateActor(false, info.PilotActor.ToLowerInvariant(), new TypeDictionary { new OwnerInit(self.Owner) }); var r = self.World.SharedRandom.Next(1, 100); - var aircraft = self.Trait(); + var aircraft = self.Trait(); if (IsSuitableCell(pilot, self.Location) && r > 100 - info.SuccessRate && aircraft.Altitude > 10 && self.Owner.WinState != WinState.Lost) diff --git a/OpenRA.Mods.RA/Armament.cs b/OpenRA.Mods.RA/Armament.cs index e1b09e3e79..5bee9aaa0a 100755 --- a/OpenRA.Mods.RA/Armament.cs +++ b/OpenRA.Mods.RA/Armament.cs @@ -99,7 +99,7 @@ namespace OpenRA.Mods.RA // Note: facing is only used by the legacy positioning code // The world coordinate model uses Actor.Orientation - public void CheckFire(Actor self, AttackBase attack, IMove move, IFacing facing, Target target) + public void CheckFire(Actor self, AttackBase attack, IFacing facing, Target target) { if (FireDelay > 0) return; @@ -120,7 +120,7 @@ namespace OpenRA.Mods.RA return; var barrel = Barrels[Burst % Barrels.Length]; - var destMove = target.IsActor ? target.Actor.TraitOrDefault() : null; + var destios = target.IsActor ? target.Actor.TraitOrDefault() : null; var muzzlePosition = self.CenterPosition + MuzzleOffset(self, barrel); var legacyMuzzlePosition = PPos.FromWPos(muzzlePosition); @@ -136,7 +136,7 @@ namespace OpenRA.Mods.RA srcAltitude = legacyMuzzleAltitude, dest = target.CenterLocation, - destAltitude = destMove != null ? destMove.Altitude : 0, + destAltitude = destios != null ? destios.Altitude : 0, facing = legacyFacing, diff --git a/OpenRA.Mods.RA/Attack/AttackBase.cs b/OpenRA.Mods.RA/Attack/AttackBase.cs index c8263c6dec..9321698c67 100644 --- a/OpenRA.Mods.RA/Attack/AttackBase.cs +++ b/OpenRA.Mods.RA/Attack/AttackBase.cs @@ -89,12 +89,12 @@ namespace OpenRA.Mods.RA public virtual void DoAttack(Actor self, Target target) { - if( !CanAttack( self, target ) ) return; + if (!CanAttack(self, target)) + return; - var move = self.TraitOrDefault(); var facing = self.TraitOrDefault(); foreach (var a in Armaments) - a.CheckFire(self, this, move, facing, target); + a.CheckFire(self, this, facing, target); } public IEnumerable Orders diff --git a/OpenRA.Mods.RA/Attack/AttackLoyalty.cs b/OpenRA.Mods.RA/Attack/AttackLoyalty.cs index ceb8caab0f..e7f7d64c83 100644 --- a/OpenRA.Mods.RA/Attack/AttackLoyalty.cs +++ b/OpenRA.Mods.RA/Attack/AttackLoyalty.cs @@ -38,10 +38,9 @@ namespace OpenRA.Mods.RA if (!target.IsInRange(self.CenterPosition, range)) return; - var move = self.TraitOrDefault(); var facing = self.TraitOrDefault(); foreach (var a in Armaments) - a.CheckFire(self, this, move, facing, target); + a.CheckFire(self, this, facing, target); if (target.Actor != null) target.Actor.ChangeOwner(self.Owner); diff --git a/OpenRA.Mods.RA/Bridge.cs b/OpenRA.Mods.RA/Bridge.cs index ea51b80d62..3eb7dc9cac 100644 --- a/OpenRA.Mods.RA/Bridge.cs +++ b/OpenRA.Mods.RA/Bridge.cs @@ -158,7 +158,7 @@ namespace OpenRA.Mods.RA { foreach (var c in TileSprites[currentTemplate].Keys) foreach (var a in self.World.ActorMap.GetUnitsAt(c)) - if (a.HasTrait() && !a.Trait().CanEnterCell(c)) + if (a.HasTrait() && !a.Trait().CanEnterCell(c)) a.Kill(self); } diff --git a/OpenRA.Mods.RA/Buildings/Building.cs b/OpenRA.Mods.RA/Buildings/Building.cs index 057523555e..3beb58e7f6 100755 --- a/OpenRA.Mods.RA/Buildings/Building.cs +++ b/OpenRA.Mods.RA/Buildings/Building.cs @@ -111,6 +111,7 @@ namespace OpenRA.Mods.RA.Buildings public CPos TopLeft { get { return topLeft; } } public PPos PxPosition { get { return pxPosition; } } + public int Altitude { get { return 0; } set { } } public IEnumerable ProvidesPrerequisites { get { yield return self.Info.Name; } } diff --git a/OpenRA.Mods.RA/Cargo.cs b/OpenRA.Mods.RA/Cargo.cs index 4223a6c57d..3be939620f 100644 --- a/OpenRA.Mods.RA/Cargo.cs +++ b/OpenRA.Mods.RA/Cargo.cs @@ -92,8 +92,8 @@ namespace OpenRA.Mods.RA return false; // Cannot unload mid-air - var move = self.TraitOrDefault(); - if (move != null && move.Altitude > info.minimalUnloadAltitude) + var ios = self.TraitOrDefault(); + if (ios != null && ios.Altitude > info.minimalUnloadAltitude) return false; // TODO: Check if there is a free tile to unload to @@ -106,8 +106,8 @@ namespace OpenRA.Mods.RA return false; // Cannot load mid-air - var move = self.TraitOrDefault(); - return move == null || move.Altitude == info.minimalUnloadAltitude; + var ios = self.TraitOrDefault(); + return ios == null || ios.Altitude == info.minimalUnloadAltitude; } public string CursorForOrder(Actor self, Order order) diff --git a/OpenRA.Mods.RA/CarpetBomb.cs b/OpenRA.Mods.RA/CarpetBomb.cs index 80148646a6..cfdcb607f8 100644 --- a/OpenRA.Mods.RA/CarpetBomb.cs +++ b/OpenRA.Mods.RA/CarpetBomb.cs @@ -58,7 +58,7 @@ namespace OpenRA.Mods.RA var args = new ProjectileArgs { - srcAltitude = self.Trait().Altitude, + srcAltitude = self.Trait().Altitude, destAltitude = 0, src = self.CenterLocation, dest = self.CenterLocation, diff --git a/OpenRA.Mods.RA/ChronoshiftDeploy.cs b/OpenRA.Mods.RA/ChronoshiftDeploy.cs index 36fc932535..dc96a6b006 100644 --- a/OpenRA.Mods.RA/ChronoshiftDeploy.cs +++ b/OpenRA.Mods.RA/ChronoshiftDeploy.cs @@ -94,7 +94,7 @@ namespace OpenRA.Mods.RA public bool CanJumpTo(CPos xy, bool ignoreVis) { - var movement = self.TraitOrDefault(); + var movement = self.TraitOrDefault(); if (chargeTick <= 0 // Can jump && (self.Location - xy).Length <= Info.JumpDistance // Within jump range diff --git a/OpenRA.Mods.RA/Crate.cs b/OpenRA.Mods.RA/Crate.cs index e1a2c87041..8acafa496c 100644 --- a/OpenRA.Mods.RA/Crate.cs +++ b/OpenRA.Mods.RA/Crate.cs @@ -24,7 +24,7 @@ namespace OpenRA.Mods.RA } // ITeleportable is required for paradrop - class Crate : ITick, IOccupySpace, ITeleportable, ICrushable, ISync, INotifyParachuteLanded + class Crate : ITick, ITeleportable, ICrushable, ISync, INotifyParachuteLanded { readonly Actor self; [Sync] int ticks; @@ -86,6 +86,7 @@ namespace OpenRA.Mods.RA public IEnumerable> OccupiedCells() { yield return Pair.New( Location, SubCell.FullCell); } public PPos PxPosition { get; private set; } + public int Altitude { get { return 0; } set { } } public void SetPxPosition(Actor self, PPos px) { diff --git a/OpenRA.Mods.RA/Effects/Missile.cs b/OpenRA.Mods.RA/Effects/Missile.cs index 6b3aea3198..1c8297e1ed 100755 --- a/OpenRA.Mods.RA/Effects/Missile.cs +++ b/OpenRA.Mods.RA/Effects/Missile.cs @@ -98,8 +98,8 @@ namespace OpenRA.Mods.RA.Effects var dist = Args.target.CenterLocation + offset - PxPosition; var targetAltitude = 0; - if (Args.target.IsValid && Args.target.IsActor && Args.target.Actor.HasTrait()) - targetAltitude = Args.target.Actor.Trait().Altitude; + if (Args.target.IsValid && Args.target.IsActor && Args.target.Actor.HasTrait()) + targetAltitude = Args.target.Actor.Trait().Altitude; var jammed = Info.Jammable && world.ActorsWithTrait().Any(tp => (tp.Actor.CenterLocation - PxPosition).ToCVec().Length <= tp.Trait.Range diff --git a/OpenRA.Mods.RA/Husk.cs b/OpenRA.Mods.RA/Husk.cs index 7c8a03c701..9da6ce0153 100644 --- a/OpenRA.Mods.RA/Husk.cs +++ b/OpenRA.Mods.RA/Husk.cs @@ -27,6 +27,7 @@ namespace OpenRA.Mods.RA [Sync] CPos location; [Sync] public PPos PxPosition { get; set; } + public int Altitude { get { return 0; } set { } } [Sync] public int Facing { get; set; } public int ROT { get { return 0; } } diff --git a/OpenRA.Mods.RA/Mine.cs b/OpenRA.Mods.RA/Mine.cs index 8d57909240..c2589b877e 100644 --- a/OpenRA.Mods.RA/Mine.cs +++ b/OpenRA.Mods.RA/Mine.cs @@ -62,6 +62,7 @@ namespace OpenRA.Mods.RA public IEnumerable> OccupiedCells() { yield return Pair.New(TopLeft, SubCell.FullCell); } public PPos PxPosition { get { return Util.CenterOfCell( location ); } } + public int Altitude { get { return 0; } set { } } } /* tag trait for stuff that shouldnt trigger mines */ diff --git a/OpenRA.Mods.RA/Minelayer.cs b/OpenRA.Mods.RA/Minelayer.cs index 6d638a0e0e..ddd6de89f2 100644 --- a/OpenRA.Mods.RA/Minelayer.cs +++ b/OpenRA.Mods.RA/Minelayer.cs @@ -60,7 +60,7 @@ namespace OpenRA.Mods.RA if (order.OrderString == "PlaceMinefield") { - var movement = self.Trait(); + var movement = self.Trait(); minefield = GetMinefieldCells(minefieldStart, order.TargetLocation, self.Info.Traits.Get().MinefieldDepth) @@ -130,7 +130,7 @@ namespace OpenRA.Mods.RA if (!minelayer.IsInWorld) return; - var movement = minelayer.Trait(); + var movement = minelayer.Trait(); var minefield = GetMinefieldCells(minefieldStart, lastMousePos, minelayer.Info.Traits.Get().MinefieldDepth) .Where(p => movement.CanEnterCell(p)).ToArray(); diff --git a/OpenRA.Mods.RA/Missions/Allies02Script.cs b/OpenRA.Mods.RA/Missions/Allies02Script.cs index 9703e9a999..89bebdd3b1 100644 --- a/OpenRA.Mods.RA/Missions/Allies02Script.cs +++ b/OpenRA.Mods.RA/Missions/Allies02Script.cs @@ -170,7 +170,7 @@ namespace OpenRA.Mods.RA.Missions if (yak == null || (yak != null && !yak.IsDead() && (yak.GetCurrentActivity() is FlyCircle || yak.IsIdle))) { var alliedUnitsNearYakPoint = world.FindAliveCombatantActorsInCircle(yakAttackPoint.CenterPosition, WRange.FromCells(10)) - .Where(a => a.Owner != soviets && a.HasTrait() && a != tanya && a != einstein && a != engineer); + .Where(a => a.Owner != soviets && a.HasTrait() && a != tanya && a != einstein && a != engineer); if (alliedUnitsNearYakPoint.Any()) YakStrafe(alliedUnitsNearYakPoint); } @@ -384,7 +384,7 @@ namespace OpenRA.Mods.RA.Missions bool AlliesNearTown() { return world.FindAliveCombatantActorsInCircle(townPoint.CenterPosition, WRange.FromCells(AlliedTownTransferRange)) - .Any(a => a.Owner == allies1 && a.HasTrait()); + .Any(a => a.Owner == allies1 && a.HasTrait()); } void TransferTownUnitsToAllies() @@ -399,7 +399,7 @@ namespace OpenRA.Mods.RA.Missions var sovietAttackUnits = world.FindAliveCombatantActorsInCircle(sovietTownAttackPoint1.CenterPosition, WRange.FromCells(SovietTownAttackGroupRange)) .Union(world.FindAliveCombatantActorsInCircle(sovietTownAttackPoint2.CenterPosition, WRange.FromCells(SovietTownAttackGroupRange))) .Union(world.FindAliveCombatantActorsInCircle(townPoint.CenterPosition, WRange.FromCells(AlliedTownTransferRange))) - .Where(a => a.HasTrait() && a.Owner == soviets); + .Where(a => a.HasTrait() && a.Owner == soviets); foreach (var unit in sovietAttackUnits) unit.QueueActivity(new AttackMove.AttackMoveActivity(unit, new Move.Move(townPoint.Location, SovietTownMoveNearEnough))); diff --git a/OpenRA.Mods.RA/Missions/MissionUtils.cs b/OpenRA.Mods.RA/Missions/MissionUtils.cs index cdb15634c3..8e1fff1360 100644 --- a/OpenRA.Mods.RA/Missions/MissionUtils.cs +++ b/OpenRA.Mods.RA/Missions/MissionUtils.cs @@ -106,7 +106,7 @@ namespace OpenRA.Mods.RA.Missions public static bool AreaSecuredWithUnits(World world, Player player, WPos location, WRange range) { - var units = world.FindAliveCombatantActorsInCircle(location, range).Where(a => a.HasTrait()); + var units = world.FindAliveCombatantActorsInCircle(location, range).Where(a => a.HasTrait()); return units.Any() && units.All(a => a.Owner == player); } diff --git a/OpenRA.Mods.RA/Missions/Survival01Script.cs b/OpenRA.Mods.RA/Missions/Survival01Script.cs index 9ca1de8e66..4f93229a60 100644 --- a/OpenRA.Mods.RA/Missions/Survival01Script.cs +++ b/OpenRA.Mods.RA/Missions/Survival01Script.cs @@ -185,7 +185,7 @@ namespace OpenRA.Mods.RA.Missions var units = world.CreateActor((sovietInfantry).Random(world.SharedRandom), new TypeDictionary { new LocationInit(sovietinfantryentry1.Location), new OwnerInit(soviets) }); units.QueueActivity(new Move.Move(sovietinfantryrally1.Location, 3)); var unitsincircle = world.FindAliveCombatantActorsInCircle(sovietinfantryrally1.CenterPosition, WRange.FromCells(10)) - .Where(a => a.Owner == soviets && a.IsIdle && a.HasTrait()); + .Where(a => a.Owner == soviets && a.IsIdle && a.HasTrait()); if (unitsincircle.Count() >= sovietInfantryGroupSize) { foreach (var scatteredunits in unitsincircle) diff --git a/OpenRA.Mods.RA/Missions/Survival02Script.cs b/OpenRA.Mods.RA/Missions/Survival02Script.cs index 7d2b69828d..9e4da5604e 100644 --- a/OpenRA.Mods.RA/Missions/Survival02Script.cs +++ b/OpenRA.Mods.RA/Missions/Survival02Script.cs @@ -299,7 +299,7 @@ namespace OpenRA.Mods.RA.Missions void ManageSovietUnits() { var units = world.FindAliveCombatantActorsInCircle(sovietrally.CenterPosition, WRange.FromCells(3)) - .Where(u => u.IsIdle && u.HasTrait() && u.HasTrait() && u.Owner == soviets); + .Where(u => u.IsIdle && u.HasTrait() && u.HasTrait() && u.Owner == soviets); if (units.Count() >= sovietAttackGroupSize) { foreach (var unit in units) diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index f7679b096c..22f285c9cf 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -145,7 +145,7 @@ namespace OpenRA.Mods.RA.Move public int GetInitialFacing() { return InitialFacing; } } - public class Mobile : IIssueOrder, IResolveOrder, IOrderVoice, IOccupySpace, IMove, IFacing, ISync + public class Mobile : IIssueOrder, IResolveOrder, IOrderVoice, ITeleportable, IFacing, ISync { public readonly Actor self; public readonly MobileInfo Info; diff --git a/OpenRA.Mods.RA/Orders/SetChronoTankDestination.cs b/OpenRA.Mods.RA/Orders/SetChronoTankDestination.cs index 20c8ee01cf..5b31bc408b 100644 --- a/OpenRA.Mods.RA/Orders/SetChronoTankDestination.cs +++ b/OpenRA.Mods.RA/Orders/SetChronoTankDestination.cs @@ -50,7 +50,7 @@ namespace OpenRA.Mods.RA.Orders if (!world.LocalPlayer.Shroud.IsExplored(xy)) return "move-blocked"; - var movement = self.TraitOrDefault(); + var movement = self.TraitOrDefault(); return (movement.CanEnterCell(xy)) ? "chrono-target" : "move-blocked"; } } diff --git a/OpenRA.Mods.RA/Player/PlayerStatistics.cs b/OpenRA.Mods.RA/Player/PlayerStatistics.cs index 5091501494..c6fdaaef0f 100644 --- a/OpenRA.Mods.RA/Player/PlayerStatistics.cs +++ b/OpenRA.Mods.RA/Player/PlayerStatistics.cs @@ -112,7 +112,7 @@ namespace OpenRA.Mods.RA attackerStats.BuildingsKilled++; defenderStats.BuildingsDead++; } - else if (self.HasTrait()) + else if (self.HasTrait()) { attackerStats.UnitsKilled++; defenderStats.UnitsDead++; diff --git a/OpenRA.Mods.RA/Render/WithRotor.cs b/OpenRA.Mods.RA/Render/WithRotor.cs index 2da92ea359..5135be0fd4 100755 --- a/OpenRA.Mods.RA/Render/WithRotor.cs +++ b/OpenRA.Mods.RA/Render/WithRotor.cs @@ -40,7 +40,7 @@ namespace OpenRA.Mods.RA.Render public void Tick(Actor self) { - var isFlying = self.Trait().Altitude > 0 && !self.IsDead(); + var isFlying = self.Trait().Altitude > 0 && !self.IsDead(); if (isFlying ^ (rotorAnim.CurrentSequence.Name != "rotor")) return; diff --git a/OpenRA.Mods.RA/Render/WithShadow.cs b/OpenRA.Mods.RA/Render/WithShadow.cs index a6e265921f..685f8fad8a 100644 --- a/OpenRA.Mods.RA/Render/WithShadow.cs +++ b/OpenRA.Mods.RA/Render/WithShadow.cs @@ -24,16 +24,16 @@ namespace OpenRA.Mods.RA.Render { public IEnumerable ModifyRender(Actor self, WorldRenderer wr, IEnumerable r) { - var move = self.Trait(); + var ios = self.Trait(); /* rude hack */ - var visualOffset = ((move is Helicopter || move is Mobile) && move.Altitude > 0) + var visualOffset = ((ios is Helicopter || ios is Mobile) && ios.Altitude > 0) ? (int)Math.Abs((self.ActorID + Game.LocalTick) / 5 % 4 - 1) - 1 : 0; var shadowSprites = r.Select(a => a.WithPalette(wr.Palette("shadow")) .WithPos(a.Pos - new WVec(0, 0, a.Pos.Z)).WithZOffset(a.ZOffset + a.Pos.Z)); - var flyingSprites = (move.Altitude <= 0) ? r : + var flyingSprites = (ios.Altitude <= 0) ? r : r.Select(a => a.WithPos(a.Pos - new WVec(0,0,43*visualOffset))); return shadowSprites.Concat(flyingSprites); From ac4b07bf7b67a15614e34e55043b29a7f393f931 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 10:45:23 +1200 Subject: [PATCH 13/26] Add missing SetChronoTankDestination.cs to project. --- OpenRA.Mods.RA/OpenRA.Mods.RA.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 7073279bc8..b45286a48b 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -460,6 +460,7 @@ + From 048bed0a5efb6852cc7011c244f4a322ae094ba5 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 11:05:08 +1200 Subject: [PATCH 14/26] Rename ITeleportable -> IPositionable. --- OpenRA.Game/Traits/TraitsInterfaces.cs | 2 +- OpenRA.Mods.Cnc/Missions/Gdi01Script.cs | 2 +- OpenRA.Mods.Cnc/Missions/Nod01Script.cs | 3 ++- OpenRA.Mods.RA/AI/HackyAI.cs | 6 +++--- OpenRA.Mods.RA/Activities/Teleport.cs | 6 +++--- OpenRA.Mods.RA/Air/Aircraft.cs | 2 +- OpenRA.Mods.RA/Air/EjectOnDeath.cs | 6 +++--- OpenRA.Mods.RA/Bridge.cs | 2 +- OpenRA.Mods.RA/ChronoshiftDeploy.cs | 2 +- OpenRA.Mods.RA/Chronoshiftable.cs | 4 ++-- OpenRA.Mods.RA/Crate.cs | 2 +- OpenRA.Mods.RA/Effects/Parachute.cs | 2 +- OpenRA.Mods.RA/Minelayer.cs | 6 +++--- OpenRA.Mods.RA/Missions/Allies02Script.cs | 6 +++--- OpenRA.Mods.RA/Missions/MissionUtils.cs | 2 +- OpenRA.Mods.RA/Missions/Survival01Script.cs | 4 ++-- OpenRA.Mods.RA/Missions/Survival02Script.cs | 4 ++-- OpenRA.Mods.RA/Move/Mobile.cs | 2 +- OpenRA.Mods.RA/Orders/SetChronoTankDestination.cs | 4 ++-- OpenRA.Mods.RA/ParaDrop.cs | 4 ++-- OpenRA.Mods.RA/Player/PlayerStatistics.cs | 2 +- OpenRA.Mods.RA/Production.cs | 2 +- 22 files changed, 38 insertions(+), 37 deletions(-) diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 4e1457d89d..4d37136723 100755 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -138,7 +138,7 @@ namespace OpenRA.Traits public interface ITags { IEnumerable GetTags(); } public interface ISelectionBar { float GetValue(); Color GetColor(); } - public interface ITeleportable : IOccupySpace + public interface IPositionable : IOccupySpace { bool CanEnterCell(CPos location); void SetPosition(Actor self, CPos cell); diff --git a/OpenRA.Mods.Cnc/Missions/Gdi01Script.cs b/OpenRA.Mods.Cnc/Missions/Gdi01Script.cs index 4b1e8276e6..97fc4f0c66 100644 --- a/OpenRA.Mods.Cnc/Missions/Gdi01Script.cs +++ b/OpenRA.Mods.Cnc/Missions/Gdi01Script.cs @@ -205,7 +205,7 @@ namespace OpenRA.Mods.Cnc.Missions { if (b.Destroyed) return; w2.Add(b); - b.TraitsImplementing().FirstOrDefault().SetPosition(b, a.Location); + b.TraitsImplementing().FirstOrDefault().SetPosition(b, a.Location); b.QueueActivity(mobile.MoveTo(unload, 2)); }); } diff --git a/OpenRA.Mods.Cnc/Missions/Nod01Script.cs b/OpenRA.Mods.Cnc/Missions/Nod01Script.cs index d0f8c6d517..1eb7a1c667 100644 --- a/OpenRA.Mods.Cnc/Missions/Nod01Script.cs +++ b/OpenRA.Mods.Cnc/Missions/Nod01Script.cs @@ -5,6 +5,7 @@ * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, * see COPYING. +<<<<<<< HEAD */ #endregion @@ -135,7 +136,7 @@ namespace OpenRA.Mods.Cnc.Missions IEnumerable UnitsNearActor(Actor actor, int range) { return world.FindActorsInCircle(actor.CenterPosition, WRange.FromCells(range)) - .Where(a => a.IsInWorld && a != world.WorldActor && !a.Destroyed && a.HasTrait() && !a.Owner.NonCombatant); + .Where(a => a.IsInWorld && a != world.WorldActor && !a.Destroyed && a.HasTrait() && !a.Owner.NonCombatant); } void NODReinforceNthA() diff --git a/OpenRA.Mods.RA/AI/HackyAI.cs b/OpenRA.Mods.RA/AI/HackyAI.cs index f759199a26..c0201ce051 100644 --- a/OpenRA.Mods.RA/AI/HackyAI.cs +++ b/OpenRA.Mods.RA/AI/HackyAI.cs @@ -763,7 +763,7 @@ namespace OpenRA.Mods.RA.AI if (!buildableThings.Any()) return null; var myUnits = p.World - .ActorsWithTrait() + .ActorsWithTrait() .Where(a => a.Actor.Owner == p) .Select(a => a.Actor.Info.Name).ToArray(); @@ -783,7 +783,7 @@ namespace OpenRA.Mods.RA.AI int CountUnits(string unit, Player owner) { - return world.ActorsWithTrait().Where(a => a.Actor.Owner == owner && a.Actor.Info.Name == unit).Count(); + return world.ActorsWithTrait().Where(a => a.Actor.Owner == owner && a.Actor.Info.Name == unit).Count(); } int? CountBuildingByCommonName(string commonName, Player owner) @@ -1145,7 +1145,7 @@ namespace OpenRA.Mods.RA.AI void FindNewUnits(Actor self) { - var newUnits = self.World.ActorsWithTrait() + var newUnits = self.World.ActorsWithTrait() .Where(a => a.Actor.Owner == p && !a.Actor.HasTrait() && !activeUnits.Contains(a.Actor)) .Select(a => a.Actor).ToArray(); diff --git a/OpenRA.Mods.RA/Activities/Teleport.cs b/OpenRA.Mods.RA/Activities/Teleport.cs index 0b58ab398e..39ad10bd0d 100755 --- a/OpenRA.Mods.RA/Activities/Teleport.cs +++ b/OpenRA.Mods.RA/Activities/Teleport.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made @@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA.Activities Sound.Play(sound, self.CenterPosition); Sound.Play(sound, destination.CenterPosition); - self.Trait().SetPosition(self, destination); + self.Trait().SetPosition(self, destination); self.Generation++; if (killCargo && self.HasTrait()) @@ -68,7 +68,7 @@ namespace OpenRA.Mods.RA.Activities public override Activity Tick(Actor self) { - self.Trait().SetPosition(self, destination); + self.Trait().SetPosition(self, destination); self.Generation++; return NextActivity; } diff --git a/OpenRA.Mods.RA/Air/Aircraft.cs b/OpenRA.Mods.RA/Air/Aircraft.cs index f105538e3c..74ed1da009 100755 --- a/OpenRA.Mods.RA/Air/Aircraft.cs +++ b/OpenRA.Mods.RA/Air/Aircraft.cs @@ -36,7 +36,7 @@ namespace OpenRA.Mods.RA.Air public int GetInitialFacing() { return InitialFacing; } } - public class Aircraft : IFacing, ITeleportable, ISync, INotifyKilled, IIssueOrder, IOrderVoice + public class Aircraft : IFacing, IPositionable, ISync, INotifyKilled, IIssueOrder, IOrderVoice { public IDisposable reservation; diff --git a/OpenRA.Mods.RA/Air/EjectOnDeath.cs b/OpenRA.Mods.RA/Air/EjectOnDeath.cs index 879aebc631..24e357239b 100644 --- a/OpenRA.Mods.RA/Air/EjectOnDeath.cs +++ b/OpenRA.Mods.RA/Air/EjectOnDeath.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made @@ -30,7 +30,7 @@ namespace OpenRA.Mods.RA var pilot = self.World.CreateActor(false, info.PilotActor.ToLowerInvariant(), new TypeDictionary { new OwnerInit(self.Owner) }); var r = self.World.SharedRandom.Next(1, 100); - var aircraft = self.Trait(); + var aircraft = self.Trait(); if (IsSuitableCell(pilot, self.Location) && r > 100 - info.SuccessRate && aircraft.Altitude > 10 && self.Owner.WinState != WinState.Lost) @@ -44,7 +44,7 @@ namespace OpenRA.Mods.RA bool IsSuitableCell(Actor actorToDrop, CPos p) { - return actorToDrop.Trait().CanEnterCell(p); + return actorToDrop.Trait().CanEnterCell(p); } } } \ No newline at end of file diff --git a/OpenRA.Mods.RA/Bridge.cs b/OpenRA.Mods.RA/Bridge.cs index 3eb7dc9cac..ec2d7545f0 100644 --- a/OpenRA.Mods.RA/Bridge.cs +++ b/OpenRA.Mods.RA/Bridge.cs @@ -158,7 +158,7 @@ namespace OpenRA.Mods.RA { foreach (var c in TileSprites[currentTemplate].Keys) foreach (var a in self.World.ActorMap.GetUnitsAt(c)) - if (a.HasTrait() && !a.Trait().CanEnterCell(c)) + if (a.HasTrait() && !a.Trait().CanEnterCell(c)) a.Kill(self); } diff --git a/OpenRA.Mods.RA/ChronoshiftDeploy.cs b/OpenRA.Mods.RA/ChronoshiftDeploy.cs index dc96a6b006..0a6c5bb7a6 100644 --- a/OpenRA.Mods.RA/ChronoshiftDeploy.cs +++ b/OpenRA.Mods.RA/ChronoshiftDeploy.cs @@ -94,7 +94,7 @@ namespace OpenRA.Mods.RA public bool CanJumpTo(CPos xy, bool ignoreVis) { - var movement = self.TraitOrDefault(); + var movement = self.TraitOrDefault(); if (chargeTick <= 0 // Can jump && (self.Location - xy).Length <= Info.JumpDistance // Within jump range diff --git a/OpenRA.Mods.RA/Chronoshiftable.cs b/OpenRA.Mods.RA/Chronoshiftable.cs index 44e54bc9e4..2c70fffd64 100755 --- a/OpenRA.Mods.RA/Chronoshiftable.cs +++ b/OpenRA.Mods.RA/Chronoshiftable.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made @@ -58,7 +58,7 @@ namespace OpenRA.Mods.RA public virtual bool CanChronoshiftTo(Actor self, CPos targetLocation) { // TODO: Allow enemy units to be chronoshifted into bad terrain to kill them - return (self.HasTrait() && self.Trait().CanEnterCell(targetLocation)); + return (self.HasTrait() && self.Trait().CanEnterCell(targetLocation)); } public virtual bool Teleport(Actor self, CPos targetLocation, int duration, bool killCargo, Actor chronosphere) diff --git a/OpenRA.Mods.RA/Crate.cs b/OpenRA.Mods.RA/Crate.cs index 8acafa496c..fde9751988 100644 --- a/OpenRA.Mods.RA/Crate.cs +++ b/OpenRA.Mods.RA/Crate.cs @@ -24,7 +24,7 @@ namespace OpenRA.Mods.RA } // ITeleportable is required for paradrop - class Crate : ITick, ITeleportable, ICrushable, ISync, INotifyParachuteLanded + class Crate : ITick, IPositionable, ICrushable, ISync, INotifyParachuteLanded { readonly Actor self; [Sync] int ticks; diff --git a/OpenRA.Mods.RA/Effects/Parachute.cs b/OpenRA.Mods.RA/Effects/Parachute.cs index 9939f0f74a..8ebbf056e1 100644 --- a/OpenRA.Mods.RA/Effects/Parachute.cs +++ b/OpenRA.Mods.RA/Effects/Parachute.cs @@ -36,7 +36,7 @@ namespace OpenRA.Mods.RA.Effects parachuteOffset = pai.Offset; // Adjust x,y to match the target subcell - cargo.Trait().SetPosition(cargo, dropPosition.ToCPos()); + cargo.Trait().SetPosition(cargo, dropPosition.ToCPos()); var cp = cargo.CenterPosition; pos = new WPos(cp.X, cp.Y, dropPosition.Z); } diff --git a/OpenRA.Mods.RA/Minelayer.cs b/OpenRA.Mods.RA/Minelayer.cs index ddd6de89f2..f6d25c367f 100644 --- a/OpenRA.Mods.RA/Minelayer.cs +++ b/OpenRA.Mods.RA/Minelayer.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made @@ -60,7 +60,7 @@ namespace OpenRA.Mods.RA if (order.OrderString == "PlaceMinefield") { - var movement = self.Trait(); + var movement = self.Trait(); minefield = GetMinefieldCells(minefieldStart, order.TargetLocation, self.Info.Traits.Get().MinefieldDepth) @@ -130,7 +130,7 @@ namespace OpenRA.Mods.RA if (!minelayer.IsInWorld) return; - var movement = minelayer.Trait(); + var movement = minelayer.Trait(); var minefield = GetMinefieldCells(minefieldStart, lastMousePos, minelayer.Info.Traits.Get().MinefieldDepth) .Where(p => movement.CanEnterCell(p)).ToArray(); diff --git a/OpenRA.Mods.RA/Missions/Allies02Script.cs b/OpenRA.Mods.RA/Missions/Allies02Script.cs index 89bebdd3b1..f6a63cd091 100644 --- a/OpenRA.Mods.RA/Missions/Allies02Script.cs +++ b/OpenRA.Mods.RA/Missions/Allies02Script.cs @@ -170,7 +170,7 @@ namespace OpenRA.Mods.RA.Missions if (yak == null || (yak != null && !yak.IsDead() && (yak.GetCurrentActivity() is FlyCircle || yak.IsIdle))) { var alliedUnitsNearYakPoint = world.FindAliveCombatantActorsInCircle(yakAttackPoint.CenterPosition, WRange.FromCells(10)) - .Where(a => a.Owner != soviets && a.HasTrait() && a != tanya && a != einstein && a != engineer); + .Where(a => a.Owner != soviets && a.HasTrait() && a != tanya && a != einstein && a != engineer); if (alliedUnitsNearYakPoint.Any()) YakStrafe(alliedUnitsNearYakPoint); } @@ -384,7 +384,7 @@ namespace OpenRA.Mods.RA.Missions bool AlliesNearTown() { return world.FindAliveCombatantActorsInCircle(townPoint.CenterPosition, WRange.FromCells(AlliedTownTransferRange)) - .Any(a => a.Owner == allies1 && a.HasTrait()); + .Any(a => a.Owner == allies1 && a.HasTrait()); } void TransferTownUnitsToAllies() @@ -399,7 +399,7 @@ namespace OpenRA.Mods.RA.Missions var sovietAttackUnits = world.FindAliveCombatantActorsInCircle(sovietTownAttackPoint1.CenterPosition, WRange.FromCells(SovietTownAttackGroupRange)) .Union(world.FindAliveCombatantActorsInCircle(sovietTownAttackPoint2.CenterPosition, WRange.FromCells(SovietTownAttackGroupRange))) .Union(world.FindAliveCombatantActorsInCircle(townPoint.CenterPosition, WRange.FromCells(AlliedTownTransferRange))) - .Where(a => a.HasTrait() && a.Owner == soviets); + .Where(a => a.HasTrait() && a.Owner == soviets); foreach (var unit in sovietAttackUnits) unit.QueueActivity(new AttackMove.AttackMoveActivity(unit, new Move.Move(townPoint.Location, SovietTownMoveNearEnough))); diff --git a/OpenRA.Mods.RA/Missions/MissionUtils.cs b/OpenRA.Mods.RA/Missions/MissionUtils.cs index 8e1fff1360..8bd035139c 100644 --- a/OpenRA.Mods.RA/Missions/MissionUtils.cs +++ b/OpenRA.Mods.RA/Missions/MissionUtils.cs @@ -106,7 +106,7 @@ namespace OpenRA.Mods.RA.Missions public static bool AreaSecuredWithUnits(World world, Player player, WPos location, WRange range) { - var units = world.FindAliveCombatantActorsInCircle(location, range).Where(a => a.HasTrait()); + var units = world.FindAliveCombatantActorsInCircle(location, range).Where(a => a.HasTrait()); return units.Any() && units.All(a => a.Owner == player); } diff --git a/OpenRA.Mods.RA/Missions/Survival01Script.cs b/OpenRA.Mods.RA/Missions/Survival01Script.cs index 4f93229a60..4a77635de2 100644 --- a/OpenRA.Mods.RA/Missions/Survival01Script.cs +++ b/OpenRA.Mods.RA/Missions/Survival01Script.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made @@ -185,7 +185,7 @@ namespace OpenRA.Mods.RA.Missions var units = world.CreateActor((sovietInfantry).Random(world.SharedRandom), new TypeDictionary { new LocationInit(sovietinfantryentry1.Location), new OwnerInit(soviets) }); units.QueueActivity(new Move.Move(sovietinfantryrally1.Location, 3)); var unitsincircle = world.FindAliveCombatantActorsInCircle(sovietinfantryrally1.CenterPosition, WRange.FromCells(10)) - .Where(a => a.Owner == soviets && a.IsIdle && a.HasTrait()); + .Where(a => a.Owner == soviets && a.IsIdle && a.HasTrait()); if (unitsincircle.Count() >= sovietInfantryGroupSize) { foreach (var scatteredunits in unitsincircle) diff --git a/OpenRA.Mods.RA/Missions/Survival02Script.cs b/OpenRA.Mods.RA/Missions/Survival02Script.cs index 9e4da5604e..47b54ab47b 100644 --- a/OpenRA.Mods.RA/Missions/Survival02Script.cs +++ b/OpenRA.Mods.RA/Missions/Survival02Script.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made @@ -299,7 +299,7 @@ namespace OpenRA.Mods.RA.Missions void ManageSovietUnits() { var units = world.FindAliveCombatantActorsInCircle(sovietrally.CenterPosition, WRange.FromCells(3)) - .Where(u => u.IsIdle && u.HasTrait() && u.HasTrait() && u.Owner == soviets); + .Where(u => u.IsIdle && u.HasTrait() && u.HasTrait() && u.Owner == soviets); if (units.Count() >= sovietAttackGroupSize) { foreach (var unit in units) diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index 22f285c9cf..082b2d8b32 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -145,7 +145,7 @@ namespace OpenRA.Mods.RA.Move public int GetInitialFacing() { return InitialFacing; } } - public class Mobile : IIssueOrder, IResolveOrder, IOrderVoice, ITeleportable, IFacing, ISync + public class Mobile : IIssueOrder, IResolveOrder, IOrderVoice, IPositionable, IFacing, ISync { public readonly Actor self; public readonly MobileInfo Info; diff --git a/OpenRA.Mods.RA/Orders/SetChronoTankDestination.cs b/OpenRA.Mods.RA/Orders/SetChronoTankDestination.cs index 5b31bc408b..3b4d2f3ab5 100644 --- a/OpenRA.Mods.RA/Orders/SetChronoTankDestination.cs +++ b/OpenRA.Mods.RA/Orders/SetChronoTankDestination.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made @@ -50,7 +50,7 @@ namespace OpenRA.Mods.RA.Orders if (!world.LocalPlayer.Shroud.IsExplored(xy)) return "move-blocked"; - var movement = self.TraitOrDefault(); + var movement = self.TraitOrDefault(); return (movement.CanEnterCell(xy)) ? "chrono-target" : "move-blocked"; } } diff --git a/OpenRA.Mods.RA/ParaDrop.cs b/OpenRA.Mods.RA/ParaDrop.cs index 9adc524ad7..992d8c3033 100644 --- a/OpenRA.Mods.RA/ParaDrop.cs +++ b/OpenRA.Mods.RA/ParaDrop.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made @@ -60,7 +60,7 @@ namespace OpenRA.Mods.RA bool IsSuitableCell(Actor actorToDrop, CPos p) { - return actorToDrop.Trait().CanEnterCell(p); + return actorToDrop.Trait().CanEnterCell(p); } void FinishedDropping(Actor self) diff --git a/OpenRA.Mods.RA/Player/PlayerStatistics.cs b/OpenRA.Mods.RA/Player/PlayerStatistics.cs index c6fdaaef0f..631c10c221 100644 --- a/OpenRA.Mods.RA/Player/PlayerStatistics.cs +++ b/OpenRA.Mods.RA/Player/PlayerStatistics.cs @@ -112,7 +112,7 @@ namespace OpenRA.Mods.RA attackerStats.BuildingsKilled++; defenderStats.BuildingsDead++; } - else if (self.HasTrait()) + else if (self.HasTrait()) { attackerStats.UnitsKilled++; defenderStats.UnitsDead++; diff --git a/OpenRA.Mods.RA/Production.cs b/OpenRA.Mods.RA/Production.cs index 3a516b6bb8..daa7a2cf05 100755 --- a/OpenRA.Mods.RA/Production.cs +++ b/OpenRA.Mods.RA/Production.cs @@ -67,7 +67,7 @@ namespace OpenRA.Mods.RA // TODO: Move this into an *Init // TODO: We should be adjusting the actual position for aircraft, not just visuals. - var teleportable = newUnit.Trait(); + var teleportable = newUnit.Trait(); teleportable.AdjustPxPosition(newUnit, PPos.FromWPos(spawn)); // TODO: Generalize this for non-mobile (e.g. aircraft) too From abdfac6e85848cbaed50b890242eeb96795b53cb Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 11:19:26 +1200 Subject: [PATCH 15/26] More style fixes for Move. --- OpenRA.Mods.RA/Move/Move.cs | 64 +++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/OpenRA.Mods.RA/Move/Move.cs b/OpenRA.Mods.RA/Move/Move.cs index b0a527c1ec..8d7152d7a6 100755 --- a/OpenRA.Mods.RA/Move/Move.cs +++ b/OpenRA.Mods.RA/Move/Move.cs @@ -20,11 +20,13 @@ namespace OpenRA.Mods.RA.Move { class Move : Activity { + static readonly List NoPath = new List(); + CPos? destination; WRange nearEnough; - public List path; + List path; Func> getPath; - public Actor ignoreBuilding; + Actor ignoreBuilding; // For dealing with blockers bool hasWaited; @@ -35,9 +37,9 @@ namespace OpenRA.Mods.RA.Move // Ignores lane bias and nearby units public Move(CPos destination) { - this.getPath = (self,mobile) => + this.getPath = (self, mobile) => self.World.WorldActor.Trait().FindPath( - PathSearch.FromPoint( self.World, mobile.Info, self, mobile.toCell, destination, false ) + PathSearch.FromPoint(self.World, mobile.Info, self, mobile.toCell, destination, false) .WithoutLaneBias()); this.destination = destination; this.nearEnough = WRange.Zero; @@ -45,29 +47,28 @@ namespace OpenRA.Mods.RA.Move // Hack for legacy code public Move(CPos destination, int nearEnough) - : this(destination, WRange.FromCells(nearEnough)) {} + : this(destination, WRange.FromCells(nearEnough)) { } public Move(CPos destination, WRange nearEnough) { - this.getPath = (self,mobile) => self.World.WorldActor.Trait().FindUnitPath( mobile.toCell, destination, self ); + this.getPath = (self, mobile) => self.World.WorldActor.Trait() + .FindUnitPath(mobile.toCell, destination, self); this.destination = destination; this.nearEnough = nearEnough; } public Move(CPos destination, Actor ignoreBuilding) { - this.getPath = (self,mobile) => + this.getPath = (self, mobile) => self.World.WorldActor.Trait().FindPath( PathSearch.FromPoint(self.World, mobile.Info, self, mobile.toCell, destination, false) - .WithIgnoredBuilding(ignoreBuilding) - ); + .WithIgnoredBuilding(ignoreBuilding)); this.destination = destination; this.nearEnough = WRange.Zero; this.ignoreBuilding = ignoreBuilding; } - static readonly List NoPath = new List(); public Move(Target target, WRange range) { this.getPath = (self, mobile) => @@ -85,7 +86,7 @@ namespace OpenRA.Mods.RA.Move public Move(Func> getPath) { - this.getPath = (_1,_2) => getPath(); + this.getPath = (_1, _2) => getPath(); this.destination = null; this.nearEnough = WRange.Zero; } @@ -132,7 +133,7 @@ namespace OpenRA.Mods.RA.Move } path = EvalPath(self, mobile); - SanityCheckPath( mobile ); + SanityCheckPath(mobile); } if (path.Count == 0) @@ -151,7 +152,7 @@ namespace OpenRA.Mods.RA.Move var firstFacing = Util.GetFacing(dir, mobile.Facing); if (firstFacing != mobile.Facing) { - path.Add( nextCell.Value.First ); + path.Add(nextCell.Value.First); return Util.SequenceActivities(new Turn(firstFacing), this); } else @@ -163,8 +164,7 @@ namespace OpenRA.Mods.RA.Move Util.BetweenCells(mobile.fromCell, mobile.toCell) + (MobileInfo.SubCellOffsets[mobile.fromSubCell] + MobileInfo.SubCellOffsets[mobile.toSubCell]) / 2, mobile.Facing, mobile.Facing, - 0 - ); + 0); return move; } @@ -206,7 +206,7 @@ namespace OpenRA.Mods.RA.Move { // Are we close enough? var cellRange = nearEnough.Range / 1024; - if ((mobile.toCell - destination.Value).LengthSquared <= cellRange*cellRange) + if ((mobile.toCell - destination.Value).LengthSquared <= cellRange * cellRange) { path.Clear(); return null; @@ -255,9 +255,9 @@ namespace OpenRA.Mods.RA.Move return Pair.New(nextCell, subCell); } - public override void Cancel( Actor self ) + public override void Cancel(Actor self) { - path = new List(0); + path = NoPath; base.Cancel(self); } @@ -272,11 +272,11 @@ namespace OpenRA.Mods.RA.Move abstract class MovePart : Activity { - public readonly Move move; - public readonly PPos from, to; - public readonly int fromFacing, toFacing; - public int moveFraction; - public readonly int moveFractionTotal; + protected readonly Move move; + protected readonly PPos from, to; + protected readonly int fromFacing, toFacing; + protected readonly int moveFractionTotal; + protected int moveFraction; public MovePart(Move move, PPos from, PPos to, int fromFacing, int toFacing, int startingFraction) { @@ -286,7 +286,7 @@ namespace OpenRA.Mods.RA.Move this.fromFacing = fromFacing; this.toFacing = toFacing; this.moveFraction = startingFraction; - this.moveFractionTotal = 3*(to - from).Length; + this.moveFractionTotal = 3 * (to - from).Length; } public override void Cancel(Actor self) @@ -304,7 +304,7 @@ namespace OpenRA.Mods.RA.Move { var mobile = self.Trait(); var ret = InnerTick(self, mobile); - mobile.IsMoving = (ret is MovePart); + mobile.IsMoving = ret is MovePart; if (moveFraction > moveFractionTotal) moveFraction = moveFractionTotal; @@ -372,8 +372,7 @@ namespace OpenRA.Mods.RA.Move Util.BetweenCells(mobile.toCell, nextCell.Value.First) + (toSubcellOffset + nextSubcellOffset) / 2, mobile.Facing, Util.GetNearestFacing(mobile.Facing, Util.GetFacing(nextCell.Value.First - mobile.toCell, mobile.Facing)), - moveFraction - moveFractionTotal - ); + moveFraction - moveFractionTotal); mobile.SetLocation(mobile.toCell, mobile.toSubCell, nextCell.Value.First, nextCell.Value.Second); return ret; @@ -388,8 +387,7 @@ namespace OpenRA.Mods.RA.Move Util.CenterOfCell(mobile.toCell) + toSubcellOffset, mobile.Facing, mobile.Facing, - moveFraction - moveFractionTotal - ); + moveFraction - moveFractionTotal); mobile.EnteringCell(self); mobile.SetLocation(mobile.toCell, mobile.toSubCell, mobile.toCell, mobile.toSubCell); @@ -400,7 +398,7 @@ namespace OpenRA.Mods.RA.Move class MoveSecondHalf : MovePart { public MoveSecondHalf(Move move, PPos from, PPos to, int fromFacing, int toFacing, int startingFraction) - : base(move, from, to, fromFacing, toFacing, startingFraction) {} + : base(move, from, to, fromFacing, toFacing, startingFraction) { } protected override MovePart OnComplete(Actor self, Mobile mobile, Move parent) { @@ -416,12 +414,10 @@ namespace OpenRA.Mods.RA.Move { public static bool IsMoving(this Actor self) { - if (self.IsIdle) + var a = self.GetCurrentActivity(); + if (a == null) return false; - Activity a = self.GetCurrentActivity(); - Debug.Assert(a != null); - // Dirty, but it suffices until we do something better: if (a.GetType() == typeof(Move)) return true; if (a.GetType() == typeof(MoveAdjacentTo)) return true; From 0676116d77c5932fc82ba386b09315777d7acf5e Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 11:31:38 +1200 Subject: [PATCH 16/26] Convert Move and related plumbing to world coordinates. --- OpenRA.Game/Traits/Util.cs | 4 ++-- OpenRA.Mods.RA/Activities/Enter.cs | 4 ++-- OpenRA.Mods.RA/Activities/Leap.cs | 3 +-- OpenRA.Mods.RA/Activities/UnloadCargo.cs | 4 ++-- OpenRA.Mods.RA/LeavesHusk.cs | 2 +- OpenRA.Mods.RA/Move/Mobile.cs | 25 ++++++++++-------------- OpenRA.Mods.RA/Move/Move.cs | 16 +++++++-------- OpenRA.Mods.RA/Move/PathFinder.cs | 3 +-- OpenRA.Mods.RA/Production.cs | 4 ++-- 9 files changed, 29 insertions(+), 36 deletions(-) diff --git a/OpenRA.Game/Traits/Util.cs b/OpenRA.Game/Traits/Util.cs index dc87b9b473..874f84c73a 100755 --- a/OpenRA.Game/Traits/Util.cs +++ b/OpenRA.Game/Traits/Util.cs @@ -100,9 +100,9 @@ namespace OpenRA.Traits return loc.ToPPos() + new PVecInt(Game.CellSize / 2, Game.CellSize / 2); } - public static PPos BetweenCells(CPos from, CPos to) + public static WPos BetweenCells(CPos from, CPos to) { - return PPos.Lerp(CenterOfCell(from), CenterOfCell(to), 1, 2); + return WPos.Lerp(from.CenterPosition, to.CenterPosition, 1, 2); } public static int2 AsInt2(this int[] xs) { return new int2(xs[0], xs[1]); } diff --git a/OpenRA.Mods.RA/Activities/Enter.cs b/OpenRA.Mods.RA/Activities/Enter.cs index fbf2243139..c4afe104b5 100755 --- a/OpenRA.Mods.RA/Activities/Enter.cs +++ b/OpenRA.Mods.RA/Activities/Enter.cs @@ -37,8 +37,8 @@ namespace OpenRA.Mods.RA.Activities var mobile = self.Trait(); var to = target.CenterPosition; var from = self.CenterPosition; - var speed = mobile.WorldMovementSpeedForCell(self, self.Location); - var length = speed > 0 ? (int)((to - from).Length * 3 / speed) : 0; + var speed = mobile.MovementSpeedForCell(self, self.Location); + var length = speed > 0 ? (to - from).Length / speed : 0; return Util.SequenceActivities( new Turn(Util.GetFacing(to - from, mobile.Facing)), diff --git a/OpenRA.Mods.RA/Activities/Leap.cs b/OpenRA.Mods.RA/Activities/Leap.cs index 7be3de70d2..2d403cece1 100644 --- a/OpenRA.Mods.RA/Activities/Leap.cs +++ b/OpenRA.Mods.RA/Activities/Leap.cs @@ -41,8 +41,7 @@ namespace OpenRA.Mods.RA.Activities mobile.IsMoving = true; from = self.CenterPosition; - var offset = MobileInfo.SubCellOffsets[targetMobile.fromSubCell]; - to = targetMobile.fromCell.CenterPosition + new WVec(offset.X * 1024 / Game.CellSize, offset.Y * 1024 / Game.CellSize, 0); + to = targetMobile.fromCell.CenterPosition + MobileInfo.SubCellOffsets[targetMobile.fromSubCell]; length = Math.Max((to - from).Length / speed.Range, 1); self.Trait().Attacking(self, Target.FromActor(target)); diff --git a/OpenRA.Mods.RA/Activities/UnloadCargo.cs b/OpenRA.Mods.RA/Activities/UnloadCargo.cs index e4cba01ee2..946fd23dfd 100644 --- a/OpenRA.Mods.RA/Activities/UnloadCargo.cs +++ b/OpenRA.Mods.RA/Activities/UnloadCargo.cs @@ -91,8 +91,8 @@ namespace OpenRA.Mods.RA.Activities mobile.Facing = Util.GetFacing(exit - current, mobile.Facing ); mobile.SetPosition(actor, exitTile.Value); mobile.AdjustPxPosition(actor, PPos.FromWPos(current)); - var speed = mobile.WorldMovementSpeedForCell(actor, exitTile.Value); - var length = speed > 0 ? ((int)(exit - current).Length * 3 / speed) : 0; + var speed = mobile.MovementSpeedForCell(actor, exitTile.Value); + var length = speed > 0 ? (exit - current).Length / speed : 0; w.Add(actor); actor.CancelActivity(); diff --git a/OpenRA.Mods.RA/LeavesHusk.cs b/OpenRA.Mods.RA/LeavesHusk.cs index 7b04b1d9c2..f5efe15fc1 100644 --- a/OpenRA.Mods.RA/LeavesHusk.cs +++ b/OpenRA.Mods.RA/LeavesHusk.cs @@ -49,7 +49,7 @@ namespace OpenRA.Mods.RA if (mobile != null) { if (!mobile.CanEnterCell(self.Location, self, false)) return; - td.Add(new HuskSpeedInit(mobile.MovementSpeedForCell(self, self.Location))); + td.Add(new HuskSpeedInit(mobile.MovementSpeedForCell(self, self.Location) * 3 * Game.CellSize / 1024)); } var aircraft = self.TraitOrDefault(); diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index 082b2d8b32..d0da5736e0 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -81,14 +81,14 @@ namespace OpenRA.Mods.RA.Move return passability.ToBits(); } - public static readonly Dictionary SubCellOffsets = new Dictionary() + public static readonly Dictionary SubCellOffsets = new Dictionary() { - {SubCell.TopLeft, new PVecInt(-7,-6)}, - {SubCell.TopRight, new PVecInt(6,-6)}, - {SubCell.Center, new PVecInt(0,0)}, - {SubCell.BottomLeft, new PVecInt(-7,6)}, - {SubCell.BottomRight, new PVecInt(6,6)}, - {SubCell.FullCell, new PVecInt(0,0)}, + {SubCell.TopLeft, new WVec(-299, -256, 0)}, + {SubCell.TopRight, new WVec(256, -256, 0)}, + {SubCell.Center, new WVec(0, 0, 0)}, + {SubCell.BottomLeft, new WVec(-299, 256, 0)}, + {SubCell.BottomRight, new WVec(256, 256, 0)}, + {SubCell.FullCell, new WVec(0, 0, 0)}, }; static bool IsMovingInMyDirection(Actor self, Actor other) @@ -204,7 +204,7 @@ namespace OpenRA.Mods.RA.Move if (init.Contains()) { this.__fromCell = this.__toCell = init.Get(); - this.PxPosition = Util.CenterOfCell(fromCell) + MobileInfo.SubCellOffsets[fromSubCell]; + this.PxPosition = PPos.FromWPos(fromCell.CenterPosition + MobileInfo.SubCellOffsets[fromSubCell]); } this.Facing = init.Contains() ? init.Get() : info.InitialFacing; @@ -214,7 +214,7 @@ namespace OpenRA.Mods.RA.Move public void SetPosition(Actor self, CPos cell) { SetLocation(cell,fromSubCell, cell,fromSubCell); - PxPosition = Util.CenterOfCell(fromCell) + MobileInfo.SubCellOffsets[fromSubCell]; + PxPosition = PPos.FromWPos(fromCell.CenterPosition + MobileInfo.SubCellOffsets[fromSubCell]); FinishedMoving(self); } @@ -422,12 +422,7 @@ namespace OpenRA.Mods.RA.Move decimal speed = Info.Speed * Info.TerrainSpeeds[type].Speed; foreach (var t in self.TraitsImplementing()) speed *= t.GetSpeedModifier(); - return (int)(speed / 100); - } - - public int WorldMovementSpeedForCell(Actor self, CPos cell) - { - return MovementSpeedForCell(self, cell) * 1024 / Game.CellSize; + return (int)(speed / 100) * 1024 / (3 * Game.CellSize); } public void AddInfluence() diff --git a/OpenRA.Mods.RA/Move/Move.cs b/OpenRA.Mods.RA/Move/Move.cs index 8d7152d7a6..63959732ea 100755 --- a/OpenRA.Mods.RA/Move/Move.cs +++ b/OpenRA.Mods.RA/Move/Move.cs @@ -160,7 +160,7 @@ namespace OpenRA.Mods.RA.Move mobile.SetLocation(mobile.fromCell, mobile.fromSubCell, nextCell.Value.First, nextCell.Value.Second); var move = new MoveFirstHalf( this, - Util.CenterOfCell(mobile.fromCell) + MobileInfo.SubCellOffsets[mobile.fromSubCell], + mobile.fromCell.CenterPosition + MobileInfo.SubCellOffsets[mobile.fromSubCell], Util.BetweenCells(mobile.fromCell, mobile.toCell) + (MobileInfo.SubCellOffsets[mobile.fromSubCell] + MobileInfo.SubCellOffsets[mobile.toSubCell]) / 2, mobile.Facing, mobile.Facing, @@ -273,12 +273,12 @@ namespace OpenRA.Mods.RA.Move abstract class MovePart : Activity { protected readonly Move move; - protected readonly PPos from, to; + protected readonly WPos from, to; protected readonly int fromFacing, toFacing; protected readonly int moveFractionTotal; protected int moveFraction; - public MovePart(Move move, PPos from, PPos to, int fromFacing, int toFacing, int startingFraction) + public MovePart(Move move, WPos from, WPos to, int fromFacing, int toFacing, int startingFraction) { this.move = move; this.from = from; @@ -286,7 +286,7 @@ namespace OpenRA.Mods.RA.Move this.fromFacing = fromFacing; this.toFacing = toFacing; this.moveFraction = startingFraction; - this.moveFractionTotal = 3 * (to - from).Length; + this.moveFractionTotal = (to - from).Length; } public override void Cancel(Actor self) @@ -328,7 +328,7 @@ namespace OpenRA.Mods.RA.Move void UpdateCenterLocation(Actor self, Mobile mobile) { - mobile.PxPosition = PPos.Lerp(from, to, moveFraction, moveFractionTotal); + mobile.PxPosition = PPos.FromWPos(WPos.Lerp(from, to, moveFraction, moveFractionTotal)); if (moveFraction >= moveFractionTotal) mobile.Facing = toFacing & 0xFF; @@ -346,7 +346,7 @@ namespace OpenRA.Mods.RA.Move class MoveFirstHalf : MovePart { - public MoveFirstHalf(Move move, PPos from, PPos to, int fromFacing, int toFacing, int startingFraction) + public MoveFirstHalf(Move move, WPos from, WPos to, int fromFacing, int toFacing, int startingFraction) : base(move, from, to, fromFacing, toFacing, startingFraction) { } static bool IsTurn(Mobile mobile, CPos nextCell) @@ -384,7 +384,7 @@ namespace OpenRA.Mods.RA.Move var ret2 = new MoveSecondHalf( move, Util.BetweenCells(mobile.fromCell, mobile.toCell) + (fromSubcellOffset + toSubcellOffset) / 2, - Util.CenterOfCell(mobile.toCell) + toSubcellOffset, + mobile.toCell.CenterPosition + toSubcellOffset, mobile.Facing, mobile.Facing, moveFraction - moveFractionTotal); @@ -397,7 +397,7 @@ namespace OpenRA.Mods.RA.Move class MoveSecondHalf : MovePart { - public MoveSecondHalf(Move move, PPos from, PPos to, int fromFacing, int toFacing, int startingFraction) + public MoveSecondHalf(Move move, WPos from, WPos to, int fromFacing, int toFacing, int startingFraction) : base(move, from, to, fromFacing, toFacing, startingFraction) { } protected override MovePart OnComplete(Actor self, Mobile mobile, Move parent) diff --git a/OpenRA.Mods.RA/Move/PathFinder.cs b/OpenRA.Mods.RA/Move/PathFinder.cs index 959e2cecf7..c09e6d8126 100755 --- a/OpenRA.Mods.RA/Move/PathFinder.cs +++ b/OpenRA.Mods.RA/Move/PathFinder.cs @@ -88,8 +88,7 @@ namespace OpenRA.Mods.RA.Move var rangeSquared = range.Range*range.Range; // Correct for SubCell offset - var so = MobileInfo.SubCellOffsets[srcSub]; - target -= new WVec(so.X * 1024 / Game.CellSize, so.Y * 1024 / Game.CellSize, 0); + target -= MobileInfo.SubCellOffsets[srcSub]; // Select only the tiles that are within range from the requested SubCell // This assumes that the SubCell does not change during the path traversal diff --git a/OpenRA.Mods.RA/Production.cs b/OpenRA.Mods.RA/Production.cs index daa7a2cf05..a87efdba94 100755 --- a/OpenRA.Mods.RA/Production.cs +++ b/OpenRA.Mods.RA/Production.cs @@ -76,8 +76,8 @@ namespace OpenRA.Mods.RA if (mobile != null) { // Animate the spawn -> exit transition - var speed = mobile.WorldMovementSpeedForCell(newUnit, exit); - var length = speed > 0 ? (int)((to - spawn).Length * 3 / speed) : 0; + var speed = mobile.MovementSpeedForCell(newUnit, exit); + var length = speed > 0 ? (to - spawn).Length / speed : 0; newUnit.QueueActivity(new Drag(spawn, to, length)); } From 3e9bc63d4efde8583c8c21927a6b4ecabfadb9cd Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 11:48:59 +1200 Subject: [PATCH 17/26] Prevent things from tweaking mobile position directly. --- OpenRA.Mods.RA/Move/Drag.cs | 2 +- OpenRA.Mods.RA/Move/Mobile.cs | 2 +- OpenRA.Mods.RA/Move/Move.cs | 6 ++---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/OpenRA.Mods.RA/Move/Drag.cs b/OpenRA.Mods.RA/Move/Drag.cs index 307f71b5ee..154e963957 100755 --- a/OpenRA.Mods.RA/Move/Drag.cs +++ b/OpenRA.Mods.RA/Move/Drag.cs @@ -33,7 +33,7 @@ namespace OpenRA.Mods.RA.Move ? WPos.Lerp(start, end, ticks, length - 1) : end; - mobile.PxPosition = PPos.FromWPos(pos); + mobile.AdjustPxPosition(self, PPos.FromWPos(pos)); if (++ticks >= length) { mobile.IsMoving = false; diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index d0da5736e0..3d36a3816f 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -167,7 +167,7 @@ namespace OpenRA.Mods.RA.Move public int ROT { get { return Info.ROT; } } - [Sync] public PPos PxPosition { get; set; } + [Sync] public PPos PxPosition { get; private set; } [Sync] public CPos fromCell { get { return __fromCell; } } [Sync] public CPos toCell { get { return __toCell; } } diff --git a/OpenRA.Mods.RA/Move/Move.cs b/OpenRA.Mods.RA/Move/Move.cs index 63959732ea..744d2a7373 100755 --- a/OpenRA.Mods.RA/Move/Move.cs +++ b/OpenRA.Mods.RA/Move/Move.cs @@ -328,7 +328,7 @@ namespace OpenRA.Mods.RA.Move void UpdateCenterLocation(Actor self, Mobile mobile) { - mobile.PxPosition = PPos.FromWPos(WPos.Lerp(from, to, moveFraction, moveFractionTotal)); + mobile.AdjustPxPosition(self, PPos.FromWPos(WPos.Lerp(from, to, moveFraction, moveFractionTotal))); if (moveFraction >= moveFractionTotal) mobile.Facing = toFacing & 0xFF; @@ -402,9 +402,7 @@ namespace OpenRA.Mods.RA.Move protected override MovePart OnComplete(Actor self, Mobile mobile, Move parent) { - mobile.PxPosition = Util.CenterOfCell(mobile.toCell); - mobile.SetLocation(mobile.toCell, mobile.toSubCell, mobile.toCell, mobile.toSubCell); - mobile.FinishedMoving(self); + mobile.SetPosition(self, mobile.toCell); return null; } } From 19165d259d07697ab2a0904d2acdcbee63db846a Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 12:04:00 +1200 Subject: [PATCH 18/26] Add world coord overloads to IOccupySpace and IPositionable. --- OpenRA.Game/Traits/TraitsInterfaces.cs | 4 ++++ OpenRA.Game/Traits/Waypoint.cs | 1 + OpenRA.Mods.RA/Air/Aircraft.cs | 11 ++++++++++- OpenRA.Mods.RA/Buildings/Building.cs | 1 + OpenRA.Mods.RA/Crate.cs | 6 +++++- OpenRA.Mods.RA/Husk.cs | 3 ++- OpenRA.Mods.RA/Mine.cs | 1 + OpenRA.Mods.RA/Move/Mobile.cs | 13 +++++++++++++ 8 files changed, 37 insertions(+), 3 deletions(-) diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 4d37136723..8ed42e5c67 100755 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -100,6 +100,7 @@ namespace OpenRA.Traits public interface IOccupySpace { PPos PxPosition { get; } + WPos CenterPosition { get; } CPos TopLeft { get; } IEnumerable> OccupiedCells(); @@ -144,6 +145,9 @@ namespace OpenRA.Traits void SetPosition(Actor self, CPos cell); void SetPxPosition(Actor self, PPos px); void AdjustPxPosition(Actor self, PPos px); /* works like SetPxPosition, but visual only */ + + void SetPosition(Actor self, WPos pos); + void SetVisualPosition(Actor self, WPos pos); } public interface INotifyBlockingMove { void OnNotifyBlockingMove(Actor self, Actor blocking); } diff --git a/OpenRA.Game/Traits/Waypoint.cs b/OpenRA.Game/Traits/Waypoint.cs index d60b8079cd..0223fa9fda 100644 --- a/OpenRA.Game/Traits/Waypoint.cs +++ b/OpenRA.Game/Traits/Waypoint.cs @@ -30,6 +30,7 @@ namespace OpenRA.Traits public CPos TopLeft { get { return location; } } public IEnumerable> OccupiedCells() { yield break; } + public WPos CenterPosition { get { return location.CenterPosition; } } public PPos PxPosition { get { return Util.CenterOfCell(location); } } public int Altitude { get { return 0; } set { } } } diff --git a/OpenRA.Mods.RA/Air/Aircraft.cs b/OpenRA.Mods.RA/Air/Aircraft.cs index 74ed1da009..5e65b70eae 100755 --- a/OpenRA.Mods.RA/Air/Aircraft.cs +++ b/OpenRA.Mods.RA/Air/Aircraft.cs @@ -54,11 +54,12 @@ namespace OpenRA.Mods.RA.Air UnReserve(); } - protected readonly Actor self; [Sync] public int Facing { get; set; } [Sync] public int Altitude { get; set; } [Sync] public PSubPos SubPxPosition; + + public WPos CenterPosition { get { return PxPosition.ToWPos(Altitude); } } public PPos PxPosition { get { return SubPxPosition.ToPPos(); } } public CPos TopLeft { get { return PxPosition.ToCPos(); } } @@ -110,6 +111,14 @@ namespace OpenRA.Mods.RA.Air public void AdjustPxPosition(Actor self, PPos px) { SetPxPosition(self, px); } + public void SetPosition(Actor self, WPos pos) + { + // TODO: Handle altitude + SubPxPosition = PPos.FromWPos(pos).ToPSubPos(); + } + + public void SetVisualPosition(Actor self, WPos pos) { SetPosition(self, pos); } + public bool AircraftCanEnter(Actor a) { if (self.AppearsHostileTo(a)) return false; diff --git a/OpenRA.Mods.RA/Buildings/Building.cs b/OpenRA.Mods.RA/Buildings/Building.cs index 3beb58e7f6..114809e683 100755 --- a/OpenRA.Mods.RA/Buildings/Building.cs +++ b/OpenRA.Mods.RA/Buildings/Building.cs @@ -110,6 +110,7 @@ namespace OpenRA.Mods.RA.Buildings public void Unlock() { Locked = false; } public CPos TopLeft { get { return topLeft; } } + public WPos CenterPosition { get { return PxPosition.ToWPos(0); } } public PPos PxPosition { get { return pxPosition; } } public int Altitude { get { return 0; } set { } } diff --git a/OpenRA.Mods.RA/Crate.cs b/OpenRA.Mods.RA/Crate.cs index fde9751988..e45f56bfa4 100644 --- a/OpenRA.Mods.RA/Crate.cs +++ b/OpenRA.Mods.RA/Crate.cs @@ -85,16 +85,20 @@ namespace OpenRA.Mods.RA public CPos TopLeft { get { return Location; } } public IEnumerable> OccupiedCells() { yield return Pair.New( Location, SubCell.FullCell); } + public WPos CenterPosition { get { return PxPosition.ToWPos(Altitude); } } public PPos PxPosition { get; private set; } public int Altitude { get { return 0; } set { } } public void SetPxPosition(Actor self, PPos px) { - SetPosition( self, px.ToCPos() ); + SetPosition(self, px.ToCPos()); } public void AdjustPxPosition(Actor self, PPos px) { SetPxPosition(self, px); } + public void SetPosition(Actor self, WPos pos) { SetPosition(self, pos.ToCPos()); } + public void SetVisualPosition(Actor self, WPos pos) { SetPosition(self, pos.ToCPos()); } + public bool CanEnterCell(CPos cell) { if (!self.World.Map.IsInMap(cell.X, cell.Y)) return false; diff --git a/OpenRA.Mods.RA/Husk.cs b/OpenRA.Mods.RA/Husk.cs index 9da6ce0153..c06a96e841 100644 --- a/OpenRA.Mods.RA/Husk.cs +++ b/OpenRA.Mods.RA/Husk.cs @@ -26,7 +26,8 @@ namespace OpenRA.Mods.RA { [Sync] CPos location; - [Sync] public PPos PxPosition { get; set; } + public WPos CenterPosition { get { return PxPosition.ToWPos(0); } } + [Sync] public PPos PxPosition { get; private set; } public int Altitude { get { return 0; } set { } } [Sync] public int Facing { get; set; } diff --git a/OpenRA.Mods.RA/Mine.cs b/OpenRA.Mods.RA/Mine.cs index c2589b877e..9b34282c07 100644 --- a/OpenRA.Mods.RA/Mine.cs +++ b/OpenRA.Mods.RA/Mine.cs @@ -61,6 +61,7 @@ namespace OpenRA.Mods.RA public CPos TopLeft { get { return location; } } public IEnumerable> OccupiedCells() { yield return Pair.New(TopLeft, SubCell.FullCell); } + public WPos CenterPosition { get { return PxPosition.ToWPos(0); } } public PPos PxPosition { get { return Util.CenterOfCell( location ); } } public int Altitude { get { return 0; } set { } } } diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index 3d36a3816f..6985f07c83 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -167,6 +167,7 @@ namespace OpenRA.Mods.RA.Move public int ROT { get { return Info.ROT; } } + public WPos CenterPosition { get { return PxPosition.ToWPos(Altitude); } } [Sync] public PPos PxPosition { get; private set; } [Sync] public CPos fromCell { get { return __fromCell; } } [Sync] public CPos toCell { get { return __toCell; } } @@ -231,6 +232,18 @@ namespace OpenRA.Mods.RA.Move PxPosition = px; } + public void SetPosition(Actor self, WPos pos) + { + // TODO: Handle altitude + SetPxPosition(self, PPos.FromWPos(pos)); + } + + public void SetVisualPosition(Actor self, WPos pos) + { + // TODO: Handle altitude + AdjustPxPosition(self, PPos.FromWPos(pos)); + } + public IEnumerable Orders { get { yield return new MoveOrderTargeter(Info); } } // Note: Returns a valid order even if the unit can't move to the target From 6a435752fdbd48cc7b5c4006b788153350a504f6 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 12:17:40 +1200 Subject: [PATCH 19/26] Remove *PxPosition from IOccupySpace/IPositionable. --- OpenRA.Game/Actor.cs | 13 ++----------- OpenRA.Game/Traits/TraitsInterfaces.cs | 4 ---- OpenRA.Mods.RA/Activities/UnloadCargo.cs | 2 +- OpenRA.Mods.RA/Air/Aircraft.cs | 9 +-------- OpenRA.Mods.RA/Air/HeliFly.cs | 2 +- OpenRA.Mods.RA/Air/Land.cs | 2 +- OpenRA.Mods.RA/Crate.cs | 7 ------- OpenRA.Mods.RA/Husk.cs | 2 +- OpenRA.Mods.RA/Move/Drag.cs | 8 ++++---- OpenRA.Mods.RA/Move/Mobile.cs | 17 ++++++----------- OpenRA.Mods.RA/Move/Move.cs | 2 +- OpenRA.Mods.RA/Production.cs | 2 +- 12 files changed, 19 insertions(+), 51 deletions(-) diff --git a/OpenRA.Game/Actor.cs b/OpenRA.Game/Actor.cs index e93c8cacca..bb0a5413ad 100755 --- a/OpenRA.Game/Actor.cs +++ b/OpenRA.Game/Actor.cs @@ -34,17 +34,8 @@ namespace OpenRA public IOccupySpace OccupiesSpace { get { return occupySpace.Value; } } public CPos Location { get { return occupySpace.Value.TopLeft; } } - - public PPos CenterLocation { get { return occupySpace.Value.PxPosition; } } - - public WPos CenterPosition - { - get - { - var altitude = occupySpace.Value != null ? occupySpace.Value.Altitude : 0; - return CenterLocation.ToWPos(altitude); - } - } + public PPos CenterLocation { get { return PPos.FromWPos(occupySpace.Value.CenterPosition); } } + public WPos CenterPosition { get { return occupySpace.Value.CenterPosition; } } public WRot Orientation { diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 8ed42e5c67..8b0f1a404d 100755 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -99,7 +99,6 @@ namespace OpenRA.Traits public interface IOccupySpace { - PPos PxPosition { get; } WPos CenterPosition { get; } CPos TopLeft { get; } IEnumerable> OccupiedCells(); @@ -143,9 +142,6 @@ namespace OpenRA.Traits { bool CanEnterCell(CPos location); void SetPosition(Actor self, CPos cell); - void SetPxPosition(Actor self, PPos px); - void AdjustPxPosition(Actor self, PPos px); /* works like SetPxPosition, but visual only */ - void SetPosition(Actor self, WPos pos); void SetVisualPosition(Actor self, WPos pos); } diff --git a/OpenRA.Mods.RA/Activities/UnloadCargo.cs b/OpenRA.Mods.RA/Activities/UnloadCargo.cs index 946fd23dfd..1d5b7f328d 100644 --- a/OpenRA.Mods.RA/Activities/UnloadCargo.cs +++ b/OpenRA.Mods.RA/Activities/UnloadCargo.cs @@ -90,7 +90,7 @@ namespace OpenRA.Mods.RA.Activities var mobile = actor.Trait(); mobile.Facing = Util.GetFacing(exit - current, mobile.Facing ); mobile.SetPosition(actor, exitTile.Value); - mobile.AdjustPxPosition(actor, PPos.FromWPos(current)); + mobile.SetVisualPosition(actor, current); var speed = mobile.MovementSpeedForCell(actor, exitTile.Value); var length = speed > 0 ? (exit - current).Length / speed : 0; diff --git a/OpenRA.Mods.RA/Air/Aircraft.cs b/OpenRA.Mods.RA/Air/Aircraft.cs index 5e65b70eae..9a1ad6394c 100755 --- a/OpenRA.Mods.RA/Air/Aircraft.cs +++ b/OpenRA.Mods.RA/Air/Aircraft.cs @@ -101,16 +101,9 @@ namespace OpenRA.Mods.RA.Air public void SetPosition(Actor self, CPos cell) { - SetPxPosition(self, Util.CenterOfCell(cell)); + SubPxPosition = Util.CenterOfCell(cell).ToPSubPos(); } - public void SetPxPosition(Actor self, PPos px) - { - SubPxPosition = px.ToPSubPos(); - } - - public void AdjustPxPosition(Actor self, PPos px) { SetPxPosition(self, px); } - public void SetPosition(Actor self, WPos pos) { // TODO: Handle altitude diff --git a/OpenRA.Mods.RA/Air/HeliFly.cs b/OpenRA.Mods.RA/Air/HeliFly.cs index 041edd6256..7a77667909 100755 --- a/OpenRA.Mods.RA/Air/HeliFly.cs +++ b/OpenRA.Mods.RA/Air/HeliFly.cs @@ -39,7 +39,7 @@ namespace OpenRA.Mods.RA.Air var moveDist = aircraft.MovementSpeed * 7 * 1024 / (Game.CellSize * 32); if (dist.HorizontalLengthSquared < moveDist*moveDist) { - aircraft.SubPxPosition = PPos.FromWPos(pos).ToPSubPos(); + aircraft.SetPosition(self, pos); return NextActivity; } diff --git a/OpenRA.Mods.RA/Air/Land.cs b/OpenRA.Mods.RA/Air/Land.cs index cedd99ebdb..36712ce1a4 100755 --- a/OpenRA.Mods.RA/Air/Land.cs +++ b/OpenRA.Mods.RA/Air/Land.cs @@ -35,7 +35,7 @@ namespace OpenRA.Mods.RA.Air var moveDist = aircraft.MovementSpeed * 7 * 1024 / (Game.CellSize * 32); if (d.HorizontalLengthSquared < moveDist*moveDist) { - aircraft.SetPxPosition(self, PPos.FromWPos(Target.CenterPosition)); + aircraft.SetPosition(self, Target.CenterPosition); return NextActivity; } diff --git a/OpenRA.Mods.RA/Crate.cs b/OpenRA.Mods.RA/Crate.cs index e45f56bfa4..db7de2a24b 100644 --- a/OpenRA.Mods.RA/Crate.cs +++ b/OpenRA.Mods.RA/Crate.cs @@ -89,13 +89,6 @@ namespace OpenRA.Mods.RA public PPos PxPosition { get; private set; } public int Altitude { get { return 0; } set { } } - public void SetPxPosition(Actor self, PPos px) - { - SetPosition(self, px.ToCPos()); - } - - public void AdjustPxPosition(Actor self, PPos px) { SetPxPosition(self, px); } - public void SetPosition(Actor self, WPos pos) { SetPosition(self, pos.ToCPos()); } public void SetVisualPosition(Actor self, WPos pos) { SetPosition(self, pos.ToCPos()); } diff --git a/OpenRA.Mods.RA/Husk.cs b/OpenRA.Mods.RA/Husk.cs index c06a96e841..a399e3b7b2 100644 --- a/OpenRA.Mods.RA/Husk.cs +++ b/OpenRA.Mods.RA/Husk.cs @@ -25,9 +25,9 @@ namespace OpenRA.Mods.RA class Husk : IOccupySpace, IFacing, ISync { [Sync] CPos location; + [Sync] PPos PxPosition; public WPos CenterPosition { get { return PxPosition.ToWPos(0); } } - [Sync] public PPos PxPosition { get; private set; } public int Altitude { get { return 0; } set { } } [Sync] public int Facing { get; set; } diff --git a/OpenRA.Mods.RA/Move/Drag.cs b/OpenRA.Mods.RA/Move/Drag.cs index 154e963957..17eeb0d92e 100755 --- a/OpenRA.Mods.RA/Move/Drag.cs +++ b/OpenRA.Mods.RA/Move/Drag.cs @@ -26,14 +26,14 @@ namespace OpenRA.Mods.RA.Move this.length = length; } - public override Activity Tick( Actor self ) + public override Activity Tick(Actor self) { var mobile = self.Trait(); var pos = length > 1 ? WPos.Lerp(start, end, ticks, length - 1) : end; - mobile.AdjustPxPosition(self, PPos.FromWPos(pos)); + mobile.SetVisualPosition(self, pos); if (++ticks >= length) { mobile.IsMoving = false; @@ -44,12 +44,12 @@ namespace OpenRA.Mods.RA.Move return this; } - public override IEnumerable GetTargets( Actor self ) + public override IEnumerable GetTargets(Actor self) { yield return Target.FromPos(end); } // Cannot be cancelled - public override void Cancel( Actor self ) { } + public override void Cancel(Actor self) { } } } diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index 6985f07c83..95d56dca94 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -205,7 +205,7 @@ namespace OpenRA.Mods.RA.Move if (init.Contains()) { this.__fromCell = this.__toCell = init.Get(); - this.PxPosition = PPos.FromWPos(fromCell.CenterPosition + MobileInfo.SubCellOffsets[fromSubCell]); + SetVisualPosition(self, fromCell.CenterPosition + MobileInfo.SubCellOffsets[fromSubCell]); } this.Facing = init.Contains() ? init.Get() : info.InitialFacing; @@ -215,15 +215,7 @@ namespace OpenRA.Mods.RA.Move public void SetPosition(Actor self, CPos cell) { SetLocation(cell,fromSubCell, cell,fromSubCell); - PxPosition = PPos.FromWPos(fromCell.CenterPosition + MobileInfo.SubCellOffsets[fromSubCell]); - FinishedMoving(self); - } - - public void SetPxPosition(Actor self, PPos px) - { - var cell = px.ToCPos(); - SetLocation(cell,fromSubCell, cell,fromSubCell); - PxPosition = px; + SetVisualPosition(self, fromCell.CenterPosition + MobileInfo.SubCellOffsets[fromSubCell]); FinishedMoving(self); } @@ -235,7 +227,10 @@ namespace OpenRA.Mods.RA.Move public void SetPosition(Actor self, WPos pos) { // TODO: Handle altitude - SetPxPosition(self, PPos.FromWPos(pos)); + var cell = pos.ToCPos(); + SetLocation(cell,fromSubCell, cell,fromSubCell); + PxPosition = PPos.FromWPos(pos); + FinishedMoving(self); } public void SetVisualPosition(Actor self, WPos pos) diff --git a/OpenRA.Mods.RA/Move/Move.cs b/OpenRA.Mods.RA/Move/Move.cs index 744d2a7373..f8c972911c 100755 --- a/OpenRA.Mods.RA/Move/Move.cs +++ b/OpenRA.Mods.RA/Move/Move.cs @@ -328,7 +328,7 @@ namespace OpenRA.Mods.RA.Move void UpdateCenterLocation(Actor self, Mobile mobile) { - mobile.AdjustPxPosition(self, PPos.FromWPos(WPos.Lerp(from, to, moveFraction, moveFractionTotal))); + mobile.SetVisualPosition(self, WPos.Lerp(from, to, moveFraction, moveFractionTotal)); if (moveFraction >= moveFractionTotal) mobile.Facing = toFacing & 0xFF; diff --git a/OpenRA.Mods.RA/Production.cs b/OpenRA.Mods.RA/Production.cs index a87efdba94..ad6c8241e3 100755 --- a/OpenRA.Mods.RA/Production.cs +++ b/OpenRA.Mods.RA/Production.cs @@ -68,7 +68,7 @@ namespace OpenRA.Mods.RA // TODO: Move this into an *Init // TODO: We should be adjusting the actual position for aircraft, not just visuals. var teleportable = newUnit.Trait(); - teleportable.AdjustPxPosition(newUnit, PPos.FromWPos(spawn)); + teleportable.SetVisualPosition(newUnit, spawn); // TODO: Generalize this for non-mobile (e.g. aircraft) too // Remember to update the Enter activity too From e23c1ad33e7a6e515bfd8f1a05e67113c94aa121 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 13:01:36 +1200 Subject: [PATCH 20/26] Rewrite husks using world coords. --- OpenRA.Mods.RA/Husk.cs | 95 ++++++++++++++++-------------------- OpenRA.Mods.RA/LeavesHusk.cs | 2 +- OpenRA.Mods.RA/Move/Drag.cs | 14 ++++-- mods/cnc/rules/defaults.yaml | 1 + mods/d2k/rules/defaults.yaml | 1 + mods/ra/rules/defaults.yaml | 1 + 6 files changed, 57 insertions(+), 57 deletions(-) diff --git a/OpenRA.Mods.RA/Husk.cs b/OpenRA.Mods.RA/Husk.cs index a399e3b7b2..9e18197c68 100644 --- a/OpenRA.Mods.RA/Husk.cs +++ b/OpenRA.Mods.RA/Husk.cs @@ -9,88 +9,79 @@ #endregion using System.Collections.Generic; +using System.Linq; using OpenRA.FileFormats; -using OpenRA.Traits; using OpenRA.Mods.RA.Move; +using OpenRA.Traits; namespace OpenRA.Mods.RA { class HuskInfo : ITraitInfo, IFacingInfo { - public object Create( ActorInitializer init ) { return new Husk( init ); } + public readonly string[] AllowedTerrain = { }; + + public object Create(ActorInitializer init) { return new Husk(init, this); } public int GetInitialFacing() { return 128; } } - class Husk : IOccupySpace, IFacing, ISync + class Husk : IPositionable, IFacing, ISync { - [Sync] CPos location; - [Sync] PPos PxPosition; + readonly HuskInfo info; + readonly Actor self; - public WPos CenterPosition { get { return PxPosition.ToWPos(0); } } + [Sync] public CPos TopLeft { get; private set; } + [Sync] public WPos CenterPosition { get; private set; } + [Sync] public int Facing { get; set; } + + public int ROT { get { return 0; } } public int Altitude { get { return 0; } set { } } - [Sync] public int Facing { get; set; } - public int ROT { get { return 0; } } - - public Husk(ActorInitializer init) + public Husk(ActorInitializer init, HuskInfo info) { - var self = init.self; - location = init.Get(); - PxPosition = init.Contains() ? init.Get() : Util.CenterOfCell(location); - Facing = init.Contains() ? init.Get() : 128; + this.info = info; + this.self = init.self; - var speed = init.Contains() ? init.Get() : 0; - if (speed > 0) - { - var to = Util.CenterOfCell(location); - var length = (int)((to - PxPosition).Length * 3 / speed); - self.QueueActivity(new DragHusk(PxPosition, to, length, this)); - } + TopLeft = init.Get(); + var ppos = init.Contains() ? init.Get() : Util.CenterOfCell(TopLeft); + CenterPosition = ppos.ToWPos(0); + Facing = init.Contains() ? init.Get() : 128; + + var speed = init.Contains() ? init.Get() : 0; + var distance = (TopLeft.CenterPosition - CenterPosition).Length; + if (speed > 0 && distance > 0) + self.QueueActivity(new Drag(CenterPosition, TopLeft.CenterPosition, distance / speed)); } - public CPos TopLeft { get { return location; } } - public IEnumerable> OccupiedCells() { yield return Pair.New(TopLeft, SubCell.FullCell); } - - class DragHusk : Activity + public bool CanEnterCell(CPos cell) { - Husk husk; - PPos endLocation; - PPos startLocation; - int length; + if (!self.World.Map.IsInMap(cell.X, cell.Y)) + return false; - public DragHusk(PPos start, PPos end, int length, Husk husk) - { - startLocation = start; - endLocation = end; - this.length = length; - this.husk = husk; - } + if (!info.AllowedTerrain.Contains(self.World.GetTerrainType(cell))) + return false; - int ticks = 0; - public override Activity Tick( Actor self ) - { - if (ticks >= length || length <= 1) - { - husk.PxPosition = endLocation; - return NextActivity; - } + return !self.World.ActorMap.AnyUnitsAt(cell); + } - husk.PxPosition = PPos.Lerp(startLocation, endLocation, ticks++, length - 1); - return this; - } + public void SetPosition(Actor self, CPos cell) { SetPosition(self, cell.CenterPosition); } + public void SetVisualPosition(Actor self, WPos pos) { CenterPosition = pos; } - public override IEnumerable GetTargets( Actor self ) { yield break; } - public override void Cancel( Actor self ) { } + public void SetPosition(Actor self, WPos pos) + { + self.World.ActorMap.Remove(self, this); + CenterPosition = pos; + TopLeft = pos.ToCPos(); + self.World.ActorMap.Add(self, this); } } public class HuskSpeedInit : IActorInit { - [FieldFromYamlKey] public readonly int value = 0; + [FieldFromYamlKey] readonly int value = 0; public HuskSpeedInit() { } - public HuskSpeedInit( int init ) { value = init; } - public int Value( World world ) { return value; } + public HuskSpeedInit(int init) { value = init; } + public int Value(World world) { return value; } } } diff --git a/OpenRA.Mods.RA/LeavesHusk.cs b/OpenRA.Mods.RA/LeavesHusk.cs index f5efe15fc1..7b04b1d9c2 100644 --- a/OpenRA.Mods.RA/LeavesHusk.cs +++ b/OpenRA.Mods.RA/LeavesHusk.cs @@ -49,7 +49,7 @@ namespace OpenRA.Mods.RA if (mobile != null) { if (!mobile.CanEnterCell(self.Location, self, false)) return; - td.Add(new HuskSpeedInit(mobile.MovementSpeedForCell(self, self.Location) * 3 * Game.CellSize / 1024)); + td.Add(new HuskSpeedInit(mobile.MovementSpeedForCell(self, self.Location))); } var aircraft = self.TraitOrDefault(); diff --git a/OpenRA.Mods.RA/Move/Drag.cs b/OpenRA.Mods.RA/Move/Drag.cs index 17eeb0d92e..41c8ff89ed 100755 --- a/OpenRA.Mods.RA/Move/Drag.cs +++ b/OpenRA.Mods.RA/Move/Drag.cs @@ -28,19 +28,25 @@ namespace OpenRA.Mods.RA.Move public override Activity Tick(Actor self) { - var mobile = self.Trait(); + var positionable = self.Trait(); + var mobile = positionable as Mobile; + var pos = length > 1 ? WPos.Lerp(start, end, ticks, length - 1) : end; - mobile.SetVisualPosition(self, pos); + positionable.SetVisualPosition(self, pos); if (++ticks >= length) { - mobile.IsMoving = false; + if (mobile != null) + mobile.IsMoving = false; + return NextActivity; } - mobile.IsMoving = true; + if (mobile != null) + mobile.IsMoving = true; + return this; } diff --git a/mods/cnc/rules/defaults.yaml b/mods/cnc/rules/defaults.yaml index f9b9dd77d5..91240d58a8 100644 --- a/mods/cnc/rules/defaults.yaml +++ b/mods/cnc/rules/defaults.yaml @@ -449,6 +449,7 @@ Armor: Type: Light Husk: + AllowedTerrain: Clear, Rough, Road, Tiberium, BlueTiberium, Beach HiddenUnderFog: AppearsOnRadar: Burns: diff --git a/mods/d2k/rules/defaults.yaml b/mods/d2k/rules/defaults.yaml index f465db8147..af1f33ef81 100644 --- a/mods/d2k/rules/defaults.yaml +++ b/mods/d2k/rules/defaults.yaml @@ -78,6 +78,7 @@ Armor: Type: Light Husk: + AllowedTerrain: Sand, Rock, Transition, Concrete, Spice, SpiceBlobs, Dune HiddenUnderFog: AppearsOnRadar: Burns: diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml index b9abf0f52b..d43f5c585e 100644 --- a/mods/ra/rules/defaults.yaml +++ b/mods/ra/rules/defaults.yaml @@ -373,6 +373,7 @@ ^Husk: Husk: + AllowedTerrain: Clear, Rough, Road, Ore, Gems, Beach RenderUnit: Health: HP: 140 From 29009fe3a402d57a3ea502e5055e7b5555222480 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 13:12:42 +1200 Subject: [PATCH 21/26] Allow husks to chronoshift and return to their parent actors location. --- OpenRA.Mods.RA/Chronoshiftable.cs | 66 +++++++++++++++++++++---------- OpenRA.Mods.RA/LeavesHusk.cs | 23 ++++++----- mods/ra/rules/defaults.yaml | 1 + 3 files changed, 60 insertions(+), 30 deletions(-) diff --git a/OpenRA.Mods.RA/Chronoshiftable.cs b/OpenRA.Mods.RA/Chronoshiftable.cs index 2c70fffd64..da7311defe 100755 --- a/OpenRA.Mods.RA/Chronoshiftable.cs +++ b/OpenRA.Mods.RA/Chronoshiftable.cs @@ -9,6 +9,7 @@ #endregion using System.Drawing; +using OpenRA.FileFormats; using OpenRA.Mods.RA.Activities; using OpenRA.Traits; @@ -19,38 +20,43 @@ namespace OpenRA.Mods.RA public readonly bool ExplodeInstead = false; public readonly string ChronoshiftSound = "chrono2.aud"; - public object Create(ActorInitializer init) { return new Chronoshiftable(this); } + public object Create(ActorInitializer init) { return new Chronoshiftable(init, this); } } public class Chronoshiftable : ITick, ISync, ISelectionBar { - // Return-to-sender logic - [Sync] CPos chronoshiftOrigin; - [Sync] int chronoshiftReturnTicks = 0; + readonly ChronoshiftableInfo info; Actor chronosphere; bool killCargo; - int TotalTicks; - readonly ChronoshiftableInfo info; + int duration; - public Chronoshiftable(ChronoshiftableInfo info) + // Return-to-sender logic + [Sync] public CPos Origin; + [Sync] public int ReturnTicks = 0; + + public Chronoshiftable(ActorInitializer init, ChronoshiftableInfo info) { this.info = info; + + if (init.Contains()) + ReturnTicks = init.Get(); + + if (init.Contains()) + Origin = init.Get(); } public void Tick(Actor self) { - if (chronoshiftReturnTicks <= 0) + if (ReturnTicks <= 0) return; - if (chronoshiftReturnTicks > 0) - chronoshiftReturnTicks--; - // Return to original location - if (chronoshiftReturnTicks == 0) + if (--ReturnTicks == 0) { self.CancelActivity(); + // TODO: need a new Teleport method that will move to the closest available cell - self.QueueActivity(new Teleport(chronosphere, chronoshiftOrigin, killCargo, info.ChronoshiftSound)); + self.QueueActivity(new Teleport(chronosphere, Origin, killCargo, info.ChronoshiftSound)); } } @@ -58,25 +64,27 @@ namespace OpenRA.Mods.RA public virtual bool CanChronoshiftTo(Actor self, CPos targetLocation) { // TODO: Allow enemy units to be chronoshifted into bad terrain to kill them - return (self.HasTrait() && self.Trait().CanEnterCell(targetLocation)); + return self.HasTrait() && self.Trait().CanEnterCell(targetLocation); } public virtual bool Teleport(Actor self, CPos targetLocation, int duration, bool killCargo, Actor chronosphere) { - if (info.ExplodeInstead) // some things appear chronoshiftable, but instead they just die. + // some things appear chronoshiftable, but instead they just die. + if (info.ExplodeInstead) { self.World.AddFrameEndTask(w => { // damage is inflicted by the chronosphere - if (!self.Destroyed) self.InflictDamage(chronosphere, int.MaxValue, null); + if (!self.Destroyed) + self.InflictDamage(chronosphere, int.MaxValue, null); }); return true; } /// Set up return-to-sender info - chronoshiftOrigin = self.Location; - chronoshiftReturnTicks = duration; - TotalTicks = duration; + Origin = self.Location; + ReturnTicks = duration; + this.duration = duration; this.chronosphere = chronosphere; this.killCargo = killCargo; @@ -90,11 +98,27 @@ namespace OpenRA.Mods.RA // Show the remaining time as a bar public float GetValue() { - if (chronoshiftReturnTicks == 0) // otherwise an empty bar is rendered all the time + if (ReturnTicks == 0) // otherwise an empty bar is rendered all the time return 0f; - return (float)chronoshiftReturnTicks / TotalTicks; + return (float)ReturnTicks / duration; } + public Color GetColor() { return Color.White; } } + + public class ChronoshiftReturnInit : IActorInit + { + [FieldFromYamlKey] readonly int value = 0; + public ChronoshiftReturnInit() { } + public ChronoshiftReturnInit(int init) { value = init; } + public int Value(World world) { return value; } + } + + public class ChronoshiftOriginInit : IActorInit + { + [FieldFromYamlKey] readonly CPos value; + public ChronoshiftOriginInit(CPos init) { value = init; } + public CPos Value(World world) { return value; } + } } diff --git a/OpenRA.Mods.RA/LeavesHusk.cs b/OpenRA.Mods.RA/LeavesHusk.cs index 7b04b1d9c2..8dce4cdb42 100644 --- a/OpenRA.Mods.RA/LeavesHusk.cs +++ b/OpenRA.Mods.RA/LeavesHusk.cs @@ -21,16 +21,14 @@ namespace OpenRA.Mods.RA [ActorReference] public readonly string HuskActor = null; - public object Create( ActorInitializer init ) { return new LeavesHusk(this); } + public object Create(ActorInitializer init) { return new LeavesHusk(this); } } public class LeavesHusk : INotifyKilled { - LeavesHuskInfo Info; - public LeavesHusk(LeavesHuskInfo info) - { - Info = info; - } + LeavesHuskInfo info; + + public LeavesHusk(LeavesHuskInfo info) { this.info = info; } public void Killed(Actor self, AttackInfo e) { @@ -58,19 +56,26 @@ namespace OpenRA.Mods.RA var facing = self.TraitOrDefault(); if (facing != null) - td.Add(new FacingInit( facing.Facing )); + td.Add(new FacingInit(facing.Facing)); // TODO: This will only take the first turret if there are multiple // This isn't a problem with the current units, but may be a problem for mods var turreted = self.TraitsImplementing().FirstOrDefault(); if (turreted != null) - td.Add( new TurretFacingInit(turreted.turretFacing) ); + td.Add(new TurretFacingInit(turreted.turretFacing)); + + var chronoshiftable = self.TraitOrDefault(); + if (chronoshiftable != null && chronoshiftable.ReturnTicks > 0) + { + td.Add(new ChronoshiftOriginInit(chronoshiftable.Origin)); + td.Add(new ChronoshiftReturnInit(chronoshiftable.ReturnTicks)); + } var huskActor = self.TraitsImplementing() .Select(ihm => ihm.HuskActor(self)) .FirstOrDefault(a => a != null); - w.CreateActor(huskActor ?? Info.HuskActor, td); + w.CreateActor(huskActor ?? info.HuskActor, td); }); } } diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml index d43f5c585e..e5259b6b02 100644 --- a/mods/ra/rules/defaults.yaml +++ b/mods/ra/rules/defaults.yaml @@ -386,6 +386,7 @@ Types:Husk BelowUnits: BodyOrientation: + Chronoshiftable: ^HelicopterHusk: Inherits: ^Husk From c3f04cc32e520ff2904b1c1493c7cf7093856da4 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 13:42:25 +1200 Subject: [PATCH 22/26] Convert non-aircraft positioning to world coords. This removes the incomplete and unused hover code on Mobile, which would be more trouble that it is currently worth to carry over. --- OpenRA.FileFormats/WVec.cs | 1 + OpenRA.Game/Actor.cs | 5 ++-- OpenRA.Game/Traits/TraitsInterfaces.cs | 5 +--- OpenRA.Game/Traits/Waypoint.cs | 5 +--- OpenRA.Mods.RA/Activities/Leap.cs | 2 +- OpenRA.Mods.RA/Air/Aircraft.cs | 4 +-- OpenRA.Mods.RA/Air/EjectOnDeath.cs | 12 +++++---- OpenRA.Mods.RA/Armament.cs | 6 ++--- OpenRA.Mods.RA/Buildings/Building.cs | 10 +++---- OpenRA.Mods.RA/Cargo.cs | 9 +++---- OpenRA.Mods.RA/CarpetBomb.cs | 8 +++--- OpenRA.Mods.RA/Crate.cs | 36 ++++++++++++-------------- OpenRA.Mods.RA/Effects/Missile.cs | 6 ++--- OpenRA.Mods.RA/Husk.cs | 3 +-- OpenRA.Mods.RA/Mine.cs | 6 ++--- OpenRA.Mods.RA/Move/Mobile.cs | 26 +++++++------------ OpenRA.Mods.RA/Move/Move.cs | 9 ------- OpenRA.Mods.RA/Render/WithRotor.cs | 2 +- OpenRA.Mods.RA/Render/WithShadow.cs | 6 ++--- mods/d2k/rules/aircraft.yaml | 2 +- 20 files changed, 67 insertions(+), 96 deletions(-) diff --git a/OpenRA.FileFormats/WVec.cs b/OpenRA.FileFormats/WVec.cs index ab96bea054..72b2df78b9 100644 --- a/OpenRA.FileFormats/WVec.cs +++ b/OpenRA.FileFormats/WVec.cs @@ -39,6 +39,7 @@ namespace OpenRA public long LengthSquared { get { return (long)X * X + (long)Y * Y + (long)Z * Z; } } public int Length { get { return (int)Math.Sqrt(LengthSquared); } } public long HorizontalLengthSquared { get { return (long)X * X + (long)Y * Y; } } + public int HorizontalLength { get { return (int)Math.Sqrt(HorizontalLengthSquared); } } public WVec Rotate(WRot rot) { diff --git a/OpenRA.Game/Actor.cs b/OpenRA.Game/Actor.cs index bb0a5413ad..dc77cd1e13 100755 --- a/OpenRA.Game/Actor.cs +++ b/OpenRA.Game/Actor.cs @@ -135,10 +135,11 @@ namespace OpenRA var ios = occupySpace.Value; if (ios != null) { - loc -= new PVecInt(0, ios.Altitude); + var altitude = ios.CenterPosition.Z * Game.CellSize / 1024; + loc -= new PVecInt(0, altitude); if (useAltitude) - size = new PVecInt(size.X, size.Y + ios.Altitude); + size = new PVecInt(size.X, size.Y + altitude); } return new Rectangle(loc.X, loc.Y, size.X, size.Y); diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 8b0f1a404d..e979a7ce14 100755 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -97,15 +97,12 @@ namespace OpenRA.Traits public interface IVisibilityModifier { bool IsVisible(Actor self, Player byPlayer); } public interface IRadarColorModifier { Color RadarColorOverride(Actor self); } + public interface IOccupySpaceInfo { } public interface IOccupySpace { WPos CenterPosition { get; } CPos TopLeft { get; } IEnumerable> OccupiedCells(); - - // TODO: We shouldn't expose the setter here - // This will be going away soon, so isn't a big deal - int Altitude { get; set; } } public static class IOccupySpaceExts diff --git a/OpenRA.Game/Traits/Waypoint.cs b/OpenRA.Game/Traits/Waypoint.cs index 0223fa9fda..2ea8e2a381 100644 --- a/OpenRA.Game/Traits/Waypoint.cs +++ b/OpenRA.Game/Traits/Waypoint.cs @@ -13,7 +13,7 @@ using OpenRA.FileFormats; namespace OpenRA.Traits { - class WaypointInfo : ITraitInfo + class WaypointInfo : ITraitInfo, IOccupySpaceInfo { public object Create( ActorInitializer init ) { return new Waypoint( init ); } } @@ -28,10 +28,7 @@ namespace OpenRA.Traits } public CPos TopLeft { get { return location; } } - public IEnumerable> OccupiedCells() { yield break; } public WPos CenterPosition { get { return location.CenterPosition; } } - public PPos PxPosition { get { return Util.CenterOfCell(location); } } - public int Altitude { get { return 0; } set { } } } } diff --git a/OpenRA.Mods.RA/Activities/Leap.cs b/OpenRA.Mods.RA/Activities/Leap.cs index 2d403cece1..9ab86d9335 100644 --- a/OpenRA.Mods.RA/Activities/Leap.cs +++ b/OpenRA.Mods.RA/Activities/Leap.cs @@ -55,7 +55,7 @@ namespace OpenRA.Mods.RA.Activities if (ticks == 0 && IsCanceled) return NextActivity; - mobile.AdjustPxPosition(self, PPos.FromWPosHackZ(WPos.LerpQuadratic(from, to, angle, ++ticks, length))); + mobile.SetVisualPosition(self, WPos.LerpQuadratic(from, to, angle, ++ticks, length)); if (ticks >= length) { mobile.SetLocation(mobile.toCell, mobile.toSubCell, mobile.toCell, mobile.toSubCell); diff --git a/OpenRA.Mods.RA/Air/Aircraft.cs b/OpenRA.Mods.RA/Air/Aircraft.cs index 9a1ad6394c..c4a454ef14 100755 --- a/OpenRA.Mods.RA/Air/Aircraft.cs +++ b/OpenRA.Mods.RA/Air/Aircraft.cs @@ -20,7 +20,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA.Air { - public class AircraftInfo : ITraitInfo, IFacingInfo, UsesInit, UsesInit, UsesInit + public class AircraftInfo : ITraitInfo, IFacingInfo, IOccupySpaceInfo, UsesInit, UsesInit, UsesInit { public readonly int CruiseAltitude = 30; [ActorReference] @@ -78,7 +78,7 @@ namespace OpenRA.Mods.RA.Air public Actor GetActorBelow() { - if (self.Trait().Altitude != 0) + if (Altitude != 0) return null; // not on the ground. return self.World.FindActorsInBox(self.CenterPosition, self.CenterPosition) diff --git a/OpenRA.Mods.RA/Air/EjectOnDeath.cs b/OpenRA.Mods.RA/Air/EjectOnDeath.cs index 24e357239b..e6d213c0e6 100644 --- a/OpenRA.Mods.RA/Air/EjectOnDeath.cs +++ b/OpenRA.Mods.RA/Air/EjectOnDeath.cs @@ -20,6 +20,7 @@ namespace OpenRA.Mods.RA public readonly string PilotActor = "E1"; public readonly int SuccessRate = 50; public readonly string ChuteSound = "chute1.aud"; + public readonly WRange MinimumEjectHeight = new WRange(427); } public class EjectOnDeath : INotifyKilled @@ -29,14 +30,15 @@ namespace OpenRA.Mods.RA var info = self.Info.Traits.Get(); var pilot = self.World.CreateActor(false, info.PilotActor.ToLowerInvariant(), new TypeDictionary { new OwnerInit(self.Owner) }); - var r = self.World.SharedRandom.Next(1, 100); - var aircraft = self.Trait(); - if (IsSuitableCell(pilot, self.Location) && r > 100 - info.SuccessRate && aircraft.Altitude > 10 + var r = self.World.SharedRandom.Next(1, 100); + var cp = self.CenterPosition; + + if (IsSuitableCell(pilot, self.Location) && r > 100 - info.SuccessRate && cp.Z > info.MinimumEjectHeight.Range && self.Owner.WinState != WinState.Lost) { - self.World.AddFrameEndTask(w => w.Add(new Parachute(pilot, self.CenterPosition))); - Sound.Play(info.ChuteSound, self.CenterPosition); + self.World.AddFrameEndTask(w => w.Add(new Parachute(pilot, cp))); + Sound.Play(info.ChuteSound, cp); } else pilot.Destroy(); diff --git a/OpenRA.Mods.RA/Armament.cs b/OpenRA.Mods.RA/Armament.cs index 5bee9aaa0a..7eb5faf061 100755 --- a/OpenRA.Mods.RA/Armament.cs +++ b/OpenRA.Mods.RA/Armament.cs @@ -120,8 +120,6 @@ namespace OpenRA.Mods.RA return; var barrel = Barrels[Burst % Barrels.Length]; - var destios = target.IsActor ? target.Actor.TraitOrDefault() : null; - var muzzlePosition = self.CenterPosition + MuzzleOffset(self, barrel); var legacyMuzzlePosition = PPos.FromWPos(muzzlePosition); var legacyMuzzleAltitude = Game.CellSize*muzzlePosition.Z/1024; @@ -135,8 +133,8 @@ namespace OpenRA.Mods.RA src = legacyMuzzlePosition, srcAltitude = legacyMuzzleAltitude, - dest = target.CenterLocation, - destAltitude = destios != null ? destios.Altitude : 0, + dest = PPos.FromWPos(target.CenterPosition), + destAltitude = target.CenterPosition.Z * Game.CellSize / 1024, facing = legacyFacing, diff --git a/OpenRA.Mods.RA/Buildings/Building.cs b/OpenRA.Mods.RA/Buildings/Building.cs index 114809e683..ef99c3eb38 100755 --- a/OpenRA.Mods.RA/Buildings/Building.cs +++ b/OpenRA.Mods.RA/Buildings/Building.cs @@ -20,7 +20,7 @@ namespace OpenRA.Mods.RA.Buildings public class GivesBuildableAreaInfo : TraitInfo {} public class GivesBuildableArea {} - public class BuildingInfo : ITraitInfo, UsesInit + public class BuildingInfo : ITraitInfo, IOccupySpaceInfo, UsesInit { [Desc("If negative, it will drain power, if positive, it will provide power.")] public readonly int Power = 0; @@ -96,7 +96,6 @@ namespace OpenRA.Mods.RA.Buildings [Sync] readonly CPos topLeft; PowerManager PlayerPower; - PPos pxPosition; [Sync] public bool Locked; /* shared activity lock: undeploy, sell, capture, etc */ @@ -110,9 +109,7 @@ namespace OpenRA.Mods.RA.Buildings public void Unlock() { Locked = false; } public CPos TopLeft { get { return topLeft; } } - public WPos CenterPosition { get { return PxPosition.ToWPos(0); } } - public PPos PxPosition { get { return pxPosition; } } - public int Altitude { get { return 0; } set { } } + public WPos CenterPosition { get; private set; } public IEnumerable ProvidesPrerequisites { get { yield return self.Info.Name; } } @@ -126,8 +123,7 @@ namespace OpenRA.Mods.RA.Buildings occupiedCells = FootprintUtils.UnpathableTiles( self.Info.Name, Info, TopLeft ) .Select(c => Pair.New(c, SubCell.FullCell)).ToArray(); - var position = topLeft.CenterPosition + FootprintUtils.CenterOffset(Info); - pxPosition = PPos.FromWPosHackZ(position); + CenterPosition = topLeft.CenterPosition + FootprintUtils.CenterOffset(Info); } public int GetPowerUsage() diff --git a/OpenRA.Mods.RA/Cargo.cs b/OpenRA.Mods.RA/Cargo.cs index 3be939620f..af77268715 100644 --- a/OpenRA.Mods.RA/Cargo.cs +++ b/OpenRA.Mods.RA/Cargo.cs @@ -17,14 +17,14 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA { - public class CargoInfo : ITraitInfo + public class CargoInfo : ITraitInfo, Requires { public readonly int MaxWeight = 0; public readonly int PipCount = 0; public readonly string[] Types = { }; public readonly int UnloadFacing = 0; public readonly string[] InitialUnits = { }; - public readonly int minimalUnloadAltitude = 0; + public readonly WRange MaximumUnloadAltitude = WRange.Zero; public object Create( ActorInitializer init ) { return new Cargo( init, this ); } } @@ -93,7 +93,7 @@ namespace OpenRA.Mods.RA // Cannot unload mid-air var ios = self.TraitOrDefault(); - if (ios != null && ios.Altitude > info.minimalUnloadAltitude) + if (ios != null && ios.CenterPosition.Z > info.MaximumUnloadAltitude.Range) return false; // TODO: Check if there is a free tile to unload to @@ -106,8 +106,7 @@ namespace OpenRA.Mods.RA return false; // Cannot load mid-air - var ios = self.TraitOrDefault(); - return ios == null || ios.Altitude == info.minimalUnloadAltitude; + return self.CenterPosition.Z < info.MaximumUnloadAltitude.Range; } public string CursorForOrder(Actor self, Order order) diff --git a/OpenRA.Mods.RA/CarpetBomb.cs b/OpenRA.Mods.RA/CarpetBomb.cs index cfdcb607f8..13a40c98ae 100644 --- a/OpenRA.Mods.RA/CarpetBomb.cs +++ b/OpenRA.Mods.RA/CarpetBomb.cs @@ -56,12 +56,14 @@ namespace OpenRA.Mods.RA var weapon = Rules.Weapons[info.Weapon.ToLowerInvariant()]; dropDelay = weapon.ROF; + var centerLocation = PPos.FromWPos(self.CenterPosition); + var altitude = self.CenterPosition.Z * Game.CellSize / 1024; var args = new ProjectileArgs { - srcAltitude = self.Trait().Altitude, + srcAltitude = altitude, destAltitude = 0, - src = self.CenterLocation, - dest = self.CenterLocation, + src = centerLocation, + dest = centerLocation, facing = self.Trait().Facing, firedBy = self, weapon = weapon diff --git a/OpenRA.Mods.RA/Crate.cs b/OpenRA.Mods.RA/Crate.cs index db7de2a24b..b1ab283250 100644 --- a/OpenRA.Mods.RA/Crate.cs +++ b/OpenRA.Mods.RA/Crate.cs @@ -11,12 +11,12 @@ using System.Collections.Generic; using System.Linq; using OpenRA.FileFormats; -using OpenRA.Traits; using OpenRA.Mods.RA.Buildings; +using OpenRA.Traits; namespace OpenRA.Mods.RA { - class CrateInfo : ITraitInfo, Requires + class CrateInfo : ITraitInfo, IOccupySpaceInfo, Requires { public readonly int Lifetime = 5; // Seconds public readonly string[] TerrainTypes = { }; @@ -27,23 +27,22 @@ namespace OpenRA.Mods.RA class Crate : ITick, IPositionable, ICrushable, ISync, INotifyParachuteLanded { readonly Actor self; + readonly CrateInfo info; + bool collected; + [Sync] int ticks; [Sync] public CPos Location; - CrateInfo Info; - bool collected; public Crate(ActorInitializer init, CrateInfo info) { this.self = init.self; + this.info = info; + if (init.Contains()) - { - this.Location = init.Get(); - PxPosition = Util.CenterOfCell(Location); - } - this.Info = info; + SetPosition(self, init.Get()); } - public void WarnCrush(Actor crusher) {} + public void WarnCrush(Actor crusher) { } public void OnCrush(Actor crusher) { @@ -78,17 +77,14 @@ namespace OpenRA.Mods.RA public void Tick(Actor self) { - if( ++ticks >= Info.Lifetime * 25 ) + if (++ticks >= info.Lifetime * 25) self.Destroy(); } public CPos TopLeft { get { return Location; } } - public IEnumerable> OccupiedCells() { yield return Pair.New( Location, SubCell.FullCell); } - - public WPos CenterPosition { get { return PxPosition.ToWPos(Altitude); } } - public PPos PxPosition { get; private set; } - public int Altitude { get { return 0; } set { } } + public IEnumerable> OccupiedCells() { yield return Pair.New(Location, SubCell.FullCell); } + public WPos CenterPosition { get; private set; } public void SetPosition(Actor self, WPos pos) { SetPosition(self, pos.ToCPos()); } public void SetVisualPosition(Actor self, WPos pos) { SetPosition(self, pos.ToCPos()); } @@ -96,7 +92,7 @@ namespace OpenRA.Mods.RA { if (!self.World.Map.IsInMap(cell.X, cell.Y)) return false; var type = self.World.GetTerrainType(cell); - if (!Info.TerrainTypes.Contains(type)) + if (!info.TerrainTypes.Contains(type)) return false; if (self.World.WorldActor.Trait().GetBuildingAt(cell) != null) return false; @@ -107,18 +103,18 @@ namespace OpenRA.Mods.RA public void SetPosition(Actor self, CPos cell) { - if( self.IsInWorld ) + if (self.IsInWorld) self.World.ActorMap.Remove(self, this); Location = cell; - PxPosition = Util.CenterOfCell(cell); + CenterPosition = cell.CenterPosition; var seq = self.World.GetTerrainInfo(cell).IsWater ? "water" : "land"; var rs = self.Trait(); if (seq != rs.anim.CurrentSequence.Name) rs.anim.PlayRepeating(seq); - if( self.IsInWorld ) + if (self.IsInWorld) self.World.ActorMap.Add(self, this); } diff --git a/OpenRA.Mods.RA/Effects/Missile.cs b/OpenRA.Mods.RA/Effects/Missile.cs index 1c8297e1ed..7eae2bffdb 100755 --- a/OpenRA.Mods.RA/Effects/Missile.cs +++ b/OpenRA.Mods.RA/Effects/Missile.cs @@ -97,9 +97,9 @@ namespace OpenRA.Mods.RA.Effects // In pixels var dist = Args.target.CenterLocation + offset - PxPosition; - var targetAltitude = 0; - if (Args.target.IsValid && Args.target.IsActor && Args.target.Actor.HasTrait()) - targetAltitude = Args.target.Actor.Trait().Altitude; + var targetAltitude = 0; + if (Args.target.IsValid) + targetAltitude = Args.target.CenterPosition.Z * Game.CellSize / 1024; var jammed = Info.Jammable && world.ActorsWithTrait().Any(tp => (tp.Actor.CenterLocation - PxPosition).ToCVec().Length <= tp.Trait.Range diff --git a/OpenRA.Mods.RA/Husk.cs b/OpenRA.Mods.RA/Husk.cs index 9e18197c68..a46f577362 100644 --- a/OpenRA.Mods.RA/Husk.cs +++ b/OpenRA.Mods.RA/Husk.cs @@ -16,7 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA { - class HuskInfo : ITraitInfo, IFacingInfo + class HuskInfo : ITraitInfo, IOccupySpaceInfo, IFacingInfo { public readonly string[] AllowedTerrain = { }; @@ -35,7 +35,6 @@ namespace OpenRA.Mods.RA [Sync] public int Facing { get; set; } public int ROT { get { return 0; } } - public int Altitude { get { return 0; } set { } } public Husk(ActorInitializer init, HuskInfo info) { diff --git a/OpenRA.Mods.RA/Mine.cs b/OpenRA.Mods.RA/Mine.cs index 9b34282c07..3c3ad8df31 100644 --- a/OpenRA.Mods.RA/Mine.cs +++ b/OpenRA.Mods.RA/Mine.cs @@ -17,7 +17,7 @@ using OpenRA.FileFormats; namespace OpenRA.Mods.RA { - class MineInfo : ITraitInfo + class MineInfo : ITraitInfo, IOccupySpaceInfo { public readonly string[] CrushClasses = { }; public readonly bool AvoidFriendly = true; @@ -61,9 +61,7 @@ namespace OpenRA.Mods.RA public CPos TopLeft { get { return location; } } public IEnumerable> OccupiedCells() { yield return Pair.New(TopLeft, SubCell.FullCell); } - public WPos CenterPosition { get { return PxPosition.ToWPos(0); } } - public PPos PxPosition { get { return Util.CenterOfCell( location ); } } - public int Altitude { get { return 0; } set { } } + public WPos CenterPosition { get { return location.CenterPosition; } } } /* tag trait for stuff that shouldnt trigger mines */ diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index 95d56dca94..86ef2231a8 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -19,7 +19,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA.Move { [Desc("Unit is able to move.")] - public class MobileInfo : ITraitInfo, IFacingInfo, UsesInit, UsesInit, UsesInit + public class MobileInfo : ITraitInfo, IOccupySpaceInfo, IFacingInfo, UsesInit, UsesInit, UsesInit { [FieldLoader.LoadUsing("LoadSpeeds")] [Desc("Set Water: 0 for ground units and lower the value on rough terrain.")] @@ -35,7 +35,6 @@ namespace OpenRA.Mods.RA.Move public readonly bool OnRails = false; [Desc("Allow multiple (infantry) units in one cell.")] public readonly bool SharesCell = false; - public readonly int Altitude; public virtual object Create(ActorInitializer init) { return new Mobile(init, this); } @@ -163,12 +162,9 @@ namespace OpenRA.Mods.RA.Move set { __facing = value; } } - [Sync] public int Altitude { get; set; } - public int ROT { get { return Info.ROT; } } - public WPos CenterPosition { get { return PxPosition.ToWPos(Altitude); } } - [Sync] public PPos PxPosition { get; private set; } + [Sync] public WPos CenterPosition { get; private set; } [Sync] public CPos fromCell { get { return __fromCell; } } [Sync] public CPos toCell { get { return __toCell; } } @@ -209,7 +205,12 @@ namespace OpenRA.Mods.RA.Move } this.Facing = init.Contains() ? init.Get() : info.InitialFacing; - this.Altitude = init.Contains() ? init.Get() : 0; + + if (init.Contains()) + { + var z = init.Get() * 1024 / Game.CellSize; + SetVisualPosition(self, CenterPosition + new WVec(0, 0, z - CenterPosition.Z)); + } } public void SetPosition(Actor self, CPos cell) @@ -219,24 +220,17 @@ namespace OpenRA.Mods.RA.Move FinishedMoving(self); } - public void AdjustPxPosition(Actor self, PPos px) /* visual hack only */ - { - PxPosition = px; - } - public void SetPosition(Actor self, WPos pos) { - // TODO: Handle altitude var cell = pos.ToCPos(); SetLocation(cell,fromSubCell, cell,fromSubCell); - PxPosition = PPos.FromWPos(pos); + SetVisualPosition(self, pos); FinishedMoving(self); } public void SetVisualPosition(Actor self, WPos pos) { - // TODO: Handle altitude - AdjustPxPosition(self, PPos.FromWPos(pos)); + CenterPosition = pos; } public IEnumerable Orders { get { yield return new MoveOrderTargeter(Info); } } diff --git a/OpenRA.Mods.RA/Move/Move.cs b/OpenRA.Mods.RA/Move/Move.cs index f8c972911c..e3d8e79e0e 100755 --- a/OpenRA.Mods.RA/Move/Move.cs +++ b/OpenRA.Mods.RA/Move/Move.cs @@ -111,15 +111,6 @@ namespace OpenRA.Mods.RA.Move public override Activity Tick(Actor self) { var mobile = self.Trait(); - var info = self.Info.Traits.Get(); - - if (mobile.Altitude != info.Altitude) - { - if (mobile.Altitude < info.Altitude) - ++mobile.Altitude; - - return this; - } if (destination == mobile.toCell) return NextActivity; diff --git a/OpenRA.Mods.RA/Render/WithRotor.cs b/OpenRA.Mods.RA/Render/WithRotor.cs index 5135be0fd4..9a7202a23a 100755 --- a/OpenRA.Mods.RA/Render/WithRotor.cs +++ b/OpenRA.Mods.RA/Render/WithRotor.cs @@ -40,7 +40,7 @@ namespace OpenRA.Mods.RA.Render public void Tick(Actor self) { - var isFlying = self.Trait().Altitude > 0 && !self.IsDead(); + var isFlying = self.CenterPosition.Z > 0 && !self.IsDead(); if (isFlying ^ (rotorAnim.CurrentSequence.Name != "rotor")) return; diff --git a/OpenRA.Mods.RA/Render/WithShadow.cs b/OpenRA.Mods.RA/Render/WithShadow.cs index 685f8fad8a..6cde2c7c3c 100644 --- a/OpenRA.Mods.RA/Render/WithShadow.cs +++ b/OpenRA.Mods.RA/Render/WithShadow.cs @@ -14,7 +14,6 @@ using System.Linq; using OpenRA.Graphics; using OpenRA.Traits; using OpenRA.Mods.RA.Air; -using OpenRA.Mods.RA.Move; namespace OpenRA.Mods.RA.Render { @@ -27,13 +26,14 @@ namespace OpenRA.Mods.RA.Render var ios = self.Trait(); /* rude hack */ - var visualOffset = ((ios is Helicopter || ios is Mobile) && ios.Altitude > 0) + var flying = ios.CenterPosition.Z > 0; + var visualOffset = (ios is Helicopter && flying) ? (int)Math.Abs((self.ActorID + Game.LocalTick) / 5 % 4 - 1) - 1 : 0; var shadowSprites = r.Select(a => a.WithPalette(wr.Palette("shadow")) .WithPos(a.Pos - new WVec(0, 0, a.Pos.Z)).WithZOffset(a.ZOffset + a.Pos.Z)); - var flyingSprites = (ios.Altitude <= 0) ? r : + var flyingSprites = !flying ? r : r.Select(a => a.WithPos(a.Pos - new WVec(0,0,43*visualOffset))); return shadowSprites.Concat(flyingSprites); diff --git a/mods/d2k/rules/aircraft.yaml b/mods/d2k/rules/aircraft.yaml index c7194ccde4..abcb74c285 100644 --- a/mods/d2k/rules/aircraft.yaml +++ b/mods/d2k/rules/aircraft.yaml @@ -28,7 +28,7 @@ Types: Vehicle MaxWeight: 1 PipCount: 1 - minimalUnloadAltitude: 25 + MaximumUnloadAltitude: 800 LeavesHusk: HuskActor: CARRYALL.Husk From 57adaf46b0bbe9d9039a4d7ccc0af43bd4bc62af Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 16:41:35 +1200 Subject: [PATCH 23/26] Rewrite Aircraft movement using world coords. --- OpenRA.Mods.RA/Air/Aircraft.cs | 111 +++++++++--------- OpenRA.Mods.RA/Air/AttackPlane.cs | 7 +- OpenRA.Mods.RA/Air/FallsToEarth.cs | 14 +-- OpenRA.Mods.RA/Air/Fly.cs | 45 ++++--- OpenRA.Mods.RA/Air/FlyCircle.cs | 20 ++-- OpenRA.Mods.RA/Air/FlyTimed.cs | 20 ++-- OpenRA.Mods.RA/Air/HeliAttack.cs | 33 +++--- OpenRA.Mods.RA/Air/HeliFly.cs | 41 ++++--- OpenRA.Mods.RA/Air/HeliLand.cs | 24 ++-- OpenRA.Mods.RA/Air/HeliReturn.cs | 22 ++-- OpenRA.Mods.RA/Air/Helicopter.cs | 45 +++---- OpenRA.Mods.RA/Air/Land.cs | 26 ++-- OpenRA.Mods.RA/Air/Plane.cs | 15 ++- OpenRA.Mods.RA/Air/ReturnOnIdle.cs | 13 +- OpenRA.Mods.RA/Air/ReturnToBase.cs | 13 +- OpenRA.Mods.RA/Air/TargetableAircraft.cs | 14 +-- OpenRA.Mods.RA/LeavesHusk.cs | 4 +- OpenRA.Mods.RA/Missions/Allies03Script.cs | 7 +- .../Missions/DesertShellmapScript.cs | 2 +- OpenRA.Mods.RA/Missions/MissionUtils.cs | 4 +- mods/d2k/rules/aircraft.yaml | 2 +- 21 files changed, 252 insertions(+), 230 deletions(-) diff --git a/OpenRA.Mods.RA/Air/Aircraft.cs b/OpenRA.Mods.RA/Air/Aircraft.cs index c4a454ef14..b9b407b1c4 100755 --- a/OpenRA.Mods.RA/Air/Aircraft.cs +++ b/OpenRA.Mods.RA/Air/Aircraft.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -19,10 +19,10 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA.Air { - public class AircraftInfo : ITraitInfo, IFacingInfo, IOccupySpaceInfo, UsesInit, UsesInit, UsesInit { public readonly int CruiseAltitude = 30; + [ActorReference] public readonly string[] RepairBuildings = { "fix" }; [ActorReference] @@ -32,57 +32,47 @@ namespace OpenRA.Mods.RA.Air public readonly int Speed = 1; public readonly string[] LandableTerrainTypes = { }; - public virtual object Create( ActorInitializer init ) { return new Aircraft( init , this ); } + public virtual object Create(ActorInitializer init) { return new Aircraft(init, this); } public int GetInitialFacing() { return InitialFacing; } } public class Aircraft : IFacing, IPositionable, ISync, INotifyKilled, IIssueOrder, IOrderVoice { - public IDisposable reservation; + static readonly Pair[] NoCells = new Pair[] { }; - public void UnReserve() - { - if (reservation != null) - { - reservation.Dispose(); - reservation = null; - } - } + readonly AircraftInfo info; + readonly Actor self; - public void Killed(Actor self, AttackInfo e) - { - UnReserve(); - } - - protected readonly Actor self; [Sync] public int Facing { get; set; } - [Sync] public int Altitude { get; set; } - [Sync] public PSubPos SubPxPosition; + [Sync] public WPos CenterPosition { get; private set; } + public CPos TopLeft { get { return CenterPosition.ToCPos(); } } + public IDisposable Reservation; + public int ROT { get { return info.ROT; } } - public WPos CenterPosition { get { return PxPosition.ToWPos(Altitude); } } - public PPos PxPosition { get { return SubPxPosition.ToPPos(); } } - public CPos TopLeft { get { return PxPosition.ToCPos(); } } - - readonly AircraftInfo Info; - - public Aircraft(ActorInitializer init , AircraftInfo info) + public Aircraft(ActorInitializer init, AircraftInfo info) { + this.info = info; this.self = init.self; - if( init.Contains() ) - this.SubPxPosition = Util.CenterOfCell( init.Get() ).ToPSubPos(); - this.Facing = init.Contains() ? init.Get() : info.InitialFacing; - this.Altitude = init.Contains() ? init.Get() : 0; - Info = info; + if (init.Contains()) + SetPosition(self, init.Get()); + + this.Facing = init.Contains() ? init.Get() : info.InitialFacing; + + if (init.Contains()) + { + var z = init.Get() * 1024 / Game.CellSize; + SetPosition(self, CenterPosition + new WVec(0, 0, z - CenterPosition.Z)); + } } public Actor GetActorBelow() { - if (Altitude != 0) + if (self.CenterPosition.Z != 0) return null; // not on the ground. return self.World.FindActorsInBox(self.CenterPosition, self.CenterPosition) - .FirstOrDefault( a => a.HasTrait() ); + .FirstOrDefault(a => a.HasTrait()); } protected void ReserveSpawnBuilding() @@ -94,29 +84,39 @@ namespace OpenRA.Mods.RA.Air var res = afld.Trait(); if (res != null) - reservation = res.Reserve(afld, self, this); + Reservation = res.Reserve(afld, self, this); } - public int ROT { get { return Info.ROT; } } + public void UnReserve() + { + if (Reservation != null) + { + Reservation.Dispose(); + Reservation = null; + } + } + + public void Killed(Actor self, AttackInfo e) + { + UnReserve(); + } public void SetPosition(Actor self, CPos cell) { - SubPxPosition = Util.CenterOfCell(cell).ToPSubPos(); - } - - public void SetPosition(Actor self, WPos pos) - { - // TODO: Handle altitude - SubPxPosition = PPos.FromWPos(pos).ToPSubPos(); + // Changes position, but not altitude + CenterPosition = cell.CenterPosition + new WVec(0, 0, CenterPosition.Z); } + public void SetPosition(Actor self, WPos pos) { CenterPosition = pos; } public void SetVisualPosition(Actor self, WPos pos) { SetPosition(self, pos); } public bool AircraftCanEnter(Actor a) { - if (self.AppearsHostileTo(a)) return false; - return Info.RearmBuildings.Contains(a.Info.Name) - || Info.RepairBuildings.Contains(a.Info.Name); + if (self.AppearsHostileTo(a)) + return false; + + return info.RearmBuildings.Contains(a.Info.Name) + || info.RepairBuildings.Contains(a.Info.Name); } public bool CanEnterCell(CPos location) { return true; } @@ -125,20 +125,20 @@ namespace OpenRA.Mods.RA.Air { get { - decimal ret = Info.Speed; + decimal ret = info.Speed; foreach (var t in self.TraitsImplementing()) ret *= t.GetSpeedModifier(); return (int)ret; } } - Pair[] noCells = new Pair[] { }; - public IEnumerable> OccupiedCells() { return noCells; } + public IEnumerable> OccupiedCells() { return NoCells; } - public void TickMove(int speed, int facing) + public WVec FlyStep(int facing) { - var rawspeed = speed * 7 / (32 * PSubPos.PerPx); - SubPxPosition += rawspeed * -Util.SubPxVector[facing]; + var speed = MovementSpeed * 7 * 1024 / (Game.CellSize * 32); + var dir = new WVec(0, -1024, 0).Rotate(WRot.FromFacing(facing)); + return speed * dir / 1024; } public bool CanLand(CPos cell) @@ -150,15 +150,15 @@ namespace OpenRA.Mods.RA.Air return false; var type = self.World.GetTerrainType(cell); - return Info.LandableTerrainTypes.Contains(type); + return info.LandableTerrainTypes.Contains(type); } public IEnumerable GetResupplyActivities(Actor a) { var name = a.Info.Name; - if (Info.RearmBuildings.Contains(name)) + if (info.RearmBuildings.Contains(name)) yield return new Rearm(self); - if (Info.RepairBuildings.Contains(name)) + if (info.RepairBuildings.Contains(name)) yield return new Repair(a); } @@ -228,6 +228,7 @@ namespace OpenRA.Mods.RA.Air cursor = self.World.Map.IsInMap(location) ? "move" : "move-blocked"; return true; } + public bool IsQueued { get; protected set; } } } diff --git a/OpenRA.Mods.RA/Air/AttackPlane.cs b/OpenRA.Mods.RA/Air/AttackPlane.cs index b23da20bd6..fce0c636af 100755 --- a/OpenRA.Mods.RA/Air/AttackPlane.cs +++ b/OpenRA.Mods.RA/Air/AttackPlane.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -24,14 +24,13 @@ namespace OpenRA.Mods.RA.Air public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove) { - return new FlyAttack( newTarget ); + return new FlyAttack(newTarget); } protected override bool CanAttack(Actor self, Target target) { // dont fire while landed - return base.CanAttack(self, target) - && self.Trait().Altitude > 0; + return base.CanAttack(self, target) && self.CenterPosition.Z > 0; } } } diff --git a/OpenRA.Mods.RA/Air/FallsToEarth.cs b/OpenRA.Mods.RA/Air/FallsToEarth.cs index 9f62efcc01..5099953e2f 100755 --- a/OpenRA.Mods.RA/Air/FallsToEarth.cs +++ b/OpenRA.Mods.RA/Air/FallsToEarth.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -19,6 +19,7 @@ namespace OpenRA.Mods.RA.Air public readonly bool Spins = true; public readonly bool Moves = false; + public readonly WRange Velocity = new WRange(43); public object Create(ActorInitializer init) { return new FallsToEarth(init.self, this); } } @@ -47,7 +48,7 @@ namespace OpenRA.Mods.RA.Air public override Activity Tick(Actor self) { var aircraft = self.Trait(); - if (aircraft.Altitude <= 0) + if (self.CenterPosition.Z <= 0) { if (info.Explosion != null) Combat.DoExplosion(self, info.Explosion, self.CenterPosition); @@ -62,15 +63,14 @@ namespace OpenRA.Mods.RA.Air aircraft.Facing = (aircraft.Facing + spin) % 256; } - if (info.Moves) - FlyUtil.Fly(self, aircraft.Altitude); - - aircraft.Altitude--; + var move = info.Moves ? aircraft.FlyStep(aircraft.Facing) : WVec.Zero; + move -= new WVec(WRange.Zero, WRange.Zero, info.Velocity); + aircraft.SetPosition(self, aircraft.CenterPosition + move); return this; } // Cannot be cancelled - public override void Cancel( Actor self ) { } + public override void Cancel(Actor self) { } } } diff --git a/OpenRA.Mods.RA/Air/Fly.cs b/OpenRA.Mods.RA/Air/Fly.cs index bd900f72b9..198ea181d0 100755 --- a/OpenRA.Mods.RA/Air/Fly.cs +++ b/OpenRA.Mods.RA/Air/Fly.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -20,6 +20,23 @@ namespace OpenRA.Mods.RA.Air Fly(WPos pos) { this.pos = pos; } + public static void FlyToward(Actor self, Plane plane, int desiredFacing, WRange desiredAltitude) + { + var move = plane.FlyStep(plane.Facing); + var altitude = plane.CenterPosition.Z; + + plane.Facing = Util.TickFacing(plane.Facing, desiredFacing, plane.ROT); + + if (altitude != desiredAltitude.Range) + { + var delta = move.HorizontalLength * plane.Info.MaximumPitch.Tan() / 1024; + var dz = (desiredAltitude.Range - altitude).Clamp(-delta, delta); + move += new WVec(0, 0, dz); + } + + plane.SetPosition(self, plane.CenterPosition + move); + } + public static Fly ToPos(WPos pos) { return new Fly(pos); } public static Fly ToCell(CPos pos) { return new Fly(pos.CenterPosition); } @@ -33,16 +50,16 @@ namespace OpenRA.Mods.RA.Air if (d.HorizontalLengthSquared < 91022) return NextActivity; - var aircraft = self.Trait(); - var cruiseAltitude = self.Info.Traits.Get().CruiseAltitude; - var desiredFacing = Util.GetFacing(d, aircraft.Facing); - if (aircraft.Altitude == cruiseAltitude) - aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT); + var plane = self.Trait(); + var desiredFacing = Util.GetFacing(d, plane.Facing); + var cruiseAltitude = new WRange(plane.Info.CruiseAltitude * 1024 / Game.CellSize); - if (aircraft.Altitude < cruiseAltitude) - ++aircraft.Altitude; + // Don't turn until we've reached the cruise altitude + if (plane.CenterPosition.Z < cruiseAltitude.Range) + desiredFacing = plane.Facing; + + FlyToward(self, plane, desiredFacing, cruiseAltitude); - FlyUtil.Fly(self, cruiseAltitude); return this; } @@ -51,14 +68,4 @@ namespace OpenRA.Mods.RA.Air yield return Target.FromPos(pos); } } - - public static class FlyUtil - { - public static void Fly(Actor self, int desiredAltitude) - { - var aircraft = self.Trait(); - aircraft.TickMove(PSubPos.PerPx * aircraft.MovementSpeed, aircraft.Facing); - aircraft.Altitude += Math.Sign(desiredAltitude - aircraft.Altitude); - } - } } diff --git a/OpenRA.Mods.RA/Air/FlyCircle.cs b/OpenRA.Mods.RA/Air/FlyCircle.cs index 24c92d2ad1..9302a5e951 100644 --- a/OpenRA.Mods.RA/Air/FlyCircle.cs +++ b/OpenRA.Mods.RA/Air/FlyCircle.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -17,20 +17,16 @@ namespace OpenRA.Mods.RA.Air { public override Activity Tick(Actor self) { - var cruiseAltitude = self.Info.Traits.Get().CruiseAltitude; + if (IsCanceled) + return NextActivity; - if (IsCanceled) return NextActivity; + var plane = self.Trait(); - var aircraft = self.Trait(); + // We can't possibly turn this fast + var desiredFacing = plane.Facing + 64; + var cruiseAltitude = new WRange(plane.Info.CruiseAltitude * 1024 / Game.CellSize); + Fly.FlyToward(self, plane, desiredFacing, cruiseAltitude); - var desiredFacing = aircraft.Facing + 64; // we can't possibly turn this fast. - if (aircraft.Altitude == cruiseAltitude) - aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT); - - if (aircraft.Altitude < cruiseAltitude) - ++aircraft.Altitude; - - FlyUtil.Fly(self, cruiseAltitude); return this; } } diff --git a/OpenRA.Mods.RA/Air/FlyTimed.cs b/OpenRA.Mods.RA/Air/FlyTimed.cs index 7968d5a9d7..03ee64688f 100755 --- a/OpenRA.Mods.RA/Air/FlyTimed.cs +++ b/OpenRA.Mods.RA/Air/FlyTimed.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -20,10 +20,13 @@ namespace OpenRA.Mods.RA.Air public override Activity Tick(Actor self) { - if( IsCanceled ) return NextActivity; - var targetAltitude = self.Info.Traits.Get().CruiseAltitude; - if (remainingTicks-- == 0) return NextActivity; - FlyUtil.Fly(self, targetAltitude); + if (IsCanceled || remainingTicks-- == 0) + return NextActivity; + + var plane = self.Trait(); + var cruiseAltitude = new WRange(plane.Info.CruiseAltitude * 1024 / Game.CellSize); + Fly.FlyToward(self, plane, plane.Facing, cruiseAltitude); + return this; } } @@ -32,15 +35,16 @@ namespace OpenRA.Mods.RA.Air { public override Activity Tick(Actor self) { - var targetAltitude = self.Info.Traits.Get().CruiseAltitude; if (IsCanceled || !self.World.Map.IsInMap(self.Location)) return NextActivity; - FlyUtil.Fly(self, targetAltitude); + var plane = self.Trait(); + var cruiseAltitude = new WRange(plane.Info.CruiseAltitude * 1024 / Game.CellSize); + Fly.FlyToward(self, plane, plane.Facing, cruiseAltitude); return this; } - public override void Cancel( Actor self ) + public override void Cancel(Actor self) { base.Cancel(self); } diff --git a/OpenRA.Mods.RA/Air/HeliAttack.cs b/OpenRA.Mods.RA/Air/HeliAttack.cs index 87e3de5eed..1ba4d4d417 100755 --- a/OpenRA.Mods.RA/Air/HeliAttack.cs +++ b/OpenRA.Mods.RA/Air/HeliAttack.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -17,36 +17,35 @@ namespace OpenRA.Mods.RA.Air public class HeliAttack : Activity { Target target; - public HeliAttack( Target target ) { this.target = target; } + public HeliAttack(Target target) { this.target = target; } public override Activity Tick(Actor self) { - if (IsCanceled) return NextActivity; - if (!target.IsValid) return NextActivity; + if (IsCanceled || !target.IsValid) + return NextActivity; var limitedAmmo = self.TraitOrDefault(); var reloads = self.TraitOrDefault(); if (limitedAmmo != null && !limitedAmmo.HasAmmo() && reloads == null) - return Util.SequenceActivities( new HeliReturn(), NextActivity ); - - var aircraft = self.Trait(); - var info = self.Info.Traits.Get(); - if (aircraft.Altitude != info.CruiseAltitude) - { - aircraft.Altitude += Math.Sign(info.CruiseAltitude - aircraft.Altitude); - return this; - } + return Util.SequenceActivities(new HeliReturn(), NextActivity); + var helicopter = self.Trait(); var attack = self.Trait(); var dist = target.CenterPosition - self.CenterPosition; - var desiredFacing = Util.GetFacing(dist, aircraft.Facing); - aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT); + // Can rotate facing while ascending + var desiredFacing = Util.GetFacing(dist, helicopter.Facing); + helicopter.Facing = Util.TickFacing(helicopter.Facing, desiredFacing, helicopter.ROT); + var cruiseAltitude = new WRange(helicopter.Info.CruiseAltitude * 1024 / Game.CellSize); + if (HeliFly.AdjustAltitude(self, helicopter, cruiseAltitude)) + return this; + + // Fly towards the target if (!target.IsInRange(self.CenterPosition, attack.GetMaximumRange())) - aircraft.TickMove(PSubPos.PerPx * aircraft.MovementSpeed, desiredFacing); + helicopter.SetPosition(self, helicopter.CenterPosition + helicopter.FlyStep(desiredFacing)); - attack.DoAttack( self, target ); + attack.DoAttack(self, target); return this; } diff --git a/OpenRA.Mods.RA/Air/HeliFly.cs b/OpenRA.Mods.RA/Air/HeliFly.cs index 7a77667909..f4ac312b23 100755 --- a/OpenRA.Mods.RA/Air/HeliFly.cs +++ b/OpenRA.Mods.RA/Air/HeliFly.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -17,35 +17,48 @@ namespace OpenRA.Mods.RA.Air class HeliFly : Activity { readonly WPos pos; + public HeliFly(WPos pos) { this.pos = pos; } public HeliFly(CPos pos) { this.pos = pos.CenterPosition; } + public static bool AdjustAltitude(Actor self, Helicopter helicopter, WRange targetAltitude) + { + var altitude = helicopter.CenterPosition.Z; + if (altitude == targetAltitude.Range) + return false; + + var delta = helicopter.Info.AltitudeVelocity.Range; + var dz = (targetAltitude.Range - altitude).Clamp(-delta, delta); + helicopter.SetPosition(self, helicopter.CenterPosition + new WVec(0, 0, dz)); + + return true; + } + public override Activity Tick(Actor self) { if (IsCanceled) return NextActivity; - var info = self.Info.Traits.Get(); - var aircraft = self.Trait(); + var helicopter = self.Trait(); - if (aircraft.Altitude != info.CruiseAltitude) - { - aircraft.Altitude += Math.Sign(info.CruiseAltitude - aircraft.Altitude); + var cruiseAltitude = new WRange(helicopter.Info.CruiseAltitude * 1024 / Game.CellSize); + if (HeliFly.AdjustAltitude(self, helicopter, cruiseAltitude)) return this; - } + + // Rotate towards the target + var dist = pos - self.CenterPosition; + var desiredFacing = Util.GetFacing(dist, helicopter.Facing); + helicopter.Facing = Util.TickFacing(helicopter.Facing, desiredFacing, helicopter.ROT); // The next move would overshoot, so just set the final position - var dist = pos - self.CenterPosition; - var moveDist = aircraft.MovementSpeed * 7 * 1024 / (Game.CellSize * 32); - if (dist.HorizontalLengthSquared < moveDist*moveDist) + var move = helicopter.FlyStep(desiredFacing); + if (dist.HorizontalLengthSquared < move.HorizontalLengthSquared) { - aircraft.SetPosition(self, pos); + helicopter.SetPosition(self, pos + new WVec(0, 0, cruiseAltitude.Range - pos.Z)); return NextActivity; } - var desiredFacing = Util.GetFacing(dist, aircraft.Facing); - aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT); - aircraft.TickMove(PSubPos.PerPx * aircraft.MovementSpeed, desiredFacing); + helicopter.SetPosition(self, helicopter.CenterPosition + move); return this; } diff --git a/OpenRA.Mods.RA/Air/HeliLand.cs b/OpenRA.Mods.RA/Air/HeliLand.cs index 00479cae7a..0842b7201f 100755 --- a/OpenRA.Mods.RA/Air/HeliLand.cs +++ b/OpenRA.Mods.RA/Air/HeliLand.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -14,27 +14,27 @@ namespace OpenRA.Mods.RA.Air { class HeliLand : Activity { - public HeliLand(bool requireSpace, int minimalAltitude) + bool requireSpace; + + public HeliLand(bool requireSpace) { this.requireSpace = requireSpace; - this.minimalAltitude = minimalAltitude; } - bool requireSpace; - int minimalAltitude = 0; - public override Activity Tick(Actor self) { - if (IsCanceled) return NextActivity; - var aircraft = self.Trait(); - if (aircraft.Altitude == minimalAltitude) + if (IsCanceled) return NextActivity; - if (requireSpace && !aircraft.CanLand(self.Location)) + var helicopter = self.Trait(); + + if (requireSpace && !helicopter.CanLand(self.Location)) return this; - --aircraft.Altitude; - return this; + if (HeliFly.AdjustAltitude(self, helicopter, helicopter.Info.LandAltitude)) + return this; + + return NextActivity; } } } diff --git a/OpenRA.Mods.RA/Air/HeliReturn.cs b/OpenRA.Mods.RA/Air/HeliReturn.cs index b1638bcace..5b11319df0 100755 --- a/OpenRA.Mods.RA/Air/HeliReturn.cs +++ b/OpenRA.Mods.RA/Air/HeliReturn.cs @@ -1,6 +1,6 @@ -#region Copyright & License Information +#region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -9,8 +9,8 @@ #endregion using System.Linq; -using OpenRA.Traits; using OpenRA.Mods.RA.Activities; +using OpenRA.Traits; namespace OpenRA.Mods.RA.Air { @@ -19,16 +19,16 @@ namespace OpenRA.Mods.RA.Air static Actor ChooseHelipad(Actor self) { var rearmBuildings = self.Info.Traits.Get().RearmBuildings; - return self.World.Actors.Where( a => a.Owner == self.Owner ).FirstOrDefault( - a => rearmBuildings.Contains(a.Info.Name) && - !Reservable.IsReserved(a)); + return self.World.Actors.Where(a => a.Owner == self.Owner).FirstOrDefault( + a => rearmBuildings.Contains(a.Info.Name) && !Reservable.IsReserved(a)); } public override Activity Tick(Actor self) { - if (IsCanceled) return NextActivity; - var dest = ChooseHelipad(self); + if (IsCanceled) + return NextActivity; + var dest = ChooseHelipad(self); var initialFacing = self.Info.Traits.Get().InitialFacing; if (dest == null) @@ -40,7 +40,7 @@ namespace OpenRA.Mods.RA.Air .ClosestTo(self); if (nearestHpad == null) - return Util.SequenceActivities(new Turn(initialFacing), new HeliLand(true, 0), NextActivity); + return Util.SequenceActivities(new Turn(initialFacing), new HeliLand(true), NextActivity); else return Util.SequenceActivities(new HeliFly(nearestHpad.CenterPosition)); } @@ -48,7 +48,7 @@ namespace OpenRA.Mods.RA.Air var res = dest.TraitOrDefault(); var heli = self.Trait(); if (res != null) - heli.reservation = res.Reserve(dest, self, heli); + heli.Reservation = res.Reserve(dest, self, heli); var exit = dest.Info.Traits.WithInterface().FirstOrDefault(); var offset = (exit != null) ? exit.SpawnOffsetVector : WVec.Zero; @@ -56,7 +56,7 @@ namespace OpenRA.Mods.RA.Air return Util.SequenceActivities( new HeliFly(dest.CenterPosition + offset), new Turn(initialFacing), - new HeliLand(false, 0), + new HeliLand(false), new Rearm(self), NextActivity); } diff --git a/OpenRA.Mods.RA/Air/Helicopter.cs b/OpenRA.Mods.RA/Air/Helicopter.cs index a0a8529355..33c5a2d89e 100755 --- a/OpenRA.Mods.RA/Air/Helicopter.cs +++ b/OpenRA.Mods.RA/Air/Helicopter.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -19,28 +19,29 @@ namespace OpenRA.Mods.RA.Air { public readonly WRange IdealSeparation = new WRange(1706); public readonly bool LandWhenIdle = true; - public readonly int MinimalLandAltitude = 0; + public readonly WRange LandAltitude = WRange.Zero; + public readonly WRange AltitudeVelocity = new WRange(43); public override object Create(ActorInitializer init) { return new Helicopter(init, this); } } class Helicopter : Aircraft, ITick, IResolveOrder { - HelicopterInfo info; + public HelicopterInfo Info; bool firstTick = true; public Helicopter(ActorInitializer init, HelicopterInfo info) : base(init, info) { - this.info = info; + Info = info; } public void ResolveOrder(Actor self, Order order) { - if (reservation != null) + if (Reservation != null) { - reservation.Dispose(); - reservation = null; + Reservation.Dispose(); + Reservation = null; } if (order.OrderString == "Move") @@ -51,10 +52,10 @@ namespace OpenRA.Mods.RA.Air self.CancelActivity(); self.QueueActivity(new HeliFly(target)); - if (info.LandWhenIdle) + if (Info.LandWhenIdle) { - self.QueueActivity(new Turn(info.InitialFacing)); - self.QueueActivity(new HeliLand(true, info.MinimalLandAltitude)); + self.QueueActivity(new Turn(Info.InitialFacing)); + self.QueueActivity(new HeliLand(true)); } } @@ -69,7 +70,7 @@ namespace OpenRA.Mods.RA.Air { var res = order.TargetActor.TraitOrDefault(); if (res != null) - reservation = res.Reserve(order.TargetActor, self, this); + Reservation = res.Reserve(order.TargetActor, self, this); var exit = order.TargetActor.Info.Traits.WithInterface().FirstOrDefault(); var offset = (exit != null) ? exit.SpawnOffsetVector : WVec.Zero; @@ -78,8 +79,8 @@ namespace OpenRA.Mods.RA.Air self.CancelActivity(); self.QueueActivity(new HeliFly(order.TargetActor.CenterPosition + offset)); - self.QueueActivity(new Turn(info.InitialFacing)); - self.QueueActivity(new HeliLand(false, info.MinimalLandAltitude)); + self.QueueActivity(new Turn(Info.InitialFacing)); + self.QueueActivity(new HeliLand(false)); self.QueueActivity(new ResupplyAircraft()); } } @@ -94,10 +95,10 @@ namespace OpenRA.Mods.RA.Air { self.CancelActivity(); - if (info.LandWhenIdle) + if (Info.LandWhenIdle) { - self.QueueActivity(new Turn(info.InitialFacing)); - self.QueueActivity(new HeliLand(true, info.MinimalLandAltitude)); + self.QueueActivity(new Turn(Info.InitialFacing)); + self.QueueActivity(new HeliLand(true)); } } } @@ -112,10 +113,12 @@ namespace OpenRA.Mods.RA.Air } // Repulsion only applies when we're flying! - if (Altitude != info.CruiseAltitude) + var altitude = CenterPosition.Z; + var cruiseAltitude = Info.CruiseAltitude * 1024 / Game.CellSize; + if (altitude != cruiseAltitude) return; - var otherHelis = self.World.FindActorsInCircle(self.CenterPosition, info.IdealSeparation) + var otherHelis = self.World.FindActorsInCircle(self.CenterPosition, Info.IdealSeparation) .Where(a => a.HasTrait()); var f = otherHelis @@ -124,17 +127,17 @@ namespace OpenRA.Mods.RA.Air int repulsionFacing = Util.GetFacing(f, -1); if (repulsionFacing != -1) - TickMove(PSubPos.PerPx * MovementSpeed, repulsionFacing); + SetPosition(self, CenterPosition + FlyStep(repulsionFacing)); } public WVec GetRepulseForce(Actor self, Actor other) { - if (self == other || other.Trait().Altitude < Altitude) + if (self == other || other.CenterPosition.Z < self.CenterPosition.Z) return WVec.Zero; var d = self.CenterPosition - other.CenterPosition; var distSq = d.HorizontalLengthSquared; - if (distSq > info.IdealSeparation.Range * info.IdealSeparation.Range) + if (distSq > Info.IdealSeparation.Range * Info.IdealSeparation.Range) return WVec.Zero; if (distSq < 1) diff --git a/OpenRA.Mods.RA/Air/Land.cs b/OpenRA.Mods.RA/Air/Land.cs index 36712ce1a4..d6bde50f44 100755 --- a/OpenRA.Mods.RA/Air/Land.cs +++ b/OpenRA.Mods.RA/Air/Land.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -16,35 +16,31 @@ namespace OpenRA.Mods.RA.Air { public class Land : Activity { - Target Target; + Target target; - public Land(Target t) { Target = t; } + public Land(Target t) { target = t; } public override Activity Tick(Actor self) { - if (!Target.IsValid) + if (!target.IsValid) Cancel(self); if (IsCanceled) return NextActivity; - var aircraft = self.Trait(); - var d = Target.CenterPosition - self.CenterPosition; + var plane = self.Trait(); + var d = target.CenterPosition - self.CenterPosition; // The next move would overshoot, so just set the final position - var moveDist = aircraft.MovementSpeed * 7 * 1024 / (Game.CellSize * 32); - if (d.HorizontalLengthSquared < moveDist*moveDist) + var move = plane.FlyStep(plane.Facing); + if (d.HorizontalLengthSquared < move.HorizontalLengthSquared) { - aircraft.SetPosition(self, Target.CenterPosition); + plane.SetPosition(self, target.CenterPosition); return NextActivity; } - if (aircraft.Altitude > 0) - --aircraft.Altitude; - - var desiredFacing = Util.GetFacing(d, aircraft.Facing); - aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT); - aircraft.TickMove(PSubPos.PerPx * aircraft.MovementSpeed, aircraft.Facing); + var desiredFacing = Util.GetFacing(d, plane.Facing); + Fly.FlyToward(self, plane, desiredFacing, WRange.Zero); return this; } diff --git a/OpenRA.Mods.RA/Air/Plane.cs b/OpenRA.Mods.RA/Air/Plane.cs index 0d07f8a657..9c90191f72 100755 --- a/OpenRA.Mods.RA/Air/Plane.cs +++ b/OpenRA.Mods.RA/Air/Plane.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -16,15 +16,21 @@ namespace OpenRA.Mods.RA.Air { public class PlaneInfo : AircraftInfo { - public override object Create( ActorInitializer init ) { return new Plane( init, this ); } + public readonly WAngle MaximumPitch = WAngle.FromDegrees(10); + + public override object Create(ActorInitializer init) { return new Plane(init, this); } } public class Plane : Aircraft, IResolveOrder, ITick, ISync { + public readonly PlaneInfo Info; [Sync] public WPos RTBPathHash; - public Plane( ActorInitializer init, PlaneInfo info ) - : base( init, info ) { } + public Plane(ActorInitializer init, PlaneInfo info) + : base(init, info) + { + Info = info; + } bool firstTick = true; public void Tick(Actor self) @@ -49,7 +55,6 @@ namespace OpenRA.Mods.RA.Air self.QueueActivity(Fly.ToCell(target)); self.QueueActivity(new FlyCircle()); } - else if (order.OrderString == "Enter") { if (Reservable.IsReserved(order.TargetActor)) return; diff --git a/OpenRA.Mods.RA/Air/ReturnOnIdle.cs b/OpenRA.Mods.RA/Air/ReturnOnIdle.cs index ee643df58c..3b9ca48beb 100755 --- a/OpenRA.Mods.RA/Air/ReturnOnIdle.cs +++ b/OpenRA.Mods.RA/Air/ReturnOnIdle.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -17,14 +17,13 @@ namespace OpenRA.Mods.RA.Air { class ReturnOnIdleInfo : TraitInfo { } - // fly home or fly-off-map behavior for idle planes - class ReturnOnIdle : INotifyIdle { public void TickIdle(Actor self) { - var altitude = self.Trait().Altitude; - if (altitude == 0) return; // we're on the ground, let's stay there. + // We're on the ground, let's stay there. + if (self.CenterPosition.Z == 0) + return; var airfield = ReturnToBase.ChooseAirfield(self, true); if (airfield != null) @@ -38,13 +37,13 @@ namespace OpenRA.Mods.RA.Air // i'd prefer something we own var someBuilding = self.World.ActorsWithTrait() - .Select( a => a.Actor ) + .Select(a => a.Actor) .FirstOrDefault(a => a.Owner == self.Owner); // failing that, something unlikely to shoot at us if (someBuilding == null) someBuilding = self.World.ActorsWithTrait() - .Select( a => a.Actor ) + .Select(a => a.Actor) .FirstOrDefault(a => self.Owner.Stances[a.Owner] == Stance.Ally); if (someBuilding == null) diff --git a/OpenRA.Mods.RA/Air/ReturnToBase.cs b/OpenRA.Mods.RA/Air/ReturnToBase.cs index 4fddcdf466..0d19cb48f5 100755 --- a/OpenRA.Mods.RA/Air/ReturnToBase.cs +++ b/OpenRA.Mods.RA/Air/ReturnToBase.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -10,8 +10,8 @@ using System; using System.Linq; -using OpenRA.Traits; using OpenRA.Mods.RA.Buildings; +using OpenRA.Traits; namespace OpenRA.Mods.RA.Air { @@ -46,22 +46,21 @@ namespace OpenRA.Mods.RA.Air if (res != null) { plane.UnReserve(); - plane.reservation = res.Reserve(dest, self, plane); + plane.Reservation = res.Reserve(dest, self, plane); } var landPos = dest.CenterPosition; - var speed = plane.MovementSpeed * 1024 / Game.CellSize / 5; // Distance required for descent. - // TODO: Generalize this for arbitrary flight pitches - var landDistance = planeInfo.CruiseAltitude * speed; + var landDistance = planeInfo.CruiseAltitude * 1024 * 1024 / (Game.CellSize * plane.Info.MaximumPitch.Tan()); var altitude = planeInfo.CruiseAltitude * 1024 / Game.CellSize; // Land towards the east var approachStart = landPos + new WVec(-landDistance, 0, altitude); // Add 10% to the turning radius to ensure we have enough room - var turnRadius = (int)(141 * speed / planeInfo.ROT / (float)(Math.PI)); + var speed = plane.MovementSpeed * 1024 / (Game.CellSize * 5); + var turnRadius = (int)(141 * speed / planeInfo.ROT / (float)Math.PI); // Find the center of the turning circles for clockwise and counterclockwise turns var angle = WAngle.FromFacing(plane.Facing); diff --git a/OpenRA.Mods.RA/Air/TargetableAircraft.cs b/OpenRA.Mods.RA/Air/TargetableAircraft.cs index 49bcd2ffd8..0cbeb27e41 100755 --- a/OpenRA.Mods.RA/Air/TargetableAircraft.cs +++ b/OpenRA.Mods.RA/Air/TargetableAircraft.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -9,13 +9,13 @@ #endregion using System.Drawing; -using OpenRA.Graphics; using System.Linq; +using OpenRA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.RA.Air { - public class TargetableAircraftInfo : TargetableUnitInfo, Requires + public class TargetableAircraftInfo : TargetableUnitInfo { public readonly string[] GroundedTargetTypes = { }; public override object Create(ActorInitializer init) { return new TargetableAircraft(init.self, this); } @@ -24,19 +24,19 @@ namespace OpenRA.Mods.RA.Air public class TargetableAircraft : TargetableUnit { readonly TargetableAircraftInfo info; - readonly Aircraft Aircraft; + readonly Actor self; public TargetableAircraft(Actor self, TargetableAircraftInfo info) : base(self, info) { this.info = info; - Aircraft = self.Trait(); + this.self = self; } public override string[] TargetTypes { - get { return (Aircraft.Altitude > 0) ? info.TargetTypes - : info.GroundedTargetTypes; } + get { return (self.CenterPosition.Z > 0) ? info.TargetTypes + : info.GroundedTargetTypes; } } } } diff --git a/OpenRA.Mods.RA/LeavesHusk.cs b/OpenRA.Mods.RA/LeavesHusk.cs index 8dce4cdb42..1fc3f91fe3 100644 --- a/OpenRA.Mods.RA/LeavesHusk.cs +++ b/OpenRA.Mods.RA/LeavesHusk.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -52,7 +52,7 @@ namespace OpenRA.Mods.RA var aircraft = self.TraitOrDefault(); if (aircraft != null) - td.Add(new AltitudeInit(aircraft.Altitude)); + td.Add(new AltitudeInit(aircraft.CenterPosition.Z * Game.CellSize / 1024)); var facing = self.TraitOrDefault(); if (facing != null) diff --git a/OpenRA.Mods.RA/Missions/Allies03Script.cs b/OpenRA.Mods.RA/Missions/Allies03Script.cs index f57bd3ac21..9bebeabf7c 100644 --- a/OpenRA.Mods.RA/Missions/Allies03Script.cs +++ b/OpenRA.Mods.RA/Missions/Allies03Script.cs @@ -215,9 +215,10 @@ namespace OpenRA.Mods.RA.Missions foreach (var aircraft in SovietAircraft()) { + var pos = aircraft.CenterPosition; var plane = aircraft.Trait(); var ammo = aircraft.Trait(); - if ((plane.Altitude == 0 && ammo.FullAmmo()) || (plane.Altitude != 0 && ammo.HasAmmo())) + if ((pos.Z == 0 && ammo.FullAmmo()) || (pos.Z != 0 && ammo.HasAmmo())) { var enemy = FirstUnshroudedOrDefault(enemies.OrderBy(u => (aircraft.CenterPosition - u.CenterPosition).LengthSquared), world, 10); if (enemy != null) @@ -225,13 +226,13 @@ namespace OpenRA.Mods.RA.Missions if (!aircraft.IsIdle && aircraft.GetCurrentActivity().GetType() != typeof(FlyAttack)) aircraft.CancelActivity(); - if (plane.Altitude == 0) + if (pos.Z == 0) plane.UnReserve(); aircraft.QueueActivity(new FlyAttack(Target.FromActor(enemy))); } } - else if (plane.Altitude != 0 && !LandIsQueued(aircraft)) + else if (pos.Z != 0 && !LandIsQueued(aircraft)) { aircraft.CancelActivity(); aircraft.QueueActivity(new ReturnToBase(aircraft, null)); diff --git a/OpenRA.Mods.RA/Missions/DesertShellmapScript.cs b/OpenRA.Mods.RA/Missions/DesertShellmapScript.cs index ed185f1ed0..c0e8661733 100644 --- a/OpenRA.Mods.RA/Missions/DesertShellmapScript.cs +++ b/OpenRA.Mods.RA/Missions/DesertShellmapScript.cs @@ -221,7 +221,7 @@ namespace OpenRA.Mods.RA.Missions chinook.QueueActivity(new HeliFly(lz.CenterPosition + offset)); // no reservation of hpad but it's not needed chinook.QueueActivity(new Turn(0)); - chinook.QueueActivity(new HeliLand(false, 0)); + chinook.QueueActivity(new HeliLand(false)); chinook.QueueActivity(new UnloadCargo(true)); chinook.QueueActivity(new Wait(150)); chinook.QueueActivity(new HeliFly(entry)); diff --git a/OpenRA.Mods.RA/Missions/MissionUtils.cs b/OpenRA.Mods.RA/Missions/MissionUtils.cs index 8bd035139c..e237223096 100644 --- a/OpenRA.Mods.RA/Missions/MissionUtils.cs +++ b/OpenRA.Mods.RA/Missions/MissionUtils.cs @@ -47,7 +47,7 @@ namespace OpenRA.Mods.RA.Missions var chinook = world.CreateActor("tran", new TypeDictionary { new OwnerInit(owner), new LocationInit(entry) }); chinook.QueueActivity(new HeliFly(lz)); chinook.QueueActivity(new Turn(0)); - chinook.QueueActivity(new HeliLand(true, 0)); + chinook.QueueActivity(new HeliLand(true)); chinook.QueueActivity(new WaitFor(() => chinook.Trait().Passengers.Contains(unit))); chinook.QueueActivity(new Wait(150)); chinook.QueueActivity(new HeliFly(exit)); @@ -62,7 +62,7 @@ namespace OpenRA.Mods.RA.Missions chinook.Trait().Load(chinook, unit); chinook.QueueActivity(new HeliFly(lz)); chinook.QueueActivity(new Turn(0)); - chinook.QueueActivity(new HeliLand(true, 0)); + chinook.QueueActivity(new HeliLand(true)); chinook.QueueActivity(new UnloadCargo(true)); chinook.QueueActivity(new CallFunc(() => afterUnload(unit))); chinook.QueueActivity(new Wait(150)); diff --git a/mods/d2k/rules/aircraft.yaml b/mods/d2k/rules/aircraft.yaml index abcb74c285..ff46bdb260 100644 --- a/mods/d2k/rules/aircraft.yaml +++ b/mods/d2k/rules/aircraft.yaml @@ -19,7 +19,7 @@ LandableTerrainTypes: Sand, Rock, Transition, Spice, Dune RepairBuildings: repair RearmBuildings: starporta,starporto,starporth - MinimalLandAltitude: 25 + LandAltitude: 800 RenderUnit: WithCargo: LocalOffset: 0,0,-854 From 05948220780dea89cb57826b97de6cdca458b4a0 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 18:35:12 +1200 Subject: [PATCH 24/26] Fix cargo loading. --- OpenRA.Mods.RA/Cargo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenRA.Mods.RA/Cargo.cs b/OpenRA.Mods.RA/Cargo.cs index af77268715..a9add822c1 100644 --- a/OpenRA.Mods.RA/Cargo.cs +++ b/OpenRA.Mods.RA/Cargo.cs @@ -106,7 +106,7 @@ namespace OpenRA.Mods.RA return false; // Cannot load mid-air - return self.CenterPosition.Z < info.MaximumUnloadAltitude.Range; + return self.CenterPosition.Z <= info.MaximumUnloadAltitude.Range; } public string CursorForOrder(Actor self, Order order) From cff5b8bfb0f58a9afa55dea9edcd5539f068fbb6 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 20:41:04 +1200 Subject: [PATCH 25/26] Remove rebase cruft. --- OpenRA.Mods.Cnc/Missions/Nod01Script.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenRA.Mods.Cnc/Missions/Nod01Script.cs b/OpenRA.Mods.Cnc/Missions/Nod01Script.cs index 1eb7a1c667..5b6843e19c 100644 --- a/OpenRA.Mods.Cnc/Missions/Nod01Script.cs +++ b/OpenRA.Mods.Cnc/Missions/Nod01Script.cs @@ -5,7 +5,6 @@ * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, * see COPYING. -<<<<<<< HEAD */ #endregion From cc00c5bc18b445a7c7da66341b531437bcc45f13 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 21 Jul 2013 20:42:07 +1200 Subject: [PATCH 26/26] Fix Nod01Script line endings. --- OpenRA.Mods.Cnc/Missions/Nod01Script.cs | 388 ++++++++++++------------ 1 file changed, 194 insertions(+), 194 deletions(-) diff --git a/OpenRA.Mods.Cnc/Missions/Nod01Script.cs b/OpenRA.Mods.Cnc/Missions/Nod01Script.cs index 5b6843e19c..de88d228f9 100644 --- a/OpenRA.Mods.Cnc/Missions/Nod01Script.cs +++ b/OpenRA.Mods.Cnc/Missions/Nod01Script.cs @@ -1,201 +1,201 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, * see COPYING. - */ -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using OpenRA.Mods.Cnc; -using OpenRA.Mods.RA; -using OpenRA.Mods.RA.Air; -using OpenRA.Mods.RA.Move; -using OpenRA.Mods.RA.Activities; -using OpenRA.Mods.RA.Missions; -using OpenRA.Mods.RA.Buildings; -using OpenRA.Scripting; -using OpenRA.Traits; -using OpenRA.FileFormats; - -namespace OpenRA.Mods.Cnc.Missions -{ - class Nod01ScriptInfo : TraitInfo, Requires { } - - class Nod01Script : IHasObjectives, IWorldLoaded, ITick - { - public event Action OnObjectivesUpdated = notify => { }; - - public IEnumerable Objectives { get { return new[] { killnikoomba, levelvillage }; } } - - Objective killnikoomba = new Objective(ObjectiveType.Primary, KillNikoombaText, ObjectiveStatus.InProgress); - Objective levelvillage = new Objective(ObjectiveType.Primary, LevelVillageText, ObjectiveStatus.Inactive); - - const string KillNikoombaText = "Find Nikoomba. Once found he must be assasinated."; - const string LevelVillageText = "Nikoomba has met his demise, now level the village."; - - Player gdi; - Player nod; - - //actors and the likes go here - Actor nikoomba; - Actor vil01; - Actor vil02; - Actor vil03; - Actor vil04; - Actor vil05; - Actor vil06; - Actor vil07; - Actor vil08; - Actor vil09; - Actor vil10; - Actor vil11; - Actor vil12; - Actor vil13; - Actor civ01; - Actor civ02; - Actor civ03; - Actor civ04; - Actor civ05; - Actor civ06; - Actor civ07; - - //waypoints - Actor nr1; - Actor nr2; - Actor gr1; - - World world; - - //in the allies01 script stuff was here not needed for me so far - const string NRName = "E1"; - const string GRName = "E2"; - const string GRName2 = "JEEP"; - - void MissionFailed(string text) - { - MissionUtils.CoopMissionFailed(world, text, nod); - } - - void MissionAccomplished(string text) - { - MissionUtils.CoopMissionAccomplished(world, text, nod); - } - - public void Tick(Actor self) - { - if (nod.WinState != WinState.Undefined) return; - - //spawns nod reinf - if (world.FrameNumber == 700) - { - NODReinforceNthA(); - Sound.Play("reinfor1.aud"); - } - if (world.FrameNumber == 1400) - { - NODReinforceNthB(); - Sound.Play("reinfor1.aud"); - } - // objectives - if (killnikoomba.Status == ObjectiveStatus.InProgress) - { - if (nikoomba.Destroyed) - { - killnikoomba.Status = ObjectiveStatus.Completed; - levelvillage.Status = ObjectiveStatus.InProgress; - OnObjectivesUpdated(true); - //DisplayObjective(); - //GDIReinforceNth(); - } - } - if (levelvillage.Status == ObjectiveStatus.InProgress) - { - if (vil01.Destroyed && vil02.Destroyed && vil03.Destroyed && vil04.Destroyed && vil05.Destroyed && vil06.Destroyed && - vil07.Destroyed && vil08.Destroyed && vil09.Destroyed && vil10.Destroyed && vil11.Destroyed && vil12.Destroyed && - vil13.Destroyed && civ01.Destroyed && civ02.Destroyed && civ03.Destroyed && civ04.Destroyed && civ05.Destroyed && - civ06.Destroyed && civ07.Destroyed) - { - levelvillage.Status = ObjectiveStatus.Completed; - OnObjectivesUpdated(true); - MissionAccomplished("Nikoomba was killed and the village was destroyed."); - } - } - - if (!world.Actors.Any(a => (a.Owner == nod) && a.IsInWorld && !a.IsDead())) - { - MissionFailed("The Nod forces in the area have been wiped out."); - } - } - - IEnumerable UnitsNearActor(Actor actor, int range) - { - return world.FindActorsInCircle(actor.CenterPosition, WRange.FromCells(range)) - .Where(a => a.IsInWorld && a != world.WorldActor && !a.Destroyed && a.HasTrait() && !a.Owner.NonCombatant); - } - - void NODReinforceNthA() - { - nr1 = world.CreateActor(true, NRName, new TypeDictionary { new OwnerInit(nod), new LocationInit(nr1.Location) }); - nr1 = world.CreateActor(true, NRName, new TypeDictionary { new OwnerInit(nod), new LocationInit(nr1.Location) }); - } - - void NODReinforceNthB() - { - nr2 = world.CreateActor(true, NRName, new TypeDictionary { new OwnerInit(nod), new LocationInit(nr2.Location) }); - nr2 = world.CreateActor(true, NRName, new TypeDictionary { new OwnerInit(nod), new LocationInit(nr2.Location) }); - //nr1.QueueActivity(new Move.Move(nr1.Location - new CVec(0, 2))); - } - - void GDIReinforceNth() - { - gr1 = world.CreateActor(true, GRName, new TypeDictionary { new OwnerInit(gdi), new LocationInit(gr1.Location) }); - gr1 = world.CreateActor(true, GRName, new TypeDictionary { new OwnerInit(gdi), new LocationInit(gr1.Location) }); - gr1 = world.CreateActor(true, GRName2, new TypeDictionary { new OwnerInit(gdi), new LocationInit(gr1.Location) }); - //gr1.QueueActivity(new Move.Move(nr1.Location - new CVec(0, 2))); - } - - public void WorldLoaded(World w) - { - world = w; - gdi = w.Players.Single(p => p.InternalName == "GDI"); - nod = w.Players.Single(p => p.InternalName == "NOD"); - var actors = w.WorldActor.Trait().Actors; - nikoomba = actors["Nikoomba"]; - vil01 = actors["Vil01"]; - vil02 = actors["Vil02"]; - vil03 = actors["Vil03"]; - vil04 = actors["Vil04"]; - vil05 = actors["Vil05"]; - vil06 = actors["Vil06"]; - vil07 = actors["Vil07"]; - vil08 = actors["Vil08"]; - vil09 = actors["Vil09"]; - vil10 = actors["Vil10"]; - vil11 = actors["Vil11"]; - vil12 = actors["Vil12"]; - vil13 = actors["Vil13"]; - civ01 = actors["Civ01"]; - civ02 = actors["Civ02"]; - civ03 = actors["Civ03"]; - civ04 = actors["Civ04"]; - civ05 = actors["Civ05"]; - civ06 = actors["Civ06"]; - civ07 = actors["Civ07"]; - nr1 = actors["NODReinforceNthA"]; - nr2 = actors["NODReinforceNthB"]; - gr1 = actors["GDIReinforceNth"]; - Game.MoveViewport(nr1.Location.ToFloat2()); - Action afterFMV = () => - { - Sound.PlayMusic(Rules.Music["aoi"]); - }; - Game.RunAfterDelay(0, () => Media.PlayFMVFullscreen(w, "nod1pre.vqa", () => - Media.PlayFMVFullscreen(w, "nod1.vqa", afterFMV))); - } - } + */ +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using OpenRA.Mods.Cnc; +using OpenRA.Mods.RA; +using OpenRA.Mods.RA.Air; +using OpenRA.Mods.RA.Move; +using OpenRA.Mods.RA.Activities; +using OpenRA.Mods.RA.Missions; +using OpenRA.Mods.RA.Buildings; +using OpenRA.Scripting; +using OpenRA.Traits; +using OpenRA.FileFormats; + +namespace OpenRA.Mods.Cnc.Missions +{ + class Nod01ScriptInfo : TraitInfo, Requires { } + + class Nod01Script : IHasObjectives, IWorldLoaded, ITick + { + public event Action OnObjectivesUpdated = notify => { }; + + public IEnumerable Objectives { get { return new[] { killnikoomba, levelvillage }; } } + + Objective killnikoomba = new Objective(ObjectiveType.Primary, KillNikoombaText, ObjectiveStatus.InProgress); + Objective levelvillage = new Objective(ObjectiveType.Primary, LevelVillageText, ObjectiveStatus.Inactive); + + const string KillNikoombaText = "Find Nikoomba. Once found he must be assasinated."; + const string LevelVillageText = "Nikoomba has met his demise, now level the village."; + + Player gdi; + Player nod; + + //actors and the likes go here + Actor nikoomba; + Actor vil01; + Actor vil02; + Actor vil03; + Actor vil04; + Actor vil05; + Actor vil06; + Actor vil07; + Actor vil08; + Actor vil09; + Actor vil10; + Actor vil11; + Actor vil12; + Actor vil13; + Actor civ01; + Actor civ02; + Actor civ03; + Actor civ04; + Actor civ05; + Actor civ06; + Actor civ07; + + //waypoints + Actor nr1; + Actor nr2; + Actor gr1; + + World world; + + //in the allies01 script stuff was here not needed for me so far + const string NRName = "E1"; + const string GRName = "E2"; + const string GRName2 = "JEEP"; + + void MissionFailed(string text) + { + MissionUtils.CoopMissionFailed(world, text, nod); + } + + void MissionAccomplished(string text) + { + MissionUtils.CoopMissionAccomplished(world, text, nod); + } + + public void Tick(Actor self) + { + if (nod.WinState != WinState.Undefined) return; + + //spawns nod reinf + if (world.FrameNumber == 700) + { + NODReinforceNthA(); + Sound.Play("reinfor1.aud"); + } + if (world.FrameNumber == 1400) + { + NODReinforceNthB(); + Sound.Play("reinfor1.aud"); + } + // objectives + if (killnikoomba.Status == ObjectiveStatus.InProgress) + { + if (nikoomba.Destroyed) + { + killnikoomba.Status = ObjectiveStatus.Completed; + levelvillage.Status = ObjectiveStatus.InProgress; + OnObjectivesUpdated(true); + //DisplayObjective(); + //GDIReinforceNth(); + } + } + if (levelvillage.Status == ObjectiveStatus.InProgress) + { + if (vil01.Destroyed && vil02.Destroyed && vil03.Destroyed && vil04.Destroyed && vil05.Destroyed && vil06.Destroyed && + vil07.Destroyed && vil08.Destroyed && vil09.Destroyed && vil10.Destroyed && vil11.Destroyed && vil12.Destroyed && + vil13.Destroyed && civ01.Destroyed && civ02.Destroyed && civ03.Destroyed && civ04.Destroyed && civ05.Destroyed && + civ06.Destroyed && civ07.Destroyed) + { + levelvillage.Status = ObjectiveStatus.Completed; + OnObjectivesUpdated(true); + MissionAccomplished("Nikoomba was killed and the village was destroyed."); + } + } + + if (!world.Actors.Any(a => (a.Owner == nod) && a.IsInWorld && !a.IsDead())) + { + MissionFailed("The Nod forces in the area have been wiped out."); + } + } + + IEnumerable UnitsNearActor(Actor actor, int range) + { + return world.FindActorsInCircle(actor.CenterPosition, WRange.FromCells(range)) + .Where(a => a.IsInWorld && a != world.WorldActor && !a.Destroyed && a.HasTrait() && !a.Owner.NonCombatant); + } + + void NODReinforceNthA() + { + nr1 = world.CreateActor(true, NRName, new TypeDictionary { new OwnerInit(nod), new LocationInit(nr1.Location) }); + nr1 = world.CreateActor(true, NRName, new TypeDictionary { new OwnerInit(nod), new LocationInit(nr1.Location) }); + } + + void NODReinforceNthB() + { + nr2 = world.CreateActor(true, NRName, new TypeDictionary { new OwnerInit(nod), new LocationInit(nr2.Location) }); + nr2 = world.CreateActor(true, NRName, new TypeDictionary { new OwnerInit(nod), new LocationInit(nr2.Location) }); + //nr1.QueueActivity(new Move.Move(nr1.Location - new CVec(0, 2))); + } + + void GDIReinforceNth() + { + gr1 = world.CreateActor(true, GRName, new TypeDictionary { new OwnerInit(gdi), new LocationInit(gr1.Location) }); + gr1 = world.CreateActor(true, GRName, new TypeDictionary { new OwnerInit(gdi), new LocationInit(gr1.Location) }); + gr1 = world.CreateActor(true, GRName2, new TypeDictionary { new OwnerInit(gdi), new LocationInit(gr1.Location) }); + //gr1.QueueActivity(new Move.Move(nr1.Location - new CVec(0, 2))); + } + + public void WorldLoaded(World w) + { + world = w; + gdi = w.Players.Single(p => p.InternalName == "GDI"); + nod = w.Players.Single(p => p.InternalName == "NOD"); + var actors = w.WorldActor.Trait().Actors; + nikoomba = actors["Nikoomba"]; + vil01 = actors["Vil01"]; + vil02 = actors["Vil02"]; + vil03 = actors["Vil03"]; + vil04 = actors["Vil04"]; + vil05 = actors["Vil05"]; + vil06 = actors["Vil06"]; + vil07 = actors["Vil07"]; + vil08 = actors["Vil08"]; + vil09 = actors["Vil09"]; + vil10 = actors["Vil10"]; + vil11 = actors["Vil11"]; + vil12 = actors["Vil12"]; + vil13 = actors["Vil13"]; + civ01 = actors["Civ01"]; + civ02 = actors["Civ02"]; + civ03 = actors["Civ03"]; + civ04 = actors["Civ04"]; + civ05 = actors["Civ05"]; + civ06 = actors["Civ06"]; + civ07 = actors["Civ07"]; + nr1 = actors["NODReinforceNthA"]; + nr2 = actors["NODReinforceNthB"]; + gr1 = actors["GDIReinforceNth"]; + Game.MoveViewport(nr1.Location.ToFloat2()); + Action afterFMV = () => + { + Sound.PlayMusic(Rules.Music["aoi"]); + }; + Game.RunAfterDelay(0, () => Media.PlayFMVFullscreen(w, "nod1pre.vqa", () => + Media.PlayFMVFullscreen(w, "nod1.vqa", afterFMV))); + } + } }