Some mods may be broken due to the recent Alloyed Collective update.
Decompiled source of PillarRevive v1.1.2
plugins/PillarRevive.dll
Decompiled 2 weeks agousing 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 } }