248 lines
10 KiB
C#
248 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Xml.Linq;
|
|
using CodeWriter.ExpressionParser;
|
|
using UnityEngine;
|
|
|
|
public class MinEventActionCVarExpression : MinEventActionTargetedBase
|
|
{
|
|
private enum VariableType
|
|
{
|
|
None,
|
|
CVar,
|
|
RandomInt,
|
|
RandomFloat,
|
|
TierList
|
|
}
|
|
|
|
private class VariableInfo
|
|
{
|
|
public VariableType varType;
|
|
public string cvarName;
|
|
public float[] valueList;
|
|
public float randomMin;
|
|
public float randomMax;
|
|
}
|
|
public string cvarName;
|
|
public MinEventActionModifyCVar.OperationTypes operation;
|
|
private bool isValid = false;
|
|
private ExpressionContext<float> context;
|
|
private Expression<float> compiledExpr;
|
|
private VariableInfo[] variableInfos;
|
|
private MinEventParams minEventContext;
|
|
private EntityAlive target;
|
|
|
|
public override bool CanExecute(MinEventTypes _eventType, MinEventParams _params)
|
|
{
|
|
if (cvarName != null && cvarName.StartsWith("_"))
|
|
{
|
|
Log.Out("CVar '{0}' is readonly", new object[] { cvarName });
|
|
return false;
|
|
}
|
|
if (!isValid)
|
|
{
|
|
Log.Out("Invalid expression!");
|
|
return false;
|
|
}
|
|
return base.CanExecute(_eventType, _params);
|
|
}
|
|
|
|
public override void Execute(MinEventParams _params)
|
|
{
|
|
if (_params.Self.isEntityRemote && !_params.IsLocal)
|
|
{
|
|
return;
|
|
}
|
|
minEventContext = _params;
|
|
if (compiledExpr == null)
|
|
{
|
|
return;
|
|
}
|
|
for (int i = 0; i < targets.Count; i++)
|
|
{
|
|
target = targets[i];
|
|
float cvar = target.Buffs.GetCustomVar(cvarName);
|
|
float value = compiledExpr.Invoke();
|
|
switch (operation)
|
|
{
|
|
case MinEventActionModifyCVar.OperationTypes.set:
|
|
case MinEventActionModifyCVar.OperationTypes.setvalue:
|
|
cvar = value;
|
|
break;
|
|
case MinEventActionModifyCVar.OperationTypes.add:
|
|
cvar += value;
|
|
break;
|
|
case MinEventActionModifyCVar.OperationTypes.subtract:
|
|
cvar -= value;
|
|
break;
|
|
case MinEventActionModifyCVar.OperationTypes.multiply:
|
|
cvar *= value;
|
|
break;
|
|
case MinEventActionModifyCVar.OperationTypes.divide:
|
|
cvar /= ((value == 0f) ? 0.0001f : value);
|
|
break;
|
|
case MinEventActionModifyCVar.OperationTypes.percentadd:
|
|
cvar += cvar * value;
|
|
break;
|
|
case MinEventActionModifyCVar.OperationTypes.percentsubtract:
|
|
cvar -= cvar * value;
|
|
break;
|
|
}
|
|
target.Buffs.SetCustomVar(cvarName, cvar);
|
|
}
|
|
minEventContext = null;
|
|
target = null;
|
|
}
|
|
|
|
public override bool ParseXmlAttribute(XAttribute _attribute)
|
|
{
|
|
bool flag = base.ParseXmlAttribute(_attribute);
|
|
if (!flag)
|
|
{
|
|
switch(_attribute.Name.LocalName)
|
|
{
|
|
case "cvar":
|
|
cvarName = _attribute.Value;
|
|
flag = true;
|
|
break;
|
|
case "expression":
|
|
isValid = true;
|
|
string expr = _attribute.Value;
|
|
context = new ExpressionContext<float>();
|
|
List<VariableInfo> variableInfos = new List<VariableInfo>();
|
|
Dictionary<string, int> varStrs = new Dictionary<string, int>();
|
|
while (true)
|
|
{
|
|
int nextVarStart = expr.IndexOf('[');
|
|
if (nextVarStart < 0)
|
|
{
|
|
break;
|
|
}
|
|
int nextVarEnd = expr.IndexOf(']', nextVarStart);
|
|
if (nextVarEnd < 0)
|
|
{
|
|
isValid = false;
|
|
break;
|
|
}
|
|
string varStr = expr.Substring(nextVarStart + 1, nextVarEnd - nextVarStart - 1);
|
|
VariableInfo variableInfo = null;
|
|
if (varStr.StartsWith("@"))
|
|
{
|
|
if (!varStrs.ContainsKey(varStr))
|
|
{
|
|
variableInfo = new VariableInfo();
|
|
variableInfo.varType = VariableType.CVar;
|
|
variableInfo.cvarName = varStr.Substring(1);
|
|
varStrs.Add(varStr, variableInfos.Count);
|
|
}
|
|
}
|
|
else if (varStr.StartsWith("randomInt", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
variableInfo = new VariableInfo();
|
|
variableInfo.varType = VariableType.RandomInt;
|
|
Vector2 vector = StringParsers.ParseVector2(varStr.Substring(varStr.IndexOf('(') + 1, varStr.IndexOf(')') - (varStr.IndexOf('(') + 1)));
|
|
variableInfo.randomMin = (int)vector.x;
|
|
variableInfo.randomMax = (int)vector.y;
|
|
}
|
|
else if (varStr.StartsWith("randomFloat", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
variableInfo = new VariableInfo();
|
|
variableInfo.varType = VariableType.RandomFloat;
|
|
Vector2 vector = StringParsers.ParseVector2(varStr.Substring(varStr.IndexOf('(') + 1, varStr.IndexOf(')') - (varStr.IndexOf('(') + 1)));
|
|
variableInfo.randomMin = vector.x;
|
|
variableInfo.randomMax = vector.y;
|
|
}
|
|
else if (varStr.Contains(','))
|
|
{
|
|
if (!varStrs.ContainsKey(varStr))
|
|
{
|
|
variableInfo = new VariableInfo();
|
|
variableInfo.varType = VariableType.TierList;
|
|
string[] array = varStr.Split(',', StringSplitOptions.None);
|
|
variableInfo.valueList = new float[array.Length];
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
variableInfo.valueList[i] = float.Parse(array[i]);
|
|
}
|
|
varStrs.Add(varStr, variableInfos.Count);
|
|
}
|
|
}
|
|
else if (float.TryParse(varStr, out _))
|
|
{
|
|
|
|
expr = expr.Remove(nextVarEnd).Remove(nextVarStart);
|
|
}
|
|
else
|
|
{
|
|
isValid = false;
|
|
break;
|
|
}
|
|
int curIndex = varStrs.TryGetValue(varStr, out var index) ? index : variableInfos.Count;
|
|
string varName = "x" + curIndex;
|
|
expr = expr.Remove(nextVarStart, nextVarEnd - nextVarStart + 1).Insert(nextVarStart, varName);
|
|
//Log.Out($"cur index {curIndex} var name {varStr} is new var {curIndex == variableInfos.Count}");
|
|
if (curIndex == variableInfos.Count)
|
|
{
|
|
context.RegisterVariable(varName, () => { return EvaluateVar(curIndex); });
|
|
}
|
|
if (variableInfo != null)
|
|
{
|
|
variableInfos.Add(variableInfo);
|
|
}
|
|
}
|
|
if (!isValid)
|
|
{
|
|
Log.Out("Invalid expression: {0}", new object[] { expr });
|
|
return false;
|
|
}
|
|
Log.Out($"Compiling expr {expr}...");
|
|
compiledExpr = FloatExpressionParser.Instance.Compile(expr, context, true);
|
|
this.variableInfos = variableInfos.ToArray();
|
|
flag = true;
|
|
break;
|
|
case "operation":
|
|
this.operation = EnumUtils.Parse<MinEventActionModifyCVar.OperationTypes>(_attribute.Value, true);
|
|
flag = true;
|
|
break;
|
|
}
|
|
}
|
|
return flag;
|
|
}
|
|
|
|
private float EvaluateVar(int index)
|
|
{
|
|
var variableInfo = variableInfos[index];
|
|
switch (variableInfo.varType)
|
|
{
|
|
case VariableType.CVar:
|
|
return target.Buffs.GetCustomVar(variableInfo.cvarName);
|
|
case VariableType.RandomInt:
|
|
return Mathf.Clamp(minEventContext.Self.rand.RandomRange((int)variableInfo.randomMin, (int)variableInfo.randomMax + 1), variableInfo.randomMin, variableInfo.randomMax);
|
|
case VariableType.RandomFloat:
|
|
return Mathf.Clamp(minEventContext.Self.rand.RandomRange(variableInfo.randomMin, variableInfo.randomMax + 1), variableInfo.randomMin, variableInfo.randomMax);
|
|
case VariableType.TierList:
|
|
if (minEventContext.ParentType == MinEffectController.SourceParentType.ItemClass || minEventContext.ParentType == MinEffectController.SourceParentType.ItemModifierClass)
|
|
{
|
|
if (!minEventContext.ItemValue.IsEmpty())
|
|
{
|
|
int tier = (int)(minEventContext.ItemValue.Quality - 1);
|
|
if (tier >= 0)
|
|
{
|
|
return variableInfo.valueList[tier];
|
|
}
|
|
}
|
|
}
|
|
else if (minEventContext.ParentType == MinEffectController.SourceParentType.ProgressionClass && minEventContext.ProgressionValue != null)
|
|
{
|
|
int level = minEventContext.ProgressionValue.CalculatedLevel(minEventContext.Self);
|
|
if (level >= 0)
|
|
{
|
|
return variableInfo.valueList[level];
|
|
}
|
|
}
|
|
return 0f;
|
|
default:
|
|
return 0f;
|
|
}
|
|
}
|
|
} |