Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moved impact actor type and validity against terrain to Warhead #18777

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 0 additions & 40 deletions OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs
Expand Up @@ -43,35 +43,6 @@ public class CreateEffectWarhead : Warhead
[Desc("Chance of impact sound to play.")]
public readonly int ImpactSoundChance = 100;

[Desc("Whether to consider actors in determining whether the explosion should happen. If false, only terrain will be considered.")]
public readonly bool ImpactActors = true;

static readonly BitSet<TargetableType> TargetTypeAir = new BitSet<TargetableType>("Air");

/// <summary>Checks if there are any actors at impact position and if the warhead is valid against any of them.</summary>
ImpactActorType ActorTypeAtImpact(World world, WPos pos, Actor firedBy)
{
var anyInvalidActor = false;

// Check whether the impact position overlaps with an actor's hitshape
foreach (var victim in world.FindActorsOnCircle(pos, WDist.Zero))
{
if (!AffectsParent && victim == firedBy)
continue;

var activeShapes = victim.TraitsImplementing<HitShape>().Where(Exts.IsTraitEnabled);
if (!activeShapes.Any(s => s.DistanceFromEdge(victim, pos).Length <= 0))
continue;

if (IsValidAgainst(victim, firedBy))
return ImpactActorType.Valid;

anyInvalidActor = true;
}

return anyInvalidActor ? ImpactActorType.Invalid : ImpactActorType.None;
}

// ActorTypeAtImpact already checks AffectsParent beforehand, to avoid parent HitShape look-ups
// (and to prevent returning ImpactActorType.Invalid on AffectsParent=false)
public override bool IsValidAgainst(Actor victim, Actor firedBy)
Expand Down Expand Up @@ -126,16 +97,5 @@ public override void DoImpact(Target target, WarheadArgs args)
if (impactSound != null && world.LocalRandom.Next(0, 100) < ImpactSoundChance)
Game.Sound.Play(SoundType.World, impactSound, pos);
}

/// <summary>Checks if the warhead is valid against the terrain at impact position.</summary>
bool IsValidAgainstTerrain(World world, WPos pos)
{
var cell = world.Map.CellContaining(pos);
if (!world.Map.Contains(cell))
return false;

var dat = world.Map.DistanceAboveTerrain(pos);
return IsValidTarget(dat > AirThreshold ? TargetTypeAir : world.Map.GetTerrainInfo(cell).TargetTypes);
}
}
}
43 changes: 43 additions & 0 deletions OpenRA.Mods.Common/Warheads/Warhead.cs
Expand Up @@ -9,7 +9,9 @@
*/
#endregion

using System.Linq;
using OpenRA.GameRules;
using OpenRA.Mods.Common.Traits;
using OpenRA.Primitives;
using OpenRA.Traits;

Expand Down Expand Up @@ -45,6 +47,11 @@ public abstract class Warhead : IWarhead

int IWarhead.Delay { get { return Delay; } }

static readonly BitSet<TargetableType> TargetTypeAir = new BitSet<TargetableType>("Air");

[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("The color used for this warhead's visualization in the world's `WarheadDebugOverlay` trait.")]
public readonly Color DebugOverlayColor = Color.Red;

Expand Down Expand Up @@ -90,5 +97,41 @@ public bool IsValidAgainst(FrozenActor victim, Actor firedBy)

return true;
}

/// <summary>Checks if there are any actors at impact position and if the warhead is valid against any of them.</summary>
protected ImpactActorType ActorTypeAtImpact(World world, WPos pos, Actor firedBy)
{
var anyInvalidActor = false;

// Check whether the impact position 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<HitShape>().Where(Exts.IsTraitEnabled);
if (!activeShapes.Any(s => s.DistanceFromEdge(victim, pos).Length <= 0))
continue;

if (IsValidAgainst(victim, firedBy))
return ImpactActorType.Valid;

anyInvalidActor = true;
}

return anyInvalidActor ? ImpactActorType.Invalid : ImpactActorType.None;
}

/// <summary>Checks if the warhead is valid against the terrain at impact position.</summary>
protected bool IsValidAgainstTerrain(World world, WPos pos)
{
var cell = world.Map.CellContaining(pos);
if (!world.Map.Contains(cell))
return false;

var dat = world.Map.DistanceAboveTerrain(pos);
return IsValidTarget(dat > AirThreshold ? TargetTypeAir : world.Map.GetTerrainInfo(cell).TargetTypes);
}
}
}