Merge pull request #8658 from matija-hustic/higher_level_timed_upgrades

Higher level timed upgrades
This commit is contained in:
Oliver Brakmann
2015-07-15 20:51:51 +02:00
7 changed files with 83 additions and 31 deletions

View File

@@ -47,7 +47,8 @@ namespace OpenRA.Mods.Common.Traits
bool AcceptsUpgrade(Actor a) bool AcceptsUpgrade(Actor a)
{ {
var um = a.TraitOrDefault<UpgradeManager>(); var um = a.TraitOrDefault<UpgradeManager>();
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) public override int GetSelectionShares(Actor collector)
@@ -73,13 +74,16 @@ namespace OpenRA.Mods.Common.Traits
var um = a.TraitOrDefault<UpgradeManager>(); var um = a.TraitOrDefault<UpgradeManager>();
foreach (var u in info.Upgrades) foreach (var u in info.Upgrades)
{ {
if (!um.AcceptsUpgrade(a, u))
continue;
if (info.Duration > 0) if (info.Duration > 0)
um.GrantTimedUpgrade(a, u, info.Duration); {
if (um.AcknowledgesUpgrade(a, u))
um.GrantTimedUpgrade(a, u, info.Duration);
}
else else
um.GrantUpgrade(a, u, this); {
if (um.AcceptsUpgrade(a, u))
um.GrantUpgrade(a, u, this);
}
} }
} }
}); });

View File

@@ -65,13 +65,16 @@ namespace OpenRA.Mods.Common.Traits
foreach (var u in info.Upgrades) foreach (var u in info.Upgrades)
{ {
if (!um.AcceptsUpgrade(a, u))
continue;
if (info.Duration > 0) if (info.Duration > 0)
um.GrantTimedUpgrade(a, u, info.Duration); {
if (um.AcknowledgesUpgrade(a, u))
um.GrantTimedUpgrade(a, u, info.Duration);
}
else 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; return false;
var um = a.TraitOrDefault<UpgradeManager>(); var um = a.TraitOrDefault<UpgradeManager>();
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)));
}); });
} }

View File

@@ -116,7 +116,7 @@ namespace OpenRA.Mods.Common.Traits
var um = produced.TraitOrDefault<UpgradeManager>(); var um = produced.TraitOrDefault<UpgradeManager>();
if (um != null) if (um != null)
foreach (var u in info.Upgrades) foreach (var u in info.Upgrades)
if (um.AcceptsUpgrade(produced, u)) if (um.AcknowledgesUpgrade(produced, u))
um.GrantTimedUpgrade(produced, u, 1); um.GrantTimedUpgrade(produced, u, 1);
} }
} }

View File

@@ -28,18 +28,37 @@ namespace OpenRA.Mods.Common.Traits
{ {
class TimedUpgrade 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 string Upgrade;
public readonly int Duration; public readonly int Duration;
public int Remaining; public readonly HashSet<UpgradeSource> 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; Upgrade = upgrade;
Duration = duration; Duration = duration;
Remaining = duration; Remaining = duration;
Sources = new HashSet<UpgradeSource> { new UpgradeSource(duration, source) };
} }
public void Tick() { Remaining--; } public void Tick()
{
Remaining--;
foreach (var source in Sources)
source.Remaining--;
}
} }
class UpgradeState class UpgradeState
@@ -66,17 +85,36 @@ namespace OpenRA.Mods.Common.Traits
}); });
} }
public void GrantTimedUpgrade(Actor self, string upgrade, int duration) /// <summary>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.</summary>
public void GrantTimedUpgrade(Actor self, string upgrade, int duration, object source = null)
{ {
var timed = timedUpgrades.FirstOrDefault(u => u.Upgrade == upgrade); var timed = timedUpgrades.FirstOrDefault(u => u.Upgrade == upgrade);
if (timed == null) if (timed == null)
{ {
timed = new TimedUpgrade(upgrade, duration); timed = new TimedUpgrade(upgrade, duration, source);
timedUpgrades.Add(timed); timedUpgrades.Add(timed);
GrantUpgrade(self, upgrade, 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 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, // 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); s.Watchers.Add(action);
} }
/// <summary>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).</summary>
public void Tick(Actor self) public void Tick(Actor self)
{ {
foreach (var u in timedUpgrades) foreach (var u in timedUpgrades)
{ {
u.Tick(); u.Tick();
if (u.Remaining <= 0) foreach (var source in u.Sources)
RevokeUpgrade(self, u.Upgrade, u); 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) foreach (var a in upgrades.Value[u.Upgrade].Watchers)
a(u.Duration, u.Remaining); a(u.Duration, u.Remaining);

View File

@@ -49,13 +49,16 @@ namespace OpenRA.Mods.Common.Warheads
foreach (var u in Upgrades) foreach (var u in Upgrades)
{ {
if (!um.AcceptsUpgrade(a, u))
continue;
if (Duration > 0) if (Duration > 0)
um.GrantTimedUpgrade(a, u, Duration); {
if (um.AcknowledgesUpgrade(a, u))
um.GrantTimedUpgrade(a, u, Duration, firedBy);
}
else else
um.GrantUpgrade(a, u, this); {
if (um.AcceptsUpgrade(a, u))
um.GrantUpgrade(a, u, this);
}
} }
} }
} }

View File

@@ -55,7 +55,7 @@
UpgradeMinEnabledLevel: 1 UpgradeMinEnabledLevel: 1
DamageMultiplier@IRONCURTAIN: DamageMultiplier@IRONCURTAIN:
UpgradeTypes: invulnerability UpgradeTypes: invulnerability
Modifier: 0, 0 Modifier: 0
TimedUpgradeBar: TimedUpgradeBar:
Upgrade: invulnerability Upgrade: invulnerability

View File

@@ -359,12 +359,10 @@
UpgradeOverlay@EMPDISABLE: UpgradeOverlay@EMPDISABLE:
UpgradeTypes: empdisable UpgradeTypes: empdisable
UpgradeMinEnabledLevel: 1 UpgradeMinEnabledLevel: 1
UpgradeMaxAcceptedLevel: 2
Palette: disabled Palette: disabled
DisableUpgrade@EMPDISABLE: DisableUpgrade@EMPDISABLE:
UpgradeTypes: empdisable UpgradeTypes: empdisable
UpgradeMinEnabledLevel: 1 UpgradeMinEnabledLevel: 1
UpgradeMaxAcceptedLevel: 2
TimedUpgradeBar@EMPDISABLE: TimedUpgradeBar@EMPDISABLE:
Upgrade: empdisable Upgrade: empdisable
Color: 255,255,255 Color: 255,255,255
@@ -377,11 +375,9 @@
ShowToEnemies: true ShowToEnemies: true
ZOffset: 512 ZOffset: 512
UpgradeMinEnabledLevel: 1 UpgradeMinEnabledLevel: 1
UpgradeMaxAcceptedLevel: 2
Cloak@CLOAKGENERATOR: Cloak@CLOAKGENERATOR:
UpgradeTypes: cloakgenerator UpgradeTypes: cloakgenerator
UpgradeMinEnabledLevel: 1 UpgradeMinEnabledLevel: 1
UpgradeMaxAcceptedLevel: 2
InitialDelay: 0 InitialDelay: 0
CloakDelay: 90 CloakDelay: 90
MustBeDestroyed: MustBeDestroyed: