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