From d830bca706cd40e2a2fba36495a45168519940d1 Mon Sep 17 00:00:00 2001 From: abcdefg30 Date: Thu, 9 Jun 2022 14:41:50 +0200 Subject: [PATCH] Fix force fire opportunity targets not being persisted properly --- OpenRA.Game/Traits/Target.cs | 65 +++++++++++++++++++ .../Traits/Attack/AttackFollow.cs | 4 ++ 2 files changed, 69 insertions(+) diff --git a/OpenRA.Game/Traits/Target.cs b/OpenRA.Game/Traits/Target.cs index 61a8952eb4..8a9fcb1a92 100644 --- a/OpenRA.Game/Traits/Target.cs +++ b/OpenRA.Game/Traits/Target.cs @@ -224,6 +224,71 @@ namespace OpenRA.Traits } } + public static bool operator ==(in Target me, in Target other) + { + if (me.type != other.type) + return false; + + switch (me.type) + { + case TargetType.Terrain: + return me.terrainCenterPosition == other.terrainCenterPosition + && me.terrainPositions == other.terrainPositions + && me.cell == other.cell && me.subCell == other.subCell; + + case TargetType.Actor: + return me.Actor == other.Actor && me.generation == other.generation; + + case TargetType.FrozenActor: + return me.FrozenActor == other.FrozenActor; + + default: + case TargetType.Invalid: + return false; + } + } + + public static bool operator !=(in Target me, in Target other) + { + return !(me == other); + } + + public override int GetHashCode() + { + switch (type) + { + case TargetType.Terrain: + var hash = terrainCenterPosition.GetHashCode() ^ terrainPositions.GetHashCode(); + if (cell != null) + hash ^= cell.GetHashCode(); + + if (subCell != null) + hash ^= subCell.GetHashCode(); + + return hash; + + case TargetType.Actor: + return Actor.GetHashCode() ^ generation.GetHashCode(); + + case TargetType.FrozenActor: + return FrozenActor.GetHashCode(); + + default: + case TargetType.Invalid: + return 0; + } + } + + public bool Equals(Target other) + { + return other == this; + } + + public override bool Equals(object other) + { + return other is Target t && t == this; + } + // Expose internal state for serialization by the orders code *only* internal static Target FromSerializedActor(Actor a, int generation) { return a != null ? new Target(a, generation) : Invalid; } internal TargetType SerializableType => type; diff --git a/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs b/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs index 2f847776b7..71e580883a 100644 --- a/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs +++ b/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs @@ -156,6 +156,10 @@ namespace OpenRA.Mods.Common.Traits public override Activity GetAttackActivity(Actor self, AttackSource source, in Target newTarget, bool allowMove, bool forceAttack, Color? targetLineColor = null) { + // HACK: Manually set force attacking if we persisted an opportunity target that required force attacking + if (opportunityTargetIsPersistentTarget && opportunityForceAttack && newTarget == OpportunityTarget) + forceAttack = true; + return new AttackActivity(self, newTarget, allowMove, forceAttack, targetLineColor); }