using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using IL.RoR2;
using Microsoft.CodeAnalysis;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using R2API.AutoVersionGen;
using R2API.Utils;
using RoR2;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("R2API.RecalculateStats")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.5.0.0")]
[assembly: AssemblyInformationalVersion("1.5.0+6cbdb1fa58a63657a947bd504a196f039014f78e")]
[assembly: AssemblyProduct("R2API.RecalculateStats")]
[assembly: AssemblyTitle("R2API.RecalculateStats")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.5.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 System.Diagnostics.CodeAnalysis
{
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
[ExcludeFromCodeCoverage]
[DebuggerNonUserCode]
internal sealed class MemberNotNullAttribute : Attribute
{
public string[] Members { get; }
public MemberNotNullAttribute(string member)
{
Members = new string[1] { member };
}
public MemberNotNullAttribute(params string[] members)
{
Members = members;
}
}
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
[ExcludeFromCodeCoverage]
[DebuggerNonUserCode]
internal sealed class MemberNotNullWhenAttribute : Attribute
{
public bool ReturnValue { get; }
public string[] Members { get; }
public MemberNotNullWhenAttribute(bool returnValue, string member)
{
ReturnValue = returnValue;
Members = new string[1] { member };
}
public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
{
ReturnValue = returnValue;
Members = members;
}
}
}
namespace R2API
{
[AutoVersion]
public static class RecalculateStatsAPI
{
public class StatHookEventArgs : EventArgs
{
[EditorBrowsable(EditorBrowsableState.Never)]
public const string _levelMultiplier = "Used for internal documentation";
public float baseHealthAdd;
public float levelHealthAdd;
public float healthMultAdd;
public float baseShieldAdd;
public float levelShieldAdd;
public float shieldMultAdd;
public float baseRegenAdd;
public float levelRegenAdd;
public float regenMultAdd;
public float baseMoveSpeedAdd;
public float levelMoveSpeedAdd;
public float moveSpeedMultAdd;
public float moveSpeedReductionMultAdd;
public float sprintSpeedAdd;
public int moveSpeedRootCount;
public float baseJumpPowerAdd;
public float levelJumpPowerAdd;
public float jumpPowerMultAdd;
public float baseDamageAdd;
public float levelDamageAdd;
public float damageMultAdd;
public float baseAttackSpeedAdd;
public float levelAttackSpeedAdd;
public float attackSpeedMultAdd;
public float attackSpeedReductionMultAdd;
public float critAdd;
public float levelCritAdd;
public float critDamageMultAdd;
public float bleedChanceAdd;
public float armorAdd;
public float levelArmorAdd;
public float baseCurseAdd;
public float cooldownReductionAdd;
public float cooldownMultAdd;
public float primaryCooldownMultAdd;
public float secondaryCooldownMultAdd;
public float utilityCooldownMultAdd;
public float specialCooldownMultAdd;
public float levelFlatAdd;
public float levelMultAdd;
}
public delegate void StatHookEventHandler(CharacterBody sender, StatHookEventArgs args);
[CompilerGenerated]
private static class <>O
{
public static Manipulator <0>__HookRecalculateStats;
public static Action<CharacterBody> <1>__GetStatMods;
}
public const string PluginGUID = "com.bepis.r2api.recalculatestats";
public const string PluginName = "R2API.RecalculateStats";
private static bool _hooksEnabled;
private static StatHookEventArgs StatMods;
public const string PluginVersion = "1.5.0";
[Obsolete("All submodules are automatically loaded and this property is now unused")]
public static bool Loaded => true;
private static event StatHookEventHandler _getStatCoefficients;
public static event StatHookEventHandler GetStatCoefficients
{
add
{
SetHooks();
_getStatCoefficients += value;
}
remove
{
_getStatCoefficients -= value;
if (RecalculateStatsAPI._getStatCoefficients != null)
{
Delegate[] invocationList = RecalculateStatsAPI._getStatCoefficients.GetInvocationList();
if (invocationList == null || invocationList.Length != 0)
{
return;
}
}
UnsetHooks();
}
}
internal static void SetHooks()
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected O, but got Unknown
if (!_hooksEnabled)
{
object obj = <>O.<0>__HookRecalculateStats;
if (obj == null)
{
Manipulator val = HookRecalculateStats;
<>O.<0>__HookRecalculateStats = val;
obj = (object)val;
}
CharacterBody.RecalculateStats += (Manipulator)obj;
_hooksEnabled = true;
}
}
internal static void UnsetHooks()
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Expected O, but got Unknown
object obj = <>O.<0>__HookRecalculateStats;
if (obj == null)
{
Manipulator val = HookRecalculateStats;
<>O.<0>__HookRecalculateStats = val;
obj = (object)val;
}
CharacterBody.RecalculateStats -= (Manipulator)obj;
_hooksEnabled = false;
}
private static void HookRecalculateStats(ILContext il)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
ILCursor c = new ILCursor(il);
c.Emit(OpCodes.Ldarg_0);
c.EmitDelegate<Action<CharacterBody>>((Action<CharacterBody>)GetStatMods);
FindLocLevelMultiplierIndex(c, out var locLevelMultiplierIndex);
Action emitLevelMultiplier = ((locLevelMultiplierIndex >= 0) ? new Action(EmitLevelMultiplier) : new Action(EmitFallbackLevelMultiplier));
ModifyHealthStat(c, emitLevelMultiplier);
ModifyShieldStat(c, emitLevelMultiplier);
ModifyHealthRegenStat(c, emitLevelMultiplier);
ModifyMovementSpeedStat(c, emitLevelMultiplier);
ModifyJumpStat(c, emitLevelMultiplier);
ModifyDamageStat(c, emitLevelMultiplier);
ModifyAttackSpeedStat(c, emitLevelMultiplier);
ModifyCritStat(c, emitLevelMultiplier);
ModifyBleedStat(c);
ModifyArmorStat(c, emitLevelMultiplier);
ModifyCurseStat(c);
ModifyCooldownStat(c);
ModifyLevelingStat(c);
void EmitFallbackLevelMultiplier()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
c.Emit(OpCodes.Ldc_R4, 0f);
}
void EmitLevelMultiplier()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
c.Emit(OpCodes.Ldloc, locLevelMultiplierIndex);
}
}
private static void GetStatMods(CharacterBody characterBody)
{
StatMods = new StatHookEventArgs();
if (RecalculateStatsAPI._getStatCoefficients == null)
{
return;
}
Delegate[] invocationList = RecalculateStatsAPI._getStatCoefficients.GetInvocationList();
for (int i = 0; i < invocationList.Length; i++)
{
StatHookEventHandler statHookEventHandler = (StatHookEventHandler)invocationList[i];
try
{
statHookEventHandler(characterBody, StatMods);
}
catch (Exception arg)
{
RecalculateStatsPlugin.Logger.LogError((object)$"Exception thrown by : {statHookEventHandler.Method.DeclaringType.Name}.{statHookEventHandler.Method.Name}:\n{arg}");
}
}
}
private static void FindLocLevelMultiplierIndex(ILCursor c, out int locLevelMultiplierIndex)
{
c.Index = 0;
int _locLevelMultiplierIndex = -1;
c.TryGotoNext(new Func<Instruction, bool>[4]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertyGetter(typeof(CharacterBody), "level")),
(Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, 1f),
(Instruction x) => ILPatternMatchingExt.MatchSub(x),
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref _locLevelMultiplierIndex)
});
locLevelMultiplierIndex = _locLevelMultiplierIndex;
if (locLevelMultiplierIndex < 0)
{
RecalculateStatsPlugin.Logger.LogError((object)"FindLocLevelMultiplierIndex failed! Level-scaled stats will be ignored!");
}
}
private static void ModifyCurseStat(ILCursor c)
{
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
c.Index = 0;
if (c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[3]
{
(Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, 10f),
(Instruction x) => ILPatternMatchingExt.MatchMul(x),
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(CharacterBody), "cursePenalty"))
}))
{
c.MoveAfterLabels();
c.Emit(OpCodes.Ldarg_0);
c.EmitDelegate<Action<CharacterBody>>((Action<CharacterBody>)delegate(CharacterBody body)
{
body.cursePenalty += StatMods.baseCurseAdd;
});
}
else
{
RecalculateStatsPlugin.Logger.LogError((object)"ModifyCurseStat failed.");
}
}
private static void ModifyCooldownStat(ILCursor c)
{
c.Index = 0;
int num = 0;
while (c.TryGotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "cooldownScale"))
}) && c.TryGotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "flatCooldownReduction"))
}))
{
num++;
}
if (num >= 4)
{
c.Index = 0;
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "cooldownScale"))
});
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float oldCooldown) => oldCooldown * (1f + StatMods.cooldownMultAdd + StatMods.primaryCooldownMultAdd)));
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "flatCooldownReduction"))
});
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float oldCooldown) => oldCooldown + StatMods.cooldownReductionAdd));
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "cooldownScale"))
});
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float oldCooldown) => oldCooldown * (1f + StatMods.cooldownMultAdd + StatMods.secondaryCooldownMultAdd)));
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "flatCooldownReduction"))
});
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float oldCooldown) => oldCooldown + StatMods.cooldownReductionAdd));
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "cooldownScale"))
});
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float oldCooldown) => oldCooldown * (1f + StatMods.cooldownMultAdd + StatMods.utilityCooldownMultAdd)));
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "flatCooldownReduction"))
});
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float oldCooldown) => oldCooldown + StatMods.cooldownReductionAdd));
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "cooldownScale"))
});
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float oldCooldown) => oldCooldown * (1f + StatMods.cooldownMultAdd + StatMods.specialCooldownMultAdd)));
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "flatCooldownReduction"))
});
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float oldCooldown) => oldCooldown + StatMods.cooldownReductionAdd));
}
else
{
RecalculateStatsPlugin.Logger.LogError((object)"ModifyCooldownStat failed.");
}
}
private static void ModifyLevelingStat(ILCursor c)
{
c.Index = 0;
if (c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[3]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertyGetter(typeof(CharacterBody), "level")),
(Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, 1f),
(Instruction x) => ILPatternMatchingExt.MatchSub(x)
}))
{
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float oldScaling) => (oldScaling + StatMods.levelFlatAdd) * (1f + StatMods.levelMultAdd)));
}
else
{
RecalculateStatsPlugin.Logger.LogError((object)"ModifyLevelingStat failed.");
}
}
private static void ModifyArmorStat(ILCursor c, Action emitLevelMultiplier)
{
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
c.Index = 0;
if (c.TryGotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseArmor")
}) && c.TryGotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(CharacterBody), "armor"))
}))
{
emitLevelMultiplier();
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float levelMultiplier) => StatMods.armorAdd + StatMods.levelArmorAdd * levelMultiplier));
c.Emit(OpCodes.Add);
}
else
{
RecalculateStatsPlugin.Logger.LogError((object)"ModifyArmorStat failed.");
}
}
private static void ModifyAttackSpeedStat(ILCursor c, Action emitLevelMultiplier)
{
//IL_0187: Unknown result type (might be due to invalid IL or missing references)
//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
c.Index = 0;
int locBaseAttackSpeedIndex = -1;
int locAttackSpeedMultIndex = -1;
if (c.TryGotoNext(new Func<Instruction, bool>[3]
{
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseAttackSpeed"),
(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "levelAttackSpeed")
}) && c.TryGotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref locBaseAttackSpeedIndex)
}) && c.TryGotoNext(new Func<Instruction, bool>[4]
{
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, locBaseAttackSpeedIndex),
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref locAttackSpeedMultIndex),
(Instruction x) => ILPatternMatchingExt.MatchMul(x),
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locBaseAttackSpeedIndex)
}))
{
c.GotoPrev(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseAttackSpeed")
});
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locBaseAttackSpeedIndex)
});
emitLevelMultiplier();
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float levelMultiplier) => StatMods.baseAttackSpeedAdd + StatMods.levelAttackSpeedAdd * levelMultiplier));
c.Emit(OpCodes.Add);
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locAttackSpeedMultIndex)
});
c.EmitDelegate<Func<float>>((Func<float>)(() => StatMods.attackSpeedMultAdd));
c.Emit(OpCodes.Add);
c.GotoNext(new Func<Instruction, bool>[2]
{
(Instruction x) => ILPatternMatchingExt.MatchDiv(x),
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locAttackSpeedMultIndex)
});
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float origSpeedReductionMult) => Mathf.Max(Mathf.Epsilon, origSpeedReductionMult + StatMods.attackSpeedReductionMultAdd)));
}
else
{
RecalculateStatsPlugin.Logger.LogError((object)"ModifyAttackSpeedStat failed.");
}
}
private static void ModifyCritStat(ILCursor c, Action emitLevelMultiplier)
{
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
c.Index = 0;
int locOrigCrit = -1;
if (c.TryGotoNext(new Func<Instruction, bool>[3]
{
(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref locOrigCrit),
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(CharacterBody), "crit"))
}) && c.TryGotoPrev((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(CharacterBody), "critMultiplier"))
}))
{
int index = c.Index;
c.Index = index - 1;
c.EmitDelegate<Func<float>>((Func<float>)(() => StatMods.critDamageMultAdd));
c.Emit(OpCodes.Add);
c.GotoNext((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locOrigCrit)
});
c.Emit(OpCodes.Ldloc, locOrigCrit);
emitLevelMultiplier();
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float levelMultiplier) => StatMods.critAdd + StatMods.levelCritAdd * levelMultiplier));
c.Emit(OpCodes.Add);
c.Emit(OpCodes.Stloc, locOrigCrit);
}
else
{
RecalculateStatsPlugin.Logger.LogError((object)"ModifyCritStat failed.");
}
}
private static void ModifyBleedStat(ILCursor c)
{
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
c.Index = 0;
int num = default(int);
if (c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[6]
{
(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
(Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, 10f),
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref num),
(Instruction x) => ILPatternMatchingExt.MatchConvR4(x),
(Instruction x) => ILPatternMatchingExt.MatchMul(x),
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(CharacterBody), "bleedChance"))
}))
{
int index = c.Index;
c.Index = index - 1;
c.EmitDelegate<Func<float>>((Func<float>)(() => StatMods.bleedChanceAdd));
c.Emit(OpCodes.Add);
}
else
{
RecalculateStatsPlugin.Logger.LogError((object)"ModifyBleedStat failed.");
}
}
private static void ModifyDamageStat(ILCursor c, Action emitLevelMultiplier)
{
//IL_0187: Unknown result type (might be due to invalid IL or missing references)
c.Index = 0;
int locBaseDamageIndex = -1;
int locDamageMultIndex = -1;
if (c.TryGotoNext(new Func<Instruction, bool>[3]
{
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseDamage"),
(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "levelDamage")
}) && c.TryGotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref locBaseDamageIndex)
}) && c.TryGotoNext(new Func<Instruction, bool>[4]
{
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, locBaseDamageIndex),
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref locDamageMultIndex),
(Instruction x) => ILPatternMatchingExt.MatchMul(x),
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locBaseDamageIndex)
}))
{
c.GotoPrev(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseDamage")
});
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locBaseDamageIndex)
});
emitLevelMultiplier();
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float levelMultiplier) => StatMods.baseDamageAdd + StatMods.levelDamageAdd * levelMultiplier));
c.Emit(OpCodes.Add);
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locDamageMultIndex)
});
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float origDamageMult) => origDamageMult + StatMods.damageMultAdd));
}
else
{
RecalculateStatsPlugin.Logger.LogError((object)"ModifyDamageStat failed.");
}
}
private static void ModifyJumpStat(ILCursor c, Action emitLevelMultiplier)
{
c.Index = 0;
int num = default(int);
if (c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[6]
{
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseJumpPower"),
(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "levelJumpPower"),
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref num),
(Instruction x) => ILPatternMatchingExt.MatchMul(x),
(Instruction x) => ILPatternMatchingExt.MatchAdd(x)
}))
{
emitLevelMultiplier();
c.EmitDelegate<Func<float, float, float>>((Func<float, float, float>)((float origJumpPower, float levelMultiplier) => (origJumpPower + StatMods.baseJumpPowerAdd + StatMods.levelJumpPowerAdd * levelMultiplier) * (1f + StatMods.jumpPowerMultAdd)));
}
else
{
RecalculateStatsPlugin.Logger.LogError((object)"ModifyJumpStat failed.");
}
}
private static void ModifyHealthStat(ILCursor c, Action emitLevelMultiplier)
{
//IL_0187: Unknown result type (might be due to invalid IL or missing references)
//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
c.Index = 0;
int locBaseHealthIndex = -1;
int locHealthMultIndex = -1;
if (c.TryGotoNext(new Func<Instruction, bool>[3]
{
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseMaxHealth"),
(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "levelMaxHealth")
}) && c.TryGotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref locBaseHealthIndex)
}) && c.TryGotoNext(new Func<Instruction, bool>[4]
{
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, locBaseHealthIndex),
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref locHealthMultIndex),
(Instruction x) => ILPatternMatchingExt.MatchMul(x),
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locBaseHealthIndex)
}))
{
c.GotoPrev(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseMaxHealth")
});
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locBaseHealthIndex)
});
emitLevelMultiplier();
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float levelMultiplier) => StatMods.baseHealthAdd + StatMods.levelHealthAdd * levelMultiplier));
c.Emit(OpCodes.Add);
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locHealthMultIndex)
});
c.EmitDelegate<Func<float>>((Func<float>)(() => StatMods.healthMultAdd));
c.Emit(OpCodes.Add);
}
else
{
RecalculateStatsPlugin.Logger.LogError((object)"ModifyHealthStat failed.");
}
}
private static void ModifyShieldStat(ILCursor c, Action emitLevelMultiplier)
{
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
c.Index = 0;
int locBaseShieldIndex = -1;
if (c.TryGotoNext(new Func<Instruction, bool>[3]
{
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseMaxShield"),
(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "levelMaxShield")
}) && c.TryGotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref locBaseShieldIndex)
}) && c.TryGotoNext(new Func<Instruction, bool>[2]
{
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, locBaseShieldIndex),
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(CharacterBody), "maxShield"))
}))
{
int index = c.Index;
c.Index = index + 1;
c.EmitDelegate<Func<float>>((Func<float>)(() => 1f + StatMods.shieldMultAdd));
c.Emit(OpCodes.Mul);
c.GotoPrev(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "levelMaxShield")
});
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref locBaseShieldIndex)
});
emitLevelMultiplier();
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float levelMultiplier) => StatMods.baseShieldAdd + StatMods.levelShieldAdd * levelMultiplier));
c.Emit(OpCodes.Add);
}
else
{
RecalculateStatsPlugin.Logger.LogError((object)"ModifyShieldStat failed.");
}
}
private static void ModifyHealthRegenStat(ILCursor c, Action emitLevelMultiplier)
{
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
c.Index = 0;
int locRegenMultIndex = -1;
int locFinalRegenIndex = -1;
if (c.TryGotoNext(new Func<Instruction, bool>[2]
{
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref locFinalRegenIndex),
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(CharacterBody), "regen"))
}) && c.TryGotoPrev(new Func<Instruction, bool>[4]
{
(Instruction x) => ILPatternMatchingExt.MatchAdd(x),
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref locRegenMultIndex),
(Instruction x) => ILPatternMatchingExt.MatchMul(x),
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref locFinalRegenIndex)
}))
{
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref locRegenMultIndex)
});
emitLevelMultiplier();
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float levelMultiplier) => StatMods.baseRegenAdd + StatMods.levelRegenAdd * levelMultiplier));
c.Emit(OpCodes.Add);
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchMul(x)
});
c.EmitDelegate<Func<float>>((Func<float>)(() => StatMods.regenMultAdd));
c.Emit(OpCodes.Add);
}
else
{
RecalculateStatsPlugin.Logger.LogError((object)"ModifyHealthRegenStat failed.");
}
}
private static void ModifyMovementSpeedStat(ILCursor c, Action emitLevelMultiplier)
{
//IL_020e: Unknown result type (might be due to invalid IL or missing references)
//IL_0291: Unknown result type (might be due to invalid IL or missing references)
//IL_02df: Unknown result type (might be due to invalid IL or missing references)
//IL_0313: Unknown result type (might be due to invalid IL or missing references)
//IL_0380: Unknown result type (might be due to invalid IL or missing references)
//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
c.Index = 0;
int locBaseSpeedIndex = -1;
int locSpeedMultIndex = -1;
int locSpeedDivIndex = -1;
int num2 = default(int);
int num = default(int);
if (c.TryGotoNext(new Func<Instruction, bool>[3]
{
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseMoveSpeed"),
(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "levelMoveSpeed")
}) && c.TryGotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref locBaseSpeedIndex)
}) && c.TryGotoNext(new Func<Instruction, bool>[6]
{
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, locBaseSpeedIndex),
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref locSpeedMultIndex),
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref locSpeedDivIndex),
(Instruction x) => ILPatternMatchingExt.MatchDiv(x),
(Instruction x) => ILPatternMatchingExt.MatchMul(x),
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locBaseSpeedIndex)
}) && c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[4]
{
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref num2),
(Instruction x) => ILPatternMatchingExt.MatchOr(x),
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref num),
(Instruction x) => ILPatternMatchingExt.MatchOr(x)
}))
{
c.EmitDelegate<Func<bool>>((Func<bool>)(() => StatMods.moveSpeedRootCount > 0));
c.Emit(OpCodes.Or);
c.GotoPrev(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "levelMoveSpeed")
});
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locBaseSpeedIndex)
});
emitLevelMultiplier();
c.EmitDelegate<Func<float, float>>((Func<float, float>)((float levelMultiplier) => StatMods.baseMoveSpeedAdd + StatMods.levelMoveSpeedAdd * levelMultiplier));
c.Emit(OpCodes.Add);
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locSpeedMultIndex)
});
c.EmitDelegate<Func<float>>((Func<float>)(() => StatMods.moveSpeedMultAdd));
c.Emit(OpCodes.Add);
while (c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "sprintingSpeedMultiplier")
}))
{
c.EmitDelegate<Func<float>>((Func<float>)(() => StatMods.sprintSpeedAdd));
c.Emit(OpCodes.Add);
}
c.GotoPrev((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertyGetter(typeof(CharacterBody), "isSprinting"))
});
c.Emit(OpCodes.Ldarg_0);
c.EmitDelegate<Func<bool, CharacterBody, bool>>((Func<bool, CharacterBody, bool>)((bool isSprinting, CharacterBody sender) => isSprinting && sender.sprintingSpeedMultiplier + StatMods.sprintSpeedAdd != 0f));
c.GotoNext(new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locSpeedDivIndex)
});
c.EmitDelegate<Func<float>>((Func<float>)(() => StatMods.moveSpeedReductionMultAdd));
c.Emit(OpCodes.Add);
}
else
{
RecalculateStatsPlugin.Logger.LogError((object)"ModifyMovementSpeedStat failed.");
}
}
}
[BepInPlugin("com.bepis.r2api.recalculatestats", "R2API.RecalculateStats", "1.5.0")]
public sealed class RecalculateStatsPlugin : BaseUnityPlugin
{
internal static ManualLogSource Logger { get; set; }
private void Awake()
{
Logger = ((BaseUnityPlugin)this).Logger;
}
private void OnDestroy()
{
RecalculateStatsAPI.UnsetHooks();
}
}
public static class StandardLevelScaling
{
public const float Health = 0.3f;
public const float Shield = 0.3f;
public const float Regen = 0.2f;
public const float Damage = 0.2f;
}
}
namespace R2API.AutoVersionGen
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
internal class AutoVersionAttribute : Attribute
{
}
}