Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Lethal Missions v1.1.8
LethalMissions.dll
Decompiled 2 years agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LethalCompanyInputUtils.Api; using LethalMissions.Input; using LethalMissions.Localization; using LethalMissions.Networking; using LethalMissions.Patches; using LethalMissions.Scripts; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using TMPro; using TerminalApi; using TerminalApi.Classes; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("LethalMissions")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("A mod that adds missions to the game.")] [assembly: AssemblyFileVersion("1.1.8.0")] [assembly: AssemblyInformationalVersion("1.1.8")] [assembly: AssemblyProduct("LethalMissions")] [assembly: AssemblyTitle("LethalMissions")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/valentin-marquez/LethalMissions")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.8.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] internal class <Module> { static <Module>() { } } 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; } } } public class ItemExtra : MonoBehaviour { public string uniqueID; private void Awake() { uniqueID = Guid.NewGuid().ToString(); } } public class MissionItem : MonoBehaviour { [NonSerialized] public MissionType Type; public string Name; public string Objective; public MissionStatus Status; private GameObject LeftContainer; private GameObject MidleContainer; private GameObject RightContainer; [NonSerialized] private TextMeshProUGUI MissionInfo; [NonSerialized] private Image CheckMark; private Image Icon; private void Awake() { LeftContainer = ((Component)((Component)this).transform.GetChild(0)).gameObject; MidleContainer = ((Component)((Component)this).transform.GetChild(1)).gameObject; RightContainer = ((Component)((Component)this).transform.GetChild(2)).gameObject; MissionInfo = MidleContainer.GetComponentInChildren<TextMeshProUGUI>(); CheckMark = ((Component)RightContainer.transform.GetChild(0)).GetComponent<Image>(); Icon = ((Component)LeftContainer.transform.GetChild(0)).GetComponent<Image>(); } public void SetMissionInfo(MissionType mType, string missionName, string missionDescription, MissionStatus missionStatus = MissionStatus.Incomplete, Sprite sprite = null) { Type = mType; Name = missionName; Objective = missionDescription; ((TMP_Text)MissionInfo).text = missionName + "\n" + missionDescription; if (missionStatus == MissionStatus.Complete) { SetMissionCompleted(); } else { SetMissionUncompleted(); } if ((Object)(object)sprite != (Object)null) { Icon.sprite = sprite; } } public void SetMissionStatus(MissionStatus missionStatus) { if (missionStatus == MissionStatus.Complete) { SetMissionCompleted(); } else { SetMissionUncompleted(); } } public void SetMissionCompleted() { Status = MissionStatus.Complete; ((Behaviour)CheckMark).enabled = true; } public void SetMissionUncompleted() { Status = MissionStatus.Incomplete; ((Behaviour)CheckMark).enabled = false; } } namespace LethalMissions { public static class Assets { public static AssetBundle MainAssetBundle; public static void PopulateAssets(string streamName) { if ((Object)(object)MainAssetBundle == (Object)null) { using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(streamName)) { MainAssetBundle = AssetBundle.LoadFromStream(stream); } } } } [BepInPlugin("com.nozz.lethalmissions", "LethalMissions", "1.1.8")] [BepInDependency("atomic.terminalapi", "1.5.0")] [BepInDependency("com.rune580.LethalCompanyInputUtils", "0.4.4")] public class Plugin : BaseUnityPlugin { public const string modGUID = "com.nozz.lethalmissions"; public const string modName = "LethalMissions"; public const string modVersion = "1.1.8"; public static GameObject MissionsMenuPrefab; public static GameObject missionItemPrefab; private static GameStateEnum _currentstate; public static ManualLogSource logger; public static ConfigFile config; public static MissionManager MissionManager { get; private set; } public static MenuManager MissionMenuManager { get; private set; } public static GameStateEnum CurrentState { get { return _currentstate; } set { _currentstate = value; GameStateChanged(value); } } private void Awake() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown logger = ((BaseUnityPlugin)this).Logger; config = ((BaseUnityPlugin)this).Config; Config.Load(); LogInfo("Loading missions for language: " + Config.LanguageCode.Value); MissionManager = new MissionManager(); MissionMenuManager = new MenuManager(); Keybinds.Initialize(); LogInfo("Installing patches..."); Harmony val = new Harmony("LethalMissions"); val.PatchAll(typeof(MissionsEvents)); val.PatchAll(typeof(StartOfRoundPatch)); val.PatchAll(typeof(NetworkObjectManager)); val.PatchAll(typeof(Keybinds)); val.PatchAll(typeof(MenuManager)); val.PatchAll(typeof(GrabbableObjectPatch)); LogInfo("Loading assets..."); Assets.PopulateAssets("LethalMissions.asset"); LoadMissionsMenuAsset(); LoadMissionItemAsset(); LogInfo("Registering commands..."); DetermineCommandLibrary(); LogInfo("Patching with netcode..."); NetcodeWeaver(); LogInfo("Plugin LethalMissions is loaded!"); } public static void LoadMissionsMenuAsset() { try { MissionsMenuPrefab = Assets.MainAssetBundle.LoadAsset<GameObject>("LethalMissionsMenu"); LogInfo("MissionsMenu asset loaded"); } catch { LogError("Failed to load MissionsMenu asset"); } } public static void LoadMissionItemAsset() { try { missionItemPrefab = Assets.MainAssetBundle.LoadAsset<GameObject>("MissionItem"); LogInfo("MissionItem asset loaded"); } catch { LogError("Failed to load MissionItem asset"); } } public void DetermineCommandLibrary() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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_00d1: Expected O, but got Unknown string value = Config.LanguageCode.Value; string text = ((value == "es") ? "misiones" : "missions"); if (value != "en" && value != "es") { LogWarning("Language not supported, using english"); text = "missions"; } if (IsModLoaded("atomic.terminalapi")) { LogWarning("Using atomic.terminalapi for commands"); TerminalApi.AddCommand(text, new CommandInfo { DisplayTextSupplier = () => MissionManager.ShowMissionOverview(), Description = ((value == "es") ? "Muestra todas las Misiones Letales" : "Show all Lethal Missions"), Category = "Other" }, (string)null, true); } else { LogError("No command library found, please install atomic.terminalapi"); } } public static bool IsModLoaded(string guid) { return Chainloader.PluginInfos.ContainsKey(guid); } private void NetcodeWeaver() { Type[] types = Assembly.GetExecutingAssembly().GetTypes(); Type[] array = types; foreach (Type type in array) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); MethodInfo[] array2 = methods; foreach (MethodInfo methodInfo in array2) { object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false); if (customAttributes.Length != 0) { methodInfo.Invoke(null, null); } } } } public static void LogInfo(string message) { logger.LogInfo((object)message); } public static void LogWarning(string message) { logger.LogWarning((object)message); } public static void LogError(string message) { logger.LogError((object)message); } private static void GameStateChanged(GameStateEnum gameState) { switch (gameState) { case GameStateEnum.InOrbit: break; case GameStateEnum.TakingOff: ResetAll(); break; case GameStateEnum.OnMoon: if (NetworkManager.Singleton.IsHost || (NetworkManager.Singleton.IsServer && StartOfRound.Instance.currentLevelID != 3)) { LogInfo("Host or server - Generating missions"); MissionManager.GenerateMissions(Config.NumberOfMissions.Value); } Utils.NotifyMissions(); break; } } private static void ResetAll() { MissionManager.RemoveActiveMissions(); MissionsEvents.ResetAttr(); MissionManager.ResetFirstSync(); } } public enum NotificationOption { None, SoundOnly, SoundAndBanner, BannerOnly } public class Config { public static ConfigEntry<string> LanguageCode { get; set; } public static ConfigEntry<int> NumberOfMissions { get; set; } public static ConfigEntry<NotificationOption> MissionsNotification { get; set; } public static ConfigEntry<bool> RandomMode { get; set; } public static ConfigEntry<int> RecoverBodyReward { get; set; } public static ConfigEntry<int> LightningRodReward { get; set; } public static ConfigEntry<int> WitnessDeathReward { get; set; } public static ConfigEntry<int> ObtainHiveReward { get; set; } public static ConfigEntry<int> SurviveCrewmatesReward { get; set; } public static ConfigEntry<int> OutOfTimeReward { get; set; } public static ConfigEntry<int> KillMonsterReward { get; set; } public static ConfigEntry<int> ObtainGeneratorReward { get; set; } public static ConfigEntry<int> FindScrapReward { get; set; } public static ConfigEntry<int> RepairValveReward { get; set; } public static void Load() { LanguageCode = Plugin.config.Bind<string>("General", "LanguageCode", "en", "The language code for translations (e.g., en for English, es for Spanish)."); NumberOfMissions = Plugin.config.Bind<int>("General", "NumberOfMissions", 3, "The maximum number of missions to start per map. Recommended is 3-4. More than this may cause errors. Total missions are 10 but 3 are generated based on map conditions."); MissionsNotification = Plugin.config.Bind<NotificationOption>("General", "NotificationOption", NotificationOption.SoundAndBanner, "The option for new mission notifications. Options: None, SoundOnly, SoundAndBanner, BannerOnly."); RandomMode = Plugin.config.Bind<bool>("General", "RandomMode", false, "Generate random number of missions."); RecoverBodyReward = Plugin.config.Bind<int>("Rewards", "RecoverBody", 20, "The reward for completing a Recover Body mission."); LightningRodReward = Plugin.config.Bind<int>("Rewards", "LightningRod", 300, "The reward for completing a Lightning Rod mission."); WitnessDeathReward = Plugin.config.Bind<int>("Rewards", "WitnessDeath", 40, "The reward for completing a Witness Death mission."); ObtainHiveReward = Plugin.config.Bind<int>("Rewards", "ObtainHive", 80, "The reward for completing an Obtain Hive mission."); SurviveCrewmatesReward = Plugin.config.Bind<int>("Rewards", "SurviveCrewmates", 100, "The reward for completing a Survive Crewmates mission."); OutOfTimeReward = Plugin.config.Bind<int>("Rewards", "OutOfTime", 30, "The reward for completing an Out of Time mission."); KillMonsterReward = Plugin.config.Bind<int>("Rewards", "KillMonster", 50, "The reward for completing a Kill Monster mission."); ObtainGeneratorReward = Plugin.config.Bind<int>("Rewards", "ObtainGenerator", 50, "The reward for completing an Obtain Generator mission."); FindScrapReward = Plugin.config.Bind<int>("Rewards", "FindScrap", 50, "The reward for completing a Find Scrap mission."); RepairValveReward = Plugin.config.Bind<int>("Rewards", "RepairValve", 80, "The reward for completing a Repair Valve mission."); } } [HarmonyPatch] public class MenuManager : Behaviour { public static GameObject MenugameObject; public static GameObject MenuPanelMissions; public static GameObject ItemListMission; public static ScrollRect scrollRect; public static Animator MissionsMenuAnimator; public static bool isOpen; public static QuickMenuManager QuickMenuManager => StartOfRound.Instance?.localPlayerController?.quickMenuManager; public static PlayerControllerB LocalPlayerController => StartOfRound.Instance?.localPlayerController; [HarmonyPostfix] [HarmonyPatch(typeof(HUDManager), "Start")] public static void Initialize(HUDManager __instance) { if (!((Object)(object)Plugin.MissionsMenuPrefab == (Object)null)) { MenugameObject = Object.Instantiate<GameObject>(Plugin.MissionsMenuPrefab); MissionsMenuAnimator = MenugameObject.GetComponent<Animator>(); if ((Object)(object)MissionsMenuAnimator != (Object)null) { RuntimeAnimatorController runtimeAnimatorController = MissionsMenuAnimator.runtimeAnimatorController; } MenugameObject.transform.SetAsLastSibling(); MenuPanelMissions = ((Component)((Component)MenugameObject.transform.GetChild(0)).GetComponentInChildren<ScrollRect>().content).gameObject; scrollRect = ((Component)MenugameObject.transform.GetChild(0)).GetComponentInChildren<ScrollRect>(); } } public static void ToggleMissionsMenu() { if (!isOpen) { OpenMissionsMenu(); } else { CloseMissionsMenu(); } } public static void CloseMissionsMenu() { MissionsMenuAnimator.SetTrigger("close"); isOpen = false; } public static void OpenMissionsMenu() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown MissionsMenuAnimator.SetTrigger("open"); isOpen = true; List<Mission> activeMissions = Plugin.MissionManager.GetActiveMissions(); foreach (Transform item in MenuPanelMissions.transform) { Transform val = item; Object.Destroy((Object)(object)((Component)val).gameObject); } foreach (Mission item2 in activeMissions) { CreateAndConfigureMissionItem(item2); } } private static void CreateAndConfigureMissionItem(Mission mission) { GameObject val = Object.Instantiate<GameObject>(Plugin.missionItemPrefab, MenuPanelMissions.transform); string missionName = mission.Name ?? ""; string missionDescription = mission.Objective ?? ""; Sprite sprite = null; switch (mission.Type) { case MissionType.OutOfTime: missionName = string.Format(mission.Name, Utils.NumberToHour(mission.LeaveTime.Value, isPM: true) + " PM") ?? ""; missionDescription = string.Format(mission.Objective, Utils.NumberToHour(mission.LeaveTime.Value, isPM: true) + " PM") ?? ""; break; case MissionType.SurviveCrewmates: missionDescription = string.Format(mission.Objective, mission.SurviveCrewmates) ?? ""; break; case MissionType.FindScrap: missionDescription = string.Format(mission.Objective, mission.Item.ItemName) ?? ""; break; case MissionType.RepairValve: missionDescription = string.Format(mission.Objective, mission.ValveCount) ?? ""; break; } val.AddComponent<MissionItem>().SetMissionInfo(mission.Type, missionName, missionDescription, mission.Status, sprite); } public static bool CanOpenMenu() { if (QuickMenuManager.isMenuOpen && !isOpen) { return false; } if (LocalPlayerController.isPlayerDead || LocalPlayerController.inTerminalMenu || LocalPlayerController.isTypingChat || LocalPlayerController.isPlayerDead || LocalPlayerController.inSpecialInteractAnimation || LocalPlayerController.isGrabbingObjectAnimation || LocalPlayerController.inShockingMinigame || LocalPlayerController.isClimbingLadder || LocalPlayerController.isSinking || (Object)(object)LocalPlayerController.inAnimationWithEnemy != (Object)null || StartOfRound.Instance.inShipPhase || StartOfRound.Instance.shipIsLeaving || !RoundManager.Instance.dungeonCompletedGenerating) { return false; } return true; } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "Update")] public static void OnUpdate() { if (StartOfRound.Instance.shipIsLeaving && isOpen) { CloseMissionsMenu(); } } [HarmonyPrefix] [HarmonyPatch(typeof(PlayerControllerB), "ScrollMouse_performed")] public static bool OnScrollMouse(CallbackContext context, PlayerControllerB __instance) { if (!isOpen || (Object)(object)__instance != (Object)(object)LocalPlayerController || !((CallbackContext)(ref context)).performed) { return true; } float num = ((CallbackContext)(ref context)).ReadValue<float>(); ScrollRect obj = scrollRect; obj.verticalNormalizedPosition += num * 0.3f; return false; } [HarmonyPrefix] [HarmonyPatch(typeof(PlayerControllerB), "OpenMenu_performed")] public static void OnQuickMenu(CallbackContext context) { if (isOpen) { CloseMissionsMenu(); } } } public static class PluginInfo { public const string PLUGIN_GUID = "LethalMissions"; public const string PLUGIN_NAME = "LethalMissions"; public const string PLUGIN_VERSION = "1.1.8"; } } namespace LethalMissions.Input { internal class IngameKeybinds : LcInputActions { internal static IngameKeybinds Instance = new IngameKeybinds(); [InputAction("<keyboard>/j", Name = "[LethalMissions]\nOpen Missions Menu")] public InputAction OpenMissionsMenuHotkey { get; set; } internal static InputActionAsset GetAsset() { return ((LcInputActions)Instance).Asset; } } internal class InputUtilsCompat { internal static InputActionAsset Asset => IngameKeybinds.GetAsset(); internal static bool Enabled => Plugin.IsModLoaded("com.rune580.LethalCompanyInputUtils"); public static InputAction OpenMissionsMenuHotkey => IngameKeybinds.Instance.OpenMissionsMenuHotkey; } } namespace LethalMissions.Patches { public class GrabbableObjectPatch { [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "StartGame")] public static void OnStartGameItems() { if (StartOfRound.Instance.currentLevel.levelID == 3) { return; } GameObject val = GameObject.Find("/Environment/HangarShip"); GrabbableObject[] componentsInChildren = val.GetComponentsInChildren<GrabbableObject>(); GrabbableObject val2 = ((IEnumerable<GrabbableObject>)componentsInChildren).FirstOrDefault((Func<GrabbableObject, bool>)((GrabbableObject obj) => ((Object)obj).name == "ClipboardManual")); GrabbableObject val3 = ((IEnumerable<GrabbableObject>)componentsInChildren).FirstOrDefault((Func<GrabbableObject, bool>)((GrabbableObject obj) => ((Object)obj).name == "StickyNoteItem")); GrabbableObject[] array = componentsInChildren; foreach (GrabbableObject val4 in array) { if ((Object)(object)val4 != (Object)(object)val2 && (Object)(object)val4 != (Object)(object)val3) { ((Component)val4).gameObject.AddComponent<ItemExtra>(); } } } } [HarmonyPatch] public static class Keybinds { public static InputActionAsset Asset; public static InputActionMap ActionMap; private static InputAction OpenMissionsMenuHotkey; public static InputAction RawScrollAction; public static PlayerControllerB LocalPlayerController => StartOfRound.Instance?.localPlayerController; public static void Initialize() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_0051: Expected O, but got Unknown if (InputUtilsCompat.Enabled) { Asset = InputUtilsCompat.Asset; ActionMap = Asset.actionMaps[0]; OpenMissionsMenuHotkey = InputUtilsCompat.OpenMissionsMenuHotkey; RawScrollAction = new InputAction("LethalMissions.ScrollMenu", (InputActionType)0, "<Mouse>/scroll", (string)null, (string)null, (string)null); } else { Asset = new InputActionAsset(); ActionMap = InputActionSetupExtensions.AddActionMap(Asset, "LethalMissions"); InputActionSetupExtensions.AddActionMap(Asset, ActionMap); OpenMissionsMenuHotkey = InputActionSetupExtensions.AddAction(ActionMap, "LethalMissions.OpenMissionsMenuHotkey", (InputActionType)0, "<keyboard>/j", "Press", (string)null, (string)null, (string)null); RawScrollAction = new InputAction("LethalMissions.ScrollMenu", (InputActionType)0, "<Mouse>/scroll", (string)null, (string)null, (string)null); } } [HarmonyPatch(typeof(StartOfRound), "OnEnable")] [HarmonyPostfix] public static void OnEnable() { Asset.Enable(); OpenMissionsMenuHotkey.performed += OnPressMissionMenuHotkey; OpenMissionsMenuHotkey.canceled += OnPressMissionMenuHotkey; } [HarmonyPatch(typeof(StartOfRound), "OnDisable")] [HarmonyPostfix] public static void OnDisable() { Asset.Disable(); OpenMissionsMenuHotkey.performed -= OnPressMissionMenuHotkey; OpenMissionsMenuHotkey.canceled -= OnPressMissionMenuHotkey; } private static void OnPressMissionMenuHotkey(CallbackContext context) { if ((Object)(object)LocalPlayerController == (Object)null) { Plugin.LogError("LocalPlayerController is null"); } else if (((CallbackContext)(ref context)).performed && MenuManager.CanOpenMenu()) { MenuManager.ToggleMissionsMenu(); } } } public class MissionsEvents { public static int hoursPassed; public static int lastHour; [HarmonyPostfix] [HarmonyPatch(typeof(HUDManager), "SetClock")] private static void OnSetClock(float timeNormalized, float numberOfHours) { if (Plugin.MissionManager.IsMissionActive(MissionType.OutOfTime)) { int num = (int)(timeNormalized * (60f * numberOfHours)) + 360; int num2 = num / 60; if (num2 != lastHour) { lastHour = num2; hoursPassed++; } if (hoursPassed < Plugin.MissionManager.GetMissionLeaveTime(MissionType.OutOfTime)) { Plugin.MissionManager.CompleteMission(MissionType.OutOfTime); } else { Plugin.MissionManager.IncompleteMission(MissionType.OutOfTime); } } } public static void ResetAttr() { hoursPassed = 0; lastHour = 0; } [HarmonyPostfix] [HarmonyPatch(typeof(EnemyAI), "KillEnemy")] public static void OnEnemyKilled(EnemyAI __instance) { if (Plugin.MissionManager.IsMissionActive(MissionType.KillMonster) && __instance.isEnemyDead) { Plugin.MissionManager.CompleteMission(MissionType.KillMonster); } } [HarmonyPostfix] [HarmonyPatch(typeof(DeadBodyInfo), "DetectIfSeenByLocalPlayer")] private static void OnDetect() { if (Plugin.MissionManager.IsMissionActive(MissionType.WitnessDeath)) { Plugin.MissionManager.CompleteMission(MissionType.WitnessDeath); } } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] private static void OnKillPlayer(CauseOfDeath causeOfDeath = 0) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between I4 and Unknown if (Plugin.MissionManager.IsMissionActive(MissionType.LightningRod) && 11 == (int)causeOfDeath) { Plugin.MissionManager.CompleteMission(MissionType.LightningRod); } } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerControllerB), "SetItemInElevator")] private static void OnSetItemInElevator(bool droppedInShipRoom, bool droppedInElevator, GrabbableObject gObject) { if (!droppedInShipRoom) { return; } Dictionary<int, MissionType> dictionary = new Dictionary<int, MissionType> { { 1531, MissionType.ObtainHive }, { 3, MissionType.ObtainGenerator } }; if (dictionary.TryGetValue(gObject.itemProperties.itemId, out var value)) { if ((Object)(object)((Component)gObject).GetComponent<ItemExtra>() == (Object)null) { Plugin.MissionManager.CompleteMission(value); } } else if (gObject is RagdollGrabbableObject && Plugin.MissionManager.IsMissionActive(MissionType.RecoverBody) && (Object)(object)((Component)gObject).GetComponent<ItemExtra>() == (Object)null) { Plugin.MissionManager.CompleteMission(MissionType.RecoverBody); } } [HarmonyPostfix] [HarmonyPatch(typeof(GrabbableObject), "GrabItem")] private static void OnGrabItem(GrabbableObject __instance) { Mission findScrapItem = Plugin.MissionManager.GetFindScrapItem(); if (findScrapItem != null && __instance.itemProperties.itemId == findScrapItem.Item.ItemId) { Plugin.MissionManager.CompleteMission(MissionType.FindScrap); } } [HarmonyPostfix] [HarmonyPatch(typeof(SteamValveHazard), "FixValve")] private static void OnFixValve(SteamValveHazard __instance) { if (Plugin.MissionManager.IsMissionActive(MissionType.RepairValve)) { Plugin.MissionManager.ProgressValveRepair(); } } [HarmonyPrefix] [HarmonyPatch(typeof(StartOfRound), "ShipLeave")] private static void OnEndGame() { if (Plugin.MissionManager.IsMissionActive(MissionType.SurviveCrewmates)) { PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; int num = allPlayerScripts.Count((PlayerControllerB player) => !player.isPlayerDead && (player.isInHangarShipRoom || player.isInElevator)); int surviveCrewmates = Plugin.MissionManager.GetSurviveCrewmates(); if (num >= surviveCrewmates) { Plugin.MissionManager.CompleteMission(MissionType.SurviveCrewmates); } } } } public class NetworkObjectManager { private static GameObject networkPrefab; private static GameObject networkHandlerHost; [HarmonyPrefix] [HarmonyPatch(typeof(GameNetworkManager), "Start")] public static void OnStart() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown if (!((Object)(object)networkPrefab != (Object)null)) { networkPrefab = (GameObject)Assets.MainAssetBundle.LoadAsset("LethalMissionsNetworkHandler"); networkPrefab.AddComponent<NetworkHandler>(); NetworkManager.Singleton.AddNetworkPrefab(networkPrefab); } } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "Awake")] private static void SpawnNetworkHandler() { if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) { networkHandlerHost = Object.Instantiate<GameObject>(networkPrefab); networkHandlerHost.GetComponent<NetworkObject>().Spawn(true); } } [HarmonyPostfix] [HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")] private static void DestroyNetworkHandler() { try { if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) { Plugin.LogInfo("LethalMissions: Destroying NetworkHandler on Host"); Object.Destroy((Object)(object)networkHandlerHost); networkHandlerHost = null; } } catch { Plugin.LogError("LethalMissions: Failed to destroy NetworkHandler on Host"); } } [HarmonyPrefix] [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] private static void OnConnectClientToPlayerObject() { if (!NetworkManager.Singleton.IsHost || !NetworkManager.Singleton.IsServer) { Plugin.MissionManager.RequestMissions(); } } } [HarmonyPatch(typeof(StartOfRound))] public class StartOfRoundPatch : NetworkBehaviour { [HarmonyPrefix] [HarmonyPatch("Update")] private static void OnUpdate() { if ((Object)(object)StartOfRound.Instance == (Object)null) { return; } Dictionary<GameStateEnum, Func<bool>> dictionary = new Dictionary<GameStateEnum, Func<bool>> { { GameStateEnum.OnMoon, () => ((Object)((AnimatorClipInfo)(ref StartOfRound.Instance.shipAnimator.GetCurrentAnimatorClipInfo(0)[0])).clip).name == "HangarShipLandB" }, { GameStateEnum.InOrbit, () => StartOfRound.Instance.inShipPhase }, { GameStateEnum.TakingOff, () => StartOfRound.Instance.shipIsLeaving } }; foreach (KeyValuePair<GameStateEnum, Func<bool>> item in dictionary) { if (item.Value() && Plugin.CurrentState != item.Key) { ChangeGameState(item.Key); } } } private static void ChangeGameState(GameStateEnum state) { Plugin.CurrentState = state; } [HarmonyPostfix] [HarmonyPatch("ShipLeave")] private static void OnEndGame() { if (!StartOfRound.Instance.allPlayersDead && StartOfRound.Instance.currentLevel.levelID != 3) { CalculateRewards(); } } public static void CalculateRewards() { Terminal val = Object.FindObjectOfType<Terminal>(); int groupCredits = val.groupCredits; int creditsEarned = Plugin.MissionManager.GetCreditsEarned(); int groupCredits2 = groupCredits + creditsEarned; val.groupCredits = groupCredits2; DisplayMissionCompletion(creditsEarned); } public static void DisplayMissionCompletion(int creditsEarned) { //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Expected O, but got Unknown List<Mission> completedMissions = Plugin.MissionManager.GetCompletedMissions(); string text = ((completedMissions.Count == 0) ? MissionLocalization.GetMissionString("NoCompletedMissionsMessage") : MissionLocalization.GetMissionString("CompletedMissionsCountMessage", completedMissions.Count)); GameObject val = GameObject.Find("Systems/UI/Canvas/IngamePlayerHUD/SpecialHUDGraphics/RewardsScreen/Container/Container2/Header"); ((TMP_Text)val.GetComponent<TextMeshProUGUI>()).fontSize = 26f; ((TMP_Text)val.GetComponent<TextMeshProUGUI>()).text = "Lethal Missions"; ((TMP_Text)HUDManager.Instance.moneyRewardsListText).fontSize = ((TMP_Text)HUDManager.Instance.moneyRewardsListText).fontSize / 2f; ((TMP_Text)HUDManager.Instance.moneyRewardsListText).text = text; ((TMP_Text)HUDManager.Instance.moneyRewardsTotalText).text = $"TOTAL: ${creditsEarned}"; HUDManager.Instance.rewardsScrollbar.value = 1f; if (Config.NumberOfMissions.Value > 8) { Type typeFromHandle = typeof(HUDManager); FieldInfo field = typeFromHandle.GetField("scrollRewardTextCoroutine", BindingFlags.Instance | BindingFlags.NonPublic); HUDManager instance = HUDManager.Instance; Coroutine val2 = (Coroutine)field.GetValue(instance); if (val2 != null) { ((MonoBehaviour)instance).StopCoroutine(val2); } field.SetValue(instance, ((MonoBehaviour)instance).StartCoroutine(ScrollRewardsListText())); } ((MonoBehaviour)HUDManager.Instance).StartCoroutine(ShowRewardsAndRestoreHeader(val)); } private static IEnumerator ShowRewardsAndRestoreHeader(GameObject header) { HUDManager.Instance.moneyRewardsAnimator.SetTrigger("showRewards"); yield return (object)new WaitForSeconds(10f); ((TMP_Text)HUDManager.Instance.moneyRewardsListText).fontSize = ((TMP_Text)HUDManager.Instance.moneyRewardsListText).fontSize * 2f; ((TMP_Text)header.GetComponent<TextMeshProUGUI>()).fontSize = 36f; ((TMP_Text)header.GetComponent<TextMeshProUGUI>()).text = "PAYCHECK!"; } private static IEnumerator ScrollRewardsListText() { yield return (object)new WaitForSeconds(1.5f); float num = 3f; while (num >= 0f) { num -= Time.deltaTime; Scrollbar rewardsScrollbar = HUDManager.Instance.rewardsScrollbar; rewardsScrollbar.value -= Time.deltaTime / num; } } protected override void __initializeVariables() { ((NetworkBehaviour)this).__initializeVariables(); } protected internal override string __getTypeName() { return "StartOfRoundPatch"; } } } namespace LethalMissions.Networking { public class NetworkHandler : NetworkBehaviour { private string currentSerializedMissions; public static NetworkHandler Instance { get; private set; } public override void OnNetworkSpawn() { ((NetworkBehaviour)this).OnNetworkSpawn(); } private void Awake() { Instance = this; } [ServerRpc(RequireOwnership = false)] public void SyncMissionsServerRpc(string serializedMissions) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Invalid comparison between Unknown and I4 //IL_005f: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { ServerRpcParams val = default(ServerRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(4080571439u, val, (RpcDelivery)0); bool flag = serializedMissions != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); if (flag) { ((FastBufferWriter)(ref val2)).WriteValueSafe(serializedMissions, false); } ((NetworkBehaviour)this).__endSendServerRpc(ref val2, 4080571439u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost)) { currentSerializedMissions = serializedMissions; SyncMissionsClientRpc(serializedMissions); } } [ClientRpc] public void SyncMissionsClientRpc(string serializedMissions) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Invalid comparison between Unknown and I4 //IL_005f: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1031828279u, val, (RpcDelivery)0); bool flag = serializedMissions != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); if (flag) { ((FastBufferWriter)(ref val2)).WriteValueSafe(serializedMissions, false); } ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1031828279u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost)) { currentSerializedMissions = serializedMissions; Plugin.MissionManager.SyncMissions(serializedMissions); } } [ServerRpc(RequireOwnership = false)] public void RequestMissionsServerRpc(ulong clientId) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Invalid comparison between Unknown and I4 //IL_005f: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { ServerRpcParams val = default(ServerRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(293238159u, val, (RpcDelivery)0); BytePacker.WriteValueBitPacked(val2, clientId); ((NetworkBehaviour)this).__endSendServerRpc(ref val2, 293238159u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost)) { if (string.IsNullOrEmpty(currentSerializedMissions)) { Debug.LogError((object)"currentSerializedMissions is null or empty"); } else { SendMissionsClientRpc(currentSerializedMissions, clientId); } } } [ClientRpc] public void SendMissionsClientRpc(string serializedMissions, ulong targetClientId) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Invalid comparison between Unknown and I4 //IL_005f: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_00c7: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3600468003u, val, (RpcDelivery)0); bool flag = serializedMissions != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); if (flag) { ((FastBufferWriter)(ref val2)).WriteValueSafe(serializedMissions, false); } BytePacker.WriteValueBitPacked(val2, targetClientId); ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3600468003u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && NetworkManager.Singleton.LocalClientId == targetClientId) { Plugin.MissionManager.SyncMissions(serializedMissions); } } protected override void __initializeVariables() { ((NetworkBehaviour)this).__initializeVariables(); } [RuntimeInitializeOnLoadMethod] internal static void InitializeRPCS_NetworkHandler() { //IL_0011: 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_0036: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown NetworkManager.__rpc_func_table.Add(4080571439u, new RpcReceiveHandler(__rpc_handler_4080571439)); NetworkManager.__rpc_func_table.Add(1031828279u, new RpcReceiveHandler(__rpc_handler_1031828279)); NetworkManager.__rpc_func_table.Add(293238159u, new RpcReceiveHandler(__rpc_handler_293238159)); NetworkManager.__rpc_func_table.Add(3600468003u, new RpcReceiveHandler(__rpc_handler_3600468003)); } private static void __rpc_handler_4080571439(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_002f: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { bool flag = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives)); string serializedMissions = null; if (flag) { ((FastBufferReader)(ref reader)).ReadValueSafe(ref serializedMissions, false); } target.__rpc_exec_stage = (__RpcExecStage)1; ((NetworkHandler)(object)target).SyncMissionsServerRpc(serializedMissions); target.__rpc_exec_stage = (__RpcExecStage)0; } } private static void __rpc_handler_1031828279(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_002f: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { bool flag = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives)); string serializedMissions = null; if (flag) { ((FastBufferReader)(ref reader)).ReadValueSafe(ref serializedMissions, false); } target.__rpc_exec_stage = (__RpcExecStage)2; ((NetworkHandler)(object)target).SyncMissionsClientRpc(serializedMissions); target.__rpc_exec_stage = (__RpcExecStage)0; } } private static void __rpc_handler_293238159(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_0023: 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_0050: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { ulong clientId = default(ulong); ByteUnpacker.ReadValueBitPacked(reader, ref clientId); target.__rpc_exec_stage = (__RpcExecStage)1; ((NetworkHandler)(object)target).RequestMissionsServerRpc(clientId); target.__rpc_exec_stage = (__RpcExecStage)0; } } private static void __rpc_handler_3600468003(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_002f: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { bool flag = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives)); string serializedMissions = null; if (flag) { ((FastBufferReader)(ref reader)).ReadValueSafe(ref serializedMissions, false); } ulong targetClientId = default(ulong); ByteUnpacker.ReadValueBitPacked(reader, ref targetClientId); target.__rpc_exec_stage = (__RpcExecStage)2; ((NetworkHandler)(object)target).SendMissionsClientRpc(serializedMissions, targetClientId); target.__rpc_exec_stage = (__RpcExecStage)0; } } protected internal override string __getTypeName() { return "NetworkHandler"; } } } namespace LethalMissions.Scripts { public static class Utils { private static class ThreadSafeRandom { [ThreadStatic] private static Random Local; public static Random ThisThreadsRandom => Local ?? (Local = new Random(Environment.TickCount * 31 + Thread.CurrentThread.ManagedThreadId)); } public static Dictionary<string, (string Name, bool IsOutside, int Id)> EnemyOutsideStatus = new Dictionary<string, (string, bool, int)> { { "BaboonHawk", ("BaboonHawk", true, 1) }, { "Blob", ("Blob", false, 2) }, { "Centipede", ("Centipede", false, 3) }, { "Crawler", ("Crawler", false, 4) }, { "DocileLocustBees", ("DocileLocustBees", true, 5) }, { "Doublewing", ("Doublewing", true, 6) }, { "RedLocustBees", ("RedLocustBees", true, 7) }, { "DressGirl", ("DressGirl", false, 8) }, { "Flowerman", ("Flowerman", false, 9) }, { "ForestGiant", ("ForestGiant", true, 10) }, { "HoarderBug", ("HoarderBug", false, 11) }, { "Jester", ("Jester", false, 12) }, { "LassoMan", ("LassoMan", false, 13) }, { "MaskedPlayerEnemy", ("MaskedPlayerEnemy", true, 14) }, { "MouthDog", ("MouthDog", true, 15) }, { "Nutcracker", ("Nutcracker", false, 16) }, { "Puffer", ("Puffer", false, 17) }, { "RedPillEnemyType", ("RedPillEnemyType", false, 18) }, { "SandSpider", ("SandSpider", false, 19) }, { "SandWorm", ("SandWorm", true, 20) }, { "SpringMan", ("SpringMan", false, 21) } }; public static void Shuffle<T>(this IList<T> list) { int num = list.Count; while (num > 1) { int index = ThreadSafeRandom.ThisThreadsRandom.Next(--num + 1); T value = list[index]; list[index] = list[num]; list[num] = value; } } public static void NotifyMissions() { switch (Config.MissionsNotification.Value) { case NotificationOption.SoundOnly: RoundManager.PlayRandomClip(HUDManager.Instance.UIAudio, HUDManager.Instance.tipsSFX, true, 1f, 0); break; case NotificationOption.SoundAndBanner: RoundManager.PlayRandomClip(HUDManager.Instance.UIAudio, HUDManager.Instance.tipsSFX, true, 1f, 0); HUDManager.Instance.DisplayTip("LethalMissions", MissionLocalization.GetMissionString("NewMissionsAvailable"), true, false, "LC_Tip1"); break; case NotificationOption.BannerOnly: ((TMP_Text)HUDManager.Instance.tipsPanelHeader).text = "LethalMissions"; ((TMP_Text)HUDManager.Instance.tipsPanelBody).text = MissionLocalization.GetMissionString("NewMissionsAvailable"); HUDManager.Instance.tipsPanelAnimator.SetTrigger("TriggerWarning"); break; case NotificationOption.None: break; } } public static string NumberToHour(int n, bool isPM) { return ((n >= 1 && n <= 19) ? ((isPM && n >= 6) ? (n - 6) : ((isPM || n != 19) ? (n + 5) : 12)) : 0).ToString(); } public static string GetEnemyNameById(int id) { foreach (var (result, flag, num) in EnemyOutsideStatus.Values) { if (num == id) { return result; } } return null; } } public class SimpleItem { public int ItemId { get; set; } public string ItemName { get; set; } public SimpleItem(int itemId, string itemName) { ItemId = itemId; ItemName = itemName; } } public enum GameStateEnum { InOrbit, TakingOff, OnMoon } public class MissionGenerator { private readonly Random random; public MissionGenerator() { random = new Random(); } public List<Mission> GenerateRandomMissions(int missionCount, List<Mission> allMissionsClone) { missionCount = ValidateMissionCount(missionCount, allMissionsClone); List<Mission> list = ChooseRandomMissions(missionCount, allMissionsClone); SetMissionSpecificProperties(list); foreach (Mission item in list) { Plugin.LogInfo($"Generated Mission: {item.Name}, Type: {item.Type}, Objective: {item.Objective}"); } return list; } private int ValidateMissionCount(int n, List<Mission> availableMissions) { if (Config.RandomMode.Value) { return random.Next(1, 6); } if (n > availableMissions.Count) { return availableMissions.Count; } return n; } private List<Mission> ChooseRandomMissions(int n, List<Mission> availableMissions) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Invalid comparison between Unknown and I4 List<Mission> list = new List<Mission>(); for (int i = 0; i < n; i++) { if (!availableMissions.Any()) { Plugin.LogError("No available missions to choose from."); break; } int index = random.Next(availableMissions.Count); Mission mission = availableMissions[index]; if (mission.Type == MissionType.RepairValve && !MapHasValves()) { Plugin.LogInfo("Skipped RepairValve mission as there are no valves on the map."); availableMissions.RemoveAt(index); } else if (mission.Type == MissionType.LightningRod && (int)StartOfRound.Instance.currentLevel.currentWeather != 2) { Plugin.LogInfo("Skipped LightningRod mission as the weather is not stormy."); availableMissions.RemoveAt(index); } else if (mission.Type == MissionType.ObtainGenerator && !MapHasApparatus()) { Plugin.LogInfo("Skipped ObtainGenerator mission as there is no apparatus on the map."); availableMissions.RemoveAt(index); } else { list.Add(mission); availableMissions.RemoveAt(index); } } return list; } private void SetMissionSpecificProperties(List<Mission> generatedMissions) { foreach (Mission generatedMission in generatedMissions) { if (generatedMission.Type == MissionType.OutOfTime) { generatedMission.LeaveTime = GenerateRandomLeaveTime(); } else if (generatedMission.Type == MissionType.SurviveCrewmates) { generatedMission.SurviveCrewmates = GenerateRandomSurviveCrewmates(); } else if (generatedMission.Type == MissionType.FindScrap) { generatedMission.Item = ObtainRandomScrap(); } else if (generatedMission.Type == MissionType.ObtainHive) { SetObtainHiveMissionProperties(generatedMission); } else if (generatedMission.Type == MissionType.RepairValve) { SetRepairValveMissionProperties(generatedMission); } } } private void SetObtainHiveMissionProperties(Mission mission) { //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_0062: 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_0074: Unknown result type (might be due to invalid IL or missing references) GameObject gameObject = ((Component)StartOfRound.Instance.shipAnimator).gameObject; GameObject enemyPrefab = ((IEnumerable<EnemyType>)Resources.FindObjectsOfTypeAll<EnemyType>()).FirstOrDefault((Func<EnemyType, bool>)((EnemyType obj) => ((Object)obj).name == Utils.GetEnemyNameById(7))).enemyPrefab; GameObject[] array = GameObject.FindGameObjectsWithTag("OutsideAINode"); Vector3 position = array[Random.Range(0, array.Length)].transform.position; GameObject val = Object.Instantiate<GameObject>(enemyPrefab, position, Quaternion.identity); Plugin.LogInfo($"Enemy spawned at {position}"); RedLocustBees component = val.GetComponent<RedLocustBees>(); ((Component)component).gameObject.GetComponentInChildren<NetworkObject>().Spawn(true); } private void SetRepairValveMissionProperties(Mission mission) { SteamValveHazard[] array = Object.FindObjectsOfType<SteamValveHazard>(); Array.Sort(array, (SteamValveHazard valve1, SteamValveHazard valve2) => ((Object)valve1).name.CompareTo(((Object)valve2).name)); int value = ((array.Length == 1) ? 1 : random.Next(1, array.Length + 1)); mission.ValveCount = value; } private int GenerateRandomLeaveTime() { return random.Next(12, 17); } private bool MapHasValves() { return Object.FindObjectsOfType<SteamValveHazard>().Length != 0; } private bool MapHasApparatus() { return Object.FindObjectsOfType<GrabbableObject>().Any((GrabbableObject grabbable) => grabbable.itemProperties.itemId == 3); } private int GenerateRandomSurviveCrewmates() { int count = NetworkManager.Singleton.ConnectedClientsIds.Count; if (count == 1) { return 1; } return (int)((double)count * 0.6); } private SimpleItem ObtainRandomScrap() { GrabbableObject[] array = (from grabbable in Object.FindObjectsOfType<GrabbableObject>() where grabbable.itemProperties.isScrap && grabbable.isInFactory && !grabbable.isInElevator && grabbable.itemProperties.itemId != 3 select grabbable).ToArray(); Item itemProperties = array[random.Next(array.Length)].itemProperties; return new SimpleItem(itemProperties.itemId, itemProperties.itemName); } } public enum MissionStatus { Incomplete, Complete } public enum MissionType { RecoverBody, LightningRod, WitnessDeath, ObtainHive, SurviveCrewmates, OutOfTime, KillMonster, ObtainGenerator, FindScrap, RepairValve } public class Mission { public string Name { get; set; } public string Objective { get; set; } public MissionStatus Status { get; set; } public MissionType Type { get; set; } public int Reward { get; set; } public int Weight { get; set; } public int? LeaveTime { get; set; } public int? SurviveCrewmates { get; set; } public LevelWeatherType? RequiredWeather { get; set; } public SimpleItem? Item { get; set; } public int? ValveCount { get; set; } public Mission(MissionType missionType, string missionName, string missionObjective, int reward, int? leaveTime = null, int? surviveCrewmates = null, LevelWeatherType? requiredWeather = -1, SimpleItem item = null, int? valveCount = null) { Type = missionType; Name = missionName; Objective = missionObjective; Status = MissionStatus.Incomplete; Reward = reward; Weight = 1; LeaveTime = leaveTime; SurviveCrewmates = surviveCrewmates; RequiredWeather = requiredWeather; Item = item; ValveCount = valveCount; } } public class MissionManager : MonoBehaviour { private List<Mission> Allmissions = new List<Mission>(); private List<Mission> Currentmissions = new List<Mission>(); private readonly MissionGenerator missionGenerator; private bool isFirstSync = true; public MissionManager() { Allmissions = MissionLocalization.GetLocalizedMissions(); missionGenerator = new MissionGenerator(); } public bool AreMissionsEqual(List<Mission> missions, List<Mission> missions1) { if (missions == null || missions1 == null) { return false; } if (missions.Count != missions1.Count) { return false; } for (int i = 0; i < missions.Count; i++) { if (missions[i].Type != missions1[i].Type || missions[i].Status != missions1[i].Status || missions[i].Name != missions1[i].Name || missions[i].Objective != missions1[i].Objective || missions[i].Reward != missions1[i].Reward) { return false; } } return true; } public void GenerateMissions(int missionCount) { Allmissions = MissionLocalization.GetLocalizedMissions(); if (Allmissions.Count == 0) { Plugin.LogError("No missions found."); return; } Currentmissions = missionGenerator.GenerateRandomMissions(missionCount, Allmissions); SyncMissionsServer(); } public string ShowMissionOverview() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("Lethal Missions\n"); if (Currentmissions.Count == 0) { stringBuilder.AppendLine(MissionLocalization.GetMissionString("NoMissionsMessage")); } else { foreach (Mission currentmission in Currentmissions) { if (currentmission.Type == MissionType.OutOfTime) { stringBuilder.AppendLine(MissionLocalization.GetMissionString("Name") + string.Format(currentmission.Name, Utils.NumberToHour(currentmission.LeaveTime.Value, isPM: true) + " PM")); stringBuilder.AppendLine(MissionLocalization.GetMissionString("Objective") + string.Format(currentmission.Objective, Utils.NumberToHour(currentmission.LeaveTime.Value, isPM: true) + " PM")); } else if (currentmission.Type == MissionType.SurviveCrewmates) { stringBuilder.AppendLine(MissionLocalization.GetMissionString("Name") + currentmission.Name); stringBuilder.AppendLine(MissionLocalization.GetMissionString("Objective") + string.Format(currentmission.Objective, currentmission.SurviveCrewmates)); } else if (currentmission.Type == MissionType.FindScrap) { stringBuilder.AppendLine(MissionLocalization.GetMissionString("Name") + currentmission.Name); stringBuilder.AppendLine(MissionLocalization.GetMissionString("Objective") + string.Format(currentmission.Objective, currentmission.Item.ItemName)); } else if (currentmission.Type == MissionType.RepairValve) { stringBuilder.AppendLine(MissionLocalization.GetMissionString("Name") + currentmission.Name); stringBuilder.AppendLine(MissionLocalization.GetMissionString("Objective") + string.Format(currentmission.Objective, currentmission.ValveCount)); } else { stringBuilder.AppendLine(MissionLocalization.GetMissionString("Name") + currentmission.Name); stringBuilder.AppendLine(MissionLocalization.GetMissionString("Objective") + currentmission.Objective); } stringBuilder.AppendLine(string.Format("{0}{1}", MissionLocalization.GetMissionString("Status"), currentmission.Status)); stringBuilder.AppendLine(string.Format("{0}{1}", MissionLocalization.GetMissionString("Reward"), currentmission.Reward)); stringBuilder.AppendLine("-----------------------------"); } } return stringBuilder.ToString(); } public void RemoveActiveMissions() { Currentmissions.Clear(); } public List<Mission> GetActiveMissions() { return Currentmissions; } public void CompleteMission(MissionType missionType) { Mission mission = Currentmissions.FirstOrDefault((Mission m) => m.Type == missionType); if (mission != null && mission.Status != MissionStatus.Complete) { mission.Status = MissionStatus.Complete; SyncMissionsServer(); } } public void IncompleteMission(MissionType missionType) { Mission mission = Currentmissions.FirstOrDefault((Mission m) => m.Type == missionType); if (mission != null && mission.Status != 0) { mission.Status = MissionStatus.Incomplete; SyncMissionsServer(); } } private void SyncMissionsServer() { if (!NetworkManager.Singleton.IsServer && !NetworkManager.Singleton.IsHost) { return; } if (Currentmissions != null && Currentmissions.Count > 0) { string serializedMissions = JsonConvert.SerializeObject((object)Currentmissions); if ((Object)(object)NetworkHandler.Instance != (Object)null) { NetworkHandler.Instance.SyncMissionsServerRpc(serializedMissions); } else { Plugin.LogError("SyncMissionsServer - NetworkHandler.Instance is null"); } } else { Plugin.LogError("Currentmissions is null or empty, unable to sync missions."); } } internal void SyncMissions(string serializedMissions) { List<Mission> collection = JsonConvert.DeserializeObject<List<Mission>>(serializedMissions); Currentmissions.Clear(); Currentmissions.AddRange(collection); if (isFirstSync) { isFirstSync = false; OnFirstReceiveMissions(); } } public void RequestMissions() { if (NetworkManager.Singleton.IsClient && !NetworkManager.Singleton.IsHost && !NetworkManager.Singleton.IsServer) { NetworkHandler.Instance?.RequestMissionsServerRpc(NetworkManager.Singleton.LocalClientId); } } public bool IsMissionActive(MissionType type) { return Currentmissions.Any((Mission m) => m.Type == type); } public int GetMissionLeaveTime(MissionType type) { return Currentmissions.FirstOrDefault((Mission m) => m.Type == type).LeaveTime.Value; } public int GetCreditsEarned() { return Currentmissions.Where((Mission m) => m.Status == MissionStatus.Complete).Sum((Mission m) => m.Reward); } public List<Mission> GetCompletedMissions() { return Currentmissions.Where((Mission m) => m.Status == MissionStatus.Complete).ToList(); } public int GetSurviveCrewmates() { return Currentmissions.FirstOrDefault((Mission m) => m.Type == MissionType.SurviveCrewmates).SurviveCrewmates.Value; } public Mission GetFindScrapItem() { return Currentmissions.FirstOrDefault((Mission m) => m.Type == MissionType.FindScrap); } public void ProgressValveRepair() { Mission mission = Currentmissions.FirstOrDefault((Mission m) => m.Type == MissionType.RepairValve); if (mission != null && mission.ValveCount > 0) { mission.ValveCount--; if (mission.ValveCount == 0) { CompleteMission(MissionType.RepairValve); } SyncMissionsServer(); } } public void ResetFirstSync() { isFirstSync = true; } private void OnFirstReceiveMissions() { foreach (Mission currentmission in Currentmissions) { if (currentmission.Type != MissionType.RepairValve) { continue; } List<SteamValveHazard> list = new List<SteamValveHazard>(); foreach (SteamValveHazard item in from v in Object.FindObjectsOfType<SteamValveHazard>() orderby ((Component)v).transform.position.y descending select v) { list.Add(item); } SteamValveHazard[] array = list.ToArray(); for (int i = 0; i < currentmission.ValveCount.Value; i++) { array[i].valveCrackTime = 0.001f; array[i].valveBurstTime = 0.01f; array[i].triggerScript.interactable = true; } } } } } namespace LethalMissions.Localization { public class MissionDataStore { public List<LocalizedMission> Missions { get; set; } public MissionDataStore() { List<LocalizedMission> obj = new List<LocalizedMission> { new LocalizedMission(MissionType.OutOfTime, "Escape before {0}", "Don't stay on the moon after {0}! It's a dangerous place!", Config.OutOfTimeReward.Value, null, null, (LevelWeatherType)(-1)) }; int value = Config.LightningRodReward.Value; LevelWeatherType? requiredWeather = (LevelWeatherType)2; obj.Add(new LocalizedMission(MissionType.LightningRod, "Lightning rod", "Become the human lightning rod, stop a lightning with style", value, null, null, requiredWeather)); obj.Add(new LocalizedMission(MissionType.WitnessDeath, "Witness a Celestial Event", "Witness the dramatic farewell of a fellow crewmate", Config.WitnessDeathReward.Value, null, null, (LevelWeatherType)(-1))); obj.Add(new LocalizedMission(MissionType.RecoverBody, "Retrieve Your Pal's Corpse", "Because being a hero also means playing space undertaker", Config.RecoverBodyReward.Value, null, null, (LevelWeatherType)(-1))); obj.Add(new LocalizedMission(MissionType.ObtainHive, "Get a beehive!", "Because even in space, we all need some honey and laughter", Config.ObtainHiveReward.Value, null, null, (LevelWeatherType)(-1))); obj.Add(new LocalizedMission(MissionType.SurviveCrewmates, "Preserve the Group's Life", "Make sure at least {0} crewmates survive the space odyssey!", Config.SurviveCrewmatesReward.Value, null, null, (LevelWeatherType)(-1))); obj.Add(new LocalizedMission(MissionType.KillMonster, "Defeat the Monster", "Embark on a daring mission to eliminate a menacing creature", Config.KillMonsterReward.Value, null, null, (LevelWeatherType)(-1))); obj.Add(new LocalizedMission(MissionType.ObtainGenerator, "Obtaining the Apparatus", "Take the Generator from the factory to the ship.", Config.ObtainGeneratorReward.Value, null, null, (LevelWeatherType)(-1))); obj.Add(new LocalizedMission(MissionType.FindScrap, "Find Scrap", "Find the next scrap: {0}", Config.FindScrapReward.Value, null, null, (LevelWeatherType)(-1))); obj.Add(new LocalizedMission(MissionType.RepairValve, "Repair the Valves", "As broken as your heart, show your skills and fix at least {0} of them.", Config.RepairValveReward.Value, null, null, (LevelWeatherType)(-1))); obj.Add(new LocalizedMission(MissionType.OutOfTime, "Escapa antes de las {0}", "¡No te quedes en la luna después de las {0}! ¡Es un lugar peligroso!", Config.OutOfTimeReward.Value, null, null, (LevelWeatherType)(-1), null, null, "es")); int value2 = Config.LightningRodReward.Value; requiredWeather = (LevelWeatherType)2; obj.Add(new LocalizedMission(MissionType.LightningRod, "Atrayendo rayos", "Conviértete en el pararrayos humano, detén un rayo con estilo", value2, null, null, requiredWeather, null, null, "es")); obj.Add(new LocalizedMission(MissionType.WitnessDeath, "Atestigua un suceso celestial", "Observa el dramático adiós de un compañero de la nave", Config.WitnessDeathReward.Value, null, null, (LevelWeatherType)(-1), null, null, "es")); obj.Add(new LocalizedMission(MissionType.RecoverBody, "Recupera el cuerpo de un amigo", "Porque ser un héroe incluye ser también sepulturero espacial", Config.RecoverBodyReward.Value, null, null, (LevelWeatherType)(-1), null, null, "es")); obj.Add(new LocalizedMission(MissionType.ObtainHive, "Consigue una colmena", "Porque incluso en el espacio, todos necesitamos un poco de miel y risas", Config.ObtainHiveReward.Value, null, null, (LevelWeatherType)(-1), null, null, "es")); obj.Add(new LocalizedMission(MissionType.SurviveCrewmates, "Preserva la Vida del Grupo", "¡Asegurate de que al menos {0} tripulantes sobrevivan a la odisea espacial!", Config.SurviveCrewmatesReward.Value, null, null, (LevelWeatherType)(-1), null, null, "es")); obj.Add(new LocalizedMission(MissionType.KillMonster, "Elimina al Monstruo", "Embarcate en una misión audaz para eliminar a una amenazante criatura", Config.KillMonsterReward.Value, null, null, (LevelWeatherType)(-1), null, null, "es")); obj.Add(new LocalizedMission(MissionType.ObtainGenerator, "Obteniendo el Aparato", "Lleva el generador de la fábrica a la nave.", Config.ObtainGeneratorReward.Value, null, null, (LevelWeatherType)(-1), null, null, "es")); obj.Add(new LocalizedMission(MissionType.FindScrap, "Encuentra chatarra", "Encuentra el siguiente objeto: {0}", Config.FindScrapReward.Value, null, null, (LevelWeatherType)(-1), null, null, "es")); obj.Add(new LocalizedMission(MissionType.RepairValve, "Repara las Válvulas", "Tan rota como tu corazón, demuestra tus habilidades y arregla al menos {0} de ellas.", Config.RepairValveReward.Value, null, null, (LevelWeatherType)(-1), null, null, "es")); Missions = obj; } } public class LocalizedMission : Mission { public string LanguageCode { get; set; } public LocalizedMission(MissionType missionType, string missionName, string missionObjective, int reward, int? leaveTime = null, int? surviveCrewmates = null, LevelWeatherType? requiredWeather = -1, SimpleItem item = null, int? valveCount = null, string languageCode = "en") : base(missionType, missionName, missionObjective, reward, leaveTime, surviveCrewmates, requiredWeather, item, valveCount) { LanguageCode = languageCode; } } public static class MissionLocalization { private static readonly string CurrentLanguage; private static readonly Dictionary<string, Dictionary<string, string>> MissionStrings; public static readonly List<LocalizedMission> missions; static MissionLocalization() { CurrentLanguage = Config.LanguageCode.Value; MissionStrings = new Dictionary<string, Dictionary<string, string>> { ["NoMissionsMessage"] = new Dictionary<string, string> { { "en", "There are no missions at the moment..." }, { "es", "No hay misiones en este momento..." } }, ["CompletedMissionMessage"] = new Dictionary<string, string> { { "en", "Completed Missions:" }, { "es", "Misiones Completadas:" } }, ["NoCompletedMissionsMessage"] = new Dictionary<string, string> { { "en", "No completed missions" }, { "es", "No hay misiones completadas" } }, ["CompletedMissionsCountMessage"] = new Dictionary<string, string> { { "en", "You have completed {0}\nmissions.\n\nHere are your rewards:\n\n" }, { "es", "Has completado {0}\nmisiones.\n\nAqui estan tus \nrecompensas:\n\n" } }, ["Name"] = new Dictionary<string, string> { { "en", "Name: " }, { "es", "Nombre: " } }, ["Objective"] = new Dictionary<string, string> { { "en", "Objective: " }, { "es", "Objetivo: " } }, ["Status"] = new Dictionary<string, string> { { "en", "Status: " }, { "es", "Estado: " } }, ["Reward"] = new Dictionary<string, string> { { "en", "Reward: " }, { "es", "Recompensa: " } }, ["NewMissionsAvailable"] = new Dictionary<string, string> { { "en", "New missions are available!" }, { "es", "Hay nuevas misiones disponibles!" } } }; MissionDataStore missionDataStore = new MissionDataStore(); missions = new List<LocalizedMission>(); foreach (LocalizedMission mission in missionDataStore.Missions) { LocalizedMission item = new LocalizedMission(mission.Type, mission.Name, mission.Objective, mission.Reward, mission.LeaveTime, mission.SurviveCrewmates, mission.RequiredWeather, mission.Item, mission.ValveCount, mission.LanguageCode); missions.Add(item); } } public static string GetMissionString(string key, params object[] args) { string format = MissionStrings[key][CurrentLanguage] ?? MissionStrings[key]["en"]; return string.Format(format, args); } public static List<Mission> GetLocalizedMissions() { return (from mission in missions where mission.LanguageCode == CurrentLanguage select new Mission(mission.Type, mission.Name, mission.Objective, mission.Reward, mission.LeaveTime, mission.SurviveCrewmates, mission.RequiredWeather, mission.Item, mission.ValveCount)).ToList(); } } }