using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
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 ReviveUtils.Components;
using ReviveUtils.Patches;
using UnityEngine;
using UnityEngine.InputSystem;
[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("Jay")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ab4536b0ebae776412bfdc40aaa16cdf6a612f01")]
[assembly: AssemblyProduct("ReviveUtils")]
[assembly: AssemblyTitle("ReviveUtils")]
[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 ReviveUtils
{
[BepInPlugin("jaydev.ReviveUtils", "ReviveUtils", "1.1.1")]
public class ReviveUtils : BaseUnityPlugin
{
internal static ReviveUtils 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;
ConfigManager.Init();
Patch();
Logger.LogInfo((object)"模組載入完成!");
}
internal void Patch()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Expected O, but got Unknown
//IL_0025: Expected O, but got Unknown
if (Harmony == null)
{
Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
Harmony val2 = val;
Harmony = val;
}
Harmony.PatchAll(typeof(PlayerAvatarPatch));
Harmony.PatchAll(typeof(PlayerControllerPatch));
Harmony.PatchAll(typeof(PlayerDeathHeadPatch));
Harmony.PatchAll(typeof(ShopManagerPatch));
}
internal void Unpatch()
{
Harmony? harmony = Harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
private void Update()
{
}
}
public static class ConfigManager
{
private static readonly ConfigFile configFile = new ConfigFile(Path.Combine(Paths.ConfigPath, "ReviveUtils.cfg"), true);
private static ConfigEntry<bool> _enableShopRespawn;
private static ConfigEntry<int> _shopRespawnDelay;
private static ConfigEntry<bool> _enableExtractionHeal;
private static ConfigEntry<int> _extractionHealValue;
private static ConfigEntry<bool> _enableExtractionHealPercentage;
private static ConfigEntry<int> _extractionHealPercentage;
private static ConfigEntry<bool> _enableCustomTruckHeal;
private static ConfigEntry<int> _truckHealValue;
private static ConfigEntry<bool> _enableTruckHealPercentage;
private static ConfigEntry<int> _truckHealPercentage;
private static ConfigEntry<bool> _enableSacrificialRevive;
private static ConfigEntry<int> _sacrificialReviveHpCost;
private static ConfigEntry<string> _sacrificialReviveKeybind;
private static ConfigEntry<bool> _enablePointRevive;
public static bool EnableShopRespawn => _enableShopRespawn.Value;
public static int ShopRespawnDelay => _shopRespawnDelay.Value;
public static bool EnableExtractionHeal => _enableExtractionHeal.Value;
public static int ExtractionHealValue => _extractionHealValue.Value;
public static bool EnableExtractionHealPercentage => _enableExtractionHealPercentage.Value;
public static int ExtractionHealPercentage => _extractionHealPercentage.Value;
public static bool EnableCustomTruckHeal => _enableCustomTruckHeal.Value;
public static int TruckHealValue => _truckHealValue.Value;
public static bool EnableTruckHealPercentage => _enableTruckHealPercentage.Value;
public static int TruckHealPercentage => _truckHealPercentage.Value;
public static bool EnableSacrificialRevive => _enableSacrificialRevive.Value;
public static int SacrificialReviveHpCost => _sacrificialReviveHpCost.Value;
public static string SacrificialReviveKeybind => _sacrificialReviveKeybind.Value;
public static bool EnablePointRevive => _enablePointRevive.Value;
public static void Init()
{
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Expected O, but got Unknown
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Expected O, but got Unknown
//IL_0161: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: Expected O, but got Unknown
_enableShopRespawn = configFile.Bind<bool>("Shop Respawn", "Enable", true, "Enable shop respawn");
_shopRespawnDelay = configFile.Bind<int>("Shop Respawn", "Respawn Delay", 5, new ConfigDescription("Respawn delay in seconds", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 30), Array.Empty<object>()));
_enableExtractionHeal = configFile.Bind<bool>("Extraction Heal", "Enable", true, "Enable extraction healing");
_extractionHealValue = configFile.Bind<int>("Extraction Heal", "Heal Value", 50, "Extraction healing value");
_enableExtractionHealPercentage = configFile.Bind<bool>("Extraction Heal", "Enable Percentage Healing", false, "Whether to heal player by the percentage of their max hp");
_extractionHealPercentage = configFile.Bind<int>("Extraction Heal", "Heal Percentage", 50, new ConfigDescription("Extraction healing percentage", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
_enableCustomTruckHeal = configFile.Bind<bool>("Truck Heal", "Enable", true, "Enable custom truck healing value");
_truckHealValue = configFile.Bind<int>("Truck Heal", "Heal Value", 50, "Truck healing value");
_enableTruckHealPercentage = configFile.Bind<bool>("Truck Heal", "Enable Percentage Healing", false, "Whether to heal player by the percentage of their max hp");
_truckHealPercentage = configFile.Bind<int>("Truck Heal", "Heal Percentage", 50, new ConfigDescription("Truck healing percentage", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
_enableSacrificialRevive = configFile.Bind<bool>("Sacrificial Revive", "Enable", true, "Enable sacrificial revive");
_sacrificialReviveHpCost = configFile.Bind<int>("Sacrificial Revive", "Health Cost", 10, "Amount of health to spend on reviving");
_sacrificialReviveKeybind = configFile.Bind<string>("Sacrificial Revive", "Keybind", "R", "Keybind for sacrificial revive");
_enablePointRevive = configFile.Bind<bool>("Extraction Point Revive", "Enable", false, "Enable instant revive on extraction point");
}
}
}
namespace ReviveUtils.Patches
{
[HarmonyPatch(typeof(PlayerAvatar))]
public static class PlayerAvatarPatch
{
[HarmonyPostfix]
[HarmonyPatch("ReviveRPC")]
public static void ExtractionHealPatch(PlayerAvatar __instance, bool _revivedByTruck)
{
if (!(!ConfigManager.EnableExtractionHeal || _revivedByTruck))
{
int num = ConfigManager.ExtractionHealValue;
if (ConfigManager.EnableExtractionHealPercentage)
{
num = __instance.playerHealth.maxHealth * ConfigManager.ExtractionHealPercentage / 100;
}
__instance.playerHealth.Heal(num - 1, true);
ReviveUtils.Logger.LogInfo((object)$"玩家 {__instance.playerName} 復活,恢復 {num} 血量");
}
}
[HarmonyPrefix]
[HarmonyPatch("FinalHealRPC")]
public static bool TruckHealPatch(PlayerAvatar __instance)
{
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
if (!ConfigManager.EnableCustomTruckHeal || __instance.finalHeal || !__instance.isLocal)
{
return true;
}
int num = ConfigManager.TruckHealValue;
if (ConfigManager.EnableTruckHealPercentage)
{
num = __instance.playerHealth.maxHealth * ConfigManager.TruckHealPercentage / 100;
}
if (SemiFunc.IsMasterClientOrSingleplayer())
{
TruckScreenText.instance.MessageSendCustom("", __instance.playerName + " {arrowright}{truck}{check}\n {point}{shades}{pointright}<b><color=#00FF00>+" + num + "</color></b>{heart}", 0);
}
__instance.playerHealth.EyeMaterialOverride((EyeOverrideState)2, 2f, 1);
__instance.playerHealth.Heal(num, true);
TruckHealer.instance.Heal(__instance);
__instance.truckReturn.Play(__instance.PlayerVisionTarget.VisionTransform.position, 1f, 1f, 1f, 1f);
__instance.truckReturnGlobal.Play(__instance.PlayerVisionTarget.VisionTransform.position, 1f, 1f, 1f, 1f);
((Component)__instance.playerAvatarVisuals.effectGetIntoTruck).gameObject.SetActive(true);
__instance.finalHeal = true;
ReviveUtils.Logger.LogInfo((object)$"玩家 {__instance.playerName} 上車,恢復 {num} 血量");
return false;
}
[HarmonyPostfix]
[HarmonyPatch("PlayerDeathRPC")]
public static void ShopRespawnPatch(PlayerAvatar __instance)
{
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Expected O, but got Unknown
if (ConfigManager.EnableShopRespawn && SemiFunc.IsMasterClient() && !((Object)(object)RunManager.instance.levelCurrent != (Object)(object)RunManager.instance.levelShop))
{
ReviveUtils.Logger.LogInfo((object)("玩家 " + __instance.playerName + " 死於商店中,準備復活..."));
GameObject val = new GameObject("ShopRespawn");
ShopRespawn shopRespawn = val.AddComponent<ShopRespawn>();
shopRespawn.PlayerAvatarInstance = __instance;
}
}
}
[HarmonyPatch(typeof(PlayerController))]
public static class PlayerControllerPatch
{
public static PlayerDeathHead? grabbedHead { get; private set; }
[HarmonyPostfix]
[HarmonyPatch("FixedUpdate")]
public static void GrabbedHeadDetectionPatch(PlayerController __instance)
{
if (!ConfigManager.EnableSacrificialRevive || !SemiFunc.IsMultiplayer() || (Object)(object)__instance == (Object)null)
{
return;
}
if ((Object)(object)__instance.physGrabObject != (Object)null && __instance.physGrabActive)
{
PlayerDeathHead component = __instance.physGrabObject.GetComponent<PlayerDeathHead>();
if ((Object)(object)component != (Object)null && (Object)(object)component.playerAvatar != (Object)null)
{
grabbedHead = component;
}
}
else if ((Object)(object)grabbedHead != (Object)null)
{
grabbedHead = null;
}
}
}
[HarmonyPatch(typeof(PlayerDeathHead))]
public static class PlayerDeathHeadPatch
{
[HarmonyPostfix]
[HarmonyPatch("Update")]
public static void InstantRevivePatch(PlayerDeathHead __instance)
{
if (ConfigManager.EnablePointRevive && SemiFunc.IsMasterClient() && __instance.inExtractionPoint)
{
__instance.playerAvatar.Revive(false);
ReviveUtils.Logger.LogInfo((object)("點上復活 " + __instance.playerAvatar.playerName));
}
}
}
[HarmonyPatch(typeof(ShopManager))]
public static class ShopManagerPatch
{
[HarmonyPostfix]
[HarmonyPatch("Awake")]
public static void SacrificialReviveListener(ShopManager __instance)
{
if (ConfigManager.EnableSacrificialRevive && (Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).gameObject.GetComponent<SacrificialRevive>() == (Object)null)
{
((Component)__instance).gameObject.AddComponent<SacrificialRevive>();
}
}
}
}
namespace ReviveUtils.Components
{
public class SacrificialRevive : MonoBehaviour
{
private void Update()
{
PlayerDeathHead grabbedHead = PlayerControllerPatch.grabbedHead;
PlayerAvatar playerAvatarScript = PlayerController.instance.playerAvatarScript;
int sacrificialReviveHpCost = ConfigManager.SacrificialReviveHpCost;
if (InputControlExtensions.IsPressed(((InputControl)Keyboard.current)[ConfigManager.SacrificialReviveKeybind], 0f) && !((Object)(object)grabbedHead == (Object)null) && playerAvatarScript.playerHealth.health >= sacrificialReviveHpCost)
{
grabbedHead.playerAvatar.Revive(false);
playerAvatarScript.playerHealth.Hurt(sacrificialReviveHpCost, false, -1);
ReviveUtils.Logger.LogInfo((object)("復活 " + grabbedHead.playerAvatar.playerName));
}
}
}
public class ShopRespawn : MonoBehaviour
{
[CompilerGenerated]
private sealed class <RespawnPlayer>d__5 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public ShopRespawn <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <RespawnPlayer>d__5(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Expected O, but got Unknown
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
int num = <>1__state;
ShopRespawn shopRespawn = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = (object)new WaitForSeconds((float)ConfigManager.ShopRespawnDelay);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
if ((Object)(object)LevelGenerator.Instance == (Object)null)
{
ReviveUtils.Logger.LogWarning((object)"LevelGenerator不存在");
}
else if (shopRespawn.PlayerAvatarInstance.deadSet)
{
Vector3 position = ((Component)Object.FindObjectOfType<SpawnPoint>()).transform.position;
Quaternion rotation = ((Component)shopRespawn.PlayerAvatarInstance.playerDeathHead).transform.rotation;
shopRespawn.PlayerAvatarInstance.Revive(false);
shopRespawn.PlayerAvatarInstance.Spawn(position, rotation);
ReviveUtils.Logger.LogInfo((object)("復活玩家 " + shopRespawn.PlayerAvatarInstance.playerName));
}
else
{
ReviveUtils.Logger.LogInfo((object)("取消復活,玩家 " + shopRespawn.PlayerAvatarInstance.playerName + " 已復活或未死亡"));
}
Object.Destroy((Object)(object)((Component)shopRespawn).gameObject);
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
public PlayerAvatar PlayerAvatarInstance { get; set; }
private void Start()
{
((MonoBehaviour)this).StartCoroutine(RespawnPlayer());
}
[IteratorStateMachine(typeof(<RespawnPlayer>d__5))]
private IEnumerator RespawnPlayer()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <RespawnPlayer>d__5(0)
{
<>4__this = this
};
}
}
}