Fix ResupplyAircraft being cancelable by Stop command
It is now immediately queued again, as long as the actor has not finished rearming/repairing yet.
This commit is contained in:
@@ -171,8 +171,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public readonly AircraftInfo Info;
|
public readonly AircraftInfo Info;
|
||||||
readonly Actor self;
|
readonly Actor self;
|
||||||
|
|
||||||
RepairableInfo repairableInfo;
|
Repairable repairable;
|
||||||
RearmableInfo rearmableInfo;
|
Rearmable rearmable;
|
||||||
ConditionManager conditionManager;
|
ConditionManager conditionManager;
|
||||||
IDisposable reservation;
|
IDisposable reservation;
|
||||||
IEnumerable<int> speedModifiers;
|
IEnumerable<int> speedModifiers;
|
||||||
@@ -228,8 +228,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
protected virtual void Created(Actor self)
|
protected virtual void Created(Actor self)
|
||||||
{
|
{
|
||||||
repairableInfo = self.Info.TraitInfoOrDefault<RepairableInfo>();
|
repairable = self.TraitOrDefault<Repairable>();
|
||||||
rearmableInfo = self.Info.TraitInfoOrDefault<RearmableInfo>();
|
rearmable = self.TraitOrDefault<Rearmable>();
|
||||||
conditionManager = self.TraitOrDefault<ConditionManager>();
|
conditionManager = self.TraitOrDefault<ConditionManager>();
|
||||||
speedModifiers = self.TraitsImplementing<ISpeedModifier>().ToArray().Select(sm => sm.GetSpeedModifier());
|
speedModifiers = self.TraitsImplementing<ISpeedModifier>().ToArray().Select(sm => sm.GetSpeedModifier());
|
||||||
cachedPosition = self.CenterPosition;
|
cachedPosition = self.CenterPosition;
|
||||||
@@ -469,8 +469,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (self.AppearsHostileTo(a))
|
if (self.AppearsHostileTo(a))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return (rearmableInfo != null && rearmableInfo.RearmActors.Contains(a.Info.Name))
|
return (rearmable != null && rearmable.Info.RearmActors.Contains(a.Info.Name))
|
||||||
|| (repairableInfo != null && repairableInfo.RepairActors.Contains(a.Info.Name));
|
|| (repairable != null && repairable.Info.RepairActors.Contains(a.Info.Name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int MovementSpeed
|
public int MovementSpeed
|
||||||
@@ -503,14 +503,23 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return Info.LandableTerrainTypes.Contains(type);
|
return Info.LandableTerrainTypes.Contains(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool CanRearmAt(Actor host)
|
||||||
|
{
|
||||||
|
return rearmable != null && rearmable.Info.RearmActors.Contains(host.Info.Name) && rearmable.RearmableAmmoPools.Any(p => !p.FullAmmo());
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanRepairAt(Actor host)
|
||||||
|
{
|
||||||
|
return repairable != null && repairable.Info.RepairActors.Contains(host.Info.Name) && self.GetDamageState() != DamageState.Undamaged;
|
||||||
|
}
|
||||||
|
|
||||||
public virtual IEnumerable<Activity> GetResupplyActivities(Actor a)
|
public virtual IEnumerable<Activity> GetResupplyActivities(Actor a)
|
||||||
{
|
{
|
||||||
var name = a.Info.Name;
|
// The ResupplyAircraft activity guarantees that we're on the helipad/repair depot
|
||||||
if (rearmableInfo != null && rearmableInfo.RearmActors.Contains(name))
|
if (CanRearmAt(a))
|
||||||
yield return new Rearm(self, a, WDist.Zero);
|
yield return new Rearm(self, a, WDist.Zero);
|
||||||
|
|
||||||
// The ResupplyAircraft activity guarantees that we're on the helipad
|
if (CanRepairAt(a))
|
||||||
if (repairableInfo != null && repairableInfo.RepairActors.Contains(name))
|
|
||||||
yield return new Repair(self, a, WDist.Zero);
|
yield return new Repair(self, a, WDist.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,21 +530,45 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
void INotifyBecomingIdle.OnBecomingIdle(Actor self)
|
void INotifyBecomingIdle.OnBecomingIdle(Actor self)
|
||||||
{
|
{
|
||||||
if (Info.VTOL && Info.LandWhenIdle)
|
OnBecomingIdle(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnBecomingIdle(Actor self)
|
||||||
|
{
|
||||||
|
var atLandAltitude = self.World.Map.DistanceAboveTerrain(CenterPosition) == Info.LandAltitude;
|
||||||
|
|
||||||
|
// Work-around to prevent players from accidentally canceling resupply by pressing 'Stop',
|
||||||
|
// by re-queueing ResupplyAircraft as long as resupply hasn't finished and aircraft is still on resupplier.
|
||||||
|
// TODO: Investigate moving this back to ResolveOrder's "Stop" handling,
|
||||||
|
// once conflicts with other traits' "Stop" orders have been fixed.
|
||||||
|
if (atLandAltitude)
|
||||||
|
{
|
||||||
|
var host = GetActorBelow();
|
||||||
|
if (host != null && (CanRearmAt(host) || CanRepairAt(host)))
|
||||||
|
{
|
||||||
|
self.QueueActivity(new ResupplyAircraft(self));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!atLandAltitude && Info.VTOL && Info.LandWhenIdle)
|
||||||
{
|
{
|
||||||
if (Info.TurnToLand)
|
if (Info.TurnToLand)
|
||||||
self.QueueActivity(new Turn(self, Info.InitialFacing));
|
self.QueueActivity(new Turn(self, Info.InitialFacing));
|
||||||
|
|
||||||
self.QueueActivity(new HeliLand(self, true));
|
self.QueueActivity(new HeliLand(self, true));
|
||||||
}
|
}
|
||||||
else if (!Info.CanHover && (Info.TakeOffOnResupply || ReservedActor == null || self.World.Map.DistanceAboveTerrain(CenterPosition) != Info.LandAltitude))
|
else if (!Info.CanHover && !atLandAltitude)
|
||||||
self.QueueActivity(new FlyCircle(self, -1, Info.IdleTurnSpeed > -1 ? Info.IdleTurnSpeed : TurnSpeed));
|
self.QueueActivity(new FlyCircle(self, -1, Info.IdleTurnSpeed > -1 ? Info.IdleTurnSpeed : TurnSpeed));
|
||||||
|
else if (atLandAltitude && (Info.TakeOffOnResupply || ReservedActor == null))
|
||||||
|
self.QueueActivity(new TakeOff(self));
|
||||||
|
else if (Info.CanHover && self.Info.HasTraitInfo<AutoCarryallInfo>() && Info.IdleTurnSpeed > -1)
|
||||||
|
{
|
||||||
// Temporary HACK for the AutoCarryall special case (needs CanHover, but also HeliFlyCircle on idle).
|
// Temporary HACK for the AutoCarryall special case (needs CanHover, but also HeliFlyCircle on idle).
|
||||||
// Will go away soon (in a separate PR) with the arrival of ActionsWhenIdle.
|
// Will go away soon (in a separate PR) with the arrival of ActionsWhenIdle.
|
||||||
else if (Info.CanHover && self.Info.HasTraitInfo<AutoCarryallInfo>() && Info.IdleTurnSpeed > -1)
|
|
||||||
self.QueueActivity(new HeliFlyCircle(self, Info.IdleTurnSpeed > -1 ? Info.IdleTurnSpeed : TurnSpeed));
|
self.QueueActivity(new HeliFlyCircle(self, Info.IdleTurnSpeed > -1 ? Info.IdleTurnSpeed : TurnSpeed));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#region Implement IPositionable
|
#region Implement IPositionable
|
||||||
|
|
||||||
@@ -717,13 +750,13 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
Order IIssueDeployOrder.IssueDeployOrder(Actor self, bool queued)
|
Order IIssueDeployOrder.IssueDeployOrder(Actor self, bool queued)
|
||||||
{
|
{
|
||||||
if (rearmableInfo == null || !rearmableInfo.RearmActors.Any())
|
if (rearmable == null || !rearmable.Info.RearmActors.Any())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new Order("ReturnToBase", self, queued);
|
return new Order("ReturnToBase", self, queued);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IIssueDeployOrder.CanIssueDeployOrder(Actor self) { return rearmableInfo != null && rearmableInfo.RearmActors.Any(); }
|
bool IIssueDeployOrder.CanIssueDeployOrder(Actor self) { return rearmable != null && rearmable.Info.RearmActors.Any(); }
|
||||||
|
|
||||||
public string VoicePhraseForOrder(Actor self, Order order)
|
public string VoicePhraseForOrder(Actor self, Order order)
|
||||||
{
|
{
|
||||||
@@ -742,7 +775,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
case "Stop":
|
case "Stop":
|
||||||
return Info.Voice;
|
return Info.Voice;
|
||||||
case "ReturnToBase":
|
case "ReturnToBase":
|
||||||
return rearmableInfo != null && rearmableInfo.RearmActors.Any() ? Info.Voice : null;
|
return rearmable != null && rearmable.Info.RearmActors.Any() ? Info.Voice : null;
|
||||||
default: return null;
|
default: return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -791,15 +824,15 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
else if (order.OrderString == "Stop")
|
else if (order.OrderString == "Stop")
|
||||||
{
|
{
|
||||||
self.CancelActivity();
|
self.CancelActivity();
|
||||||
|
|
||||||
|
// HACK: If the player accidentally pressed 'Stop', we don't want this to cancel reservation.
|
||||||
|
// If unreserving is actually desired despite an actor below, it should be triggered from OnBecomingIdle.
|
||||||
if (GetActorBelow() != null)
|
if (GetActorBelow() != null)
|
||||||
{
|
|
||||||
self.QueueActivity(new ResupplyAircraft(self));
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
UnReserve();
|
UnReserve();
|
||||||
}
|
}
|
||||||
else if (order.OrderString == "ReturnToBase" && rearmableInfo != null && rearmableInfo.RearmActors.Any())
|
else if (order.OrderString == "ReturnToBase" && rearmable != null && rearmable.Info.RearmActors.Any())
|
||||||
{
|
{
|
||||||
if (!order.Queued)
|
if (!order.Queued)
|
||||||
UnReserve();
|
UnReserve();
|
||||||
|
|||||||
Reference in New Issue
Block a user