diff --git a/OpenRA.Mods.Common/Activities/Attack.cs b/OpenRA.Mods.Common/Activities/Attack.cs index 20ca4ed63c..c3d701f7f3 100644 --- a/OpenRA.Mods.Common/Activities/Attack.cs +++ b/OpenRA.Mods.Common/Activities/Attack.cs @@ -114,7 +114,7 @@ namespace OpenRA.Mods.Common.Activities return NextActivity; } - var targetedPosition = attack.Info.AttackTargetCenter ? Target.CenterPosition : Target.Positions.PositionClosestTo(pos); + var targetedPosition = attack.GetTargetPosition(pos, Target); var desiredFacing = (targetedPosition - pos).Yaw.Facing; if (facing.Facing != desiredFacing) { diff --git a/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs b/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs index 6749ec6d8e..3626defbf7 100644 --- a/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs +++ b/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs @@ -24,9 +24,6 @@ namespace OpenRA.Mods.Common.Traits [Desc("Armament names")] public readonly string[] Armaments = { "primary", "secondary" }; - [Desc("Attack the target's center, instead of the closest targetable offset.")] - public readonly bool AttackTargetCenter = false; - public readonly string Cursor = null; public readonly string OutsideRangeCursor = null; @@ -211,12 +208,37 @@ namespace OpenRA.Mods.Common.Traits // PERF: Avoid LINQ. foreach (var armament in Armaments) + { if (!armament.OutOfAmmo && armament.Weapon.IsValidAgainst(t, self.World, self)) return true; + } return false; } + public bool HasAnyValidCenterTargetingWeapons(Target t) + { + if (IsTraitDisabled) + return false; + + if (Info.AttackRequiresEnteringCell && (positionable == null || !positionable.CanEnterCell(t.Actor.Location, null, false))) + return false; + + // PERF: Avoid LINQ. + foreach (var armament in Armaments) + { + if (armament.Weapon.TargetActorCenter && armament.Weapon.IsValidAgainst(t, self.World, self)) + return true; + } + + return false; + } + + public virtual WPos GetTargetPosition(WPos pos, Target target) + { + return HasAnyValidCenterTargetingWeapons(target) ? target.CenterPosition : target.Positions.PositionClosestTo(pos); + } + public WDist GetMinimumRange() { if (IsTraitDisabled) diff --git a/OpenRA.Mods.Common/Traits/Attack/AttackFrontal.cs b/OpenRA.Mods.Common/Traits/Attack/AttackFrontal.cs index b516eea19b..c71646e07e 100644 --- a/OpenRA.Mods.Common/Traits/Attack/AttackFrontal.cs +++ b/OpenRA.Mods.Common/Traits/Attack/AttackFrontal.cs @@ -40,7 +40,7 @@ namespace OpenRA.Mods.Common.Traits var f = facing.Facing; var pos = self.CenterPosition; - var targetedPosition = Info.AttackTargetCenter ? target.CenterPosition : target.Positions.PositionClosestTo(pos); + var targetedPosition = GetTargetPosition(pos, target); var delta = targetedPosition - pos; var facingToTarget = delta.HorizontalLengthSquared != 0 ? delta.Yaw.Facing : f; diff --git a/OpenRA.Mods.Common/Traits/Attack/AttackGarrisoned.cs b/OpenRA.Mods.Common/Traits/Attack/AttackGarrisoned.cs index 2bd34d93cc..a9c418cc36 100644 --- a/OpenRA.Mods.Common/Traits/Attack/AttackGarrisoned.cs +++ b/OpenRA.Mods.Common/Traits/Attack/AttackGarrisoned.cs @@ -146,7 +146,7 @@ namespace OpenRA.Mods.Common.Traits return; var pos = self.CenterPosition; - var targetedPosition = Info.AttackTargetCenter ? target.CenterPosition : target.Positions.PositionClosestTo(pos); + var targetedPosition = GetTargetPosition(pos, target); var targetYaw = (targetedPosition - pos).Yaw; foreach (var a in Armaments) diff --git a/OpenRA.Mods.Common/Traits/Turreted.cs b/OpenRA.Mods.Common/Traits/Turreted.cs index c94a589c94..20de835ebe 100644 --- a/OpenRA.Mods.Common/Traits/Turreted.cs +++ b/OpenRA.Mods.Common/Traits/Turreted.cs @@ -131,7 +131,7 @@ namespace OpenRA.Mods.Common.Traits return false; var pos = self.CenterPosition; - var targetPos = attack != null && attack.Info.AttackTargetCenter ? target.CenterPosition : target.Positions.PositionClosestTo(pos); + var targetPos = attack != null ? attack.GetTargetPosition(pos, target) : target.CenterPosition; var delta = targetPos - pos; DesiredFacing = delta.HorizontalLengthSquared != 0 ? delta.Yaw.Facing : TurretFacing; MoveTurret(); diff --git a/mods/cnc/rules/vehicles.yaml b/mods/cnc/rules/vehicles.yaml index 2ddd3807a4..b6696cf697 100644 --- a/mods/cnc/rules/vehicles.yaml +++ b/mods/cnc/rules/vehicles.yaml @@ -156,7 +156,6 @@ ARTY: LocalOffset: 624,0,208 MuzzleSequence: muzzle AttackFrontal: - AttackTargetCenter: true WithMuzzleOverlay: AutoTarget: InitialStanceAI: Defend @@ -473,7 +472,6 @@ MSAM: Weapon: 227mm LocalOffset: 213,-128,0, 213,128,0 AttackFrontal: - AttackTargetCenter: true WithSpriteTurret: AimSequence: aim SpawnActorOnDeath: diff --git a/mods/ra/rules/ships.yaml b/mods/ra/rules/ships.yaml index 68cc39b1f7..27215a99dc 100644 --- a/mods/ra/rules/ships.yaml +++ b/mods/ra/rules/ships.yaml @@ -113,7 +113,6 @@ MSUB: LocalOffset: 0,-171,0, 0,171,0 FireDelay: 2 AttackFrontal: - AttackTargetCenter: true SelectionDecorations: VisualBounds: 44,44 AutoTarget: @@ -226,7 +225,6 @@ CA: RecoilRecovery: 34 MuzzleSequence: muzzle AttackTurreted: - AttackTargetCenter: true WithMuzzleOverlay: SelectionDecorations: VisualBounds: 44,44 diff --git a/mods/ra/rules/vehicles.yaml b/mods/ra/rules/vehicles.yaml index 9ee00f83da..2ac32e40d5 100644 --- a/mods/ra/rules/vehicles.yaml +++ b/mods/ra/rules/vehicles.yaml @@ -243,7 +243,6 @@ ARTY: LocalOffset: 624,0,208 MuzzleSequence: muzzle AttackFrontal: - AttackTargetCenter: true WithMuzzleOverlay: Explodes: Weapon: ArtilleryExplode diff --git a/mods/ts/rules/gdi-vehicles.yaml b/mods/ts/rules/gdi-vehicles.yaml index 1ad6c981b4..836f530050 100644 --- a/mods/ts/rules/gdi-vehicles.yaml +++ b/mods/ts/rules/gdi-vehicles.yaml @@ -357,7 +357,6 @@ JUGG: Voice: Attack Armaments: deployed RequiresCondition: deployed - AttackTargetCenter: true Armament@deployed: Name: deployed Turret: deployed