using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Dolso;
using HG.Reflection;
using MonoMod.Cil;
using MonoMod.RuntimeDetour;
using RiskOfOptions;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using TMPro;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.ResourceManagement.AsyncOperations;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: OptIn]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("PillarRevive")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+e0a590a2904280d8ee202d3d354040d1e2002cba")]
[assembly: AssemblyProduct("PillarRevive")]
[assembly: AssemblyTitle("PillarRevive")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Dolso
{
internal static class log
{
private static readonly ManualLogSource logger = Logger.CreateLogSource(Assembly.GetExecutingAssembly().GetName().Name);
[Conditional("DEBUG")]
internal static void debug(object data)
{
logger.LogDebug(data);
}
internal static void info(object data)
{
logger.LogInfo(data);
}
internal static void message(object data)
{
logger.LogMessage(data);
}
internal static void warning(object data)
{
logger.LogWarning(data);
}
internal static void error(object data)
{
logger.LogError(data);
}
internal static void fatal(object data)
{
logger.LogFatal(data);
}
internal static void LogError(this ILCursor c, object data)
{
logger.LogError((object)$"ILCursor failure, skipping: {data}\n{c}");
}
internal static void LogErrorCaller(this ILCursor c, object data)
{
logger.LogError((object)$"ILCursor failed in {new StackFrame(1).GetMethod().Name}, skipping: {data}\n{c}");
}
}
internal static class HookManager
{
internal delegate bool ConfigEnabled<T>(T configValue);
private class HookedConfig<T>
{
private readonly ConfigEnabled<T> enabled;
private readonly IDetour detour;
internal HookedConfig(ConfigEntry<T> configEntry, ConfigEnabled<T> enabled, IDetour detour)
{
this.enabled = enabled;
this.detour = detour;
if (configEntry != null)
{
configEntry.SettingChanged += ConfigChanged;
ConfigChanged(configEntry, null);
}
else
{
detour.Apply();
}
}
private void ConfigChanged(object sender, EventArgs args)
{
if (enabled(((ConfigEntry<T>)sender).Value))
{
if (!detour.IsApplied)
{
detour.Apply();
}
}
else if (detour.IsApplied)
{
detour.Undo();
}
}
}
internal const BindingFlags allFlags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
private static readonly ConfigEnabled<bool> boolConfigEnabled = BoolEnabled;
private static ILHookConfig ilHookConfig = new ILHookConfig
{
ManualApply = true
};
private static HookConfig onHookConfig = new HookConfig
{
ManualApply = true
};
internal static void Hook(Type typeFrom, string fromMethod, Manipulator ilHook)
{
Hook(GetMethod(typeFrom, fromMethod), ilHook);
}
internal static void Hook(Delegate fromMethod, Manipulator ilHook)
{
Hook(fromMethod.Method, ilHook);
}
internal static void Hook(MethodBase fromMethod, Manipulator ilHook)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
try
{
new ILHook(fromMethod, ilHook, ref ilHookConfig).Apply();
}
catch (Exception e)
{
e.LogHookError(fromMethod, ((Delegate)(object)ilHook).Method);
}
}
internal static void Hook(Type typeFrom, string fromMethod, Delegate onHook)
{
Hook(GetMethod(typeFrom, fromMethod), onHook.Method, onHook.Target);
}
internal static void Hook(Delegate fromMethod, Delegate onHook)
{
Hook(fromMethod.Method, onHook.Method, onHook.Target);
}
internal static void Hook(MethodBase fromMethod, Delegate onHook)
{
Hook(fromMethod, onHook.Method, onHook.Target);
}
internal static void Hook(MethodBase fromMethod, MethodInfo onHook, object target = null)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
try
{
new Hook(fromMethod, onHook, target, ref onHookConfig).Apply();
}
catch (Exception e)
{
e.LogHookError(fromMethod, onHook);
}
}
internal static void HookConfig(this ConfigEntry<bool> configEntry, Type typeFrom, string fromMethod, Delegate hook)
{
configEntry.HookConfig(boolConfigEnabled, GetMethod(typeFrom, fromMethod), hook.Method, hook.Target);
}
internal static void HookConfig(this ConfigEntry<bool> configEntry, MethodBase fromMethod, Delegate hook)
{
configEntry.HookConfig(boolConfigEnabled, fromMethod, hook.Method, hook.Target);
}
internal static void HookConfig(this ConfigEntry<bool> configEntry, MethodBase fromMethod, MethodInfo hook)
{
configEntry.HookConfig(boolConfigEnabled, fromMethod, hook);
}
internal static void HookConfig<T>(this ConfigEntry<T> configEntry, ConfigEnabled<T> enabled, Type typeFrom, string fromMethod, Delegate hook)
{
configEntry.HookConfig(enabled, GetMethod(typeFrom, fromMethod), hook.Method, hook.Target);
}
internal static void HookConfig<T>(this ConfigEntry<T> configEntry, ConfigEnabled<T> enabled, MethodBase fromMethod, Delegate hook)
{
configEntry.HookConfig(enabled, fromMethod, hook.Method, hook.Target);
}
internal static void HookConfig<T>(this ConfigEntry<T> configEntry, ConfigEnabled<T> enabled, MethodBase fromMethod, MethodInfo hook, object target = null)
{
try
{
new HookedConfig<T>(configEntry, enabled, ManualDetour(fromMethod, hook, target));
}
catch (Exception e)
{
e.LogHookError(fromMethod, hook);
}
}
internal static IDetour ManualDetour(Type typeFrom, string fromMethod, Delegate hook)
{
return ManualDetour(GetMethod(typeFrom, fromMethod), hook.Method, hook.Target);
}
internal static IDetour ManualDetour(MethodBase fromMethod, Delegate hook)
{
return ManualDetour(fromMethod, hook.Method, hook.Target);
}
internal static IDetour ManualDetour(MethodBase fromMethod, MethodInfo hook, object target = null)
{
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Expected O, but got Unknown
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Expected O, but got Unknown
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Expected O, but got Unknown
try
{
ParameterInfo[] parameters = hook.GetParameters();
if (parameters.Length == 1 && parameters[0].ParameterType == typeof(ILContext))
{
return (IDetour)new ILHook(fromMethod, (Manipulator)hook.CreateDelegate(typeof(Manipulator)), ref ilHookConfig);
}
return (IDetour)new Hook(fromMethod, hook, target, ref onHookConfig);
}
catch (Exception e)
{
e.LogHookError(fromMethod, hook);
return null;
}
}
internal static MethodInfo GetMethod(Type typeFrom, string methodName)
{
if (typeFrom == null || methodName == null)
{
log.error($"Null argument in GetMethod: type={typeFrom}, name={methodName}");
return null;
}
MethodInfo[] array = (from a in typeFrom.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
where a.Name == methodName
select a).ToArray();
switch (array.Length)
{
case 1:
return array[0];
case 0:
log.error($"Failed to find method: {typeFrom}::{methodName}");
return null;
default:
{
string text = $"{array.Length} ambiguous matches found for: {typeFrom}::{methodName}, may be incorrect";
MethodInfo[] array2 = array;
for (int i = 0; i < array2.Length; i++)
{
text = text + "\n" + array2[i];
}
log.warning(text);
return array[0];
}
}
}
internal static MethodInfo GetMethod(Type typeFrom, string methodName, params Type[] parameters)
{
if (typeFrom == null || methodName == null)
{
log.error($"Null argument in GetMethod: type={typeFrom}, name={methodName}");
return null;
}
MethodInfo? method = typeFrom.GetMethod(methodName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, parameters, null);
if (method == null)
{
log.error($"Failed to find method: {typeFrom}::{methodName}_{parameters.Length}");
}
return method;
}
internal static void SetPriority(string[] before_il = null, string[] before_on = null, string[] after_il = null, string[] after_on = null)
{
ilHookConfig.Before = before_il;
onHookConfig.Before = before_on;
ilHookConfig.After = after_il;
onHookConfig.After = after_on;
}
internal static void LogHookError(this Exception e, MethodBase fromMethod, MethodInfo hook)
{
log.error((fromMethod == null) ? $"null from-method for hook: {hook.Name}\n{e}" : $"Failed to hook: {fromMethod.DeclaringType}::{fromMethod.Name} - {hook.Name}\n{e}");
}
private static bool BoolEnabled(bool configValue)
{
return configValue;
}
}
internal static class Utilities
{
internal struct AsyncHandle<T> : IDisposable
{
private AsyncOperationHandle<T> handle;
public T result => handle.Result;
public Task<T> task => handle.Task;
internal AsyncHandle(AsyncOperationHandle<T> handle)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
this.handle = handle;
}
public TaskAwaiter<T> GetAwaiter()
{
return handle.Task.GetAwaiter();
}
public void Dispose()
{
handle.Release();
}
public static implicit operator AsyncOperationHandle<T>(AsyncHandle<T> handle)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
return handle.handle;
}
}
private static GameObject _prefabParent;
internal static GameObject CreatePrefab(GameObject gameObject, string name = null)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Expected O, but got Unknown
if (!Object.op_Implicit((Object)(object)_prefabParent))
{
_prefabParent = new GameObject("DolsoPrefabs");
Object.DontDestroyOnLoad((Object)(object)_prefabParent);
((Object)_prefabParent).hideFlags = (HideFlags)61;
_prefabParent.SetActive(false);
}
GameObject val = Object.Instantiate<GameObject>(gameObject, _prefabParent.transform);
if (name != null)
{
((Object)val).name = name;
}
return val;
}
internal static AsyncHandle<T> GetAddressableAsync<T>(string addressable) where T : Object
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
return new AsyncHandle<T>(Addressables.LoadAssetAsync<T>((object)addressable));
}
internal static AsyncHandle<GameObject> GetAddressableAsync(string addressable)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
return new AsyncHandle<GameObject>(Addressables.LoadAssetAsync<GameObject>((object)addressable));
}
internal static void DoAddressable<T>(string addressable, Action<T> callback, bool release = false) where T : Object
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
AsyncOperationHandle<T> handle = Addressables.LoadAssetAsync<T>((object)addressable);
handle.Completed += delegate(AsyncOperationHandle<T> a)
{
callback(a.Result);
if (release)
{
handle.Release();
}
};
}
internal static void DoAddressable(string addressable, Action<GameObject> callback, bool release = false)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
AsyncOperationHandle<GameObject> handle = Addressables.LoadAssetAsync<GameObject>((object)addressable);
handle.Completed += delegate(AsyncOperationHandle<GameObject> a)
{
callback(a.Result);
if (release)
{
handle.Release();
}
};
}
internal static void AddressableAddComp<TComp>(string addressable, Action<TComp> callback = null) where TComp : Component
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
AsyncOperationHandle<GameObject> val = Addressables.LoadAssetAsync<GameObject>((object)addressable);
val.Completed += delegate(AsyncOperationHandle<GameObject> a)
{
TComp obj = a.Result.AddComponent<TComp>();
callback?.Invoke(obj);
};
}
internal static void AddressableAddCompSingle<Comp>(string addressable) where Comp : Component
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
AsyncOperationHandle<GameObject> val = Addressables.LoadAssetAsync<GameObject>((object)addressable);
val.Completed += delegate(AsyncOperationHandle<GameObject> a)
{
if (!Object.op_Implicit((Object)(object)a.Result.GetComponent<Comp>()))
{
a.Result.AddComponent<Comp>();
}
};
}
}
internal static class RiskofOptions
{
internal const string RooGuid = "com.rune580.riskofoptions";
internal static bool enabled => Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions");
[MethodImpl(MethodImplOptions.NoInlining)]
internal static void SetSprite(Sprite sprite)
{
ModSettingsManager.SetModIcon(sprite);
}
internal static void SetSpriteDefaultIcon()
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Expected O, but got Unknown
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
try
{
string fullName = new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)).FullName;
Texture2D val = new Texture2D(256, 256);
if (ImageConversion.LoadImage(val, File.ReadAllBytes(Path.Combine(fullName, "icon.png"))))
{
ModSettingsManager.SetModIcon(Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)));
}
else
{
log.error("Failed to load icon.png");
}
}
catch (Exception ex)
{
log.error("Failed to load icon.png\n" + ex);
}
}
internal static void AddOption(ConfigEntryBase entry)
{
AddOption(entry, string.Empty, string.Empty);
}
[MethodImpl(MethodImplOptions.NoInlining)]
internal static void AddOption(ConfigEntryBase entry, string categoryName = "", string name = "", bool restartRequired = false)
{
//IL_0157: Unknown result type (might be due to invalid IL or missing references)
//IL_015c: Unknown result type (might be due to invalid IL or missing references)
//IL_0177: Unknown result type (might be due to invalid IL or missing references)
//IL_0192: Unknown result type (might be due to invalid IL or missing references)
//IL_019d: Unknown result type (might be due to invalid IL or missing references)
//IL_01b3: Expected O, but got Unknown
//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
//IL_0129: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Expected O, but got Unknown
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_014f: Expected O, but got Unknown
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Expected O, but got Unknown
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_01b4: Expected O, but got Unknown
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Expected O, but got Unknown
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Expected O, but got Unknown
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Expected O, but got Unknown
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Expected O, but got Unknown
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Expected O, but got Unknown
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
Type settingType = entry.SettingType;
object obj;
if (!(settingType == typeof(float)))
{
obj = ((!(settingType == typeof(string))) ? ((!(settingType == typeof(bool))) ? ((!(settingType == typeof(int))) ? ((!(settingType == typeof(Color))) ? ((!(settingType == typeof(KeyboardShortcut))) ? ((object)((!settingType.IsEnum) ? ((ChoiceOption)null) : new ChoiceOption(entry, new ChoiceConfig()))) : ((object)new KeyBindOption((ConfigEntry<KeyboardShortcut>)(object)entry, new KeyBindConfig()))) : ((object)new ColorOption((ConfigEntry<Color>)(object)entry, new ColorOptionConfig()))) : ((object)new IntFieldOption((ConfigEntry<int>)(object)entry, new IntFieldConfig()))) : ((object)new CheckBoxOption((ConfigEntry<bool>)(object)entry, new CheckBoxConfig()))) : ((object)new StringInputFieldOption((ConfigEntry<string>)(object)entry, new InputFieldConfig
{
submitOn = (SubmitEnum)6,
lineType = (LineType)0
})));
}
else if (entry.Description.AcceptableValues is AcceptableValueRange<float>)
{
obj = (object)new SliderOption((ConfigEntry<float>)(object)entry, new SliderConfig
{
min = ((AcceptableValueRange<float>)(object)entry.Description.AcceptableValues).MinValue,
max = ((AcceptableValueRange<float>)(object)entry.Description.AcceptableValues).MaxValue,
FormatString = "{0:f2}",
description = entry.DescWithDefault("{0:f2}")
});
}
else
{
ConfigEntry<float> obj2 = (ConfigEntry<float>)(object)entry;
FloatFieldConfig val = new FloatFieldConfig();
((NumericFieldConfig<float>)val).FormatString = "{0:f2}";
((BaseOptionConfig)val).description = entry.DescWithDefault("{0:f2}");
obj = (object)new FloatFieldOption(obj2, val);
}
BaseOption val2 = (BaseOption)obj;
if (val2 == null)
{
return;
}
BaseOptionConfig config = val2.GetConfig();
config.category = categoryName;
config.name = name;
config.restartRequired = restartRequired;
if (config.description == "")
{
config.description = entry.DescWithDefault();
}
try
{
ModSettingsManager.AddOption(val2);
}
catch (Exception arg)
{
log.error($"AddOption {entry.Definition} failed\n{arg}");
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
internal static void AddOption(ConfigEntry<float> entry, float min, float max, string format = "{0:f2}", string categoryName = "")
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: 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)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Expected O, but got Unknown
ModSettingsManager.AddOption((BaseOption)new SliderOption(entry, new SliderConfig
{
min = min,
max = max,
FormatString = format,
category = categoryName,
description = ((ConfigEntryBase)(object)entry).DescWithDefault(format)
}));
}
[MethodImpl(MethodImplOptions.NoInlining)]
internal static void AddIntSlider(ConfigEntry<int> entry, int min, int max, string categoryName = "")
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: 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)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Expected O, but got Unknown
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Expected O, but got Unknown
ModSettingsManager.AddOption((BaseOption)new IntSliderOption(entry, new IntSliderConfig
{
min = min,
max = max,
category = categoryName,
description = ((ConfigEntryBase)(object)entry).DescWithDefault()
}));
}
private static string DescWithDefault(this ConfigEntryBase entry, string format = "{0}")
{
return string.Format("{1}\n[Default: " + format + "]", entry.DefaultValue, entry.Description.Description);
}
}
}
namespace PillarRevive
{
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("dolso.pillarrevive", "PillarRevive", "1.1.2")]
[DefaultExecutionOrder(1)]
public class Main : BaseUnityPlugin
{
private static readonly Queue<(NetworkUser, float)> event_list = new Queue<(NetworkUser, float)>(0);
private void Awake()
{
PRConfig.DoConfig(((BaseUnityPlugin)this).Config);
Prefab.CreatePillarPrefabs();
TeleporterInteraction.onTeleporterChargedGlobal += OnTeleporterChargedGlobal_RevivePlayers;
HookManager.Hook(typeof(GlobalEventManager), "OnPlayerCharacterDeath", (Delegate)new Action<Action<GlobalEventManager, DamageReport, NetworkUser>, GlobalEventManager, DamageReport, NetworkUser>(On_GlobalEventManager_OnPlayerDeath));
}
private void Update()
{
if (event_list.Count == 0)
{
return;
}
while (event_list.Count > 0)
{
if (event_list.Peek().Item2 > Time.time)
{
return;
}
TrySpawnPillar(event_list.Dequeue().Item1);
}
event_list.TrimExcess();
}
private static void On_GlobalEventManager_OnPlayerDeath(Action<GlobalEventManager, DamageReport, NetworkUser> orig, GlobalEventManager self, DamageReport damagereport, NetworkUser networkuser)
{
orig(self, damagereport, networkuser);
if (PRConfig.enabled.Value)
{
event_list.Enqueue((networkuser, Time.time + 2.2f));
}
}
private static void OnTeleporterChargedGlobal_RevivePlayers(TeleporterInteraction obj)
{
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
if (!PRConfig.onTeleRespawn.Value || !NetworkServer.active)
{
return;
}
foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
{
if (instance.isConnected && instance.master.IsDeadAndOutOfLivesServer())
{
CharacterBody val = instance.master.Respawn(instance.master.deathFootPosition, default(Quaternion), false);
for (int i = 0; i < PRConfig.curseStacks.Value; i++)
{
val.AddBuff(Buffs.PermanentCurse);
}
}
}
}
private static void TrySpawnPillar(NetworkUser networkuser)
{
if (!Object.op_Implicit((Object)(object)networkuser) || !Object.op_Implicit((Object)(object)networkuser.master) || !networkuser.master.IsDeadAndOutOfLivesServer())
{
return;
}
Run instance = Run.instance;
if (instance == null || instance.isGameOverServer || RoR2Application.isInSinglePlayer)
{
return;
}
GameObject val = SpawnPillar(networkuser.master);
PlayerRevive component = val.GetComponent<PlayerRevive>();
component.SetNetworkUser(networkuser);
if (Object.op_Implicit((Object)(object)TeleporterInteraction.instance))
{
if (Run.instance.stageClearCount == 0 && TeleporterInteraction.instance.currentState is IdleState)
{
HoldoutZoneController component2 = val.GetComponent<HoldoutZoneController>();
component2.baseChargeDuration *= PRConfig.earlyGameDivider.Value;
CombatDirector component3 = val.GetComponent<CombatDirector>();
component3.monsterCredit *= PRConfig.earlyGameDivider.Value;
log.info("Applied early game boost");
}
else if (TeleporterInteraction.instance.currentState is ChargedState)
{
HoldoutZoneController component4 = val.GetComponent<HoldoutZoneController>();
component4.baseChargeDuration *= PRConfig.postTeleDivider.Value;
CombatDirector component5 = val.GetComponent<CombatDirector>();
component5.monsterCredit *= PRConfig.postTeleDivider.Value;
component.setTeleFinished = true;
log.info("Applied post teleporter boost");
}
}
}
private static GameObject SpawnPillar(CharacterMaster master)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = (Vector3)(((??)TeleportHelper.FindSafeTeleportDestination(master.deathFootPosition, master.bodyPrefab.GetComponent<CharacterBody>(), RoR2Application.rng)) ?? master.deathFootPosition);
GameObject obj = Object.Instantiate<GameObject>(Prefab.pillarSelection.Evaluate(Run.instance.stageRng.nextNormalizedFloat), val, default(Quaternion));
NetworkServer.Spawn(obj);
return obj;
}
}
internal class PlayerRevive : MonoBehaviour
{
private static readonly List<PlayerRevive> instances = new List<PlayerRevive>();
public Pillar pillarIndex;
private NetworkUser networkUser;
private bool didRespawn;
public bool setTeleFinished;
public void SetNetworkUser(NetworkUser networkUser)
{
this.networkUser = networkUser;
PurchaseInteraction component = ((Component)this).GetComponent<PurchaseInteraction>();
component.NetworkdisplayNameToken = $"{networkUser.userName}'s {Prefab.pillarNames[(int)pillarIndex]}";
component.NetworkcontextToken = "Reform " + networkUser.userName;
if (PRConfig.autoPing.Value)
{
((MonoBehaviour)this).Invoke("PingPillar", 3f);
}
}
private void OnEnable()
{
if (NetworkServer.active)
{
((UnityEvent<HoldoutZoneController>)(object)((Component)this).GetComponent<HoldoutZoneController>().onCharged).AddListener((UnityAction<HoldoutZoneController>)OnCharged);
instances.Add(this);
}
}
private void OnDisable()
{
if (NetworkServer.active)
{
instances.Remove(this);
}
}
private void OnCharged(HoldoutZoneController holdout)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Expected O, but got Unknown
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Expected O, but got Unknown
if (!Object.op_Implicit((Object)(object)networkUser) || !Object.op_Implicit((Object)(object)networkUser.master))
{
Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
{
baseToken = "<color=red>Player not found</color>"
});
return;
}
CharacterMaster master = networkUser.master;
CharacterBody val = master.Respawn(master.deathFootPosition, default(Quaternion), false);
for (int i = 0; i < PRConfig.curseStacks.Value; i++)
{
val.AddBuff(Buffs.PermanentCurse);
}
didRespawn = true;
Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
{
baseToken = "<style=cLunarObjective>Reformed " + networkUser.userName + "</style>"
});
((MonoBehaviour)this).Invoke("DestroySelf", 60f);
}
private void FixedUpdate()
{
if (!NetworkServer.active)
{
return;
}
bool flag = !Object.op_Implicit((Object)(object)networkUser) || !Object.op_Implicit((Object)(object)networkUser.master);
if (!flag)
{
if (!didRespawn)
{
CharacterBody currentBody = networkUser.GetCurrentBody();
if (currentBody != null && currentBody.healthComponent.alive)
{
goto IL_0055;
}
}
if (!setTeleFinished && Object.op_Implicit((Object)(object)TeleporterInteraction.instance) && TeleporterInteraction.instance.currentState is ChargedState)
{
HoldoutZoneController component = ((Component)this).GetComponent<HoldoutZoneController>();
component.baseChargeDuration *= PRConfig.postTeleDivider.Value;
CombatDirector component2 = ((Component)this).GetComponent<CombatDirector>();
component2.monsterCredit *= PRConfig.postTeleDivider.Value;
setTeleFinished = true;
log.info("Applied post teleporter boost");
}
return;
}
goto IL_0055;
IL_0055:
if (flag)
{
log.info("Pillar detected player missing, removing self");
}
Object.Destroy((Object)(object)((Component)this).gameObject);
}
private void PingPillar()
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//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_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
PingInfo val = default(PingInfo);
val.active = true;
val.origin = ((Component)this).transform.position;
val.normal = Vector3.zero;
val.targetNetworkIdentity = ((Component)this).GetComponent<NetworkIdentity>();
PingInfo currentPing = val;
LocalUserManager.GetFirstLocalUser().cachedMasterObject.GetComponent<PingerController>().SetCurrentPing(currentPing);
}
private void DestroySelf()
{
Object.Destroy((Object)(object)((Component)this).gameObject);
}
internal static void DestroyAll()
{
for (int num = instances.Count - 1; num >= 0; num--)
{
instances[num].DestroySelf();
}
}
}
internal static class PRConfig
{
internal class PillarConfig
{
public ConfigEntry<float> weight;
public ConfigEntry<float> chargeDuration;
public ConfigEntry<float> monsterCredits;
private int index;
public PillarConfig(int index)
{
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Expected O, but got Unknown
this.index = index;
string text = Prefab.pillarNames[index];
weight = configFile.Bind<float>(text, "Weight", 1f, new ConfigDescription("Spawn weighting of " + text + " Pillar", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
chargeDuration = configFile.Bind<float>(text, "Charge duration", (float)((Pillar)index switch
{
Pillar.Blood => 10,
Pillar.Mass => 60,
_ => 30,
}), "Charge duration of " + text + " Pillar");
monsterCredits = configFile.Bind<float>(text, "Monster Credits", (float)((index != 3) ? 700 : 0), "How many monsters to spawn on pillar activation");
weight.SettingChanged += delegate
{
Prefab.pillarSelection.ModifyChoiceWeight(this.index, weight.Value);
};
chargeDuration.SettingChanged += delegate
{
Prefab.pillarSelection.choices[this.index].value.GetComponent<HoldoutZoneController>().baseChargeDuration = chargeDuration.Value;
};
monsterCredits.SettingChanged += delegate
{
Prefab.pillarSelection.choices[this.index].value.GetComponent<CombatDirector>().monsterCredit = monsterCredits.Value;
};
}
}
public static ConfigFile configFile;
public static ConfigEntry<bool> enabled;
public static ConfigEntry<int> curseStacks;
public static ConfigEntry<bool> healingNova;
public static ConfigEntry<float> earlyGameDivider;
public static ConfigEntry<float> postTeleDivider;
public static ConfigEntry<bool> autoPing;
public static ConfigEntry<bool> onTeleRespawn;
public static PillarConfig[] pillars;
public static void DoConfig(ConfigFile bepConfigFile)
{
configFile = bepConfigFile;
enabled = configFile.Bind<bool>("_Main", "Enable Mod", true, "Enables mod. Toggle in-game with pillarrevive_toggle command");
onTeleRespawn = configFile.Bind<bool>("_Main", "On Teleporter Completion Revive", false, "If should automatically revive dead players on teleporter completion");
curseStacks = configFile.Bind<int>("_Main", "Curse Stacks", 25, "Give n stacks of curse to the revived player, set to 0 to disable");
earlyGameDivider = configFile.Bind<float>("_Main", "Early game pillar difficulty", 0.3f, "On stage 1 and teleporter has not been hit, multiply monster credits and charge duration by this number");
postTeleDivider = configFile.Bind<float>("_Main", "Tele finished pillar difficulty", 0.1f, "After teleporter has been fully completed, spawn this many less monsters and charge pillar faster");
autoPing = configFile.Bind<bool>("_Main", "Auto ping pillars", true, "Have host automatically ping pillars when they spawn. This is so that they can be highlighted for everyone");
healingNova = configFile.Bind<bool>("_Main", "Use Lepton Daisy", true, "If revive pillars should use Lepton Daisies");
pillars = new PillarConfig[Prefab.pillarNames.Length];
for (int i = 0; i < pillars.Length; i++)
{
pillars[i] = new PillarConfig(i);
}
if (RiskofOptions.enabled)
{
DoRiskOfOptions();
}
enabled.SettingChanged += delegate
{
if (!enabled.Value)
{
PlayerRevive.DestroyAll();
}
};
healingNova.SettingChanged += delegate
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
ChoiceInfo<GameObject>[] choices = Prefab.pillarSelection.choices;
for (int j = 0; j < choices.Length; j++)
{
choices[j].value.GetComponent<HoldoutZoneController>().applyHealingNova = healingNova.Value;
}
};
}
private static void DoRiskOfOptions()
{
RiskofOptions.SetSpriteDefaultIcon();
RiskofOptions.AddOption((ConfigEntryBase)(object)enabled);
RiskofOptions.AddOption((ConfigEntryBase)(object)onTeleRespawn);
RiskofOptions.AddIntSlider(curseStacks, 0, 100);
RiskofOptions.AddOption(earlyGameDivider, 0f, 1f);
RiskofOptions.AddOption(postTeleDivider, 0f, 1f);
RiskofOptions.AddOption((ConfigEntryBase)(object)autoPing);
RiskofOptions.AddOption((ConfigEntryBase)(object)healingNova);
for (int i = 0; i < pillars.Length; i++)
{
RiskofOptions.AddOption((ConfigEntryBase)(object)pillars[i].monsterCredits);
RiskofOptions.AddOption(pillars[i].chargeDuration, 0f, 120f, "{0:0.0}");
RiskofOptions.AddOption(pillars[i].weight, 0f, 10f, "{0:0.0}");
}
}
[ConCommand(/*Could not decode attribute arguments.*/)]
private static void PRPillarConfigReload(ConCommandArgs args)
{
configFile.Reload();
Debug.Log((object)"Reloaded PillarRevive's config");
}
[ConCommand(/*Could not decode attribute arguments.*/)]
private static void PRPillarToggle(ConCommandArgs args)
{
if (enabled.Value)
{
Debug.Log((object)"Disabled new pillars from spawning");
}
else
{
Debug.Log((object)"Enabled PillarRevive");
}
enabled.Value = !enabled.Value;
}
}
public static class Prefab
{
public static readonly string[] pillarNames = new string[4] { "Blood", "Design", "Mass", "Soul" };
public static WeightedSelection<GameObject> pillarSelection;
public static async void CreatePillarPrefabs()
{
if (pillarSelection == null)
{
Utilities.AsyncHandle<GameObject>[] pillarTasks = new Utilities.AsyncHandle<GameObject>[pillarNames.Length];
for (int i = 0; i < pillarNames.Length; i++)
{
pillarTasks[i] = Utilities.GetAddressableAsync("RoR2/Base/moon2/MoonBattery" + pillarNames[i] + ".prefab");
}
await Task.WhenAll(pillarTasks.Select((Utilities.AsyncHandle<GameObject> a) => a.task));
pillarSelection = new WeightedSelection<GameObject>(8);
for (int j = 0; j < pillarNames.Length; j++)
{
GameObject val = Utilities.CreatePrefab(pillarTasks[j].result);
((Object)val).name = pillarNames[j] + "Pillar";
val.AddComponent<PlayerRevive>().pillarIndex = (Pillar)j;
pillarSelection.AddChoice(val, 1f);
pillarTasks[j].Dispose();
}
}
for (int k = 0; k < pillarSelection.Count; k++)
{
ModifyPillar(k);
}
}
private static void ModifyPillar(int index)
{
pillarSelection.ModifyChoiceWeight(index, PRConfig.pillars[index].weight.Value);
GameObject value = pillarSelection.choices[index].value;
HoldoutZoneController component = value.GetComponent<HoldoutZoneController>();
component.applyHealingNova = PRConfig.healingNova.Value;
component.baseChargeDuration = PRConfig.pillars[index].chargeDuration.Value;
CombatDirector component2 = value.GetComponent<CombatDirector>();
component2.expRewardCoefficient = 0f;
component2.goldRewardCoefficient = 0f;
component2.monsterCredit = PRConfig.pillars[index].monsterCredits.Value;
}
}
internal enum Pillar
{
Blood,
Desgin,
Mass,
Soul
}
}