diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 049903fbd5..f843856bcc 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -178,6 +178,7 @@ namespace OpenRA.Traits public interface ISpeedModifier { int GetSpeedModifier(); } public interface IFirepowerModifier { int GetFirepowerModifier(); } public interface IReloadModifier { int GetReloadModifier(); } + public interface IInaccuracyModifier { int GetInaccuracyModifier(); } public interface IPowerModifier { int GetPowerModifier(); } public interface ILoadsPalettes { void LoadPalettes(WorldRenderer wr); } public interface IPaletteModifier { void AdjustPalette(IReadOnlyDictionary b); } diff --git a/OpenRA.Mods.RA/Effects/Bullet.cs b/OpenRA.Mods.RA/Effects/Bullet.cs index bda2e0a9a7..03f54a5808 100755 --- a/OpenRA.Mods.RA/Effects/Bullet.cs +++ b/OpenRA.Mods.RA/Effects/Bullet.cs @@ -82,7 +82,10 @@ namespace OpenRA.Mods.RA.Effects target = args.PassiveTarget; if (info.Inaccuracy.Range > 0) { - var maxOffset = info.Inaccuracy.Range * (target - pos).Length / args.Weapon.Range.Range; + var modifiers = args.SourceActor.TraitsImplementing() + .Select(m => m.GetInaccuracyModifier()); + var inaccuracy = Traits.Util.ApplyPercentageModifiers(info.Inaccuracy.Range, modifiers); + var maxOffset = inaccuracy * (target - pos).Length / args.Weapon.Range.Range; target += WVec.FromPDF(args.SourceActor.World.SharedRandom, 2) * maxOffset / 1024; } diff --git a/OpenRA.Mods.RA/Effects/Missile.cs b/OpenRA.Mods.RA/Effects/Missile.cs index 97167085a3..222d02474c 100755 --- a/OpenRA.Mods.RA/Effects/Missile.cs +++ b/OpenRA.Mods.RA/Effects/Missile.cs @@ -85,7 +85,12 @@ namespace OpenRA.Mods.RA.Effects targetPosition = args.PassiveTarget; if (info.Inaccuracy.Range > 0) - offset = WVec.FromPDF(args.SourceActor.World.SharedRandom, 2) * info.Inaccuracy.Range / 1024; + { + var modifiers = args.SourceActor.TraitsImplementing() + .Select(m => m.GetInaccuracyModifier()); + var inaccuracy = Traits.Util.ApplyPercentageModifiers(info.Inaccuracy.Range, modifiers); + offset = WVec.FromPDF(args.SourceActor.World.SharedRandom, 2) * inaccuracy / 1024; + } if (info.Image != null) { diff --git a/OpenRA.Mods.RA/GainsStatUpgrades.cs b/OpenRA.Mods.RA/GainsStatUpgrades.cs index 24f8b05f35..89bc57acd8 100644 --- a/OpenRA.Mods.RA/GainsStatUpgrades.cs +++ b/OpenRA.Mods.RA/GainsStatUpgrades.cs @@ -30,16 +30,20 @@ namespace OpenRA.Mods.RA public readonly string ReloadUpgrade = "reload"; public readonly int[] ReloadModifier = { 95, 90, 85, 75 }; + public readonly string InaccuracyUpgrade = "inaccuracy"; + public readonly int[] InaccuracyModifier = { 90, 80, 70, 50 }; + public object Create(ActorInitializer init) { return new GainsStatUpgrades(this); } } - public class GainsStatUpgrades : IUpgradable, IFirepowerModifier, IDamageModifier, ISpeedModifier, IReloadModifier + public class GainsStatUpgrades : IUpgradable, IFirepowerModifier, IDamageModifier, ISpeedModifier, IReloadModifier, IInaccuracyModifier { readonly GainsStatUpgradesInfo info; [Sync] int firepowerLevel = 0; [Sync] int speedLevel = 0; [Sync] int damageLevel = 0; [Sync] int reloadLevel = 0; + [Sync] int inaccuracyLevel = 0; public GainsStatUpgrades(GainsStatUpgradesInfo info) { @@ -51,7 +55,8 @@ namespace OpenRA.Mods.RA return (type == info.FirepowerUpgrade && firepowerLevel < info.FirepowerModifier.Length) || (type == info.DamageUpgrade && damageLevel < info.DamageModifier.Length) || (type == info.SpeedUpgrade && speedLevel < info.SpeedModifier.Length) - || (type == info.ReloadUpgrade && reloadLevel < info.ReloadModifier.Length); + || (type == info.ReloadUpgrade && reloadLevel < info.ReloadModifier.Length) + || (type == info.InaccuracyUpgrade && inaccuracyLevel < info.InaccuracyModifier.Length); } public void UpgradeAvailable(Actor self, string type, bool available) @@ -65,6 +70,8 @@ namespace OpenRA.Mods.RA speedLevel = (speedLevel + mod).Clamp(0, info.SpeedModifier.Length); else if (type == info.ReloadUpgrade) reloadLevel = (reloadLevel + mod).Clamp(0, info.ReloadModifier.Length); + else if (type == info.InaccuracyUpgrade) + inaccuracyLevel = (inaccuracyLevel + mod).Clamp(0, info.InaccuracyModifier.Length); } public int GetDamageModifier(Actor attacker, DamageWarhead warhead) @@ -86,5 +93,10 @@ namespace OpenRA.Mods.RA { return reloadLevel > 0 ? info.ReloadModifier[reloadLevel - 1] : 100; } + + public int GetInaccuracyModifier() + { + return inaccuracyLevel > 0 ? info.InaccuracyModifier[inaccuracyLevel - 1] : 100; + } } }