using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using IL.RoR2;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using On.RoR2;
using R2API;
using R2API.Utils;
using RoR2;
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.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("BorboStatUtils")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BorboStatUtils")]
[assembly: AssemblyTitle("BorboStatUtils")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace BorboStatUtils;
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("com.HouseOfFruits.2R4RStatUtils", "2R4RStatUtils", "1.0.2")]
[R2APISubmoduleDependency(new string[] { "LanguageAPI" })]
public class BorboStatUtils : BaseUnityPlugin
{
public delegate void LuckHookEventHandler(CharacterBody sender, ref float luck);
public delegate void ExecuteHookEventHandler(CharacterBody sender, ref float executeThreshold);
public const string guid = "com.HouseOfFruits.2R4RStatUtils";
public const string teamName = "HouseOfFruits";
public const string modName = "2R4RStatUtils";
public const string version = "1.0.2";
public const string executeKeywordToken = "2R4R_EXECUTION_KEYWORD";
public const float survivorExecuteThreshold = 0.15f;
public static PluginInfo PInfo { get; private set; }
public static event LuckHookEventHandler ModifyLuckStat
{
add
{
SetLuckHooks();
_modifyLuckStat += value;
}
remove
{
_modifyLuckStat -= value;
if (BorboStatUtils._modifyLuckStat != null)
{
Delegate[] invocationList = BorboStatUtils._modifyLuckStat.GetInvocationList();
if (invocationList == null || invocationList.Length != 0)
{
return;
}
}
UnsetLuckHooks();
}
}
private static event LuckHookEventHandler _modifyLuckStat;
public static event ExecuteHookEventHandler GetExecutionThreshold
{
add
{
SetExecutionHooks();
_getExecutionThreshold += value;
}
remove
{
_getExecutionThreshold -= value;
if (BorboStatUtils._getExecutionThreshold != null)
{
Delegate[] invocationList = BorboStatUtils._getExecutionThreshold.GetInvocationList();
if (invocationList == null || invocationList.Length != 0)
{
return;
}
}
UnsetExecutionHooks();
}
}
private static event ExecuteHookEventHandler _getExecutionThreshold;
public void Awake()
{
LanguageAPI.Add("2R4R_EXECUTION_KEYWORD", "<style=cKeywordName>Finisher</style><style=cSub>Enemies targeted by this skill can be <style=cIsHealth>instantly killed</style> if below " + $"<style=cIsHealth>{15.000001f}% health</style>.</style>");
}
internal static void SetLuckHooks()
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
CharacterBody.RecalculateStats += new hook_RecalculateStats(RecalculateLuckStat);
}
internal static void UnsetLuckHooks()
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
CharacterBody.RecalculateStats -= new hook_RecalculateStats(RecalculateLuckStat);
}
private static void RecalculateLuckStat(orig_RecalculateStats orig, CharacterBody self)
{
orig.Invoke(self);
CalculateLuck(self);
}
public static void CalculateLuck(CharacterBody self)
{
CharacterMaster master = self.master;
if ((Object)(object)master == (Object)null)
{
return;
}
float luck = 0f;
if (Object.op_Implicit((Object)(object)self) && BorboStatUtils._modifyLuckStat != null)
{
Delegate[] invocationList = BorboStatUtils._modifyLuckStat.GetInvocationList();
for (int i = 0; i < invocationList.Length; i++)
{
LuckHookEventHandler luckHookEventHandler = (LuckHookEventHandler)invocationList[i];
try
{
luckHookEventHandler(self, ref luck);
}
catch (Exception ex)
{
Debug.LogError((object)ex);
}
}
}
if (Object.op_Implicit((Object)(object)self.inventory))
{
luck += (float)self.inventory.GetItemCount(Items.Clover);
luck -= (float)self.inventory.GetItemCount(Items.LunarBadLuck);
}
master.luck = luck;
}
internal static void SetExecutionHooks()
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
HealthComponent.TakeDamage += new Manipulator(InterceptExecutionThreshold);
HealthComponent.GetHealthBarValues += new hook_GetHealthBarValues(DisplayExecutionThreshold);
}
internal static void UnsetExecutionHooks()
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
HealthComponent.TakeDamage -= new Manipulator(InterceptExecutionThreshold);
HealthComponent.GetHealthBarValues -= new hook_GetHealthBarValues(DisplayExecutionThreshold);
}
private static void InterceptExecutionThreshold(ILContext il)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Expected O, but got Unknown
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
ILCursor val = new ILCursor(il);
int thresholdPosition = 0;
val.GotoNext((MoveType)2, new Func<Instruction, bool>[2]
{
(Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, float.NegativeInfinity),
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref thresholdPosition)
});
val.GotoNext((MoveType)0, new Func<Instruction, bool>[2]
{
(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<HealthComponent>(x, "get_isInFrozenState")
});
val.Emit(OpCodes.Ldloc, thresholdPosition);
val.Emit(OpCodes.Ldarg, 0);
val.EmitDelegate<Func<float, HealthComponent, float>>((Func<float, HealthComponent, float>)((float currentThreshold, HealthComponent hc) => RecalculateExecutionThreshold(currentThreshold, hc)));
val.Emit(OpCodes.Stloc, thresholdPosition);
}
private static float RecalculateExecutionThreshold(float currentThreshold, HealthComponent healthComponent)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
float executeThreshold = currentThreshold;
CharacterBody body = healthComponent.body;
if ((Object)(object)body != (Object)null && !((Enum)body.bodyFlags).HasFlag((Enum)(object)(BodyFlags)16) && BorboStatUtils._getExecutionThreshold != null)
{
Delegate[] invocationList = BorboStatUtils._getExecutionThreshold.GetInvocationList();
for (int i = 0; i < invocationList.Length; i++)
{
ExecuteHookEventHandler executeHookEventHandler = (ExecuteHookEventHandler)invocationList[i];
try
{
executeHookEventHandler(body, ref executeThreshold);
}
catch (Exception ex)
{
Debug.LogError((object)ex);
}
}
}
return executeThreshold;
}
public static float ModifyExecutionThreshold(float currentThreshold, float newThreshold, bool condition)
{
if (condition)
{
currentThreshold = Mathf.Max(currentThreshold, newThreshold);
}
return currentThreshold;
}
private static HealthBarValues DisplayExecutionThreshold(orig_GetHealthBarValues orig, HealthComponent self)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
HealthBarValues val = orig.Invoke(self);
val.cullFraction = Mathf.Clamp01(RecalculateExecutionThreshold(val.cullFraction, self));
return val;
}
}