Simplify CreateEffectWarhead

This commit is contained in:
reaperrr
2019-03-15 03:40:49 +01:00
committed by Paul Chote
parent 78a70be0d4
commit 3735c60533
2 changed files with 28 additions and 80 deletions

View File

@@ -43,65 +43,14 @@ namespace OpenRA.Mods.Common.Warheads
[Desc("Chance of impact sound to play.")] [Desc("Chance of impact sound to play.")]
public readonly int ImpactSoundChance = 100; public readonly int ImpactSoundChance = 100;
[Desc("Consider explosion above this altitude an air explosion.", [Desc("Explosions above this altitude that don't impact an actor will check target validity against the 'TargetTypeAir' target types.")]
"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).")]
public readonly WDist AirThreshold = new WDist(128); 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.")] [Desc("Target types to use when the warhead detonated at an altitude greater than 'AirThreshold'.")]
public readonly bool ImpactActors = true;
static readonly BitSet<TargetableType> TargetTypeAir = new BitSet<TargetableType>("Air"); static readonly BitSet<TargetableType> TargetTypeAir = new BitSet<TargetableType>("Air");
public ImpactType GetImpactType(World world, CPos cell, WPos pos, Actor firedBy) [Desc("Check for direct hits against nearby actors for use in the target validity checks.")]
{ public readonly bool ImpactActors = true;
// 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<IHealthInfo>())
continue;
// If the impact position is within any HitShape, we have a direct hit
var activeShapes = victim.TraitsImplementing<HitShape>().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;
}
public override void DoImpact(Target target, Actor firedBy, IEnumerable<int> damageModifiers) public override void DoImpact(Target target, Actor firedBy, IEnumerable<int> damageModifiers)
{ {
@@ -123,11 +72,9 @@ namespace OpenRA.Mods.Common.Warheads
var explosion = Explosions.RandomOrDefault(world.LocalRandom); var explosion = Explosions.RandomOrDefault(world.LocalRandom);
if (Image != null && explosion != null) if (Image != null && explosion != null)
{ {
var dat = world.Map.DistanceAboveTerrain(pos);
if (ForceDisplayAtGroundLevel) if (ForceDisplayAtGroundLevel)
{ pos -= new WVec(0, 0, dat.Length);
var dat = world.Map.DistanceAboveTerrain(pos);
pos = new WPos(pos.X, pos.Y, pos.Z - dat.Length);
}
world.AddFrameEndTask(w => w.Add(new SpriteEffect(pos, w, Image, explosion, palette))); 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) public bool IsValidImpact(WPos pos, Actor firedBy)
{ {
var world = firedBy.World; 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<HitShape>().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); var targetTile = world.Map.CellContaining(pos);
if (!world.Map.Contains(targetTile)) if (!world.Map.Contains(targetTile))
return false; return false;
var impactType = GetImpactType(world, targetTile, pos, firedBy); var dat = world.Map.DistanceAboveTerrain(pos);
switch (impactType) var tileInfo = world.Map.GetTerrainInfo(targetTile);
{ return IsValidTarget(dat > AirThreshold ? TargetTypeAir : tileInfo.TargetTypes);
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;
}
} }
} }
} }

View File

@@ -15,14 +15,6 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Warheads namespace OpenRA.Mods.Common.Warheads
{ {
public enum ImpactType
{
None,
Ground,
Air,
TargetHit
}
public enum ImpactTargetType public enum ImpactTargetType
{ {
NoActor, NoActor,