diff --git a/OpenRA.Mods.Common/Traits/Upgrades/UpgradeManager.cs b/OpenRA.Mods.Common/Traits/Upgrades/UpgradeManager.cs
index 81a7765d1e..7a440bce0a 100644
--- a/OpenRA.Mods.Common/Traits/Upgrades/UpgradeManager.cs
+++ b/OpenRA.Mods.Common/Traits/Upgrades/UpgradeManager.cs
@@ -85,13 +85,13 @@ namespace OpenRA.Mods.Common.Traits
});
}
- /// 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)
+ /// Upgrade level increments are limited to dupesAllowed per source, i.e., if a single
+ /// source attempts granting more upgrades than dupesAllowed, they will not accumulate. They will
+ /// replace each other instead, leaving only the most recently granted upgrade active. Each new
+ /// upgrade granting request 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, int dupesAllowed = 1)
{
var timed = timedUpgrades.FirstOrDefault(u => u.Upgrade == upgrade);
if (timed == null)
@@ -102,17 +102,17 @@ namespace OpenRA.Mods.Common.Traits
return;
}
- var src = timed.Sources.FirstOrDefault(s => s.Source == source);
- if (src == null)
+ var srcs = timed.Sources.Where(s => s.Source == source);
+ if (srcs.Count() < dupesAllowed)
{
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());
+ timed.Sources.Remove(timed.Sources.MinBy(s => s.Remaining));
}
else
- src.Remaining = duration;
+ srcs.MinBy(s => s.Remaining).Remaining = duration;
timed.Remaining = Math.Max(duration, timed.Remaining);
}
diff --git a/OpenRA.Mods.Common/Warheads/GrantUpgradeWarhead.cs b/OpenRA.Mods.Common/Warheads/GrantUpgradeWarhead.cs
index 4ea45972e7..f45e1b4ea1 100644
--- a/OpenRA.Mods.Common/Warheads/GrantUpgradeWarhead.cs
+++ b/OpenRA.Mods.Common/Warheads/GrantUpgradeWarhead.cs
@@ -48,7 +48,7 @@ namespace OpenRA.Mods.Common.Warheads
if (Duration > 0)
{
if (um.AcknowledgesUpgrade(a, u))
- um.GrantTimedUpgrade(a, u, Duration, firedBy);
+ um.GrantTimedUpgrade(a, u, Duration, firedBy, Upgrades.Count(upg => upg == u));
}
else
{