Merge pull request #9054 from penev92/bleed_aircraft
Merge Plane and Helicopter traits
This commit is contained in:
@@ -55,7 +55,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
if (!self.IsInWorld || self.IsDead)
|
||||
return;
|
||||
|
||||
var altitude = self.World.Map.Rules.Actors[actorType].TraitInfo<PlaneInfo>().CruiseAltitude;
|
||||
var altitude = self.World.Map.Rules.Actors[actorType].TraitInfo<AircraftInfo>().CruiseAltitude;
|
||||
var actor = w.CreateActor(actorType, new TypeDictionary
|
||||
{
|
||||
new CenterPositionInit(w.Map.CenterOfCell(startPos) + new WVec(WDist.Zero, WDist.Zero, altitude)),
|
||||
|
||||
@@ -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>();
|
||||
plane = self.Trait<Aircraft>();
|
||||
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);
|
||||
|
||||
|
||||
@@ -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>();
|
||||
plane = self.Trait<Aircraft>();
|
||||
cruiseAltitude = plane.Info.CruiseAltitude;
|
||||
}
|
||||
|
||||
|
||||
@@ -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>();
|
||||
plane = self.Trait<Aircraft>();
|
||||
this.minRange = minRange;
|
||||
this.maxRange = maxRange;
|
||||
}
|
||||
|
||||
@@ -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>();
|
||||
plane = self.Trait<Aircraft>();
|
||||
}
|
||||
|
||||
public override Activity Tick(Actor self)
|
||||
|
||||
@@ -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>();
|
||||
plane = self.Trait<Aircraft>();
|
||||
cruiseAltitude = plane.Info.CruiseAltitude;
|
||||
}
|
||||
|
||||
|
||||
@@ -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>();
|
||||
helicopter = self.Trait<Aircraft>();
|
||||
attackHeli = self.Trait<AttackHeli>();
|
||||
ammoPools = self.TraitsImplementing<AmmoPool>().ToArray();
|
||||
this.attackOnlyVisibleTargets = attackOnlyVisibleTargets;
|
||||
@@ -68,7 +67,7 @@ namespace OpenRA.Mods.Common.Activities
|
||||
// If all ammo pools are depleted and none reload automatically, return to helipad to reload and then move to next activity
|
||||
// TODO: This should check whether there is ammo left that is actually suitable for the target
|
||||
if (ammoPools.All(x => !x.Info.SelfReloads && !x.HasAmmo()))
|
||||
return Util.SequenceActivities(new HeliReturn(self), NextActivity);
|
||||
return Util.SequenceActivities(new HeliReturnToBase(self), NextActivity);
|
||||
|
||||
var dist = target.CenterPosition - self.CenterPosition;
|
||||
|
||||
|
||||
@@ -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>();
|
||||
helicopter = self.Trait<Aircraft>();
|
||||
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;
|
||||
|
||||
@@ -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>();
|
||||
helicopter = self.Trait<Aircraft>();
|
||||
}
|
||||
|
||||
public override Activity Tick(Actor self)
|
||||
|
||||
@@ -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>();
|
||||
helicopter = self.Trait<Aircraft>();
|
||||
}
|
||||
|
||||
public override Activity Tick(Actor self)
|
||||
|
||||
@@ -15,13 +15,13 @@ using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Activities
|
||||
{
|
||||
public class HeliReturn : Activity
|
||||
public class HeliReturnToBase : Activity
|
||||
{
|
||||
readonly Helicopter heli;
|
||||
readonly Aircraft heli;
|
||||
|
||||
public HeliReturn(Actor self)
|
||||
public HeliReturnToBase(Actor self)
|
||||
{
|
||||
heli = self.Trait<Helicopter>();
|
||||
heli = self.Trait<Aircraft>();
|
||||
}
|
||||
|
||||
public Actor ChooseHelipad(Actor self)
|
||||
@@ -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>();
|
||||
plane = self.Trait<Aircraft>();
|
||||
}
|
||||
|
||||
public override Activity Tick(Actor self)
|
||||
|
||||
@@ -18,22 +18,22 @@ 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;
|
||||
|
||||
public ReturnToBase(Actor self, Actor dest)
|
||||
public ReturnToBase(Actor self, Actor dest = null)
|
||||
{
|
||||
this.dest = dest;
|
||||
plane = self.Trait<Plane>();
|
||||
planeInfo = self.Info.TraitInfo<PlaneInfo>();
|
||||
plane = self.Trait<Aircraft>();
|
||||
planeInfo = self.Info.TraitInfo<AircraftInfo>();
|
||||
}
|
||||
|
||||
public static Actor ChooseAirfield(Actor self, bool unreservedOnly)
|
||||
{
|
||||
var rearmBuildings = self.Info.TraitInfo<PlaneInfo>().RearmBuildings;
|
||||
var rearmBuildings = self.Info.TraitInfo<AircraftInfo>().RearmBuildings;
|
||||
return self.World.ActorsWithTrait<Reservable>()
|
||||
.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;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
<Compile Include="Activities\Air\HeliFly.cs" />
|
||||
<Compile Include="Activities\Air\HeliFlyCircle.cs" />
|
||||
<Compile Include="Activities\Air\HeliLand.cs" />
|
||||
<Compile Include="Activities\Air\HeliReturn.cs" />
|
||||
<Compile Include="Activities\Air\HeliReturnToBase.cs" />
|
||||
<Compile Include="Activities\Air\Land.cs" />
|
||||
<Compile Include="Activities\Air\ResupplyAircraft.cs" />
|
||||
<Compile Include="Activities\Air\ReturnToBase.cs" />
|
||||
@@ -202,9 +202,11 @@
|
||||
<Compile Include="Orders\RepairOrderGenerator.cs" />
|
||||
<Compile Include="Orders\GlobalButtonOrderGenerator.cs" />
|
||||
<Compile Include="Orders\PlaceBuildingOrderGenerator.cs" />
|
||||
<Compile Include="Orders\AircraftMoveOrderTargeter.cs" />
|
||||
<Compile Include="Orders\UnitOrderTargeter.cs" />
|
||||
<Compile Include="Pathfinder\CellInfo.cs" />
|
||||
<Compile Include="PlayerExtensions.cs" />
|
||||
<Compile Include="Scripting\Properties\AircraftProperties.cs" />
|
||||
<Compile Include="Scripting\ScriptUpgradesCache.cs" />
|
||||
<Compile Include="Scripting\Properties\CaptureProperties.cs" />
|
||||
<Compile Include="ServerTraits\ColorValidator.cs" />
|
||||
@@ -235,13 +237,11 @@
|
||||
<Compile Include="Scripting\Properties\DiplomacyProperties.cs" />
|
||||
<Compile Include="Scripting\Properties\HarvesterProperties.cs" />
|
||||
<Compile Include="Scripting\Properties\HealthProperties.cs" />
|
||||
<Compile Include="Scripting\Properties\HelicopterProperties.cs" />
|
||||
<Compile Include="Scripting\Properties\GeneralProperties.cs" />
|
||||
<Compile Include="Scripting\Properties\GuardProperties.cs" />
|
||||
<Compile Include="Scripting\Properties\MissionObjectiveProperties.cs" />
|
||||
<Compile Include="Scripting\Properties\MobileProperties.cs" />
|
||||
<Compile Include="Scripting\Properties\DemolitionProperties.cs" />
|
||||
<Compile Include="Scripting\Properties\PlaneProperties.cs" />
|
||||
<Compile Include="Scripting\Properties\PlayerProperties.cs" />
|
||||
<Compile Include="Scripting\Properties\PowerProperties.cs" />
|
||||
<Compile Include="Scripting\Properties\ProductionProperties.cs" />
|
||||
@@ -258,8 +258,6 @@
|
||||
<Compile Include="Traits\Air\AttackPlane.cs" />
|
||||
<Compile Include="Traits\Air\FlyAwayOnIdle.cs" />
|
||||
<Compile Include="Traits\Air\FallsToEarth.cs" />
|
||||
<Compile Include="Traits\Air\Helicopter.cs" />
|
||||
<Compile Include="Traits\Air\Plane.cs" />
|
||||
<Compile Include="Traits\Air\ReturnOnIdle.cs" />
|
||||
<Compile Include="Traits\AppearsOnRadar.cs" />
|
||||
<Compile Include="Traits\Armament.cs" />
|
||||
|
||||
48
OpenRA.Mods.Common/Orders/AircraftMoveOrderTargeter.cs
Normal file
48
OpenRA.Mods.Common/Orders/AircraftMoveOrderTargeter.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
#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.Collections.Generic;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Orders
|
||||
{
|
||||
class AircraftMoveOrderTargeter : IOrderTargeter
|
||||
{
|
||||
public string OrderID { get { return "Move"; } }
|
||||
public int OrderPriority { get { return 4; } }
|
||||
public bool OverrideSelection { get { return false; } }
|
||||
|
||||
readonly AircraftInfo info;
|
||||
|
||||
public AircraftMoveOrderTargeter(AircraftInfo info) { this.info = info; }
|
||||
|
||||
public bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, TargetModifiers modifiers, ref string cursor)
|
||||
{
|
||||
if (target.Type != TargetType.Terrain)
|
||||
return false;
|
||||
|
||||
var location = self.World.Map.CellContaining(target.CenterPosition);
|
||||
var explored = self.Owner.Shroud.IsExplored(location);
|
||||
cursor = self.World.Map.Contains(location) ?
|
||||
(self.World.Map.GetTerrainInfo(location).CustomCursor ?? "move") :
|
||||
"move-blocked";
|
||||
|
||||
IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue);
|
||||
|
||||
if (!explored && !info.MoveIntoShroud)
|
||||
cursor = "move-blocked";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsQueued { get; protected set; }
|
||||
}
|
||||
}
|
||||
@@ -137,11 +137,19 @@ namespace OpenRA.Mods.Common.Scripting
|
||||
}
|
||||
else
|
||||
{
|
||||
var heli = transport.Info.TraitInfoOrDefault<HelicopterInfo>();
|
||||
if (heli != null)
|
||||
var aircraftInfo = transport.TraitOrDefault<Aircraft>();
|
||||
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)
|
||||
|
||||
@@ -16,23 +16,34 @@ using OpenRA.Traits;
|
||||
namespace OpenRA.Mods.Common.Scripting
|
||||
{
|
||||
[ScriptPropertyGroup("Movement")]
|
||||
public class PlaneProperties : ScriptActorProperties, Requires<PlaneInfo>
|
||||
public class AircraftProperties : ScriptActorProperties, Requires<AircraftInfo>
|
||||
{
|
||||
public PlaneProperties(ScriptContext context, Actor self)
|
||||
: base(context, self) { }
|
||||
readonly bool isPlane;
|
||||
|
||||
public AircraftProperties(ScriptContext context, Actor self)
|
||||
: base(context, self)
|
||||
{
|
||||
isPlane = self.Trait<Aircraft>().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 HeliReturnToBase(Self));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<HelicopterInfo>
|
||||
{
|
||||
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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<LocationInit>, UsesInit<FacingInit>
|
||||
public class AircraftInfo : IPositionableInfo, IFacingInfo, IOccupySpaceInfo, IMoveInfo, ICruiseAltitudeInfo,
|
||||
UsesInit<LocationInit>, UsesInit<FacingInit>
|
||||
{
|
||||
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<CPos, SubCell> OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any) { return new ReadOnlyDictionary<CPos, SubCell>(); }
|
||||
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<CPos, SubCell>[] 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<LocationInit>())
|
||||
SetPosition(self, init.Get<LocationInit, CPos>());
|
||||
@@ -108,10 +136,23 @@ namespace OpenRA.Mods.Common.Traits
|
||||
SetPosition(self, init.Get<CenterPositionInit, WPos>());
|
||||
|
||||
Facing = init.Contains<FacingInit>() ? init.Get<FacingInit, int>() : 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<UpgradeManager>(); }
|
||||
|
||||
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<AircraftInfo>() && a.Info.TraitInfo<AircraftInfo>().CruiseAltitude == info.CruiseAltitude)
|
||||
var repulsionForce = self.World.FindActorsInCircle(self.CenterPosition, Info.IdealSeparation)
|
||||
.Where(a => !a.IsDead && a.Info.HasTraitInfo<AircraftInfo>()
|
||||
&& a.Info.TraitInfo<AircraftInfo>().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<Reservable>();
|
||||
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<ISpeedModifier>()
|
||||
.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<Activity> 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<Reservable>();
|
||||
if (res == null)
|
||||
return true;
|
||||
|
||||
UnReserve();
|
||||
Reservation = res.Reserve(target.Actor, self, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implement order interfaces
|
||||
|
||||
public IEnumerable<IOrderTargeter> Orders
|
||||
{
|
||||
get
|
||||
@@ -344,7 +468,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
yield return new EnterAlliedActorTargeter<BuildingInfo>("Enter", 5,
|
||||
target => AircraftCanEnter(target), target => !Reservable.IsReserved(target));
|
||||
|
||||
yield return new AircraftMoveOrderTargeter(info);
|
||||
yield return new AircraftMoveOrderTargeter(Info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,41 +491,125 @@ namespace OpenRA.Mods.Common.Traits
|
||||
case "Enter":
|
||||
case "ReturnToBase":
|
||||
case "Stop":
|
||||
return info.Voice;
|
||||
return Info.Voice;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AircraftMoveOrderTargeter : IOrderTargeter
|
||||
{
|
||||
public string OrderID { get { return "Move"; } }
|
||||
public int OrderPriority { get { return 4; } }
|
||||
public bool OverrideSelection { get { return false; } }
|
||||
|
||||
readonly AircraftInfo info;
|
||||
|
||||
public AircraftMoveOrderTargeter(AircraftInfo info) { this.info = info; }
|
||||
|
||||
public bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, TargetModifiers modifiers, ref string cursor)
|
||||
public void ResolveOrder(Actor self, Order order)
|
||||
{
|
||||
if (target.Type != TargetType.Terrain)
|
||||
return false;
|
||||
if (order.OrderString == "Move")
|
||||
{
|
||||
var cell = self.World.Map.Clamp(order.TargetLocation);
|
||||
|
||||
var location = self.World.Map.CellContaining(target.CenterPosition);
|
||||
var explored = self.Owner.Shroud.IsExplored(location);
|
||||
cursor = self.World.Map.Contains(location) ?
|
||||
(self.World.Map.GetTerrainInfo(location).CustomCursor ?? "move") :
|
||||
"move-blocked";
|
||||
if (!Info.MoveIntoShroud && !self.Owner.Shroud.IsExplored(cell))
|
||||
return;
|
||||
|
||||
IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue);
|
||||
if (!order.Queued)
|
||||
UnReserve();
|
||||
|
||||
if (!explored && !info.MoveIntoShroud)
|
||||
cursor = "move-blocked";
|
||||
var target = Target.FromCell(self.World, cell);
|
||||
|
||||
return true;
|
||||
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 HeliReturnToBase(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<Reservable>();
|
||||
if (res != null)
|
||||
Reservation = res.Reserve(order.TargetActor, self, this);
|
||||
|
||||
Action enter = () =>
|
||||
{
|
||||
var exit = order.TargetActor.Info.TraitInfos<ExitInfo>().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")
|
||||
{
|
||||
self.CancelActivity();
|
||||
if (GetActorBelow() != null)
|
||||
{
|
||||
self.QueueActivity(new ResupplyAircraft(self));
|
||||
return;
|
||||
}
|
||||
|
||||
UnReserve();
|
||||
|
||||
// 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 HeliReturnToBase(self));
|
||||
|
||||
self.QueueActivity(new ResupplyAircraft(self));
|
||||
}
|
||||
else
|
||||
UnReserve();
|
||||
}
|
||||
|
||||
public bool IsQueued { get; protected set; }
|
||||
#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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Reservable>();
|
||||
if (res != null)
|
||||
Reservation = res.Reserve(order.TargetActor, self, this);
|
||||
|
||||
var exit = order.TargetActor.Info.TraitInfos<ExitInfo>().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<Activity> GetResupplyActivities(Actor a)
|
||||
{
|
||||
foreach (var b in base.GetResupplyActivities(a))
|
||||
yield return b;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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); }
|
||||
}
|
||||
}
|
||||
@@ -66,7 +66,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
int totalWeight = 0;
|
||||
int reservedWeight = 0;
|
||||
Helicopter helicopter;
|
||||
Aircraft aircraft;
|
||||
|
||||
CPos currentCell;
|
||||
public IEnumerable<CPos> CurrentAdjacentCells { get; private set; }
|
||||
@@ -116,7 +116,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public void Created(Actor self)
|
||||
{
|
||||
helicopter = self.TraitOrDefault<Helicopter>();
|
||||
aircraft = self.TraitOrDefault<Aircraft>();
|
||||
}
|
||||
|
||||
static int GetWeight(Actor a) { return a.Info.TraitInfo<PassengerInfo>().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<IPositionable>().CanEnterCell(c)));
|
||||
}
|
||||
|
||||
|
||||
@@ -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<PlaneInfo>().CruiseAltitude.Length;
|
||||
var altitude = self.World.Map.Rules.Actors[info.UnitType].TraitInfo<AircraftInfo>().CruiseAltitude.Length;
|
||||
var attackRotation = WRot.FromFacing(attackFacing);
|
||||
var delta = new WVec(0, -1024, 0).Rotate(attackRotation);
|
||||
target = target + new WVec(0, 0, altitude);
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (self.Info.HasTraitInfo<IFacingInfo>())
|
||||
self.QueueActivity(new Turn(self, info.Facing));
|
||||
|
||||
if (self.Info.HasTraitInfo<HelicopterInfo>())
|
||||
if (self.Info.HasTraitInfo<AircraftInfo>())
|
||||
self.QueueActivity(new HeliLand(self, true));
|
||||
|
||||
foreach (var nt in self.TraitsImplementing<INotifyTransform>())
|
||||
|
||||
@@ -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<PlaneInfo>().CruiseAltitude.Length;
|
||||
var altitude = self.World.Map.Rules.Actors[info.DeliveryAircraft].TraitInfo<AircraftInfo>().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;
|
||||
|
||||
@@ -1832,9 +1832,9 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
||||
if (inftraits != null)
|
||||
{
|
||||
node.Value.Nodes.Add(new MiniYamlNode("QuantizeFacingsFromSequence", null, new List<MiniYamlNode>
|
||||
{
|
||||
new MiniYamlNode("Sequence", "stand"),
|
||||
}));
|
||||
{
|
||||
new MiniYamlNode("Sequence", "stand"),
|
||||
}));
|
||||
}
|
||||
|
||||
var other = node.Value.Nodes.FirstOrDefault(x =>
|
||||
@@ -2030,7 +2030,8 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
||||
}
|
||||
else
|
||||
cloakedTargetTypes = new MiniYamlNode("TargetTypes", "");
|
||||
node.Value.Nodes.Add(new MiniYamlNode("Targetable@UNDERWATER", "", new List<MiniYamlNode> {
|
||||
node.Value.Nodes.Add(new MiniYamlNode("Targetable@UNDERWATER", "", new List<MiniYamlNode>
|
||||
{
|
||||
cloakedTargetTypes,
|
||||
new MiniYamlNode("UpgradeTypes", "underwater"),
|
||||
new MiniYamlNode("UpgradeMinEnabledLevel", "1")
|
||||
@@ -2067,7 +2068,8 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
||||
}
|
||||
else
|
||||
groundTargetTypes = new MiniYamlNode("TargetTypes", "");
|
||||
node.Value.Nodes.Add(new MiniYamlNode("Targetable@GROUND", "", new List<MiniYamlNode> {
|
||||
node.Value.Nodes.Add(new MiniYamlNode("Targetable@GROUND", "", new List<MiniYamlNode>
|
||||
{
|
||||
groundTargetTypes,
|
||||
new MiniYamlNode("UpgradeTypes", "airborne"),
|
||||
new MiniYamlNode("UpgradeMaxEnabledLevel", "0")
|
||||
@@ -2175,6 +2177,18 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
||||
}
|
||||
}
|
||||
|
||||
if (engineVersion < 20150927)
|
||||
{
|
||||
if (depth == 1 && node.Key == "Plane")
|
||||
node.Key = "Aircraft";
|
||||
|
||||
if (depth == 1 && node.Key == "Helicopter")
|
||||
{
|
||||
node.Key = "Aircraft";
|
||||
node.Value.Nodes.Add(new MiniYamlNode("CanHover", "True"));
|
||||
}
|
||||
}
|
||||
|
||||
UpgradeActorRules(engineVersion, ref node.Value.Nodes, node, depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<IMove>();
|
||||
carryable = cargo.Trait<Carryable>();
|
||||
helicopter = self.Trait<Helicopter>();
|
||||
aircraft = self.Trait<Aircraft>();
|
||||
positionable = cargo.Trait<IPositionable>();
|
||||
cargoFacing = cargo.Trait<IFacing>();
|
||||
selfFacing = self.Trait<IFacing>();
|
||||
@@ -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);
|
||||
|
||||
@@ -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<IFacing>();
|
||||
movement = self.Trait<IMove>();
|
||||
carryall = self.Trait<Carryall>();
|
||||
helicopter = self.Trait<Helicopter>();
|
||||
aircraft = self.Trait<Aircraft>();
|
||||
selfFacing = self.Trait<IFacing>();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,8 @@ namespace OpenRA.Mods.D2k.Traits
|
||||
|
||||
IsBusy = false;
|
||||
IsCarrying = false;
|
||||
var helicopter = self.Info.TraitInfoOrDefault<HelicopterInfo>();
|
||||
|
||||
var helicopter = self.Info.TraitInfoOrDefault<AircraftInfo>();
|
||||
carryHeight = helicopter != null ? helicopter.LandAltitude : WDist.Zero;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<PlaneInfo>().CruiseAltitude.Length;
|
||||
var altitude = self.World.Map.Rules.Actors[info.UnitType].TraitInfo<AircraftInfo>().CruiseAltitude.Length;
|
||||
var dropRotation = WRot.FromFacing(dropFacing);
|
||||
var delta = new WVec(0, -1024, 0).Rotate(dropRotation);
|
||||
target = target + new WVec(0, 0, altitude);
|
||||
|
||||
@@ -9,14 +9,13 @@ TRAN:
|
||||
BuildPaletteOrder: 10
|
||||
Prerequisites: hpad
|
||||
Queue: Aircraft.GDI, Aircraft.Nod
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
LandWhenIdle: true
|
||||
ROT: 5
|
||||
Speed: 140
|
||||
InitialFacing: 0
|
||||
LandableTerrainTypes: Clear,Rough,Road,Ore,Beach,Tiberium,BlueTiberium
|
||||
AltitudeVelocity: 0c100
|
||||
AirborneUpgrades: airborne
|
||||
Health:
|
||||
HP: 90
|
||||
Armor:
|
||||
@@ -53,11 +52,10 @@ HELI:
|
||||
BuildPaletteOrder: 20
|
||||
Prerequisites: hpad, anyhq, ~techlevel.medium
|
||||
Queue: Aircraft.Nod
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
RearmBuildings: hpad
|
||||
ROT: 4
|
||||
Speed: 186
|
||||
AirborneUpgrades: airborne
|
||||
Health:
|
||||
HP: 125
|
||||
Armor:
|
||||
@@ -105,11 +103,10 @@ ORCA:
|
||||
BuildPaletteOrder: 20
|
||||
Prerequisites: hpad, anyhq, ~techlevel.medium
|
||||
Queue: Aircraft.GDI
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
RearmBuildings: hpad
|
||||
ROT: 4
|
||||
Speed: 186
|
||||
AirborneUpgrades: airborne
|
||||
Health:
|
||||
HP: 90
|
||||
Armor:
|
||||
@@ -151,7 +148,7 @@ C17:
|
||||
Description: Drops vehicle reinforcements on Airstrips
|
||||
Valued:
|
||||
Cost: 2000
|
||||
Plane:
|
||||
Aircraft:
|
||||
ROT: 5
|
||||
Speed: 326
|
||||
Repulsable: False
|
||||
@@ -188,7 +185,7 @@ A10:
|
||||
Description: Used to deliver air strikes.
|
||||
Valued:
|
||||
Cost: 2000
|
||||
Plane:
|
||||
Aircraft:
|
||||
ROT: 4
|
||||
Speed: 373
|
||||
Repulsable: False
|
||||
@@ -221,10 +218,9 @@ TRAN.Husk:
|
||||
Inherits: ^HelicopterHusk
|
||||
Tooltip:
|
||||
Name: Chinook Transport
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
ROT: 5
|
||||
Speed: 140
|
||||
AirborneUpgrades: airborne
|
||||
RevealsShroud:
|
||||
Range: 8c0
|
||||
Type: CenterPosition
|
||||
@@ -239,10 +235,9 @@ HELI.Husk:
|
||||
Inherits: ^HelicopterHusk
|
||||
Tooltip:
|
||||
Name: Apache Longbow
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
ROT: 4
|
||||
Speed: 186
|
||||
AirborneUpgrades: airborne
|
||||
RevealsShroud:
|
||||
Range: 10c0
|
||||
Type: CenterPosition
|
||||
@@ -255,10 +250,9 @@ ORCA.Husk:
|
||||
Inherits: ^HelicopterHusk
|
||||
Tooltip:
|
||||
Name: Orca
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
ROT: 4
|
||||
Speed: 186
|
||||
AirborneUpgrades: airborne
|
||||
RevealsShroud:
|
||||
Range: 10c0
|
||||
Type: CenterPosition
|
||||
|
||||
@@ -131,11 +131,12 @@
|
||||
SelectionDecorations:
|
||||
Selectable:
|
||||
Bounds: 24,24
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
RepairBuildings: hpad
|
||||
RearmBuildings:
|
||||
LandWhenIdle: false
|
||||
AirborneUpgrades: airborne
|
||||
CanHover: True
|
||||
HiddenUnderFog:
|
||||
Type: CenterPosition
|
||||
ActorLostNotification:
|
||||
@@ -664,6 +665,9 @@
|
||||
^HelicopterHusk:
|
||||
Inherits: ^CommonHuskDefaults
|
||||
WithShadow:
|
||||
Aircraft:
|
||||
AirborneUpgrades: airborne
|
||||
CanHover: True
|
||||
FallsToEarth:
|
||||
Spins: True
|
||||
Moves: False
|
||||
|
||||
@@ -9,7 +9,7 @@ carryall.reinforce:
|
||||
HP: 4800
|
||||
Armor:
|
||||
Type: light
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
CruiseAltitude: 2100
|
||||
InitialFacing: 0
|
||||
ROT: 4
|
||||
@@ -21,6 +21,7 @@ carryall.reinforce:
|
||||
LandAltitude: 100
|
||||
LandWhenIdle: False
|
||||
AirborneUpgrades: airborne
|
||||
CanHover: True
|
||||
Targetable@GROUND:
|
||||
TargetTypes: Ground, Vehicle
|
||||
UpgradeTypes: airborne
|
||||
@@ -51,7 +52,7 @@ frigate:
|
||||
Tooltip:
|
||||
Name: Frigate
|
||||
Description: Supply spacecraft
|
||||
Plane:
|
||||
Aircraft:
|
||||
ROT: 1
|
||||
Speed: 126
|
||||
RepairBuildings: repair_pad
|
||||
@@ -66,7 +67,6 @@ frigate:
|
||||
|
||||
ornithopter:
|
||||
Inherits: ^Plane
|
||||
Targetable:
|
||||
TargetTypes: Air
|
||||
AttackBomber:
|
||||
Armament:
|
||||
@@ -75,12 +75,13 @@ ornithopter:
|
||||
HP: 900
|
||||
Armor:
|
||||
Type: light
|
||||
Plane:
|
||||
Aircraft:
|
||||
ROT: 2
|
||||
Speed: 189
|
||||
RepairBuildings:
|
||||
RearmBuildings:
|
||||
Repulsable: False
|
||||
CanHover: True
|
||||
AmmoPool:
|
||||
Ammo: 5
|
||||
Tooltip:
|
||||
@@ -93,7 +94,7 @@ ornithopter.husk:
|
||||
Inherits: ^AircraftHusk
|
||||
Tooltip:
|
||||
Name: Ornithopter
|
||||
Plane:
|
||||
Aircraft:
|
||||
ROT: 5
|
||||
Speed: 189
|
||||
RepairBuildings:
|
||||
@@ -105,11 +106,12 @@ carryall.husk:
|
||||
Inherits: ^AircraftHusk
|
||||
Tooltip:
|
||||
Name: Carryall
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
ROT: 4
|
||||
Speed: 112
|
||||
RepairBuildings:
|
||||
RearmBuildings:
|
||||
CanHover: True
|
||||
RenderSprites:
|
||||
Image: carryall
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ waypoint:
|
||||
|
||||
^carryall.colorpicker:
|
||||
Inherits: carryall
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
InitialFacing: 104
|
||||
RenderSprites:
|
||||
Image: carryall
|
||||
|
||||
@@ -719,7 +719,7 @@ Rules:
|
||||
HP: 60
|
||||
Armor:
|
||||
Type: Light
|
||||
Plane:
|
||||
Aircraft:
|
||||
ROT: 5
|
||||
Speed: 280
|
||||
AmmoPool:
|
||||
|
||||
@@ -6,7 +6,7 @@ BADR:
|
||||
HP: 300
|
||||
Armor:
|
||||
Type: Light
|
||||
Plane:
|
||||
Aircraft:
|
||||
CruiseAltitude: 2560
|
||||
ROT: 5
|
||||
Speed: 149
|
||||
@@ -44,7 +44,7 @@ BADR.Bomber:
|
||||
HP: 300
|
||||
Armor:
|
||||
Type: Light
|
||||
Plane:
|
||||
Aircraft:
|
||||
CruiseAltitude: 2560
|
||||
ROT: 5
|
||||
Speed: 149
|
||||
@@ -100,7 +100,7 @@ MIG:
|
||||
LocalYaw: -40, 24
|
||||
AttackPlane:
|
||||
FacingTolerance: 20
|
||||
Plane:
|
||||
Aircraft:
|
||||
CruiseAltitude: 2560
|
||||
InitialFacing: 192
|
||||
ROT: 4
|
||||
@@ -162,7 +162,7 @@ YAK:
|
||||
MuzzleSequence: muzzle
|
||||
AttackPlane:
|
||||
FacingTolerance: 20
|
||||
Plane:
|
||||
Aircraft:
|
||||
CruiseAltitude: 2560
|
||||
RearmBuildings: afld
|
||||
InitialFacing: 192
|
||||
@@ -212,7 +212,7 @@ TRAN:
|
||||
RevealsShroud:
|
||||
Range: 12c0
|
||||
Type: CenterPosition
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
RearmBuildings: hpad
|
||||
InitialFacing: 0
|
||||
ROT: 5
|
||||
@@ -220,6 +220,7 @@ TRAN:
|
||||
LandableTerrainTypes: Clear,Rough,Road,Ore,Beach
|
||||
AltitudeVelocity: 0c100
|
||||
AirborneUpgrades: airborne
|
||||
CanHover: True
|
||||
WithRotor@PRIMARY:
|
||||
Offset: -597,0,341
|
||||
Sequence: rotor2
|
||||
@@ -260,13 +261,14 @@ HELI:
|
||||
LocalOffset: 0,213,-85
|
||||
AttackHeli:
|
||||
FacingTolerance: 20
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
RearmBuildings: hpad
|
||||
LandWhenIdle: false
|
||||
InitialFacing: 20
|
||||
ROT: 4
|
||||
Speed: 149
|
||||
AirborneUpgrades: airborne
|
||||
CanHover: True
|
||||
AutoTarget:
|
||||
InitialStance: HoldFire
|
||||
WithRotor:
|
||||
@@ -312,13 +314,14 @@ HIND:
|
||||
MuzzleSequence: muzzle
|
||||
AttackHeli:
|
||||
FacingTolerance: 20
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
RearmBuildings: hpad
|
||||
LandWhenIdle: false
|
||||
InitialFacing: 20
|
||||
ROT: 4
|
||||
Speed: 112
|
||||
AirborneUpgrades: airborne
|
||||
CanHover: True
|
||||
AutoTarget:
|
||||
InitialStance: HoldFire
|
||||
WithRotor:
|
||||
@@ -342,7 +345,7 @@ U2:
|
||||
HP: 2000
|
||||
Armor:
|
||||
Type: Heavy
|
||||
Plane:
|
||||
Aircraft:
|
||||
CruiseAltitude: 2560
|
||||
ROT: 7
|
||||
Speed: 373
|
||||
|
||||
@@ -85,10 +85,11 @@ TRAN.Husk:
|
||||
Inherits: ^HelicopterHusk
|
||||
Tooltip:
|
||||
Name: Transport Helicopter
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
ROT: 4
|
||||
Speed: 149
|
||||
AirborneUpgrades: airborne
|
||||
CanHover: True
|
||||
WithRotor@PRIMARY:
|
||||
Offset: -597,0,341
|
||||
WithRotor@SECONDARY:
|
||||
@@ -117,7 +118,7 @@ BADR.Husk:
|
||||
Inherits: ^PlaneHusk
|
||||
Tooltip:
|
||||
Name: Badger
|
||||
Plane:
|
||||
Aircraft:
|
||||
ROT: 5
|
||||
Speed: 149
|
||||
AirborneUpgrades: airborne
|
||||
@@ -140,7 +141,7 @@ MIG.Husk:
|
||||
Offset: -598,-683,0
|
||||
Contrail@2:
|
||||
Offset: -598,683,0
|
||||
Plane:
|
||||
Aircraft:
|
||||
ROT: 5
|
||||
Speed: 186
|
||||
AirborneUpgrades: airborne
|
||||
@@ -160,7 +161,7 @@ YAK.Husk:
|
||||
Name: Yak Attack Plane
|
||||
Contrail:
|
||||
Offset: -853,0,0
|
||||
Plane:
|
||||
Aircraft:
|
||||
ROT: 5
|
||||
Speed: 149
|
||||
AirborneUpgrades: airborne
|
||||
@@ -178,10 +179,11 @@ HELI.Husk:
|
||||
Inherits: ^HelicopterHusk
|
||||
Tooltip:
|
||||
Name: Longbow
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
ROT: 4
|
||||
Speed: 149
|
||||
AirborneUpgrades: airborne
|
||||
CanHover: True
|
||||
WithRotor:
|
||||
Offset: 0,0,85
|
||||
SmokeTrailWhenDamaged:
|
||||
@@ -197,10 +199,11 @@ HIND.Husk:
|
||||
Inherits: ^HelicopterHusk
|
||||
Tooltip:
|
||||
Name: Hind
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
ROT: 4
|
||||
Speed: 112
|
||||
AirborneUpgrades: airborne
|
||||
CanHover: True
|
||||
WithRotor:
|
||||
SmokeTrailWhenDamaged:
|
||||
Offset: -427,0,0
|
||||
@@ -213,7 +216,7 @@ HIND.Husk:
|
||||
|
||||
U2.Husk:
|
||||
Inherits: ^PlaneHusk
|
||||
Plane:
|
||||
Aircraft:
|
||||
ROT: 7
|
||||
Speed: 373
|
||||
AirborneUpgrades: airborne
|
||||
|
||||
@@ -4,13 +4,12 @@ DPOD:
|
||||
Cost: 10
|
||||
Tooltip:
|
||||
Name: Drop Pod
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
LandWhenIdle: yes
|
||||
ROT: 5
|
||||
Speed: 149
|
||||
InitialFacing: 0
|
||||
LandableTerrainTypes: Clear
|
||||
AirborneUpgrades: airborne
|
||||
Health:
|
||||
HP: 60
|
||||
Armor:
|
||||
@@ -40,7 +39,7 @@ DSHP:
|
||||
Cost: 1000
|
||||
Tooltip:
|
||||
Name: Dropship
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
LandWhenIdle: yes
|
||||
ROT: 5
|
||||
Speed: 168
|
||||
@@ -48,7 +47,6 @@ DSHP:
|
||||
LandableTerrainTypes: Clear
|
||||
TakeoffSound: dropup1.aud
|
||||
LandingSound: dropdwn1.aud
|
||||
AirborneUpgrades: airborne
|
||||
Health:
|
||||
HP: 200
|
||||
Armor:
|
||||
@@ -76,11 +74,10 @@ ORCA:
|
||||
Prerequisites: ~gahpad
|
||||
Selectable:
|
||||
Bounds: 30,24
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
RearmBuildings: gahpad, nahpad
|
||||
ROT: 5
|
||||
Speed: 186
|
||||
AirborneUpgrades: airborne
|
||||
Health:
|
||||
HP: 200
|
||||
Armor:
|
||||
@@ -115,7 +112,7 @@ ORCAB:
|
||||
Prerequisites: ~gahpad, gatech
|
||||
Selectable:
|
||||
Bounds: 30,24
|
||||
Plane:
|
||||
Aircraft:
|
||||
CruiseAltitude: 3072
|
||||
MaximumPitch: 120
|
||||
ROT: 3
|
||||
@@ -155,7 +152,7 @@ ORCATRAN:
|
||||
BuildPaletteOrder: 10
|
||||
Prerequisites: ~disabled
|
||||
RenderSprites:
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
LandWhenIdle: yes
|
||||
ROT: 5
|
||||
Speed: 84
|
||||
@@ -163,7 +160,6 @@ ORCATRAN:
|
||||
LandableTerrainTypes: Clear
|
||||
TakeoffSound: dropup1.aud
|
||||
LandingSound: dropdwn1.aud
|
||||
AirborneUpgrades: airborne
|
||||
Health:
|
||||
HP: 200
|
||||
Armor:
|
||||
@@ -189,7 +185,7 @@ TRNSPORT:
|
||||
Queue: Air
|
||||
BuildPaletteOrder: 10
|
||||
Prerequisites: ~gahpad, gadept
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
LandWhenIdle: yes
|
||||
ROT: 5
|
||||
Speed: 149
|
||||
@@ -198,7 +194,6 @@ TRNSPORT:
|
||||
TakeoffSound: dropup1.aud
|
||||
LandingSound: dropdwn1.aud
|
||||
AltitudeVelocity: 64
|
||||
AirborneUpgrades: airborne
|
||||
Health:
|
||||
HP: 175
|
||||
Armor:
|
||||
@@ -226,7 +221,7 @@ SCRIN:
|
||||
Bounds: 30,24
|
||||
Voiced:
|
||||
VoiceSet: Scrin
|
||||
Plane:
|
||||
Aircraft:
|
||||
MaximumPitch: 90
|
||||
ROT: 3
|
||||
Speed: 168
|
||||
@@ -265,11 +260,10 @@ APACHE:
|
||||
Prerequisites: ~nahpad
|
||||
Selectable:
|
||||
Bounds: 30,24
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
RearmBuildings: gahpad, nahpad
|
||||
ROT: 5
|
||||
Speed: 130
|
||||
AirborneUpgrades: airborne
|
||||
Health:
|
||||
HP: 225
|
||||
Armor:
|
||||
|
||||
@@ -482,17 +482,18 @@
|
||||
|
||||
^Helicopter:
|
||||
Inherits: ^Aircraft
|
||||
Helicopter:
|
||||
Aircraft:
|
||||
RepairBuildings: gadept
|
||||
RearmBuildings:
|
||||
LandWhenIdle: no
|
||||
CruiseAltitude: 2048
|
||||
Voice: Move
|
||||
AirborneUpgrades: airborne
|
||||
CanHover: True
|
||||
|
||||
^Plane:
|
||||
Inherits: ^Aircraft
|
||||
Plane:
|
||||
Aircraft:
|
||||
RepairBuildings: gadept
|
||||
RearmBuildings: gahpad, nahpad
|
||||
LandWhenIdle: no
|
||||
|
||||
Reference in New Issue
Block a user