Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ScopophobiaSnapPatch v1.0.1
ScopoSnapPatch.dll
Decompiled 6 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization.Formatters.Binary; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LCSoundTool; using LethalSnapProject; using Microsoft.CodeAnalysis; using ScopoSnapPatch; using ShyGuy.AI; using Unity.Collections; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyCompany("ScopoSnapPatch")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ScopoSnapPatch")] [assembly: AssemblyTitle("ScopoSnapPatch")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } [Serializable] public class CustomConfig : SyncedInstance<CustomConfig> { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnRequestSync; public static HandleNamedMessageDelegate <1>__OnReceiveSync; } public static ConfigEntry<bool> DebugMode; public static ConfigEntry<int> calmPhotoWorth; public static ConfigEntry<bool> calmPhotoUnique; public static ConfigEntry<int> triggeredPhotoWorth; public static ConfigEntry<bool> triggeredPhotoUnique; public static ConfigEntry<int> angryPhotoWorth; public static ConfigEntry<bool> angryPhotoUnique; public static ConfigEntry<float> photoAlertVolume; public static ConfigEntry<bool> enableEnragement; public static ConfigEntry<int> enrageChange; public CustomConfig(ConfigFile cfg) { InitInstance(this); calmPhotoWorth = cfg.Bind<int>("Gameplay", "Calm Photo value", 150, "How much money should a calm state SPC-096 photo be worth? Unaffected by monster multiplier config"); calmPhotoUnique = cfg.Bind<bool>("Gameplay", "Calm Photo Unique", false, "Can you take multiple photos of SPC-096 and still get money while hes calm?"); triggeredPhotoWorth = cfg.Bind<int>("Gameplay", "Triggered Photo value", 300, "How much money should a triggered/upset state SPC-096 photo be worth? Unaffected by monster multiplier config"); triggeredPhotoUnique = cfg.Bind<bool>("Gameplay", "Triggered Photo Unique", true, "Can you take multiple photos of SPC-096 and still get money while hes triggered?"); angryPhotoWorth = cfg.Bind<int>("Gameplay", "Raging Photo value", 600, "How much money should a raging/chasing SPC-096 photo be worth? Unaffected by monster multiplier config"); angryPhotoUnique = cfg.Bind<bool>("Gameplay", "Raging Photo Unique", true, "Can you take multiple photos of SPC-096 and still get money while hes Raging?"); enableEnragement = cfg.Bind<bool>("Enrage", "Enable Photo Enragement", true, "Should taking a photo of SPC-096 make him more angry?"); enrageChange = cfg.Bind<int>("Enrage", "Enragement Change", 2, "How much angrier should SPC-096 get when photographed? ( remaining trigger time = trigger time / Enragement Change)"); photoAlertVolume = cfg.Bind<float>("Audio", "Photo Alert Volume", 1.8f, "Volume multiplier for the photo alert sound effect."); DebugMode = cfg.Bind<bool>("Debug", "debugMode", false, "Enable more logging for troubleshooting."); } public static void RequestSync() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!SyncedInstance<CustomConfig>.IsClient) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(SyncedInstance<CustomConfig>.IntSize, (Allocator)2, -1); try { SyncedInstance<CustomConfig>.MessageManager.SendNamedMessage("ScopoSnap_OnRequestConfigSync", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } public static void OnRequestSync(ulong clientId, FastBufferReader _) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (!SyncedInstance<CustomConfig>.IsHost) { return; } Plugin.Log.LogInfo((object)$"Config sync request received from client: {clientId}"); byte[] array = SyncedInstance<CustomConfig>.SerializeToBytes(SyncedInstance<CustomConfig>.Instance); int num = array.Length; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(num + SyncedInstance<CustomConfig>.IntSize, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0); SyncedInstance<CustomConfig>.MessageManager.SendNamedMessage("ScopoSnap_OnReceiveConfigSync", clientId, val, (NetworkDelivery)3); } catch (Exception arg) { Plugin.Log.LogInfo((object)$"Error occurred syncing config with client: {clientId}\n{arg}"); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } public static void OnReceiveSync(ulong _, FastBufferReader reader) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (!((FastBufferReader)(ref reader)).TryBeginRead(SyncedInstance<CustomConfig>.IntSize)) { Plugin.Log.LogError((object)"Config sync error: Could not begin reading buffer."); return; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives)); if (!((FastBufferReader)(ref reader)).TryBeginRead(num)) { Plugin.Log.LogError((object)"Config sync error: Host could not sync."); return; } byte[] data = new byte[num]; ((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0); SyncedInstance<CustomConfig>.SyncInstance(data); Plugin.Log.LogInfo((object)"Successfully synced config with host."); } [HarmonyPostfix] [HarmonyPatch(typeof(GameNetworkManager), "SteamMatchmaking_OnLobbyMemberJoined")] public static void InitializeLocalPlayer() { //IL_0070: 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) //IL_007b: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown Plugin.Log.LogInfo((object)"Trying to sync config files"); if (SyncedInstance<CustomConfig>.IsHost) { CustomMessagingManager messageManager = SyncedInstance<CustomConfig>.MessageManager; object obj = <>O.<0>__OnRequestSync; if (obj == null) { HandleNamedMessageDelegate val = OnRequestSync; <>O.<0>__OnRequestSync = val; obj = (object)val; } messageManager.RegisterNamedMessageHandler("ScopoSnap_OnRequestConfigSync", (HandleNamedMessageDelegate)obj); SyncedInstance<CustomConfig>.Synced = true; return; } SyncedInstance<CustomConfig>.Synced = false; CustomMessagingManager messageManager2 = SyncedInstance<CustomConfig>.MessageManager; object obj2 = <>O.<1>__OnReceiveSync; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnReceiveSync; <>O.<1>__OnReceiveSync = val2; obj2 = (object)val2; } messageManager2.RegisterNamedMessageHandler("ScopoSnap_OnReceiveConfigSync", (HandleNamedMessageDelegate)obj2); RequestSync(); } [HarmonyPostfix] [HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")] public static void PlayerLeave() { Plugin.Log.LogInfo((object)"Trying to reset config file"); SyncedInstance<CustomConfig>.RevertSync(); } } [Serializable] public class SyncedInstance<T> { [NonSerialized] protected static int IntSize = 4; internal static CustomMessagingManager MessageManager => NetworkManager.Singleton.CustomMessagingManager; internal static bool IsClient => NetworkManager.Singleton.IsClient; internal static bool IsHost => NetworkManager.Singleton.IsHost; public static T Default { get; private set; } public static T Instance { get; private set; } public static bool Synced { get; internal set; } protected void InitInstance(T instance) { Default = instance; Instance = instance; IntSize = 4; } internal static void SyncInstance(byte[] data) { Instance = DeserializeFromBytes(data); Synced = true; } internal static void RevertSync() { Instance = Default; Synced = false; } public static byte[] SerializeToBytes(T val) { BinaryFormatter binaryFormatter = new BinaryFormatter(); using MemoryStream memoryStream = new MemoryStream(); try { binaryFormatter.Serialize(memoryStream, val); return memoryStream.ToArray(); } catch (Exception arg) { Plugin.MyLogger.LogError((object)$"Error serializing instance: {arg}"); return null; } } public static T DeserializeFromBytes(byte[] data) { BinaryFormatter binaryFormatter = new BinaryFormatter(); using MemoryStream serializationStream = new MemoryStream(data); try { return (T)binaryFormatter.Deserialize(serializationStream); } catch (Exception arg) { Plugin.MyLogger.LogError((object)$"Error deserializing instance: {arg}"); return default(T); } } } internal static class LCMPluginInfo { public const string PLUGIN_GUID = "ScopoSnapPatch"; public const string PLUGIN_NAME = "ScopoSnapPatch"; public const string PLUGIN_VERSION = "1.0.0"; } namespace ScopoSnapPatch { [BepInPlugin("gulfbones.scoposnappatch", "ScopoSnap Patch", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string GUID = "gulfbones.scoposnappatch"; public const string NAME = "ScopoSnap Patch"; public const string VER = "1.0.0"; internal static ManualLogSource Log = null; private readonly Harmony _harmony = new Harmony("gulfbones.scoposnappatch"); private static Plugin _instance; public static bool DebugMode = true; internal static AudioClip photoAlertSFX; public static CustomConfig MyConfig { get; internal set; } private void Awake() { if ((Object)(object)_instance == (Object)null) { _instance = this; } MyConfig = new CustomConfig(((BaseUnityPlugin)this).Config); DebugMode = CustomConfig.DebugMode.Value; Log = ((BaseUnityPlugin)this).Logger; if (DebugMode) { Log.LogInfo((object)"Debug logging is enabled for this plugin."); } photoAlertSFX = SoundTool.GetAudioClip(Path.GetDirectoryName(((BaseUnityPlugin)_instance).Info.Location), "096_Angered.ogg"); if ((Object)(object)photoAlertSFX == (Object)null) { Log.LogError((object)"Failed to load sound effect 096_Angered.ogg from embedded resources."); } else { Log.LogInfo((object)"Successfully loaded sound effect 096_Angered.ogg from embedded resources."); } SnapReactPatch.Apply(_harmony); Log.LogInfo((object)"Plugin ScopoSnap Patch version 1.0.0 is loaded!"); } } internal class SnapReactPatch { public static Dictionary<string, float> scopoCustomValues = new Dictionary<string, float> { { "shyguy_calm", CustomConfig.calmPhotoWorth.Value }, { "shyguy_triggered", CustomConfig.triggeredPhotoWorth.Value }, { "shyguy_angry", CustomConfig.angryPhotoWorth.Value } }; public static void Apply(Harmony harmony) { //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Expected O, but got Unknown //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Expected O, but got Unknown Type type = AccessTools.TypeByName("LethalSnapProject.Behaviour.MonsterReact"); MethodInfo methodInfo = AccessTools.Method(type, "ReactToFlash", (Type[])null, (Type[])null); Type type2 = AccessTools.TypeByName("LethalSnapProject.Behaviour.PictureHelper"); MethodInfo methodInfo2 = AccessTools.Method(type2, "ComputePictureValue", (Type[])null, (Type[])null); Type type3 = AccessTools.TypeByName("LethalSnapProject.Behaviour.PictureHelper"); MethodInfo methodInfo3 = AccessTools.Method(type3, "GetMonsterScore", (Type[])null, (Type[])null); foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type2)) { Plugin.Log.LogInfo((object)("Found method: " + declaredMethod.Name)); } if (type == null || methodInfo == null) { Plugin.Log.LogError((object)"Failed to find MonsterReact.ReactToFlash() for patching."); } else { if (Plugin.DebugMode) { Plugin.Log.LogInfo((object)("type: " + type?.ToString() + "| Method: " + methodInfo)); } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(SnapReactPatch), "SnapAngerPatch", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (type2 == null || methodInfo2 == null) { Plugin.Log.LogError((object)"Failed to find PictureHelper.ComputePictureValue() method for patching."); } else { if (Plugin.DebugMode) { Plugin.Log.LogInfo((object)("type: " + type2?.ToString() + "| Method: " + methodInfo2)); } harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(SnapReactPatch), "SnapValuePatch", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (type3 == null || methodInfo3 == null) { Plugin.Log.LogError((object)"Failed to find PictureHelper.GetMonsterScore() method for patching."); return; } if (Plugin.DebugMode) { Plugin.Log.LogInfo((object)("type: " + type3?.ToString() + "| Method: " + methodInfo3)); } harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(typeof(SnapReactPatch), "MonsterScorePatch", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } public static void SnapAngerPatch(ref PlayerControllerB owner, ref EnemyAI enemy) { PlayerControllerB val = owner; EnemyAI val2 = enemy; string text = val2.enemyType.enemyName.ToLower(); if (!(text == "shy guy") || !CustomConfig.enableEnragement.Value) { return; } ShyGuyAI val3 = (ShyGuyAI)(object)((val2 is ShyGuyAI) ? val2 : null); if ((Object)(object)val3 == (Object)null) { return; } if (((EnemyAI)val3).currentBehaviourStateIndex != 1) { if (Plugin.DebugMode) { Plugin.Log.LogWarning((object)("Shy guy was in state " + ((EnemyAI)val3).currentBehaviourStateIndex + " therefore no timer change")); } return; } Plugin.Log.LogInfo((object)"Shy guy got Angrier!"); FieldInfo fieldInfo = AccessTools.Field(typeof(ShyGuyAI), "triggerTime"); float num = (float)fieldInfo.GetValue(val3); num /= (float)CustomConfig.enrageChange.Value; if (Plugin.DebugMode) { Plugin.Log.LogInfo((object)("Shyguy timer reduced to: " + num)); } fieldInfo.SetValue(val3, num); val3.AddTargetToList((int)owner.actualClientId, false); if ((Object)(object)Plugin.photoAlertSFX == (Object)null) { Plugin.Log.LogError((object)"Photo alert SFX is null!"); return; } if (Plugin.DebugMode) { Plugin.Log.LogInfo((object)"Playing photo alert SFX"); } val3.farAudio.PlayOneShot(Plugin.photoAlertSFX, CustomConfig.photoAlertVolume.Value); } public static void SnapValuePatch(ref List<VisibleEntity> entities, ref bool isUnique) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < entities.Count; i++) { if (!(entities[i].name.ToLower() == "shy guy")) { continue; } string name = "shy guy"; ShyGuyAI[] array = Object.FindObjectsOfType<ShyGuyAI>(false); if (((EnemyAI)array[0]).currentBehaviourStateIndex == 0) { name = "shyguy_calm"; if (CustomConfig.calmPhotoUnique.Value) { isUnique = true; } } if (((EnemyAI)array[0]).currentBehaviourStateIndex == 1) { name = "shyguy_triggered"; if (CustomConfig.triggeredPhotoUnique.Value) { isUnique = true; } } if (((EnemyAI)array[0]).currentBehaviourStateIndex == 2) { name = "shyguy_angry"; if (CustomConfig.angryPhotoUnique.Value) { isUnique = true; } } VisibleEntity val = default(VisibleEntity); val.name = name; val.isPlayer = false; val.isOutside = entities[i].isOutside; val.networkID = entities[i].networkID; VisibleEntity value = val; entities[i] = value; } } public static bool MonsterScorePatch(ref string monsterName, ref float __result) { string key = monsterName.ToLower(); if (scopoCustomValues.TryGetValue(key, out var value)) { __result = value; Plugin.Log.LogInfo((object)$"SCP-096 '{monsterName}' scored with value {__result}"); return false; } if (Plugin.DebugMode) { Plugin.Log.LogInfo((object)("didnt find NOTHING! Monster name was: " + monsterName)); } return true; } } }