Add support for stacked condition bonuses.

This commit is contained in:
Paul Chote
2016-11-20 18:46:44 +00:00
parent 34a94e16f6
commit da6fd74881
3 changed files with 72 additions and 6 deletions

View File

@@ -776,6 +776,7 @@
<Compile Include="Traits\World\CliffBackImpassabilityLayer.cs" />
<Compile Include="Traits\Upgrades\GrantCondition.cs" />
<Compile Include="Traits\Upgrades\ExternalConditions.cs" />
<Compile Include="Traits\Upgrades\StackedCondition.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="AfterBuild">

View File

@@ -0,0 +1,32 @@
#region Copyright & License Information
/*
* Copyright 2007-2016 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("Grant additional conditions when a specified condition has been granted multiple times.")]
public class StackedConditionInfo : TraitInfo<StackedCondition>
{
[FieldLoader.Require]
[UpgradeUsedReference]
[Desc("Condition to monitor.")]
public readonly string Condition = null;
[FieldLoader.Require]
[UpgradeGrantedReference]
[Desc("Conditions to grant when the monitored condition is granted multiple times.",
"The first entry is activated at 2x grants, second entry at 3x grants, and so on.")]
public readonly string[] StackedConditions = { };
}
public class StackedCondition { }
}

View File

@@ -31,7 +31,6 @@ namespace OpenRA.Mods.Common.Traits
{
/// <summary>Value used to represent an invalid token.</summary>
public static readonly int InvalidConditionToken = -1;
string[] externalConditions = { };
class ConditionTimer
{
@@ -64,6 +63,15 @@ namespace OpenRA.Mods.Common.Traits
/// <summary>Each granted condition receives a unique token that is used when revoking.</summary>
Dictionary<int, string> tokens = new Dictionary<int, string>();
/// <summary>Set of whitelisted externally grantable conditions cached from ExternalConditions traits.</summary>
string[] externalConditions = { };
/// <summary>Set of conditions that are monitored for stacked bonuses, and the bonus conditions that they grant.</summary>
readonly Dictionary<string, string[]> stackedConditions = new Dictionary<string, string[]>();
/// <summary>Tokens granted by the stacked condition bonuses defined in stackedConditions.</summary>
readonly Dictionary<string, Stack<int>> stackedTokens = new Dictionary<string, Stack<int>>();
int nextToken = 1;
/// <summary>Temporary shim between the old and new upgrade/condition grant and revoke methods.</summary>
@@ -109,15 +117,21 @@ namespace OpenRA.Mods.Common.Traits
conditionCache[kv.Value] = conditionState.Tokens.Count > 0;
}
// Update all traits with their initial condition state
foreach (var consumer in allConsumers)
consumer.ConditionsChanged(self, readOnlyConditionCache);
// Build external condition whitelist
externalConditions = self.Info.TraitInfos<ExternalConditionsInfo>()
.SelectMany(t => t.Conditions)
.Distinct()
.ToArray();
foreach (var sc in self.Info.TraitInfos<StackedConditionInfo>())
{
stackedConditions[sc.Condition] = sc.StackedConditions;
stackedTokens[sc.Condition] = new Stack<int>();
}
// Update all traits with their initial condition state
foreach (var consumer in allConsumers)
consumer.ConditionsChanged(self, readOnlyConditionCache);
}
void UpdateConditionState(Actor self, string condition, int token, bool isRevoke)
@@ -135,6 +149,18 @@ namespace OpenRA.Mods.Common.Traits
foreach (var t in conditionState.Consumers)
t.ConditionsChanged(self, readOnlyConditionCache);
string[] sc;
if (stackedConditions.TryGetValue(condition, out sc))
{
var target = (conditionState.Tokens.Count - 1).Clamp(0, sc.Length);
var st = stackedTokens[condition];
for (var i = st.Count; i < target; i++)
st.Push(GrantCondition(self, sc[i]));
for (var i = st.Count; i > target; i--)
RevokeCondition(self, st.Pop());
}
}
/// <summary>Grants a specified condition.</summary>
@@ -193,7 +219,14 @@ namespace OpenRA.Mods.Common.Traits
if (state == null)
throw new InvalidOperationException("AcceptsExternalCondition cannot be queried before the actor has been fully created.");
return externalConditions.Contains(condition) && !conditionCache[condition];
if (!externalConditions.Contains(condition))
return false;
string[] sc;
if (stackedConditions.TryGetValue(condition, out sc))
return stackedTokens[condition].Count < sc.Length;
return !conditionCache[condition];
}
/// <summary>Returns whether the specified token is valid for RevokeCondition</summary>