Move movement to resupplier inside Resupply activity
From Repairable(Near).
This commit is contained in:
@@ -10,9 +10,11 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Activities;
|
using OpenRA.Activities;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
using OpenRA.Primitives;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Activities
|
namespace OpenRA.Mods.Common.Activities
|
||||||
@@ -27,9 +29,13 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
readonly RepairableNear repairableNear;
|
readonly RepairableNear repairableNear;
|
||||||
readonly Rearmable rearmable;
|
readonly Rearmable rearmable;
|
||||||
readonly INotifyResupply[] notifyResupplies;
|
readonly INotifyResupply[] notifyResupplies;
|
||||||
|
readonly ICallForTransport[] transportCallers;
|
||||||
|
readonly IMove move;
|
||||||
|
readonly Aircraft aircraft;
|
||||||
|
|
||||||
int remainingTicks;
|
int remainingTicks;
|
||||||
bool played;
|
bool played;
|
||||||
|
bool actualResupplyStarted;
|
||||||
ResupplyType activeResupplyTypes = ResupplyType.None;
|
ResupplyType activeResupplyTypes = ResupplyType.None;
|
||||||
|
|
||||||
public Resupply(Actor self, Actor host, WDist closeEnough)
|
public Resupply(Actor self, Actor host, WDist closeEnough)
|
||||||
@@ -42,6 +48,9 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
repairableNear = self.TraitOrDefault<RepairableNear>();
|
repairableNear = self.TraitOrDefault<RepairableNear>();
|
||||||
rearmable = self.TraitOrDefault<Rearmable>();
|
rearmable = self.TraitOrDefault<Rearmable>();
|
||||||
notifyResupplies = host.TraitsImplementing<INotifyResupply>().ToArray();
|
notifyResupplies = host.TraitsImplementing<INotifyResupply>().ToArray();
|
||||||
|
transportCallers = self.TraitsImplementing<ICallForTransport>().ToArray();
|
||||||
|
move = self.Trait<IMove>();
|
||||||
|
aircraft = move as Aircraft;
|
||||||
|
|
||||||
var cannotRepairAtHost = health == null || health.DamageState == DamageState.Undamaged
|
var cannotRepairAtHost = health == null || health.DamageState == DamageState.Undamaged
|
||||||
|| !allRepairsUnits.Any()
|
|| !allRepairsUnits.Any()
|
||||||
@@ -56,23 +65,6 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
activeResupplyTypes |= ResupplyType.Rearm;
|
activeResupplyTypes |= ResupplyType.Rearm;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnFirstRun(Actor self)
|
|
||||||
{
|
|
||||||
if (host.Type == TargetType.Invalid)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (activeResupplyTypes > 0)
|
|
||||||
foreach (var notifyResupply in notifyResupplies)
|
|
||||||
notifyResupply.BeforeResupply(host.Actor, self, activeResupplyTypes);
|
|
||||||
|
|
||||||
// Reset the ReloadDelay to avoid any issues with early cancellation
|
|
||||||
// from previous reload attempts (explicit order, host building died, etc).
|
|
||||||
// HACK: this really shouldn't be managed from here
|
|
||||||
if (activeResupplyTypes.HasFlag(ResupplyType.Rearm))
|
|
||||||
foreach (var pool in rearmable.RearmableAmmoPools)
|
|
||||||
pool.RemainingTicks = pool.Info.ReloadDelay;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Tick(Actor self)
|
public override bool Tick(Actor self)
|
||||||
{
|
{
|
||||||
// HACK: If the activity is cancelled while we're already resupplying (or about to start resupplying),
|
// HACK: If the activity is cancelled while we're already resupplying (or about to start resupplying),
|
||||||
@@ -83,7 +75,6 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
foreach (var notifyResupply in notifyResupplies)
|
foreach (var notifyResupply in notifyResupplies)
|
||||||
notifyResupply.ResupplyTick(host.Actor, self, ResupplyType.None);
|
notifyResupply.ResupplyTick(host.Actor, self, ResupplyType.None);
|
||||||
|
|
||||||
var aircraft = self.TraitOrDefault<Aircraft>();
|
|
||||||
if (aircraft != null)
|
if (aircraft != null)
|
||||||
{
|
{
|
||||||
aircraft.AllowYieldingReservation();
|
aircraft.AllowYieldingReservation();
|
||||||
@@ -92,14 +83,15 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (self.Info.HasTraitInfo<MobileInfo>())
|
else if (repairableNear != null)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
QueueChild(self.Trait<IMove>().MoveToTarget(self, host));
|
QueueChild(move.MoveToTarget(self, host));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (IsCanceling || host.Type == TargetType.Invalid
|
else if (IsCanceling || host.Type != TargetType.Actor || !host.Actor.IsInWorld || host.Actor.IsDead)
|
||||||
|| (closeEnough.LengthSquared > 0 && !host.IsInRange(self.CenterPosition, closeEnough)))
|
|
||||||
{
|
{
|
||||||
// This is necessary to ensure host resupply actions (like animations) finish properly
|
// This is necessary to ensure host resupply actions (like animations) finish properly
|
||||||
foreach (var notifyResupply in notifyResupplies)
|
foreach (var notifyResupply in notifyResupplies)
|
||||||
@@ -107,6 +99,50 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (activeResupplyTypes != 0 && aircraft == null &&
|
||||||
|
(closeEnough.LengthSquared > 0 && !host.IsInRange(self.CenterPosition, closeEnough)))
|
||||||
|
{
|
||||||
|
var targetCell = self.World.Map.CellContaining(host.Actor.CenterPosition);
|
||||||
|
List<Activity> movement = new List<Activity>();
|
||||||
|
|
||||||
|
movement.Add(move.MoveWithinRange(host, closeEnough, targetLineColor: Color.Green));
|
||||||
|
|
||||||
|
// HACK: Repairable needs the actor to move to host center.
|
||||||
|
// TODO: Get rid of this or at least replace it with something less hacky.
|
||||||
|
if (repairableNear == null)
|
||||||
|
movement.Add(move.MoveTo(targetCell, host.Actor));
|
||||||
|
|
||||||
|
var moveActivities = ActivityUtils.SequenceActivities(movement.ToArray());
|
||||||
|
|
||||||
|
var delta = (self.CenterPosition - host.CenterPosition).LengthSquared;
|
||||||
|
var transport = transportCallers.FirstOrDefault(t => t.MinimumDistance.LengthSquared < delta);
|
||||||
|
if (transport != null)
|
||||||
|
{
|
||||||
|
QueueChild(new WaitForTransport(self, moveActivities));
|
||||||
|
|
||||||
|
// TODO: Make this compatible with RepairableNear
|
||||||
|
transport.RequestTransport(self, targetCell, new Resupply(self, host.Actor, closeEnough));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
QueueChild(moveActivities);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't want to trigger this until we've reached the resupplier and can start resupplying
|
||||||
|
if (!actualResupplyStarted && activeResupplyTypes > 0)
|
||||||
|
{
|
||||||
|
actualResupplyStarted = true;
|
||||||
|
foreach (var notifyResupply in notifyResupplies)
|
||||||
|
notifyResupply.BeforeResupply(host.Actor, self, activeResupplyTypes);
|
||||||
|
|
||||||
|
// Reset the ReloadDelay to avoid any issues with early cancellation
|
||||||
|
// from previous reload attempts (explicit order, host building died, etc).
|
||||||
|
// HACK: this really shouldn't be managed from here
|
||||||
|
if (activeResupplyTypes.HasFlag(ResupplyType.Rearm))
|
||||||
|
foreach (var pool in rearmable.RearmableAmmoPools)
|
||||||
|
pool.RemainingTicks = pool.Info.ReloadDelay;
|
||||||
|
}
|
||||||
|
|
||||||
if (activeResupplyTypes.HasFlag(ResupplyType.Repair))
|
if (activeResupplyTypes.HasFlag(ResupplyType.Repair))
|
||||||
RepairTick(self);
|
RepairTick(self);
|
||||||
@@ -119,10 +155,18 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
|
|
||||||
if (activeResupplyTypes == 0)
|
if (activeResupplyTypes == 0)
|
||||||
{
|
{
|
||||||
var aircraft = self.TraitOrDefault<Aircraft>();
|
|
||||||
if (aircraft != null)
|
if (aircraft != null)
|
||||||
aircraft.AllowYieldingReservation();
|
aircraft.AllowYieldingReservation();
|
||||||
|
|
||||||
|
if (self.CurrentActivity.NextActivity == null)
|
||||||
|
{
|
||||||
|
var rp = host.Actor.TraitOrDefault<RallyPoint>();
|
||||||
|
if (rp != null)
|
||||||
|
Queue(move.MoveTo(rp.Location, repairableNear != null ? null : host.Actor));
|
||||||
|
else if (repairableNear == null)
|
||||||
|
Queue(move.MoveToTarget(self, host));
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,20 +44,20 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
{
|
{
|
||||||
public readonly RepairableInfo Info;
|
public readonly RepairableInfo Info;
|
||||||
readonly IHealth health;
|
readonly IHealth health;
|
||||||
readonly IMove movement;
|
|
||||||
Rearmable rearmable;
|
Rearmable rearmable;
|
||||||
bool requireForceMove;
|
bool requireForceMove;
|
||||||
|
bool isAircraft;
|
||||||
|
|
||||||
public Repairable(Actor self, RepairableInfo info)
|
public Repairable(Actor self, RepairableInfo info)
|
||||||
{
|
{
|
||||||
Info = info;
|
Info = info;
|
||||||
health = self.Trait<IHealth>();
|
health = self.Trait<IHealth>();
|
||||||
movement = self.Trait<IMove>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void INotifyCreated.Created(Actor self)
|
void INotifyCreated.Created(Actor self)
|
||||||
{
|
{
|
||||||
rearmable = self.TraitOrDefault<Rearmable>();
|
rearmable = self.TraitOrDefault<Rearmable>();
|
||||||
|
isAircraft = self.Info.HasTraitInfo<AircraftInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<IOrderTargeter> Orders
|
public IEnumerable<IOrderTargeter> Orders
|
||||||
@@ -106,58 +106,38 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
void IResolveOrder.ResolveOrder(Actor self, Order order)
|
void IResolveOrder.ResolveOrder(Actor self, Order order)
|
||||||
{
|
{
|
||||||
if (order.OrderString == "Repair")
|
if (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;
|
|
||||||
|
|
||||||
// Aircraft handle Repair orders directly in the Aircraft trait
|
// Repair orders are only valid for own/allied actors,
|
||||||
if (self.Info.HasTraitInfo<AircraftInfo>())
|
// which are guaranteed to never be frozen.
|
||||||
return;
|
|
||||||
|
|
||||||
if (!CanRepairAt(order.Target.Actor) || (!CanRepair() && !CanRearm()))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!order.Queued)
|
|
||||||
self.CancelActivity();
|
|
||||||
|
|
||||||
self.SetTargetLine(order.Target, Color.Green);
|
|
||||||
var activities = ActivityUtils.SequenceActivities(
|
|
||||||
movement.MoveToTarget(self, order.Target, targetLineColor: Color.Green),
|
|
||||||
new CallFunc(() => AfterReachActivities(self, order, movement)));
|
|
||||||
|
|
||||||
self.QueueActivity(new WaitForTransport(self, activities));
|
|
||||||
TryCallTransport(self, order.Target, new CallFunc(() => AfterReachActivities(self, order, movement)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AfterReachActivities(Actor self, Order order, IMove movement)
|
|
||||||
{
|
|
||||||
if (order.Target.Type != TargetType.Actor)
|
if (order.Target.Type != TargetType.Actor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var targetActor = order.Target.Actor;
|
// Aircraft handle Repair orders directly in the Aircraft trait
|
||||||
if (!targetActor.IsInWorld || targetActor.IsDead || targetActor.TraitsImplementing<RepairsUnits>().All(r => r.IsTraitDisabled))
|
// TODO: Move the order handling of both this trait and Aircraft to a generalistic DockManager
|
||||||
|
if (isAircraft)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: This is hacky, but almost every single component affected
|
if (!CanRepairAt(order.Target.Actor) || (!CanRepair() && !CanRearm()))
|
||||||
// will need to be rewritten anyway, so this is OK for now.
|
return;
|
||||||
self.QueueActivity(movement.MoveTo(self.World.Map.CellContaining(targetActor.CenterPosition), targetActor));
|
|
||||||
|
|
||||||
// Add a CloseEnough range of 512 to ensure we're at the host actor
|
if (!order.Queued)
|
||||||
self.QueueActivity(new Resupply(self, targetActor, new WDist(512)));
|
self.CancelActivity();
|
||||||
|
|
||||||
var rp = targetActor.TraitOrDefault<RallyPoint>();
|
self.SetTargetLine(order.Target, Color.Green);
|
||||||
if (rp != null)
|
self.QueueActivity(new Resupply(self, order.Target.Actor, new WDist(512)));
|
||||||
{
|
}
|
||||||
self.QueueActivity(new CallFunc(() =>
|
|
||||||
{
|
IEnumerable<VariableObserver> IObservesVariables.GetVariableObservers()
|
||||||
self.SetTargetLine(Target.FromCell(self.World, rp.Location), Color.Green);
|
{
|
||||||
self.QueueActivity(movement.MoveTo(rp.Location, targetActor));
|
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 Actor FindRepairBuilding(Actor self)
|
public Actor FindRepairBuilding(Actor self)
|
||||||
@@ -172,27 +152,5 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
// Worst case FirstOrDefault() will return a TraitPair<null, null>, which is OK.
|
// Worst case FirstOrDefault() will return a TraitPair<null, null>, which is OK.
|
||||||
return repairBuilding.FirstOrDefault().Actor;
|
return repairBuilding.FirstOrDefault().Actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TryCallTransport(Actor self, Target target, Activity nextActivity)
|
|
||||||
{
|
|
||||||
var targetCell = self.World.Map.CellContaining(target.CenterPosition);
|
|
||||||
var delta = (self.CenterPosition - target.CenterPosition).LengthSquared;
|
|
||||||
var transports = self.TraitsImplementing<ICallForTransport>()
|
|
||||||
.Where(t => t.MinimumDistance.LengthSquared < delta);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,14 +41,12 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
{
|
{
|
||||||
public readonly RepairableNearInfo Info;
|
public readonly RepairableNearInfo Info;
|
||||||
readonly Actor self;
|
readonly Actor self;
|
||||||
readonly IMove movement;
|
|
||||||
bool requireForceMove;
|
bool requireForceMove;
|
||||||
|
|
||||||
public RepairableNear(Actor self, RepairableNearInfo info)
|
public RepairableNear(Actor self, RepairableNearInfo info)
|
||||||
{
|
{
|
||||||
this.self = self;
|
this.self = self;
|
||||||
Info = info;
|
Info = info;
|
||||||
movement = self.Trait<IMove>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<IOrderTargeter> Orders
|
public IEnumerable<IOrderTargeter> Orders
|
||||||
@@ -104,10 +102,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (!order.Queued)
|
if (!order.Queued)
|
||||||
self.CancelActivity();
|
self.CancelActivity();
|
||||||
|
|
||||||
self.QueueActivity(movement.MoveWithinRange(order.Target, Info.CloseEnough, targetLineColor: Color.Green));
|
self.SetTargetLine(order.Target, Color.Green);
|
||||||
self.QueueActivity(new Resupply(self, order.Target.Actor, Info.CloseEnough));
|
self.QueueActivity(new Resupply(self, order.Target.Actor, Info.CloseEnough));
|
||||||
|
|
||||||
self.SetTargetLine(order.Target, Color.Green, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Actor FindRepairBuilding(Actor self)
|
public Actor FindRepairBuilding(Actor self)
|
||||||
|
|||||||
Reference in New Issue
Block a user