Make projectiles use most sensible blocker scan radius

By default, but allow custom overrides.
This commit is contained in:
reaperrr
2017-01-20 15:20:35 +01:00
committed by Chris Forbes
parent 9f9d1f9e5f
commit 033268a7ba
5 changed files with 77 additions and 28 deletions

View File

@@ -22,7 +22,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Projectiles namespace OpenRA.Mods.Common.Projectiles
{ {
public class AreaBeamInfo : IProjectileInfo public class AreaBeamInfo : IProjectileInfo, IRulesetLoaded<WeaponInfo>
{ {
[Desc("Projectile speed in WDist / tick, two values indicate a randomly picked velocity per beam.")] [Desc("Projectile speed in WDist / tick, two values indicate a randomly picked velocity per beam.")]
public readonly WDist[] Speed = { new WDist(128) }; public readonly WDist[] Speed = { new WDist(128) };
@@ -57,9 +57,6 @@ namespace OpenRA.Mods.Common.Projectiles
[Desc("Does the beam follow the target.")] [Desc("Does the beam follow the target.")]
public readonly bool TrackTarget = false; public readonly bool TrackTarget = false;
[Desc("Extra search radius beyond beam width. Required to ensure affecting actors with large health radius.")]
public readonly WDist TargetExtraSearchRadius = new WDist(1536);
[Desc("Should the beam be visually rendered? False = Beam is invisible.")] [Desc("Should the beam be visually rendered? False = Beam is invisible.")]
public readonly bool RenderBeam = true; public readonly bool RenderBeam = true;
@@ -72,11 +69,28 @@ namespace OpenRA.Mods.Common.Projectiles
[Desc("Beam color is the player's color.")] [Desc("Beam color is the player's color.")]
public readonly bool UsePlayerColor = false; public readonly bool UsePlayerColor = false;
[Desc("Scan radius for actors with projectile-blocking trait. If set to zero (default), it will automatically scale",
"to the blocker with the largest health shape. Only set custom values if you know what you're doing.")]
public WDist BlockerScanRadius = WDist.Zero;
[Desc("Scan radius for actors damaged by beam. If set to zero (default), it will automatically scale to the largest health shape.",
"Only set custom values if you know what you're doing.")]
public WDist AreaVictimScanRadius = WDist.Zero;
public IProjectile Create(ProjectileArgs args) public IProjectile Create(ProjectileArgs args)
{ {
var c = UsePlayerColor ? args.SourceActor.Owner.Color.RGB : Color; var c = UsePlayerColor ? args.SourceActor.Owner.Color.RGB : Color;
return new AreaBeam(this, args, c); return new AreaBeam(this, args, c);
} }
public void RulesetLoaded(Ruleset rules, WeaponInfo wi)
{
if (BlockerScanRadius == WDist.Zero)
BlockerScanRadius = Util.MinimumRequiredBlockerScanRadius(rules);
if (AreaVictimScanRadius == WDist.Zero)
AreaVictimScanRadius = Util.MinimumRequiredVictimScanRadius(rules);
}
} }
public class AreaBeam : IProjectile, ISync public class AreaBeam : IProjectile, ISync
@@ -211,7 +225,7 @@ namespace OpenRA.Mods.Common.Projectiles
// Check for blocking actors // Check for blocking actors
WPos blockedPos; WPos blockedPos;
if (info.Blockable && BlocksProjectiles.AnyBlockingActorsBetween(world, tailPos, headPos, if (info.Blockable && BlocksProjectiles.AnyBlockingActorsBetween(world, tailPos, headPos,
info.Width, info.TargetExtraSearchRadius, out blockedPos)) info.Width, info.BlockerScanRadius, out blockedPos))
{ {
headPos = blockedPos; headPos = blockedPos;
target = headPos; target = headPos;
@@ -221,7 +235,7 @@ namespace OpenRA.Mods.Common.Projectiles
// Damage is applied to intersected actors every DamageInterval ticks // Damage is applied to intersected actors every DamageInterval ticks
if (headTicks % info.DamageInterval == 0) if (headTicks % info.DamageInterval == 0)
{ {
var actors = world.FindActorsOnLine(tailPos, headPos, info.Width, info.TargetExtraSearchRadius); var actors = world.FindActorsOnLine(tailPos, headPos, info.Width, info.AreaVictimScanRadius);
foreach (var a in actors) foreach (var a in actors)
{ {
var adjustedModifiers = args.DamageModifiers.Append(GetFalloff((args.Source - a.CenterPosition).Length)); var adjustedModifiers = args.DamageModifiers.Append(GetFalloff((args.Source - a.CenterPosition).Length));

View File

@@ -22,7 +22,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Projectiles namespace OpenRA.Mods.Common.Projectiles
{ {
public class BulletInfo : IProjectileInfo public class BulletInfo : IProjectileInfo, IRulesetLoaded<WeaponInfo>
{ {
[Desc("Projectile speed in WDist / tick, two values indicate variable velocity.")] [Desc("Projectile speed in WDist / tick, two values indicate variable velocity.")]
public readonly WDist[] Speed = { new WDist(17) }; public readonly WDist[] Speed = { new WDist(17) };
@@ -57,9 +57,6 @@ namespace OpenRA.Mods.Common.Projectiles
[Desc("Width of projectile (used for finding blocking actors).")] [Desc("Width of projectile (used for finding blocking actors).")]
public readonly WDist Width = new WDist(1); public readonly WDist Width = new WDist(1);
[Desc("Extra search radius beyond path for blocking actors.")]
public readonly WDist TargetExtraSearchRadius = new WDist(1536);
[Desc("Arc in WAngles, two values indicate variable arc.")] [Desc("Arc in WAngles, two values indicate variable arc.")]
public readonly WAngle[] LaunchAngle = { WAngle.Zero }; public readonly WAngle[] LaunchAngle = { WAngle.Zero };
@@ -95,7 +92,24 @@ namespace OpenRA.Mods.Common.Projectiles
public readonly int ContrailDelay = 1; public readonly int ContrailDelay = 1;
public readonly WDist ContrailWidth = new WDist(64); public readonly WDist ContrailWidth = new WDist(64);
[Desc("Scan radius for actors with projectile-blocking trait. If set to zero (default), it will automatically scale",
"to the blocker with the largest health shape. Only set custom values if you know what you're doing.")]
public WDist BlockerScanRadius = WDist.Zero;
[Desc("Extra search radius beyond path for actors with ValidBounceBlockerStances. If set to zero (default), ",
"it will automatically scale to the largest health shape. Only set custom values if you know what you're doing.")]
public WDist BounceBlockerScanRadius = WDist.Zero;
public IProjectile Create(ProjectileArgs args) { return new Bullet(this, args); } public IProjectile Create(ProjectileArgs args) { return new Bullet(this, args); }
public void RulesetLoaded(Ruleset rules, WeaponInfo wi)
{
if (BlockerScanRadius == WDist.Zero)
BlockerScanRadius = Util.MinimumRequiredBlockerScanRadius(rules);
if (BounceBlockerScanRadius == WDist.Zero)
BounceBlockerScanRadius = Util.MinimumRequiredVictimScanRadius(rules);
}
} }
public class Bullet : IProjectile, ISync public class Bullet : IProjectile, ISync
@@ -196,7 +210,7 @@ namespace OpenRA.Mods.Common.Projectiles
var shouldExplode = false; var shouldExplode = false;
WPos blockedPos; WPos blockedPos;
if (info.Blockable && BlocksProjectiles.AnyBlockingActorsBetween(world, lastPos, pos, info.Width, if (info.Blockable && BlocksProjectiles.AnyBlockingActorsBetween(world, lastPos, pos, info.Width,
info.TargetExtraSearchRadius, out blockedPos)) info.BlockerScanRadius, out blockedPos))
{ {
pos = blockedPos; pos = blockedPos;
shouldExplode = true; shouldExplode = true;
@@ -219,7 +233,7 @@ namespace OpenRA.Mods.Common.Projectiles
if (flightLengthReached && shouldBounce) if (flightLengthReached && shouldBounce)
{ {
shouldExplode |= AnyValidTargetsInRadius(world, pos, info.Width + info.TargetExtraSearchRadius, args.SourceActor, true); shouldExplode |= AnyValidTargetsInRadius(world, pos, info.Width + info.BounceBlockerScanRadius, args.SourceActor, true);
target += (pos - source) * info.BounceRangeModifier / 100; target += (pos - source) * info.BounceRangeModifier / 100;
var dat = world.Map.DistanceAboveTerrain(target); var dat = world.Map.DistanceAboveTerrain(target);
target += new WVec(0, 0, -dat.Length); target += new WVec(0, 0, -dat.Length);
@@ -237,7 +251,7 @@ namespace OpenRA.Mods.Common.Projectiles
// After first bounce, check for targets each tick // After first bounce, check for targets each tick
if (remainingBounces < info.BounceCount) if (remainingBounces < info.BounceCount)
shouldExplode |= AnyValidTargetsInRadius(world, pos, info.Width + info.TargetExtraSearchRadius, args.SourceActor, true); shouldExplode |= AnyValidTargetsInRadius(world, pos, info.Width + info.BounceBlockerScanRadius, args.SourceActor, true);
if (shouldExplode) if (shouldExplode)
Explode(world); Explode(world);

View File

@@ -18,8 +18,8 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Projectiles namespace OpenRA.Mods.Common.Projectiles
{ {
[Desc("Simple invisible direct on target projectile.")] [Desc("Simple, invisible, usually direct-on-target projectile.")]
public class InstantHitInfo : IProjectileInfo public class InstantHitInfo : IProjectileInfo, IRulesetLoaded<WeaponInfo>
{ {
[Desc("Maximum offset at the maximum range.")] [Desc("Maximum offset at the maximum range.")]
public readonly WDist Inaccuracy = WDist.Zero; public readonly WDist Inaccuracy = WDist.Zero;
@@ -30,10 +30,17 @@ namespace OpenRA.Mods.Common.Projectiles
[Desc("The width of the projectile.")] [Desc("The width of the projectile.")]
public readonly WDist Width = new WDist(1); public readonly WDist Width = new WDist(1);
[Desc("Extra search radius beyond projectile width. Required to ensure affecting actors with large health radius.")] [Desc("Scan radius for actors with projectile-blocking trait. If set to zero (default), it will automatically scale",
public readonly WDist TargetExtraSearchRadius = new WDist(1536); "to the blocker with the largest health shape. Only set custom values if you know what you're doing.")]
public WDist BlockerScanRadius = WDist.Zero;
public IProjectile Create(ProjectileArgs args) { return new InstantHit(this, args); } public IProjectile Create(ProjectileArgs args) { return new InstantHit(this, args); }
public void RulesetLoaded(Ruleset rules, WeaponInfo wi)
{
if (BlockerScanRadius == WDist.Zero)
BlockerScanRadius = Util.MinimumRequiredBlockerScanRadius(rules);
}
} }
public class InstantHit : IProjectile public class InstantHit : IProjectile
@@ -65,7 +72,7 @@ namespace OpenRA.Mods.Common.Projectiles
// Check for blocking actors // Check for blocking actors
WPos blockedPos; WPos blockedPos;
if (info.Blockable && BlocksProjectiles.AnyBlockingActorsBetween(world, source, target.CenterPosition, if (info.Blockable && BlocksProjectiles.AnyBlockingActorsBetween(world, source, target.CenterPosition,
info.Width, info.TargetExtraSearchRadius, out blockedPos)) info.Width, info.BlockerScanRadius, out blockedPos))
{ {
target = Target.FromPos(blockedPos); target = Target.FromPos(blockedPos);
} }

View File

@@ -22,7 +22,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Projectiles namespace OpenRA.Mods.Common.Projectiles
{ {
[Desc("Not a sprite, but an engine effect.")] [Desc("Not a sprite, but an engine effect.")]
public class LaserZapInfo : IProjectileInfo public class LaserZapInfo : IProjectileInfo, IRulesetLoaded<WeaponInfo>
{ {
[Desc("The width of the zap.")] [Desc("The width of the zap.")]
public readonly WDist Width = new WDist(86); public readonly WDist Width = new WDist(86);
@@ -46,9 +46,6 @@ namespace OpenRA.Mods.Common.Projectiles
[Desc("Maximum offset at the maximum range.")] [Desc("Maximum offset at the maximum range.")]
public readonly WDist Inaccuracy = WDist.Zero; public readonly WDist Inaccuracy = WDist.Zero;
[Desc("Extra search radius beyond beam width. Required to ensure affecting actors with large health radius.")]
public readonly WDist TargetExtraSearchRadius = new WDist(1536);
[Desc("Beam can be blocked.")] [Desc("Beam can be blocked.")]
public readonly bool Blockable = false; public readonly bool Blockable = false;
@@ -77,11 +74,21 @@ namespace OpenRA.Mods.Common.Projectiles
[PaletteReference] public readonly string HitAnimPalette = "effect"; [PaletteReference] public readonly string HitAnimPalette = "effect";
[Desc("Scan radius for actors with projectile-blocking trait. If set to zero (default), it will automatically scale",
"to the blocker with the largest health shape. Only set custom values if you know what you're doing.")]
public WDist BlockerScanRadius = WDist.Zero;
public IProjectile Create(ProjectileArgs args) public IProjectile Create(ProjectileArgs args)
{ {
var c = UsePlayerColor ? args.SourceActor.Owner.Color.RGB : Color; var c = UsePlayerColor ? args.SourceActor.Owner.Color.RGB : Color;
return new LaserZap(this, args, c); return new LaserZap(this, args, c);
} }
public void RulesetLoaded(Ruleset rules, WeaponInfo wi)
{
if (BlockerScanRadius == WDist.Zero)
BlockerScanRadius = Util.MinimumRequiredBlockerScanRadius(rules);
}
} }
public class LaserZap : IProjectile, ISync public class LaserZap : IProjectile, ISync
@@ -126,7 +133,7 @@ namespace OpenRA.Mods.Common.Projectiles
// Check for blocking actors // Check for blocking actors
WPos blockedPos; WPos blockedPos;
if (info.Blockable && BlocksProjectiles.AnyBlockingActorsBetween(world, source, target, if (info.Blockable && BlocksProjectiles.AnyBlockingActorsBetween(world, source, target,
info.Width, info.TargetExtraSearchRadius, out blockedPos)) info.Width, info.BlockerScanRadius, out blockedPos))
{ {
target = blockedPos; target = blockedPos;
} }

View File

@@ -23,7 +23,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Projectiles namespace OpenRA.Mods.Common.Projectiles
{ {
public class MissileInfo : IProjectileInfo public class MissileInfo : IProjectileInfo, IRulesetLoaded<WeaponInfo>
{ {
[Desc("Name of the image containing the projectile sequence.")] [Desc("Name of the image containing the projectile sequence.")]
public readonly string Image = null; public readonly string Image = null;
@@ -64,9 +64,6 @@ namespace OpenRA.Mods.Common.Projectiles
[Desc("Width of projectile (used for finding blocking actors).")] [Desc("Width of projectile (used for finding blocking actors).")]
public readonly WDist Width = new WDist(1); public readonly WDist Width = new WDist(1);
[Desc("Extra search radius beyond path for blocking actors.")]
public readonly WDist TargetExtraSearchRadius = new WDist(1536);
[Desc("Maximum offset at the maximum range")] [Desc("Maximum offset at the maximum range")]
public readonly WDist Inaccuracy = WDist.Zero; public readonly WDist Inaccuracy = WDist.Zero;
@@ -145,7 +142,17 @@ namespace OpenRA.Mods.Common.Projectiles
"not trigger fast enough, causing the missile to fly past the target.")] "not trigger fast enough, causing the missile to fly past the target.")]
public readonly WDist CloseEnough = new WDist(298); public readonly WDist CloseEnough = new WDist(298);
[Desc("Scan radius for actors with projectile-blocking trait. If set to zero (default), it will automatically scale",
"to the blocker with the largest health shape. Only set custom values if you know what you're doing.")]
public WDist BlockerScanRadius = WDist.Zero;
public IProjectile Create(ProjectileArgs args) { return new Missile(this, args); } public IProjectile Create(ProjectileArgs args) { return new Missile(this, args); }
public void RulesetLoaded(Ruleset rules, WeaponInfo wi)
{
if (BlockerScanRadius == WDist.Zero)
BlockerScanRadius = Util.MinimumRequiredBlockerScanRadius(rules);
}
} }
// TODO: double check square roots!!! // TODO: double check square roots!!!
@@ -826,7 +833,7 @@ namespace OpenRA.Mods.Common.Projectiles
var shouldExplode = false; var shouldExplode = false;
WPos blockedPos; WPos blockedPos;
if (info.Blockable && BlocksProjectiles.AnyBlockingActorsBetween(world, lastPos, pos, info.Width, if (info.Blockable && BlocksProjectiles.AnyBlockingActorsBetween(world, lastPos, pos, info.Width,
info.TargetExtraSearchRadius, out blockedPos)) info.BlockerScanRadius, out blockedPos))
{ {
pos = blockedPos; pos = blockedPos;
shouldExplode = true; shouldExplode = true;