using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Audio;
[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("SchizophreniaMod")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SchizophreniaMod")]
[assembly: AssemblyTitle("SchizophreniaMod")]
[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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace SchizophreniaMod
{
[BepInPlugin("com.tibby.schizophrenia", "Schizophrenia Mod", "1.1.0")]
public class SchizophreniaBase : BaseUnityPlugin
{
public static ManualLogSource mls;
private void Awake()
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
mls = Logger.CreateLogSource("SchizoDebug");
new Harmony("com.tibby.schizophrenia").PatchAll();
mls.LogWarning((object)"=== SCHIZOPHRENIA MOD v1.1.0 LOADED ===");
mls.LogInfo((object)"Audio hallucination system initialized.");
}
}
public static class AudioClipDatabase
{
public static readonly HashSet<string> Blacklist = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"SnareFleaTipChannel", "SlimeIdle", "NutcrackerVentCrawl", "GhostlySynth2", "CrawlerDie", "SpiderDie", "NutcrackerDie", "StingrayDie", "BushWolfDie", "KillCaveDweller",
"BugDie", "SporeDamage", "SporeDamageB", "SporeDamageC", "SporeDamageD", "PlantSpores", "HangPlayerOnCeiling", "ClingToPlayerLocal", "LradBrainwashingSignal1", "LradBrainwashingSignal4",
"LradBrainwashingSignal6", "LradBrainwashingSignal7", "LradBrainwashingSignal8", "KillPlayerSpring", "MaskComedyAttach", "JackInTheBoxTheme"
};
public static readonly Dictionary<string, string[]> EnemyClipPatterns = new Dictionary<string, string[]>
{
{
"Centipede",
new string[3] { "centipedewalk", "clingto", "snarebuildup" }
},
{
"Bunker Spider",
new string[8] { "spiderattack", "spiderhit", "stunspider", "hitweb", "breakweb", "spoolinplayerweb", "clickingmandibles", "stuckweb" }
},
{
"HoarderBug",
new string[4] { "hoarderbugcry", "chitter", "bugwalk", "takeitems" }
},
{
"Flowerman",
new string[3] { "flowerman", "bracken", "crackneck" }
},
{
"Crawler",
new string[6] { "hitcrawler", "stuncrawler", "chargeforward", "startchargeforward", "longroar", "shortroar" }
},
{
"Puffer",
new string[4] { "puffsfx", "frighten", "rattletail", "hiss" }
},
{
"Jester",
new string[5] { "jesterstomp", "pop1", "chatteringteeth", "icecreamtruck", "turncrank" }
},
{
"DressGirl",
new string[6] { "monsternoise", "phonescream", "breathe1", "ghostlysynth", "wallrumblevoice", "voicecry" }
},
{
"Spring",
new string[4] { "spring1", "spring2", "spring3", "springwobble" }
},
{
"Nutcracker",
new string[6] { "nutcrackerangry", "nutcrackerhiteye", "nutcrackerturn", "headgoup", "hitmetal", "shotgunreloadnutcracker" }
},
{
"Butler",
new string[7] { "butlerstab", "butlerblowup", "butlersuitrustle", "butlerbeeswarm", "butlerstep", "butleruntuckknife", "butlermurdertheme" }
},
{
"Masked",
new string[5] { "maskattackplayer", "maskfacelightup", "maskpuke", "maskcry", "masklaugh" }
},
{
"Hygrodere",
new string[5] { "walkslime", "hitslime", "slimekillplayer", "slimeangry", "slimedance" }
},
{
"Barber",
new string[2] { "scissorssnip", "scissors" }
},
{
"Maneater",
new string[7] { "babycry", "babypuke", "babysquirm", "babyfootstep", "cavedweller", "chewmeat", "biteplay" }
}
};
public static readonly Dictionary<string, string[]> MoonIndoorEnemies = new Dictionary<string, string[]>
{
{
"experimentation",
new string[9] { "Bunker Spider", "Centipede", "Hygrodere", "HoarderBug", "Puffer", "Crawler", "Flowerman", "DressGirl", "Nutcracker" }
},
{
"assurance",
new string[11]
{
"Centipede", "HoarderBug", "Bunker Spider", "Hygrodere", "Crawler", "Maneater", "Flowerman", "Puffer", "Barber", "DressGirl",
"Nutcracker"
}
},
{
"vow",
new string[10] { "Flowerman", "HoarderBug", "Maneater", "Centipede", "Bunker Spider", "Hygrodere", "Puffer", "Barber", "Crawler", "Spring" }
},
{
"offense",
new string[10] { "Crawler", "Bunker Spider", "Hygrodere", "Centipede", "Spring", "HoarderBug", "Puffer", "Maneater", "Flowerman", "Nutcracker" }
},
{
"march",
new string[11]
{
"Crawler", "Bunker Spider", "Flowerman", "Centipede", "HoarderBug", "Hygrodere", "Spring", "Puffer", "Maneater", "Nutcracker",
"Jester"
}
},
{
"adamance",
new string[13]
{
"Bunker Spider", "Centipede", "HoarderBug", "Hygrodere", "Flowerman", "Puffer", "Crawler", "Spring", "Maneater", "Nutcracker",
"Masked", "DressGirl", "Jester"
}
},
{
"rend",
new string[12]
{
"Nutcracker", "Jester", "Flowerman", "Bunker Spider", "Spring", "Centipede", "Masked", "DressGirl", "Butler", "Barber",
"Puffer", "Hygrodere"
}
},
{
"dine",
new string[13]
{
"Butler", "Barber", "Flowerman", "Centipede", "Hygrodere", "HoarderBug", "Jester", "Nutcracker", "Spring", "DressGirl",
"Crawler", "Puffer", "Maneater"
}
},
{
"titan",
new string[12]
{
"Jester", "Nutcracker", "Flowerman", "Bunker Spider", "Spring", "Crawler", "Centipede", "HoarderBug", "Masked", "Hygrodere",
"DressGirl", "Puffer"
}
},
{
"artifice",
new string[15]
{
"Bunker Spider", "Flowerman", "Nutcracker", "HoarderBug", "Crawler", "Jester", "Butler", "Puffer", "Masked", "Spring",
"Centipede", "Hygrodere", "Barber", "DressGirl", "Maneater"
}
},
{
"embrion",
new string[10] { "HoarderBug", "Hygrodere", "Barber", "Puffer", "Crawler", "Spring", "Bunker Spider", "Nutcracker", "Centipede", "Flowerman" }
}
};
public static string[] GetIndoorEnemiesForMoon(string planetName)
{
string text = planetName.ToLower();
foreach (KeyValuePair<string, string[]> moonIndoorEnemy in MoonIndoorEnemies)
{
if (text.Contains(moonIndoorEnemy.Key))
{
return moonIndoorEnemy.Value;
}
}
return EnemyClipPatterns.Keys.ToArray();
}
}
public class GhostAudioMover : MonoBehaviour
{
[CompilerGenerated]
private sealed class <MoveRoutine>d__1 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public AudioSource src;
public Vector3 dir;
public float speed;
public float dur;
public GhostAudioMover <>4__this;
private float <elapsed>5__1;
private float <startVol>5__2;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <MoveRoutine>d__1(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: 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)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<elapsed>5__1 = 0f;
<startVol>5__2 = (((Object)(object)src != (Object)null) ? src.volume : 0f);
break;
case 1:
<>1__state = -1;
break;
}
if (<elapsed>5__1 < dur && (Object)(object)src != (Object)null)
{
Transform transform = ((Component)<>4__this).transform;
transform.position += dir * speed * Time.deltaTime;
if (<elapsed>5__1 > dur * 0.8f)
{
src.volume = Mathf.Lerp(<startVol>5__2, 0f, (<elapsed>5__1 - dur * 0.8f) / (dur * 0.2f));
}
<elapsed>5__1 += Time.deltaTime;
<>2__current = null;
<>1__state = 1;
return true;
}
Object.Destroy((Object)(object)((Component)<>4__this).gameObject);
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 void Initialize(AudioSource src, Vector3 dir, float speed, float dur)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
((MonoBehaviour)this).StartCoroutine(MoveRoutine(src, dir, speed, dur));
}
[IteratorStateMachine(typeof(<MoveRoutine>d__1))]
private IEnumerator MoveRoutine(AudioSource src, Vector3 dir, float speed, float dur)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <MoveRoutine>d__1(0)
{
<>4__this = this,
src = src,
dir = dir,
speed = speed,
dur = dur
};
}
}
[HarmonyPatch(typeof(PlayerControllerB), "Update")]
public class PlayerSchizoPatch
{
private static float timer = 0f;
private static bool isSystemActive = false;
private static float activationCountdown = 120f;
private static bool countdownExpired = false;
private static float countdownLogTimer = 0f;
private static readonly Dictionary<ulong, float> PlayerCooldowns = new Dictionary<ulong, float>();
private const float COOLDOWN_DURATION = 18f;
private static List<(AudioClip clip, string enemyName)> _cachedClips = null;
private static string _lastPlanetName = "";
private static Dictionary<string, Dictionary<string, int>> PlayerHallucinationStats = new Dictionary<string, Dictionary<string, int>>();
[HarmonyPostfix]
private static void Postfix(PlayerControllerB __instance)
{
if (!((NetworkBehaviour)__instance).IsOwner || !__instance.isPlayerControlled)
{
return;
}
ulong playerClientId = __instance.playerClientId;
if (PlayerCooldowns.TryGetValue(playerClientId, out var value) && value > 0f)
{
PlayerCooldowns[playerClientId] = Mathf.Max(0f, value - Time.deltaTime);
}
if ((Object)(object)StartOfRound.Instance == (Object)null || !StartOfRound.Instance.shipHasLanded)
{
if (isSystemActive)
{
ResetSystem();
}
return;
}
SelectableLevel currentLevel = StartOfRound.Instance.currentLevel;
if (currentLevel.levelID == 3 || currentLevel.PlanetName.ToLower().Contains("gordion"))
{
if (isSystemActive)
{
ResetSystem();
}
return;
}
if (!isSystemActive)
{
if (StartOfRound.Instance.allPlayerScripts.Any((PlayerControllerB p) => p.isPlayerControlled && p.isInsideFactory))
{
isSystemActive = true;
SchizophreniaBase.mls.LogWarning((object)"!!! [SYSTEM ACTIVE] A player entered the facility !!!");
return;
}
if (!countdownExpired)
{
activationCountdown -= Time.deltaTime;
countdownLogTimer -= Time.deltaTime;
if (countdownLogTimer <= 0f)
{
countdownLogTimer = 10f;
}
if (activationCountdown <= 0f)
{
activationCountdown = 0f;
countdownExpired = true;
isSystemActive = true;
SchizophreniaBase.mls.LogWarning((object)"!!! [SYSTEM ACTIVE] 120s countdown expired !!!");
}
}
if (!isSystemActive)
{
return;
}
}
if (__instance.isInsideFactory && !__instance.isInHangarShipRoom)
{
timer += Time.deltaTime;
if (timer >= 1f)
{
timer = 0f;
ProcessLogic(__instance);
}
}
}
private static void ResetSystem()
{
PrintRoundSummary();
isSystemActive = false;
activationCountdown = 120f;
countdownExpired = false;
countdownLogTimer = 0f;
PlayerCooldowns.Clear();
PlayerHallucinationStats.Clear();
_cachedClips = null;
_lastPlanetName = "";
}
private static void ProcessLogic(PlayerControllerB player)
{
ulong playerClientId = player.playerClientId;
if (!PlayerCooldowns.TryGetValue(playerClientId, out var value) || !(value > 0f))
{
float num = Mathf.Clamp(player.insanityLevel / 50f, 0f, 1f);
float num2 = 0.0015f + num * 0.0015f;
float num3 = CalculateWeight(player);
float num4 = num2 * num3;
float value2 = Random.value;
if (value2 < num4)
{
PlaySchizoAudio(player);
}
}
}
private static float CalculateWeight(PlayerControllerB player)
{
return StartOfRound.Instance.allPlayerScripts.Count((PlayerControllerB p) => (Object)(object)p != (Object)(object)player && !p.isPlayerDead && p.isPlayerControlled && p.isInsideFactory && Vector3.Distance(((Component)player).transform.position, ((Component)p).transform.position) < 15f) switch
{
0 => 2f,
1 => 1f,
_ => 0.5f,
};
}
private static void PlaySchizoAudio(PlayerControllerB player)
{
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Expected O, but got Unknown
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
//IL_01bf: 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)
//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
SelectableLevel val = StartOfRound.Instance?.currentLevel;
if ((Object)(object)val == (Object)null)
{
return;
}
string planetName = val.PlanetName;
if (_cachedClips == null || _lastPlanetName != planetName)
{
_lastPlanetName = planetName;
_cachedClips = BuildClipCache(planetName, val);
}
if (_cachedClips.Count != 0)
{
(AudioClip, string) tuple = _cachedClips[Random.Range(0, _cachedClips.Count)];
AudioClip item = tuple.Item1;
string item2 = tuple.Item2;
float num = Random.Range(15f, 25f);
Vector3 position = ((Component)player).transform.position;
Vector3 val2 = Random.insideUnitSphere;
Vector3 val3 = position + ((Vector3)(ref val2)).normalized * num;
NavMeshHit val4 = default(NavMeshHit);
Vector3 val5 = (NavMesh.SamplePosition(val3, ref val4, 10f, -1) ? ((NavMeshHit)(ref val4)).position : val3);
GameObject val6 = new GameObject("SchizoGhost");
val6.transform.position = val5;
AudioSource val7 = val6.AddComponent<AudioSource>();
val7.spatialize = false;
val7.spatialBlend = 1f;
val7.rolloffMode = (AudioRolloffMode)1;
val7.minDistance = 10f;
val7.maxDistance = 40f;
val7.volume = 0.8f;
val7.clip = item;
AudioMixerGroup val8 = ((IEnumerable<AudioMixerGroup>)Resources.FindObjectsOfTypeAll<AudioMixerGroup>()).FirstOrDefault((Func<AudioMixerGroup, bool>)((AudioMixerGroup g) => ((Object)g).name == "Master"));
if ((Object)(object)val8 != (Object)null)
{
val7.outputAudioMixerGroup = val8;
}
val2 = val5 - ((Component)player).transform.position;
Vector3 normalized = ((Vector3)(ref val2)).normalized;
val6.AddComponent<GhostAudioMover>().Initialize(val7, normalized, 3f, item.length);
if (!PlayerHallucinationStats.ContainsKey(player.playerUsername))
{
PlayerHallucinationStats[player.playerUsername] = new Dictionary<string, int>();
}
if (!PlayerHallucinationStats[player.playerUsername].ContainsKey(item2))
{
PlayerHallucinationStats[player.playerUsername][item2] = 0;
}
PlayerHallucinationStats[player.playerUsername][item2]++;
val7.Play();
PlayerCooldowns[player.playerClientId] = 18f;
}
}
private static List<(AudioClip, string)> BuildClipCache(string planetName, SelectableLevel level)
{
List<(AudioClip, string)> list = new List<(AudioClip, string)>();
string[] indoorEnemiesForMoon = AudioClipDatabase.GetIndoorEnemiesForMoon(planetName);
AudioClip[] array = Resources.FindObjectsOfTypeAll<AudioClip>();
HashSet<string> hashSet = new HashSet<string>();
AudioClip[] array2 = array;
foreach (AudioClip val in array2)
{
if ((Object)(object)val == (Object)null || val.length < 0.1f || AudioClipDatabase.Blacklist.Contains(((Object)val).name))
{
continue;
}
string clipLower = ((Object)val).name.ToLower();
foreach (KeyValuePair<string, string[]> enemyClipPattern in AudioClipDatabase.EnemyClipPatterns)
{
string key = enemyClipPattern.Key;
if (!indoorEnemiesForMoon.Contains(key) || !enemyClipPattern.Value.Any((string pattern) => clipLower.Contains(pattern)))
{
continue;
}
string item = key + "_" + ((Object)val).name;
if (hashSet.Add(item))
{
list.Add((val, key));
}
break;
}
}
if ((Object)(object)level != (Object)null)
{
HashSet<string> hashSet2 = new HashSet<string>(list.Select(((AudioClip, string) r) => r.Item2));
string[] array3 = indoorEnemiesForMoon;
foreach (string enemyKey in array3)
{
if (hashSet2.Contains(enemyKey))
{
continue;
}
EnemyType val2 = level.Enemies.Select((SpawnableEnemyWithRarity e) => e.enemyType).FirstOrDefault((Func<EnemyType, bool>)((EnemyType e) => (Object)(object)e != (Object)null && e.enemyName != null && AudioClipDatabase.EnemyClipPatterns.ContainsKey(enemyKey) && (e.enemyName.Contains(enemyKey) || enemyKey.Contains(e.enemyName) || NameMatchesKey(e.enemyName, enemyKey))));
if ((Object)(object)val2 == (Object)null || val2.audioClips == null || val2.audioClips.Length == 0)
{
continue;
}
int num = 0;
AudioClip[] audioClips = val2.audioClips;
foreach (AudioClip val3 in audioClips)
{
if (!((Object)(object)val3 == (Object)null) && !(val3.length < 0.1f) && !AudioClipDatabase.Blacklist.Contains(((Object)val3).name))
{
string item2 = enemyKey + "_" + ((Object)val3).name;
if (hashSet.Add(item2))
{
list.Add((val3, enemyKey));
num++;
}
}
}
}
}
return list;
}
private static bool NameMatchesKey(string enemyName, string enemyKey)
{
if (enemyName == null || enemyKey == null)
{
return false;
}
string text = enemyName.ToLower().Replace(" ", "").Replace("-", "");
string text2 = enemyKey.ToLower().Replace(" ", "").Replace("-", "");
if (text == text2)
{
return true;
}
return text2 switch
{
"hoarderbug" => text.Contains("hoarding") || text.Contains("hoarder"),
"centipede" => text.Contains("centipede") || text.Contains("snare"),
"flowerman" => text.Contains("flowerman") || text.Contains("bracken"),
"crawler" => text.Contains("crawler") || text.Contains("thumper"),
"puffer" => text.Contains("puffer") || text.Contains("spore"),
"dressgirl" => text.Contains("dressgirl") || text.Contains("girl"),
"spring" => text.Contains("spring") || text.Contains("coil"),
"hygrodere" => text.Contains("hygrodere") || text.Contains("blob") || text.Contains("slime"),
"maneater" => text.Contains("maneater") || text.Contains("cavedweller") || text.Contains("cave"),
"bunker spider" => text.Contains("spider") || text.Contains("bunker"),
_ => text.Contains(text2) || text2.Contains(text),
};
}
private static void PrintRoundSummary()
{
if (PlayerHallucinationStats.Count == 0)
{
return;
}
SchizophreniaBase.mls.LogWarning((object)"========================================");
SchizophreniaBase.mls.LogWarning((object)" HALLUCINATION SUMMARY");
SchizophreniaBase.mls.LogWarning((object)"========================================");
foreach (KeyValuePair<string, Dictionary<string, int>> item in PlayerHallucinationStats.OrderBy((KeyValuePair<string, Dictionary<string, int>> x) => x.Key))
{
IOrderedEnumerable<KeyValuePair<string, int>> source = item.Value.OrderByDescending((KeyValuePair<string, int> x) => x.Value);
int num = source.Sum((KeyValuePair<string, int> x) => x.Value);
string text = string.Join(", ", source.Select((KeyValuePair<string, int> x) => $"{x.Value}x {x.Key}"));
SchizophreniaBase.mls.LogWarning((object)(" " + item.Key + ": " + text));
SchizophreniaBase.mls.LogWarning((object)$" Total: {num} hallucination(s)");
}
SchizophreniaBase.mls.LogWarning((object)"========================================");
}
}
}