using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
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.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BetterNoRevivePenalty")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BetterNoRevivePenalty")]
[assembly: AssemblyTitle("BetterNoRevivePenalty")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[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 BetterNoRevivePenalty
{
[BepInPlugin("BetterNoRevivePenalty", "BetterNoRevivePenalty", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
public const string GUID = "BetterNoRevivePenalty";
public const string NAME = "BetterNoRevivePenalty";
public const string VERSION = "1.0.0";
internal static ManualLogSource Log;
internal static ConfigEntry<bool> BlockCurse;
internal static ConfigEntry<bool> BlockHunger;
internal static int CurseIndex = -1;
internal static int HungerIndex = -1;
internal static int ReviveScopeDepth;
internal static int VoidEntryDepth;
internal static bool BlockingAtSource;
internal static bool InReviveScope
{
get
{
if (ReviveScopeDepth > 0)
{
return VoidEntryDepth == 0;
}
return false;
}
}
internal static bool ShouldBlock(int statusIndex)
{
if (!InReviveScope)
{
return false;
}
if (statusIndex == CurseIndex)
{
if (BlockCurse != null)
{
return BlockCurse.Value;
}
return false;
}
if (statusIndex == HungerIndex)
{
if (BlockHunger != null)
{
return BlockHunger.Value;
}
return false;
}
return false;
}
private void Awake()
{
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
BlockCurse = ((BaseUnityPlugin)this).Config.Bind<bool>("Revive Penalty", "Block Curse", true, "Prevent the Curse applied by being revived. Curse from every other source is untouched.");
BlockHunger = ((BaseUnityPlugin)this).Config.Bind<bool>("Revive Penalty", "Block Hunger", false, "Also prevent the Hunger applied by being revived. Vanilla adds 30%.");
CurseIndex = ResolveStatus("Curse");
HungerIndex = ResolveStatus("Hunger");
try
{
Install(new Harmony("BetterNoRevivePenalty"));
}
catch (Exception ex)
{
Log.LogError((object)("Patching failed. The mod is inert but the game is untouched: " + ex));
}
}
private void LateUpdate()
{
if (ReviveScopeDepth != 0)
{
ReviveScopeDepth = 0;
}
if (VoidEntryDepth != 0)
{
VoidEntryDepth = 0;
}
}
private static int ResolveStatus(string name)
{
try
{
return (int)Enum.Parse(typeof(STATUSTYPE), name);
}
catch (Exception)
{
Log.LogWarning((object)("STATUSTYPE." + name + " no longer exists - that penalty will not be blocked."));
return -1;
}
}
private static void Install(Harmony harmony)
{
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Expected O, but got Unknown
//IL_00b0: Expected O, but got Unknown
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
//IL_0124: Expected O, but got Unknown
//IL_0124: Expected O, but got Unknown
MethodInfo methodInfo = AccessTools.Method(typeof(Character), "ApplyPostReviveStatus", (Type[])null, (Type[])null);
bool flag = methodInfo != null;
if (methodInfo == null)
{
methodInfo = AccessTools.Method(typeof(Character), "ReviveCharacter", (Type[])null, (Type[])null);
if (methodInfo != null)
{
Log.LogWarning((object)"Character.ApplyPostReviveStatus is gone; scoping Character.ReviveCharacter instead.");
}
}
if (methodInfo == null)
{
Log.LogError((object)"Found no revive method to scope - mod has no effect. PEAK probably renamed it.");
return;
}
harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(ReviveScope), "Enter", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(ReviveScope), "Exit", (Type[])null, (Type[])null)), (HarmonyMethod)null);
TryExcludeVoidEntry(harmony);
BlockingAtSource = TryBlockAtSource(harmony);
if (BlockingAtSource)
{
Log.LogInfo((object)"Ready. Revive penalties are blocked at CharacterAfflictions.AddStatus.");
}
else if (flag && SnapshotRestore.TargetIsCompatible(methodInfo))
{
harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(SnapshotRestore), "Prefix", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.Method(typeof(SnapshotRestore), "Postfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
Log.LogWarning((object)"CharacterAfflictions.AddStatus changed shape; using the snapshot/restore fallback.");
}
else
{
Log.LogError((object)"Neither strategy is available - mod has no effect, but revives still work normally.");
}
}
private static void TryExcludeVoidEntry(Harmony harmony)
{
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Expected O, but got Unknown
//IL_0083: Expected O, but got Unknown
MethodInfo methodInfo = AccessTools.Method(typeof(MapHandler), "GoToVoidRoutine", (Type[])null, (Type[])null);
MethodInfo methodInfo2 = ((methodInfo != null) ? AccessTools.EnumeratorMoveNext((MethodBase)methodInfo) : null);
if (methodInfo2 == null)
{
Log.LogWarning((object)"Could not scope MapHandler.GoToVoidRoutine; entering the Void will have its curse blocked too.");
}
else
{
harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(AccessTools.Method(typeof(VoidEntryScope), "Enter", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(VoidEntryScope), "Exit", (Type[])null, (Type[])null)), (HarmonyMethod)null);
}
}
private static bool TryBlockAtSource(Harmony harmony)
{
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Expected O, but got Unknown
MethodInfo methodInfo = AccessTools.Method(typeof(CharacterAfflictions), "AddStatus", (Type[])null, (Type[])null);
if (methodInfo == null)
{
return false;
}
ParameterInfo[] parameters = methodInfo.GetParameters();
if (parameters.Length < 1 || parameters[0].ParameterType != typeof(STATUSTYPE))
{
return false;
}
if (methodInfo.ReturnType != typeof(bool))
{
return false;
}
harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(BlockStatus), "Prefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
return true;
}
}
internal static class ReviveScope
{
public static void Enter()
{
Plugin.ReviveScopeDepth++;
}
public static void Exit()
{
if (Plugin.ReviveScopeDepth > 0)
{
Plugin.ReviveScopeDepth--;
}
}
}
internal static class VoidEntryScope
{
public static void Enter()
{
Plugin.VoidEntryDepth++;
}
public static void Exit()
{
if (Plugin.VoidEntryDepth > 0)
{
Plugin.VoidEntryDepth--;
}
}
}
internal static class BlockStatus
{
public static bool Prefix(STATUSTYPE __0, ref bool __result)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Expected I4, but got Unknown
if (!Plugin.ShouldBlock((int)__0))
{
return true;
}
__result = false;
return false;
}
}
internal static class SnapshotRestore
{
public static bool TargetIsCompatible(MethodInfo target)
{
ParameterInfo[] parameters = target.GetParameters();
if (parameters.Length >= 1)
{
return parameters[0].ParameterType == typeof(CharacterAfflictions);
}
return false;
}
public static void Prefix(CharacterAfflictions __0, out float[] __state)
{
__state = null;
float[] array = (((Object)(object)__0 != (Object)null) ? __0.currentStatuses : null);
if (array != null)
{
__state = new float[2];
__state[0] = Read(array, Plugin.CurseIndex);
__state[1] = Read(array, Plugin.HungerIndex);
}
}
public static void Postfix(CharacterAfflictions __0, float[] __state)
{
if (__state != null && !((Object)(object)__0 == (Object)null) && __0.currentStatuses != null)
{
if (Plugin.BlockCurse.Value)
{
Write(__0.currentStatuses, Plugin.CurseIndex, __state[0]);
}
if (Plugin.BlockHunger.Value)
{
Write(__0.currentStatuses, Plugin.HungerIndex, __state[1]);
}
}
}
private static float Read(float[] statuses, int index)
{
if (index < 0 || index >= statuses.Length)
{
return 0f;
}
return statuses[index];
}
private static void Write(float[] statuses, int index, float value)
{
if (index >= 0 && index < statuses.Length)
{
statuses[index] = value;
}
}
}
}