Decompiled source of OverTheCounter v2.0.10

OverTheCounter.Il2Cpp.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using HarmonyLib;
using Il2Cpp;
using Il2CppEPOOutline;
using Il2CppFishNet;
using Il2CppFishNet.Component.Ownership;
using Il2CppFishNet.Connection;
using Il2CppFishNet.Managing;
using Il2CppFishNet.Managing.Object;
using Il2CppFishNet.Object;
using Il2CppFishNet.Observing;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppScheduleOne;
using Il2CppScheduleOne.Audio;
using Il2CppScheduleOne.AvatarFramework;
using Il2CppScheduleOne.AvatarFramework.Animation;
using Il2CppScheduleOne.AvatarFramework.Equipping;
using Il2CppScheduleOne.AvatarFramework.Impostors;
using Il2CppScheduleOne.Building;
using Il2CppScheduleOne.Cartel;
using Il2CppScheduleOne.Combat;
using Il2CppScheduleOne.Core.Items.Framework;
using Il2CppScheduleOne.DevUtilities;
using Il2CppScheduleOne.Dialogue;
using Il2CppScheduleOne.Doors;
using Il2CppScheduleOne.Economy;
using Il2CppScheduleOne.Effects;
using Il2CppScheduleOne.Employees;
using Il2CppScheduleOne.EntityFramework;
using Il2CppScheduleOne.GameTime;
using Il2CppScheduleOne.Graffiti;
using Il2CppScheduleOne.Interaction;
using Il2CppScheduleOne.ItemFramework;
using Il2CppScheduleOne.Law;
using Il2CppScheduleOne.Levelling;
using Il2CppScheduleOne.Lighting;
using Il2CppScheduleOne.Management;
using Il2CppScheduleOne.Map;
using Il2CppScheduleOne.Messaging;
using Il2CppScheduleOne.Money;
using Il2CppScheduleOne.NPCs;
using Il2CppScheduleOne.NPCs.Behaviour;
using Il2CppScheduleOne.NPCs.Relation;
using Il2CppScheduleOne.Networking;
using Il2CppScheduleOne.ObjectScripts;
using Il2CppScheduleOne.ObjectScripts.Cash;
using Il2CppScheduleOne.Persistence;
using Il2CppScheduleOne.Persistence.Datas;
using Il2CppScheduleOne.PlayerScripts;
using Il2CppScheduleOne.PlayerScripts.Health;
using Il2CppScheduleOne.Police;
using Il2CppScheduleOne.Product;
using Il2CppScheduleOne.Product.Packaging;
using Il2CppScheduleOne.Property;
using Il2CppScheduleOne.Quests;
using Il2CppScheduleOne.StationFramework;
using Il2CppScheduleOne.Storage;
using Il2CppScheduleOne.Tiles;
using Il2CppScheduleOne.Tools;
using Il2CppScheduleOne.UI;
using Il2CppScheduleOne.UI.Compass;
using Il2CppScheduleOne.UI.Handover;
using Il2CppScheduleOne.UI.Items;
using Il2CppScheduleOne.UI.Management;
using Il2CppScheduleOne.UI.Phone;
using Il2CppScheduleOne.UI.Phone.ContactsApp;
using Il2CppScheduleOne.UI.Phone.Map;
using Il2CppScheduleOne.UI.Phone.ProductManagerApp;
using Il2CppScheduleOne.UI.Relations;
using Il2CppScheduleOne.UI.Shop;
using Il2CppScheduleOne.Variables;
using Il2CppScheduleOne.Vehicles;
using Il2CppScheduleOne.VoiceOver;
using Il2CppScheduleOne.Weather;
using Il2CppSteamworks;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using Il2CppTMPro;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using MeshVault;
using Microsoft.CodeAnalysis;
using OverTheCounter;
using OverTheCounter.Apps;
using OverTheCounter.Logic;
using OverTheCounter.Logic.Placement;
using OverTheCounter.NPCs;
using OverTheCounter.Patches;
using OverTheCounter.Quests;
using OverTheCounter.SaveData;
using OverTheCounter.UI;
using OverTheCounter.Utilities;
using S1API.Entities;
using S1API.Entities.Appearances.AccessoryFields;
using S1API.Entities.Appearances.BodyLayerFields;
using S1API.Entities.Appearances.CustomizationFields;
using S1API.Entities.Appearances.FaceLayerFields;
using S1API.Entities.Dialogue;
using S1API.Entities.Schedule;
using S1API.GameTime;
using S1API.Internal.Abstraction;
using S1API.Items;
using S1API.Leveling;
using S1API.Messaging;
using S1API.Misc;
using S1API.Money;
using S1API.PhoneApp;
using S1API.Products;
using S1API.Quests;
using S1API.Saveables;
using S1API.Shops;
using S1API.UI;
using S1API.Utils;
using S1MAPI.Building;
using S1MAPI.Building.Components;
using S1MAPI.Building.Config;
using S1MAPI.Building.Structural;
using S1MAPI.Core;
using S1MAPI.Gltf;
using S1MAPI.ProceduralMesh;
using S1MAPI.S1;
using S1MAPI.Utils;
using SteamNetworkLib;
using SteamNetworkLib.Models;
using SteamNetworkLib.Sync;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "OverTheCounter", "2.0.10", "hdlmrell", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: MelonOptionalDependencies(new string[] { "SteamNetworkLib" })]
[assembly: HarmonyDontPatchAll]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("OverTheCounter.Il2Cpp")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+6b7caa4bc824a2bf8fc9dcdc200bf94491a1a140")]
[assembly: AssemblyProduct("OverTheCounter.Il2Cpp")]
[assembly: AssemblyTitle("OverTheCounter.Il2Cpp")]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace OverTheCounter
{
	internal static class PrivateAccess
	{
		public static VODatabase GetDatabase(this VOEmitter emitter)
		{
			return emitter.Database;
		}

		public static CustomerData GetCustData(this Customer customer)
		{
			return customer.customerData;
		}

		public static void SetCustData(this Customer customer, CustomerData data)
		{
			customer.customerData = data;
		}

		public static string GetTitle(this Quest quest)
		{
			return quest.title;
		}

		public static void SetTitle(this Quest quest, string value)
		{
			quest.title = value;
		}

		public static DialogueHandler GetHandler(this DialogueController dc)
		{
			return dc.handler;
		}

		public static ConfigurableTypePanel[] GetConfigPanelPrefabs(this ManagementInterface mi)
		{
			return Il2CppArrayBase<ConfigurableTypePanel>.op_Implicit((Il2CppArrayBase<ConfigurableTypePanel>)(object)mi.ConfigPanelPrefabs);
		}

		public static MSGConversation GetMSGConversation(this NPC npc)
		{
			return npc.MSGConversation;
		}

		public static void SetMSGConversation(this NPC npc, MSGConversation conv)
		{
			npc.MSGConversation = conv;
		}

		public static void SetCurrentBuilding(this NPC npc, NPCEnterableBuilding building)
		{
			npc.CurrentBuilding = building;
		}

		public static void SetTimeSinceLastDealCompleted(this Customer customer, int value)
		{
			customer.TimeSinceLastDealCompleted = value;
		}

		public static void SetTimeSinceLastDealOffered(this Customer customer, int value)
		{
			customer.TimeSinceLastDealOffered = value;
		}

		public static ContractInfo GetOfferedContractInfo(this Customer customer)
		{
			return customer.OfferedContractInfo;
		}

		public static void SetOfferedContractInfo(this Customer customer, ContractInfo info)
		{
			customer.OfferedContractInfo = info;
		}

		public static NPCPoI GetPotentialCustomerPoI(this Customer customer)
		{
			return customer.potentialCustomerPoI;
		}

		public static void SetPotentialCustomerPoI(this Customer customer, NPCPoI poi)
		{
			customer.potentialCustomerPoI = poi;
		}

		public static QuestEntryHUDUI GetEntryUI(this QuestEntry entry)
		{
			return entry.entryUI;
		}

		public static void SetShouldShowCheck(this DialogueChoice choice, Func<bool, bool> func)
		{
			choice.shouldShowCheck = ShouldShowCheck.op_Implicit(func);
		}

		public static ItemSlot[] GetCustomerSlots(this HandoverScreen hs)
		{
			return Il2CppArrayBase<ItemSlot>.op_Implicit((Il2CppArrayBase<ItemSlot>)(object)hs.CustomerSlots);
		}

		public static void TrackItemAsPlayer(this HandoverScreen hs, ItemInstance item)
		{
			hs.OriginalItemLocations[item] = (EItemSource)0;
		}
	}
	public class Core : MelonMod
	{
		private NotificationManager _notificationManager;

		private DesperationManager _desperationManager;

		private DrifterManager _drifterManager;

		private ManagerController _managerManager;

		private CustomerManager _customerManager;

		private bool _multiplayerDepChecked;

		private static bool _meshVaultRegistered;

		private static bool _loadHooked;

		private static bool _budtendersRestored;

		private static UnityAction _onGameLoadedAction;

		private static bool _gameLoadedRan;

		internal static string OtcIconDir { get; private set; }

		public override void OnInitializeMelon()
		{
			DependencyChecker.RunChecks();
			if (DependencyChecker.HasMissingDeps)
			{
				((MelonBase)this).LoggerInstance.Warning("Missing dependencies — mod features disabled. Check the main menu for details.");
			}
			else
			{
				OnInitializeMelonImpl();
			}
		}

		private void OnInitializeMelonImpl()
		{
			Config.Initialize();
			Config.SubscribeToChanges();
			CustomersApp.ApplyHireMeDefaults();
			SafeTypeLoadPatch.Apply(((MelonBase)this).HarmonyInstance);
			foreach (Type validType in MelonUtils.GetValidTypes(typeof(Core).Assembly))
			{
				try
				{
					((MelonBase)this).HarmonyInstance.CreateClassProcessor(validType).Patch();
				}
				catch (Exception ex)
				{
					OTCLog.Error("Patch", "Failed to patch " + validType.FullName + ": " + ex.Message);
				}
			}
			NpcTypeDiscoveryPatch.Apply(((MelonBase)this).HarmonyInstance);
			StackSizePatch.Apply(((MelonBase)this).HarmonyInstance);
			ManagerClipboardPatch.Apply(((MelonBase)this).HarmonyInstance);
			try
			{
				BuildingPlacementPatch.Apply(((MelonBase)this).HarmonyInstance);
			}
			catch (Exception value)
			{
				OTCLog.Error("Patch", $"BuildingPlacementPatch.Apply failed: {value}");
			}
			try
			{
				ConfigReplicatorPatch.Apply(((MelonBase)this).HarmonyInstance);
			}
			catch (Exception value2)
			{
				OTCLog.Error("Patch", $"ConfigReplicatorPatch.Apply failed: {value2}");
			}
			ContactsAppFix.Apply(((MelonBase)this).HarmonyInstance);
			GraffitiPatch.Apply(((MelonBase)this).HarmonyInstance);
			RecipePinPatch.Apply(((MelonBase)this).HarmonyInstance);
			SupplierWarehousePatch.Apply(((MelonBase)this).HarmonyInstance);
			SupplierFleePatch.Apply(((MelonBase)this).HarmonyInstance);
			SaveManagerPatch.Apply(((MelonBase)this).HarmonyInstance);
			GameProfilerPatches.Apply(((MelonBase)this).HarmonyInstance);
			WeatherPatches.Apply(((MelonBase)this).HarmonyInstance);
			CustomerCheckoutInterceptPatch.Apply(((MelonBase)this).HarmonyInstance);
			TimeManager.OnSleepEnd = (Action<int>)Delegate.Combine(TimeManager.OnSleepEnd, new Action<int>(OnSleepEnd));
			TimeManager.OnDayPass = (Action)Delegate.Combine(TimeManager.OnDayPass, new Action(OnDayPass));
			if (!ConfigSyncData.IsNetworkLibAvailable)
			{
				OTCLog.Warning("Network", "SteamNetworkLib not installed — multiplayer sync disabled. Single-player works fine. Install SteamNetworkLib for co-op support.");
			}
			OTCLog.Msg("Patch", "OverTheCounter Initialized.");
			ImmediateQuestWindowConfig.Register();
			MinimapOverlay.Register();
			HUDOverlay.Register();
			StoreAlertOverlay.Register();
			RecipeOverlay.Register();
			ExtractIcons();
			_notificationManager = new NotificationManager();
			_desperationManager = new DesperationManager();
			_drifterManager = new DrifterManager();
			_managerManager = new ManagerController();
			_customerManager = new CustomerManager();
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			if (DependencyChecker.HasMissingDeps)
			{
				if (sceneName == "Menu")
				{
					DependencyChecker.ShowPopup();
				}
			}
			else
			{
				OnSceneWasLoadedImpl(buildIndex, sceneName);
			}
		}

		private void OnSceneWasLoadedImpl(int buildIndex, string sceneName)
		{
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			//IL_0119: 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_012a: Expected O, but got Unknown
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Expected O, but got Unknown
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Expected O, but got Unknown
			StaticSaveData.ResetInstance();
			StaticThreadSaveData.ResetInstance();
			PropertySaveData.ResetInstance();
			PricingSaveData.ResetInstance();
			VicSaveData.ResetInstance();
			BellaSaveData.ResetInstance();
			StaticIntroQuest.ResetInstance();
			StaticUpgrade1Quest.ResetInstance();
			StaticUpgrade2Quest.ResetInstance();
			VicIntroQuest.ResetInstance();
			BellaProtocolQuest.ResetInstance();
			StorefrontGrowthQuest.ResetInstance();
			StorefrontExpansionQuest.ResetInstance();
			BellaSummonPatch.Reset();
			try
			{
				(typeof(Saveable).Assembly.GetType("S1API.Saveables.SaveableAutoRegistry")?.GetMethod("ClearCache", BindingFlags.Static | BindingFlags.NonPublic))?.Invoke(null, null);
				OTCLog.Msg("Patch", "Cleared S1API SaveableAutoRegistry cache");
			}
			catch (Exception ex)
			{
				OTCLog.Warning("Patch", "Failed to clear SaveableAutoRegistry: " + ex.Message);
			}
			DrifterInstance.CleanupAll();
			CustomerInstance.CleanupAll();
			DrifterSpawner.ResetCache();
			BudtenderInstance.CleanupAll();
			_budtendersRestored = false;
			ManagerSaveData.ResetInstance();
			ManagerInstance.CleanupAll();
			ManagerSpawner.ResetCache();
			MugshotUtility.ResetSession();
			if (!Object.op_Implicit((Object)(object)GameObject.Find("OTC_MinimapController")))
			{
				GameObject val = new GameObject("OTC_MinimapController");
				val.AddComponent<MinimapOverlay>();
				Object.DontDestroyOnLoad((Object)val);
			}
			if (!Object.op_Implicit((Object)(object)GameObject.Find("OTC_HUDOverlay")))
			{
				GameObject val2 = new GameObject("OTC_HUDOverlay");
				val2.AddComponent<HUDOverlay>();
				Object.DontDestroyOnLoad((Object)val2);
			}
			if (!Object.op_Implicit((Object)(object)GameObject.Find("OTC_RecipeOverlay")))
			{
				GameObject val3 = new GameObject("OTC_RecipeOverlay");
				val3.AddComponent<RecipeOverlay>();
				Object.DontDestroyOnLoad((Object)val3);
			}
			if (!Object.op_Implicit((Object)(object)GameObject.Find("OTC_StoreAlertOverlay")))
			{
				GameObject val4 = new GameObject("OTC_StoreAlertOverlay");
				val4.AddComponent<StoreAlertOverlay>();
				Object.DontDestroyOnLoad((Object)val4);
			}
			WeatherPatches.Cleanup();
			MapBuildingOverlay.Clear();
			CheckoutCounter.Cleanup();
			WestvilleShack.Cleanup();
			Dispensary.Cleanup();
			OTCWarehouse.Cleanup();
			OTCSupplierArea.Cleanup();
			CasinoDeadDrop.Cleanup();
			CheckoutProcess.ResetStatic();
			CustomerSpawnPoints.Cleanup();
			BuildingGridFactory.Cleanup();
			_loadHooked = false;
			_gameLoadedRan = false;
		}

		public override void OnSceneWasInitialized(int buildIndex, string sceneName)
		{
			if (!DependencyChecker.HasMissingDeps)
			{
				OnSceneWasInitializedImpl(buildIndex, sceneName);
			}
		}

		private void OnSceneWasInitializedImpl(int buildIndex, string sceneName)
		{
			if (!(sceneName == "Main"))
			{
				return;
			}
			MeshVaultAPI.Init();
			if (!_meshVaultRegistered)
			{
				bool flag = false;
				bool flag2 = false;
				try
				{
					byte[] array = EmbeddedResourceLoader.LoadBytes("OverTheCounter.Resources.MeshDatabase.json", Assembly.GetExecutingAssembly());
					if (array != null)
					{
						MeshVaultAPI.RegisterMeshes("otc", "OverTheCounter", Encoding.UTF8.GetString(array));
						flag = true;
					}
				}
				catch (Exception ex)
				{
					OTCLog.Warning("Patch", "OTC mesh registration failed: " + ex.Message);
				}
				try
				{
					MeshVaultAPI.RegisterDecals("otc", "OverTheCounter", Assembly.GetExecutingAssembly(), "OverTheCounter.Resources.MeshVaultDecals.");
					flag2 = true;
				}
				catch (Exception ex2)
				{
					OTCLog.Warning("Patch", "OTC decal registration failed: " + ex2.Message);
				}
				_meshVaultRegistered = flag || flag2;
			}
			CheckoutCounter.Register();
			WestvilleShack.SpawnBuilding();
			Dispensary.SpawnBuilding();
			OTCWarehouse.Initialize();
			OTCSupplierArea.Initialize(OTCWarehouse.BuildingTransform);
			HookLoadComplete();
			CheckoutCounter.AddToShop();
		}

		private static void HookLoadComplete()
		{
			if (_loadHooked)
			{
				return;
			}
			try
			{
				if ((Delegate)(object)_onGameLoadedAction == (Delegate)null)
				{
					_onGameLoadedAction = UnityAction.op_Implicit((Action)OnGameLoaded);
				}
				LoadManager instance = Singleton<LoadManager>.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					instance.onLoadComplete.RemoveListener(_onGameLoadedAction);
					instance.onLoadComplete.AddListener(_onGameLoadedAction);
					_loadHooked = true;
					OTCLog.Msg("Patch", "Hooked LoadManager.onLoadComplete");
				}
				else
				{
					OTCLog.Warning("Patch", "LoadManager.Instance is null — cannot hook onLoadComplete");
				}
			}
			catch (Exception ex)
			{
				OTCLog.Error("Patch", "Failed to hook LoadManager.onLoadComplete: " + ex.Message);
			}
		}

		private static void OnGameLoaded()
		{
			if (_gameLoadedRan)
			{
				OTCLog.Warning("Patch", "OnGameLoaded fired more than once this session (stale listener?) — ignoring duplicate.");
				return;
			}
			_gameLoadedRan = true;
			try
			{
				WestvilleShack.ClearTerrain();
				Dispensary.ClearTerrain();
				OTCWarehouse.ClearTerrain();
				WestvilleShack.SpawnNetworkedObjects();
				Dispensary.SpawnNetworkedObjects();
				OTCWarehouse.SpawnNetworkedObjects();
				CheckoutCounter.AddToShop();
				CasinoDeadDrop.Initialize();
				CheckoutProcess.InitP2P();
				CheckoutProcess.RequestSalesLog();
				BuildingGridFactory.SuppressNavigationRebuild = true;
				if (PropertySaveData.Instance != null)
				{
					foreach (KeyValuePair<Grid, OtcGridInfo> item in BuildingGridFactory.GridRegistry)
					{
						PropertySaveData.Instance.RestorePlacedItems(item.Value.BuildingId, item.Key);
					}
				}
				else
				{
					Grid shackGrid = WestvilleShack.ShackGrid;
					if ((Object)(object)shackGrid != (Object)null)
					{
						CheckoutCounter.SpawnOnGrid(shackGrid);
					}
				}
				BuildingGridFactory.SuppressNavigationRebuild = false;
				WestvilleShack.RebuildNavigation();
				Dispensary.RebuildNavigation();
				OTCWarehouse.RebuildNavigation();
				if (!MapBuildingOverlay.PaintBuildings())
				{
					OTCLog.Warning("Patch", "MapBuildingOverlay.PaintBuildings failed — MapApp or MapPositionUtility not ready");
				}
			}
			catch (Exception ex)
			{
				BuildingGridFactory.SuppressNavigationRebuild = false;
				OTCLog.Error("General", "OnGameLoaded restore failed: " + ex.Message + "\n" + ex.StackTrace);
			}
		}

		public override void OnLateUpdate()
		{
			if (!DependencyChecker.HasMissingDeps)
			{
				OnLateUpdateImpl();
			}
		}

		private void OnLateUpdateImpl()
		{
			PerfTracker.BeginFrame();
			try
			{
				PerfTracker.Begin("NetworkInit");
				ConfigSyncData.EnsureNetworkReady();
				PerfTracker.End("NetworkInit");
				PerfTracker.Begin("SyncMessages");
				ConfigSyncData.ProcessMessages();
				PerfTracker.End("SyncMessages");
				if (!_multiplayerDepChecked && !ConfigSyncData.IsNetworkLibAvailable)
				{
					Lobby instance = Singleton<Lobby>.Instance;
					if ((Object)(object)instance != (Object)null && instance.IsInLobby && instance.PlayerCount > 1)
					{
						_multiplayerDepChecked = true;
						DependencyChecker.RunMultiplayerChecks();
						if (DependencyChecker.HasMultiplayerIssues)
						{
							DependencyChecker.ShowMultiplayerPopup();
						}
					}
				}
				PerfTracker.Begin("SaveDataTicks");
				_notificationManager.ProcessContractState();
				VicSaveData.Instance?.Tick();
				StaticSaveData.Instance?.Tick();
				BellaSaveData.Instance?.Tick();
				ManagerSaveData.Instance?.Tick();
				PerfTracker.End("SaveDataTicks");
				PerfTracker.Begin("AdoptionRetries");
				_drifterManager?.RetryPendingAdoptions();
				_customerManager?.RetryPendingAdoptions();
				ManagerInstance.RetryPendingAdoptions();
				PerfTracker.End("AdoptionRetries");
				PerfTracker.Begin("ManagerAI");
				PerfTracker.Begin("ManagerAI.Wages");
				_managerManager?.CheckImmediateWages();
				PerfTracker.End("ManagerAI.Wages");
				PerfTracker.Begin("ManagerAI.EnsureMoving");
				foreach (ManagerInstance value in ManagerInstance.Active.Values)
				{
					value.EnsureMoving();
				}
				PerfTracker.End("ManagerAI.EnsureMoving");
				PerfTracker.Begin("ManagerAI.SupplyDistribution");
				if (NetworkHelper.IsHost)
				{
					foreach (ManagerInstance value2 in ManagerInstance.Active.Values)
					{
						value2.SupplyBehaviour?.Tick();
						value2.DistributionBehaviour?.Tick();
					}
				}
				PerfTracker.End("ManagerAI.SupplyDistribution");
				PerfTracker.End("ManagerAI");
				PerfTracker.Begin("NetworkPublish");
				if (NetworkHelper.IsHost)
				{
					ConfigSyncData.FlushDirtyState();
					if (ManagerInstance.HasPendingMessages)
					{
						ConfigSyncData.Instance?.PublishManagerMessages();
					}
					if (DrifterManager.HasPendingDrifterMessages)
					{
						ConfigSyncData.Instance?.PublishDrifterMessages();
					}
					_customerManager?.PublishIfNeeded();
					if (ManagerInstance.StatePublishNeeded)
					{
						ManagerInstance.StatePublishNeeded = false;
						ConfigSyncData.Instance?.PublishManagerState();
					}
				}
				PerfTracker.End("NetworkPublish");
				PerfTracker.Begin("ClientDoorSetup");
				if (!NetworkHelper.IsHost)
				{
					WestvilleShack.TickClientDoorSetup();
					Dispensary.TickClientDoorSetup();
				}
				PerfTracker.End("ClientDoorSetup");
				if (!_budtendersRestored && NetworkHelper.IsHost && CheckoutCounter.AllCounters.Count > 0 && PropertySaveData.Instance != null)
				{
					_budtendersRestored = true;
					string budtenderSaveState = PropertySaveData.Instance.BudtenderSaveState;
					if (!string.IsNullOrEmpty(budtenderSaveState))
					{
						BudtenderController.Deserialize(budtenderSaveState);
					}
				}
				PerfTracker.Begin("BudtenderAI");
				if (NetworkHelper.IsHost)
				{
					BudtenderController.Tick();
				}
				PerfTracker.End("BudtenderAI");
				PerfTracker.Begin("Checkout");
				CheckoutProcess.Instance?.Tick();
				CheckoutProcess.TryStartCheckout();
				CheckoutProcess.PollLockGrant();
				if (CheckoutProcess.Instance == null)
				{
					CheckoutCounter.TryCollectRegister();
				}
				PerfTracker.End("Checkout");
				PerfTracker.Begin("ScreenTicks");
				foreach (CheckoutCounterInstance allCounter in CheckoutCounter.AllCounters)
				{
					allCounter.Screen?.Tick();
				}
				PerfTracker.End("ScreenTicks");
				Dispensary.UpdateLightBrightness();
				WestvilleShack.UpdateLightBrightness();
				PerfTracker.Begin("QuestTicks");
				_drifterManager?.ClientQuestTick();
				StorefrontGrowthQuest.Instance?.Tick();
				StorefrontExpansionQuest.Instance?.Tick();
				PerfTracker.End("QuestTicks");
			}
			catch (Exception ex)
			{
				OTCLog.Error("Patch", "Error in OnLateUpdate: " + ex.Message + "\n" + ex.StackTrace);
			}
			PerfTracker.EndFrame();
		}

		private static void OnSleepEnd(int minutesSkipped)
		{
			if (NetworkHelper.IsHost)
			{
				LoadManager instance = Singleton<LoadManager>.Instance;
				if (!((Object)(object)instance == (Object)null) && instance.IsGameLoaded)
				{
					StaticNPC.Instance?.WarpToSpawn();
					BellaNPC.Instance?.ReInjectIntoBuilding();
				}
			}
		}

		public override void OnDeinitializeMelon()
		{
			if (!DependencyChecker.HasMissingDeps)
			{
				OnDeinitializeMelonImpl();
			}
		}

		private static void OnDayPass()
		{
			if (!NetworkHelper.IsHost)
			{
				return;
			}
			PropertySaveData instance = PropertySaveData.Instance;
			if (instance != null)
			{
				int num = 0;
				if (instance.IsPropertyOwned("westville_shack"))
				{
					num += PropertyInventory.GetTotalProductCount(WestvilleShack.ShackGrid);
				}
				if (instance.IsPropertyOwned("big_dispensary"))
				{
					num += PropertyInventory.GetTotalProductCount(Dispensary.DispensaryGrid);
				}
				instance.RecordInventorySnapshot(TimeManager.ElapsedDays, num);
				instance.TrimSalesLog(TimeManager.ElapsedDays);
			}
		}

		private void OnDeinitializeMelonImpl()
		{
			PerfTracker.WriteReport();
			TimeManager.OnSleepEnd = (Action<int>)Delegate.Remove(TimeManager.OnSleepEnd, new Action<int>(OnSleepEnd));
			TimeManager.OnDayPass = (Action)Delegate.Remove(TimeManager.OnDayPass, new Action(OnDayPass));
			ConfigSyncData.Cleanup();
			_notificationManager?.Cleanup();
			_desperationManager?.Cleanup();
			_drifterManager?.Cleanup();
			_managerManager?.Cleanup();
			_customerManager?.Cleanup();
		}

		private void ExtractIcons()
		{
			OtcIconDir = Path.Combine(MelonEnvironment.UserDataDirectory, "OverTheCounter", "Icons");
			if (!Directory.Exists(OtcIconDir))
			{
				Directory.CreateDirectory(OtcIconDir);
			}
			ExtractResource(OtcIconDir, "CustomersIcon.png");
			ExtractResource(OtcIconDir, "DrifterQuestIcon.png");
			ExtractResource(OtcIconDir, "DrifterProfileIcon.png");
			ExtractResource(OtcIconDir, "RinseCycle.png");
			ExtractResource(OtcIconDir, "CrimeWareQuest.png");
			ExtractResource(OtcIconDir, "ExecutivePrivilege.png");
			ExtractResource(OtcIconDir, "ManagerIcon.png");
			ExtractResource(OtcIconDir, "CheckoutCounter.png");
			ExtractResource(OtcIconDir, "StoreAlertIcon.png");
		}

		private void ExtractResource(string directory, string fileName)
		{
			string path = Path.Combine(directory, fileName);
			if (File.Exists(path))
			{
				return;
			}
			OTCLog.Msg("Patch", "Extracting " + fileName + "...");
			string text = "OverTheCounter.Resources." + fileName;
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text);
			if (stream != null)
			{
				using (FileStream destination = new FileStream(path, FileMode.Create, FileAccess.Write))
				{
					stream.CopyTo(destination);
				}
				OTCLog.Msg("Patch", fileName + " extracted successfully.");
			}
			else
			{
				OTCLog.Error("Patch", "Could not find embedded resource '" + text + "'.");
			}
		}
	}
	public static class Config
	{
		private static MelonPreferences_Category _managers;

		public static ConfigEntry<float> ManagerDailyWage;

		public static ConfigEntry<float> ManagerSigningFee;

		public static ConfigEntry<bool> AlternateHire;

		private static MelonPreferences_Category _laundering;

		public static ConfigEntry<float> VicTier1Cost;

		public static ConfigEntry<float> VicTier1Return;

		public static ConfigEntry<int> VicTier2TrustUnlock;

		public static ConfigEntry<float> VicTier2Cost;

		public static ConfigEntry<float> VicTier2Return;

		public static ConfigEntry<int> VicIntroWeedGrams;

		public static ConfigEntry<float> VicDepositTrigger;

		private static MelonPreferences_Category _bella;

		public static ConfigEntry<float> BellaWeedValue;

		public static ConfigEntry<float> BellaMethValue;

		public static ConfigEntry<float> BellaCokeValue;

		private static MelonPreferences_Category _notifications;

		public static ConfigEntry<bool> ConsolidationEnabled;

		public static ConfigEntry<int> ConsolidationThreshold;

		private static MelonPreferences_Category _subscription;

		public static ConfigEntry<float> SaasWeeklyCost;

		public static ConfigEntry<int> SaasCycleDays;

		public static ConfigEntry<float> StaticTier1BankCost;

		public static ConfigEntry<int> StaticTier1WeedGrams;

		public static ConfigEntry<float> StaticTier2BankCost;

		public static ConfigEntry<int> StaticTier2MethGrams;

		public static ConfigEntry<float> StaticTier3BankCost;

		public static ConfigEntry<int> StaticTier3PremiumMethGrams;

		private static MelonPreferences_Category _world;

		public static ConfigEntry<float> ShackPurchasePrice;

		public static ConfigEntry<float> WarehousePurchasePrice;

		public static ConfigEntry<float> DispensaryPurchasePrice;

		public static ConfigEntry<int> StackSizeMultiplier;

		public static ConfigEntry<bool> GraffitiReEdit;

		public static ConfigEntry<bool> RecipePinEnabled;

		public static ConfigEntry<int> ShackDailyCustomerCap;

		public static ConfigEntry<bool> PreserveVanillaDeals;

		public static ConfigEntry<float> WalkInMirrorRate;

		private static MelonPreferences_Category _desperation;

		public static ConfigEntry<bool> DesperationEnabled;

		public static ConfigEntry<float> FiendAddictionThreshold;

		public static ConfigEntry<float> TriggerChancePerHour;

		public static ConfigEntry<int> MaxEventsPerDay;

		public static ConfigEntry<int> ResponseDeadlineMinutes;

		public static ConfigEntry<int> DeadlineMinutes;

		public static ConfigEntry<float> BonusMultiplier;

		public static ConfigEntry<float> RelationshipPenalty;

		public static ConfigEntry<int> CooldownMinutes;

		public static ConfigEntry<int> DayStartHour;

		public static ConfigEntry<int> DayEndHour;

		private static MelonPreferences_Category _drifters;

		public static ConfigEntry<bool> DrifterEnabled;

		public static ConfigEntry<float> DrifterSpawnChancePerHour;

		public static ConfigEntry<int> MaxActiveDrifters;

		public static ConfigEntry<int> DrifterDayStartHour;

		public static ConfigEntry<int> DrifterDayEndHour;

		public static ConfigEntry<int> DrifterOfferWindowMin;

		public static ConfigEntry<int> DrifterDeliveryDeadlineMin;

		public static ConfigEntry<int> DrifterLingerMinMin;

		public static ConfigEntry<int> DrifterLingerMaxMin;

		public static ConfigEntry<float> DrifterMinDealValue;

		private static MelonPreferences_Category _debug;

		public static ConfigEntry<bool> VerboseLogging;

		public static ConfigEntry<bool> ManagerVerboseLogging;

		public static ConfigEntry<bool> DrifterVerboseLogging;

		public static ConfigEntry<bool> DesperationVerboseLogging;

		public static ConfigEntry<bool> NpcVerboseLogging;

		public static ConfigEntry<bool> NetworkVerboseLogging;

		public static ConfigEntry<bool> QuestVerboseLogging;

		public static ConfigEntry<bool> NotificationVerboseLogging;

		public static ConfigEntry<bool> PatchVerboseLogging;

		public static ConfigEntry<bool> ProfilingEnabled;

		private static MelonPreferences_Category _minimap;

		public static ConfigEntry<bool> MinimapEnabled;

		public static ConfigEntry<int> MinimapSize;

		public static ConfigEntry<bool> MinimapRotateWithPlayer;

		public static ConfigEntry<bool> MinimapCircle;

		public static ConfigEntry<int> MinimapDefaultZoom;

		public static ConfigEntry<float> MinimapIconScale;

		public static MelonPreferences_Entry<KeyCode> MinimapToggleKey;

		public static ConfigEntry<int> MinimapHorizontalOffset;

		public static ConfigEntry<int> MinimapVerticalOffset;

		public static ConfigEntry<bool> MinimapInfoOnTop;

		public static MelonPreferences_Entry<Color> MinimapBorderColor;

		public static ConfigEntry<int> MinimapBorderWidth;

		public static ConfigEntry<bool> MinimapShowTime;

		public static ConfigEntry<bool> MinimapShowDay;

		public static ConfigEntry<bool> MinimapUse24HourClock;

		public static ConfigEntry<bool> MinimapShowCompass;

		public static ConfigEntry<bool> MinimapShowEdgeIndicators;

		public static ConfigEntry<bool> MinimapPerfLimit;

		private static MelonPreferences_Category _hud;

		public static ConfigEntry<bool> HUDShowRankXP;

		public static ConfigEntry<bool> HUDShowHealth;

		public static ConfigEntry<bool> HUDShowStamina;

		public static ConfigEntry<bool> StoreAlertEnabled;

		private static MelonPreferences_Category _minimapPoi;

		public static ConfigEntry<bool> MinimapShowPotentialCustomers;

		public static ConfigEntry<bool> MinimapShowCustomers;

		public static ConfigEntry<bool> MinimapShowDealers;

		public static ConfigEntry<bool> MinimapShowDeadDrops;

		public static ConfigEntry<bool> MinimapShowContracts;

		public static ConfigEntry<bool> MinimapShowQuests;

		public static ConfigEntry<bool> MinimapShowProperties;

		public static ConfigEntry<bool> MinimapShowManagers;

		public static ConfigEntry<bool> MinimapShowModdedNPCs;

		private static readonly Dictionary<string, ConfigEntry<float>> _floatEntries = new Dictionary<string, ConfigEntry<float>>();

		private static readonly Dictionary<string, ConfigEntry<int>> _intEntries = new Dictionary<string, ConfigEntry<int>>();

		private static readonly Dictionary<string, ConfigEntry<bool>> _boolEntries = new Dictionary<string, ConfigEntry<bool>>();

		private static readonly HashSet<string> _localOnlyKeys = new HashSet<string>
		{
			"ConsolidationEnabled", "ConsolidationThreshold", "ManagerVerboseLogging", "DrifterVerboseLogging", "DesperationVerboseLogging", "NpcVerboseLogging", "NetworkVerboseLogging", "QuestVerboseLogging", "NotificationVerboseLogging", "PatchVerboseLogging",
			"ProfilingEnabled", "VerboseLogging", "MinimapEnabled", "MinimapSize", "MinimapRotateWithPlayer", "MinimapCircle", "MinimapDefaultZoom", "MinimapIconScale", "MinimapHorizontalOffset", "MinimapVerticalOffset",
			"MinimapInfoOnTop", "MinimapBorderWidth", "MinimapShowTime", "MinimapShowDay", "MinimapUse24HourClock", "MinimapShowPotentialCustomers", "MinimapShowCustomers", "MinimapShowDealers", "MinimapShowDeadDrops", "MinimapShowContracts",
			"MinimapShowQuests", "MinimapShowProperties", "MinimapShowManagers", "MinimapShowModdedNPCs", "MinimapShowCompass", "MinimapShowEdgeIndicators", "MinimapPerfLimit", "HUDShowRankXP", "HUDShowHealth", "HUDShowStamina",
			"StoreAlertEnabled", "RecipePinEnabled"
		};

		public static void Initialize()
		{
			//IL_0e73: Unknown result type (might be due to invalid IL or missing references)
			_managers = MelonPreferences.CreateCategory("OverTheCounter_Managers", "Manager System");
			ManagerDailyWage = Register(_managers.CreateEntry<float>("ManagerDailyWage", 350f, "Base Daily Wage", "Base daily wage before upgrade fees are added", false, false, (ValueValidator)null, (string)null));
			ManagerSigningFee = Register(_managers.CreateEntry<float>("ManagerSigningFee", 3000f, "Signing Fee", "One-time fee deducted from player cash when hiring a manager", false, false, (ValueValidator)null, (string)null));
			AlternateHire = Register(_managers.CreateEntry<bool>("AlternateHire", false, "Alternate Hire", "Show hire buttons in the OTC app instead of using Manny's dialogue. Enable if another mod conflicts with Manny.", false, false, (ValueValidator)null, (string)null));
			_laundering = MelonPreferences.CreateCategory("OverTheCounter_Laundering", "Vic Laundering");
			VicTier1Cost = Register(_laundering.CreateEntry<float>("VicTier1Cost", 500f, "Tier 1 Cost", "Cash required for tier-1 laundering", false, false, (ValueValidator)null, (string)null));
			VicTier1Return = Register(_laundering.CreateEntry<float>("VicTier1Return", 400f, "Tier 1 Return", "Clean money returned for tier-1 laundering", false, false, (ValueValidator)null, (string)null));
			VicTier2TrustUnlock = Register(_laundering.CreateEntry<int>("VicTier2TrustUnlock", 7, "Tier 2 Trust Unlock", "Trust level required to unlock tier-2 laundering", false, false, (ValueValidator)null, (string)null));
			VicTier2Cost = Register(_laundering.CreateEntry<float>("VicTier2Cost", 900f, "Tier 2 Cost", "Cash required for tier-2 laundering", false, false, (ValueValidator)null, (string)null));
			VicTier2Return = Register(_laundering.CreateEntry<float>("VicTier2Return", 750f, "Tier 2 Return", "Clean money returned for tier-2 laundering", false, false, (ValueValidator)null, (string)null));
			VicIntroWeedGrams = Register(_laundering.CreateEntry<int>("VicIntroWeedGrams", 40, "Intro Quest Weed Grams", "Grams of weed required to complete Vic's intro quest", false, false, (ValueValidator)null, (string)null));
			VicDepositTrigger = Register(_laundering.CreateEntry<float>("VicDepositTrigger", 10000f, "Deposit Trigger Amount", "Weekly deposit total that triggers Vic's intro quest", false, false, (ValueValidator)null, (string)null));
			_bella = MelonPreferences.CreateCategory("OverTheCounter_Bella", "Bella Protocol");
			BellaWeedValue = Register(_bella.CreateEntry<float>("BellaWeedValue", 105f, "Weed Mix Value", "Minimum base price for the weed mix Bella requires", false, false, (ValueValidator)null, (string)null));
			BellaMethValue = Register(_bella.CreateEntry<float>("BellaMethValue", 200f, "Meth Mix Value", "Minimum base price for the meth mix Bella requires", false, false, (ValueValidator)null, (string)null));
			BellaCokeValue = Register(_bella.CreateEntry<float>("BellaCokeValue", 400f, "Cocaine Mix Value", "Minimum base price for the cocaine mix Bella requires", false, false, (ValueValidator)null, (string)null));
			_notifications = MelonPreferences.CreateCategory("OverTheCounter_Notifications", "Contract Notifications");
			ConsolidationEnabled = Register(_notifications.CreateEntry<bool>("Enabled", true, "Enabled", "Enable/disable contract consolidation (groups same-window deliveries into one HUD entry)", false, false, (ValueValidator)null, (string)null));
			ConsolidationThreshold = Register(_notifications.CreateEntry<int>("ConsolidationThreshold", 5, "Consolidation Threshold", "Minimum contracts in a window before consolidation kicks in", false, false, (ValueValidator)null, (string)null));
			_subscription = MelonPreferences.CreateCategory("OverTheCounter_Subscription", "Static Subscription");
			SaasWeeklyCost = Register(_subscription.CreateEntry<float>("SaasWeeklyCost", 1000f, "Weekly Cost", "Bank balance deducted each billing cycle", false, false, (ValueValidator)null, (string)null));
			SaasCycleDays = Register(_subscription.CreateEntry<int>("SaasCycleDays", 7, "Cycle Days", "Number of days between subscription payments", false, false, (ValueValidator)null, (string)null));
			StaticTier1BankCost = Register(_subscription.CreateEntry<float>("StaticTier1BankCost", 3000f, "Tier 1 Bank Cost", "Bank transfer cost for the initial software package", false, false, (ValueValidator)null, (string)null));
			StaticTier1WeedGrams = Register(_subscription.CreateEntry<int>("StaticTier1WeedGrams", 20, "Tier 1 Weed Grams", "Grams of weed required for the initial package", false, false, (ValueValidator)null, (string)null));
			StaticTier2BankCost = Register(_subscription.CreateEntry<float>("StaticTier2BankCost", 6000f, "Tier 2 Bank Cost", "Bank transfer cost for the Premium upgrade", false, false, (ValueValidator)null, (string)null));
			StaticTier2MethGrams = Register(_subscription.CreateEntry<int>("StaticTier2MethGrams", 5, "Tier 2 Meth Grams", "Grams of meth required for the Premium upgrade", false, false, (ValueValidator)null, (string)null));
			StaticTier3BankCost = Register(_subscription.CreateEntry<float>("StaticTier3BankCost", 12000f, "Tier 3 Bank Cost", "Bank transfer cost for the Enterprise upgrade", false, false, (ValueValidator)null, (string)null));
			StaticTier3PremiumMethGrams = Register(_subscription.CreateEntry<int>("StaticTier3PremiumMethGrams", 10, "Tier 3 Premium Meth Grams", "Grams of premium meth required for Enterprise upgrade", false, false, (ValueValidator)null, (string)null));
			_world = MelonPreferences.CreateCategory("OverTheCounter_World", "World");
			ShackPurchasePrice = Register(_world.CreateEntry<float>("ShackPurchasePrice", 5000f, "Shack Purchase Price", "Bank transfer cost for the Westville Shack property", false, false, (ValueValidator)null, (string)null));
			WarehousePurchasePrice = Register(_world.CreateEntry<float>("WarehousePurchasePrice", 18000f, "Warehouse Purchase Price", "Bank transfer cost for the Warehouse property", false, false, (ValueValidator)null, (string)null));
			DispensaryPurchasePrice = Register(_world.CreateEntry<float>("DispensaryPurchasePrice", 30000f, "Dispensary Purchase Price", "Bank transfer cost for the Big Dispensary property", false, false, (ValueValidator)null, (string)null));
			StackSizeMultiplier = Register(_world.CreateEntry<int>("StackSizeMultiplier", 1, "Stack Size Multiplier", "Multiplies the stack limit of all stackable items by this value. 1 = vanilla stacks (default). 2 = double stacks. Affects all inventories. Host value is used in multiplayer. Changing mid-save does not retroactively adjust existing item quantities.", false, false, (ValueValidator)(object)new ValueRange<int>(1, 10), (string)null));
			GraffitiReEdit = Register(_world.CreateEntry<bool>("GraffitiReEdit", true, "Graffiti Re-Edit", "Allow re-editing spray paint surfaces without consuming spray cans. Spray can must still be equipped to interact.", false, false, (ValueValidator)null, (string)null));
			RecipePinEnabled = Register(_world.CreateEntry<bool>("RecipePinEnabled", true, "Recipe Pin", "Show a Pin Recipe button in the Product Manager app. Pins a draggable overlay showing the full mixing chain for a product.", false, false, (ValueValidator)null, (string)null));
			ShackDailyCustomerCap = Register(_world.CreateEntry<int>("ShackDailyCustomerCap", 12, "Shack Daily Customer Cap", "Maximum customers redirected to the Westville Shack per day", false, false, (ValueValidator)null, (string)null));
			PreserveVanillaDeals = Register(_world.CreateEntry<bool>("PreserveVanillaDeals", false, "Preserve Vanilla Deals", "When enabled, vanilla NPCs keep their normal deal behavior instead of being redirected to the dispensary. Each redirected deal has a chance (set by Mirror Spawn Rate) to also spawn a random walk-in customer. Off by default because keeping both vanilla deals AND dispensary sales effectively doubles income.", false, false, (ValueValidator)null, (string)null));
			WalkInMirrorRate = Register(_world.CreateEntry<float>("WalkInMirrorRate", 0.4f, "Mirror Spawn Rate", "Only used when Preserve Vanilla Deals is enabled. Chance (0-1) that each vanilla deal that would have been redirected also spawns a random store customer. Has no effect when Preserve Vanilla Deals is off. 0.4 = 40% of deals spawn one. 1.0 = every deal spawns one.", false, false, (ValueValidator)(object)new ValueRange<float>(0f, 1f), (string)null));
			_desperation = MelonPreferences.CreateCategory("OverTheCounter", "Desperation System");
			DesperationEnabled = Register(_desperation.CreateEntry<bool>("Enabled", true, "Enabled", "Enable/disable the desperation system (urgent fiend requests)", false, false, (ValueValidator)null, (string)null));
			FiendAddictionThreshold = Register(_desperation.CreateEntry<float>("FiendAddictionThreshold", 0.67f, "Fiend Addiction Threshold", "Addiction level required to qualify as a Fiend (0.0–1.0)", false, false, (ValueValidator)null, (string)null));
			TriggerChancePerHour = Register(_desperation.CreateEntry<float>("TriggerChancePerHour", 0.12f, "Trigger Chance Per Hour", "Probability of a desperation event each hour (0.0–1.0)", false, false, (ValueValidator)null, (string)null));
			MaxEventsPerDay = Register(_desperation.CreateEntry<int>("MaxEventsPerDay", 3, "Max Events Per Day", "Hard cap on desperation events per day", false, false, (ValueValidator)null, (string)null));
			ResponseDeadlineMinutes = Register(_desperation.CreateEntry<int>("ResponseDeadlineMinutes", 60, "Response Deadline (min)", "In-game minutes the player has to respond to a desperation offer", false, false, (ValueValidator)null, (string)null));
			DeadlineMinutes = Register(_desperation.CreateEntry<int>("DeadlineMinutes", 120, "Delivery Deadline (min)", "In-game minutes to deliver after accepting a desperation contract", false, false, (ValueValidator)null, (string)null));
			BonusMultiplier = Register(_desperation.CreateEntry<float>("BonusMultiplier", 0.45f, "Bonus Multiplier", "Extra payment multiplier for desperation deliveries (0.45 = 45%)", false, false, (ValueValidator)null, (string)null));
			RelationshipPenalty = Register(_desperation.CreateEntry<float>("RelationshipPenalty", -15f, "Relationship Penalty", "Relationship change on failed desperation event", false, false, (ValueValidator)null, (string)null));
			CooldownMinutes = Register(_desperation.CreateEntry<int>("CooldownMinutes", 1440, "Cooldown (min)", "Minutes a customer is locked out after a failed event (1440 = 24h)", false, false, (ValueValidator)null, (string)null));
			DayStartHour = Register(_desperation.CreateEntry<int>("DayStartHour", 800, "Day Start Hour", "Earliest 24h time for desperation rolls (800 = 8:00 AM)", false, false, (ValueValidator)null, (string)null));
			DayEndHour = Register(_desperation.CreateEntry<int>("DayEndHour", 2100, "Day End Hour", "Latest 24h time for desperation rolls (2100 = 9:00 PM)", false, false, (ValueValidator)null, (string)null));
			_drifters = MelonPreferences.CreateCategory("OverTheCounter_Drifters", "Drifter System");
			DrifterEnabled = Register(_drifters.CreateEntry<bool>("Enabled", true, "Enabled", "Enable/disable the drifter system (random street NPCs offering one-time deals)", false, false, (ValueValidator)null, (string)null));
			DrifterSpawnChancePerHour = Register(_drifters.CreateEntry<float>("DrifterSpawnChancePerHour", 0.38f, "Spawn Chance Per Hour", "Base spawn chance per hour at max regions. Scaled down by unlocked region count (0.0-1.0)", false, false, (ValueValidator)null, (string)null));
			MaxActiveDrifters = Register(_drifters.CreateEntry<int>("MaxActiveDrifters", 3, "Max Active Drifters", "Maximum number of drifters that can be active at once", false, false, (ValueValidator)null, (string)null));
			DrifterDayStartHour = Register(_drifters.CreateEntry<int>("DrifterDayStartHour", 800, "Day Start Hour", "Earliest 24h time for drifter spawns (800 = 8:00 AM)", false, false, (ValueValidator)null, (string)null));
			DrifterDayEndHour = Register(_drifters.CreateEntry<int>("DrifterDayEndHour", 2100, "Day End Hour", "Latest 24h time for drifter spawns (2100 = 9:00 PM)", false, false, (ValueValidator)null, (string)null));
			DrifterOfferWindowMin = Register(_drifters.CreateEntry<int>("DrifterOfferWindowMin", 120, "Offer Window (min)", "Minutes player has to respond to a drifter offer (120 = 2 hours)", false, false, (ValueValidator)null, (string)null));
			DrifterDeliveryDeadlineMin = Register(_drifters.CreateEntry<int>("DrifterDeliveryDeadlineMin", 240, "Delivery Deadline (min)", "Minutes to deliver after accepting a drifter deal (240 = 4 hours)", false, false, (ValueValidator)null, (string)null));
			DrifterLingerMinMin = Register(_drifters.CreateEntry<int>("DrifterLingerMinMin", 30, "Linger Min (min)", "Minimum minutes a drifter lingers after deal completion/expiry", false, false, (ValueValidator)null, (string)null));
			DrifterLingerMaxMin = Register(_drifters.CreateEntry<int>("DrifterLingerMaxMin", 60, "Linger Max (min)", "Maximum minutes a drifter lingers after deal completion/expiry", false, false, (ValueValidator)null, (string)null));
			DrifterMinDealValue = Register(_drifters.CreateEntry<float>("DrifterMinDealValue", 90f, "Min Deal Value ($)", "Soft minimum deal value - drifters ask for more quantity until the deal reaches this threshold", false, false, (ValueValidator)null, (string)null));
			_debug = MelonPreferences.CreateCategory("OverTheCounter_Debug", "Debug");
			VerboseLogging = Register(_debug.CreateEntry<bool>("VerboseLogging", false, "Verbose Logging (General)", "Catch-all verbose logging for systems without a dedicated toggle", false, false, (ValueValidator)null, (string)null));
			ManagerVerboseLogging = Register(_debug.CreateEntry<bool>("ManagerVerboseLogging", false, "Verbose: Manager", "Enable detailed manager logging (shopping list breakdowns, per-item details)", false, false, (ValueValidator)null, (string)null));
			DrifterVerboseLogging = Register(_debug.CreateEntry<bool>("DrifterVerboseLogging", false, "Verbose: Drifter", "Enable detailed drifter system logging", false, false, (ValueValidator)null, (string)null));
			DesperationVerboseLogging = Register(_debug.CreateEntry<bool>("DesperationVerboseLogging", false, "Verbose: Desperation", "Enable detailed desperation system logging", false, false, (ValueValidator)null, (string)null));
			NpcVerboseLogging = Register(_debug.CreateEntry<bool>("NpcVerboseLogging", false, "Verbose: NPC", "Enable detailed NPC logging (Vic, Bella, Static)", false, false, (ValueValidator)null, (string)null));
			NetworkVerboseLogging = Register(_debug.CreateEntry<bool>("NetworkVerboseLogging", false, "Verbose: Network", "Enable detailed network sync logging", false, false, (ValueValidator)null, (string)null));
			QuestVerboseLogging = Register(_debug.CreateEntry<bool>("QuestVerboseLogging", false, "Verbose: Quest", "Enable detailed quest logging", false, false, (ValueValidator)null, (string)null));
			NotificationVerboseLogging = Register(_debug.CreateEntry<bool>("NotificationVerboseLogging", false, "Verbose: Notification", "Enable detailed notification system logging", false, false, (ValueValidator)null, (string)null));
			PatchVerboseLogging = Register(_debug.CreateEntry<bool>("PatchVerboseLogging", false, "Verbose: Patch", "Enable detailed Harmony patch logging", false, false, (ValueValidator)null, (string)null));
			ProfilingEnabled = Register(_debug.CreateEntry<bool>("ProfilingEnabled", false, "Performance Profiling", "Write periodic performance reports to UserData/OTC_PerfReport.txt", false, false, (ValueValidator)null, (string)null));
			_minimapPoi = MelonPreferences.CreateCategory("OverTheCounter_MinimapPOI", "Minimap POIs");
			MinimapShowPotentialCustomers = Register(_minimapPoi.CreateEntry<bool>("MinimapShowPotentialCustomers", true, "Show Potential Customers", "Show potential customer icons on the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapShowCustomers = Register(_minimapPoi.CreateEntry<bool>("MinimapShowCustomers", false, "Show Customers", "Show unlocked customer icons on the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapShowDealers = Register(_minimapPoi.CreateEntry<bool>("MinimapShowDealers", true, "Show Dealers", "Show dealer icons on the minimap (potential and active)", false, false, (ValueValidator)null, (string)null));
			MinimapShowDeadDrops = Register(_minimapPoi.CreateEntry<bool>("MinimapShowDeadDrops", true, "Show Dead Drops", "Show dead drop icons on the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapShowContracts = Register(_minimapPoi.CreateEntry<bool>("MinimapShowContracts", true, "Show Contracts", "Show contract delivery icons on the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapShowQuests = Register(_minimapPoi.CreateEntry<bool>("MinimapShowQuests", true, "Show Quests", "Show quest objective icons on the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapShowProperties = Register(_minimapPoi.CreateEntry<bool>("MinimapShowProperties", true, "Show Properties", "Show owned property icons on the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapShowManagers = Register(_minimapPoi.CreateEntry<bool>("MinimapShowManagers", true, "Show Managers", "Show manager icons on the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapShowModdedNPCs = Register(_minimapPoi.CreateEntry<bool>("MinimapShowModdedNPCs", true, "Show Modded NPCs", "Show NPC icons added by other mods (e.g. police, cartel) on the minimap", false, false, (ValueValidator)null, (string)null));
			_minimap = MelonPreferences.CreateCategory("OverTheCounter_Minimap", "Minimap");
			MinimapEnabled = Register(_minimap.CreateEntry<bool>("MinimapEnabled", false, "Enabled", "Show the minimap overlay", false, false, (ValueValidator)null, (string)null));
			MinimapSize = Register(_minimap.CreateEntry<int>("MinimapSize", 250, "Size (px)", "Minimap size in pixels", false, false, (ValueValidator)null, (string)null));
			MinimapRotateWithPlayer = Register(_minimap.CreateEntry<bool>("MinimapRotateWithPlayer", false, "Rotate With Player", "Rotate minimap to match player facing direction", false, false, (ValueValidator)null, (string)null));
			MinimapCircle = Register(_minimap.CreateEntry<bool>("MinimapCircle", false, "Circle Shape", "Use circular minimap shape instead of square", false, false, (ValueValidator)null, (string)null));
			MinimapDefaultZoom = Register(_minimap.CreateEntry<int>("MinimapDefaultZoom", 2, "Default Zoom", "Starting zoom level, 1=closest, 3=farthest (1-3)", false, false, (ValueValidator)null, (string)null));
			MinimapIconScale = Register(_minimap.CreateEntry<float>("MinimapIconScale", 0.7f, "Icon Scale", "POI icon scale on the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapToggleKey = _minimap.CreateEntry<KeyCode>("MinimapToggleKey", (KeyCode)110, "Toggle Key", "Hotkey to cycle minimap zoom", false, false, (ValueValidator)null, (string)null);
			MinimapHorizontalOffset = Register(_minimap.CreateEntry<int>("MinimapHorizontalOffset", 100, "Horizontal Offset", "Horizontal position (0=left, 100=right)", false, false, (ValueValidator)(object)new ValueRange<int>(0, 100), (string)null));
			MinimapVerticalOffset = Register(_minimap.CreateEntry<int>("MinimapVerticalOffset", 0, "Vertical Offset", "Vertical position (0=top, 100=bottom)", false, false, (ValueValidator)(object)new ValueRange<int>(0, 100), (string)null));
			MinimapInfoOnTop = Register(_minimap.CreateEntry<bool>("MinimapInfoOnTop", false, "Info Panels On Top", "Place clock and day display above the minimap instead of below", false, false, (ValueValidator)null, (string)null));
			MinimapBorderColor = _minimap.CreateEntry<Color>("MinimapBorderColor", new Color(0.2f, 0.2f, 0.2f, 0.9f), "Border Color", "Minimap border color", false, false, (ValueValidator)null, (string)null);
			MinimapBorderWidth = Register(_minimap.CreateEntry<int>("MinimapBorderWidth", 4, "Border Width", "Border thickness in pixels per side (2-10)", false, false, (ValueValidator)null, (string)null));
			MinimapShowTime = Register(_minimap.CreateEntry<bool>("MinimapShowTime", true, "Show Time", "Display the current time near the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapShowDay = Register(_minimap.CreateEntry<bool>("MinimapShowDay", true, "Show Day", "Display the current day near the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapUse24HourClock = Register(_minimap.CreateEntry<bool>("MinimapUse24HourClock", false, "24-Hour Clock", "Use 24-hour time format instead of 12-hour AM/PM", false, false, (ValueValidator)null, (string)null));
			MinimapShowCompass = Register(_minimap.CreateEntry<bool>("MinimapShowCompass", true, "Show Compass", "Display N/S/E/W cardinal direction labels on the minimap edge", false, false, (ValueValidator)null, (string)null));
			MinimapShowEdgeIndicators = Register(_minimap.CreateEntry<bool>("MinimapShowEdgeIndicators", true, "Edge Indicators", "Show POI icons pinned to the minimap edge for off-screen points of interest", false, false, (ValueValidator)null, (string)null));
			MinimapPerfLimit = Register(_minimap.CreateEntry<bool>("MinimapPerfLimit", true, "Performance Limiting", "Adaptively reduce minimap update rate to limit CPU usage", false, false, (ValueValidator)null, (string)null));
			_hud = MelonPreferences.CreateCategory("OverTheCounter_HUD", "HUD Overlay");
			HUDShowRankXP = Register(_hud.CreateEntry<bool>("HUDShowRankXP", false, "Show Rank/XP", "Display rank and XP progress bar above the hotbar", false, false, (ValueValidator)null, (string)null));
			HUDShowHealth = Register(_hud.CreateEntry<bool>("HUDShowHealth", false, "Show Health", "Display health bar above the hotbar", false, false, (ValueValidator)null, (string)null));
			HUDShowStamina = Register(_hud.CreateEntry<bool>("HUDShowStamina", false, "Show Stamina", "Display stamina bar above the hotbar", false, false, (ValueValidator)null, (string)null));
			StoreAlertEnabled = Register(_hud.CreateEntry<bool>("StoreAlertEnabled", true, "Show Store Alerts", "Show checkout queue alerts on the right side of the screen", false, false, (ValueValidator)null, (string)null));
		}

		private static ConfigEntry<float> Register(MelonPreferences_Entry<float> entry)
		{
			ConfigEntry<float> configEntry = new ConfigEntry<float>(entry);
			_floatEntries[((MelonPreferences_Entry)entry).Identifier] = configEntry;
			return configEntry;
		}

		private static ConfigEntry<int> Register(MelonPreferences_Entry<int> entry)
		{
			ConfigEntry<int> configEntry = new ConfigEntry<int>(entry);
			_intEntries[((MelonPreferences_Entry)entry).Identifier] = configEntry;
			return configEntry;
		}

		private static ConfigEntry<bool> Register(MelonPreferences_Entry<bool> entry)
		{
			ConfigEntry<bool> configEntry = new ConfigEntry<bool>(entry);
			_boolEntries[((MelonPreferences_Entry)entry).Identifier] = configEntry;
			return configEntry;
		}

		public static string SerializeAll()
		{
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, ConfigEntry<float>> floatEntry in _floatEntries)
			{
				if (!_localOnlyKeys.Contains(floatEntry.Key))
				{
					list.Add(floatEntry.Key + "=" + floatEntry.Value.RawEntry.Value.ToString(CultureInfo.InvariantCulture));
				}
			}
			foreach (KeyValuePair<string, ConfigEntry<int>> intEntry in _intEntries)
			{
				if (!_localOnlyKeys.Contains(intEntry.Key))
				{
					list.Add(intEntry.Key + "=" + intEntry.Value.RawEntry.Value.ToString(CultureInfo.InvariantCulture));
				}
			}
			foreach (KeyValuePair<string, ConfigEntry<bool>> boolEntry in _boolEntries)
			{
				if (!_localOnlyKeys.Contains(boolEntry.Key))
				{
					list.Add($"{boolEntry.Key}={boolEntry.Value.RawEntry.Value}");
				}
			}
			return string.Join("|", list);
		}

		public static void ApplyOverrides(Dictionary<string, string> data)
		{
			foreach (KeyValuePair<string, string> datum in data)
			{
				if (_localOnlyKeys.Contains(datum.Key))
				{
					continue;
				}
				ConfigEntry<int> value2;
				ConfigEntry<bool> value3;
				bool result3;
				if (_floatEntries.TryGetValue(datum.Key, out var value))
				{
					if (float.TryParse(datum.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
					{
						value.SetOverride(result);
					}
				}
				else if (_intEntries.TryGetValue(datum.Key, out value2))
				{
					if (int.TryParse(datum.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2))
					{
						value2.SetOverride(result2);
					}
				}
				else if (_boolEntries.TryGetValue(datum.Key, out value3) && bool.TryParse(datum.Value, out result3))
				{
					value3.SetOverride(result3);
				}
			}
		}

		public static void ClearAllOverrides()
		{
			foreach (ConfigEntry<float> value in _floatEntries.Values)
			{
				value.ClearOverride();
			}
			foreach (ConfigEntry<int> value2 in _intEntries.Values)
			{
				value2.ClearOverride();
			}
			foreach (ConfigEntry<bool> value3 in _boolEntries.Values)
			{
				value3.ClearOverride();
			}
		}

		public static void SubscribeToChanges()
		{
			foreach (KeyValuePair<string, ConfigEntry<float>> floatEntry in _floatEntries)
			{
				if (!_localOnlyKeys.Contains(floatEntry.Key))
				{
					((MelonEventBase<LemonAction<object, object>>)(object)((MelonPreferences_Entry)floatEntry.Value.RawEntry).OnEntryValueChangedUntyped).Subscribe((LemonAction<object, object>)OnSyncableEntryChanged, 0, false);
				}
			}
			foreach (KeyValuePair<string, ConfigEntry<int>> intEntry in _intEntries)
			{
				if (!_localOnlyKeys.Contains(intEntry.Key))
				{
					((MelonEventBase<LemonAction<object, object>>)(object)((MelonPreferences_Entry)intEntry.Value.RawEntry).OnEntryValueChangedUntyped).Subscribe((LemonAction<object, object>)OnSyncableEntryChanged, 0, false);
				}
			}
			foreach (KeyValuePair<string, ConfigEntry<bool>> boolEntry in _boolEntries)
			{
				if (!_localOnlyKeys.Contains(boolEntry.Key))
				{
					((MelonEventBase<LemonAction<object, object>>)(object)((MelonPreferences_Entry)boolEntry.Value.RawEntry).OnEntryValueChangedUntyped).Subscribe((LemonAction<object, object>)OnSyncableEntryChanged, 0, false);
				}
			}
		}

		private static void OnSyncableEntryChanged(object oldValue, object newValue)
		{
			if (NetworkHelper.IsHost)
			{
				ConfigSyncData.Instance?.RefreshFromConfig();
			}
		}
	}
}
namespace OverTheCounter.Quests
{
	internal static class QuestHelper
	{
		public static string StableGuid(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				throw new ArgumentException("StableGuid key cannot be null/empty", "key");
			}
			using MD5 mD = MD5.Create();
			return new Guid(mD.ComputeHash(Encoding.UTF8.GetBytes("otc-quest:" + key))).ToString();
		}

		public static T CreateWithGuid<T>(string guid) where T : Quest
		{
			T val = (T)(object)QuestManager.CreateQuest<T>((string)null);
			if (val == null)
			{
				OTCLog.Error("Quest", "QuestManager.CreateQuest<" + typeof(T).Name + "> returned null.");
				return default(T);
			}
			TryForceInit((Quest)(object)val, guid);
			return val;
		}

		public static string GetCurrentGuid(Quest quest)
		{
			if (quest == null)
			{
				return string.Empty;
			}
			Quest s1Quest = GetS1Quest(quest);
			return ((s1Quest != null) ? s1Quest.StaticGUID : null) ?? string.Empty;
		}

		private static void TryForceInit(Quest quest, string guid)
		{
			try
			{
				Quest s1Quest = GetS1Quest(quest);
				if ((Object)(object)s1Quest == (Object)null)
				{
					OTCLog.Warning("Quest", "TryForceInit: S1Quest field not found on " + ((object)quest).GetType().Name + ".");
					return;
				}
				s1Quest.StaticGUID = guid;
				string protectedString = GetProtectedString(quest, "Title");
				string protectedString2 = GetProtectedString(quest, "Description");
				Il2CppReferenceArray<QuestEntryData> val = new Il2CppReferenceArray<QuestEntryData>(0L);
				s1Quest.InitializeQuest(protectedString ?? string.Empty, protectedString2 ?? string.Empty, val, guid);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "TryForceInit failed for " + ((object)quest).GetType().Name + ": " + ex.Message);
			}
		}

		private static Quest GetS1Quest(Quest quest)
		{
			object? obj = typeof(Quest).GetField("S1Quest", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(quest);
			return (Quest)((obj is Quest) ? obj : null);
		}

		private static string GetProtectedString(Quest quest, string propertyName)
		{
			return ((object)quest).GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(quest) as string;
		}
	}
	public class VicIntroQuest : Quest
	{
		[SaveableField("vic_quest_stage")]
		private int _stage;

		private QuestEntry _meetVicEntry;

		private QuestEntry _bringWeedEntry;

		private static readonly Vector3 VicPosition = new Vector3(67.75f, 0.97f, 32.36f);

		protected override string Title => "Rinse Cycle";

		protected override string Description => "Help Vic with his party supplies and he'll help you clean some cash.";

		protected override bool AutoBegin => false;

		protected override Sprite QuestIcon
		{
			get
			{
				if (Core.OtcIconDir == null)
				{
					return null;
				}
				return ImageUtils.LoadImage(Path.Combine(Core.OtcIconDir, "RinseCycle.png"));
			}
		}

		public static VicIntroQuest Instance { get; private set; }

		public int Stage => _stage;

		internal static void ResetInstance()
		{
			Instance = null;
		}

		public void Initialize()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_meetVicEntry = ((Quest)this).AddEntry("Meet Vic in the alleyway behind the bank", (Vector3?)VicPosition);
				_bringWeedEntry = ((Quest)this).AddEntry(GetWeedText(), (Vector3?)VicPosition);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "Initialize failed: " + ex.Message);
			}
		}

		private static string GetWeedText()
		{
			return $"Bring Vic {Config.VicIntroWeedGrams.Value} grams of weed";
		}

		public void RefreshEntryText()
		{
			if (_bringWeedEntry != null && _stage >= 1 && _stage < 3)
			{
				_bringWeedEntry.Title = GetWeedText();
			}
		}

		public void StartQuest()
		{
			try
			{
				_stage = 1;
				((Quest)this).Begin();
				QuestEntry meetVicEntry = _meetVicEntry;
				if (meetVicEntry != null)
				{
					meetVicEntry.Begin();
				}
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "StartQuest failed: " + ex.Message);
			}
		}

		public void CompleteObj1()
		{
			try
			{
				_stage = 2;
				QuestEntry meetVicEntry = _meetVicEntry;
				if (meetVicEntry != null)
				{
					meetVicEntry.Begin();
				}
				QuestEntry meetVicEntry2 = _meetVicEntry;
				if (meetVicEntry2 != null)
				{
					meetVicEntry2.Complete();
				}
				QuestEntry bringWeedEntry = _bringWeedEntry;
				if (bringWeedEntry != null)
				{
					bringWeedEntry.Begin();
				}
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "CompleteObj1 failed: " + ex.Message);
			}
		}

		public void CompleteObj2()
		{
			try
			{
				_stage = 3;
				QuestEntry bringWeedEntry = _bringWeedEntry;
				if (bringWeedEntry != null)
				{
					bringWeedEntry.Begin();
				}
				QuestEntry bringWeedEntry2 = _bringWeedEntry;
				if (bringWeedEntry2 != null)
				{
					bringWeedEntry2.Complete();
				}
				((Quest)this).Complete();
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "CompleteObj2 failed: " + ex.Message);
			}
		}

		protected override void OnCreated()
		{
			((Registerable)this).OnCreated();
			Instance = this;
		}

		protected override void OnLoaded()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			((Saveable)this).OnLoaded();
			Instance = this;
			try
			{
				if (VicSaveData.Instance != null)
				{
					int num = (VicSaveData.Instance.Unlocked ? 3 : (VicSaveData.Instance.QuestAccepted ? 2 : (VicSaveData.Instance.HasBeenTexted ? 1 : 0)));
					if (num > _stage)
					{
						_stage = num;
					}
				}
				base.QuestEntries.Clear();
				_meetVicEntry = ((Quest)this).AddEntry("Meet Vic in the alleyway behind the bank", (Vector3?)VicPosition);
				_bringWeedEntry = ((Quest)this).AddEntry(GetWeedText(), (Vector3?)VicPosition);
				if (_stage >= 1)
				{
					QuestEntry meetVicEntry = _meetVicEntry;
					if (meetVicEntry != null)
					{
						meetVicEntry.Begin();
					}
				}
				if (_stage >= 2)
				{
					QuestEntry meetVicEntry2 = _meetVicEntry;
					if (meetVicEntry2 != null)
					{
						meetVicEntry2.Complete();
					}
					QuestEntry bringWeedEntry = _bringWeedEntry;
					if (bringWeedEntry != null)
					{
						bringWeedEntry.Begin();
					}
				}
				if (_stage >= 3)
				{
					QuestEntry bringWeedEntry2 = _bringWeedEntry;
					if (bringWeedEntry2 != null)
					{
						bringWeedEntry2.Complete();
					}
					((Quest)this).Complete();
				}
			}
			catch (Exception ex)
			{
				OTCLog.Warning("Quest", "OnLoaded rebuild failed: " + ex.Message);
			}
		}
	}
	internal static class QuestIconHelper
	{
		private static readonly Dictionary<int, Sprite> _cache = new Dictionary<int, Sprite>();

		private static string IconPath
		{
			get
			{
				if (Core.OtcIconDir == null)
				{
					return null;
				}
				return Path.Combine(Core.OtcIconDir, "CrimeWareQuest.png");
			}
		}

		internal static Sprite Load()
		{
			if (IconPath == null)
			{
				return null;
			}
			return ImageUtils.LoadImage(IconPath);
		}

		internal static Sprite LoadTinted(Color tint)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			int hashCode = ((object)(Color)(ref tint)).GetHashCode();
			if (_cache.TryGetValue(hashCode, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			try
			{
				byte[] array = File.ReadAllBytes(IconPath);
				Texture2D val = new Texture2D(2, 2);
				if (!ImageConversion.LoadImage(val, Il2CppStructArray<byte>.op_Implicit(array)))
				{
					return Load();
				}
				Il2CppStructArray<Color> pixels = val.GetPixels();
				for (int i = 0; i < ((Il2CppArrayBase<Color>)(object)pixels).Length; i++)
				{
					((Il2CppArrayBase<Color>)(object)pixels)[i] = new Color(((Il2CppArrayBase<Color>)(object)pixels)[i].r * tint.r, ((Il2CppArrayBase<Color>)(object)pixels)[i].g * tint.g, ((Il2CppArrayBase<Color>)(object)pixels)[i].b * tint.b, ((Il2CppArrayBase<Color>)(object)pixels)[i].a);
				}
				val.SetPixels(pixels);
				val.Apply();
				Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
				_cache[hashCode] = val2;
				return val2;
			}
			catch
			{
				return Load();
			}
		}
	}
	internal static class QuestPoiFixer
	{
		[CompilerGenerated]
		private sealed class <FixPositionDelayed>d__2 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Vector3 worldPos;

			public QuestEntry entry;

			private int <i>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <FixPositionDelayed>d__2(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				//IL_0180: Unknown result type (might be due to invalid IL or missing references)
				//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
				//IL_022b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0264: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					OTCLog.Msg("Quest", $"QuestPoiFixer: starting, target={worldPos}");
					<i>5__2 = 0;
					break;
				case 1:
					<>1__state = -1;
					<i>5__2++;
					break;
				}
				if (<i>5__2 < 5)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				try
				{
					if (_s1EntryField == null)
					{
						_s1EntryField = typeof(QuestEntry).GetField("S1QuestEntry", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					}
					OTCLog.Msg("Quest", $"QuestPoiFixer: field={_s1EntryField != null}");
					object? obj = _s1EntryField?.GetValue(entry);
					QuestEntry val = (QuestEntry)((obj is QuestEntry) ? obj : null);
					if ((Object)(object)val == (Object)null)
					{
						OTCLog.Warning("Quest", "QuestPoiFixer: s1Entry is null");
						return false;
					}
					Transform poILocation = val.PoILocation;
					POI poI = val.PoI;
					OTCLog.Msg("Quest", $"QuestPoiFixer: PoILocation={(Object)(object)poILocation != (Object)null} pos={((poILocation != null) ? new Vector3?(poILocation.position) : null)} PoI={(Object)(object)poI != (Object)null} poiPos={((poI != null) ? new Vector3?(((Component)poI).transform.position) : null)}");
					val.SetPoILocation(worldPos);
					DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(63, 2);
					defaultInterpolatedStringHandler.AppendLiteral("QuestPoiFixer: AFTER SetPoILocation → PoILocation.pos=");
					Transform poILocation2 = val.PoILocation;
					defaultInterpolatedStringHandler.AppendFormatted((poILocation2 != null) ? new Vector3?(poILocation2.position) : null);
					defaultInterpolatedStringHandler.AppendLiteral(" PoI.pos=");
					POI poI2 = val.PoI;
					defaultInterpolatedStringHandler.AppendFormatted((poI2 != null) ? new Vector3?(((Component)poI2).transform.position) : null);
					OTCLog.Msg("Quest", defaultInterpolatedStringHandler.ToStringAndClear());
				}
				catch (Exception ex)
				{
					OTCLog.Warning("Quest", "QuestPoiFixer failed: " + ex.Message);
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static FieldInfo _s1EntryField;

		public static void FixPosition(QuestEntry entry, Vector3 worldPos)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (entry != null)
			{
				MelonCoroutines.Start(FixPositionDelayed(entry, worldPos));
			}
		}

		[IteratorStateMachine(typeof(<FixPositionDelayed>d__2))]
		private static IEnumerator FixPositionDelayed(QuestEntry entry, Vector3 worldPos)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <FixPositionDelayed>d__2(0)
			{
				entry = entry,
				worldPos = worldPos
			};
		}
	}
	public class StaticIntroQuest : Quest
	{
		[SaveableField("static_quest_stage")]
		private int _stage;

		private QuestEntry _checkMessagesEntry;

		private QuestEntry _payEntry;

		private QuestEntry _dropOffEntry;

		protected override string Title => "Crimeware as a Service";

		protected override string Description => "Someone noticed your operation. Check the OTC app for a new message.";

		protected override bool AutoBegin => false;

		protected override Sprite QuestIcon => QuestIconHelper.Load();

		public static StaticIntroQuest Instance { get; private set; }

		public int Stage => _stage;

		private static Vector3 DeadDropPosition => CasinoDeadDrop.Position;

		internal static void ResetInstance()
		{
			Instance = null;
		}

		public void Initialize()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_checkMessagesEntry = ((Quest)this).AddEntry("Check your messages in the OTC app", (Vector3?)null);
				_payEntry = ((Quest)this).AddEntry(GetPayText(), (Vector3?)null);
				_dropOffEntry = ((Quest)this).AddEntry(GetDropOffText(), (Vector3?)DeadDropPosition);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "Initialize failed: " + ex.Message);
			}
		}

		private static string GetPayText()
		{
			return $"Pay ${Config.StaticTier1BankCost.Value:N0} via OTC app";
		}

		private static string GetDropOffText()
		{
			return $"Drop off {Config.StaticTier1WeedGrams.Value}g weed at the casino dead drop";
		}

		public void RefreshEntryText()
		{
			if (_payEntry != null && _stage >= 2 && _stage < 4)
			{
				_payEntry.Title = GetPayText();
			}
			if (_dropOffEntry != null && _stage >= 2 && _stage < 4)
			{
				_dropOffEntry.Title = GetDropOffText();
			}
		}

		public void StartQuest()
		{
			try
			{
				_stage = 1;
				((Quest)this).Begin();
				QuestEntry checkMessagesEntry = _checkMessagesEntry;
				if (checkMessagesEntry != null)
				{
					checkMessagesEntry.Begin();
				}
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "StartQuest failed: " + ex.Message);
			}
		}

		public void CompleteObj1()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_stage = 2;
				QuestEntry checkMessagesEntry = _checkMessagesEntry;
				if (checkMessagesEntry != null)
				{
					checkMessagesEntry.Begin();
				}
				QuestEntry checkMessagesEntry2 = _checkMessagesEntry;
				if (checkMessagesEntry2 != null)
				{
					checkMessagesEntry2.Complete();
				}
				QuestEntry payEntry = _payEntry;
				if (payEntry != null)
				{
					payEntry.Begin();
				}
				QuestEntry dropOffEntry = _dropOffEntry;
				if (dropOffEntry != null)
				{
					dropOffEntry.Begin();
				}
				QuestPoiFixer.FixPosition(_dropOffEntry, DeadDropPosition);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "CompleteObj1 failed: " + ex.Message);
			}
		}

		public void CompleteObj2()
		{
			try
			{
				_stage = 3;
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "CompleteObj2 failed: " + ex.Message);
			}
		}

		public void CompleteObj3()
		{
			try
			{
				_stage = 4;
				QuestEntry payEntry = _payEntry;
				if (payEntry != null)
				{
					payEntry.Begin();
				}
				QuestEntry payEntry2 = _payEntry;
				if (payEntry2 != null)
				{
					payEntry2.Complete();
				}
				QuestEntry dropOffEntry = _dropOffEntry;
				if (dropOffEntry != null)
				{
					dropOffEntry.Begin();
				}
				QuestEntry dropOffEntry2 = _dropOffEntry;
				if (dropOffEntry2 != null)
				{
					dropOffEntry2.Complete();
				}
				((Quest)this).Complete();
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "CompleteObj3 failed: " + ex.Message);
			}
		}

		public void CompletePay()
		{
			QuestEntry payEntry = _payEntry;
			if (payEntry != null)
			{
				payEntry.Begin();
			}
			QuestEntry payEntry2 = _payEntry;
			if (payEntry2 != null)
			{
				payEntry2.Complete();
			}
			QuestEntry dropOffEntry = _dropOffEntry;
			if (dropOffEntry != null)
			{
				dropOffEntry.Begin();
			}
		}

		public void CompleteDropOff()
		{
			QuestEntry dropOffEntry = _dropOffEntry;
			if (dropOffEntry != null)
			{
				dropOffEntry.Begin();
			}
			QuestEntry dropOffEntry2 = _dropOffEntry;
			if (dropOffEntry2 != null)
			{
				dropOffEntry2.Complete();
			}
		}

		protected override void OnCreated()
		{
			((Registerable)this).OnCreated();
			Instance = this;
		}

		protected override void OnLoaded()
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			((Saveable)this).OnLoaded();
			Instance = this;
			try
			{
				if (StaticSaveData.Instance != null)
				{
					int num = ((StaticSaveData.Instance.CrmTier >= 1) ? 4 : (StaticSaveData.Instance.IntroCompleted ? 2 : (StaticSaveData.Instance.QuestTriggered ? 1 : 0)));
					if (num > _stage)
					{
						_stage = num;
					}
				}
				base.QuestEntries.Clear();
				_checkMessagesEntry = ((Quest)this).AddEntry("Check your messages in the OTC app", (Vector3?)null);
				_payEntry = ((Quest)this).AddEntry(GetPayText(), (Vector3?)null);
				_dropOffEntry = ((Quest)this).AddEntry(GetDropOffText(), (Vector3?)DeadDropPosition);
				if (_stage >= 1)
				{
					QuestEntry checkMessagesEntry = _checkMessagesEntry;
					if (checkMessagesEntry != null)
					{
						checkMessagesEntry.Begin();
					}
				}
				if (_stage >= 2)
				{
					QuestEntry checkMessagesEntry2 = _checkMessagesEntry;
					if (checkMessagesEntry2 != null)
					{
						checkMessagesEntry2.Complete();
					}
					QuestEntry payEntry = _payEntry;
					if (payEntry != null)
					{
						payEntry.Begin();
					}
					QuestEntry dropOffEntry = _dropOffEntry;
					if (dropOffEntry != null)
					{
						dropOffEntry.Begin();
					}
					QuestPoiFixer.FixPosition(_dropOffEntry, DeadDropPosition);
				}
				if (_stage >= 2 && _stage < 4 && StaticSaveData.Instance != null)
				{
					if (StaticSaveData.Instance.Tier1MoneyPaid)
					{
						CompletePay();
					}
					if (StaticSaveData.Instance.Tier1ProductDelivered)
					{
						CompleteDropOff();
					}
				}
				if (_stage >= 4)
				{
					QuestEntry payEntry2 = _payEntry;
					if (payEntry2 != null)
					{
						payEntry2.Complete();
					}
					QuestEntry dropOffEntry2 = _dropOffEntry;
					if (dropOffEntry2 != null)
					{
						dropOffEntry2.Complete();
					}
					((Quest)this).Complete();
				}
			}
			catch (Exception ex)
			{
				OTCLog.Warning("Quest", "OnLoaded rebuild failed: " + ex.Message);
			}
		}
	}
	public class StaticUpgrade1Quest : Quest
	{
		[SaveableField("static_upgrade1_stage")]
		private int _stage;

		private QuestEntry _payEntry;

		private QuestEntry _dropOffEntry;

		protected override string Title => "Premium Tier";

		protected override string Description => "Static has the premium tier upgrade available. Pay and deliver via the OTC app.";

		protected override bool AutoBegin => false;

		protected override Sprite QuestIcon => QuestIconHelper.Load();

		public static StaticUpgrade1Quest Instance { get; private set; }

		public int Stage => _stage;

		internal static void ResetInstance()
		{
			Instance = null;
		}

		public void Initialize()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_payEntry = ((Quest)this).AddEntry(GetPayText(), (Vector3?)null);
				_dropOffEntry = ((Quest)this).AddEntry(GetDropOffText(), (Vector3?)CasinoDeadDrop.Position);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "Initialize failed: " + ex.Message);
			}
		}

		private static string GetPayText()
		{
			return $"Pay ${Config.StaticTier2BankCost.Value:N0} via OTC app";
		}

		private static string GetDropOffText()
		{
			return $"Drop off {Config.StaticTier2MethGrams.Value}g meth at the casino dead drop";
		}

		public void RefreshEntryText()
		{
			if (_payEntry != null && _stage >= 1 && _stage < 2)
			{
				_payEntry.Title = GetPayText();
			}
			if (_dropOffEntry != null && _stage >= 1 && _stage < 2)
			{
				_dropOffEntry.Title = GetDropOffText();
			}
		}

		public void StartQuest()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_stage = 1;
				((Quest)this).Begin();
				QuestEntry payEntry = _payEntry;
				if (payEntry != null)
				{
					payEntry.Begin();
				}
				QuestEntry dropOffEntry = _dropOffEntry;
				if (dropOffEntry != null)
				{
					dropOffEntry.Begin();
				}
				QuestPoiFixer.FixPosition(_dropOffEntry, CasinoDeadDrop.Position);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "StartQuest failed: " + ex.Message);
			}
		}

		public void CompleteObj1()
		{
			try
			{
				_stage = 2;
				QuestEntry payEntry = _payEntry;
				if (payEntry != null)
				{
					payEntry.Begin();
				}
				QuestEntry payEntry2 = _payEntry;
				if (payEntry2 != null)
				{
					payEntry2.Complete();
				}
				QuestEntry dropOffEntry = _dropOffEntry;
				if (dropOffEntry != null)
				{
					dropOffEntry.Begin();
				}
				QuestEntry dropOffEntry2 = _dropOffEntry;
				if (dropOffEntry2 != null)
				{
					dropOffEntry2.Complete();
				}
				((Quest)this).Complete();
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "CompleteObj1 failed: " + ex.Message);
			}
		}

		public void CompletePay()
		{
			QuestEntry payEntry = _payEntry;
			if (payEntry != null)
			{
				payEntry.Begin();
			}
			QuestEntry payEntry2 = _payEntry;
			if (payEntry2 != null)
			{
				payEntry2.Complete();
			}
			QuestEntry dropOffEntry = _dropOffEntry;
			if (dropOffEntry != null)
			{
				dropOffEntry.Begin();
			}
		}

		public void CompleteDropOff()
		{
			QuestEntry dropOffEntry = _dropOffEntry;
			if (dropOffEntry != null)
			{
				dropOffEntry.Begin();
			}
			QuestEntry dropOffEntry2 = _dropOffEntry;
			if (dropOffEntry2 != null)
			{
				dropOffEntry2.Complete();
			}
		}

		protected override void OnCreated()
		{
			((Registerable)this).OnCreated();
			Instance = this;
		}

		protected override void OnLoaded()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			((Saveable)this).OnLoaded();
			Instance = this;
			try
			{
				base.QuestEntries.Clear();
				_payEntry = ((Quest)this).AddEntry(GetPayText(), (Vector3?)null);
				_dropOffEntry = ((Quest)this).AddEntry(GetDropOffText(), (Vector3?)CasinoDeadDrop.Position);
				if (_stage >= 1)
				{
					QuestEntry payEntry = _payEntry;
					if (payEntry != null)
					{
						payEntry.Begin();
					}
					QuestEntry dropOffEntry = _dropOffEntry;
					if (dropOffEntry != null)
					{
						dropOffEntry.Begin();
					}
					QuestPoiFixer.FixPosition(_dropOffEntry, CasinoDeadDrop.Position);
				}
				if (_stage >= 1 && _stage < 2 && StaticSaveData.Instance != null)
				{
					if (StaticSaveData.Instance.UpgradeMoneyPaid)
					{
						CompletePay();
					}
					if (StaticSaveData.Instance.UpgradeProductDelivered)
					{
						CompleteDropOff();
					}
				}
				if (_stage >= 2)
				{
					QuestEntry payEntry2 = _payEntry;
					if (payEntry2 != null)
					{
						payEntry2.Complete();
					}
					QuestEntry dropOffEntry2 = _dropOffEntry;
					if (dropOffEntry2 != null)
					{
						dropOffEntry2.Complete();
					}
					((Quest)this).Complete();
				}
			}
			catch (Exception ex)
			{
				OTCLog.Warning("Quest", "OnLoaded rebuild failed: " + ex.Message);
			}
		}
	}
	public class StaticUpgrade2Quest : Quest
	{
		[SaveableField("static_upgrade2_stage")]
		private int _stage;

		private QuestEntry _payEntry;

		private QuestEntry _dropOffEntry;

		protected override string Title => "Full Scale";

		protected override string Description => "Static has the final tier-3 enterprise upgrade available. Pay and deliver via the OTC app.";

		protected override bool AutoBegin => false;

		protected override Sprite QuestIcon => QuestIconHelper.Load();

		public static StaticUpgrade2Quest Instance { get; private set; }

		public int Stage => _stage;

		internal static void ResetInstance()
		{
			Instance = null;
		}

		public void Initialize()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_payEntry = ((Quest)this).AddEntry(GetPayText(), (Vector3?)null);
				_dropOffEntry = ((Quest)this).AddEntry(GetDropOffText(), (Vector3?)CasinoDeadDrop.Position);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "Initialize failed: " + ex.Message);
			}
		}

		private static string GetPayText()
		{
			return $"Pay ${Config.StaticTier3BankCost.Value:N0} via OTC app";
		}

		private static string GetDropOffText()
		{
			return $"Drop off {Config.StaticTier3PremiumMethGrams.Value}g premium meth at the casino dead drop";
		}

		public void RefreshEntryText()
		{
			if (_payEntry != null && _stage >= 1 && _stage < 2)
			{
				_payEntry.Title = GetPayText();
			}
			if (_dropOffEntry != null && _stage >= 1 && _stage < 2)
			{
				_dropOffEntry.Title = GetDropOffText();
			}
		}

		public void StartQuest()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_stage = 1;
				((Quest)this).Begin();
				QuestEntry payEntry = _payEntry;
				if (payEntry != null)
				{
					payEntry.Begin();
				}
				QuestEntry dropOffEntry = _dropOffEntry;
				if (dropOffEntry != null)
				{
					dropOffEntry.Begin();
				}
				QuestPoiFixer.FixPosition(_dropOffEntry, CasinoDeadDrop.Position);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "StartQuest failed: " + ex.Message);
			}
		}

		public void CompleteObj1()
		{
			try
			{
				_stage = 2;
				QuestEntry payEntry = _payEntry;
				if (payEntry != null)
				{
					payEntry.Begin();
				}
				QuestEntry payEntry2 = _payEntry;
				if (payEntry2 != null)
				{
					payEntry2.Complete();
				}
				QuestEntry dropOffEntry = _dropOffEntry;
				if (dropOffEntry != null)
				{
					dropOffEntry.Begin();
				}
				QuestEntry dropOffEntry2 = _dropOffEntry;
				if (dropOffEntry2 != null)
				{
					dropOffEntry2.Complete();
				}
				((Quest)this).Complete();
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "CompleteObj1 failed: " + ex.Message);
			}
		}

		public void CompletePay()
		{
			QuestEntry payEntry = _payEntry;
			if (payEntry != null)
			{
				payEntry.Begin();
			}
			QuestEntry payEntry2 = _payEntry;
			if (payEntry2 != null)
			{
				payEntry2.Complete();
			}
			QuestEntry dropOffEntry = _dropOffEntry;
			if (dropOffEntry != null)
			{
				dropOffEntry.Begin();
			}
		}

		public void CompleteDropOff()
		{
			QuestEntry dropOffEntry = _dropOffEntry;
			if (dropOffEntry != null)
			{
				dropOffEntry.Begin();
			}
			QuestEntry dropOffEntry2 = _dropOffEntry;
			if (dropOffEntry2 != null)
			{
				dropOffEntry2.Complete();
			}
		}

		protected override void OnCreated()
		{
			((Registerable)this).OnCreated();
			Instance = this;
		}

		protected override void OnLoaded()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			((Saveable)this).OnLoaded();
			Instance = this;
			try
			{
				base.QuestEntries.Clear();
				_payEntry = ((Quest)this).AddEntry(GetPayText(), (Vector3?)null);
				_dropOffEntry = ((Quest)this).AddEntry(GetDropOffText(), (Vector3?)CasinoDeadDrop.Position);
				if (_stage >= 1)
				{
					QuestEntry payEntry = _payEntry;
					if (payEntry != null)
					{
						payEntry.Begin();
					}
					QuestEntry dropOffEntry = _dropOffEntry;
					if (dropOffEntry != null)
					{
						dropOffEntry.Begin();
					}
					QuestPoiFixer.FixPosition(_dropOffEntry, CasinoDeadDrop.Position);
				}
				if (_stage >= 1 && _stage < 2 && StaticSaveData.Instance != null)
				{
					if (StaticSaveData.Instance.UpgradeMoneyPaid)
					{
						CompletePay();
					}
					if (StaticSaveData.Instance.UpgradeProductDelivered)
					{
						CompleteDropOff();
					}
				}
				if (_stage >= 2)
				{
					QuestEntry payEntry2 = _payEntry;
					if (payEntry2 != null)
					{
						payEntry2.Complete();
					}
					QuestEntry dropOffEntry2 = _dropOffEntry;
					if (dropOffEntry2 != null)
					{
						dropOffEntry2.Complete();
					}
					((Quest)this).Complete();
				}
			}
			catch (Exception ex)
			{
				OTCLog.Warning("Quest", "OnLoaded rebuild failed: " + ex.Message);
			}
		}
	}
	public class DrifterDealQuest : Quest
	{
		private string _title;

		private string _description;

		private QuestEntry _deliverEntry;

		private int _deadlineElapsedMinutes;

		protected override string Title => _title ?? "Drifter Deal";

		protected override string Description => _description ?? "Complete a deal with a drifter.";

		protected override bool AutoBegin => false;

		protected override Sprite QuestIcon
		{
			get
			{
				if (Core.OtcIconDir == null)
				{
					return null;
				}
				return ImageUtils.LoadImage(Path.Combine(Core.OtcIconDir, "DrifterQuestIcon.png"));
			}
		}

		public string DrifterId { get; private set; }

		public static Dictionary<string, DrifterDealQuest> ActiveQuests { get; } = new Dictionary<string, DrifterDealQuest>();


		private Quest GetS1Quest()
		{
			object? obj = typeof(Quest).GetField("S1Quest", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(this);
			return (Quest)((obj is Quest) ? obj : null);
		}

		private void TriggerInternalInit()
		{
			try
			{
				Quest s1Quest = GetS1Quest();
				if (!((Object)(object)s1Quest == (Object)null))
				{
					s1Quest.InitializeQuest(((Quest)this).Title, ((Quest)this).Description, Il2CppReferenceArray<QuestEntryData>.op_Implicit(Array.Empty<QuestEntryData>()), s1Quest.StaticGUID);
				}
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "TriggerInternalInit failed: " + ex.Message);
			}
		}

		public void Initialize(string drifterId, string productName, int quantity, float payment, Vector3 destination, string locationDesc, int deadlineElapsedMinutes)
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			DrifterId = drifterId;
			_title = "Drifter Deal";
			_description = $"Deliver {quantity} {productName} for ${payment:F0}";
			_deadlineElapsedMinutes = deadlineElapsedMinutes;
			TriggerInternalInit();
			_deliverEntry = ((Quest)this).AddEntry($"Deliver {quantity} {productName} to the drifter {locationDesc}", (Vector3?)destination);
			ActiveQuests[drifterId] = this;
		}

		public void StartQuest()
		{
			try
			{
				((Quest)this).Begin();
				QuestEntry deliverEntry = _deliverEntry;
				if (deliverEntry != null)
				{
					deliverEntry.Begin();
				}
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "StartQuest failed: " + ex.Message);
			}
		}

		public void UpdateTiming()
		{
			try
			{
				if (_deadlineElapsedMinutes > 0)
				{
					int currentElapsedMinutes = GetCurrentElapsedMinutes();
					int num = _deadlineElapsedMinutes - currentElapsedMinutes;
					if (num < 0)
					{
						num = 0;
					}
					int num2 = num / 60;
					int value = num % 60;
					string subtitleViaReflection = ((num >= 120) ? $"<color=green> (Expires in {num2}h {value}m)</color>" : ((num2 <= 0) ? $"<color=#ff6b6b> (Expires in {num} min)</color>" : $"<color=#ff6b6b> (Expires in {num2}h {value}m)</color>"));
					SetSubtitleViaReflection(subtitleViaReflection);
				}
			}
			catch (Exception ex)
			{
				OTCLog.Warning("Quest", "UpdateTiming failed: " + ex.Message);
			}
		}

		private void SetSubtitleViaReflection(string subtitle)
		{
			try
			{
				Quest s1Quest = GetS1Quest();
				if (!((Object)(object)s1Quest == (Object)null))
				{
					s1Quest.SetSubtitle(subtitle);
					if ((Object)(object)s1Quest.hudUI != (Object)null)
					{
						s1Quest.hudUI.UpdateMainLabel();
					}
				}
			}
			catch (Exception ex)
			{
				OTCLog.Warning("Quest", "SetSubtitleViaReflection failed: " + ex.Message);
			}
		}

		private static int GetCurrentElapsedMinutes()
		{
			int elapsedDays = TimeManager.ElapsedDays;
			int currentTime = TimeManager.CurrentTime;
			int num = currentTime / 100;
			int num2 = currentTime % 100;
			return elapsedDays * 1440 + num * 60 + num2;
		}

		public void CompleteDeal()
		{
			try
			{
				QuestEntry deliverEntry = _deliverEntry;
				if (deliverEntry != null)
				{
					deliverEntry.Complete();
				}
				((Quest)this).Complete();
				((Quest)this).End();
				ActiveQuests.Remove(DrifterId);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "CompleteDeal failed: " + ex.Message);
			}
		}

		public void FailDeal()
		{
			try
			{
				QuestEntry deliverEntry = _deliverEntry;
				if (deliverEntry != null)
				{
					deliverEntry.Complete();
				}
				((Quest)this).Fail();
				ActiveQuests.Remove(DrifterId);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "FailDeal failed: " + ex.Message);
			}
		}

		public void CancelDeal()
		{
			try
			{
				((Quest)this).Cancel();
				ActiveQuests.Remove(DrifterId);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "CancelDeal failed: " + ex.Message);
			}
		}
	}
	public enum QuestHighlight
	{
		None,
		InventoryNav,
		PricingArea,
		ProductRows,
		OverviewNav,
		StoreToggle
	}
	public class StorefrontGrowthQuest : Quest
	{
		[SaveableField("storefront_quest_stage")]
		private int _stage;

		[SaveableField("storefront_quest_touched_pricing")]
		private bool _hasTouchedPricing;

		[SaveableField("storefront_quest_viewed_product")]
		private bool _hasViewedProduct;

		private QuestEntry _placeStorageEntry;

		private QuestEntry _stockProductEntry;

		private QuestEntry _setPricesEntry;

		private QuestEntry _viewProductEntry;

		private QuestEntry _turnOnLightsEntry;

		private QuestEntry _openStoreEntry;

		private QuestEntry _makeSaleEntry;

		private static readonly Vector3 ShackPosition = new Vector3(-164.4f, -3f, 76f);

		private float _lastTickTime;

		private const float TickInterval = 3f;

		private TutorialCustomerHelper _tutorialCustomer;

		protected override string Title => "Storefront Growth";

		protected override string Description => "You've got the keys. Now turn this place into a working storefront.";

		protected override bool AutoBegin => false;

		protected override Sprite QuestIcon
		{
			get
			{
				if (Core.OtcIconDir == null)
				{
					return null;
				}
				return ImageUtils.LoadImage(Path.Combine(Core.OtcIconDir, "StoreAlertIcon.png"));
			}
		}

		public static StorefrontGrowthQuest Instance { get; private set; }

		public int Stage => _stage;

		public static QuestHighlight ActiveHighlight
		{
			get
			{
				if (Instance == null)
				{
					return QuestHighlight.None;
				}
				return Instance._stage switch
				{
					3 => QuestHighlight.InventoryNav, 
					4 => QuestHighlight.InventoryNav, 
					6 => QuestHighlight.OverviewNav, 
					_ => QuestHighlight.None, 
				};
			}
		}

		internal static void ResetInstance()
		{
			Instance = null;
		}

		private TutorialCustomerHelper GetTutorialCustomer()
		{
			return _tutorialCustomer ?? (_tutorialCustomer = new TutorialCustomerHelper("westville_shack", () => WestvilleShack.IsStoreOpen, () => WestvilleShack.Target));
		}

		private void TriggerInternalInit()
		{
			try
			{
				FieldInfo field = typeof(Quest).GetField("S1Quest", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field == null))
				{
					object? value = field.GetValue(this);
					Quest val = (Quest)((value is Quest) ? value : null);
					if (!((Object)(object)val == (Object)null))
					{
						val.InitializeQuest(((Quest)this).Title, ((Quest)this).Description, Il2CppReferenceArray<QuestEntryData>.op_Implicit(Array.Empty<QuestEntryData>()), val.StaticGUID);
					}
				}
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "StorefrontGrowth TriggerInternalInit failed: " + ex.Message);
			}
		}

		public void Initialize()
		{
			try
			{
				TriggerInternalInit();
				BuildEntries();
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "StorefrontGrowth Initialize failed: " + ex.Message);
			}
		}

		private void BuildEntries()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			_placeStorageEntry = ((Quest)this).AddEntry("Place a Display Cabinet or any storage in your new dispensary", (Vector3?)ShackPosition);
			_stockProductEntry = ((Quest)this).AddEntry("Stock your shelves with packaged weed", (Vector3?)ShackPosition);
			_setPricesEntry = ((Quest)this).AddEntry("Open the GreenTab app and set your product prices", (Vector3?)ShackPosition);
			_viewProductEntry = ((Quest)this).AddEntry("Click on a product in the Inventory tab to view its details", (Vector3?)ShackPosition);
			_turnOnLightsEntry = ((Quest)this).AddEntry("Turn on the lights using the light switch on the wall", (Vector3?)ShackPosition);
			_openStoreEntry = ((Quest)this).AddEntry("Open the store using the GreenTab app on your phone", (Vector3?)ShackPosition);
			_makeSaleEntry = ((Quest)this).AddEntry("Make your first sale. A customer is on their way!", (Vector3?)ShackPosition);
		}

		public void StartQuest()
		{
			try
			{
				_stage = 1;
				((Quest)this).Begin();
				QuestEntry placeStorageEntry = _placeStorageEntry;
				if (placeStorageEntry != null)
				{
					placeStorageEntry.Begin();
				}
				SubscribeSaleEvent();
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "StorefrontGrowth StartQuest failed: " + ex.Message);
			}
		}

		public void OnPricingTouched()
		{
			if (_stage == 3)
			{
				_hasTouchedPricing = true;
			}
		}

		public void OnProductViewed()
		{
			if (_stage == 4)
			{
				_hasViewedProduct = true;
			}
	

OverTheCounter.Mono.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using EPOOutline;
using FishNet;
using FishNet.Component.Ownership;
using FishNet.Connection;
using FishNet.Managing;
using FishNet.Managing.Object;
using FishNet.Object;
using FishNet.Observing;
using HarmonyLib;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using MeshVault;
using Microsoft.CodeAnalysis;
using OverTheCounter;
using OverTheCounter.Apps;
using OverTheCounter.Logic;
using OverTheCounter.Logic.Placement;
using OverTheCounter.NPCs;
using OverTheCounter.Patches;
using OverTheCounter.Quests;
using OverTheCounter.SaveData;
using OverTheCounter.UI;
using OverTheCounter.Utilities;
using S1API.Entities;
using S1API.Entities.Appearances.AccessoryFields;
using S1API.Entities.Appearances.BodyLayerFields;
using S1API.Entities.Appearances.CustomizationFields;
using S1API.Entities.Appearances.FaceLayerFields;
using S1API.Entities.Dialogue;
using S1API.Entities.Schedule;
using S1API.GameTime;
using S1API.Internal.Abstraction;
using S1API.Items;
using S1API.Leveling;
using S1API.Messaging;
using S1API.Misc;
using S1API.Money;
using S1API.PhoneApp;
using S1API.Products;
using S1API.Quests;
using S1API.Saveables;
using S1API.Shops;
using S1API.UI;
using S1API.Utils;
using S1MAPI.Building;
using S1MAPI.Building.Components;
using S1MAPI.Building.Config;
using S1MAPI.Building.Structural;
using S1MAPI.Core;
using S1MAPI.Gltf;
using S1MAPI.ProceduralMesh;
using S1MAPI.S1;
using S1MAPI.Utils;
using ScheduleOne;
using ScheduleOne.Audio;
using ScheduleOne.AvatarFramework;
using ScheduleOne.AvatarFramework.Animation;
using ScheduleOne.AvatarFramework.Equipping;
using ScheduleOne.AvatarFramework.Impostors;
using ScheduleOne.Building;
using ScheduleOne.Cartel;
using ScheduleOne.Combat;
using ScheduleOne.Core.Items.Framework;
using ScheduleOne.DevUtilities;
using ScheduleOne.Dialogue;
using ScheduleOne.Doors;
using ScheduleOne.Economy;
using ScheduleOne.Effects;
using ScheduleOne.Employees;
using ScheduleOne.EntityFramework;
using ScheduleOne.GameTime;
using ScheduleOne.Graffiti;
using ScheduleOne.Interaction;
using ScheduleOne.ItemFramework;
using ScheduleOne.Law;
using ScheduleOne.Levelling;
using ScheduleOne.Lighting;
using ScheduleOne.Management;
using ScheduleOne.Map;
using ScheduleOne.Messaging;
using ScheduleOne.Money;
using ScheduleOne.NPCs;
using ScheduleOne.NPCs.Behaviour;
using ScheduleOne.NPCs.Relation;
using ScheduleOne.Networking;
using ScheduleOne.ObjectScripts;
using ScheduleOne.ObjectScripts.Cash;
using ScheduleOne.Persistence;
using ScheduleOne.Persistence.Datas;
using ScheduleOne.PlayerScripts;
using ScheduleOne.PlayerScripts.Health;
using ScheduleOne.Police;
using ScheduleOne.Product;
using ScheduleOne.Product.Packaging;
using ScheduleOne.Property;
using ScheduleOne.Quests;
using ScheduleOne.StationFramework;
using ScheduleOne.Storage;
using ScheduleOne.Tiles;
using ScheduleOne.Tools;
using ScheduleOne.UI;
using ScheduleOne.UI.Compass;
using ScheduleOne.UI.Handover;
using ScheduleOne.UI.Items;
using ScheduleOne.UI.Management;
using ScheduleOne.UI.Phone;
using ScheduleOne.UI.Phone.ContactsApp;
using ScheduleOne.UI.Phone.Map;
using ScheduleOne.UI.Phone.ProductManagerApp;
using ScheduleOne.UI.Relations;
using ScheduleOne.UI.Shop;
using ScheduleOne.Variables;
using ScheduleOne.Vehicles;
using ScheduleOne.VoiceOver;
using ScheduleOne.Weather;
using SteamNetworkLib;
using SteamNetworkLib.Models;
using SteamNetworkLib.Sync;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
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(Core), "OverTheCounter", "2.0.10", "hdlmrell", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: MelonOptionalDependencies(new string[] { "SteamNetworkLib" })]
[assembly: HarmonyDontPatchAll]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("OverTheCounter.Mono")]
[assembly: AssemblyConfiguration("MonoRelease")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+6b7caa4bc824a2bf8fc9dcdc200bf94491a1a140")]
[assembly: AssemblyProduct("OverTheCounter.Mono")]
[assembly: AssemblyTitle("OverTheCounter.Mono")]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace OverTheCounter
{
	public static class Il2CppCompat
	{
		public static T TryCast<T>(this object obj) where T : class
		{
			return obj as T;
		}

		public static T Cast<T>(this object obj) where T : class
		{
			return (T)obj;
		}
	}
	public static class UnityEventCompat
	{
		public static void AddListener(this UnityEvent ev, Action action)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			ev.AddListener(new UnityAction(action.Invoke));
		}

		public static void RemoveListener(this UnityEvent ev, Action action)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			ev.RemoveListener(new UnityAction(action.Invoke));
		}

		public static void AddListener<T0>(this UnityEvent<T0> ev, Action<T0> action)
		{
			ev.AddListener((UnityAction<T0>)action.Invoke);
		}

		public static void RemoveListener<T0>(this UnityEvent<T0> ev, Action<T0> action)
		{
			ev.RemoveListener((UnityAction<T0>)action.Invoke);
		}
	}
	internal static class PrivateAccess
	{
		private static readonly FieldInfo _voeDatabase = AccessTools.Field(typeof(VOEmitter), "Database");

		private static readonly FieldInfo _customerData = AccessTools.Field(typeof(Customer), "customerData");

		private static readonly FieldInfo _questTitle = AccessTools.Field(typeof(Quest), "title");

		private static readonly FieldInfo _dcHandler = AccessTools.Field(typeof(DialogueController), "handler");

		private static readonly FieldInfo _questEntryUI = AccessTools.Field(typeof(QuestEntry), "entryUI");

		private static readonly FieldInfo _miConfigPanels = AccessTools.Field(typeof(ManagementInterface), "ConfigPanelPrefabs");

		private static readonly PropertyInfo _npcMsgConv = AccessTools.Property(typeof(NPC), "MSGConversation");

		private static readonly PropertyInfo _npcCurrentBuilding = AccessTools.Property(typeof(NPC), "CurrentBuilding");

		private static readonly PropertyInfo _custTimeDealCompleted = AccessTools.Property(typeof(Customer), "TimeSinceLastDealCompleted");

		private static readonly PropertyInfo _custTimeDealOffered = AccessTools.Property(typeof(Customer), "TimeSinceLastDealOffered");

		private static readonly PropertyInfo _custOfferedContract = AccessTools.Property(typeof(Customer), "OfferedContractInfo");

		private static readonly PropertyInfo _custPoI = AccessTools.Property(typeof(Customer), "potentialCustomerPoI");

		private static readonly FieldInfo _hsCustomerSlots = AccessTools.Field(typeof(HandoverScreen), "CustomerSlots");

		private static readonly FieldInfo _hsOriginalItemLocations = AccessTools.Field(typeof(HandoverScreen), "OriginalItemLocations");

		private static readonly Type _hsEItemSource = typeof(HandoverScreen).GetNestedType("EItemSource", BindingFlags.NonPublic);

		private static readonly object _hsEItemSourcePlayer = ((_hsEItemSource != null) ? Enum.Parse(_hsEItemSource, "Player") : null);

		public static VODatabase GetDatabase(this VOEmitter emitter)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			return (VODatabase)(_voeDatabase?.GetValue(emitter));
		}

		public static CustomerData GetCustData(this Customer customer)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			return (CustomerData)(_customerData?.GetValue(customer));
		}

		public static void SetCustData(this Customer customer, CustomerData data)
		{
			_customerData?.SetValue(customer, data);
		}

		public static string GetTitle(this Quest quest)
		{
			return (string)_questTitle?.GetValue(quest);
		}

		public static void SetTitle(this Quest quest, string value)
		{
			_questTitle?.SetValue(quest, value);
		}

		public static DialogueHandler GetHandler(this DialogueController dc)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			return (DialogueHandler)(_dcHandler?.GetValue(dc));
		}

		public static ConfigurableTypePanel[] GetConfigPanelPrefabs(this ManagementInterface mi)
		{
			return (ConfigurableTypePanel[])_miConfigPanels?.GetValue(mi);
		}

		public static MSGConversation GetMSGConversation(this NPC npc)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			return (MSGConversation)(_npcMsgConv?.GetValue(npc));
		}

		public static void SetMSGConversation(this NPC npc, MSGConversation conv)
		{
			_npcMsgConv?.SetValue(npc, conv);
		}

		public static void SetCurrentBuilding(this NPC npc, NPCEnterableBuilding building)
		{
			_npcCurrentBuilding?.SetValue(npc, building);
		}

		public static void SetTimeSinceLastDealCompleted(this Customer customer, int value)
		{
			_custTimeDealCompleted?.SetValue(customer, value);
		}

		public static void SetTimeSinceLastDealOffered(this Customer customer, int value)
		{
			_custTimeDealOffered?.SetValue(customer, value);
		}

		public static ContractInfo GetOfferedContractInfo(this Customer customer)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			return (ContractInfo)(_custOfferedContract?.GetValue(customer));
		}

		public static void SetOfferedContractInfo(this Customer customer, ContractInfo info)
		{
			_custOfferedContract?.SetValue(customer, info);
		}

		public static NPCPoI GetPotentialCustomerPoI(this Customer customer)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			return (NPCPoI)(_custPoI?.GetValue(customer));
		}

		public static void SetPotentialCustomerPoI(this Customer customer, NPCPoI poi)
		{
			_custPoI?.SetValue(customer, poi);
		}

		public static QuestEntryHUDUI GetEntryUI(this QuestEntry entry)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			return (QuestEntryHUDUI)(_questEntryUI?.GetValue(entry));
		}

		public static void SetShouldShowCheck(this DialogueChoice choice, Func<bool, bool> func)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			choice.shouldShowCheck = new ShouldShowCheck(func.Invoke);
		}

		public static ItemSlot[] GetCustomerSlots(this HandoverScreen hs)
		{
			return (ItemSlot[])_hsCustomerSlots?.GetValue(hs);
		}

		public static void TrackItemAsPlayer(this HandoverScreen hs, ItemInstance item)
		{
			object obj = _hsOriginalItemLocations?.GetValue(hs);
			if (obj != null && _hsEItemSourcePlayer != null)
			{
				obj.GetType().GetMethod("set_Item")?.Invoke(obj, new object[2] { item, _hsEItemSourcePlayer });
			}
		}
	}
	public class Core : MelonMod
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static Action<int> <0>__OnSleepEnd;

			public static Action <1>__OnDayPass;

			public static UnityAction <2>__OnGameLoaded;
		}

		private NotificationManager _notificationManager;

		private DesperationManager _desperationManager;

		private DrifterManager _drifterManager;

		private ManagerController _managerManager;

		private CustomerManager _customerManager;

		private bool _multiplayerDepChecked;

		private static bool _meshVaultRegistered;

		private static bool _loadHooked;

		private static bool _budtendersRestored;

		private static UnityAction _onGameLoadedAction;

		private static bool _gameLoadedRan;

		internal static string OtcIconDir { get; private set; }

		public override void OnInitializeMelon()
		{
			DependencyChecker.RunChecks();
			if (DependencyChecker.HasMissingDeps)
			{
				((MelonBase)this).LoggerInstance.Warning("Missing dependencies — mod features disabled. Check the main menu for details.");
			}
			else
			{
				OnInitializeMelonImpl();
			}
		}

		private void OnInitializeMelonImpl()
		{
			Config.Initialize();
			Config.SubscribeToChanges();
			CustomersApp.ApplyHireMeDefaults();
			SafeTypeLoadPatch.Apply(((MelonBase)this).HarmonyInstance);
			foreach (Type validType in MelonUtils.GetValidTypes(typeof(Core).Assembly))
			{
				try
				{
					((MelonBase)this).HarmonyInstance.CreateClassProcessor(validType).Patch();
				}
				catch (Exception ex)
				{
					OTCLog.Error("Patch", "Failed to patch " + validType.FullName + ": " + ex.Message);
				}
			}
			NpcTypeDiscoveryPatch.Apply(((MelonBase)this).HarmonyInstance);
			StackSizePatch.Apply(((MelonBase)this).HarmonyInstance);
			ManagerClipboardPatch.Apply(((MelonBase)this).HarmonyInstance);
			try
			{
				BuildingPlacementPatch.Apply(((MelonBase)this).HarmonyInstance);
			}
			catch (Exception arg)
			{
				OTCLog.Error("Patch", $"BuildingPlacementPatch.Apply failed: {arg}");
			}
			try
			{
				ConfigReplicatorPatch.Apply(((MelonBase)this).HarmonyInstance);
			}
			catch (Exception arg2)
			{
				OTCLog.Error("Patch", $"ConfigReplicatorPatch.Apply failed: {arg2}");
			}
			ContactsAppFix.Apply(((MelonBase)this).HarmonyInstance);
			GraffitiPatch.Apply(((MelonBase)this).HarmonyInstance);
			RecipePinPatch.Apply(((MelonBase)this).HarmonyInstance);
			SupplierWarehousePatch.Apply(((MelonBase)this).HarmonyInstance);
			SupplierFleePatch.Apply(((MelonBase)this).HarmonyInstance);
			SaveManagerPatch.Apply(((MelonBase)this).HarmonyInstance);
			GameProfilerPatches.Apply(((MelonBase)this).HarmonyInstance);
			WeatherPatches.Apply(((MelonBase)this).HarmonyInstance);
			CustomerCheckoutInterceptPatch.Apply(((MelonBase)this).HarmonyInstance);
			TimeManager.OnSleepEnd = (Action<int>)Delegate.Combine(TimeManager.OnSleepEnd, new Action<int>(OnSleepEnd));
			TimeManager.OnDayPass = (Action)Delegate.Combine(TimeManager.OnDayPass, new Action(OnDayPass));
			if (!ConfigSyncData.IsNetworkLibAvailable)
			{
				OTCLog.Warning("Network", "SteamNetworkLib not installed — multiplayer sync disabled. Single-player works fine. Install SteamNetworkLib for co-op support.");
			}
			OTCLog.Msg("Patch", "OverTheCounter Initialized.");
			ImmediateQuestWindowConfig.Register();
			MinimapOverlay.Register();
			HUDOverlay.Register();
			StoreAlertOverlay.Register();
			RecipeOverlay.Register();
			ExtractIcons();
			_notificationManager = new NotificationManager();
			_desperationManager = new DesperationManager();
			_drifterManager = new DrifterManager();
			_managerManager = new ManagerController();
			_customerManager = new CustomerManager();
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			if (DependencyChecker.HasMissingDeps)
			{
				if (sceneName == "Menu")
				{
					DependencyChecker.ShowPopup();
				}
			}
			else
			{
				OnSceneWasLoadedImpl(buildIndex, sceneName);
			}
		}

		private void OnSceneWasLoadedImpl(int buildIndex, string sceneName)
		{
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Expected O, but got Unknown
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Expected O, but got Unknown
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Expected O, but got Unknown
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Expected O, but got Unknown
			StaticSaveData.ResetInstance();
			StaticThreadSaveData.ResetInstance();
			PropertySaveData.ResetInstance();
			PricingSaveData.ResetInstance();
			VicSaveData.ResetInstance();
			BellaSaveData.ResetInstance();
			StaticIntroQuest.ResetInstance();
			StaticUpgrade1Quest.ResetInstance();
			StaticUpgrade2Quest.ResetInstance();
			VicIntroQuest.ResetInstance();
			BellaProtocolQuest.ResetInstance();
			StorefrontGrowthQuest.ResetInstance();
			StorefrontExpansionQuest.ResetInstance();
			BellaSummonPatch.Reset();
			try
			{
				(typeof(Saveable).Assembly.GetType("S1API.Saveables.SaveableAutoRegistry")?.GetMethod("ClearCache", BindingFlags.Static | BindingFlags.NonPublic))?.Invoke(null, null);
				OTCLog.Msg("Patch", "Cleared S1API SaveableAutoRegistry cache");
			}
			catch (Exception ex)
			{
				OTCLog.Warning("Patch", "Failed to clear SaveableAutoRegistry: " + ex.Message);
			}
			DrifterInstance.CleanupAll();
			CustomerInstance.CleanupAll();
			DrifterSpawner.ResetCache();
			BudtenderInstance.CleanupAll();
			_budtendersRestored = false;
			ManagerSaveData.ResetInstance();
			ManagerInstance.CleanupAll();
			ManagerSpawner.ResetCache();
			MugshotUtility.ResetSession();
			if (!Object.op_Implicit((Object)(object)GameObject.Find("OTC_MinimapController")))
			{
				GameObject val = new GameObject("OTC_MinimapController");
				val.AddComponent<MinimapOverlay>();
				Object.DontDestroyOnLoad((Object)(object)val);
			}
			if (!Object.op_Implicit((Object)(object)GameObject.Find("OTC_HUDOverlay")))
			{
				GameObject val2 = new GameObject("OTC_HUDOverlay");
				val2.AddComponent<HUDOverlay>();
				Object.DontDestroyOnLoad((Object)(object)val2);
			}
			if (!Object.op_Implicit((Object)(object)GameObject.Find("OTC_RecipeOverlay")))
			{
				GameObject val3 = new GameObject("OTC_RecipeOverlay");
				val3.AddComponent<RecipeOverlay>();
				Object.DontDestroyOnLoad((Object)(object)val3);
			}
			if (!Object.op_Implicit((Object)(object)GameObject.Find("OTC_StoreAlertOverlay")))
			{
				GameObject val4 = new GameObject("OTC_StoreAlertOverlay");
				val4.AddComponent<StoreAlertOverlay>();
				Object.DontDestroyOnLoad((Object)(object)val4);
			}
			WeatherPatches.Cleanup();
			MapBuildingOverlay.Clear();
			CheckoutCounter.Cleanup();
			WestvilleShack.Cleanup();
			Dispensary.Cleanup();
			OTCWarehouse.Cleanup();
			OTCSupplierArea.Cleanup();
			CasinoDeadDrop.Cleanup();
			CheckoutProcess.ResetStatic();
			CustomerSpawnPoints.Cleanup();
			BuildingGridFactory.Cleanup();
			_loadHooked = false;
			_gameLoadedRan = false;
		}

		public override void OnSceneWasInitialized(int buildIndex, string sceneName)
		{
			if (!DependencyChecker.HasMissingDeps)
			{
				OnSceneWasInitializedImpl(buildIndex, sceneName);
			}
		}

		private void OnSceneWasInitializedImpl(int buildIndex, string sceneName)
		{
			if (!(sceneName == "Main"))
			{
				return;
			}
			MeshVaultAPI.Init();
			if (!_meshVaultRegistered)
			{
				bool flag = false;
				bool flag2 = false;
				try
				{
					byte[] array = EmbeddedResourceLoader.LoadBytes("OverTheCounter.Resources.MeshDatabase.json", Assembly.GetExecutingAssembly());
					if (array != null)
					{
						MeshVaultAPI.RegisterMeshes("otc", "OverTheCounter", Encoding.UTF8.GetString(array));
						flag = true;
					}
				}
				catch (Exception ex)
				{
					OTCLog.Warning("Patch", "OTC mesh registration failed: " + ex.Message);
				}
				try
				{
					MeshVaultAPI.RegisterDecals("otc", "OverTheCounter", Assembly.GetExecutingAssembly(), "OverTheCounter.Resources.MeshVaultDecals.");
					flag2 = true;
				}
				catch (Exception ex2)
				{
					OTCLog.Warning("Patch", "OTC decal registration failed: " + ex2.Message);
				}
				_meshVaultRegistered = flag || flag2;
			}
			CheckoutCounter.Register();
			WestvilleShack.SpawnBuilding();
			Dispensary.SpawnBuilding();
			OTCWarehouse.Initialize();
			OTCSupplierArea.Initialize(OTCWarehouse.BuildingTransform);
			HookLoadComplete();
			CheckoutCounter.AddToShop();
		}

		private static void HookLoadComplete()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (_loadHooked)
			{
				return;
			}
			try
			{
				if (_onGameLoadedAction == null)
				{
					object obj = <>O.<2>__OnGameLoaded;
					if (obj == null)
					{
						UnityAction val = OnGameLoaded;
						<>O.<2>__OnGameLoaded = val;
						obj = (object)val;
					}
					_onGameLoadedAction = (UnityAction)obj;
				}
				LoadManager instance = Singleton<LoadManager>.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					instance.onLoadComplete.RemoveListener(_onGameLoadedAction);
					instance.onLoadComplete.AddListener(_onGameLoadedAction);
					_loadHooked = true;
					OTCLog.Msg("Patch", "Hooked LoadManager.onLoadComplete");
				}
				else
				{
					OTCLog.Warning("Patch", "LoadManager.Instance is null — cannot hook onLoadComplete");
				}
			}
			catch (Exception ex)
			{
				OTCLog.Error("Patch", "Failed to hook LoadManager.onLoadComplete: " + ex.Message);
			}
		}

		private static void OnGameLoaded()
		{
			if (_gameLoadedRan)
			{
				OTCLog.Warning("Patch", "OnGameLoaded fired more than once this session (stale listener?) — ignoring duplicate.");
				return;
			}
			_gameLoadedRan = true;
			try
			{
				WestvilleShack.ClearTerrain();
				Dispensary.ClearTerrain();
				OTCWarehouse.ClearTerrain();
				WestvilleShack.SpawnNetworkedObjects();
				Dispensary.SpawnNetworkedObjects();
				OTCWarehouse.SpawnNetworkedObjects();
				CheckoutCounter.AddToShop();
				CasinoDeadDrop.Initialize();
				CheckoutProcess.InitP2P();
				CheckoutProcess.RequestSalesLog();
				BuildingGridFactory.SuppressNavigationRebuild = true;
				if (PropertySaveData.Instance != null)
				{
					foreach (KeyValuePair<Grid, OtcGridInfo> item in BuildingGridFactory.GridRegistry)
					{
						PropertySaveData.Instance.RestorePlacedItems(item.Value.BuildingId, item.Key);
					}
				}
				else
				{
					Grid shackGrid = WestvilleShack.ShackGrid;
					if ((Object)(object)shackGrid != (Object)null)
					{
						CheckoutCounter.SpawnOnGrid(shackGrid);
					}
				}
				BuildingGridFactory.SuppressNavigationRebuild = false;
				WestvilleShack.RebuildNavigation();
				Dispensary.RebuildNavigation();
				OTCWarehouse.RebuildNavigation();
				if (!MapBuildingOverlay.PaintBuildings())
				{
					OTCLog.Warning("Patch", "MapBuildingOverlay.PaintBuildings failed — MapApp or MapPositionUtility not ready");
				}
			}
			catch (Exception ex)
			{
				BuildingGridFactory.SuppressNavigationRebuild = false;
				OTCLog.Error("General", "OnGameLoaded restore failed: " + ex.Message + "\n" + ex.StackTrace);
			}
		}

		public override void OnLateUpdate()
		{
			if (!DependencyChecker.HasMissingDeps)
			{
				OnLateUpdateImpl();
			}
		}

		private void OnLateUpdateImpl()
		{
			PerfTracker.BeginFrame();
			try
			{
				PerfTracker.Begin("NetworkInit");
				ConfigSyncData.EnsureNetworkReady();
				PerfTracker.End("NetworkInit");
				PerfTracker.Begin("SyncMessages");
				ConfigSyncData.ProcessMessages();
				PerfTracker.End("SyncMessages");
				if (!_multiplayerDepChecked && !ConfigSyncData.IsNetworkLibAvailable)
				{
					Lobby instance = Singleton<Lobby>.Instance;
					if ((Object)(object)instance != (Object)null && instance.IsInLobby && instance.PlayerCount > 1)
					{
						_multiplayerDepChecked = true;
						DependencyChecker.RunMultiplayerChecks();
						if (DependencyChecker.HasMultiplayerIssues)
						{
							DependencyChecker.ShowMultiplayerPopup();
						}
					}
				}
				PerfTracker.Begin("SaveDataTicks");
				_notificationManager.ProcessContractState();
				VicSaveData.Instance?.Tick();
				StaticSaveData.Instance?.Tick();
				BellaSaveData.Instance?.Tick();
				ManagerSaveData.Instance?.Tick();
				PerfTracker.End("SaveDataTicks");
				PerfTracker.Begin("AdoptionRetries");
				_drifterManager?.RetryPendingAdoptions();
				_customerManager?.RetryPendingAdoptions();
				ManagerInstance.RetryPendingAdoptions();
				PerfTracker.End("AdoptionRetries");
				PerfTracker.Begin("ManagerAI");
				PerfTracker.Begin("ManagerAI.Wages");
				_managerManager?.CheckImmediateWages();
				PerfTracker.End("ManagerAI.Wages");
				PerfTracker.Begin("ManagerAI.EnsureMoving");
				foreach (ManagerInstance value in ManagerInstance.Active.Values)
				{
					value.EnsureMoving();
				}
				PerfTracker.End("ManagerAI.EnsureMoving");
				PerfTracker.Begin("ManagerAI.SupplyDistribution");
				if (NetworkHelper.IsHost)
				{
					foreach (ManagerInstance value2 in ManagerInstance.Active.Values)
					{
						value2.SupplyBehaviour?.Tick();
						value2.DistributionBehaviour?.Tick();
					}
				}
				PerfTracker.End("ManagerAI.SupplyDistribution");
				PerfTracker.End("ManagerAI");
				PerfTracker.Begin("NetworkPublish");
				if (NetworkHelper.IsHost)
				{
					ConfigSyncData.FlushDirtyState();
					if (ManagerInstance.HasPendingMessages)
					{
						ConfigSyncData.Instance?.PublishManagerMessages();
					}
					if (DrifterManager.HasPendingDrifterMessages)
					{
						ConfigSyncData.Instance?.PublishDrifterMessages();
					}
					_customerManager?.PublishIfNeeded();
					if (ManagerInstance.StatePublishNeeded)
					{
						ManagerInstance.StatePublishNeeded = false;
						ConfigSyncData.Instance?.PublishManagerState();
					}
				}
				PerfTracker.End("NetworkPublish");
				PerfTracker.Begin("ClientDoorSetup");
				if (!NetworkHelper.IsHost)
				{
					WestvilleShack.TickClientDoorSetup();
					Dispensary.TickClientDoorSetup();
				}
				PerfTracker.End("ClientDoorSetup");
				if (!_budtendersRestored && NetworkHelper.IsHost && CheckoutCounter.AllCounters.Count > 0 && PropertySaveData.Instance != null)
				{
					_budtendersRestored = true;
					string budtenderSaveState = PropertySaveData.Instance.BudtenderSaveState;
					if (!string.IsNullOrEmpty(budtenderSaveState))
					{
						BudtenderController.Deserialize(budtenderSaveState);
					}
				}
				PerfTracker.Begin("BudtenderAI");
				if (NetworkHelper.IsHost)
				{
					BudtenderController.Tick();
				}
				PerfTracker.End("BudtenderAI");
				PerfTracker.Begin("Checkout");
				CheckoutProcess.Instance?.Tick();
				CheckoutProcess.TryStartCheckout();
				CheckoutProcess.PollLockGrant();
				if (CheckoutProcess.Instance == null)
				{
					CheckoutCounter.TryCollectRegister();
				}
				PerfTracker.End("Checkout");
				PerfTracker.Begin("ScreenTicks");
				foreach (CheckoutCounterInstance allCounter in CheckoutCounter.AllCounters)
				{
					allCounter.Screen?.Tick();
				}
				PerfTracker.End("ScreenTicks");
				Dispensary.UpdateLightBrightness();
				WestvilleShack.UpdateLightBrightness();
				PerfTracker.Begin("QuestTicks");
				_drifterManager?.ClientQuestTick();
				StorefrontGrowthQuest.Instance?.Tick();
				StorefrontExpansionQuest.Instance?.Tick();
				PerfTracker.End("QuestTicks");
			}
			catch (Exception ex)
			{
				OTCLog.Error("Patch", "Error in OnLateUpdate: " + ex.Message + "\n" + ex.StackTrace);
			}
			PerfTracker.EndFrame();
		}

		private static void OnSleepEnd(int minutesSkipped)
		{
			if (NetworkHelper.IsHost)
			{
				LoadManager instance = Singleton<LoadManager>.Instance;
				if (!((Object)(object)instance == (Object)null) && instance.IsGameLoaded)
				{
					StaticNPC.Instance?.WarpToSpawn();
					BellaNPC.Instance?.ReInjectIntoBuilding();
				}
			}
		}

		public override void OnDeinitializeMelon()
		{
			if (!DependencyChecker.HasMissingDeps)
			{
				OnDeinitializeMelonImpl();
			}
		}

		private static void OnDayPass()
		{
			if (!NetworkHelper.IsHost)
			{
				return;
			}
			PropertySaveData instance = PropertySaveData.Instance;
			if (instance != null)
			{
				int num = 0;
				if (instance.IsPropertyOwned("westville_shack"))
				{
					num += PropertyInventory.GetTotalProductCount(WestvilleShack.ShackGrid);
				}
				if (instance.IsPropertyOwned("big_dispensary"))
				{
					num += PropertyInventory.GetTotalProductCount(Dispensary.DispensaryGrid);
				}
				instance.RecordInventorySnapshot(TimeManager.ElapsedDays, num);
				instance.TrimSalesLog(TimeManager.ElapsedDays);
			}
		}

		private void OnDeinitializeMelonImpl()
		{
			PerfTracker.WriteReport();
			TimeManager.OnSleepEnd = (Action<int>)Delegate.Remove(TimeManager.OnSleepEnd, new Action<int>(OnSleepEnd));
			TimeManager.OnDayPass = (Action)Delegate.Remove(TimeManager.OnDayPass, new Action(OnDayPass));
			ConfigSyncData.Cleanup();
			_notificationManager?.Cleanup();
			_desperationManager?.Cleanup();
			_drifterManager?.Cleanup();
			_managerManager?.Cleanup();
			_customerManager?.Cleanup();
		}

		private void ExtractIcons()
		{
			OtcIconDir = Path.Combine(MelonEnvironment.UserDataDirectory, "OverTheCounter", "Icons");
			if (!Directory.Exists(OtcIconDir))
			{
				Directory.CreateDirectory(OtcIconDir);
			}
			ExtractResource(OtcIconDir, "CustomersIcon.png");
			ExtractResource(OtcIconDir, "DrifterQuestIcon.png");
			ExtractResource(OtcIconDir, "DrifterProfileIcon.png");
			ExtractResource(OtcIconDir, "RinseCycle.png");
			ExtractResource(OtcIconDir, "CrimeWareQuest.png");
			ExtractResource(OtcIconDir, "ExecutivePrivilege.png");
			ExtractResource(OtcIconDir, "ManagerIcon.png");
			ExtractResource(OtcIconDir, "CheckoutCounter.png");
			ExtractResource(OtcIconDir, "StoreAlertIcon.png");
		}

		private void ExtractResource(string directory, string fileName)
		{
			string path = Path.Combine(directory, fileName);
			if (File.Exists(path))
			{
				return;
			}
			OTCLog.Msg("Patch", "Extracting " + fileName + "...");
			string text = "OverTheCounter.Resources." + fileName;
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text);
			if (stream != null)
			{
				using (FileStream destination = new FileStream(path, FileMode.Create, FileAccess.Write))
				{
					stream.CopyTo(destination);
				}
				OTCLog.Msg("Patch", fileName + " extracted successfully.");
			}
			else
			{
				OTCLog.Error("Patch", "Could not find embedded resource '" + text + "'.");
			}
		}
	}
	public static class Config
	{
		private static MelonPreferences_Category _managers;

		public static ConfigEntry<float> ManagerDailyWage;

		public static ConfigEntry<float> ManagerSigningFee;

		public static ConfigEntry<bool> AlternateHire;

		private static MelonPreferences_Category _laundering;

		public static ConfigEntry<float> VicTier1Cost;

		public static ConfigEntry<float> VicTier1Return;

		public static ConfigEntry<int> VicTier2TrustUnlock;

		public static ConfigEntry<float> VicTier2Cost;

		public static ConfigEntry<float> VicTier2Return;

		public static ConfigEntry<int> VicIntroWeedGrams;

		public static ConfigEntry<float> VicDepositTrigger;

		private static MelonPreferences_Category _bella;

		public static ConfigEntry<float> BellaWeedValue;

		public static ConfigEntry<float> BellaMethValue;

		public static ConfigEntry<float> BellaCokeValue;

		private static MelonPreferences_Category _notifications;

		public static ConfigEntry<bool> ConsolidationEnabled;

		public static ConfigEntry<int> ConsolidationThreshold;

		private static MelonPreferences_Category _subscription;

		public static ConfigEntry<float> SaasWeeklyCost;

		public static ConfigEntry<int> SaasCycleDays;

		public static ConfigEntry<float> StaticTier1BankCost;

		public static ConfigEntry<int> StaticTier1WeedGrams;

		public static ConfigEntry<float> StaticTier2BankCost;

		public static ConfigEntry<int> StaticTier2MethGrams;

		public static ConfigEntry<float> StaticTier3BankCost;

		public static ConfigEntry<int> StaticTier3PremiumMethGrams;

		private static MelonPreferences_Category _world;

		public static ConfigEntry<float> ShackPurchasePrice;

		public static ConfigEntry<float> WarehousePurchasePrice;

		public static ConfigEntry<float> DispensaryPurchasePrice;

		public static ConfigEntry<int> StackSizeMultiplier;

		public static ConfigEntry<bool> GraffitiReEdit;

		public static ConfigEntry<bool> RecipePinEnabled;

		public static ConfigEntry<int> ShackDailyCustomerCap;

		public static ConfigEntry<bool> PreserveVanillaDeals;

		public static ConfigEntry<float> WalkInMirrorRate;

		private static MelonPreferences_Category _desperation;

		public static ConfigEntry<bool> DesperationEnabled;

		public static ConfigEntry<float> FiendAddictionThreshold;

		public static ConfigEntry<float> TriggerChancePerHour;

		public static ConfigEntry<int> MaxEventsPerDay;

		public static ConfigEntry<int> ResponseDeadlineMinutes;

		public static ConfigEntry<int> DeadlineMinutes;

		public static ConfigEntry<float> BonusMultiplier;

		public static ConfigEntry<float> RelationshipPenalty;

		public static ConfigEntry<int> CooldownMinutes;

		public static ConfigEntry<int> DayStartHour;

		public static ConfigEntry<int> DayEndHour;

		private static MelonPreferences_Category _drifters;

		public static ConfigEntry<bool> DrifterEnabled;

		public static ConfigEntry<float> DrifterSpawnChancePerHour;

		public static ConfigEntry<int> MaxActiveDrifters;

		public static ConfigEntry<int> DrifterDayStartHour;

		public static ConfigEntry<int> DrifterDayEndHour;

		public static ConfigEntry<int> DrifterOfferWindowMin;

		public static ConfigEntry<int> DrifterDeliveryDeadlineMin;

		public static ConfigEntry<int> DrifterLingerMinMin;

		public static ConfigEntry<int> DrifterLingerMaxMin;

		public static ConfigEntry<float> DrifterMinDealValue;

		private static MelonPreferences_Category _debug;

		public static ConfigEntry<bool> VerboseLogging;

		public static ConfigEntry<bool> ManagerVerboseLogging;

		public static ConfigEntry<bool> DrifterVerboseLogging;

		public static ConfigEntry<bool> DesperationVerboseLogging;

		public static ConfigEntry<bool> NpcVerboseLogging;

		public static ConfigEntry<bool> NetworkVerboseLogging;

		public static ConfigEntry<bool> QuestVerboseLogging;

		public static ConfigEntry<bool> NotificationVerboseLogging;

		public static ConfigEntry<bool> PatchVerboseLogging;

		public static ConfigEntry<bool> ProfilingEnabled;

		private static MelonPreferences_Category _minimap;

		public static ConfigEntry<bool> MinimapEnabled;

		public static ConfigEntry<int> MinimapSize;

		public static ConfigEntry<bool> MinimapRotateWithPlayer;

		public static ConfigEntry<bool> MinimapCircle;

		public static ConfigEntry<int> MinimapDefaultZoom;

		public static ConfigEntry<float> MinimapIconScale;

		public static MelonPreferences_Entry<KeyCode> MinimapToggleKey;

		public static ConfigEntry<int> MinimapHorizontalOffset;

		public static ConfigEntry<int> MinimapVerticalOffset;

		public static ConfigEntry<bool> MinimapInfoOnTop;

		public static MelonPreferences_Entry<Color> MinimapBorderColor;

		public static ConfigEntry<int> MinimapBorderWidth;

		public static ConfigEntry<bool> MinimapShowTime;

		public static ConfigEntry<bool> MinimapShowDay;

		public static ConfigEntry<bool> MinimapUse24HourClock;

		public static ConfigEntry<bool> MinimapShowCompass;

		public static ConfigEntry<bool> MinimapShowEdgeIndicators;

		public static ConfigEntry<bool> MinimapPerfLimit;

		private static MelonPreferences_Category _hud;

		public static ConfigEntry<bool> HUDShowRankXP;

		public static ConfigEntry<bool> HUDShowHealth;

		public static ConfigEntry<bool> HUDShowStamina;

		public static ConfigEntry<bool> StoreAlertEnabled;

		private static MelonPreferences_Category _minimapPoi;

		public static ConfigEntry<bool> MinimapShowPotentialCustomers;

		public static ConfigEntry<bool> MinimapShowCustomers;

		public static ConfigEntry<bool> MinimapShowDealers;

		public static ConfigEntry<bool> MinimapShowDeadDrops;

		public static ConfigEntry<bool> MinimapShowContracts;

		public static ConfigEntry<bool> MinimapShowQuests;

		public static ConfigEntry<bool> MinimapShowProperties;

		public static ConfigEntry<bool> MinimapShowManagers;

		public static ConfigEntry<bool> MinimapShowModdedNPCs;

		private static readonly Dictionary<string, ConfigEntry<float>> _floatEntries = new Dictionary<string, ConfigEntry<float>>();

		private static readonly Dictionary<string, ConfigEntry<int>> _intEntries = new Dictionary<string, ConfigEntry<int>>();

		private static readonly Dictionary<string, ConfigEntry<bool>> _boolEntries = new Dictionary<string, ConfigEntry<bool>>();

		private static readonly HashSet<string> _localOnlyKeys = new HashSet<string>
		{
			"ConsolidationEnabled", "ConsolidationThreshold", "ManagerVerboseLogging", "DrifterVerboseLogging", "DesperationVerboseLogging", "NpcVerboseLogging", "NetworkVerboseLogging", "QuestVerboseLogging", "NotificationVerboseLogging", "PatchVerboseLogging",
			"ProfilingEnabled", "VerboseLogging", "MinimapEnabled", "MinimapSize", "MinimapRotateWithPlayer", "MinimapCircle", "MinimapDefaultZoom", "MinimapIconScale", "MinimapHorizontalOffset", "MinimapVerticalOffset",
			"MinimapInfoOnTop", "MinimapBorderWidth", "MinimapShowTime", "MinimapShowDay", "MinimapUse24HourClock", "MinimapShowPotentialCustomers", "MinimapShowCustomers", "MinimapShowDealers", "MinimapShowDeadDrops", "MinimapShowContracts",
			"MinimapShowQuests", "MinimapShowProperties", "MinimapShowManagers", "MinimapShowModdedNPCs", "MinimapShowCompass", "MinimapShowEdgeIndicators", "MinimapPerfLimit", "HUDShowRankXP", "HUDShowHealth", "HUDShowStamina",
			"StoreAlertEnabled", "RecipePinEnabled"
		};

		public static void Initialize()
		{
			//IL_0e74: Unknown result type (might be due to invalid IL or missing references)
			_managers = MelonPreferences.CreateCategory("OverTheCounter_Managers", "Manager System");
			ManagerDailyWage = Register(_managers.CreateEntry<float>("ManagerDailyWage", 350f, "Base Daily Wage", "Base daily wage before upgrade fees are added", false, false, (ValueValidator)null, (string)null));
			ManagerSigningFee = Register(_managers.CreateEntry<float>("ManagerSigningFee", 3000f, "Signing Fee", "One-time fee deducted from player cash when hiring a manager", false, false, (ValueValidator)null, (string)null));
			AlternateHire = Register(_managers.CreateEntry<bool>("AlternateHire", false, "Alternate Hire", "Show hire buttons in the OTC app instead of using Manny's dialogue. Enable if another mod conflicts with Manny.", false, false, (ValueValidator)null, (string)null));
			_laundering = MelonPreferences.CreateCategory("OverTheCounter_Laundering", "Vic Laundering");
			VicTier1Cost = Register(_laundering.CreateEntry<float>("VicTier1Cost", 500f, "Tier 1 Cost", "Cash required for tier-1 laundering", false, false, (ValueValidator)null, (string)null));
			VicTier1Return = Register(_laundering.CreateEntry<float>("VicTier1Return", 400f, "Tier 1 Return", "Clean money returned for tier-1 laundering", false, false, (ValueValidator)null, (string)null));
			VicTier2TrustUnlock = Register(_laundering.CreateEntry<int>("VicTier2TrustUnlock", 7, "Tier 2 Trust Unlock", "Trust level required to unlock tier-2 laundering", false, false, (ValueValidator)null, (string)null));
			VicTier2Cost = Register(_laundering.CreateEntry<float>("VicTier2Cost", 900f, "Tier 2 Cost", "Cash required for tier-2 laundering", false, false, (ValueValidator)null, (string)null));
			VicTier2Return = Register(_laundering.CreateEntry<float>("VicTier2Return", 750f, "Tier 2 Return", "Clean money returned for tier-2 laundering", false, false, (ValueValidator)null, (string)null));
			VicIntroWeedGrams = Register(_laundering.CreateEntry<int>("VicIntroWeedGrams", 40, "Intro Quest Weed Grams", "Grams of weed required to complete Vic's intro quest", false, false, (ValueValidator)null, (string)null));
			VicDepositTrigger = Register(_laundering.CreateEntry<float>("VicDepositTrigger", 10000f, "Deposit Trigger Amount", "Weekly deposit total that triggers Vic's intro quest", false, false, (ValueValidator)null, (string)null));
			_bella = MelonPreferences.CreateCategory("OverTheCounter_Bella", "Bella Protocol");
			BellaWeedValue = Register(_bella.CreateEntry<float>("BellaWeedValue", 105f, "Weed Mix Value", "Minimum base price for the weed mix Bella requires", false, false, (ValueValidator)null, (string)null));
			BellaMethValue = Register(_bella.CreateEntry<float>("BellaMethValue", 200f, "Meth Mix Value", "Minimum base price for the meth mix Bella requires", false, false, (ValueValidator)null, (string)null));
			BellaCokeValue = Register(_bella.CreateEntry<float>("BellaCokeValue", 400f, "Cocaine Mix Value", "Minimum base price for the cocaine mix Bella requires", false, false, (ValueValidator)null, (string)null));
			_notifications = MelonPreferences.CreateCategory("OverTheCounter_Notifications", "Contract Notifications");
			ConsolidationEnabled = Register(_notifications.CreateEntry<bool>("Enabled", true, "Enabled", "Enable/disable contract consolidation (groups same-window deliveries into one HUD entry)", false, false, (ValueValidator)null, (string)null));
			ConsolidationThreshold = Register(_notifications.CreateEntry<int>("ConsolidationThreshold", 5, "Consolidation Threshold", "Minimum contracts in a window before consolidation kicks in", false, false, (ValueValidator)null, (string)null));
			_subscription = MelonPreferences.CreateCategory("OverTheCounter_Subscription", "Static Subscription");
			SaasWeeklyCost = Register(_subscription.CreateEntry<float>("SaasWeeklyCost", 1000f, "Weekly Cost", "Bank balance deducted each billing cycle", false, false, (ValueValidator)null, (string)null));
			SaasCycleDays = Register(_subscription.CreateEntry<int>("SaasCycleDays", 7, "Cycle Days", "Number of days between subscription payments", false, false, (ValueValidator)null, (string)null));
			StaticTier1BankCost = Register(_subscription.CreateEntry<float>("StaticTier1BankCost", 3000f, "Tier 1 Bank Cost", "Bank transfer cost for the initial software package", false, false, (ValueValidator)null, (string)null));
			StaticTier1WeedGrams = Register(_subscription.CreateEntry<int>("StaticTier1WeedGrams", 20, "Tier 1 Weed Grams", "Grams of weed required for the initial package", false, false, (ValueValidator)null, (string)null));
			StaticTier2BankCost = Register(_subscription.CreateEntry<float>("StaticTier2BankCost", 6000f, "Tier 2 Bank Cost", "Bank transfer cost for the Premium upgrade", false, false, (ValueValidator)null, (string)null));
			StaticTier2MethGrams = Register(_subscription.CreateEntry<int>("StaticTier2MethGrams", 5, "Tier 2 Meth Grams", "Grams of meth required for the Premium upgrade", false, false, (ValueValidator)null, (string)null));
			StaticTier3BankCost = Register(_subscription.CreateEntry<float>("StaticTier3BankCost", 12000f, "Tier 3 Bank Cost", "Bank transfer cost for the Enterprise upgrade", false, false, (ValueValidator)null, (string)null));
			StaticTier3PremiumMethGrams = Register(_subscription.CreateEntry<int>("StaticTier3PremiumMethGrams", 10, "Tier 3 Premium Meth Grams", "Grams of premium meth required for Enterprise upgrade", false, false, (ValueValidator)null, (string)null));
			_world = MelonPreferences.CreateCategory("OverTheCounter_World", "World");
			ShackPurchasePrice = Register(_world.CreateEntry<float>("ShackPurchasePrice", 5000f, "Shack Purchase Price", "Bank transfer cost for the Westville Shack property", false, false, (ValueValidator)null, (string)null));
			WarehousePurchasePrice = Register(_world.CreateEntry<float>("WarehousePurchasePrice", 18000f, "Warehouse Purchase Price", "Bank transfer cost for the Warehouse property", false, false, (ValueValidator)null, (string)null));
			DispensaryPurchasePrice = Register(_world.CreateEntry<float>("DispensaryPurchasePrice", 30000f, "Dispensary Purchase Price", "Bank transfer cost for the Big Dispensary property", false, false, (ValueValidator)null, (string)null));
			StackSizeMultiplier = Register(_world.CreateEntry<int>("StackSizeMultiplier", 1, "Stack Size Multiplier", "Multiplies the stack limit of all stackable items by this value. 1 = vanilla stacks (default). 2 = double stacks. Affects all inventories. Host value is used in multiplayer. Changing mid-save does not retroactively adjust existing item quantities.", false, false, (ValueValidator)(object)new ValueRange<int>(1, 10), (string)null));
			GraffitiReEdit = Register(_world.CreateEntry<bool>("GraffitiReEdit", true, "Graffiti Re-Edit", "Allow re-editing spray paint surfaces without consuming spray cans. Spray can must still be equipped to interact.", false, false, (ValueValidator)null, (string)null));
			RecipePinEnabled = Register(_world.CreateEntry<bool>("RecipePinEnabled", true, "Recipe Pin", "Show a Pin Recipe button in the Product Manager app. Pins a draggable overlay showing the full mixing chain for a product.", false, false, (ValueValidator)null, (string)null));
			ShackDailyCustomerCap = Register(_world.CreateEntry<int>("ShackDailyCustomerCap", 12, "Shack Daily Customer Cap", "Maximum customers redirected to the Westville Shack per day", false, false, (ValueValidator)null, (string)null));
			PreserveVanillaDeals = Register(_world.CreateEntry<bool>("PreserveVanillaDeals", false, "Preserve Vanilla Deals", "When enabled, vanilla NPCs keep their normal deal behavior instead of being redirected to the dispensary. Each redirected deal has a chance (set by Mirror Spawn Rate) to also spawn a random walk-in customer. Off by default because keeping both vanilla deals AND dispensary sales effectively doubles income.", false, false, (ValueValidator)null, (string)null));
			WalkInMirrorRate = Register(_world.CreateEntry<float>("WalkInMirrorRate", 0.4f, "Mirror Spawn Rate", "Only used when Preserve Vanilla Deals is enabled. Chance (0-1) that each vanilla deal that would have been redirected also spawns a random store customer. Has no effect when Preserve Vanilla Deals is off. 0.4 = 40% of deals spawn one. 1.0 = every deal spawns one.", false, false, (ValueValidator)(object)new ValueRange<float>(0f, 1f), (string)null));
			_desperation = MelonPreferences.CreateCategory("OverTheCounter", "Desperation System");
			DesperationEnabled = Register(_desperation.CreateEntry<bool>("Enabled", true, "Enabled", "Enable/disable the desperation system (urgent fiend requests)", false, false, (ValueValidator)null, (string)null));
			FiendAddictionThreshold = Register(_desperation.CreateEntry<float>("FiendAddictionThreshold", 0.67f, "Fiend Addiction Threshold", "Addiction level required to qualify as a Fiend (0.0–1.0)", false, false, (ValueValidator)null, (string)null));
			TriggerChancePerHour = Register(_desperation.CreateEntry<float>("TriggerChancePerHour", 0.12f, "Trigger Chance Per Hour", "Probability of a desperation event each hour (0.0–1.0)", false, false, (ValueValidator)null, (string)null));
			MaxEventsPerDay = Register(_desperation.CreateEntry<int>("MaxEventsPerDay", 3, "Max Events Per Day", "Hard cap on desperation events per day", false, false, (ValueValidator)null, (string)null));
			ResponseDeadlineMinutes = Register(_desperation.CreateEntry<int>("ResponseDeadlineMinutes", 60, "Response Deadline (min)", "In-game minutes the player has to respond to a desperation offer", false, false, (ValueValidator)null, (string)null));
			DeadlineMinutes = Register(_desperation.CreateEntry<int>("DeadlineMinutes", 120, "Delivery Deadline (min)", "In-game minutes to deliver after accepting a desperation contract", false, false, (ValueValidator)null, (string)null));
			BonusMultiplier = Register(_desperation.CreateEntry<float>("BonusMultiplier", 0.45f, "Bonus Multiplier", "Extra payment multiplier for desperation deliveries (0.45 = 45%)", false, false, (ValueValidator)null, (string)null));
			RelationshipPenalty = Register(_desperation.CreateEntry<float>("RelationshipPenalty", -15f, "Relationship Penalty", "Relationship change on failed desperation event", false, false, (ValueValidator)null, (string)null));
			CooldownMinutes = Register(_desperation.CreateEntry<int>("CooldownMinutes", 1440, "Cooldown (min)", "Minutes a customer is locked out after a failed event (1440 = 24h)", false, false, (ValueValidator)null, (string)null));
			DayStartHour = Register(_desperation.CreateEntry<int>("DayStartHour", 800, "Day Start Hour", "Earliest 24h time for desperation rolls (800 = 8:00 AM)", false, false, (ValueValidator)null, (string)null));
			DayEndHour = Register(_desperation.CreateEntry<int>("DayEndHour", 2100, "Day End Hour", "Latest 24h time for desperation rolls (2100 = 9:00 PM)", false, false, (ValueValidator)null, (string)null));
			_drifters = MelonPreferences.CreateCategory("OverTheCounter_Drifters", "Drifter System");
			DrifterEnabled = Register(_drifters.CreateEntry<bool>("Enabled", true, "Enabled", "Enable/disable the drifter system (random street NPCs offering one-time deals)", false, false, (ValueValidator)null, (string)null));
			DrifterSpawnChancePerHour = Register(_drifters.CreateEntry<float>("DrifterSpawnChancePerHour", 0.38f, "Spawn Chance Per Hour", "Base spawn chance per hour at max regions. Scaled down by unlocked region count (0.0-1.0)", false, false, (ValueValidator)null, (string)null));
			MaxActiveDrifters = Register(_drifters.CreateEntry<int>("MaxActiveDrifters", 3, "Max Active Drifters", "Maximum number of drifters that can be active at once", false, false, (ValueValidator)null, (string)null));
			DrifterDayStartHour = Register(_drifters.CreateEntry<int>("DrifterDayStartHour", 800, "Day Start Hour", "Earliest 24h time for drifter spawns (800 = 8:00 AM)", false, false, (ValueValidator)null, (string)null));
			DrifterDayEndHour = Register(_drifters.CreateEntry<int>("DrifterDayEndHour", 2100, "Day End Hour", "Latest 24h time for drifter spawns (2100 = 9:00 PM)", false, false, (ValueValidator)null, (string)null));
			DrifterOfferWindowMin = Register(_drifters.CreateEntry<int>("DrifterOfferWindowMin", 120, "Offer Window (min)", "Minutes player has to respond to a drifter offer (120 = 2 hours)", false, false, (ValueValidator)null, (string)null));
			DrifterDeliveryDeadlineMin = Register(_drifters.CreateEntry<int>("DrifterDeliveryDeadlineMin", 240, "Delivery Deadline (min)", "Minutes to deliver after accepting a drifter deal (240 = 4 hours)", false, false, (ValueValidator)null, (string)null));
			DrifterLingerMinMin = Register(_drifters.CreateEntry<int>("DrifterLingerMinMin", 30, "Linger Min (min)", "Minimum minutes a drifter lingers after deal completion/expiry", false, false, (ValueValidator)null, (string)null));
			DrifterLingerMaxMin = Register(_drifters.CreateEntry<int>("DrifterLingerMaxMin", 60, "Linger Max (min)", "Maximum minutes a drifter lingers after deal completion/expiry", false, false, (ValueValidator)null, (string)null));
			DrifterMinDealValue = Register(_drifters.CreateEntry<float>("DrifterMinDealValue", 90f, "Min Deal Value ($)", "Soft minimum deal value - drifters ask for more quantity until the deal reaches this threshold", false, false, (ValueValidator)null, (string)null));
			_debug = MelonPreferences.CreateCategory("OverTheCounter_Debug", "Debug");
			VerboseLogging = Register(_debug.CreateEntry<bool>("VerboseLogging", false, "Verbose Logging (General)", "Catch-all verbose logging for systems without a dedicated toggle", false, false, (ValueValidator)null, (string)null));
			ManagerVerboseLogging = Register(_debug.CreateEntry<bool>("ManagerVerboseLogging", false, "Verbose: Manager", "Enable detailed manager logging (shopping list breakdowns, per-item details)", false, false, (ValueValidator)null, (string)null));
			DrifterVerboseLogging = Register(_debug.CreateEntry<bool>("DrifterVerboseLogging", false, "Verbose: Drifter", "Enable detailed drifter system logging", false, false, (ValueValidator)null, (string)null));
			DesperationVerboseLogging = Register(_debug.CreateEntry<bool>("DesperationVerboseLogging", false, "Verbose: Desperation", "Enable detailed desperation system logging", false, false, (ValueValidator)null, (string)null));
			NpcVerboseLogging = Register(_debug.CreateEntry<bool>("NpcVerboseLogging", false, "Verbose: NPC", "Enable detailed NPC logging (Vic, Bella, Static)", false, false, (ValueValidator)null, (string)null));
			NetworkVerboseLogging = Register(_debug.CreateEntry<bool>("NetworkVerboseLogging", false, "Verbose: Network", "Enable detailed network sync logging", false, false, (ValueValidator)null, (string)null));
			QuestVerboseLogging = Register(_debug.CreateEntry<bool>("QuestVerboseLogging", false, "Verbose: Quest", "Enable detailed quest logging", false, false, (ValueValidator)null, (string)null));
			NotificationVerboseLogging = Register(_debug.CreateEntry<bool>("NotificationVerboseLogging", false, "Verbose: Notification", "Enable detailed notification system logging", false, false, (ValueValidator)null, (string)null));
			PatchVerboseLogging = Register(_debug.CreateEntry<bool>("PatchVerboseLogging", false, "Verbose: Patch", "Enable detailed Harmony patch logging", false, false, (ValueValidator)null, (string)null));
			ProfilingEnabled = Register(_debug.CreateEntry<bool>("ProfilingEnabled", false, "Performance Profiling", "Write periodic performance reports to UserData/OTC_PerfReport.txt", false, false, (ValueValidator)null, (string)null));
			_minimapPoi = MelonPreferences.CreateCategory("OverTheCounter_MinimapPOI", "Minimap POIs");
			MinimapShowPotentialCustomers = Register(_minimapPoi.CreateEntry<bool>("MinimapShowPotentialCustomers", true, "Show Potential Customers", "Show potential customer icons on the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapShowCustomers = Register(_minimapPoi.CreateEntry<bool>("MinimapShowCustomers", false, "Show Customers", "Show unlocked customer icons on the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapShowDealers = Register(_minimapPoi.CreateEntry<bool>("MinimapShowDealers", true, "Show Dealers", "Show dealer icons on the minimap (potential and active)", false, false, (ValueValidator)null, (string)null));
			MinimapShowDeadDrops = Register(_minimapPoi.CreateEntry<bool>("MinimapShowDeadDrops", true, "Show Dead Drops", "Show dead drop icons on the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapShowContracts = Register(_minimapPoi.CreateEntry<bool>("MinimapShowContracts", true, "Show Contracts", "Show contract delivery icons on the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapShowQuests = Register(_minimapPoi.CreateEntry<bool>("MinimapShowQuests", true, "Show Quests", "Show quest objective icons on the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapShowProperties = Register(_minimapPoi.CreateEntry<bool>("MinimapShowProperties", true, "Show Properties", "Show owned property icons on the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapShowManagers = Register(_minimapPoi.CreateEntry<bool>("MinimapShowManagers", true, "Show Managers", "Show manager icons on the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapShowModdedNPCs = Register(_minimapPoi.CreateEntry<bool>("MinimapShowModdedNPCs", true, "Show Modded NPCs", "Show NPC icons added by other mods (e.g. police, cartel) on the minimap", false, false, (ValueValidator)null, (string)null));
			_minimap = MelonPreferences.CreateCategory("OverTheCounter_Minimap", "Minimap");
			MinimapEnabled = Register(_minimap.CreateEntry<bool>("MinimapEnabled", false, "Enabled", "Show the minimap overlay", false, false, (ValueValidator)null, (string)null));
			MinimapSize = Register(_minimap.CreateEntry<int>("MinimapSize", 250, "Size (px)", "Minimap size in pixels", false, false, (ValueValidator)null, (string)null));
			MinimapRotateWithPlayer = Register(_minimap.CreateEntry<bool>("MinimapRotateWithPlayer", false, "Rotate With Player", "Rotate minimap to match player facing direction", false, false, (ValueValidator)null, (string)null));
			MinimapCircle = Register(_minimap.CreateEntry<bool>("MinimapCircle", false, "Circle Shape", "Use circular minimap shape instead of square", false, false, (ValueValidator)null, (string)null));
			MinimapDefaultZoom = Register(_minimap.CreateEntry<int>("MinimapDefaultZoom", 2, "Default Zoom", "Starting zoom level, 1=closest, 3=farthest (1-3)", false, false, (ValueValidator)null, (string)null));
			MinimapIconScale = Register(_minimap.CreateEntry<float>("MinimapIconScale", 0.7f, "Icon Scale", "POI icon scale on the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapToggleKey = _minimap.CreateEntry<KeyCode>("MinimapToggleKey", (KeyCode)110, "Toggle Key", "Hotkey to cycle minimap zoom", false, false, (ValueValidator)null, (string)null);
			MinimapHorizontalOffset = Register(_minimap.CreateEntry<int>("MinimapHorizontalOffset", 100, "Horizontal Offset", "Horizontal position (0=left, 100=right)", false, false, (ValueValidator)(object)new ValueRange<int>(0, 100), (string)null));
			MinimapVerticalOffset = Register(_minimap.CreateEntry<int>("MinimapVerticalOffset", 0, "Vertical Offset", "Vertical position (0=top, 100=bottom)", false, false, (ValueValidator)(object)new ValueRange<int>(0, 100), (string)null));
			MinimapInfoOnTop = Register(_minimap.CreateEntry<bool>("MinimapInfoOnTop", false, "Info Panels On Top", "Place clock and day display above the minimap instead of below", false, false, (ValueValidator)null, (string)null));
			MinimapBorderColor = _minimap.CreateEntry<Color>("MinimapBorderColor", new Color(0.2f, 0.2f, 0.2f, 0.9f), "Border Color", "Minimap border color", false, false, (ValueValidator)null, (string)null);
			MinimapBorderWidth = Register(_minimap.CreateEntry<int>("MinimapBorderWidth", 4, "Border Width", "Border thickness in pixels per side (2-10)", false, false, (ValueValidator)null, (string)null));
			MinimapShowTime = Register(_minimap.CreateEntry<bool>("MinimapShowTime", true, "Show Time", "Display the current time near the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapShowDay = Register(_minimap.CreateEntry<bool>("MinimapShowDay", true, "Show Day", "Display the current day near the minimap", false, false, (ValueValidator)null, (string)null));
			MinimapUse24HourClock = Register(_minimap.CreateEntry<bool>("MinimapUse24HourClock", false, "24-Hour Clock", "Use 24-hour time format instead of 12-hour AM/PM", false, false, (ValueValidator)null, (string)null));
			MinimapShowCompass = Register(_minimap.CreateEntry<bool>("MinimapShowCompass", true, "Show Compass", "Display N/S/E/W cardinal direction labels on the minimap edge", false, false, (ValueValidator)null, (string)null));
			MinimapShowEdgeIndicators = Register(_minimap.CreateEntry<bool>("MinimapShowEdgeIndicators", true, "Edge Indicators", "Show POI icons pinned to the minimap edge for off-screen points of interest", false, false, (ValueValidator)null, (string)null));
			MinimapPerfLimit = Register(_minimap.CreateEntry<bool>("MinimapPerfLimit", true, "Performance Limiting", "Adaptively reduce minimap update rate to limit CPU usage", false, false, (ValueValidator)null, (string)null));
			_hud = MelonPreferences.CreateCategory("OverTheCounter_HUD", "HUD Overlay");
			HUDShowRankXP = Register(_hud.CreateEntry<bool>("HUDShowRankXP", false, "Show Rank/XP", "Display rank and XP progress bar above the hotbar", false, false, (ValueValidator)null, (string)null));
			HUDShowHealth = Register(_hud.CreateEntry<bool>("HUDShowHealth", false, "Show Health", "Display health bar above the hotbar", false, false, (ValueValidator)null, (string)null));
			HUDShowStamina = Register(_hud.CreateEntry<bool>("HUDShowStamina", false, "Show Stamina", "Display stamina bar above the hotbar", false, false, (ValueValidator)null, (string)null));
			StoreAlertEnabled = Register(_hud.CreateEntry<bool>("StoreAlertEnabled", true, "Show Store Alerts", "Show checkout queue alerts on the right side of the screen", false, false, (ValueValidator)null, (string)null));
		}

		private static ConfigEntry<float> Register(MelonPreferences_Entry<float> entry)
		{
			ConfigEntry<float> configEntry = new ConfigEntry<float>(entry);
			_floatEntries[((MelonPreferences_Entry)entry).Identifier] = configEntry;
			return configEntry;
		}

		private static ConfigEntry<int> Register(MelonPreferences_Entry<int> entry)
		{
			ConfigEntry<int> configEntry = new ConfigEntry<int>(entry);
			_intEntries[((MelonPreferences_Entry)entry).Identifier] = configEntry;
			return configEntry;
		}

		private static ConfigEntry<bool> Register(MelonPreferences_Entry<bool> entry)
		{
			ConfigEntry<bool> configEntry = new ConfigEntry<bool>(entry);
			_boolEntries[((MelonPreferences_Entry)entry).Identifier] = configEntry;
			return configEntry;
		}

		public static string SerializeAll()
		{
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, ConfigEntry<float>> floatEntry in _floatEntries)
			{
				if (!_localOnlyKeys.Contains(floatEntry.Key))
				{
					list.Add(floatEntry.Key + "=" + floatEntry.Value.RawEntry.Value.ToString(CultureInfo.InvariantCulture));
				}
			}
			foreach (KeyValuePair<string, ConfigEntry<int>> intEntry in _intEntries)
			{
				if (!_localOnlyKeys.Contains(intEntry.Key))
				{
					list.Add(intEntry.Key + "=" + intEntry.Value.RawEntry.Value.ToString(CultureInfo.InvariantCulture));
				}
			}
			foreach (KeyValuePair<string, ConfigEntry<bool>> boolEntry in _boolEntries)
			{
				if (!_localOnlyKeys.Contains(boolEntry.Key))
				{
					list.Add($"{boolEntry.Key}={boolEntry.Value.RawEntry.Value}");
				}
			}
			return string.Join("|", list);
		}

		public static void ApplyOverrides(Dictionary<string, string> data)
		{
			foreach (KeyValuePair<string, string> datum in data)
			{
				if (_localOnlyKeys.Contains(datum.Key))
				{
					continue;
				}
				ConfigEntry<int> value2;
				ConfigEntry<bool> value3;
				bool result3;
				if (_floatEntries.TryGetValue(datum.Key, out var value))
				{
					if (float.TryParse(datum.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
					{
						value.SetOverride(result);
					}
				}
				else if (_intEntries.TryGetValue(datum.Key, out value2))
				{
					if (int.TryParse(datum.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2))
					{
						value2.SetOverride(result2);
					}
				}
				else if (_boolEntries.TryGetValue(datum.Key, out value3) && bool.TryParse(datum.Value, out result3))
				{
					value3.SetOverride(result3);
				}
			}
		}

		public static void ClearAllOverrides()
		{
			foreach (ConfigEntry<float> value in _floatEntries.Values)
			{
				value.ClearOverride();
			}
			foreach (ConfigEntry<int> value2 in _intEntries.Values)
			{
				value2.ClearOverride();
			}
			foreach (ConfigEntry<bool> value3 in _boolEntries.Values)
			{
				value3.ClearOverride();
			}
		}

		public static void SubscribeToChanges()
		{
			foreach (KeyValuePair<string, ConfigEntry<float>> floatEntry in _floatEntries)
			{
				if (!_localOnlyKeys.Contains(floatEntry.Key))
				{
					((MelonEventBase<LemonAction<object, object>>)(object)((MelonPreferences_Entry)floatEntry.Value.RawEntry).OnEntryValueChangedUntyped).Subscribe((LemonAction<object, object>)OnSyncableEntryChanged, 0, false);
				}
			}
			foreach (KeyValuePair<string, ConfigEntry<int>> intEntry in _intEntries)
			{
				if (!_localOnlyKeys.Contains(intEntry.Key))
				{
					((MelonEventBase<LemonAction<object, object>>)(object)((MelonPreferences_Entry)intEntry.Value.RawEntry).OnEntryValueChangedUntyped).Subscribe((LemonAction<object, object>)OnSyncableEntryChanged, 0, false);
				}
			}
			foreach (KeyValuePair<string, ConfigEntry<bool>> boolEntry in _boolEntries)
			{
				if (!_localOnlyKeys.Contains(boolEntry.Key))
				{
					((MelonEventBase<LemonAction<object, object>>)(object)((MelonPreferences_Entry)boolEntry.Value.RawEntry).OnEntryValueChangedUntyped).Subscribe((LemonAction<object, object>)OnSyncableEntryChanged, 0, false);
				}
			}
		}

		private static void OnSyncableEntryChanged(object oldValue, object newValue)
		{
			if (NetworkHelper.IsHost)
			{
				ConfigSyncData.Instance?.RefreshFromConfig();
			}
		}
	}
}
namespace OverTheCounter.Quests
{
	internal static class QuestHelper
	{
		public static string StableGuid(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				throw new ArgumentException("StableGuid key cannot be null/empty", "key");
			}
			using MD5 mD = MD5.Create();
			byte[] b = mD.ComputeHash(Encoding.UTF8.GetBytes("otc-quest:" + key));
			return new Guid(b).ToString();
		}

		public static T CreateWithGuid<T>(string guid) where T : Quest
		{
			T val = (T)(object)QuestManager.CreateQuest<T>((string)null);
			if (val == null)
			{
				OTCLog.Error("Quest", "QuestManager.CreateQuest<" + typeof(T).Name + "> returned null.");
				return default(T);
			}
			TryForceInit((Quest)(object)val, guid);
			return val;
		}

		public static string GetCurrentGuid(Quest quest)
		{
			if (quest == null)
			{
				return string.Empty;
			}
			return GetS1Quest(quest)?.StaticGUID ?? string.Empty;
		}

		private static void TryForceInit(Quest quest, string guid)
		{
			try
			{
				Quest s1Quest = GetS1Quest(quest);
				if ((Object)(object)s1Quest == (Object)null)
				{
					OTCLog.Warning("Quest", "TryForceInit: S1Quest field not found on " + ((object)quest).GetType().Name + ".");
					return;
				}
				s1Quest.StaticGUID = guid;
				string protectedString = GetProtectedString(quest, "Title");
				string protectedString2 = GetProtectedString(quest, "Description");
				QuestEntryData[] array = Array.Empty<QuestEntryData>();
				s1Quest.InitializeQuest(protectedString ?? string.Empty, protectedString2 ?? string.Empty, array, guid);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "TryForceInit failed for " + ((object)quest).GetType().Name + ": " + ex.Message);
			}
		}

		private static Quest GetS1Quest(Quest quest)
		{
			object? obj = typeof(Quest).GetField("S1Quest", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(quest);
			return (Quest)((obj is Quest) ? obj : null);
		}

		private static string GetProtectedString(Quest quest, string propertyName)
		{
			return ((object)quest).GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(quest) as string;
		}
	}
	public class VicIntroQuest : Quest
	{
		[SaveableField("vic_quest_stage")]
		private int _stage;

		private QuestEntry _meetVicEntry;

		private QuestEntry _bringWeedEntry;

		private static readonly Vector3 VicPosition = new Vector3(67.75f, 0.97f, 32.36f);

		protected override string Title => "Rinse Cycle";

		protected override string Description => "Help Vic with his party supplies and he'll help you clean some cash.";

		protected override bool AutoBegin => false;

		protected override Sprite QuestIcon => (Core.OtcIconDir != null) ? ImageUtils.LoadImage(Path.Combine(Core.OtcIconDir, "RinseCycle.png")) : null;

		public static VicIntroQuest Instance { get; private set; }

		public int Stage => _stage;

		internal static void ResetInstance()
		{
			Instance = null;
		}

		public void Initialize()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_meetVicEntry = ((Quest)this).AddEntry("Meet Vic in the alleyway behind the bank", (Vector3?)VicPosition);
				_bringWeedEntry = ((Quest)this).AddEntry(GetWeedText(), (Vector3?)VicPosition);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "Initialize failed: " + ex.Message);
			}
		}

		private static string GetWeedText()
		{
			return $"Bring Vic {Config.VicIntroWeedGrams.Value} grams of weed";
		}

		public void RefreshEntryText()
		{
			if (_bringWeedEntry != null && _stage >= 1 && _stage < 3)
			{
				_bringWeedEntry.Title = GetWeedText();
			}
		}

		public void StartQuest()
		{
			try
			{
				_stage = 1;
				((Quest)this).Begin();
				QuestEntry meetVicEntry = _meetVicEntry;
				if (meetVicEntry != null)
				{
					meetVicEntry.Begin();
				}
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "StartQuest failed: " + ex.Message);
			}
		}

		public void CompleteObj1()
		{
			try
			{
				_stage = 2;
				QuestEntry meetVicEntry = _meetVicEntry;
				if (meetVicEntry != null)
				{
					meetVicEntry.Begin();
				}
				QuestEntry meetVicEntry2 = _meetVicEntry;
				if (meetVicEntry2 != null)
				{
					meetVicEntry2.Complete();
				}
				QuestEntry bringWeedEntry = _bringWeedEntry;
				if (bringWeedEntry != null)
				{
					bringWeedEntry.Begin();
				}
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "CompleteObj1 failed: " + ex.Message);
			}
		}

		public void CompleteObj2()
		{
			try
			{
				_stage = 3;
				QuestEntry bringWeedEntry = _bringWeedEntry;
				if (bringWeedEntry != null)
				{
					bringWeedEntry.Begin();
				}
				QuestEntry bringWeedEntry2 = _bringWeedEntry;
				if (bringWeedEntry2 != null)
				{
					bringWeedEntry2.Complete();
				}
				((Quest)this).Complete();
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "CompleteObj2 failed: " + ex.Message);
			}
		}

		protected override void OnCreated()
		{
			((Registerable)this).OnCreated();
			Instance = this;
		}

		protected override void OnLoaded()
		{
			//IL_0074: 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)
			((Saveable)this).OnLoaded();
			Instance = this;
			try
			{
				if (VicSaveData.Instance != null)
				{
					int num = (VicSaveData.Instance.Unlocked ? 3 : (VicSaveData.Instance.QuestAccepted ? 2 : (VicSaveData.Instance.HasBeenTexted ? 1 : 0)));
					if (num > _stage)
					{
						_stage = num;
					}
				}
				base.QuestEntries.Clear();
				_meetVicEntry = ((Quest)this).AddEntry("Meet Vic in the alleyway behind the bank", (Vector3?)VicPosition);
				_bringWeedEntry = ((Quest)this).AddEntry(GetWeedText(), (Vector3?)VicPosition);
				if (_stage >= 1)
				{
					QuestEntry meetVicEntry = _meetVicEntry;
					if (meetVicEntry != null)
					{
						meetVicEntry.Begin();
					}
				}
				if (_stage >= 2)
				{
					QuestEntry meetVicEntry2 = _meetVicEntry;
					if (meetVicEntry2 != null)
					{
						meetVicEntry2.Complete();
					}
					QuestEntry bringWeedEntry = _bringWeedEntry;
					if (bringWeedEntry != null)
					{
						bringWeedEntry.Begin();
					}
				}
				if (_stage >= 3)
				{
					QuestEntry bringWeedEntry2 = _bringWeedEntry;
					if (bringWeedEntry2 != null)
					{
						bringWeedEntry2.Complete();
					}
					((Quest)this).Complete();
				}
			}
			catch (Exception ex)
			{
				OTCLog.Warning("Quest", "OnLoaded rebuild failed: " + ex.Message);
			}
		}
	}
	internal static class QuestIconHelper
	{
		private static readonly Dictionary<int, Sprite> _cache = new Dictionary<int, Sprite>();

		private static string IconPath => (Core.OtcIconDir != null) ? Path.Combine(Core.OtcIconDir, "CrimeWareQuest.png") : null;

		internal static Sprite Load()
		{
			return (IconPath != null) ? ImageUtils.LoadImage(IconPath) : null;
		}

		internal static Sprite LoadTinted(Color tint)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			int hashCode = ((object)(Color)(ref tint)).GetHashCode();
			if (_cache.TryGetValue(hashCode, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			try
			{
				byte[] array = File.ReadAllBytes(IconPath);
				Texture2D val = new Texture2D(2, 2);
				if (!ImageConversion.LoadImage(val, array))
				{
					return Load();
				}
				Color[] pixels = val.GetPixels();
				for (int i = 0; i < pixels.Length; i++)
				{
					pixels[i] = new Color(pixels[i].r * tint.r, pixels[i].g * tint.g, pixels[i].b * tint.b, pixels[i].a);
				}
				val.SetPixels(pixels);
				val.Apply();
				Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
				_cache[hashCode] = val2;
				return val2;
			}
			catch
			{
				return Load();
			}
		}
	}
	internal static class QuestPoiFixer
	{
		[CompilerGenerated]
		private sealed class <FixPositionDelayed>d__2 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public QuestEntry entry;

			public Vector3 worldPos;

			private int <i>5__1;

			private QuestEntry <s1Entry>5__2;

			private Transform <poiLoc>5__3;

			private POI <poi>5__4;

			private Exception <ex>5__5;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <FixPositionDelayed>d__2(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<s1Entry>5__2 = null;
				<poiLoc>5__3 = null;
				<poi>5__4 = null;
				<ex>5__5 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_017a: Unknown result type (might be due to invalid IL or missing references)
				//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
				//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
				//IL_020d: Unknown result type (might be due to invalid IL or missing references)
				//IL_023c: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					OTCLog.Msg("Quest", $"QuestPoiFixer: starting, target={worldPos}");
					<i>5__1 = 0;
					break;
				case 1:
					<>1__state = -1;
					<i>5__1++;
					break;
				}
				if (<i>5__1 < 5)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				try
				{
					if (_s1EntryField == null)
					{
						_s1EntryField = typeof(QuestEntry).GetField("S1QuestEntry", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					}
					OTCLog.Msg("Quest", $"QuestPoiFixer: field={_s1EntryField != null}");
					ref QuestEntry reference = ref <s1Entry>5__2;
					object? obj = _s1EntryField?.GetValue(entry);
					reference = (QuestEntry)((obj is QuestEntry) ? obj : null);
					if ((Object)(object)<s1Entry>5__2 == (Object)null)
					{
						OTCLog.Warning("Quest", "QuestPoiFixer: s1Entry is null");
						return false;
					}
					<poiLoc>5__3 = <s1Entry>5__2.PoILocation;
					<poi>5__4 = <s1Entry>5__2.PoI;
					object[] obj2 = new object[4]
					{
						(Object)(object)<poiLoc>5__3 != (Object)null,
						null,
						null,
						null
					};
					Transform obj3 = <poiLoc>5__3;
					obj2[1] = ((obj3 != null) ? new Vector3?(obj3.position) : null);
					obj2[2] = (Object)(object)<poi>5__4 != (Object)null;
					POI obj4 = <poi>5__4;
					obj2[3] = ((obj4 != null) ? new Vector3?(((Component)obj4).transform.position) : null);
					OTCLog.Msg("Quest", string.Format("QuestPoiFixer: PoILocation={0} pos={1} PoI={2} poiPos={3}", obj2));
					<s1Entry>5__2.SetPoILocation(worldPos);
					Transform poILocation = <s1Entry>5__2.PoILocation;
					object arg = ((poILocation != null) ? new Vector3?(poILocation.position) : null);
					POI poI = <s1Entry>5__2.PoI;
					OTCLog.Msg("Quest", $"QuestPoiFixer: AFTER SetPoILocation → PoILocation.pos={arg} PoI.pos={((poI != null) ? new Vector3?(((Component)poI).transform.position) : null)}");
					<s1Entry>5__2 = null;
					<poiLoc>5__3 = null;
					<poi>5__4 = null;
				}
				catch (Exception ex)
				{
					<ex>5__5 = ex;
					OTCLog.Warning("Quest", "QuestPoiFixer failed: " + <ex>5__5.Message);
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static FieldInfo _s1EntryField;

		public static void FixPosition(QuestEntry entry, Vector3 worldPos)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (entry != null)
			{
				MelonCoroutines.Start(FixPositionDelayed(entry, worldPos));
			}
		}

		[IteratorStateMachine(typeof(<FixPositionDelayed>d__2))]
		private static IEnumerator FixPositionDelayed(QuestEntry entry, Vector3 worldPos)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <FixPositionDelayed>d__2(0)
			{
				entry = entry,
				worldPos = worldPos
			};
		}
	}
	public class StaticIntroQuest : Quest
	{
		[SaveableField("static_quest_stage")]
		private int _stage;

		private QuestEntry _checkMessagesEntry;

		private QuestEntry _payEntry;

		private QuestEntry _dropOffEntry;

		protected override string Title => "Crimeware as a Service";

		protected override string Description => "Someone noticed your operation. Check the OTC app for a new message.";

		protected override bool AutoBegin => false;

		protected override Sprite QuestIcon => QuestIconHelper.Load();

		public static StaticIntroQuest Instance { get; private set; }

		public int Stage => _stage;

		private static Vector3 DeadDropPosition => CasinoDeadDrop.Position;

		internal static void ResetInstance()
		{
			Instance = null;
		}

		public void Initialize()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_checkMessagesEntry = ((Quest)this).AddEntry("Check your messages in the OTC app", (Vector3?)null);
				_payEntry = ((Quest)this).AddEntry(GetPayText(), (Vector3?)null);
				_dropOffEntry = ((Quest)this).AddEntry(GetDropOffText(), (Vector3?)DeadDropPosition);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "Initialize failed: " + ex.Message);
			}
		}

		private static string GetPayText()
		{
			return $"Pay ${Config.StaticTier1BankCost.Value:N0} via OTC app";
		}

		private static string GetDropOffText()
		{
			return $"Drop off {Config.StaticTier1WeedGrams.Value}g weed at the casino dead drop";
		}

		public void RefreshEntryText()
		{
			if (_payEntry != null && _stage >= 2 && _stage < 4)
			{
				_payEntry.Title = GetPayText();
			}
			if (_dropOffEntry != null && _stage >= 2 && _stage < 4)
			{
				_dropOffEntry.Title = GetDropOffText();
			}
		}

		public void StartQuest()
		{
			try
			{
				_stage = 1;
				((Quest)this).Begin();
				QuestEntry checkMessagesEntry = _checkMessagesEntry;
				if (checkMessagesEntry != null)
				{
					checkMessagesEntry.Begin();
				}
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "StartQuest failed: " + ex.Message);
			}
		}

		public void CompleteObj1()
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_stage = 2;
				QuestEntry checkMessagesEntry = _checkMessagesEntry;
				if (checkMessagesEntry != null)
				{
					checkMessagesEntry.Begin();
				}
				QuestEntry checkMessagesEntry2 = _checkMessagesEntry;
				if (checkMessagesEntry2 != null)
				{
					checkMessagesEntry2.Complete();
				}
				QuestEntry payEntry = _payEntry;
				if (payEntry != null)
				{
					payEntry.Begin();
				}
				QuestEntry dropOffEntry = _dropOffEntry;
				if (dropOffEntry != null)
				{
					dropOffEntry.Begin();
				}
				QuestPoiFixer.FixPosition(_dropOffEntry, DeadDropPosition);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "CompleteObj1 failed: " + ex.Message);
			}
		}

		public void CompleteObj2()
		{
			try
			{
				_stage = 3;
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "CompleteObj2 failed: " + ex.Message);
			}
		}

		public void CompleteObj3()
		{
			try
			{
				_stage = 4;
				QuestEntry payEntry = _payEntry;
				if (payEntry != null)
				{
					payEntry.Begin();
				}
				QuestEntry payEntry2 = _payEntry;
				if (payEntry2 != null)
				{
					payEntry2.Complete();
				}
				QuestEntry dropOffEntry = _dropOffEntry;
				if (dropOffEntry != null)
				{
					dropOffEntry.Begin();
				}
				QuestEntry dropOffEntry2 = _dropOffEntry;
				if (dropOffEntry2 != null)
				{
					dropOffEntry2.Complete();
				}
				((Quest)this).Complete();
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "CompleteObj3 failed: " + ex.Message);
			}
		}

		public void CompletePay()
		{
			QuestEntry payEntry = _payEntry;
			if (payEntry != null)
			{
				payEntry.Begin();
			}
			QuestEntry payEntry2 = _payEntry;
			if (payEntry2 != null)
			{
				payEntry2.Complete();
			}
			QuestEntry dropOffEntry = _dropOffEntry;
			if (dropOffEntry != null)
			{
				dropOffEntry.Begin();
			}
		}

		public void CompleteDropOff()
		{
			QuestEntry dropOffEntry = _dropOffEntry;
			if (dropOffEntry != null)
			{
				dropOffEntry.Begin();
			}
			QuestEntry dropOffEntry2 = _dropOffEntry;
			if (dropOffEntry2 != null)
			{
				dropOffEntry2.Complete();
			}
		}

		protected override void OnCreated()
		{
			((Registerable)this).OnCreated();
			Instance = this;
		}

		protected override void OnLoaded()
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			((Saveable)this).OnLoaded();
			Instance = this;
			try
			{
				if (StaticSaveData.Instance != null)
				{
					int num = ((StaticSaveData.Instance.CrmTier >= 1) ? 4 : (StaticSaveData.Instance.IntroCompleted ? 2 : (StaticSaveData.Instance.QuestTriggered ? 1 : 0)));
					if (num > _stage)
					{
						_stage = num;
					}
				}
				base.QuestEntries.Clear();
				_checkMessagesEntry = ((Quest)this).AddEntry("Check your messages in the OTC app", (Vector3?)null);
				_payEntry = ((Quest)this).AddEntry(GetPayText(), (Vector3?)null);
				_dropOffEntry = ((Quest)this).AddEntry(GetDropOffText(), (Vector3?)DeadDropPosition);
				if (_stage >= 1)
				{
					QuestEntry checkMessagesEntry = _checkMessagesEntry;
					if (checkMessagesEntry != null)
					{
						checkMessagesEntry.Begin();
					}
				}
				if (_stage >= 2)
				{
					QuestEntry checkMessagesEntry2 = _checkMessagesEntry;
					if (checkMessagesEntry2 != null)
					{
						checkMessagesEntry2.Complete();
					}
					QuestEntry payEntry = _payEntry;
					if (payEntry != null)
					{
						payEntry.Begin();
					}
					QuestEntry dropOffEntry = _dropOffEntry;
					if (dropOffEntry != null)
					{
						dropOffEntry.Begin();
					}
					QuestPoiFixer.FixPosition(_dropOffEntry, DeadDropPosition);
				}
				if (_stage >= 2 && _stage < 4 && StaticSaveData.Instance != null)
				{
					if (StaticSaveData.Instance.Tier1MoneyPaid)
					{
						CompletePay();
					}
					if (StaticSaveData.Instance.Tier1ProductDelivered)
					{
						CompleteDropOff();
					}
				}
				if (_stage >= 4)
				{
					QuestEntry payEntry2 = _payEntry;
					if (payEntry2 != null)
					{
						payEntry2.Complete();
					}
					QuestEntry dropOffEntry2 = _dropOffEntry;
					if (dropOffEntry2 != null)
					{
						dropOffEntry2.Complete();
					}
					((Quest)this).Complete();
				}
			}
			catch (Exception ex)
			{
				OTCLog.Warning("Quest", "OnLoaded rebuild failed: " + ex.Message);
			}
		}
	}
	public class StaticUpgrade1Quest : Quest
	{
		[SaveableField("static_upgrade1_stage")]
		private int _stage;

		private QuestEntry _payEntry;

		private QuestEntry _dropOffEntry;

		protected override string Title => "Premium Tier";

		protected override string Description => "Static has the premium tier upgrade available. Pay and deliver via the OTC app.";

		protected override bool AutoBegin => false;

		protected override Sprite QuestIcon => QuestIconHelper.Load();

		public static StaticUpgrade1Quest Instance { get; private set; }

		public int Stage => _stage;

		internal static void ResetInstance()
		{
			Instance = null;
		}

		public void Initialize()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_payEntry = ((Quest)this).AddEntry(GetPayText(), (Vector3?)null);
				_dropOffEntry = ((Quest)this).AddEntry(GetDropOffText(), (Vector3?)CasinoDeadDrop.Position);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "Initialize failed: " + ex.Message);
			}
		}

		private static string GetPayText()
		{
			return $"Pay ${Config.StaticTier2BankCost.Value:N0} via OTC app";
		}

		private static string GetDropOffText()
		{
			return $"Drop off {Config.StaticTier2MethGrams.Value}g meth at the casino dead drop";
		}

		public void RefreshEntryText()
		{
			if (_payEntry != null && _stage >= 1 && _stage < 2)
			{
				_payEntry.Title = GetPayText();
			}
			if (_dropOffEntry != null && _stage >= 1 && _stage < 2)
			{
				_dropOffEntry.Title = GetDropOffText();
			}
		}

		public void StartQuest()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_stage = 1;
				((Quest)this).Begin();
				QuestEntry payEntry = _payEntry;
				if (payEntry != null)
				{
					payEntry.Begin();
				}
				QuestEntry dropOffEntry = _dropOffEntry;
				if (dropOffEntry != null)
				{
					dropOffEntry.Begin();
				}
				QuestPoiFixer.FixPosition(_dropOffEntry, CasinoDeadDrop.Position);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "StartQuest failed: " + ex.Message);
			}
		}

		public void CompleteObj1()
		{
			try
			{
				_stage = 2;
				QuestEntry payEntry = _payEntry;
				if (payEntry != null)
				{
					payEntry.Begin();
				}
				QuestEntry payEntry2 = _payEntry;
				if (payEntry2 != null)
				{
					payEntry2.Complete();
				}
				QuestEntry dropOffEntry = _dropOffEntry;
				if (dropOffEntry != null)
				{
					dropOffEntry.Begin();
				}
				QuestEntry dropOffEntry2 = _dropOffEntry;
				if (dropOffEntry2 != null)
				{
					dropOffEntry2.Complete();
				}
				((Quest)this).Complete();
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "CompleteObj1 failed: " + ex.Message);
			}
		}

		public void CompletePay()
		{
			QuestEntry payEntry = _payEntry;
			if (payEntry != null)
			{
				payEntry.Begin();
			}
			QuestEntry payEntry2 = _payEntry;
			if (payEntry2 != null)
			{
				payEntry2.Complete();
			}
			QuestEntry dropOffEntry = _dropOffEntry;
			if (dropOffEntry != null)
			{
				dropOffEntry.Begin();
			}
		}

		public void CompleteDropOff()
		{
			QuestEntry dropOffEntry = _dropOffEntry;
			if (dropOffEntry != null)
			{
				dropOffEntry.Begin();
			}
			QuestEntry dropOffEntry2 = _dropOffEntry;
			if (dropOffEntry2 != null)
			{
				dropOffEntry2.Complete();
			}
		}

		protected override void OnCreated()
		{
			((Registerable)this).OnCreated();
			Instance = this;
		}

		protected override void OnLoaded()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			((Saveable)this).OnLoaded();
			Instance = this;
			try
			{
				base.QuestEntries.Clear();
				_payEntry = ((Quest)this).AddEntry(GetPayText(), (Vector3?)null);
				_dropOffEntry = ((Quest)this).AddEntry(GetDropOffText(), (Vector3?)CasinoDeadDrop.Position);
				if (_stage >= 1)
				{
					QuestEntry payEntry = _payEntry;
					if (payEntry != null)
					{
						payEntry.Begin();
					}
					QuestEntry dropOffEntry = _dropOffEntry;
					if (dropOffEntry != null)
					{
						dropOffEntry.Begin();
					}
					QuestPoiFixer.FixPosition(_dropOffEntry, CasinoDeadDrop.Position);
				}
				if (_stage >= 1 && _stage < 2 && StaticSaveData.Instance != null)
				{
					if (StaticSaveData.Instance.UpgradeMoneyPaid)
					{
						CompletePay();
					}
					if (StaticSaveData.Instance.UpgradeProductDelivered)
					{
						CompleteDropOff();
					}
				}
				if (_stage >= 2)
				{
					QuestEntry payEntry2 = _payEntry;
					if (payEntry2 != null)
					{
						payEntry2.Complete();
					}
					QuestEntry dropOffEntry2 = _dropOffEntry;
					if (dropOffEntry2 != null)
					{
						dropOffEntry2.Complete();
					}
					((Quest)this).Complete();
				}
			}
			catch (Exception ex)
			{
				OTCLog.Warning("Quest", "OnLoaded rebuild failed: " + ex.Message);
			}
		}
	}
	public class StaticUpgrade2Quest : Quest
	{
		[SaveableField("static_upgrade2_stage")]
		private int _stage;

		private QuestEntry _payEntry;

		private QuestEntry _dropOffEntry;

		protected override string Title => "Full Scale";

		protected override string Description => "Static has the final tier-3 enterprise upgrade available. Pay and deliver via the OTC app.";

		protected override bool AutoBegin => false;

		protected override Sprite QuestIcon => QuestIconHelper.Load();

		public static StaticUpgrade2Quest Instance { get; private set; }

		public int Stage => _stage;

		internal static void ResetInstance()
		{
			Instance = null;
		}

		public void Initialize()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_payEntry = ((Quest)this).AddEntry(GetPayText(), (Vector3?)null);
				_dropOffEntry = ((Quest)this).AddEntry(GetDropOffText(), (Vector3?)CasinoDeadDrop.Position);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "Initialize failed: " + ex.Message);
			}
		}

		private static string GetPayText()
		{
			return $"Pay ${Config.StaticTier3BankCost.Value:N0} via OTC app";
		}

		private static string GetDropOffText()
		{
			return $"Drop off {Config.StaticTier3PremiumMethGrams.Value}g premium meth at the casino dead drop";
		}

		public void RefreshEntryText()
		{
			if (_payEntry != null && _stage >= 1 && _stage < 2)
			{
				_payEntry.Title = GetPayText();
			}
			if (_dropOffEntry != null && _stage >= 1 && _stage < 2)
			{
				_dropOffEntry.Title = GetDropOffText();
			}
		}

		public void StartQuest()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_stage = 1;
				((Quest)this).Begin();
				QuestEntry payEntry = _payEntry;
				if (payEntry != null)
				{
					payEntry.Begin();
				}
				QuestEntry dropOffEntry = _dropOffEntry;
				if (dropOffEntry != null)
				{
					dropOffEntry.Begin();
				}
				QuestPoiFixer.FixPosition(_dropOffEntry, CasinoDeadDrop.Position);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "StartQuest failed: " + ex.Message);
			}
		}

		public void CompleteObj1()
		{
			try
			{
				_stage = 2;
				QuestEntry payEntry = _payEntry;
				if (payEntry != null)
				{
					payEntry.Begin();
				}
				QuestEntry payEntry2 = _payEntry;
				if (payEntry2 != null)
				{
					payEntry2.Complete();
				}
				QuestEntry dropOffEntry = _dropOffEntry;
				if (dropOffEntry != null)
				{
					dropOffEntry.Begin();
				}
				QuestEntry dropOffEntry2 = _dropOffEntry;
				if (dropOffEntry2 != null)
				{
					dropOffEntry2.Complete();
				}
				((Quest)this).Complete();
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "CompleteObj1 failed: " + ex.Message);
			}
		}

		public void CompletePay()
		{
			QuestEntry payEntry = _payEntry;
			if (payEntry != null)
			{
				payEntry.Begin();
			}
			QuestEntry payEntry2 = _payEntry;
			if (payEntry2 != null)
			{
				payEntry2.Complete();
			}
			QuestEntry dropOffEntry = _dropOffEntry;
			if (dropOffEntry != null)
			{
				dropOffEntry.Begin();
			}
		}

		public void CompleteDropOff()
		{
			QuestEntry dropOffEntry = _dropOffEntry;
			if (dropOffEntry != null)
			{
				dropOffEntry.Begin();
			}
			QuestEntry dropOffEntry2 = _dropOffEntry;
			if (dropOffEntry2 != null)
			{
				dropOffEntry2.Complete();
			}
		}

		protected override void OnCreated()
		{
			((Registerable)this).OnCreated();
			Instance = this;
		}

		protected override void OnLoaded()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			((Saveable)this).OnLoaded();
			Instance = this;
			try
			{
				base.QuestEntries.Clear();
				_payEntry = ((Quest)this).AddEntry(GetPayText(), (Vector3?)null);
				_dropOffEntry = ((Quest)this).AddEntry(GetDropOffText(), (Vector3?)CasinoDeadDrop.Position);
				if (_stage >= 1)
				{
					QuestEntry payEntry = _payEntry;
					if (payEntry != null)
					{
						payEntry.Begin();
					}
					QuestEntry dropOffEntry = _dropOffEntry;
					if (dropOffEntry != null)
					{
						dropOffEntry.Begin();
					}
					QuestPoiFixer.FixPosition(_dropOffEntry, CasinoDeadDrop.Position);
				}
				if (_stage >= 1 && _stage < 2 && StaticSaveData.Instance != null)
				{
					if (StaticSaveData.Instance.UpgradeMoneyPaid)
					{
						CompletePay();
					}
					if (StaticSaveData.Instance.UpgradeProductDelivered)
					{
						CompleteDropOff();
					}
				}
				if (_stage >= 2)
				{
					QuestEntry payEntry2 = _payEntry;
					if (payEntry2 != null)
					{
						payEntry2.Complete();
					}
					QuestEntry dropOffEntry2 = _dropOffEntry;
					if (dropOffEntry2 != null)
					{
						dropOffEntry2.Complete();
					}
					((Quest)this).Complete();
				}
			}
			catch (Exception ex)
			{
				OTCLog.Warning("Quest", "OnLoaded rebuild failed: " + ex.Message);
			}
		}
	}
	public class DrifterDealQuest : Quest
	{
		private string _title;

		private string _description;

		private QuestEntry _deliverEntry;

		private int _deadlineElapsedMinutes;

		protected override string Title => _title ?? "Drifter Deal";

		protected override string Description => _description ?? "Complete a deal with a drifter.";

		protected override bool AutoBegin => false;

		protected override Sprite QuestIcon => (Core.OtcIconDir != null) ? ImageUtils.LoadImage(Path.Combine(Core.OtcIconDir, "DrifterQuestIcon.png")) : null;

		public string DrifterId { get; private set; }

		public static Dictionary<string, DrifterDealQuest> ActiveQuests { get; } = new Dictionary<string, DrifterDealQuest>();


		private Quest GetS1Quest()
		{
			object? obj = typeof(Quest).GetField("S1Quest", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(this);
			return (Quest)((obj is Quest) ? obj : null);
		}

		private void TriggerInternalInit()
		{
			try
			{
				Quest s1Quest = GetS1Quest();
				if (!((Object)(object)s1Quest == (Object)null))
				{
					s1Quest.InitializeQuest(((Quest)this).Title, ((Quest)this).Description, Array.Empty<QuestEntryData>(), s1Quest.StaticGUID);
				}
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "TriggerInternalInit failed: " + ex.Message);
			}
		}

		public void Initialize(string drifterId, string productName, int quantity, float payment, Vector3 destination, string locationDesc, int deadlineElapsedMinutes)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			DrifterId = drifterId;
			_title = "Drifter Deal";
			_description = $"Deliver {quantity} {productName} for ${payment:F0}";
			_deadlineElapsedMinutes = deadlineElapsedMinutes;
			TriggerInternalInit();
			_deliverEntry = ((Quest)this).AddEntry($"Deliver {quantity} {productName} to the drifter {locationDesc}", (Vector3?)destination);
			ActiveQuests[drifterId] = this;
		}

		public void StartQuest()
		{
			try
			{
				((Quest)this).Begin();
				QuestEntry deliverEntry = _deliverEntry;
				if (deliverEntry != null)
				{
					deliverEntry.Begin();
				}
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "StartQuest failed: " + ex.Message);
			}
		}

		public void UpdateTiming()
		{
			try
			{
				if (_deadlineElapsedMinutes > 0)
				{
					int currentElapsedMinutes = GetCurrentElapsedMinutes();
					int num = _deadlineElapsedMinutes - currentElapsedMinutes;
					if (num < 0)
					{
						num = 0;
					}
					int num2 = num / 60;
					int num3 = num % 60;
					string subtitleViaReflection = ((num >= 120) ? $"<color=green> (Expires in {num2}h {num3}m)</color>" : ((num2 <= 0) ? $"<color=#ff6b6b> (Expires in {num} min)</color>" : $"<color=#ff6b6b> (Expires in {num2}h {num3}m)</color>"));
					SetSubtitleViaReflection(subtitleViaReflection);
				}
			}
			catch (Exception ex)
			{
				OTCLog.Warning("Quest", "UpdateTiming failed: " + ex.Message);
			}
		}

		private void SetSubtitleViaReflection(string subtitle)
		{
			try
			{
				Quest s1Quest = GetS1Quest();
				if (!((Object)(object)s1Quest == (Object)null))
				{
					s1Quest.SetSubtitle(subtitle);
					if ((Object)(object)s1Quest.hudUI != (Object)null)
					{
						s1Quest.hudUI.UpdateMainLabel();
					}
				}
			}
			catch (Exception ex)
			{
				OTCLog.Warning("Quest", "SetSubtitleViaReflection failed: " + ex.Message);
			}
		}

		private static int GetCurrentElapsedMinutes()
		{
			int elapsedDays = TimeManager.ElapsedDays;
			int currentTime = TimeManager.CurrentTime;
			int num = currentTime / 100;
			int num2 = currentTime % 100;
			return elapsedDays * 1440 + num * 60 + num2;
		}

		public void CompleteDeal()
		{
			try
			{
				QuestEntry deliverEntry = _deliverEntry;
				if (deliverEntry != null)
				{
					deliverEntry.Complete();
				}
				((Quest)this).Complete();
				((Quest)this).End();
				ActiveQuests.Remove(DrifterId);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "CompleteDeal failed: " + ex.Message);
			}
		}

		public void FailDeal()
		{
			try
			{
				QuestEntry deliverEntry = _deliverEntry;
				if (deliverEntry != null)
				{
					deliverEntry.Complete();
				}
				((Quest)this).Fail();
				ActiveQuests.Remove(DrifterId);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "FailDeal failed: " + ex.Message);
			}
		}

		public void CancelDeal()
		{
			try
			{
				((Quest)this).Cancel();
				ActiveQuests.Remove(DrifterId);
			}
			catch (Exception ex)
			{
				OTCLog.Error("Quest", "CancelDeal failed: " + ex.Message);
			}
		}
	}
	public enum QuestHighlight
	{
		None,
		InventoryNav,
		PricingArea,
		ProductRows,
		OverviewNav,
		StoreToggle
	}
	public class StorefrontGrowthQuest : Quest
	{
		[SaveableField("storefront_quest_stage")]
		private int _stage;

		[SaveableField("storefront_quest_touched_pricing")]
		private bool _hasTouchedPricing;

		[SaveableField("storefront_quest_viewed_product")]
		private bool _hasViewedProduct;

		private QuestEntry _placeStorageEntry;

		private QuestEntry _stockProductEntry;

		private QuestEntry _setPricesEntry;

		private QuestEntry _viewProductEntry;

		private QuestEntry _turnOnLightsEntry;

		private QuestEntry _openStoreEntry;

		private QuestEntry _makeSaleEntry;

		private static readonly Vector3 ShackPosition = new Vector3(-164.4f, -3f, 76f);

		private float _lastTickTime;

		private const float TickInterval = 3f;

		private TutorialCustomerHelper _tutorialCustomer;

		protected override string Title => "Storefront Growth";

		protected override string Description => "You've got the keys. Now turn this place into a working storefront.";

		protected override bool AutoBegin => false;

		protected override Sprite QuestIcon => (Core.OtcIconDir != null) ? ImageUtils.LoadImage(Path.Combine(Core.OtcIconDir, "StoreAlertIcon.png")) : null;

		public static StorefrontGrowthQuest Instance { get; private set; }

		public int Stage => _stage;

		public static QuestHighlight ActiveHighlight
		{
			get
			{
				if (Instance == null)
				{
					return QuestHighlight.None;
				}
				int stage = Instance._stage;
				if (1 == 0)
				{
				}
				QuestHighlight result = stage switch
				{
					3 => QuestHighlight.InventoryNav,