Convert helicopter activities to world coords.

This commit is contained in:
Paul Chote
2013-07-20 19:49:39 +12:00
parent 712e13b1e7
commit 179f97a598
6 changed files with 53 additions and 47 deletions

View File

@@ -16,15 +16,14 @@ namespace OpenRA.Mods.RA.Air
{ {
class HeliFly : Activity class HeliFly : Activity
{ {
public readonly PPos Dest; readonly WPos pos;
public HeliFly(PPos dest) public HeliFly(WPos pos) { this.pos = pos; }
{ public HeliFly(CPos pos) { this.pos = pos.CenterPosition; }
Dest = dest;
}
public override Activity Tick(Actor self) public override Activity Tick(Actor self)
{ {
if (IsCanceled) return NextActivity; if (IsCanceled)
return NextActivity;
var info = self.Info.Traits.Get<HelicopterInfo>(); var info = self.Info.Traits.Get<HelicopterInfo>();
var aircraft = self.Trait<Aircraft>(); var aircraft = self.Trait<Aircraft>();
@@ -35,23 +34,25 @@ namespace OpenRA.Mods.RA.Air
return this; return this;
} }
var dist = Dest - aircraft.PxPosition; // The next move would overshoot, so just set the final position
if (Math.Abs(dist.X) < 2 && Math.Abs(dist.Y) < 2) 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; return NextActivity;
} }
var desiredFacing = Util.GetFacing(dist, aircraft.Facing); var desiredFacing = Util.GetFacing(dist, aircraft.Facing);
aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT); 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; return this;
} }
public override IEnumerable<Target> GetTargets( Actor self ) public override IEnumerable<Target> GetTargets(Actor self)
{ {
yield return Target.FromPos(Dest); yield return Target.FromPos(pos);
} }
} }
} }

View File

@@ -42,7 +42,7 @@ namespace OpenRA.Mods.RA.Air
if (nearestHpad == null) if (nearestHpad == null)
return Util.SequenceActivities(new Turn(initialFacing), new HeliLand(true, 0), NextActivity); return Util.SequenceActivities(new Turn(initialFacing), new HeliLand(true, 0), NextActivity);
else else
return Util.SequenceActivities(new HeliFly(Util.CenterOfCell(nearestHpad.Location))); return Util.SequenceActivities(new HeliFly(nearestHpad.CenterPosition));
} }
var res = dest.TraitOrDefault<Reservable>(); var res = dest.TraitOrDefault<Reservable>();
@@ -51,10 +51,11 @@ namespace OpenRA.Mods.RA.Air
heli.reservation = res.Reserve(dest, self, heli); heli.reservation = res.Reserve(dest, self, heli);
var exit = dest.Info.Traits.WithInterface<ExitInfo>().FirstOrDefault(); var exit = dest.Info.Traits.WithInterface<ExitInfo>().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( return Util.SequenceActivities(
new HeliFly(dest.Trait<IHasLocation>().PxPosition + offset), new HeliFly(dest.CenterPosition + offset),
new Turn(initialFacing), new Turn(initialFacing),
new HeliLand(false, 0), new HeliLand(false, 0),
new Rearm(self), new Rearm(self),

View File

@@ -17,7 +17,7 @@ namespace OpenRA.Mods.RA.Air
{ {
class HelicopterInfo : AircraftInfo class HelicopterInfo : AircraftInfo
{ {
public readonly int IdealSeparation = 40; public readonly WRange IdealSeparation = new WRange(1706);
public readonly bool LandWhenIdle = true; public readonly bool LandWhenIdle = true;
public readonly int MinimalLandAltitude = 0; public readonly int MinimalLandAltitude = 0;
@@ -48,7 +48,7 @@ namespace OpenRA.Mods.RA.Air
self.SetTargetLine(Target.FromCell(target), Color.Green); self.SetTargetLine(Target.FromCell(target), Color.Green);
self.CancelActivity(); self.CancelActivity();
self.QueueActivity(new HeliFly(Util.CenterOfCell(target))); self.QueueActivity(new HeliFly(target));
if (Info.LandWhenIdle) if (Info.LandWhenIdle)
{ {
@@ -71,12 +71,13 @@ namespace OpenRA.Mods.RA.Air
reservation = res.Reserve(order.TargetActor, self, this); reservation = res.Reserve(order.TargetActor, self, this);
var exit = order.TargetActor.Info.Traits.WithInterface<ExitInfo>().FirstOrDefault(); var exit = order.TargetActor.Info.Traits.WithInterface<ExitInfo>().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.SetTargetLine(Target.FromActor(order.TargetActor), Color.Green);
self.CancelActivity(); self.CancelActivity();
self.QueueActivity(new HeliFly(order.TargetActor.Trait<IHasLocation>().PxPosition + offset)); self.QueueActivity(new HeliFly(order.TargetActor.CenterPosition + offset));
self.QueueActivity(new Turn(Info.InitialFacing)); self.QueueActivity(new Turn(Info.InitialFacing));
self.QueueActivity(new HeliLand(false, Info.MinimalLandAltitude)); self.QueueActivity(new HeliLand(false, Info.MinimalLandAltitude));
self.QueueActivity(new ResupplyAircraft()); self.QueueActivity(new ResupplyAircraft());
@@ -110,38 +111,40 @@ namespace OpenRA.Mods.RA.Air
ReserveSpawnBuilding(); ReserveSpawnBuilding();
} }
/* repulsion only applies when we're flying */ // Repulsion only applies when we're flying!
if (Altitude <= 0) return; if (Altitude != Info.CruiseAltitude)
return;
var separation = new WRange(Info.IdealSeparation * 1024 / Game.CellSize); var otherHelis = self.World.FindActorsInCircle(self.CenterPosition, Info.IdealSeparation)
var otherHelis = self.World.FindActorsInCircle(self.CenterPosition, separation)
.Where(a => a.HasTrait<Helicopter>()); .Where(a => a.HasTrait<Helicopter>());
var f = otherHelis var f = otherHelis
.Select(h => GetRepulseForce(self, h)) .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, -1);
int repulsionFacing = Util.GetFacing( f.ToInt2(), -1 ); if (repulsionFacing != -1)
if( repulsionFacing != -1 )
TickMove(PSubPos.PerPx * MovementSpeed, repulsionFacing); TickMove(PSubPos.PerPx * MovementSpeed, repulsionFacing);
} }
// Returns a vector in subPx units public WVec GetRepulseForce(Actor self, Actor other)
public PSubVec GetRepulseForce(Actor self, Actor h)
{ {
if (self == h) if (self == other || other.Trait<Helicopter>().Altitude < Altitude)
return PSubVec.Zero; return WVec.Zero;
if( h.Trait<Helicopter>().Altitude < Altitude )
return PSubVec.Zero;
var d = self.CenterLocation - h.CenterLocation;
if (d.Length > Info.IdealSeparation) var d = self.CenterPosition - other.CenterPosition;
return PSubVec.Zero; var dlSq = d.HorizontalLengthSquared;
if (dlSq > Info.IdealSeparation.Range*Info.IdealSeparation.Range)
return WVec.Zero;
if (d.LengthSquared < 1) if (dlSq < 1)
return Util.SubPxVector[self.World.SharedRandom.Next(255)]; {
return (5 * d.ToPSubVec()) / d.LengthSquared; 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;
} }
} }
} }

View File

@@ -217,14 +217,15 @@ namespace OpenRA.Mods.RA.Missions
cargo.Load(chinook, world.CreateActor(false, ChinookCargo.Random(world.SharedRandom), allies, null, null)); cargo.Load(chinook, world.CreateActor(false, ChinookCargo.Random(world.SharedRandom), allies, null, null));
var exit = lz.Info.Traits.WithInterface<ExitInfo>().FirstOrDefault(); var exit = lz.Info.Traits.WithInterface<ExitInfo>().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 Turn(0));
chinook.QueueActivity(new HeliLand(false, 0)); chinook.QueueActivity(new HeliLand(false, 0));
chinook.QueueActivity(new UnloadCargo(true)); chinook.QueueActivity(new UnloadCargo(true));
chinook.QueueActivity(new Wait(150)); chinook.QueueActivity(new Wait(150));
chinook.QueueActivity(new HeliFly(Util.CenterOfCell(entry))); chinook.QueueActivity(new HeliFly(entry));
chinook.QueueActivity(new RemoveSelf()); chinook.QueueActivity(new RemoveSelf());
} }

View File

@@ -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) 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) }); 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 Turn(0));
chinook.QueueActivity(new HeliLand(true, 0)); chinook.QueueActivity(new HeliLand(true, 0));
chinook.QueueActivity(new WaitFor(() => chinook.Trait<Cargo>().Passengers.Contains(unit))); chinook.QueueActivity(new WaitFor(() => chinook.Trait<Cargo>().Passengers.Contains(unit)));
chinook.QueueActivity(new Wait(150)); chinook.QueueActivity(new Wait(150));
chinook.QueueActivity(new HeliFly(Util.CenterOfCell(exit))); chinook.QueueActivity(new HeliFly(exit));
chinook.QueueActivity(new RemoveSelf()); chinook.QueueActivity(new RemoveSelf());
return chinook; return chinook;
} }
@@ -60,13 +60,13 @@ namespace OpenRA.Mods.RA.Missions
var unit = world.CreateActor(false, unitName, new TypeDictionary { new OwnerInit(owner) }); var unit = world.CreateActor(false, unitName, new TypeDictionary { new OwnerInit(owner) });
var chinook = world.CreateActor("tran", new TypeDictionary { new OwnerInit(owner), new LocationInit(entry) }); var chinook = world.CreateActor("tran", new TypeDictionary { new OwnerInit(owner), new LocationInit(entry) });
chinook.Trait<Cargo>().Load(chinook, unit); chinook.Trait<Cargo>().Load(chinook, unit);
chinook.QueueActivity(new HeliFly(Util.CenterOfCell(lz))); chinook.QueueActivity(new HeliFly(lz));
chinook.QueueActivity(new Turn(0)); chinook.QueueActivity(new Turn(0));
chinook.QueueActivity(new HeliLand(true, 0)); chinook.QueueActivity(new HeliLand(true, 0));
chinook.QueueActivity(new UnloadCargo(true)); chinook.QueueActivity(new UnloadCargo(true));
chinook.QueueActivity(new CallFunc(() => afterUnload(unit))); chinook.QueueActivity(new CallFunc(() => afterUnload(unit)));
chinook.QueueActivity(new Wait(150)); chinook.QueueActivity(new Wait(150));
chinook.QueueActivity(new HeliFly(Util.CenterOfCell(exit))); chinook.QueueActivity(new HeliFly(exit));
chinook.QueueActivity(new RemoveSelf()); chinook.QueueActivity(new RemoveSelf());
return Pair.New(chinook, unit); return Pair.New(chinook, unit);
} }

View File

@@ -104,7 +104,7 @@ namespace OpenRA.Mods.RA
var helicopter = newUnit.TraitOrDefault<Helicopter>(); var helicopter = newUnit.TraitOrDefault<Helicopter>();
if (helicopter != null) if (helicopter != null)
{ {
newUnit.QueueActivity(new HeliFly(Util.CenterOfCell(rp.rallyPoint))); newUnit.QueueActivity(new HeliFly(rp.rallyPoint));
return rp.rallyPoint; return rp.rallyPoint;
} }