Merge ConditionManager trait directly into Actor

This commit is contained in:
atlimit8
2020-04-18 23:25:05 -05:00
committed by reaperrr
parent e12c1dc9aa
commit 259c8d2c98
65 changed files with 466 additions and 707 deletions

View File

@@ -1,144 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2020 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 System;
using System.Collections.Generic;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Attach this to a unit to enable dynamic conditions by warheads, experience, crates, support powers, etc.")]
public class ConditionManagerInfo : TraitInfo<ConditionManager>, Requires<IObservesVariablesInfo> { }
public class ConditionManager : INotifyCreated
{
/// <summary>Value used to represent an invalid token.</summary>
public static readonly int InvalidConditionToken = -1;
class ConditionState
{
/// <summary>Delegates that have registered to be notified when this condition changes.</summary>
public readonly List<VariableObserverNotifier> Notifiers = new List<VariableObserverNotifier>();
/// <summary>Unique integers identifying granted instances of the condition.</summary>
public readonly HashSet<int> Tokens = new HashSet<int>();
}
Dictionary<string, ConditionState> state;
/// <summary>Each granted condition receives a unique token that is used when revoking.</summary>
Dictionary<int, string> tokens = new Dictionary<int, string>();
int nextToken = 1;
/// <summary>Cache of condition -> enabled state for quick evaluation of token counter conditions.</summary>
readonly Dictionary<string, int> conditionCache = new Dictionary<string, int>();
/// <summary>Read-only version of conditionCache that is passed to IConditionConsumers.</summary>
IReadOnlyDictionary<string, int> readOnlyConditionCache;
void INotifyCreated.Created(Actor self)
{
state = new Dictionary<string, ConditionState>();
readOnlyConditionCache = new ReadOnlyDictionary<string, int>(conditionCache);
var allObservers = new HashSet<VariableObserverNotifier>();
foreach (var provider in self.TraitsImplementing<IObservesVariables>())
{
foreach (var variableUser in provider.GetVariableObservers())
{
allObservers.Add(variableUser.Notifier);
foreach (var variable in variableUser.Variables)
{
var cs = state.GetOrAdd(variable);
cs.Notifiers.Add(variableUser.Notifier);
conditionCache[variable] = 0;
}
}
}
// Enable any conditions granted during trait setup
foreach (var kv in tokens)
{
ConditionState conditionState;
if (!state.TryGetValue(kv.Value, out conditionState))
continue;
conditionState.Tokens.Add(kv.Key);
conditionCache[kv.Value] = conditionState.Tokens.Count;
}
// Update all traits with their initial condition state
foreach (var consumer in allObservers)
consumer(self, readOnlyConditionCache);
}
void UpdateConditionState(Actor self, string condition, int token, bool isRevoke)
{
ConditionState conditionState;
if (!state.TryGetValue(condition, out conditionState))
return;
if (isRevoke)
conditionState.Tokens.Remove(token);
else
conditionState.Tokens.Add(token);
conditionCache[condition] = conditionState.Tokens.Count;
foreach (var notify in conditionState.Notifiers)
notify(self, readOnlyConditionCache);
}
/// <summary>Grants a specified condition.</summary>
/// <returns>The token that is used to revoke this condition.</returns>
public int GrantCondition(Actor self, string condition)
{
var token = nextToken++;
tokens.Add(token, condition);
// Conditions may be granted before the state is initialized.
// These conditions will be processed in INotifyCreated.Created.
if (state != null)
UpdateConditionState(self, condition, token, false);
return token;
}
/// <summary>
/// Revokes a previously granted condition.
/// </summary>
/// <param name="self">The actor to which this trait is attached.</param>
/// <param name="token">The token ID returned by GrantCondition.</param>
/// <returns>The invalid token ID.</returns>
public int RevokeCondition(Actor self, int token)
{
string condition;
if (!tokens.TryGetValue(token, out condition))
throw new InvalidOperationException("Attempting to revoke condition with invalid token {0} for {1}.".F(token, self));
tokens.Remove(token);
// Conditions may be granted and revoked before the state is initialized.
if (state != null)
UpdateConditionState(self, condition, token, true);
return InvalidConditionToken;
}
/// <summary>Returns whether the specified token is valid for RevokeCondition</summary>
public bool TokenValid(Actor self, int token)
{
return tokens.ContainsKey(token);
}
}
}

View File

@@ -23,7 +23,7 @@ namespace OpenRA.Mods.Common.Traits
}
[Desc("Allows a condition to be granted from an external source (Lua, warheads, etc).")]
public class ExternalConditionInfo : ITraitInfo, Requires<ConditionManagerInfo>
public class ExternalConditionInfo : ITraitInfo
{
[GrantedConditionReference]
[FieldLoader.Require]
@@ -55,7 +55,6 @@ namespace OpenRA.Mods.Common.Traits
}
public readonly ExternalConditionInfo Info;
readonly ConditionManager conditionManager;
readonly Dictionary<object, HashSet<int>> permanentTokens = new Dictionary<object, HashSet<int>>();
// Tokens are sorted on insert/remove by ascending expiry time
@@ -67,12 +66,11 @@ namespace OpenRA.Mods.Common.Traits
public ExternalCondition(Actor self, ExternalConditionInfo info)
{
Info = info;
conditionManager = self.Trait<ConditionManager>();
}
public bool CanGrantCondition(Actor self, object source)
{
if (conditionManager == null || source == null)
if (source == null)
return false;
// Timed tokens do not count towards the source cap: the condition with the shortest
@@ -93,9 +91,9 @@ namespace OpenRA.Mods.Common.Traits
public int GrantCondition(Actor self, object source, int duration = 0, int remaining = 0)
{
if (!CanGrantCondition(self, source))
return ConditionManager.InvalidConditionToken;
return Actor.InvalidConditionToken;
var token = conditionManager.GrantCondition(self, Info.Condition);
var token = self.GrantCondition(Info.Condition);
HashSet<int> permanent;
permanentTokens.TryGetValue(source, out permanent);
@@ -118,8 +116,8 @@ namespace OpenRA.Mods.Common.Traits
{
var expireToken = timedTokens[expireIndex].Token;
timedTokens.RemoveAt(expireIndex);
if (conditionManager.TokenValid(self, expireToken))
conditionManager.RevokeCondition(self, expireToken);
if (self.TokenValid(expireToken))
self.RevokeCondition(expireToken);
}
}
}
@@ -133,8 +131,8 @@ namespace OpenRA.Mods.Common.Traits
if (timedTokens.Count > 0)
{
var expire = timedTokens[0].Token;
if (conditionManager.TokenValid(self, expire))
conditionManager.RevokeCondition(self, expire);
if (self.TokenValid(expire))
self.RevokeCondition(expire);
timedTokens.RemoveAt(0);
}
@@ -166,7 +164,7 @@ namespace OpenRA.Mods.Common.Traits
/// <returns><c>true</c> if the now-revoked condition was originally granted by this trait.</returns>
public bool TryRevokeCondition(Actor self, object source, int token)
{
if (conditionManager == null || source == null)
if (source == null)
return false;
HashSet<int> permanentTokensForSource;
@@ -184,8 +182,8 @@ namespace OpenRA.Mods.Common.Traits
return false;
}
if (conditionManager.TokenValid(self, token))
conditionManager.RevokeCondition(self, token);
if (self.TokenValid(token))
self.RevokeCondition(token);
return true;
}
@@ -201,8 +199,8 @@ namespace OpenRA.Mods.Common.Traits
while (count < timedTokens.Count && timedTokens[count].Expires < worldTick)
{
var token = timedTokens[count].Token;
if (conditionManager.TokenValid(self, token))
conditionManager.RevokeCondition(self, token);
if (self.TokenValid(token))
self.RevokeCondition(token);
count++;
}

View File

@@ -29,31 +29,23 @@ namespace OpenRA.Mods.Common.Traits
class GrantCondition : ConditionalTrait<GrantConditionInfo>
{
ConditionManager conditionManager;
int conditionToken = ConditionManager.InvalidConditionToken;
int conditionToken = Actor.InvalidConditionToken;
public GrantCondition(GrantConditionInfo info)
: base(info) { }
protected override void Created(Actor self)
{
conditionManager = self.Trait<ConditionManager>();
base.Created(self);
}
protected override void TraitEnabled(Actor self)
{
if (conditionToken == ConditionManager.InvalidConditionToken)
conditionToken = conditionManager.GrantCondition(self, Info.Condition);
if (conditionToken == Actor.InvalidConditionToken)
conditionToken = self.GrantCondition(Info.Condition);
}
protected override void TraitDisabled(Actor self)
{
if (Info.GrantPermanently || conditionToken == ConditionManager.InvalidConditionToken)
if (Info.GrantPermanently || conditionToken == Actor.InvalidConditionToken)
return;
conditionToken = conditionManager.RevokeCondition(self, conditionToken);
conditionToken = self.RevokeCondition(conditionToken);
}
}
}

View File

@@ -52,7 +52,6 @@ namespace OpenRA.Mods.Common.Traits
int cooldown = 0;
int shotsFired = 0;
ConditionManager manager;
// Only tracked when RevokeOnNewTarget is true.
Target lastTarget = Target.Invalid;
@@ -60,33 +59,26 @@ namespace OpenRA.Mods.Common.Traits
public GrantConditionOnAttack(ActorInitializer init, GrantConditionOnAttackInfo info)
: base(info) { }
protected override void Created(Actor self)
{
base.Created(self);
manager = self.TraitOrDefault<ConditionManager>();
}
void GrantInstance(Actor self, string cond)
{
if (manager == null || string.IsNullOrEmpty(cond))
if (string.IsNullOrEmpty(cond))
return;
tokens.Push(manager.GrantCondition(self, cond));
tokens.Push(self.GrantCondition(cond));
}
void RevokeInstance(Actor self, bool revokeAll)
{
shotsFired = 0;
if (manager == null || tokens.Count == 0)
if (tokens.Count == 0)
return;
if (!revokeAll)
manager.RevokeCondition(self, tokens.Pop());
self.RevokeCondition(tokens.Pop());
else
while (tokens.Count > 0)
manager.RevokeCondition(self, tokens.Pop());
self.RevokeCondition(tokens.Pop());
}
void ITick.Tick(Actor self)

View File

@@ -33,8 +33,7 @@ namespace OpenRA.Mods.Common.Traits
{
readonly GrantConditionOnBotOwnerInfo info;
ConditionManager conditionManager;
int conditionToken = ConditionManager.InvalidConditionToken;
int conditionToken = Actor.InvalidConditionToken;
public GrantConditionOnBotOwner(ActorInitializer init, GrantConditionOnBotOwnerInfo info)
{
@@ -49,22 +48,18 @@ namespace OpenRA.Mods.Common.Traits
// it's defined on the PlayerActor.
self.World.AddFrameEndTask(w =>
{
conditionManager = self.TraitOrDefault<ConditionManager>();
if (conditionManager != null && self.Owner.IsBot && info.Bots.Contains(self.Owner.BotType))
conditionToken = conditionManager.GrantCondition(self, info.Condition);
if (self.Owner.IsBot && info.Bots.Contains(self.Owner.BotType))
conditionToken = self.GrantCondition(info.Condition);
});
}
void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
{
if (conditionManager == null)
return;
if (conditionToken != ConditionManager.InvalidConditionToken)
conditionToken = conditionManager.RevokeCondition(self, conditionToken);
if (conditionToken != Actor.InvalidConditionToken)
conditionToken = self.RevokeCondition(conditionToken);
if (info.Bots.Contains(newOwner.BotType))
conditionToken = conditionManager.GrantCondition(self, info.Condition);
conditionToken = self.GrantCondition(info.Condition);
}
}
}

View File

@@ -41,8 +41,7 @@ namespace OpenRA.Mods.Common.Traits
readonly GrantConditionOnDamageStateInfo info;
readonly IHealth health;
ConditionManager conditionManager;
int conditionToken = ConditionManager.InvalidConditionToken;
int conditionToken = Actor.InvalidConditionToken;
public GrantConditionOnDamageState(Actor self, GrantConditionOnDamageStateInfo info)
{
@@ -52,16 +51,15 @@ namespace OpenRA.Mods.Common.Traits
void INotifyCreated.Created(Actor self)
{
conditionManager = self.Trait<ConditionManager>();
GrantConditionOnValidDamageState(self, health.DamageState);
}
void GrantConditionOnValidDamageState(Actor self, DamageState state)
{
if (!info.ValidDamageStates.HasFlag(state) || conditionToken != ConditionManager.InvalidConditionToken)
if (!info.ValidDamageStates.HasFlag(state) || conditionToken != Actor.InvalidConditionToken)
return;
conditionToken = conditionManager.GrantCondition(self, info.Condition);
conditionToken = self.GrantCondition(info.Condition);
var sound = info.EnabledSounds.RandomOrDefault(Game.CosmeticRandom);
Game.Sound.Play(SoundType.World, sound, self.CenterPosition);
@@ -69,7 +67,7 @@ namespace OpenRA.Mods.Common.Traits
void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e)
{
var granted = conditionToken != ConditionManager.InvalidConditionToken;
var granted = conditionToken != Actor.InvalidConditionToken;
if (granted && info.GrantPermanently)
return;
@@ -77,7 +75,7 @@ namespace OpenRA.Mods.Common.Traits
GrantConditionOnValidDamageState(self, health.DamageState);
else if (granted && !info.ValidDamageStates.HasFlag(e.DamageState) && info.ValidDamageStates.HasFlag(e.PreviousDamageState))
{
conditionToken = conditionManager.RevokeCondition(self, conditionToken);
conditionToken = self.RevokeCondition(conditionToken);
var sound = info.DisabledSounds.RandomOrDefault(Game.CosmeticRandom);
Game.Sound.Play(SoundType.World, sound, self.CenterPosition);

View File

@@ -98,10 +98,9 @@ namespace OpenRA.Mods.Common.Traits
readonly IMove move;
DeployState deployState;
ConditionManager conditionManager;
INotifyDeployTriggered[] notify;
int deployedToken = ConditionManager.InvalidConditionToken;
int undeployedToken = ConditionManager.InvalidConditionToken;
int deployedToken = Actor.InvalidConditionToken;
int undeployedToken = Actor.InvalidConditionToken;
public DeployState DeployState { get { return deployState; } }
@@ -118,7 +117,6 @@ namespace OpenRA.Mods.Common.Traits
protected override void Created(Actor self)
{
conditionManager = self.TraitOrDefault<ConditionManager>();
notify = self.TraitsImplementing<INotifyDeployTriggered>().ToArray();
base.Created(self);
@@ -317,32 +315,32 @@ namespace OpenRA.Mods.Common.Traits
void OnDeployStarted()
{
if (undeployedToken != ConditionManager.InvalidConditionToken)
undeployedToken = conditionManager.RevokeCondition(self, undeployedToken);
if (undeployedToken != Actor.InvalidConditionToken)
undeployedToken = self.RevokeCondition(undeployedToken);
deployState = DeployState.Deploying;
}
void OnDeployCompleted()
{
if (conditionManager != null && !string.IsNullOrEmpty(Info.DeployedCondition) && deployedToken == ConditionManager.InvalidConditionToken)
deployedToken = conditionManager.GrantCondition(self, Info.DeployedCondition);
if (!string.IsNullOrEmpty(Info.DeployedCondition) && deployedToken == Actor.InvalidConditionToken)
deployedToken = self.GrantCondition(Info.DeployedCondition);
deployState = DeployState.Deployed;
}
void OnUndeployStarted()
{
if (deployedToken != ConditionManager.InvalidConditionToken)
deployedToken = conditionManager.RevokeCondition(self, deployedToken);
if (deployedToken != Actor.InvalidConditionToken)
deployedToken = self.RevokeCondition(deployedToken);
deployState = DeployState.Deploying;
}
void OnUndeployCompleted()
{
if (conditionManager != null && !string.IsNullOrEmpty(Info.UndeployedCondition) && undeployedToken == ConditionManager.InvalidConditionToken)
undeployedToken = conditionManager.GrantCondition(self, Info.UndeployedCondition);
if (!string.IsNullOrEmpty(Info.UndeployedCondition) && undeployedToken == Actor.InvalidConditionToken)
undeployedToken = self.GrantCondition(Info.UndeployedCondition);
deployState = DeployState.Undeployed;
}

View File

@@ -33,8 +33,7 @@ namespace OpenRA.Mods.Common.Traits
class GrantConditionOnFaction : ConditionalTrait<GrantConditionOnFactionInfo>, INotifyOwnerChanged
{
ConditionManager conditionManager;
int conditionToken = ConditionManager.InvalidConditionToken;
int conditionToken = Actor.InvalidConditionToken;
string faction;
public GrantConditionOnFaction(ActorInitializer init, GrantConditionOnFactionInfo info)
@@ -43,13 +42,6 @@ namespace OpenRA.Mods.Common.Traits
faction = init.Contains<FactionInit>() ? init.Get<FactionInit, string>() : init.Self.Owner.Faction.InternalName;
}
protected override void Created(Actor self)
{
conditionManager = self.Trait<ConditionManager>();
base.Created(self);
}
public void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
{
if (Info.ResetOnOwnerChange && faction != newOwner.Faction.InternalName)
@@ -63,16 +55,16 @@ namespace OpenRA.Mods.Common.Traits
protected override void TraitEnabled(Actor self)
{
if (conditionToken == ConditionManager.InvalidConditionToken && Info.Factions.Contains(faction))
conditionToken = conditionManager.GrantCondition(self, Info.Condition);
if (conditionToken == Actor.InvalidConditionToken && Info.Factions.Contains(faction))
conditionToken = self.GrantCondition(Info.Condition);
}
protected override void TraitDisabled(Actor self)
{
if (conditionToken == ConditionManager.InvalidConditionToken)
if (conditionToken == Actor.InvalidConditionToken)
return;
conditionToken = conditionManager.RevokeCondition(self, conditionToken);
conditionToken = self.RevokeCondition(conditionToken);
}
}
}

View File

@@ -53,8 +53,7 @@ namespace OpenRA.Mods.Common.Traits
readonly IHealth health;
readonly int maxHP;
ConditionManager conditionManager;
int conditionToken = ConditionManager.InvalidConditionToken;
int conditionToken = Actor.InvalidConditionToken;
public GrantConditionOnHealth(Actor self, GrantConditionOnHealthInfo info)
{
@@ -65,16 +64,15 @@ namespace OpenRA.Mods.Common.Traits
void INotifyCreated.Created(Actor self)
{
conditionManager = self.Trait<ConditionManager>();
GrantConditionOnValidHealth(self, health.HP);
}
void GrantConditionOnValidHealth(Actor self, int hp)
{
if (info.MinHP > hp || maxHP < hp || conditionToken != ConditionManager.InvalidConditionToken)
if (info.MinHP > hp || maxHP < hp || conditionToken != Actor.InvalidConditionToken)
return;
conditionToken = conditionManager.GrantCondition(self, info.Condition);
conditionToken = self.GrantCondition(info.Condition);
var sound = info.EnabledSounds.RandomOrDefault(Game.CosmeticRandom);
Game.Sound.Play(SoundType.World, sound, self.CenterPosition);
@@ -82,7 +80,7 @@ namespace OpenRA.Mods.Common.Traits
void INotifyDamage.Damaged(Actor self, AttackInfo e)
{
var granted = conditionToken != ConditionManager.InvalidConditionToken;
var granted = conditionToken != Actor.InvalidConditionToken;
if (granted && info.GrantPermanently)
return;
@@ -90,7 +88,7 @@ namespace OpenRA.Mods.Common.Traits
GrantConditionOnValidHealth(self, health.HP);
else if (granted && (info.MinHP > health.HP || maxHP < health.HP))
{
conditionToken = conditionManager.RevokeCondition(self, conditionToken);
conditionToken = self.RevokeCondition(conditionToken);
var sound = info.DisabledSounds.RandomOrDefault(Game.CosmeticRandom);
Game.Sound.Play(SoundType.World, sound, self.CenterPosition);

View File

@@ -40,16 +40,16 @@ namespace OpenRA.Mods.Common.Traits
protected override void UpdateConditions(Actor self, byte oldLayer, byte newLayer)
{
if (!jumpjetInAir && newLayer == ValidLayerType && oldLayer != ValidLayerType && conditionToken == ConditionManager.InvalidConditionToken)
if (!jumpjetInAir && newLayer == ValidLayerType && oldLayer != ValidLayerType && conditionToken == Actor.InvalidConditionToken)
{
conditionToken = conditionManager.GrantCondition(self, Info.Condition);
conditionToken = self.GrantCondition(Info.Condition);
jumpjetInAir = true;
}
// By the time the condition is meant to be revoked, the 'oldLayer' is already no longer the Jumpjet layer, either
if (jumpjetInAir && newLayer != ValidLayerType && oldLayer != ValidLayerType && conditionToken != ConditionManager.InvalidConditionToken)
if (jumpjetInAir && newLayer != ValidLayerType && oldLayer != ValidLayerType && conditionToken != Actor.InvalidConditionToken)
{
conditionToken = conditionManager.RevokeCondition(self, conditionToken);
conditionToken = self.RevokeCondition(conditionToken);
jumpjetInAir = false;
}
}

View File

@@ -24,8 +24,7 @@ namespace OpenRA.Mods.Common.Traits
public abstract class GrantConditionOnLayer<InfoType> : ConditionalTrait<InfoType>, INotifyCustomLayerChanged where InfoType : GrantConditionOnLayerInfo
{
protected readonly byte ValidLayerType;
protected ConditionManager conditionManager;
protected int conditionToken = ConditionManager.InvalidConditionToken;
protected int conditionToken = Actor.InvalidConditionToken;
public GrantConditionOnLayer(Actor self, InfoType info, byte validLayer)
: base(info)
@@ -33,40 +32,31 @@ namespace OpenRA.Mods.Common.Traits
ValidLayerType = validLayer;
}
protected override void Created(Actor self)
{
conditionManager = self.TraitOrDefault<ConditionManager>();
base.Created(self);
}
void INotifyCustomLayerChanged.CustomLayerChanged(Actor self, byte oldLayer, byte newLayer)
{
if (conditionManager == null)
return;
UpdateConditions(self, oldLayer, newLayer);
}
protected virtual void UpdateConditions(Actor self, byte oldLayer, byte newLayer)
{
if (newLayer == ValidLayerType && oldLayer != ValidLayerType && conditionToken == ConditionManager.InvalidConditionToken)
conditionToken = conditionManager.GrantCondition(self, Info.Condition);
else if (newLayer != ValidLayerType && oldLayer == ValidLayerType && conditionToken != ConditionManager.InvalidConditionToken)
conditionToken = conditionManager.RevokeCondition(self, conditionToken);
if (newLayer == ValidLayerType && oldLayer != ValidLayerType && conditionToken == Actor.InvalidConditionToken)
conditionToken = self.GrantCondition(Info.Condition);
else if (newLayer != ValidLayerType && oldLayer == ValidLayerType && conditionToken != Actor.InvalidConditionToken)
conditionToken = self.RevokeCondition(conditionToken);
}
protected override void TraitEnabled(Actor self)
{
if (self.Location.Layer == ValidLayerType && conditionToken == ConditionManager.InvalidConditionToken)
conditionToken = conditionManager.GrantCondition(self, Info.Condition);
if (self.Location.Layer == ValidLayerType && conditionToken == Actor.InvalidConditionToken)
conditionToken = self.GrantCondition(Info.Condition);
}
protected override void TraitDisabled(Actor self)
{
if (conditionToken == ConditionManager.InvalidConditionToken)
if (conditionToken == Actor.InvalidConditionToken)
return;
conditionToken = conditionManager.RevokeCondition(self, conditionToken);
conditionToken = self.RevokeCondition(conditionToken);
}
}
}

View File

@@ -43,9 +43,8 @@ namespace OpenRA.Mods.Common.Traits
if (direction != info.Direction)
return;
var conditionManager = self.TraitOrDefault<ConditionManager>();
if (conditionManager != null && !string.IsNullOrEmpty(info.Condition))
conditionManager.GrantCondition(self, info.Condition);
if (!string.IsNullOrEmpty(info.Condition))
self.GrantCondition(info.Condition);
}
}
}

View File

@@ -29,8 +29,7 @@ namespace OpenRA.Mods.Common.Traits
public class GrantConditionOnMovement : ConditionalTrait<GrantConditionOnMovementInfo>, INotifyMoving
{
readonly IMove movement;
ConditionManager conditionManager;
int conditionToken = ConditionManager.InvalidConditionToken;
int conditionToken = Actor.InvalidConditionToken;
public GrantConditionOnMovement(Actor self, GrantConditionOnMovementInfo info)
: base(info)
@@ -38,23 +37,14 @@ namespace OpenRA.Mods.Common.Traits
movement = self.Trait<IMove>();
}
protected override void Created(Actor self)
{
conditionManager = self.TraitOrDefault<ConditionManager>();
base.Created(self);
}
void UpdateCondition(Actor self, MovementType types)
{
if (conditionManager == null)
return;
var validMovement = !IsTraitDisabled && (types & Info.ValidMovementTypes) != 0;
if (!validMovement && conditionToken != ConditionManager.InvalidConditionToken)
conditionToken = conditionManager.RevokeCondition(self, conditionToken);
else if (validMovement && conditionToken == ConditionManager.InvalidConditionToken)
conditionToken = conditionManager.GrantCondition(self, Info.Condition);
if (!validMovement && conditionToken != Actor.InvalidConditionToken)
conditionToken = self.RevokeCondition(conditionToken);
else if (validMovement && conditionToken == Actor.InvalidConditionToken)
conditionToken = self.GrantCondition(Info.Condition);
}
void INotifyMoving.MovementTypeChanged(Actor self, MovementType types)

View File

@@ -33,8 +33,7 @@ namespace OpenRA.Mods.Common.Traits
readonly GrantConditionOnPlayerResourcesInfo info;
PlayerResources playerResources;
ConditionManager conditionManager;
int conditionToken = ConditionManager.InvalidConditionToken;
int conditionToken = Actor.InvalidConditionToken;
public GrantConditionOnPlayerResources(GrantConditionOnPlayerResourcesInfo info)
{
@@ -49,7 +48,6 @@ namespace OpenRA.Mods.Common.Traits
// it refers to the same actor as self.Owner.PlayerActor
var playerActor = self.Info.Name == "player" ? self : self.Owner.PlayerActor;
playerResources = playerActor.Trait<PlayerResources>();
conditionManager = self.TraitOrDefault<ConditionManager>();
}
void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
@@ -59,14 +57,14 @@ namespace OpenRA.Mods.Common.Traits
void ITick.Tick(Actor self)
{
if (string.IsNullOrEmpty(info.Condition) || conditionManager == null)
if (string.IsNullOrEmpty(info.Condition))
return;
var enabled = playerResources.Resources > info.Threshold;
if (enabled && conditionToken == ConditionManager.InvalidConditionToken)
conditionToken = conditionManager.GrantCondition(self, info.Condition);
else if (!enabled && conditionToken != ConditionManager.InvalidConditionToken)
conditionToken = conditionManager.RevokeCondition(self, conditionToken);
if (enabled && conditionToken == Actor.InvalidConditionToken)
conditionToken = self.GrantCondition(info.Condition);
else if (!enabled && conditionToken != Actor.InvalidConditionToken)
conditionToken = self.RevokeCondition(conditionToken);
}
}
}

View File

@@ -31,8 +31,7 @@ namespace OpenRA.Mods.Common.Traits
public class GrantConditionOnPowerState : ConditionalTrait<GrantConditionOnPowerStateInfo>, INotifyOwnerChanged, INotifyPowerLevelChanged
{
PowerManager playerPower;
ConditionManager conditionManager;
int conditionToken = ConditionManager.InvalidConditionToken;
int conditionToken = Actor.InvalidConditionToken;
bool validPowerState;
@@ -46,8 +45,6 @@ namespace OpenRA.Mods.Common.Traits
{
base.Created(self);
conditionManager = self.TraitOrDefault<ConditionManager>();
Update(self);
}
@@ -63,15 +60,12 @@ namespace OpenRA.Mods.Common.Traits
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);
if (validPowerState && conditionToken == Actor.InvalidConditionToken)
conditionToken = self.GrantCondition(Info.Condition);
else if (!validPowerState && conditionToken != Actor.InvalidConditionToken)
conditionToken = self.RevokeCondition(conditionToken);
}
void INotifyPowerLevelChanged.PowerLevelChanged(Actor self)

View File

@@ -34,9 +34,8 @@ namespace OpenRA.Mods.Common.Traits
readonly GrantConditionOnPrerequisiteInfo info;
bool wasAvailable;
ConditionManager conditionManager;
GrantConditionOnPrerequisiteManager globalManager;
int conditionToken = ConditionManager.InvalidConditionToken;
int conditionToken = Actor.InvalidConditionToken;
public GrantConditionOnPrerequisite(Actor self, GrantConditionOnPrerequisiteInfo info)
{
@@ -52,7 +51,6 @@ namespace OpenRA.Mods.Common.Traits
var playerActor = self.Info.Name == "player" ? self : self.Owner.PlayerActor;
globalManager = playerActor.Trait<GrantConditionOnPrerequisiteManager>();
conditionManager = self.TraitOrDefault<ConditionManager>();
}
void INotifyAddedToWorld.AddedToWorld(Actor self)
@@ -74,13 +72,13 @@ namespace OpenRA.Mods.Common.Traits
public void PrerequisitesUpdated(Actor self, bool available)
{
if (available == wasAvailable || conditionManager == null)
if (available == wasAvailable)
return;
if (available && conditionToken == ConditionManager.InvalidConditionToken)
conditionToken = conditionManager.GrantCondition(self, info.Condition);
else if (!available && conditionToken != ConditionManager.InvalidConditionToken)
conditionToken = conditionManager.RevokeCondition(self, conditionToken);
if (available && conditionToken == Actor.InvalidConditionToken)
conditionToken = self.GrantCondition(info.Condition);
else if (!available && conditionToken != Actor.InvalidConditionToken)
conditionToken = self.RevokeCondition(conditionToken);
wasAvailable = available;
}

View File

@@ -38,12 +38,11 @@ namespace OpenRA.Mods.Common.Traits
public object Create(ActorInitializer init) { return new GrantConditionOnProduction(init.Self, this); }
}
public class GrantConditionOnProduction : INotifyCreated, INotifyProduction, ITick, ISync, ISelectionBar
public class GrantConditionOnProduction : INotifyProduction, ITick, ISync, ISelectionBar
{
readonly GrantConditionOnProductionInfo info;
ConditionManager conditionManager;
int token = ConditionManager.InvalidConditionToken;
int token = Actor.InvalidConditionToken;
[Sync]
int ticks;
@@ -54,31 +53,26 @@ namespace OpenRA.Mods.Common.Traits
ticks = info.Duration;
}
void INotifyCreated.Created(Actor self)
{
conditionManager = self.TraitOrDefault<ConditionManager>();
}
void INotifyProduction.UnitProduced(Actor self, Actor other, CPos exit)
{
if (info.Actors.Any() && !info.Actors.Select(a => a.ToLowerInvariant()).Contains(other.Info.Name))
return;
if (conditionManager != null && token == ConditionManager.InvalidConditionToken)
token = conditionManager.GrantCondition(self, info.Condition);
if (token == Actor.InvalidConditionToken)
token = self.GrantCondition(info.Condition);
ticks = info.Duration;
}
void ITick.Tick(Actor self)
{
if (info.Duration >= 0 && token != ConditionManager.InvalidConditionToken && --ticks < 0)
token = conditionManager.RevokeCondition(self, token);
if (info.Duration >= 0 && token != Actor.InvalidConditionToken && --ticks < 0)
token = self.RevokeCondition(token);
}
float ISelectionBar.GetValue()
{
if (!info.ShowSelectionBar || info.Duration < 0 || token == ConditionManager.InvalidConditionToken)
if (!info.ShowSelectionBar || info.Duration < 0 || token == Actor.InvalidConditionToken)
return 0;
return (float)ticks / info.Duration;

View File

@@ -74,11 +74,11 @@ namespace OpenRA.Mods.Common.Traits
// Grant condition when new layer is Subterranean and depth is lower than transition depth,
// revoke condition when new layer is not Subterranean and depth is at or higher than transition depth.
if (newLayer == ValidLayerType && depth < transitionDepth && conditionToken == ConditionManager.InvalidConditionToken)
conditionToken = conditionManager.GrantCondition(self, Info.Condition);
else if (newLayer != ValidLayerType && depth > transitionDepth && conditionToken != ConditionManager.InvalidConditionToken)
if (newLayer == ValidLayerType && depth < transitionDepth && conditionToken == Actor.InvalidConditionToken)
conditionToken = self.GrantCondition(Info.Condition);
else if (newLayer != ValidLayerType && depth > transitionDepth && conditionToken != Actor.InvalidConditionToken)
{
conditionToken = conditionManager.RevokeCondition(self, conditionToken);
conditionToken = self.RevokeCondition(conditionToken);
PlayTransitionAudioVisuals(self, self.Location);
}
}

View File

@@ -28,13 +28,12 @@ namespace OpenRA.Mods.Common.Traits
public object Create(ActorInitializer init) { return new GrantConditionOnTerrain(init, this); }
}
public class GrantConditionOnTerrain : INotifyCreated, ITick
public class GrantConditionOnTerrain : ITick
{
readonly GrantConditionOnTerrainInfo info;
readonly TileSet tileSet;
ConditionManager conditionManager;
int conditionToken = ConditionManager.InvalidConditionToken;
int conditionToken = Actor.InvalidConditionToken;
string cachedTerrain;
public GrantConditionOnTerrain(ActorInitializer init, GrantConditionOnTerrainInfo info)
@@ -43,20 +42,12 @@ namespace OpenRA.Mods.Common.Traits
tileSet = init.World.Map.Rules.TileSet;
}
void INotifyCreated.Created(Actor self)
{
conditionManager = self.TraitOrDefault<ConditionManager>();
}
void ITick.Tick(Actor self)
{
var cell = self.Location;
if (!self.World.Map.Contains(cell))
return;
if (conditionManager == null)
return;
// The terrain type may change between ticks without the actor moving
var currentTerrain = cell.Layer == 0 ? self.World.Map.GetTerrainInfo(cell).Type :
tileSet[self.World.GetCustomMovementLayers()[cell.Layer].GetTerrainIndex(cell)].Type;
@@ -64,10 +55,10 @@ namespace OpenRA.Mods.Common.Traits
var wantsGranted = info.TerrainTypes.Contains(currentTerrain);
if (currentTerrain != cachedTerrain)
{
if (wantsGranted && conditionToken == ConditionManager.InvalidConditionToken)
conditionToken = conditionManager.GrantCondition(self, info.Condition);
else if (!wantsGranted && conditionToken != ConditionManager.InvalidConditionToken)
conditionToken = conditionManager.RevokeCondition(self, conditionToken);
if (wantsGranted && conditionToken == Actor.InvalidConditionToken)
conditionToken = self.GrantCondition(info.Condition);
else if (!wantsGranted && conditionToken != Actor.InvalidConditionToken)
conditionToken = self.RevokeCondition(conditionToken);
}
cachedTerrain = currentTerrain;

View File

@@ -23,33 +23,27 @@ namespace OpenRA.Mods.Common.Traits
object ITraitInfo.Create(ActorInitializer init) { return new GrantConditionWhileAiming(this); }
}
public class GrantConditionWhileAiming : INotifyCreated, INotifyAiming
public class GrantConditionWhileAiming : INotifyAiming
{
readonly GrantConditionWhileAimingInfo info;
ConditionManager conditionManager;
int conditionToken = ConditionManager.InvalidConditionToken;
int conditionToken = Actor.InvalidConditionToken;
public GrantConditionWhileAiming(GrantConditionWhileAimingInfo info)
{
this.info = info;
}
void INotifyCreated.Created(Actor self)
{
conditionManager = self.TraitOrDefault<ConditionManager>();
}
void INotifyAiming.StartedAiming(Actor self, AttackBase attack)
{
if (conditionToken == ConditionManager.InvalidConditionToken)
conditionToken = conditionManager.GrantCondition(self, info.Condition);
if (conditionToken == Actor.InvalidConditionToken)
conditionToken = self.GrantCondition(info.Condition);
}
void INotifyAiming.StoppedAiming(Actor self, AttackBase attack)
{
if (conditionToken != ConditionManager.InvalidConditionToken)
conditionToken = conditionManager.RevokeCondition(self, conditionToken);
if (conditionToken != Actor.InvalidConditionToken)
conditionToken = self.RevokeCondition(conditionToken);
}
}
}

View File

@@ -40,8 +40,7 @@ namespace OpenRA.Mods.Common.Traits.Conditions
return;
var condition = info.Conditions.Random(self.World.SharedRandom);
var conditionManager = self.Trait<ConditionManager>();
conditionManager.GrantCondition(self, condition);
self.GrantCondition(condition);
}
}
}

View File

@@ -42,8 +42,7 @@ namespace OpenRA.Mods.Common.Traits
public class ToggleConditionOnOrder : PausableConditionalTrait<ToggleConditionOnOrderInfo>, IResolveOrder
{
ConditionManager conditionManager;
int conditionToken = ConditionManager.InvalidConditionToken;
int conditionToken = Actor.InvalidConditionToken;
// If the trait is paused this may be true with no condition granted
[Sync]
@@ -52,21 +51,11 @@ namespace OpenRA.Mods.Common.Traits
public ToggleConditionOnOrder(Actor self, ToggleConditionOnOrderInfo info)
: base(info) { }
protected override void Created(Actor self)
{
base.Created(self);
conditionManager = self.TraitOrDefault<ConditionManager>();
}
void SetCondition(Actor self, bool granted)
{
if (conditionManager == null)
return;
if (granted && conditionToken == ConditionManager.InvalidConditionToken)
if (granted && conditionToken == Actor.InvalidConditionToken)
{
conditionToken = conditionManager.GrantCondition(self, Info.Condition);
conditionToken = self.GrantCondition(Info.Condition);
if (Info.EnabledSound != null)
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", Info.EnabledSound, self.Owner.Faction.InternalName);
@@ -74,9 +63,9 @@ namespace OpenRA.Mods.Common.Traits
if (Info.EnabledSpeech != null)
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", Info.EnabledSpeech, self.Owner.Faction.InternalName);
}
else if (!granted && conditionToken != ConditionManager.InvalidConditionToken)
else if (!granted && conditionToken != Actor.InvalidConditionToken)
{
conditionToken = conditionManager.RevokeCondition(self, conditionToken);
conditionToken = self.RevokeCondition(conditionToken);
if (Info.DisabledSound != null)
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", Info.DisabledSound, self.Owner.Faction.InternalName);