Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate-beta"
Decompiled source of RepairRV v1.0.1
RVRepairVan.dll
Decompiled 2 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using HarmonyLib; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using RVRepairVan; using ScheduleOne.DevUtilities; using ScheduleOne.Dialogue; using ScheduleOne.Money; using ScheduleOne.Persistence; using ScheduleOne.Property; using ScheduleOne.VoiceOver; using TMPro; using UnityEngine; using UnityEngine.Events; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(Core), "RVRepairVan", "1.0.0", "DooDesch", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("RVRepairVan")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("RVRepairVan")] [assembly: AssemblyTitle("RVRepairVan")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace RVRepairVan { public class Core : MelonMod { public static MelonPreferences_Entry<float> repairPrice; public static Core Instance { get; private set; } public static Instance Logger { get; private set; } public float RepairPrice => repairPrice.Value; public override void OnInitializeMelon() { Instance = this; repairPrice = MelonPreferences.CreateEntry<float>("Settings", "Repair Price", 1500f, "The price to repair the RV.", (string)null, false, false, (ValueValidator)null); if (repairPrice.Value < 0f) { Logger.Msg("Repair price cannot be negative. Setting to default value of 1500."); repairPrice.Value = 1500f; } Logger = ((MelonBase)this).LoggerInstance; Logger.Msg("RVRepairVan Initialized."); } } public class RVManager : MonoBehaviour { private RV rv; public void Init(RV rvInstance) { rv = rvInstance; LoadState(); Start(); } private void Start() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if ((Object)(object)Singleton<LoadManager>.Instance != (Object)null) { Singleton<LoadManager>.Instance.onLoadComplete.AddListener(new UnityAction(OnLoadComplete)); } } private void OnLoadComplete() { Core.Logger.Msg("Load complete!"); LoadState(selfCall: true); } private void OnDestroy() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if ((Object)(object)Singleton<LoadManager>.Instance != (Object)null) { Singleton<LoadManager>.Instance.onLoadComplete.RemoveListener(new UnityAction(OnLoadComplete)); } } public bool IsVanDestroyed() { Transform val = ((Component)this).transform.Find("Destroyed RV"); if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf) { return true; } return false; } private bool IsVanOwned() { return Property.OwnedProperties.Contains((Property)(object)rv); } private bool IsVanUnowned() { return Property.UnownedProperties.Contains((Property)(object)rv); } private void SetVanOwned() { if (IsVanOwned()) { Core.Logger.Msg("RV is already owned."); return; } Property.OwnedProperties.Add((Property)(object)rv); Property.UnownedProperties.Remove((Property)(object)rv); if ((Object)(object)((Property)rv).ForSaleSign != (Object)null && ((Property)rv).ForSaleSign.activeSelf) { ((Property)rv).ForSaleSign.SetActive(false); } Core.Logger.Msg("RV is now owned."); } private void SetVanUnowned() { if (!IsVanOwned()) { Core.Logger.Msg("RV is already unowned."); return; } Property.UnownedProperties.Add((Property)(object)rv); Property.OwnedProperties.Remove((Property)(object)rv); if ((Object)(object)((Property)rv).ForSaleSign != (Object)null && !((Property)rv).ForSaleSign.activeSelf) { ((Property)rv).ForSaleSign.SetActive(true); ((TMP_Text)((Component)((Property)rv).ForSaleSign.transform.Find("Price")).GetComponent<TextMeshPro>()).text = MoneyManager.FormatAmount(10000f, false, false); } Core.Logger.Msg("RV is now unowned."); } public void RepairVan() { Core.Logger.Msg("Repairing RV..."); SetVanOwned(); if (!IsVanDestroyed()) { Core.Logger.Msg("RV is not destroyed, no repair needed."); return; } FieldInfo field = typeof(RV).GetField("<_isExploded>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { field.SetValue(rv, false); } else { Core.Logger.Msg("_isExploded field not found, cannot set to false."); } Transform val = ((Component)this).transform.Find("RV"); Transform val2 = ((Component)this).transform.Find("Destroyed RV"); Transform val3 = null; if ((Object)(object)val2 != (Object)null) { val3 = val2.Find("CartelNote"); } if ((Object)(object)val != (Object)null && !((Component)val).gameObject.activeSelf) { ((Component)val).gameObject.SetActive(true); } if ((Object)(object)val2 != (Object)null && ((Component)val2).gameObject.activeSelf) { ((Component)val2).gameObject.SetActive(false); } if ((Object)(object)val3 != (Object)null && ((Component)val3).gameObject.activeSelf) { ((Component)val3).gameObject.SetActive(false); if ((Object)(object)val != (Object)null) { val3.SetParent(val); } } if ((Object)(object)rv.FXContainer != (Object)null && !((Component)rv.FXContainer).gameObject.activeSelf) { ((Component)rv.FXContainer).gameObject.SetActive(true); } Core.Logger.Msg("RV was repaired."); } public void SaveState(bool setDefaultSettings = false) { RVStateData rVStateData = new RVStateData(); if (setDefaultSettings) { rVStateData.isDestroyed = true; rVStateData.isOwned = false; } else { rVStateData.isDestroyed = IsVanDestroyed(); rVStateData.isOwned = IsVanOwned(); } string contents = JsonUtility.ToJson((object)rVStateData, true); string path = Path.Combine(Application.persistentDataPath, "rv_state.json"); File.WriteAllText(path, contents); } public void LoadState(bool selfCall = false) { Core.Logger.Msg("Loading RV state..."); string text = Path.Combine(Application.persistentDataPath, "rv_state.json"); if (File.Exists(text)) { string text2 = File.ReadAllText(text); RVStateData rVStateData = JsonUtility.FromJson<RVStateData>(text2); if (!rVStateData.isDestroyed) { RepairVan(); } if (rVStateData.isOwned) { SetVanOwned(); } else { SetVanUnowned(); } Core.Logger.Msg("RV state loaded."); } else { SaveState(setDefaultSettings: true); if (!selfCall) { LoadState(selfCall: true); } Core.Logger.Msg("RV state file not found at: " + text); } } } [Serializable] public class RVStateData { public bool isDestroyed; public bool isOwned; } } namespace RVRepairVan.Patches { [HarmonyPatch(typeof(DialogueController_Ming))] public class DialogueController_Ming_Patch : DialogueController { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ShouldShowCheck <>9__2_0; internal bool <StartPostfix>b__2_0(bool enabled) { return RV_Patch.Instance.IsVanDestroyed(); } } public static float RepairPrice = Core.Instance.RepairPrice; public static DialogueChoice RepairVanChoice; [HarmonyPostfix] [HarmonyPatch("Start")] public static void StartPostfix(DialogueController_Ming __instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown DialogueChoice val = new DialogueChoice(); val.ChoiceText = "Can you repair my Van?"; val.Conversation = CreateVanRepairDialogue(); val.Enabled = true; object obj = <>c.<>9__2_0; if (obj == null) { ShouldShowCheck val2 = (bool enabled) => RV_Patch.Instance.IsVanDestroyed(); <>c.<>9__2_0 = val2; obj = (object)val2; } val.shouldShowCheck = (ShouldShowCheck)obj; RepairVanChoice = val; ((DialogueController)__instance).AddDialogueChoice(val, 10); } public static DialogueContainer CreateVanRepairDialogue() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0069: 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_0076: 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) //IL_0081: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown DialogueContainer val = ScriptableObject.CreateInstance<DialogueContainer>(); val.NodeLinks = new List<NodeLinkData>(); val.DialogueNodeData = new List<DialogueNodeData>(); val.BranchNodeData = new List<BranchNodeData>(); DialogueNodeData val2 = new DialogueNodeData(); val2.Guid = Guid.NewGuid().ToString(); val2.DialogueNodeLabel = "ENTRY"; val2.DialogueText = "Alright, I'll repair your van. It will cost you a fee, but you'll be back on the road in no time!"; val2.Position = new Vector2(100f, 100f); val2.VoiceLine = (EVOLineType)10; DialogueChoiceData val3 = new DialogueChoiceData(); val3.Guid = Guid.NewGuid().ToString(); val3.ChoiceLabel = "CHOICE_REPAIR_VAN"; val3.ChoiceText = $"Yes ({RepairPrice}$)"; DialogueChoiceData val4 = new DialogueChoiceData(); val4.Guid = Guid.NewGuid().ToString(); val4.ChoiceText = "Maybe later"; val2.choices = new List<DialogueChoiceData> { val3, val4 }.ToArray(); val.DialogueNodeData.Add(val2); return val; } } [HarmonyPatch(typeof(DialogueController_Ming), "ChoiceCallback")] public class DialogueController_Ming_ChoiceCallback_Patch { public static void Postfix(DialogueController_Ming __instance, string choiceLabel) { if (!(choiceLabel == "CHOICE_REPAIR_VAN")) { return; } MoneyManager instance = NetworkSingleton<MoneyManager>.Instance; if (instance.cashBalance >= DialogueController_Ming_Patch.RepairPrice) { instance.ChangeCashBalance(0f - DialogueController_Ming_Patch.RepairPrice, true, true); if ((Object)(object)RV_Patch.Instance != (Object)null) { RV_Patch.Instance.RepairVan(); } else { Core.Logger.Msg("RVRepairer instance not found!"); } } else { Core.Logger.Msg("Not enough cash."); } } } [HarmonyPatch(typeof(RV))] public class RV_Patch { public static RVManager Instance; [HarmonyPostfix] [HarmonyPatch("Awake")] public static void AwakePostfix(RV __instance) { RVManager rVManager = ((Component)__instance).gameObject.GetComponent<RVManager>(); if ((Object)(object)rVManager == (Object)null) { rVManager = ((Component)__instance).gameObject.AddComponent<RVManager>(); rVManager.Init(__instance); } Instance = rVManager; } [HarmonyPostfix] [HarmonyPatch("OnSpawnServer")] public static void StartPostfix(RV __instance) { Instance.LoadState(); } } [HarmonyPatch(typeof(SaveManager), "Save", new Type[] { })] public class SaveManager_Patch { [HarmonyPostfix] public static void SavePostfix() { Core.Logger.Msg("SavePostfix called!"); RV_Patch.Instance.SaveState(); } } }