using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Mutators.Enums; using Mutators.Extensions; using Mutators.Managers; using Mutators.Mutators; using Mutators.Mutators.Behaviours; using Mutators.Mutators.Behaviours.Custom; using Mutators.Mutators.Behaviours.Marker; using Mutators.Mutators.Behaviours.UI; using Mutators.Mutators.Patches; using Mutators.Network; using Mutators.Network.Meta; using Mutators.Patches; using Mutators.Settings; using Mutators.Settings.Specific; using Mutators.Utility; using Photon.Pun; using Photon.Realtime; using REPOLib; using REPOLib.Modules; using Sirenix.Utilities; using TMPro; using Unity.VisualScripting; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("Xepos")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.6.5.0")] [assembly: AssemblyInformationalVersion("0.6.5+84898801e39b06dcd82d1eeada0ea61eccf78aa8")] [assembly: AssemblyProduct("Mutators")] [assembly: AssemblyTitle("Mutators")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.6.5.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 Mutators { internal class AssetStore { internal static ExplosionPreset Preset { get; set; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "Xepos.REPO-Mutators"; public const string NAME = "Mutators"; public const string PLUGIN_VERSION = "0.6.5"; } [BepInDependency("REPOLib", "4.0.0")] [BepInPlugin("Xepos.REPO-Mutators", "Mutators", "0.6.5")] public class RepoMutators : BaseUnityPlugin { internal const string MainScenePath = "Assets/Scenes/Main/Main.unity"; internal const string NETWORKMANAGER_NAME = "MutatorsNetworkManager"; internal static RepoMutators Instance { get; private set; } internal static ModSettings Settings { get; private set; } internal static ManualLogSource Logger => Instance._logger; private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; set; } private void Awake() { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown Instance = this; ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "mutators"); BundleLoader.LoadBundle(text, (Action)delegate(AssetBundle assetbundle) { AssetStore.Preset = assetbundle.LoadAsset("explosion default"); GameObject val3 = assetbundle.LoadAsset("FiringMyLaser"); val3.SetActive(false); val3.AddComponent(); val3.AddComponent(); NetworkPrefabs.RegisterNetworkPrefab("Xepos.REPO-Mutators/FiringMyLaser", val3); _logger.LogInfo((object)"Loaded Mutators asset bundle"); }, false); Settings = new ModSettings(((BaseUnityPlugin)this).Config); MutatorSettings.Initialize(((BaseUnityPlugin)this).Config); GameObject val = new GameObject("RepoMutatorsPrefab") { hideFlags = (HideFlags)61 }; val.SetActive(false); val.AddComponent(); val.AddComponent(); string myPrefabId = "Xepos.REPO-Mutators/MutatorsNetworkManager"; NetworkPrefabs.RegisterNetworkPrefab(myPrefabId, val); SceneManager.sceneLoaded += delegate(Scene scene, LoadSceneMode loadSceneMode) { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) if (!(((Scene)(ref scene)).path != "Assets/Scenes/Main/Main.unity") && SemiFunc.IsMasterClientOrSingleplayer()) { if ((Object)(object)RunManager.instance.levelCurrent == (Object)(object)RunManager.instance.levelMainMenu) { if ((Object)(object)MutatorsNetworkManager.Instance != (Object)null && (Object)(object)((Component)MutatorsNetworkManager.Instance).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)MutatorsNetworkManager.Instance).gameObject); } } else if (!((Object)(object)MutatorsNetworkManager.Instance != (Object)null) && SemiFunc.RunIsLobbyMenu()) { Logger.LogDebug((object)"Reviving network manager"); PrefabRef val2 = default(PrefabRef); if (!NetworkPrefabs.TryGetNetworkPrefabRef(myPrefabId, ref val2)) { throw new Exception("Unable to establish Mutators NetworkManager: Could not find PrefabRef with id: " + myPrefabId); } NetworkPrefabs.SpawnNetworkPrefab(val2, Vector3.zero, Quaternion.identity, (byte)0, (object[])null); MutatorManager instance2 = MutatorManager.Instance; IMutator weightedMutator = instance2.GetWeightedMutator(); Logger.LogDebug((object)("Picked weighted mutator: " + weightedMutator.Name)); instance2.CurrentMutator = weightedMutator; MutatorsNetworkManager.Instance.SendActiveMutator(weightedMutator.Name, weightedMutator.Settings.AsMetadata()); Logger.LogDebug((object)("Mutator set: " + weightedMutator.Name)); } } }; MutatorManager instance = MutatorManager.Instance; instance.GameStateChanged = (Action)Delegate.Combine(instance.GameStateChanged, (Action)delegate(MutatorsGameState gameState) { Logger.LogDebug((object)$"Changed Mutators gamestate to {gameState}"); }); Patch(); Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!"); Logger.LogDebug((object)"Initializing default mutators."); MutatorManager.Instance.InitializeDefaultMutators(); } internal void Patch() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0054: Expected O, but got Unknown bool flag = Chainloader.PluginInfos.Values.Any((PluginInfo x) => x.Metadata.GUID == "soundedsquash.spawnmanager"); if (Harmony == null) { Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; Harmony = val; } Harmony.PatchAll(typeof(RunManagerPatch)); Harmony.PatchAll(typeof(LoadingUIPatch)); Harmony.PatchAll(typeof(MapToolControllerPatch)); Harmony.PatchAll(typeof(SemiFuncPatch)); Harmony.PatchAll(typeof(MenuPagePatch)); Harmony.PatchAll(typeof(SpectateCameraPatch)); Harmony.PatchAll(typeof(LevelGeneratorPatch)); Harmony.PatchAll(typeof(MenuManagerPatch)); Harmony.PatchAll(typeof(HealthUIPatch)); if (!flag) { Harmony.PatchAll(typeof(EnemyDirectorPatch)); } } internal void Unpatch() { Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } foreach (IMutator value in MutatorManager.Instance.RegisteredMutators.Values) { value.Unpatch(); } } } } namespace Mutators.Utility { internal static class DescriptionUtils { internal enum DescriptionReplacementType { REPLACE, PREPEND, APPEND } [CompilerGenerated] private sealed class d__1 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public DescriptionReplacementType replacementType; public string description; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if (!Object.op_Implicit((Object)(object)MutatorDescriptionAnnouncingBehaviour.Instance)) { <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } TextMeshProUGUI text = MutatorDescriptionAnnouncingBehaviour.Instance.Text; switch (replacementType) { case DescriptionReplacementType.REPLACE: ((TMP_Text)text).text = description; break; case DescriptionReplacementType.PREPEND: ((TMP_Text)text).text = description + "\n" + ((TMP_Text)text).text; break; case DescriptionReplacementType.APPEND: ((TMP_Text)text).text = ((TMP_Text)text).text + "\n" + description; break; } 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(); } } [IteratorStateMachine(typeof(d__1))] internal static IEnumerator LateUpdateDescription(string description, DescriptionReplacementType replacementType = DescriptionReplacementType.REPLACE) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__1(0) { description = description, replacementType = replacementType }; } } public static class TemporaryItemUtils { public static void RemoveMarkedItems(string marker) { string marker2 = marker; StatsManager instance = StatsManager.instance; foreach (string item in (from item in instance.item where item.Key.Contains("(" + marker2 + ")") select item into x select x.Key).ToList()) { instance.item.Remove(item); instance.itemStatBattery.Remove(item); } } public static void DropMarkedItems(string marker) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) Inventory instance = Inventory.instance; foreach (InventorySpot inventorySpot in instance.inventorySpots) { ItemEquippable currentItem = inventorySpot.CurrentItem; if (Object.op_Implicit((Object)(object)currentItem) && Object.op_Implicit((Object)(object)((Component)currentItem).gameObject.GetComponent())) { ((Component)currentItem).GetComponent().ForceUnequip(instance.playerAvatar.PlayerVisionTarget.VisionTransform.position, SemiFunc.IsMultiplayer() ? instance.physGrabber.photonView.ViewID : (-1)); } } RemoveMarkedItems(marker); } } } namespace Mutators.Settings { public abstract class AbstractMutatorSettings { protected const string WeightConfigKey = "Weight"; protected const string MinimumLevelConfigKey = "Minimum level"; protected const string MaximumLevelConfigKey = "Maximum level"; public abstract string MutatorName { get; } public abstract string MutatorDescription { get; } public abstract uint Weight { get; } public abstract uint MinimumLevel { get; } public abstract uint MaximumLevel { get; } public virtual bool IsEligibleForSelection() { int levelsCompleted = RunManager.instance.levelsCompleted; if (MaximumLevel != 0 && MinimumLevel > MaximumLevel) { RepoMutators.Logger.LogWarning((object)(MutatorName + " was configured with a minimum level larger than the maximum level!")); RepoMutators.Logger.LogWarning((object)"This configuration is consider invalid, the level bounds will be ignored."); return true; } if (MaximumLevel == 0) { return levelsCompleted >= MinimumLevel; } if (levelsCompleted >= MinimumLevel) { return levelsCompleted <= MaximumLevel; } return false; } public virtual IDictionary? AsMetadata() { return null; } } public class EnemyDisablingMutatorSettings : GenericMutatorSettings { private readonly ConfigEntry _excludedEnemies; public IList ExcludedEnemies { get; private set; } = new List(); public EnemyDisablingMutatorSettings(string name, string description, ConfigFile config, params string[] defaultDisabledEnemies) : base(name, description, config) { _excludedEnemies = config.Bind(GenericMutatorSettings.GetSection(name), "Excluded enemies", string.Join(", ", defaultDisabledEnemies), "Enemies that cannot be spawned by the " + name + " Mutator. (Comma separated e.g. Apex Predator,Huntsman)"); CacheEnemies(); } internal void CacheEnemies() { ExcludedEnemies = (from value in _excludedEnemies.Value.Split(",") select value.Trim()).ToList(); } } public class GenericMutatorSettings : AbstractMutatorSettings { private readonly ConfigEntry _weight; private readonly ConfigEntry _minimumLevel; private readonly ConfigEntry _maximumLevel; public override string MutatorName { get; } public override string MutatorDescription { get; } public override uint Weight => _weight.Value; public override uint MinimumLevel => _minimumLevel.Value; public override uint MaximumLevel => _maximumLevel.Value; public GenericMutatorSettings(string name, string description, ConfigFile config) { MutatorName = name; MutatorDescription = description; _weight = config.Bind(GetSection(name), "Weight", 100u, "Weighted chance for the " + name + " Mutator to be active."); _minimumLevel = config.Bind(GetSection(name), "Minimum level", 0u, "The minimum level on which the " + name + " Mutator can show up"); _maximumLevel = config.Bind(GetSection(name), "Maximum level", 1000u, "The maximum level on which the " + name + " mutator can show up (0 = no upper bound)"); } protected static string GetSection(string name) { return name + " Mutator"; } } internal interface ILevelRemovingMutatorSettings { bool AllowCustomLevels { get; } IList ExcludedLevels { get; } } internal class ModSettings { internal enum MutatorNameToggleType { Keybind, WithDescription } private readonly ConfigEntry _mutatorDisplayY; private readonly ConfigEntry _mutatorDisplaySize; private readonly ConfigEntry _mutatorDisplayToggleKey; private readonly ConfigEntry _mutatorDisplayToggleType; private readonly ConfigEntry _mutatorDescriptionDisplayY; private readonly ConfigEntry _mutatorDescriptionDisplaySize; private readonly ConfigEntry _mutatorDescriptionInitialDisplayTime; private readonly ConfigEntry _mutatorDescriptionPinned; private readonly ConfigEntry _mutatorDescriptionInMapTool; private readonly ConfigEntry _targetDisplaySize; private readonly ConfigEntry _specialActionY; private readonly ConfigEntry _specialActionKey; public float MutatorDisplayY => _mutatorDisplayY.Value; public float MutatorDisplaySize => _mutatorDisplaySize.Value; public KeyCode MutatorDisplayToggleKey { get; private set; } public MutatorNameToggleType MutatorDisplayToggleType { get; private set; } public float MutatorDescriptionDisplayY => _mutatorDescriptionDisplayY.Value; public float MutatorDescriptionDisplaySize => _mutatorDescriptionDisplaySize.Value; public float MutatorDescriptionInitialDisplayTime => _mutatorDescriptionInitialDisplayTime.Value; public bool MutatorDescriptionPinned => _mutatorDescriptionPinned.Value; public bool MutatorDescriptionInMapTool => _mutatorDescriptionInMapTool.Value; public float TargetDisplaySize => _targetDisplaySize.Value; public float SpecialActionY => _specialActionY.Value; public KeyCode SpecialActionKey { get; private set; } internal ModSettings(ConfigFile config) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown _mutatorDisplayY = config.Bind("Mutator Interface", "Y position", -75f, "The Y position of the active Mutator overlay"); _mutatorDisplaySize = config.Bind("Mutator Interface", "Size", 30f, "The size of the active Mutator overlay"); _mutatorDisplayToggleType = config.Bind("Mutator Interface", "Mutator display toggle type", "Keybind", new ConfigDescription("The method used to toggle the active Mutator overlay", (AcceptableValueBase)(object)new AcceptableValueList(new string[2] { "Keybind", "With Description" }), Array.Empty())); _mutatorDisplayToggleKey = config.Bind("Mutator Interface", "Mutator display toggle key", "H", "The key use to toggle the active Mutator overlay"); _mutatorDescriptionDisplayY = config.Bind("Mutator Interface", "Description Y position", -110f, "The Y position of the active Mutator's description overlay"); _mutatorDescriptionDisplaySize = config.Bind("Mutator Interface", "Description size", 20f, "The size of the active Mutator's description overlay"); _mutatorDescriptionInitialDisplayTime = config.Bind("Mutator Interface", "Description initial display time", 8f, "The time for which the mutator's description is on screen when starting the level"); _mutatorDescriptionPinned = config.Bind("Mutator Interface", "Description always active", false, "If true, \"Description initial display time\" will be ignored and the description will always stay on screen"); _mutatorDescriptionInMapTool = config.Bind("Mutator Interface", "Description active in map tool", true, "If true, the mutator's description will be displayed when opening the map tool"); _targetDisplaySize = config.Bind("Mutator Interface", "Target Size", 40f, "The size of the target (e.g. president health) overlay"); _specialActionY = config.Bind("Special Action", "Special Action Y position", -50f, "The Y position of the Special Action overlay"); _specialActionKey = config.Bind("Special Action", "Special Action Key", "R", "Keybind that activates the Special Action"); CacheKeys(); } internal void CacheKeys() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got I4 //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got I4 //IL_0028->IL0028: Incompatible stack types: O vs I4 //IL_0022->IL0028: Incompatible stack types: I4 vs O //IL_0022->IL0028: Incompatible stack types: O vs I4 //IL_0091->IL0091: Incompatible stack types: O vs I4 //IL_008b->IL0091: Incompatible stack types: I4 vs O //IL_008b->IL0091: Incompatible stack types: O vs I4 object obj = this; int num; if (Enum.TryParse(typeof(KeyCode), _mutatorDisplayToggleKey.Value, out object result)) { obj = (object)(KeyCode)result; num = (int)obj; } else { num = 0; obj = num; num = (int)obj; } ((ModSettings)num).MutatorDisplayToggleKey = (KeyCode)obj; MutatorDisplayToggleType = (Enum.TryParse(typeof(MutatorNameToggleType), _mutatorDisplayToggleType.Value.Replace(" ", ""), out object result2) ? ((MutatorNameToggleType)result2) : MutatorNameToggleType.Keybind); object obj2 = this; int num2; if (Enum.TryParse(typeof(KeyCode), _specialActionKey.Value, out object result3)) { obj2 = (object)(KeyCode)result3; num2 = (int)obj2; } else { num2 = 0; obj2 = num2; num2 = (int)obj2; } ((ModSettings)num2).SpecialActionKey = (KeyCode)obj2; } } public static class MutatorSettings { public static NopMutatorSettings NopMutator { get; private set; } public static ApolloElevenMutatorSettings ApolloEleven { get; private set; } public static OutWithABangMutatorSettings OutWithABang { get; private set; } public static DuckThisMutatorSettings DuckThis { get; private set; } public static UltraViolenceMutatorSettings UltraViolence { get; private set; } public static ProtectThePresidentMutatorSettings ProtectThePresident { get; private set; } public static OneShotOneKillMutatorSettings OneShotOneKill { get; private set; } public static GenericMutatorSettings RustyServos { get; private set; } public static HandleWithCareMutatorSettings HandleWithCare { get; private set; } public static EnemyDisablingMutatorSettings HuntingSeason { get; private set; } public static ThereCanOnlyBeOneMutatorSettings ThereCanOnlyBeOne { get; private set; } public static GenericMutatorSettings VolatileCargo { get; private set; } public static SealedAwayMutatorSettings SealedAway { get; private set; } public static GenericMutatorSettings ProtectTheWeak { get; private set; } public static FiringMyLaserMutatorSettings FiringMyLaser { get; private set; } public static VoiceoverMutatorSettings Voiceover { get; private set; } public static TheFloorIsLavaMutatorSettings TheFloorIsLava { get; private set; } public static LessIsMoreMutatorSettings LessIsMore { get; private set; } public static AmalgamMutatorSettings Amalgam { get; private set; } public static void Initialize(ConfigFile config) { NopMutator = new NopMutatorSettings(config); ApolloEleven = new ApolloElevenMutatorSettings("Apollo 11", "Level-wide Zero-Gravity", config); OutWithABang = new OutWithABangMutatorSettings("Out With a Bang!", "Monsters explode on death", config); DuckThis = new DuckThisMutatorSettings("Duck This", "Ducks aggro on sight instead of on interaction\nAlways spawn at least 1 duck", config); UltraViolence = new UltraViolenceMutatorSettings("Ultra-Violence", "Immediately activates the final extraction phase", config); ProtectThePresident = new ProtectThePresidentMutatorSettings("Protect the President", "A random player becomes the \"President\"\nIf they die, everyone else self-destructs", config); OneShotOneKill = new OneShotOneKillMutatorSettings("One Shot, One Kill", "Any damage taken by a player is lethal", config); RustyServos = new GenericMutatorSettings("Rusty Servos", "Players cannot jump\n+3 Grab Range", config); HandleWithCare = new HandleWithCareMutatorSettings("Handle With Care", "Valuables are worth more but break on any impact", config); HuntingSeason = new EnemyDisablingMutatorSettings("Hunting Season", "No valuables spawn, weapons spawn instead\nEnemy respawn time reduced to 10 seconds", config, "Voodoo", "Weeping Angel"); ThereCanOnlyBeOne = new ThereCanOnlyBeOneMutatorSettings("There Can Only Be One", "All monster spawns are of the same type", config); VolatileCargo = new GenericMutatorSettings("Volatile Cargo", "Valuables explode on destruction\nExplosion radius and strength based on value", config); SealedAway = new SealedAwayMutatorSettings("Sealed Away", "Breaking valuables has a chance to spawn monsters", config); ProtectTheWeak = new ProtectTheWeakMutatorSettings("Protect the Weak", "Protect your weaker friends!", config); FiringMyLaser = new FiringMyLaserMutatorSettings("Firing My Laser", "Fire your laser by pressing {specialActionKey}\nUncontrollably fire your laser when taking damage", config); Voiceover = new VoiceoverMutatorSettings("Voiceover", "Player voices are shuffled", config); TheFloorIsLava = new TheFloorIsLavaMutatorSettings("The Floor Is Lava", "You take damage while standing on the floor", config); LessIsMore = new LessIsMoreMutatorSettings("Less Is More", "Valuables are worth less but gain value when hit\nNormal breaking mechanics apply", config); Amalgam = new AmalgamMutatorSettings("Amalgam", "You’ve been here before — just not all at once", config); } } } namespace Mutators.Settings.Specific { public class AmalgamMutatorSettings : GenericMutatorSettings, ILevelRemovingMutatorSettings { private readonly ConfigEntry _excludedLevels; public bool AllowCustomLevels => true; public IList ExcludedLevels { get; private set; } internal AmalgamMutatorSettings(string name, string description, ConfigFile config) : base(name, description, config) { _excludedLevels = config.Bind(GenericMutatorSettings.GetSection(name), "Excluded levels", "", "Levels that should be excluded from the " + name + " Mutator. These can neither be picked as a base, nor will their rooms be used in the level generation"); ExcludedLevels = ExcludedLevelsAsList(); _excludedLevels.SettingChanged += SettingChanged; } private void SettingChanged(object sender, EventArgs e) { ExcludedLevels = ExcludedLevelsAsList(); } private IList ExcludedLevelsAsList() { IList list = (from value in _excludedLevels.Value.Split(",") select value.Trim()).ToList(); if (!list.Contains("Backrooms")) { list.Add("Backrooms"); } if (!list.Contains("PeachCastle")) { list.Add("PeachCastle"); } return list; } } public class ApolloElevenMutatorSettings : GenericMutatorSettings { private readonly ConfigEntry _applyToEnemies; private readonly ConfigEntry _applyInCart; private readonly ConfigEntry _downwardsKey; public bool ApplyToEnemies => _applyToEnemies.Value; public bool ApplyInCart => _applyInCart.Value; public KeyCode DownwardsKey { get; private set; } internal ApolloElevenMutatorSettings(string name, string description, ConfigFile config) : base(name, description, config) { _applyToEnemies = config.Bind(GenericMutatorSettings.GetSection(name), "Apply to monsters", false, "If true, Zero-Gravity will also be applied to monsters while the " + name + " Mutator is active."); _applyInCart = config.Bind(GenericMutatorSettings.GetSection(name), "Apply in cart/extraction", true, "If true, Zero-Gravity will also apply to valuables in the cart and extraction points."); _downwardsKey = config.Bind(GenericMutatorSettings.GetSection(name), "Downwards momentum keybind", "LeftControl", "(Client sided) If bound, this key can be used to control yourself downwards while the " + name + " Mutator is active"); CacheKey(); } internal void CacheKey() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (Enum.TryParse(typeof(KeyCode), _downwardsKey.Value, out object result)) { DownwardsKey = (KeyCode)result; } else { DownwardsKey = (KeyCode)0; } } } public class DuckThisMutatorSettings : GenericMutatorSettings { private readonly ConfigEntry _duckAggroCooldown; public float AggroCooldown => _duckAggroCooldown.Value; internal DuckThisMutatorSettings(string name, string description, ConfigFile config) : base(name, description, config) { _duckAggroCooldown = config.Bind(GenericMutatorSettings.GetSection(name), "Duck aggro cooldown", 50f, "The cooldown between duck aggro while the Duck This Mutator is active."); } } public class FiringMyLaserMutatorSettings : GenericMutatorSettings { private readonly ConfigEntry _laserActionCooldown; private readonly ConfigEntry _laserActionEnemyDamage; private readonly ConfigEntry _laserActionEnabled; private readonly ConfigEntry _laserOnHurtEnabled; public int LaserActionCooldown => _laserActionCooldown.Value; public int LaserActionEnemyDamage => _laserActionEnemyDamage.Value; public bool LaserActionEnabled => _laserActionEnabled.Value; public bool LaserOnHurtEnabled => _laserOnHurtEnabled.Value; internal FiringMyLaserMutatorSettings(string name, string description, ConfigFile config) : base(name, description, config) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown _laserActionEnabled = config.Bind(GenericMutatorSettings.GetSection(name), "Allow manual laser action", true, "If true, players can manually use their laser action while the cooldown is over. Otherwise, only use the laser when getting hit"); _laserOnHurtEnabled = config.Bind(GenericMutatorSettings.GetSection(name), "Fire laser on hurt", true, "If true, players will automatically fire their laser when getting hurt."); _laserActionCooldown = config.Bind(GenericMutatorSettings.GetSection(name), "Laser action cooldown", 60, new ConfigDescription("The amount of seconds before the laser special action can be used again.", (AcceptableValueBase)(object)new AcceptableValueRange(5, 10000), Array.Empty())); _laserActionEnemyDamage = config.Bind(GenericMutatorSettings.GetSection(name), "Laser action enemy damage", 30, new ConfigDescription("The amount of damage the laser special action deals to enemies per tick.", (AcceptableValueBase)(object)new AcceptableValueRange(10, 200), Array.Empty())); } public override IDictionary? AsMetadata() { IDictionary dictionary = new Dictionary { { "laserActionEnabled", LaserActionEnabled }, { "laserOnHurtEnabled", LaserOnHurtEnabled } }; return dictionary.WithMutator(MutatorName); } } public class HandleWithCareMutatorSettings : GenericMutatorSettings { private readonly ConfigEntry _valueMultiplier; private readonly ConfigEntry _instaDestroySurplus; private readonly ConfigEntry _multiplySurplus; public float ValueMultiplier => _valueMultiplier.Value; public bool InstantlyDestroySurplus => _instaDestroySurplus.Value; public bool MultiplySurplusValue => _multiplySurplus.Value; internal HandleWithCareMutatorSettings(string name, string description, ConfigFile config) : base(name, description, config) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown _valueMultiplier = config.Bind(GenericMutatorSettings.GetSection(name), "Value Multiplier", 2f, new ConfigDescription("The amount by which the value of valuables should be multiplier when " + name + " is active.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 10f), Array.Empty())); _instaDestroySurplus = config.Bind(GenericMutatorSettings.GetSection(name), "Instantly Destroy Surplus on Damage", false, "If true, while the " + name + " Mutator is active, the surplus will instantly be destroyed when taking any damage, just like other valuables."); _multiplySurplus = config.Bind(GenericMutatorSettings.GetSection(name), "Multiply Surplus Value", false, "If true, while the " + name + " Mutator is active, the surplus value will be multiplied, just like other valuables."); } } public class LessIsMoreMutatorSettings : GenericMutatorSettings { private readonly ConfigEntry _strongDivisionFactor; private readonly ConfigEntry _weakDivisionFactor; private readonly ConfigEntry _valueGainMultiplier; public float StrongDivisionFactor => _strongDivisionFactor.Value; public float WeakDivisionFactor => _weakDivisionFactor.Value; public float ValueGainMultiplier => _valueGainMultiplier.Value; internal LessIsMoreMutatorSettings(string name, string description, ConfigFile config) : base(name, description, config) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown _weakDivisionFactor = config.Bind(GenericMutatorSettings.GetSection(name), "Weak Durability Division Factor", 1f, new ConfigDescription("The amount by which the value of weak durability valuables should be divided when the " + name + " Mutator is active. Acts as an lower bound.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 5f), Array.Empty())); _strongDivisionFactor = config.Bind(GenericMutatorSettings.GetSection(name), "Strong Durability Division Factor", 2f, new ConfigDescription("The amount by which the value of strong durability valuables should be divided when the " + name + " Mutator is active. Acts as a upper bound.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 5f), Array.Empty())); _valueGainMultiplier = config.Bind(GenericMutatorSettings.GetSection(name), "Value Gain Multiplier", 2f, new ConfigDescription("The amount by which the normal value gain should be multiplied when the " + name + " Mutator is active.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 10f), Array.Empty())); } public override IDictionary? AsMetadata() { IDictionary dictionary = new Dictionary { { "ValueGainMultiplier", ValueGainMultiplier } }; return dictionary.WithMutator(MutatorName); } } public class NopMutatorSettings : AbstractMutatorSettings { private readonly ConfigEntry _weight; private readonly ConfigEntry _minimumLevel; private readonly ConfigEntry _maximumLevel; public override string MutatorName => "None"; public override string MutatorDescription => "A normal run, no special effects"; public override uint Weight => _weight.Value; public override uint MinimumLevel => _minimumLevel.Value; public override uint MaximumLevel => _maximumLevel.Value; internal NopMutatorSettings(ConfigFile config) { _weight = config.Bind("No Mutator", "Weight", (uint)((ulong)(global::Mutators.Mutators.Mutators.All().Length - 1) * 100uL), "Weighted chance for no mutator to be active."); _minimumLevel = config.Bind("No Mutator", "Minimum level", 0u, "The minimum level on which no mutator can show up"); _maximumLevel = config.Bind("No Mutator", "Maximum level", 1000u, "The maximum level on which no mutator can show up (0 = no upper bound)"); } } public class OneShotOneKillMutatorSettings : EnemyDisablingMutatorSettings { private readonly ConfigEntry _instaReviveInTruckOrExtraction; private readonly ConfigEntry _instaReviveHealth; public bool InstaReviveInTruckOrExtraction => _instaReviveInTruckOrExtraction.Value; public int InstaReviveHealth { get; private set; } internal OneShotOneKillMutatorSettings(string name, string description, ConfigFile config) : base(name, description, config, "Peeper") { _instaReviveInTruckOrExtraction = config.Bind(GenericMutatorSettings.GetSection(name), "Instant revive in truck or extraction", false, "If true, while the " + name + " Mutator is active, players are instantly revived with full head if their head is brought to the truck or an active extraction point."); _instaReviveHealth = config.Bind(GenericMutatorSettings.GetSection(name), "Instant revive health", 0u, "The amount of health the player should be revived with when Instant revive is enabled. (0 = Revive with max health)"); Cache(); } private void Cache() { InstaReviveHealth = (int)Math.Clamp(_instaReviveHealth.Value, 0u, 2147483647u); } } public class OutWithABangMutatorSettings : GenericMutatorSettings { public const string Tier1Radius = "OutWithABang-Radius1"; public const string Tier1Damage = "OutWithABang-Damage1"; public const string Tier2Radius = "OutWithABang-Radius2"; public const string Tier2Damage = "OutWithABang-Damage2"; public const string Tier3Radius = "OutWithABang-Radius3"; public const string Tier3Damage = "OutWithABang-Damage3"; private readonly ConfigEntry _tier1ExplosionRadius; private readonly ConfigEntry _tier1ExplosionDamage; private readonly ConfigEntry _tier2ExplosionRadius; private readonly ConfigEntry _tier2ExplosionDamage; private readonly ConfigEntry _tier3ExplosionRadius; private readonly ConfigEntry _tier3ExplosionDamage; public float Tier1ExplosionRadius => _tier1ExplosionRadius.Value; public int Tier1ExplosionDamage => _tier1ExplosionDamage.Value; public float Tier2ExplosionRadius => _tier2ExplosionRadius.Value; public int Tier2ExplosionDamage => _tier2ExplosionDamage.Value; public float Tier3ExplosionRadius => _tier3ExplosionRadius.Value; public int Tier3ExplosionDamage => _tier3ExplosionDamage.Value; internal OutWithABangMutatorSettings(string name, string description, ConfigFile config) : base(name, description, config) { _tier1ExplosionRadius = config.Bind(GenericMutatorSettings.GetSection(name), "Tier 1 Enemy Explosion Radius", 1f, "The on-death explosion radius of Tier 1 enemies during the " + name + " Mutator."); _tier1ExplosionDamage = config.Bind(GenericMutatorSettings.GetSection(name), "Tier 1 Enemy Explosion Damage", 50, "The on-death explosion damage of Tier 1 enemies during the " + name + " Mutator."); _tier2ExplosionRadius = config.Bind(GenericMutatorSettings.GetSection(name), "Tier 2 Enemy Explosion Radius", 2f, "The on-death explosion radius of Tier 2 enemies during the " + name + " Mutator."); _tier2ExplosionDamage = config.Bind(GenericMutatorSettings.GetSection(name), "Tier 2 Enemy Explosion Damage", 100, "The on-death explosion damage of Tier 2 enemies during the " + name + " Mutator."); _tier3ExplosionRadius = config.Bind(GenericMutatorSettings.GetSection(name), "Tier 3 Enemy Explosion Radius", 3f, "The on-death explosion radius of Tier 3 enemies during the " + name + " Mutator."); _tier3ExplosionDamage = config.Bind(GenericMutatorSettings.GetSection(name), "Tier 3 Enemy Explosion Damage", 200, "The on-death explosion damage of Tier 3 enemies during the " + name + " Mutator."); } public override IDictionary? AsMetadata() { IDictionary dictionary = new Dictionary { { "OutWithABang-Radius1", Tier1ExplosionRadius }, { "OutWithABang-Damage1", Tier1ExplosionDamage }, { "OutWithABang-Radius2", Tier2ExplosionRadius }, { "OutWithABang-Damage2", Tier2ExplosionDamage }, { "OutWithABang-Radius3", Tier3ExplosionRadius }, { "OutWithABang-Damage3", Tier3ExplosionDamage } }; return dictionary.WithMutator(MutatorName); } } public class ProtectThePresidentMutatorSettings : GenericMutatorSettings { private readonly ConfigEntry _minimumPlayerCount; public byte MinimumPlayerCount => _minimumPlayerCount.Value; internal ProtectThePresidentMutatorSettings(string name, string description, ConfigFile config) : base(name, description, config) { _minimumPlayerCount = config.Bind(GenericMutatorSettings.GetSection(name), "Minimum player amount requirement", (byte)3, "The minimum amount of players required for the " + name + " Mutator to be available for selection."); } public override bool IsEligibleForSelection() { if (base.IsEligibleForSelection()) { Room currentRoom = PhotonNetwork.CurrentRoom; if (currentRoom != null) { return currentRoom.PlayerCount >= MinimumPlayerCount; } return false; } return false; } } public class ProtectTheWeakMutatorSettings : GenericMutatorSettings { private readonly ConfigEntry _minimumPlayerCount; public byte MinimumPlayerCount => _minimumPlayerCount.Value; internal ProtectTheWeakMutatorSettings(string name, string description, ConfigFile config) : base(name, description, config) { _minimumPlayerCount = config.Bind(GenericMutatorSettings.GetSection(name), "Minimum player amount requirement", (byte)3, "The minimum amount of players required for the " + name + " Mutator to be available for selection."); } public override bool IsEligibleForSelection() { if (base.IsEligibleForSelection()) { Room currentRoom = PhotonNetwork.CurrentRoom; if (currentRoom != null) { return currentRoom.PlayerCount >= MinimumPlayerCount; } return false; } return false; } } public class SealedAwayMutatorSettings : EnemyDisablingMutatorSettings { private readonly ConfigEntry _maximumMonsterSpawns; private readonly ConfigEntry _monsterSpawnChance; public int MaximumMonsterSpawns => _maximumMonsterSpawns.Value; public float MonsterSpawnChance => _monsterSpawnChance.Value; internal SealedAwayMutatorSettings(string name, string description, ConfigFile config) : base(name, description, config, "Voodoo", "Shadow Child") { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown _maximumMonsterSpawns = config.Bind(GenericMutatorSettings.GetSection(name), "Maximum monster spawns", 5, new ConfigDescription("Maximum amount of extra monsters that can be spawned by the " + name + " Mutator per level.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 15), Array.Empty())); _monsterSpawnChance = config.Bind(GenericMutatorSettings.GetSection(name), "Monster spawn chance", 10f, new ConfigDescription("The chance that a monster is spawned when breaking a valuable when the " + name + " Mutator is active.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 100f), Array.Empty())); } } public class TheFloorIsLavaMutatorSettings : GenericMutatorSettings, ILevelRemovingMutatorSettings { private readonly ConfigEntry _usePercentageDamage; private readonly ConfigEntry _allowCustomLevels; private readonly ConfigEntry _disableEnemies; private readonly ConfigEntry _reviveImmunityDuration; public int DamagePerTick { get; private set; } public int ImmunePlayerCount { get; private set; } public bool UsePercentageDamage => _usePercentageDamage.Value; public bool AllowCustomLevels => _allowCustomLevels.Value; public bool DisableEnemies => _disableEnemies.Value; public float ReviveImmunityDuration => _reviveImmunityDuration.Value; public IList ExcludedLevels => new List(); internal TheFloorIsLavaMutatorSettings(string name, string description, ConfigFile config) : base(name, description, config) { ConfigEntry val = config.Bind(GenericMutatorSettings.GetSection(name), "Damage", 1, "The amount of damage that players receive per second when standing on floor tiles."); _usePercentageDamage = config.Bind(GenericMutatorSettings.GetSection(name), "Use percentage damage", false, "If true, players will receive percentage max health damage instead of a flat amount."); ConfigEntry val2 = config.Bind(GenericMutatorSettings.GetSection(name), "Immune player count", 0, "The amount of players that are immune to " + name + " damage."); _allowCustomLevels = config.Bind(GenericMutatorSettings.GetSection(name), "Allow custom levels", true, "If false, custom levels cannot be picked while the " + name + " Mutator is active."); _disableEnemies = config.Bind(GenericMutatorSettings.GetSection(name), "Disable enemies", false, "If true, no enemies will spawn while the " + name + " Mutator is active."); _disableEnemies = config.Bind(GenericMutatorSettings.GetSection(name), "Disable enemies", false, "If true, no enemies will spawn while the " + name + " Mutator is active."); _reviveImmunityDuration = config.Bind(GenericMutatorSettings.GetSection(name), "Revive immunity duration", 20f, "The time in seconds for which players are immune to lava damage after reviving while the " + name + " Mutator is active."); DamagePerTick = Math.Clamp(val.Value, 1, int.MaxValue); ImmunePlayerCount = Math.Clamp(val2.Value, 0, int.MaxValue); } public override IDictionary? AsMetadata() { IDictionary dictionary = new Dictionary { { "damage", DamagePerTick }, { "usePercentageDamage", UsePercentageDamage }, { "reviveImmunityDuration", ReviveImmunityDuration } }; return dictionary.WithMutator(MutatorName); } } public class ThereCanOnlyBeOneMutatorSettings : EnemyDisablingMutatorSettings { private readonly ConfigEntry _groupSpawnsThreshold; public uint GroupSpawnsThreshold => _groupSpawnsThreshold.Value; internal ThereCanOnlyBeOneMutatorSettings(string name, string description, ConfigFile config) : base(name, description, config) { _groupSpawnsThreshold = config.Bind(GenericMutatorSettings.GetSection(name), "Group spawn minimum level", 8u, "The minimum level from which enemy groups (e.g. 3 mentalists or 10 gnomes) can be spawned by the " + name + " Mutator."); } } public class UltraViolenceMutatorSettings : EnemyDisablingMutatorSettings { private ConfigEntry _keepOnLight; private readonly ConfigEntry _minimumPlayerCount; public bool KeepOnLight => _keepOnLight.Value; public byte MinimumPlayerCount => _minimumPlayerCount.Value; internal UltraViolenceMutatorSettings(string name, string description, ConfigFile config) : base(name, description, config) { _keepOnLight = config.Bind(GenericMutatorSettings.GetSection(name), "Keep on lights", false, "Keep on the level lighting while the " + name + " Mutator is active."); _minimumPlayerCount = config.Bind(GenericMutatorSettings.GetSection(name), "Minimum player amount requirement", (byte)0, "The minimum amount of players required for the " + name + " Mutator to be available for selection."); } public override bool IsEligibleForSelection() { if (base.IsEligibleForSelection()) { Room currentRoom = PhotonNetwork.CurrentRoom; if (currentRoom != null) { return currentRoom.PlayerCount >= MinimumPlayerCount; } return false; } return false; } public override IDictionary? AsMetadata() { IDictionary dictionary = new Dictionary { { "keepLightsOn", KeepOnLight } }; return dictionary.WithMutator(MutatorName); } } public class VoiceoverMutatorSettings : GenericMutatorSettings { private readonly ConfigEntry _minimumPlayerCount; public byte MinimumPlayerCount => _minimumPlayerCount.Value; internal VoiceoverMutatorSettings(string name, string description, ConfigFile config) : base(name, description, config) { _minimumPlayerCount = config.Bind(GenericMutatorSettings.GetSection(name), "Minimum player amount requirement", (byte)3, "The minimum amount of players required for the " + name + " Mutator to be available for selection."); } public override bool IsEligibleForSelection() { if (base.IsEligibleForSelection()) { Room currentRoom = PhotonNetwork.CurrentRoom; if (currentRoom != null) { return currentRoom.PlayerCount >= MinimumPlayerCount; } return false; } return false; } } } namespace Mutators.Patches { [HarmonyPatch(typeof(EnemyDirector))] internal class EnemyDirectorPatch { private static List _startingEnemyList = new List(); private static bool _isListSet; [HarmonyPrefix] [HarmonyPriority(600)] [HarmonyPatch("GetEnemy")] private static void EnemyDirectorGetEnemyPrefix(ref List ___enemyList, int ___enemyListIndex) { if (!SemiFunc.IsMultiplayer() || !SemiFunc.IsNotMasterClient()) { ___enemyList.RemoveAll((EnemySetup x) => (Object)(object)x == (Object)null); if (!_isListSet) { _startingEnemyList = new List(___enemyList); _isListSet = true; } if (___enemyList.Count == 0) { EnemySetup val = ScriptableObject.CreateInstance(); val.spawnObjects = new List(); ___enemyList.Add(val); } while (___enemyList.Count < ___enemyListIndex + 1) { int index = Random.Range(0, _startingEnemyList.Count); ___enemyList.Add(___enemyList[index]); } } } } [HarmonyPatch(typeof(HealthUI))] public class HealthUIPatch { [HarmonyPostfix] [HarmonyPriority(600)] [HarmonyPatch("Start")] private static void HealthUIStartPostfix() { if (SemiFunc.IsMasterClientOrSingleplayer() && MutatorManager.Instance.CurrentMutator.Settings is ILevelRemovingMutatorSettings settings) { settings.RemoveLevels(); } } } [HarmonyPatch(typeof(LevelGenerator))] internal class LevelGeneratorPatch { [HarmonyPrefix] [HarmonyPriority(800)] [HarmonyPatch("GenerateDone")] private static void LevelGeneratorGenerateDonePrefix() { if (SemiFunc.RunIsLevel()) { MutatorManager.Instance.GameState = MutatorsGameState.LevelReady; } } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch("GenerateDone")] private static void LevelGeneratorGenerateDonePostfix() { if (SemiFunc.RunIsLevel()) { MutatorManager.Instance.GameState = MutatorsGameState.LevelGenerated; } } } [HarmonyPatch(typeof(LoadingUI))] internal class LoadingUIPatch { [HarmonyPostfix] [HarmonyPriority(800)] [HarmonyPatch("StopLoading")] private static void LoadingUIStopLoadingPostfix() { if (SemiFunc.RunIsLevel()) { GameObject hud = GameObject.Find("Game Hud"); GameObject health = GameObject.Find("Health"); CreateMutatorText(hud, health); CreateMutatorDescriptionText(hud, health); CreateTargetPlayerText(hud, health); IMutator currentMutator = MutatorManager.Instance.CurrentMutator; if (currentMutator != null && currentMutator.HasSpecialAction) { GameObject energy = GameObject.Find("Energy"); CreateSpecialActionText(hud, health, energy); } } } private static void CreateMutatorText(GameObject hud, GameObject health) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0055: 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) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Mutator"); val.transform.SetParent(hud.transform, false); TextMeshProUGUI val2 = val.AddComponent(); TextMeshProUGUI component = health.GetComponent(); ((TMP_Text)val2).font = ((TMP_Text)component).font; ((TMP_Text)val2).fontMaterial = ((TMP_Text)component).fontMaterial; RectTransform component2 = val.GetComponent(); component2.sizeDelta = new Vector2(200f, 50f); component2.anchorMin = new Vector2(1f, 1f); component2.anchorMax = new Vector2(1f, 1f); component2.pivot = new Vector2(1f, 1f); component2.anchoredPosition = new Vector2(0f, RepoMutators.Settings.MutatorDisplayY); ((TMP_Text)val2).alignment = (TextAlignmentOptions)516; val.AddComponent(); ((TMP_Text)val2).text = MutatorManager.Instance.CurrentMutator.Name; ((TMP_Text)val2).fontSize = RepoMutators.Settings.MutatorDisplaySize; ((Behaviour)val2).enabled = true; } private static void CreateMutatorDescriptionText(GameObject hud, GameObject health) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0055: 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) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Mutator Description"); val.transform.SetParent(hud.transform, false); TextMeshProUGUI val2 = val.AddComponent(); TextMeshProUGUI component = health.GetComponent(); ((TMP_Text)val2).font = ((TMP_Text)component).font; ((TMP_Text)val2).fontMaterial = ((TMP_Text)component).fontMaterial; RectTransform component2 = val.GetComponent(); component2.sizeDelta = new Vector2(300f, 100f); component2.anchorMin = new Vector2(1f, 1f); component2.anchorMax = new Vector2(1f, 1f); component2.pivot = new Vector2(1f, 1f); component2.anchoredPosition = new Vector2(0f, RepoMutators.Settings.MutatorDescriptionDisplayY); ((TMP_Text)val2).alignment = (TextAlignmentOptions)516; ((TMP_Text)val2).verticalAlignment = (VerticalAlignmentOptions)256; val.AddComponent(); ((TMP_Text)val2).text = string.Empty; ((TMP_Text)val2).lineSpacing = -50f; ((TMP_Text)val2).fontSize = RepoMutators.Settings.MutatorDescriptionDisplaySize; ((Behaviour)val2).enabled = true; } private static void CreateTargetPlayerText(GameObject hud, GameObject health) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_00a0: 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) GameObject val = new GameObject("ChosenPlayerTarget"); val.transform.SetParent(hud.transform, false); TextMeshProUGUI val2 = val.AddComponent(); TextMeshProUGUI component = health.GetComponent(); ((TMP_Text)val2).font = ((TMP_Text)component).font; ((TMP_Text)val2).fontMaterial = ((TMP_Text)component).fontMaterial; ((Graphic)val2).color = ((Graphic)component).color; RectTransform component2 = val.GetComponent(); component2.sizeDelta = new Vector2(300f, 50f); component2.anchorMin = new Vector2(0.5f, 1f); component2.anchorMax = new Vector2(0.5f, 1f); component2.pivot = new Vector2(0.5f, 1f); component2.anchoredPosition = new Vector2(0f, 10f); ((TMP_Text)val2).alignment = (TextAlignmentOptions)4098; val.AddComponent(); ((TMP_Text)val2).text = string.Empty; ((TMP_Text)val2).fontSize = RepoMutators.Settings.TargetDisplaySize; ((Behaviour)val2).enabled = true; } private static void CreateSpecialActionText(GameObject hud, GameObject health, GameObject energy) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("SpecialAction"); val.transform.SetParent(hud.transform, false); TextMeshProUGUI val2 = val.AddComponent(); Zap(val, energy); GameObject val3 = new GameObject("SpecialActionMax"); val3.transform.SetParent(val.transform, false); TextMeshProUGUI val4 = val3.AddComponent(); TextMeshProUGUI component = health.GetComponent(); ((TMP_Text)val2).font = ((TMP_Text)component).font; ((TMP_Text)val2).fontWeight = ((TMP_Text)component).fontWeight; ((TMP_Text)val2).fontMaterial = ((TMP_Text)component).fontMaterial; ((Graphic)val2).color = Color.red; RectTransform component2 = val.GetComponent(); component2.sizeDelta = new Vector2(120f, 50f); component2.anchorMin = new Vector2(0f, 1f); component2.anchorMax = new Vector2(0f, 1f); component2.pivot = new Vector2(0f, 1f); component2.anchoredPosition = new Vector2(29f, RepoMutators.Settings.SpecialActionY); ((TMP_Text)val2).alignment = (TextAlignmentOptions)513; ((TMP_Text)val2).text = string.Empty; ((TMP_Text)val2).fontStyle = (FontStyles)1; ((TMP_Text)val2).fontSize = 40f; ((Behaviour)val2).enabled = true; ((TMP_Text)val4).font = ((TMP_Text)component).font; ((TMP_Text)val4).fontMaterial = ((TMP_Text)component).fontMaterial; ((Graphic)val4).color = Color.red; RectTransform component3 = val3.GetComponent(); component3.sizeDelta = new Vector2(120f, 50f); component3.anchorMin = new Vector2(0f, 1f); component3.anchorMax = new Vector2(0f, 1f); component3.pivot = new Vector2(0f, 1f); component3.anchoredPosition = new Vector2(45f, 5f); ((TMP_Text)val4).alignment = (TextAlignmentOptions)513; val.AddComponent(); ((TMP_Text)val4).text = string.Empty; ((TMP_Text)val4).fontSize = 20f; ((Behaviour)val4).enabled = true; } private static void Zap(GameObject specialActionObject, GameObject energy) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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) GameObject val = new GameObject("SpecialActionZap"); val.transform.SetParent(specialActionObject.transform, false); Image component = ((Component)energy.transform.Find("Zap")).GetComponent(); Image val2 = val.AddComponent(); val2.sprite = component.sprite; ((Graphic)val2).color = Color.red; RectTransform component2 = val.GetComponent(); component2.sizeDelta = new Vector2(25f, 25f); component2.anchoredPosition = new Vector2(-75f, 0f); } } [HarmonyPatch(typeof(MapToolController))] internal class MapToolControllerPatch { [HarmonyPostfix] [HarmonyPatch("Update")] private static void Postfix(MapToolController __instance) { MutatorDescriptionAnnouncingBehaviour instance = MutatorDescriptionAnnouncingBehaviour.Instance; if (Object.op_Implicit((Object)(object)instance) && __instance.Active && RepoMutators.Settings.MutatorDescriptionInMapTool && (Object)(object)__instance.PlayerAvatar == (Object)(object)PlayerAvatar.instance) { ((SemiUI)instance).Show(); } if (RepoMutators.Settings.MutatorDisplayToggleType == ModSettings.MutatorNameToggleType.WithDescription) { MutatorAnnouncingBehaviour instance2 = MutatorAnnouncingBehaviour.instance; if (Object.op_Implicit((Object)(object)instance2) && __instance.Active && RepoMutators.Settings.MutatorDescriptionInMapTool && (Object)(object)__instance.PlayerAvatar == (Object)(object)PlayerAvatar.instance) { ((SemiUI)instance2).Show(); } } } } [HarmonyPatch(typeof(MenuManager))] internal class MenuManagerPatch { [HarmonyPostfix] [HarmonyPriority(600)] [HarmonyPatch("PageOpen")] private static void PageOpenPostfix(MenuPageIndex menuPageIndex) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_002a: Unknown result type (might be due to invalid IL or missing references) if ((int)menuPageIndex == 8 && SemiFunc.IsMasterClient() && MutatorManager.Instance.CurrentMutator.Settings is ILevelRemovingMutatorSettings settings) { settings.RemoveLevels(lobbyMenu: true); } if ((int)menuPageIndex == 0) { LevelManager.Instance.RestoreLevels(); } } } [HarmonyPatch(typeof(MenuPage))] internal class MenuPagePatch { [HarmonyPostfix] [HarmonyPatch("LockAndHide")] private static void MenuPageLockAndHidePostfix() { MutatorAnnouncingBehaviour instance = MutatorAnnouncingBehaviour.instance; MutatorDescriptionAnnouncingBehaviour instance2 = MutatorDescriptionAnnouncingBehaviour.Instance; TargetPlayerAnnouncingBehaviour instance3 = TargetPlayerAnnouncingBehaviour.instance; SpecialActionAnnouncingBehaviour instance4 = SpecialActionAnnouncingBehaviour.instance; if (Object.op_Implicit((Object)(object)instance)) { ((SemiUI)instance).Hide(); } if (Object.op_Implicit((Object)(object)instance2)) { ((SemiUI)instance2).Hide(); } if (Object.op_Implicit((Object)(object)instance3)) { ((SemiUI)instance3).Hide(); } if (Object.op_Implicit((Object)(object)instance4)) { ((SemiUI)instance4).Hide(); } } } [HarmonyPatch(typeof(RunManager))] internal class RunManagerPatch { [HarmonyPostfix] [HarmonyPatch("ChangeLevel")] private static void RunManagerChangeLevelPostfix() { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) if (SemiFunc.IsMultiplayer() && SemiFunc.IsNotMasterClient()) { return; } RepoMutators.Logger.LogDebug((object)"RunManagerPatch Host only"); if (!SemiFunc.IsMultiplayer() && !SemiFunc.RunIsLobbyMenu() && (Object)(object)MutatorsNetworkManager.Instance == (Object)null) { RepoMutators.Logger.LogDebug((object)"Spawning singleplayer NetworkManager"); string text = "Xepos.REPO-Mutators/MutatorsNetworkManager"; PrefabRef val = default(PrefabRef); if (!NetworkPrefabs.TryGetNetworkPrefabRef(text, ref val)) { throw new Exception("Unable to establish Mutators NetworkManager: Could not find PrefabRef with id: " + text); } GameObject val2 = NetworkPrefabs.SpawnNetworkPrefab(val, Vector3.zero, Quaternion.identity, (byte)0, (object[])null); if (val2 != null) { val2.SetActive(true); } GetAndSendMutator(); } ApplyPatch(); } [HarmonyPostfix] [HarmonyPatch("UpdateLevel")] private static void RunManagerUpdateLevelPostfix() { if (!SemiFunc.IsMasterClientOrSingleplayer()) { RepoMutators.Logger.LogDebug((object)"RunManagerPatch Client only"); ApplyPatch(); } } private static void ApplyPatch() { MutatorManager instance = MutatorManager.Instance; if (IsInShop()) { instance.GameState = MutatorsGameState.Shop; if (SemiFunc.IsMasterClientOrSingleplayer()) { MutatorsNetworkManager.Instance.ClearBufferedRPCs(); GetAndSendMutator(); } } else if (SemiFunc.RunIsLevel()) { RepoMutators.Logger.LogDebug((object)("Applying patch now for mutator: " + instance.CurrentMutator.Name)); instance.CurrentMutator.Patch(); } else { instance.GameState = MutatorsGameState.None; if (SemiFunc.RunIsArena()) { instance.SetActiveMutator("None"); } } } private static void GetAndSendMutator() { IMutator weightedMutator = MutatorManager.Instance.GetWeightedMutator(); MutatorsNetworkManager.Instance.SendActiveMutator(weightedMutator.Name, weightedMutator.Settings.AsMetadata()); } private static bool IsInShop() { RunManager runManager = RunManager.instance; return runManager.levelShop.Any((Level level) => ((Object)level).name == ((Object)runManager.levelCurrent).name); } } [HarmonyPatch(typeof(SemiFunc))] internal class SemiFuncPatch { [HarmonyPostfix] [HarmonyPriority(800)] [HarmonyPatch("OnSceneSwitch")] private static void SemiFuncOnSceneSwitchPostfix(bool _gameOver, bool _leaveGame) { if (_leaveGame) { MutatorManager instance = MutatorManager.Instance; instance.GameState = MutatorsGameState.None; instance.SetActiveMutator("None"); } } } [HarmonyPatch(typeof(SpectateCamera))] internal class SpectateCameraPatch { [HarmonyPostfix] [HarmonyPatch("LateUpdate")] private static void SpectateCameraLateUpdatePostfix() { SpecialActionAnnouncingBehaviour instance = SpecialActionAnnouncingBehaviour.instance; if (Object.op_Implicit((Object)(object)instance)) { ((SemiUI)instance).Hide(); } } } } namespace Mutators.Network { internal class MutatorsNetworkManager : MonoBehaviourPunCallbacks { [CompilerGenerated] private sealed class d__26 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public MutatorsNetworkManager <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__26(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown int num = <>1__state; MutatorsNetworkManager mutatorsNetworkManager = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if ((Object)(object)mutatorsNetworkManager._photonView == (Object)null) { <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 1; return true; } mutatorsNetworkManager._photonView.RPC("CompareModVersion", (RpcTarget)2, new object[1] { "0.6.5" }); 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(); } } [CompilerGenerated] private sealed class d__7 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public MutatorsNetworkManager <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown int num = <>1__state; MutatorsNetworkManager mutatorsNetworkManager = <>4__this; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; RepoMutators.Logger.LogInfo((object)$"ViewID - {mutatorsNetworkManager._photonView.ViewID}"); } else { <>1__state = -1; } <>2__current = (object)new WaitForSeconds(3f); <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private PhotonView _photonView; private readonly bool _debug; internal static MutatorsNetworkManager Instance { get; private set; } private void Awake() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) Instance = this; ((Component)this).transform.parent = ((Component)StatsManager.instance).transform; ((Object)((Component)this).gameObject).name = "MutatorsNetworkManager"; GameObject gameObject = ((Component)this).gameObject; ((Object)gameObject).hideFlags = (HideFlags)(((Object)gameObject).hideFlags & -62); _photonView = ((Component)this).GetComponent(); if (_debug) { Run(PrintViewId()); } } [IteratorStateMachine(typeof(d__7))] private IEnumerator PrintViewId() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__7(0) { <>4__this = this }; } internal void ClearBufferedRPCs() { if (_photonView.IsMine) { PhotonNetwork.RemoveBufferedRPCs(_photonView.ViewID, (string)null, (int[])null); } } public void SendMetadata(IDictionary metadata) { Send(metadata.ToPhotonHashtable(), SetMetadata, (RpcTarget)4); } public void SendActiveMutator(string name, IDictionary? metadata = null) { if (SemiFunc.IsMasterClientOrSingleplayer()) { Hashtable value = metadata?.ToPhotonHashtable(); Send(name, value, SetActiveMutator, (RpcTarget)4); } } public void SendComponentForViews(int[] views, Type componentType) { Send(views, componentType.FullName, AddComponentToViewGameObject, (RpcTarget)4); } internal void SendScaleChange(int photonViewId, float scale, bool buffered = true) { Send(photonViewId, scale, SetScale, (RpcTarget)((!buffered) ? 1 : 4)); } public void SendMetaToHost(string sender, IDictionary meta) { Hashtable val = meta.ToPhotonHashtable(); if (SemiFunc.IsMultiplayer() && !SemiFunc.IsMasterClient()) { _photonView.RPC("SetClientMetadata", (RpcTarget)2, new object[2] { sender, val }); } } [PunRPC] public void AddComponentToViewGameObject(int[] views, string componentType) { Type type = Type.GetType(componentType); if (type == null) { RepoMutators.Logger.LogError((object)("Failed to resolve type: " + componentType)); return; } foreach (int num in views) { PhotonView val = PhotonView.Find(num); if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)((Component)val).gameObject)) { ((Component)val).gameObject.AddComponent(type); } } } [PunRPC] public void SetActiveMutator(string name, Hashtable? hashtable) { MutatorManager instance = MutatorManager.Instance; bool flag = SemiFunc.RunIsLevel(); RepoMutators.Logger.LogDebug((object)("Set mutator to " + name + ", applying patch " + (flag ? "now" : "later"))); instance.SetActiveMutator(name, flag); IDictionary dictionary; if (hashtable != null) { dictionary = hashtable.FromPhotonHashtable(); } else { IDictionary dictionary2 = new Dictionary(); dictionary = dictionary2; } IDictionary dictionary3 = dictionary; if (dictionary3.TryGetValue(MutatorSettings.TheFloorIsLava.MutatorName, out var value) && value is IDictionary source) { RepoMutators.Logger.LogDebug((object)("[RPC] Received metadata: " + string.Join(", ", source.Select((KeyValuePair kvp) => $"{kvp.Key}: {kvp.Value}")))); } else { RepoMutators.Logger.LogDebug((object)("[RPC] Received metadata: " + string.Join(", ", dictionary3.Select((KeyValuePair kvp) => $"{kvp.Key}: {kvp.Value}")))); } instance.CurrentMutator.ConsumeMetadata(dictionary3); } [PunRPC] public void SetMetadata(Hashtable hashtable) { MutatorManager instance = MutatorManager.Instance; IDictionary dictionary = hashtable.FromPhotonHashtable(); if (dictionary.TryGetValue(MutatorSettings.TheFloorIsLava.MutatorName, out var value) && value is IDictionary source) { RepoMutators.Logger.LogDebug((object)("[RPC] Received metadata: " + string.Join(", ", source.Select((KeyValuePair kvp) => $"{kvp.Key}: {kvp.Value}")))); } else { RepoMutators.Logger.LogDebug((object)("[RPC] Received metadata: " + string.Join(", ", dictionary.Select((KeyValuePair kvp) => $"{kvp.Key}: {kvp.Value}")))); } instance.CurrentMutator.ConsumeMetadata(dictionary); } [PunRPC] public void SetClientMetadata(string steamId, Hashtable hashtable) { MutatorManager instance = MutatorManager.Instance; IDictionary value = hashtable.FromPhotonHashtable(); IDictionary value2 = new Dictionary { { steamId, value } }; IDictionary metadata = new Dictionary { { "clients", value2 } }; instance.CurrentMutator.ConsumeMetadata(metadata); } [PunRPC] public void SetScale(int viewId, float scale) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) PhotonView val = PhotonView.Find(viewId); if ((Object)(object)val != (Object)null) { ((Component)val).transform.localScale = new Vector3(scale, scale, scale); } } [PunRPC] public void SendModVersion() { ((MonoBehaviour)this).StartCoroutine(ComparedModVersionCoroutine()); } [PunRPC] public void CompareModVersion(string version, PhotonMessageInfo info) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (version == "0.6.5") { RepoMutators.Logger.LogInfo((object)(info.Sender.NickName + " is on the same version!")); } else { HandleVersionMismatch(version, info.Sender.NickName); } } public override void OnPlayerEnteredRoom(Player newPlayer) { if (_photonView.IsMine) { _photonView.RPC("SendModVersion", newPlayer, Array.Empty()); } } private void HandleVersionMismatch(string version, string playerName) { string[] array = version.Split('.'); string[] array2 = "0.6.5".Split('.'); if (array[0] != array2[0] || array[1] != array2[1]) { RepoMutators.Logger.LogError((object)(playerName + " is on version " + version + ", which doesn't match the host version!")); } else if (array[2] != array2[2]) { RepoMutators.Logger.LogWarning((object)(playerName + " is on version " + version + ", which doesn't match the host version!")); } } private bool ValidateClientMeta(IDictionary clientMeta, IDictionary allowedMeta) { foreach (KeyValuePair clientMetum in clientMeta) { if (!allowedMeta.TryGetValue(clientMetum.Key, out IAllowedClientMeta value)) { return false; } if (value.HasNested()) { if (!(clientMetum.Value is IDictionary clientMeta2)) { return false; } if (!ValidateClientMeta(clientMeta2, value.NestedMeta)) { return false; } } } return true; } private void Send(T data, Action rpcMethod, RpcTarget rpcTarget) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (SemiFunc.IsMultiplayer()) { if (SemiFunc.IsMasterClient()) { _photonView.RPC(rpcMethod.Method.Name, rpcTarget, new object[1] { data }); rpcMethod(data); } } else { rpcMethod(data); } } private void Send(T data, D value, Action rpcMethod, RpcTarget rpcTarget) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (SemiFunc.IsMultiplayer()) { if (SemiFunc.IsMasterClient()) { _photonView.RPC(rpcMethod.Method.Name, rpcTarget, new object[2] { data, value }); rpcMethod(data, value); } } else { rpcMethod(data, value); } } [IteratorStateMachine(typeof(d__26))] private IEnumerator ComparedModVersionCoroutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__26(0) { <>4__this = this }; } internal void Run(IEnumerator coroutine) { ((MonoBehaviour)this).StartCoroutine(coroutine); } } } namespace Mutators.Network.Meta { public class AllowedClientMeta : IAllowedClientMeta { public bool PurgeAfterAccepting { get; private set; } public IDictionary NestedMeta { get; private set; } public AllowedClientMeta(IDictionary meta, bool purgeAfterAccepting = false) { PurgeAfterAccepting = purgeAfterAccepting; NestedMeta = meta; } public AllowedClientMeta(bool purgeAfterAccepting = false) { PurgeAfterAccepting = purgeAfterAccepting; NestedMeta = new Dictionary(); } } public interface IAllowedClientMeta { bool PurgeAfterAccepting { get; } IDictionary NestedMeta { get; } bool HasNested() { if (NestedMeta != null) { return NestedMeta.Count > 0; } return false; } } } namespace Mutators.Mutators { public interface IMutator { string Name { get; } string Description { get; } bool Active { get; } bool HasSpecialAction { get; } AbstractMutatorSettings Settings { get; } IReadOnlyList Patches { get; } IReadOnlyList> Conditions { get; } void Patch(); void Unpatch(); void ConsumeMetadata(IDictionary metadata); } public class Mutator : IMutator { private readonly Harmony _harmony; private readonly IList _patches; private readonly IList> _conditions; private readonly IDictionary _pendingDeferredMetadata = new Dictionary(); private IDictionary _metadata; private readonly IList _beforePatchAllHooks = new List(); private readonly IList _afterPatchAllHooks = new List(); private readonly IList>> _onMetadataChangedHooks = new List>>(); private readonly IList _beforeUnpatchAllHooks = new List(); private readonly IList _afterUnpatchAllHooks = new List(); public string Name => Settings.MutatorName; public string Description => Settings.MutatorDescription; public IReadOnlyDictionary Metadata => new ReadOnlyDictionary(_metadata); public bool Active { get; private set; } public bool HasSpecialAction { get; private set; } public AbstractMutatorSettings Settings { get; private set; } public IReadOnlyList> Conditions => new ReadOnlyCollection>(_conditions); public IReadOnlyList Patches => new ReadOnlyCollection(_patches); public Mutator(AbstractMutatorSettings settings, IList patches, IList> conditions = null, bool specialActionOverlay = false) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown Settings = settings; _harmony = new Harmony("Xepos.REPO-Mutators-" + settings.MutatorName); _patches = patches ?? new List(); _conditions = conditions ?? new List>(); _metadata = new Dictionary(); HasSpecialAction = specialActionOverlay; foreach (Type patch in _patches) { TryAddHook(patch, "BeforePatchAll", _beforePatchAllHooks); TryAddHook(patch, "AfterPatchAll", _afterPatchAllHooks); TryAddHook(patch, "BeforeUnpatchAll", _beforeUnpatchAllHooks); TryAddHook(patch, "AfterUnpatchAll", _afterUnpatchAllHooks); TryAddMetadataHook(patch); } } public Mutator(AbstractMutatorSettings settings, Type patch, IList> conditions = null, bool specialActionOverlay = false) : this(settings, new List(1) { patch }, conditions, specialActionOverlay) { } public void Patch() { RepoMutators.Logger.LogDebug((object)$"{Name} active: {Active}"); if (Active) { return; } RepoMutators.Logger.LogDebug((object)$"About to apply {_patches.Count} patches for {Name}"); Active = true; MutatorManager instance = MutatorManager.Instance; instance.GameStateChanged = (Action)Delegate.Combine(instance.GameStateChanged, new Action(TryApplyDeferredMetadata)); LinqExtensions.ForEach((IEnumerable)_beforePatchAllHooks, (Action)delegate(Action action) { action?.Invoke(); }); foreach (Type patch in _patches) { _harmony.PatchAll(patch); RepoMutators.Logger.LogDebug((object)("Applied patch: " + patch.Name)); } LinqExtensions.ForEach((IEnumerable)_afterPatchAllHooks, (Action)delegate(Action action) { action?.Invoke(); }); } public void Unpatch() { if (Active) { MutatorManager instance = MutatorManager.Instance; instance.GameStateChanged = (Action)Delegate.Remove(instance.GameStateChanged, new Action(TryApplyDeferredMetadata)); _metadata.Clear(); _pendingDeferredMetadata.Clear(); LinqExtensions.ForEach((IEnumerable)_beforeUnpatchAllHooks, (Action)delegate(Action action) { action?.Invoke(); }); _harmony.UnpatchSelf(); Active = false; LinqExtensions.ForEach((IEnumerable)_afterUnpatchAllHooks, (Action)delegate(Action action) { action?.Invoke(); }); RepoMutators.Logger.LogDebug((object)("Unpatched mutator: " + Name)); } } public void ConsumeMetadata(IDictionary metadata) { if (metadata == null || metadata.Count == 0) { return; } IDictionary dictionary = metadata; if (metadata.TryGetValue(Settings.MutatorName, out object value) && value is IDictionary dictionary2) { dictionary = dictionary2; } Dictionary dictionary3 = new Dictionary(); IDictionary dictionary4 = Settings.AsMetadata() ?? new Dictionary(); if (dictionary4.TryGetValue(Settings.MutatorName, out var value2) && value2 is IDictionary dictionary5) { dictionary4 = dictionary5; } foreach (var (text2, value3) in dictionary) { if (MutatorManager.Instance.GameState > MutatorsGameState.None || dictionary4.ContainsKey(text2)) { dictionary3[text2] = value3; RepoMutators.Logger.LogDebug((object)("Metadata key '" + text2 + "' immediate for mutator '" + Name + "'.")); } else { _pendingDeferredMetadata[text2] = value3; RepoMutators.Logger.LogDebug((object)("Metadata key '" + text2 + "' deferred for mutator '" + Name + "'.")); } } if (dictionary3.Count > 0) { ApplyMetadata(dictionary3); } } protected void TryApplyDeferredMetadata(MutatorsGameState gameState) { if (gameState == MutatorsGameState.LevelReady && _pendingDeferredMetadata.Count != 0) { RepoMutators.Logger.LogDebug((object)("Applying deferred metadata for mutator '" + Name + "'")); ApplyDeferredMetadata(_pendingDeferredMetadata); } } protected void ApplyDeferredMetadata(IDictionary pendingDeferredMetadata) { Dictionary metadataToApply = new Dictionary(pendingDeferredMetadata); pendingDeferredMetadata.Clear(); ApplyMetadata(metadataToApply); } protected void ApplyMetadata(IDictionary metadataToApply) { _metadata = _metadata.DeepMergedWith(metadataToApply); RepoMutators.Logger.LogDebug((object)"DeepMerged: "); foreach (KeyValuePair metadatum in _metadata) { RepoMutators.Logger.LogDebug((object)$"{metadatum.Key}: {metadatum.Value}"); } LinqExtensions.ForEach>>((IEnumerable>>)_onMetadataChangedHooks, (Action>>)delegate(Action> hook) { hook?.Invoke(_metadata); }); } protected static void TryAddHook(Type type, string methodName, IList hookList) { MethodInfo method = type.GetMethod(methodName, BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { return; } if (method.GetParameters().Length != 0) { RepoMutators.Logger.LogWarning((object)("Lifecycle hook '" + methodName + "' in type '" + type.FullName + "' must not have parameters.")); return; } if (method.ReturnType != typeof(void)) { RepoMutators.Logger.LogWarning((object)("Lifecycle hook '" + methodName + "' in type '" + type.FullName + "' must return void.")); return; } try { Action item = (Action)Delegate.CreateDelegate(typeof(Action), method); hookList.Add(item); RepoMutators.Logger.LogDebug((object)("Lifecycle hook '" + methodName + "' in type '" + type.FullName + "' was succesfully registered")); } catch (Exception ex) { RepoMutators.Logger.LogError((object)("Failed to bind lifecycle hook '" + methodName + "' in type '" + type.FullName + "': " + ex.Message)); } } protected void TryAddMetadataHook(Type type) { MethodInfo method = type.GetMethod("OnMetadataChanged", BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { return; } ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length != 1) { RepoMutators.Logger.LogWarning((object)("Lifecycle hook 'OnMetadataChanged' in type '" + type.FullName + "' must have one parameter of type IDictionary.")); return; } if (method.ReturnType != typeof(void)) { RepoMutators.Logger.LogWarning((object)("Lifecycle hook 'OnMetadataChanged' in type '" + type.FullName + "' must return void.")); return; } if (!typeof(IDictionary).IsAssignableFrom(parameters[0].ParameterType)) { RepoMutators.Logger.LogWarning((object)("Lifecycle hook 'OnMetadataChanged' in type '" + type.FullName + "' must take a parameter of type IDictionary or a compatible type.")); return; } try { Action> item = (Action>)Delegate.CreateDelegate(typeof(Action>), method); _onMetadataChangedHooks.Add(item); RepoMutators.Logger.LogDebug((object)("Lifecycle hook 'OnMetadataChanged' in type '" + type.FullName + "' was succesfully registered")); } catch (Exception ex) { RepoMutators.Logger.LogError((object)("Failed to bind lifecycle hook 'OnMetadataChanged' in type '" + type.FullName + "': " + ex.Message)); } } } public static class Mutators { public const string NopMutatorName = "None"; public const string OutWithABangName = "Out With a Bang!"; public const string ApolloElevenName = "Apollo 11"; public const string UltraViolenceName = "Ultra-Violence"; public const string DuckThisName = "Duck This"; public const string ProtectThePresidentName = "Protect the President"; public const string OneShotOneKillName = "One Shot, One Kill"; public const string RustyServosName = "Rusty Servos"; public const string HandleWithCareName = "Handle With Care"; public const string HuntingSeasonName = "Hunting Season"; public const string ThereCanOnlyBeOneName = "There Can Only Be One"; public const string VolatileCargoName = "Volatile Cargo"; public const string SealedAwayName = "Sealed Away"; public const string ProtectTheWeakName = "Protect the Weak"; public const string FiringMyLaserName = "Firing My Laser"; public const string VoiceoverName = "Voiceover"; public const string TheFloorIsLavaName = "The Floor Is Lava"; public const string LessIsMoreName = "Less Is More"; public const string FragmentationProtocolName = "Fragmentation Protocol"; public const string AmalgamName = "Amalgam"; public const string NopMutatorDescription = "A normal run, no special effects"; public const string OutWithABangDescription = "Monsters explode on death"; public const string ApolloElevenDescription = "Level-wide Zero-Gravity"; public const string UltraViolenceDescription = "Immediately activates the final extraction phase"; public const string DuckThisDescription = "Ducks aggro on sight instead of on interaction\nAlways spawn at least 1 duck"; public const string ProtectThePresidentDescription = "A random player becomes the \"President\"\nIf they die, everyone else self-destructs"; public const string OneShotOneKillDescription = "Any damage taken by a player is lethal"; public const string RustyServosDescription = "Players cannot jump\n+3 Grab Range"; public const string HandleWithCareDescription = "Valuables are worth more but break on any impact"; public const string HuntingSeasonDescription = "No valuables spawn, weapons spawn instead\nEnemy respawn time reduced to 10 seconds"; public const string ThereCanOnlyBeOneDescription = "All monster spawns are of the same type"; public const string VolatileCargoDescription = "Valuables explode on destruction\nExplosion radius and strength based on value"; public const string SealedAwayDescription = "Breaking valuables has a chance to spawn monsters"; public const string ProtectTheWeakDescription = "Protect your weaker friends!"; public const string FiringMyLaserDescription = "Fire your laser by pressing {specialActionKey}\nUncontrollably fire your laser when taking damage"; public const string VoiceoverDescription = "Player voices are shuffled"; public const string TheFloorIsLavaDescription = "You take damage while standing on the floor"; public const string LessIsMoreDescription = "Valuables are worth less but gain value when hit\nNormal breaking mechanics apply"; public const string AmalgamDescription = "You’ve been here before — just not all at once"; internal static string[] All() { return new string[18] { "None", "Out With a Bang!", "Apollo 11", "Ultra-Violence", "Duck This", "Protect the President", "Rusty Servos", "Handle With Care", "Hunting Season", "There Can Only Be One", "Volatile Cargo", "Sealed Away", "Protect the Weak", "Firing My Laser", "Voiceover", "The Floor Is Lava", "Less Is More", "Amalgam" }; } } public sealed class NopMutator : IMutator { private static readonly IReadOnlyList _patches = Array.Empty(); private static readonly IReadOnlyList> _conditions = Array.Empty>(); public string Name => "None"; public string Description => "A normal run, no special effects"; public bool Active { get; private set; } public AbstractMutatorSettings Settings { get; private set; } public IReadOnlyList Patches => _patches; public IReadOnlyList> Conditions => _conditions; public bool HasSpecialAction => false; internal NopMutator(AbstractMutatorSettings settings) { Settings = settings; } public void Patch() { Active = true; } public void Unpatch() { Active = false; } public void ConsumeMetadata(IDictionary metadata) { } } } namespace Mutators.Mutators.Patches { internal class AmalgamPatch { [CompilerGenerated] private sealed class d__4 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__4(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; case 1: { <>1__state = -1; DirtFinderMapDoor[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (DirtFinderMapDoor val in array) { if (!Object.op_Implicit((Object)(object)val)) { continue; } PhysGrabHinge component = ((Component)val).GetComponent(); if (Object.op_Implicit((Object)(object)component) && component.broken) { PhysGrabObjectImpactDetector component2 = ((Component)val).GetComponent(); if (Object.op_Implicit((Object)(object)component2)) { RepoMutators.Logger.LogDebug((object)("[Amalgam] removing broken door " + ((Object)((Component)val).transform).name)); component2.DestroyObject(false); } else { RepoMutators.Logger.LogWarning((object)("[Amalgam] unable to find impactDetector on " + ((Object)((Component)val).transform).name)); } } } 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(); } } private static bool initDone; private static Level actualLevel; private static void BeforePatchAll() { if (SemiFunc.IsMasterClientOrSingleplayer()) { MutatorManager instance = MutatorManager.Instance; instance.GameStateChanged = (Action)Delegate.Combine(instance.GameStateChanged, new Action(RemoveBrokenDoors)); } } private static void RemoveBrokenDoors(MutatorsGameState gameState) { if (gameState == MutatorsGameState.LevelGenerated) { MutatorsNetworkManager.Instance.Run(ScheduleRemoveBrokenDoors()); } } [IteratorStateMachine(typeof(d__4))] private static IEnumerator ScheduleRemoveBrokenDoors() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__4(0); } [HarmonyPrefix] [HarmonyPatch(typeof(LevelGenerator))] [HarmonyPatch("SpawnModule")] private static void LevelGeneratorSpawnModulePrefix(LevelGenerator __instance) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown if (!SemiFunc.IsMasterClientOrSingleplayer() || initDone) { return; } actualLevel = __instance.Level; __instance.Level = new Level(); __instance.Level.BlockObject = actualLevel.BlockObject; __instance.Level.MusicPreset = actualLevel.MusicPreset; __instance.Level.ConstantMusicPreset = actualLevel.ConstantMusicPreset; RepoMutators.Logger.LogInfo((object)"[Amalgam] Building level from the following available levels:"); foreach (Level allEligibleLevel in GetAllEligibleLevels()) { RepoMutators.Logger.LogInfo((object)("[Amalgam] " + ((Object)allEligibleLevel).name)); AddNormalModules(__instance, allEligibleLevel); AddPassageModules(__instance, allEligibleLevel); AddDeadEndModules(__instance, allEligibleLevel); AddExtractionModules(__instance, allEligibleLevel); } initDone = true; } [HarmonyPrefix] [HarmonyPatch(typeof(EnvironmentDirector))] [HarmonyPatch("Setup")] private static void EnvironmentDirectorSetupPrefix() { if (SemiFunc.IsMasterClientOrSingleplayer() && (Object)(object)actualLevel != (Object)null) { LevelGenerator.Instance.Level = actualLevel; } } private static void AddNormalModules(LevelGenerator levelGenerator, Level level) { levelGenerator.ModulesNormalShuffled_1.AddRange(level.ModulesNormal1); levelGenerator.ModulesNormalShuffled_2.AddRange(level.ModulesNormal2); levelGenerator.ModulesNormalShuffled_3.AddRange(level.ModulesNormal3); ListExtension.Shuffle((IList)levelGenerator.ModulesNormalShuffled_1); ListExtension.Shuffle((IList)levelGenerator.ModulesNormalShuffled_2); ListExtension.Shuffle((IList)levelGenerator.ModulesNormalShuffled_3); } private static void AddPassageModules(LevelGenerator levelGenerator, Level level) { levelGenerator.ModulesPassageShuffled_1.AddRange(level.ModulesPassage1); levelGenerator.ModulesPassageShuffled_2.AddRange(level.ModulesPassage2); levelGenerator.ModulesPassageShuffled_3.AddRange(level.ModulesPassage3); ListExtension.Shuffle((IList)levelGenerator.ModulesPassageShuffled_1); ListExtension.Shuffle((IList)levelGenerator.ModulesPassageShuffled_2); ListExtension.Shuffle((IList)levelGenerator.ModulesPassageShuffled_3); } private static void AddDeadEndModules(LevelGenerator levelGenerator, Level level) { levelGenerator.ModulesDeadEndShuffled_1.AddRange(level.ModulesDeadEnd1); levelGenerator.ModulesDeadEndShuffled_2.AddRange(level.ModulesDeadEnd2); levelGenerator.ModulesDeadEndShuffled_3.AddRange(level.ModulesDeadEnd3); ListExtension.Shuffle((IList)levelGenerator.ModulesDeadEndShuffled_1); ListExtension.Shuffle((IList)levelGenerator.ModulesDeadEndShuffled_2); ListExtension.Shuffle((IList)levelGenerator.ModulesDeadEndShuffled_3); } private static void AddExtractionModules(LevelGenerator levelGenerator, Level level) { levelGenerator.ModulesExtractionShuffled_1.AddRange(level.ModulesExtraction1); levelGenerator.ModulesExtractionShuffled_2.AddRange(level.ModulesExtraction2); levelGenerator.ModulesExtractionShuffled_3.AddRange(level.ModulesExtraction3); ListExtension.Shuffle((IList)levelGenerator.ModulesExtractionShuffled_1); ListExtension.Shuffle((IList)levelGenerator.ModulesExtractionShuffled_2); ListExtension.Shuffle((IList)levelGenerator.ModulesExtractionShuffled_3); } private static IList GetAllEligibleLevels() { ISet excludedSet = new HashSet(MutatorSettings.Amalgam.ExcludedLevels.Select((string level) => (!level.StartsWith("level - ", StringComparison.OrdinalIgnoreCase)) ? ("level - " + level).ToLowerInvariant() : level.ToLowerInvariant())); return (from level in Levels.AllLevels where !((Object)level).name.Equals(((Object)actualLevel).name, StringComparison.OrdinalIgnoreCase) where !excludedSet.Contains(((Object)level).name.ToLowerInvariant()) select level).ToList(); } private static void AfterUnpatchAll() { if (SemiFunc.IsMasterClientOrSingleplayer()) { MutatorManager instance = MutatorManager.Instance; instance.GameStateChanged = (Action)Delegate.Remove(instance.GameStateChanged, new Action(RemoveBrokenDoors)); } initDone = false; actualLevel = null; } } internal class ApolloElevenPatch { [HarmonyPostfix] [HarmonyPatch(typeof(LevelGenerator))] [HarmonyPatch("GenerateDone")] private static void LevelGeneratorGenerateDonePostfix() { if (SemiFunc.RunIsLevel()) { PlayerController.instance.AntiGravity(float.MaxValue); if (SemiFunc.IsMasterClientOrSingleplayer()) { MakeAllPhysGrabObjectsZeroGravity(); } } else { PlayerController.instance.AntiGravity(0f); } } [HarmonyPostfix] [HarmonyPatch(typeof(PhysGrabObjectImpactDetector))] [HarmonyPatch("Update")] private static void PhysGrabObjectImpactDetectorUpdatePostfix(PhysGrabObjectImpactDetector __instance) { if (SemiFunc.IsMasterClientOrSingleplayer() && !MutatorSettings.ApolloEleven.ApplyInCart && !__instance.isNotValuable) { if (__instance.inCart && !__instance.inCartPrevious) { __instance.physGrabObject.OverrideDrag(0.5f, 0.1f); __instance.physGrabObject.OverrideAngularDrag(0.5f, 0.1f); __instance.physGrabObject.OverrideZeroGravity(0.1f); } else if (!__instance.inCart && __instance.inCartPrevious) { MakeObjectZeroGravity(__instance.physGrabObject); } } } [HarmonyPrefix] [HarmonyPatch(typeof(PlayerController))] [HarmonyPatch("AntiGravity")] private static bool PlayControllerAntiGravityPrefix(float _timer) { return _timer == float.MaxValue; } [HarmonyPrefix] [HarmonyPatch(typeof(PhysGrabObject))] [HarmonyPatch("OverrideDrag")] private static bool PhysGrabObjectOverrideDragPrefix(PhysGrabObject __instance, float value, float time) { if (__instance.impactDetector.inCart && !MutatorSettings.ApolloEleven.ApplyInCart) { return true; } return time == float.MaxValue; } [HarmonyPrefix] [HarmonyPatch(typeof(PhysGrabObject))] [HarmonyPatch("OverrideAngularDrag")] private static bool PhysGrabObjectOverrideAngularDragPrefix(PhysGrabObject __instance, float value, float time) { if (__instance.impactDetector.inCart && !MutatorSettings.ApolloEleven.ApplyInCart) { return true; } return time == float.MaxValue; } [HarmonyPrefix] [HarmonyPatch(typeof(PhysGrabObject))] [HarmonyPatch("OverrideZeroGravity")] private static bool PhysGrabObjectOverrideZeroGravityPrefix(PhysGrabObject __instance, float time) { if (__instance.impactDetector.inCart && !MutatorSettings.ApolloEleven.ApplyInCart) { return true; } return time == float.MaxValue; } [HarmonyPrefix] [HarmonyPatch(typeof(PlayerController))] [HarmonyPatch("FixedUpdate")] private static void PlayerControllerFixedUpdatePrefix(PlayerController __instance) { //IL_0011: 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_002d: Unknown result type (might be due to invalid IL or missing references) if (!ChatManager.instance.StateIsActive() && Input.GetKey(MutatorSettings.ApolloEleven.DownwardsKey)) { __instance.rb.AddForce(Vector3.down * 50f, (ForceMode)0); } } [HarmonyPostfix] [HarmonyPatch(typeof(RoundDirector))] [HarmonyPatch("PhysGrabObjectAdd")] private static void RoundDirectorPhysGrabObjectAddPostfix(PhysGrabObject _physGrabObject) { MakeObjectZeroGravity(_physGrabObject); } private static void MakeAllPhysGrabObjectsZeroGravity() { foreach (PhysGrabObject physGrabObject in RoundDirector.instance.physGrabObjects) { MakeObjectZeroGravity(physGrabObject); } } private static void MakeObjectZeroGravity(PhysGrabObject physGrabObject) { if (MutatorSettings.ApolloEleven.ApplyToEnemies || !Object.op_Implicit((Object)(object)((Component)physGrabObject).GetComponent())) { physGrabObject.OverrideDrag(0.5f, float.MaxValue); physGrabObject.OverrideAngularDrag(0.5f, float.MaxValue); physGrabObject.OverrideZeroGravity(float.MaxValue); } } } internal class DuckThisPatch { private const string Ducky = "Apex Predator"; [HarmonyPostfix] [HarmonyPriority(100)] [HarmonyPatch(typeof(EnemyDirector))] [HarmonyPatch("AmountSetup")] private static void EnemyDirectorAmountSetupPostfix(EnemyDirector __instance) { if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } IList enemyList = __instance.enemyList; if (enemyList.Any((EnemySetup setup) => setup.spawnObjects.Select((PrefabRef so) => so.Prefab.GetComponent()).Any((EnemyParent ep) => (Object)(object)ep != (Object)null && ep.enemyName == "Apex Predator"))) { return; } EnemySetup val = Enemies.AllEnemies.Where((EnemySetup enemySetup) => ((Object)enemySetup).name == "Enemy - Duck").FirstOrDefault(); if (!Object.op_Implicit((Object)(object)val)) { return; } IList list = enemyList.Where(delegate(EnemySetup setup) { IEnumerable source = from so in setup.spawnObjects select so.Prefab.GetComponent() into ep where (Object)(object)ep != (Object)null select ep; return source.All((EnemyParent ep) => (int)ep.difficulty == 0) && source.All((EnemyParent ep) => ep.enemyName != "Apex Predator"); }).ToList(); if (list.Count == 0) { RepoMutators.Logger.LogWarning((object)"No suitable enemies found to replace with Apex Predator"); return; } EnemySetup val2 = list[Random.RandomRangeInt(0, list.Count)]; if (enemyList.Remove(val2)) { RepoMutators.Logger.LogDebug((object)("[" + MutatorSettings.DuckThis.MutatorName + "] " + ((Object)val2).name + " was removed in favor of Apex Predator")); enemyList.Add(val); } } [HarmonyPrefix] [HarmonyPatch(typeof(EnemyDuck))] [HarmonyPatch("Update")] private static void EnemyDuckUpdatePrefix(EnemyDuck __instance) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 if (SemiFunc.IsMasterClientOrSingleplayer()) { DuckThisBehaviour orAddComponent = ComponentHolderProtocol.GetOrAddComponent((Object)(object)__instance); if (((int)__instance.currentState == 5 || (int)__instance.currentState == 6 || (int)__instance.currentState == 7) && orAddComponent.CanNotice()) { __instance.UpdateState((State)11); } if ((int)__instance.currentState == 16) { __instance.playerTarget = null; __instance.UpdateState((State)1); orAddComponent.NoticeCooldown = MutatorSettings.DuckThis.AggroCooldown; } } } } internal class FiringMyLaserPatch { private const string LaserActionEnabled = "laserActionEnabled"; private const string LaserOnHurtEnabled = "laserOnHurtEnabled"; private static bool LaserBlocked = false; private static bool LaserOnHurt = true; private static void OnMetadataChanged(IDictionary metadata) { LaserOnHurt = metadata.Get("laserOnHurtEnabled"); bool flag = metadata.Get("laserActionEnabled"); if (!flag && !flag) { MutatorsNetworkManager.Instance.Run(DescriptionUtils.LateUpdateDescription("Laser module not installed...")); } else if (!flag) { MutatorsNetworkManager.Instance.Run(DescriptionUtils.LateUpdateDescription("Fire your laser by pressing {specialActionKey}\nUncontrollably fire your laser when taking damage".Split("\n")[1])); } else if (!LaserOnHurt) { MutatorsNetworkManager.Instance.Run(DescriptionUtils.LateUpdateDescription("Fire your laser by pressing {specialActionKey}\nUncontrollably fire your laser when taking damage".Split("\n")[0])); } } [HarmonyPostfix] [HarmonyPatch(typeof(LevelGenerator))] [HarmonyPatch("GenerateDone")] private static void LevelGeneratorGenerateDonePostfix() { if (SemiFunc.IsMasterClientOrSingleplayer()) { IDictionary metadata = new Dictionary { { "laserActionEnabled", MutatorSettings.FiringMyLaser.LaserActionEnabled }, { "laserOnHurtEnabled", MutatorSettings.FiringMyLaser.LaserOnHurtEnabled } }; MutatorsNetworkManager.Instance.SendMetadata(metadata); } } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerAvatar))] [HarmonyPatch("Start")] private static void PlayerAvatarStartPostfix(PlayerAvatar __instance) { //IL_002f: 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) if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } string text = "Xepos.REPO-Mutators/FiringMyLaser"; PrefabRef val = default(PrefabRef); if (!NetworkPrefabs.TryGetNetworkPrefabRef(text, ref val)) { RepoMutators.Logger.LogError((object)("Unable to instantiate laser: Could not find PrefabRef with id " + text)); return; } GameObject val2 = NetworkPrefabs.SpawnNetworkPrefab(val, Vector3.zero, Quaternion.identity, (byte)0, new object[4] { __instance.steamID, MutatorSettings.FiringMyLaser.LaserActionCooldown, MutatorSettings.FiringMyLaser.LaserActionEnemyDamage, MutatorSettings.FiringMyLaser.LaserActionEnabled }); if (!Object.op_Implicit((Object)(object)val2) || (Object)(object)val2 == (Object)null) { RepoMutators.Logger.LogWarning((object)("Failed to create laser for " + __instance.playerName)); } else if (!SemiFunc.IsMultiplayer()) { val2.transform.SetParent(((Component)__instance).transform, false); LaserFiringBehaviour componentInChildren = val2.GetComponentInChildren(); if (Object.op_Implicit((Object)(object)componentInChildren)) { val2.SetActive(true); componentInChildren.laserCooldown = MutatorSettings.FiringMyLaser.LaserActionCooldown; componentInChildren.laserCooldownTimer = MutatorSettings.FiringMyLaser.LaserActionCooldown; componentInChildren.manualActionEnabled = MutatorSettings.FiringMyLaser.LaserActionEnabled; ((HurtCollider)val2.GetComponentInChildren(true)).enemyDamage = MutatorSettings.FiringMyLaser.LaserActionEnemyDamage; } } } [HarmonyPrefix] [HarmonyPatch(typeof(HurtCollider))] [HarmonyPatch("PlayerHurt")] private static bool HurtColliderPlayerHurt(HurtCollider __instance, PlayerAvatar _player) { if (__instance is PlayerIgnoringHurtCollider playerIgnoringHurtCollider && playerIgnoringHurtCollider.ignoredPlayers.Contains(_player)) { return false; } return true; } [HarmonyPrefix] [HarmonyPatch(typeof(PlayerHealth))] [HarmonyPatch("HurtOtherRPC")] private static void PlayerHealthHurtOtherRPCPrefix(PlayerHealth __instance, int damage, Vector3 hurtPosition, int enemyIndex) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance.playerAvatar != (Object)(object)PlayerAvatar.instance) && enemyIndex == -1 && !(hurtPosition != Vector3.zero)) { LaserBlocked = true; } } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerHealth))] [HarmonyPatch("Hurt")] private static void PlayerHealthHurtPostfix(PlayerHealth __instance, int damage) { if (LaserOnHurt && damage >= 1 && !__instance.playerAvatar.deadSet && !LaserBlocked) { LaserFiringBehaviour componentInChildren = ((Component)__instance.playerAvatar).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)componentInChildren) && !componentInChildren.IsActive() && !componentInChildren.IsReviveLockout()) { componentInChildren.FireLaser(2.5f); } } } [HarmonyPostfix] [HarmonyPriority(1)] [HarmonyPatch(typeof(PlayerHealth))] [HarmonyPatch("Hurt")] private static void PlayerHealthHurtLaserResetPostfix() { LaserBlocked = false; } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerAvatar))] [HarmonyPatch("PlayerDeath")] private static void PlayerAvatarDeathPostfix(PlayerAvatar __instance) { LaserFiringBehaviour componentInChildren = ((Component)__instance).GetComponentInChildren(true); if (Object.op_Implicit((Object)(object)componentInChildren)) { componentInChildren.StopLaser(localOnly: true); } } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerAvatar))] [HarmonyPatch("Revive")] private static void PlayerAvatarReviveRPCPostfix(PlayerAvatar __instance) { LaserFiringBehaviour componentInChildren = ((Component)__instance).GetComponentInChildren(true); if (Object.op_Implicit((Object)(object)componentInChildren)) { componentInChildren.ActivateReviveLockout(); } } private static void BeforeUnpatchAll() { LaserBlocked = false; LaserOnHurt = true; } } internal class FragmentationProtocolPatch { private static readonly IDictionary fragmentsParentMap = new Dictionary(); [HarmonyPostfix] [HarmonyPatch(typeof(Enemy))] [HarmonyPatch("Start")] private static void EnemyHealthAwakePostfix(Enemy __instance) { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown Enemy __instance2 = __instance; if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } RepoMutators.Logger.LogInfo((object)"Checking fragment"); if (!__instance2.HasHealth || IsFragment(__instance2.EnemyParent)) { return; } RepoMutators.Logger.LogInfo((object)"Enemy was not a fragment"); EnemySetup enemySetup = Enemies.AllEnemies.Where((EnemySetup x) => __instance2.EnemyParent.enemyName.Equals(((Object)x).name, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); if (Object.op_Implicit((Object)(object)enemySetup)) { FragmentationProtocolBehaviour fragmentationProtocolBehaviour = ComponentHolderProtocol.GetOrAddComponent((Object)(object)__instance2.EnemyParent); __instance2.Health.onDeath.AddListener((UnityAction)delegate { MakeBabies(__instance2.EnemyParent, enemySetup, fragmentationProtocolBehaviour); }); } } [HarmonyPostfix] [HarmonyPatch(typeof(EnemyParent))] [HarmonyPatch("Despawn")] private static void EnemyHealthAwakePostfix(EnemyParent __instance) { if (SemiFunc.IsMasterClientOrSingleplayer() && fragmentsParentMap.ContainsKey(__instance)) { RepoMutators.Logger.LogInfo((object)("Despawned " + __instance.enemyName)); __instance.DespawnedTimer = float.MaxValue; } } [HarmonyPrefix] [HarmonyPatch(typeof(EnemyParent))] [HarmonyPatch("SpawnedTimerPause")] private static void EnemyHealthAwakePostfix(EnemyParent __instance, ref float _time) { if (SemiFunc.IsMasterClientOrSingleplayer() && fragmentsParentMap.ContainsKey(__instance)) { _time = 0f; } } [HarmonyPrefix] [HarmonyPatch(typeof(EnemyParent))] [HarmonyPatch("Spawn")] private static bool EnemyParentSpawnPrefix(EnemyParent __instance) { if (fragmentsParentMap.TryGetValue(__instance, out EnemyParent value) && value.Enemy.HasHealth) { FragmentationProtocolBehaviour component = ((Component)value).GetComponent(); RepoMutators.Logger.LogInfo((object)$"In Fragment Window: {component.IsInFragmentWindow} - {component.FragmentWindow}"); if (Object.op_Implicit((Object)(object)component) && !component.IsInFragmentWindow) { __instance.DespawnedTimer = (RoundDirector.instance.allExtractionPointsCompleted ? 30f : float.MaxValue); return false; } } return true; } private static void MakeBabies(EnemyParent enemyParent, EnemySetup enemySetup, FragmentationProtocolBehaviour fragmentationProtocolBehaviour) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) fragmentationProtocolBehaviour.FragmentWindow = 0.5f; if (fragmentationProtocolBehaviour.GetFragmentations().Count == 0) { List list = Enemies.SpawnEnemy(enemySetup, enemyParent.Enemy.CenterTransform.position, Quaternion.identity, false); RepoMutators.Logger.LogInfo((object)$"Created {list?.Count ?? 0} fragments"); if (list == null || list.Count == 0) { return; } { foreach (EnemyParent item in list) { RepoMutators.Logger.LogInfo((object)("Adding fragment: " + ((Object)((Component)item).transform).name)); MutatorsNetworkManager.Instance.SendScaleChange(((MonoBehaviourPun)item).photonView.ViewID, 0.6f); fragmentationProtocolBehaviour.AddFragmentation(item); fragmentsParentMap.Add(item, enemyParent); RepoMutators.Logger.LogInfo((object)("Added fragment: " + ((Object)((Component)item).transform).name)); } return; } } foreach (EnemyParent fragmentation in fragmentationProtocolBehaviour.GetFragmentations()) { fragmentation.DespawnedTimer = 0f; fragmentation.Spawn(); fragmentation.Enemy.EnemyTeleported(((Component)enemyParent).transform.position); } } private static bool IsFragment(EnemyParent enemyParent) { return fragmentsParentMap.ContainsKey(enemyParent); } private static void AfterUnpatchAll() { fragmentsParentMap.Clear(); } } internal class HandleWithCarePatch { private const string SurplusValuable = "Surplus Valuable"; private static readonly IList valuableObjects = new List(); private static bool SetupDone = false; [HarmonyPostfix] [HarmonyPatch(typeof(ValuableObject))] [HarmonyPatch("Awake")] private static void ValuableObjectAwake(ValuableObject __instance) { if (SemiFunc.IsMasterClientOrSingleplayer() && (MutatorSettings.HandleWithCare.MultiplySurplusValue || !((Object)((Component)__instance).gameObject).name.StartsWith("Surplus Valuable"))) { valuableObjects.Add(__instance); } } [HarmonyPostfix] [HarmonyPatch(typeof(ValuableObject))] [HarmonyPatch("DollarValueSetLogic")] private static void ValuableObjectDollarValueSetLogicPostfix(ValuableObject __instance) { if (SemiFunc.IsMasterClientOrSingleplayer() && SetupDone && (MutatorSettings.HandleWithCare.MultiplySurplusValue || !((Object)((Component)__instance).gameObject).name.StartsWith("Surplus Valuable"))) { __instance.dollarValueCurrent *= MutatorSettings.HandleWithCare.ValueMultiplier; __instance.dollarValueOriginal *= MutatorSettings.HandleWithCare.ValueMultiplier; } } [HarmonyPostfix] [HarmonyPatch(typeof(LevelGenerator))] [HarmonyPatch("GenerateDone")] private static void LevelGeneratorGenerateDonePostfix() { if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } SetupDone = true; foreach (ValuableObject valuableObject in valuableObjects) { valuableObject.dollarValueCurrent *= MutatorSettings.HandleWithCare.ValueMultiplier; valuableObject.dollarValueOriginal *= MutatorSettings.HandleWithCare.ValueMultiplier; valuableObject.photonView.RPC("DollarValueSetRPC", (RpcTarget)1, new object[1] { valuableObject.dollarValueCurrent }); } valuableObjects.Clear(); } [HarmonyPrefix] [HarmonyPatch(typeof(PhysGrabObjectImpactDetector))] [HarmonyPatch("BreakRPC")] private static void PhysGrabObjectImpactDetectorBreakRPCPrefix(PhysGrabObjectImpactDetector __instance, ref float valueLost, bool _loseValue) { if (SemiFunc.IsMasterClientOrSingleplayer() && (MutatorSettings.HandleWithCare.InstantlyDestroySurplus || !((Object)__instance).name.StartsWith("Surplus Valuable")) && __instance.isValuable && _loseValue) { valueLost = __instance.valuableObject.dollarValueCurrent; } } private static void BeforeUnpatchAll() { SetupDone = false; valuableObjects.Clear(); } } internal class HuntingSeasonPatch { [HarmonyPostfix] [HarmonyPriority(300)] [HarmonyPatch(typeof(EnemyDirector))] [HarmonyPatch("Start")] private static void EnemyDirectorAmountSetupPostfix(EnemyDirector __instance) { if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } __instance.DisableEnemies((EnemySetup setup) => setup.spawnObjects.All(delegate(PrefabRef so) { EnemyParent component = so.Prefab.GetComponent(); if ((Object)(object)component == (Object)null) { return true; } if (!(component.enemyName == "Peeper")) { EnemyHealth componentInChildren = so.Prefab.GetComponentInChildren(); if (componentInChildren == null) { return false; } return !componentInChildren.spawnValuable; } return true; })); } [HarmonyPrefix] [HarmonyPatch(typeof(StatsManager))] [HarmonyPatch("ItemFetchName")] private static void StatsManagerItemFetchNamePrefix(ref string itemName, ItemAttributes itemAttributes) { if (Object.op_Implicit((Object)(object)((Component)itemAttributes).GetComponent())) { itemName += "(Hunting Season)"; } } [HarmonyPostfix] [HarmonyPatch(typeof(LevelGenerator))] [HarmonyPatch("GenerateDone")] private static void LevelGeneratorGenerateDonePostfix() { //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_010d: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) if (!SemiFunc.IsMasterClientOrSingleplayer() || !SemiFunc.RunIsLevel()) { return; } int num = RoundDirector.instance.physGrabObjects.Count / 2; Item[] possibleItems = GetPossibleItems(); if (possibleItems.Length == 0) { RepoMutators.Logger.LogWarning((object)"No eligable weapons found"); RepoMutators.Logger.LogWarning((object)"Valuables will not removed in order to prevent softlocks"); return; } foreach (PhysGrabObject item in RoundDirector.instance.physGrabObjects.ToList()) { if (!item.isNonValuable) { item.DestroyPhysGrabObject(); } } RepoMutators.Logger.LogDebug((object)string.Format("[{0}] Spawning {1} weapons", "Hunting Season", num)); IList list = SemiFunc.LevelPointsGetAll(); IList list2 = new List(); for (int i = 0; i < num; i++) { LevelPoint val = list[Random.Range(0, list.Count)]; Item val2 = possibleItems[Random.Range(0, possibleItems.Length)]; Vector3 position = ((Component)val).transform.position; position.y += 2f; GameObject val3 = Items.SpawnItem(val2, position, Quaternion.identityQuaternion); if (!((Object)(object)val3 == (Object)null)) { val3.AddComponent(); PhotonView component = val3.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { list2.Add(component); } } } MutatorsNetworkManager.Instance.SendComponentForViews(list2.Select((PhotonView x) => x.ViewID).ToArray(), typeof(TemporaryLevelItemBehaviour)); } [HarmonyPostfix] [HarmonyPatch(typeof(ItemAttributes))] [HarmonyPatch("Start")] private static void ItemAttributesStartPostfix(ItemAttributes __instance) { TemporaryLevelItemBehaviour component = ((Component)__instance).gameObject.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { __instance.itemName += " (Temporary)"; } } [HarmonyPostfix] [HarmonyPatch(typeof(EnemyParent))] [HarmonyPatch("Despawn")] private static void EnemyParentDespawnPostfix(EnemyParent __instance) { if (__instance.Enemy.HasHealth && __instance.DespawnedTimer > 10f) { __instance.DespawnedTimer = 10f; __instance.Enemy.Health.spawnValuableCurrent = 0; } } [HarmonyPostfix] [HarmonyPatch(typeof(RunManager))] [HarmonyPriority(500)] [HarmonyPatch("ChangeLevel")] private static void RunManagerChangeLevelPostfix() { if (!SemiFunc.IsMultiplayer() || !SemiFunc.IsNotMasterClient()) { TemporaryItemUtils.DropMarkedItems("Hunting Season"); } } [HarmonyPostfix] [HarmonyPatch(typeof(RunManager))] [HarmonyPriority(500)] [HarmonyPatch("UpdateLevel")] private static void RunManagerUpdateLevelPostfix() { if (!SemiFunc.IsMasterClientOrSingleplayer()) { TemporaryItemUtils.DropMarkedItems("Hunting Season"); } } [HarmonyPrefix] [HarmonyPatch(typeof(PunManager))] [HarmonyPatch("SyncAllDictionaries")] private static void PunManagerSyncAllDictionariesPrefix() { if (SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.RunIsShop()) { TemporaryItemUtils.RemoveMarkedItems("Hunting Season"); } } private static Item[] GetPossibleItems() { return Items.AllItems.Where((Item i) => !Object.op_Implicit((Object)(object)i.prefab.Prefab.GetComponent()) && ((int)i.itemType == 7 || (int)i.itemType == 9)).ToArray(); } } internal class LessIsMorePatch { private const string SurplusValuable = "Surplus Valuable"; internal const string ValueGainMultiplier = "ValueGainMultiplier"; private static float valueGainMultiplier = MutatorSettings.LessIsMore.ValueGainMultiplier; private static void OnMetadataChanged(IDictionary metadata) { if (!SemiFunc.IsMasterClientOrSingleplayer()) { valueGainMultiplier = metadata.Get("ValueGainMultiplier"); } } [HarmonyPostfix] [HarmonyPriority(500)] [HarmonyPatch(typeof(ValuableObject))] [HarmonyPatch("DollarValueSetLogic")] private static void ValuableObjectDollarValueSetLogicPostfix(ValuableObject __instance) { if (SemiFunc.IsMasterClientOrSingleplayer() && !((Object)((Component)__instance).gameObject).name.StartsWith("Surplus Valuable") && !((Object)(object)((Component)__instance).GetComponent() != (Object)null)) { float num = Mathf.InverseLerp(100f, 30f, __instance.durabilityPreset.fragility); float num2 = Mathf.Lerp(MutatorSettings.LessIsMore.StrongDivisionFactor, MutatorSettings.LessIsMore.WeakDivisionFactor, num); __instance.dollarValueCurrent /= num2; __instance.dollarValueOriginal /= num2; ComponentHolderProtocol.AddComponent((Object)(object)__instance); } } [HarmonyPrefix] [HarmonyPatch(typeof(RoundDirector))] [HarmonyPatch("StartRoundLogic")] private static void RoundDirectorStartRoundLogic(ref int value) { if (SemiFunc.IsMasterClientOrSingleplayer()) { value = (int)((double)value * 1.1); } } [HarmonyPrefix] [HarmonyPatch(typeof(PhysGrabObjectImpactDetector))] [HarmonyPatch("BreakRPC")] private static void PhysGrabObjectImpactDetectorBreakRPC(PhysGrabObjectImpactDetector __instance, ref float valueLost, bool _loseValue) { if (_loseValue && __instance.isValuable && !__instance.isNotValuable && !((Object)((Component)__instance).gameObject).name.StartsWith("Surplus Valuable")) { if (SemiFunc.IsMasterClientOrSingleplayer()) { ((Component)__instance).GetComponent()?.SubtractValue(valueLost); } valueLost = (0f - valueLost) * valueGainMultiplier; } } private static void AfterUnpatchAll() { valueGainMultiplier = MutatorSettings.LessIsMore.ValueGainMultiplier; } } internal class OneShotOneKillPatch { [HarmonyPostfix] [HarmonyPatch(typeof(PlayerHealthGrab))] [HarmonyPatch("Start")] private static void PlayerHealthGrabStart(PlayerHealthGrab __instance) { ((Behaviour)__instance).enabled = false; } [HarmonyPostfix] [HarmonyPriority(300)] [HarmonyPatch(typeof(EnemyDirector))] [HarmonyPatch("Start")] private static void EnemyDirectorAmountSetupPostfix(EnemyDirector __instance) { if (SemiFunc.IsMasterClientOrSingleplayer()) { __instance.DisableEnemies(); } } [HarmonyPostfix] [HarmonyPriority(450)] [HarmonyPatch(typeof(PlayerDeathHead))] [HarmonyPatch("Update")] private static void PlayerDeathHeadUpdatePostfix(PlayerDeathHead __instance) { if (__instance.triggered && MutatorSettings.OneShotOneKill.InstaReviveInTruckOrExtraction && !SemiFunc.IsNotMasterClient()) { if (__instance.roomVolumeCheck.inTruck) { DoRevive(__instance, inTruck: true); } else if (__instance.roomVolumeCheck.inExtractionPoint) { DoRevive(__instance, inTruck: false); } } } [HarmonyPrefix] [HarmonyPatch(typeof(PlayerHealth))] [HarmonyPatch("Hurt")] private static void PlayerHealthHurtPrefix(PlayerHealth __instance, ref int damage, ref bool savingGrace) { if (!__instance.godMode && damage >= 1) { damage = __instance.maxHealth; savingGrace = false; } } [HarmonyPrefix] [HarmonyPatch(typeof(PlayerHealth))] [HarmonyPatch("HurtOther")] private static void PlayerHealthHurtOtherPrefix(PlayerHealth __instance, ref int damage, ref bool savingGrace) { if (!__instance.godMode && damage >= 1) { damage = __instance.maxHealth; savingGrace = false; } } private static void DoRevive(PlayerDeathHead playerDeathHead, bool inTruck) { int num = ((MutatorSettings.OneShotOneKill.InstaReviveHealth == 0) ? (playerDeathHead.playerAvatar.playerHealth.maxHealth - 1) : (MutatorSettings.OneShotOneKill.InstaReviveHealth - 1)); playerDeathHead.playerAvatar.Revive(inTruck); if (num > 0) { playerDeathHead.playerAvatar.playerHealth.HealOther(num, true); } } } [HarmonyPatch(typeof(EnemyHealth))] internal class OutWithABangPatch { private static ExplosionPreset explosionPreset = null; private static readonly float ExplosionSizeFallback = 3f; private static readonly int ExplosionDamageFallback = 200; private static readonly IDictionary SizeDamage = new Dictionary(); private static void OnMetadataChanged(IDictionary metadata) { float item = metadata.Get("OutWithABang-Radius1"); int item2 = metadata.Get("OutWithABang-Damage1"); SizeDamage[(Difficulty)0] = (item, item2); float item3 = metadata.Get("OutWithABang-Radius2"); int item4 = metadata.Get("OutWithABang-Damage2"); SizeDamage[(Difficulty)1] = (item3, item4); float item5 = metadata.Get("OutWithABang-Radius3"); int item6 = metadata.Get("OutWithABang-Damage3"); SizeDamage[(Difficulty)2] = (item5, item6); } [HarmonyPostfix] [HarmonyPatch("Awake")] private static void EnemeyHealthAwakePostfix(EnemyHealth __instance) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown EnemyHealth __instance2 = __instance; if ((Object)(object)explosionPreset == (Object)null) { explosionPreset = Object.Instantiate(AssetStore.Preset); } EnemyParent enemyParent = __instance2.enemy.EnemyParent; if (enemyParent.enemyName != "Banger") { ParticleScriptExplosion particleScriptExplosion = ComponentHolderProtocol.AddComponent((Object)(object)__instance2); particleScriptExplosion.explosionPreset = explosionPreset; float explosionSize = ExplosionSizeFallback; int explosionDamage = ExplosionDamageFallback; if (SizeDamage.TryGetValue(enemyParent.difficulty, out (float, int) value)) { (explosionSize, explosionDamage) = value; } __instance2.onDeath.AddListener((UnityAction)delegate { Explode(__instance2.enemy, particleScriptExplosion, explosionSize, explosionDamage); }); } } private static void Explode(Enemy enemy, ParticleScriptExplosion particleScriptExplosion, float size, int damage) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) particleScriptExplosion.Spawn(enemy.CenterTransform.position, size, damage, damage, 1f, false, false, 1f); } private static void BeforeUnpatchAll() { SizeDamage.Clear(); } } internal class ProtectThePresidentPatch { [CompilerGenerated] private sealed class d__13 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string presidentId; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__13(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if ((Object)(object)TargetPlayerAnnouncingBehaviour.instance == (Object)null) { <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 1; return true; } UpdatePresidentHealth(presidentId); 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(); } } private const string PresidentId = "presidentId"; private static bool _presidentAlive = true; private static bool _failureMessageSent = false; private static string? _presidentId; private static void OnMetadataChanged(IDictionary metadata) { string text = metadata.Get("presidentId"); if (_presidentId != text) { _presidentId = text; UpdatePresidentHealth(_presidentId); } } [HarmonyPostfix] [HarmonyPatch(typeof(LevelGenerator))] [HarmonyPatch("GenerateDone")] private static void LevelGeneratorGenerateDonePostfix() { _presidentAlive = true; _failureMessageSent = false; if (SemiFunc.IsMultiplayer() && SemiFunc.IsMasterClient()) { PlayerAvatar val = PickPresidentPlayer(); RepoMutators.Logger.LogDebug((object)("Picked " + val.playerName + " as the president!")); SendPresidentMeta(val); } } [HarmonyPrefix] [HarmonyPatch(typeof(NetworkManager))] [HarmonyPatch("OnPlayerLeftRoom")] private static void NetworkManagerOnPlayerLeftRoomPrefix(Player otherPlayer) { PlayerAvatar val = SemiFunc.PlayerGetFromName(otherPlayer.NickName); if (val.steamID == _presidentId && SemiFunc.IsMultiplayer() && SemiFunc.IsMasterClient()) { PlayerAvatar president = PickPresidentPlayer(); SendPresidentMeta(president); } } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerAvatar))] [HarmonyPatch("PlayerDeathRPC")] private static void PlayerAvatarPlayerDeathRPCPostfix(PlayerAvatar __instance, int enemyIndex) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) if (__instance.steamID == _presidentId && __instance.steamID != PlayerAvatar.instance.steamID) { _presidentAlive = false; PlayerAvatar val = SemiFunc.PlayerGetFromSteamID(_presidentId); SemiFunc.UIFocusText("President " + ((val != null && val.playerName != null) ? (val.playerName + " ") : "") + " has died.", Color.white, AssetManager.instance.colorYellow, 3f); ChatManager.instance.PossessSelfDestruction(); } } [HarmonyPrefix] [HarmonyPatch(typeof(ChatManager))] [HarmonyPatch("PossessChat")] private static void ChatManagerPossessChatPrefix(PossessChatID _possessChatID, ref string message) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if (!_presidentAlive && !_failureMessageSent && (int)_possessChatID == 3) { message = "We have failed " + (SemiFunc.PlayerGetFromSteamID(_presidentId)?.playerName ?? " the president"); _failureMessageSent = true; } } [HarmonyPostfix] [HarmonyPriority(100)] [HarmonyPatch(typeof(PlayerHealth))] [HarmonyPatch("UpdateHealthRPC")] private static void PlayerHealthUpdateHealthRPCPostfix(PlayerHealth __instance) { if (!(__instance.playerAvatar.steamID != _presidentId) && !(_presidentId == PlayerAvatar.instance.steamID)) { UpdatePresidentHealth(_presidentId); } } [HarmonyPrefix] [HarmonyPatch(typeof(LoadingUI))] [HarmonyPatch("StopLoading")] private static void InitializePresidentHealth() { if (!SemiFunc.RunIsLevel()) { TargetPlayerAnnouncingBehaviour instance = TargetPlayerAnnouncingBehaviour.instance; if (Object.op_Implicit((Object)(object)instance)) { ((TMP_Text)instance.Text).text = string.Empty; } } else if (_presidentId != null && _presidentId != PlayerAvatar.instance.steamID) { MutatorsNetworkManager.Instance.Run(InitializePresidentHealthEnumerator(_presidentId)); } } private static void UpdatePresidentHealth(string presidentId) { TargetPlayerAnnouncingBehaviour instance = TargetPlayerAnnouncingBehaviour.instance; if (Object.op_Implicit((Object)(object)instance)) { RepoMutators.Logger.LogDebug((object)"Updating President Health"); if (presidentId == PlayerAvatar.instance.steamID) { ((TMP_Text)instance.Text).text = string.Empty; } else { ((TMP_Text)instance.Text).text = BuildPresidentText(presidentId); } } } internal static string BuildPresidentText(string presidentId) { PlayerAvatar val = SemiFunc.PlayerAvatarGetFromSteamID(presidentId); return string.Format("{0}: {1}/{2}", val.playerName ?? "President", val.playerHealth.health, val.playerHealth.maxHealth); } [IteratorStateMachine(typeof(d__13))] private static IEnumerator InitializePresidentHealthEnumerator(string presidentId) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__13(0) { presidentId = presidentId }; } private static PlayerAvatar PickPresidentPlayer() { List list = SemiFunc.PlayerGetAll(); return list[Random.RandomRangeInt(0, list.Count)]; } private static void SendPresidentMeta(PlayerAvatar president) { MutatorsNetworkManager.Instance.SendMetadata(new Dictionary { { "presidentId", president.steamID } }.WithMutator(MutatorSettings.ProtectThePresident.MutatorName)); } private static void AfterUnpatchAll() { _presidentId = null; } } internal class ProtectTheWeakPatch { [CompilerGenerated] private sealed class d__8 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PlayerAvatar playerAvatar; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__8(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if (playerAvatar.steamID == null) { <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } if (playerAvatar.steamID == PlayerAvatar.instance.steamID) { ComponentHolderProtocol.AddComponent((Object)(object)playerAvatar); } 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(); } } [CompilerGenerated] private sealed class d__24 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float delay; public IDictionary metadata; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__24(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(delay); <>1__state = 1; return true; case 1: <>1__state = -1; RepoMutators.Logger.LogDebug((object)"I am the bodyguard"); HandleWeapon(metadata.Get("tranqViewId")); 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(); } } [CompilerGenerated] private sealed class d__25 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string description; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__25(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if (!Object.op_Implicit((Object)(object)MutatorDescriptionAnnouncingBehaviour.Instance)) { <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } ((TMP_Text)MutatorDescriptionAnnouncingBehaviour.Instance.Text).text = description; 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(); } } private static bool initDone = false; private static int initialHealth = 100; internal const string BodyGuardId = "BodyguardId"; internal const string TranqViewId = "tranqViewId"; private static string? _bodyGuardId = null; private static IDictionary? _clients; private static void OnMetadataChanged(IDictionary metadata) { string text = metadata.Get("BodyguardId"); _clients = metadata.Get>("clients"); if (text != _bodyGuardId) { _bodyGuardId = text; PlayerAvatar instance = PlayerAvatar.instance; BodyguardPlayerHealthBehaviour bodyguardPlayerHealthBehaviour = ((instance != null) ? ((Component)instance).GetComponent() : null); if ((Object)(object)bodyguardPlayerHealthBehaviour != (Object)null && Object.op_Implicit((Object)(object)bodyguardPlayerHealthBehaviour)) { bodyguardPlayerHealthBehaviour.BodyguardId = _bodyGuardId; } AssignBodyguard(metadata); } } [HarmonyPrefix] [HarmonyPatch(typeof(PlayerAvatar))] [HarmonyPatch("Awake")] private static void PlayerAvatarAwakePrefix(PlayerAvatar __instance) { MutatorsNetworkManager.Instance.Run(Check(__instance)); } [IteratorStateMachine(typeof(d__8))] private static IEnumerator Check(PlayerAvatar playerAvatar) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__8(0) { playerAvatar = playerAvatar }; } [HarmonyPostfix] [HarmonyPatch(typeof(LevelGenerator))] [HarmonyPatch("GenerateDone")] private static void LevelGeneratorGenerateDonePostfix() { StartupLogic(); } [HarmonyPrefix] [HarmonyPatch(typeof(StatsManager))] [HarmonyPatch("ItemFetchName")] private static void StatsManagerItemFetchNamePrefix(ref string itemName, ItemAttributes itemAttributes) { if (Object.op_Implicit((Object)(object)((Component)itemAttributes).GetComponent())) { itemName += "(Protect the Weak)"; } } [HarmonyPostfix] [HarmonyPatch(typeof(ItemAttributes))] [HarmonyPatch("Start")] private static void ItemAttributesStartPostfix(ItemAttributes __instance) { TemporaryLevelItemBehaviour component = ((Component)__instance).gameObject.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { __instance.itemName += " (Bodyguard Only)"; } } [HarmonyPrefix] [HarmonyPatch(typeof(ItemGun))] [HarmonyPatch("Shoot")] private static bool ItemGunShootPrefix(ItemGun __instance) { if (Object.op_Implicit((Object)(object)((Component)__instance).GetComponent())) { bool flag = false; foreach (PhysGrabber item in __instance.physGrabObject.playerGrabbing) { flag = item.playerAvatar.steamID == _bodyGuardId; if (flag) { break; } } return flag; } return true; } [HarmonyPrefix] [HarmonyPatch(typeof(NetworkManager))] [HarmonyPatch("OnPlayerLeftRoom")] private static void NetworkManagerOnPlayerLeftRoomPrefix(Player otherPlayer) { PlayerAvatar val = SemiFunc.PlayerGetFromName(otherPlayer.NickName); if (val.steamID == _bodyGuardId) { StartupLogic(val.steamID); } } [HarmonyPrefix] [HarmonyPatch(typeof(ItemBattery))] [HarmonyPatch("RemoveFullBar")] private static bool ItemBatteryRemoveFullBarPrefix(ItemBattery __instance) { return !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent()); } [HarmonyPostfix] [HarmonyPatch(typeof(RunManager))] [HarmonyPriority(500)] [HarmonyPatch("ChangeLevel")] private static void RunManagerChangeLevelPostfix() { if (!SemiFunc.IsMultiplayer() || !SemiFunc.IsNotMasterClient()) { TemporaryItemUtils.DropMarkedItems("Protect the Weak"); } } [HarmonyPostfix] [HarmonyPatch(typeof(RunManager))] [HarmonyPriority(500)] [HarmonyPatch("UpdateLevel")] private static void RunManagerUpdateLevelPostfix() { if (!SemiFunc.IsMasterClientOrSingleplayer()) { TemporaryItemUtils.DropMarkedItems("Protect the Weak"); } } [HarmonyPrefix] [HarmonyPatch(typeof(PunManager))] [HarmonyPatch("SyncAllDictionaries")] private static void PunManagerSyncAllDictionariesPrefix() { if (SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.RunIsShop()) { TemporaryItemUtils.RemoveMarkedItems("Protect the Weak"); } } [HarmonyPrefix] [HarmonyPatch(typeof(TruckScreenText))] [HarmonyPatch("GotoNextLevel")] private static void TruckScreenTextEngineStartRPCPrefix() { if (!SemiFunc.IsMultiplayer() || !SemiFunc.IsMasterClient()) { return; } foreach (PlayerAvatar item in from player in SemiFunc.PlayerGetAll() where player.steamID != PlayerAvatar.instance.steamID select player) { int? num = _clients.Get>(item.steamID).Get("originalHealth"); if (!num.HasValue) { RepoMutators.Logger.LogWarning((object)("Failed to restore original health for " + item.playerName)); continue; } RepoMutators.Logger.LogDebug((object)$"Setting health to {num.Value} for {item.playerName}"); StatsManager.instance.SetPlayerHealth(item.steamID, num.Value, false); } ((Component)PlayerAvatar.instance).GetComponent()?.RestoreOriginalHealth(); } [HarmonyPostfix] [HarmonyPriority(300)] [HarmonyPatch(typeof(PunManager))] [HarmonyPatch("UpdateHealthRightAway")] private static void PunManagerUpgradeHealthRightAwayPostfix(string _steamID) { PlayerAvatar val = SemiFunc.PlayerAvatarGetFromSteamID(_steamID); BodyguardPlayerHealthBehaviour component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { component.originalHealth += 20; component.originalMaxHealth += 20; component.UpdateHealth(); component.SendHealth(); } } [HarmonyPostfix] [HarmonyPriority(100)] [HarmonyPatch(typeof(PlayerAvatar))] [HarmonyPatch("PlayerDeathRPC")] private static void PlayerDeathRPCPostfix() { PlayerAvatar localPlayer = PlayerAvatar.instance; if (_bodyGuardId == PlayerAvatar.instance.steamID && !localPlayer.deadSet) { IList list = SemiFunc.PlayerGetAll(); if (list.Count > 1 && list.Where((PlayerAvatar player) => player.steamID != localPlayer.steamID).All((PlayerAvatar player) => player.deadSet)) { ChatManager.instance.PossessSelfDestruction(); } } } private static PlayerAvatar PickBodyguardPlayer(string? excludedId = null) { string excludedId2 = excludedId; List list = (from x in SemiFunc.PlayerGetAll() where x.steamID != excludedId2 select x).ToList(); return list[Random.RandomRangeInt(0, list.Count)]; } private static void StartupLogic(string? excludedId = null) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (!SemiFunc.IsMasterClient()) { return; } PlayerAvatar val = PickBodyguardPlayer(excludedId); RepoMutators.Logger.LogDebug((object)("Picked " + val.playerName + " as the bodyguard!")); Item val2 = Items.AllItems.Where((Item x) => "Tranq Gun".Equals(x.itemName)).FirstOrDefault(); if (Object.op_Implicit((Object)(object)val2)) { GameObject val3 = Items.SpawnItem(val2, ((Component)val).transform.position, Quaternion.identity); if ((Object)(object)val3 != (Object)null) { PhotonView component = val3.GetComponent(); int? num = ((component != null) ? new int?(component.ViewID) : null); if (num.HasValue) { MutatorsNetworkManager.Instance.SendMetadata(BuildMeta(val, num.Value)); MutatorsNetworkManager.Instance.SendComponentForViews(new int[1] { num.Value }, typeof(TemporaryLevelItemBehaviour)); return; } } } RepoMutators.Logger.LogWarning((object)"Failed to spawn Tranq gun"); MutatorsNetworkManager.Instance.SendMetadata(BuildMeta(val)); } private static void AssignBodyguard(IDictionary metadata) { if (string.IsNullOrEmpty(_bodyGuardId)) { return; } PlayerAvatar instance = PlayerAvatar.instance; if (initDone) { MutatorDescriptionAnnouncingBehaviour instance2 = MutatorDescriptionAnnouncingBehaviour.Instance; if (_bodyGuardId == instance.steamID) { ((TMP_Text)instance2.Text).text = metadata.Get("descriptionBodyguard"); ((Component)instance).GetComponent()?.UpdateHealth(); MutatorsNetworkManager.Instance.Run(EquipDelayed(metadata, 1f)); } else { ((TMP_Text)instance2.Text).text = metadata.Get("description"); } instance2.ShowDescription(); } else { initDone = true; if (_bodyGuardId == instance.steamID) { MutatorsNetworkManager.Instance.Run(LateUpdateDescription(metadata.Get("descriptionBodyguard"))); MutatorsNetworkManager.Instance.Run(EquipDelayed(metadata)); } else { MutatorsNetworkManager.Instance.Run(LateUpdateDescription(metadata.Get("description"))); } } } [IteratorStateMachine(typeof(d__24))] private static IEnumerator EquipDelayed(IDictionary metadata, float delay = 3f) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__24(0) { metadata = metadata, delay = delay }; } [IteratorStateMachine(typeof(d__25))] private static IEnumerator LateUpdateDescription(string description) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__25(0) { description = description }; } private static void HandleWeapon(int tranqViewId) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) PhotonView val = PhotonView.Find(tranqViewId); ItemEquippable val2 = ((val != null) ? ((Component)val).GetComponent() : null); if ((Object)(object)val2 != (Object)null) { RepoMutators.Logger.LogDebug((object)"Attempting to equip tranq gun"); PlayerAvatar instance = PlayerAvatar.instance; Inventory instance2 = Inventory.instance; int num = instance2.GetFirstFreeInventorySpotIndex(); if (num == -1) { InventorySpot spotByIndex = instance2.GetSpotByIndex(0); spotByIndex.CurrentItem.ForceUnequip(((Component)instance).transform.position + Vector3.forward, instance.photonView.ViewID); num = 0; } val2.RequestEquip(num, instance.photonView.ViewID); } else { RepoMutators.Logger.LogWarning((object)$"Failed to equip bodyguard weapon - viewId: {tranqViewId} - equippable: {(Object)(object)val2 != (Object)null}"); } } private static IDictionary BuildMeta(PlayerAvatar bodyguard, int tranqGunId = 0) { Dictionary dictionary = new Dictionary(); dictionary.Add("BodyguardId", bodyguard.steamID); dictionary.Add("description", "You are fragile but " + bodyguard.playerName + " will protect you!\n" + bodyguard.playerName + " dies if they are the last one standing"); dictionary.Add("descriptionBodyguard", "You are the bodyguard, you have increased health\nYour tranq gun has infinite ammo\nYou die if you are the last one standing\nProtect your friends!"); IDictionary dictionary2 = dictionary; if (tranqGunId > 0) { dictionary2.Add("tranqViewId", tranqGunId); } return dictionary2.WithMutator(MutatorSettings.ProtectTheWeak.MutatorName); } private static void BeforeUnpatchAll() { initialHealth = 100; initDone = false; _bodyGuardId = null; _clients?.Clear(); } } internal class RustyServosPatch { [HarmonyPostfix] [HarmonyPatch(typeof(PhysGrabber))] [HarmonyPatch("Start")] private static void PhysGrabberStartPostfix(PhysGrabber __instance) { if (!((Object)(object)__instance != (Object)(object)PhysGrabber.instance)) { __instance.grabRange += 3f; } } [HarmonyPrefix] [HarmonyPatch(typeof(PlayerController))] [HarmonyPatch("Start")] private static void PlayerControllerStartPostfix(PlayerController __instance) { __instance.JumpCooldown = float.MaxValue; } } internal class SealedAwayPatch { [CompilerGenerated] private sealed class d__3 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public EnemyVision enemyVision; public PlayerAvatar playerAvatar; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__3(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 1; return true; case 1: <>1__state = -1; ((Behaviour)enemyVision).enabled = true; if (Object.op_Implicit((Object)(object)playerAvatar) && (Object)(object)playerAvatar != (Object)null) { enemyVision.Enemy.SetChaseTarget(playerAvatar); } 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(); } } private static uint _currentSpawns; [HarmonyPostfix] [HarmonyPatch(typeof(ValuableObject))] [HarmonyPatch("DollarValueSetLogic")] private static void ValuableObjectDollarValueSetLogicPostfix(ValuableObject __instance) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown ValuableObject __instance2 = __instance; if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } PhysGrabObjectImpactDetector component = ((Component)__instance2).GetComponent(); if ((Object)(object)component != (Object)null) { SealedAwayMarkerBehaviour component2 = ((Component)component).GetComponent(); if (!((Object)(object)component2 != (Object)null)) { component.onDestroy.AddListener((UnityAction)delegate { Spawn(__instance2); }); ComponentHolderProtocol.AddComponent((Object)(object)component); } } else { RepoMutators.Logger.LogWarning((object)("[Sealed Away] unable to find impactDetector on " + ((Object)((Component)__instance2).transform).name)); } } private static void Spawn(ValuableObject valuableObject) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) if (_currentSpawns >= MutatorSettings.SealedAway.MaximumMonsterSpawns || !(Random.Range(0f, 100f) <= MutatorSettings.SealedAway.MonsterSpawnChance)) { return; } EnemyDirector instance = EnemyDirector.instance; EnemySetup[] array = (from setup in instance.enemiesDifficulty1.Concat(instance.enemiesDifficulty2).Concat(instance.enemiesDifficulty3) where setup.spawnObjects.Count == 1 && !setup.spawnObjects.Any(delegate(PrefabRef so) { EnemyParent enemyParent = so.Prefab.GetComponent(); if (!((Object)(object)enemyParent == (Object)null)) { EnemyHealth componentInChildren = so.Prefab.GetComponentInChildren(); if (componentInChildren != null && componentInChildren.spawnValuable) { return MutatorSettings.SealedAway.ExcludedEnemies.Any((string excluded) => excluded.Equals(enemyParent?.enemyName, StringComparison.OrdinalIgnoreCase)); } } return true; }) select setup).ToArray(); if (array.Length == 0) { return; } EnemySetup val = array[Random.RandomRangeInt(0, array.Length)]; List list = Enemies.SpawnEnemy(val, ((Component)valuableObject).transform.position, Quaternion.identity, false); if (list == null) { return; } PlayerAvatar lastPlayerGrabbing = valuableObject.physGrabObject.lastPlayerGrabbing; foreach (EnemyParent item in list) { RepoMutators.Logger.LogDebug((object)("Valuable broken - Spawned " + item.enemyName)); EnemyVision component = ((Component)item.Enemy).GetComponent(); EnemyHealth component2 = ((Component)item.Enemy).GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.health /= 2; component2.healthCurrent = component2.health; component2.spawnValuableMax = int.MaxValue; } if (SemiFunc.IsMultiplayer()) { PhotonView component3 = ((Component)item).GetComponent(); if ((Object)(object)component3 != (Object)null) { MutatorsNetworkManager.Instance.SendScaleChange(component3.ViewID, 0.6f); } } else { ((Component)item).transform.localScale = new Vector3(0.6f, 0.6f, 0.6f); } if (!((Object)(object)component == (Object)null)) { ((Behaviour)component).enabled = false; MutatorsNetworkManager.Instance.Run(ActivateVisionLater(component, lastPlayerGrabbing)); } } _currentSpawns++; } [IteratorStateMachine(typeof(d__3))] private static IEnumerator ActivateVisionLater(EnemyVision enemyVision, PlayerAvatar? playerAvatar) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__3(0) { enemyVision = enemyVision, playerAvatar = playerAvatar }; } private static void BeforeUnpatchAll() { _currentSpawns = 0u; RepoMutators.Logger.LogDebug((object)$"[Sealed Away] Set tracked monster spawns to {_currentSpawns}"); } } internal class TheFloorIsLavaPatch { internal const string Damage = "damage"; internal const string UsePercentageDamage = "usePercentageDamage"; internal const string ExtraDescription = "extraDescription"; internal const string ImmunePlayers = "immunePlayers"; internal const string RevivalImmunityDuration = "reviveImmunityDuration"; internal static readonly ISet immunePlayers = new HashSet(); private static float reviveImmunityDuration = MutatorSettings.TheFloorIsLava.ReviveImmunityDuration; private static bool initDone = false; private static void OnMetadataChanged(IDictionary metadata) { if (!SemiFunc.IsMasterClientOrSingleplayer()) { reviveImmunityDuration = metadata.Get("reviveImmunityDuration"); if (MutatorManager.Instance.GameState == MutatorsGameState.LevelReady) { HandleImmuneLogic(metadata.GetAsList("immunePlayers") ?? new List(), metadata.Get("extraDescription"), metadata.Get("damage"), metadata.Get("usePercentageDamage")); } } } [HarmonyPrefix] [HarmonyPriority(601)] [HarmonyPatch(typeof(EnemyDirector))] [HarmonyPatch("GetEnemy")] private static void EnemyDirectorGetEnemyPrefix(ref List ___enemyList, int ___enemyListIndex) { if (SemiFunc.IsMasterClientOrSingleplayer() && MutatorSettings.TheFloorIsLava.DisableEnemies) { ___enemyList.Clear(); EnemySetup val = ScriptableObject.CreateInstance(); val.spawnObjects = new List(); ___enemyList.Add(val); while (___enemyList.Count < ___enemyListIndex + 1) { ___enemyList.Add(val); } } } [HarmonyPostfix] [HarmonyPatch(typeof(LevelGenerator))] [HarmonyPatch("GenerateDone")] private static void LevelGeneratorGenerateDonePostfix() { if (!SemiFunc.IsMultiplayer() || !SemiFunc.IsMasterClient()) { return; } IList list = SemiFunc.PlayerGetAll().ToList(); if (MutatorSettings.TheFloorIsLava.ImmunePlayerCount > 0 && list.Count > 1) { int num = Mathf.Min(MutatorSettings.TheFloorIsLava.ImmunePlayerCount, list.Count); for (int i = 0; i < num; i++) { PlayerAvatar item = list[Random.RandomRangeInt(0, list.Count)]; list.Remove(item); immunePlayers.Add(item); } } SendMetadata(); } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerAvatar))] [HarmonyPatch("Start")] private static void PlayerAvatarAwakePostfix(PlayerAvatar __instance) { if ((Object)(object)__instance == (Object)(object)PlayerAvatar.instance) { ComponentHolderProtocol.AddComponent((Object)(object)__instance); } } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerAvatar))] [HarmonyPatch("ReviveRPC")] private static void PlayerAvatarReviveRPCPostfix(PlayerAvatar __instance) { if ((Object)(object)__instance == (Object)(object)PlayerAvatar.instance && reviveImmunityDuration > 0f) { TheFloorIsLavaBehaviour component = ((Component)__instance).GetComponent(); if ((Object)(object)component != (Object)null) { component.immunityTimer = reviveImmunityDuration; } else { RepoMutators.Logger.LogWarning((object)"No TheFloorIsLavaBehaviour found on local player!"); } } } private static void HandleImmuneLogic(IList immunePlayerList, string? extraDescription, int damagePerTick, bool usePercentageDamage) { immunePlayers.Clear(); LinqUtility.AddRange((ICollection)immunePlayers, (IEnumerable)immunePlayerList.Select((string ip) => SemiFunc.PlayerAvatarGetFromSteamID(ip)).ToList()); ApplyImmunity(damagePerTick, usePercentageDamage); HandleDescription(extraDescription); } private static void ApplyImmunity(int damagePerTick, bool usePercentageDamage) { TheFloorIsLavaBehaviour component = ((Component)PlayerAvatar.instance).GetComponent(); if (Object.op_Implicit((Object)(object)component)) { component.Immune = immunePlayers.Contains(PlayerAvatar.instance); component.damagePerTick = damagePerTick; component.usePercentageDamage = usePercentageDamage; } else { RepoMutators.Logger.LogWarning((object)"No TheFloorIsLavaBehaviour found on local player!"); } } private static void HandleDescription(string? extraDescription) { if (initDone) { if (extraDescription != null) { ((TMP_Text)MutatorDescriptionAnnouncingBehaviour.Instance.Text).text = MutatorSettings.TheFloorIsLava.MutatorDescription + "\n" + extraDescription; } return; } initDone = true; if (extraDescription != null) { MutatorsNetworkManager.Instance.Run(DescriptionUtils.LateUpdateDescription(extraDescription, DescriptionUtils.DescriptionReplacementType.APPEND)); } } private static IDictionary BuildMeta() { IDictionary dictionary = new Dictionary { { "damage", MutatorSettings.TheFloorIsLava.DamagePerTick }, { "usePercentageDamage", MutatorSettings.TheFloorIsLava.UsePercentageDamage } }; if (immunePlayers.Count > 0) { dictionary.Add("immunePlayers", immunePlayers.Select((PlayerAvatar player) => player.steamID).ToList()); string value = JoinWithAnd(immunePlayers.Select((PlayerAvatar p) => p.playerName).ToList()) + " " + ((immunePlayers.Count == 1) ? "is" : "are") + " immune to lava damage!"; dictionary.Add("extraDescription", value); } return dictionary.WithMutator(MutatorSettings.TheFloorIsLava.MutatorName); } private static void SendMetadata() { IDictionary dictionary = BuildMeta(); MutatorsNetworkManager.Instance.SendMetadata(dictionary); ApplyImmunity(MutatorSettings.TheFloorIsLava.DamagePerTick, MutatorSettings.TheFloorIsLava.UsePercentageDamage); HandleDescription(dictionary.Get("extraDescription")); } private static void AfterUnpatchAll() { immunePlayers.Clear(); initDone = false; } private static string JoinWithAnd(IList items) { if (items == null || items.Count == 0) { return ""; } if (items.Count == 1) { return items[0]; } if (items.Count == 2) { return items[0] + " and " + items[1]; } return string.Join(", ", items.Take(items.Count - 1)) + " and " + items.Last(); } } internal class ThereCanOnlyBeOnePatch { private const string EnemyGroupPrefix = "Enemy Group - "; [HarmonyPostfix] [HarmonyPriority(100)] [HarmonyPatch(typeof(EnemyDirector))] [HarmonyPatch("AmountSetup")] private static void EnemyDirectorAmountSetupPostfix(EnemyDirector __instance) { if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } IList excludedEnemies = MutatorSettings.ThereCanOnlyBeOne.ExcludedEnemies; bool groupsAllowed = RunManager.instance.levelsCompleted >= MutatorSettings.ThereCanOnlyBeOne.GroupSpawnsThreshold; IList list = (from setup in __instance.enemiesDifficulty1.Concat(__instance.enemiesDifficulty2).Concat(__instance.enemiesDifficulty3) where groupsAllowed || !((Object)setup).name.StartsWith("Enemy Group - ") where setup.spawnObjects.All((PrefabRef so) => !excludedEnemies.Any((string excluded) => excluded.Equals(so.Prefab.GetComponent()?.enemyName, StringComparison.OrdinalIgnoreCase))) select setup).ToList(); if (list.Count == 0) { RepoMutators.Logger.LogWarning((object)("Based on your config, there were no enemies that could be spawned for the " + MutatorSettings.ThereCanOnlyBeOne.MutatorName + " Mutator!")); return; } __instance.enemyList.Clear(); EnemySetup item = list[Random.RandomRangeInt(0, list.Count)]; __instance.enemyList.Add(item); for (int i = 0; i < __instance.totalAmount; i++) { __instance.enemyList.Add(item); } } } internal class UltraViolencePatch { [CompilerGenerated] private sealed class d__13 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__13(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; RoundDirector.instance.allExtractionPointsCompleted = false; 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(); } } private static readonly Func _getExtractionPoints = CreateFieldGetter("extractionPoints"); private static readonly Func _getExtractionPointsCompleted = CreateFieldGetter("extractionPointsCompleted"); private static readonly Action _setExtractionPointsCompleted = CreateFieldSetter("extractionPointsCompleted"); private static bool _keepLightsOn = MutatorSettings.UltraViolence.KeepOnLight; private static void OnMetadataChanged(IDictionary metadata) { _keepLightsOn = metadata.Get("keepLightsOn"); } [HarmonyPostfix] [HarmonyPatch(typeof(LevelGenerator))] [HarmonyPatch("GenerateDone")] private static void LevelGeneratorGenerateDonePostfix() { if (SemiFunc.IsMasterClientOrSingleplayer()) { MutatorsNetworkManager.Instance.SendMetadata(new Dictionary { { "keepLightsOn", MutatorSettings.UltraViolence.KeepOnLight } }); } } [HarmonyPostfix] [HarmonyPriority(300)] [HarmonyPatch(typeof(EnemyDirector))] [HarmonyPatch("Start")] private static void EnemyDirectorAmountSetupPostfix(EnemyDirector __instance) { if (SemiFunc.IsMasterClientOrSingleplayer()) { __instance.DisableEnemies(); } } [HarmonyPostfix] [HarmonyPatch(typeof(ExtractionPoint))] [HarmonyPatch("ActivateTheFirstExtractionPointAutomaticallyWhenAPlayerLeaveTruck")] private static void ExtractionPointActivateTheFirstExtractionPointAutomaticallyWhenAPlayerLeaveTruckPostfix() { int arg = _getExtractionPoints(RoundDirector.instance); _setExtractionPointsCompleted(RoundDirector.instance, arg); RoundDirector.instance.ExtractionCompletedAllCheck(); _setExtractionPointsCompleted(RoundDirector.instance, 0); if (_keepLightsOn) { RoundDirector.instance.allExtractionPointsCompleted = false; } else { MutatorsNetworkManager.Instance.Run(TurnOffLightsLate()); } } [HarmonyPrefix] [HarmonyPatch(typeof(LightManager))] [HarmonyPatch("TurnOffLights")] private static bool LightManagerTurnOffLightsPrefix() { if (_keepLightsOn) { return RoundDirector.instance.allExtractionPointsCompleted; } return true; } [HarmonyPrefix] [HarmonyPatch(typeof(PlayerAvatar))] [HarmonyPatch("FinalHeal")] private static bool PlayerAvatarFinalHealPrefix() { int num = _getExtractionPoints(RoundDirector.instance); int num2 = _getExtractionPointsCompleted(RoundDirector.instance); return num2 >= num; } [HarmonyPrefix] [HarmonyPatch(typeof(TruckHealer))] [HarmonyPatch("StateUpdate")] private static bool TruckHealerStateUpdatePrefixPrefix() { int num = _getExtractionPoints(RoundDirector.instance); int num2 = _getExtractionPointsCompleted(RoundDirector.instance); return num2 >= num; } private static Func CreateFieldGetter(string fieldName) { FieldInfo field = AccessTools.Field(typeof(T), fieldName) ?? throw new Exception($"Field {fieldName} not found on {typeof(T)}"); ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "instance"); MemberExpression body = Expression.Field(parameterExpression, field); Expression> expression = Expression.Lambda>(body, new ParameterExpression[1] { parameterExpression }); return expression.Compile(); } private static Action CreateFieldSetter(string fieldName) { FieldInfo field = AccessTools.Field(typeof(T), fieldName) ?? throw new Exception($"Field {fieldName} not found on {typeof(T)}"); ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "instance"); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(V), "value"); MemberExpression left = Expression.Field(parameterExpression, field); BinaryExpression body = Expression.Assign(left, parameterExpression2); Expression> expression = Expression.Lambda>(body, new ParameterExpression[2] { parameterExpression, parameterExpression2 }); return expression.Compile(); } [IteratorStateMachine(typeof(d__13))] private static IEnumerator TurnOffLightsLate() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__13(0); } private static void BeforeUnpatchAll() { _keepLightsOn = MutatorSettings.UltraViolence.KeepOnLight; } } internal class VoiceoverPatch { [CompilerGenerated] private sealed class d__8 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private PlayerVoiceChat 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__8(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; } else { <>1__state = -1; 5__2 = PlayerAvatar.instance.voiceChat; } RepoMutators.Logger.LogInfo((object)$"ToggleMute: {5__2.toggleMute} - Director: {DataDirector.instance.toggleMute}"); RepoMutators.Logger.LogInfo((object)$"Lobby: {(Object)(object)5__2.audioSource.outputAudioMixerGroup == (Object)(object)5__2.mixerMicrophoneSpectate} - Game: {(Object)(object)5__2.audioSource.outputAudioMixerGroup == (Object)(object)5__2.mixerMicrophoneSound}"); RepoMutators.Logger.LogInfo((object)$"Active and Enabled: {((Behaviour)5__2).isActiveAndEnabled}"); <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__5 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public IList playerAvatars; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__5(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if (playerAvatars.Any((PlayerAvatar avatar) => !avatar.voiceChatFetched)) { <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } originalVoiceChats = playerAvatars.ToDictionary((PlayerAvatar a) => a.steamID, (PlayerAvatar a) => a.voiceChat.photonView.ViewID); voiceOwnership = DerangeVoices(originalVoiceChats, out Dictionary newAssignments); IDictionary metadata = new Dictionary { { "voices", newAssignments }, { "voiceOwnership", voiceOwnership }, { "originalVoices", originalVoiceChats } }; MutatorsNetworkManager.Instance.SendMetadata(metadata); LinqExtensions.ForEach>((IEnumerable>)voiceOwnership, (Action>)delegate(KeyValuePair kvp) { RepoMutators.Logger.LogDebug((object)("Gave voice of " + SemiFunc.PlayerAvatarGetFromSteamID(kvp.Value)?.playerName + " to " + SemiFunc.PlayerAvatarGetFromSteamID(kvp.Key)?.playerName)); }); foreach (KeyValuePair item in newAssignments) { ChangeVoices(item.Key, item.Value); } 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(); } } private static IDictionary originalVoiceChats = new Dictionary(); private static IDictionary voiceOwnership = new Dictionary(); private static void OnMetadataChanged(IDictionary metadata) { IDictionary dictionary = metadata.Get>("originalVoices"); IDictionary dictionary2 = metadata.Get>("voiceOwnership"); if (originalVoiceChats.Count != 0 || dictionary == null || dictionary.Count <= 0 || dictionary2.Count <= 0) { return; } originalVoiceChats = dictionary; voiceOwnership = dictionary2; IDictionary dictionary3 = metadata.Get>("voices"); foreach (KeyValuePair item in dictionary3) { ChangeVoices(item.Key, item.Value); } } [HarmonyPostfix] [HarmonyPatch(typeof(LevelGenerator))] [HarmonyPatch("GenerateDone")] private static void LevelGeneratorGenerateDone() { if (SemiFunc.IsMasterClient()) { IList playerAvatars = SemiFunc.PlayerGetAll(); MutatorsNetworkManager.Instance.Run(WaitForVoiceChats(playerAvatars)); } } [HarmonyPrefix] [HarmonyPatch(typeof(NetworkManager))] [HarmonyPatch("OnPlayerLeftRoom")] private static void NetworkManagerOnPlayerLeftRoomPrefix(Player otherPlayer) { string leavingPlayerId = SemiFunc.PlayerGetFromName(otherPlayer.NickName)?.steamID; if (leavingPlayerId != null && originalVoiceChats.ContainsKey(leavingPlayerId)) { string text = voiceOwnership[leavingPlayerId]; string key = voiceOwnership.First>((KeyValuePair kvp) => kvp.Value == leavingPlayerId).Key; ChangeVoices(leavingPlayerId, originalVoiceChats[leavingPlayerId]); ChangeVoices(key, originalVoiceChats[text]); voiceOwnership[key] = text; originalVoiceChats.Remove(leavingPlayerId); voiceOwnership.Remove(leavingPlayerId); } } [IteratorStateMachine(typeof(d__5))] private static IEnumerator WaitForVoiceChats(IList playerAvatars) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__5(0) { playerAvatars = playerAvatars }; } public static Dictionary DerangeVoices(IDictionary originalMap, out Dictionary newAssignments) { List list = new List(originalMap.Keys); List list2 = new List(originalMap.Values); int count = list.Count; List list3 = new List(list2); for (int i = 0; i < count - 1; i++) { int num = Random.Range(i + 1, count); List list4 = list3; int index = i; int index2 = num; int value = list3[num]; int value2 = list3[i]; list4[index] = value; list3[index2] = value2; } if (list3[count - 1] == list2[count - 1]) { int num2 = Random.Range(0, count - 1); List list4 = list3; int index2 = count - 1; int index = num2; int value2 = list3[num2]; int value = list3[count - 1]; list4[index2] = value2; list3[index] = value; } newAssignments = new Dictionary(); Dictionary dictionary = new Dictionary(); Dictionary dictionary2 = new Dictionary(); for (int j = 0; j < count; j++) { dictionary2[list2[j]] = list[j]; } for (int k = 0; k < count; k++) { string key = list[k]; int num3 = list3[k]; newAssignments[key] = num3; string value3 = dictionary2[num3]; dictionary[key] = value3; } return dictionary; } private static void ChangeVoices(string steamId, int photonViewID) { PlayerAvatar val = SemiFunc.PlayerAvatarGetFromSteamID(steamId); val.voiceChat = ((Component)PhotonView.Find(photonViewID)).GetComponent(); val.voiceChat.playerAvatar = val; if (val.voiceChat.TTSinstantiated) { val.voiceChat.ttsVoice.playerAvatar = val; } if (!SemiFunc.MenuLevel()) { val.voiceChat.ToggleMixer(false, false); } } [IteratorStateMachine(typeof(d__8))] private static IEnumerator Debug() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__8(0); } private static void BeforeUnpatchAll() { originalVoiceChats.Clear(); voiceOwnership.Clear(); } } internal class VolatileCargoPatch { private static ExplosionPreset explosionPreset; [HarmonyPostfix] [HarmonyPatch(typeof(ValuableObject))] [HarmonyPatch("DollarValueSetLogic")] private static void ValuableObjectDollarValueSetLogicPostfix(ValuableObject __instance) { if (!((Object)(object)((Component)__instance).GetComponent() != (Object)null)) { AddExplosion(__instance, __instance.dollarValueOriginal); } } [HarmonyPostfix] [HarmonyPatch(typeof(ValuableObject))] [HarmonyPatch("DollarValueSetRPC")] private static void ValuableObjectDollarValueSetRPCPostfix(ValuableObject __instance, float value) { if (!((Object)(object)((Component)__instance).GetComponent() != (Object)null)) { AddExplosion(__instance, value); } } private static void Explode(ValuableObject valuableObject, ParticleScriptExplosion particleScriptExplosion, float size, int damage) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) particleScriptExplosion.Spawn(((Component)valuableObject).transform.position, size, damage, damage, 1f, false, false, 1f); } private static void AddExplosion(ValuableObject __instance, float value) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown ValuableObject __instance2 = __instance; if ((Object)(object)explosionPreset == (Object)null) { explosionPreset = Object.Instantiate(AssetStore.Preset); } ParticleScriptExplosion particleScriptExplosion = ComponentHolderProtocol.GetOrAddComponent((Object)(object)__instance2); if ((Object)(object)particleScriptExplosion.explosionPreset == (Object)null) { particleScriptExplosion.explosionPreset = explosionPreset; } int damage = (int)Math.Ceiling(Math.Max(25f, value / 250f)); float size = Math.Clamp(value / 12000f, 0.5f, 3f); PhysGrabObjectImpactDetector component = ((Component)__instance2).GetComponent(); if ((Object)(object)component != (Object)null) { component.onDestroy.AddListener((UnityAction)delegate { Explode(__instance2, particleScriptExplosion, size, damage); }); ComponentHolderProtocol.AddComponent((Object)(object)__instance2); } else { RepoMutators.Logger.LogWarning((object)("[Volatile Cargo] unable to find impactDetector on " + ((Object)((Component)__instance2).transform).name)); } } } } namespace Mutators.Mutators.Behaviours { internal class BodyguardPlayerHealthBehaviour : MonoBehaviour { [CompilerGenerated] private sealed class d__11 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public BodyguardPlayerHealthBehaviour <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__11(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown int num = <>1__state; BodyguardPlayerHealthBehaviour bodyguardPlayerHealthBehaviour = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; goto IL_004b; case 1: <>1__state = -1; goto IL_004b; case 2: { <>1__state = -1; break; } IL_004b: if (!bodyguardPlayerHealthBehaviour.playerHealth.healthSet) { <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } bodyguardPlayerHealthBehaviour.originalHealth = bodyguardPlayerHealthBehaviour.playerHealth.health; bodyguardPlayerHealthBehaviour.originalMaxHealth = bodyguardPlayerHealthBehaviour.playerHealth.maxHealth; bodyguardPlayerHealthBehaviour.SendHealth(); break; } if (bodyguardPlayerHealthBehaviour.BodyguardId == null) { <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 2; return true; } bodyguardPlayerHealthBehaviour.UpdateHealth(); 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 BodyguardPlayerHealthBehaviour instance; private PlayerAvatar playerAvatar; private PlayerHealth playerHealth; internal int originalHealth = 100; internal int originalMaxHealth = 100; private bool initDone; internal string? BodyguardId { get; set; } private void Awake() { instance = this; playerAvatar = PlayerAvatar.instance; playerHealth = playerAvatar.playerHealth; ((MonoBehaviour)this).StartCoroutine(GetAndSetHealthLate()); } [IteratorStateMachine(typeof(d__11))] private IEnumerator GetAndSetHealthLate() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__11(0) { <>4__this = this }; } internal void UpdateHealth() { if (BodyguardId == playerAvatar.steamID) { if (!initDone) { float num = CalculateBodyguardHealthMultiplier(playerHealth.maxHealth); playerHealth.health = (int)((float)playerHealth.health * num); playerHealth.maxHealth = (int)((float)playerHealth.maxHealth * num); } else { float num2 = CalculateBodyguardHealthMultiplier(originalMaxHealth); playerHealth.health = (int)((float)originalMaxHealth * num2); playerHealth.maxHealth = (int)((float)originalMaxHealth * num2); } } else { playerHealth.health = 60; playerHealth.maxHealth = 60; } SetHealth(playerHealth.health, playerHealth.maxHealth); initDone = true; } internal void RestoreOriginalHealth() { SetHealth(originalHealth, originalMaxHealth); } private void SetHealth(int health, int maxHealth, bool setInShop = false) { StatsManager.instance.SetPlayerHealth(playerAvatar.steamID, health, setInShop); if (SemiFunc.IsMultiplayer()) { playerHealth.photonView.RPC("UpdateHealthRPC", (RpcTarget)1, new object[3] { health, maxHealth, true }); } } internal void SendHealth() { Dictionary meta = new Dictionary { { "originalHealth", originalHealth } }; MutatorsNetworkManager.Instance.SendMetaToHost(playerAvatar.steamID, meta); } private static float CalculateBodyguardHealthMultiplier(int health) { float num = 2f; float num2 = 1.1f; float num3 = 125f; int num4 = Math.Max(health, 100); float num5 = num3 / ((float)(num4 - 100) + num3); return num2 + (num - num2) * num5; } } internal class DuckThisBehaviour : MonoBehaviour { public float NoticeCooldown { get; internal set; } private void Update() { if (NoticeCooldown > 0f && SemiFunc.IsMasterClientOrSingleplayer()) { NoticeCooldown -= Time.deltaTime; } } internal bool CanNotice() { return NoticeCooldown <= 0f; } } public class FragmentationProtocolBehaviour : MonoBehaviour { private EnemyParent _enemyParent; private ISet _fragmentations = new HashSet(); internal float FragmentWindow { get; set; } internal bool IsInFragmentWindow => FragmentWindow > 0f; private void Awake() { _enemyParent = ((Component)this).GetComponent(); } private void Update() { if (FragmentWindow > 0f) { FragmentWindow -= Time.deltaTime; } } public void AddFragmentation(EnemyParent fragmentation) { _fragmentations.Add(fragmentation); } internal ISet GetFragmentations() { return _fragmentations; } } internal class LaserFiringBehaviour : MonoBehaviour, IPunInstantiateMagicCallback { [CompilerGenerated] private sealed class d__21 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public LaserFiringBehaviour <>4__this; public int damage; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__21(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown int num = <>1__state; LaserFiringBehaviour laserFiringBehaviour = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if ((Object)(object)laserFiringBehaviour.semiLaser == (Object)null) { <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } ((HurtCollider)((Component)laserFiringBehaviour.semiLaser).GetComponentInChildren(true)).enemyDamage = damage; 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(); } } private PhotonView photonView; private PlayerAvatar playerAvatar; private SemiLaser semiLaser; private Transform visionTransform; private float laserTimer; internal float laserReviveLockout = 5f; internal float laserReviveLockoutTimer = 5f; internal float laserCooldown = 100f; internal float laserCooldownTimer = 100f; internal bool canFire = true; internal bool manualActionEnabled = true; private void Awake() { photonView = ((Component)this).GetComponent(); } private void Start() { playerAvatar = ((Component)((Component)this).transform.parent).GetComponent(); visionTransform = ((Component)playerAvatar).transform.Find("Vision Target"); semiLaser = ((Component)((Component)this).transform.Find("SemiLaser")).GetComponent(); ((Component)((Component)this).transform).GetComponentInChildren(true).ignoredPlayers.Add(playerAvatar); } private void Update() { //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //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_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: 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_0197: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)playerAvatar == (Object)(object)PlayerAvatar.instance) { if (laserCooldownTimer < laserCooldown) { laserCooldownTimer += Time.deltaTime; } if (laserReviveLockoutTimer > 0f) { laserReviveLockoutTimer -= Time.deltaTime; } if (manualActionEnabled && laserCooldownTimer >= laserCooldown && !ChatManager.instance.StateIsActive() && Input.GetKeyDown(RepoMutators.Settings.SpecialActionKey)) { FireLaser(2.5f); laserCooldownTimer = 0f; } SpecialActionAnnouncingBehaviour instance = SpecialActionAnnouncingBehaviour.instance; if ((Object)(object)instance?.Text != (Object)null && (Object)(object)instance?.TextMax != (Object)null) { if (manualActionEnabled) { ((TMP_Text)instance.Text).text = $"{(int)laserCooldownTimer}"; ((TMP_Text)instance.TextMax).text = $"/{(int)laserCooldown}"; } else { ((SemiUI)instance).Hide(); } } } if (IsActive()) { laserTimer -= Time.deltaTime; bool flag = false; Vector3 val = visionTransform.position + visionTransform.forward * 15f; RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(visionTransform.position, visionTransform.forward, ref val2, 15f, LayerMask.op_Implicit(SemiFunc.LayerMaskGetVisionObstruct()))) { val = ((RaycastHit)(ref val2)).point; flag = true; } semiLaser.LaserActive(visionTransform.position, val, flag); } } [PunRPC] public void StaffLaserRPC(float _time) { laserTimer = _time; } public void FireLaser(float _time) { if (SemiFunc.IsMultiplayer()) { photonView.RPC("StaffLaserRPC", (RpcTarget)0, new object[1] { _time }); } else { StaffLaserRPC(_time); } } public void StopLaser(bool localOnly = false) { if (localOnly) { laserTimer = 0f; } else { FireLaser(0f); } } public bool IsActive() { return laserTimer > 0f; } public bool IsReviveLockout() { return laserReviveLockoutTimer > 0f; } public void ActivateReviveLockout() { laserReviveLockoutTimer = laserReviveLockout; } public void OnPhotonInstantiate(PhotonMessageInfo info) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) object[] instantiationData = info.photonView.InstantiationData; if (instantiationData.Length < 4) { RepoMutators.Logger.LogWarning((object)"Received invalid data for LaserFiringBehaviour"); return; } if (instantiationData[0] is string text) { PlayerAvatar val = SemiFunc.PlayerAvatarGetFromSteamID(text); ((Component)this).transform.SetParent(((Component)val).transform, false); } if (instantiationData[1] is int num) { laserCooldown = num; laserCooldownTimer = num; } if (instantiationData[2] is int damage) { ((MonoBehaviour)this).StartCoroutine(ApplyDamageDelayed(damage)); } object obj = instantiationData[3]; if (obj is bool) { bool flag = (bool)obj; manualActionEnabled = flag; } } [IteratorStateMachine(typeof(d__21))] private IEnumerator ApplyDamageDelayed(int damage) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__21(0) { <>4__this = this, damage = damage }; } } internal class LessIsMoreBehaviour : MonoBehaviour { private ValuableObject valuableObject; private PhysGrabObjectImpactDetector physGrabObjectImpactDetector; private float realValue; private void Awake() { valuableObject = ((Component)this).GetComponent(); physGrabObjectImpactDetector = ((Component)this).GetComponent(); realValue = valuableObject.dollarValueCurrent; } private void Update() { if ((double)realValue < (double)valuableObject.dollarValueOriginal * 0.15) { physGrabObjectImpactDetector.DestroyObject(true); } } internal void SubtractValue(float value) { realValue -= value; } } internal class TemporaryLevelItemBehaviour : MonoBehaviour { internal PhysGrabObject _physGrabObject; internal string levelName; private void Awake() { _physGrabObject = ((Component)this).GetComponent(); ItemAttributes component = ((Component)this).GetComponent(); if ((Object)(object)component != (Object)null) { component.itemName += " (Temporary)"; } } } internal class TheFloorIsLavaBehaviour : MonoBehaviour { private PlayerAvatar playerAvatar; private Transform physObjectStander; private LayerMask layerMask = LayerMask.op_Implicit(~LayerMask.GetMask(new string[2] { "Player", "CollisionCheck" })); internal float immunityTimer; private float groundedTimer; private float damageCooldownTimer; private readonly float damageCooldown = 1f; private readonly float damageInterval = 1f; private readonly float raycastDistance = 0.5f; internal int damagePerTick = MutatorSettings.TheFloorIsLava.DamagePerTick; internal bool usePercentageDamage = MutatorSettings.TheFloorIsLava.UsePercentageDamage; private int playerOnlyCollisionLayer; internal bool Immune { get; set; } private void Start() { playerAvatar = ((Component)this).GetComponent(); physObjectStander = ((Component)playerAvatar).transform.Find("Phys Object Stander"); playerOnlyCollisionLayer = LayerMask.NameToLayer("PlayerOnlyCollision"); } private void Update() { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Invalid comparison between Unknown and I4 if (!LevelGenerator.Instance.Generated || playerAvatar.RoomVolumeCheck.inTruck || playerAvatar.RoomVolumeCheck.inExtractionPoint) { return; } if (immunityTimer > 0f) { immunityTimer -= Time.deltaTime; } else { if (Immune) { return; } damageCooldownTimer += Time.deltaTime; groundedTimer += Time.deltaTime; bool flag = false; RaycastHit val = default(RaycastHit); if (Physics.Raycast(physObjectStander.position, Vector3.down, ref val, raycastDistance, LayerMask.op_Implicit(layerMask))) { Collider collider = ((RaycastHit)(ref val)).collider; if (((Component)collider).CompareTag("Floor") || ((Component)collider).CompareTag("Wall")) { flag = true; } else if (((Component)collider).CompareTag("Untagged") && ((int)playerAvatar.MaterialTrigger.LastMaterialType == 5 || ((Component)((RaycastHit)(ref val)).collider).gameObject.layer == playerOnlyCollisionLayer)) { flag = true; } } if (flag && groundedTimer >= damageInterval && damageCooldownTimer >= damageCooldown) { int num = damagePerTick; if (usePercentageDamage) { num = (int)MathF.Ceiling((float)playerAvatar.playerHealth.maxHealth * ((float)num / 100f)); } playerAvatar.playerHealth.Hurt(num, false, -1, false); groundedTimer = 0f; damageCooldownTimer = 0f; } } } } } namespace Mutators.Mutators.Behaviours.UI { internal class MutatorAnnouncingBehaviour : SemiUI { private TextMeshProUGUI Text; internal static MutatorAnnouncingBehaviour instance; private bool _isVisible = true; private float _showTimer = (IsToggleWithDescription() ? RepoMutators.Settings.MutatorDescriptionInitialDisplayTime : 0f); public override void Start() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) base.animateTheEntireObject = true; base.hidePosition = new Vector2(300f, 0f); ((SemiUI)this).Start(); Text = ((Component)this).GetComponent(); instance = this; ((TMP_Text)Text).text = MutatorManager.Instance.CurrentMutator.Name; } public override void Update() { //IL_0081: Unknown result type (might be due to invalid IL or missing references) ((SemiUI)this).Update(); if (RepoMutators.Settings.MutatorDisplayToggleType == ModSettings.MutatorNameToggleType.WithDescription) { ((SemiUI)this).Hide(); if (_showTimer > 0f) { if (!RepoMutators.Settings.MutatorDescriptionPinned) { _showTimer -= Time.deltaTime; } if ((Object)(object)MenuPageEsc.instance?.menuPage == (Object)null) { ((SemiUI)this).Show(); } } } else { if (!ChatManager.instance.StateIsActive() && RepoMutators.Settings.MutatorDisplayToggleType == ModSettings.MutatorNameToggleType.Keybind && Input.GetKeyDown(RepoMutators.Settings.MutatorDisplayToggleKey)) { _isVisible = !_isVisible; } if (!_isVisible) { ((SemiUI)this).Hide(); } } } private static bool IsToggleWithDescription() { return RepoMutators.Settings.MutatorDisplayToggleType == ModSettings.MutatorNameToggleType.WithDescription; } } public class MutatorDescriptionAnnouncingBehaviour : SemiUI { private float _showTimer = RepoMutators.Settings.MutatorDescriptionInitialDisplayTime; public TextMeshProUGUI Text { get; private set; } public static MutatorDescriptionAnnouncingBehaviour Instance { get; private set; } public override void Start() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) base.animateTheEntireObject = true; base.hidePosition = new Vector2(400f, 0f); ((SemiUI)this).Start(); Text = ((Component)this).GetComponent(); Instance = this; ((TMP_Text)Text).text = GetDescription(); } public override void Update() { ((SemiUI)this).Update(); ((SemiUI)this).Hide(); if (_showTimer > 0f) { if (!RepoMutators.Settings.MutatorDescriptionPinned) { _showTimer -= Time.deltaTime; } if ((Object)(object)MenuPageEsc.instance?.menuPage == (Object)null) { ((SemiUI)this).Show(); } } } public void ShowDescription(float showTimerOverride = 0f) { ((SemiUI)this).SemiUISpringShakeY(20f, 10f, 0.3f); ((SemiUI)this).SemiUISpringScale(0.4f, 5f, 0.2f); float mutatorDescriptionInitialDisplayTime = RepoMutators.Settings.MutatorDescriptionInitialDisplayTime; _showTimer = ((showTimerOverride > mutatorDescriptionInitialDisplayTime) ? showTimerOverride : mutatorDescriptionInitialDisplayTime); } private string GetDescription() { //IL_002a: 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) string description = MutatorManager.Instance.CurrentMutator.Description; if (!description.Contains("{specialActionKey}")) { return description; } KeyCode specialActionKey = RepoMutators.Settings.SpecialActionKey; return description.Replace("{specialActionKey}", ((object)(KeyCode)(ref specialActionKey)).ToString()); } } public class SpecialActionAnnouncingBehaviour : SemiUI { internal static SpecialActionAnnouncingBehaviour instance; public TextMeshProUGUI Text { get; private set; } public TextMeshProUGUI TextMax { get; private set; } public override void Start() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) base.animateTheEntireObject = true; base.hidePosition = new Vector2(-140f, 0f); base.doNotDisable = new List(); ((SemiUI)this).Start(); Text = ((Component)this).GetComponent(); TextMax = ((Component)((Component)this).transform.Find("SpecialActionMax")).GetComponent(); instance = this; ((TMP_Text)Text).text = string.Empty; } public override void Update() { ((SemiUI)this).Update(); } } public class TargetPlayerAnnouncingBehaviour : SemiUI { public static TargetPlayerAnnouncingBehaviour instance; public TextMeshProUGUI Text { get; private set; } public void Awake() { instance = this; ((SemiUI)instance).doNotDisable = new List(); Text = ((Component)this).GetComponent(); } public override void Start() { ((SemiUI)this).Start(); } public override void Update() { ((SemiUI)this).Update(); if (((TMP_Text)Text).text == string.Empty) { ((SemiUI)this).Hide(); } } } } namespace Mutators.Mutators.Behaviours.Marker { internal class SealedAwayMarkerBehaviour : MonoBehaviour { } internal class VolatileCargoMarkerBehaviour : MonoBehaviour { } } namespace Mutators.Mutators.Behaviours.Custom { internal class PlayerIgnoringHurtCollider : HurtCollider { internal readonly ISet ignoredPlayers = new HashSet(); } } namespace Mutators.Managers { public class LevelManager { private static readonly IDictionary RemovedLevels = new Dictionary(StringComparer.OrdinalIgnoreCase); public static LevelManager Instance { get; private set; } = new LevelManager(); public void RemoveLevels(ICollection levelsToRemove) { if (levelsToRemove.Count == 0) { return; } List levels = RunManager.instance.levels; ISet removeSet = new HashSet(levelsToRemove, StringComparer.OrdinalIgnoreCase); List list = levels.FindAll((Level level) => removeSet.Contains(((Object)level).name)); foreach (Level item in list) { RemovedLevels[((Object)item).name] = item; } levels.RemoveAll((Level level) => removeSet.Contains(((Object)level).name)); } public void RestoreLevels() { if (RemovedLevels.Count == 0) { return; } List levels = RunManager.instance.levels; ISet existingNames = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (Level item in levels) { existingNames.Add(((Object)item).name); } levels.AddRange(RemovedLevels.Values.Where((Level level) => existingNames.Add(((Object)level).name))); foreach (Level value in RemovedLevels.Values) { RepoMutators.Logger.LogInfo((object)("Restoring level " + ((Object)value).name)); } foreach (Level level in RunManager.instance.levels) { RepoMutators.Logger.LogInfo((object)("Level " + ((Object)level).name + " is now active")); } RemovedLevels.Clear(); } } public class MutatorManager { private static readonly NopMutator _nopMutator = new NopMutator(MutatorSettings.NopMutator); private readonly IDictionary _mutators = new Dictionary(); private MutatorsGameState _gameState; private IMutator? _previousMutator; private int _repeatCount; private bool _initialized; public static MutatorManager Instance { get; private set; } = new MutatorManager(); public IReadOnlyDictionary RegisteredMutators => new ReadOnlyDictionary(_mutators); public IMutator CurrentMutator { get; internal set; } = _nopMutator; public Action GameStateChanged { get; set; } public MutatorsGameState GameState { get { return _gameState; } internal set { if (_gameState != value) { _gameState = value; GameStateChanged?.Invoke(value); } } } internal void InitializeDefaultMutators() { if (_initialized) { RepoMutators.Logger.LogWarning((object)"Tried to initialize default mutators, but these were already initialized!"); return; } List list = new List(19); list.Add(_nopMutator); list.Add(new Mutator(MutatorSettings.OutWithABang, typeof(OutWithABangPatch))); list.Add(new Mutator(MutatorSettings.ApolloEleven, typeof(ApolloElevenPatch))); list.Add(new Mutator(MutatorSettings.UltraViolence, typeof(UltraViolencePatch))); list.Add(new Mutator(MutatorSettings.DuckThis, typeof(DuckThisPatch))); list.Add(new Mutator(MutatorSettings.OneShotOneKill, typeof(OneShotOneKillPatch))); list.Add(new Mutator(MutatorSettings.ProtectThePresident, typeof(ProtectThePresidentPatch), new List>(1) { (Func)SemiFunc.IsMultiplayer })); list.Add(new Mutator(MutatorSettings.RustyServos, typeof(RustyServosPatch))); list.Add(new Mutator(MutatorSettings.HandleWithCare, typeof(HandleWithCarePatch))); list.Add(new Mutator(MutatorSettings.HuntingSeason, typeof(HuntingSeasonPatch))); list.Add(new Mutator(MutatorSettings.ThereCanOnlyBeOne, typeof(ThereCanOnlyBeOnePatch))); list.Add(new Mutator(MutatorSettings.VolatileCargo, typeof(VolatileCargoPatch))); list.Add(new Mutator(MutatorSettings.SealedAway, typeof(SealedAwayPatch))); list.Add(new Mutator(MutatorSettings.ProtectTheWeak, typeof(ProtectTheWeakPatch), new List>(1) { (Func)SemiFunc.IsMultiplayer })); list.Add(new Mutator(MutatorSettings.FiringMyLaser, typeof(FiringMyLaserPatch), null, specialActionOverlay: true)); list.Add(new Mutator(MutatorSettings.Voiceover, typeof(VoiceoverPatch), new List>(1) { (Func)SemiFunc.IsMultiplayer })); list.Add(new Mutator(MutatorSettings.TheFloorIsLava, typeof(TheFloorIsLavaPatch))); list.Add(new Mutator(MutatorSettings.LessIsMore, typeof(LessIsMorePatch))); list.Add(new Mutator(MutatorSettings.Amalgam, typeof(AmalgamPatch))); IList list2 = list; LinqExtensions.ForEach((IEnumerable)list2, (Action)delegate(IMutator mutator) { _mutators[mutator.Name] = mutator; }); GameStateChanged = (Action)Delegate.Combine(GameStateChanged, (Action)delegate(MutatorsGameState gameState) { if (gameState == MutatorsGameState.LevelReady) { LevelManager.Instance.RestoreLevels(); } }); _initialized = true; } public void RegisterMutator(IMutator mutator) { _mutators.Add(mutator.Name, mutator); } public void UnregisterMutator(IMutator mutator) { if (_mutators.Remove(mutator.Name) && mutator.Active) { mutator.Unpatch(); } } public void UnregisterMutator(string name) { if (_mutators.TryGetValue(name, out IMutator value)) { UnregisterMutator(value); } } internal void SetActiveMutator(string name, bool applyPatchNow = true) { LinqExtensions.ForEach(RegisteredMutators.Values.Where((IMutator mutator) => mutator.Active), (Action)delegate(IMutator mutator) { mutator.Unpatch(); }); if (_mutators.TryGetValue(name, out IMutator value)) { CurrentMutator = value; RepoMutators.Logger.LogDebug((object)("Mutator " + name + " set as active")); if (applyPatchNow) { CurrentMutator.Patch(); } } else { RepoMutators.Logger.LogWarning((object)("Tried to active unknown mutator: " + name + ".")); RepoMutators.Logger.LogWarning((object)"You might be out of sync if you are not the host!"); } } internal IMutator GetWeightedMutator() { IList list = (from mutator in _mutators.Values where mutator.Settings.IsEligibleForSelection() where mutator.Conditions.All((Func condition) => condition()) select mutator).ToList(); float num = _previousMutator?.Settings.Weight ?? 0; float num2 = list.Sum((IMutator item) => item.Settings.Weight); if (num > 0f && num2 > 0f) { float num3 = 0.1f; float num4 = Mathf.Pow(num / num2, (float)(_repeatCount + 1)); if (num4 < num3) { RepoMutators.Logger.LogDebug((object)("Cannot pick " + (_previousMutator?.Name ?? "None") + ", threshold reached")); list = list.Where((IMutator m) => m != _previousMutator).ToList(); num2 = list.Sum((IMutator m) => m.Settings.Weight); } } if (num2 <= 0f) { RepoMutators.Logger.LogWarning((object)$"Fell back to None mutator, invalid total weight: {num2}"); return _nopMutator; } float num5 = Random.Range(0f, num2); float num6 = 0f; foreach (IMutator item in list) { num6 += (float)item.Settings.Weight; if (num5 <= num6) { if (item == _previousMutator) { _repeatCount++; } else { _previousMutator = item; _repeatCount = 1; } return item; } } RepoMutators.Logger.LogWarning((object)"Fell back to None mutator, mutator selection failed"); return _nopMutator; } } } namespace Mutators.Extensions { public static class DictionaryExtensions { public static T? Get(this IDictionary dictionary, string key) { if (dictionary.TryGetValue(key, out object value)) { return (T)value; } return default(T); } public static T? Get(this IReadOnlyDictionary dictionary, string key) { if (dictionary.TryGetValue(key, out object value)) { return (T)value; } return default(T); } public static List GetAsList(this IDictionary metadata, string key) { return ((IReadOnlyDictionary)metadata).GetAsList(key); } public static List GetAsList(this IReadOnlyDictionary metadata, string key) { if (metadata.TryGetValue(key, out object value)) { if (value is List result) { return result; } if (value is IEnumerable source) { return source.Select((object o) => (o is T) ? ((T)o) : ((T)Convert.ChangeType(o, typeof(T)))).ToList(); } if (value is T item) { return new List { item }; } } return new List(); } public static IDictionary DeepMergedWith(this IDictionary dict1, IDictionary dict2) { Dictionary dictionary = new Dictionary(dict1); foreach (KeyValuePair item in dict2) { if (dictionary.TryGetValue(item.Key, out var value) && value is IDictionary dict3 && item.Value is IDictionary dict4) { dictionary[item.Key] = dict3.DeepMergedWith(dict4); } else { dictionary[item.Key] = item.Value; } } return dictionary; } public static IDictionary WithMutator(this IDictionary dictionary, string mutatorName) { return new Dictionary { { mutatorName, dictionary } }; } public static IDictionary WithMutator(this IDictionary dictionary, IMutator mutator) { return new Dictionary { { mutator.Name, dictionary } }; } } internal static class EnemyDirectorExtensions { internal static void DisableEnemies(this EnemyDirector enemyDirector, Predicate? condition = null) { Predicate condition2 = condition; AbstractMutatorSettings settings = MutatorManager.Instance.CurrentMutator.Settings; EnemyDisablingMutatorSettings enemyDisablingMutatorSettings = settings as EnemyDisablingMutatorSettings; Predicate predicate; if (enemyDisablingMutatorSettings != null) { predicate = delegate(EnemySetup setup) { Predicate predicate2 = condition2; return (predicate2 != null && predicate2(setup)) || setup.spawnObjects.Any((PrefabRef so) => enemyDisablingMutatorSettings.ExcludedEnemies.Any((string excluded) => excluded.Equals(so.Prefab.GetComponent()?.enemyName, StringComparison.OrdinalIgnoreCase))); }; } else { predicate = condition2 ?? ((Predicate)((EnemySetup _) => true)); } IList list = (from setup in enemyDirector.enemiesDifficulty1.Concat(enemyDirector.enemiesDifficulty2).Concat(enemyDirector.enemiesDifficulty3) where predicate(setup) select setup).ToList(); foreach (EnemySetup item in list) { enemyDirector.enemiesDifficulty1.Remove(item); enemyDirector.enemiesDifficulty2.Remove(item); enemyDirector.enemiesDifficulty3.Remove(item); } } } internal static class LevelRemovingMutatorSettingsExtensions { private const string TRUCK_LEVEL_NAME = "Level - Lobby"; private static readonly ISet vanillaLevelNames = new HashSet { "Level - Artic", "Level - Manor", "Level - Wizard", "Level - Museum" }; internal static void RemoveLevels(this ILevelRemovingMutatorSettings settings, bool lobbyMenu = false) { RunManager instance = RunManager.instance; if (!lobbyMenu && ((Object)instance.levelCurrent).name != "Level - Lobby") { return; } if (!settings.AllowCustomLevels) { LevelManager.Instance.RemoveLevels(vanillaLevelNames); } if (settings.ExcludedLevels.Count > 0) { ISet levelsToRemove = new HashSet(settings.ExcludedLevels.Select((string level) => (!level.StartsWith("level - ", StringComparison.OrdinalIgnoreCase)) ? ("level - " + level).ToLowerInvariant() : level.ToLowerInvariant())); LevelManager.Instance.RemoveLevels(levelsToRemove); } if (instance.levels.Count == 1) { instance.previousRunLevel = null; } else if (instance.levels.Count == 0) { instance.previousRunLevel = null; RepoMutators.Logger.LogError((object)"Attempted to start a run with 0 available levels, please revisit your mod settings!"); RepoMutators.Logger.LogError((object)"There must be at least one level available to choose from!"); } } } internal static class PhotonHashtableExtensions { internal static Hashtable ToPhotonHashtable(this IDictionary dict) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown Hashtable val = new Hashtable(); foreach (KeyValuePair item in dict) { if (item.Value is IDictionary dict2) { val[(object)item.Key] = dict2.ToPhotonHashtable(); } else if (item.Value is IList list) { val[(object)item.Key] = list.ToPhotonArray(); } else { val[(object)item.Key] = item.Value; } } return val; } private static object[] ToPhotonArray(this IList list) { object[] array = new object[list.Count]; for (int i = 0; i < list.Count; i++) { if (list[i] is IDictionary dict) { array[i] = dict.ToPhotonHashtable(); } else { array[i] = list[i]; } } return array; } internal static IDictionary FromPhotonHashtable(this Hashtable hashtable) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); DictionaryEntryEnumerator enumerator = hashtable.GetEnumerator(); try { while (((DictionaryEntryEnumerator)(ref enumerator)).MoveNext()) { DictionaryEntry current = ((DictionaryEntryEnumerator)(ref enumerator)).Current; if (current.Key is string key) { object value = current.Value; Hashtable val = (Hashtable)((value is Hashtable) ? value : null); if (val != null) { dictionary[key] = val.FromPhotonHashtable(); } else if (value is object[] array) { dictionary[key] = array.FromPhotonArray(); } else { dictionary[key] = value; } } } return dictionary; } finally { ((IDisposable)(DictionaryEntryEnumerator)(ref enumerator)).Dispose(); } } private static IList FromPhotonArray(this object[] array) { IList list = new List(); foreach (object obj in array) { Hashtable val = (Hashtable)((obj is Hashtable) ? obj : null); if (val != null) { list.Add(val.FromPhotonHashtable()); } else { list.Add(obj); } } return list; } } } namespace Mutators.Enums { public enum MutatorsGameState { None = 0, Shop = 5, LevelReady = 29, LevelGenerated = 30 } }