using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using ChaosCompany.Scripts.Abstracts;
using ChaosCompany.Scripts.Components;
using ChaosCompany.Scripts.DataStructures;
using ChaosCompany.Scripts.Entities;
using ChaosCompany.Scripts.Items;
using ChaosCompany.Scripts.Managers;
using ChaosCompany.Scripts.Patches;
using Dissonance.Integrations.Unity_NFGO;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ChaosCompany")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("It's unpredictable chaos can you survive?")]
[assembly: AssemblyFileVersion("1.2.5.0")]
[assembly: AssemblyInformationalVersion("1.2.5+6f6be5ce8483c7c7e8198489f2f482d770ad0542")]
[assembly: AssemblyProduct("ChaosCompany")]
[assembly: AssemblyTitle("ChaosCompany")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.5.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace ChaosCompany
{
public static class PluginInfo
{
public const string PLUGIN_GUID = "ChaosCompany";
public const string PLUGIN_NAME = "ChaosCompany";
public const string PLUGIN_VERSION = "1.2.5";
}
}
namespace ChaosCompany.Scripts
{
[BepInPlugin("ChaosCompany", "ChaosCompany", "1.2.5")]
public class Plugin : BaseUnityPlugin
{
private readonly Harmony harmony = new Harmony("ChaosCompany");
public static ManualLogSource Logger { get; private set; } = Logger.CreateLogSource("ChaosCompany");
private void Awake()
{
Logger.LogInfo((object)"Plugin ChaosCompany is loaded! yeah baby!!!");
harmony.PatchAll(Assembly.GetExecutingAssembly());
}
}
}
namespace ChaosCompany.Scripts.Patches
{
[HarmonyPatch(typeof(DepositItemsDesk))]
internal static class DepositItemsDeskPatch
{
public static HashSet<float> soundVolumes = new HashSet<float>();
private static int timesHearingNoise = 0;
public static Timer consecutiveNoiseDelay = new Timer(3f, oneshot: false);
[HarmonyPostfix]
[HarmonyPatch("Start")]
private static void StartPostfix(DepositItemsDesk __instance)
{
if (NetworkManager.Singleton.IsServer)
{
GameManager.Timers.Add(consecutiveNoiseDelay);
}
}
[HarmonyPostfix]
[HarmonyPatch("SetTimesHeardNoiseServerRpc")]
private static void SetTimesHeardNoiseServerRpcPostfix(DepositItemsDesk __instance, ref float valueChange)
{
if (!NetworkManager.Singleton.IsServer)
{
return;
}
int num = 0;
bool flag = false;
foreach (float soundVolume in soundVolumes)
{
if (soundVolume < valueChange)
{
num++;
}
if (MathF.Abs(soundVolume - valueChange) <= 0.1f)
{
flag = true;
}
}
if (flag && num < 1)
{
return;
}
if (num < 1 || soundVolumes.Count == 0)
{
soundVolumes.Add(valueChange);
return;
}
soundVolumes.Add(valueChange);
consecutiveNoiseDelay.Restart();
consecutiveNoiseDelay.OnTimeout += delegate
{
timesHearingNoise = 0;
consecutiveNoiseDelay.Stop();
};
if (timesHearingNoise > 2 && timesHearingNoise < 8)
{
__instance.MakeWarningNoiseClientRpc();
}
else if (timesHearingNoise >= 8)
{
__instance.AttackPlayersServerRpc();
timesHearingNoise = 0;
return;
}
timesHearingNoise++;
}
}
[HarmonyPatch(typeof(GameNetworkManager))]
public class GameNetworkManagerPatch
{
[HarmonyPostfix]
[HarmonyPatch("DisconnectProcess")]
private static void DisconnectProcessPostfix()
{
if (NetworkManager.Singleton.IsServer)
{
if (TimeOfDayPatch.Instance != null)
{
TimeOfDayPatch.Instance.quotaVariables.deadlineDaysAmount = Random.Range(4, 7);
}
GameManager.gameOver = true;
Plugin.Logger.LogError((object)"Game Ended");
GameManager.Reset();
}
}
}
[HarmonyPatch(typeof(PlayerControllerB))]
internal static class PlayerControllerBPatch
{
public static bool isEnemyAlreadySpawnedOnItemPosition;
[HarmonyPrefix]
[HarmonyPatch("StartSinkingServerRpc")]
private static void StartSinkingServerRpcPrefix(ref float sinkingSpeed, ref int audioClipIndex)
{
if (NetworkManager.Singleton.IsServer)
{
sinkingSpeed *= Random.Range(0.25f, 2f);
}
}
[HarmonyPrefix]
[HarmonyPatch("DamagePlayerServerRpc")]
private static void DamagePlayerServerRpcPrefix(ref int damageNumber, ref int newHealthAmount)
{
if (NetworkManager.Singleton.IsServer)
{
damageNumber = (int)((float)damageNumber * Random.Range(0.25f, 1f));
}
}
[HarmonyPostfix]
[HarmonyPatch("GrabObjectServerRpc")]
private static void GrabObjectServerRpcPostfix(PlayerControllerB __instance, ref NetworkObjectReference grabbedObject)
{
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
NetworkObject val = default(NetworkObject);
if (!NetworkManager.Singleton.IsServer || (Object)(object)__instance == (Object)null || (Object)(object)NetworkManager.Singleton == (Object)null || (Object)(object)RoundManagerPatch.Instance == (Object)null || !((NetworkObjectReference)(ref grabbedObject)).TryGet(ref val, NetworkManager.Singleton))
{
return;
}
ChaoticItemAdditionalData component = ((Component)val).GetComponent<ChaoticItemAdditionalData>();
if (component != null)
{
component.pickedUp = true;
}
if (RoundManagerPatch.Instance.currentLevel.Enemies.Count == 0 || isEnemyAlreadySpawnedOnItemPosition || __instance.isInElevator || Random.Range(0, 100) != 0)
{
return;
}
if (__instance.isInsideFactory)
{
var (val2, val3) = GameManager.SpawnRandomEnemy(RoundManagerPatch.Instance, inside: true, ((Component)val).transform.position, 0f, new List<string>(2) { "dressedgirl", "nutcracker" });
if ((Object)(object)val2 == (Object)null)
{
return;
}
}
else if (!__instance.isInsideFactory && !__instance.isInHangarShipRoom)
{
var (val4, val5) = GameManager.SpawnRandomEnemy(RoundManagerPatch.Instance, inside: false, ((Component)val).transform.position, 0f, new List<string>(4) { "mech", "worm", "dog", "double" });
if ((Object)(object)val4 == (Object)null)
{
return;
}
}
isEnemyAlreadySpawnedOnItemPosition = true;
Timer timer = new Timer(1f, oneshot: true);
timer.OnTimeout += delegate
{
isEnemyAlreadySpawnedOnItemPosition = false;
};
timer.Start();
GameManager.Timers.Add(timer);
}
}
[HarmonyPatch(typeof(RoundManager))]
internal static class RoundManagerPatch
{
public static RoundManager? Instance { get; private set; }
[HarmonyPostfix]
[HarmonyPatch("Start")]
private static void StartPostfix(RoundManager __instance)
{
if (NetworkManager.Singleton.IsServer)
{
Plugin.Logger.LogError((object)"Round Manager start method get called");
GameManager.Reset();
Instance = __instance;
}
}
[HarmonyPrefix]
[HarmonyPatch("Update")]
private static void UpdatePrefix()
{
if (!NetworkManager.Singleton.IsServer)
{
return;
}
for (int num = GameManager.Timers.Count - 1; num >= 0; num--)
{
GameManager.Timers[num].Update();
if (GameManager.Timers[num].Finished)
{
GameManager.Timers.RemoveAt(num);
}
}
if (Instance == null || GameManager.gameOver || !Instance.dungeonFinishedGeneratingForAllPlayers || Instance.allEnemyVents.Length == 0)
{
return;
}
for (int num2 = GameManager.chaoticEntities.Count - 1; num2 >= 0; num2--)
{
GameManager.chaoticEntities[num2].Update();
if (GameManager.chaoticEntities[num2].ItsJoever)
{
if (GameManager.chaoticEntities[num2] is ChaoticEnemy)
{
Timer timer = new Timer(Random.Range(120, 150), oneshot: true);
timer.OnTimeout += delegate
{
GameManager.SpawnChaoticEnemy(Instance);
};
timer.Start();
GameManager.Timers.Add(timer);
}
GameManager.chaoticEntities.RemoveAt(num2);
}
}
if (GameManager.beginChaos)
{
return;
}
GameManager.StartSpawning(Instance);
Plugin.Logger.LogError((object)"Chaos is starting");
Timer timer2 = new Timer(5f, oneshot: true);
timer2.OnTimeout += delegate
{
for (int i = 0; i < GameManager.maxChaoticItemSpawn; i++)
{
GameManager.SpawnChaoticItem(Instance);
}
};
timer2.Start();
GameManager.Timers.Add(timer2);
GameManager.spawnEnemyTimer.Start();
GameManager.beginChaos = true;
}
[HarmonyPrefix]
[HarmonyPatch("DetectElevatorIsRunning")]
private static void DetectElevatorIsRunningPrefix()
{
if (NetworkManager.Singleton.IsServer)
{
if (TimeOfDayPatch.Instance != null)
{
TimeOfDayPatch.Instance.quotaVariables.deadlineDaysAmount = Random.Range(4, 7);
}
GameManager.gameOver = true;
GameManager.Reset();
}
}
}
[HarmonyPatch(typeof(StartOfRound))]
public class StartOfRoundPatch
{
[HarmonyPrefix]
[HarmonyPatch("SceneManager_OnLoad")]
private static void SceneManager_OnLoadPatch(StartOfRound __instance, ulong clientId, ref string sceneName, ref LoadSceneMode loadSceneMode, ref AsyncOperation asyncOperation)
{
if (NetworkManager.Singleton.IsServer)
{
Random.InitState(__instance.randomMapSeed);
Plugin.Logger.LogError((object)("Game Starting with level " + sceneName));
if (sceneName != "CompanyBuilding")
{
GameManager.gameOver = false;
}
}
}
}
[HarmonyPatch(typeof(TimeOfDay))]
internal static class TimeOfDayPatch
{
public static TimeOfDay? Instance { get; set; }
[HarmonyPrefix]
[HarmonyPatch("Awake")]
private static void AwakePrefix(TimeOfDay __instance)
{
if (NetworkManager.Singleton.IsServer)
{
if ((Object)(object)Instance == (Object)null)
{
__instance.quotaVariables.deadlineDaysAmount = Random.Range(4, 7);
__instance.SyncTimeClientRpc(__instance.globalTime, (int)__instance.timeUntilDeadline);
}
Instance = __instance;
GameManager.timeMultiplier = Random.Range(0.25f, 1.75f);
GameManager.spawnEnemyTimer = new Timer(180f * (1f / GameManager.timeMultiplier), oneshot: false);
__instance.globalTimeSpeedMultiplier = GameManager.timeMultiplier;
}
}
}
}
namespace ChaosCompany.Scripts.Managers
{
public enum EnemySpawnType
{
Inside,
Outside
}
public static class GameManager
{
public static bool gameOver;
public static Timer spawnEnemyTimer = new Timer(Random.Range(180, 240), oneshot: false);
public static EnemySpawnType[] spawnTypes = new EnemySpawnType[2]
{
EnemySpawnType.Inside,
EnemySpawnType.Outside
};
public static List<Chaotic> chaoticEntities = new List<Chaotic>();
public static int numberOfTriesOfSpawningRandomEnemyNearPlayer = 6;
public static int modMaxEnemyNumber = Random.Range(2, 4);
public static int modEnemyNumber = 0;
public static int maxChaoticEnemySpawn = 2;
public static int maxMoveEnemySpawn = 2;
public static int maxChaoticItemSpawn = Random.Range(2, 5);
public static bool beginChaos;
public static float timeMultiplier;
public static List<Timer> Timers { get; private set; } = new List<Timer>();
public static void Reset()
{
Plugin.Logger.LogError((object)"Game Reset");
Timers.Clear();
foreach (Chaotic chaoticEntity in chaoticEntities)
{
if ((Object)(object)chaoticEntity.NetworkObject == (Object)null)
{
Plugin.Logger.LogError((object)"Despawning chaotic entities failed because network object == null");
continue;
}
if (!chaoticEntity.NetworkObject.IsSpawned)
{
Plugin.Logger.LogError((object)"chaoticEntity is not spawned on the network");
continue;
}
if (chaoticEntity is ChaoticEnemy chaoticEnemy)
{
if ((Object)(object)chaoticEnemy.EnemyAI == (Object)null)
{
Plugin.Logger.LogError((object)"chaoticEnemy.EnemyAI == null while trying to print the enemy");
chaoticEntity.NetworkObject.Despawn(true);
continue;
}
Plugin.Logger.LogError((object)("Despawning chaotic enemy " + chaoticEnemy.EnemyAI.enemyType.enemyName));
}
else if (chaoticEntity is MoveEnemy moveEnemy)
{
if ((Object)(object)moveEnemy.EnemyAI == (Object)null)
{
Plugin.Logger.LogError((object)"moveEnemy.EnemyAI == null while trying to print the enemy");
chaoticEntity.NetworkObject.Despawn(true);
continue;
}
Plugin.Logger.LogError((object)("Despawning move enemy " + moveEnemy.EnemyAI.enemyType.enemyName));
}
else if (chaoticEntity is ChaoticItem)
{
Plugin.Logger.LogError((object)"Despawning chaotic item");
}
chaoticEntity.NetworkObject.Despawn(true);
}
PlayerControllerBPatch.isEnemyAlreadySpawnedOnItemPosition = false;
chaoticEntities.Clear();
modEnemyNumber = 0;
maxChaoticItemSpawn = Random.Range(2, 5);
modMaxEnemyNumber = Random.Range(2, 4);
maxChaoticEnemySpawn = 2;
maxMoveEnemySpawn = 2;
beginChaos = false;
numberOfTriesOfSpawningRandomEnemyNearPlayer = 6;
}
public static (EnemyType?, NetworkObjectReference?) SpawnRandomEnemy(RoundManager roundManager, bool inside, Vector3 position, float yRotation = 0f, List<string>? exclusion = null)
{
//IL_0193: Unknown result type (might be due to invalid IL or missing references)
//IL_019c: Unknown result type (might be due to invalid IL or missing references)
//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
Plugin.Logger.LogError((object)"Trying to spawn random enemy");
List<SpawnableEnemyWithRarity> list;
if (inside)
{
list = roundManager.currentLevel.Enemies;
}
else
{
List<SpawnableEnemyWithRarity> outsideEnemies = roundManager.currentLevel.OutsideEnemies;
outsideEnemies.AddRange(roundManager.currentLevel.DaytimeEnemies);
list = outsideEnemies;
}
int count = list.Count;
if (count == 0)
{
Plugin.Logger.LogError((object)"Cannot spawn enemy, enemiesTypes list is empty");
return (null, null);
}
SpawnableEnemyWithRarity val = list[Random.Range(0, count)];
bool flag = false;
if (exclusion != null)
{
foreach (string item in exclusion)
{
string text = ((object)val.enemyType).ToString().ToLower().Trim();
string text2 = item.ToLower().Trim();
if (text.Contains(text2) || text == text2)
{
flag = true;
break;
}
}
int num = 20;
while (flag && num != 0)
{
val = list[Random.Range(0, count)];
flag = false;
foreach (string item2 in exclusion)
{
string text3 = ((object)val.enemyType).ToString().ToLower().Trim();
if (text3.Contains(item2.ToLower().Trim()))
{
flag = true;
break;
}
}
num--;
}
}
if (flag)
{
Plugin.Logger.LogError((object)"Cannot spawn enemy all of the enemies level in the map is in the exclusion list");
return (null, null);
}
NetworkObjectReference value = roundManager.SpawnEnemyGameObject(position, yRotation, -1, val.enemyType);
NetworkObject val2 = default(NetworkObject);
((NetworkObjectReference)(ref value)).TryGet(ref val2, (NetworkManager)null);
return (val.enemyType, value);
}
public static PlayerControllerB? GetClosestPlayerWithLineOfSight(RoundManager roundManager, EnemyAI enemyAI)
{
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
List<PlayerControllerB> list = roundManager.playersManager.allPlayerScripts.ToList();
for (int num = list.Count - 1; num >= 0; num--)
{
if (list[num].isPlayerDead)
{
list.RemoveAt(num);
}
}
if (list.Count == 0)
{
return null;
}
PlayerControllerB val = list[0];
for (int i = 0; i < list.Count; i++)
{
if (enemyAI.CheckLineOfSightForPosition(((Component)((NetworkBehaviour)list[i]).NetworkObject).transform.position, 360f, 100000, -1f, (Transform)null) && !list[i].isPlayerDead && Vector3.Distance(((Component)((NetworkBehaviour)list[i]).NetworkObject).transform.position, ((Component)((NetworkBehaviour)enemyAI).NetworkObject).transform.position) < Vector3.Distance(((Component)((NetworkBehaviour)val).NetworkObject).transform.position, ((Component)((NetworkBehaviour)enemyAI).NetworkObject).transform.position))
{
val = list[i];
}
}
return val;
}
public static PlayerControllerB? GetRandomAlivePlayer(RoundManager roundManager, bool inside)
{
Plugin.Logger.LogError((object)"Trying to get random alive player");
List<PlayerControllerB> list = roundManager.playersManager.allPlayerScripts.ToList();
int count = list.Count;
if (count == 0)
{
Plugin.Logger.LogError((object)"No player is online lmao");
return null;
}
PlayerControllerB val = list[Random.Range(0, count)];
int num = list.Count;
int num2 = 20;
while ((val.isInsideFactory != inside || (Object)(object)val.deadBody != (Object)null) && num2 != 0)
{
list.Remove(val);
if (list.Count == 0)
{
return null;
}
val = list[Random.Range(0, list.Count)];
num--;
if (num <= 0)
{
return null;
}
num2--;
}
if (val.isInsideFactory != inside && (Object)(object)val.deadBody != (Object)null)
{
return null;
}
return val;
}
public static void SpawnRandomEnemyNearRandomPlayer(RoundManager roundManager, bool inside)
{
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
RoundManager roundManager2 = roundManager;
if (roundManager2.playersManager.allPlayerScripts.Length == 0)
{
Plugin.Logger.LogError((object)"Cannot spawn enemy there is no player");
return;
}
PlayerControllerB randomAlivePlayer = GetRandomAlivePlayer(roundManager2, inside);
if ((Object)(object)randomAlivePlayer == (Object)null)
{
return;
}
Vector3 targetPositionPrevious = ((Component)randomAlivePlayer).gameObject.GetComponent<NfgoPlayer>().Position;
Timer timer = new Timer(10f, oneshot: true);
timer.OnTimeout += delegate
{
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_015d: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)randomAlivePlayer.deadBody != (Object)null || randomAlivePlayer.isInsideFactory != inside)
{
if (numberOfTriesOfSpawningRandomEnemyNearPlayer != 0)
{
SpawnRandomEnemyNearRandomPlayer(roundManager2, inside);
numberOfTriesOfSpawningRandomEnemyNearPlayer--;
}
}
else
{
Vector3 position = ((Component)randomAlivePlayer).gameObject.GetComponent<NfgoPlayer>().Position;
int num = 20;
if (Vector3.Distance(targetPositionPrevious, position) <= (float)num)
{
if (numberOfTriesOfSpawningRandomEnemyNearPlayer != 0)
{
SpawnRandomEnemyNearRandomPlayer(roundManager2, inside);
numberOfTriesOfSpawningRandomEnemyNearPlayer--;
}
}
else
{
bool flag = false;
PlayerControllerB[] allPlayerScripts = roundManager2.playersManager.allPlayerScripts;
foreach (PlayerControllerB val in allPlayerScripts)
{
if (Vector3.Distance(((Component)val).transform.position, targetPositionPrevious) <= (float)num)
{
flag = true;
break;
}
}
if (flag)
{
if (numberOfTriesOfSpawningRandomEnemyNearPlayer != 0)
{
SpawnRandomEnemyNearRandomPlayer(roundManager2, inside);
numberOfTriesOfSpawningRandomEnemyNearPlayer--;
}
}
else
{
if (inside)
{
var (val2, val3) = SpawnRandomEnemy(roundManager2, inside: true, targetPositionPrevious, 0f, new List<string>(1) { "DressGirl" });
if ((Object)(object)val2 == (Object)null)
{
return;
}
}
else
{
var (val4, val5) = SpawnRandomEnemy(roundManager2, inside: false, targetPositionPrevious, 0f, new List<string>(3) { "mech", "worm", "double" });
if ((Object)(object)val4 == (Object)null)
{
return;
}
}
numberOfTriesOfSpawningRandomEnemyNearPlayer = 6;
}
}
}
};
Timers.Add(timer);
timer.Start();
}
public static void SpawnChaoticItem(RoundManager roundManager)
{
if ((Object)(object)roundManager == (Object)null)
{
Plugin.Logger.LogError((object)"roundManager == null");
return;
}
ChaoticItem chaoticItem = new ChaoticItem(roundManager);
if (chaoticItem.Spawn() == null)
{
Plugin.Logger.LogError((object)"Cannot spawn chaotic item");
}
else
{
chaoticEntities.Add(chaoticItem);
}
}
public static NetworkObjectReference? SwitchToRandomEnemyType(RoundManager roundManager, EnemyAI? enemyTarget, bool inside, NetworkObject networkObject)
{
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
Plugin.Logger.LogError((object)"Trying to switch an enemy type to random enemy");
if ((Object)(object)enemyTarget == (Object)null)
{
Plugin.Logger.LogError((object)"enemyTarget target == null");
return null;
}
if ((Object)(object)enemyTarget.thisNetworkObject == (Object)null)
{
Plugin.Logger.LogError((object)"enemyTarget.thisNetworkObject == null");
return null;
}
if (roundManager?.currentLevel.Enemies == null)
{
Plugin.Logger.LogError((object)"roundManager?.currentLevel.Enemies == null");
return null;
}
if (!((NetworkBehaviour)enemyTarget).IsSpawned)
{
Plugin.Logger.LogError((object)"!enemyTarget.IsSpawned");
return null;
}
var (val, result) = SpawnRandomEnemy(roundManager, inside, ((Component)enemyTarget.thisNetworkObject).transform.position, 0f, new List<string>(6) { "cave", "double", "redlocust", "DressGirl", "Nutcracker", "Spider" });
if ((Object)(object)val == (Object)null)
{
Plugin.Logger.LogError((object)"enemySpawnedType == null");
return null;
}
if (!result.HasValue)
{
Plugin.Logger.LogError((object)"networkObjectReference == null");
return null;
}
enemyTarget.KillEnemyOnOwnerClient(true);
if (((NetworkBehaviour)enemyTarget).IsSpawned)
{
networkObject.Despawn(true);
}
return result;
}
public static void SpawnChaoticEnemy(RoundManager roundManager)
{
ChaoticEnemy chaoticEnemy = new ChaoticEnemy(roundManager, Random.Range(0f, 1f) > 0.2f);
if (chaoticEnemy.Spawn() == null)
{
Plugin.Logger.LogError((object)"Cannot spawn chaotic enemy");
}
else
{
chaoticEntities.Add(chaoticEnemy);
}
}
public static void SpawnMoveEnemy(RoundManager roundManager)
{
MoveEnemy moveEnemy = new MoveEnemy(roundManager, Random.Range(0f, 1f) > 0.5f);
if (moveEnemy.Spawn() == null)
{
Plugin.Logger.LogError((object)"Cannot spawn move enemy");
}
else
{
chaoticEntities.Add(moveEnemy);
}
}
public static void StartSpawning(RoundManager roundManager)
{
RoundManager roundManager2 = roundManager;
Plugin.Logger.LogError((object)"Start spawning enemies");
if ((Object)(object)roundManager2 == (Object)null)
{
Plugin.Logger.LogError((object)"Cannot spawn monster roundManager == null");
return;
}
spawnEnemyTimer.OnTimeout += delegate
{
//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
//IL_0218: Unknown result type (might be due to invalid IL or missing references)
//IL_01e0: 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_0346: Unknown result type (might be due to invalid IL or missing references)
//IL_034e: Unknown result type (might be due to invalid IL or missing references)
//IL_0357: 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_037c: Unknown result type (might be due to invalid IL or missing references)
//IL_0381: Unknown result type (might be due to invalid IL or missing references)
//IL_0389: Unknown result type (might be due to invalid IL or missing references)
//IL_0394: Unknown result type (might be due to invalid IL or missing references)
//IL_0399: Unknown result type (might be due to invalid IL or missing references)
//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
if (modEnemyNumber >= modMaxEnemyNumber)
{
spawnEnemyTimer.Stop();
return;
}
if (Random.Range(0f, 1f) > 0.5f)
{
if (Random.Range(0f, 1f) > 0.5f)
{
if (maxChaoticEnemySpawn != 0)
{
SpawnChaoticEnemy(roundManager2);
maxChaoticEnemySpawn--;
return;
}
}
else if (maxMoveEnemySpawn != 0)
{
SpawnMoveEnemy(roundManager2);
maxMoveEnemySpawn--;
return;
}
}
float num = Random.Range(0, 100);
EnemySpawnType enemySpawnType = ((num <= 30f) ? EnemySpawnType.Outside : EnemySpawnType.Inside);
if (Random.Range(0, 100) < 10)
{
roundManager2.SwitchPower(false);
int num2 = Random.Range(30, 180);
HUDManager.Instance.AddTextToChatOnServer("Warning: There is a power outage for " + TimeSpan.FromSeconds(num2).ToString("mm\\:ss"), -1);
Timer timer = new Timer(num2, oneshot: true);
timer.OnTimeout += delegate
{
roundManager2.SwitchPower(true);
};
timer.Start();
Timers.Add(timer);
}
try
{
switch (enemySpawnType)
{
case EnemySpawnType.Inside:
if (Random.Range(0, 100) <= 20)
{
SpawnRandomEnemyNearRandomPlayer(roundManager2, inside: true);
modEnemyNumber++;
}
else
{
int num4 = roundManager2.allEnemyVents.Length;
if (num4 == 0)
{
Plugin.Logger.LogError((object)"Cannot spawn enemy on the vent because there is no vent available");
}
else
{
EnemyVent val2 = roundManager2.allEnemyVents[Random.Range(0, num4)];
Vector3 randomNavMeshPositionInBoxPredictable = val2.floorNode.position;
float y = val2.floorNode.eulerAngles.y;
if (Random.Range(0f, 1f) <= 0.5f)
{
var (val3, val4) = SpawnRandomEnemy(roundManager2, inside: true, randomNavMeshPositionInBoxPredictable, y);
if ((Object)(object)val3 == (Object)null)
{
break;
}
val2.OpenVentClientRpc();
}
else
{
var (val5, val6) = SpawnRandomEnemy(roundManager2, inside: false, randomNavMeshPositionInBoxPredictable, 0f, new List<string>(3) { "giant", "worm", "double" });
if ((Object)(object)val5 == (Object)null)
{
Plugin.Logger.LogError((object)"Cannot spawn enemy inside");
break;
}
val2.OpenVentClientRpc();
}
modEnemyNumber++;
}
}
break;
case EnemySpawnType.Outside:
if (Random.Range(0, 100) <= 20)
{
SpawnRandomEnemyNearRandomPlayer(roundManager2, inside: false);
modEnemyNumber++;
}
else
{
int count = roundManager2.currentLevel.OutsideEnemies.Count;
if (count == 0)
{
Plugin.Logger.LogError((object)"Cannot spawn enemy outside, no enemy list available");
}
else
{
SpawnableEnemyWithRarity val = roundManager2.currentLevel.OutsideEnemies[Random.Range(0, count)];
GameObject[] array = GameObject.FindGameObjectsWithTag("OutsideAINode");
int num3 = array.Length;
if (num3 == 0)
{
Plugin.Logger.LogError((object)"Cannot spawn enemy outside, no spawn point available");
}
else
{
Vector3 position = array[Random.Range(0, num3)].transform.position;
Vector3 randomNavMeshPositionInBoxPredictable = roundManager2.GetRandomNavMeshPositionInBoxPredictable(position, 10f, default(NavMeshHit), roundManager2.AnomalyRandom, roundManager2.GetLayermaskForEnemySizeLimit(val.enemyType));
randomNavMeshPositionInBoxPredictable = roundManager2.PositionWithDenialPointsChecked(randomNavMeshPositionInBoxPredictable, array, val.enemyType);
roundManager2.SpawnEnemyGameObject(randomNavMeshPositionInBoxPredictable, 0f, -1, val.enemyType);
modEnemyNumber++;
}
}
}
break;
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
};
Timers.Add(spawnEnemyTimer);
}
}
}
namespace ChaosCompany.Scripts.Items
{
public class ChaoticItem : Chaotic
{
private Timer changeType;
public ChaoticItem(RoundManager roundManager)
: base(roundManager)
{
changeType = new Timer(1f, oneshot: false);
changeType.OnTimeout += delegate
{
if (!((Object)(object)base.NetworkObject == (Object)null))
{
GrabbableObject component = ((Component)base.NetworkObject).gameObject.GetComponent<GrabbableObject>();
if (component != null)
{
ChaoticItemAdditionalData component2 = ((Component)base.NetworkObject).gameObject.GetComponent<ChaoticItemAdditionalData>();
if (component2 != null && component2.pickedUp)
{
changeType.Stop();
changeType.Finished = true;
base.ItsJoever = true;
}
component.scrapValue = Random.Range(10, 150);
}
}
};
GameManager.Timers.Add(changeType);
}
public override void Update()
{
if (!((Object)(object)base.NetworkObject == (Object)null) && ((Component)base.NetworkObject).gameObject.GetComponent<GrabbableObject>().isHeld)
{
changeType.Stop();
changeType.Finished = true;
base.ItsJoever = true;
}
}
public override Chaotic? Spawn()
{
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
if (base.RoundManager.currentLevel.spawnableScrap.Count == 0)
{
Plugin.Logger.LogError((object)"No spawnable scrap in the level");
return null;
}
SpawnableItemWithRarity val = base.RoundManager.currentLevel.spawnableScrap[Random.Range(0, base.RoundManager.currentLevel.spawnableScrap.Count)];
RandomScrapSpawn[] array = Object.FindObjectsOfType<RandomScrapSpawn>();
if (array.Length == 0)
{
Plugin.Logger.LogError((object)"randomScrapSpawnArray is empty");
return null;
}
RandomScrapSpawn val2 = array[Random.Range(0, array.Length)];
Vector3 val3 = base.RoundManager.GetRandomNavMeshPositionInBoxPredictable(((Component)val2).transform.position, val2.itemSpawnRange, base.RoundManager.navHit, base.RoundManager.AnomalyRandom, -1) + Vector3.up * val.spawnableItem.verticalOffset;
GameObject val4 = Object.Instantiate<GameObject>(val.spawnableItem.spawnPrefab, val3 + new Vector3(0f, 0.5f, 0f), Quaternion.identity);
GrabbableObject component = val4.GetComponent<GrabbableObject>();
((Component)component).transform.rotation = Quaternion.Euler(component.itemProperties.restingRotation);
component.fallTime = 0f;
component.scrapValue = Random.Range(5, 150);
((NetworkBehaviour)component).NetworkObject.Spawn(false);
base.NetworkObject = ((NetworkBehaviour)component).NetworkObject;
((Component)base.NetworkObject).gameObject.AddComponent<ChaoticItemAdditionalData>();
changeType.Start();
return this;
}
}
}
namespace ChaosCompany.Scripts.Extensions
{
public static class Vector2Extension
{
public static Vector2 RotateDegrees(this Vector2 value, float degrees)
{
float x = MathF.PI / 180f * degrees;
float num = MathF.Cos(x);
float num2 = MathF.Sin(x);
return new Vector2(num * value.X - num2 * value.Y, num2 * value.X + num * value.Y);
}
}
}
namespace ChaosCompany.Scripts.Entities
{
public class ChaoticEnemy : ChaoticEntities
{
private Timer changeType;
private bool isChaoticEnemyAlreadyTryingToChange;
public ChaoticEnemy(RoundManager roundManager, bool inside)
{
RoundManager roundManager2 = roundManager;
base..ctor(roundManager2, inside, new List<string>(7) { "DocileLocust", "cave", "DressGirl", "Nutcracker", "Spider", "double", "Red" });
ChaoticEnemy chaoticEnemy = this;
changeType = new Timer(10f, oneshot: false);
changeType.OnTimeout += delegate
{
//IL_015d: Unknown result type (might be due to invalid IL or missing references)
if (!GameManager.gameOver)
{
if (chaoticEnemy.isChaoticEnemyAlreadyTryingToChange)
{
chaoticEnemy.isChaoticEnemyAlreadyTryingToChange = !chaoticEnemy.isChaoticEnemyAlreadyTryingToChange;
}
else if ((Object)(object)chaoticEnemy.NetworkObject == (Object)null)
{
Plugin.Logger.LogError((object)"NetworkObject == null");
}
else if ((Object)(object)chaoticEnemy.EnemyAI == (Object)null)
{
Plugin.Logger.LogError((object)"enemyAI == null");
}
else
{
NetworkObject? networkObject = chaoticEnemy.NetworkObject;
if ((Object)(object)((networkObject != null) ? ((Component)networkObject).gameObject : null) == (Object)null)
{
Plugin.Logger.LogError((object)"NetworkObject.gameObject == null");
}
else if ((Object)(object)((Component)chaoticEnemy.NetworkObject).gameObject == (Object)null)
{
Plugin.Logger.LogError((object)"A chaotic enemy gameObject == null");
}
else
{
Plugin.Logger.LogError((object)("An " + chaoticEnemy.kindString + " " + chaoticEnemy.EnemyAI.enemyType.enemyName + " chaotic enemy is changing"));
NetworkObjectReference? val = GameManager.SwitchToRandomEnemyType(roundManager2, chaoticEnemy.EnemyAI, chaoticEnemy.Inside, chaoticEnemy.NetworkObject);
if (val.HasValue)
{
chaoticEnemy.NetworkObject = NetworkObjectReference.op_Implicit(val.GetValueOrDefault());
chaoticEnemy.EnemyAI = ((Component)chaoticEnemy.NetworkObject).gameObject.GetComponent<EnemyAI>();
}
else
{
Plugin.Logger.LogError((object)"networkObjectReference == null after switching enemy type");
}
chaoticEnemy.isChaoticEnemyAlreadyTryingToChange = !chaoticEnemy.isChaoticEnemyAlreadyTryingToChange;
}
}
}
};
GameManager.Timers.Add(changeType);
}
public override void Update()
{
if (!((Object)(object)base.EnemyAI == (Object)null))
{
if (base.EnemyAI.isEnemyDead)
{
Plugin.Logger.LogError((object)("An " + kindString + " chaotic enemy died as " + base.EnemyAI.enemyType.enemyName));
changeType.Stop();
changeType.Finished = true;
base.ItsJoever = true;
}
else
{
base.Inside = !base.EnemyAI.isOutside;
}
}
}
public override Chaotic? Spawn()
{
ChaoticEnemy chaoticEnemy = (ChaoticEnemy)base.Spawn();
if (chaoticEnemy == null)
{
return null;
}
if ((Object)(object)base.EnemyAI == (Object)null)
{
Plugin.Logger.LogError((object)"EnemyAI shouldn't be null here");
return null;
}
changeType.Start();
return chaoticEnemy;
}
}
public class ChaoticEntities : Chaotic
{
protected string kindString;
private List<string>? exclusion;
public EnemyAI? EnemyAI { get; protected set; }
public bool Inside { get; protected set; }
public ChaoticEntities(RoundManager roundManager, bool inside, List<string>? exclusion)
: base(roundManager)
{
this.exclusion = exclusion;
Inside = inside;
kindString = (Inside ? "inside" : "outside");
}
public override Chaotic? Spawn()
{
//IL_003a: 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_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
//IL_0137: Unknown result type (might be due to invalid IL or missing references)
//IL_013c: Unknown result type (might be due to invalid IL or missing references)
//IL_0149: Unknown result type (might be due to invalid IL or missing references)
//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
float yRotation;
Vector3 position;
if (Inside)
{
int num = base.RoundManager.allEnemyVents.Length;
if (num == 0)
{
return null;
}
EnemyVent val = base.RoundManager.allEnemyVents[Random.Range(0, num)];
position = val.floorNode.position;
yRotation = val.floorNode.eulerAngles.y;
val.OpenVentClientRpc();
}
else
{
int count = base.RoundManager.currentLevel.OutsideEnemies.Count;
if (count == 0)
{
Plugin.Logger.LogError((object)"Cannot spawn enemy outside, no enemy list available");
return null;
}
SpawnableEnemyWithRarity val2 = base.RoundManager.currentLevel.OutsideEnemies[Random.Range(0, count)];
GameObject[] array = GameObject.FindGameObjectsWithTag("OutsideAINode");
int num2 = array.Length;
if (num2 == 0)
{
Plugin.Logger.LogError((object)"Cannot chaotic outside, no spawn point available");
return null;
}
Vector3 position2 = array[Random.Range(0, num2)].transform.position;
yRotation = 0f;
position = base.RoundManager.GetRandomNavMeshPositionInBoxPredictable(position2, 10f, default(NavMeshHit), base.RoundManager.AnomalyRandom, base.RoundManager.GetLayermaskForEnemySizeLimit(val2.enemyType));
position = base.RoundManager.PositionWithDenialPointsChecked(position, array, val2.enemyType);
}
var (val3, val4) = GameManager.SpawnRandomEnemy(base.RoundManager, Inside, position, yRotation, exclusion);
if ((Object)(object)val3 == (Object)null || !val4.HasValue)
{
return null;
}
if (!val4.HasValue)
{
Plugin.Logger.LogError((object)"Error networkObjectReference == null when trying to spawn chaotic entity");
return null;
}
NetworkObjectReference? val5 = val4;
base.NetworkObject = (val5.HasValue ? NetworkObjectReference.op_Implicit(val5.GetValueOrDefault()) : null);
EnemyAI = ((Component)base.NetworkObject).gameObject.GetComponent<EnemyAI>();
return this;
}
}
public class MoveEnemy : ChaoticEntities
{
private PlayerControllerB? closestPlayer;
private Vector3 lastClosestPlayerPosition;
private NavMeshAgent? navMeshAgent;
private Timer findClosestPlayerDelay;
private Vector3? freezePosition;
private string playerUsername = "";
private string previousPlayerUsername = "";
public MoveEnemy(RoundManager roundManager, bool inside)
: base(roundManager, inside, new List<string>(8) { "forest", "RedLocust", "Doublewing", "FlowerSnake", "DocileLocust", "double", "Centipede", "puffer" })
{
findClosestPlayerDelay = new Timer(1f, oneshot: false);
findClosestPlayerDelay.OnTimeout += delegate
{
if (!((Object)(object)base.NetworkObject == (Object)null) && !((Object)(object)base.EnemyAI == (Object)null))
{
closestPlayer = GameManager.GetClosestPlayerWithLineOfSight(base.RoundManager, base.EnemyAI);
if (!((Object)(object)closestPlayer == (Object)null))
{
previousPlayerUsername = playerUsername;
playerUsername = closestPlayer.playerUsername;
if (playerUsername != previousPlayerUsername)
{
Plugin.Logger.LogError((object)("Changing target to " + closestPlayer.playerUsername));
}
}
}
};
findClosestPlayerDelay.Start();
GameManager.Timers.Add(findClosestPlayerDelay);
}
public override void Update()
{
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
if (GameManager.gameOver || (Object)(object)base.EnemyAI == (Object)null || (Object)(object)base.NetworkObject == (Object)null)
{
return;
}
if (base.EnemyAI.isEnemyDead)
{
Plugin.Logger.LogError((object)("A " + kindString + " move enemy died as " + base.EnemyAI.enemyType.enemyName));
base.ItsJoever = true;
return;
}
EnemyAIAdditionalData component = ((Component)base.NetworkObject).gameObject.GetComponent<EnemyAIAdditionalData>();
if ((Object)(object)closestPlayer == (Object)null)
{
component.paused = false;
return;
}
component.paused = closestPlayer.timeSincePlayerMoving > 0.05f;
if (component.paused)
{
Vector3? val = freezePosition;
if (val.HasValue)
{
Vector3 valueOrDefault = val.GetValueOrDefault();
((Component)base.NetworkObject).transform.position = valueOrDefault;
base.EnemyAI.SyncPositionToClients();
}
}
else
{
freezePosition = ((Component)base.NetworkObject).transform.position;
}
}
public override Chaotic? Spawn()
{
MoveEnemy moveEnemy = (MoveEnemy)base.Spawn();
if ((Object)(object)base.EnemyAI == (Object)null)
{
Plugin.Logger.LogError((object)"EnemyAI shouldn't be null here");
return null;
}
if (moveEnemy == null)
{
Plugin.Logger.LogError((object)"Move enemy == null");
return null;
}
if ((Object)(object)moveEnemy.NetworkObject == (Object)null)
{
Plugin.Logger.LogError((object)"Move enemy NetworkObject == null");
return null;
}
((Component)moveEnemy.NetworkObject).gameObject.AddComponent<EnemyAIAdditionalData>();
navMeshAgent = ((Component)base.EnemyAI).GetComponent<NavMeshAgent>();
return moveEnemy;
}
}
}
namespace ChaosCompany.Scripts.DataStructures
{
public class ChaoticItemAdditionalData : MonoBehaviour
{
public bool pickedUp;
}
public class EnemyAIAdditionalData : MonoBehaviour
{
public bool paused;
}
}
namespace ChaosCompany.Scripts.Components
{
public sealed class Timer
{
public bool Finished { get; set; }
public float WaitTime { get; set; }
public bool Oneshot { get; set; }
public float TimeLeft { get; private set; }
public bool Paused { get; private set; } = true;
public event Action? OnTimeout;
public Timer(float waitTime, bool oneshot)
{
WaitTime = waitTime;
Oneshot = oneshot;
}
public void Start()
{
Paused = false;
}
public void Restart()
{
TimeLeft = 0f;
Start();
}
public void Stop()
{
Paused = true;
}
public void Update()
{
if (Paused)
{
return;
}
TimeLeft += Time.deltaTime;
if (!(TimeLeft >= WaitTime))
{
return;
}
TimeLeft = 0f;
if (this.OnTimeout != null)
{
this.OnTimeout();
if (Oneshot)
{
Finished = true;
}
}
if (Oneshot)
{
Paused = true;
}
}
}
}
namespace ChaosCompany.Scripts.Abstracts
{
public abstract class Chaotic
{
public RoundManager RoundManager { get; private set; }
public NetworkObject? NetworkObject { get; protected set; }
public bool ItsJoever { get; protected set; }
public Chaotic(RoundManager roundManager)
{
RoundManager = roundManager;
}
public virtual void Update()
{
}
public virtual Chaotic? Spawn()
{
return null;
}
}
}