diff --git a/OpenRA.Game/WAngle.cs b/OpenRA.Game/WAngle.cs index ab16e4b0a5..74cec071bd 100644 --- a/OpenRA.Game/WAngle.cs +++ b/OpenRA.Game/WAngle.cs @@ -19,6 +19,7 @@ namespace OpenRA public struct WAngle : IEquatable { public readonly int Angle; + public int AngleSquared { get { return (int)Angle * Angle; } } public WAngle(int a) { diff --git a/OpenRA.Mods.Common/Lint/CheckAngle.cs b/OpenRA.Mods.Common/Lint/CheckAngle.cs new file mode 100644 index 0000000000..64fcb15039 --- /dev/null +++ b/OpenRA.Mods.Common/Lint/CheckAngle.cs @@ -0,0 +1,70 @@ +#region Copyright & License Information +/* + * Copyright 2007-2016 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System; +using System.Linq; +using OpenRA.Mods.Common.Projectiles; +using OpenRA.Mods.Common.Traits; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Lint +{ + class CheckAngle : ILintRulesPass + { + public void Run(Action emitError, Action emitWarning, Ruleset rules) + { + foreach (var weaponInfo in rules.Weapons) + { + var missile = weaponInfo.Value.Projectile as MissileInfo; + if (missile != null) + { + var minAngle = missile.MinimumLaunchAngle.Angle; + var maxAngle = missile.MaximumLaunchAngle.Angle; + + // If both angles are identical, we only need to test one of them + var testMaxAngle = minAngle != maxAngle; + CheckLaunchAngles(weaponInfo.Key, minAngle, testMaxAngle, maxAngle, emitError); + } + + var bullet = weaponInfo.Value.Projectile as BulletInfo; + if (bullet != null) + { + var minAngle = bullet.LaunchAngle[0].Angle; + var maxAngle = bullet.LaunchAngle.Length > 1 ? bullet.LaunchAngle[1].Angle : minAngle; + + // If both angles are identical, we only need to test one of them + var testMaxAngle = minAngle != maxAngle; + CheckLaunchAngles(weaponInfo.Key, minAngle, testMaxAngle, maxAngle, emitError); + } + } + } + + static bool InvalidAngle(int value) + { + return value > 255 && value < 769; + } + + static void CheckLaunchAngles(string weaponInfo, int minAngle, bool testMaxAngle, int maxAngle, Action emitError) + { + if (InvalidAngle(minAngle)) + emitError("Weapon `{0}`: Projectile minimum LaunchAngle must not exceed (-)255!".F(weaponInfo)); + if (testMaxAngle && InvalidAngle(maxAngle)) + emitError("Weapon `{0}`: Projectile maximum LaunchAngle must not exceed (-)255!".F(weaponInfo)); + + if ((minAngle < 256) && (maxAngle < 256) && (minAngle > maxAngle)) + emitError("Weapon `{0}`: Projectile minimum LaunchAngle must not exceed maximum LaunchAngle!".F(weaponInfo)); + if ((minAngle > 768) && (maxAngle > 768) && (minAngle > maxAngle)) + emitError("Weapon `{0}`: Projectile minimum LaunchAngle must not exceed maximum LaunchAngle!".F(weaponInfo)); + if ((minAngle < 256) && (maxAngle > 768)) + emitError("Weapon `{0}`: Projectile minimum LaunchAngle must not exceed maximum LaunchAngle!".F(weaponInfo)); + } + } +} diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index f69b054427..b8d3d5eb41 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -168,6 +168,7 @@ + diff --git a/OpenRA.Mods.Common/Projectiles/Bullet.cs b/OpenRA.Mods.Common/Projectiles/Bullet.cs index 3d4685a9b9..3e45d5f201 100644 --- a/OpenRA.Mods.Common/Projectiles/Bullet.cs +++ b/OpenRA.Mods.Common/Projectiles/Bullet.cs @@ -61,7 +61,7 @@ namespace OpenRA.Mods.Common.Projectiles public readonly WDist TargetExtraSearchRadius = new WDist(1536); [Desc("Arc in WAngles, two values indicate variable arc.")] - public readonly WAngle[] Angle = { WAngle.Zero }; + public readonly WAngle[] LaunchAngle = { WAngle.Zero }; [Desc("Interval in ticks between each spawned Trail animation.")] public readonly int TrailInterval = 2; @@ -97,11 +97,11 @@ namespace OpenRA.Mods.Common.Projectiles string trailPalette; [Sync] WPos pos, target; - [Sync] int length; + int length; [Sync] int facing; - [Sync] int ticks, smokeTicks; + int ticks, smokeTicks; - [Sync] public Actor SourceActor { get { return args.SourceActor; } } + public Actor SourceActor { get { return args.SourceActor; } } public Bullet(BulletInfo info, ProjectileArgs args) { @@ -111,10 +111,10 @@ namespace OpenRA.Mods.Common.Projectiles var world = args.SourceActor.World; - if (info.Angle.Length > 1) - angle = new WAngle(world.SharedRandom.Next(info.Angle[0].Angle, info.Angle[1].Angle)); + if (info.LaunchAngle.Length > 1) + angle = new WAngle(world.SharedRandom.Next(info.LaunchAngle[0].Angle, info.LaunchAngle[1].Angle)); else - angle = info.Angle[0]; + angle = info.LaunchAngle[0]; if (info.Speed.Length > 1) speed = new WDist(world.SharedRandom.Next(info.Speed[0].Length, info.Speed[1].Length)); diff --git a/OpenRA.Mods.Common/Projectiles/Missile.cs b/OpenRA.Mods.Common/Projectiles/Missile.cs index eb4f80c546..2342d10640 100644 --- a/OpenRA.Mods.Common/Projectiles/Missile.cs +++ b/OpenRA.Mods.Common/Projectiles/Missile.cs @@ -159,6 +159,11 @@ namespace OpenRA.Mods.Common.Projectiles readonly Animation anim; readonly WVec gravity; + readonly int minLaunchSpeed; + readonly int maxLaunchSpeed; + readonly int maxSpeed; + readonly WAngle minLaunchAngle; + readonly WAngle maxLaunchAngle; int ticks; @@ -201,6 +206,11 @@ namespace OpenRA.Mods.Common.Projectiles gravity = new WVec(0, 0, -info.Gravity); targetPosition = args.PassiveTarget; rangeLimit = info.RangeLimit != WDist.Zero ? info.RangeLimit : args.Weapon.Range; + minLaunchSpeed = info.MinimumLaunchSpeed.Length > -1 ? info.MinimumLaunchSpeed.Length : info.Speed.Length; + maxLaunchSpeed = info.MaximumLaunchSpeed.Length > -1 ? info.MaximumLaunchSpeed.Length : info.Speed.Length; + maxSpeed = info.Speed.Length; + minLaunchAngle = info.MinimumLaunchAngle; + maxLaunchAngle = info.MaximumLaunchAngle; var world = args.SourceActor.World; @@ -248,13 +258,11 @@ namespace OpenRA.Mods.Common.Projectiles void DetermineLaunchSpeedAndAngleForIncline(int predClfDist, int diffClfMslHgt, int relTarHorDist, out int speed, out int vFacing) { - var minLaunchSpeed = info.MinimumLaunchSpeed.Length > -1 ? info.MinimumLaunchSpeed.Length : info.Speed.Length; - var maxLaunchSpeed = info.MaximumLaunchSpeed.Length > -1 ? info.MaximumLaunchSpeed.Length : info.Speed.Length; - speed = info.MaximumLaunchSpeed.Length > -1 ? info.MaximumLaunchSpeed.Length : info.Speed.Length; + speed = maxLaunchSpeed; // Find smallest vertical facing, for which the missile will be able to climb terrAltDiff w-units // within hHeightChange w-units all the while ending the ascent with vertical facing 0 - vFacing = info.MaximumLaunchAngle.Angle >> 2; + vFacing = maxLaunchAngle.Angle >> 2; // Compute minimum speed necessary to both be able to face directly upwards and have enough space // to hit the target without passing it by (and thus having to do horizontal loops) @@ -282,8 +290,8 @@ namespace OpenRA.Mods.Common.Projectiles // Find least vertical facing that will allow the missile to climb // terrAltDiff w-units within hHeightChange w-units // all the while ending the ascent with vertical facing 0 - vFacing = BisectionSearch(System.Math.Max((sbyte)(info.MinimumLaunchAngle.Angle >> 2), (sbyte)0), - (sbyte)(info.MaximumLaunchAngle.Angle >> 2), + vFacing = BisectionSearch(System.Math.Max((sbyte)(minLaunchAngle.Angle >> 2), (sbyte)0), + (sbyte)(maxLaunchAngle.Angle >> 2), vFac => !WillClimbWithinDistance(vFac, loopRadius, predClfDist, diffClfMslHgt)) + 1; } } @@ -291,7 +299,7 @@ namespace OpenRA.Mods.Common.Projectiles // TODO: Double check Launch parameter determination void DetermineLaunchSpeedAndAngle(World world, out int speed, out int vFacing) { - speed = info.MaximumLaunchSpeed.Length > -1 ? info.MaximumLaunchSpeed.Length : info.Speed.Length; + speed = maxLaunchSpeed; loopRadius = LoopRadius(speed, info.VerticalRateOfTurn); // Compute current distance from target position @@ -309,8 +317,8 @@ namespace OpenRA.Mods.Common.Projectiles DetermineLaunchSpeedAndAngleForIncline(predClfDist, diffClfMslHgt, relTarHorDist, out speed, out vFacing); else if (lastHt != 0) { - vFacing = System.Math.Max((sbyte)(info.MinimumLaunchAngle.Angle >> 2), (sbyte)0); - speed = info.MaximumLaunchSpeed.Length > -1 ? info.MaximumLaunchSpeed.Length : info.Speed.Length; + vFacing = System.Math.Max((sbyte)(minLaunchAngle.Angle >> 2), (sbyte)0); + speed = maxLaunchSpeed; } else { @@ -324,8 +332,8 @@ namespace OpenRA.Mods.Common.Projectiles vFacing = 0; // Make sure the chosen vertical facing adheres to prescribed bounds - vFacing = vFacing.Clamp((sbyte)(info.MinimumLaunchAngle.Angle >> 2), - (sbyte)(info.MaximumLaunchAngle.Angle >> 2)); + vFacing = vFacing.Clamp((sbyte)(minLaunchAngle.Angle >> 2), + (sbyte)(maxLaunchAngle.Angle >> 2)); } } @@ -404,7 +412,7 @@ namespace OpenRA.Mods.Common.Projectiles void ChangeSpeed(int sign = 1) { - speed = (speed + sign * info.Acceleration.Length).Clamp(0, info.Speed.Length); + speed = (speed + sign * info.Acceleration.Length).Clamp(0, maxSpeed); // Compute the vertical loop radius loopRadius = LoopRadius(speed, info.VerticalRateOfTurn); @@ -415,7 +423,7 @@ namespace OpenRA.Mods.Common.Projectiles // Compute the projectile's freefall displacement var move = velocity + gravity / 2; velocity += gravity; - var velRatio = info.Speed.Length * 1024 / velocity.Length; + var velRatio = maxSpeed * 1024 / velocity.Length; if (velRatio < 1024) velocity = velocity * velRatio / 1024; diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs index 5db2a92216..782bee908a 100644 --- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs +++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs @@ -497,6 +497,13 @@ namespace OpenRA.Mods.Common.UtilityCommands node.Key = "Duration"; } + // Rename Bullet Angle to LaunchAngle + if (engineVersion < 20161016) + { + if (node.Key == "Angle") + node.Key = "LaunchAngle"; + } + UpgradeWeaponRules(modData, engineVersion, ref node.Value.Nodes, node, depth + 1); } } diff --git a/mods/cnc/weapons/largecaliber.yaml b/mods/cnc/weapons/largecaliber.yaml index 1dcaf70d0f..9640081dba 100644 --- a/mods/cnc/weapons/largecaliber.yaml +++ b/mods/cnc/weapons/largecaliber.yaml @@ -123,7 +123,7 @@ ArtilleryShell: Projectile: Bullet Speed: 204 Blockable: false - Angle: 56 + LaunchAngle: 56 Inaccuracy: 1c256 ContrailLength: 30 Image: 120MM diff --git a/mods/cnc/weapons/missiles.yaml b/mods/cnc/weapons/missiles.yaml index d180e19281..8427920041 100644 --- a/mods/cnc/weapons/missiles.yaml +++ b/mods/cnc/weapons/missiles.yaml @@ -182,7 +182,7 @@ MammothMissiles: Blockable: false Shadow: true Inaccuracy: 853 - Angle: 62 + LaunchAngle: 62 Image: DRAGON RateOfTurn: 2 ContrailLength: 10 @@ -349,7 +349,7 @@ HonestJohn: TrailImage: smokey Speed: 187 RangeLimit: 35 - Angle: 88 + LaunchAngle: 88 Warhead@1Dam: SpreadDamage Spread: 256 Damage: 100 diff --git a/mods/cnc/weapons/other.yaml b/mods/cnc/weapons/other.yaml index 6ae400d624..1b98b624ff 100644 --- a/mods/cnc/weapons/other.yaml +++ b/mods/cnc/weapons/other.yaml @@ -81,7 +81,7 @@ Grenade: Projectile: Bullet Speed: 140 Blockable: false - Angle: 62 + LaunchAngle: 62 Inaccuracy: 213 Image: BOMB Warhead@1Dam: SpreadDamage diff --git a/mods/d2k/weapons/debris.yaml b/mods/d2k/weapons/debris.yaml index 7f52a09c79..5d1dbe5833 100644 --- a/mods/d2k/weapons/debris.yaml +++ b/mods/d2k/weapons/debris.yaml @@ -4,7 +4,7 @@ Debris: Projectile: Bullet Speed: 32, 96 Blockable: false - Angle: 30, 90 + LaunchAngle: 30, 90 Inaccuracy: 1c256 Image: shrapnel Warhead@1Dam: SpreadDamage @@ -36,7 +36,7 @@ Debris2: Projectile: Bullet Speed: 32, 96 Blockable: false - Angle: 30, 90 + LaunchAngle: 30, 90 Inaccuracy: 1c256 Image: shrapnel2 TrailImage: bazooka_trail @@ -71,7 +71,7 @@ Debris3: Projectile: Bullet Speed: 32, 96 Blockable: false - Angle: 30, 90 + LaunchAngle: 30, 90 Inaccuracy: 1c256 Image: shrapnel3 TrailImage: large_trail @@ -106,7 +106,7 @@ Debris4: Projectile: Bullet Speed: 32, 96 Blockable: false - Angle: 30, 90 + LaunchAngle: 30, 90 Inaccuracy: 1c256 Image: shrapnel4 TrailImage: large_trail diff --git a/mods/d2k/weapons/largeguns.yaml b/mods/d2k/weapons/largeguns.yaml index eb375e449c..34ba5fd164 100644 --- a/mods/d2k/weapons/largeguns.yaml +++ b/mods/d2k/weapons/largeguns.yaml @@ -99,7 +99,7 @@ DevBullet: Speed: 192 Blockable: false Shadow: yes - Angle: 62 + LaunchAngle: 62 Inaccuracy: 768 ContrailLength: 20 Image: 155mm diff --git a/mods/d2k/weapons/other.yaml b/mods/d2k/weapons/other.yaml index 4864fca353..5d000c5ca3 100644 --- a/mods/d2k/weapons/other.yaml +++ b/mods/d2k/weapons/other.yaml @@ -192,7 +192,7 @@ grenade: Projectile: Bullet Speed: 256 Blockable: false - Angle: 75 + LaunchAngle: 75 Inaccuracy: 416 Image: grenade Shadow: true @@ -261,7 +261,7 @@ SpiceExplosion: Projectile: Bullet Speed: 50, 75 Blockable: false - Angle: 60, 90 + LaunchAngle: 60, 90 TrailImage: large_trail Image: 120mm Warhead@1Dam: SpreadDamage diff --git a/mods/ra/weapons/largecaliber.yaml b/mods/ra/weapons/largecaliber.yaml index 8fc6d68f20..cf692d8287 100644 --- a/mods/ra/weapons/largecaliber.yaml +++ b/mods/ra/weapons/largecaliber.yaml @@ -146,7 +146,7 @@ TurretGun: Projectile: Bullet Speed: 204 Blockable: false - Angle: 62 + LaunchAngle: 62 Inaccuracy: 1c682 Image: 120MM ContrailLength: 30 @@ -180,7 +180,7 @@ TurretGun: Projectile: Bullet Speed: 204 Blockable: false - Angle: 62 + LaunchAngle: 62 Inaccuracy: 2c938 Image: 120MM ContrailLength: 30 diff --git a/mods/ra/weapons/missiles.yaml b/mods/ra/weapons/missiles.yaml index dff2748e9d..28e40cbd1c 100644 --- a/mods/ra/weapons/missiles.yaml +++ b/mods/ra/weapons/missiles.yaml @@ -251,7 +251,7 @@ SubMissile: Projectile: Bullet Speed: 162 Blockable: false - Angle: 120 + LaunchAngle: 120 Inaccuracy: 2c938 Image: MISSILE TrailImage: smokey @@ -422,7 +422,7 @@ SCUD: TrailDelay: 5 Inaccuracy: 213 Image: V2 - Angle: 62 + LaunchAngle: 62 Warhead@1Dam: SpreadDamage Spread: 341 Damage: 45 diff --git a/mods/ra/weapons/other.yaml b/mods/ra/weapons/other.yaml index bb425b28dc..d776ab5294 100644 --- a/mods/ra/weapons/other.yaml +++ b/mods/ra/weapons/other.yaml @@ -36,7 +36,7 @@ Flamer: Speed: 170 TrailImage: fb4 Image: fb3 - Angle: 62 + LaunchAngle: 62 Inaccuracy: 853 Warhead@1Dam: SpreadDamage Spread: 341 @@ -93,7 +93,7 @@ Grenade: Projectile: Bullet Speed: 136 Blockable: false - Angle: 62 + LaunchAngle: 62 Inaccuracy: 554 Image: BOMB Warhead@1Dam: SpreadDamage @@ -125,7 +125,7 @@ DepthCharge: Projectile: Bullet Speed: 85 Image: BOMB - Angle: 62 + LaunchAngle: 62 Blockable: false Inaccuracy: 128 Warhead@1Dam: SpreadDamage diff --git a/mods/ts/weapons/bombsandgrenades.yaml b/mods/ts/weapons/bombsandgrenades.yaml index c8f0a2942d..b320fd6abe 100644 --- a/mods/ts/weapons/bombsandgrenades.yaml +++ b/mods/ts/weapons/bombsandgrenades.yaml @@ -5,7 +5,7 @@ Grenade: Speed: 85 Blockable: false Shadow: true - Angle: 45 + LaunchAngle: 45 Inaccuracy: 384 Image: DISCUS Warhead@1Dam: SpreadDamage @@ -73,7 +73,7 @@ RPGTower: Speed: 384 Blockable: false Shadow: true - Angle: 62 + LaunchAngle: 62 Image: canister Palette: player Warhead@1Dam: SpreadDamage diff --git a/mods/ts/weapons/explosions.yaml b/mods/ts/weapons/explosions.yaml index 98d42e4907..e419809df1 100644 --- a/mods/ts/weapons/explosions.yaml +++ b/mods/ts/weapons/explosions.yaml @@ -63,7 +63,7 @@ SmallDebris: Report: Projectile: Bullet Speed: 50, 125 - Angle: 45, 135 + LaunchAngle: 45, 135 Image: dbrissm Sequences: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 Shadow: true @@ -74,7 +74,7 @@ LargeDebris: Report: Projectile: Bullet Speed: 50, 125 - Angle: 45, 135 + LaunchAngle: 45, 135 Image: dbrislg Sequences: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 Shadow: true diff --git a/mods/ts/weapons/largeguns.yaml b/mods/ts/weapons/largeguns.yaml index 31d62f5ab2..4952792ca3 100644 --- a/mods/ts/weapons/largeguns.yaml +++ b/mods/ts/weapons/largeguns.yaml @@ -6,7 +6,7 @@ Speed: 682 Image: 120mm Shadow: true - Angle: 75 + LaunchAngle: 75 Palette: ra Warhead@1Dam: SpreadDamage Spread: 128 @@ -70,7 +70,7 @@ Speed: 682 Image: 120mm Shadow: true - Angle: 62 + LaunchAngle: 62 Palette: ra Warhead@1Dam: SpreadDamage Spread: 128 @@ -102,7 +102,7 @@ Projectile: Bullet Speed: 170 Image: 120mm - Angle: 165 + LaunchAngle: 165 Shadow: true Blockable: false Palette: ra diff --git a/mods/ts/weapons/otherweapons.yaml b/mods/ts/weapons/otherweapons.yaml index b06dfae0af..e2edaacea2 100644 --- a/mods/ts/weapons/otherweapons.yaml +++ b/mods/ts/weapons/otherweapons.yaml @@ -32,7 +32,7 @@ FiendShard: Image: CRYSTAL4 Inaccuracy: 512 Shadow: true - Angle: 60 + LaunchAngle: 60 Palette: greentiberium Warhead@1Dam: SpreadDamage Damage: 35 diff --git a/mods/ts/weapons/superweapons.yaml b/mods/ts/weapons/superweapons.yaml index 90d7069c10..7c9f6fdf9d 100644 --- a/mods/ts/weapons/superweapons.yaml +++ b/mods/ts/weapons/superweapons.yaml @@ -103,7 +103,7 @@ EMPulseCannon: Speed: 425 Blockable: false Shadow: true - Angle: 62 + LaunchAngle: 62 Image: pulsball Warhead@1Eff: CreateEffect Explosions: pulse_explosion