Refactor PowerManager and RequiresPower to use conditions
Instead of Actor.IsDisabled. Added INotifyPowerLevelChanged interface to do so as efficiently as possible.
This commit is contained in:
@@ -24,7 +24,14 @@ using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public enum PowerState { Normal, Low, Critical }
|
||||
[Flags]
|
||||
public enum PowerState
|
||||
{
|
||||
Normal = 1,
|
||||
Low = 2,
|
||||
Critical = 4
|
||||
}
|
||||
|
||||
public enum WinState { Undefined, Won, Lost }
|
||||
|
||||
public class Player : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding
|
||||
|
||||
@@ -403,7 +403,7 @@
|
||||
<Compile Include="Traits\Power\CanPowerDown.cs" />
|
||||
<Compile Include="Traits\Power\Player\PowerManager.cs" />
|
||||
<Compile Include="Traits\Power\Power.cs" />
|
||||
<Compile Include="Traits\Power\RequiresPower.cs" />
|
||||
<Compile Include="Traits\Conditions\GrantConditionOnPowerState.cs" />
|
||||
<Compile Include="Traits\Power\ScalePowerWithHealth.cs" />
|
||||
<Compile Include="Traits\Production.cs" />
|
||||
<Compile Include="Traits\ProductionFromMapEdge.cs" />
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2017 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("Grants condition as long as a valid power state is maintained.")]
|
||||
public class GrantConditionOnPowerStateInfo : ConditionalTraitInfo
|
||||
{
|
||||
[FieldLoader.Require]
|
||||
[GrantedConditionReference]
|
||||
[Desc("Condition to grant.")]
|
||||
public readonly string Condition = null;
|
||||
|
||||
[FieldLoader.Require]
|
||||
[Desc("PowerStates at which the condition is granted. Options are Normal, Low and Critical.")]
|
||||
public readonly PowerState ValidPowerStates = PowerState.Low | PowerState.Critical;
|
||||
|
||||
public override object Create(ActorInitializer init) { return new GrantConditionOnPowerState(init.Self, this); }
|
||||
}
|
||||
|
||||
public class GrantConditionOnPowerState : ConditionalTrait<GrantConditionOnPowerStateInfo>, INotifyOwnerChanged, INotifyPowerLevelChanged
|
||||
{
|
||||
PowerManager playerPower;
|
||||
ConditionManager conditionManager;
|
||||
int conditionToken = ConditionManager.InvalidConditionToken;
|
||||
|
||||
bool validPowerState;
|
||||
|
||||
public GrantConditionOnPowerState(Actor self, GrantConditionOnPowerStateInfo info)
|
||||
: base(info)
|
||||
{
|
||||
playerPower = self.Owner.PlayerActor.Trait<PowerManager>();
|
||||
}
|
||||
|
||||
protected override void Created(Actor self)
|
||||
{
|
||||
base.Created(self);
|
||||
|
||||
conditionManager = self.TraitOrDefault<ConditionManager>();
|
||||
|
||||
Update(self);
|
||||
}
|
||||
|
||||
protected override void TraitEnabled(Actor self)
|
||||
{
|
||||
Update(self);
|
||||
}
|
||||
|
||||
protected override void TraitDisabled(Actor self)
|
||||
{
|
||||
Update(self);
|
||||
}
|
||||
|
||||
void Update(Actor self)
|
||||
{
|
||||
if (conditionManager == null)
|
||||
return;
|
||||
|
||||
validPowerState = !IsTraitDisabled && Info.ValidPowerStates.HasFlag(playerPower.PowerState);
|
||||
|
||||
if (validPowerState && conditionToken == ConditionManager.InvalidConditionToken)
|
||||
conditionToken = conditionManager.GrantCondition(self, Info.Condition);
|
||||
else if (!validPowerState && conditionToken != ConditionManager.InvalidConditionToken)
|
||||
conditionToken = conditionManager.RevokeCondition(self, conditionToken);
|
||||
}
|
||||
|
||||
void INotifyPowerLevelChanged.PowerLevelChanged(Actor self)
|
||||
{
|
||||
Update(self);
|
||||
}
|
||||
|
||||
void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
|
||||
{
|
||||
playerPower = newOwner.PlayerActor.Trait<PowerManager>();
|
||||
Update(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
readonly DeveloperMode devMode;
|
||||
|
||||
readonly Dictionary<Actor, int> powerDrain = new Dictionary<Actor, int>();
|
||||
|
||||
[Sync] int totalProvided;
|
||||
public int PowerProvided { get { return totalProvided; } }
|
||||
|
||||
@@ -43,6 +44,11 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public int PowerOutageRemainingTicks { get; private set; }
|
||||
public int PowerOutageTotalTicks { get; private set; }
|
||||
|
||||
int nextPowerAdviceTime = 0;
|
||||
bool lowPower = false;
|
||||
bool wasLowPower = false;
|
||||
bool wasHackEnabled;
|
||||
|
||||
public PowerManager(Actor self, PowerManagerInfo info)
|
||||
{
|
||||
this.self = self;
|
||||
@@ -86,10 +92,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
totalDrained += amount;
|
||||
}
|
||||
|
||||
int nextPowerAdviceTime = 0;
|
||||
bool wasLowPower = false;
|
||||
bool wasHackEnabled;
|
||||
|
||||
void ITick.Tick(Actor self)
|
||||
{
|
||||
if (wasHackEnabled != devMode.UnlimitedPower)
|
||||
@@ -107,15 +109,21 @@ namespace OpenRA.Mods.Common.Traits
|
||||
wasHackEnabled = devMode.UnlimitedPower;
|
||||
}
|
||||
|
||||
var lowPower = totalProvided < totalDrained;
|
||||
lowPower = ExcessPower < 0;
|
||||
|
||||
if (lowPower != wasLowPower)
|
||||
UpdateRequiresPowerActors();
|
||||
|
||||
if (lowPower && !wasLowPower)
|
||||
nextPowerAdviceTime = 0;
|
||||
|
||||
wasLowPower = lowPower;
|
||||
|
||||
if (--nextPowerAdviceTime <= 0)
|
||||
{
|
||||
if (lowPower)
|
||||
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.SpeechNotification, self.Owner.Faction.InternalName);
|
||||
|
||||
nextPowerAdviceTime = info.AdviceInterval;
|
||||
}
|
||||
|
||||
@@ -148,6 +156,15 @@ namespace OpenRA.Mods.Common.Traits
|
||||
p.Trait.UpdateStatus(p.Actor);
|
||||
}
|
||||
|
||||
void UpdateRequiresPowerActors()
|
||||
{
|
||||
var traitPairs = self.World.ActorsWithTrait<INotifyPowerLevelChanged>()
|
||||
.Where(p => !p.Actor.IsDead && p.Actor.IsInWorld && p.Actor.Owner == self.Owner);
|
||||
|
||||
foreach (var p in traitPairs)
|
||||
p.Trait.PowerLevelChanged(p.Actor);
|
||||
}
|
||||
|
||||
void IResolveOrder.ResolveOrder(Actor self, Order order)
|
||||
{
|
||||
if (devMode.Enabled && order.OrderString == "PowerOutage")
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2017 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("Needs power to operate.")]
|
||||
class RequiresPowerInfo : ConditionalTraitInfo, ITraitInfo
|
||||
{
|
||||
public override object Create(ActorInitializer init) { return new RequiresPower(init.Self, this); }
|
||||
}
|
||||
|
||||
class RequiresPower : ConditionalTrait<RequiresPowerInfo>, IDisable, INotifyOwnerChanged
|
||||
{
|
||||
PowerManager playerPower;
|
||||
|
||||
public RequiresPower(Actor self, RequiresPowerInfo info)
|
||||
: base(info)
|
||||
{
|
||||
playerPower = self.Owner.PlayerActor.Trait<PowerManager>();
|
||||
}
|
||||
|
||||
public bool Disabled
|
||||
{
|
||||
get { return playerPower.PowerProvided < playerPower.PowerDrained && !IsTraitDisabled; }
|
||||
}
|
||||
|
||||
public void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
|
||||
{
|
||||
playerPower = newOwner.PlayerActor.Trait<PowerManager>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,6 +95,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
void AfterRepair(Actor self, Actor target);
|
||||
}
|
||||
|
||||
[RequireExplicitImplementation]
|
||||
public interface INotifyPowerLevelChanged { void PowerLevelChanged(Actor self); }
|
||||
|
||||
public interface INotifyBuildingPlaced { void BuildingPlaced(Actor self); }
|
||||
public interface INotifyNuke { void Launching(Actor self); }
|
||||
public interface INotifyBurstComplete { void FiredBurst(Actor self, Target target, Armament a); }
|
||||
|
||||
Reference in New Issue
Block a user