Merge pull request #9054 from penev92/bleed_aircraft

Merge Plane and Helicopter traits
This commit is contained in:
reaperrr
2015-10-03 01:52:30 +02:00
39 changed files with 527 additions and 558 deletions

View File

@@ -55,7 +55,7 @@ namespace OpenRA.Mods.Cnc.Traits
if (!self.IsInWorld || self.IsDead) if (!self.IsInWorld || self.IsDead)
return; 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 var actor = w.CreateActor(actorType, new TypeDictionary
{ {
new CenterPositionInit(w.Map.CenterOfCell(startPos) + new WVec(WDist.Zero, WDist.Zero, altitude)), new CenterPositionInit(w.Map.CenterOfCell(startPos) + new WVec(WDist.Zero, WDist.Zero, altitude)),

View File

@@ -17,14 +17,14 @@ namespace OpenRA.Mods.Common.Activities
{ {
public class Fly : Activity public class Fly : Activity
{ {
readonly Plane plane; readonly Aircraft plane;
readonly Target target; readonly Target target;
readonly WDist maxRange; readonly WDist maxRange;
readonly WDist minRange; readonly WDist minRange;
public Fly(Actor self, Target t) public Fly(Actor self, Target t)
{ {
plane = self.Trait<Plane>(); plane = self.Trait<Aircraft>();
target = t; target = t;
} }
@@ -35,7 +35,7 @@ namespace OpenRA.Mods.Common.Activities
this.minRange = minRange; 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); desiredAltitude = new WDist(plane.CenterPosition.Z) + desiredAltitude - self.World.Map.DistanceAboveTerrain(plane.CenterPosition);

View File

@@ -10,18 +10,17 @@
using OpenRA.Activities; using OpenRA.Activities;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Activities namespace OpenRA.Mods.Common.Activities
{ {
public class FlyCircle : Activity public class FlyCircle : Activity
{ {
readonly Plane plane; readonly Aircraft plane;
readonly WDist cruiseAltitude; readonly WDist cruiseAltitude;
public FlyCircle(Actor self) public FlyCircle(Actor self)
{ {
plane = self.Trait<Plane>(); plane = self.Trait<Aircraft>();
cruiseAltitude = plane.Info.CruiseAltitude; cruiseAltitude = plane.Info.CruiseAltitude;
} }

View File

@@ -17,14 +17,14 @@ namespace OpenRA.Mods.Common.Activities
public class FlyFollow : Activity public class FlyFollow : Activity
{ {
Target target; Target target;
Plane plane; Aircraft plane;
WDist minRange; WDist minRange;
WDist maxRange; WDist maxRange;
public FlyFollow(Actor self, Target target, WDist minRange, WDist maxRange) public FlyFollow(Actor self, Target target, WDist minRange, WDist maxRange)
{ {
this.target = target; this.target = target;
plane = self.Trait<Plane>(); plane = self.Trait<Aircraft>();
this.minRange = minRange; this.minRange = minRange;
this.maxRange = maxRange; this.maxRange = maxRange;
} }

View File

@@ -10,17 +10,16 @@
using OpenRA.Activities; using OpenRA.Activities;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Activities namespace OpenRA.Mods.Common.Activities
{ {
public class FlyOffMap : Activity public class FlyOffMap : Activity
{ {
readonly Plane plane; readonly Aircraft plane;
public FlyOffMap(Actor self) public FlyOffMap(Actor self)
{ {
plane = self.Trait<Plane>(); plane = self.Trait<Aircraft>();
} }
public override Activity Tick(Actor self) public override Activity Tick(Actor self)

View File

@@ -10,20 +10,19 @@
using OpenRA.Activities; using OpenRA.Activities;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Activities namespace OpenRA.Mods.Common.Activities
{ {
public class FlyTimed : Activity public class FlyTimed : Activity
{ {
readonly Plane plane; readonly Aircraft plane;
readonly WDist cruiseAltitude; readonly WDist cruiseAltitude;
int remainingTicks; int remainingTicks;
public FlyTimed(int ticks, Actor self) public FlyTimed(int ticks, Actor self)
{ {
remainingTicks = ticks; remainingTicks = ticks;
plane = self.Trait<Plane>(); plane = self.Trait<Aircraft>();
cruiseAltitude = plane.Info.CruiseAltitude; cruiseAltitude = plane.Info.CruiseAltitude;
} }

View File

@@ -8,7 +8,6 @@
*/ */
#endregion #endregion
using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using OpenRA.Activities; using OpenRA.Activities;
@@ -19,7 +18,7 @@ namespace OpenRA.Mods.Common.Activities
{ {
public class HeliAttack : Activity public class HeliAttack : Activity
{ {
readonly Helicopter helicopter; readonly Aircraft helicopter;
readonly AttackHeli attackHeli; readonly AttackHeli attackHeli;
readonly AmmoPool[] ammoPools; readonly AmmoPool[] ammoPools;
readonly bool attackOnlyVisibleTargets; readonly bool attackOnlyVisibleTargets;
@@ -44,7 +43,7 @@ namespace OpenRA.Mods.Common.Activities
public HeliAttack(Actor self, Target target, bool attackOnlyVisibleTargets = true) public HeliAttack(Actor self, Target target, bool attackOnlyVisibleTargets = true)
{ {
Target = target; Target = target;
helicopter = self.Trait<Helicopter>(); helicopter = self.Trait<Aircraft>();
attackHeli = self.Trait<AttackHeli>(); attackHeli = self.Trait<AttackHeli>();
ammoPools = self.TraitsImplementing<AmmoPool>().ToArray(); ammoPools = self.TraitsImplementing<AmmoPool>().ToArray();
this.attackOnlyVisibleTargets = attackOnlyVisibleTargets; 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 // 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 // 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())) 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; var dist = target.CenterPosition - self.CenterPosition;

View File

@@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Activities
{ {
public class HeliFly : Activity public class HeliFly : Activity
{ {
readonly Helicopter helicopter; readonly Aircraft helicopter;
readonly Target target; readonly Target target;
readonly WDist maxRange; readonly WDist maxRange;
readonly WDist minRange; readonly WDist minRange;
@@ -25,7 +25,7 @@ namespace OpenRA.Mods.Common.Activities
public HeliFly(Actor self, Target t) public HeliFly(Actor self, Target t)
{ {
helicopter = self.Trait<Helicopter>(); helicopter = self.Trait<Aircraft>();
target = t; target = t;
} }
@@ -36,7 +36,7 @@ namespace OpenRA.Mods.Common.Activities
this.minRange = minRange; 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); 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 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) : base(self, t)
{ {
this.info = info; this.info = info;

View File

@@ -8,8 +8,6 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic;
using OpenRA.Activities; using OpenRA.Activities;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
using OpenRA.Traits; using OpenRA.Traits;
@@ -18,11 +16,11 @@ namespace OpenRA.Mods.Common.Activities
{ {
public class HeliFlyCircle : Activity public class HeliFlyCircle : Activity
{ {
readonly Helicopter helicopter; readonly Aircraft helicopter;
public HeliFlyCircle(Actor self) public HeliFlyCircle(Actor self)
{ {
helicopter = self.Trait<Helicopter>(); helicopter = self.Trait<Aircraft>();
} }
public override Activity Tick(Actor self) public override Activity Tick(Actor self)

View File

@@ -15,14 +15,14 @@ namespace OpenRA.Mods.Common.Activities
{ {
public class HeliLand : Activity public class HeliLand : Activity
{ {
readonly Helicopter helicopter; readonly Aircraft helicopter;
bool requireSpace; bool requireSpace;
bool playedSound; bool playedSound;
public HeliLand(Actor self, bool requireSpace) public HeliLand(Actor self, bool requireSpace)
{ {
this.requireSpace = requireSpace; this.requireSpace = requireSpace;
helicopter = self.Trait<Helicopter>(); helicopter = self.Trait<Aircraft>();
} }
public override Activity Tick(Actor self) public override Activity Tick(Actor self)

View File

@@ -15,13 +15,13 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Activities 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) public Actor ChooseHelipad(Actor self)

View File

@@ -17,12 +17,12 @@ namespace OpenRA.Mods.Common.Activities
public class Land : Activity public class Land : Activity
{ {
readonly Target target; readonly Target target;
readonly Plane plane; readonly Aircraft plane;
public Land(Actor self, Target t) public Land(Actor self, Target t)
{ {
target = t; target = t;
plane = self.Trait<Plane>(); plane = self.Trait<Aircraft>();
} }
public override Activity Tick(Actor self) public override Activity Tick(Actor self)

View File

@@ -18,22 +18,22 @@ namespace OpenRA.Mods.Common.Activities
{ {
public class ReturnToBase : Activity public class ReturnToBase : Activity
{ {
readonly Plane plane; readonly Aircraft plane;
readonly PlaneInfo planeInfo; readonly AircraftInfo planeInfo;
bool isCalculated; bool isCalculated;
Actor dest; Actor dest;
WPos w1, w2, w3; WPos w1, w2, w3;
public ReturnToBase(Actor self, Actor dest) public ReturnToBase(Actor self, Actor dest = null)
{ {
this.dest = dest; this.dest = dest;
plane = self.Trait<Plane>(); plane = self.Trait<Aircraft>();
planeInfo = self.Info.TraitInfo<PlaneInfo>(); planeInfo = self.Info.TraitInfo<AircraftInfo>();
} }
public static Actor ChooseAirfield(Actor self, bool unreservedOnly) 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>() return self.World.ActorsWithTrait<Reservable>()
.Where(a => a.Actor.Owner == self.Owner) .Where(a => a.Actor.Owner == self.Owner)
.Where(a => rearmBuildings.Contains(a.Actor.Info.Name) .Where(a => rearmBuildings.Contains(a.Actor.Info.Name)
@@ -94,7 +94,6 @@ namespace OpenRA.Mods.Common.Activities
w1 = posCenter + tangentOffset; w1 = posCenter + tangentOffset;
w2 = approachCenter + tangentOffset; w2 = approachCenter + tangentOffset;
w3 = approachStart; w3 = approachStart;
plane.RTBPathHash = w1 + (WVec)w2 + (WVec)w3;
isCalculated = true; isCalculated = true;
} }

View File

@@ -101,7 +101,7 @@
<Compile Include="Activities\Air\HeliFly.cs" /> <Compile Include="Activities\Air\HeliFly.cs" />
<Compile Include="Activities\Air\HeliFlyCircle.cs" /> <Compile Include="Activities\Air\HeliFlyCircle.cs" />
<Compile Include="Activities\Air\HeliLand.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\Land.cs" />
<Compile Include="Activities\Air\ResupplyAircraft.cs" /> <Compile Include="Activities\Air\ResupplyAircraft.cs" />
<Compile Include="Activities\Air\ReturnToBase.cs" /> <Compile Include="Activities\Air\ReturnToBase.cs" />
@@ -202,9 +202,11 @@
<Compile Include="Orders\RepairOrderGenerator.cs" /> <Compile Include="Orders\RepairOrderGenerator.cs" />
<Compile Include="Orders\GlobalButtonOrderGenerator.cs" /> <Compile Include="Orders\GlobalButtonOrderGenerator.cs" />
<Compile Include="Orders\PlaceBuildingOrderGenerator.cs" /> <Compile Include="Orders\PlaceBuildingOrderGenerator.cs" />
<Compile Include="Orders\AircraftMoveOrderTargeter.cs" />
<Compile Include="Orders\UnitOrderTargeter.cs" /> <Compile Include="Orders\UnitOrderTargeter.cs" />
<Compile Include="Pathfinder\CellInfo.cs" /> <Compile Include="Pathfinder\CellInfo.cs" />
<Compile Include="PlayerExtensions.cs" /> <Compile Include="PlayerExtensions.cs" />
<Compile Include="Scripting\Properties\AircraftProperties.cs" />
<Compile Include="Scripting\ScriptUpgradesCache.cs" /> <Compile Include="Scripting\ScriptUpgradesCache.cs" />
<Compile Include="Scripting\Properties\CaptureProperties.cs" /> <Compile Include="Scripting\Properties\CaptureProperties.cs" />
<Compile Include="ServerTraits\ColorValidator.cs" /> <Compile Include="ServerTraits\ColorValidator.cs" />
@@ -235,13 +237,11 @@
<Compile Include="Scripting\Properties\DiplomacyProperties.cs" /> <Compile Include="Scripting\Properties\DiplomacyProperties.cs" />
<Compile Include="Scripting\Properties\HarvesterProperties.cs" /> <Compile Include="Scripting\Properties\HarvesterProperties.cs" />
<Compile Include="Scripting\Properties\HealthProperties.cs" /> <Compile Include="Scripting\Properties\HealthProperties.cs" />
<Compile Include="Scripting\Properties\HelicopterProperties.cs" />
<Compile Include="Scripting\Properties\GeneralProperties.cs" /> <Compile Include="Scripting\Properties\GeneralProperties.cs" />
<Compile Include="Scripting\Properties\GuardProperties.cs" /> <Compile Include="Scripting\Properties\GuardProperties.cs" />
<Compile Include="Scripting\Properties\MissionObjectiveProperties.cs" /> <Compile Include="Scripting\Properties\MissionObjectiveProperties.cs" />
<Compile Include="Scripting\Properties\MobileProperties.cs" /> <Compile Include="Scripting\Properties\MobileProperties.cs" />
<Compile Include="Scripting\Properties\DemolitionProperties.cs" /> <Compile Include="Scripting\Properties\DemolitionProperties.cs" />
<Compile Include="Scripting\Properties\PlaneProperties.cs" />
<Compile Include="Scripting\Properties\PlayerProperties.cs" /> <Compile Include="Scripting\Properties\PlayerProperties.cs" />
<Compile Include="Scripting\Properties\PowerProperties.cs" /> <Compile Include="Scripting\Properties\PowerProperties.cs" />
<Compile Include="Scripting\Properties\ProductionProperties.cs" /> <Compile Include="Scripting\Properties\ProductionProperties.cs" />
@@ -258,8 +258,6 @@
<Compile Include="Traits\Air\AttackPlane.cs" /> <Compile Include="Traits\Air\AttackPlane.cs" />
<Compile Include="Traits\Air\FlyAwayOnIdle.cs" /> <Compile Include="Traits\Air\FlyAwayOnIdle.cs" />
<Compile Include="Traits\Air\FallsToEarth.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\Air\ReturnOnIdle.cs" />
<Compile Include="Traits\AppearsOnRadar.cs" /> <Compile Include="Traits\AppearsOnRadar.cs" />
<Compile Include="Traits\Armament.cs" /> <Compile Include="Traits\Armament.cs" />

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

View File

@@ -137,11 +137,19 @@ namespace OpenRA.Mods.Common.Scripting
} }
else else
{ {
var heli = transport.Info.TraitInfoOrDefault<HelicopterInfo>(); var aircraftInfo = transport.TraitOrDefault<Aircraft>();
if (heli != null) if (aircraftInfo != null)
{ {
transport.QueueActivity(new Turn(transport, heli.InitialFacing)); if (!aircraftInfo.IsPlane)
transport.QueueActivity(new HeliLand(transport, true)); {
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)); transport.QueueActivity(new Wait(15));
} }
@@ -151,7 +159,7 @@ namespace OpenRA.Mods.Common.Scripting
transport.QueueActivity(new WaitFor(() => cargo.IsEmpty(transport))); 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) if (exitFunc != null)

View File

@@ -16,23 +16,34 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Scripting namespace OpenRA.Mods.Common.Scripting
{ {
[ScriptPropertyGroup("Movement")] [ScriptPropertyGroup("Movement")]
public class PlaneProperties : ScriptActorProperties, Requires<PlaneInfo> public class AircraftProperties : ScriptActorProperties, Requires<AircraftInfo>
{ {
public PlaneProperties(ScriptContext context, Actor self) readonly bool isPlane;
: base(context, self) { }
public AircraftProperties(ScriptContext context, Actor self)
: base(context, self)
{
isPlane = self.Trait<Aircraft>().IsPlane;
}
[ScriptActorPropertyActivity] [ScriptActorPropertyActivity]
[Desc("Fly within the cell grid.")] [Desc("Fly within the cell grid.")]
public void Move(CPos cell) 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] [ScriptActorPropertyActivity]
[Desc("Return to the base, which is either the airfield given, or an auto-selected one otherwise.")] [Desc("Return to the base, which is either the airfield given, or an auto-selected one otherwise.")]
public void ReturnToBase(Actor airfield = null) 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));
} }
} }
} }

View File

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

View File

@@ -10,6 +10,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing;
using System.Linq; using System.Linq;
using OpenRA.Activities; using OpenRA.Activities;
using OpenRA.Mods.Common.Activities; using OpenRA.Mods.Common.Activities;
@@ -19,7 +20,8 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.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 CruiseAltitude = new WDist(1280);
public readonly WDist IdealSeparation = new WDist(1706); 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.")] [Desc("The upgrades to grant to self while airborne.")]
public readonly string[] AirborneUpgrades = { }; 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>(); } public IReadOnlyDictionary<CPos, SubCell> OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any) { return new ReadOnlyDictionary<CPos, SubCell>(); }
bool IOccupySpaceInfo.SharesCell { get { return false; } } 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 = { }; static readonly Pair<CPos, SubCell>[] NoCells = { };
readonly AircraftInfo info; public readonly bool IsPlane;
public readonly AircraftInfo Info;
readonly Actor self; readonly Actor self;
UpgradeManager um; UpgradeManager um;
[Sync] public int Facing { get; set; } [Sync] public int Facing { get; set; }
[Sync] public WPos CenterPosition { get; private set; } [Sync] public WPos CenterPosition { get; private set; }
public CPos TopLeft { get { return self.World.Map.CellContaining(CenterPosition); } } public CPos TopLeft { get { return self.World.Map.CellContaining(CenterPosition); } }
public IDisposable Reservation; public IDisposable Reservation;
public int ROT { get { return info.ROT; } } public int ROT { get { return Info.ROT; } }
bool airborne;
bool IsAirborne bool IsAirborne
{ {
get get
@@ -85,21 +115,19 @@ namespace OpenRA.Mods.Common.Traits
if (um != null) if (um != null)
{ {
if (airborne) if (airborne)
foreach (var u in info.AirborneUpgrades) foreach (var u in Info.AirborneUpgrades)
um.GrantUpgrade(self, u, this); um.GrantUpgrade(self, u, this);
else else
foreach (var u in info.AirborneUpgrades) foreach (var u in Info.AirborneUpgrades)
um.RevokeUpgrade(self, u, this); um.RevokeUpgrade(self, u, this);
} }
} }
} }
bool airborne = false;
public Aircraft(ActorInitializer init, AircraftInfo info) public Aircraft(ActorInitializer init, AircraftInfo info)
{ {
this.info = info; Info = info;
this.self = init.Self; self = init.Self;
if (init.Contains<LocationInit>()) if (init.Contains<LocationInit>())
SetPosition(self, init.Get<LocationInit, CPos>()); SetPosition(self, init.Get<LocationInit, CPos>());
@@ -108,10 +136,23 @@ namespace OpenRA.Mods.Common.Traits
SetPosition(self, init.Get<CenterPositionInit, WPos>()); SetPosition(self, init.Get<CenterPositionInit, WPos>());
Facing = init.Contains<FacingInit>() ? init.Get<FacingInit, int>() : info.InitialFacing; 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 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; bool firstTick = true;
public virtual void Tick(Actor self) public virtual void Tick(Actor self)
{ {
@@ -143,24 +184,39 @@ namespace OpenRA.Mods.Common.Traits
if (repulsionFacing == -1) if (repulsionFacing == -1)
return; return;
var speed = info.RepulsionSpeed != -1 ? info.RepulsionSpeed : MovementSpeed; var speed = Info.RepulsionSpeed != -1 ? Info.RepulsionSpeed : MovementSpeed;
SetPosition(self, CenterPosition + FlyStep(speed, repulsionFacing)); SetPosition(self, CenterPosition + FlyStep(speed, repulsionFacing));
} }
public virtual WVec GetRepulsionForce() public virtual WVec GetRepulsionForce()
{ {
if (!info.Repulsable) if (!Info.Repulsable)
return WVec.Zero; return WVec.Zero;
// Repulsion only applies when we're flying! // Repulsion only applies when we're flying!
var altitude = CenterPosition.Z; var altitude = CenterPosition.Z;
if (altitude != info.CruiseAltitude.Length) if (altitude != Info.CruiseAltitude.Length)
return WVec.Zero; return WVec.Zero;
return self.World.FindActorsInCircle(self.CenterPosition, info.IdealSeparation) var repulsionForce = self.World.FindActorsInCircle(self.CenterPosition, Info.IdealSeparation)
.Where(a => !a.IsDead && a.Info.HasTraitInfo<AircraftInfo>() && a.Info.TraitInfo<AircraftInfo>().CruiseAltitude == info.CruiseAltitude) .Where(a => !a.IsDead && a.Info.HasTraitInfo<AircraftInfo>()
&& a.Info.TraitInfo<AircraftInfo>().CruiseAltitude == Info.CruiseAltitude)
.Select(GetRepulsionForce) .Select(GetRepulsionForce)
.Aggregate(WVec.Zero, (a, b) => a + b); .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) public WVec GetRepulsionForce(Actor other)
@@ -170,7 +226,7 @@ namespace OpenRA.Mods.Common.Traits
var d = self.CenterPosition - other.CenterPosition; var d = self.CenterPosition - other.CenterPosition;
var distSq = d.HorizontalLengthSquared; var distSq = d.HorizontalLengthSquared;
if (distSq > info.IdealSeparation.LengthSquared) if (distSq > Info.IdealSeparation.LengthSquared)
return WVec.Zero; return WVec.Zero;
if (distSq < 1) 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) public bool AircraftCanEnter(Actor a)
{ {
if (self.AppearsHostileTo(a)) if (self.AppearsHostileTo(a))
return false; return false;
return info.RearmBuildings.Contains(a.Info.Name) return Info.RearmBuildings.Contains(a.Info.Name)
|| info.RepairBuildings.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;
} }
public int MovementSpeed public int MovementSpeed
@@ -299,7 +290,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
var modifiers = self.TraitsImplementing<ISpeedModifier>() var modifiers = self.TraitsImplementing<ISpeedModifier>()
.Select(m => m.GetSpeedModifier()); .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; return false;
var type = self.World.Map.GetTerrainInfo(cell).Type; 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) public virtual IEnumerable<Activity> GetResupplyActivities(Actor a)
{ {
var name = a.Info.Name; var name = a.Info.Name;
if (info.RearmBuildings.Contains(name)) if (Info.RearmBuildings.Contains(name))
yield return new Rearm(self); yield return new Rearm(self);
if (info.RepairBuildings.Contains(name)) if (Info.RepairBuildings.Contains(name))
yield return new Repair(a); 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 public IEnumerable<IOrderTargeter> Orders
{ {
get get
@@ -344,7 +468,7 @@ namespace OpenRA.Mods.Common.Traits
yield return new EnterAlliedActorTargeter<BuildingInfo>("Enter", 5, yield return new EnterAlliedActorTargeter<BuildingInfo>("Enter", 5,
target => AircraftCanEnter(target), target => !Reservable.IsReserved(target)); 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 "Enter":
case "ReturnToBase": case "ReturnToBase":
case "Stop": case "Stop":
return info.Voice; return Info.Voice;
default: return null; default: return null;
} }
} }
}
class AircraftMoveOrderTargeter : IOrderTargeter public void ResolveOrder(Actor self, Order order)
{
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) if (order.OrderString == "Move")
return false; {
var cell = self.World.Map.Clamp(order.TargetLocation);
var location = self.World.Map.CellContaining(target.CenterPosition); if (!Info.MoveIntoShroud && !self.Owner.Shroud.IsExplored(cell))
var explored = self.Owner.Shroud.IsExplored(location); return;
cursor = self.World.Map.Contains(location) ?
(self.World.Map.GetTerrainInfo(location).CustomCursor ?? "move") :
"move-blocked";
IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue); if (!order.Queued)
UnReserve();
if (!explored && !info.MoveIntoShroud) var target = Target.FromCell(self.World, cell);
cursor = "move-blocked";
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();
}
} }
} }

View File

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

View File

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

View File

@@ -66,7 +66,7 @@ namespace OpenRA.Mods.Common.Traits
int totalWeight = 0; int totalWeight = 0;
int reservedWeight = 0; int reservedWeight = 0;
Helicopter helicopter; Aircraft aircraft;
CPos currentCell; CPos currentCell;
public IEnumerable<CPos> CurrentAdjacentCells { get; private set; } public IEnumerable<CPos> CurrentAdjacentCells { get; private set; }
@@ -116,7 +116,7 @@ namespace OpenRA.Mods.Common.Traits
public void Created(Actor self) public void Created(Actor self)
{ {
helicopter = self.TraitOrDefault<Helicopter>(); aircraft = self.TraitOrDefault<Aircraft>();
} }
static int GetWeight(Actor a) { return a.Info.TraitInfo<PassengerInfo>().Weight; } static int GetWeight(Actor a) { return a.Info.TraitInfo<PassengerInfo>().Weight; }
@@ -144,7 +144,7 @@ namespace OpenRA.Mods.Common.Traits
Unloading = true; Unloading = true;
self.CancelActivity(); self.CancelActivity();
if (helicopter != null) if (aircraft != null)
self.QueueActivity(new HeliLand(self, true)); self.QueueActivity(new HeliLand(self, true));
self.QueueActivity(new UnloadCargo(self, true)); self.QueueActivity(new UnloadCargo(self, true));
} }
@@ -165,7 +165,7 @@ namespace OpenRA.Mods.Common.Traits
return false; 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))); && CurrentAdjacentCells != null && CurrentAdjacentCells.Any(c => Passengers.Any(p => p.Trait<IPositionable>().CanEnterCell(c)));
} }

View File

@@ -61,7 +61,7 @@ namespace OpenRA.Mods.Common.Traits
if (randomize) if (randomize)
attackFacing = Util.QuantizeFacing(self.World.SharedRandom.Next(256), info.QuantizedFacings) * (256 / info.QuantizedFacings); 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 attackRotation = WRot.FromFacing(attackFacing);
var delta = new WVec(0, -1024, 0).Rotate(attackRotation); var delta = new WVec(0, -1024, 0).Rotate(attackRotation);
target = target + new WVec(0, 0, altitude); target = target + new WVec(0, 0, altitude);

View File

@@ -112,7 +112,7 @@ namespace OpenRA.Mods.Common.Traits
if (self.Info.HasTraitInfo<IFacingInfo>()) if (self.Info.HasTraitInfo<IFacingInfo>())
self.QueueActivity(new Turn(self, info.Facing)); self.QueueActivity(new Turn(self, info.Facing));
if (self.Info.HasTraitInfo<HelicopterInfo>()) if (self.Info.HasTraitInfo<AircraftInfo>())
self.QueueActivity(new HeliLand(self, true)); self.QueueActivity(new HeliLand(self, true));
foreach (var nt in self.TraitsImplementing<INotifyTransform>()) foreach (var nt in self.TraitsImplementing<INotifyTransform>())

View File

@@ -111,7 +111,7 @@ namespace OpenRA.Mods.Common.Traits
var dropFacing = Util.QuantizeFacing(self.World.SharedRandom.Next(256), info.QuantizedFacings) * (256 / info.QuantizedFacings); 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 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 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 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; var finishEdge = target + (self.World.Map.DistanceToEdge(target, delta) + info.Cordon).Length * delta / 1024;

View File

@@ -1832,9 +1832,9 @@ namespace OpenRA.Mods.Common.UtilityCommands
if (inftraits != null) if (inftraits != null)
{ {
node.Value.Nodes.Add(new MiniYamlNode("QuantizeFacingsFromSequence", null, new List<MiniYamlNode> 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 => var other = node.Value.Nodes.FirstOrDefault(x =>
@@ -2030,7 +2030,8 @@ namespace OpenRA.Mods.Common.UtilityCommands
} }
else else
cloakedTargetTypes = new MiniYamlNode("TargetTypes", ""); 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, cloakedTargetTypes,
new MiniYamlNode("UpgradeTypes", "underwater"), new MiniYamlNode("UpgradeTypes", "underwater"),
new MiniYamlNode("UpgradeMinEnabledLevel", "1") new MiniYamlNode("UpgradeMinEnabledLevel", "1")
@@ -2067,7 +2068,8 @@ namespace OpenRA.Mods.Common.UtilityCommands
} }
else else
groundTargetTypes = new MiniYamlNode("TargetTypes", ""); 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, groundTargetTypes,
new MiniYamlNode("UpgradeTypes", "airborne"), new MiniYamlNode("UpgradeTypes", "airborne"),
new MiniYamlNode("UpgradeMaxEnabledLevel", "0") 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); UpgradeActorRules(engineVersion, ref node.Value.Nodes, node, depth + 1);
} }
} }

View File

@@ -23,7 +23,7 @@ namespace OpenRA.Mods.D2k.Activities
readonly IMove movement; readonly IMove movement;
readonly Carryable carryable; readonly Carryable carryable;
readonly Carryall carryall; readonly Carryall carryall;
readonly Helicopter helicopter; readonly Aircraft aircraft;
readonly IPositionable positionable; readonly IPositionable positionable;
readonly IFacing cargoFacing; readonly IFacing cargoFacing;
readonly IFacing selfFacing; readonly IFacing selfFacing;
@@ -39,7 +39,7 @@ namespace OpenRA.Mods.D2k.Activities
cargo = carryall.Carrying; cargo = carryall.Carrying;
movement = self.Trait<IMove>(); movement = self.Trait<IMove>();
carryable = cargo.Trait<Carryable>(); carryable = cargo.Trait<Carryable>();
helicopter = self.Trait<Helicopter>(); aircraft = self.Trait<Aircraft>();
positionable = cargo.Trait<IPositionable>(); positionable = cargo.Trait<IPositionable>();
cargoFacing = cargo.Trait<IFacing>(); cargoFacing = cargo.Trait<IFacing>();
selfFacing = self.Trait<IFacing>(); selfFacing = self.Trait<IFacing>();
@@ -95,7 +95,7 @@ namespace OpenRA.Mods.D2k.Activities
return this; return this;
} }
if (HeliFly.AdjustAltitude(self, helicopter, helicopter.Info.LandAltitude)) if (HeliFly.AdjustAltitude(self, aircraft, aircraft.Info.LandAltitude))
return this; return this;
state = State.Release; state = State.Release;
return Util.SequenceActivities(new Wait(15), this); return Util.SequenceActivities(new Wait(15), this);

View File

@@ -22,7 +22,7 @@ namespace OpenRA.Mods.D2k.Activities
readonly IMove movement; readonly IMove movement;
readonly Carryable carryable; readonly Carryable carryable;
readonly Carryall carryall; readonly Carryall carryall;
readonly Helicopter helicopter; readonly Aircraft aircraft;
readonly IFacing cargoFacing; readonly IFacing cargoFacing;
readonly IFacing selfFacing; readonly IFacing selfFacing;
@@ -37,7 +37,7 @@ namespace OpenRA.Mods.D2k.Activities
cargoFacing = cargo.Trait<IFacing>(); cargoFacing = cargo.Trait<IFacing>();
movement = self.Trait<IMove>(); movement = self.Trait<IMove>();
carryall = self.Trait<Carryall>(); carryall = self.Trait<Carryall>();
helicopter = self.Trait<Helicopter>(); aircraft = self.Trait<Aircraft>();
selfFacing = self.Trait<IFacing>(); selfFacing = self.Trait<IFacing>();
state = State.Intercept; state = State.Intercept;
} }
@@ -90,7 +90,7 @@ namespace OpenRA.Mods.D2k.Activities
state = State.TakeOff; state = State.TakeOff;
return this; return this;
case State.TakeOff: case State.TakeOff:
if (HeliFly.AdjustAltitude(self, helicopter, helicopter.Info.CruiseAltitude)) if (HeliFly.AdjustAltitude(self, aircraft, aircraft.Info.CruiseAltitude))
return this; return this;
return NextActivity; return NextActivity;
} }

View File

@@ -50,7 +50,8 @@ namespace OpenRA.Mods.D2k.Traits
IsBusy = false; IsBusy = false;
IsCarrying = false; IsCarrying = false;
var helicopter = self.Info.TraitInfoOrDefault<HelicopterInfo>();
var helicopter = self.Info.TraitInfoOrDefault<AircraftInfo>();
carryHeight = helicopter != null ? helicopter.LandAltitude : WDist.Zero; carryHeight = helicopter != null ? helicopter.LandAltitude : WDist.Zero;
} }

View File

@@ -72,7 +72,7 @@ namespace OpenRA.Mods.RA.Traits
if (randomize) if (randomize)
dropFacing = Util.QuantizeFacing(self.World.SharedRandom.Next(256), info.QuantizedFacings) * (256 / info.QuantizedFacings); 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 dropRotation = WRot.FromFacing(dropFacing);
var delta = new WVec(0, -1024, 0).Rotate(dropRotation); var delta = new WVec(0, -1024, 0).Rotate(dropRotation);
target = target + new WVec(0, 0, altitude); target = target + new WVec(0, 0, altitude);

View File

@@ -9,14 +9,13 @@ TRAN:
BuildPaletteOrder: 10 BuildPaletteOrder: 10
Prerequisites: hpad Prerequisites: hpad
Queue: Aircraft.GDI, Aircraft.Nod Queue: Aircraft.GDI, Aircraft.Nod
Helicopter: Aircraft:
LandWhenIdle: true LandWhenIdle: true
ROT: 5 ROT: 5
Speed: 140 Speed: 140
InitialFacing: 0 InitialFacing: 0
LandableTerrainTypes: Clear,Rough,Road,Ore,Beach,Tiberium,BlueTiberium LandableTerrainTypes: Clear,Rough,Road,Ore,Beach,Tiberium,BlueTiberium
AltitudeVelocity: 0c100 AltitudeVelocity: 0c100
AirborneUpgrades: airborne
Health: Health:
HP: 90 HP: 90
Armor: Armor:
@@ -53,11 +52,10 @@ HELI:
BuildPaletteOrder: 20 BuildPaletteOrder: 20
Prerequisites: hpad, anyhq, ~techlevel.medium Prerequisites: hpad, anyhq, ~techlevel.medium
Queue: Aircraft.Nod Queue: Aircraft.Nod
Helicopter: Aircraft:
RearmBuildings: hpad RearmBuildings: hpad
ROT: 4 ROT: 4
Speed: 186 Speed: 186
AirborneUpgrades: airborne
Health: Health:
HP: 125 HP: 125
Armor: Armor:
@@ -105,11 +103,10 @@ ORCA:
BuildPaletteOrder: 20 BuildPaletteOrder: 20
Prerequisites: hpad, anyhq, ~techlevel.medium Prerequisites: hpad, anyhq, ~techlevel.medium
Queue: Aircraft.GDI Queue: Aircraft.GDI
Helicopter: Aircraft:
RearmBuildings: hpad RearmBuildings: hpad
ROT: 4 ROT: 4
Speed: 186 Speed: 186
AirborneUpgrades: airborne
Health: Health:
HP: 90 HP: 90
Armor: Armor:
@@ -151,7 +148,7 @@ C17:
Description: Drops vehicle reinforcements on Airstrips Description: Drops vehicle reinforcements on Airstrips
Valued: Valued:
Cost: 2000 Cost: 2000
Plane: Aircraft:
ROT: 5 ROT: 5
Speed: 326 Speed: 326
Repulsable: False Repulsable: False
@@ -188,7 +185,7 @@ A10:
Description: Used to deliver air strikes. Description: Used to deliver air strikes.
Valued: Valued:
Cost: 2000 Cost: 2000
Plane: Aircraft:
ROT: 4 ROT: 4
Speed: 373 Speed: 373
Repulsable: False Repulsable: False
@@ -221,10 +218,9 @@ TRAN.Husk:
Inherits: ^HelicopterHusk Inherits: ^HelicopterHusk
Tooltip: Tooltip:
Name: Chinook Transport Name: Chinook Transport
Helicopter: Aircraft:
ROT: 5 ROT: 5
Speed: 140 Speed: 140
AirborneUpgrades: airborne
RevealsShroud: RevealsShroud:
Range: 8c0 Range: 8c0
Type: CenterPosition Type: CenterPosition
@@ -239,10 +235,9 @@ HELI.Husk:
Inherits: ^HelicopterHusk Inherits: ^HelicopterHusk
Tooltip: Tooltip:
Name: Apache Longbow Name: Apache Longbow
Helicopter: Aircraft:
ROT: 4 ROT: 4
Speed: 186 Speed: 186
AirborneUpgrades: airborne
RevealsShroud: RevealsShroud:
Range: 10c0 Range: 10c0
Type: CenterPosition Type: CenterPosition
@@ -255,10 +250,9 @@ ORCA.Husk:
Inherits: ^HelicopterHusk Inherits: ^HelicopterHusk
Tooltip: Tooltip:
Name: Orca Name: Orca
Helicopter: Aircraft:
ROT: 4 ROT: 4
Speed: 186 Speed: 186
AirborneUpgrades: airborne
RevealsShroud: RevealsShroud:
Range: 10c0 Range: 10c0
Type: CenterPosition Type: CenterPosition

View File

@@ -131,11 +131,12 @@
SelectionDecorations: SelectionDecorations:
Selectable: Selectable:
Bounds: 24,24 Bounds: 24,24
Helicopter: Aircraft:
RepairBuildings: hpad RepairBuildings: hpad
RearmBuildings: RearmBuildings:
LandWhenIdle: false LandWhenIdle: false
AirborneUpgrades: airborne AirborneUpgrades: airborne
CanHover: True
HiddenUnderFog: HiddenUnderFog:
Type: CenterPosition Type: CenterPosition
ActorLostNotification: ActorLostNotification:
@@ -664,6 +665,9 @@
^HelicopterHusk: ^HelicopterHusk:
Inherits: ^CommonHuskDefaults Inherits: ^CommonHuskDefaults
WithShadow: WithShadow:
Aircraft:
AirborneUpgrades: airborne
CanHover: True
FallsToEarth: FallsToEarth:
Spins: True Spins: True
Moves: False Moves: False

View File

@@ -9,7 +9,7 @@ carryall.reinforce:
HP: 4800 HP: 4800
Armor: Armor:
Type: light Type: light
Helicopter: Aircraft:
CruiseAltitude: 2100 CruiseAltitude: 2100
InitialFacing: 0 InitialFacing: 0
ROT: 4 ROT: 4
@@ -21,6 +21,7 @@ carryall.reinforce:
LandAltitude: 100 LandAltitude: 100
LandWhenIdle: False LandWhenIdle: False
AirborneUpgrades: airborne AirborneUpgrades: airborne
CanHover: True
Targetable@GROUND: Targetable@GROUND:
TargetTypes: Ground, Vehicle TargetTypes: Ground, Vehicle
UpgradeTypes: airborne UpgradeTypes: airborne
@@ -51,7 +52,7 @@ frigate:
Tooltip: Tooltip:
Name: Frigate Name: Frigate
Description: Supply spacecraft Description: Supply spacecraft
Plane: Aircraft:
ROT: 1 ROT: 1
Speed: 126 Speed: 126
RepairBuildings: repair_pad RepairBuildings: repair_pad
@@ -66,7 +67,6 @@ frigate:
ornithopter: ornithopter:
Inherits: ^Plane Inherits: ^Plane
Targetable:
TargetTypes: Air TargetTypes: Air
AttackBomber: AttackBomber:
Armament: Armament:
@@ -75,12 +75,13 @@ ornithopter:
HP: 900 HP: 900
Armor: Armor:
Type: light Type: light
Plane: Aircraft:
ROT: 2 ROT: 2
Speed: 189 Speed: 189
RepairBuildings: RepairBuildings:
RearmBuildings: RearmBuildings:
Repulsable: False Repulsable: False
CanHover: True
AmmoPool: AmmoPool:
Ammo: 5 Ammo: 5
Tooltip: Tooltip:
@@ -93,7 +94,7 @@ ornithopter.husk:
Inherits: ^AircraftHusk Inherits: ^AircraftHusk
Tooltip: Tooltip:
Name: Ornithopter Name: Ornithopter
Plane: Aircraft:
ROT: 5 ROT: 5
Speed: 189 Speed: 189
RepairBuildings: RepairBuildings:
@@ -105,11 +106,12 @@ carryall.husk:
Inherits: ^AircraftHusk Inherits: ^AircraftHusk
Tooltip: Tooltip:
Name: Carryall Name: Carryall
Helicopter: Aircraft:
ROT: 4 ROT: 4
Speed: 112 Speed: 112
RepairBuildings: RepairBuildings:
RearmBuildings: RearmBuildings:
CanHover: True
RenderSprites: RenderSprites:
Image: carryall Image: carryall

View File

@@ -131,7 +131,7 @@ waypoint:
^carryall.colorpicker: ^carryall.colorpicker:
Inherits: carryall Inherits: carryall
Helicopter: Aircraft:
InitialFacing: 104 InitialFacing: 104
RenderSprites: RenderSprites:
Image: carryall Image: carryall

View File

@@ -719,7 +719,7 @@ Rules:
HP: 60 HP: 60
Armor: Armor:
Type: Light Type: Light
Plane: Aircraft:
ROT: 5 ROT: 5
Speed: 280 Speed: 280
AmmoPool: AmmoPool:

View File

@@ -6,7 +6,7 @@ BADR:
HP: 300 HP: 300
Armor: Armor:
Type: Light Type: Light
Plane: Aircraft:
CruiseAltitude: 2560 CruiseAltitude: 2560
ROT: 5 ROT: 5
Speed: 149 Speed: 149
@@ -44,7 +44,7 @@ BADR.Bomber:
HP: 300 HP: 300
Armor: Armor:
Type: Light Type: Light
Plane: Aircraft:
CruiseAltitude: 2560 CruiseAltitude: 2560
ROT: 5 ROT: 5
Speed: 149 Speed: 149
@@ -100,7 +100,7 @@ MIG:
LocalYaw: -40, 24 LocalYaw: -40, 24
AttackPlane: AttackPlane:
FacingTolerance: 20 FacingTolerance: 20
Plane: Aircraft:
CruiseAltitude: 2560 CruiseAltitude: 2560
InitialFacing: 192 InitialFacing: 192
ROT: 4 ROT: 4
@@ -162,7 +162,7 @@ YAK:
MuzzleSequence: muzzle MuzzleSequence: muzzle
AttackPlane: AttackPlane:
FacingTolerance: 20 FacingTolerance: 20
Plane: Aircraft:
CruiseAltitude: 2560 CruiseAltitude: 2560
RearmBuildings: afld RearmBuildings: afld
InitialFacing: 192 InitialFacing: 192
@@ -212,7 +212,7 @@ TRAN:
RevealsShroud: RevealsShroud:
Range: 12c0 Range: 12c0
Type: CenterPosition Type: CenterPosition
Helicopter: Aircraft:
RearmBuildings: hpad RearmBuildings: hpad
InitialFacing: 0 InitialFacing: 0
ROT: 5 ROT: 5
@@ -220,6 +220,7 @@ TRAN:
LandableTerrainTypes: Clear,Rough,Road,Ore,Beach LandableTerrainTypes: Clear,Rough,Road,Ore,Beach
AltitudeVelocity: 0c100 AltitudeVelocity: 0c100
AirborneUpgrades: airborne AirborneUpgrades: airborne
CanHover: True
WithRotor@PRIMARY: WithRotor@PRIMARY:
Offset: -597,0,341 Offset: -597,0,341
Sequence: rotor2 Sequence: rotor2
@@ -260,13 +261,14 @@ HELI:
LocalOffset: 0,213,-85 LocalOffset: 0,213,-85
AttackHeli: AttackHeli:
FacingTolerance: 20 FacingTolerance: 20
Helicopter: Aircraft:
RearmBuildings: hpad RearmBuildings: hpad
LandWhenIdle: false LandWhenIdle: false
InitialFacing: 20 InitialFacing: 20
ROT: 4 ROT: 4
Speed: 149 Speed: 149
AirborneUpgrades: airborne AirborneUpgrades: airborne
CanHover: True
AutoTarget: AutoTarget:
InitialStance: HoldFire InitialStance: HoldFire
WithRotor: WithRotor:
@@ -312,13 +314,14 @@ HIND:
MuzzleSequence: muzzle MuzzleSequence: muzzle
AttackHeli: AttackHeli:
FacingTolerance: 20 FacingTolerance: 20
Helicopter: Aircraft:
RearmBuildings: hpad RearmBuildings: hpad
LandWhenIdle: false LandWhenIdle: false
InitialFacing: 20 InitialFacing: 20
ROT: 4 ROT: 4
Speed: 112 Speed: 112
AirborneUpgrades: airborne AirborneUpgrades: airborne
CanHover: True
AutoTarget: AutoTarget:
InitialStance: HoldFire InitialStance: HoldFire
WithRotor: WithRotor:
@@ -342,7 +345,7 @@ U2:
HP: 2000 HP: 2000
Armor: Armor:
Type: Heavy Type: Heavy
Plane: Aircraft:
CruiseAltitude: 2560 CruiseAltitude: 2560
ROT: 7 ROT: 7
Speed: 373 Speed: 373

View File

@@ -85,10 +85,11 @@ TRAN.Husk:
Inherits: ^HelicopterHusk Inherits: ^HelicopterHusk
Tooltip: Tooltip:
Name: Transport Helicopter Name: Transport Helicopter
Helicopter: Aircraft:
ROT: 4 ROT: 4
Speed: 149 Speed: 149
AirborneUpgrades: airborne AirborneUpgrades: airborne
CanHover: True
WithRotor@PRIMARY: WithRotor@PRIMARY:
Offset: -597,0,341 Offset: -597,0,341
WithRotor@SECONDARY: WithRotor@SECONDARY:
@@ -117,7 +118,7 @@ BADR.Husk:
Inherits: ^PlaneHusk Inherits: ^PlaneHusk
Tooltip: Tooltip:
Name: Badger Name: Badger
Plane: Aircraft:
ROT: 5 ROT: 5
Speed: 149 Speed: 149
AirborneUpgrades: airborne AirborneUpgrades: airborne
@@ -140,7 +141,7 @@ MIG.Husk:
Offset: -598,-683,0 Offset: -598,-683,0
Contrail@2: Contrail@2:
Offset: -598,683,0 Offset: -598,683,0
Plane: Aircraft:
ROT: 5 ROT: 5
Speed: 186 Speed: 186
AirborneUpgrades: airborne AirborneUpgrades: airborne
@@ -160,7 +161,7 @@ YAK.Husk:
Name: Yak Attack Plane Name: Yak Attack Plane
Contrail: Contrail:
Offset: -853,0,0 Offset: -853,0,0
Plane: Aircraft:
ROT: 5 ROT: 5
Speed: 149 Speed: 149
AirborneUpgrades: airborne AirborneUpgrades: airborne
@@ -178,10 +179,11 @@ HELI.Husk:
Inherits: ^HelicopterHusk Inherits: ^HelicopterHusk
Tooltip: Tooltip:
Name: Longbow Name: Longbow
Helicopter: Aircraft:
ROT: 4 ROT: 4
Speed: 149 Speed: 149
AirborneUpgrades: airborne AirborneUpgrades: airborne
CanHover: True
WithRotor: WithRotor:
Offset: 0,0,85 Offset: 0,0,85
SmokeTrailWhenDamaged: SmokeTrailWhenDamaged:
@@ -197,10 +199,11 @@ HIND.Husk:
Inherits: ^HelicopterHusk Inherits: ^HelicopterHusk
Tooltip: Tooltip:
Name: Hind Name: Hind
Helicopter: Aircraft:
ROT: 4 ROT: 4
Speed: 112 Speed: 112
AirborneUpgrades: airborne AirborneUpgrades: airborne
CanHover: True
WithRotor: WithRotor:
SmokeTrailWhenDamaged: SmokeTrailWhenDamaged:
Offset: -427,0,0 Offset: -427,0,0
@@ -213,7 +216,7 @@ HIND.Husk:
U2.Husk: U2.Husk:
Inherits: ^PlaneHusk Inherits: ^PlaneHusk
Plane: Aircraft:
ROT: 7 ROT: 7
Speed: 373 Speed: 373
AirborneUpgrades: airborne AirborneUpgrades: airborne

View File

@@ -4,13 +4,12 @@ DPOD:
Cost: 10 Cost: 10
Tooltip: Tooltip:
Name: Drop Pod Name: Drop Pod
Helicopter: Aircraft:
LandWhenIdle: yes LandWhenIdle: yes
ROT: 5 ROT: 5
Speed: 149 Speed: 149
InitialFacing: 0 InitialFacing: 0
LandableTerrainTypes: Clear LandableTerrainTypes: Clear
AirborneUpgrades: airborne
Health: Health:
HP: 60 HP: 60
Armor: Armor:
@@ -40,7 +39,7 @@ DSHP:
Cost: 1000 Cost: 1000
Tooltip: Tooltip:
Name: Dropship Name: Dropship
Helicopter: Aircraft:
LandWhenIdle: yes LandWhenIdle: yes
ROT: 5 ROT: 5
Speed: 168 Speed: 168
@@ -48,7 +47,6 @@ DSHP:
LandableTerrainTypes: Clear LandableTerrainTypes: Clear
TakeoffSound: dropup1.aud TakeoffSound: dropup1.aud
LandingSound: dropdwn1.aud LandingSound: dropdwn1.aud
AirborneUpgrades: airborne
Health: Health:
HP: 200 HP: 200
Armor: Armor:
@@ -76,11 +74,10 @@ ORCA:
Prerequisites: ~gahpad Prerequisites: ~gahpad
Selectable: Selectable:
Bounds: 30,24 Bounds: 30,24
Helicopter: Aircraft:
RearmBuildings: gahpad, nahpad RearmBuildings: gahpad, nahpad
ROT: 5 ROT: 5
Speed: 186 Speed: 186
AirborneUpgrades: airborne
Health: Health:
HP: 200 HP: 200
Armor: Armor:
@@ -115,7 +112,7 @@ ORCAB:
Prerequisites: ~gahpad, gatech Prerequisites: ~gahpad, gatech
Selectable: Selectable:
Bounds: 30,24 Bounds: 30,24
Plane: Aircraft:
CruiseAltitude: 3072 CruiseAltitude: 3072
MaximumPitch: 120 MaximumPitch: 120
ROT: 3 ROT: 3
@@ -155,7 +152,7 @@ ORCATRAN:
BuildPaletteOrder: 10 BuildPaletteOrder: 10
Prerequisites: ~disabled Prerequisites: ~disabled
RenderSprites: RenderSprites:
Helicopter: Aircraft:
LandWhenIdle: yes LandWhenIdle: yes
ROT: 5 ROT: 5
Speed: 84 Speed: 84
@@ -163,7 +160,6 @@ ORCATRAN:
LandableTerrainTypes: Clear LandableTerrainTypes: Clear
TakeoffSound: dropup1.aud TakeoffSound: dropup1.aud
LandingSound: dropdwn1.aud LandingSound: dropdwn1.aud
AirborneUpgrades: airborne
Health: Health:
HP: 200 HP: 200
Armor: Armor:
@@ -189,7 +185,7 @@ TRNSPORT:
Queue: Air Queue: Air
BuildPaletteOrder: 10 BuildPaletteOrder: 10
Prerequisites: ~gahpad, gadept Prerequisites: ~gahpad, gadept
Helicopter: Aircraft:
LandWhenIdle: yes LandWhenIdle: yes
ROT: 5 ROT: 5
Speed: 149 Speed: 149
@@ -198,7 +194,6 @@ TRNSPORT:
TakeoffSound: dropup1.aud TakeoffSound: dropup1.aud
LandingSound: dropdwn1.aud LandingSound: dropdwn1.aud
AltitudeVelocity: 64 AltitudeVelocity: 64
AirborneUpgrades: airborne
Health: Health:
HP: 175 HP: 175
Armor: Armor:
@@ -226,7 +221,7 @@ SCRIN:
Bounds: 30,24 Bounds: 30,24
Voiced: Voiced:
VoiceSet: Scrin VoiceSet: Scrin
Plane: Aircraft:
MaximumPitch: 90 MaximumPitch: 90
ROT: 3 ROT: 3
Speed: 168 Speed: 168
@@ -265,11 +260,10 @@ APACHE:
Prerequisites: ~nahpad Prerequisites: ~nahpad
Selectable: Selectable:
Bounds: 30,24 Bounds: 30,24
Helicopter: Aircraft:
RearmBuildings: gahpad, nahpad RearmBuildings: gahpad, nahpad
ROT: 5 ROT: 5
Speed: 130 Speed: 130
AirborneUpgrades: airborne
Health: Health:
HP: 225 HP: 225
Armor: Armor:

View File

@@ -482,17 +482,18 @@
^Helicopter: ^Helicopter:
Inherits: ^Aircraft Inherits: ^Aircraft
Helicopter: Aircraft:
RepairBuildings: gadept RepairBuildings: gadept
RearmBuildings: RearmBuildings:
LandWhenIdle: no LandWhenIdle: no
CruiseAltitude: 2048 CruiseAltitude: 2048
Voice: Move Voice: Move
AirborneUpgrades: airborne AirborneUpgrades: airborne
CanHover: True
^Plane: ^Plane:
Inherits: ^Aircraft Inherits: ^Aircraft
Plane: Aircraft:
RepairBuildings: gadept RepairBuildings: gadept
RearmBuildings: gahpad, nahpad RearmBuildings: gahpad, nahpad
LandWhenIdle: no LandWhenIdle: no