diff --git a/OpenRA.Game/Traits/Player/PowerManager.cs b/OpenRA.Game/Traits/Player/PowerManager.cs index e3bc100476..0eaf4a5398 100644 --- a/OpenRA.Game/Traits/Player/PowerManager.cs +++ b/OpenRA.Game/Traits/Player/PowerManager.cs @@ -102,11 +102,13 @@ namespace OpenRA.Traits } } - public PowerState GetPowerState() + public PowerState PowerState { - if (PowerProvided >= PowerDrained) return PowerState.Normal; - if (PowerProvided > PowerDrained / 2) return PowerState.Low; - return PowerState.Critical; + get { + if (PowerProvided >= PowerDrained) return PowerState.Normal; + if (PowerProvided > PowerDrained / 2) return PowerState.Low; + return PowerState.Critical; + } } } } diff --git a/OpenRA.Game/Traits/Player/ProductionQueue.cs b/OpenRA.Game/Traits/Player/ProductionQueue.cs index 570268e1bc..9c6906688b 100644 --- a/OpenRA.Game/Traits/Player/ProductionQueue.cs +++ b/OpenRA.Game/Traits/Player/ProductionQueue.cs @@ -276,7 +276,7 @@ namespace OpenRA.Traits if (Paused) return; - if (pm.GetPowerState() != PowerState.Normal) + if (pm.PowerState != PowerState.Normal) { if (--slowdown <= 0) slowdown = Queue.Info.LowPowerSlowdown; diff --git a/OpenRA.Game/Traits/Player/TechTree.cs b/OpenRA.Game/Traits/Player/TechTree.cs index f2c9b9e3ca..5a5af226ca 100755 --- a/OpenRA.Game/Traits/Player/TechTree.cs +++ b/OpenRA.Game/Traits/Player/TechTree.cs @@ -14,12 +14,12 @@ using OpenRA.FileFormats; namespace OpenRA.Traits { - class TechTreeInfo : ITraitInfo + public class TechTreeInfo : ITraitInfo { public object Create(ActorInitializer init) { return new TechTree(init);} } - class TechTree + public class TechTree { readonly List watchers = new List(); readonly Player player; @@ -42,10 +42,16 @@ namespace OpenRA.Traits foreach(var w in watchers) w.Update(buildings); } - + public void Add(string key, List prerequisites, ITechTreeElement tte) { - watchers.Add(new Watcher( key, prerequisites, tte )); + Add(key, prerequisites, false, tte); + } + + // set requiresPowered = true to discard buildings that have an IDisabled active (eg manually powered down) + public void Add(string key, List prerequisites, bool requiresPowered, ITechTreeElement tte) + { + watchers.Add(new Watcher( key, prerequisites, requiresPowered, tte )); } public void Remove(string key) @@ -53,7 +59,7 @@ namespace OpenRA.Traits watchers.RemoveAll(x => x.key == key); } - public static Cache> GatherBuildings( Player player ) + static Cache> GatherBuildings( Player player ) { var ret = new Cache>( x => new List() ); if (player == null) @@ -77,25 +83,28 @@ namespace OpenRA.Traits public readonly List prerequisites; public readonly ITechTreeElement watcher; bool hasPrerequisites; - - public Watcher(string key, List prerequisites, ITechTreeElement watcher) + bool requiresPowered; + + public Watcher(string key, List prerequisites, bool requiresPowered, ITechTreeElement watcher) { this.key = key; this.prerequisites = prerequisites; this.watcher = watcher; this.hasPrerequisites = false; + this.requiresPowered = requiresPowered; } public void Update(Cache> buildings) - { + { var nowHasPrerequisites = true; foreach (var p in prerequisites) - if (!buildings.Keys.Contains(p)) + if (!buildings.Keys.Contains(p) || + (requiresPowered && buildings[p].All(b => b.TraitsImplementing().Any(d => d.Disabled)))) { nowHasPrerequisites = false; break; } - + if( nowHasPrerequisites && !hasPrerequisites ) watcher.PrerequisitesAvailable(key); @@ -107,7 +116,7 @@ namespace OpenRA.Traits } } - interface ITechTreeElement + public interface ITechTreeElement { void PrerequisitesAvailable(string key); void PrerequisitesUnavailable(string key); diff --git a/OpenRA.Game/Traits/SupportPower.cs b/OpenRA.Game/Traits/SupportPower.cs index a886d434f8..f99dc1a6d4 100644 --- a/OpenRA.Game/Traits/SupportPower.cs +++ b/OpenRA.Game/Traits/SupportPower.cs @@ -47,7 +47,6 @@ namespace OpenRA.Traits protected readonly Actor Self; protected readonly Player Owner; - string[] effectivePrereq = {}; bool notifiedCharging; bool notifiedReady; @@ -60,9 +59,6 @@ namespace OpenRA.Traits Self = self; Owner = self.Owner; PlayerPower = self.Trait(); - - effectivePrereq = Info.Prerequisites - .Select(a => a.ToLowerInvariant()).ToArray(); self.Trait().Add( Info.OrderName, Info.Prerequisites.Select( a => a.ToLowerInvariant() ).ToList(), this ); } @@ -74,8 +70,8 @@ namespace OpenRA.Traits if (Info.GivenAuto) IsAvailable = hasPrerequisites; - - if (IsAvailable && (!Info.RequiresPower || IsPowered())) + + if (IsAvailable && (!Info.RequiresPower || PlayerPower.PowerState == PowerState.Normal)) { if (Game.LobbyInfo.GlobalSettings.AllowCheats && self.Trait().FastCharge) RemainingTime = 0; @@ -97,16 +93,6 @@ namespace OpenRA.Traits } } - bool IsPowered() - { - if (effectivePrereq.Count() == 0) - return PlayerPower.GetPowerState() == PowerState.Normal; - - // Takes 0.3ms on pchote's machine -- calling it every tick for every active special power is retarded - var buildings = TechTree.GatherBuildings(Owner); - return effectivePrereq.All(a => buildings[a].Any(b => !b.TraitsImplementing().All(d => d.Disabled))); - } - public void FinishActivate() { if (Info.OneShot) @@ -135,7 +121,7 @@ namespace OpenRA.Traits if (!IsAvailable || !IsReady) return; - if (Info.RequiresPower && !IsPowered()) + if (Info.RequiresPower && PlayerPower.PowerState != PowerState.Normal) { var eva = Owner.World.WorldActor.Info.Traits.Get(); Sound.Play(eva.AbilityInsufficientPower); diff --git a/OpenRA.Mods.RA/CanPowerDown.cs b/OpenRA.Mods.RA/CanPowerDown.cs index f6c0049929..012491a7bc 100755 --- a/OpenRA.Mods.RA/CanPowerDown.cs +++ b/OpenRA.Mods.RA/CanPowerDown.cs @@ -22,11 +22,13 @@ namespace OpenRA.Mods.RA [Sync] bool disabled = false; int normalPower = 0; - readonly PowerManager PlayerPower; + readonly PowerManager PowerManager; + readonly TechTree TechTree; public CanPowerDown(ActorInitializer init) { - PlayerPower = init.self.Owner.PlayerActor.Trait(); + PowerManager = init.self.Owner.PlayerActor.Trait(); + TechTree = init.self.Owner.PlayerActor.Trait(); normalPower = init.self.Info.Traits.Get().Power; } public bool Disabled { get { return disabled; } } @@ -39,7 +41,10 @@ namespace OpenRA.Mods.RA var eva = self.World.WorldActor.Info.Traits.Get(); Sound.PlayToPlayer(self.Owner, disabled ? eva.EnablePower : eva.DisablePower); - PlayerPower.UpdateActor(self, disabled ? 0 : normalPower); + PowerManager.UpdateActor(self, disabled ? 0 : normalPower); + + // Rebuild the tech tree; some support powers require active buildings + TechTree.Update(); } } } diff --git a/OpenRA.Mods.RA/HackyAI.cs b/OpenRA.Mods.RA/HackyAI.cs index 5904631a43..16e1c89679 100644 --- a/OpenRA.Mods.RA/HackyAI.cs +++ b/OpenRA.Mods.RA/HackyAI.cs @@ -31,7 +31,6 @@ namespace OpenRA.Mods.RA bool enabled; int ticks; Player p; - PlayerResources playerResources; PowerManager playerPower; int2 baseCenter; @@ -70,8 +69,6 @@ namespace OpenRA.Mods.RA { this.p = p; enabled = true; - - playerResources = p.PlayerActor.Trait(); playerPower = p.PlayerActor.Trait(); } diff --git a/OpenRA.Mods.RA/OreRefinery.cs b/OpenRA.Mods.RA/OreRefinery.cs index 3ca05b4168..8760db3b43 100644 --- a/OpenRA.Mods.RA/OreRefinery.cs +++ b/OpenRA.Mods.RA/OreRefinery.cs @@ -90,7 +90,7 @@ namespace OpenRA.Mods.RA Ore -= amount; PlayerResources.GiveOre (amount); } - nextProcessTime = (PlayerPower.GetPowerState() == PowerState.Normal)? + nextProcessTime = (PlayerPower.PowerState == PowerState.Normal)? Info.ProcessTick : Info.LowPowerProcessTick ; } } diff --git a/OpenRA.Mods.RA/RequiresPower.cs b/OpenRA.Mods.RA/RequiresPower.cs index 7f22060571..5a3f8c0f35 100644 --- a/OpenRA.Mods.RA/RequiresPower.cs +++ b/OpenRA.Mods.RA/RequiresPower.cs @@ -19,11 +19,9 @@ namespace OpenRA.Mods.RA class RequiresPower : IDisable { - readonly Actor self; readonly PowerManager power; public RequiresPower( Actor self ) { - this.self = self; power = self.Owner.PlayerActor.Trait(); } diff --git a/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs b/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs index 119e090204..4c58b6270d 100755 --- a/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs +++ b/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs @@ -454,7 +454,7 @@ namespace OpenRA.Mods.RA.Widgets DrawRightAligned("${0}".F(cost), pos + new int2(-5, 5), (resources.DisplayCash + resources.DisplayOre >= cost ? Color.White : Color.Red )); - var lowpower = power.GetPowerState() != PowerState.Normal; + var lowpower = power.PowerState != PowerState.Normal; var time = CurrentQueue.GetBuildTime(info.Name) * ((lowpower)? CurrentQueue.Info.LowPowerSlowdown : 1); DrawRightAligned(WorldUtils.FormatTime(time), pos + new int2(-5, 35), lowpower ? Color.Red: Color.White); diff --git a/OpenRA.Mods.RA/Widgets/PowerBinWidget.cs b/OpenRA.Mods.RA/Widgets/PowerBinWidget.cs index ea62964c7e..03981f21a4 100755 --- a/OpenRA.Mods.RA/Widgets/PowerBinWidget.cs +++ b/OpenRA.Mods.RA/Widgets/PowerBinWidget.cs @@ -50,9 +50,9 @@ namespace OpenRA.Mods.RA.Widgets float2 powerLevel = new float2(lastPowerProvidedPos.Value, barStart.Y); var color = Color.LimeGreen; - if (power.GetPowerState() == PowerState.Low) + if (power.PowerState == PowerState.Low) color = Color.Orange; - if (power.GetPowerState() == PowerState.Critical) + if (power.PowerState == PowerState.Critical) color = Color.Red; var colorDark = Graphics.Util.Lerp(0.25f, color, Color.Black);