using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("zombie zombo")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Go Go Gadget zombies")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0")]
[assembly: AssemblyProduct("zombie zombo")]
[assembly: AssemblyTitle("zombie zombo")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[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;
}
}
}
public static class Sfx
{
private static readonly Dictionary<string, List<AudioSource>> _libraries = new Dictionary<string, List<AudioSource>>();
private static GameObject _host;
private static bool _classRegistered = false;
private static string _defaultLibrary = null;
public static void Init(string folderName = "sfx")
{
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Expected O, but got Unknown
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Expected O, but got Unknown
if (!_libraries.ContainsKey(folderName))
{
if (!_classRegistered)
{
ClassInjector.RegisterTypeInIl2Cpp<SfxLoader>();
_classRegistered = true;
}
if ((Object)(object)_host == (Object)null)
{
_host = new GameObject("SfxHost")
{
hideFlags = (HideFlags)61
};
Object.DontDestroyOnLoad((Object)(object)_host);
}
if (_defaultLibrary == null)
{
_defaultLibrary = folderName;
}
_libraries[folderName] = new List<AudioSource>();
string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string path = Path.Combine(directoryName, folderName);
GameObject val = new GameObject("SfxLoader_" + folderName);
val.transform.SetParent(_host.transform, false);
SfxLoader sfxLoader = val.AddComponent<SfxLoader>();
sfxLoader.BeginLoad(folderName, path);
}
}
public static void PlayRandom(string folderName = null)
{
string text = folderName ?? _defaultLibrary;
if (text == null || !_libraries.TryGetValue(text, out var value) || value.Count == 0)
{
Debug.LogWarning(Object.op_Implicit("[Sfx] PlayRandom('" + folderName + "') — no sounds loaded yet for that library. Did you call Sfx.Init()?"));
return;
}
AudioSource val = value[Random.Range(0, value.Count)];
if ((Object)(object)val == (Object)null || (Object)(object)val.clip == (Object)null)
{
Debug.LogWarning(Object.op_Implicit("[Sfx] Picked a null/destroyed clip holder — skipping this play."));
}
else
{
val.Play();
}
}
public static AudioClip GetRandomClip(string folderName = null)
{
string text = folderName ?? _defaultLibrary;
if (text == null || !_libraries.TryGetValue(text, out var value) || value.Count == 0)
{
return null;
}
AudioSource val = value[Random.Range(0, value.Count)];
return ((Object)(object)val != (Object)null) ? val.clip : null;
}
public static int GetLoadedCount(string folderName = null)
{
string text = folderName ?? _defaultLibrary;
List<AudioSource> value;
return (text != null && _libraries.TryGetValue(text, out value)) ? value.Count : 0;
}
internal static void RegisterHolder(string folderName, AudioSource holder)
{
if (!_libraries.TryGetValue(folderName, out var value))
{
value = new List<AudioSource>();
_libraries[folderName] = value;
}
value.Add(holder);
}
}
internal class SfxLoader : MonoBehaviour
{
private string libraryKey;
private string folderPath;
private readonly Queue<string> pendingFiles = new Queue<string>();
private UnityWebRequest currentRequest;
private string currentFile;
public SfxLoader(IntPtr ptr)
: base(ptr)
{
}
public void BeginLoad(string key, string path)
{
libraryKey = key;
folderPath = path;
if (!Directory.Exists(folderPath))
{
Debug.LogWarning(Object.op_Implicit($"[Sfx] '{libraryKey}': no folder found at {folderPath} — this library will have no sounds."));
return;
}
string[] files = Directory.GetFiles(folderPath);
foreach (string text in files)
{
string text2 = Path.GetExtension(text).ToLowerInvariant();
if (text2 == ".wav" || text2 == ".ogg" || text2 == ".mp3")
{
pendingFiles.Enqueue(text);
}
}
Debug.Log(Object.op_Implicit($"[Sfx] '{libraryKey}': found {pendingFiles.Count} sound file(s) in {folderPath}, loading..."));
StartNextLoad();
}
private void StartNextLoad()
{
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
if (pendingFiles.Count == 0)
{
Debug.Log(Object.op_Implicit($"[Sfx] '{libraryKey}': finished loading — {Sfx.GetLoadedCount(libraryKey)} sound(s) ready."));
}
else
{
currentFile = pendingFiles.Dequeue();
AudioType audioType = GetAudioType(currentFile);
string absoluteUri = new Uri(currentFile).AbsoluteUri;
currentRequest = UnityWebRequestMultimedia.GetAudioClip(absoluteUri, audioType);
currentRequest.SendWebRequest();
}
}
private void Update()
{
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Invalid comparison between Unknown and I4
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Expected O, but got Unknown
if (currentRequest == null || !currentRequest.isDone)
{
return;
}
try
{
if ((int)currentRequest.result == 1)
{
AudioClip content = DownloadHandlerAudioClip.GetContent(currentRequest);
if ((Object)(object)content != (Object)null)
{
((Object)content).name = Path.GetFileNameWithoutExtension(currentFile);
GameObject val = new GameObject("SfxClipHolder_" + libraryKey + "_" + ((Object)content).name);
val.transform.SetParent(((Component)this).transform, false);
AudioSource val2 = ((Il2CppObjectBase)val.AddComponent(Il2CppType.Of<AudioSource>())).Cast<AudioSource>();
val2.clip = content;
val2.playOnAwake = false;
val2.spatialBlend = 0f;
Sfx.RegisterHolder(libraryKey, val2);
Debug.Log(Object.op_Implicit($"[Sfx] '{libraryKey}': loaded '{((Object)content).name}'."));
}
else
{
Debug.LogWarning(Object.op_Implicit($"[Sfx] '{libraryKey}': {currentFile} downloaded fine but produced a null AudioClip."));
}
}
else
{
Debug.LogWarning(Object.op_Implicit($"[Sfx] '{libraryKey}': failed to load {currentFile}: {currentRequest.error}"));
}
}
catch (Exception value)
{
Debug.LogError(Object.op_Implicit($"[Sfx] '{libraryKey}': exception loading {currentFile}: {value}"));
}
finally
{
currentRequest.Dispose();
currentRequest = null;
}
StartNextLoad();
}
private static AudioType GetAudioType(string filePath)
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
return (AudioType)(Path.GetExtension(filePath).ToLowerInvariant() switch
{
".mp3" => 13,
".ogg" => 14,
".wav" => 20,
_ => 0,
});
}
}
namespace ZombieMod
{
public static class NightDirector
{
private enum State
{
Idle,
FastForwardingToNight,
HoldingNight,
RestoringDaylight
}
private static State _state;
private static float _originalHour;
private static float _fromHour;
private static float _targetHour;
private static float _forwardDistance;
private static float _transitionStartTime;
private static float _transitionDuration;
public static bool IsNightLocked => _state == State.FastForwardingToNight || _state == State.HoldingNight;
public static void RequestNight()
{
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Expected O, but got Unknown
if (!Plugin.NightUntilScriptComplete.Value || _state == State.FastForwardingToNight || _state == State.HoldingNight || !SkyManagerReady())
{
return;
}
float currentTime = SkyManager.GetCurrentTime();
if (_state == State.Idle)
{
_originalHour = currentTime;
}
_fromHour = currentTime;
_targetHour = Mathf.Repeat(Plugin.NightTargetHour.Value, 24f);
float num;
for (num = _targetHour - _fromHour; num < 0f; num += 24f)
{
}
_forwardDistance = num;
_transitionDuration = Mathf.Max(0.5f, Plugin.NightTransitionSeconds.Value);
_transitionStartTime = Time.time;
_state = State.FastForwardingToNight;
ManualLogSource modLog = Plugin.ModLog;
if (modLog != null)
{
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(44, 3, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("NightDirector: forcing night, ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(_fromHour, "0.0");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("h -> ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(_targetHour, "0.0");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("h over ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(_transitionDuration, "0.0");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("s.");
}
modLog.LogInfo(val);
}
}
public static void ReleaseNight()
{
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Expected O, but got Unknown
if (_state == State.Idle || _state == State.RestoringDaylight)
{
return;
}
if (!SkyManagerReady())
{
_state = State.Idle;
return;
}
float currentTime = SkyManager.GetCurrentTime();
_fromHour = currentTime;
_targetHour = _originalHour;
float num;
for (num = _targetHour - _fromHour; num < 0f; num += 24f)
{
}
_forwardDistance = num;
_transitionDuration = Mathf.Max(0.5f, Plugin.NightTransitionSeconds.Value * 0.8f);
_transitionStartTime = Time.time;
_state = State.RestoringDaylight;
ManualLogSource modLog = Plugin.ModLog;
if (modLog != null)
{
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(55, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("NightDirector: script complete, restoring daylight (");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(_originalHour, "0.0");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("h).");
}
modLog.LogInfo(val);
}
}
public static void Tick()
{
//IL_014c: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: Expected O, but got Unknown
if (_state == State.Idle)
{
return;
}
if (!SkyManagerReady())
{
_state = State.Idle;
}
else if (_state == State.FastForwardingToNight)
{
float num = Mathf.Clamp01((Time.time - _transitionStartTime) / _transitionDuration);
float num2 = Mathf.SmoothStep(0f, 1f, num);
SkyManager.SetFixedTime(Mathf.Repeat(_fromHour + _forwardDistance * num2, 24f));
if (num >= 1f)
{
_state = State.HoldingNight;
SkyManager.SetFixedTime(_targetHour);
}
}
else if (_state == State.HoldingNight)
{
SkyManager.SetFixedTime(_targetHour);
}
else
{
if (_state != State.RestoringDaylight)
{
return;
}
float num3 = Mathf.Clamp01((Time.time - _transitionStartTime) / _transitionDuration);
float num4 = Mathf.SmoothStep(0f, 1f, num3);
SkyManager.SetFixedTime(Mathf.Repeat(_fromHour + _forwardDistance * num4, 24f));
if (!(num3 >= 1f))
{
return;
}
RestoreImmediate();
ManualLogSource modLog = Plugin.ModLog;
if (modLog != null)
{
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(37, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("NightDirector: daylight restored (");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(_originalHour, "0.0");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("h).");
}
modLog.LogInfo(val);
}
}
}
public static void RestoreImmediate()
{
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Expected O, but got Unknown
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Expected O, but got Unknown
bool flag = _state != State.Idle;
_state = State.Idle;
if (!flag || !SkyManagerReady())
{
return;
}
bool flag2 = default(bool);
try
{
SkyManager.SetFixedTime(_originalHour);
SkyManager.ClearFixedTime();
ManualLogSource modLog = Plugin.ModLog;
if (modLog != null)
{
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(52, 1, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("NightDirector: hard-restored daylight instantly (");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(_originalHour, "0.0");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("h).");
}
modLog.LogInfo(val);
}
}
catch (Exception ex)
{
ManualLogSource modLog2 = Plugin.ModLog;
if (modLog2 != null)
{
BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(71, 1, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("NightDirector: RestoreImmediate hit an error, sky may still be frozen: ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
}
modLog2.LogWarning(val2);
}
}
}
private static bool SkyManagerReady()
{
try
{
return SkyManager.initalized;
}
catch
{
return false;
}
}
}
[BepInPlugin("gogogadgetjustice.bigtypingofthehive", "Typing of the Hive", "1.0.0")]
public class Plugin : BasePlugin
{
public static ManualLogSource ModLog;
public static ConfigEntry<KeyCode> ActivationKey { get; private set; }
public static ConfigEntry<KeyCode> SpawnKey { get; private set; }
public static ConfigEntry<float> SpawnDistanceMin { get; private set; }
public static ConfigEntry<float> SpawnDistanceMax { get; private set; }
public static ConfigEntry<float> ZombieSpeed { get; private set; }
public static ConfigEntry<int> MaxZombies { get; private set; }
public static ConfigEntry<float> SurroundRadiusMin { get; private set; }
public static ConfigEntry<float> SurroundRadiusMax { get; private set; }
public static ConfigEntry<bool> EnableTypingMode { get; private set; }
public static ConfigEntry<string> PhraseBankFileName { get; private set; }
public static ConfigEntry<bool> RandomMode { get; private set; }
public static ConfigEntry<float> LabelHeightOffset { get; private set; }
public static ConfigEntry<int> LabelFontSize { get; private set; }
public static ConfigEntry<bool> AutoRespawnOnKill { get; private set; }
public static ConfigEntry<bool> EnableSfx { get; private set; }
public static ConfigEntry<string> KeySoundFolder { get; private set; }
public static ConfigEntry<string> SpaceSoundFolder { get; private set; }
public static ConfigEntry<string> BuzzSoundFolder { get; private set; }
public static ConfigEntry<float> BuzzIntervalMin { get; private set; }
public static ConfigEntry<float> BuzzIntervalMax { get; private set; }
public static ConfigEntry<float> BuzzMinDistance { get; private set; }
public static ConfigEntry<float> BuzzMaxDistance { get; private set; }
public static ConfigEntry<float> BuzzVolume { get; private set; }
public static ConfigEntry<bool> NightUntilScriptComplete { get; private set; }
public static ConfigEntry<float> NightTargetHour { get; private set; }
public static ConfigEntry<float> NightTransitionSeconds { get; private set; }
public static ConfigEntry<int> CyclesBeforeDawn { get; private set; }
public static ConfigEntry<KeyCode> HardResetKey { get; private set; }
public static ConfigEntry<bool> AutoResetOnSceneLoad { get; private set; }
public static PhraseSelectionMode CurrentSelectionMode => RandomMode.Value ? PhraseSelectionMode.Random : PhraseSelectionMode.Sequential;
public override void Load()
{
ModLog = ((BasePlugin)this).Log;
ActivationKey = ((BasePlugin)this).Config.Bind<KeyCode>("Controls", "ActivationKey", (KeyCode)45, "Press '-' to enable zombie spawning.");
SpawnKey = ((BasePlugin)this).Config.Bind<KeyCode>("Controls", "SpawnKey", (KeyCode)270, "Press '+' to spawn a zombie.");
SpawnDistanceMin = ((BasePlugin)this).Config.Bind<float>("Settings", "SpawnDistanceMin", 8f, "Nearest distance (meters) a new zombie can spawn from the player. Spawns at a random compass direction, not just straight ahead.");
SpawnDistanceMax = ((BasePlugin)this).Config.Bind<float>("Settings", "SpawnDistanceMax", 14f, "Farthest distance (meters) a new zombie can spawn from the player.");
ZombieSpeed = ((BasePlugin)this).Config.Bind<float>("Settings", "ZombieSpeed", 2.5f, "Zombie movement speed.");
MaxZombies = ((BasePlugin)this).Config.Bind<int>("Settings", "MaxZombies", 30, "Max active zombies allowed.");
SurroundRadiusMin = ((BasePlugin)this).Config.Bind<float>("Settings", "SurroundRadiusMin", 3.5f, "Nearest distance (meters) zombies circle at while waiting. Bigger = easier to read their phrase.");
SurroundRadiusMax = ((BasePlugin)this).Config.Bind<float>("Settings", "SurroundRadiusMax", 6f, "Farthest distance (meters) zombies circle at while waiting.");
EnableTypingMode = ((BasePlugin)this).Config.Bind<bool>("Typing", "EnableTypingMode", true, "If true, each zombie carries a phrase you must type to kill it (Typing of the Dead style).");
PhraseBankFileName = ((BasePlugin)this).Config.Bind<string>("Typing", "PhraseBankFile", "phrases.json", "Name of the JSON phrase bank file, expected to sit next to this plugin's DLL. Generate one from any text file with the included phrase_converter.py script.");
RandomMode = ((BasePlugin)this).Config.Bind<bool>("Typing", "RandomMode", false, "false (default) = walk straight down the phrase file in order, wrapping at the end. true = shuffled, guaranteed no repeats until every phrase has been used once.");
LabelHeightOffset = ((BasePlugin)this).Config.Bind<float>("Typing", "LabelHeightOffset", 0.55f, "How far above the zombie's head (in meters) the floating phrase label sits.");
LabelFontSize = ((BasePlugin)this).Config.Bind<int>("Typing", "LabelFontSize", 42, "Font size for the floating typing label.");
AutoRespawnOnKill = ((BasePlugin)this).Config.Bind<bool>("Typing", "AutoRespawnOnKill", true, "If true, typing out a zombie immediately spawns a fresh one so the horde never runs dry.");
EnableSfx = ((BasePlugin)this).Config.Bind<bool>("Audio", "EnableSfx", true, "Master on/off switch for keystroke and ambient buzzing sound effects.");
KeySoundFolder = ((BasePlugin)this).Config.Bind<string>("Audio", "KeySoundFolder", "key", "Subfolder (next to this DLL) holding the sound played for a correctly typed letter — e.g. key.ogg.");
SpaceSoundFolder = ((BasePlugin)this).Config.Bind<string>("Audio", "SpaceSoundFolder", "space", "Subfolder holding the sound played for a correctly typed space — e.g. space.ogg.");
BuzzSoundFolder = ((BasePlugin)this).Config.Bind<string>("Audio", "BuzzSoundFolder", "buzz", "Subfolder holding bee-buzz sounds — e.g. bzz.ogg and buzz.ogg. Each zombie has its own positional AudioSource and picks a random clip from this folder on its own timer below.");
BuzzIntervalMin = ((BasePlugin)this).Config.Bind<float>("Audio", "BuzzIntervalMin", 1.5f, "Shortest gap (seconds) between one zombie's own buzz sounds.");
BuzzIntervalMax = ((BasePlugin)this).Config.Bind<float>("Audio", "BuzzIntervalMax", 4f, "Longest gap (seconds) between one zombie's own buzz sounds.");
BuzzMinDistance = ((BasePlugin)this).Config.Bind<float>("Audio", "BuzzMinDistance", 2f, "Distance (meters) within which a zombie's buzz plays at full volume.");
BuzzMaxDistance = ((BasePlugin)this).Config.Bind<float>("Audio", "BuzzMaxDistance", 20f, "Distance (meters) beyond which a zombie's buzz is inaudible. Should comfortably cover SurroundRadiusMax so a circling bee doesn't go silent.");
BuzzVolume = ((BasePlugin)this).Config.Bind<float>("Audio", "BuzzVolume", 0.8f, "Per-zombie buzz volume (0-1). Lower this if a full horde gets too loud.");
NightUntilScriptComplete = ((BasePlugin)this).Config.Bind<bool>("Night", "NightUntilScriptComplete", true, "If true, activating the mod forces night (via the game's own SkyManager,) until the whole phrase script has been typed through.");
NightTargetHour = ((BasePlugin)this).Config.Bind<float>("Night", "NightTargetHour", 0f, "The hour (0-24) to fast-forward to and hold. 0 = midnight.");
NightTransitionSeconds = ((BasePlugin)this).Config.Bind<float>("Night", "NightTransitionSeconds", 2.5f, "Seconds to smoothly fast-forward into (and, later, back out of) night.");
CyclesBeforeDawn = ((BasePlugin)this).Config.Bind<int>("Night", "CyclesBeforeDawn", 1, "How many full passes through the phrase script are required before daylight is restored.");
HardResetKey = ((BasePlugin)this).Config.Bind<KeyCode>("Reset", "HardResetKey", (KeyCode)290, "Press to instantly clear every zombie, stop ambient sound, restore the sky, and restart the phrase script from the top.");
AutoResetOnSceneLoad = ((BasePlugin)this).Config.Bind<bool>("Reset", "AutoResetOnSceneLoad", true, "If true, a hard reset runs automatically whenever a new scene loads (e.g. joining a new session), so nothing - zombies, sound, forced night, script position - carries over from a previous session.");
ClassInjector.RegisterTypeInIl2Cpp<ZombieManager>();
string directoryName = Path.GetDirectoryName(typeof(Plugin).Assembly.Location);
string jsonPath = Path.Combine(directoryName ?? ".", PhraseBankFileName.Value);
PhraseBank.Load(jsonPath);
if (EnableSfx.Value)
{
Sfx.Init(KeySoundFolder.Value);
Sfx.Init(SpaceSoundFolder.Value);
Sfx.Init(BuzzSoundFolder.Value);
}
ZombieManager.EnsureExists();
ModLog.LogInfo((object)"Zombie Horde Mod initialized. Press '-' to activate.");
}
}
public enum PhraseSelectionMode
{
Sequential,
Random
}
public static class TypingColors
{
public static readonly Color Typed = new Color(1f, 0.85f, 0.15f);
public static readonly Color ActiveRemaining = Color.white;
public static readonly Color IdleRemaining = new Color(0.75f, 0.75f, 0.75f);
}
public static class PhraseBank
{
private static List<string> _phrases = new List<string>();
private static int _sequentialIndex = 0;
private static Queue<string> _shuffleBag = new Queue<string>();
private static string _lastHandedOut = null;
private static int _completedCount = 0;
public static bool IsLoaded => _phrases.Count > 0;
public static int Count => _phrases.Count;
public static int CompletedCycles => (_phrases.Count > 0) ? (_completedCount / _phrases.Count) : 0;
public static void MarkCompleted()
{
_completedCount++;
}
public static void ResetProgress()
{
_sequentialIndex = 0;
_shuffleBag.Clear();
_lastHandedOut = null;
_completedCount = 0;
}
public static bool Load(string jsonPath)
{
//IL_0245: Unknown result type (might be due to invalid IL or missing references)
//IL_024c: Expected O, but got Unknown
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Expected O, but got Unknown
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Expected O, but got Unknown
//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
//IL_01dd: Expected O, but got Unknown
//IL_0180: Unknown result type (might be due to invalid IL or missing references)
//IL_0187: Expected O, but got Unknown
_phrases.Clear();
_sequentialIndex = 0;
_shuffleBag.Clear();
_lastHandedOut = null;
_completedCount = 0;
bool flag = default(bool);
try
{
if (string.IsNullOrEmpty(jsonPath) || !File.Exists(jsonPath))
{
ManualLogSource modLog = Plugin.ModLog;
if (modLog != null)
{
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(67, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("PhraseBank: file not found at '");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(jsonPath);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("'. Falling back to built-in phrases.");
}
modLog.LogWarning(val);
}
LoadFallback();
return false;
}
string json = File.ReadAllText(jsonPath);
List<string> list = ParsePhrasesFromJson(json);
if (list.Count == 0)
{
ManualLogSource modLog2 = Plugin.ModLog;
if (modLog2 != null)
{
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(70, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("PhraseBank: '");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(jsonPath);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' contained no phrases. Falling back to built-in phrases.");
}
modLog2.LogWarning(val);
}
LoadFallback();
return false;
}
foreach (string item in list)
{
if (!string.IsNullOrWhiteSpace(item))
{
_phrases.Add(item.Trim());
}
}
if (_phrases.Count == 0)
{
ManualLogSource modLog3 = Plugin.ModLog;
if (modLog3 != null)
{
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(80, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("PhraseBank: '");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(jsonPath);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' had entries but all were empty. Falling back to built-in phrases.");
}
modLog3.LogWarning(val);
}
LoadFallback();
return false;
}
ManualLogSource modLog4 = Plugin.ModLog;
if (modLog4 != null)
{
BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(36, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("PhraseBank: loaded ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(_phrases.Count);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" phrases from '");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(jsonPath);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("'.");
}
modLog4.LogInfo(val2);
}
return true;
}
catch (Exception ex)
{
ManualLogSource modLog5 = Plugin.ModLog;
if (modLog5 != null)
{
BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(31, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("PhraseBank: failed to load '");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(jsonPath);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("': ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(ex.Message);
}
modLog5.LogError(val3);
}
LoadFallback();
return false;
}
}
private static List<string> ParsePhrasesFromJson(string json)
{
List<string> list = new List<string>();
if (string.IsNullOrEmpty(json))
{
return list;
}
int num = json.IndexOf("\"phrases\"", StringComparison.OrdinalIgnoreCase);
if (num < 0)
{
return list;
}
int num2 = json.IndexOf('[', num);
if (num2 < 0)
{
return list;
}
int num3 = FindMatchingBracket(json, num2);
if (num3 < 0)
{
num3 = json.Length - 1;
}
int i = num2 + 1;
while (i < num3)
{
for (; i < num3 && (char.IsWhiteSpace(json[i]) || json[i] == ','); i++)
{
}
if (i >= num3 || json[i] != '"')
{
break;
}
i++;
StringBuilder stringBuilder = new StringBuilder();
while (i < num3 && json[i] != '"')
{
char c = json[i];
if (c == '\\' && i + 1 < num3)
{
switch (json[i + 1])
{
case '"':
stringBuilder.Append('"');
i += 2;
continue;
case '\\':
stringBuilder.Append('\\');
i += 2;
continue;
case '/':
stringBuilder.Append('/');
i += 2;
continue;
case 'n':
stringBuilder.Append('\n');
i += 2;
continue;
case 't':
stringBuilder.Append('\t');
i += 2;
continue;
case 'r':
stringBuilder.Append('\r');
i += 2;
continue;
case 'b':
stringBuilder.Append('\b');
i += 2;
continue;
case 'f':
stringBuilder.Append('\f');
i += 2;
continue;
case 'u':
if (i + 6 <= json.Length)
{
string s = json.Substring(i + 2, 4);
if (int.TryParse(s, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result))
{
stringBuilder.Append((char)result);
}
i += 6;
continue;
}
break;
}
}
stringBuilder.Append(c);
i++;
}
i++;
list.Add(stringBuilder.ToString());
}
return list;
}
private static int FindMatchingBracket(string json, int openIndex)
{
int num = 0;
for (int i = openIndex; i < json.Length; i++)
{
if (json[i] == '[')
{
num++;
}
else if (json[i] == ']')
{
num--;
if (num == 0)
{
return i;
}
}
}
return -1;
}
private static void LoadFallback()
{
_phrases = new List<string> { "brains", "run for your life", "the horde is coming", "type to survive", "keep your fingers moving", "do not stop typing" };
}
public static string GetNext(PhraseSelectionMode mode)
{
if (_phrases.Count == 0)
{
LoadFallback();
}
return (mode == PhraseSelectionMode.Sequential) ? GetSequential() : GetRandomNoRepeat();
}
private static string GetSequential()
{
string result = _phrases[_sequentialIndex % _phrases.Count];
_sequentialIndex++;
return result;
}
private static string GetRandomNoRepeat()
{
if (_shuffleBag.Count == 0)
{
RefillShuffleBag();
}
return _lastHandedOut = _shuffleBag.Dequeue();
}
private static void RefillShuffleBag()
{
List<string> list = new List<string>(_phrases);
for (int num = list.Count - 1; num > 0; num--)
{
int num2 = Random.Range(0, num + 1);
List<string> list2 = list;
int index = num;
int index2 = num2;
string value = list[num2];
string value2 = list[num];
list2[index] = value;
list[index2] = value2;
}
if (list.Count > 1 && list[0] == _lastHandedOut)
{
List<string> list2 = list;
string value2 = list[1];
string value = list[0];
list[0] = value2;
list2[1] = value;
}
_shuffleBag = new Queue<string>(list);
}
}
public static class ZombieLabel
{
public static TextMesh Create(Transform parent, float heightOffset, int fontSize)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
//IL_002b: 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_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Expected O, but got Unknown
GameObject val = new GameObject("TypingLabel");
val.transform.SetParent(parent, false);
val.transform.localPosition = new Vector3(0f, heightOffset, 0f);
TextMesh val2 = val.AddComponent<TextMesh>();
val2.characterSize = 0.12f;
val2.fontSize = fontSize;
val2.anchor = (TextAnchor)4;
val2.alignment = (TextAlignment)1;
val2.richText = true;
val2.color = Color.white;
MeshRenderer component = val.GetComponent<MeshRenderer>();
if ((Object)component != (Object)null)
{
((Renderer)component).shadowCastingMode = (ShadowCastingMode)0;
((Renderer)component).receiveShadows = false;
}
return val2;
}
public static void SetText(TextMesh tm, string fullPhrase, int typedCount, bool isActiveTarget)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Expected O, but got Unknown
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)tm == (Object)null) && !string.IsNullOrEmpty(fullPhrase))
{
typedCount = Mathf.Clamp(typedCount, 0, fullPhrase.Length);
string value = fullPhrase.Substring(0, typedCount);
string value2 = fullPhrase.Substring(typedCount);
string value3 = ColorUtility.ToHtmlStringRGB(TypingColors.Typed);
Color val = (isActiveTarget ? TypingColors.ActiveRemaining : TypingColors.IdleRemaining);
string value4 = ColorUtility.ToHtmlStringRGB(val);
tm.text = ((typedCount > 0) ? $"<color=#{value3}>{value}</color><color=#{value4}>{value2}</color>" : $"<color=#{value4}>{value2}</color>");
}
}
public static void Billboard(TextMesh tm, Camera cam)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Expected O, but got Unknown
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Expected O, but got Unknown
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: 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_0064: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)tm == (Object)null) && !((Object)cam == (Object)null))
{
Transform transform = ((Component)tm).transform;
Vector3 val = transform.position - ((Component)cam).transform.position;
val.y = 0f;
if (!(((Vector3)(ref val)).sqrMagnitude < 0.0001f))
{
transform.rotation = Quaternion.LookRotation(val);
}
}
}
}
public class ZombieManager : MonoBehaviour
{
private class ZombieInstance
{
public GameObject Root;
public Transform Transform;
public Transform HeadTransform;
public float BobOffset;
public float VerticalVelocity;
public Vector3 TargetOffset;
public float SwayFrequency;
public float SwayAmplitude;
public float SwayPhase;
public string Phrase;
public int TypedCount;
public TextMesh Label;
public bool IsActiveTarget;
public AudioSource BuzzSource;
public float NextBuzzTime;
}
private static Shader _cachedShader;
private bool _isActivated = false;
private readonly List<ZombieInstance> _zombies = new List<ZombieInstance>();
private ZombieInstance _currentTarget;
private int _lastSceneHandle;
public static ZombieManager Instance { get; private set; }
public ZombieManager(IntPtr ptr)
: base(ptr)
{
}
public static void EnsureExists()
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Expected O, but got Unknown
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Expected O, but got Unknown
if ((Object)(object)Instance == (Object)null || (Object)Instance == (Object)null)
{
GameObject val = new GameObject("ZombieManager");
Object.DontDestroyOnLoad((Object)(object)val);
Instance = val.AddComponent<ZombieManager>();
}
}
private void Awake()
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
Instance = this;
Scene activeScene = SceneManager.GetActiveScene();
_lastSceneHandle = SceneHandle.op_Implicit(((Scene)(ref activeScene)).handle);
ManualLogSource modLog = Plugin.ModLog;
if (modLog != null)
{
modLog.LogInfo((object)"ZombieManager awake and persistent.");
}
}
private void Update()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: 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)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
if (Input.GetKeyDown(Plugin.HardResetKey.Value))
{
PerformHardReset("manual key press");
}
if (Plugin.AutoResetOnSceneLoad.Value)
{
Scene activeScene = SceneManager.GetActiveScene();
if (((Scene)(ref activeScene)).handle != SceneHandle.op_Implicit(_lastSceneHandle))
{
_lastSceneHandle = SceneHandle.op_Implicit(((Scene)(ref activeScene)).handle);
PerformHardReset("scene changed to '" + ((Scene)(ref activeScene)).name + "'");
}
}
PurgeDeadZombies();
NightDirector.Tick();
if (!_isActivated)
{
if (Input.GetKeyDown(Plugin.ActivationKey.Value) || ((Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303)) && Input.GetKeyDown((KeyCode)45)))
{
_isActivated = true;
ManualLogSource modLog = Plugin.ModLog;
if (modLog != null)
{
modLog.LogInfo((object)"Zombie Mod Activated! Press '+' to spawn zombies.");
}
NightDirector.RequestNight();
}
}
else
{
if (Input.GetKeyDown(Plugin.SpawnKey.Value) || ((Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303)) && Input.GetKeyDown((KeyCode)61)))
{
SpawnZombie();
}
UpdateZombieAI();
ProcessTypingInput();
}
}
private void PurgeDeadZombies()
{
_zombies.RemoveAll((ZombieInstance z) => z == null || (Object)z.Root == (Object)null);
}
public static void HardReset(string reason)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Expected O, but got Unknown
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Expected O, but got Unknown
if ((Object)(object)Instance == (Object)null || (Object)Instance == (Object)null)
{
ManualLogSource modLog = Plugin.ModLog;
if (modLog != null)
{
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(66, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ZombieManager: hard reset requested (");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(reason);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(") but no instance exists yet.");
}
modLog.LogInfo(val);
}
}
else
{
Instance.PerformHardReset(reason);
}
}
private void PerformHardReset(string reason)
{
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Expected O, but got Unknown
int count = _zombies.Count;
foreach (ZombieInstance zombie in _zombies)
{
if (zombie != null && (Object)zombie.Root != (Object)null)
{
Object.Destroy((Object)(object)zombie.Root);
}
}
_zombies.Clear();
_currentTarget = null;
_isActivated = false;
NightDirector.RestoreImmediate();
PhraseBank.ResetProgress();
ManualLogSource modLog = Plugin.ModLog;
if (modLog != null)
{
modLog.LogInfo((object)($"ZombieManager: hard reset ({reason}) - cleared {count} zombie(s) (and their buzz sources), " + "restored the sky, and restarted the script from the top."));
}
}
private static Shader GetWorkingShader()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Expected O, but got Unknown
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Expected O, but got Unknown
if ((Object)_cachedShader != (Object)null)
{
return _cachedShader;
}
string[] array = new string[7] { "Universal Render Pipeline/Lit", "Universal Render Pipeline/Simple Lit", "Universal Render Pipeline/Unlit", "HDRP/Lit", "Standard", "Legacy Shaders/Diffuse", "Sprites/Default" };
string[] array2 = array;
bool flag = default(bool);
foreach (string text in array2)
{
Shader val = Shader.Find(text);
if (!((Object)val != (Object)null))
{
continue;
}
_cachedShader = val;
ManualLogSource modLog = Plugin.ModLog;
if (modLog != null)
{
BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(29, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("ZombieManager using shader '");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("'");
}
modLog.LogInfo(val2);
}
return val;
}
ManualLogSource modLog2 = Plugin.ModLog;
if (modLog2 != null)
{
modLog2.LogWarning((object)"ZombieManager: No URP shader found.");
}
return null;
}
private static void ApplyColor(Renderer rend, Color color)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Expected O, but got Unknown
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Expected O, but got Unknown
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Expected O, but got Unknown
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
if ((Object)rend == (Object)null)
{
return;
}
Shader workingShader = GetWorkingShader();
if ((Object)workingShader != (Object)null)
{
Material val = new Material(workingShader);
if (val.HasProperty("_BaseColor"))
{
val.SetColor("_BaseColor", color);
}
if (val.HasProperty("_Color"))
{
val.SetColor("_Color", color);
}
rend.material = val;
}
else
{
rend.material.color = color;
}
}
private void SpawnZombie()
{
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Expected O, but got Unknown
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Expected O, but got Unknown
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_0133: 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)
//IL_013a: Unknown result type (might be due to invalid IL or missing references)
//IL_013f: Unknown result type (might be due to invalid IL or missing references)
//IL_0141: 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: Expected O, but got Unknown
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_0179: Unknown result type (might be due to invalid IL or missing references)
//IL_0185: Unknown result type (might be due to invalid IL or missing references)
//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
//IL_01af: 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_01f0: Unknown result type (might be due to invalid IL or missing references)
//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
//IL_022a: Unknown result type (might be due to invalid IL or missing references)
//IL_024b: Unknown result type (might be due to invalid IL or missing references)
//IL_025d: Unknown result type (might be due to invalid IL or missing references)
//IL_0267: Expected O, but got Unknown
//IL_026f: Unknown result type (might be due to invalid IL or missing references)
//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
//IL_02e7: Expected O, but got Unknown
//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
//IL_032a: Unknown result type (might be due to invalid IL or missing references)
//IL_034b: Unknown result type (might be due to invalid IL or missing references)
//IL_035d: Unknown result type (might be due to invalid IL or missing references)
//IL_0367: Expected O, but got Unknown
//IL_036f: Unknown result type (might be due to invalid IL or missing references)
//IL_03aa: Unknown result type (might be due to invalid IL or missing references)
//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0408: Expected O, but got Unknown
//IL_0410: Unknown result type (might be due to invalid IL or missing references)
//IL_044b: Unknown result type (might be due to invalid IL or missing references)
//IL_046c: Unknown result type (might be due to invalid IL or missing references)
//IL_048d: Unknown result type (might be due to invalid IL or missing references)
//IL_049f: Unknown result type (might be due to invalid IL or missing references)
//IL_04a9: Expected O, but got Unknown
//IL_04b1: Unknown result type (might be due to invalid IL or missing references)
//IL_04b9: Unknown result type (might be due to invalid IL or missing references)
//IL_04d7: Unknown result type (might be due to invalid IL or missing references)
//IL_04dc: Unknown result type (might be due to invalid IL or missing references)
//IL_0625: Unknown result type (might be due to invalid IL or missing references)
//IL_0631: Unknown result type (might be due to invalid IL or missing references)
//IL_0638: Unknown result type (might be due to invalid IL or missing references)
//IL_063d: Unknown result type (might be due to invalid IL or missing references)
//IL_0549: Unknown result type (might be due to invalid IL or missing references)
//IL_0550: Expected O, but got Unknown
//IL_06dd: Unknown result type (might be due to invalid IL or missing references)
//IL_06e4: Expected O, but got Unknown
//IL_06f7: Unknown result type (might be due to invalid IL or missing references)
_zombies.RemoveAll((ZombieInstance z) => z == null || (Object)z.Root == (Object)null);
bool flag = default(bool);
if (_zombies.Count >= Plugin.MaxZombies.Value)
{
ManualLogSource modLog = Plugin.ModLog;
if (modLog != null)
{
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(22, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Zombie cap reached (");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Plugin.MaxZombies.Value);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(").");
}
modLog.LogWarning(val);
}
return;
}
Camera main = Camera.main;
if ((Object)(object)main == (Object)null || (Object)main == (Object)null)
{
ManualLogSource modLog2 = Plugin.ModLog;
if (modLog2 != null)
{
modLog2.LogError((object)"Cannot spawn zombie: Camera.main not found.");
}
return;
}
float num = Random.Range(0f, 360f);
float num2 = Random.Range(Plugin.SpawnDistanceMin.Value, Plugin.SpawnDistanceMax.Value);
Vector3 val2 = Quaternion.Euler(0f, num, 0f) * Vector3.forward;
Vector3 val3 = ((Component)main).transform.position + val2 * num2;
if (TryGetGroundY(val3, null, out var groundY))
{
val3.y = groundY;
}
GameObject val4 = new GameObject("Zombie_NPC");
val4.transform.position = val3;
Vector3 val5 = default(Vector3);
((Vector3)(ref val5))..ctor(0f - val2.x, 0f, 0f - val2.z);
val4.transform.rotation = ((((Vector3)(ref val5)).sqrMagnitude > 0.0001f) ? Quaternion.LookRotation(val5) : Quaternion.identity);
Color color = default(Color);
((Color)(ref color))..ctor(1f, 0.82f, 0.05f, 1f);
Color color2 = default(Color);
((Color)(ref color2))..ctor(0.05f, 0.05f, 0.05f, 1f);
Color black = Color.black;
GameObject val6 = GameObject.CreatePrimitive((PrimitiveType)0);
val6.transform.SetParent(val4.transform, false);
val6.transform.localPosition = new Vector3(0f, 0.4f, 0f);
val6.transform.localScale = new Vector3(0.85f, 0.75f, 0.85f);
Object.Destroy((Object)val6.GetComponent<Collider>());
ApplyColor(val6.GetComponent<Renderer>(), color);
GameObject val7 = GameObject.CreatePrimitive((PrimitiveType)0);
val7.transform.SetParent(val4.transform, false);
val7.transform.localPosition = new Vector3(0f, 1f, 0f);
val7.transform.localScale = new Vector3(0.65f, 0.65f, 0.65f);
Object.Destroy((Object)val7.GetComponent<Collider>());
ApplyColor(val7.GetComponent<Renderer>(), color2);
GameObject val8 = GameObject.CreatePrimitive((PrimitiveType)0);
val8.transform.SetParent(val4.transform, false);
val8.transform.localPosition = new Vector3(0f, 1.55f, 0f);
val8.transform.localScale = new Vector3(0.55f, 0.55f, 0.55f);
Object.Destroy((Object)val8.GetComponent<Collider>());
ApplyColor(val8.GetComponent<Renderer>(), color);
GameObject val9 = GameObject.CreatePrimitive((PrimitiveType)3);
val9.transform.SetParent(val8.transform, false);
val9.transform.localPosition = new Vector3(-0.15f, 0.05f, 0.22f);
val9.transform.localRotation = Quaternion.Euler(0f, 0f, 45f);
val9.transform.localScale = new Vector3(0.12f, 0.03f, 0.03f);
Object.Destroy((Object)val9.GetComponent<Collider>());
ApplyColor(val9.GetComponent<Renderer>(), black);
GameObject val10 = GameObject.CreatePrimitive((PrimitiveType)3);
val10.transform.SetParent(val8.transform, false);
val10.transform.localPosition = new Vector3(0.15f, 0.05f, 0.22f);
val10.transform.localRotation = Quaternion.Euler(0f, 0f, -45f);
val10.transform.localScale = new Vector3(0.12f, 0.03f, 0.03f);
Object.Destroy((Object)val10.GetComponent<Collider>());
ApplyColor(val10.GetComponent<Renderer>(), black);
Vector2 val11 = Random.insideUnitCircle * Random.Range(Plugin.SurroundRadiusMin.Value, Plugin.SurroundRadiusMax.Value);
string next = PhraseBank.GetNext(Plugin.CurrentSelectionMode);
TextMesh val12 = null;
if (Plugin.EnableTypingMode.Value)
{
val12 = ZombieLabel.Create(val8.transform, Plugin.LabelHeightOffset.Value, Plugin.LabelFontSize.Value);
ZombieLabel.SetText(val12, next, 0, isActiveTarget: false);
}
AudioSource val13 = null;
if (Plugin.EnableSfx.Value)
{
GameObject val14 = new GameObject("ZombieBuzzSource");
val14.transform.SetParent(val7.transform, false);
val13 = ((Il2CppObjectBase)val14.AddComponent(Il2CppType.Of<AudioSource>())).Cast<AudioSource>();
val13.playOnAwake = false;
val13.loop = false;
val13.spatialBlend = 1f;
val13.minDistance = Plugin.BuzzMinDistance.Value;
val13.maxDistance = Plugin.BuzzMaxDistance.Value;
val13.rolloffMode = (AudioRolloffMode)1;
val13.volume = Plugin.BuzzVolume.Value;
}
_zombies.Add(new ZombieInstance
{
Root = val4,
Transform = val4.transform,
HeadTransform = val8.transform,
BobOffset = Random.Range(0f, 100f),
VerticalVelocity = 0f,
TargetOffset = new Vector3(val11.x, 0f, val11.y),
SwayFrequency = Random.Range(2f, 4.5f),
SwayAmplitude = Random.Range(0.5f, 1.3f),
SwayPhase = Random.Range(0f, 6.28f),
Phrase = next,
TypedCount = 0,
Label = val12,
IsActiveTarget = false,
BuzzSource = val13,
NextBuzzTime = Time.time + Random.Range(0f, Plugin.BuzzIntervalMax.Value)
});
ManualLogSource modLog3 = Plugin.ModLog;
if (modLog3 != null)
{
BepInExInfoLogInterpolatedStringHandler val15 = new BepInExInfoLogInterpolatedStringHandler(49, 3, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val15).AppendLiteral("Zombie spawned at ");
((BepInExLogInterpolatedStringHandler)val15).AppendFormatted<Vector3>(val3);
((BepInExLogInterpolatedStringHandler)val15).AppendLiteral(" with phrase \"");
((BepInExLogInterpolatedStringHandler)val15).AppendFormatted<string>(next);
((BepInExLogInterpolatedStringHandler)val15).AppendLiteral("\". Active count: ");
((BepInExLogInterpolatedStringHandler)val15).AppendFormatted<int>(_zombies.Count);
}
modLog3.LogInfo(val15);
}
}
private void UpdateZombieAI()
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: 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_0075: Expected O, but got Unknown
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: 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_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: 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_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_010b: Unknown result type (might be due to invalid IL or missing references)
//IL_0110: Unknown result type (might be due to invalid IL or missing references)
//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
//IL_0238: Unknown result type (might be due to invalid IL or missing references)
//IL_023a: Unknown result type (might be due to invalid IL or missing references)
//IL_023c: Unknown result type (might be due to invalid IL or missing references)
//IL_0241: Unknown result type (might be due to invalid IL or missing references)
//IL_0223: Unknown result type (might be due to invalid IL or missing references)
//IL_0227: Unknown result type (might be due to invalid IL or missing references)
//IL_0230: Unknown result type (might be due to invalid IL or missing references)
//IL_0235: Unknown result type (might be due to invalid IL or missing references)
//IL_0146: Unknown result type (might be due to invalid IL or missing references)
//IL_0151: Expected O, but got Unknown
//IL_028e: Unknown result type (might be due to invalid IL or missing references)
//IL_0290: Unknown result type (might be due to invalid IL or missing references)
//IL_0293: Unknown result type (might be due to invalid IL or missing references)
//IL_0298: Unknown result type (might be due to invalid IL or missing references)
//IL_029d: Unknown result type (might be due to invalid IL or missing references)
//IL_029f: Unknown result type (might be due to invalid IL or missing references)
//IL_025a: Unknown result type (might be due to invalid IL or missing references)
//IL_025f: Unknown result type (might be due to invalid IL or missing references)
//IL_0264: Unknown result type (might be due to invalid IL or missing references)
//IL_0274: Unknown result type (might be due to invalid IL or missing references)
//IL_0279: Unknown result type (might be due to invalid IL or missing references)
//IL_0282: 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_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_0300: Unknown result type (might be due to invalid IL or missing references)
//IL_0341: Unknown result type (might be due to invalid IL or missing references)
//IL_0353: Unknown result type (might be due to invalid IL or missing references)
//IL_035e: Expected O, but got Unknown
//IL_01a2: 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_01be: Unknown result type (might be due to invalid IL or missing references)
//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
Camera main = Camera.main;
if ((Object)(object)main == (Object)null || (Object)main == (Object)null)
{
return;
}
Vector3 position = ((Component)main).transform.position;
float value = Plugin.ZombieSpeed.Value;
float deltaTime = Time.deltaTime;
Vector3 val = default(Vector3);
for (int i = 0; i < _zombies.Count; i++)
{
ZombieInstance zombieInstance = _zombies[i];
if (zombieInstance == null || (Object)zombieInstance.Root == (Object)null)
{
continue;
}
Vector3 position2 = zombieInstance.Transform.position;
float num = Time.time * zombieInstance.SwayFrequency + zombieInstance.SwayPhase;
((Vector3)(ref val))..ctor(Mathf.Sin(num) * zombieInstance.SwayAmplitude, 0f, Mathf.Cos(num * 0.63f) * zombieInstance.SwayAmplitude * 0.75f);
Vector3 val2 = position + zombieInstance.TargetOffset + val;
Vector3 val3 = val2 - position2;
val3.y = 0f;
Vector3 val4 = Vector3.zero;
for (int j = 0; j < _zombies.Count; j++)
{
if (i == j)
{
continue;
}
ZombieInstance zombieInstance2 = _zombies[j];
if (zombieInstance2 != null && !((Object)zombieInstance2.Root == (Object)null))
{
Vector3 val5 = position2 - zombieInstance2.Transform.position;
val5.y = 0f;
float sqrMagnitude = ((Vector3)(ref val5)).sqrMagnitude;
if (sqrMagnitude < 0.64f && sqrMagnitude > 0.0001f)
{
val4 += ((Vector3)(ref val5)).normalized * ((0.8f - Mathf.Sqrt(sqrMagnitude)) * 2f);
}
}
}
float magnitude = ((Vector3)(ref val3)).magnitude;
Vector3 val6 = Vector3.zero;
if (magnitude > 0.001f)
{
float num2 = Mathf.Max(Mathf.Clamp01(magnitude / 1.5f), 0.35f);
val6 = val3 / magnitude * (value * num2);
}
Vector3 val7 = val6 + val4;
if (((Vector3)(ref val7)).sqrMagnitude > 0.0025f)
{
Quaternion val8 = Quaternion.LookRotation(((Vector3)(ref val7)).normalized);
zombieInstance.Transform.rotation = Quaternion.Slerp(zombieInstance.Transform.rotation, val8, deltaTime * 6f);
}
Vector3 val9 = position2 + val7 * deltaTime;
if (TryGetGroundY(val9, zombieInstance.Transform, out var groundY))
{
val9.y = groundY;
zombieInstance.VerticalVelocity = 0f;
}
else
{
zombieInstance.VerticalVelocity -= 9.81f * deltaTime;
val9.y += zombieInstance.VerticalVelocity * deltaTime;
}
zombieInstance.Transform.position = val9;
float num3 = Mathf.Sin(Time.time * 8f + zombieInstance.BobOffset) * 0.05f;
zombieInstance.HeadTransform.localPosition = new Vector3(0f, 1.55f + num3, 0f);
if ((Object)zombieInstance.Label != (Object)null)
{
ZombieLabel.Billboard(zombieInstance.Label, main);
}
UpdateZombieBuzz(zombieInstance);
}
}
private void UpdateZombieBuzz(ZombieInstance zombie)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Expected O, but got Unknown
if (Plugin.EnableSfx.Value && !((Object)zombie.BuzzSource == (Object)null) && !(Time.time < zombie.NextBuzzTime))
{
AudioClip randomClip = Sfx.GetRandomClip(Plugin.BuzzSoundFolder.Value);
if ((Object)(object)randomClip != (Object)null)
{
zombie.BuzzSource.clip = randomClip;
zombie.BuzzSource.Play();
}
zombie.NextBuzzTime = Time.time + Random.Range(Plugin.BuzzIntervalMin.Value, Plugin.BuzzIntervalMax.Value);
}
}
private void ProcessTypingInput()
{
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Expected O, but got Unknown
if (!Plugin.EnableTypingMode.Value)
{
return;
}
string inputString = Input.inputString;
if (string.IsNullOrEmpty(inputString))
{
return;
}
for (int i = 0; i < inputString.Length; i++)
{
char c = char.ToLowerInvariant(inputString[i]);
if (char.IsControl(c) && c != ' ')
{
continue;
}
if (_currentTarget == null || (Object)_currentTarget.Root == (Object)null)
{
ZombieInstance zombieInstance = FindTargetStartingWith(c);
if (zombieInstance != null)
{
if (zombieInstance.TypedCount >= zombieInstance.Phrase.Length)
{
KillZombie(zombieInstance);
_currentTarget = null;
}
else
{
_currentTarget = zombieInstance;
}
}
}
else
{
TryAdvanceTarget(c);
}
}
}
private ZombieInstance FindTargetStartingWith(char c)
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: 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_006c: Expected O, but got Unknown
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
Camera main = Camera.main;
Vector3 val = (((Object)(object)main != (Object)null && (Object)main != (Object)null) ? ((Component)main).transform.position : Vector3.zero);
ZombieInstance zombieInstance = null;
float num = float.MaxValue;
foreach (ZombieInstance zombie in _zombies)
{
if (zombie != null && !((Object)zombie.Root == (Object)null) && !string.IsNullOrEmpty(zombie.Phrase) && char.ToLowerInvariant(zombie.Phrase[0]) == c)
{
Vector3 val2 = zombie.Transform.position - val;
float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
if (sqrMagnitude < num)
{
num = sqrMagnitude;
zombieInstance = zombie;
}
}
}
if (zombieInstance != null)
{
zombieInstance.IsActiveTarget = true;
zombieInstance.TypedCount = 1;
RefreshLabel(zombieInstance);
PlayKeystrokeSound(c);
}
return zombieInstance;
}
private void TryAdvanceTarget(char c)
{
ZombieInstance currentTarget = _currentTarget;
if (currentTarget.TypedCount >= currentTarget.Phrase.Length)
{
KillZombie(currentTarget);
_currentTarget = null;
return;
}
char c2 = char.ToLowerInvariant(currentTarget.Phrase[currentTarget.TypedCount]);
if (c == c2)
{
PlayKeystrokeSound(c);
currentTarget.TypedCount++;
if (currentTarget.TypedCount >= currentTarget.Phrase.Length)
{
KillZombie(currentTarget);
_currentTarget = null;
}
else
{
RefreshLabel(currentTarget);
}
}
}
private void RefreshLabel(ZombieInstance z)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
if ((Object)z.Label != (Object)null)
{
ZombieLabel.SetText(z.Label, z.Phrase, z.TypedCount, z.IsActiveTarget);
}
}
private void PlayKeystrokeSound(char c)
{
if (Plugin.EnableSfx.Value)
{
Sfx.PlayRandom((c == ' ') ? Plugin.SpaceSoundFolder.Value : Plugin.KeySoundFolder.Value);
}
}
private void KillZombie(ZombieInstance z)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Expected O, but got Unknown
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Expected O, but got Unknown
_zombies.Remove(z);
if ((Object)z.Root != (Object)null)
{
Object.Destroy((Object)(object)z.Root);
}
ManualLogSource modLog = Plugin.ModLog;
if (modLog != null)
{
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(20, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Zombie typed out: \"");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(z.Phrase);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\"");
}
modLog.LogInfo(val);
}
PhraseBank.MarkCompleted();
if (PhraseBank.CompletedCycles >= Mathf.Max(1, Plugin.CyclesBeforeDawn.Value))
{
TriggerVictory();
}
else if (_isActivated && Plugin.AutoRespawnOnKill.Value)
{
SpawnZombie();
}
}
private void TriggerVictory()
{
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Expected O, but got Unknown
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
int count = _zombies.Count;
foreach (ZombieInstance zombie in _zombies)
{
if (zombie != null && (Object)zombie.Root != (Object)null)
{
Object.Destroy((Object)(object)zombie.Root);
}
}
_zombies.Clear();
_currentTarget = null;
_isActivated = false;
NightDirector.ReleaseNight();
PhraseBank.ResetProgress();
ManualLogSource modLog = Plugin.ModLog;
if (modLog != null)
{
modLog.LogInfo((object)("Horde defeated - full script typed out" + ((count > 0) ? $" (cleared {count} remaining zombie(s))" : "") + $". Press '{Plugin.ActivationKey.Value}' to start a new round."));
}
}
private static bool TryGetGroundY(Vector3 pos, Transform selfTransform, out float groundY)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: 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)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: 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_0068: 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)
groundY = pos.y;
Ray val = default(Ray);
((Ray)(ref val))..ctor(pos + Vector3.up * 2.5f, Vector3.down);
RaycastHit[] array = Il2CppArrayBase<RaycastHit>.op_Implicit((Il2CppArrayBase<RaycastHit>)(object)Physics.RaycastAll(val, 15f));
if (array != null && array.Length != 0)
{
float num = -9999f;
bool flag = false;
for (int i = 0; i < array.Length; i++)
{
RaycastHit val2 = array[i];
if (!((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null) && !((RaycastHit)(ref val2)).collider.isTrigger && (!((Object)(object)selfTransform != (Object)null) || !((RaycastHit)(ref val2)).transform.IsChildOf(selfTransform)) && ((RaycastHit)(ref val2)).point.y > num)
{
num = ((RaycastHit)(ref val2)).point.y;
flag = true;
}
}
if (flag)
{
groundY = num;
return true;
}
}
return false;
}
}
}