Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of VelocityDamage v1.0.0
VelocityDamage.dll
Decompiled 3 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("McHorse")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+8d973f08bd55896d534c97eba8dec604eb08c189")] [assembly: AssemblyProduct("VelocityDamage")] [assembly: AssemblyTitle("VelocityDamage")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace VelocityDamage { internal sealed class FormulaEngine { private interface IFormulaNode { bool TryEvaluate(out float value, out string? error); } private sealed class ConstantNode : IFormulaNode { private readonly float _value; internal ConstantNode(float value) { _value = value; } public bool TryEvaluate(out float value, out string? error) { value = _value; error = null; return true; } } private sealed class VariableBinding { internal float Value { get; set; } internal VariableBinding(float value) { Value = value; } } private sealed class VariableNode : IFormulaNode { private readonly string _name; private readonly VariableBinding _binding; internal VariableNode(string name, VariableBinding binding) { _name = name; _binding = binding; } public bool TryEvaluate(out float value, out string? error) { value = _binding.Value; error = null; return true; } } private sealed class UnaryNegateNode : IFormulaNode { private readonly IFormulaNode _inner; internal UnaryNegateNode(IFormulaNode inner) { _inner = inner; } public bool TryEvaluate(out float value, out string? error) { if (!_inner.TryEvaluate(out var value2, out error)) { value = 0f; return false; } value = 0f - value2; return true; } } private sealed class BinaryOperatorNode : IFormulaNode { private readonly string _operator; private readonly IFormulaNode _left; private readonly IFormulaNode _right; internal BinaryOperatorNode(string @operator, IFormulaNode left, IFormulaNode right) { _operator = @operator; _left = left; _right = right; } public bool TryEvaluate(out float value, out string? error) { value = 0f; if (!_left.TryEvaluate(out var value2, out error)) { return false; } if (!_right.TryEvaluate(out var value3, out error)) { return false; } string @operator = _operator; if (1 == 0) { } float num = @operator switch { "+" => value2 + value3, "-" => value2 - value3, "*" => value2 * value3, "/" => (Math.Abs(value3) < 1E-05f) ? 0f : (value2 / value3), "%" => (Math.Abs(value3) < 1E-05f) ? 0f : (value2 % value3), "^" => (float)Math.Pow(value2, value3), _ => throw new InvalidOperationException("Unsupported operator '" + _operator + "'."), }; if (1 == 0) { } value = num; error = null; return true; } } private sealed class Parser { private readonly List<Token> _tokens; private int _index; internal Token Current => _tokens[_index]; internal bool IsAtEnd => Current.Type == TokenType.End; internal Parser(List<Token> tokens) { _tokens = tokens; _index = 0; } internal bool TryParseExpression(Dictionary<string, VariableBinding> variables, out IFormulaNode? node, out string? error) { return TryParseAddSub(variables, out node, out error); } private bool TryParseAddSub(Dictionary<string, VariableBinding> variables, out IFormulaNode? node, out string? error) { if (!TryParseMulDiv(variables, out node, out error) || node == null) { return false; } while (Match("+") || Match("-")) { string text = Previous().Text; if (!TryParseMulDiv(variables, out IFormulaNode node2, out error) || node2 == null) { return false; } node = new BinaryOperatorNode(text, node, node2); } return true; } private bool TryParseMulDiv(Dictionary<string, VariableBinding> variables, out IFormulaNode? node, out string? error) { if (!TryParsePowMod(variables, out node, out error) || node == null) { return false; } while (Match("*") || Match("/")) { string text = Previous().Text; if (!TryParsePowMod(variables, out IFormulaNode node2, out error) || node2 == null) { return false; } node = new BinaryOperatorNode(text, node, node2); } return true; } private bool TryParsePowMod(Dictionary<string, VariableBinding> variables, out IFormulaNode? node, out string? error) { if (!TryParseUnary(variables, out node, out error) || node == null) { return false; } while (Match("^") || Match("%")) { string text = Previous().Text; if (!TryParseUnary(variables, out IFormulaNode node2, out error) || node2 == null) { return false; } node = new BinaryOperatorNode(text, node, node2); } return true; } private bool TryParseUnary(Dictionary<string, VariableBinding> variables, out IFormulaNode? node, out string? error) { error = null; if (Match("-")) { if (!TryParseUnary(variables, out IFormulaNode node2, out error) || node2 == null) { node = null; return false; } node = new UnaryNegateNode(node2); return true; } return TryParsePrimary(variables, out node, out error); } private bool TryParsePrimary(Dictionary<string, VariableBinding> variables, out IFormulaNode? node, out string? error) { error = null; if (MatchType(TokenType.Number)) { node = new ConstantNode(Previous().NumberValue); return true; } if (MatchType(TokenType.Variable)) { string text = Previous().Text; if (!variables.TryGetValue(text, out VariableBinding value)) { error = "Unknown variable '" + text + "'. Register variables before parsing."; node = null; return false; } node = new VariableNode(text, value); return true; } if (Match("(")) { if (!TryParseExpression(variables, out node, out error) || node == null) { return false; } if (!Match(")")) { error = "Missing closing parenthesis."; return false; } return true; } error = "Unexpected token '" + Current.Text + "'."; node = null; return false; } private bool Match(string symbol) { if (Current.Type == TokenType.Symbol && Current.Text == symbol) { _index++; return true; } return false; } private bool MatchType(TokenType type) { if (Current.Type == type) { _index++; return true; } return false; } private Token Previous() { return _tokens[_index - 1]; } } private enum TokenType { Number, Variable, Symbol, End } private readonly struct Token { internal readonly TokenType Type; internal readonly string Text; internal readonly float NumberValue; internal Token(TokenType type, string text, float numberValue) { Type = type; Text = text; NumberValue = numberValue; } } private readonly Dictionary<string, VariableBinding> _variables = new Dictionary<string, VariableBinding>(StringComparer.OrdinalIgnoreCase); private IFormulaNode _root = new ConstantNode(0f); internal FormulaEngine() { } internal static bool TryCreate(string expression, out FormulaEngine? engine, out string? error) { engine = new FormulaEngine(); return engine.TryParse(expression, out error); } internal static FormulaEngine FromKnownValid(string expression) { if (!TryCreate(expression, out FormulaEngine engine, out string _)) { throw new InvalidOperationException("Expected valid formula."); } return engine; } internal void RegisterVariable(string name, float initialValue = 0f) { _variables[name] = new VariableBinding(initialValue); } internal void SetVariableValue(string name, float value) { if (_variables.TryGetValue(name, out VariableBinding value2)) { value2.Value = value; } } internal bool TryParse(string expression, out string? error) { error = null; if (string.IsNullOrWhiteSpace(expression)) { error = "Expression is empty."; return false; } if (!Tokenize(expression, out List<Token> tokens, out error) || tokens == null) { return false; } Parser parser = new Parser(tokens); if (!parser.TryParseExpression(_variables, out IFormulaNode node, out error) || node == null) { return false; } if (!parser.IsAtEnd) { error = "Unexpected token '" + parser.Current.Text + "'."; return false; } _root = node; return true; } internal bool TryEvaluate(out float value, out string? error) { return _root.TryEvaluate(out value, out error); } private static bool Tokenize(string expression, out List<Token>? tokens, out string? error) { tokens = new List<Token>(); error = null; int i = 0; while (i < expression.Length) { char c = expression[i]; if (char.IsWhiteSpace(c)) { i++; continue; } if (char.IsDigit(c) || c == '.') { int num = i; for (i++; i < expression.Length && (char.IsDigit(expression[i]) || expression[i] == '.'); i++) { } int num2 = num; string text = expression.Substring(num2, i - num2); if (!float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { error = "Invalid number '" + text + "'."; return false; } tokens.Add(new Token(TokenType.Number, text, result)); continue; } if (char.IsLetter(c) || c == '_') { int num3 = i; for (i++; i < expression.Length && (char.IsLetterOrDigit(expression[i]) || expression[i] == '_'); i++) { } int num2 = num3; string text2 = expression.Substring(num2, i - num2); tokens.Add(new Token(TokenType.Variable, text2, 0f)); continue; } bool flag; switch (c) { case '%': case '(': case ')': case '*': case '+': case '-': case '/': case '^': flag = true; break; default: flag = false; break; } if (flag) { tokens.Add(new Token(TokenType.Symbol, c.ToString(), 0f)); i++; continue; } error = $"Unexpected character '{c}'."; return false; } tokens.Add(new Token(TokenType.End, string.Empty, 0f)); return true; } } internal static class FormulaEngineSelfTests { private const float Epsilon = 0.0001f; internal static void Run(ManualLogSource logger) { int passed = 0; int failed = 0; Execute(logger, "PEDMAS", "2 + 3 * 4 - 8 / 2", 10f, null, ref passed, ref failed); Execute(logger, "Variables", "d + v * l", 16f, delegate(FormulaEngine engine) { engine.SetVariableValue("d", 4f); engine.SetVariableValue("v", 3f); engine.SetVariableValue("l", 4f); }, ref passed, ref failed); Execute(logger, "Negation (parenthesis)", "-(2 + 3)", -5f, null, ref passed, ref failed); Execute(logger, "Negation (variable)", "-d", -7f, delegate(FormulaEngine engine) { engine.SetVariableValue("d", 7f); }, ref passed, ref failed); Execute(logger, "Negation (constant)", "-2 + 5", 3f, null, ref passed, ref failed); Execute(logger, "Parenthesis", "(2 + 3) * (4 - 1)", 15f, null, ref passed, ref failed); logger.LogInfo((object)$"FormulaEngine tests complete. Passed: {passed}, Failed: {failed}"); } private static void Execute(ManualLogSource logger, string name, string expression, float expected, Action<FormulaEngine>? setupVariables, ref int passed, ref int failed) { FormulaEngine formulaEngine = CreateTestEngine(); if (!formulaEngine.TryParse(expression, out string error)) { failed++; logger.LogError((object)("[FormulaEngine Test] " + name + " FAILED: parse error: " + error)); return; } setupVariables?.Invoke(formulaEngine); if (!formulaEngine.TryEvaluate(out float value, out string error2)) { failed++; logger.LogError((object)("[FormulaEngine Test] " + name + " FAILED: eval error: " + error2)); } else if (Math.Abs(value - expected) <= 0.0001f) { passed++; logger.LogInfo((object)$"[FormulaEngine Test] {name} PASSED: expected={expected}, actual={value}"); } else { failed++; logger.LogError((object)$"[FormulaEngine Test] {name} FAILED: expected={expected}, actual={value}"); } } private static FormulaEngine CreateTestEngine() { FormulaEngine formulaEngine = new FormulaEngine(); formulaEngine.RegisterVariable("d"); formulaEngine.RegisterVariable("damage"); formulaEngine.RegisterVariable("v"); formulaEngine.RegisterVariable("velocity"); formulaEngine.RegisterVariable("l"); formulaEngine.RegisterVariable("level"); return formulaEngine; } } [HarmonyPatch] internal static class PhysGrabObjectImpactDetector_OnCollisionStay_Patch { [ThreadStatic] private static bool _isInCollisionHurtScope; [ThreadStatic] private static float _currentRelativeSpeed; internal static bool IsInCollisionHurtScope => _isInCollisionHurtScope; internal static float CurrentRelativeSpeed => _currentRelativeSpeed; private static MethodBase? TargetMethod() { Type type = AccessTools.TypeByName("PhysGrabObjectImpactDetector"); return ((object)type == null) ? null : AccessTools.Method(type, "OnCollisionStay", new Type[1] { typeof(Collision) }, (Type[])null); } private static void Prefix(Collision collision) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) _isInCollisionHurtScope = true; Vector3 relativeVelocity = collision.relativeVelocity; _currentRelativeSpeed = ((Vector3)(ref relativeVelocity)).magnitude; } private static void Finalizer() { _isInCollisionHurtScope = false; _currentRelativeSpeed = 0f; } } [HarmonyPatch] internal static class EnemyHealth_Hurt_Patch { private static MethodBase? TargetMethod() { Type type = AccessTools.TypeByName("EnemyHealth"); return ((object)type == null) ? null : AccessTools.Method(type, "Hurt", new Type[2] { typeof(int), typeof(Vector3) }, (Type[])null); } private static void Prefix(ref int __0) { if (PhysGrabObjectImpactDetector_OnCollisionStay_Patch.IsInCollisionHurtScope) { float currentRelativeSpeed = PhysGrabObjectImpactDetector_OnCollisionStay_Patch.CurrentRelativeSpeed; __0 = VelocityDamage.Instance.ScaleCollisionDamage(__0, currentRelativeSpeed); } else if (HurtCollider_EnemyHurt_TumbleScope_Patch.IsInTumbleEnemyHurtScope) { float currentTumbleVelocity = HurtCollider_EnemyHurt_TumbleScope_Patch.CurrentTumbleVelocity; __0 = VelocityDamage.Instance.ScaleTumblingPlayerEnemyDamage(__0, currentTumbleVelocity); } } } [HarmonyPatch] internal static class HurtCollider_EnemyHurt_TumbleScope_Patch { [ThreadStatic] private static bool _isInTumbleEnemyHurtScope; [ThreadStatic] private static float _currentTumbleVelocity; private static readonly Type? PlayerTumbleType = AccessTools.TypeByName("PlayerTumble"); private static readonly FieldInfo? PlayerTumblePhysGrabObjectField = (((object)PlayerTumbleType == null) ? null : AccessTools.Field(PlayerTumbleType, "physGrabObject")); private static readonly PropertyInfo? PhysGrabObjectRbVelocityProperty = AccessTools.Property(AccessTools.TypeByName("PhysGrabObject"), "rbVelocity"); private static readonly FieldInfo? PhysGrabObjectRbVelocityField = AccessTools.Field(AccessTools.TypeByName("PhysGrabObject"), "rbVelocity"); internal static bool IsInTumbleEnemyHurtScope => _isInTumbleEnemyHurtScope; internal static float CurrentTumbleVelocity => _currentTumbleVelocity; private static MethodBase? TargetMethod() { Type type = AccessTools.TypeByName("HurtCollider"); return ((object)type == null) ? null : AccessTools.Method(type, "EnemyHurt", (Type[])null, (Type[])null); } private static void Prefix(object __instance) { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) _isInTumbleEnemyHurtScope = false; _currentTumbleVelocity = 0f; Component val = (Component)((__instance is Component) ? __instance : null); if (val == null || (object)PlayerTumbleType == null) { return; } Component componentInParent = val.GetComponentInParent(PlayerTumbleType); if (componentInParent != null) { float currentTumbleVelocity = 0f; object obj = PlayerTumblePhysGrabObjectField?.GetValue(componentInParent); if (obj != null && (PhysGrabObjectRbVelocityProperty?.GetValue(obj) ?? PhysGrabObjectRbVelocityField?.GetValue(obj)) is Vector3 val2) { currentTumbleVelocity = ((Vector3)(ref val2)).magnitude; } _isInTumbleEnemyHurtScope = true; _currentTumbleVelocity = currentTumbleVelocity; } } private static void Finalizer() { _isInTumbleEnemyHurtScope = false; _currentTumbleVelocity = 0f; } } [BepInPlugin("McHorse.VelocityDamage", "VelocityDamage", "1.0")] public class VelocityDamage : BaseUnityPlugin { private const string DefaultFormula = "d * (1 + (v / 4) ^ 0.5)"; private const string DefaultTumbleEnemyFormula = "d * (1 + (v / 4) ^ 0.5)"; private ConfigEntry<string>? _damageFormulaConfig; private ConfigEntry<string>? _tumbleEnemyDamageFormulaConfig; private ConfigEntry<bool>? _debugDamageTestsConfig; private FormulaEngine? _formulaEngine; private FormulaEngine? _tumbleEnemyFormulaEngine; internal static VelocityDamage Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; set; } private void Awake() { Instance = this; ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; _damageFormulaConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Damage", "Collision damage", "d * (1 + (v / 4) ^ 0.5)", "Formula variables: d/damage, v/velocity, l/level (current level number, 1-based). Supported operators: +, -, *, /, % (modulo), ^ (power), and parentheses."); _damageFormulaConfig.SettingChanged += OnDamageFormulaChanged; _tumbleEnemyDamageFormulaConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Damage", "Tumble damage", "d * (1 + (v / 4) ^ 0.5)", "Formula used when a tumbling player damages an enemy. Variables: d/damage, v/velocity, l/level (current level number, 1-based). Supported operators: +, -, *, /, % (modulo), ^ (power), and parentheses."); _tumbleEnemyDamageFormulaConfig.SettingChanged += OnTumbleEnemyDamageFormulaChanged; _debugDamageTestsConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Damage", "Debug", false, "Enable FormulaEngine startup self-tests logging."); _formulaEngine = CreateFormulaEngine(); _tumbleEnemyFormulaEngine = CreateFormulaEngine(); ReloadFormulaEngine(_damageFormulaConfig.Value, isRuntimeChange: false); ReloadTumbleEnemyFormulaEngine(_tumbleEnemyDamageFormulaConfig.Value, isRuntimeChange: false); ConfigEntry<bool>? debugDamageTestsConfig = _debugDamageTestsConfig; if (debugDamageTestsConfig != null && debugDamageTestsConfig.Value) { FormulaEngineSelfTests.Run(Logger); } Patch(); Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!"); } internal void Patch() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0026: Expected O, but got Unknown if (Harmony == null) { Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; Harmony = val; } Harmony.PatchAll(); } internal void Unpatch() { Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void OnDestroy() { if (_damageFormulaConfig != null) { _damageFormulaConfig.SettingChanged -= OnDamageFormulaChanged; } if (_tumbleEnemyDamageFormulaConfig != null) { _tumbleEnemyDamageFormulaConfig.SettingChanged -= OnTumbleEnemyDamageFormulaChanged; } } private void OnDamageFormulaChanged(object sender, EventArgs e) { if (_damageFormulaConfig != null) { ReloadFormulaEngine(_damageFormulaConfig.Value, isRuntimeChange: true); } } private void OnTumbleEnemyDamageFormulaChanged(object sender, EventArgs e) { if (_tumbleEnemyDamageFormulaConfig != null) { ReloadTumbleEnemyFormulaEngine(_tumbleEnemyDamageFormulaConfig.Value, isRuntimeChange: true); } } private FormulaEngine CreateFormulaEngine() { FormulaEngine formulaEngine = new FormulaEngine(); formulaEngine.RegisterVariable("d"); formulaEngine.RegisterVariable("damage"); formulaEngine.RegisterVariable("v"); formulaEngine.RegisterVariable("velocity"); formulaEngine.RegisterVariable("l"); formulaEngine.RegisterVariable("level"); return formulaEngine; } private void ReloadFormulaEngine(string formulaText, bool isRuntimeChange) { string error = null; if (_formulaEngine != null && _formulaEngine.TryParse(formulaText, out error)) { Logger.LogInfo((object)("Damage formula " + (isRuntimeChange ? "updated" : "loaded") + ": " + formulaText)); return; } if (isRuntimeChange) { Logger.LogWarning((object)("Rejected invalid runtime formula '" + formulaText + "'. Keeping previous formula. Error: " + error)); return; } Logger.LogWarning((object)("Invalid startup formula '" + formulaText + "'. Using default 'd * (1 + (v / 4) ^ 0.5)'. Error: " + error)); _formulaEngine?.TryParse("d * (1 + (v / 4) ^ 0.5)", out string _); } private void ReloadTumbleEnemyFormulaEngine(string formulaText, bool isRuntimeChange) { string error = null; if (_tumbleEnemyFormulaEngine != null && _tumbleEnemyFormulaEngine.TryParse(formulaText, out error)) { Logger.LogInfo((object)("Tumble-enemy formula " + (isRuntimeChange ? "updated" : "loaded") + ": " + formulaText)); return; } if (isRuntimeChange) { Logger.LogWarning((object)("Rejected invalid runtime tumble-enemy formula '" + formulaText + "'. Keeping previous formula. Error: " + error)); return; } Logger.LogWarning((object)("Invalid startup tumble-enemy formula '" + formulaText + "'. Using default 'd * (1 + (v / 4) ^ 0.5)'. Error: " + error)); _tumbleEnemyFormulaEngine?.TryParse("d * (1 + (v / 4) ^ 0.5)", out string _); } internal int ScaleCollisionDamage(int baseDamage, float velocityDistance) { float value = SemiFunc.RunGetLevelsCompleted() + 1; if (_formulaEngine == null) { return Mathf.RoundToInt((float)baseDamage * (1f + Mathf.Sqrt(velocityDistance / 4f))); } _formulaEngine.SetVariableValue("d", baseDamage); _formulaEngine.SetVariableValue("damage", baseDamage); _formulaEngine.SetVariableValue("v", velocityDistance); _formulaEngine.SetVariableValue("velocity", velocityDistance); _formulaEngine.SetVariableValue("l", value); _formulaEngine.SetVariableValue("level", value); if (!_formulaEngine.TryEvaluate(out float value2, out string error)) { Logger.LogWarning((object)("Failed to evaluate formula. Falling back to default. Error: " + error)); return Mathf.RoundToInt((float)baseDamage * (1f + Mathf.Sqrt(velocityDistance / 4f))); } return Mathf.RoundToInt(value2); } internal int ScaleTumblingPlayerEnemyDamage(int baseDamage, float velocityDistance) { float value = SemiFunc.RunGetLevelsCompleted() + 1; if (_tumbleEnemyFormulaEngine == null) { return Mathf.RoundToInt((float)baseDamage * (1f + Mathf.Sqrt(velocityDistance / 4f))); } _tumbleEnemyFormulaEngine.SetVariableValue("d", baseDamage); _tumbleEnemyFormulaEngine.SetVariableValue("damage", baseDamage); _tumbleEnemyFormulaEngine.SetVariableValue("v", velocityDistance); _tumbleEnemyFormulaEngine.SetVariableValue("velocity", velocityDistance); _tumbleEnemyFormulaEngine.SetVariableValue("l", value); _tumbleEnemyFormulaEngine.SetVariableValue("level", value); if (!_tumbleEnemyFormulaEngine.TryEvaluate(out float value2, out string error)) { Logger.LogWarning((object)("Failed to evaluate tumble-enemy formula. Falling back to default. Error: " + error)); return Mathf.RoundToInt((float)baseDamage * (1f + Mathf.Sqrt(velocityDistance / 4f))); } return Mathf.RoundToInt(value2); } } }