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; }