Require force move for all undeploy-triggering orders.
This commit is contained in:
@@ -1,57 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2019 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, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Orders
|
||||
{
|
||||
public class AircraftMoveOrderTargeter : IOrderTargeter
|
||||
{
|
||||
public string OrderID { get; protected set; }
|
||||
public int OrderPriority { get; protected set; }
|
||||
public bool TargetOverridesSelection(TargetModifiers modifiers)
|
||||
{
|
||||
return modifiers.HasModifier(TargetModifiers.ForceMove);
|
||||
}
|
||||
|
||||
readonly AircraftInfo info;
|
||||
|
||||
public AircraftMoveOrderTargeter(AircraftInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
OrderID = "Move";
|
||||
OrderPriority = 4;
|
||||
}
|
||||
|
||||
public virtual bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref 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; }
|
||||
}
|
||||
}
|
||||
@@ -16,11 +16,11 @@ namespace OpenRA.Mods.Common.Orders
|
||||
{
|
||||
public class EnterAlliedActorTargeter<T> : UnitOrderTargeter where T : ITraitInfo
|
||||
{
|
||||
readonly Func<Actor, bool> canTarget;
|
||||
readonly Func<Actor, TargetModifiers, bool> canTarget;
|
||||
readonly Func<Actor, bool> useEnterCursor;
|
||||
|
||||
public EnterAlliedActorTargeter(string order, int priority,
|
||||
Func<Actor, bool> canTarget, Func<Actor, bool> useEnterCursor)
|
||||
Func<Actor, TargetModifiers, bool> canTarget, Func<Actor, bool> useEnterCursor)
|
||||
: base(order, priority, "enter", false, true)
|
||||
{
|
||||
this.canTarget = canTarget;
|
||||
@@ -29,7 +29,7 @@ namespace OpenRA.Mods.Common.Orders
|
||||
|
||||
public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor)
|
||||
{
|
||||
if (!self.Owner.IsAlliedWith(target.Owner) || !target.Info.HasTraitInfo<T>() || !canTarget(target))
|
||||
if (!self.Owner.IsAlliedWith(target.Owner) || !target.Info.HasTraitInfo<T>() || !canTarget(target, modifiers))
|
||||
return false;
|
||||
|
||||
cursor = useEnterCursor(target) ? "enter" : "enter-blocked";
|
||||
|
||||
@@ -22,7 +22,7 @@ using OpenRA.Traits;
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
public class AircraftInfo : ITraitInfo, IPositionableInfo, IFacingInfo, IMoveInfo, ICruiseAltitudeInfo,
|
||||
IActorPreviewInitInfo, IEditorActorOptions
|
||||
IActorPreviewInitInfo, IEditorActorOptions, IObservesVariablesInfo
|
||||
{
|
||||
public readonly WDist CruiseAltitude = new WDist(1280);
|
||||
|
||||
@@ -120,6 +120,10 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("Display order for the facing slider in the map editor")]
|
||||
public readonly int EditorFacingDisplayOrder = 3;
|
||||
|
||||
[ConsumedConditionReference]
|
||||
[Desc("Boolean expression defining the condition under which the regular (non-force) move cursor is disabled.")]
|
||||
public readonly BooleanExpression RequireForceMoveCondition = null;
|
||||
|
||||
public int GetInitialFacing() { return InitialFacing; }
|
||||
public WDist GetCruiseAltitude() { return CruiseAltitude; }
|
||||
|
||||
@@ -197,6 +201,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public bool MayYieldReservation { get; private set; }
|
||||
public bool ForceLanding { get; private set; }
|
||||
CPos? landingCell;
|
||||
bool requireForceMove;
|
||||
|
||||
public WDist LandAltitude { get; private set; }
|
||||
|
||||
@@ -245,6 +250,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
if (Info.LandOnCondition != null)
|
||||
yield return new VariableObserver(ForceLandConditionChanged, Info.LandOnCondition.Variables);
|
||||
|
||||
if (Info.RequireForceMoveCondition != null)
|
||||
yield return new VariableObserver(RequireForceMoveConditionChanged, Info.RequireForceMoveCondition.Variables);
|
||||
}
|
||||
|
||||
void ForceLandConditionChanged(Actor self, IReadOnlyDictionary<string, int> variables)
|
||||
@@ -252,6 +260,11 @@ namespace OpenRA.Mods.Common.Traits
|
||||
landNow = Info.LandOnCondition.Evaluate(variables);
|
||||
}
|
||||
|
||||
void RequireForceMoveConditionChanged(Actor self, IReadOnlyDictionary<string, int> conditions)
|
||||
{
|
||||
requireForceMove = Info.RequireForceMoveCondition.Evaluate(conditions);
|
||||
}
|
||||
|
||||
void INotifyCreated.Created(Actor self)
|
||||
{
|
||||
Created(self);
|
||||
@@ -508,6 +521,14 @@ namespace OpenRA.Mods.Common.Traits
|
||||
self.QueueActivity(new TakeOff(self));
|
||||
}
|
||||
|
||||
bool AircraftCanEnter(Actor a, TargetModifiers modifiers)
|
||||
{
|
||||
if (requireForceMove && !modifiers.HasModifier(TargetModifiers.ForceMove))
|
||||
return false;
|
||||
|
||||
return AircraftCanEnter(a);
|
||||
}
|
||||
|
||||
public bool AircraftCanEnter(Actor a)
|
||||
{
|
||||
if (self.AppearsHostileTo(a))
|
||||
@@ -854,9 +875,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
get
|
||||
{
|
||||
yield return new EnterAlliedActorTargeter<BuildingInfo>("Enter", 5,
|
||||
target => AircraftCanEnter(target), target => Reservable.IsAvailableFor(target, self));
|
||||
AircraftCanEnter, target => Reservable.IsAvailableFor(target, self));
|
||||
|
||||
yield return new AircraftMoveOrderTargeter(Info);
|
||||
yield return new AircraftMoveOrderTargeter(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1038,5 +1059,43 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (!inits.Contains<DynamicFacingInit>() && !inits.Contains<FacingInit>())
|
||||
inits.Add(new DynamicFacingInit(() => Facing));
|
||||
}
|
||||
|
||||
public class AircraftMoveOrderTargeter : IOrderTargeter
|
||||
{
|
||||
readonly Aircraft aircraft;
|
||||
|
||||
public string OrderID { get { return "Move"; } }
|
||||
public int OrderPriority { get { return 4; } }
|
||||
public bool IsQueued { get; protected set; }
|
||||
|
||||
public AircraftMoveOrderTargeter(Aircraft aircraft)
|
||||
{
|
||||
this.aircraft = aircraft;
|
||||
}
|
||||
|
||||
public bool TargetOverridesSelection(TargetModifiers modifiers)
|
||||
{
|
||||
return modifiers.HasModifier(TargetModifiers.ForceMove);
|
||||
}
|
||||
|
||||
public virtual bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor)
|
||||
{
|
||||
if (target.Type != TargetType.Terrain || (aircraft.requireForceMove && !modifiers.HasModifier(TargetModifiers.ForceMove)))
|
||||
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 && !aircraft.Info.MoveIntoShroud)
|
||||
cursor = "move-blocked";
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[VoiceReference]
|
||||
public readonly string Voice = "Action";
|
||||
|
||||
[Desc("Require the force-move modifier to display the move cursor.")]
|
||||
public readonly bool RequiresForceMove = false;
|
||||
|
||||
public override object Create(ActorInitializer init) { return new TransformsIntoAircraft(init, this); }
|
||||
}
|
||||
|
||||
@@ -66,6 +69,14 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
}
|
||||
|
||||
public bool AircraftCanEnter(Actor a, TargetModifiers modifiers)
|
||||
{
|
||||
if (Info.RequiresForceMove && !modifiers.HasModifier(TargetModifiers.ForceMove))
|
||||
return false;
|
||||
|
||||
return AircraftCanEnter(a);
|
||||
}
|
||||
|
||||
public bool AircraftCanEnter(Actor a)
|
||||
{
|
||||
return !self.AppearsHostileTo(a) && Info.DockActors.Contains(a.Info.Name);
|
||||
|
||||
@@ -29,6 +29,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[VoiceReference]
|
||||
public readonly string Voice = "Action";
|
||||
|
||||
[Desc("Require the force-move modifier to display the enter cursor.")]
|
||||
public readonly bool RequiresForceMove = false;
|
||||
|
||||
public override object Create(ActorInitializer init) { return new TransformsIntoEntersTunnels(this); }
|
||||
}
|
||||
|
||||
@@ -50,7 +53,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
get
|
||||
{
|
||||
if (!IsTraitDisabled)
|
||||
yield return new EntersTunnels.EnterTunnelOrderTargeter(Info.EnterCursor, Info.EnterBlockedCursor);
|
||||
yield return new EntersTunnels.EnterTunnelOrderTargeter(Info.EnterCursor, Info.EnterBlockedCursor, () => Info.RequiresForceMove);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[VoiceReference]
|
||||
public readonly string Voice = "Action";
|
||||
|
||||
[Desc("Require the force-move modifier to display the enter cursor.")]
|
||||
public readonly bool RequiresForceMove = false;
|
||||
|
||||
public override object Create(ActorInitializer init) { return new TransformsIntoPassenger(this); }
|
||||
}
|
||||
|
||||
@@ -62,6 +65,14 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return null;
|
||||
}
|
||||
|
||||
bool IsCorrectCargoType(Actor target, TargetModifiers modifiers)
|
||||
{
|
||||
if (Info.RequiresForceMove && !modifiers.HasModifier(TargetModifiers.ForceMove))
|
||||
return false;
|
||||
|
||||
return IsCorrectCargoType(target);
|
||||
}
|
||||
|
||||
bool IsCorrectCargoType(Actor target)
|
||||
{
|
||||
var ci = target.Info.TraitInfo<CargoInfo>();
|
||||
|
||||
@@ -30,6 +30,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[VoiceReference]
|
||||
public readonly string Voice = "Action";
|
||||
|
||||
[Desc("Require the force-move modifier to display the enter cursor.")]
|
||||
public readonly bool RequiresForceMove = false;
|
||||
|
||||
public override object Create(ActorInitializer init) { return new TransformsIntoRepairable(this); }
|
||||
}
|
||||
|
||||
@@ -62,6 +65,14 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return health.DamageState > DamageState.Undamaged && transforms.Any(t => !t.IsTraitDisabled && !t.IsTraitPaused);
|
||||
}
|
||||
|
||||
bool CanRepairAt(Actor target, TargetModifiers modifiers)
|
||||
{
|
||||
if (Info.RequiresForceMove && !modifiers.HasModifier(TargetModifiers.ForceMove))
|
||||
return false;
|
||||
|
||||
return CanRepairAt(target);
|
||||
}
|
||||
|
||||
bool CanRepairAt(Actor target)
|
||||
{
|
||||
return Info.RepairActors.Contains(target.Info.Name);
|
||||
|
||||
@@ -257,7 +257,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
yield return new CarryallPickupOrderTargeter();
|
||||
yield return new DeployOrderTargeter("Unload", 10,
|
||||
() => CanUnload() ? Info.UnloadCursor : Info.UnloadBlockedCursor);
|
||||
yield return new CarryallDeliverUnitTargeter(aircraftInfo, Info, CarryableOffset);
|
||||
yield return new CarryallDeliverUnitTargeter(aircraftInfo, Info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,23 +355,23 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
}
|
||||
|
||||
class CarryallDeliverUnitTargeter : AircraftMoveOrderTargeter
|
||||
class CarryallDeliverUnitTargeter : IOrderTargeter
|
||||
{
|
||||
readonly AircraftInfo aircraftInfo;
|
||||
readonly CarryallInfo info;
|
||||
readonly WVec carryableOffset;
|
||||
|
||||
public CarryallDeliverUnitTargeter(AircraftInfo aircraftInfo, CarryallInfo info, WVec carryableOffset)
|
||||
: base(aircraftInfo)
|
||||
public string OrderID { get { return "DeliverUnit"; } }
|
||||
public int OrderPriority { get { return 6; } }
|
||||
public bool IsQueued { get; protected set; }
|
||||
public bool TargetOverridesSelection(TargetModifiers modifiers) { return true; }
|
||||
|
||||
public CarryallDeliverUnitTargeter(AircraftInfo aircraftInfo, CarryallInfo info)
|
||||
{
|
||||
OrderID = "DeliverUnit";
|
||||
OrderPriority = 6;
|
||||
this.carryableOffset = carryableOffset;
|
||||
this.aircraftInfo = aircraftInfo;
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public override bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor)
|
||||
public bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor)
|
||||
{
|
||||
if (!info.AllowDropOff || !modifiers.HasModifier(TargetModifiers.ForceMove))
|
||||
return false;
|
||||
|
||||
@@ -9,16 +9,18 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.Common.Orders;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("This actor can interact with TunnelEntrances to move through TerrainTunnels.")]
|
||||
public class EntersTunnelsInfo : ITraitInfo, Requires<IMoveInfo>
|
||||
public class EntersTunnelsInfo : ITraitInfo, Requires<IMoveInfo>, IObservesVariablesInfo
|
||||
{
|
||||
public readonly string EnterCursor = "enter";
|
||||
public readonly string EnterBlockedCursor = "enter-blocked";
|
||||
@@ -26,13 +28,18 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[VoiceReference]
|
||||
public readonly string Voice = "Action";
|
||||
|
||||
[ConsumedConditionReference]
|
||||
[Desc("Boolean expression defining the condition under which the regular (non-force) enter cursor is disabled.")]
|
||||
public readonly BooleanExpression RequireForceMoveCondition = null;
|
||||
|
||||
public object Create(ActorInitializer init) { return new EntersTunnels(init.Self, this); }
|
||||
}
|
||||
|
||||
public class EntersTunnels : IIssueOrder, IResolveOrder, IOrderVoice
|
||||
public class EntersTunnels : IIssueOrder, IResolveOrder, IOrderVoice, IObservesVariables
|
||||
{
|
||||
readonly EntersTunnelsInfo info;
|
||||
readonly IMove move;
|
||||
bool requireForceMove;
|
||||
|
||||
public EntersTunnels(Actor self, EntersTunnelsInfo info)
|
||||
{
|
||||
@@ -44,7 +51,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return new EnterTunnelOrderTargeter(info.EnterCursor, info.EnterBlockedCursor);
|
||||
yield return new EnterTunnelOrderTargeter(info.EnterCursor, info.EnterBlockedCursor, () => requireForceMove);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,21 +85,34 @@ namespace OpenRA.Mods.Common.Traits
|
||||
self.QueueActivity(move.MoveTo(tunnel.Exit.Value, tunnel.NearEnough));
|
||||
}
|
||||
|
||||
IEnumerable<VariableObserver> IObservesVariables.GetVariableObservers()
|
||||
{
|
||||
if (info.RequireForceMoveCondition != null)
|
||||
yield return new VariableObserver(RequireForceMoveConditionChanged, info.RequireForceMoveCondition.Variables);
|
||||
}
|
||||
|
||||
void RequireForceMoveConditionChanged(Actor self, IReadOnlyDictionary<string, int> conditions)
|
||||
{
|
||||
requireForceMove = info.RequireForceMoveCondition.Evaluate(conditions);
|
||||
}
|
||||
|
||||
public class EnterTunnelOrderTargeter : UnitOrderTargeter
|
||||
{
|
||||
readonly string enterCursor;
|
||||
readonly string enterBlockedCursor;
|
||||
readonly Func<bool> requireForceMove;
|
||||
|
||||
public EnterTunnelOrderTargeter(string enterCursor, string enterBlockedCursor)
|
||||
public EnterTunnelOrderTargeter(string enterCursor, string enterBlockedCursor, Func<bool> requireForceMove)
|
||||
: base("EnterTunnel", 6, enterCursor, true, true)
|
||||
{
|
||||
this.enterCursor = enterCursor;
|
||||
this.enterBlockedCursor = enterBlockedCursor;
|
||||
this.requireForceMove = requireForceMove;
|
||||
}
|
||||
|
||||
public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor)
|
||||
{
|
||||
if (target == null || target.IsDead)
|
||||
if (target == null || target.IsDead || (requireForceMove() && !modifiers.HasModifier(TargetModifiers.ForceMove)))
|
||||
return false;
|
||||
|
||||
var tunnel = target.TraitOrDefault<TunnelEntrance>();
|
||||
|
||||
@@ -299,7 +299,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
get
|
||||
{
|
||||
yield return new EnterAlliedActorTargeter<IAcceptResourcesInfo>("Deliver", 5,
|
||||
proc => IsAcceptableProcType(proc),
|
||||
(proc, _) => IsAcceptableProcType(proc),
|
||||
proc => proc.Trait<IAcceptResources>().AllowDocking);
|
||||
yield return new HarvestOrderTargeter();
|
||||
}
|
||||
|
||||
@@ -14,12 +14,13 @@ using System.Collections.Generic;
|
||||
using OpenRA.Mods.Common.Activities;
|
||||
using OpenRA.Mods.Common.Orders;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("This actor can enter Cargo actors.")]
|
||||
public class PassengerInfo : ITraitInfo
|
||||
public class PassengerInfo : ITraitInfo, IObservesVariablesInfo
|
||||
{
|
||||
public readonly string CargoType = null;
|
||||
public readonly PipType PipType = PipType.Green;
|
||||
@@ -39,13 +40,18 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[VoiceReference]
|
||||
public readonly string Voice = "Action";
|
||||
|
||||
[ConsumedConditionReference]
|
||||
[Desc("Boolean expression defining the condition under which the regular (non-force) enter cursor is disabled.")]
|
||||
public readonly BooleanExpression RequireForceMoveCondition = null;
|
||||
|
||||
public object Create(ActorInitializer init) { return new Passenger(this); }
|
||||
}
|
||||
|
||||
public class Passenger : INotifyCreated, IIssueOrder, IResolveOrder, IOrderVoice, INotifyRemovedFromWorld, INotifyEnteredCargo, INotifyExitedCargo, INotifyKilled
|
||||
public class Passenger : INotifyCreated, IIssueOrder, IResolveOrder, IOrderVoice, INotifyRemovedFromWorld, INotifyEnteredCargo, INotifyExitedCargo, INotifyKilled, IObservesVariables
|
||||
{
|
||||
public readonly PassengerInfo Info;
|
||||
public Actor Transport;
|
||||
bool requireForceMove;
|
||||
|
||||
ConditionManager conditionManager;
|
||||
int anyCargoToken = ConditionManager.InvalidConditionToken;
|
||||
@@ -79,6 +85,14 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return null;
|
||||
}
|
||||
|
||||
bool IsCorrectCargoType(Actor target, TargetModifiers modifiers)
|
||||
{
|
||||
if (requireForceMove && !modifiers.HasModifier(TargetModifiers.ForceMove))
|
||||
return false;
|
||||
|
||||
return IsCorrectCargoType(target);
|
||||
}
|
||||
|
||||
bool IsCorrectCargoType(Actor target)
|
||||
{
|
||||
var ci = target.Info.TraitInfo<CargoInfo>();
|
||||
@@ -128,7 +142,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
specificCargoToken = conditionManager.RevokeCondition(self, specificCargoToken);
|
||||
}
|
||||
|
||||
public void ResolveOrder(Actor self, Order order)
|
||||
void IResolveOrder.ResolveOrder(Actor self, Order order)
|
||||
{
|
||||
if (order.OrderString != "EnterTransport")
|
||||
return;
|
||||
@@ -180,5 +194,16 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (!Transport.IsDead)
|
||||
Transport.Trait<Cargo>().Unload(Transport, self);
|
||||
}
|
||||
|
||||
IEnumerable<VariableObserver> IObservesVariables.GetVariableObservers()
|
||||
{
|
||||
if (Info.RequireForceMoveCondition != null)
|
||||
yield return new VariableObserver(RequireForceMoveConditionChanged, Info.RequireForceMoveCondition.Variables);
|
||||
}
|
||||
|
||||
void RequireForceMoveConditionChanged(Actor self, IReadOnlyDictionary<string, int> conditions)
|
||||
{
|
||||
requireForceMove = Info.RequireForceMoveCondition.Evaluate(conditions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,13 @@ 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
|
||||
{
|
||||
[Desc("This actor can be sent to a structure for repairs.")]
|
||||
public class RepairableInfo : ITraitInfo, Requires<IHealthInfo>, Requires<IMoveInfo>
|
||||
public class RepairableInfo : ITraitInfo, Requires<IHealthInfo>, Requires<IMoveInfo>, IObservesVariablesInfo
|
||||
{
|
||||
[ActorReference]
|
||||
[FieldLoader.Require]
|
||||
@@ -32,15 +33,20 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("The amount the unit will be repaired at each step. Use -1 for fallback behavior where HpPerStep from RepairsUnits trait will be used.")]
|
||||
public readonly int HpPerStep = -1;
|
||||
|
||||
[ConsumedConditionReference]
|
||||
[Desc("Boolean expression defining the condition under which the regular (non-force) enter cursor is disabled.")]
|
||||
public readonly BooleanExpression RequireForceMoveCondition = null;
|
||||
|
||||
public virtual object Create(ActorInitializer init) { return new Repairable(init.Self, this); }
|
||||
}
|
||||
|
||||
public class Repairable : IIssueOrder, IResolveOrder, IOrderVoice, INotifyCreated
|
||||
public class Repairable : IIssueOrder, IResolveOrder, IOrderVoice, INotifyCreated, IObservesVariables
|
||||
{
|
||||
public readonly RepairableInfo Info;
|
||||
readonly IHealth health;
|
||||
readonly IMove movement;
|
||||
Rearmable rearmable;
|
||||
bool requireForceMove;
|
||||
|
||||
public Repairable(Actor self, RepairableInfo info)
|
||||
{
|
||||
@@ -75,9 +81,12 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return Info.RepairActors.Contains(target.Info.Name);
|
||||
}
|
||||
|
||||
bool CanRearmAt(Actor target)
|
||||
bool CanRepairAt(Actor target, TargetModifiers modifiers)
|
||||
{
|
||||
return rearmable != null && rearmable.Info.RearmActors.Contains(target.Info.Name);
|
||||
if (requireForceMove && !modifiers.HasModifier(TargetModifiers.ForceMove))
|
||||
return false;
|
||||
|
||||
return Info.RepairActors.Contains(target.Info.Name);
|
||||
}
|
||||
|
||||
bool CanRepair()
|
||||
@@ -95,7 +104,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return order.OrderString == "Repair" && (CanRepair() || CanRearm()) ? Info.Voice : null;
|
||||
}
|
||||
|
||||
public void ResolveOrder(Actor self, Order order)
|
||||
void IResolveOrder.ResolveOrder(Actor self, Order order)
|
||||
{
|
||||
if (order.OrderString == "Repair")
|
||||
{
|
||||
@@ -174,5 +183,16 @@ namespace OpenRA.Mods.Common.Traits
|
||||
foreach (var t in transports)
|
||||
t.RequestTransport(self, targetCell, nextActivity);
|
||||
}
|
||||
|
||||
IEnumerable<VariableObserver> IObservesVariables.GetVariableObservers()
|
||||
{
|
||||
if (Info.RequireForceMoveCondition != null)
|
||||
yield return new VariableObserver(RequireForceMoveConditionChanged, Info.RequireForceMoveCondition.Variables);
|
||||
}
|
||||
|
||||
void RequireForceMoveConditionChanged(Actor self, IReadOnlyDictionary<string, int> conditions)
|
||||
{
|
||||
requireForceMove = Info.RequireForceMoveCondition.Evaluate(conditions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,12 @@ using System.Linq;
|
||||
using OpenRA.Mods.Common.Activities;
|
||||
using OpenRA.Mods.Common.Orders;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
class RepairableNearInfo : ITraitInfo, Requires<IHealthInfo>, Requires<IMoveInfo>
|
||||
class RepairableNearInfo : ITraitInfo, Requires<IHealthInfo>, Requires<IMoveInfo>, IObservesVariablesInfo
|
||||
{
|
||||
[ActorReference]
|
||||
[FieldLoader.Require]
|
||||
@@ -29,14 +30,19 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[VoiceReference]
|
||||
public readonly string Voice = "Action";
|
||||
|
||||
[ConsumedConditionReference]
|
||||
[Desc("Boolean expression defining the condition under which the regular (non-force) enter cursor is disabled.")]
|
||||
public readonly BooleanExpression RequireForceMoveCondition = null;
|
||||
|
||||
public object Create(ActorInitializer init) { return new RepairableNear(init.Self, this); }
|
||||
}
|
||||
|
||||
class RepairableNear : IIssueOrder, IResolveOrder, IOrderVoice
|
||||
class RepairableNear : IIssueOrder, IResolveOrder, IOrderVoice, IObservesVariables
|
||||
{
|
||||
public readonly RepairableNearInfo Info;
|
||||
readonly Actor self;
|
||||
readonly IMove movement;
|
||||
bool requireForceMove;
|
||||
|
||||
public RepairableNear(Actor self, RepairableNearInfo info)
|
||||
{
|
||||
@@ -50,7 +56,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
get
|
||||
{
|
||||
yield return new EnterAlliedActorTargeter<BuildingInfo>("RepairNear", 5,
|
||||
target => CanRepairAt(target), _ => ShouldRepair());
|
||||
CanRepairAt, _ => ShouldRepair());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +68,14 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return null;
|
||||
}
|
||||
|
||||
bool CanRepairAt(Actor target, TargetModifiers modifiers)
|
||||
{
|
||||
if (requireForceMove && !modifiers.HasModifier(TargetModifiers.ForceMove))
|
||||
return false;
|
||||
|
||||
return Info.RepairActors.Contains(target.Info.Name);
|
||||
}
|
||||
|
||||
bool CanRepairAt(Actor target)
|
||||
{
|
||||
return Info.RepairActors.Contains(target.Info.Name);
|
||||
@@ -108,5 +122,16 @@ namespace OpenRA.Mods.Common.Traits
|
||||
// Worst case FirstOrDefault() will return a TraitPair<null, null>, which is OK.
|
||||
return repairBuilding.FirstOrDefault().Actor;
|
||||
}
|
||||
|
||||
IEnumerable<VariableObserver> IObservesVariables.GetVariableObservers()
|
||||
{
|
||||
if (Info.RequireForceMoveCondition != null)
|
||||
yield return new VariableObserver(RequireForceMoveConditionChanged, Info.RequireForceMoveCondition.Variables);
|
||||
}
|
||||
|
||||
void RequireForceMoveConditionChanged(Actor self, IReadOnlyDictionary<string, int> conditions)
|
||||
{
|
||||
requireForceMove = Info.RequireForceMoveCondition.Evaluate(conditions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,9 +32,11 @@ FACT:
|
||||
TransformsIntoPassenger:
|
||||
RequiresCondition: factundeploy
|
||||
CargoType: Vehicle
|
||||
RequiresForceMove: true
|
||||
TransformsIntoRepairable:
|
||||
RequiresCondition: factundeploy
|
||||
RepairActors: fix
|
||||
RequiresForceMove: true
|
||||
GrantConditionOnPrerequisite@GLOBALFACTUNDEPLOY:
|
||||
Condition: factundeploy
|
||||
Prerequisites: global-factundeploy
|
||||
|
||||
@@ -1149,9 +1149,11 @@ FACT:
|
||||
TransformsIntoPassenger:
|
||||
RequiresCondition: factundeploy
|
||||
CargoType: Vehicle
|
||||
RequiresForceMove: true
|
||||
TransformsIntoRepairable:
|
||||
RequiresCondition: factundeploy
|
||||
RepairActors: fix
|
||||
RequiresForceMove: true
|
||||
Sellable:
|
||||
RequiresCondition: !build-incomplete && !chrono-vortex && !being-captured && !being-demolished
|
||||
GrantConditionOnPrerequisite@GLOBALFACTUNDEPLOY:
|
||||
|
||||
@@ -358,6 +358,12 @@ JUGG:
|
||||
DeploySounds: place2.aud
|
||||
UndeploySounds: clicky1.aud
|
||||
Voice: Move
|
||||
EntersTunnels:
|
||||
RequireForceMoveCondition: !undeployed
|
||||
Repairable:
|
||||
RequireForceMoveCondition: !undeployed
|
||||
Passenger:
|
||||
RequireForceMoveCondition: !undeployed
|
||||
GrantCondition@PREVIEWWORKAROUND:
|
||||
Condition: real-actor
|
||||
QuantizeFacingsFromSequence:
|
||||
|
||||
@@ -141,6 +141,12 @@ TTNK:
|
||||
DeploySounds: place2.aud
|
||||
UndeploySounds: clicky1.aud
|
||||
Voice: Move
|
||||
EntersTunnels:
|
||||
RequireForceMoveCondition: !undeployed
|
||||
Repairable:
|
||||
RequireForceMoveCondition: !undeployed
|
||||
Passenger:
|
||||
RequireForceMoveCondition: !undeployed
|
||||
GrantCondition@PREVIEWWORKAROUND:
|
||||
Condition: real-actor
|
||||
WithVoxelBody:
|
||||
@@ -249,6 +255,12 @@ ART2:
|
||||
DeploySounds: place2.aud
|
||||
UndeploySounds: clicky1.aud
|
||||
Voice: Move
|
||||
EntersTunnels:
|
||||
RequireForceMoveCondition: !undeployed
|
||||
Repairable:
|
||||
RequireForceMoveCondition: !undeployed
|
||||
Passenger:
|
||||
RequireForceMoveCondition: !undeployed
|
||||
GrantCondition@PREVIEWWORKAROUND:
|
||||
Condition: real-actor
|
||||
WithVoxelBody:
|
||||
|
||||
@@ -43,13 +43,16 @@ GACNST:
|
||||
RequiresCondition: factundeploy
|
||||
RepairActors: gadept
|
||||
Voice: Move
|
||||
RequiresForceMove: true
|
||||
TransformsIntoEntersTunnels:
|
||||
RequiresCondition: factundeploy
|
||||
Voice: Move
|
||||
RequiresForceMove: true
|
||||
TransformsIntoPassenger:
|
||||
RequiresCondition: factundeploy
|
||||
CargoType: Vehicle
|
||||
Voice: Move
|
||||
RequiresForceMove: true
|
||||
GrantConditionOnPrerequisite@GLOBALFACTUNDEPLOY:
|
||||
Condition: factundeploy
|
||||
Prerequisites: global-factundeploy
|
||||
|
||||
@@ -154,6 +154,12 @@ LPST:
|
||||
DeploySounds: place2.aud
|
||||
UndeploySounds: clicky1.aud
|
||||
Voice: Move
|
||||
EntersTunnels:
|
||||
RequireForceMoveCondition: !undeployed
|
||||
Repairable:
|
||||
RequireForceMoveCondition: !undeployed
|
||||
Passenger:
|
||||
RequireForceMoveCondition: !undeployed
|
||||
WithVoxelBody:
|
||||
RequiresCondition: undeployed
|
||||
WithSpriteBody@deployed:
|
||||
|
||||
Reference in New Issue
Block a user