From 52102da839fea895c4c78ce8ac4aa5fd6958588f Mon Sep 17 00:00:00 2001
From: Gustas <37534529+PunkPun@users.noreply.github.com>
Date: Mon, 2 Dec 2024 14:57:41 +0200
Subject: [PATCH] Fix harvesters refusing to queue dock orders whenn empty
(cherry picked from commit 19040126046a53fd5092515f2a4895fdd5c9c87a)
---
.../TransformsIntoDockClientManager.cs | 29 +++++++++++------
OpenRA.Mods.Common/Traits/DockClientBase.cs | 11 +++++--
.../Traits/DockClientManager.cs | 32 +++++++++++++------
OpenRA.Mods.Common/Traits/Harvester.cs | 6 ++++
OpenRA.Mods.Common/TraitsInterfaces.cs | 11 +++++--
5 files changed, 64 insertions(+), 25 deletions(-)
diff --git a/OpenRA.Mods.Common/Traits/Buildings/TransformsIntoDockClientManager.cs b/OpenRA.Mods.Common/Traits/Buildings/TransformsIntoDockClientManager.cs
index ed6a99ed23..73b6bbeb4b 100644
--- a/OpenRA.Mods.Common/Traits/Buildings/TransformsIntoDockClientManager.cs
+++ b/OpenRA.Mods.Common/Traits/Buildings/TransformsIntoDockClientManager.cs
@@ -70,7 +70,7 @@ namespace OpenRA.Mods.Common.Traits
Info.EnterCursor,
Info.EnterBlockedCursor,
() => Info.RequiresForceMove,
- DockingPossible,
+ CanQueueDockAt,
CanDockAt);
}
}
@@ -109,9 +109,13 @@ namespace OpenRA.Mods.Common.Traits
string IOrderVoice.VoicePhraseForOrder(Actor self, Order order)
{
- if (order.OrderString == "Dock" && CanDockAt(order.Target.Actor, false))
- return Info.Voice;
- else if (order.OrderString == "ForceDock" && CanDockAt(order.Target.Actor, true))
+ if (order.Target.Type != TargetType.Actor || IsTraitDisabled)
+ return null;
+
+ if (order.OrderString != "Dock" && order.OrderString != "ForceDock")
+ return null;
+
+ if (CanQueueDockAt(order.Target.Actor, order.OrderString == "ForceDock", order.Queued))
return Info.Voice;
return null;
@@ -125,12 +129,6 @@ namespace OpenRA.Mods.Common.Traits
return null;
}
- /// Clone of .
- public bool DockingPossible(Actor target, bool forceEnter)
- {
- return !IsTraitDisabled && target.TraitsImplementing().Any(host => dockClients.Any(client => client.CanDock(host.GetDockType)));
- }
-
/// Clone of .
public bool CanDockAt(Actor target, bool forceEnter)
{
@@ -140,5 +138,16 @@ namespace OpenRA.Mods.Common.Traits
return !IsTraitDisabled && target.TraitsImplementing().Any(
host => dockClients.Any(client => client.CanDockAt(target, host, forceEnter, true)));
}
+
+ /// Clone of .
+ public bool CanQueueDockAt(Actor target, bool forceEnter, bool isQueued)
+ {
+ if (Info.RequiresForceMove && !forceEnter)
+ return false;
+
+ return (!IsTraitDisabled)
+ && target.TraitsImplementing().Any(
+ host => dockClients.Any(client => client.CanQueueDockAt(target, host, forceEnter, isQueued)));
+ }
}
}
diff --git a/OpenRA.Mods.Common/Traits/DockClientBase.cs b/OpenRA.Mods.Common/Traits/DockClientBase.cs
index e542209199..cb2a08f709 100644
--- a/OpenRA.Mods.Common/Traits/DockClientBase.cs
+++ b/OpenRA.Mods.Common/Traits/DockClientBase.cs
@@ -37,9 +37,14 @@ namespace OpenRA.Mods.Common.Traits
public virtual bool CanDockAt(Actor hostActor, IDockHost host, bool forceEnter = false, bool ignoreOccupancy = false)
{
- return (forceEnter || self.Owner.IsAlliedWith(hostActor.Owner)) &&
- CanDock(host.GetDockType, forceEnter) &&
- host.IsDockingPossible(self, this, ignoreOccupancy);
+ return CanDock(host.GetDockType, forceEnter)
+ && host.IsDockingPossible(self, this, ignoreOccupancy);
+ }
+
+ public virtual bool CanQueueDockAt(Actor hostActor, IDockHost host, bool forceEnter, bool isQueued)
+ {
+ return CanDock(host.GetDockType, true)
+ && host.IsDockingPossible(self, this, true);
}
public virtual void OnDockStarted(Actor self, Actor hostActor, IDockHost host) { }
diff --git a/OpenRA.Mods.Common/Traits/DockClientManager.cs b/OpenRA.Mods.Common/Traits/DockClientManager.cs
index 794ad5895f..ca1d17f671 100644
--- a/OpenRA.Mods.Common/Traits/DockClientManager.cs
+++ b/OpenRA.Mods.Common/Traits/DockClientManager.cs
@@ -160,7 +160,7 @@ namespace OpenRA.Mods.Common.Traits
Info.EnterCursor,
Info.EnterBlockedCursor,
() => requireForceMove,
- DockingPossible,
+ CanQueueDockAt,
(target, forceEnter) => CanDockAt(target, forceEnter, true));
}
}
@@ -194,9 +194,10 @@ namespace OpenRA.Mods.Common.Traits
if (order.Target.Type != TargetType.Actor || IsTraitDisabled)
return null;
- if (order.OrderString == "Dock" && CanDockAt(order.Target.Actor, false, true))
- return Info.Voice;
- else if (order.OrderString == "ForceDock" && CanDockAt(order.Target.Actor, true, true))
+ if (order.OrderString != "Dock" && order.OrderString != "ForceDock")
+ return null;
+
+ if (CanQueueDockAt(order.Target.Actor, order.OrderString == "ForceDock", order.Queued))
return Info.Voice;
return null;
@@ -225,13 +226,13 @@ namespace OpenRA.Mods.Common.Traits
}
/// Do we have an enabled client with matching .
- public bool DockingPossible(BitSet type, bool forceEnter = false)
+ public bool CanDock(BitSet type, bool forceEnter = false)
{
return !IsTraitDisabled && dockClients.Any(client => client.CanDock(type, forceEnter));
}
/// Does this contain at least one enabled with maching .
- public bool DockingPossible(Actor target, bool forceEnter = false)
+ public bool CanDock(Actor target, bool forceEnter = false)
{
return !IsTraitDisabled &&
target.TraitsImplementing()
@@ -252,6 +253,14 @@ namespace OpenRA.Mods.Common.Traits
host => dockClients.Any(client => client.CanDockAt(target, host, forceEnter, ignoreOccupancy)));
}
+ /// Can we dock to this .
+ public bool CanQueueDockAt(Actor target, bool forceEnter, bool isQueued)
+ {
+ return !IsTraitDisabled
+ && target.TraitsImplementing()
+ .Any(host => dockClients.Any(client => client.CanQueueDockAt(target, host, forceEnter, isQueued)));
+ }
+
/// Find the closest viable .
/// If is not set, scans all clients. Does not check if is enabled.
public TraitPair? ClosestDock(IDockHost ignore, BitSet type = default, bool forceEnter = false, bool ignoreOccupancy = false)
@@ -292,11 +301,11 @@ namespace OpenRA.Mods.Common.Traits
readonly string enterCursor;
readonly string enterBlockedCursor;
readonly Func requireForceMove;
- readonly Func canTarget;
+ readonly Func canTarget;
readonly Func useEnterCursor;
public DockActorTargeter(int priority, string enterCursor, string enterBlockedCursor,
- Func requireForceMove, Func canTarget, Func useEnterCursor)
+ Func requireForceMove, Func canTarget, Func useEnterCursor)
{
OrderID = "Dock";
OrderPriority = priority;
@@ -325,10 +334,13 @@ namespace OpenRA.Mods.Common.Traits
if (requireForceMove() && !forceEnter)
return false;
- if (!canTarget(target.Actor, forceEnter))
+ if (!canTarget(target.Actor, forceEnter, IsQueued))
return false;
- cursor = useEnterCursor(target.Actor, forceEnter) ? enterCursor : enterBlockedCursor;
+ cursor = IsQueued || useEnterCursor(target.Actor, forceEnter)
+ ? enterCursor
+ : enterBlockedCursor;
+
return true;
}
diff --git a/OpenRA.Mods.Common/Traits/Harvester.cs b/OpenRA.Mods.Common/Traits/Harvester.cs
index 87b6d09f73..455edc2013 100644
--- a/OpenRA.Mods.Common/Traits/Harvester.cs
+++ b/OpenRA.Mods.Common/Traits/Harvester.cs
@@ -137,6 +137,12 @@ namespace OpenRA.Mods.Common.Traits
&& (self.Owner == hostActor.Owner || (ignoreOccupancy && self.Owner.IsAlliedWith(hostActor.Owner)));
}
+ public override bool CanQueueDockAt(Actor hostActor, IDockHost host, bool forceEnter, bool isQueued)
+ {
+ return base.CanQueueDockAt(hostActor, host, forceEnter, isQueued)
+ && self.Owner.IsAlliedWith(hostActor.Owner);
+ }
+
void UpdateCondition(Actor self)
{
if (string.IsNullOrEmpty(Info.EmptyCondition))
diff --git a/OpenRA.Mods.Common/TraitsInterfaces.cs b/OpenRA.Mods.Common/TraitsInterfaces.cs
index 74e24f3316..cc766a47b8 100644
--- a/OpenRA.Mods.Common/TraitsInterfaces.cs
+++ b/OpenRA.Mods.Common/TraitsInterfaces.cs
@@ -220,19 +220,26 @@ namespace OpenRA.Mods.Common.Traits
bool OnDockTick(Actor self, Actor hostActor, IDockHost dock);
void OnDockCompleted(Actor self, Actor hostActor, IDockHost host);
- /// Is this client allowed to dock.
+ /// Are we allowed to dock.
///
/// Does not check if is enabled.
/// Function should only be called from within or .
///
bool CanDock(BitSet type, bool forceEnter = false);
- /// Is this client allowed to dock to .
+ /// Are we allowed to dock to this .
///
/// Does not check if is enabled.
/// Function should only be called from within or .
///
bool CanDockAt(Actor hostActor, IDockHost host, bool forceEnter = false, bool ignoreOccupancy = false);
+
+ /// Are we allowed to give a docking order for this .
+ ///
+ /// Does not check if is enabled.
+ /// Function should only be called from within or .
+ ///
+ bool CanQueueDockAt(Actor hostActor, IDockHost host, bool forceEnter, bool isQueued);
}
public interface IDockHostInfo : ITraitInfoInterface { }