From 0ca5336072ae944d3e3fda60e2fb4e296eb6ac30 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Wed, 30 Jul 2014 19:36:24 +1200 Subject: [PATCH] Reimplement UnitUpgradeCrate using IUpgradable. --- .../Crates/UnitUpgradeCrateAction.cs | 63 +++++++------- OpenRA.Mods.RA/GainsStatUpgrades.cs | 78 +++++++++++++++++ OpenRA.Mods.RA/GainsUnitUpgrades.cs | 87 ------------------- OpenRA.Mods.RA/OpenRA.Mods.RA.csproj | 2 +- 4 files changed, 111 insertions(+), 119 deletions(-) create mode 100644 OpenRA.Mods.RA/GainsStatUpgrades.cs delete mode 100644 OpenRA.Mods.RA/GainsUnitUpgrades.cs diff --git a/OpenRA.Mods.RA/Crates/UnitUpgradeCrateAction.cs b/OpenRA.Mods.RA/Crates/UnitUpgradeCrateAction.cs index bab5b01445..a8c2c8f14e 100644 --- a/OpenRA.Mods.RA/Crates/UnitUpgradeCrateAction.cs +++ b/OpenRA.Mods.RA/Crates/UnitUpgradeCrateAction.cs @@ -9,6 +9,7 @@ #endregion using System.Linq; +using OpenRA.Traits; namespace OpenRA.Mods.RA.Crates { @@ -16,15 +17,12 @@ namespace OpenRA.Mods.RA.Crates public class UnitUpgradeCrateActionInfo : CrateActionInfo { [Desc("The upgrade to grant.")] - public readonly UnitUpgrade? Upgrade = null; + public readonly string[] Upgrades = {}; - [Desc("The number of levels of the upgrade to grant.")] - public readonly int Levels = 1; - - [Desc("The range to search for extra collectors in.","Extra collectors will also be granted the crate action.")] + [Desc("The range to search for extra collectors in.", "Extra collectors will also be granted the crate action.")] public readonly WRange Range = new WRange(3); - [Desc("The maximum number of extra collectors to grant the crate action to.","-1 = no limit")] + [Desc("The maximum number of extra collectors to grant the crate action to.", "-1 = no limit")] public readonly int MaxExtraCollectors = 4; public override object Create(ActorInitializer init) { return new UnitUpgradeCrateAction(init.self, this); } @@ -32,7 +30,7 @@ namespace OpenRA.Mods.RA.Crates public class UnitUpgradeCrateAction : CrateAction { - UnitUpgradeCrateActionInfo Info; + readonly UnitUpgradeCrateActionInfo Info; public UnitUpgradeCrateAction(Actor self, UnitUpgradeCrateActionInfo info) : base(self, info) @@ -40,42 +38,45 @@ namespace OpenRA.Mods.RA.Crates Info = info; } + bool AcceptsUpgrade(Actor a) + { + return a.TraitsImplementing() + .Any(up => Info.Upgrades.Any(u => up.AcceptsUpgrade(u))); + } + + void GrantActorUpgrades(Actor a) + { + foreach (var up in a.TraitsImplementing()) + foreach (var u in Info.Upgrades) + if (up.AcceptsUpgrade(u)) + up.UpgradeAvailable(a, u, true); + } + public override int GetSelectionShares(Actor collector) { - var up = collector.TraitOrDefault(); - return up != null && up.CanGainUnitUpgrade(Info.Upgrade) ? info.SelectionShares : 0; + return AcceptsUpgrade(collector) ? info.SelectionShares : 0; } public override void Activate(Actor collector) { - collector.World.AddFrameEndTask(w => - { - var gainsStatBonuses = collector.TraitOrDefault(); - if (gainsStatBonuses != null) - gainsStatBonuses.GiveUnitUpgrade(Info.Upgrade, Info.Levels); - }); + collector.World.AddFrameEndTask(w => GrantActorUpgrades(collector)); - var inRange = self.World.FindActorsInCircle(self.CenterPosition, Info.Range); - inRange = inRange.Where(a => - (a.Owner == collector.Owner) && - (a != collector) && - (a.TraitOrDefault() != null) && - (a.TraitOrDefault().CanGainUnitUpgrade(Info.Upgrade))); - if (inRange.Any()) + var actorsInRange = self.World.FindActorsInCircle(self.CenterPosition, Info.Range) + .Where(a => a != self && a.Owner == collector.Owner && AcceptsUpgrade(a)); + + if (actorsInRange.Any()) { if (Info.MaxExtraCollectors > -1) - inRange = inRange.Take(Info.MaxExtraCollectors); + actorsInRange = actorsInRange.Take(Info.MaxExtraCollectors); - if (inRange.Any()) - foreach (Actor actor in inRange) + collector.World.AddFrameEndTask(w => + { + foreach (var a in actorsInRange) { - actor.World.AddFrameEndTask(w => - { - var gainsStatBonuses = actor.TraitOrDefault(); - if (gainsStatBonuses != null) - gainsStatBonuses.GiveUnitUpgrade(Info.Upgrade, Info.Levels); - }); + if (!a.IsDead() && a.IsInWorld) + GrantActorUpgrades(a); } + }); } base.Activate(collector); diff --git a/OpenRA.Mods.RA/GainsStatUpgrades.cs b/OpenRA.Mods.RA/GainsStatUpgrades.cs new file mode 100644 index 0000000000..f7889e1446 --- /dev/null +++ b/OpenRA.Mods.RA/GainsStatUpgrades.cs @@ -0,0 +1,78 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 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. For more information, + * see COPYING. + */ +#endregion + +using System; +using System.Collections.Generic; +using OpenRA.GameRules; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA +{ + [Desc("This actor has properties that upgrade when a specific criteria is met.")] + public class GainsStatUpgradesInfo : ITraitInfo + { + public readonly string FirepowerUpgrade = "firepower"; + public readonly float[] FirepowerModifier = { 1.1f, 1.15f, 1.2f, 1.5f }; + + public readonly string ArmorUpgrade = "armor"; + public readonly float[] ArmorModifier = { 1.1f, 1.2f, 1.3f, 1.5f }; + + public readonly string SpeedUpgrade = "speed"; + public readonly decimal[] SpeedModifier = { 1.1m, 1.15m, 1.2m, 1.5m }; + + public object Create(ActorInitializer init) { return new GainsStatUpgrades(this); } + } + + public class GainsStatUpgrades : IUpgradable, IFirepowerModifier, IDamageModifier, ISpeedModifier + { + readonly GainsStatUpgradesInfo info; + [Sync] int firepowerLevel = 0; + [Sync] int speedLevel = 0; + [Sync] int armorLevel = 0; + + public GainsStatUpgrades(GainsStatUpgradesInfo info) + { + this.info = info; + } + + public bool AcceptsUpgrade(string type) + { + return (type == info.FirepowerUpgrade && firepowerLevel < info.FirepowerModifier.Length) + || (type == info.ArmorUpgrade && armorLevel < info.ArmorModifier.Length) + || (type == info.SpeedUpgrade && speedLevel < info.SpeedModifier.Length); + } + + public void UpgradeAvailable(Actor self, string type, bool available) + { + var mod = available ? 1 : -1; + if (type == info.FirepowerUpgrade) + firepowerLevel = (firepowerLevel + mod).Clamp(0, info.FirepowerModifier.Length); + else if (type == info.ArmorUpgrade) + armorLevel = (armorLevel + mod).Clamp(0, info.ArmorModifier.Length); + else if (type == info.SpeedUpgrade) + speedLevel = (speedLevel + mod).Clamp(0, info.SpeedModifier.Length); + } + + public float GetDamageModifier(Actor attacker, DamageWarhead warhead) + { + return armorLevel > 0 ? 1 / info.ArmorModifier[armorLevel - 1] : 1; + } + + public float GetFirepowerModifier() + { + return firepowerLevel > 0 ? info.FirepowerModifier[firepowerLevel - 1] : 1; + } + + public decimal GetSpeedModifier() + { + return speedLevel > 0 ? info.SpeedModifier[speedLevel - 1] : 1m; + } + } +} diff --git a/OpenRA.Mods.RA/GainsUnitUpgrades.cs b/OpenRA.Mods.RA/GainsUnitUpgrades.cs deleted file mode 100644 index 095a12cbd8..0000000000 --- a/OpenRA.Mods.RA/GainsUnitUpgrades.cs +++ /dev/null @@ -1,87 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2014 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. For more information, - * see COPYING. - */ -#endregion - -using System; -using OpenRA.GameRules; -using OpenRA.Traits; - -namespace OpenRA.Mods.RA -{ - [Desc("This actor has properties that upgrade when a specific criteria is met.")] - public class GainsUnitUpgradesInfo : ITraitInfo - { - public readonly int FirepowerMaxLevel = 15; - public readonly float FirepowerModifier = .2f; - public readonly int ArmorMaxLevel = 15; - public readonly float ArmorModifier = .2f; - public readonly int SpeedMaxLevel = 15; - public readonly decimal SpeedModifier = .2m; - // TODO: weapon range, rate of fire modifiers. potentially a vision modifier. - - public object Create(ActorInitializer init) { return new GainsUnitUpgrades(this); } - } - - public class GainsUnitUpgrades : IFirepowerModifier, IDamageModifier, ISpeedModifier - { - GainsUnitUpgradesInfo info; - [Sync] public int FirepowerLevel = 0; - [Sync] public int SpeedLevel = 0; - [Sync] public int ArmorLevel = 0; - - public GainsUnitUpgrades(GainsUnitUpgradesInfo info) - { - this.info = info; - } - - public bool CanGainUnitUpgrade(UnitUpgrade? upgrade) - { - if (upgrade == UnitUpgrade.Firepower) - return FirepowerLevel < info.FirepowerMaxLevel; - if (upgrade == UnitUpgrade.Armor) - return ArmorLevel < info.ArmorMaxLevel; - if (upgrade == UnitUpgrade.Speed) - return SpeedLevel < info.SpeedMaxLevel; - - return false; - } - - public void GiveUnitUpgrade(UnitUpgrade? upgrade, int numLevels) - { - if (upgrade == UnitUpgrade.Firepower) - FirepowerLevel = Math.Min(FirepowerLevel + numLevels, info.FirepowerMaxLevel); - else if (upgrade == UnitUpgrade.Armor) - ArmorLevel = Math.Min(ArmorLevel + numLevels, info.ArmorMaxLevel); - else if (upgrade == UnitUpgrade.Speed) - SpeedLevel = Math.Min(SpeedLevel + numLevels, info.SpeedMaxLevel); - } - - public float GetFirepowerModifier() - { - return FirepowerLevel > 0 ? (1 + FirepowerLevel * info.FirepowerModifier) : 1; - } - - public float GetDamageModifier(Actor attacker, DamageWarhead warhead) - { - return ArmorLevel > 0 ? (1 / (1 + ArmorLevel * info.ArmorModifier)) : 1; - } - - public decimal GetSpeedModifier() - { - return SpeedLevel > 0 ? (1m + SpeedLevel * info.SpeedModifier) : 1m; - } - } - - public enum UnitUpgrade - { - Firepower = 0, - Armor = 1, - Speed = 2 - } -} diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index b13a78e143..5c8e85bb74 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -234,7 +234,6 @@ - @@ -552,6 +551,7 @@ +