diff --git a/OpenRA.Game/Actor.cs b/OpenRA.Game/Actor.cs index 066b5277a0..d0fb5e7981 100644 --- a/OpenRA.Game/Actor.cs +++ b/OpenRA.Game/Actor.cs @@ -204,9 +204,12 @@ namespace OpenRA { World.AddFrameEndTask(w => { - if (Destroyed) return; + if (Destroyed) + return; + + if (IsInWorld) + World.Remove(this); - World.Remove(this); World.traitDict.RemoveActor(this); Destroyed = true; }); diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs index 7113c037d3..3296d68e50 100644 --- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs +++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs @@ -563,6 +563,18 @@ namespace OpenRA.Mods.Common.UtilityCommands } } + if (engineVersion < 20140927) + { + if (depth == 0) + node.Value.Nodes.RemoveAll(n => n.Key == "SelfHealingTech"); + + if (depth == 2 && node.Key == "RequiresTech" && parentKey.StartsWith("SelfHealing")) + { + node.Key = "RequiresUpgrade"; + node.Value.Value = "selfhealing-needs-reconfiguration"; + } + } + UpgradeActorRules(engineVersion, ref node.Value.Nodes, node, depth + 1); } } diff --git a/OpenRA.Mods.RA/GainsExperience.cs b/OpenRA.Mods.RA/GainsExperience.cs index 7d0fdd6ea1..92f1e34aae 100644 --- a/OpenRA.Mods.RA/GainsExperience.cs +++ b/OpenRA.Mods.RA/GainsExperience.cs @@ -46,7 +46,7 @@ namespace OpenRA.Mods.RA { 200, new[] { "firepower", "damage", "speed", "reload", "inaccuracy" } }, { 400, new[] { "firepower", "damage", "speed", "reload", "inaccuracy" } }, { 800, new[] { "firepower", "damage", "speed", "reload", "inaccuracy" } }, - { 1600, new[] { "firepower", "damage", "speed", "reload", "inaccuracy" } } + { 1600, new[] { "firepower", "damage", "speed", "reload", "inaccuracy", "selfheal" } } }; } diff --git a/OpenRA.Mods.RA/SelfHealing.cs b/OpenRA.Mods.RA/SelfHealing.cs index 6a97d0e9f8..88b5c7da33 100644 --- a/OpenRA.Mods.RA/SelfHealing.cs +++ b/OpenRA.Mods.RA/SelfHealing.cs @@ -21,31 +21,49 @@ namespace OpenRA.Mods.RA public readonly float HealIfBelow = .5f; public readonly int DamageCooldown = 0; - [Desc("The Type defined by SelfHealingTech required to enable this.")] - public readonly string RequiresTech = null; + [Desc("Enable only if this upgrade is enabled.")] + public readonly string RequiresUpgrade = null; - public virtual object Create(ActorInitializer init) { return new SelfHealing(this); } + public virtual object Create(ActorInitializer init) { return new SelfHealing(init.self, this); } } - class SelfHealing : ITick, ISync, INotifyDamage + class SelfHealing : ITick, ISync, INotifyDamage, IUpgradable { + readonly SelfHealingInfo info; + readonly Health health; + [Sync] int ticks; [Sync] int damageTicks; - SelfHealingInfo Info; + [Sync] bool disabled; - public SelfHealing(SelfHealingInfo info) { Info = info; } + + public SelfHealing(Actor self, SelfHealingInfo info) + { + this.info = info; + + health = self.Trait(); + + // Disable if an upgrade is required + disabled = info.RequiresUpgrade != null; + } + + public bool AcceptsUpgrade(string type) + { + return type == info.RequiresUpgrade; + } + + public void UpgradeAvailable(Actor self, string type, bool available) + { + if (type == info.RequiresUpgrade) + disabled = !available; + } public void Tick(Actor self) { - if (self.IsDead()) + if (self.IsDead() || disabled) return; - if (Info.RequiresTech != null && !self.World.ActorsWithTrait() - .Any(a => !a.Actor.IsDead() && a.Actor.Owner.IsAlliedWith(self.Owner) && Info.RequiresTech == a.Trait.Type)) - return; - - var health = self.Trait(); - if (health.HP >= Info.HealIfBelow*health.MaxHP) + if (health.HP >= info.HealIfBelow * health.MaxHP) return; if (damageTicks > 0) @@ -56,35 +74,15 @@ namespace OpenRA.Mods.RA if (--ticks <= 0) { - ticks = Info.Ticks; - self.InflictDamage(self, -Info.Step, null); + ticks = info.Ticks; + self.InflictDamage(self, -info.Step, null); } } public void Damaged(Actor self, AttackInfo e) { if (e.Damage > 0) - damageTicks = Info.DamageCooldown; - } - } - - [Desc("Attach this to an actor required as prerequisite for all owned units to regenerate health.")] - class SelfHealingTechInfo : ITraitInfo - { - public readonly string Type = null; - - public object Create(ActorInitializer init) { return new SelfHealingTech(this); } - } - - class SelfHealingTech - { - public string Type { get { return info.Type; } } - - readonly SelfHealingTechInfo info; - - public SelfHealingTech(SelfHealingTechInfo info) - { - this.info = info; + damageTicks = info.DamageCooldown; } } } diff --git a/mods/cnc/rules/defaults.yaml b/mods/cnc/rules/defaults.yaml index bb1ae62efd..977088e953 100644 --- a/mods/cnc/rules/defaults.yaml +++ b/mods/cnc/rules/defaults.yaml @@ -42,6 +42,12 @@ LuaScriptEvents: ScriptTriggers: GainsStatUpgrades: + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal ^Tank: AppearsOnRadar: @@ -90,6 +96,12 @@ LuaScriptEvents: ScriptTriggers: GainsStatUpgrades: + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal ^Helicopter: AppearsOnRadar: @@ -122,6 +134,12 @@ LuaScriptEvents: ScriptTriggers: GainsStatUpgrades: + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal ^Infantry: AppearsOnRadar: @@ -172,12 +190,15 @@ Guard: Guardable: BodyOrientation: - SelfHealing: + SelfHealing@HOSPITAL: Step: 5 Ticks: 100 HealIfBelow: 1 DamageCooldown: 125 - RequiresTech: InfantryHealing + RequiresUpgrade: hospitalheal + GlobalUpgradable: + Upgrades: hospitalheal + Prerequisites: hosp UpdatesPlayerStatistics: Huntable: LuaScriptEvents: @@ -193,6 +214,12 @@ DeathSound: Poisoned DeathTypes: 6 GainsStatUpgrades: + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal ^CivInfantry: Inherits: ^Infantry @@ -293,6 +320,12 @@ LuaScriptEvents: ScriptTriggers: GainsStatUpgrades: + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal ^Ship: AppearsOnRadar: @@ -320,6 +353,12 @@ LuaScriptEvents: ScriptTriggers: GainsStatUpgrades: + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal ^Building: AppearsOnRadar: diff --git a/mods/cnc/rules/player.yaml b/mods/cnc/rules/player.yaml index f177d84ce9..cafc6c2c1a 100644 --- a/mods/cnc/rules/player.yaml +++ b/mods/cnc/rules/player.yaml @@ -30,4 +30,6 @@ Player: Prerequisites: techlevel.low, techlevel.medium, techlevel.high ProvidesTechPrerequisite@all: Name: Unrestricted - Prerequisites: techlevel.low, techlevel.medium, techlevel.high, techlevel.superweapons \ No newline at end of file + Prerequisites: techlevel.low, techlevel.medium, techlevel.high, techlevel.superweapons + GlobalUpgradeManager: + diff --git a/mods/cnc/rules/tech.yaml b/mods/cnc/rules/tech.yaml index 40a3843308..903a86ead1 100644 --- a/mods/cnc/rules/tech.yaml +++ b/mods/cnc/rules/tech.yaml @@ -27,8 +27,6 @@ HOSP: Dimensions: 2,2 Health: HP: 1000 - SelfHealingTech: - Type: InfantryHealing Tooltip: Name: Hospital LeavesHusk: diff --git a/mods/d2k/rules/defaults.yaml b/mods/d2k/rules/defaults.yaml index cb8c86655b..eda438f6c8 100644 --- a/mods/d2k/rules/defaults.yaml +++ b/mods/d2k/rules/defaults.yaml @@ -40,6 +40,12 @@ Demolishable: ScriptTriggers: GainsStatUpgrades: + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal ^Tank: AppearsOnRadar: @@ -83,6 +89,12 @@ Demolishable: ScriptTriggers: GainsStatUpgrades: + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal ^Husk: Health: @@ -203,6 +215,12 @@ Parachutable: FallRate: 130 GainsStatUpgrades: + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal ^Plane: AppearsOnRadar: @@ -229,6 +247,12 @@ LuaScriptEvents: ScriptTriggers: GainsStatUpgrades: + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal ^Helicopter: Inherits: ^Plane diff --git a/mods/ra/rules/civilian.yaml b/mods/ra/rules/civilian.yaml index 29caa4118a..8f9fba2d45 100644 --- a/mods/ra/rules/civilian.yaml +++ b/mods/ra/rules/civilian.yaml @@ -83,8 +83,6 @@ HOSP: ExternalCapturable: ExternalCapturableBar: EngineerRepairable: - SelfHealingTech: - Type: InfantryHealing Tooltip: Name: Hospital RevealsShroud: diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml index 7cb47ff0ab..906464ffa3 100644 --- a/mods/ra/rules/defaults.yaml +++ b/mods/ra/rules/defaults.yaml @@ -55,6 +55,12 @@ Notification: UnitStolen ScriptTriggers: GainsStatUpgrades: + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal ^Tank: AppearsOnRadar: @@ -113,6 +119,12 @@ Notification: UnitStolen ScriptTriggers: GainsStatUpgrades: + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal ^Infantry: AppearsOnRadar: @@ -161,12 +173,15 @@ Guard: Guardable: BodyOrientation: - SelfHealing: + SelfHealing@HOSPITAL: Step: 5 Ticks: 100 HealIfBelow: 1 DamageCooldown: 125 - RequiresTech: InfantryHealing + RequiresUpgrade: hospitalheal + GlobalUpgradable: + Upgrades: hospitalheal + Prerequisites: hosp Huntable: LuaScriptEvents: ScriptTriggers: @@ -188,6 +203,12 @@ Cloneable: Types: Infantry GainsStatUpgrades: + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal ^Ship: AppearsOnRadar: @@ -222,6 +243,12 @@ LuaScriptEvents: ScriptTriggers: GainsStatUpgrades: + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal ^Plane: AppearsOnRadar: @@ -259,6 +286,12 @@ LuaScriptEvents: ScriptTriggers: GainsStatUpgrades: + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal ^Helicopter: Inherits: ^Plane diff --git a/mods/ra/rules/player.yaml b/mods/ra/rules/player.yaml index fdf86884bc..de6c0616b3 100644 --- a/mods/ra/rules/player.yaml +++ b/mods/ra/rules/player.yaml @@ -71,4 +71,5 @@ Player: Prerequisites: techlevel.infonly, techlevel.low, techlevel.medium ProvidesTechPrerequisite@unrestricted: Name: Unrestricted - Prerequisites: techlevel.infonly, techlevel.low, techlevel.medium, techlevel.unrestricted \ No newline at end of file + Prerequisites: techlevel.infonly, techlevel.low, techlevel.medium, techlevel.unrestricted + GlobalUpgradeManager: diff --git a/mods/ts/rules/defaults.yaml b/mods/ts/rules/defaults.yaml index 7f8835df0d..0ae54f741d 100644 --- a/mods/ts/rules/defaults.yaml +++ b/mods/ts/rules/defaults.yaml @@ -118,12 +118,18 @@ ChevronPalette: ra Upgrades: 500: firepower, damage, speed, reload - 1000: firepower, damage, speed, reload + 1000: firepower, damage, speed, reload, selfheal GainsStatUpgrades: FirepowerModifier: 110, 130 DamageModifier: 83, 66 SpeedModifier: 120, 150 ReloadModifier: 90, 75 + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal GivesExperience: DrawLineToTarget: ActorLostNotification: @@ -207,12 +213,18 @@ ChevronPalette: ra Upgrades: 500: firepower, damage, speed, reload - 1000: firepower, damage, speed, reload + 1000: firepower, damage, speed, reload, selfheal GainsStatUpgrades: FirepowerModifier: 110, 130 DamageModifier: 83, 66 SpeedModifier: 120, 150 ReloadModifier: 90, 75 + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal GivesExperience: DrawLineToTarget: ActorLostNotification: @@ -260,12 +272,18 @@ ChevronPalette: ra Upgrades: 500: firepower, damage, speed, reload - 1000: firepower, damage, speed, reload + 1000: firepower, damage, speed, reload, selfheal GainsStatUpgrades: FirepowerModifier: 110, 130 DamageModifier: 83, 66 SpeedModifier: 120, 150 ReloadModifier: 90, 75 + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal GivesExperience: DrawLineToTarget: ActorLostNotification: @@ -307,12 +325,18 @@ ChevronPalette: ra Upgrades: 500: firepower, damage, speed, reload - 1000: firepower, damage, speed, reload + 1000: firepower, damage, speed, reload, selfheal GainsStatUpgrades: FirepowerModifier: 110, 130 DamageModifier: 83, 66 SpeedModifier: 120, 150 ReloadModifier: 90, 75 + SelfHealing@ELITE: + Step: 2 + Ticks: 100 + HealIfBelow: 1 + DamageCooldown: 125 + RequiresUpgrade: selfheal GivesExperience: DrawLineToTarget: ActorLostNotification: