From 58472bf09089ada52d405d87fcac681b5472d9f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Husti=C4=87?= Date: Sun, 5 Jul 2015 22:04:03 +0100 Subject: [PATCH 1/3] Timed upgrades track sources. --- .../Traits/Upgrades/UpgradeManager.cs | 61 ++++++++++++++++--- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/OpenRA.Mods.Common/Traits/Upgrades/UpgradeManager.cs b/OpenRA.Mods.Common/Traits/Upgrades/UpgradeManager.cs index 983bf4e8f7..81a7765d1e 100644 --- a/OpenRA.Mods.Common/Traits/Upgrades/UpgradeManager.cs +++ b/OpenRA.Mods.Common/Traits/Upgrades/UpgradeManager.cs @@ -28,18 +28,37 @@ namespace OpenRA.Mods.Common.Traits { class TimedUpgrade { + public class UpgradeSource + { + public readonly object Source; + public int Remaining; + + public UpgradeSource(int duration, object source) + { + Remaining = duration; + Source = source; + } + } + public readonly string Upgrade; public readonly int Duration; - public int Remaining; + public readonly HashSet Sources; + public int Remaining; // Equal to maximum of all Sources.Remaining - public TimedUpgrade(string upgrade, int duration) + public TimedUpgrade(string upgrade, int duration, object source) { Upgrade = upgrade; Duration = duration; Remaining = duration; + Sources = new HashSet { new UpgradeSource(duration, source) }; } - public void Tick() { Remaining--; } + public void Tick() + { + Remaining--; + foreach (var source in Sources) + source.Remaining--; + } } class UpgradeState @@ -66,17 +85,36 @@ namespace OpenRA.Mods.Common.Traits }); } - public void GrantTimedUpgrade(Actor self, string upgrade, int duration) + /// Upgrade level increments are limited to one per source, i.e., if a single source + /// attempts granting multiple upgrades, they will not accumulate. They will replace each other + /// instead, leaving only the last granted upgrade active. An upgrade from each new distinct + /// source will increment the upgrade's level until AcceptsUpgrade starts returning false. Then, + /// when no new levels are accepted, the upgrade source with the shortest remaining upgrade + /// duration will be replaced by the new source. + public void GrantTimedUpgrade(Actor self, string upgrade, int duration, object source = null) { var timed = timedUpgrades.FirstOrDefault(u => u.Upgrade == upgrade); if (timed == null) { - timed = new TimedUpgrade(upgrade, duration); + timed = new TimedUpgrade(upgrade, duration, source); timedUpgrades.Add(timed); GrantUpgrade(self, upgrade, timed); + return; + } + + var src = timed.Sources.FirstOrDefault(s => s.Source == source); + if (src == null) + { + timed.Sources.Add(new TimedUpgrade.UpgradeSource(duration, source)); + if (AcceptsUpgrade(self, upgrade)) + GrantUpgrade(self, upgrade, timed); + else + timed.Sources.Remove(timed.Sources.OrderByDescending(s => s.Remaining).Last()); } else - timed.Remaining = Math.Max(duration, timed.Remaining); + src.Remaining = duration; + + timed.Remaining = Math.Max(duration, timed.Remaining); } // Different upgradeable traits may define (a) different level ranges for the same upgrade type, @@ -150,13 +188,20 @@ namespace OpenRA.Mods.Common.Traits s.Watchers.Add(action); } + /// Watchers will be receiving notifications while the upgrade's level is nonzero. + /// They will also be provided with the number of ticks before the level returns to zero, + /// as well as the duration in ticks of the timed upgrade (provided in the first call to + /// GrantTimedUpgrade). public void Tick(Actor self) { foreach (var u in timedUpgrades) { u.Tick(); - if (u.Remaining <= 0) - RevokeUpgrade(self, u.Upgrade, u); + foreach (var source in u.Sources) + if (source.Remaining <= 0) + RevokeUpgrade(self, u.Upgrade, u); + + u.Sources.RemoveWhere(source => source.Remaining <= 0); foreach (var a in upgrades.Value[u.Upgrade].Watchers) a(u.Duration, u.Remaining); From 6f54fe7e5d683268f0a5625a39d11f5156859d17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Husti=C4=87?= Date: Sun, 5 Jul 2015 22:06:25 +0100 Subject: [PATCH 2/3] Upgrade granting warheads register as sources. --- OpenRA.Mods.Common/Warheads/GrantUpgradeWarhead.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/OpenRA.Mods.Common/Warheads/GrantUpgradeWarhead.cs b/OpenRA.Mods.Common/Warheads/GrantUpgradeWarhead.cs index d2eaa49680..324339ef41 100644 --- a/OpenRA.Mods.Common/Warheads/GrantUpgradeWarhead.cs +++ b/OpenRA.Mods.Common/Warheads/GrantUpgradeWarhead.cs @@ -49,13 +49,16 @@ namespace OpenRA.Mods.Common.Warheads foreach (var u in Upgrades) { - if (!um.AcceptsUpgrade(a, u)) - continue; - if (Duration > 0) - um.GrantTimedUpgrade(a, u, Duration); + { + if (um.AcknowledgesUpgrade(a, u)) + um.GrantTimedUpgrade(a, u, Duration, firedBy); + } else - um.GrantUpgrade(a, u, this); + { + if (um.AcceptsUpgrade(a, u)) + um.GrantUpgrade(a, u, this); + } } } } From b2a26c57bc18adaadd2e0a2f6f92582e2b4484a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Husti=C4=87?= Date: Mon, 6 Jul 2015 18:17:15 +0100 Subject: [PATCH 3/3] Adjusted other users of timed upgrades. --- .../Traits/Crates/GrantUpgradeCrateAction.cs | 16 ++++++++++------ .../Traits/SupportPowers/GrantUpgradePower.cs | 16 ++++++++++------ .../Traits/Upgrades/UpgradeActorsNear.cs | 2 +- mods/ra/rules/defaults.yaml | 2 +- mods/ts/rules/defaults.yaml | 4 ---- 5 files changed, 22 insertions(+), 18 deletions(-) diff --git a/OpenRA.Mods.Common/Traits/Crates/GrantUpgradeCrateAction.cs b/OpenRA.Mods.Common/Traits/Crates/GrantUpgradeCrateAction.cs index 9db05ff227..7af55fa76c 100644 --- a/OpenRA.Mods.Common/Traits/Crates/GrantUpgradeCrateAction.cs +++ b/OpenRA.Mods.Common/Traits/Crates/GrantUpgradeCrateAction.cs @@ -47,7 +47,8 @@ namespace OpenRA.Mods.Common.Traits bool AcceptsUpgrade(Actor a) { var um = a.TraitOrDefault(); - return um != null && info.Upgrades.Any(u => um.AcceptsUpgrade(a, u)); + return um != null && (info.Duration > 0 ? + info.Upgrades.Any(u => um.AcknowledgesUpgrade(a, u)) : info.Upgrades.Any(u => um.AcceptsUpgrade(a, u))); } public override int GetSelectionShares(Actor collector) @@ -73,13 +74,16 @@ namespace OpenRA.Mods.Common.Traits var um = a.TraitOrDefault(); foreach (var u in info.Upgrades) { - if (!um.AcceptsUpgrade(a, u)) - continue; - if (info.Duration > 0) - um.GrantTimedUpgrade(a, u, info.Duration); + { + if (um.AcknowledgesUpgrade(a, u)) + um.GrantTimedUpgrade(a, u, info.Duration); + } else - um.GrantUpgrade(a, u, this); + { + if (um.AcceptsUpgrade(a, u)) + um.GrantUpgrade(a, u, this); + } } } }); diff --git a/OpenRA.Mods.Common/Traits/SupportPowers/GrantUpgradePower.cs b/OpenRA.Mods.Common/Traits/SupportPowers/GrantUpgradePower.cs index e78e5822cd..1e7f7a1109 100644 --- a/OpenRA.Mods.Common/Traits/SupportPowers/GrantUpgradePower.cs +++ b/OpenRA.Mods.Common/Traits/SupportPowers/GrantUpgradePower.cs @@ -65,13 +65,16 @@ namespace OpenRA.Mods.Common.Traits foreach (var u in info.Upgrades) { - if (!um.AcceptsUpgrade(a, u)) - continue; - if (info.Duration > 0) - um.GrantTimedUpgrade(a, u, info.Duration); + { + if (um.AcknowledgesUpgrade(a, u)) + um.GrantTimedUpgrade(a, u, info.Duration); + } else - um.GrantUpgrade(a, u, this); + { + if (um.AcceptsUpgrade(a, u)) + um.GrantUpgrade(a, u, this); + } } } } @@ -90,7 +93,8 @@ namespace OpenRA.Mods.Common.Traits return false; var um = a.TraitOrDefault(); - return um != null && info.Upgrades.Any(u => um.AcceptsUpgrade(a, u)); + return um != null && (info.Duration > 0 ? + info.Upgrades.Any(u => um.AcknowledgesUpgrade(a, u)) : info.Upgrades.Any(u => um.AcceptsUpgrade(a, u))); }); } diff --git a/OpenRA.Mods.Common/Traits/Upgrades/UpgradeActorsNear.cs b/OpenRA.Mods.Common/Traits/Upgrades/UpgradeActorsNear.cs index adadbb936e..9fbe748e11 100644 --- a/OpenRA.Mods.Common/Traits/Upgrades/UpgradeActorsNear.cs +++ b/OpenRA.Mods.Common/Traits/Upgrades/UpgradeActorsNear.cs @@ -116,7 +116,7 @@ namespace OpenRA.Mods.Common.Traits var um = produced.TraitOrDefault(); if (um != null) foreach (var u in info.Upgrades) - if (um.AcceptsUpgrade(produced, u)) + if (um.AcknowledgesUpgrade(produced, u)) um.GrantTimedUpgrade(produced, u, 1); } } diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml index f90fd9582c..a832ead541 100644 --- a/mods/ra/rules/defaults.yaml +++ b/mods/ra/rules/defaults.yaml @@ -55,7 +55,7 @@ UpgradeMinEnabledLevel: 1 DamageMultiplier@IRONCURTAIN: UpgradeTypes: invulnerability - Modifier: 0, 0 + Modifier: 0 TimedUpgradeBar: Upgrade: invulnerability diff --git a/mods/ts/rules/defaults.yaml b/mods/ts/rules/defaults.yaml index 3f3ac37626..6d77dc4077 100644 --- a/mods/ts/rules/defaults.yaml +++ b/mods/ts/rules/defaults.yaml @@ -359,12 +359,10 @@ UpgradeOverlay@EMPDISABLE: UpgradeTypes: empdisable UpgradeMinEnabledLevel: 1 - UpgradeMaxAcceptedLevel: 2 Palette: disabled DisableUpgrade@EMPDISABLE: UpgradeTypes: empdisable UpgradeMinEnabledLevel: 1 - UpgradeMaxAcceptedLevel: 2 TimedUpgradeBar@EMPDISABLE: Upgrade: empdisable Color: 255,255,255 @@ -377,11 +375,9 @@ ShowToEnemies: true ZOffset: 512 UpgradeMinEnabledLevel: 1 - UpgradeMaxAcceptedLevel: 2 Cloak@CLOAKGENERATOR: UpgradeTypes: cloakgenerator UpgradeMinEnabledLevel: 1 - UpgradeMaxAcceptedLevel: 2 InitialDelay: 0 CloakDelay: 90 MustBeDestroyed: