diff --git a/OpenRA.Mods.Common/Projectiles/AreaBeam.cs b/OpenRA.Mods.Common/Projectiles/AreaBeam.cs index 166c4bee98..1c7534b8df 100644 --- a/OpenRA.Mods.Common/Projectiles/AreaBeam.cs +++ b/OpenRA.Mods.Common/Projectiles/AreaBeam.cs @@ -22,7 +22,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Projectiles { - public class AreaBeamInfo : IProjectileInfo + public class AreaBeamInfo : IProjectileInfo, IRulesetLoaded { [Desc("Projectile speed in WDist / tick, two values indicate a randomly picked velocity per beam.")] public readonly WDist[] Speed = { new WDist(128) }; @@ -57,9 +57,6 @@ namespace OpenRA.Mods.Common.Projectiles [Desc("Does the beam follow the target.")] 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.")] public readonly bool RenderBeam = true; @@ -72,11 +69,28 @@ namespace OpenRA.Mods.Common.Projectiles [Desc("Beam color is the player's color.")] 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) { var c = UsePlayerColor ? args.SourceActor.Owner.Color.RGB : Color; 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 @@ -211,7 +225,7 @@ namespace OpenRA.Mods.Common.Projectiles // Check for blocking actors WPos blockedPos; if (info.Blockable && BlocksProjectiles.AnyBlockingActorsBetween(world, tailPos, headPos, - info.Width, info.TargetExtraSearchRadius, out blockedPos)) + info.Width, info.BlockerScanRadius, out blockedPos)) { headPos = blockedPos; target = headPos; @@ -221,7 +235,7 @@ namespace OpenRA.Mods.Common.Projectiles // Damage is applied to intersected actors every DamageInterval ticks 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) { var adjustedModifiers = args.DamageModifiers.Append(GetFalloff((args.Source - a.CenterPosition).Length)); diff --git a/OpenRA.Mods.Common/Projectiles/Bullet.cs b/OpenRA.Mods.Common/Projectiles/Bullet.cs index c5666d2d88..91fd33fe62 100644 --- a/OpenRA.Mods.Common/Projectiles/Bullet.cs +++ b/OpenRA.Mods.Common/Projectiles/Bullet.cs @@ -22,7 +22,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Projectiles { - public class BulletInfo : IProjectileInfo + public class BulletInfo : IProjectileInfo, IRulesetLoaded { [Desc("Projectile speed in WDist / tick, two values indicate variable velocity.")] 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).")] 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.")] public readonly WAngle[] LaunchAngle = { WAngle.Zero }; @@ -95,7 +92,24 @@ namespace OpenRA.Mods.Common.Projectiles public readonly int ContrailDelay = 1; 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 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 @@ -196,7 +210,7 @@ namespace OpenRA.Mods.Common.Projectiles var shouldExplode = false; WPos blockedPos; if (info.Blockable && BlocksProjectiles.AnyBlockingActorsBetween(world, lastPos, pos, info.Width, - info.TargetExtraSearchRadius, out blockedPos)) + info.BlockerScanRadius, out blockedPos)) { pos = blockedPos; shouldExplode = true; @@ -219,7 +233,7 @@ namespace OpenRA.Mods.Common.Projectiles 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; var dat = world.Map.DistanceAboveTerrain(target); target += new WVec(0, 0, -dat.Length); @@ -237,7 +251,7 @@ namespace OpenRA.Mods.Common.Projectiles // After first bounce, check for targets each tick 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) Explode(world); diff --git a/OpenRA.Mods.Common/Projectiles/InstantHit.cs b/OpenRA.Mods.Common/Projectiles/InstantHit.cs index 309201abd7..797aade389 100644 --- a/OpenRA.Mods.Common/Projectiles/InstantHit.cs +++ b/OpenRA.Mods.Common/Projectiles/InstantHit.cs @@ -18,8 +18,8 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Projectiles { - [Desc("Simple invisible direct on target projectile.")] - public class InstantHitInfo : IProjectileInfo + [Desc("Simple, invisible, usually direct-on-target projectile.")] + public class InstantHitInfo : IProjectileInfo, IRulesetLoaded { [Desc("Maximum offset at the maximum range.")] public readonly WDist Inaccuracy = WDist.Zero; @@ -30,10 +30,17 @@ namespace OpenRA.Mods.Common.Projectiles [Desc("The width of the projectile.")] public readonly WDist Width = new WDist(1); - [Desc("Extra search radius beyond projectile width. Required to ensure affecting actors with large health radius.")] - public readonly WDist TargetExtraSearchRadius = new WDist(1536); + [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 InstantHit(this, args); } + + public void RulesetLoaded(Ruleset rules, WeaponInfo wi) + { + if (BlockerScanRadius == WDist.Zero) + BlockerScanRadius = Util.MinimumRequiredBlockerScanRadius(rules); + } } public class InstantHit : IProjectile @@ -65,7 +72,7 @@ namespace OpenRA.Mods.Common.Projectiles // Check for blocking actors WPos blockedPos; 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); } diff --git a/OpenRA.Mods.Common/Projectiles/LaserZap.cs b/OpenRA.Mods.Common/Projectiles/LaserZap.cs index b1fde40009..28da4682b6 100644 --- a/OpenRA.Mods.Common/Projectiles/LaserZap.cs +++ b/OpenRA.Mods.Common/Projectiles/LaserZap.cs @@ -22,7 +22,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Projectiles { [Desc("Not a sprite, but an engine effect.")] - public class LaserZapInfo : IProjectileInfo + public class LaserZapInfo : IProjectileInfo, IRulesetLoaded { [Desc("The width of the zap.")] public readonly WDist Width = new WDist(86); @@ -46,9 +46,6 @@ namespace OpenRA.Mods.Common.Projectiles [Desc("Maximum offset at the maximum range.")] 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.")] public readonly bool Blockable = false; @@ -77,11 +74,21 @@ namespace OpenRA.Mods.Common.Projectiles [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) { var c = UsePlayerColor ? args.SourceActor.Owner.Color.RGB : Color; 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 @@ -126,7 +133,7 @@ namespace OpenRA.Mods.Common.Projectiles // Check for blocking actors WPos blockedPos; if (info.Blockable && BlocksProjectiles.AnyBlockingActorsBetween(world, source, target, - info.Width, info.TargetExtraSearchRadius, out blockedPos)) + info.Width, info.BlockerScanRadius, out blockedPos)) { target = blockedPos; } diff --git a/OpenRA.Mods.Common/Projectiles/Missile.cs b/OpenRA.Mods.Common/Projectiles/Missile.cs index 143b405acf..77fd621a5a 100644 --- a/OpenRA.Mods.Common/Projectiles/Missile.cs +++ b/OpenRA.Mods.Common/Projectiles/Missile.cs @@ -23,7 +23,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Projectiles { - public class MissileInfo : IProjectileInfo + public class MissileInfo : IProjectileInfo, IRulesetLoaded { [Desc("Name of the image containing the projectile sequence.")] public readonly string Image = null; @@ -64,9 +64,6 @@ namespace OpenRA.Mods.Common.Projectiles [Desc("Width of projectile (used for finding blocking actors).")] 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")] 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.")] 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 void RulesetLoaded(Ruleset rules, WeaponInfo wi) + { + if (BlockerScanRadius == WDist.Zero) + BlockerScanRadius = Util.MinimumRequiredBlockerScanRadius(rules); + } } // TODO: double check square roots!!! @@ -826,7 +833,7 @@ namespace OpenRA.Mods.Common.Projectiles var shouldExplode = false; WPos blockedPos; if (info.Blockable && BlocksProjectiles.AnyBlockingActorsBetween(world, lastPos, pos, info.Width, - info.TargetExtraSearchRadius, out blockedPos)) + info.BlockerScanRadius, out blockedPos)) { pos = blockedPos; shouldExplode = true;