Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of Heisenberg v2.1.0
Mod/Heisenberg.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using HarmonyLib; using HeisenbergMod; using Il2CppFishNet.Object; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne; using Il2CppScheduleOne.AvatarFramework; using Il2CppScheduleOne.Clothing; using Il2CppScheduleOne.Core.Items.Framework; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.Dialogue; using Il2CppScheduleOne.Employees; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.Money; using Il2CppScheduleOne.NPCs; using Il2CppScheduleOne.ObjectScripts; using Il2CppScheduleOne.Persistence.Loaders; using Il2CppSystem.Collections.Generic; using MelonLoader; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(Mod), "Heisenberg", "1.0.0", "neato", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("Heisenberg")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Heisenberg")] [assembly: AssemblyTitle("Heisenberg")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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; } } } namespace HeisenbergMod { public class Mod : MelonMod { [HarmonyPatch(typeof(DialogueController_Fixer), "ModifyChoiceList")] private static class Patch_AddHeisenbergChoice { private static void Postfix(string dialogueLabel, ref List<DialogueChoiceData> existingChoices) { //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) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown if (existingChoices == null) { return; } DialogueChoiceData val = null; Enumerator<DialogueChoiceData> enumerator = existingChoices.GetEnumerator(); while (enumerator.MoveNext()) { DialogueChoiceData current = enumerator.Current; if (current.ChoiceLabel == "Chemist") { val = current; } if (current.ChoiceLabel == "Heisenberg") { return; } } if (val != null) { existingChoices.Add(new DialogueChoiceData { Guid = val.Guid, ChoiceLabel = "Heisenberg", ChoiceText = $"Heisenberg (like a chemist, but everything he makes is Heavenly) - ${4000f:N0} signing bonus, ${600f:N0}/day" }); } } } [HarmonyPatch(typeof(DialogueHandler), "ChoiceSelected")] private static class Patch_RelabelHeisenbergChoice { private static void Prefix(DialogueHandler __instance, int choiceIndex) { bool flag = false; List<DialogueChoiceData> finalChoices = __instance.finalChoices; if (finalChoices != null && choiceIndex >= 0 && choiceIndex < finalChoices.Count) { DialogueChoiceData val = finalChoices[choiceIndex]; if (val != null && val.ChoiceLabel == "Heisenberg") { val.ChoiceLabel = "Chemist"; flag = true; } } List<DialogueChoiceData> currentChoices = __instance.CurrentChoices; if (currentChoices != null && choiceIndex >= 0 && choiceIndex < currentChoices.Count) { DialogueChoiceData val2 = currentChoices[choiceIndex]; if (val2 != null && val2.ChoiceLabel == "Heisenberg") { val2.ChoiceLabel = "Chemist"; flag = true; } } if (flag) { MelonLogger.Msg("Heisenberg selected - continuing as a standard Chemist hire."); _hiringHeisenberg = true; _hiringHeisenbergArmedAtTicks = Environment.TickCount64; } } } [HarmonyPatch(typeof(EmployeeManager), "CreateEmployee_Server")] private static class Patch_TagHeisenberg { private static void Postfix(Employee __result) { if (!_hiringHeisenberg) { return; } _hiringHeisenberg = false; if (Environment.TickCount64 - _hiringHeisenbergArmedAtTicks >= 60000) { return; } if ((Object)(object)__result == (Object)null) { MelonLogger.Error("CreateEmployee_Server returned null - Heisenberg was not created."); return; } float signingFee = __result.SigningFee; float num = 4000f - signingFee; if (num != 0f) { NetworkSingleton<MoneyManager>.Instance.ChangeCashBalance(0f - num, true, true); } ApplyHeisenbergIdentity(__result); StartLookEnforcer(__result); MelonLogger.Msg("Heisenberg hired!"); } } [HarmonyPatch(typeof(DialogueController_Fixer), "ModifyDialogueText")] private static class Patch_HeisenbergPriceText { private static void Postfix(ref string __result) { if (_hiringHeisenberg && Environment.TickCount64 - _hiringHeisenbergArmedAtTicks < 60000 && !string.IsNullOrEmpty(__result) && Regex.IsMatch(__result, "\\$\\s?\\d")) { __result = $"Heisenberg doesn't come cheap: ${4000f:N0} up front and ${600f:N0} a day, cash. But everything he cooks comes out Heavenly. Where do you want him?"; } } } [HarmonyPatch(typeof(EmployeeLoader), "CreateAndLoadEmployee")] private static class Patch_RestoreHeisenbergOnLoad { private static void Postfix(Employee __result) { StartLookEnforcer(__result); } } [HarmonyPatch(typeof(Employee), "InitializeAppearance")] private static class Patch_ReassertLookAfterVanillaAppearance { private static void Postfix(Employee __instance) { if (!((Object)(object)__instance == (Object)null) && (!(((NPC)__instance).ID != "heisenberg_chemist") || !(((NPC)__instance).FirstName != "Heisenberg"))) { ApplyHeisenbergIdentity(__instance); StartLookEnforcer(__instance); } } } [HarmonyPatch(typeof(Chemist), "StartChemistryStation")] private static class Patch_ArmChemistryStation { private static void Postfix(Chemist __instance, ChemistryStation station) { if (IsHeisenberg((NPC)(object)__instance) && (Object)(object)station != (Object)null) { _armedStations.Add(((Il2CppObjectBase)station).Pointer.ToInt64()); } } } [HarmonyPatch(typeof(Chemist), "StartLabOven")] private static class Patch_ArmLabOven { private static void Postfix(Chemist __instance, LabOven oven) { if (IsHeisenberg((NPC)(object)__instance) && (Object)(object)oven != (Object)null) { _armedStations.Add(((Il2CppObjectBase)oven).Pointer.ToInt64()); } } } [HarmonyPatch(typeof(Chemist), "StartCauldron")] private static class Patch_ArmCauldron { private static void Postfix(Chemist __instance, Cauldron cauldron) { if (IsHeisenberg((NPC)(object)__instance) && (Object)(object)cauldron != (Object)null) { _armedStations.Add(((Il2CppObjectBase)cauldron).Pointer.ToInt64()); } } } [HarmonyPatch(typeof(Chemist), "StartMixingStation")] private static class Patch_ArmMixingStation { private static void Postfix(Chemist __instance, MixingStation station) { if (IsHeisenberg((NPC)(object)__instance) && (Object)(object)station != (Object)null) { _armedStations.Add(((Il2CppObjectBase)station).Pointer.ToInt64()); } } } [HarmonyPatch(typeof(ChemistryStation), "SendCookOperation")] private static class Patch_ChemStation_Send { private static void Prefix(ChemistryStation __instance, ChemistryCookOperation op) { if (op != null && IsHeisenbergWorking(__instance.NPCUserObject, (Component)(object)__instance, "chemistry station")) { op.ProductQuality = (EQuality)4; } } } [HarmonyPatch(typeof(ChemistryStation), "SetCookOperation")] private static class Patch_ChemStation_Set { private static void Prefix(ChemistryStation __instance, ChemistryCookOperation operation) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 if (operation != null && (int)operation.ProductQuality != 4 && IsHeisenbergWorking(__instance.NPCUserObject, (Component)(object)__instance, "chemistry station")) { operation.ProductQuality = (EQuality)4; } } } [HarmonyPatch(typeof(LabOven), "SendCookOperation")] private static class Patch_LabOven_Send { private static void Prefix(LabOven __instance, OvenCookOperation operation) { if (operation != null && IsHeisenbergWorking(__instance.NPCUserObject, (Component)(object)__instance, "lab oven")) { operation.IngredientQuality = (EQuality)4; } } } [HarmonyPatch(typeof(LabOven), "SetCookOperation")] private static class Patch_LabOven_Set { private static void Prefix(LabOven __instance, OvenCookOperation operation) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 if (operation != null && (int)operation.IngredientQuality != 4 && IsHeisenbergWorking(__instance.NPCUserObject, (Component)(object)__instance, "lab oven")) { operation.IngredientQuality = (EQuality)4; } } } [HarmonyPatch(typeof(MixingStation), "SendMixingOperation")] private static class Patch_MixStation_Send { private static void Prefix(MixingStation __instance, MixOperation operation) { if (operation != null && IsHeisenbergWorking(__instance.NPCUserObject, (Component)(object)__instance, "mixing station")) { operation.ProductQuality = (EQuality)4; } } } [HarmonyPatch(typeof(Cauldron), "SendCookOperation")] private static class Patch_Cauldron_Send { private static void Prefix(Cauldron __instance, ref EQuality quality) { if ((int)quality != 4 && IsHeisenbergWorking(__instance.NPCUserObject, (Component)(object)__instance, "cauldron")) { quality = (EQuality)4; } } } [HarmonyPatch(typeof(Cauldron), "StartCookOperation")] private static class Patch_Cauldron_Start { private static void Prefix(Cauldron __instance, ref EQuality quality) { if ((int)quality != 4 && IsHeisenbergWorking(__instance.NPCUserObject, (Component)(object)__instance, "cauldron")) { quality = (EQuality)4; } } } [HarmonyPatch(typeof(Chemist), "FinishLabOven")] private static class Patch_Chemist_FinishLabOven { private static void Postfix(Chemist __instance, LabOven oven) { if (!IsHeisenberg((NPC)(object)__instance) || ((oven != null) ? oven.OutputSlots : null) == null) { return; } Enumerator<ItemSlot> enumerator = oven.OutputSlots.GetEnumerator(); while (enumerator.MoveNext()) { ItemSlot current = enumerator.Current; ItemInstance obj = ((current != null) ? current.ItemInstance : null); QualityItemInstance val = (QualityItemInstance)(object)((obj is QualityItemInstance) ? obj : null); if (val != null) { val.SetQuality((EQuality)4); } } } } private const string BillyId = "billy_kramer"; private const string HeisenbergId = "heisenberg_chemist"; private const string HeisenbergChoiceLabel = "Heisenberg"; private const float SigningFee = 4000f; private const float DailyWage = 600f; private static bool _hiringHeisenberg; private static long _hiringHeisenbergArmedAtTicks; private const long ArmedTimeoutMs = 60000L; private static readonly HashSet<long> _armedStations = new HashSet<long>(); private static readonly Color SuitRed = new Color(0.55f, 0.07f, 0.07f); private static readonly Color FedoraBlack = new Color(0.12f, 0.12f, 0.12f); private static readonly string[] SuitKeywords = new string[10] { "shirt", "top", "coat", "jacket", "vest", "suit", "sweater", "hoodie", "polo", "apron" }; private static readonly HashSet<long> _lookEnforcersRunning = new HashSet<long>(); private static string _fedoraPath; private static bool _loggedAccessories; public override void OnInitializeMelon() { ((MelonBase)this).LoggerInstance.Msg("Say my name."); ((MelonBase)this).HarmonyInstance.PatchAll(); } private static bool IsHeisenberg(NPC npc) { return (Object)(object)npc != (Object)null && npc.ID == "heisenberg_chemist"; } private static bool HeisenbergExists() { return (Object)(object)NPCManager.GetNPC("heisenberg_chemist") != (Object)null; } private static bool IsHeisenbergWorking(NetworkObject npcUser, Component station, string stationName) { if ((Object)(object)npcUser != (Object)null) { NPC componentInParent = ((Component)npcUser).GetComponentInParent<NPC>(); if (IsHeisenberg(componentInParent)) { MelonLogger.Msg("Heisenberg is working the " + stationName + " (user check) - forcing Heavenly."); return true; } } long item = ((Il2CppObjectBase)station).Pointer.ToInt64(); if (_armedStations.Remove(item)) { MelonLogger.Msg("Heisenberg is working the " + stationName + " (armed check) - forcing Heavenly."); return true; } return false; } private static bool ApplyHeisenbergIdentity(Employee employee) { employee.SigningFee = 4000f; employee.DailyWage = 600f; ((NPC)employee).ID = "heisenberg_chemist"; ((NPC)employee).FirstName = "Heisenberg"; ((NPC)employee).LastName = ""; ((NPC)employee).hasLastName = false; return ApplyHeisenbergLook(employee); } private static bool ApplyHeisenbergLook(Employee employee) { //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Expected O, but got Unknown NPC nPC = NPCManager.GetNPC("billy_kramer"); object obj; if (nPC == null) { obj = null; } else { Avatar avatar = nPC.Avatar; obj = ((avatar != null) ? avatar.CurrentSettings : null); } if ((Object)obj == (Object)null || (Object)(object)((NPC)employee).Avatar == (Object)null) { return false; } List<LayerSetting> bodyLayerSettings = nPC.Avatar.CurrentSettings.BodyLayerSettings; if (bodyLayerSettings == null || bodyLayerSettings.Count == 0) { return false; } AvatarSettings val = Object.Instantiate<AvatarSettings>(nPC.Avatar.CurrentSettings); val.UseCombinedLayer = false; List<LayerSetting> bodyLayerSettings2 = val.BodyLayerSettings; int num = 0; for (int i = 0; i < bodyLayerSettings2.Count; i++) { LayerSetting val2 = bodyLayerSettings2[i]; string text = val2.layerPath?.ToLowerInvariant() ?? ""; string[] suitKeywords = SuitKeywords; foreach (string value in suitKeywords) { if (text.Contains(value)) { val2.layerTint = SuitRed; bodyLayerSettings2[i] = val2; num++; break; } } } if (num == 0 && bodyLayerSettings2.Count > 0) { LayerSetting val3 = bodyLayerSettings2[bodyLayerSettings2.Count - 1]; val3.layerTint = SuitRed; bodyLayerSettings2[bodyLayerSettings2.Count - 1] = val3; } if (_fedoraPath == null) { _fedoraPath = FindAccessoryPath("fedora") ?? FindAccessoryPath("porkpie") ?? FindAccessoryPath("pork pie"); } string fedoraPath = _fedoraPath; List<AccessorySetting> accessorySettings = val.AccessorySettings; if (fedoraPath != null && accessorySettings != null) { for (int num2 = accessorySettings.Count - 1; num2 >= 0; num2--) { AccessorySetting obj2 = accessorySettings[num2]; string text2 = ((obj2 == null) ? null : obj2.path?.ToLowerInvariant()) ?? ""; if (!_loggedAccessories) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(29, 2); defaultInterpolatedStringHandler.AppendLiteral("[DIAG] Billy accessory ["); defaultInterpolatedStringHandler.AppendFormatted(num2); defaultInterpolatedStringHandler.AppendLiteral("]: '"); AccessorySetting obj3 = accessorySettings[num2]; defaultInterpolatedStringHandler.AppendFormatted((obj3 != null) ? obj3.path : null); defaultInterpolatedStringHandler.AppendLiteral("'"); MelonLogger.Msg(defaultInterpolatedStringHandler.ToStringAndClear()); } if (text2.Contains("/head/") || text2.Contains("hood") || text2.Contains("hat") || text2.Contains("helmet") || text2.Contains("mask") || text2.Contains("goggle") || text2.Contains("respirator")) { accessorySettings.RemoveAt(num2); } } _loggedAccessories = true; accessorySettings.Insert(0, new AccessorySetting { path = fedoraPath, color = FedoraBlack }); } ((NPC)employee).Avatar.LoadAvatarSettings(val); int value2 = ((Il2CppArrayBase<Accessory>)(object)((NPC)employee).Avatar.appliedAccessories)?.Length ?? (-1); MelonLogger.Msg($"[DIAG] Look applied: layers={bodyLayerSettings2.Count} tinted={num} hatPath={fedoraPath ?? "NONE"} accessoriesInSettings={val.AccessorySettings?.Count ?? (-1)} appliedAccessories={value2}"); return true; } private static void StartLookEnforcer(Employee employee) { if (!((Object)(object)employee == (Object)null)) { long num = ((Il2CppObjectBase)employee).Pointer.ToInt64(); if (_lookEnforcersRunning.Add(num)) { MelonCoroutines.Start(EnforceLook(employee, num)); } } } private static IEnumerator EnforceLook(Employee employee, long key) { try { int applied = 0; for (int attempt = 0; attempt < 15; attempt++) { yield return (object)new WaitForSeconds(2f); if ((Object)(object)employee == (Object)null || (((NPC)employee).ID != "heisenberg_chemist" && ((NPC)employee).FirstName != "Heisenberg")) { break; } if (ApplyHeisenbergIdentity(employee)) { applied++; } if (applied == 1) { MelonLogger.Msg("Heisenberg look applied (red suit + porkpie hat)."); } if (applied >= 5) { break; } } } finally { _lookEnforcersRunning.Remove(key); } } private static string FindAccessoryPath(string nameFragment) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Invalid comparison between Unknown and I4 Registry instance = Singleton<Registry>.Instance; if (((instance != null) ? instance.ItemRegistry : null) == null) { return null; } Enumerator<ItemRegister> enumerator = instance.ItemRegistry.GetEnumerator(); while (enumerator.MoveNext()) { ItemRegister current = enumerator.Current; object obj; if (current == null) { obj = null; } else { ItemDefinition definition = current.Definition; obj = ((definition != null) ? ((Il2CppObjectBase)definition).TryCast<ClothingDefinition>() : null); } ClothingDefinition val = (ClothingDefinition)obj; if (!((Object)(object)val == (Object)null) && (int)val.ApplicationType == 2) { string text = current.ID?.ToLowerInvariant() ?? ""; string text2 = ((BaseItemDefinition)val).Name?.ToLowerInvariant() ?? ""; if (text.Contains(nameFragment) || text2.Contains(nameFragment)) { MelonLogger.Msg($"Found hat '{current.ID}' -> asset path '{val.ClothingAssetPath}'"); return val.ClothingAssetPath; } } } MelonLogger.Msg("No accessory matching '" + nameFragment + "' found in item registry."); return null; } } }