using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using Unity.VisualScripting; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("BLOKBUSTR")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0+5fda5134a38d55a53990e71e93394783a360bc00")] [assembly: AssemblyProduct("LoomConfig")] [assembly: AssemblyTitle("LoomConfig")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.0.0")] [module: UnverifiableCode] 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; } } } namespace LoomConfig { [HarmonyPatch(typeof(EnemyShadowAnim))] internal static class EnemyShadowAnimPatch { [HarmonyPrefix] [HarmonyPatch("Update")] internal static void UpdatePrefix(EnemyShadowAnim __instance) { float value = LoomConfig.configIdleLoopVolume.Value; if (!Mathf.Approximately(value, 0.1f) || !Mathf.Approximately(value, __instance.idleLoop.Volume)) { __instance.idleLoop.Volume = value; } } [HarmonyPrefix] [HarmonyPatch("playTargetedSound")] internal static bool PlayTargetedSoundPrefix(EnemyShadowAnim __instance) { float value = LoomConfig.configTargetedVolume.Value; if (value <= 0f) { return false; } if (!Mathf.Approximately(value, 0.5f) || !Mathf.Approximately(value, __instance.targeted.Volume)) { __instance.targeted.Volume = value; if (value < 0.2f) { __instance.targeted.VolumeRandom = value * 0.5f; } } return true; } [HarmonyPrefix] [HarmonyPatch("PlayUntargetedSound")] internal static bool PlayUntargetedSoundPrefix(EnemyShadowAnim __instance) { float value = LoomConfig.configNotTargetedVolume.Value; if (value <= 0f) { return false; } if (!Mathf.Approximately(value, 0.5f) || !Mathf.Approximately(value, __instance.notTargeted.Volume)) { __instance.notTargeted.Volume = value; if (value < 0.2f) { __instance.notTargeted.VolumeRandom = value * 0.5f; } } return true; } } [HarmonyPatch(typeof(EnemyShadow))] internal static class EnemyShadowPatch { [HarmonyPostfix] [HarmonyPatch("Awake")] internal static void AwakePostfix(EnemyShadow __instance) { LoomConfig.Debug("Applying custom properties to new Loom, if any", (MonoBehaviour?)(object)__instance); EnemyShadowUtil enemyShadowUtil = ComponentHolderProtocol.AddComponent((Object)(object)__instance); enemyShadowUtil.enemyShadow = __instance; ((MonoBehaviour)enemyShadowUtil).StartCoroutine(enemyShadowUtil.SetDelayedProperties()); if (SemiFunc.IsNotMasterClient()) { return; } int value = LoomConfig.configMaxHealth.Value; if (value != 500) { EnemyHealth component = ((Component)__instance).GetComponent(); if (Object.op_Implicit((Object)(object)component)) { component.health = value; component.healthCurrent = value; LoomConfig.Debug($"Changed health to {value}", (MonoBehaviour?)(object)__instance); } else { LoomConfig.Error("EnemyHealth component not found!", (MonoBehaviour?)(object)__instance); } } int value2 = LoomConfig.configClapEnemyDamage.Value; if (value2 != 20) { __instance.hurtColliderScript.enemyDamage = value2; LoomConfig.Debug($"Changed clap enemy damage to {value2}", (MonoBehaviour?)(object)__instance); } } [HarmonyPostfix] [HarmonyPatch("StateLeave")] internal static void StateLeavePostfix(EnemyShadow __instance) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)__instance.currentState == 8) { float value = LoomConfig.configMovementSpeedLeave.Value; if (!Mathf.Approximately(value, 2.5f)) { __instance.enemy.NavMeshAgent.OverrideAgent(value, 30f, 0.1f); } } } [HarmonyPrefix] [HarmonyPatch("BendLogic")] internal static void BendLogicPrefix(EnemyShadow __instance) { float value = LoomConfig.configPlayerLookDistance.Value; if (!Mathf.Approximately(value, 7f) && !Mathf.Approximately(value, __instance.distanceFromPlayer)) { __instance.closeEnoughToLook = __instance.distanceFromPlayer < value; } } } [HarmonyPatch(typeof(EnemyShadowScreenVeinEffect))] internal static class EnemyShadowScreenVeinEffectPatch { [HarmonyPrefix] [HarmonyPatch("Start")] internal static void StartPrefix(EnemyShadowScreenVeinEffect __instance) { if (!LoomConfig.configScreenEffectShowHands.Value) { ((Renderer)__instance.handSpriteRenderer).enabled = false; } if (!LoomConfig.configScreenEffectShowVeins.Value) { ((Renderer)__instance.veinSpriteRenderer).enabled = false; } } } public class EnemyShadowUtil : MonoBehaviour { [CompilerGenerated] private sealed class d__1 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public EnemyShadowUtil <>4__this; private int 5__1; private float 5__2; 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; break; case 2: <>1__state = -1; break; } if (!Object.op_Implicit((Object)(object)<>4__this.enemyShadow.enemy.NavMeshAgent?.Agent)) { LoomConfig.Debug("Delaying other properties, NavMeshAgent is not fully set up", (MonoBehaviour?)(object)<>4__this.enemyShadow); <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 2; return true; } 5__1 = LoomConfig.configClapPlayerDamage.Value; if (SemiFunc.IsNotMasterClient()) { 5__1 = LoomProperties.GetClapPlayerDamage(); } if (5__1 != 100) { <>4__this.enemyShadow.hurtColliderScript.playerDamage = 5__1; LoomConfig.Debug($"Changed clap player damage to {5__1}", (MonoBehaviour?)(object)<>4__this.enemyShadow); } if (SemiFunc.IsNotMasterClient()) { return false; } 5__2 = LoomConfig.configMovementSpeed.Value; if (!Mathf.Approximately(5__2, 1.2f)) { <>4__this.enemyShadow.enemy.NavMeshAgent.Agent.speed = 5__2; <>4__this.enemyShadow.enemy.NavMeshAgent.DefaultSpeed = 5__2; LoomConfig.Debug($"Changed movement speed to {5__2}", (MonoBehaviour?)(object)<>4__this.enemyShadow); } 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 EnemyShadow enemyShadow; [IteratorStateMachine(typeof(d__1))] public IEnumerator SetDelayedProperties() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__1(0) { <>4__this = this }; } } [BepInPlugin("BLOKBUSTR.LoomConfig", "LoomConfig", "1.1.0")] public class LoomConfig : BaseUnityPlugin { public static ConfigEntry configMaxHealth; public static ConfigEntry configClapPlayerDamage; public static ConfigEntry configClapEnemyDamage; public static ConfigEntry configMovementSpeed; public static ConfigEntry configMovementSpeedLeave; public static ConfigEntry configPlayerLookDistance; public static ConfigEntry configScreenEffectShowHands; public static ConfigEntry configScreenEffectShowVeins; public static ConfigEntry configIdleLoopVolume; public static ConfigEntry configTargetedVolume; public static ConfigEntry configNotTargetedVolume; private static ConfigEntry configEnableDebug; internal static LoomConfig Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; set; } private void Awake() { Instance = this; ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; RegisterConfig(); Patch(); Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!"); Debug("Debug logging is enabled."); } private void RegisterConfig() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Expected O, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Expected O, but got Unknown //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Expected O, but got Unknown //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Expected O, but got Unknown //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Expected O, but got Unknown //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Expected O, but got Unknown configMaxHealth = ((BaseUnityPlugin)this).Config.Bind("Logic", "MaxHealth", 500, new ConfigDescription("The maximum health of Loom.", (AcceptableValueBase)(object)new AcceptableValueRange(10, 1000), Array.Empty())); configClapPlayerDamage = ((BaseUnityPlugin)this).Config.Bind("Logic", "ClapPlayerDamage", 100, new ConfigDescription("The amount of damage dealt to players by the clap attack. This setting will be synced to all clients in multiplayer.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 1000), Array.Empty())); configClapEnemyDamage = ((BaseUnityPlugin)this).Config.Bind("Logic", "ClapEnemyDamage", 20, new ConfigDescription("The amount of damage dealt to enemies by the clap attack.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 1000), Array.Empty())); configMovementSpeed = ((BaseUnityPlugin)this).Config.Bind("Logic", "MovementSpeed", 1.2f, new ConfigDescription("The base movement speed of Loom.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 4f), Array.Empty())); configMovementSpeedLeave = ((BaseUnityPlugin)this).Config.Bind("Logic", "MovementSpeedLeave", 2.5f, new ConfigDescription("The movement speed of Loom in her Leave state.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 4f), Array.Empty())); configPlayerLookDistance = ((BaseUnityPlugin)this).Config.Bind("Visuals", "PlayerLookDistance", 7f, new ConfigDescription("The maximum distance at which Loom will look at the player.", (AcceptableValueBase)(object)new AcceptableValueRange(5f, 15f), Array.Empty())); configScreenEffectShowHands = ((BaseUnityPlugin)this).Config.Bind("Visuals", "ScreenEffectShowHands", true, "Whether to show the hand layer in the \"targeted\" screen effect."); configScreenEffectShowVeins = ((BaseUnityPlugin)this).Config.Bind("Visuals", "ScreenEffectShowVeins", true, "Whether to show the vein layer in the \"targeted\" screen effect."); configIdleLoopVolume = ((BaseUnityPlugin)this).Config.Bind("Audio", "IdleLoopVolume", 0.1f, new ConfigDescription("The volume of the \"idleLoop\" sound.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 0.2f), Array.Empty())); configTargetedVolume = ((BaseUnityPlugin)this).Config.Bind("Audio", "TargetedVolume", 0.5f, new ConfigDescription("The volume of the \"targeted\" sound, played when Loom begins to target you.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); configNotTargetedVolume = ((BaseUnityPlugin)this).Config.Bind("Audio", "NotTargetedVolume", 0.5f, new ConfigDescription("The volume of the \"notTargeted\" sound, played when Loom loses interest in you.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); configEnableDebug = ((BaseUnityPlugin)this).Config.Bind("Debug", "EnableDebug", false, "Whether to enable debug logging. Keep this disabled for normal gameplay."); } internal void Patch() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0026: Expected O, but got Unknown if (Harmony == null) { Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; Harmony = val; } Harmony.PatchAll(); } internal static void Debug(string message, MonoBehaviour? instance = null) { if (configEnableDebug.Value) { Logger.LogDebug((object)(Object.op_Implicit((Object)(object)instance) ? (((object)instance)?.ToString() + ": " + message) : message)); } } internal static void Error(string message, MonoBehaviour? instance = null) { Logger.LogDebug((object)(Object.op_Implicit((Object)(object)instance) ? (((object)instance)?.ToString() + ": " + message) : message)); } } public static class LoomProperties { internal const string LOOM_CLAP_PLAYER_DAMAGE = "LoomClapPlayerDamage"; public static void SetLoomProperties() { //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_0071: Expected O, but got Unknown //IL_0079: Expected O, but got Unknown if (!SemiFunc.IsNotMasterClient() && SemiFunc.IsMultiplayer()) { int value = LoomConfig.configClapPlayerDamage.Value; if (value == GetClapPlayerDamage()) { LoomConfig.Debug("playerDamage is the same, no need to sync"); return; } LoomConfig.Debug($"Setting Custom Room (Loom) Properties | playerDamage: {value}"); Room currentRoom = PhotonNetwork.CurrentRoom; Hashtable val = new Hashtable(); ((Dictionary)val).Add((object)"LoomClapPlayerDamage", (object)value); currentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } public static object? GetLoomProperties(string key) { if (!((Dictionary)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).ContainsKey((object)key)) { return null; } object obj = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties[(object)key]; LoomConfig.Debug($"Getting Custom Room (Loom) Properties | key: {key} | damage: {obj}"); return obj; } public static int GetClapPlayerDamage() { object loomProperties = GetLoomProperties("LoomClapPlayerDamage"); return (loomProperties == null) ? (-1) : ((int)loomProperties); } } [HarmonyPatch(typeof(RunManager))] internal static class RunManagerHook { [HarmonyPostfix] [HarmonyPatch("ChangeLevel")] public static void ChangeLevelPostfix(RunManager __instance, bool _levelFailed) { if (!_levelFailed && !SemiFunc.IsLevelArena(RunManager.instance.levelCurrent)) { LoomProperties.SetLoomProperties(); } } } }