Skip to content

Commit

Permalink
Merge pull request #150 from dnqbob/fix-harv-ora
Browse files Browse the repository at this point in the history
Fix Harvester Automatically Unload On Allied Refinery
  • Loading branch information
MustaphaTR authored Feb 12, 2024
2 parents 86f28f9 + 024ca5f commit 1b6b69d
Show file tree
Hide file tree
Showing 14 changed files with 67 additions and 40 deletions.
4 changes: 2 additions & 2 deletions OpenRA.Mods.Common/Activities/GenericDockSequence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public override bool Tick(Actor self)
return false;

case DockingState.Drag:
if (IsCanceling || DockHostActor.IsDead || !DockHostActor.IsInWorld || !DockClient.CanDockAt(DockHostActor, DockHost, false, true))
if (IsCanceling || DockHostActor.IsDead || !DockHostActor.IsInWorld || !DockClient.CanDockAt(DockHostActor, DockHost, null, true))
{
DockClient.UnreserveHost();
return true;
Expand All @@ -89,7 +89,7 @@ public override bool Tick(Actor self)
return false;

case DockingState.Dock:
if (!IsCanceling && !DockHostActor.IsDead && DockHostActor.IsInWorld && DockClient.CanDockAt(DockHostActor, DockHost, false, true))
if (!IsCanceling && !DockHostActor.IsDead && DockHostActor.IsInWorld && DockClient.CanDockAt(DockHostActor, DockHost, null, true))
{
dockInitiated = true;
PlayDockAnimations(self);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@

namespace OpenRA.Mods.Common.Orders
{
public class EnterAlliedActorTargeter<T> : UnitOrderTargeter where T : ITraitInfoInterface
public class EnterActorTargeter<T> : UnitOrderTargeter where T : ITraitInfoInterface
{
readonly string enterCursor;
readonly string enterBlockedCursor;
readonly Func<Actor, TargetModifiers, bool> canTarget;
readonly Func<Actor, bool> useEnterCursor;

public EnterAlliedActorTargeter(string order, int priority, string enterCursor, string enterBlockedCursor,
public EnterActorTargeter(string order, int priority, string enterCursor, string enterBlockedCursor,
Func<Actor, TargetModifiers, bool> canTarget, Func<Actor, bool> useEnterCursor)
: base(order, priority, enterCursor, false, true)
{
Expand All @@ -33,7 +33,7 @@ public EnterAlliedActorTargeter(string order, int priority, string enterCursor,

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, modifiers))
if (!target.Info.HasTraitInfo<T>() || !canTarget(target, modifiers))
return false;

cursor = useEnterCursor(target) ? enterCursor : enterBlockedCursor;
Expand Down
8 changes: 4 additions & 4 deletions OpenRA.Mods.Common/Traits/Air/Aircraft.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1010,21 +1010,21 @@ public IEnumerable<IOrderTargeter> Orders
{
get
{
yield return new EnterAlliedActorTargeter<BuildingInfo>(
yield return new EnterActorTargeter<BuildingInfo>(
"ForceEnter",
6,
Info.EnterCursor,
Info.EnterBlockedCursor,
(target, modifiers) => Info.CanForceLand && modifiers.HasModifier(TargetModifiers.ForceMove) && AircraftCanEnter(target),
target => Reservable.IsAvailableFor(target, self) && AircraftCanResupplyAt(target, true));
target => self.Owner.IsAlliedWith(target.Owner) && Reservable.IsAvailableFor(target, self) && AircraftCanResupplyAt(target, true));

yield return new EnterAlliedActorTargeter<BuildingInfo>(
yield return new EnterActorTargeter<BuildingInfo>(
"Enter",
5,
Info.EnterCursor,
Info.EnterBlockedCursor,
AircraftCanEnter,
target => Reservable.IsAvailableFor(target, self) && AircraftCanResupplyAt(target, !Info.TakeOffOnResupply));
target => self.Owner.IsAlliedWith(target.Owner) && Reservable.IsAvailableFor(target, self) && AircraftCanResupplyAt(target, !Info.TakeOffOnResupply));

yield return new AircraftMoveOrderTargeter(this);
}
Expand Down
4 changes: 2 additions & 2 deletions OpenRA.Mods.Common/Traits/Buildings/TransformsIntoAircraft.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@ IEnumerable<IOrderTargeter> IIssueOrder.Orders
{
if (!IsTraitDisabled)
{
yield return new EnterAlliedActorTargeter<BuildingInfo>(
yield return new EnterActorTargeter<BuildingInfo>(
"Enter",
5,
Info.EnterCursor,
Info.EnterBlockedCursor,
AircraftCanEnter,
target => Reservable.IsAvailableFor(target, self));
target => self.Owner.IsAlliedWith(target.Owner) && Reservable.IsAvailableFor(target, self));

yield return new AircraftMoveOrderTargeter(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@ IEnumerable<IOrderTargeter> IIssueOrder.Orders
{
get
{
yield return new EnterAlliedActorTargeter<DockHostInfo>(
yield return new EnterActorTargeter<DockHostInfo>(
"ForceDock",
6,
Info.EnterCursor,
Info.EnterBlockedCursor,
ForceDockingPossible,
target => CanDockAt(target, true));
yield return new EnterAlliedActorTargeter<DockHostInfo>(
yield return new EnterActorTargeter<DockHostInfo>(
"Dock",
5,
Info.EnterCursor,
Expand Down Expand Up @@ -153,7 +153,7 @@ public bool ForceDockingPossible(Actor target, TargetModifiers modifiers)
return !IsTraitDisabled && target.TraitsImplementing<DockHost>().Any(host => dockClients.Any(client => client.IsDockingPossible(host.GetDockType, forceEnter)));
}

/// <summary>Clone of <see cref="DockClientManager.CanDockAt(Actor, bool, bool)"/>.</summary>
/// <summary>Clone of <see cref="DockClientManager.CanDockAt(Actor, bool?, bool)"/>.</summary>
public bool CanDockAt(Actor target, bool forceEnter = false)
{
if (!(self.CurrentActivity is Transform || transforms.Any(t => !t.IsTraitDisabled && !t.IsTraitPaused)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ IEnumerable<IOrderTargeter> IIssueOrder.Orders
get
{
if (!IsTraitDisabled)
yield return new EnterAlliedActorTargeter<CargoInfo>(
yield return new EnterActorTargeter<CargoInfo>(
"EnterTransport",
5,
Info.EnterCursor,
Info.EnterBlockedCursor,
IsCorrectCargoType,
CanEnter);
target => self.Owner.IsAlliedWith(target.Owner) && CanEnter(target));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@ IEnumerable<IOrderTargeter> IIssueOrder.Orders
get
{
if (!IsTraitDisabled)
yield return new EnterAlliedActorTargeter<BuildingInfo>(
yield return new EnterActorTargeter<BuildingInfo>(
"Repair",
5,
Info.EnterCursor,
Info.EnterBlockedCursor,
CanRepairAt,
_ => CanRepair());
target => self.Owner.IsAlliedWith(target.Owner) && CanRepair());
}
}

Expand Down
33 changes: 28 additions & 5 deletions OpenRA.Mods.Common/Traits/DockClientBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,63 @@
*/
#endregion

using System;
using OpenRA.Primitives;
using OpenRA.Traits;

namespace OpenRA.Mods.Common.Traits
{
public abstract class DockClientBaseInfo : ConditionalTraitInfo, IDockClientInfo, Requires<IDockClientManagerInfo> { }
public abstract class DockClientBaseInfo : ConditionalTraitInfo, IDockClientInfo, Requires<IDockClientManagerInfo>
{
[Desc("Player relationships the owner of the dock host needs, when not forced enter.",
"Use None to only allow the same owner.")]
public readonly PlayerRelationship DockRelationships = PlayerRelationship.None;

[Desc("Player relationships the owner of the dock host needs, when forced enter.",
"Use None to only allow the same owner.")]
public readonly PlayerRelationship ForceDockRelationships = PlayerRelationship.Ally;
}

public abstract class DockClientBase<InfoType> : ConditionalTrait<InfoType>, IDockClient, INotifyCreated where InfoType : DockClientBaseInfo
{
readonly Actor self;

public abstract BitSet<DockType> GetDockType { get; }
public DockClientManager DockClientManager { get; }
readonly Predicate<Actor> hasDockRelationshipWith;
readonly Predicate<Actor> hasDockForcedRelationshipWith;

protected DockClientBase(Actor self, InfoType info)
: base(info)
{
this.self = self;
DockClientManager = self.TraitOrDefault<DockClientManager>();

if (info.DockRelationships == PlayerRelationship.None)
hasDockRelationshipWith = a => a.Owner == self.Owner;
else
hasDockRelationshipWith = a => info.DockRelationships.HasRelationship(a.Owner.RelationshipWith(self.Owner));

if (info.ForceDockRelationships == PlayerRelationship.None)
hasDockForcedRelationshipWith = a => a.Owner == self.Owner;
else
hasDockForcedRelationshipWith = a => info.ForceDockRelationships.HasRelationship(a.Owner.RelationshipWith(self.Owner));
}

protected virtual bool CanDock()
{
return true;
}

public virtual bool IsDockingPossible(BitSet<DockType> type, bool forceEnter = false)
public virtual bool IsDockingPossible(BitSet<DockType> type, bool? forceEnter = false)
{
return !IsTraitDisabled && GetDockType.Overlaps(type) && (forceEnter || CanDock());
return !IsTraitDisabled && GetDockType.Overlaps(type) && (!forceEnter.HasValue || forceEnter.Value || CanDock());
}

public virtual bool CanDockAt(Actor hostActor, IDockHost host, bool forceEnter = false, bool ignoreOccupancy = false)
public virtual bool CanDockAt(Actor hostActor, IDockHost host, bool? forceEnter = false, bool ignoreOccupancy = false)
{
return (forceEnter || self.Owner.IsAlliedWith(hostActor.Owner)) && IsDockingPossible(host.GetDockType, forceEnter) && host.IsDockingPossible(self, this, ignoreOccupancy);
return (forceEnter.HasValue ? (forceEnter.Value ? hasDockForcedRelationshipWith(hostActor) : hasDockRelationshipWith(hostActor)) : (hasDockForcedRelationshipWith(hostActor) || hasDockRelationshipWith(hostActor)))
&& IsDockingPossible(host.GetDockType, forceEnter) && host.IsDockingPossible(self, this, ignoreOccupancy);
}

public virtual void OnDockStarted(Actor self, Actor hostActor, IDockHost host) { }
Expand Down
14 changes: 7 additions & 7 deletions OpenRA.Mods.Common/Traits/DockClientManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,14 @@ IEnumerable<IOrderTargeter> IIssueOrder.Orders
{
get
{
yield return new EnterAlliedActorTargeter<IDockHostInfo>(
yield return new EnterActorTargeter<IDockHostInfo>(
"ForceDock",
6,
Info.EnterCursor,
Info.EnterBlockedCursor,
DockingPossible,
target => CanDockAt(target, true, true));
yield return new EnterAlliedActorTargeter<IDockHostInfo>(
yield return new EnterActorTargeter<IDockHostInfo>(
"Dock",
5,
Info.EnterCursor,
Expand Down Expand Up @@ -232,7 +232,7 @@ Order IIssueOrder.IssueOrder(Actor self, IOrderTargeter order, in Target target,
}

/// <summary>Do we have an enabled client with matching <paramref name="type"/>.</summary>
public bool DockingPossible(BitSet<DockType> type, bool forceEnter = false)
public bool DockingPossible(BitSet<DockType> type, bool? forceEnter = false)
{
return !IsTraitDisabled && dockClients.Any(client => client.IsDockingPossible(type, forceEnter));
}
Expand All @@ -251,20 +251,20 @@ public bool DockingPossible(Actor target, TargetModifiers modifiers)
}

/// <summary>Can we dock to this <paramref name="host"/>.</summary>
public bool CanDockAt(Actor hostActor, IDockHost host, bool forceEnter = false, bool ignoreOccupancy = false)
public bool CanDockAt(Actor hostActor, IDockHost host, bool? forceEnter = false, bool ignoreOccupancy = false)
{
return !IsTraitDisabled && dockClients.Any(client => client.CanDockAt(hostActor, host, forceEnter, ignoreOccupancy));
}

/// <summary>Can we dock to this <paramref name="target"/>.</summary>
public bool CanDockAt(Actor target, bool forceEnter = false, bool ignoreOccupancy = false)
public bool CanDockAt(Actor target, bool? forceEnter = false, bool ignoreOccupancy = false)
{
return !IsTraitDisabled && target.TraitsImplementing<IDockHost>().Any(host => dockClients.Any(client => client.CanDockAt(target, host, forceEnter, ignoreOccupancy)));
}

/// <summary>Find the closest viable <see cref="IDockHost"/>.</summary>
/// <remarks>If <paramref name="type"/> is not set, scans all clients. Does not check if <see cref="DockClientManager"/> is enabled.</remarks>
public TraitPair<IDockHost>? ClosestDock(IDockHost ignore, BitSet<DockType> type = default, bool forceEnter = false, bool ignoreOccupancy = false)
public TraitPair<IDockHost>? ClosestDock(IDockHost ignore, BitSet<DockType> type = default, bool? forceEnter = false, bool ignoreOccupancy = false)
{
var clients = type.IsEmpty ? dockClients : AvailableDockClients(type);
return self.World.ActorsWithTrait<IDockHost>()
Expand All @@ -274,7 +274,7 @@ public bool CanDockAt(Actor target, bool forceEnter = false, bool ignoreOccupanc

/// <summary>Get viable <see cref="IDockHost"/>'s on the <paramref name="target"/>.</summary>
/// <remarks>Does not check if <see cref="DockClientManager"/> is enabled.</remarks>
public IEnumerable<TraitPair<IDockHost>> AvailableDockHosts(Actor target, bool forceEnter = false, bool ignoreOccupancy = false)
public IEnumerable<TraitPair<IDockHost>> AvailableDockHosts(Actor target, bool? forceEnter = false, bool ignoreOccupancy = false)
{
return target.TraitsImplementing<IDockHost>()
.Where(host => dockClients.Any(client => client.CanDockAt(target, host, forceEnter, ignoreOccupancy)))
Expand Down
10 changes: 6 additions & 4 deletions OpenRA.Mods.Common/Traits/Passenger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,21 +58,23 @@ public class PassengerInfo : TraitInfo, IObservesVariablesInfo
[Desc("Cursor to display when unable to enter target actor.")]
public readonly string EnterBlockedCursor = "enter-blocked";

public override object Create(ActorInitializer init) { return new Passenger(this); }
public override object Create(ActorInitializer init) { return new Passenger(this, init.Self); }
}

public class Passenger : IIssueOrder, IResolveOrder, IOrderVoice, INotifyRemovedFromWorld, INotifyEnteredCargo, INotifyExitedCargo, INotifyKilled, IObservesVariables
{
public readonly PassengerInfo Info;
public Actor Transport;
readonly Actor self;
bool requireForceMove;

int anyCargoToken = Actor.InvalidConditionToken;
int specificCargoToken = Actor.InvalidConditionToken;

public Passenger(PassengerInfo info)
public Passenger(PassengerInfo info, Actor self)
{
Info = info;
this.self = self;
}

public Cargo ReservedCargo { get; private set; }
Expand All @@ -81,13 +83,13 @@ IEnumerable<IOrderTargeter> IIssueOrder.Orders
{
get
{
yield return new EnterAlliedActorTargeter<CargoInfo>(
yield return new EnterActorTargeter<CargoInfo>(
"EnterTransport",
5,
Info.EnterCursor,
Info.EnterBlockedCursor,
IsCorrectCargoType,
CanEnter);
target => self.Owner.IsAlliedWith(target.Owner) && CanEnter(target));
}
}

Expand Down
6 changes: 4 additions & 2 deletions OpenRA.Mods.Common/Traits/Repairable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public class Repairable : IIssueOrder, IResolveOrder, IOrderVoice, INotifyCreate
{
public readonly RepairableInfo Info;
readonly IHealth health;
readonly Actor self;
Rearmable rearmable;
bool requireForceMove;
bool isAircraft;
Expand All @@ -58,6 +59,7 @@ public Repairable(Actor self, RepairableInfo info)
{
Info = info;
health = self.Trait<IHealth>();
this.self = self;
}

void INotifyCreated.Created(Actor self)
Expand All @@ -71,13 +73,13 @@ IEnumerable<IOrderTargeter> IIssueOrder.Orders
get
{
if (!isAircraft)
yield return new EnterAlliedActorTargeter<BuildingInfo>(
yield return new EnterActorTargeter<BuildingInfo>(
"Repair",
5,
Info.EnterCursor,
Info.EnterBlockedCursor,
CanRepairAt,
_ => CanRepair() || CanRearm());
target => self.Owner.IsAlliedWith(target.Owner) && (CanRepair() || CanRearm()));
}
}

Expand Down
4 changes: 2 additions & 2 deletions OpenRA.Mods.Common/Traits/RepairableNear.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,13 @@ IEnumerable<IOrderTargeter> IIssueOrder.Orders
{
get
{
yield return new EnterAlliedActorTargeter<BuildingInfo>(
yield return new EnterActorTargeter<BuildingInfo>(
"RepairNear",
5,
Info.EnterCursor,
Info.EnterBlockedCursor,
CanRepairAt,
_ => ShouldRepair());
target => self.Owner.IsAlliedWith(target.Owner) && ShouldRepair());
}
}

Expand Down
4 changes: 2 additions & 2 deletions OpenRA.Mods.Common/TraitsInterfaces.cs
Original file line number Diff line number Diff line change
Expand Up @@ -225,14 +225,14 @@ public interface IDockClient
/// Does not check if <see cref="Traits.DockClientManager"/> is enabled.
/// Function should only be called from within <see cref="IDockClient"/> or <see cref="Traits.DockClientManager"/>.
/// </remarks>
bool IsDockingPossible(BitSet<DockType> type, bool forceEnter = false);
bool IsDockingPossible(BitSet<DockType> type, bool? forceEnter = false);

/// <summary>Is this client allowed to dock to <paramref name="host"/>.</summary>
/// <remarks>
/// Does not check if <see cref="Traits.DockClientManager"/> is enabled.
/// Function should only be called from within <see cref="IDockClient"/> or <see cref="Traits.DockClientManager"/>.
/// </remarks>
bool CanDockAt(Actor hostActor, IDockHost host, bool forceEnter = false, bool ignoreOccupancy = false);
bool CanDockAt(Actor hostActor, IDockHost host, bool? forceEnter = false, bool ignoreOccupancy = false);
}

public interface IDockHostInfo : ITraitInfoInterface { }
Expand Down
Binary file added mods/ra/maps/test-harv.oramap
Binary file not shown.

0 comments on commit 1b6b69d

Please sign in to comment.