From ecdae4cbbe7e441b2bf3a5522c59c49b3ec2748d Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Tue, 24 Dec 2013 23:10:05 +1300 Subject: [PATCH] Convert weapons to world coords. --- OpenRA.Game/GameRules/WeaponInfo.cs | 8 +++---- OpenRA.Mods.RA/Armament.cs | 7 ++---- OpenRA.Mods.RA/Attack/AttackBase.cs | 2 +- OpenRA.Mods.RA/Attack/AttackFrontal.cs | 4 +--- OpenRA.Mods.RA/Attack/AttackLeap.cs | 4 +--- OpenRA.Mods.RA/Attack/AttackLoyalty.cs | 4 +--- OpenRA.Mods.RA/Attack/AttackMedic.cs | 4 +--- OpenRA.Mods.RA/Attack/AttackTurreted.cs | 2 +- OpenRA.Mods.RA/AttackBomber.cs | 8 +++---- OpenRA.Mods.RA/Combat.cs | 9 ++++---- OpenRA.Mods.RA/Effects/Bullet.cs | 29 ++++++++++--------------- OpenRA.Mods.RA/Effects/Missile.cs | 22 +++++++++---------- OpenRA.Mods.RA/RenderRangeCircle.cs | 5 +++-- 13 files changed, 44 insertions(+), 64 deletions(-) diff --git a/OpenRA.Game/GameRules/WeaponInfo.cs b/OpenRA.Game/GameRules/WeaponInfo.cs index be1f0b5e1f..38c4730488 100644 --- a/OpenRA.Game/GameRules/WeaponInfo.cs +++ b/OpenRA.Game/GameRules/WeaponInfo.cs @@ -18,8 +18,8 @@ namespace OpenRA.GameRules { public class WarheadInfo { - [Desc("Distance (in pixels) from the explosion center at which damage is 1/2.")] - public readonly int Spread = 1; + [Desc("Distance from the explosion center at which damage is 1/2.")] + public readonly WRange Spread = new WRange(43); [FieldLoader.LoadUsing("LoadVersus")] [Desc("Damage vs each armortype. 0% = can't target.")] public readonly Dictionary Versus; @@ -99,7 +99,7 @@ namespace OpenRA.GameRules public class WeaponInfo { - public readonly float Range = 0; + public readonly WRange Range = WRange.Zero; public readonly string[] Report = null; [Desc("Rate of Fire")] public readonly int ROF = 1; @@ -109,7 +109,7 @@ namespace OpenRA.GameRules public readonly string[] ValidTargets = { "Ground", "Water" }; public readonly string[] InvalidTargets = { }; public readonly int BurstDelay = 5; - public readonly float MinRange = 0; + public readonly WRange MinRange = WRange.Zero; [FieldLoader.LoadUsing("LoadProjectile")] public IProjectileInfo Projectile; [FieldLoader.LoadUsing("LoadWarheads")] public List Warheads; diff --git a/OpenRA.Mods.RA/Armament.cs b/OpenRA.Mods.RA/Armament.cs index 77e2d82d7f..f58b982bf0 100644 --- a/OpenRA.Mods.RA/Armament.cs +++ b/OpenRA.Mods.RA/Armament.cs @@ -107,13 +107,10 @@ namespace OpenRA.Mods.RA if (limitedAmmo != null && !limitedAmmo.HasAmmo()) return; - // TODO: Define weapon ranges as WRange - var range = new WRange((int)(1024*Weapon.Range)); - var minRange = new WRange((int)(1024*Weapon.MinRange)); - if (!target.IsInRange(self.CenterPosition, range)) + if (!target.IsInRange(self.CenterPosition, Weapon.Range)) return; - if (minRange != WRange.Zero && target.IsInRange(self.CenterPosition, minRange)) + if (Weapon.MinRange != WRange.Zero && target.IsInRange(self.CenterPosition, Weapon.MinRange)) return; if (!Weapon.IsValidAgainst(target, self.World)) diff --git a/OpenRA.Mods.RA/Attack/AttackBase.cs b/OpenRA.Mods.RA/Attack/AttackBase.cs index decb66c065..fedba8af2c 100644 --- a/OpenRA.Mods.RA/Attack/AttackBase.cs +++ b/OpenRA.Mods.RA/Attack/AttackBase.cs @@ -144,7 +144,7 @@ namespace OpenRA.Mods.RA public abstract Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove); public bool HasAnyValidWeapons(Target t) { return Armaments.Any(a => a.Weapon.IsValidAgainst(t, self.World)); } - public WRange GetMaximumRange() { return new WRange((int)(1024 * Armaments.Max(a => a.Weapon.Range))); } + public WRange GetMaximumRange() { return Armaments.Max(a => a.Weapon.Range); } public Armament ChooseArmamentForTarget(Target t) { return Armaments.FirstOrDefault(a => a.Weapon.IsValidAgainst(t, self.World)); } diff --git a/OpenRA.Mods.RA/Attack/AttackFrontal.cs b/OpenRA.Mods.RA/Attack/AttackFrontal.cs index 47c67ef1b0..360e002be5 100644 --- a/OpenRA.Mods.RA/Attack/AttackFrontal.cs +++ b/OpenRA.Mods.RA/Attack/AttackFrontal.cs @@ -52,9 +52,7 @@ namespace OpenRA.Mods.RA if (a == null) return null; - // TODO: Define weapon ranges as WRange - var range = new WRange(Math.Max(0,(int)(1024*a.Weapon.Range))); - return new Activities.Attack(newTarget, range, allowMove); + return new Activities.Attack(newTarget, a.Weapon.Range, allowMove); } } } diff --git a/OpenRA.Mods.RA/Attack/AttackLeap.cs b/OpenRA.Mods.RA/Attack/AttackLeap.cs index 25db9156df..386d406e69 100644 --- a/OpenRA.Mods.RA/Attack/AttackLeap.cs +++ b/OpenRA.Mods.RA/Attack/AttackLeap.cs @@ -42,9 +42,7 @@ namespace OpenRA.Mods.RA if (a == null) return; - // TODO: Define weapon ranges as WRange - var range = new WRange((int)(1024*a.Weapon.Range)); - if (!target.IsInRange(self.CenterPosition, range)) + if (!target.IsInRange(self.CenterPosition, a.Weapon.Range)) return; self.CancelActivity(); diff --git a/OpenRA.Mods.RA/Attack/AttackLoyalty.cs b/OpenRA.Mods.RA/Attack/AttackLoyalty.cs index 4c6fa26da6..e216ff0196 100644 --- a/OpenRA.Mods.RA/Attack/AttackLoyalty.cs +++ b/OpenRA.Mods.RA/Attack/AttackLoyalty.cs @@ -31,9 +31,7 @@ namespace OpenRA.Mods.RA if (arm == null) return; - // TODO: Define weapon ranges as WRange - var range = new WRange((int)(1024*arm.Weapon.Range)); - if (!target.IsInRange(self.CenterPosition, range)) + if (!target.IsInRange(self.CenterPosition, arm.Weapon.Range)) return; var facing = self.TraitOrDefault(); diff --git a/OpenRA.Mods.RA/Attack/AttackMedic.cs b/OpenRA.Mods.RA/Attack/AttackMedic.cs index b4c3e8e56a..c9fbc1fc31 100644 --- a/OpenRA.Mods.RA/Attack/AttackMedic.cs +++ b/OpenRA.Mods.RA/Attack/AttackMedic.cs @@ -33,9 +33,7 @@ namespace OpenRA.Mods.RA if (a == null) return null; - // TODO: Define weapon ranges as WRange - var range = new WRange(Math.Max(0, (int)(1024 * a.Weapon.Range))); - return new Activities.Heal(newTarget, range, allowMove); + return new Activities.Heal(newTarget, a.Weapon.Range, allowMove); } } } diff --git a/OpenRA.Mods.RA/Attack/AttackTurreted.cs b/OpenRA.Mods.RA/Attack/AttackTurreted.cs index 8b0022fa34..4bfae3a11d 100644 --- a/OpenRA.Mods.RA/Attack/AttackTurreted.cs +++ b/OpenRA.Mods.RA/Attack/AttackTurreted.cs @@ -96,7 +96,7 @@ namespace OpenRA.Mods.RA if (weapon != null) { - var range = WRange.FromCells(Math.Max(0, (int)weapon.Weapon.Range - RangeTolerance)); + var range = WRange.FromCells(Math.Max(0, weapon.Weapon.Range.Range / 1024 - RangeTolerance)); attack.Target = target; if (allowMove && self.HasTrait() && !self.Info.Traits.Get().OnRails) diff --git a/OpenRA.Mods.RA/AttackBomber.cs b/OpenRA.Mods.RA/AttackBomber.cs index 920a04f1b2..590e35821f 100644 --- a/OpenRA.Mods.RA/AttackBomber.cs +++ b/OpenRA.Mods.RA/AttackBomber.cs @@ -49,8 +49,7 @@ namespace OpenRA.Mods.RA // Bombs drop anywhere in range foreach (var a in Armaments.Where(a => a.Info.Name == info.Bombs)) { - var range = new WRange((int)(1024 * a.Weapon.Range)); - if (!target.IsInRange(self.CenterPosition, range)) + if (!target.IsInRange(self.CenterPosition, a.Weapon.Range)) continue; a.CheckFire(self, this, facing, bombTarget); @@ -63,11 +62,10 @@ namespace OpenRA.Mods.RA foreach (var a in Armaments.Where(a => a.Info.Name == info.Guns)) { - var range = new WRange((int)(1024 * a.Weapon.Range)); - if (!target.IsInRange(self.CenterPosition, range)) + if (!target.IsInRange(self.CenterPosition, a.Weapon.Range)) continue; - var t = Target.FromPos(cp - new WVec(0, range.Range / 2, cp.Z).Rotate(WRot.FromFacing(facing.Facing))); + var t = Target.FromPos(cp - new WVec(0, a.Weapon.Range.Range / 2, cp.Z).Rotate(WRot.FromFacing(facing.Facing))); a.CheckFire(self, this, facing, t); } } diff --git a/OpenRA.Mods.RA/Combat.cs b/OpenRA.Mods.RA/Combat.cs index 34166b6f70..4fe3331826 100755 --- a/OpenRA.Mods.RA/Combat.cs +++ b/OpenRA.Mods.RA/Combat.cs @@ -101,9 +101,8 @@ namespace OpenRA.Mods.RA { case DamageModel.Normal: { - var maxSpread = warhead.Spread * (float)Math.Log(Math.Abs(warhead.Damage), 2); - var range = new WRange((int)maxSpread * 1024 / Game.CellSize); - var hitActors = world.FindActorsInCircle(pos, range); + var maxSpread = new WRange((int)(warhead.Spread.Range * (float)Math.Log(Math.Abs(warhead.Damage), 2))); + var hitActors = world.FindActorsInCircle(pos, maxSpread); foreach (var victim in hitActors) { @@ -192,8 +191,8 @@ namespace OpenRA.Mods.RA var rawDamage = (float)warhead.Damage; if (withFalloff) { - var distance = Math.Max(0, (target.CenterPosition - pos).Length - healthInfo.Radius.Range) * Game.CellSize / 1024; - var falloff = (float)GetDamageFalloff(distance / warhead.Spread); + var distance = Math.Max(0, (target.CenterPosition - pos).Length - healthInfo.Radius.Range); + var falloff = (float)GetDamageFalloff(distance * 1f / warhead.Spread.Range); rawDamage = (float)(falloff * rawDamage); } return (float)(rawDamage * modifier * (float)warhead.EffectivenessAgainst(target.Info)); diff --git a/OpenRA.Mods.RA/Effects/Bullet.cs b/OpenRA.Mods.RA/Effects/Bullet.cs index 63947498c6..d8bce96716 100755 --- a/OpenRA.Mods.RA/Effects/Bullet.cs +++ b/OpenRA.Mods.RA/Effects/Bullet.cs @@ -22,15 +22,16 @@ namespace OpenRA.Mods.RA.Effects { public class BulletInfo : IProjectileInfo { - public readonly int Speed = 1; + [Desc("Projectile speed in WRange / tick")] + public readonly WRange Speed = new WRange(17); public readonly string Trail = null; - [Desc("Pixels at maximum range")] - public readonly float Inaccuracy = 0; + [Desc("Maximum offset at the maximum range")] + public readonly WRange Inaccuracy = WRange.Zero; public readonly string Image = null; [Desc("Check for whether an actor with Wall: trait blocks fire")] public readonly bool High = false; public readonly bool Shadow = false; - public readonly float Angle = 0; + public readonly WAngle Angle = WAngle.Zero; public readonly int TrailInterval = 2; public readonly int TrailDelay = 1; public readonly int ContrailLength = 0; @@ -49,7 +50,6 @@ namespace OpenRA.Mods.RA.Effects ContrailRenderable trail; Animation anim; - [Sync] WAngle angle; [Sync] WPos pos, target; [Sync] int length; [Sync] int facing; @@ -63,22 +63,15 @@ namespace OpenRA.Mods.RA.Effects this.args = args; this.pos = args.Source; - // Convert ProjectileArg definitions to world coordinates - // TODO: Change the yaml definitions so we don't need this - var range = new WRange((int)(1024 * args.Weapon.Range)); // Range in world units - var inaccuracy = new WRange((int)(info.Inaccuracy * 1024 / Game.CellSize)); // Offset in world units at max range - var speed = (int)(info.Speed * 4 * 1024 / (10 * Game.CellSize)); // Speed in world units per tick - angle = WAngle.ArcTan((int)(info.Angle * 4 * 1024), 1024); // Angle in world angle - target = args.PassiveTarget; - if (info.Inaccuracy > 0) + if (info.Inaccuracy.Range > 0) { - var maxOffset = inaccuracy.Range * (target - pos).Length / range.Range; + var maxOffset = info.Inaccuracy.Range * (target - pos).Length / args.Weapon.Range.Range; target += WVec.FromPDF(args.SourceActor.World.SharedRandom, 2) * maxOffset / 1024; } facing = Traits.Util.GetFacing(target - pos, 0); - length = Math.Max((target - pos).Length / speed, 1); + length = Math.Max((target - pos).Length / info.Speed.Range, 1); if (info.Image != null) { @@ -98,7 +91,7 @@ namespace OpenRA.Mods.RA.Effects int GetEffectiveFacing() { var at = (float)ticks / (length - 1); - var attitude = angle.Tan() * (1 - 2 * at) / (4 * 1024); + var attitude = info.Angle.Tan() * (1 - 2 * at) / (4 * 1024); var u = (facing % 128) / 128f; var scale = 512 * u * (1 - u); @@ -113,11 +106,11 @@ namespace OpenRA.Mods.RA.Effects if (anim != null) anim.Tick(); - pos = WPos.LerpQuadratic(args.Source, target, angle, ticks, length); + pos = WPos.LerpQuadratic(args.Source, target, info.Angle, ticks, length); if (info.Trail != null && --smokeTicks < 0) { - var delayedPos = WPos.LerpQuadratic(args.Source, target, angle, ticks - info.TrailDelay, length); + var delayedPos = WPos.LerpQuadratic(args.Source, target, info.Angle, ticks - info.TrailDelay, length); world.AddFrameEndTask(w => w.Add(new Smoke(w, delayedPos, info.Trail))); smokeTicks = info.TrailInterval; } diff --git a/OpenRA.Mods.RA/Effects/Missile.cs b/OpenRA.Mods.RA/Effects/Missile.cs index f4cb119460..4e55632ad1 100755 --- a/OpenRA.Mods.RA/Effects/Missile.cs +++ b/OpenRA.Mods.RA/Effects/Missile.cs @@ -21,13 +21,15 @@ namespace OpenRA.Mods.RA.Effects { class MissileInfo : IProjectileInfo { - public readonly int Speed = 1; + [Desc("Projectile speed in WRange / tick")] + public readonly WRange Speed = new WRange(8); public readonly WAngle MaximumPitch = WAngle.FromDegrees(30); public readonly int Arm = 0; [Desc("Check for whether an actor with Wall: trait blocks fire")] public readonly bool High = false; public readonly string Trail = null; - public readonly float Inaccuracy = 0; + [Desc("Maximum offset at the maximum range")] + public readonly WRange Inaccuracy = WRange.Zero; public readonly string Image = null; [Desc("Rate of Turning")] public readonly int ROT = 5; @@ -46,12 +48,15 @@ namespace OpenRA.Mods.RA.Effects class Missile : IEffect, ISync { + // HACK: the missile movement code isn't smart enough to explode + // when the projectile passes the actor. This defines an arbitrary + // proximity radius that they will explode within, which makes + // missiles difficult to consistently balance. static readonly WRange MissileCloseEnough = new WRange(298); readonly MissileInfo info; readonly ProjectileArgs args; readonly Animation anim; - readonly int speed; int ticksToNextSmoke; ContrailRenderable trail; @@ -76,13 +81,8 @@ namespace OpenRA.Mods.RA.Effects targetPosition = args.PassiveTarget; - // Convert ProjectileArg definitions to world coordinates - // TODO: Change the yaml definitions so we don't need this - var inaccuracy = (int)(info.Inaccuracy * 1024 / Game.CellSize); - speed = info.Speed * 1024 / (5 * Game.CellSize); - - if (info.Inaccuracy > 0) - offset = WVec.FromPDF(args.SourceActor.World.SharedRandom, 2) * inaccuracy / 1024; + if (info.Inaccuracy.Range > 0) + offset = WVec.FromPDF(args.SourceActor.World.SharedRandom, 2) * info.Inaccuracy.Range / 1024; if (info.Image != null) { @@ -131,7 +131,7 @@ namespace OpenRA.Mods.RA.Effects desiredFacing = facing; facing = Traits.Util.TickFacing(facing, desiredFacing, info.ROT); - var move = new WVec(0, -1024, 0).Rotate(WRot.FromFacing(facing)) * speed / 1024; + var move = new WVec(0, -1024, 0).Rotate(WRot.FromFacing(facing)) * info.Speed.Range / 1024; if (targetPosition.Z > 0 && info.TurboBoost) move = (move * 3) / 2; diff --git a/OpenRA.Mods.RA/RenderRangeCircle.cs b/OpenRA.Mods.RA/RenderRangeCircle.cs index 253f9712a0..53314bdcdf 100644 --- a/OpenRA.Mods.RA/RenderRangeCircle.cs +++ b/OpenRA.Mods.RA/RenderRangeCircle.cs @@ -27,11 +27,12 @@ namespace OpenRA.Mods.RA public void Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition) { var range = ai.Traits.WithInterface() - .Select(a => Rules.Weapons[a.Weapon.ToLowerInvariant()].Range).Max(); + .Select(a => Rules.Weapons[a.Weapon.ToLowerInvariant()].Range) + .Max(); wr.DrawRangeCircleWithContrast( centerPosition, - new WRange((int)(1024 * range)), + range, Color.FromArgb(128, Color.Yellow), Color.FromArgb(96, Color.Black) );