Add LandOnCondition to the trait Aircraft which triggers a landing and prevents takeoffs while the condition is met

This commit is contained in:
Jean-Rémy Buchs
2017-06-03 00:48:28 +02:00
committed by atlimit8
parent c4d2fdbd83
commit 1d1802a163
13 changed files with 126 additions and 2 deletions

View File

@@ -17,6 +17,7 @@ using OpenRA.Activities;
using OpenRA.Mods.Common.Activities;
using OpenRA.Mods.Common.Orders;
using OpenRA.Primitives;
using OpenRA.Support;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
@@ -39,7 +40,7 @@ namespace OpenRA.Mods.Common.Traits
public readonly int TurnSpeed = 255;
public readonly int Speed = 1;
[Desc("Minimum altitude where this aircraft is considered airborne")]
[Desc("Minimum altitude where this aircraft is considered airborne.")]
public readonly int MinAirborneAltitude = 1;
public readonly HashSet<string> LandableTerrainTypes = new HashSet<string>();
@@ -100,6 +101,9 @@ namespace OpenRA.Mods.Common.Traits
yield return new FacingInit(PreviewFacing);
}
[Desc("Condition when this aircraft should land as soon as possible and refuse to take off.")]
public readonly BooleanExpression LandOnCondition;
public IReadOnlyDictionary<CPos, SubCell> OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any) { return new ReadOnlyDictionary<CPos, SubCell>(); }
bool IOccupySpaceInfo.SharesCell { get { return false; } }
@@ -124,7 +128,7 @@ namespace OpenRA.Mods.Common.Traits
}
public class Aircraft : ITick, ISync, IFacing, IPositionable, IMove, IIssueOrder, IResolveOrder, IOrderVoice, IDeathActorInitModifier,
INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyActorDisposing, IActorPreviewInitModifier, IIssueDeployOrder
INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyActorDisposing, IActorPreviewInitModifier, IIssueDeployOrder, IObservesVariables
{
static readonly Pair<CPos, SubCell>[] NoCells = { };
@@ -142,6 +146,7 @@ namespace OpenRA.Mods.Common.Traits
public int TurnSpeed { get { return Info.TurnSpeed; } }
public Actor ReservedActor { get; private set; }
public bool MayYieldReservation { get; private set; }
public bool ForceLanding { get; private set; }
bool airborne;
bool cruising;
@@ -152,6 +157,7 @@ namespace OpenRA.Mods.Common.Traits
bool isMoving;
bool isMovingVertically;
WPos cachedPosition;
bool? landNow;
public Aircraft(ActorInitializer init, AircraftInfo info)
{
@@ -171,6 +177,17 @@ namespace OpenRA.Mods.Common.Traits
IsPlane = !info.CanHover;
}
public virtual IEnumerable<VariableObserver> GetVariableObservers()
{
if (Info.LandOnCondition != null)
yield return new VariableObserver(ForceLandConditionChanged, Info.LandOnCondition.Variables);
}
void ForceLandConditionChanged(Actor self, IReadOnlyDictionary<string, int> variables)
{
landNow = Info.LandOnCondition.Evaluate(variables);
}
public void Created(Actor self)
{
conditionManager = self.TraitOrDefault<ConditionManager>();
@@ -208,6 +225,33 @@ namespace OpenRA.Mods.Common.Traits
self.QueueActivity(new TakeOff(self));
}
// Add land activity if LandOnCondidion resolves to true and the actor can land at the current location.
if (landNow.HasValue && landNow.Value && airborne && CanLand(self.Location)
&& !(self.CurrentActivity is HeliLand || self.CurrentActivity is Turn))
{
self.CancelActivity();
if (Info.TurnToLand)
self.QueueActivity(new Turn(self, Info.InitialFacing));
self.QueueActivity(new HeliLand(self, true));
ForceLanding = true;
}
// Add takeoff activity if LandOnCondidion resolves to false and the actor should not land when idle.
if (landNow.HasValue && !landNow.Value && !cruising && !(self.CurrentActivity is TakeOff))
{
ForceLanding = false;
if (!Info.LandWhenIdle)
{
self.CancelActivity();
self.QueueActivity(new TakeOff(self));
}
}
var oldCachedPosition = cachedPosition;
cachedPosition = self.CenterPosition;
isMoving = (oldCachedPosition - cachedPosition).HorizontalLengthSquared != 0;