Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of ScheduleOneEnhanced v2.0.0
ScheduleOneEnhanced.dll
Decompiled 2 months agousing System; 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 HarmonyLib; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using ScheduleOne; using ScheduleOne.DevUtilities; using ScheduleOne.Dialogue; using ScheduleOne.Economy; using ScheduleOne.Employees; using ScheduleOne.GameTime; using ScheduleOne.Growing; using ScheduleOne.Interaction; using ScheduleOne.ItemFramework; using ScheduleOne.Levelling; using ScheduleOne.Map; using ScheduleOne.Messaging; using ScheduleOne.NPCs; using ScheduleOne.NPCs.Relation; using ScheduleOne.NPCs.Responses; using ScheduleOne.Noise; using ScheduleOne.Persistence; using ScheduleOne.Persistence.Datas; using ScheduleOne.Persistence.Loaders; using ScheduleOne.PlayerScripts; using ScheduleOne.Product; using ScheduleOne.Property; using ScheduleOne.Quests; using ScheduleOne.Skating; using ScheduleOne.UI; using ScheduleOne.UI.Phone.ContactsApp; using ScheduleOne.UI.WorldspacePopup; using ScheduleOne.Variables; using ScheduleOne.Vehicles; using ScheduleOne.Vision; using ScheduleOne.VoiceOver; using ScheduleOneEnhanced; using ScheduleOneEnhanced.API; using ScheduleOneEnhanced.API.NPCs; using ScheduleOneEnhanced.API.Quests; using ScheduleOneEnhanced.API.Utils; using ScheduleOneEnhanced.Mods; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; 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: MelonInfo(typeof(ScheduleOneEnhancedMod), "ScheduleOneEnhanced", "2.0.0", "KaBooMa", null)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ScheduleOneEnhanced")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ScheduleOneEnhanced")] [assembly: AssemblyTitle("ScheduleOneEnhanced")] [assembly: AssemblyVersion("1.0.0.0")] 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; } } } namespace ScheduleOneEnhanced { public class ScheduleOneEnhancedMod : MelonMod { public static MelonPreferences_Entry<bool>? HardMode; public override void OnInitializeMelon() { MelonPreferences_Category val = MelonPreferences.CreateCategory("SOE"); HardMode = val.CreateEntry<bool>("SOE_HardMode", false, "Hard Mode", "Overrides below settings if enabled!!\nEnables my personal preference of 'Hard Mode'.", false, false, (ValueValidator)null, (string)null); CombatLowersRelationship.Initialize(); LongerGrowTimes.Initialize(); SprintRequiresStamina.Initialize(); ReassignEmployees.Initialize(); MoreEmployeeNames.Initialize(); MoreMixNames.Initialize(); IncreaseStackLimits.Initialize(); SkateboardCrashing.Initialize(); } } } namespace ScheduleOneEnhanced.Mods { [HarmonyPatch] public class CombatLowersRelationship { private static MelonPreferences_Entry<bool>? _enabled; private const float RelationshipChangeRate = -0.2f; public static void Initialize() { MelonPreferences_Category val = MelonPreferences.CreateCategory("SOE_CombatLowersRelationship"); _enabled = val.CreateEntry<bool>("SOE_CombatLowersRelationship_Enabled", true, "Enabled", "Toggles combat lowering relationship on / off.", false, false, (ValueValidator)null, (string)null); } [HarmonyPatch(typeof(NPCHealth), "TakeDamage")] [HarmonyPostfix] public static void NPCHealthTakeDamage(NPCHealth __instance, float damage) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown if (!(ScheduleOneEnhancedMod.HardMode?.Value).Value) { MelonPreferences_Entry<bool> enabled = _enabled; if (enabled != null && !enabled.Value) { return; } } FieldInfo fieldInfo = AccessTools.Field(typeof(NPCHealth), "npc"); NPC val = (NPC)fieldInfo.GetValue(__instance); val.RelationData.ChangeRelationship(-0.2f, true); } } [HarmonyPatch] public class IncreaseStackLimits { private static MelonPreferences_Entry<bool>? _enabled; private static MelonPreferences_Entry<int>? _productLimit; private static MelonPreferences_Entry<int>? _packagingLimit; private static MelonPreferences_Entry<int>? _growingLimit; private static MelonPreferences_Entry<int>? _toolsLimit; private static MelonPreferences_Entry<int>? _furnitureLimit; private static MelonPreferences_Entry<int>? _lightingLimit; private static MelonPreferences_Entry<int>? _cashLimit; private static MelonPreferences_Entry<int>? _consumableLimit; private static MelonPreferences_Entry<int>? _equipmentLimit; private static MelonPreferences_Entry<int>? _ingredientLimit; private static MelonPreferences_Entry<int>? _decorationLimit; private static List<ItemDefinition>? _allItemDefinitions; public static void Initialize() { MelonPreferences_Category val = MelonPreferences.CreateCategory("SOE_StackLimits"); _enabled = val.CreateEntry<bool>("SOE_IncreaseStackLimits_Enabled", true, "Enabled", "(Requires Game Reload) Toggles increased stack limits on / off.", false, false, (ValueValidator)null, (string)null); _productLimit = val.CreateEntry<int>("SOE_IncreaseStackLimits_ProductLimit", 20, "Product Limit", "Adjusts items such as Cocaine, Weed, etc. SpeedGrow is also in this category oddly, so keep that in mind.", false, false, (ValueValidator)null, (string)null); ((MelonEventBase<LemonAction<int, int>>)(object)_productLimit.OnEntryValueChanged).Subscribe((LemonAction<int, int>)delegate { UpdateItemCategory((EItemCategory)0); }, 0, false); _packagingLimit = val.CreateEntry<int>("SOE_IncreaseStackLimits_PackagingLimit", 20, "Packaging Limit", "Adjusts items such as Baggies, Bricks, Jars, etc.", false, false, (ValueValidator)null, (string)null); ((MelonEventBase<LemonAction<int, int>>)(object)_packagingLimit.OnEntryValueChanged).Subscribe((LemonAction<int, int>)delegate { UpdateItemCategory((EItemCategory)1); }, 0, false); _growingLimit = val.CreateEntry<int>("SOE_IncreaseStackLimits_GrowingLimit", 20, "Growing Limit", "Adjusts items such as Soil, Fertilizer, Pots, etc.", false, false, (ValueValidator)null, (string)null); ((MelonEventBase<LemonAction<int, int>>)(object)_growingLimit.OnEntryValueChanged).Subscribe((LemonAction<int, int>)delegate { UpdateItemCategory((EItemCategory)2); }, 0, false); _toolsLimit = val.CreateEntry<int>("SOE_IncreaseStackLimits_ToolsLimit", 10, "Tools Limit", "Adjusts trash bags ONLY. Other tools are left at 1 to prevent any potential issues.", false, false, (ValueValidator)null, (string)null); ((MelonEventBase<LemonAction<int, int>>)(object)_toolsLimit.OnEntryValueChanged).Subscribe((LemonAction<int, int>)delegate { UpdateItemCategory((EItemCategory)3); }, 0, false); _furnitureLimit = val.CreateEntry<int>("SOE_IncreaseStackLimits_FurnitureLimit", 10, "Furniture Limit", "Adjusts items such as TV, Trash Can, Bed, etc.", false, false, (ValueValidator)null, (string)null); ((MelonEventBase<LemonAction<int, int>>)(object)_furnitureLimit.OnEntryValueChanged).Subscribe((LemonAction<int, int>)delegate { UpdateItemCategory((EItemCategory)4); }, 0, false); _lightingLimit = val.CreateEntry<int>("SOE_IncreaseStackLimits_LightingLimit", 10, "Lighting Limit", "Adjusts items such as Floor Lamps, Halogen Lights, etc.", false, false, (ValueValidator)null, (string)null); ((MelonEventBase<LemonAction<int, int>>)(object)_lightingLimit.OnEntryValueChanged).Subscribe((LemonAction<int, int>)delegate { UpdateItemCategory((EItemCategory)5); }, 0, false); _cashLimit = val.CreateEntry<int>("SOE_IncreaseStackLimits_CashLimit", 1000, "Cash Limit", "(Not functional at this time!) Adjusts cash stack limit.", false, false, (ValueValidator)null, (string)null); ((MelonEventBase<LemonAction<int, int>>)(object)_cashLimit.OnEntryValueChanged).Subscribe((LemonAction<int, int>)delegate { UpdateItemCategory((EItemCategory)6); }, 0, false); _consumableLimit = val.CreateEntry<int>("SOE_IncreaseStackLimits_ConsumableLimit", 20, "Consumable Limit", "Adjusts items such as Cuke, Energy Drink, etc.", false, false, (ValueValidator)null, (string)null); ((MelonEventBase<LemonAction<int, int>>)(object)_consumableLimit.OnEntryValueChanged).Subscribe((LemonAction<int, int>)delegate { UpdateItemCategory((EItemCategory)7); }, 0, false); _equipmentLimit = val.CreateEntry<int>("SOE_IncreaseStackLimits_EquipmentLimit", 20, "Equipment Limit", "Adjusts items such as Drying Rack, Brick Press, Mixing Station, etc.", false, false, (ValueValidator)null, (string)null); ((MelonEventBase<LemonAction<int, int>>)(object)_equipmentLimit.OnEntryValueChanged).Subscribe((LemonAction<int, int>)delegate { UpdateItemCategory((EItemCategory)8); }, 0, false); _ingredientLimit = val.CreateEntry<int>("SOE_IncreaseStackLimits_IngredientLimit", 20, "Ingredient Limit", "Adjusts items such as Acid, Banana, Chili, etc.", false, false, (ValueValidator)null, (string)null); ((MelonEventBase<LemonAction<int, int>>)(object)_ingredientLimit.OnEntryValueChanged).Subscribe((LemonAction<int, int>)delegate { UpdateItemCategory((EItemCategory)9); }, 0, false); _decorationLimit = val.CreateEntry<int>("SOE_IncreaseStackLimits_DecorationLimit", 10, "Decoration Limit", "Adjusts items such as GoldBar, WallClock, WoodSign, etc.", false, false, (ValueValidator)null, (string)null); ((MelonEventBase<LemonAction<int, int>>)(object)_decorationLimit.OnEntryValueChanged).Subscribe((LemonAction<int, int>)delegate { UpdateItemCategory((EItemCategory)10); }, 0, false); } [HarmonyPatch(typeof(Registry), "Start")] [HarmonyPostfix] public static void RegistryStart(Registry __instance) { FieldInfo fieldInfo = AccessTools.Field(typeof(Registry), "ItemRegistry"); List<ItemRegister> source = (List<ItemRegister>)fieldInfo.GetValue(__instance); _allItemDefinitions = source.Select((ItemRegister itemRegister) => itemRegister.Definition).ToList(); UpdateEntireRegistry(); } [HarmonyPatch(typeof(Registry), "AddToRegistry")] [HarmonyPostfix] public static void RegistryAddToRegistry(Registry __instance, ItemDefinition item) { CollectionExtensions.AddItem<ItemDefinition>((IEnumerable<ItemDefinition>)_allItemDefinitions, item); UpdateItemDefinition(item); } private static void UpdateEntireRegistry() { if (_allItemDefinitions == null) { return; } MelonPreferences_Entry<bool> enabled = _enabled; if (enabled == null || !enabled.Value) { return; } foreach (ItemDefinition allItemDefinition in _allItemDefinitions) { UpdateItemDefinition(allItemDefinition); } } private static void UpdateItemCategory(EItemCategory itemCategory) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) MelonPreferences_Entry<bool> enabled = _enabled; if (enabled != null && !enabled.Value) { return; } List<ItemDefinition> list = _allItemDefinitions?.Where((ItemDefinition itemDefinition) => itemCategory == itemDefinition.Category).ToList(); if (list == null) { return; } foreach (ItemDefinition item in list) { UpdateItemDefinition(item); } } private static void UpdateItemDefinition(ItemDefinition itemDefinition) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected I4, but got Unknown EItemCategory category = itemDefinition.Category; EItemCategory val = category; switch ((int)val) { case 0: itemDefinition.StackLimit = (_productLimit?.Value).Value; break; case 1: itemDefinition.StackLimit = (_packagingLimit?.Value).Value; break; case 2: itemDefinition.StackLimit = (_growingLimit?.Value).Value; break; case 3: itemDefinition.StackLimit = (_toolsLimit?.Value).Value; break; case 4: itemDefinition.StackLimit = (_furnitureLimit?.Value).Value; break; case 5: itemDefinition.StackLimit = (_lightingLimit?.Value).Value; break; case 6: itemDefinition.StackLimit = (_cashLimit?.Value).Value; break; case 7: itemDefinition.StackLimit = (_consumableLimit?.Value).Value; break; case 8: itemDefinition.StackLimit = (_equipmentLimit?.Value).Value; break; case 9: itemDefinition.StackLimit = (_ingredientLimit?.Value).Value; break; case 10: itemDefinition.StackLimit = (_decorationLimit?.Value).Value; break; } } } [HarmonyPatch] public class LongerGrowTimes { private static MelonPreferences_Entry<bool>? _enabled; private const float WeedGrowthMultiplier = 1.5f; private const float CocaGrowthMultiplier = 2f; public static void Initialize() { MelonPreferences_Category val = MelonPreferences.CreateCategory("SOE_LongerGrowTimes"); _enabled = val.CreateEntry<bool>("SOE_LongerGrowTimes_Enabled", true, "Enabled", "(Requires Game Reload) Toggles longer grow times on / off.", false, false, (ValueValidator)null, (string)null); } [HarmonyPatch(typeof(Plant), "Initialize")] [HarmonyPostfix] public static void WeedPlantInitialize(Plant __instance) { if (!(ScheduleOneEnhancedMod.HardMode?.Value).Value) { MelonPreferences_Entry<bool> enabled = _enabled; if (enabled != null && !enabled.Value) { return; } } WeedPlant val = (WeedPlant)(object)((__instance is WeedPlant) ? __instance : null); if (val == null) { CocaPlant val2 = (CocaPlant)(object)((__instance is CocaPlant) ? __instance : null); if (val2 != null) { ((Plant)val2).GrowthTime = Mathf.RoundToInt((float)__instance.GrowthTime * 2f); } } else { ((Plant)val).GrowthTime = Mathf.RoundToInt((float)__instance.GrowthTime * 1.5f); } } } [HarmonyPatch] public class MoreEmployeeNames { private static MelonPreferences_Entry<bool>? _enabled; public static void Initialize() { MelonPreferences_Category val = MelonPreferences.CreateCategory("SOE_MoreEmployeeNames"); _enabled = val.CreateEntry<bool>("SOE_MoreEmployeeNames_Enabled", true, "Enabled", "(Requires Game Reload) Toggles more employee names on / off.", false, false, (ValueValidator)null, (string)null); } [HarmonyPatch(typeof(EmployeeManager), "Awake")] [HarmonyPostfix] public static void EmployeeManagerAwake(EmployeeManager __instance) { MelonPreferences_Entry<bool> enabled = _enabled; if (enabled == null || enabled.Value) { CollectionExtensions.AddRangeToArray<string>(__instance.MaleFirstNames, new string[9] { "Buster", "Chet", "Snoop", "Ziggy", "Hank", "Dwayne \"The Rock\"", "Gandalf", "Zezima", "Busta" }); CollectionExtensions.AddRangeToArray<string>(__instance.FemaleFirstNames, new string[8] { "Trixie", "Bambi", "Candy", "Dolly", "Lulu", "Blanche", "Wanda \"The Wrench\"", "Ruby" }); CollectionExtensions.AddRangeToArray<string>(__instance.LastNames, new string[11] { "Fizzlebottom", "McSizzle", "Flapjack", "Slobberstein", "Twinkletoes", "Trump", "Duck", "Muncher", "O'Problem", "Phuckzer", "Nutz" }); } } } [HarmonyPatch] public class MoreMixNames { private static MelonPreferences_Entry<bool>? _enabled; public static void Initialize() { MelonPreferences_Category val = MelonPreferences.CreateCategory("SOE_MoreMixNames"); _enabled = val.CreateEntry<bool>("SOE_MoreMixNames_Enabled", true, "Enabled", "(Requires Game Reload) Toggles more mix names on / off.", false, false, (ValueValidator)null, (string)null); } [HarmonyPatch(typeof(NewMixScreen), "Awake")] [HarmonyPostfix] public static void NewMixScreenAwake(NewMixScreen __instance) { MelonPreferences_Entry<bool> enabled = _enabled; if (enabled == null || enabled.Value) { FieldInfo fieldInfo = AccessTools.Field(typeof(NewMixScreen), "name1Library"); List<string> list = (List<string>)fieldInfo.GetValue(__instance); FieldInfo fieldInfo2 = AccessTools.Field(typeof(NewMixScreen), "name2Library"); List<string> list2 = (List<string>)fieldInfo2.GetValue(__instance); list.AddRange(new string[18] { "Dirty", "Nasty", "Big", "Slutty", "Wet", "Fuzzy", "Filthy", "Tasty", "Juicy", "Soggy", "Sticky", "Cosmic", "Thundering", "Crystallized", "Ultra", "Zen", "Raging", "Killer" }); list2.AddRange(new string[9] { "Sauce", "Tush", "Kush", "Crunch", "Delight", "Junk", "Puss", "Rex", "Horse" }); } } } [HarmonyPatch] public class ReassignEmployees { private static MelonPreferences_Entry<bool>? _enabled; private static DialogueContainer? _dialogueContainer; public static void Initialize() { MelonPreferences_Category val = MelonPreferences.CreateCategory("SOE_ReassignEmployees"); _enabled = val.CreateEntry<bool>("SOE_ReassignEmployees_Enabled", true, "Enabled", "(Requires Game Reload) Toggles reassign employees on / off.", false, false, (ValueValidator)null, (string)null); } private static void ShowAssignPropertyDialogue(DialogueHandler dialogueHandler) { dialogueHandler.InitializeDialogue(_dialogueContainer, true, "ASSIGN_PROPERTY"); } [HarmonyPatch(typeof(Employee), "Start")] [HarmonyPostfix] public static void EmployeeStart(Employee __instance) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected O, but got Unknown Employee __instance2 = __instance; MelonPreferences_Entry<bool> enabled2 = _enabled; if (enabled2 == null || enabled2.Value) { _dialogueContainer = ScriptableObject.CreateInstance<DialogueContainer>(); List<DialogueNodeData> dialogueNodeData = _dialogueContainer.DialogueNodeData; DialogueNodeData val = new DialogueNodeData(); val.DialogueNodeLabel = "ASSIGN_PROPERTY"; val.DialogueText = "Where would you like me to go boss?"; val.choices = (DialogueChoiceData[])(object)new DialogueChoiceData[0]; val.VoiceLine = (EVOLineType)19; dialogueNodeData.Add(val); DialogueController component = ((Component)((NPC)__instance2).dialogueHandler).GetComponent<DialogueController>(); DialogueChoice val2 = new DialogueChoice { ChoiceText = "I need you to work for me somewhere else.", Enabled = true, shouldShowCheck = (ShouldShowCheck)((bool enabled) => !__instance2.Fired), Conversation = _dialogueContainer }; val2.onChoosen.AddListener((UnityAction)delegate { ShowAssignPropertyDialogue(((NPC)__instance2).dialogueHandler); }); component.AddDialogueChoice(val2, 0); } } [HarmonyPatch(typeof(DialogueController), "ModifyChoiceList")] [HarmonyPostfix] public static void DialogueControllerModifyChoiceList(DialogueController __instance, string dialogueLabel, ref List<DialogueChoiceData> existingChoices) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown if (!(dialogueLabel == "ASSIGN_PROPERTY")) { return; } FieldInfo fieldInfo = AccessTools.Field(typeof(DialogueController), "npc"); Employee val = (Employee)fieldInfo.GetValue(__instance); foreach (Property ownedProperty in Property.OwnedProperties) { if ((Object)(object)val.AssignedProperty != (Object)(object)ownedProperty && ownedProperty.PropertyCode != "rv" && ownedProperty.PropertyCode != "motelroom") { string propertyName = ownedProperty.PropertyName; existingChoices.Add(new DialogueChoiceData { ChoiceText = propertyName, ChoiceLabel = "ASSIGNED_TO_" + ownedProperty.PropertyCode }); } } } [HarmonyPatch(typeof(DialogueController), "ChoiceCallback")] [HarmonyPostfix] public static void DialogueControllerChoiceCallback(DialogueController __instance, string choiceLabel) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown if (choiceLabel.StartsWith("ASSIGNED_TO_")) { FieldInfo fieldInfo = AccessTools.Field(typeof(DialogueController), "npc"); Employee val = (Employee)fieldInfo.GetValue(__instance); MethodInfo methodInfo = AccessTools.Method(typeof(Employee), "AssignProperty", (Type[])null, (Type[])null); Property property = Singleton<PropertyManager>.Instance.GetProperty(choiceLabel.Substring("ASSIGNED_TO_".Length)); val.AssignedProperty.DeregisterEmployee(val); methodInfo.Invoke(val, new object[1] { property }); } } [HarmonyPatch(typeof(DialogueController), "CheckChoice")] [HarmonyPostfix] public static void DialogueControllerCheckChoice(DialogueController __instance, string choiceLabel, ref string invalidReason, ref bool __result) { if (choiceLabel.StartsWith("ASSIGNED_TO_")) { Property property = Singleton<PropertyManager>.Instance.GetProperty(choiceLabel.Substring("ASSIGNED_TO_".Length)); if (property.Employees.Count >= property.EmployeeCapacity) { invalidReason = $"Employee limit reached ({property.Employees.Count}/{property.EmployeeCapacity})"; __result = false; } } } } [HarmonyPatch] public class SkateboardCrashing { private static MelonPreferences_Entry<bool>? _enabled; private static MelonPreferences_Entry<float>? _fallOffSpeed; private const float StuckSpeed = 5f; private const float FarAway = 50f; private static Vector3? _previousVelocity; private static float _timeStill; private static float _timeFalling; private static readonly Dictionary<Player, bool> FallenStatus = new Dictionary<Player, bool>(); private const float RequiredTimeStill = 1f; public static void Initialize() { MelonPreferences_Category val = MelonPreferences.CreateCategory("SOE_SkateboardCrashing"); _enabled = val.CreateEntry<bool>("SOE_SkateboardCrashing_Enabled", true, "Enabled", "Toggle skateboard crashing on / off.", false, false, (ValueValidator)null, (string)null); _fallOffSpeed = val.CreateEntry<float>("SOE_SkateboardCrashing_FallOffSpeed", 2f, "Fall Off Speed", "When your velocity drops by this amount, you will be dismounted.", false, false, (ValueValidator)null, (string)null); } private static void FallOffSkateboard(Skateboard skateboard) { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) if (_previousVelocity.HasValue) { skateboard.Equippable.Dismount(); skateboard.Rider.SetRagdolled(true); PlayerSingleton<PlayerMovement>.Instance.canMove = false; ((Collider)PlayerSingleton<PlayerMovement>.Instance.Controller).enabled = false; PlayerSingleton<PlayerCamera>.Instance.SetCameraMode((ECameraMode)0); PlayerSingleton<PlayerCamera>.Instance.StopTransformOverride(0f, false, false); PlayerSingleton<PlayerCamera>.Instance.StopFOVOverride(0f); PlayerSingleton<PlayerCamera>.Instance.SetCanLook(false); Rigidbody[] ragdollRBs = skateboard.Rider.Avatar.RagdollRBs; foreach (Rigidbody val in ragdollRBs) { val.velocity = _previousVelocity.Value * 3f; } FallenStatus[skateboard.Rider] = true; _timeStill = 0f; _timeFalling = 0f; } } [HarmonyPatch(typeof(Player), "FixedUpdate")] [HarmonyPostfix] public static void PlayerFixedUpdate(Player __instance) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_0067: 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) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: 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_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) if (FallenStatus.ContainsKey(__instance) && FallenStatus[__instance]) { PlayerCamera instance = PlayerSingleton<PlayerCamera>.Instance; Vector3 val = ((Component)__instance.Avatar.MiddleSpineRB).transform.position - ((Component)instance).transform.position; Quaternion val2 = Quaternion.LookRotation(val, ((Component)instance).transform.up); ((Component)instance).transform.rotation = Quaternion.Lerp(((Component)instance).transform.rotation, val2, 10f * Time.deltaTime); Vector3 velocity = __instance.Avatar.MiddleSpineRB.velocity; if (((Vector3)(ref velocity)).magnitude <= 1f) { _timeStill += Time.deltaTime; _timeFalling += Time.deltaTime; } else { _timeStill = 0f; } bool flag = Vector3.Distance(__instance.Avatar.MiddleSpineRB.position, __instance.CameraPosition) > 50f; if (_timeStill >= 1f || flag || _timeFalling >= 5f) { ((Component)__instance).transform.position = __instance.Avatar.MiddleSpineRB.position + new Vector3(0f, 0.5f, 0f); FallenStatus[__instance] = false; __instance.SetRagdolled(false); PlayerSingleton<PlayerCamera>.Instance.SetCanLook(true); PlayerSingleton<PlayerMovement>.Instance.canMove = true; ((Collider)PlayerSingleton<PlayerMovement>.Instance.Controller).enabled = true; } } } [HarmonyPatch(typeof(Skateboard), "Awake")] [HarmonyPostfix] public static void SkateboardAwake() { _previousVelocity = null; } [HarmonyPatch(typeof(Skateboard), "FixedUpdate")] [HarmonyPostfix] public static void SkateboardFixedUpdate(Skateboard __instance) { //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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) if (!(ScheduleOneEnhancedMod.HardMode?.Value).Value) { MelonPreferences_Entry<bool> enabled = _enabled; if (enabled != null && !enabled.Value) { return; } } if (Object.op_Implicit((Object)(object)__instance.Rider.ActiveSkateboard)) { Vector3 velocity = __instance.Rb.velocity; float? obj; if (!_previousVelocity.HasValue) { obj = null; } else { Vector3 valueOrDefault = _previousVelocity.GetValueOrDefault(); obj = ((Vector3)(ref valueOrDefault)).magnitude; } float? num = obj - ((Vector3)(ref velocity)).magnitude; MelonLogger.Msg(num?.ToString()); if (num >= _fallOffSpeed?.Value) { FallOffSkateboard(__instance); } _previousVelocity = velocity; } } } [HarmonyPatch] public class SprintRequiresStamina { private static MelonPreferences_Entry<bool>? _enabled; public static void Initialize() { MelonPreferences_Category val = MelonPreferences.CreateCategory("SOE_SprintRequiresStamina"); _enabled = val.CreateEntry<bool>("SOE_SprintRequiresStamina_Enabled", false, "Enabled", "(Requires Game Reload) Toggles sprint requiring stamina on / off.", false, false, (ValueValidator)null, (string)null); } [HarmonyPatch(typeof(PlayerMovement), "Awake")] [HarmonyPostfix] public static void PlayerMovementAwake(PlayerMovement __instance) { if (!(ScheduleOneEnhancedMod.HardMode?.Value).Value) { MelonPreferences_Entry<bool> enabled = _enabled; if (enabled != null && !enabled.Value) { return; } } __instance.SprintingRequiresStamina = true; } } } namespace ScheduleOneEnhanced.Mods.BulkBuyer { internal class BickyRobby : SOENPC { private const int ProductPerLevel = 8; private const int ProductVariation = 10; private const float ProductPriceMultiplier = 1.2f; private const int MinDaysAllowed = 1; private const int MaxDaysAllowed = 3; [SaveableField("Order")] private OrderData? _orderData; [SaveableField("Intro")] private IntroData? _introData; private static readonly (string message, string response)[] IntroTexts = new(string, string)[3] { ("Yo, your uncle said you might could help me with supply. I'm running low.", "Where you wanna meet?"), ("I can't meet up. I'm over in Belland, like 300 miles out dawg.", "What about a dead drop?"), ("That works. I'll text you when I need a drop. Peace.", "") }; private static readonly string[] RandomRequestTexts = new string[6] { "Yo, I need {amount} {product} by {day}. I've got {price} with your name on it. Can you make that happen?", "My people are fienin. Got {amount} {product}?? Need it by {day} if you can. I'll drop {price} for it.", "Ayo, can you hit me with {amount} {product} by {day} for me? You know I need it, and I'll pay {price} for that.", "{amount} {product} by {day} - you got me?? I got you {price} waiting.", "I'm runnin' low on {product}. Can you push {amount} to me by {day}? I'll pay {price} for it.", "Bro, I'm out here scrambling. Can you get {amount} {product} by {day}? I'm desperate, I'll toss {price} your way." }; private static readonly string[] RandomAcceptResponses = new string[3] { "No doubt, send me a pin.", "Say no more, I gotchu.", "Aight, let's run it." }; private static readonly string[] RandomDenyResponses = new string[3] { "Nah, ain't got it right now.", "Can't do it at the moment.", "Nah, I can't make this week." }; private static readonly string[] RandomNegativeTexts = new string[3] { "Damn, aight... guess that's it then.", "Cool, I guess... catch you later.", "Shit, no no. Ok, i'll hit you up later tho." }; private static readonly string[] RandomPositiveTexts = new string[3] { "Hell yeah bro, thanks.", "Solid, I'll drop you the cash when I pull up.", "You a real one, fam. Appreciate you." }; private bool IntroCompleted => _introData != null && _introData.progress >= IntroTexts.Length - 1; public BickyRobby() { ((NPC)this).FirstName = "Bicky"; ((NPC)this).LastName = "Robby"; ((NPC)this).ID = "bicky_robby"; } public override void Awake() { _introData = new IntroData(); TimeManager instance = NetworkSingleton<TimeManager>.Instance; instance.onDayPass = (Action)Delegate.Combine(instance.onDayPass, new Action(OnDayPass)); base.Awake(); } protected override void Start() { ((NPC)this).Start(); foreach (Response currentResponse in ((NPC)this).MSGConversation.currentResponses) { switch (currentResponse.label) { case "ACCEPT": currentResponse.callback = AcceptOrder; break; case "DENY": currentResponse.callback = DenyOrder; break; case "PROGRESS_INTRO": currentResponse.callback = ProgressIntro; break; } } } private void OnDayPass() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Invalid comparison between Unknown and I4 if (!IntroCompleted && (int)NetworkSingleton<LevelManager>.Instance.Rank >= 3) { ProgressIntro(); } else if (_orderData != null) { DenyOrder(); } else if ((int)NetworkSingleton<TimeManager>.Instance.CurrentDay == 1) { SendRandomText(); } } private void SendRandomText() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected I4, but got Unknown //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: 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_00f8: 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_0109: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Expected O, but got Unknown //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Expected O, but got Unknown ProductDefinition val = ProductManager.DiscoveredProducts[Random.Range(0, ProductManager.DiscoveredProducts.Count)]; if (Object.op_Implicit((Object)(object)val)) { _orderData = new OrderData { productID = ((ItemDefinition)val).ID }; if (!((Object)(object)_orderData.Product == (Object)null)) { int num = (int)NetworkSingleton<LevelManager>.Instance.Rank; int num2 = num * 8; int num3 = Mathf.RoundToInt(5f); int num4 = num2 - num3; int num5 = num2 + num3; _orderData.amount = Random.Range(num4, num5); _orderData.price = Mathf.RoundToInt(_orderData.Product.Price * (float)_orderData.amount * 1.2f); int num6 = Random.Range(1, 4); OrderData? orderData = _orderData; GameDateTime dateTime = NetworkSingleton<TimeManager>.Instance.GetDateTime(); orderData.expiryDateTime = ((GameDateTime)(ref dateTime)).AddMins(2400 * num6); EDay val2 = (EDay)((NetworkSingleton<TimeManager>.Instance.CurrentDay + num6) % Enum.GetValues(typeof(EDay)).Length); string text = RandomRequestTexts[Random.Range(0, RandomRequestTexts.Length)]; string text2 = text.Replace("{product}", "<color=#3399FF>" + ((ItemDefinition)_orderData.Product).Name + "</color>").Replace("{amount}", $"{_orderData.amount}x").Replace("{day}", $"<color=#FF6600>{val2}</color>") .Replace("{price}", $"<color=#00CC00>${_orderData.price:N0}</color>"); ((NPC)this).SendTextMessage(text2); string text3 = RandomDenyResponses[Random.Range(0, RandomDenyResponses.Length)]; string text4 = RandomAcceptResponses[Random.Range(0, RandomAcceptResponses.Length)]; ((NPC)this).MSGConversation.ClearResponses(false); ((NPC)this).MSGConversation.ShowResponses(new List<Response> { new Response { label = "ACCEPT", text = text4, callback = AcceptOrder }, new Response { label = "DENY", text = text3, callback = DenyOrder } }, 1f, true); } } } private void DenyOrder() { string text = RandomNegativeTexts[Random.Range(0, RandomNegativeTexts.Length)]; ((NPC)this).SendTextMessage(text); ClearPendingOrder(); } private void AcceptOrder() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown if (_orderData == null || (Object)(object)_orderData.Product == (Object)null) { throw new Exception("No pending product assigned in BulkBuyer!"); } string text = RandomPositiveTexts[Random.Range(0, RandomPositiveTexts.Length)]; ((NPC)this).SendTextMessage(text); GameObject val = new GameObject("Quest"); QuestBickyOrder questBickyOrder = val.AddComponent<QuestBickyOrder>(); questBickyOrder.Initialize(_orderData); ClearPendingOrder(); } private void ClearPendingOrder() { _orderData = null; } private void ProgressIntro() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_00a6: Expected O, but got Unknown if (_introData == null) { throw new Exception("No intro data assigned in BulkBuyer!"); } ((NPC)this).SendTextMessage(IntroTexts[_introData.progress].message); ((NPC)this).MSGConversation.ClearResponses(false); if (!IntroCompleted) { ((NPC)this).MSGConversation.ShowResponses(new List<Response> { new Response { label = "PROGRESS_INTRO", text = IntroTexts[_introData.progress].response, callback = ProgressIntro } }, 1f, true); _introData.progress++; } } } [Serializable] public class DeadDropData : SaveData { public string? deliverDeadDropGUID; public string? collectDeadDropGUID; public DeadDrop? DeliveryDeadDrop => ((IEnumerable<DeadDrop>)DeadDrop.DeadDrops).FirstOrDefault((Func<DeadDrop, bool>)((DeadDrop deadDrop) => deadDrop.GUID.ToString() == deliverDeadDropGUID)); public DeadDrop? CollectDeadDrop => ((IEnumerable<DeadDrop>)DeadDrop.DeadDrops).FirstOrDefault((Func<DeadDrop, bool>)((DeadDrop deadDrop) => deadDrop.GUID.ToString() == collectDeadDropGUID)); } [Serializable] public class IntroData : SaveData { public int progress; public IntroData(int progress = 0) { this.progress = progress; } } [Serializable] public class OrderData : SaveData { public string? productID; public int amount; public int price; public GameDateTime expiryDateTime; public ProductDefinition? Product => ((IEnumerable<ProductDefinition>)ProductManager.DiscoveredProducts).FirstOrDefault((Func<ProductDefinition, bool>)((ProductDefinition product) => ((ItemDefinition)product).ID == productID)); } internal class QuestBickyOrder : SOEQuest { [SaveableField("Order")] public OrderData? orderData; [SaveableField("DeadDrop")] public DeadDropData? deadDropData; private QuestEntry DeliveryQuestEntry => ((Quest)this).Entries[0]; private QuestEntry CollectionQuestEntry => ((Quest)this).Entries[1]; public QuestBickyOrder() { ((Quest)this).title = "Bicky Needs Product!"; ((Quest)this).Description = "Deliver Bicky his product."; } protected override void Awake() { base.Awake(); if (orderData == null) { orderData = new OrderData(); } if (deadDropData == null) { deadDropData = new DeadDropData(); } AddEntry(); AddEntry(); } protected override void Start() { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Expected O, but got Unknown if (orderData == null || deadDropData == null) { throw new Exception("Missing data for quest load."); } ((Quest)this).Description = $"Deliver Bicky his product and he'll drop you <color=#00CC00>${orderData.price:N0}</color> off."; DeliveryQuestEntry.SetEntryTitle($"Drop off {orderData.amount}x <color=#3399FF>{((ItemDefinition)(orderData.Product?)).Name}</color> at the dead drop."); CollectionQuestEntry.SetEntryTitle($"Pick up <color=#00CC00>${orderData.price:N0}</color> at the dead drop."); if ((Object)(object)deadDropData.DeliveryDeadDrop != (Object)null) { DeliveryQuestEntry.SetPoILocation(((Component)deadDropData.DeliveryDeadDrop).transform.position); deadDropData.DeliveryDeadDrop.Storage.onClosed.AddListener(new UnityAction(TryForDelivery)); } if ((Object)(object)deadDropData.CollectDeadDrop != (Object)null) { CollectionQuestEntry.SetPoILocation(((Component)deadDropData.CollectDeadDrop).transform.position); deadDropData.CollectDeadDrop.Storage.onOpened.AddListener(new UnityAction(TryForCollection)); } base.Start(); } public void Initialize(OrderData pendingOrderData) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) orderData = pendingOrderData; ((Quest)this).ConfigureExpiry(true, orderData.expiryDateTime); deadDropData = new DeadDropData { deliverDeadDropGUID = DeadDrop.DeadDrops[Random.Range(0, DeadDrop.DeadDrops.Count)].GUID.ToString(), collectDeadDropGUID = DeadDrop.DeadDrops[Random.Range(0, DeadDrop.DeadDrops.Count)].GUID.ToString() }; } private void TryForDelivery() { //IL_00ca: Unknown result type (might be due to invalid IL or missing references) if (orderData == null || deadDropData == null || (Object)(object)deadDropData.DeliveryDeadDrop == (Object)null) { throw new Exception("No dead drop data available!"); } List<ItemSlot> list = deadDropData.DeliveryDeadDrop.Storage.ItemSlots.Where(delegate(ItemSlot slot) { ItemInstance itemInstance = slot.ItemInstance; ProductItemInstance val = (ProductItemInstance)(object)((itemInstance is ProductItemInstance) ? itemInstance : null); return val != null && Object.op_Implicit((Object)(object)val.AppliedPackaging) && (Object)(object)slot.ItemInstance.Definition == (Object)(object)orderData.Product; }).ToList(); int num = list.Sum((ItemSlot slot) => slot.Quantity * ((ProductItemInstance)slot.ItemInstance).AppliedPackaging.Quantity); if (num != orderData.amount) { return; } int num2 = orderData.amount; foreach (ItemSlot item in list) { int quantity = ((ProductItemInstance)item.ItemInstance).AppliedPackaging.Quantity; int num3 = Mathf.Min(item.Quantity * quantity, num2); item.ChangeQuantity(-(num3 / quantity), false); num2 -= num3; } DeliveryQuestEntry.Complete(); CollectionQuestEntry.SetState((EQuestState)1, true); } private void TryForCollection() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown if (orderData == null || deadDropData == null || (Object)(object)deadDropData.CollectDeadDrop == (Object)null) { throw new Exception("No collection dead drop in QuestBulkOrder!"); } CashInstance val = (CashInstance)((ItemInstance)PlayerSingleton<PlayerInventory>.Instance.cashInstance).GetCopy(-1); val.SetBalance((float)orderData.price, false); if (deadDropData.CollectDeadDrop.Storage.CanItemFit((ItemInstance)(object)val, 1)) { deadDropData.CollectDeadDrop.Storage.InsertItem((ItemInstance)(object)val, true); CollectionQuestEntry.Complete(); } } } } namespace ScheduleOneEnhanced.API { [AttributeUsage(AttributeTargets.Field)] public class SaveableField : Attribute { public string fileName { get; } public SaveableField(string fileName) { this.fileName = fileName; } } } namespace ScheduleOneEnhanced.API.Utils { public static class ReflectionUtils { public static List<Type> GetDerivedClasses<TBaseClass>() { List<Type> list = new List<Type>(); Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); Assembly[] array = assemblies; foreach (Assembly assembly in array) { list.AddRange(from type in assembly.GetTypes() where typeof(TBaseClass).IsAssignableFrom(type) && type != typeof(TBaseClass) && !type.IsAbstract select type); } return list; } public static Type? GetTypeByName(string typeName) { string typeName2 = typeName; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); Assembly[] array = assemblies; foreach (Assembly assembly in array) { Type type2 = assembly.GetTypes().FirstOrDefault((Type type) => type.Name == typeName2); if (!(type2 == null)) { return type2; } } return null; } } } namespace ScheduleOneEnhanced.API.Quests { [HarmonyPatch] public class QuestManagerPatch { private static readonly List<string> _writtenQuests = new List<string>(); [HarmonyPatch(typeof(QuestManager), "WriteData")] [HarmonyPostfix] public static void WriteData(QuestManager __instance, string parentFolderPath, ref List<string> __result) { //IL_00e7: Unknown result type (might be due to invalid IL or missing references) string path = Path.Combine(parentFolderPath, "Quests"); _writtenQuests.Clear(); foreach (Quest quest in Quest.Quests) { _writtenQuests.Add(quest.SaveFolderName); if (!(quest is SOEQuest sOEQuest)) { continue; } string path2 = Path.Combine(path, ((Quest)sOEQuest).SaveFolderName); if (!Directory.Exists(path2)) { Directory.CreateDirectory(path2); } WriteData(path2, "SOEQuest", ((SaveData)sOEQuest.soeQuestData).GetJson(true)); Type type = ((object)sOEQuest).GetType(); FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { SaveableField customAttribute = fieldInfo.GetCustomAttribute<SaveableField>(); if (customAttribute != null) { WriteData(path2, customAttribute.fileName, ((SaveData)fieldInfo.GetValue(sOEQuest)).GetJson(true)); } } } } public static void WriteData(string path, string fileName, string json) { string path2 = (fileName.EndsWith(".json") ? fileName : (fileName + ".json")); try { string path3 = Path.Combine(path, path2); File.WriteAllText(path3, json); } catch (Exception ex) { MelonLogger.Msg((object)ex); } } [HarmonyPatch(typeof(QuestManager), "DeleteUnapprovedFiles")] [HarmonyPostfix] public static void DeleteUnapprovedFiles(QuestManager __instance, string parentFolderPath) { string path = Path.Combine(parentFolderPath, "Quests"); string[] array = (from directory in Directory.GetDirectories(path) where directory.StartsWith("Quest_") && !_writtenQuests.Contains(directory) select directory).ToArray(); string[] array2 = array; foreach (string path2 in array2) { Directory.Delete(path2, recursive: true); } } } [HarmonyPatch] public class QuestsLoaderPatch { [HarmonyPatch(typeof(QuestsLoader), "Load")] [HarmonyPrefix] public static void QuestsLoaderLoad(QuestsLoader __instance, string mainPath) { //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Expected O, but got Unknown string[] array = (from directory in Directory.GetDirectories(mainPath).Select(Path.GetFileName) where directory.StartsWith("Quest_") select directory).ToArray(); string[] array2 = array; string text2 = default(string); string text4 = default(string); string text6 = default(string); foreach (string path in array2) { string text = Path.Combine(mainPath, path); ((Loader)__instance).TryLoadFile(text, ref text2, true); if (text2 == null) { continue; } QuestData val = JsonUtility.FromJson<QuestData>(text2); string path2 = Path.Combine(mainPath, path); string text3 = Path.Combine(path2, "SOEQuest"); if (!((Loader)__instance).TryLoadFile(text3, ref text4, true)) { continue; } SOEQuestData sOEQuestData = JsonUtility.FromJson<SOEQuestData>(text4); if (sOEQuestData?.questType == null) { continue; } Type typeByName = ReflectionUtils.GetTypeByName(sOEQuestData.questType); if (typeByName == null || !typeof(SOEQuest).IsAssignableFrom(typeByName)) { continue; } GameObject val2 = new GameObject(typeByName.Name); val2.SetActive(false); SOEQuest sOEQuest = (SOEQuest)(object)val2.AddComponent(typeByName); ((Quest)sOEQuest).StaticGUID = val.GUID; FieldInfo[] fields = typeByName.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo[] array3 = fields; foreach (FieldInfo fieldInfo in array3) { SaveableField customAttribute = fieldInfo.GetCustomAttribute<SaveableField>(); if (customAttribute != null) { string text5 = Path.Combine(path2, customAttribute.fileName); if (((Loader)__instance).TryLoadFile(text5, ref text6, true)) { fieldInfo.SetValue(sOEQuest, JsonUtility.FromJson(text6, fieldInfo.FieldType)); } } } val2.SetActive(true); } } } public class SOEQuest : Quest { [SaveableField("SOEQuest")] public SOEQuestData soeQuestData; private void InitializeIcon() { base.IconPrefab = CreateIconPrefab().GetComponent<RectTransform>(); } private void InitializePoI() { base.PoIPrefab = CreatePoIPrefab(); } public SOEQuest() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown base.onActiveState = new UnityEvent(); base.onComplete = new UnityEvent(); base.onInitialComplete = new UnityEvent(); base.onQuestBegin = new UnityEvent(); base.onQuestEnd = new UnityEvent<EQuestState>(); base.onTrackChange = new UnityEvent<bool>(); base.TrackOnBegin = true; base.AutoCompleteOnAllEntriesComplete = true; base.autoInitialize = false; } private GameObject CreateIconPrefab() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown GameObject val = new GameObject("IconPrefab", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); val.transform.SetParent(((Component)this).transform); Image component = val.GetComponent<Image>(); component.sprite = ((App<ContactsApp>)(object)PlayerSingleton<ContactsApp>.Instance).AppIcon; return val; } private GameObject CreatePoIPrefab() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown GameObject val = new GameObject("POIPrefab"); val.SetActive(false); val.transform.SetParent(((Component)this).transform); POI val2 = val.AddComponent<POI>(); val2.DefaultMainText = "Did it work?"; FieldInfo fieldInfo = AccessTools.Field(typeof(POI), "UIPrefab"); fieldInfo.SetValue(val2, CreatePoIUIPrefab()); return val; } private GameObject CreatePoIUIPrefab() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown //IL_0118: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("PoIUIPrefab", new Type[4] { typeof(RectTransform), typeof(CanvasRenderer), typeof(EventTrigger), typeof(Button) }); val.transform.SetParent(((Component)this).transform); GameObject val2 = new GameObject("MainLabel", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Text) }); val2.transform.SetParent(val.transform); GameObject val3 = new GameObject("IconContainer", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); val3.transform.SetParent(val.transform); Image component = val3.GetComponent<Image>(); component.sprite = ((App<ContactsApp>)(object)PlayerSingleton<ContactsApp>.Instance).AppIcon; RectTransform component2 = ((Component)component).GetComponent<RectTransform>(); component2.sizeDelta = new Vector2(20f, 20f); return val; } public void AddEntry() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown GameObject val = new GameObject("QuestEntry"); val.SetActive(false); val.transform.SetParent(((Component)this).transform); QuestEntry val2 = val.AddComponent<QuestEntry>(); val2.PoILocation = val.transform; val.SetActive(true); base.Entries.Add(val2); } protected override void Awake() { soeQuestData = new SOEQuestData { questType = ((object)this).GetType().Name }; InitializeIcon(); InitializePoI(); ((Quest)this).Awake(); ((Quest)this).InitializeQuest(((Quest)this).Title, base.Description, Array.Empty<QuestEntryData>(), base.StaticGUID); } protected override void Start() { ((Quest)this).Start(); ((Quest)this).Begin(true); } public override void End() { ((Quest)this).End(); Quest.Quests.Remove((Quest)(object)this); } } [Serializable] public class SOEQuestData : SaveData { public string? questType; } } namespace ScheduleOneEnhanced.API.NPCs { [HarmonyPatch] public class NPCsLoaderPatch { [HarmonyPatch(typeof(NPCsLoader), "Load")] [HarmonyPostfix] public static void NPCsLoadersLoad(NPCsLoader __instance) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) List<Type> derivedClasses = ReflectionUtils.GetDerivedClasses<SOENPC>(); foreach (Type item in derivedClasses) { new GameObject(item.Name, new Type[1] { item }); } } } public class SOENPC : NPC { public SOENPC() { base.FirstName = "Custom"; base.LastName = "NPC"; base.BakedGUID = Guid.NewGuid().ToString(); base.MugshotSprite = ((App<ContactsApp>)(object)PlayerSingleton<ContactsApp>.Instance).AppIcon; base.ConversationCategories = new List<EConversationCategory> { (EConversationCategory)0 }; } public override void Awake() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Expected O, but got Unknown //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Expected O, but got Unknown //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Expected O, but got Unknown ((Component)this).gameObject.SetActive(false); ((NPC)this).CreateMessageConversation(); base.Health = ((Component)this).gameObject.GetComponent<NPCHealth>(); base.Health.onDie = new UnityEvent(); base.Health.onKnockedOut = new UnityEvent(); GameObject val = new GameObject("NPCAwareness"); val.SetActive(false); val.transform.SetParent(((Component)this).transform); base.awareness = val.AddComponent<NPCAwareness>(); base.awareness.onExplosionHeard = new UnityEvent<NoiseEvent>(); base.awareness.onGunshotHeard = new UnityEvent<NoiseEvent>(); base.awareness.onHitByCar = new UnityEvent<LandVehicle>(); base.awareness.onNoticedDrugDealing = new UnityEvent<Player>(); base.awareness.onNoticedGeneralCrime = new UnityEvent<Player>(); base.awareness.onNoticedPettyCrime = new UnityEvent<Player>(); base.awareness.onNoticedPlayerViolatingCurfew = new UnityEvent<Player>(); base.awareness.onNoticedSuspiciousPlayer = new UnityEvent<Player>(); base.awareness.Listener = ((Component)this).gameObject.AddComponent<Listener>(); GameObject val2 = new GameObject("NPCResponses"); val2.SetActive(false); val2.transform.SetParent(((Component)this).transform); base.awareness.Responses = (NPCResponses)(object)val2.AddComponent<NPCResponses_Civilian>(); GameObject val3 = new GameObject("VisionCone"); val3.SetActive(false); val3.transform.SetParent(((Component)this).transform); VisionCone visionCone = val3.AddComponent<VisionCone>(); base.awareness.VisionCone = visionCone; base.awareness.VisionCone.QuestionMarkPopup = ((Component)this).gameObject.AddComponent<WorldspacePopup>(); base.intObj = ((Component)this).gameObject.AddComponent<InteractableObject>(); base.RelationData = new NPCRelationData(); NPCRelationData relationData = base.RelationData; relationData.onUnlocked = (Action<EUnlockType, bool>)Delegate.Combine(relationData.onUnlocked, (Action<EUnlockType, bool>)delegate { if (!string.IsNullOrEmpty(base.NPCUnlockedVariable)) { NetworkSingleton<VariableDatabase>.Instance.SetVariableValue(base.NPCUnlockedVariable, true.ToString(), true); } }); NPCInventory val4 = ((Component)this).gameObject.AddComponent<NPCInventory>(); val4.PickpocketIntObj = ((Component)this).gameObject.AddComponent<InteractableObject>(); base.Avatar = Player.Local.Avatar; NPCManager.NPCRegistry.Add((NPC)(object)this); ((Component)this).gameObject.SetActive(true); val3.SetActive(true); val2.SetActive(true); val.SetActive(true); ((NPC)this).Awake(); } public override void Load(NPCData data, string containerPath) { ((NPC)this).Load(data, containerPath); Type type = ((object)this).GetType(); FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { SaveableField customAttribute = fieldInfo.GetCustomAttribute<SaveableField>(); if (customAttribute == null) { continue; } MelonLogger.Msg("Loading field " + fieldInfo.Name); string text = (customAttribute.fileName.EndsWith(".json") ? customAttribute.fileName : (customAttribute.fileName + ".json")); string path = Path.Combine(containerPath, text); if (File.Exists(path)) { MelonLogger.Msg("reading json for field " + fieldInfo.Name); string text2 = File.ReadAllText(path); Type fieldType = fieldInfo.FieldType; try { fieldInfo.SetValue(this, JsonUtility.FromJson(text2, fieldType)); } catch (Exception) { MelonLogger.Msg($"Failed to read `{text}` for `{fieldType}`."); throw; } } } } public override List<string> WriteData(string parentFolderPath) { //IL_00e4: Unknown result type (might be due to invalid IL or missing references) List<string> list = ((NPC)this).WriteData(parentFolderPath); Type type = ((object)this).GetType(); FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { SaveableField customAttribute = fieldInfo.GetCustomAttribute<SaveableField>(); if (customAttribute == null) { continue; } object value = fieldInfo.GetValue(this); if (!(value is SaveData)) { continue; } string text = (customAttribute.fileName.EndsWith(".json") ? customAttribute.fileName : (customAttribute.fileName + ".json")); if (fieldInfo.GetValue(this) == null) { string path = Path.Combine(parentFolderPath, text); if (File.Exists(path)) { File.Delete(path); } continue; } try { list.Add(text); ((ISaveable)this).WriteSubfile(parentFolderPath, customAttribute.fileName, ((SaveData)fieldInfo.GetValue(this)).GetJson(true)); } catch (Exception ex) { MelonLogger.Msg((object)ex); } } return list; } protected override bool ShouldSaveHealth() { return false; } } }