Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of RentIsDue v1.0.0
plugins/RentIsDue.dll
Decompiled 2 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using Il2CppScheduleOne.Building.Doors; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.Doors; using Il2CppScheduleOne.Money; using MelonLoader; using S1API.GameTime; using S1API.Property; 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(RentIsDueMod), "RentIsDue", "1.0.0", "Cfynx", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: AssemblyTitle("RentIsDue")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("RentIsDue")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("00c9f89e-cdc3-480f-ab0a-134911f3fd3d")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] public class RentIsDueMod : MelonMod { private bool assignedListener = false; public bool modEnabled = true; private bool hasInitializedInstances = false; public int weekCounter = 0; public const float MOTEL_ROOM_RENT = 75f; public const float SWEAT_SHOP_RENT = 800f; public const float STORAGE_RENT = 200f; public const int MONTHLY_RENT_INTERVAL = 4; public bool hasMotelRoomRentEligibility = false; public bool hasSweatShopRentEligibility = false; public bool hasStorageRentEligibility = false; private bool motelRoomAccessBlocked = false; private bool sweatShopAccessBlocked = false; private bool storageUnitAccessBlocked = false; private int weeksWithoutMotelRoomPayment = 0; private int weeksWithoutSweatShopPayment = 0; private int weeksWithoutStoragePayment = 0; private HashSet<string> lastKnownProperties = new HashSet<string>(); public string gameobjectPathMotelRoomDoor = "@Properties/MotelRoom/MotelRoom/Classical Wooden door/Container/"; public string gameobjectPathSweatShopDoor = "@Properties/Sweatshop/Contents/Classical Wooden door/Container/"; public string gameobjectPathStorageUnitDoor = "Property Contents/Storage unit/Industrial Metal Door (2)/Container/"; private GameObject motelDoorObject; private GameObject sweatshopDoorObject; private GameObject storageDoorObject; private PropertyDoorController doorController; private PropertyDoorController doorController1; private PropertyDoorController doorController2; public override void OnInitializeMelon() { ((MelonBase)this).LoggerInstance.Msg("Individual Property Rent System - Mod Initialized"); ((MelonBase)this).LoggerInstance.Msg($"Motel Room: ${75f} every Monday"); ((MelonBase)this).LoggerInstance.Msg($"Sweatshop: ${800f} every 4th Monday"); ((MelonBase)this).LoggerInstance.Msg($"Storage Unit: ${200f} every 4th Monday"); ((MelonBase)this).LoggerInstance.Msg($"Monthly rent interval: {4} weeks"); ((MelonBase)this).LoggerInstance.Msg($"Maximum combined rent (4th Monday): ${1075f}"); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { if (!(sceneName == "Main")) { return; } assignedListener = false; hasInitializedInstances = false; hasMotelRoomRentEligibility = false; hasSweatShopRentEligibility = false; hasStorageRentEligibility = false; weekCounter = 0; lastKnownProperties.Clear(); motelRoomAccessBlocked = false; sweatShopAccessBlocked = false; storageUnitAccessBlocked = false; weeksWithoutMotelRoomPayment = 0; weeksWithoutSweatShopPayment = 0; weeksWithoutStoragePayment = 0; ((MelonBase)this).LoggerInstance.Msg("Main scene loaded - resetting mod state"); motelDoorObject = GameObject.Find(gameobjectPathMotelRoomDoor); if ((Object)(object)motelDoorObject != (Object)null) { ((MelonBase)this).LoggerInstance.Msg("Door object found! Searching for PropertyDoorController..."); doorController = motelDoorObject.GetComponent<PropertyDoorController>(); if ((Object)(object)doorController == (Object)null) { doorController = motelDoorObject.GetComponentInChildren<PropertyDoorController>(); } if ((Object)(object)doorController == (Object)null && (Object)(object)motelDoorObject.transform.parent != (Object)null) { doorController = ((Component)motelDoorObject.transform.parent).GetComponent<PropertyDoorController>(); } if ((Object)(object)doorController != (Object)null) { ((MelonBase)this).LoggerInstance.Msg("PropertyDoorController found on: " + ((Object)((Component)doorController).gameObject).name); ((MelonBase)this).LoggerInstance.Msg("Door controller ready for toggling!"); } else { ((MelonBase)this).LoggerInstance.Warning("PropertyDoorController component not found!"); } } else { ((MelonBase)this).LoggerInstance.Warning("Door object not found at specified path!"); } sweatshopDoorObject = GameObject.Find(gameobjectPathSweatShopDoor); if ((Object)(object)sweatshopDoorObject != (Object)null) { ((MelonBase)this).LoggerInstance.Msg("Door object found! Searching for PropertyDoorController..."); doorController1 = sweatshopDoorObject.GetComponent<PropertyDoorController>(); if ((Object)(object)doorController1 == (Object)null) { doorController1 = sweatshopDoorObject.GetComponentInChildren<PropertyDoorController>(); } if ((Object)(object)doorController1 == (Object)null && (Object)(object)sweatshopDoorObject.transform.parent != (Object)null) { doorController1 = ((Component)sweatshopDoorObject.transform.parent).GetComponent<PropertyDoorController>(); } if ((Object)(object)doorController1 != (Object)null) { ((MelonBase)this).LoggerInstance.Msg("PropertyDoorController found on: " + ((Object)((Component)doorController).gameObject).name); ((MelonBase)this).LoggerInstance.Msg("Door controller ready for toggling!"); } else { ((MelonBase)this).LoggerInstance.Warning("PropertyDoorController component not found!"); } } else { ((MelonBase)this).LoggerInstance.Warning("Door object not found at specified path!"); } storageDoorObject = GameObject.Find(gameobjectPathStorageUnitDoor); if ((Object)(object)storageDoorObject != (Object)null) { ((MelonBase)this).LoggerInstance.Msg("Door object found! Searching for PropertyDoorController..."); doorController2 = storageDoorObject.GetComponent<PropertyDoorController>(); if ((Object)(object)doorController2 == (Object)null) { doorController2 = storageDoorObject.GetComponentInChildren<PropertyDoorController>(); } if ((Object)(object)doorController2 == (Object)null && (Object)(object)storageDoorObject.transform.parent != (Object)null) { doorController2 = ((Component)storageDoorObject.transform.parent).GetComponent<PropertyDoorController>(); } if ((Object)(object)doorController2 != (Object)null) { ((MelonBase)this).LoggerInstance.Msg("PropertyDoorController found on: " + ((Object)((Component)doorController).gameObject).name); ((MelonBase)this).LoggerInstance.Msg("Door controller ready for toggling!"); } else { ((MelonBase)this).LoggerInstance.Warning("PropertyDoorController component not found!"); } } else { ((MelonBase)this).LoggerInstance.Warning("Door object not found at specified path!"); } } private void ToggleDoorAccess() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 if ((Object)(object)doorController != (Object)null) { if ((int)((DoorController)doorController).PlayerAccess == 1) { ((DoorController)doorController).PlayerAccess = (EDoorAccess)0; ((MelonBase)this).LoggerInstance.Msg("Door access set to: OPEN"); } else { ((DoorController)doorController).PlayerAccess = (EDoorAccess)1; ((MelonBase)this).LoggerInstance.Msg("Door access set to: LOCKED"); } } else { ((MelonBase)this).LoggerInstance.Warning("PropertyDoorController not available for toggling!"); } } private void ToggleDoorAccess1() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 if ((Object)(object)doorController1 != (Object)null) { if ((int)((DoorController)doorController1).PlayerAccess == 1) { ((DoorController)doorController1).PlayerAccess = (EDoorAccess)0; ((MelonBase)this).LoggerInstance.Msg("Door access set to: OPEN"); } else { ((DoorController)doorController1).PlayerAccess = (EDoorAccess)1; ((MelonBase)this).LoggerInstance.Msg("Door access set to: LOCKED"); } } else { ((MelonBase)this).LoggerInstance.Warning("PropertyDoorController not available for toggling!"); } } private void ToggleDoorAccess2() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 if ((Object)(object)doorController2 != (Object)null) { if ((int)((DoorController)doorController2).PlayerAccess == 1) { ((DoorController)doorController2).PlayerAccess = (EDoorAccess)0; ((MelonBase)this).LoggerInstance.Msg("Door access set to: OPEN"); } else { ((DoorController)doorController2).PlayerAccess = (EDoorAccess)1; ((MelonBase)this).LoggerInstance.Msg("Door access set to: LOCKED"); } } else { ((MelonBase)this).LoggerInstance.Warning("PropertyDoorController not available for toggling!"); } } public override void OnUpdate() { if (Input.GetKeyDown((KeyCode)282)) { modEnabled = !modEnabled; ((MelonBase)this).LoggerInstance.Msg("Rent mod " + (modEnabled ? "enabled" : "disabled")); } if (Input.GetKeyDown((KeyCode)281)) { ((MelonBase)this).LoggerInstance.Msg("=== MANUAL MOTEL ROOM RENT TEST ==="); ((MelonBase)this).LoggerInstance.Msg(string.Format("Motel Room owned: {0}", DoesPlayerOwnProperty("Motel Room"))); ((MelonBase)this).LoggerInstance.Msg($"Motel Room eligibility: {hasMotelRoomRentEligibility}"); if (NetworkSingleton<MoneyManager>.InstanceExists) { try { float cashBalance = NetworkSingleton<MoneyManager>.Instance.cashBalance; ((MelonBase)this).LoggerInstance.Msg($"Current balance: ${cashBalance}"); ((MelonBase)this).LoggerInstance.Msg($"Required: ${75f}"); ((MelonBase)this).LoggerInstance.Msg($"Can afford: {cashBalance >= 75f}"); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error("Error checking balance: " + ex.Message); } } ((MelonBase)this).LoggerInstance.Msg("Attempting manual payment..."); PayMotelRoomRent(); ((MelonBase)this).LoggerInstance.Msg("=== END MANUAL TEST ==="); } if (Input.GetKeyDown((KeyCode)280)) { ((MelonBase)this).LoggerInstance.Msg("=== MANUAL SweatShop RENT TEST ==="); ((MelonBase)this).LoggerInstance.Msg(string.Format("SweatShop owned: {0}", DoesPlayerOwnProperty("SweatShop"))); ((MelonBase)this).LoggerInstance.Msg($"SweatShop eligibility: {hasSweatShopRentEligibility}"); if (NetworkSingleton<MoneyManager>.InstanceExists) { try { float cashBalance2 = NetworkSingleton<MoneyManager>.Instance.cashBalance; ((MelonBase)this).LoggerInstance.Msg($"Current balance: ${cashBalance2}"); ((MelonBase)this).LoggerInstance.Msg($"Required: ${800f}"); ((MelonBase)this).LoggerInstance.Msg($"Can afford: {cashBalance2 >= 800f}"); } catch (Exception ex2) { ((MelonBase)this).LoggerInstance.Error("Error checking balance: " + ex2.Message); } } ((MelonBase)this).LoggerInstance.Msg("Attempting manual payment..."); PaySweatShopRent(); ((MelonBase)this).LoggerInstance.Msg("=== END MANUAL TEST ==="); } if (Input.GetKeyDown((KeyCode)277)) { ((MelonBase)this).LoggerInstance.Msg("=== MANUAL STORAGE UNIT RENT TEST ==="); ((MelonBase)this).LoggerInstance.Msg(string.Format("Storage Unit owned: {0}", DoesPlayerOwnProperty("Storage Unit"))); ((MelonBase)this).LoggerInstance.Msg($"Storage Unit eligibility: {hasStorageRentEligibility}"); if (NetworkSingleton<MoneyManager>.InstanceExists) { try { float cashBalance3 = NetworkSingleton<MoneyManager>.Instance.cashBalance; ((MelonBase)this).LoggerInstance.Msg($"Current balance: ${cashBalance3}"); ((MelonBase)this).LoggerInstance.Msg($"Required: ${200f}"); ((MelonBase)this).LoggerInstance.Msg($"Can afford: {cashBalance3 >= 200f}"); } catch (Exception ex3) { ((MelonBase)this).LoggerInstance.Error("Error checking balance: " + ex3.Message); } } ((MelonBase)this).LoggerInstance.Msg("Attempting manual payment..."); PayStorageRent(); ((MelonBase)this).LoggerInstance.Msg("=== END MANUAL TEST ==="); } if (Input.GetKeyDown((KeyCode)291)) { ((MelonBase)this).LoggerInstance.Msg("=== FORCING MOTEL ROOM RENT ELIGIBILITY ==="); if (DoesPlayerOwnProperty("Motel Room")) { hasMotelRoomRentEligibility = true; ((MelonBase)this).LoggerInstance.Msg("Motel Room rent eligibility FORCED to true"); ((MelonBase)this).LoggerInstance.Msg("Now try manual payment with Page Down"); } else { ((MelonBase)this).LoggerInstance.Msg("Cannot force eligibility - Motel Room not owned"); } } if (Input.GetKeyDown((KeyCode)278)) { ((MelonBase)this).LoggerInstance.Msg($"Current week: {weekCounter + 1} | Next monthly rent in: {4 - weekCounter % 4} weeks"); CheckAllRentEligibilityStatus(); CheckPropertyAccessStatus(); } if (Input.GetKeyDown((KeyCode)127)) { CheckAndLogOwnedProperties(); } if (Input.GetKeyDown((KeyCode)279)) { ListAllProperties(); } if (!modEnabled) { return; } if (!hasInitializedInstances) { if (!TryInitializeInstances()) { return; } hasInitializedInstances = true; ((MelonBase)this).LoggerInstance.Msg("Successfully initialized manager instances"); CheckAndLogOwnedProperties(); } if (Time.frameCount % 120 == 0) { CheckAllRentEligibility(); } if (Time.frameCount % 180 == 0) { CheckForPropertyChanges(); } } private void CheckAllRentEligibilityStatus() { ((MelonBase)this).LoggerInstance.Msg("=== INDIVIDUAL RENT ELIGIBILITY CHECK ==="); bool flag = DoesPlayerOwnProperty("Motel Room"); ((MelonBase)this).LoggerInstance.Msg($"Motel Room owned: {flag} | Rent eligibility: {hasMotelRoomRentEligibility}"); bool flag2 = DoesPlayerOwnProperty("Sweatshop"); ((MelonBase)this).LoggerInstance.Msg($"Sweatshop owned: {flag2} | Rent eligibility: {hasSweatShopRentEligibility}"); bool flag3 = DoesPlayerOwnProperty("Storage Unit"); ((MelonBase)this).LoggerInstance.Msg($"Storage Unit owned: {flag3} | Rent eligibility: {hasStorageRentEligibility}"); if (NetworkSingleton<MoneyManager>.InstanceExists) { try { float cashBalance = NetworkSingleton<MoneyManager>.Instance.cashBalance; ((MelonBase)this).LoggerInstance.Msg($"Current balance: ${cashBalance}"); ((MelonBase)this).LoggerInstance.Msg($"Can pay Motel Room (${75f}): {cashBalance >= 75f}"); ((MelonBase)this).LoggerInstance.Msg($"Can pay Sweatshop (${800f}): {cashBalance >= 800f}"); ((MelonBase)this).LoggerInstance.Msg($"Can pay Storage Unit (${200f}): {cashBalance >= 200f}"); ((MelonBase)this).LoggerInstance.Msg($"Can pay combined (${1075f}): {cashBalance >= 1075f}"); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error("Error checking balance: " + ex.Message); } } ((MelonBase)this).LoggerInstance.Msg("=== END INDIVIDUAL RENT ELIGIBILITY ==="); } private void CheckPropertyAccessStatus() { ((MelonBase)this).LoggerInstance.Msg("=== PROPERTY ACCESS STATUS ==="); if (motelRoomAccessBlocked) { ((MelonBase)this).LoggerInstance.Msg($"\ud83d\udeab MOTEL ROOM ACCESS BLOCKED - Weeks without payment: {weeksWithoutMotelRoomPayment}"); ((MelonBase)this).LoggerInstance.Msg($" Pay ${75f} to restore access"); } else if (DoesPlayerOwnProperty("Motel Room")) { ((MelonBase)this).LoggerInstance.Msg("✅ Motel Room access: AVAILABLE"); } if (sweatShopAccessBlocked) { ((MelonBase)this).LoggerInstance.Msg($"\ud83d\udeab SWEATSHOP ACCESS BLOCKED - Weeks without payment: {weeksWithoutSweatShopPayment}"); ((MelonBase)this).LoggerInstance.Msg($" Pay ${800f} to restore access"); } else if (DoesPlayerOwnProperty("Sweatshop")) { ((MelonBase)this).LoggerInstance.Msg("✅ Sweatshop access: AVAILABLE"); } if (storageUnitAccessBlocked) { ((MelonBase)this).LoggerInstance.Msg($"\ud83d\udeab STORAGE UNIT ACCESS BLOCKED - Weeks without payment: {weeksWithoutStoragePayment}"); ((MelonBase)this).LoggerInstance.Msg($" Pay ${200f} to restore access"); } else if (DoesPlayerOwnProperty("Storage Unit")) { ((MelonBase)this).LoggerInstance.Msg("✅ Storage Unit access: AVAILABLE"); } ((MelonBase)this).LoggerInstance.Msg("=== END PROPERTY ACCESS STATUS ==="); } private void CheckAndLogOwnedProperties() { try { ((MelonBase)this).LoggerInstance.Msg("=== CHECKING OWNED PROPERTIES ==="); List<PropertyWrapper> ownedProperties = PropertyManager.GetOwnedProperties(); if (ownedProperties == null) { ((MelonBase)this).LoggerInstance.Msg("PropertyManager.GetOwnedProperties() returned null"); return; } ((MelonBase)this).LoggerInstance.Msg($"Total owned properties: {ownedProperties.Count}"); if (ownedProperties.Count == 0) { ((MelonBase)this).LoggerInstance.Msg("Player owns no properties"); return; } for (int i = 0; i < ownedProperties.Count; i++) { PropertyWrapper val = ownedProperties[i]; if (val != null) { ((MelonBase)this).LoggerInstance.Msg($"Property {i + 1}:"); ((MelonBase)this).LoggerInstance.Msg(" Name: " + (((BaseProperty)val).PropertyName ?? "NULL")); ((MelonBase)this).LoggerInstance.Msg(" Code: " + (((BaseProperty)val).PropertyCode ?? "NULL")); ((MelonBase)this).LoggerInstance.Msg($" Price: ${((BaseProperty)val).Price}"); ((MelonBase)this).LoggerInstance.Msg($" Employee Capacity: {((BaseProperty)val).EmployeeCapacity}"); ((MelonBase)this).LoggerInstance.Msg($" Is Owned: {((BaseProperty)val).IsOwned}"); } else { ((MelonBase)this).LoggerInstance.Msg($"Property {i + 1}: NULL"); } } ((MelonBase)this).LoggerInstance.Msg("=== END OWNED PROPERTIES ==="); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error("Error checking owned properties: " + ex.Message); ((MelonBase)this).LoggerInstance.Error("Stack trace: " + ex.StackTrace); } } private void ListAllProperties() { try { ((MelonBase)this).LoggerInstance.Msg("=== LISTING ALL PROPERTIES ==="); List<PropertyWrapper> allProperties = PropertyManager.GetAllProperties(); if (allProperties == null) { ((MelonBase)this).LoggerInstance.Msg("PropertyManager.GetAllProperties() returned null"); return; } ((MelonBase)this).LoggerInstance.Msg($"Total properties in game: {allProperties.Count}"); foreach (PropertyWrapper item in allProperties) { if (item != null) { string text = (((BaseProperty)item).IsOwned ? "[OWNED]" : "[NOT OWNED]"); ((MelonBase)this).LoggerInstance.Msg($"{text} {((BaseProperty)item).PropertyName} - ${((BaseProperty)item).Price} (Code: {((BaseProperty)item).PropertyCode})"); } } ((MelonBase)this).LoggerInstance.Msg("=== END ALL PROPERTIES ==="); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error("Error listing all properties: " + ex.Message); } } private void CheckForPropertyChanges() { try { List<PropertyWrapper> ownedProperties = PropertyManager.GetOwnedProperties(); if (ownedProperties == null) { return; } HashSet<string> hashSet = new HashSet<string>(); foreach (PropertyWrapper item in ownedProperties) { if (item != null && !string.IsNullOrEmpty(((BaseProperty)item).PropertyCode)) { hashSet.Add(((BaseProperty)item).PropertyCode); } } foreach (string propertyCode in hashSet) { if (lastKnownProperties.Contains(propertyCode)) { continue; } PropertyWrapper val = ownedProperties.Find((PropertyWrapper p) => ((p != null) ? ((BaseProperty)p).PropertyCode : null) == propertyCode); if (val != null) { ((MelonBase)this).LoggerInstance.Msg($"\ud83c\udfe0 NEW PROPERTY ACQUIRED: {((BaseProperty)val).PropertyName} (${((BaseProperty)val).Price})"); if (((BaseProperty)val).PropertyName == "Motel Room") { ((MelonBase)this).LoggerInstance.Msg("\ud83d\udcdd Motel Room acquired - weekly rent of $75 will now apply"); } else if (((BaseProperty)val).PropertyName == "Sweatshop") { ((MelonBase)this).LoggerInstance.Msg("\ud83d\udcdd Sweatshop acquired - monthly rent of $800 will now apply"); } else if (((BaseProperty)val).PropertyName == "Storage Unit") { ((MelonBase)this).LoggerInstance.Msg("\ud83d\udcdd Storage Unit acquired - monthly rent of $200 will now apply"); } } } foreach (string lastKnownProperty in lastKnownProperties) { if (!hashSet.Contains(lastKnownProperty)) { ((MelonBase)this).LoggerInstance.Msg("\ud83c\udfe0 PROPERTY SOLD: " + lastKnownProperty); } } lastKnownProperties = hashSet; } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error("Error checking for property changes: " + ex.Message); } } private bool TryInitializeInstances() { if (!NetworkSingleton<MoneyManager>.InstanceExists) { return false; } try { MoneyManager instance = NetworkSingleton<MoneyManager>.Instance; if ((Object)(object)instance == (Object)null) { return false; } float cashBalance = instance.cashBalance; } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Msg("MoneyManager not fully initialized yet: " + ex.Message); return false; } if (!assignedListener) { try { TimeManager.OnWeekPass = (Action)Delegate.Combine(TimeManager.OnWeekPass, new Action(OnWeekPass)); assignedListener = true; ((MelonBase)this).LoggerInstance.Msg("Successfully registered for OnWeekPass event"); } catch (Exception ex2) { ((MelonBase)this).LoggerInstance.Error("Failed to register OnWeekPass event: " + ex2.Message); return false; } } return true; } public bool DoesPlayerOwnProperty(string propertyName) { try { List<PropertyWrapper> ownedProperties = PropertyManager.GetOwnedProperties(); if (ownedProperties == null) { return false; } foreach (PropertyWrapper item in ownedProperties) { if (item != null && ((BaseProperty)item).PropertyName == propertyName) { return true; } } return false; } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error("Error checking if player owns " + propertyName + ": " + ex.Message); return false; } } private void CheckAllRentEligibility() { try { if (!NetworkSingleton<MoneyManager>.InstanceExists) { return; } MoneyManager instance = NetworkSingleton<MoneyManager>.Instance; if (!((Object)(object)instance == (Object)null)) { float cashBalance; try { cashBalance = instance.cashBalance; } catch (NullReferenceException) { return; } CheckIndividualRentEligibility("Motel Room", 75f, cashBalance, ref hasMotelRoomRentEligibility); CheckIndividualRentEligibility("Sweatshop", 800f, cashBalance, ref hasSweatShopRentEligibility); CheckIndividualRentEligibility("Storage Unit", 200f, cashBalance, ref hasStorageRentEligibility); } } catch (Exception ex2) { ((MelonBase)this).LoggerInstance.Error("Error checking all rent eligibility: " + ex2.Message); } } private void CheckIndividualRentEligibility(string propertyName, float rentAmount, float currentBalance, ref bool hasRentEligibility) { bool flag = DoesPlayerOwnProperty(propertyName); if (!flag & hasRentEligibility) { ((MelonBase)this).LoggerInstance.Msg(propertyName + " no longer owned - removing rent eligibility"); hasRentEligibility = false; } else if (flag && !hasRentEligibility && currentBalance >= rentAmount) { hasRentEligibility = true; ((MelonBase)this).LoggerInstance.Msg($"✅ ELIGIBILITY GRANTED: Player now qualifies for {propertyName} rent payment (Balance: ${currentBalance}, Required: ${rentAmount})"); } } private bool IsMonthlyRentWeek() { return (weekCounter + 1) % 4 == 0; } private void OnWeekPass() { if (!modEnabled) { ((MelonBase)this).LoggerInstance.Msg("Week passed but mod is disabled"); return; } weekCounter++; ((MelonBase)this).LoggerInstance.Msg($"Week {weekCounter} has passed (Monday start)"); ((MelonBase)this).LoggerInstance.Msg("Property status at week start:"); CheckAndLogOwnedProperties(); if (IsMonthlyRentWeek()) { ((MelonBase)this).LoggerInstance.Msg($"Monthly rent week (Week {weekCounter}) - checking combined rent payment"); float num = 0f; List<string> list = new List<string>(); bool flag = false; if (DoesPlayerOwnProperty("Motel Room")) { num += 75f; list.Add($"Motel Room (${75f})"); } if (DoesPlayerOwnProperty("Sweatshop")) { num += 800f; list.Add($"Sweatshop (${800f})"); } if (DoesPlayerOwnProperty("Storage Unit")) { num += 200f; list.Add($"Storage Unit (${200f})"); } if (num > 0f) { ((MelonBase)this).LoggerInstance.Msg($"Combined rent total: ${num}"); ((MelonBase)this).LoggerInstance.Msg("Properties included: " + string.Join(", ", list)); flag = TryPayCombinedRent(num, list); } else { ((MelonBase)this).LoggerInstance.Msg("No rent-eligible properties owned - no monthly rent charged"); flag = true; } HandleMissedPayments(flag, isMonthlyRentWeek: true); } else { bool flag2 = false; if (DoesPlayerOwnProperty("Motel Room")) { ((MelonBase)this).LoggerInstance.Msg($"Monday Week {weekCounter} - attempting Motel Room rent payment (${75f})"); flag2 = TryPayMotelRoomRent(); } else { ((MelonBase)this).LoggerInstance.Msg("Motel Room not owned - no weekly rent charged"); flag2 = true; } HandleMissedPayments(flag2, isMonthlyRentWeek: false); } } public void PayCombinedRent(float totalRentAmount, List<string> propertiesOwed) { ((MelonBase)this).LoggerInstance.Msg("=== ATTEMPTING COMBINED RENT PAYMENT (4th Monday) ==="); if (!modEnabled || !NetworkSingleton<MoneyManager>.InstanceExists) { ((MelonBase)this).LoggerInstance.Msg("Cannot pay combined rent - mod disabled or MoneyManager not available"); return; } try { MoneyManager instance = NetworkSingleton<MoneyManager>.Instance; if ((Object)(object)instance == (Object)null) { ((MelonBase)this).LoggerInstance.Error("MoneyManager instance is null"); return; } float cashBalance; try { cashBalance = instance.cashBalance; } catch (NullReferenceException ex) { ((MelonBase)this).LoggerInstance.Error("MoneyManager cashInstance not ready yet: " + ex.Message); return; } ((MelonBase)this).LoggerInstance.Msg($"Current Balance: ${cashBalance}"); ((MelonBase)this).LoggerInstance.Msg($"Total Rent Amount: ${totalRentAmount}"); ((MelonBase)this).LoggerInstance.Msg("Properties: " + string.Join(", ", propertiesOwed)); ((MelonBase)this).LoggerInstance.Msg($"Can Afford: {cashBalance >= totalRentAmount}"); if (cashBalance >= totalRentAmount) { instance.ChangeCashBalance(0f - totalRentAmount, true, false); ((MelonBase)this).LoggerInstance.Msg($"\ud83d\udcb0 COMBINED RENT PAID! ${totalRentAmount} deducted. New balance: ${instance.cashBalance}"); ((MelonBase)this).LoggerInstance.Msg("Properties paid for: " + string.Join(", ", propertiesOwed)); foreach (string item in propertiesOwed) { if (item.Contains("Motel Room")) { hasMotelRoomRentEligibility = false; } if (item.Contains("Sweatshop")) { hasSweatShopRentEligibility = false; } if (item.Contains("Storage Unit")) { hasStorageRentEligibility = false; } } } else { ((MelonBase)this).LoggerInstance.Msg($"❌ INSUFFICIENT FUNDS for combined rent. Need ${totalRentAmount}, have ${cashBalance}"); ((MelonBase)this).LoggerInstance.Msg("Combined rent not paid - player still owes rent for next opportunity"); } } catch (Exception ex2) { ((MelonBase)this).LoggerInstance.Error("Error in PayCombinedRent: " + ex2.Message); } ((MelonBase)this).LoggerInstance.Msg("=== END COMBINED RENT PAYMENT ==="); } private bool TryPayCombinedRent(float totalRentAmount, List<string> propertiesOwed) { if (!modEnabled || !NetworkSingleton<MoneyManager>.InstanceExists) { ((MelonBase)this).LoggerInstance.Msg("Cannot pay combined rent - mod disabled or MoneyManager not available"); return false; } try { MoneyManager instance = NetworkSingleton<MoneyManager>.Instance; if ((Object)(object)instance == (Object)null) { return false; } float cashBalance; try { cashBalance = instance.cashBalance; } catch (NullReferenceException) { return false; } if (cashBalance >= totalRentAmount) { instance.ChangeCashBalance(0f - totalRentAmount, true, false); ((MelonBase)this).LoggerInstance.Msg($"\ud83d\udcb0 COMBINED RENT PAID! ${totalRentAmount} deducted. New balance: ${instance.cashBalance}"); foreach (string item in propertiesOwed) { if (item.Contains("Motel Room")) { hasMotelRoomRentEligibility = false; } if (item.Contains("Sweatshop")) { hasSweatShopRentEligibility = false; } if (item.Contains("Storage Unit")) { hasStorageRentEligibility = false; } } return true; } ((MelonBase)this).LoggerInstance.Msg($"❌ INSUFFICIENT FUNDS for combined rent. Need ${totalRentAmount}, have ${cashBalance}"); return false; } catch (Exception ex2) { ((MelonBase)this).LoggerInstance.Error("Error in TryPayCombinedRent: " + ex2.Message); return false; } } private bool TryPayMotelRoomRent() { if (!modEnabled || !NetworkSingleton<MoneyManager>.InstanceExists) { return false; } if (!DoesPlayerOwnProperty("Motel Room")) { return false; } try { MoneyManager instance = NetworkSingleton<MoneyManager>.Instance; if ((Object)(object)instance == (Object)null) { return false; } float cashBalance; try { cashBalance = instance.cashBalance; } catch (NullReferenceException) { return false; } if (cashBalance >= 75f) { instance.ChangeCashBalance(-75f, true, false); ((MelonBase)this).LoggerInstance.Msg($"\ud83d\udcb0 Motel Room rent paid successfully! ${75f} deducted. New balance: ${instance.cashBalance}"); hasMotelRoomRentEligibility = false; return true; } ((MelonBase)this).LoggerInstance.Msg($"❌ Insufficient funds for Motel Room rent. Balance: ${cashBalance}, Rent: ${75f}"); return false; } catch (Exception ex2) { ((MelonBase)this).LoggerInstance.Error("Error in TryPayMotelRoomRent: " + ex2.Message); return false; } } private void HandleMissedPayments(bool rentPaid, bool isMonthlyRentWeek) { if (DoesPlayerOwnProperty("Motel Room")) { if (rentPaid) { if (motelRoomAccessBlocked) { motelRoomAccessBlocked = false; weeksWithoutMotelRoomPayment = 0; ((MelonBase)this).LoggerInstance.Msg("✅ MOTEL ROOM ACCESS RESTORED - Rent payment received!"); ToggleDoorAccess(); } } else { weeksWithoutMotelRoomPayment++; if (!motelRoomAccessBlocked) { motelRoomAccessBlocked = true; ((MelonBase)this).LoggerInstance.Msg("\ud83d\udeab MOTEL ROOM ACCESS BLOCKED - Rent not paid!"); ((MelonBase)this).LoggerInstance.Msg($" Property access suspended until ${75f} rent is paid"); ToggleDoorAccess(); } else { ((MelonBase)this).LoggerInstance.Msg($"\ud83d\udeab MOTEL ROOM ACCESS REMAINS BLOCKED - {weeksWithoutMotelRoomPayment} weeks without payment"); } } } if (!isMonthlyRentWeek) { return; } if (DoesPlayerOwnProperty("Sweatshop")) { if (rentPaid) { if (sweatShopAccessBlocked) { sweatShopAccessBlocked = false; weeksWithoutSweatShopPayment = 0; ((MelonBase)this).LoggerInstance.Msg("✅ SWEATSHOP ACCESS RESTORED - Monthly rent payment received!"); ToggleDoorAccess1(); } } else { weeksWithoutSweatShopPayment += 4; if (!sweatShopAccessBlocked) { sweatShopAccessBlocked = true; ((MelonBase)this).LoggerInstance.Msg("\ud83d\udeab SWEATSHOP ACCESS BLOCKED - Monthly rent not paid!"); ((MelonBase)this).LoggerInstance.Msg($" Property access suspended until ${800f} rent is paid"); ToggleDoorAccess1(); } else { ((MelonBase)this).LoggerInstance.Msg($"\ud83d\udeab SWEATSHOP ACCESS REMAINS BLOCKED - {weeksWithoutSweatShopPayment} weeks without payment"); } } } if (!DoesPlayerOwnProperty("Storage Unit")) { return; } if (rentPaid) { if (storageUnitAccessBlocked) { storageUnitAccessBlocked = false; weeksWithoutStoragePayment = 0; ((MelonBase)this).LoggerInstance.Msg("✅ STORAGE UNIT ACCESS RESTORED - Monthly rent payment received!"); ToggleDoorAccess2(); } return; } weeksWithoutStoragePayment += 4; if (!storageUnitAccessBlocked) { storageUnitAccessBlocked = true; ((MelonBase)this).LoggerInstance.Msg("\ud83d\udeab STORAGE UNIT ACCESS BLOCKED - Monthly rent not paid!"); ((MelonBase)this).LoggerInstance.Msg($" Property access suspended until ${200f} rent is paid"); ToggleDoorAccess2(); } else { ((MelonBase)this).LoggerInstance.Msg($"\ud83d\udeab STORAGE UNIT ACCESS REMAINS BLOCKED - {weeksWithoutStoragePayment} weeks without payment"); } } public bool HasPropertyAccess(string propertyName) { if (!DoesPlayerOwnProperty(propertyName)) { return false; } return propertyName switch { "Motel Room" => !motelRoomAccessBlocked, "Sweatshop" => !sweatShopAccessBlocked, "Storage Unit" => !storageUnitAccessBlocked, _ => true, }; } private void PayMotelRoomRent() { PayIndividualRent("Motel Room", 75f, ref hasMotelRoomRentEligibility); ToggleDoorAccess(); } private void PaySweatShopRent() { PayIndividualRent("Sweatshop", 800f, ref hasSweatShopRentEligibility); ToggleDoorAccess1(); } private void PayStorageRent() { PayIndividualRent("Storage Unit", 200f, ref hasStorageRentEligibility); ToggleDoorAccess2(); } private void PayIndividualRent(string propertyName, float rentAmount, ref bool hasRentEligibility) { ((MelonBase)this).LoggerInstance.Msg("=== ATTEMPTING " + propertyName.ToUpper() + " RENT PAYMENT ==="); if (!modEnabled || !NetworkSingleton<MoneyManager>.InstanceExists) { ((MelonBase)this).LoggerInstance.Msg("Cannot pay " + propertyName + " rent - mod disabled or MoneyManager not available"); return; } bool flag = DoesPlayerOwnProperty(propertyName); ((MelonBase)this).LoggerInstance.Msg($"Player owns {propertyName}: {flag}"); if (!flag) { ((MelonBase)this).LoggerInstance.Msg("Cannot charge " + propertyName + " rent - property not owned"); return; } try { MoneyManager instance = NetworkSingleton<MoneyManager>.Instance; if ((Object)(object)instance == (Object)null) { ((MelonBase)this).LoggerInstance.Error("MoneyManager instance is null"); return; } float cashBalance; try { cashBalance = instance.cashBalance; } catch (NullReferenceException ex) { ((MelonBase)this).LoggerInstance.Error("MoneyManager cashInstance not ready yet: " + ex.Message); return; } ((MelonBase)this).LoggerInstance.Msg($"Current Balance: ${cashBalance}"); ((MelonBase)this).LoggerInstance.Msg($"Rent Amount: ${rentAmount}"); ((MelonBase)this).LoggerInstance.Msg($"Has Eligibility: {hasRentEligibility}"); ((MelonBase)this).LoggerInstance.Msg($"Can Afford: {cashBalance >= rentAmount}"); if (flag && cashBalance >= rentAmount) { instance.ChangeCashBalance(0f - rentAmount, true, false); ((MelonBase)this).LoggerInstance.Msg($"\ud83d\udcb0 {propertyName} rent paid successfully! ${rentAmount} deducted. New balance: ${instance.cashBalance}"); hasRentEligibility = false; } else if (cashBalance < rentAmount) { ((MelonBase)this).LoggerInstance.Msg($"❌ Insufficient funds for {propertyName} rent. Balance: ${cashBalance}, Rent: ${rentAmount}"); } else { ((MelonBase)this).LoggerInstance.Msg("❌ Cannot charge " + propertyName + " rent - property not owned or other issue"); } } catch (Exception ex2) { ((MelonBase)this).LoggerInstance.Error("Error in Pay" + propertyName + "Rent: " + ex2.Message); } ((MelonBase)this).LoggerInstance.Msg("=== END " + propertyName.ToUpper() + " RENT PAYMENT ==="); } }