Add TransformsInto* traits to trigger construction yard undeploy.
This commit is contained in:
@@ -27,7 +27,7 @@ namespace OpenRA.Activities
|
|||||||
* Queue a new instance instead.
|
* Queue a new instance instead.
|
||||||
* - Avoid calling actor.CancelActivity(). It is almost always a bug. Call activity.Cancel() instead.
|
* - Avoid calling actor.CancelActivity(). It is almost always a bug. Call activity.Cancel() instead.
|
||||||
*/
|
*/
|
||||||
public abstract class Activity
|
public abstract class Activity : IActivityInterface
|
||||||
{
|
{
|
||||||
public ActivityState State { get; private set; }
|
public ActivityState State { get; private set; }
|
||||||
|
|
||||||
@@ -172,9 +172,9 @@ namespace OpenRA.Activities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<T> ActivitiesImplementing<T>() where T : IActivityInterface
|
public IEnumerable<T> ActivitiesImplementing<T>(bool includeChildren = true) where T : IActivityInterface
|
||||||
{
|
{
|
||||||
if (childActivity != null)
|
if (includeChildren && childActivity != null)
|
||||||
foreach (var a in childActivity.ActivitiesImplementing<T>())
|
foreach (var a in childActivity.ActivitiesImplementing<T>())
|
||||||
yield return a;
|
yield return a;
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
using OpenRA.Activities;
|
using OpenRA.Activities;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
using OpenRA.Mods.Common.Traits.Render;
|
using OpenRA.Mods.Common.Traits.Render;
|
||||||
@@ -87,6 +88,10 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
|
|
||||||
void DoTransform(Actor self)
|
void DoTransform(Actor self)
|
||||||
{
|
{
|
||||||
|
// This activity may be buried as a child within one or more parents
|
||||||
|
// We need to consider the top-level activities when transferring orders to the new actor!
|
||||||
|
var currentActivity = self.CurrentActivity;
|
||||||
|
|
||||||
self.World.AddFrameEndTask(w =>
|
self.World.AddFrameEndTask(w =>
|
||||||
{
|
{
|
||||||
if (self.IsDead || self.WillDispose)
|
if (self.IsDead || self.WillDispose)
|
||||||
@@ -132,6 +137,14 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
foreach (var nt in self.TraitsImplementing<INotifyTransform>())
|
foreach (var nt in self.TraitsImplementing<INotifyTransform>())
|
||||||
nt.AfterTransform(a);
|
nt.AfterTransform(a);
|
||||||
|
|
||||||
|
// Use self.CurrentActivity to capture the parent activity if Transform is a child
|
||||||
|
foreach (var transfer in currentActivity.ActivitiesImplementing<IssueOrderAfterTransform>(false))
|
||||||
|
{
|
||||||
|
var order = transfer.IssueOrderForTransformedActor(a);
|
||||||
|
foreach (var t in a.TraitsImplementing<IResolveOrder>())
|
||||||
|
t.ResolveOrder(a, order);
|
||||||
|
}
|
||||||
|
|
||||||
self.ReplacedByActor = a;
|
self.ReplacedByActor = a;
|
||||||
|
|
||||||
if (selected)
|
if (selected)
|
||||||
@@ -142,4 +155,27 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class IssueOrderAfterTransform : Activity
|
||||||
|
{
|
||||||
|
readonly string orderString;
|
||||||
|
readonly Target target;
|
||||||
|
|
||||||
|
public IssueOrderAfterTransform(string orderString, Target target)
|
||||||
|
{
|
||||||
|
this.orderString = orderString;
|
||||||
|
this.target = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Order IssueOrderForTransformedActor(Actor newActor)
|
||||||
|
{
|
||||||
|
return new Order(orderString, newActor, target, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Activity Tick(Actor self)
|
||||||
|
{
|
||||||
|
// Activity is a placeholder that should never run
|
||||||
|
return NextActivity;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
184
OpenRA.Mods.Common/Traits/Buildings/TransformsIntoAircraft.cs
Normal file
184
OpenRA.Mods.Common/Traits/Buildings/TransformsIntoAircraft.cs
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
#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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Activities;
|
||||||
|
using OpenRA.Mods.Common.Activities;
|
||||||
|
using OpenRA.Mods.Common.Orders;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Traits
|
||||||
|
{
|
||||||
|
[Desc("Add to a building to expose a move cursor that triggers Transforms and issues a move order to the transformed actor.")]
|
||||||
|
public class TransformsIntoAircraftInfo : ConditionalTraitInfo, Requires<TransformsInfo>
|
||||||
|
{
|
||||||
|
[Desc("Can the actor be ordered to move in to shroud?")]
|
||||||
|
public readonly bool MoveIntoShroud = true;
|
||||||
|
|
||||||
|
[ActorReference]
|
||||||
|
[FieldLoader.Require]
|
||||||
|
public readonly HashSet<string> DockActors = new HashSet<string> { };
|
||||||
|
|
||||||
|
[VoiceReference]
|
||||||
|
public readonly string Voice = "Action";
|
||||||
|
|
||||||
|
public override object Create(ActorInitializer init) { return new TransformsIntoAircraft(init, this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TransformsIntoAircraft : ConditionalTrait<TransformsIntoAircraftInfo>, IIssueOrder, IResolveOrder, IOrderVoice
|
||||||
|
{
|
||||||
|
readonly Actor self;
|
||||||
|
Transforms[] transforms;
|
||||||
|
|
||||||
|
public TransformsIntoAircraft(ActorInitializer init, TransformsIntoAircraftInfo info)
|
||||||
|
: base(info)
|
||||||
|
{
|
||||||
|
self = init.Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Created(Actor self)
|
||||||
|
{
|
||||||
|
transforms = self.TraitsImplementing<Transforms>().ToArray();
|
||||||
|
base.Created(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<IOrderTargeter> IIssueOrder.Orders
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!IsTraitDisabled)
|
||||||
|
{
|
||||||
|
yield return new EnterAlliedActorTargeter<BuildingInfo>("Enter", 5, AircraftCanEnter,
|
||||||
|
target => Reservable.IsAvailableFor(target, self));
|
||||||
|
yield return new AircraftMoveOrderTargeter(self, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AircraftCanEnter(Actor a)
|
||||||
|
{
|
||||||
|
return !self.AppearsHostileTo(a) && Info.DockActors.Contains(a.Info.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: Returns a valid order even if the unit can't move to the target
|
||||||
|
Order IIssueOrder.IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued)
|
||||||
|
{
|
||||||
|
if (order.OrderID == "Enter" || order.OrderID == "Move")
|
||||||
|
return new Order(order.OrderID, self, target, queued);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IResolveOrder.ResolveOrder(Actor self, Order order)
|
||||||
|
{
|
||||||
|
if (IsTraitDisabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (order.OrderString == "Move")
|
||||||
|
{
|
||||||
|
var cell = self.World.Map.Clamp(self.World.Map.CellContaining(order.Target.CenterPosition));
|
||||||
|
if (!Info.MoveIntoShroud && !self.Owner.Shroud.IsExplored(cell))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var target = Target.FromCell(self.World, cell);
|
||||||
|
|
||||||
|
self.SetTargetLine(target, Color.Green);
|
||||||
|
}
|
||||||
|
else if (order.OrderString == "Enter")
|
||||||
|
{
|
||||||
|
// Enter and Repair orders are only valid for own/allied actors,
|
||||||
|
// which are guaranteed to never be frozen.
|
||||||
|
if (order.Target.Type != TargetType.Actor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var targetActor = order.Target.Actor;
|
||||||
|
|
||||||
|
// We only want to set a target line if the order will (most likely) succeed
|
||||||
|
if (Reservable.IsAvailableFor(targetActor, self))
|
||||||
|
self.SetTargetLine(Target.FromActor(targetActor), Color.Green);
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentTransform = self.CurrentActivity as Transform;
|
||||||
|
var transform = transforms.FirstOrDefault(t => !t.IsTraitDisabled && !t.IsTraitPaused);
|
||||||
|
if (transform == null && currentTransform == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var activity = currentTransform ?? transform.GetTransformActivity(self);
|
||||||
|
activity.Queue(self, new IssueOrderAfterTransform(order.OrderString, order.Target));
|
||||||
|
|
||||||
|
if (currentTransform == null)
|
||||||
|
self.QueueActivity(order.Queued, activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
string IOrderVoice.VoicePhraseForOrder(Actor self, Order order)
|
||||||
|
{
|
||||||
|
if (IsTraitDisabled)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
switch (order.OrderString)
|
||||||
|
{
|
||||||
|
case "Move":
|
||||||
|
if (!Info.MoveIntoShroud && order.Target.Type != TargetType.Invalid)
|
||||||
|
{
|
||||||
|
var cell = self.World.Map.CellContaining(order.Target.CenterPosition);
|
||||||
|
if (!self.Owner.Shroud.IsExplored(cell))
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Info.Voice;
|
||||||
|
case "Enter":
|
||||||
|
return Info.Voice;
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AircraftMoveOrderTargeter : IOrderTargeter
|
||||||
|
{
|
||||||
|
readonly TransformsIntoAircraft aircraft;
|
||||||
|
|
||||||
|
public bool TargetOverridesSelection(TargetModifiers modifiers)
|
||||||
|
{
|
||||||
|
return modifiers.HasModifier(TargetModifiers.ForceMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AircraftMoveOrderTargeter(Actor self, TransformsIntoAircraft aircraft)
|
||||||
|
{
|
||||||
|
this.aircraft = aircraft;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string OrderID { get { return "Move"; } }
|
||||||
|
public int OrderPriority { get { return 4; } }
|
||||||
|
public bool IsQueued { get; protected set; }
|
||||||
|
|
||||||
|
public bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor)
|
||||||
|
{
|
||||||
|
if (target.Type != TargetType.Terrain || (aircraft.Info.RequiresForceMove && !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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
#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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Activities;
|
||||||
|
using OpenRA.Mods.Common.Activities;
|
||||||
|
using OpenRA.Mods.Common.Orders;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Traits
|
||||||
|
{
|
||||||
|
[Desc("Add to a building to expose a move cursor that triggers Transforms and issues an enter tunnel order to the transformed actor.")]
|
||||||
|
public class TransformsIntoEntersTunnelsInfo : ConditionalTraitInfo, Requires<TransformsInfo>
|
||||||
|
{
|
||||||
|
public readonly string EnterCursor = "enter";
|
||||||
|
public readonly string EnterBlockedCursor = "enter-blocked";
|
||||||
|
|
||||||
|
[VoiceReference]
|
||||||
|
public readonly string Voice = "Action";
|
||||||
|
|
||||||
|
public override object Create(ActorInitializer init) { return new TransformsIntoEntersTunnels(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TransformsIntoEntersTunnels : ConditionalTrait<TransformsIntoEntersTunnelsInfo>, IIssueOrder, IResolveOrder, IOrderVoice
|
||||||
|
{
|
||||||
|
Transforms[] transforms;
|
||||||
|
|
||||||
|
public TransformsIntoEntersTunnels(TransformsIntoEntersTunnelsInfo info)
|
||||||
|
: base(info) { }
|
||||||
|
|
||||||
|
protected override void Created(Actor self)
|
||||||
|
{
|
||||||
|
transforms = self.TraitsImplementing<Transforms>().ToArray();
|
||||||
|
base.Created(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<IOrderTargeter> IIssueOrder.Orders
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!IsTraitDisabled)
|
||||||
|
yield return new EntersTunnels.EnterTunnelOrderTargeter(Info.EnterCursor, Info.EnterBlockedCursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Order IIssueOrder.IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued)
|
||||||
|
{
|
||||||
|
if (order.OrderID == "EnterTunnel")
|
||||||
|
return new Order(order.OrderID, self, target, queued) { SuppressVisualFeedback = true };
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IResolveOrder.ResolveOrder(Actor self, Order order)
|
||||||
|
{
|
||||||
|
if (IsTraitDisabled || order.OrderString != "EnterTunnel" || order.Target.Type != TargetType.Actor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var tunnel = order.Target.Actor.TraitOrDefault<TunnelEntrance>();
|
||||||
|
if (tunnel == null || !tunnel.Exit.HasValue)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var currentTransform = self.CurrentActivity as Transform;
|
||||||
|
var transform = transforms.FirstOrDefault(t => !t.IsTraitDisabled && !t.IsTraitPaused);
|
||||||
|
if (transform == null && currentTransform == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
self.SetTargetLine(order.Target, Color.Green);
|
||||||
|
|
||||||
|
var activity = currentTransform ?? transform.GetTransformActivity(self);
|
||||||
|
activity.Queue(self, new IssueOrderAfterTransform(order.OrderString, order.Target));
|
||||||
|
|
||||||
|
if (currentTransform == null)
|
||||||
|
self.QueueActivity(order.Queued, activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
string IOrderVoice.VoicePhraseForOrder(Actor self, Order order)
|
||||||
|
{
|
||||||
|
return order.OrderString == "EnterTunnel" ? Info.Voice : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
192
OpenRA.Mods.Common/Traits/Buildings/TransformsIntoMobile.cs
Normal file
192
OpenRA.Mods.Common/Traits/Buildings/TransformsIntoMobile.cs
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
#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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Activities;
|
||||||
|
using OpenRA.Mods.Common.Activities;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Traits
|
||||||
|
{
|
||||||
|
[Desc("Add to a building to expose a move cursor that triggers Transforms and issues a move order to the transformed actor.")]
|
||||||
|
public class TransformsIntoMobileInfo : ConditionalTraitInfo, Requires<TransformsInfo>
|
||||||
|
{
|
||||||
|
[LocomotorReference]
|
||||||
|
[FieldLoader.Require]
|
||||||
|
[Desc("Locomotor used by the transformed actor. Must be defined on the World actor.")]
|
||||||
|
public readonly string Locomotor = null;
|
||||||
|
|
||||||
|
public readonly string Cursor = "move";
|
||||||
|
public readonly string BlockedCursor = "move-blocked";
|
||||||
|
|
||||||
|
[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 TransformsIntoMobile(init, this); }
|
||||||
|
|
||||||
|
public LocomotorInfo LocomotorInfo { get; private set; }
|
||||||
|
|
||||||
|
public override void RulesetLoaded(Ruleset rules, ActorInfo ai)
|
||||||
|
{
|
||||||
|
var locomotorInfos = rules.Actors["world"].TraitInfos<LocomotorInfo>();
|
||||||
|
LocomotorInfo = locomotorInfos.FirstOrDefault(li => li.Name == Locomotor);
|
||||||
|
if (LocomotorInfo == null)
|
||||||
|
throw new YamlException("A locomotor named '{0}' doesn't exist.".F(Locomotor));
|
||||||
|
else if (locomotorInfos.Count(li => li.Name == Locomotor) > 1)
|
||||||
|
throw new YamlException("There is more than one locomotor named '{0}'.".F(Locomotor));
|
||||||
|
|
||||||
|
base.RulesetLoaded(rules, ai);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TransformsIntoMobile : ConditionalTrait<TransformsIntoMobileInfo>, IIssueOrder, IResolveOrder, IOrderVoice
|
||||||
|
{
|
||||||
|
readonly Actor self;
|
||||||
|
Transforms[] transforms;
|
||||||
|
|
||||||
|
public TransformsIntoMobile(ActorInitializer init, TransformsIntoMobileInfo info)
|
||||||
|
: base(info)
|
||||||
|
{
|
||||||
|
self = init.Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Created(Actor self)
|
||||||
|
{
|
||||||
|
transforms = self.TraitsImplementing<Transforms>().ToArray();
|
||||||
|
base.Created(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<IOrderTargeter> IIssueOrder.Orders
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!IsTraitDisabled)
|
||||||
|
yield return new MoveOrderTargeter(self, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: Returns a valid order even if the unit can't move to the target
|
||||||
|
Order IIssueOrder.IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued)
|
||||||
|
{
|
||||||
|
if (order is MoveOrderTargeter)
|
||||||
|
return new Order("Move", self, target, queued);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IResolveOrder.ResolveOrder(Actor self, Order order)
|
||||||
|
{
|
||||||
|
if (IsTraitDisabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (order.OrderString == "Move")
|
||||||
|
{
|
||||||
|
var cell = self.World.Map.Clamp(this.self.World.Map.CellContaining(order.Target.CenterPosition));
|
||||||
|
if (!Info.LocomotorInfo.MoveIntoShroud && !self.Owner.Shroud.IsExplored(cell))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var currentTransform = self.CurrentActivity as Transform;
|
||||||
|
var transform = transforms.FirstOrDefault(t => !t.IsTraitDisabled && !t.IsTraitPaused);
|
||||||
|
if (transform == null && currentTransform == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
self.SetTargetLine(Target.FromCell(self.World, cell), Color.Green);
|
||||||
|
|
||||||
|
var activity = currentTransform ?? transform.GetTransformActivity(self);
|
||||||
|
activity.Queue(self, new IssueOrderAfterTransform("Move", order.Target));
|
||||||
|
|
||||||
|
if (currentTransform == null)
|
||||||
|
self.QueueActivity(order.Queued, activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (order.OrderString == "Stop")
|
||||||
|
self.CancelActivity();
|
||||||
|
}
|
||||||
|
|
||||||
|
string IOrderVoice.VoicePhraseForOrder(Actor self, Order order)
|
||||||
|
{
|
||||||
|
if (IsTraitDisabled)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
switch (order.OrderString)
|
||||||
|
{
|
||||||
|
case "Move":
|
||||||
|
if (!Info.LocomotorInfo.MoveIntoShroud && order.Target.Type != TargetType.Invalid)
|
||||||
|
{
|
||||||
|
var cell = self.World.Map.CellContaining(order.Target.CenterPosition);
|
||||||
|
if (!self.Owner.Shroud.IsExplored(cell))
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Info.Voice;
|
||||||
|
case "Stop":
|
||||||
|
return Info.Voice;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MoveOrderTargeter : IOrderTargeter
|
||||||
|
{
|
||||||
|
readonly TransformsIntoMobile mobile;
|
||||||
|
readonly bool rejectMove;
|
||||||
|
public bool TargetOverridesSelection(TargetModifiers modifiers)
|
||||||
|
{
|
||||||
|
return modifiers.HasModifier(TargetModifiers.ForceMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MoveOrderTargeter(Actor self, TransformsIntoMobile mobile)
|
||||||
|
{
|
||||||
|
this.mobile = mobile;
|
||||||
|
rejectMove = !self.AcceptsOrder("Move");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string OrderID { get { return "Move"; } }
|
||||||
|
public int OrderPriority { get { return 4; } }
|
||||||
|
public bool IsQueued { get; protected set; }
|
||||||
|
|
||||||
|
public bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor)
|
||||||
|
{
|
||||||
|
if (rejectMove || target.Type != TargetType.Terrain || (mobile.Info.RequiresForceMove && !modifiers.HasModifier(TargetModifiers.ForceMove)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var location = self.World.Map.CellContaining(target.CenterPosition);
|
||||||
|
IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue);
|
||||||
|
|
||||||
|
var explored = self.Owner.Shroud.IsExplored(location);
|
||||||
|
cursor = self.World.Map.Contains(location) ?
|
||||||
|
(self.World.Map.GetTerrainInfo(location).CustomCursor ?? mobile.Info.Cursor) : mobile.Info.BlockedCursor;
|
||||||
|
|
||||||
|
var locomotor = mobile.Info.LocomotorInfo;
|
||||||
|
if (!mobile.transforms.Any(t => !t.IsTraitDisabled && !t.IsTraitPaused)
|
||||||
|
|| (!explored && !locomotor.MoveIntoShroud)
|
||||||
|
|| (explored && !CanEnterCell(self.World, self, location)))
|
||||||
|
cursor = mobile.Info.BlockedCursor;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanEnterCell(World world, Actor self, CPos cell)
|
||||||
|
{
|
||||||
|
if (mobile.Info.LocomotorInfo.MovementCostForCell(world, cell) == int.MaxValue)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return mobile.Info.LocomotorInfo.CanMoveFreelyInto(world, self, cell, null, CellConditions.BlockedByMovers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
142
OpenRA.Mods.Common/Traits/Buildings/TransformsIntoPassenger.cs
Normal file
142
OpenRA.Mods.Common/Traits/Buildings/TransformsIntoPassenger.cs
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
#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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Activities;
|
||||||
|
using OpenRA.Mods.Common.Activities;
|
||||||
|
using OpenRA.Mods.Common.Orders;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Traits
|
||||||
|
{
|
||||||
|
[Desc("Add to a building to expose a move cursor that triggers Transforms and issues an EnterTransport order to the transformed actor.")]
|
||||||
|
public class TransformsIntoPassengerInfo : ConditionalTraitInfo, Requires<TransformsInfo>
|
||||||
|
{
|
||||||
|
public readonly string CargoType = null;
|
||||||
|
public readonly int Weight = 1;
|
||||||
|
|
||||||
|
[Desc("Use to set when to use alternate transports (Never, Force, Default, Always).",
|
||||||
|
"Force - use force move modifier (Alt) to enable.",
|
||||||
|
"Default - use force move modifier (Alt) to disable.")]
|
||||||
|
public readonly AlternateTransportsMode AlternateTransportsMode = AlternateTransportsMode.Force;
|
||||||
|
|
||||||
|
[VoiceReference]
|
||||||
|
public readonly string Voice = "Action";
|
||||||
|
|
||||||
|
public override object Create(ActorInitializer init) { return new TransformsIntoPassenger(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TransformsIntoPassenger : ConditionalTrait<TransformsIntoPassengerInfo>, IIssueOrder, IResolveOrder, IOrderVoice
|
||||||
|
{
|
||||||
|
readonly IOrderTargeter[] orders;
|
||||||
|
Transforms[] transforms;
|
||||||
|
|
||||||
|
public TransformsIntoPassenger(TransformsIntoPassengerInfo info)
|
||||||
|
: base(info)
|
||||||
|
{
|
||||||
|
Func<Actor, bool> canTarget = IsCorrectCargoType;
|
||||||
|
Func<Actor, bool> useEnterCursor = CanEnter;
|
||||||
|
orders = new EnterAlliedActorTargeter<CargoInfo>[]
|
||||||
|
{
|
||||||
|
new EnterTransportTargeter("EnterTransport", 5, canTarget, useEnterCursor, Info.AlternateTransportsMode),
|
||||||
|
new EnterTransportsTargeter("EnterTransports", 5, canTarget, useEnterCursor, Info.AlternateTransportsMode)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Created(Actor self)
|
||||||
|
{
|
||||||
|
transforms = self.TraitsImplementing<Transforms>().ToArray();
|
||||||
|
base.Created(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<IOrderTargeter> IIssueOrder.Orders
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return !IsTraitDisabled ? orders : Enumerable.Empty<IOrderTargeter>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Order IIssueOrder.IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued)
|
||||||
|
{
|
||||||
|
if (order.OrderID == "EnterTransport" || order.OrderID == "EnterTransports")
|
||||||
|
return new Order(order.OrderID, self, target, queued);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsCorrectCargoType(Actor target)
|
||||||
|
{
|
||||||
|
var ci = target.Info.TraitInfo<CargoInfo>();
|
||||||
|
return ci.Types.Contains(Info.CargoType);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanEnter(Actor target)
|
||||||
|
{
|
||||||
|
if (!transforms.Any(t => !t.IsTraitDisabled && !t.IsTraitPaused))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var cargo = target.TraitOrDefault<Cargo>();
|
||||||
|
return cargo != null && cargo.HasSpace(Info.Weight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IResolveOrder.ResolveOrder(Actor self, Order order)
|
||||||
|
{
|
||||||
|
if (IsTraitDisabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (order.OrderString != "EnterTransport" && order.OrderString != "EnterTransports")
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Enter orders are only valid for own/allied actors,
|
||||||
|
// which are guaranteed to never be frozen.
|
||||||
|
if (order.Target.Type != TargetType.Actor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var targetActor = order.Target.Actor;
|
||||||
|
if (!CanEnter(targetActor))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!IsCorrectCargoType(targetActor))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var currentTransform = self.CurrentActivity as Transform;
|
||||||
|
var transform = transforms.FirstOrDefault(t => !t.IsTraitDisabled && !t.IsTraitPaused);
|
||||||
|
if (transform == null && currentTransform == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
self.SetTargetLine(order.Target, Color.Green);
|
||||||
|
|
||||||
|
var activity = currentTransform ?? transform.GetTransformActivity(self);
|
||||||
|
activity.Queue(self, new IssueOrderAfterTransform(order.OrderString, order.Target));
|
||||||
|
|
||||||
|
if (currentTransform == null)
|
||||||
|
self.QueueActivity(order.Queued, activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
string IOrderVoice.VoicePhraseForOrder(Actor self, Order order)
|
||||||
|
{
|
||||||
|
if (IsTraitDisabled)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (order.OrderString != "EnterTransport" && order.OrderString != "EnterTransports")
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (order.Target.Type != TargetType.Actor || !CanEnter(order.Target.Actor))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return Info.Voice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
110
OpenRA.Mods.Common/Traits/Buildings/TransformsIntoRepairable.cs
Normal file
110
OpenRA.Mods.Common/Traits/Buildings/TransformsIntoRepairable.cs
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
#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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Activities;
|
||||||
|
using OpenRA.Mods.Common.Activities;
|
||||||
|
using OpenRA.Mods.Common.Orders;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Traits
|
||||||
|
{
|
||||||
|
[Desc("Add to a building to expose a move cursor that triggers Transforms and issues a repair order to the transformed actor.")]
|
||||||
|
public class TransformsIntoRepairableInfo : ConditionalTraitInfo, Requires<TransformsInfo>, Requires<IHealthInfo>
|
||||||
|
{
|
||||||
|
[ActorReference]
|
||||||
|
[FieldLoader.Require]
|
||||||
|
public readonly HashSet<string> RepairActors = new HashSet<string> { };
|
||||||
|
|
||||||
|
[VoiceReference]
|
||||||
|
public readonly string Voice = "Action";
|
||||||
|
|
||||||
|
public override object Create(ActorInitializer init) { return new TransformsIntoRepairable(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TransformsIntoRepairable : ConditionalTrait<TransformsIntoRepairableInfo>, IIssueOrder, IResolveOrder, IOrderVoice
|
||||||
|
{
|
||||||
|
Transforms[] transforms;
|
||||||
|
IHealth health;
|
||||||
|
|
||||||
|
public TransformsIntoRepairable(TransformsIntoRepairableInfo info)
|
||||||
|
: base(info) { }
|
||||||
|
|
||||||
|
protected override void Created(Actor self)
|
||||||
|
{
|
||||||
|
transforms = self.TraitsImplementing<Transforms>().ToArray();
|
||||||
|
health = self.Trait<IHealth>();
|
||||||
|
base.Created(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<IOrderTargeter> IIssueOrder.Orders
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!IsTraitDisabled)
|
||||||
|
yield return new EnterAlliedActorTargeter<BuildingInfo>("Repair", 5, CanRepairAt, _ => CanRepair());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanRepair()
|
||||||
|
{
|
||||||
|
return health.DamageState > DamageState.Undamaged && transforms.Any(t => !t.IsTraitDisabled && !t.IsTraitPaused);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanRepairAt(Actor target)
|
||||||
|
{
|
||||||
|
return Info.RepairActors.Contains(target.Info.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
Order IIssueOrder.IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued)
|
||||||
|
{
|
||||||
|
if (order.OrderID == "Repair")
|
||||||
|
return new Order(order.OrderID, self, target, queued);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IResolveOrder.ResolveOrder(Actor self, Order order)
|
||||||
|
{
|
||||||
|
if (IsTraitDisabled || order.OrderString != "Repair")
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Repair orders are only valid for own/allied actors,
|
||||||
|
// which are guaranteed to never be frozen.
|
||||||
|
if (order.Target.Type != TargetType.Actor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!CanRepairAt(order.Target.Actor) || !CanRepair())
|
||||||
|
return;
|
||||||
|
|
||||||
|
var currentTransform = self.CurrentActivity as Transform;
|
||||||
|
var transform = transforms.FirstOrDefault(t => !t.IsTraitDisabled && !t.IsTraitPaused);
|
||||||
|
if (transform == null && currentTransform == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
self.SetTargetLine(order.Target, Color.Green);
|
||||||
|
|
||||||
|
var activity = currentTransform ?? transform.GetTransformActivity(self);
|
||||||
|
activity.Queue(self, new IssueOrderAfterTransform(order.OrderString, order.Target));
|
||||||
|
|
||||||
|
if (currentTransform == null)
|
||||||
|
self.QueueActivity(order.Queued, activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
string IOrderVoice.VoicePhraseForOrder(Actor self, Order order)
|
||||||
|
{
|
||||||
|
return order.OrderString == "Repair" && !IsTraitDisabled && CanRepair() ? Info.Voice : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,7 +44,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
yield return new EnterTunnelOrderTargeter(info);
|
yield return new EnterTunnelOrderTargeter(info.EnterCursor, info.EnterBlockedCursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,14 +78,16 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
self.QueueActivity(move.MoveTo(tunnel.Exit.Value, tunnel.NearEnough));
|
self.QueueActivity(move.MoveTo(tunnel.Exit.Value, tunnel.NearEnough));
|
||||||
}
|
}
|
||||||
|
|
||||||
class EnterTunnelOrderTargeter : UnitOrderTargeter
|
public class EnterTunnelOrderTargeter : UnitOrderTargeter
|
||||||
{
|
{
|
||||||
readonly EntersTunnelsInfo info;
|
readonly string enterCursor;
|
||||||
|
readonly string enterBlockedCursor;
|
||||||
|
|
||||||
public EnterTunnelOrderTargeter(EntersTunnelsInfo info)
|
public EnterTunnelOrderTargeter(string enterCursor, string enterBlockedCursor)
|
||||||
: base("EnterTunnel", 6, info.EnterCursor, true, true)
|
: base("EnterTunnel", 6, enterCursor, true, true)
|
||||||
{
|
{
|
||||||
this.info = info;
|
this.enterCursor = enterCursor;
|
||||||
|
this.enterBlockedCursor = enterBlockedCursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor)
|
public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor)
|
||||||
@@ -109,11 +111,11 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
if (!tunnel.Exit.HasValue)
|
if (!tunnel.Exit.HasValue)
|
||||||
{
|
{
|
||||||
cursor = info.EnterBlockedCursor;
|
cursor = enterBlockedCursor;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor = info.EnterCursor;
|
cursor = enterCursor;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.Activities;
|
||||||
using OpenRA.Mods.Common.Activities;
|
using OpenRA.Mods.Common.Activities;
|
||||||
using OpenRA.Mods.Common.Orders;
|
using OpenRA.Mods.Common.Orders;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
@@ -85,6 +86,18 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return buildingInfo == null || self.World.CanPlaceBuilding(self.Location + Info.Offset, actorInfo, buildingInfo, self);
|
return buildingInfo == null || self.World.CanPlaceBuilding(self.Location + Info.Offset, actorInfo, buildingInfo, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Activity GetTransformActivity(Actor self)
|
||||||
|
{
|
||||||
|
return new Transform(self, Info.IntoActor)
|
||||||
|
{
|
||||||
|
Offset = Info.Offset,
|
||||||
|
Facing = Info.Facing,
|
||||||
|
Sounds = Info.TransformSounds,
|
||||||
|
Notification = Info.TransformNotification,
|
||||||
|
Faction = faction
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerable<IOrderTargeter> Orders
|
public IEnumerable<IOrderTargeter> Orders
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -127,14 +140,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (!queued)
|
if (!queued)
|
||||||
self.CancelActivity();
|
self.CancelActivity();
|
||||||
|
|
||||||
self.QueueActivity(new Transform(self, Info.IntoActor)
|
self.QueueActivity(GetTransformActivity(self));
|
||||||
{
|
|
||||||
Offset = Info.Offset,
|
|
||||||
Facing = Info.Facing,
|
|
||||||
Sounds = Info.TransformSounds,
|
|
||||||
Notification = Info.TransformNotification,
|
|
||||||
Faction = faction
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResolveOrder(Actor self, Order order)
|
public void ResolveOrder(Actor self, Order order)
|
||||||
|
|||||||
@@ -20,11 +20,21 @@ FACT:
|
|||||||
Production:
|
Production:
|
||||||
Produces: Building.GDI, Building.Nod, Defence.GDI, Defence.Nod
|
Produces: Building.GDI, Building.Nod, Defence.GDI, Defence.Nod
|
||||||
Transforms:
|
Transforms:
|
||||||
RequiresCondition: factundeploy && !build-incomplete
|
RequiresCondition: factundeploy
|
||||||
PauseOnCondition: being-demolished
|
PauseOnCondition: being-demolished || build-incomplete
|
||||||
IntoActor: mcv
|
IntoActor: mcv
|
||||||
Offset: 1,1
|
Offset: 1,1
|
||||||
Facing: 108
|
Facing: 108
|
||||||
|
TransformsIntoMobile:
|
||||||
|
RequiresCondition: factundeploy
|
||||||
|
Locomotor: heavywheeled
|
||||||
|
RequiresForceMove: true
|
||||||
|
TransformsIntoPassenger:
|
||||||
|
RequiresCondition: factundeploy
|
||||||
|
CargoType: Vehicle
|
||||||
|
TransformsIntoRepairable:
|
||||||
|
RequiresCondition: factundeploy
|
||||||
|
RepairActors: fix
|
||||||
GrantConditionOnPrerequisite@GLOBALFACTUNDEPLOY:
|
GrantConditionOnPrerequisite@GLOBALFACTUNDEPLOY:
|
||||||
Condition: factundeploy
|
Condition: factundeploy
|
||||||
Prerequisites: global-factundeploy
|
Prerequisites: global-factundeploy
|
||||||
|
|||||||
@@ -1137,11 +1137,21 @@ FACT:
|
|||||||
ActorTypes: e1,e1,e1,tecn,tecn,e6
|
ActorTypes: e1,e1,e1,tecn,tecn,e6
|
||||||
BaseBuilding:
|
BaseBuilding:
|
||||||
Transforms:
|
Transforms:
|
||||||
RequiresCondition: factundeploy && !build-incomplete
|
RequiresCondition: factundeploy
|
||||||
PauseOnCondition: chrono-vortex || being-captured || being-demolished
|
PauseOnCondition: chrono-vortex || being-captured || being-demolished || build-incomplete
|
||||||
IntoActor: mcv
|
IntoActor: mcv
|
||||||
Offset: 1,1
|
Offset: 1,1
|
||||||
Facing: 96
|
Facing: 96
|
||||||
|
TransformsIntoMobile:
|
||||||
|
RequiresCondition: factundeploy
|
||||||
|
Locomotor: heavywheeled
|
||||||
|
RequiresForceMove: true
|
||||||
|
TransformsIntoPassenger:
|
||||||
|
RequiresCondition: factundeploy
|
||||||
|
CargoType: Vehicle
|
||||||
|
TransformsIntoRepairable:
|
||||||
|
RequiresCondition: factundeploy
|
||||||
|
RepairActors: fix
|
||||||
Sellable:
|
Sellable:
|
||||||
RequiresCondition: !build-incomplete && !chrono-vortex && !being-captured && !being-demolished
|
RequiresCondition: !build-incomplete && !chrono-vortex && !being-captured && !being-demolished
|
||||||
GrantConditionOnPrerequisite@GLOBALFACTUNDEPLOY:
|
GrantConditionOnPrerequisite@GLOBALFACTUNDEPLOY:
|
||||||
|
|||||||
@@ -28,12 +28,28 @@ GACNST:
|
|||||||
Value: 2500
|
Value: 2500
|
||||||
BaseBuilding:
|
BaseBuilding:
|
||||||
Transforms:
|
Transforms:
|
||||||
RequiresCondition: factundeploy && !build-incomplete
|
RequiresCondition: factundeploy
|
||||||
PauseOnCondition: empdisable || being-demolished
|
PauseOnCondition: empdisable || being-demolished || build-incomplete
|
||||||
IntoActor: mcv
|
IntoActor: mcv
|
||||||
Offset: 1,1
|
Offset: 1,1
|
||||||
Facing: 96
|
Facing: 96
|
||||||
DeployCursor: undeploy
|
DeployCursor: undeploy
|
||||||
|
TransformsIntoMobile:
|
||||||
|
RequiresCondition: factundeploy
|
||||||
|
Locomotor: tracked
|
||||||
|
Voice: Move
|
||||||
|
RequiresForceMove: true
|
||||||
|
TransformsIntoRepairable:
|
||||||
|
RequiresCondition: factundeploy
|
||||||
|
RepairActors: gadept
|
||||||
|
Voice: Move
|
||||||
|
TransformsIntoEntersTunnels:
|
||||||
|
RequiresCondition: factundeploy
|
||||||
|
Voice: Move
|
||||||
|
TransformsIntoPassenger:
|
||||||
|
RequiresCondition: factundeploy
|
||||||
|
CargoType: Vehicle
|
||||||
|
Voice: Move
|
||||||
GrantConditionOnPrerequisite@GLOBALFACTUNDEPLOY:
|
GrantConditionOnPrerequisite@GLOBALFACTUNDEPLOY:
|
||||||
Condition: factundeploy
|
Condition: factundeploy
|
||||||
Prerequisites: global-factundeploy
|
Prerequisites: global-factundeploy
|
||||||
|
|||||||
Reference in New Issue
Block a user