diff --git a/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs b/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs index a69088caa6..d39de8cd47 100644 --- a/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs +++ b/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs @@ -43,65 +43,14 @@ namespace OpenRA.Mods.Common.Warheads [Desc("Chance of impact sound to play.")] public readonly int ImpactSoundChance = 100; - [Desc("Consider explosion above this altitude an air explosion.", - "If that's the case, this warhead will consider the explosion position to have the 'Air' TargetType (in addition to any nearby actor's TargetTypes).")] + [Desc("Explosions above this altitude that don't impact an actor will check target validity against the 'TargetTypeAir' target types.")] public readonly WDist AirThreshold = new WDist(128); - [Desc("Whether to consider actors in determining whether the explosion should happen. If false, only terrain will be considered.")] - public readonly bool ImpactActors = true; - + [Desc("Target types to use when the warhead detonated at an altitude greater than 'AirThreshold'.")] static readonly BitSet TargetTypeAir = new BitSet("Air"); - public ImpactType GetImpactType(World world, CPos cell, WPos pos, Actor firedBy) - { - // Matching target actor - if (ImpactActors) - { - var targetType = GetDirectHitTargetType(world, cell, pos, firedBy, true); - if (targetType == ImpactTargetType.ValidActor) - return ImpactType.TargetHit; - if (targetType == ImpactTargetType.InvalidActor) - return ImpactType.None; - } - - var dat = world.Map.DistanceAboveTerrain(pos); - if (dat > AirThreshold) - return ImpactType.Air; - - return ImpactType.Ground; - } - - public ImpactTargetType GetDirectHitTargetType(World world, CPos cell, WPos pos, Actor firedBy, bool checkTargetValidity = false) - { - var victims = world.FindActorsOnCircle(pos, WDist.Zero); - var invalidHit = false; - - foreach (var victim in victims) - { - if (!AffectsParent && victim == firedBy) - continue; - - if (!victim.Info.HasTraitInfo()) - continue; - - // If the impact position is within any HitShape, we have a direct hit - var activeShapes = victim.TraitsImplementing().Where(Exts.IsTraitEnabled); - var directHit = activeShapes.Any(i => i.Info.Type.DistanceFromEdge(pos, victim).Length <= 0); - - // If the warhead landed outside the actor's hit-shape(s), we need to skip the rest so it won't be considered an invalidHit - if (!directHit) - continue; - - if (!checkTargetValidity || IsValidAgainst(victim, firedBy)) - return ImpactTargetType.ValidActor; - - // If we got here, it must be an invalid target - invalidHit = true; - } - - // If there was at least a single direct hit, but none on valid target(s), we return InvalidActor - return invalidHit ? ImpactTargetType.InvalidActor : ImpactTargetType.NoActor; - } + [Desc("Check for direct hits against nearby actors for use in the target validity checks.")] + public readonly bool ImpactActors = true; public override void DoImpact(Target target, Actor firedBy, IEnumerable damageModifiers) { @@ -123,11 +72,9 @@ namespace OpenRA.Mods.Common.Warheads var explosion = Explosions.RandomOrDefault(world.LocalRandom); if (Image != null && explosion != null) { + var dat = world.Map.DistanceAboveTerrain(pos); if (ForceDisplayAtGroundLevel) - { - var dat = world.Map.DistanceAboveTerrain(pos); - pos = new WPos(pos.X, pos.Y, pos.Z - dat.Length); - } + pos -= new WVec(0, 0, dat.Length); world.AddFrameEndTask(w => w.Add(new SpriteEffect(pos, w, Image, explosion, palette))); } @@ -140,23 +87,32 @@ namespace OpenRA.Mods.Common.Warheads public bool IsValidImpact(WPos pos, Actor firedBy) { var world = firedBy.World; + + if (ImpactActors) + { + // Check whether the explosion overlaps with an actor's hitshape + var potentialVictims = world.FindActorsOnCircle(pos, WDist.Zero); + foreach (var victim in potentialVictims) + { + if (!AffectsParent && victim == firedBy) + continue; + + var activeShapes = victim.TraitsImplementing().Where(Exts.IsTraitEnabled); + if (!activeShapes.Any(i => i.Info.Type.DistanceFromEdge(pos, victim).Length <= 0)) + continue; + + if (IsValidAgainst(victim, firedBy)) + return true; + } + } + var targetTile = world.Map.CellContaining(pos); if (!world.Map.Contains(targetTile)) return false; - var impactType = GetImpactType(world, targetTile, pos, firedBy); - switch (impactType) - { - case ImpactType.TargetHit: - return true; - case ImpactType.Air: - return IsValidTarget(TargetTypeAir); - case ImpactType.Ground: - var tileInfo = world.Map.GetTerrainInfo(targetTile); - return IsValidTarget(tileInfo.TargetTypes); - default: - return false; - } + var dat = world.Map.DistanceAboveTerrain(pos); + var tileInfo = world.Map.GetTerrainInfo(targetTile); + return IsValidTarget(dat > AirThreshold ? TargetTypeAir : tileInfo.TargetTypes); } } } diff --git a/OpenRA.Mods.Common/Warheads/Warhead.cs b/OpenRA.Mods.Common/Warheads/Warhead.cs index 5b60c3560a..fe672db9ad 100644 --- a/OpenRA.Mods.Common/Warheads/Warhead.cs +++ b/OpenRA.Mods.Common/Warheads/Warhead.cs @@ -15,14 +15,6 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Warheads { - public enum ImpactType - { - None, - Ground, - Air, - TargetHit - } - public enum ImpactTargetType { NoActor,