diff --git a/OpenRA.Mods.Cnc/Traits/Buildings/ProductionAirdrop.cs b/OpenRA.Mods.Cnc/Traits/Buildings/ProductionAirdrop.cs index 617640c0bf..1cbd7d5d46 100644 --- a/OpenRA.Mods.Cnc/Traits/Buildings/ProductionAirdrop.cs +++ b/OpenRA.Mods.Cnc/Traits/Buildings/ProductionAirdrop.cs @@ -55,7 +55,7 @@ namespace OpenRA.Mods.Cnc.Traits if (!self.IsInWorld || self.IsDead) return; - var altitude = self.World.Map.Rules.Actors[actorType].TraitInfo().CruiseAltitude; + var altitude = self.World.Map.Rules.Actors[actorType].TraitInfo().CruiseAltitude; var actor = w.CreateActor(actorType, new TypeDictionary { new CenterPositionInit(w.Map.CenterOfCell(startPos) + new WVec(WDist.Zero, WDist.Zero, altitude)), diff --git a/OpenRA.Mods.Common/Activities/Air/Fly.cs b/OpenRA.Mods.Common/Activities/Air/Fly.cs index 70ada20612..dc955a15e8 100644 --- a/OpenRA.Mods.Common/Activities/Air/Fly.cs +++ b/OpenRA.Mods.Common/Activities/Air/Fly.cs @@ -17,14 +17,14 @@ namespace OpenRA.Mods.Common.Activities { public class Fly : Activity { - readonly Plane plane; + readonly Aircraft plane; readonly Target target; readonly WDist maxRange; readonly WDist minRange; public Fly(Actor self, Target t) { - plane = self.Trait(); + plane = self.Trait(); target = t; } @@ -35,7 +35,7 @@ namespace OpenRA.Mods.Common.Activities this.minRange = minRange; } - public static void FlyToward(Actor self, Plane plane, int desiredFacing, WDist desiredAltitude) + public static void FlyToward(Actor self, Aircraft plane, int desiredFacing, WDist desiredAltitude) { desiredAltitude = new WDist(plane.CenterPosition.Z) + desiredAltitude - self.World.Map.DistanceAboveTerrain(plane.CenterPosition); diff --git a/OpenRA.Mods.Common/Activities/Air/FlyCircle.cs b/OpenRA.Mods.Common/Activities/Air/FlyCircle.cs index abd86f5bd9..f3af7e605f 100644 --- a/OpenRA.Mods.Common/Activities/Air/FlyCircle.cs +++ b/OpenRA.Mods.Common/Activities/Air/FlyCircle.cs @@ -10,18 +10,17 @@ using OpenRA.Activities; using OpenRA.Mods.Common.Traits; -using OpenRA.Traits; namespace OpenRA.Mods.Common.Activities { public class FlyCircle : Activity { - readonly Plane plane; + readonly Aircraft plane; readonly WDist cruiseAltitude; public FlyCircle(Actor self) { - plane = self.Trait(); + plane = self.Trait(); cruiseAltitude = plane.Info.CruiseAltitude; } diff --git a/OpenRA.Mods.Common/Activities/Air/FlyFollow.cs b/OpenRA.Mods.Common/Activities/Air/FlyFollow.cs index 42a360a0c4..5b717d1af5 100644 --- a/OpenRA.Mods.Common/Activities/Air/FlyFollow.cs +++ b/OpenRA.Mods.Common/Activities/Air/FlyFollow.cs @@ -17,14 +17,14 @@ namespace OpenRA.Mods.Common.Activities public class FlyFollow : Activity { Target target; - Plane plane; + Aircraft plane; WDist minRange; WDist maxRange; public FlyFollow(Actor self, Target target, WDist minRange, WDist maxRange) { this.target = target; - plane = self.Trait(); + plane = self.Trait(); this.minRange = minRange; this.maxRange = maxRange; } diff --git a/OpenRA.Mods.Common/Activities/Air/FlyOffMap.cs b/OpenRA.Mods.Common/Activities/Air/FlyOffMap.cs index ae14d90ee5..19ea996400 100644 --- a/OpenRA.Mods.Common/Activities/Air/FlyOffMap.cs +++ b/OpenRA.Mods.Common/Activities/Air/FlyOffMap.cs @@ -10,17 +10,16 @@ using OpenRA.Activities; using OpenRA.Mods.Common.Traits; -using OpenRA.Traits; namespace OpenRA.Mods.Common.Activities { public class FlyOffMap : Activity { - readonly Plane plane; + readonly Aircraft plane; public FlyOffMap(Actor self) { - plane = self.Trait(); + plane = self.Trait(); } public override Activity Tick(Actor self) diff --git a/OpenRA.Mods.Common/Activities/Air/FlyTimed.cs b/OpenRA.Mods.Common/Activities/Air/FlyTimed.cs index 0b5dc020be..21de44c4a4 100644 --- a/OpenRA.Mods.Common/Activities/Air/FlyTimed.cs +++ b/OpenRA.Mods.Common/Activities/Air/FlyTimed.cs @@ -10,20 +10,19 @@ using OpenRA.Activities; using OpenRA.Mods.Common.Traits; -using OpenRA.Traits; namespace OpenRA.Mods.Common.Activities { public class FlyTimed : Activity { - readonly Plane plane; + readonly Aircraft plane; readonly WDist cruiseAltitude; int remainingTicks; public FlyTimed(int ticks, Actor self) { remainingTicks = ticks; - plane = self.Trait(); + plane = self.Trait(); cruiseAltitude = plane.Info.CruiseAltitude; } diff --git a/OpenRA.Mods.Common/Activities/Air/HeliAttack.cs b/OpenRA.Mods.Common/Activities/Air/HeliAttack.cs index 0d501ec01a..e977c6de3f 100644 --- a/OpenRA.Mods.Common/Activities/Air/HeliAttack.cs +++ b/OpenRA.Mods.Common/Activities/Air/HeliAttack.cs @@ -8,7 +8,6 @@ */ #endregion -using System.Collections.Generic; using System.Drawing; using System.Linq; using OpenRA.Activities; @@ -19,7 +18,7 @@ namespace OpenRA.Mods.Common.Activities { public class HeliAttack : Activity { - readonly Helicopter helicopter; + readonly Aircraft helicopter; readonly AttackHeli attackHeli; readonly AmmoPool[] ammoPools; readonly bool attackOnlyVisibleTargets; @@ -44,7 +43,7 @@ namespace OpenRA.Mods.Common.Activities public HeliAttack(Actor self, Target target, bool attackOnlyVisibleTargets = true) { Target = target; - helicopter = self.Trait(); + helicopter = self.Trait(); attackHeli = self.Trait(); ammoPools = self.TraitsImplementing().ToArray(); this.attackOnlyVisibleTargets = attackOnlyVisibleTargets; diff --git a/OpenRA.Mods.Common/Activities/Air/HeliFly.cs b/OpenRA.Mods.Common/Activities/Air/HeliFly.cs index 1717f87c42..f2578ec13e 100644 --- a/OpenRA.Mods.Common/Activities/Air/HeliFly.cs +++ b/OpenRA.Mods.Common/Activities/Air/HeliFly.cs @@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Activities { public class HeliFly : Activity { - readonly Helicopter helicopter; + readonly Aircraft helicopter; readonly Target target; readonly WDist maxRange; readonly WDist minRange; @@ -25,7 +25,7 @@ namespace OpenRA.Mods.Common.Activities public HeliFly(Actor self, Target t) { - helicopter = self.Trait(); + helicopter = self.Trait(); target = t; } @@ -36,7 +36,7 @@ namespace OpenRA.Mods.Common.Activities this.minRange = minRange; } - public static bool AdjustAltitude(Actor self, Helicopter helicopter, WDist targetAltitude) + public static bool AdjustAltitude(Actor self, Aircraft helicopter, WDist targetAltitude) { targetAltitude = new WDist(helicopter.CenterPosition.Z) + targetAltitude - self.World.Map.DistanceAboveTerrain(helicopter.CenterPosition); @@ -105,9 +105,9 @@ namespace OpenRA.Mods.Common.Activities public class HeliFlyAndLandWhenIdle : HeliFly { - private readonly HelicopterInfo info; + private readonly AircraftInfo info; - public HeliFlyAndLandWhenIdle(Actor self, Target t, HelicopterInfo info) + public HeliFlyAndLandWhenIdle(Actor self, Target t, AircraftInfo info) : base(self, t) { this.info = info; diff --git a/OpenRA.Mods.Common/Activities/Air/HeliFlyCircle.cs b/OpenRA.Mods.Common/Activities/Air/HeliFlyCircle.cs index 34b3704103..b414cad8d5 100644 --- a/OpenRA.Mods.Common/Activities/Air/HeliFlyCircle.cs +++ b/OpenRA.Mods.Common/Activities/Air/HeliFlyCircle.cs @@ -8,8 +8,6 @@ */ #endregion -using System; -using System.Collections.Generic; using OpenRA.Activities; using OpenRA.Mods.Common.Traits; using OpenRA.Traits; @@ -18,11 +16,11 @@ namespace OpenRA.Mods.Common.Activities { public class HeliFlyCircle : Activity { - readonly Helicopter helicopter; + readonly Aircraft helicopter; public HeliFlyCircle(Actor self) { - helicopter = self.Trait(); + helicopter = self.Trait(); } public override Activity Tick(Actor self) diff --git a/OpenRA.Mods.Common/Activities/Air/HeliLand.cs b/OpenRA.Mods.Common/Activities/Air/HeliLand.cs index 4fd677f115..3c9a2310c9 100644 --- a/OpenRA.Mods.Common/Activities/Air/HeliLand.cs +++ b/OpenRA.Mods.Common/Activities/Air/HeliLand.cs @@ -15,14 +15,14 @@ namespace OpenRA.Mods.Common.Activities { public class HeliLand : Activity { - readonly Helicopter helicopter; + readonly Aircraft helicopter; bool requireSpace; bool playedSound; public HeliLand(Actor self, bool requireSpace) { this.requireSpace = requireSpace; - helicopter = self.Trait(); + helicopter = self.Trait(); } public override Activity Tick(Actor self) diff --git a/OpenRA.Mods.Common/Activities/Air/HeliReturn.cs b/OpenRA.Mods.Common/Activities/Air/HeliReturn.cs index 42cc0da1aa..efc4eb9fef 100644 --- a/OpenRA.Mods.Common/Activities/Air/HeliReturn.cs +++ b/OpenRA.Mods.Common/Activities/Air/HeliReturn.cs @@ -17,11 +17,11 @@ namespace OpenRA.Mods.Common.Activities { public class HeliReturn : Activity { - readonly Helicopter heli; + readonly Aircraft heli; public HeliReturn(Actor self) { - heli = self.Trait(); + heli = self.Trait(); } public Actor ChooseHelipad(Actor self) diff --git a/OpenRA.Mods.Common/Activities/Air/Land.cs b/OpenRA.Mods.Common/Activities/Air/Land.cs index 762c61a73f..c7ddd74d27 100644 --- a/OpenRA.Mods.Common/Activities/Air/Land.cs +++ b/OpenRA.Mods.Common/Activities/Air/Land.cs @@ -17,12 +17,12 @@ namespace OpenRA.Mods.Common.Activities public class Land : Activity { readonly Target target; - readonly Plane plane; + readonly Aircraft plane; public Land(Actor self, Target t) { target = t; - plane = self.Trait(); + plane = self.Trait(); } public override Activity Tick(Actor self) diff --git a/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs b/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs index 050b0e0270..ff485f4549 100644 --- a/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs +++ b/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs @@ -18,8 +18,8 @@ namespace OpenRA.Mods.Common.Activities { public class ReturnToBase : Activity { - readonly Plane plane; - readonly PlaneInfo planeInfo; + readonly Aircraft plane; + readonly AircraftInfo planeInfo; bool isCalculated; Actor dest; WPos w1, w2, w3; @@ -27,13 +27,13 @@ namespace OpenRA.Mods.Common.Activities public ReturnToBase(Actor self, Actor dest = null) { this.dest = dest; - plane = self.Trait(); - planeInfo = self.Info.TraitInfo(); + plane = self.Trait(); + planeInfo = self.Info.TraitInfo(); } public static Actor ChooseAirfield(Actor self, bool unreservedOnly) { - var rearmBuildings = self.Info.TraitInfo().RearmBuildings; + var rearmBuildings = self.Info.TraitInfo().RearmBuildings; return self.World.ActorsWithTrait() .Where(a => a.Actor.Owner == self.Owner) .Where(a => rearmBuildings.Contains(a.Actor.Info.Name) @@ -94,7 +94,6 @@ namespace OpenRA.Mods.Common.Activities w1 = posCenter + tangentOffset; w2 = approachCenter + tangentOffset; w3 = approachStart; - plane.RTBPathHash = w1 + (WVec)w2 + (WVec)w3; isCalculated = true; } diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 977388d811..734bfb3fe6 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -205,6 +205,7 @@ + @@ -235,13 +236,11 @@ - - @@ -258,8 +257,6 @@ - - diff --git a/OpenRA.Mods.Common/Scripting/Global/ReinforcementsGlobal.cs b/OpenRA.Mods.Common/Scripting/Global/ReinforcementsGlobal.cs index 934c2fca76..ec62bf1dd4 100644 --- a/OpenRA.Mods.Common/Scripting/Global/ReinforcementsGlobal.cs +++ b/OpenRA.Mods.Common/Scripting/Global/ReinforcementsGlobal.cs @@ -137,11 +137,19 @@ namespace OpenRA.Mods.Common.Scripting } else { - var heli = transport.Info.TraitInfoOrDefault(); - if (heli != null) + var aircraftInfo = transport.TraitOrDefault(); + if (aircraftInfo != null) { - transport.QueueActivity(new Turn(transport, heli.InitialFacing)); - transport.QueueActivity(new HeliLand(transport, true)); + if (!aircraftInfo.IsPlane) + { + transport.QueueActivity(new Turn(transport, aircraftInfo.Info.InitialFacing)); + transport.QueueActivity(new HeliLand(transport, true)); + } + else + { + transport.QueueActivity(new Land(transport, Target.FromCell(transport.World, entryPath.Last()))); + } + transport.QueueActivity(new Wait(15)); } @@ -151,7 +159,7 @@ namespace OpenRA.Mods.Common.Scripting transport.QueueActivity(new WaitFor(() => cargo.IsEmpty(transport))); } - transport.QueueActivity(new Wait(heli != null ? 50 : 25)); + transport.QueueActivity(new Wait(aircraftInfo != null ? 50 : 25)); } if (exitFunc != null) diff --git a/OpenRA.Mods.Common/Scripting/Properties/PlaneProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/AircraftProperties.cs similarity index 60% rename from OpenRA.Mods.Common/Scripting/Properties/PlaneProperties.cs rename to OpenRA.Mods.Common/Scripting/Properties/AircraftProperties.cs index a49f21039f..68006b7c5d 100644 --- a/OpenRA.Mods.Common/Scripting/Properties/PlaneProperties.cs +++ b/OpenRA.Mods.Common/Scripting/Properties/AircraftProperties.cs @@ -16,23 +16,34 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Scripting { [ScriptPropertyGroup("Movement")] - public class PlaneProperties : ScriptActorProperties, Requires + public class AircraftProperties : ScriptActorProperties, Requires { - public PlaneProperties(ScriptContext context, Actor self) - : base(context, self) { } + readonly bool isPlane; + + public AircraftProperties(ScriptContext context, Actor self) + : base(context, self) + { + isPlane = self.Trait().IsPlane; + } [ScriptActorPropertyActivity] [Desc("Fly within the cell grid.")] public void Move(CPos cell) { - Self.QueueActivity(new Fly(Self, Target.FromCell(Self.World, cell))); + if (isPlane) + Self.QueueActivity(new Fly(Self, Target.FromCell(Self.World, cell))); + else + Self.QueueActivity(new HeliFly(Self, Target.FromCell(Self.World, cell))); } [ScriptActorPropertyActivity] [Desc("Return to the base, which is either the airfield given, or an auto-selected one otherwise.")] public void ReturnToBase(Actor airfield = null) { - Self.QueueActivity(new ReturnToBase(Self, airfield)); + if (isPlane) + Self.QueueActivity(new ReturnToBase(Self, airfield)); + else + Self.QueueActivity(new HeliReturn(Self)); } } } \ No newline at end of file diff --git a/OpenRA.Mods.Common/Scripting/Properties/HelicopterProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/HelicopterProperties.cs deleted file mode 100644 index eb0e718d63..0000000000 --- a/OpenRA.Mods.Common/Scripting/Properties/HelicopterProperties.cs +++ /dev/null @@ -1,31 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2015 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 OpenRA.Mods.Common.Activities; -using OpenRA.Mods.Common.Traits; -using OpenRA.Scripting; -using OpenRA.Traits; - -namespace OpenRA.Mods.Common.Scripting -{ - [ScriptPropertyGroup("Movement")] - public class HelicopterProperties : ScriptActorProperties, Requires - { - public HelicopterProperties(ScriptContext context, Actor self) - : base(context, self) { } - - [ScriptActorPropertyActivity] - [Desc("Fly within the cell grid.")] - public void Move(CPos cell) - { - Self.QueueActivity(new HeliFly(Self, Target.FromCell(Self.World, cell))); - } - } -} \ No newline at end of file diff --git a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs index 619a3e545f..59f416f13b 100644 --- a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs +++ b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs @@ -10,6 +10,7 @@ using System; using System.Collections.Generic; +using System.Drawing; using System.Linq; using OpenRA.Activities; using OpenRA.Mods.Common.Activities; @@ -19,7 +20,8 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { - public class AircraftInfo : IPositionableInfo, IFacingInfo, IOccupySpaceInfo, ICruiseAltitudeInfo, UsesInit, UsesInit + public class AircraftInfo : IPositionableInfo, IFacingInfo, IOccupySpaceInfo, IMoveInfo, ICruiseAltitudeInfo, + UsesInit, UsesInit { public readonly WDist CruiseAltitude = new WDist(1280); public readonly WDist IdealSeparation = new WDist(1706); @@ -53,23 +55,51 @@ namespace OpenRA.Mods.Common.Traits [Desc("The upgrades to grant to self while airborne.")] public readonly string[] AirborneUpgrades = { }; + [Desc("Can the actor hover in place mid-air? If not, then the actor will have to remain in motion (circle around).")] + public readonly bool CanHover = false; + + [Desc("Will this actor try to land after it has no more commands?")] + public readonly bool LandWhenIdle = true; + + [Desc("Does this actor need to turn before landing?")] + public readonly bool TurnToLand = false; + + public readonly WDist LandAltitude = WDist.Zero; + + [Desc("How fast this actor ascends or descends when using horizontal take off/landing.")] + public readonly WAngle MaximumPitch = WAngle.FromDegrees(10); + + [Desc("How fast this actor ascends or descends when using vertical take off/landing.")] + public readonly WDist AltitudeVelocity = new WDist(43); + + [Desc("Sound to play when the actor is taking off.")] + public readonly string TakeoffSound = null; + + [Desc("Sound to play when the actor is landing.")] + public readonly string LandingSound = null; + public IReadOnlyDictionary OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any) { return new ReadOnlyDictionary(); } bool IOccupySpaceInfo.SharesCell { get { return false; } } } - public class Aircraft : IFacing, IPositionable, ISync, IIssueOrder, IOrderVoice, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyCreated, INotifyActorDisposing + public class Aircraft : ITick, ISync, IFacing, IPositionable, IMove, IIssueOrder, IResolveOrder, IOrderVoice, + INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyActorDisposing { static readonly Pair[] NoCells = { }; - readonly AircraftInfo info; + public readonly bool IsPlane; + public readonly AircraftInfo Info; readonly Actor self; + UpgradeManager um; [Sync] public int Facing { get; set; } [Sync] public WPos CenterPosition { get; private set; } public CPos TopLeft { get { return self.World.Map.CellContaining(CenterPosition); } } public IDisposable Reservation; - public int ROT { get { return info.ROT; } } + public int ROT { get { return Info.ROT; } } + + bool airborne; bool IsAirborne { get @@ -85,21 +115,19 @@ namespace OpenRA.Mods.Common.Traits if (um != null) { if (airborne) - foreach (var u in info.AirborneUpgrades) + foreach (var u in Info.AirborneUpgrades) um.GrantUpgrade(self, u, this); else - foreach (var u in info.AirborneUpgrades) + foreach (var u in Info.AirborneUpgrades) um.RevokeUpgrade(self, u, this); } } } - bool airborne = false; - public Aircraft(ActorInitializer init, AircraftInfo info) { - this.info = info; - this.self = init.Self; + Info = info; + self = init.Self; if (init.Contains()) SetPosition(self, init.Get()); @@ -108,10 +136,23 @@ namespace OpenRA.Mods.Common.Traits SetPosition(self, init.Get()); Facing = init.Contains() ? init.Get() : info.InitialFacing; + + // TODO: HACK: This is a hack until we can properly distinquish between airplane and helicopter! + // Or until the activities get unified enough so that it doesn't matter. + IsPlane = !info.CanHover; } public void Created(Actor self) { um = self.TraitOrDefault(); } + public void AddedToWorld(Actor self) + { + self.World.ActorMap.AddInfluence(self, this); + self.World.ActorMap.AddPosition(self, this); + self.World.ScreenMap.Add(self); + if (self.World.Map.DistanceAboveTerrain(CenterPosition).Length >= Info.MinAirborneAltitude) + IsAirborne = true; + } + bool firstTick = true; public virtual void Tick(Actor self) { @@ -143,24 +184,39 @@ namespace OpenRA.Mods.Common.Traits if (repulsionFacing == -1) return; - var speed = info.RepulsionSpeed != -1 ? info.RepulsionSpeed : MovementSpeed; + var speed = Info.RepulsionSpeed != -1 ? Info.RepulsionSpeed : MovementSpeed; SetPosition(self, CenterPosition + FlyStep(speed, repulsionFacing)); } public virtual WVec GetRepulsionForce() { - if (!info.Repulsable) + if (!Info.Repulsable) return WVec.Zero; // Repulsion only applies when we're flying! var altitude = CenterPosition.Z; - if (altitude != info.CruiseAltitude.Length) + if (altitude != Info.CruiseAltitude.Length) return WVec.Zero; - return self.World.FindActorsInCircle(self.CenterPosition, info.IdealSeparation) - .Where(a => !a.IsDead && a.Info.HasTraitInfo() && a.Info.TraitInfo().CruiseAltitude == info.CruiseAltitude) + var repulsionForce = self.World.FindActorsInCircle(self.CenterPosition, Info.IdealSeparation) + .Where(a => !a.IsDead && a.Info.HasTraitInfo() + && a.Info.TraitInfo().CruiseAltitude == Info.CruiseAltitude) .Select(GetRepulsionForce) .Aggregate(WVec.Zero, (a, b) => a + b); + + if (Info.CanHover) + return repulsionForce; + + // Non-hovering actors mush always keep moving forward, so they need extra calculations. + var currentDir = FlyStep(Facing); + var length = currentDir.HorizontalLength * repulsionForce.HorizontalLength; + if (length == 0) + return WVec.Zero; + + var dot = WVec.Dot(currentDir, repulsionForce) / length; + + // avoid stalling the plane + return dot >= 0 ? repulsionForce : WVec.Zero; } public WVec GetRepulsionForce(Actor other) @@ -170,7 +226,7 @@ namespace OpenRA.Mods.Common.Traits var d = self.CenterPosition - other.CenterPosition; var distSq = d.HorizontalLengthSquared; - if (distSq > info.IdealSeparation.LengthSquared) + if (distSq > Info.IdealSeparation.LengthSquared) return WVec.Zero; if (distSq < 1) @@ -219,78 +275,13 @@ namespace OpenRA.Mods.Common.Traits } } - public void Disposing(Actor self) - { - UnReserve(); - } - - public void SetPosition(Actor self, WPos pos) - { - CenterPosition = pos; - - if (self.IsInWorld) - { - self.World.ScreenMap.Update(self); - self.World.ActorMap.UpdatePosition(self, this); - IsAirborne = self.World.Map.DistanceAboveTerrain(CenterPosition).Length >= info.MinAirborneAltitude; - } - } - - // Changes position, but not altitude - public void SetPosition(Actor self, CPos cell, SubCell subCell = SubCell.Any) - { - SetPosition(self, self.World.Map.CenterOfCell(cell) + new WVec(0, 0, CenterPosition.Z)); - } - - public void SetVisualPosition(Actor self, WPos pos) { SetPosition(self, pos); } - - public void AddedToWorld(Actor self) - { - self.World.ActorMap.AddInfluence(self, this); - self.World.ActorMap.AddPosition(self, this); - self.World.ScreenMap.Add(self); - if (self.World.Map.DistanceAboveTerrain(CenterPosition).Length >= info.MinAirborneAltitude) - IsAirborne = true; - } - - public void RemovedFromWorld(Actor self) - { - UnReserve(); - self.World.ActorMap.RemoveInfluence(self, this); - self.World.ActorMap.RemovePosition(self, this); - self.World.ScreenMap.Remove(self); - IsAirborne = false; - } - public bool AircraftCanEnter(Actor a) { if (self.AppearsHostileTo(a)) return false; - return info.RearmBuildings.Contains(a.Info.Name) - || info.RepairBuildings.Contains(a.Info.Name); - } - - public bool IsLeavingCell(CPos location, SubCell subCell = SubCell.Any) { return false; } // TODO: Handle landing - public SubCell GetValidSubCell(SubCell preferred) { return SubCell.Invalid; } - public SubCell GetAvailableSubCell(CPos a, SubCell preferredSubCell = SubCell.Any, Actor ignoreActor = null, bool checkTransientActors = true) - { - // Does not use any subcell - return SubCell.Invalid; - } - - public bool CanEnterCell(CPos cell, Actor ignoreActor = null, bool checkTransientActors = true) { return true; } - - public bool CanEnterTargetNow(Actor self, Target target) - { - if (target.Positions.Any(p => self.World.ActorMap.GetUnitsAt(self.World.Map.CellContaining(p)).Any(a => a != self && a != target.Actor))) - return false; - var res = target.Actor.TraitOrDefault(); - if (res == null) - return true; - UnReserve(); - Reservation = res.Reserve(target.Actor, self, this); - return true; + return Info.RearmBuildings.Contains(a.Info.Name) + || Info.RepairBuildings.Contains(a.Info.Name); } public int MovementSpeed @@ -299,7 +290,7 @@ namespace OpenRA.Mods.Common.Traits { var modifiers = self.TraitsImplementing() .Select(m => m.GetSpeedModifier()); - return Util.ApplyPercentageModifiers(info.Speed, modifiers); + return Util.ApplyPercentageModifiers(Info.Speed, modifiers); } } @@ -325,18 +316,151 @@ namespace OpenRA.Mods.Common.Traits return false; var type = self.World.Map.GetTerrainInfo(cell).Type; - return info.LandableTerrainTypes.Contains(type); + return Info.LandableTerrainTypes.Contains(type); } public virtual 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); } + #region Implement IPositionable + + public bool IsLeavingCell(CPos location, SubCell subCell = SubCell.Any) { return false; } // TODO: Handle landing + public bool CanEnterCell(CPos cell, Actor ignoreActor = null, bool checkTransientActors = true) { return true; } + public SubCell GetValidSubCell(SubCell preferred) { return SubCell.Invalid; } + public SubCell GetAvailableSubCell(CPos a, SubCell preferredSubCell = SubCell.Any, Actor ignoreActor = null, bool checkTransientActors = true) + { + // Does not use any subcell + return SubCell.Invalid; + } + + public void SetVisualPosition(Actor self, WPos pos) { SetPosition(self, pos); } + + // Changes position, but not altitude + public void SetPosition(Actor self, CPos cell, SubCell subCell = SubCell.Any) + { + SetPosition(self, self.World.Map.CenterOfCell(cell) + new WVec(0, 0, CenterPosition.Z)); + } + + public void SetPosition(Actor self, WPos pos) + { + CenterPosition = pos; + + if (!self.IsInWorld) + return; + + self.World.ScreenMap.Update(self); + self.World.ActorMap.UpdatePosition(self, this); + IsAirborne = self.World.Map.DistanceAboveTerrain(CenterPosition).Length >= Info.MinAirborneAltitude; + } + + #endregion + + #region Implement IMove + + public Activity MoveTo(CPos cell, int nearEnough) + { + if (IsPlane) + return new FlyAndContinueWithCirclesWhenIdle(self, Target.FromCell(self.World, cell)); + + return new HeliFly(self, Target.FromCell(self.World, cell)); + } + + public Activity MoveTo(CPos cell, Actor ignoredActor) + { + if (IsPlane) + return new FlyAndContinueWithCirclesWhenIdle(self, Target.FromCell(self.World, cell)); + + return new HeliFly(self, Target.FromCell(self.World, cell)); + } + + public Activity MoveWithinRange(Target target, WDist range) + { + if (IsPlane) + return new FlyAndContinueWithCirclesWhenIdle(self, target, WDist.Zero, range); + + return new HeliFly(self, target, WDist.Zero, range); + } + + public Activity MoveWithinRange(Target target, WDist minRange, WDist maxRange) + { + if (IsPlane) + return new FlyAndContinueWithCirclesWhenIdle(self, target, minRange, maxRange); + + return new HeliFly(self, target, minRange, maxRange); + } + + public Activity MoveFollow(Actor self, Target target, WDist minRange, WDist maxRange) + { + if (IsPlane) + return new FlyFollow(self, target, minRange, maxRange); + + return new Follow(self, target, minRange, maxRange); + } + + public Activity MoveIntoWorld(Actor self, CPos cell, SubCell subCell = SubCell.Any) + { + if (IsPlane) + return new Fly(self, Target.FromCell(self.World, cell)); + + return new HeliFly(self, Target.FromCell(self.World, cell, subCell)); + } + + public Activity MoveToTarget(Actor self, Target target) + { + if (IsPlane) + return new Fly(self, target, WDist.FromCells(3), WDist.FromCells(5)); + + return Util.SequenceActivities(new HeliFly(self, target), new Turn(self, Info.InitialFacing)); + } + + public Activity MoveIntoTarget(Actor self, Target target) + { + if (IsPlane) + return new Land(self, target); + + return new HeliLand(self, false); + } + + public Activity VisualMove(Actor self, WPos fromPos, WPos toPos) + { + // TODO: Ignore repulsion when moving + if (IsPlane) + return Util.SequenceActivities( + new CallFunc(() => SetVisualPosition(self, fromPos)), + new Fly(self, Target.FromPos(toPos))); + + return Util.SequenceActivities(new CallFunc(() => SetVisualPosition(self, fromPos)), + new HeliFly(self, Target.FromPos(toPos))); + } + + public CPos NearestMoveableCell(CPos cell) { return cell; } + + public bool IsMoving { get { return self.CenterPosition.Z > 0; } set { } } + + public bool CanEnterTargetNow(Actor self, Target target) + { + if (target.Positions.Any(p => self.World.ActorMap.GetUnitsAt(self.World.Map.CellContaining(p)).Any(a => a != self && a != target.Actor))) + return false; + + var res = target.Actor.TraitOrDefault(); + if (res == null) + return true; + + UnReserve(); + Reservation = res.Reserve(target.Actor, self, this); + return true; + } + + #endregion + + #region Implement order interfaces + public IEnumerable Orders { get @@ -344,7 +468,7 @@ namespace OpenRA.Mods.Common.Traits yield return new EnterAlliedActorTargeter("Enter", 5, target => AircraftCanEnter(target), target => !Reservable.IsReserved(target)); - yield return new AircraftMoveOrderTargeter(info); + yield return new AircraftMoveOrderTargeter(Info); } } @@ -367,9 +491,119 @@ namespace OpenRA.Mods.Common.Traits case "Enter": case "ReturnToBase": case "Stop": - return info.Voice; + return Info.Voice; default: return null; } } + + public void ResolveOrder(Actor self, Order order) + { + if (order.OrderString == "Move") + { + var cell = self.World.Map.Clamp(order.TargetLocation); + + if (!Info.MoveIntoShroud && !self.Owner.Shroud.IsExplored(cell)) + return; + + if (!order.Queued) + UnReserve(); + + var target = Target.FromCell(self.World, cell); + + self.SetTargetLine(target, Color.Green); + + if (IsPlane) + self.QueueActivity(order.Queued, new FlyAndContinueWithCirclesWhenIdle(self, target)); + else + self.QueueActivity(order.Queued, new HeliFlyAndLandWhenIdle(self, target, Info)); + } + else if (order.OrderString == "Enter") + { + if (!order.Queued) + UnReserve(); + + if (Reservable.IsReserved(order.TargetActor)) + { + if (IsPlane) + self.QueueActivity(new ReturnToBase(self)); + else + self.QueueActivity(new HeliReturn(self)); + } + else + { + self.SetTargetLine(Target.FromActor(order.TargetActor), Color.Green); + + if (IsPlane) + { + self.QueueActivity(order.Queued, Util.SequenceActivities( + new ReturnToBase(self, order.TargetActor), + new ResupplyAircraft(self))); + } + else + { + var res = order.TargetActor.TraitOrDefault(); + if (res != null) + Reservation = res.Reserve(order.TargetActor, self, this); + + Action enter = () => + { + var exit = order.TargetActor.Info.TraitInfos().FirstOrDefault(); + var offset = (exit != null) ? exit.SpawnOffset : WVec.Zero; + + self.QueueActivity(new HeliFly(self, Target.FromPos(order.TargetActor.CenterPosition + offset))); + self.QueueActivity(new Turn(self, Info.InitialFacing)); + self.QueueActivity(new HeliLand(self, false)); + self.QueueActivity(new ResupplyAircraft(self)); + self.QueueActivity(new TakeOff(self)); + }; + + self.QueueActivity(order.Queued, new CallFunc(enter)); + } + } + } + else if (order.OrderString == "Stop") + { + UnReserve(); + self.CancelActivity(); + + // TODO: Implement INotifyBecomingIdle instead + if (!IsPlane && Info.LandWhenIdle) + { + if (Info.TurnToLand) + self.QueueActivity(new Turn(self, Info.InitialFacing)); + + self.QueueActivity(new HeliLand(self, true)); + } + } + else if (order.OrderString == "ReturnToBase") + { + UnReserve(); + self.CancelActivity(); + if (IsPlane) + self.QueueActivity(new ReturnToBase(self)); + else + self.QueueActivity(new HeliReturn(self)); + + self.QueueActivity(new ResupplyAircraft(self)); + } + else + UnReserve(); + } + + #endregion + + public void RemovedFromWorld(Actor self) + { + UnReserve(); + self.World.ActorMap.RemoveInfluence(self, this); + self.World.ActorMap.RemovePosition(self, this); + self.World.ScreenMap.Remove(self); + IsAirborne = false; + } + + public void Disposing(Actor self) + { + UnReserve(); + } } } diff --git a/OpenRA.Mods.Common/Traits/Air/Helicopter.cs b/OpenRA.Mods.Common/Traits/Air/Helicopter.cs deleted file mode 100644 index 5402445ade..0000000000 --- a/OpenRA.Mods.Common/Traits/Air/Helicopter.cs +++ /dev/null @@ -1,153 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2015 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.Drawing; -using System.Linq; -using OpenRA.Activities; -using OpenRA.Mods.Common.Activities; -using OpenRA.Traits; - -namespace OpenRA.Mods.Common.Traits -{ - public class HelicopterInfo : AircraftInfo, IMoveInfo - { - [Desc("Allow the helicopter land after it has no more commands.")] - public readonly bool LandWhenIdle = true; - - [Desc("Allow the helicopter turn before landing.")] - public readonly bool TurnToLand = false; - public readonly WDist LandAltitude = WDist.Zero; - - [Desc("How fast the helicopter ascends or descends.")] - public readonly WDist AltitudeVelocity = new WDist(43); - - public readonly string TakeoffSound = null; - public readonly string LandingSound = null; - - public override object Create(ActorInitializer init) { return new Helicopter(init, this); } - } - - public class Helicopter : Aircraft, ITick, IResolveOrder, IMove - { - public readonly HelicopterInfo Info; - Actor self; - public bool IsMoving { get { return self.CenterPosition.Z > 0; } set { } } - - public Helicopter(ActorInitializer init, HelicopterInfo info) - : base(init, info) - { - self = init.Self; - Info = info; - } - - public void ResolveOrder(Actor self, Order order) - { - if (order.OrderString == "Move") - { - var cell = self.World.Map.Clamp(order.TargetLocation); - var explored = self.Owner.Shroud.IsExplored(cell); - - if (!explored && !Info.MoveIntoShroud) - return; - - var target = Target.FromCell(self.World, cell); - self.SetTargetLine(target, Color.Green); - - if (!order.Queued) - UnReserve(); - - self.QueueActivity(order.Queued, new HeliFlyAndLandWhenIdle(self, target, Info)); - } - else if (order.OrderString == "Enter") - { - Action enter = () => - { - if (Reservable.IsReserved(order.TargetActor)) - self.QueueActivity(order.Queued, new HeliReturn(self)); - else - { - var res = order.TargetActor.TraitOrDefault(); - if (res != null) - Reservation = res.Reserve(order.TargetActor, self, this); - - var exit = order.TargetActor.Info.TraitInfos().FirstOrDefault(); - var offset = (exit != null) ? exit.SpawnOffset : WVec.Zero; - - self.SetTargetLine(Target.FromActor(order.TargetActor), Color.Green); - - self.QueueActivity(new HeliFly(self, Target.FromPos(order.TargetActor.CenterPosition + offset))); - self.QueueActivity(new Turn(self, Info.InitialFacing)); - self.QueueActivity(new HeliLand(self, false)); - self.QueueActivity(new ResupplyAircraft(self)); - self.QueueActivity(new TakeOff(self)); - } - }; - - self.QueueActivity(order.Queued, new CallFunc(enter)); - - if (!order.Queued) - UnReserve(); - } - else - UnReserve(); - - if (order.OrderString == "ReturnToBase") - { - self.CancelActivity(); - self.QueueActivity(new HeliReturn(self)); - } - - if (order.OrderString == "Stop") - { - self.CancelActivity(); - - if (Info.LandWhenIdle) - { - if (Info.TurnToLand) - self.QueueActivity(new Turn(self, Info.InitialFacing)); - - self.QueueActivity(new HeliLand(self, true)); - } - } - } - - public Activity MoveTo(CPos cell, int nearEnough) { return new HeliFly(self, Target.FromCell(self.World, cell)); } - public Activity MoveTo(CPos cell, Actor ignoredActor) { return new HeliFly(self, Target.FromCell(self.World, cell)); } - public Activity MoveWithinRange(Target target, WDist range) { return new HeliFly(self, target, WDist.Zero, range); } - public Activity MoveWithinRange(Target target, WDist minRange, WDist maxRange) { return new HeliFly(self, target, minRange, maxRange); } - public Activity MoveFollow(Actor self, Target target, WDist minRange, WDist maxRange) { return new Follow(self, target, minRange, maxRange); } - public CPos NearestMoveableCell(CPos cell) { return cell; } - - public Activity MoveIntoWorld(Actor self, CPos cell, SubCell subCell = SubCell.Any) - { - return new HeliFly(self, Target.FromCell(self.World, cell, subCell)); - } - - public Activity MoveIntoTarget(Actor self, Target target) { return new HeliLand(self, false); } - public Activity MoveToTarget(Actor self, Target target) - { - return Util.SequenceActivities(new HeliFly(self, target), new Turn(self, Info.InitialFacing)); - } - - public Activity VisualMove(Actor self, WPos fromPos, WPos toPos) - { - // TODO: Ignore repulsion when moving - return Util.SequenceActivities(new CallFunc(() => SetVisualPosition(self, fromPos)), new HeliFly(self, Target.FromPos(toPos))); - } - - public override IEnumerable GetResupplyActivities(Actor a) - { - foreach (var b in base.GetResupplyActivities(a)) - yield return b; - } - } -} diff --git a/OpenRA.Mods.Common/Traits/Air/Plane.cs b/OpenRA.Mods.Common/Traits/Air/Plane.cs deleted file mode 100644 index 2b6a712cd9..0000000000 --- a/OpenRA.Mods.Common/Traits/Air/Plane.cs +++ /dev/null @@ -1,129 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2015 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.Drawing; -using OpenRA.Activities; -using OpenRA.Mods.Common.Activities; -using OpenRA.Traits; - -namespace OpenRA.Mods.Common.Traits -{ - public class PlaneInfo : AircraftInfo, IMoveInfo - { - public readonly WAngle MaximumPitch = WAngle.FromDegrees(10); - - public override object Create(ActorInitializer init) { return new Plane(init, this); } - } - - public class Plane : Aircraft, IResolveOrder, IMove, ITick, ISync - { - public readonly PlaneInfo Info; - [Sync] public WPos RTBPathHash; - Actor self; - public bool IsMoving { get { return self.CenterPosition.Z > 0; } set { } } - - public Plane(ActorInitializer init, PlaneInfo info) - : base(init, info) - { - self = init.Self; - Info = info; - } - - public override WVec GetRepulsionForce() - { - var repulsionForce = base.GetRepulsionForce(); - if (repulsionForce == WVec.Zero) - return WVec.Zero; - - var currentDir = FlyStep(Facing); - var length = currentDir.HorizontalLength * repulsionForce.HorizontalLength; - if (length == 0) - return WVec.Zero; - - var dot = WVec.Dot(currentDir, repulsionForce) / length; - - // avoid stalling the plane - return dot >= 0 ? repulsionForce : WVec.Zero; - } - - public void ResolveOrder(Actor self, Order order) - { - if (order.OrderString == "Move") - { - var cell = self.World.Map.Clamp(order.TargetLocation); - var explored = self.Owner.Shroud.IsExplored(cell); - - if (!explored && !Info.MoveIntoShroud) - return; - - if (!order.Queued) - UnReserve(); - - var target = Target.FromCell(self.World, cell); - self.SetTargetLine(target, Color.Green); - self.QueueActivity(order.Queued, new FlyAndContinueWithCirclesWhenIdle(self, target)); - } - else if (order.OrderString == "Enter") - { - if (Reservable.IsReserved(order.TargetActor)) - return; - - if (!order.Queued) - UnReserve(); - - self.SetTargetLine(Target.FromOrder(self.World, order), Color.Green); - self.QueueActivity(order.Queued, Util.SequenceActivities(new ReturnToBase(self, order.TargetActor), new ResupplyAircraft(self))); - } - else if (order.OrderString == "Stop") - { - UnReserve(); - self.CancelActivity(); - } - else if (order.OrderString == "ReturnToBase") - { - var airfield = ReturnToBase.ChooseAirfield(self, true); - if (airfield == null) - return; - - UnReserve(); - self.CancelActivity(); - self.SetTargetLine(Target.FromActor(airfield), Color.Green); - self.QueueActivity(new ReturnToBase(self, airfield)); - self.QueueActivity(new ResupplyAircraft(self)); - } - else - { - // Game.Debug("Unreserve due to unhandled order: {0}".F(order.OrderString)); - UnReserve(); - } - } - - public Activity MoveTo(CPos cell, int nearEnough) { return Util.SequenceActivities(new Fly(self, Target.FromCell(self.World, cell)), new FlyCircle(self)); } - public Activity MoveTo(CPos cell, Actor ignoredActor) { return Util.SequenceActivities(new Fly(self, Target.FromCell(self.World, cell)), new FlyCircle(self)); } - public Activity MoveWithinRange(Target target, WDist range) { return Util.SequenceActivities(new Fly(self, target, WDist.Zero, range), new FlyCircle(self)); } - public Activity MoveWithinRange(Target target, WDist minRange, WDist maxRange) - { - return Util.SequenceActivities(new Fly(self, target, minRange, maxRange), new FlyCircle(self)); - } - - public Activity MoveFollow(Actor self, Target target, WDist minRange, WDist maxRange) { return new FlyFollow(self, target, minRange, maxRange); } - public CPos NearestMoveableCell(CPos cell) { return cell; } - - public Activity MoveIntoWorld(Actor self, CPos cell, SubCell subCell = SubCell.Any) { return new Fly(self, Target.FromCell(self.World, cell)); } - public Activity VisualMove(Actor self, WPos fromPos, WPos toPos) - { - return Util.SequenceActivities(new CallFunc(() => SetVisualPosition(self, fromPos)), new Fly(self, Target.FromPos(toPos))); - } - - public Activity MoveToTarget(Actor self, Target target) { return new Fly(self, target, WDist.FromCells(3), WDist.FromCells(5)); } - public Activity MoveIntoTarget(Actor self, Target target) { return new Land(self, target); } - } -} diff --git a/OpenRA.Mods.Common/Traits/Cargo.cs b/OpenRA.Mods.Common/Traits/Cargo.cs index 437a844fd2..07bb3b5cef 100644 --- a/OpenRA.Mods.Common/Traits/Cargo.cs +++ b/OpenRA.Mods.Common/Traits/Cargo.cs @@ -66,7 +66,7 @@ namespace OpenRA.Mods.Common.Traits int totalWeight = 0; int reservedWeight = 0; - Helicopter helicopter; + Aircraft aircraft; CPos currentCell; public IEnumerable CurrentAdjacentCells { get; private set; } @@ -116,7 +116,7 @@ namespace OpenRA.Mods.Common.Traits public void Created(Actor self) { - helicopter = self.TraitOrDefault(); + aircraft = self.TraitOrDefault(); } static int GetWeight(Actor a) { return a.Info.TraitInfo().Weight; } @@ -144,7 +144,7 @@ namespace OpenRA.Mods.Common.Traits Unloading = true; self.CancelActivity(); - if (helicopter != null) + if (aircraft != null) self.QueueActivity(new HeliLand(self, true)); self.QueueActivity(new UnloadCargo(self, true)); } @@ -165,7 +165,7 @@ namespace OpenRA.Mods.Common.Traits return false; } - return !IsEmpty(self) && (helicopter == null || helicopter.CanLand(self.Location)) + return !IsEmpty(self) && (aircraft == null || aircraft.CanLand(self.Location)) && CurrentAdjacentCells != null && CurrentAdjacentCells.Any(c => Passengers.Any(p => p.Trait().CanEnterCell(c))); } diff --git a/OpenRA.Mods.Common/Traits/SupportPowers/AirstrikePower.cs b/OpenRA.Mods.Common/Traits/SupportPowers/AirstrikePower.cs index de7575b4d1..460628c582 100644 --- a/OpenRA.Mods.Common/Traits/SupportPowers/AirstrikePower.cs +++ b/OpenRA.Mods.Common/Traits/SupportPowers/AirstrikePower.cs @@ -61,7 +61,7 @@ namespace OpenRA.Mods.Common.Traits if (randomize) attackFacing = Util.QuantizeFacing(self.World.SharedRandom.Next(256), info.QuantizedFacings) * (256 / info.QuantizedFacings); - var altitude = self.World.Map.Rules.Actors[info.UnitType].TraitInfo().CruiseAltitude.Length; + var altitude = self.World.Map.Rules.Actors[info.UnitType].TraitInfo().CruiseAltitude.Length; var attackRotation = WRot.FromFacing(attackFacing); var delta = new WVec(0, -1024, 0).Rotate(attackRotation); target = target + new WVec(0, 0, altitude); diff --git a/OpenRA.Mods.Common/Traits/Transforms.cs b/OpenRA.Mods.Common/Traits/Transforms.cs index 10f934fd95..3c480ec50e 100644 --- a/OpenRA.Mods.Common/Traits/Transforms.cs +++ b/OpenRA.Mods.Common/Traits/Transforms.cs @@ -112,7 +112,7 @@ namespace OpenRA.Mods.Common.Traits if (self.Info.HasTraitInfo()) self.QueueActivity(new Turn(self, info.Facing)); - if (self.Info.HasTraitInfo()) + if (self.Info.HasTraitInfo()) self.QueueActivity(new HeliLand(self, true)); foreach (var nt in self.TraitsImplementing()) diff --git a/OpenRA.Mods.Common/Traits/World/CrateSpawner.cs b/OpenRA.Mods.Common/Traits/World/CrateSpawner.cs index 9ead8be8f8..5335b13ad4 100644 --- a/OpenRA.Mods.Common/Traits/World/CrateSpawner.cs +++ b/OpenRA.Mods.Common/Traits/World/CrateSpawner.cs @@ -111,7 +111,7 @@ namespace OpenRA.Mods.Common.Traits var dropFacing = Util.QuantizeFacing(self.World.SharedRandom.Next(256), info.QuantizedFacings) * (256 / info.QuantizedFacings); var delta = new WVec(0, -1024, 0).Rotate(WRot.FromFacing(dropFacing)); - var altitude = self.World.Map.Rules.Actors[info.DeliveryAircraft].TraitInfo().CruiseAltitude.Length; + var altitude = self.World.Map.Rules.Actors[info.DeliveryAircraft].TraitInfo().CruiseAltitude.Length; var target = self.World.Map.CenterOfCell(p) + new WVec(0, 0, altitude); var startEdge = target - (self.World.Map.DistanceToEdge(target, -delta) + info.Cordon).Length * delta / 1024; var finishEdge = target + (self.World.Map.DistanceToEdge(target, delta) + info.Cordon).Length * delta / 1024; diff --git a/OpenRA.Mods.D2k/Activities/DeliverUnit.cs b/OpenRA.Mods.D2k/Activities/DeliverUnit.cs index b707a59dda..75f058452c 100644 --- a/OpenRA.Mods.D2k/Activities/DeliverUnit.cs +++ b/OpenRA.Mods.D2k/Activities/DeliverUnit.cs @@ -23,7 +23,7 @@ namespace OpenRA.Mods.D2k.Activities readonly IMove movement; readonly Carryable carryable; readonly Carryall carryall; - readonly Helicopter helicopter; + readonly Aircraft aircraft; readonly IPositionable positionable; readonly IFacing cargoFacing; readonly IFacing selfFacing; @@ -39,7 +39,7 @@ namespace OpenRA.Mods.D2k.Activities cargo = carryall.Carrying; movement = self.Trait(); carryable = cargo.Trait(); - helicopter = self.Trait(); + aircraft = self.Trait(); positionable = cargo.Trait(); cargoFacing = cargo.Trait(); selfFacing = self.Trait(); @@ -95,7 +95,7 @@ namespace OpenRA.Mods.D2k.Activities return this; } - if (HeliFly.AdjustAltitude(self, helicopter, helicopter.Info.LandAltitude)) + if (HeliFly.AdjustAltitude(self, aircraft, aircraft.Info.LandAltitude)) return this; state = State.Release; return Util.SequenceActivities(new Wait(15), this); diff --git a/OpenRA.Mods.D2k/Activities/PickupUnit.cs b/OpenRA.Mods.D2k/Activities/PickupUnit.cs index 65ad493b9d..52131bcb77 100644 --- a/OpenRA.Mods.D2k/Activities/PickupUnit.cs +++ b/OpenRA.Mods.D2k/Activities/PickupUnit.cs @@ -22,7 +22,7 @@ namespace OpenRA.Mods.D2k.Activities readonly IMove movement; readonly Carryable carryable; readonly Carryall carryall; - readonly Helicopter helicopter; + readonly Aircraft aircraft; readonly IFacing cargoFacing; readonly IFacing selfFacing; @@ -37,7 +37,7 @@ namespace OpenRA.Mods.D2k.Activities cargoFacing = cargo.Trait(); movement = self.Trait(); carryall = self.Trait(); - helicopter = self.Trait(); + aircraft = self.Trait(); selfFacing = self.Trait(); state = State.Intercept; } @@ -90,7 +90,7 @@ namespace OpenRA.Mods.D2k.Activities state = State.TakeOff; return this; case State.TakeOff: - if (HeliFly.AdjustAltitude(self, helicopter, helicopter.Info.CruiseAltitude)) + if (HeliFly.AdjustAltitude(self, aircraft, aircraft.Info.CruiseAltitude)) return this; return NextActivity; } diff --git a/OpenRA.Mods.D2k/Traits/Carryall.cs b/OpenRA.Mods.D2k/Traits/Carryall.cs index adc02c0113..382576de31 100644 --- a/OpenRA.Mods.D2k/Traits/Carryall.cs +++ b/OpenRA.Mods.D2k/Traits/Carryall.cs @@ -50,7 +50,8 @@ namespace OpenRA.Mods.D2k.Traits IsBusy = false; IsCarrying = false; - var helicopter = self.Info.TraitInfoOrDefault(); + + var helicopter = self.Info.TraitInfoOrDefault(); carryHeight = helicopter != null ? helicopter.LandAltitude : WDist.Zero; } diff --git a/OpenRA.Mods.RA/Traits/SupportPowers/ParatroopersPower.cs b/OpenRA.Mods.RA/Traits/SupportPowers/ParatroopersPower.cs index dc6e2b06e8..b4e1933790 100644 --- a/OpenRA.Mods.RA/Traits/SupportPowers/ParatroopersPower.cs +++ b/OpenRA.Mods.RA/Traits/SupportPowers/ParatroopersPower.cs @@ -72,7 +72,7 @@ namespace OpenRA.Mods.RA.Traits if (randomize) dropFacing = Util.QuantizeFacing(self.World.SharedRandom.Next(256), info.QuantizedFacings) * (256 / info.QuantizedFacings); - var altitude = self.World.Map.Rules.Actors[info.UnitType].TraitInfo().CruiseAltitude.Length; + var altitude = self.World.Map.Rules.Actors[info.UnitType].TraitInfo().CruiseAltitude.Length; var dropRotation = WRot.FromFacing(dropFacing); var delta = new WVec(0, -1024, 0).Rotate(dropRotation); target = target + new WVec(0, 0, altitude);