Decompiled source of SimpleCall v1.1.0

Mods/SimpleCall.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using Il2CppScheduleOne.DevUtilities;
using Il2CppScheduleOne.Map;
using Il2CppScheduleOne.NPCs;
using Il2CppScheduleOne.PlayerScripts;
using Il2CppScheduleOne.UI.Phone.Messages;
using Il2CppSystem;
using Il2CppTMPro;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using SimpleCall;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(CallDealers), "SimpleCall", "1.1.0", "tiagovito", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("SimpleCall")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SimpleCall")]
[assembly: AssemblyTitle("SimpleCall")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace SimpleCall
{
	public static class ButtonManager
	{
		private record PathConfig(string ParentPath, string ReferencePath, Vector3 ButtonPosition, bool IsModded)
		{
			[CompilerGenerated]
			protected virtual bool PrintMembers(StringBuilder builder)
			{
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				RuntimeHelpers.EnsureSufficientExecutionStack();
				builder.Append("ParentPath = ");
				builder.Append((object?)ParentPath);
				builder.Append(", ReferencePath = ");
				builder.Append((object?)ReferencePath);
				builder.Append(", ButtonPosition = ");
				Vector3 buttonPosition = ButtonPosition;
				builder.Append(((object)(Vector3)(ref buttonPosition)).ToString());
				builder.Append(", IsModded = ");
				builder.Append(IsModded.ToString());
				return true;
			}
		}

		private class DealerMoveState
		{
			public Vector3 TargetPosition { get; }

			public int RetryCount { get; set; }

			public NPCScheduleManager ScheduleManager { get; }

			public DealerMoveState(Vector3 targetPosition, NPCScheduleManager scheduleManager)
			{
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				TargetPosition = targetPosition;
				ScheduleManager = scheduleManager;
				RetryCount = 0;
			}
		}

		private const float MAX_WARP_RADIUS = 150f;

		private const int MAX_INITIALIZATION_ATTEMPTS = 120;

		private const float INITIALIZATION_RETRY_DELAY = 0.5f;

		private const int MAX_MOVEMENT_RETRIES = 2;

		private const float MIN_SUCCESS_DISTANCE = 10f;

		private const float CHECK_INTERVAL = 0.25f;

		private const float RETRY_DELAY = 0.25f;

		private const string BUTTON_NAME = "CallDealerButton";

		private const string BUTTON_TEXT = "Call Dealer";

		private const int BUTTON_WIDTH = 150;

		private const int BUTTON_HEIGHT = 40;

		private const int BUTTON_FONT_SIZE = 24;

		private static readonly PathConfig[] UI_PATHS = new PathConfig[2]
		{
			new PathConfig("Player_Local/CameraContainer/Camera/OverlayCamera/GameplayMenu/Phone/phone/AppsCanvas/DealerManagement/Container/Background/Content", "Player_Local/CameraContainer/Camera/OverlayCamera/GameplayMenu/Phone/phone/AppsCanvas/DealerManagement/Container/Background/Content/Cash", new Vector3(180f, 60f, 0f), IsModded: false),
			new PathConfig("Player_Local/CameraContainer/Camera/OverlayCamera/GameplayMenu/Phone/phone/AppsCanvas/DealerManagement/Container/Background/ScrollingContent/Content", "Player_Local/CameraContainer/Camera/OverlayCamera/GameplayMenu/Phone/phone/AppsCanvas/DealerManagement/Container/Background/ScrollingContent/Content/Cash", new Vector3(190f, 387f, 0f), IsModded: true)
		};

		private static readonly Vector3[] STRATEGIC_LOCATIONS = (Vector3[])(object)new Vector3[32]
		{
			new Vector3(165.71f, 10.04f, -77.76f),
			new Vector3(147.21f, 4.05f, -104.98f),
			new Vector3(145.43f, 4.14f, -101.05f),
			new Vector3(87.15f, 4.14f, -100.74f),
			new Vector3(-14.42f, 0.14f, -80.2f),
			new Vector3(-22.53f, 0.14f, -43.03f),
			new Vector3(-57.67f, -2.36f, -63.09f),
			new Vector3(11.81f, 0.14f, -32.88f),
			new Vector3(36.17f, 0.14f, 7.04f),
			new Vector3(87.55f, 0.14f, 7.06f),
			new Vector3(140.43f, 0.14f, 7.52f),
			new Vector3(178.73f, 0.04f, -10.85f),
			new Vector3(87.08f, 0.14f, 47.01f),
			new Vector3(127.57f, 0.14f, 55.56f),
			new Vector3(129.83f, 0.14f, 89.81f),
			new Vector3(35.69f, 0.14f, 55.51f),
			new Vector3(-14.81f, 0.14f, 55.08f),
			new Vector3(-54.45f, 0.14f, 62.6f),
			new Vector3(-104.3f, -3.86f, 72.61f),
			new Vector3(-133.67f, -3.86f, 32.15f),
			new Vector3(-149.34f, -3.86f, 88.37f),
			new Vector3(-166.26f, -3.66f, 113.98f),
			new Vector3(-148.01f, -3.86f, 126.18f),
			new Vector3(-75.39f, -3.86f, 119.47f),
			new Vector3(-60.99f, -3.96f, 145.99f),
			new Vector3(-33.89f, -3.86f, 134.41f),
			new Vector3(-22.74f, 0.14f, 86.44f),
			new Vector3(-63.92f, 0.14f, 82.83f),
			new Vector3(-5.18f, 0.16f, 100.53f),
			new Vector3(27.54f, 0.14f, 80.41f),
			new Vector3(80.28f, 0.14f, 91.45f),
			new Vector3(-71.91f, -2.45f, -49.06f)
		};

		private static GameObject _targetParent;

		private static GameObject _gameObjectReference;

		private static GameObject _callDealerButton;

		private static PathConfig _currentPathConfig;

		private static readonly Dictionary<int, DealerMoveState> _dealerMoveStates = new Dictionary<int, DealerMoveState>();

		public static void Initialize()
		{
			MelonCoroutines.Start(InitializeCoroutine());
		}

		public static void Terminate()
		{
			try
			{
				RemoveButton();
				ResetState();
				LogDebug("ButtonManager terminated successfully");
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Error during termination: " + ex.Message + "\n" + ex.StackTrace);
			}
		}

		public static void LogPlayerPosition()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			Player player = GetPlayer();
			if ((Object)(object)player == (Object)null)
			{
				MelonLogger.Error("Player is null, cannot get Vector3 position.");
				return;
			}
			MelonLogger.Msg($"Player Vector3 position: {player.PlayerBasePosition}");
		}

		private static IEnumerator InitializeCoroutine()
		{
			LogDebug("Starting initialization...");
			for (int attempts = 0; attempts < 120; attempts++)
			{
				if (TryFindUiElements())
				{
					CreateCallDealerButton();
					yield break;
				}
				yield return (object)new WaitForSeconds(0.5f);
			}
			MelonLogger.Error($"Failed to find UI elements after {120} attempts");
		}

		private static bool TryFindUiElements()
		{
			PathConfig[] uI_PATHS = UI_PATHS;
			foreach (PathConfig pathConfig in uI_PATHS)
			{
				GameObject val = GameObject.Find(pathConfig.ParentPath);
				GameObject val2 = GameObject.Find(pathConfig.ReferencePath);
				if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
				{
					_targetParent = val;
					_gameObjectReference = val2;
					_currentPathConfig = pathConfig;
					LogDebug("Found UI elements (" + (pathConfig.IsModded ? "modded" : "vanilla") + " path)");
					return true;
				}
			}
			return false;
		}

		private static void CreateCallDealerButton()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			LogDebug("Creating Call Dealer button...");
			try
			{
				if ((Object)(object)_targetParent == (Object)null || (Object)(object)_gameObjectReference == (Object)null)
				{
					MelonLogger.Error("Required UI elements are null");
					return;
				}
				RemoveButton();
				_callDealerButton = new GameObject("CallDealerButton")
				{
					layer = _targetParent.layer
				};
				_callDealerButton.transform.SetParent(_targetParent.transform, false);
				SetupButtonComponents(_callDealerButton);
				LogDebug("Button created successfully");
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Error creating button: " + ex.Message + "\n" + ex.StackTrace);
			}
		}

		private static void SetupButtonComponents(GameObject buttonGameObject)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = buttonGameObject.AddComponent<RectTransform>();
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			val.pivot = val2;
			Vector2 anchorMin = (val.anchorMax = val2);
			val.anchorMin = anchorMin;
			val.sizeDelta = new Vector2(150f, 40f);
			((Transform)val).localScale = Vector3.one;
			((Transform)val).localPosition = _currentPathConfig.ButtonPosition;
			((Graphic)buttonGameObject.AddComponent<Image>()).color = new Color(0.2f, 0.2f, 0.2f);
			SetupButtonText(buttonGameObject);
			((UnityEvent)buttonGameObject.AddComponent<Button>().onClick).AddListener(UnityAction.op_Implicit((Action)OnCallDealerButtonClicked));
		}

		private static void SetupButtonText(GameObject buttonGameObject)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("ButtonText");
			val.transform.SetParent(buttonGameObject.transform, false);
			RectTransform val2 = val.AddComponent<RectTransform>();
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			Vector2 offsetMin = (val2.offsetMax = Vector2.zero);
			val2.offsetMin = offsetMin;
			TextMeshProUGUI val3 = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val3).text = "Call Dealer";
			((Graphic)val3).color = Color.white;
			((TMP_Text)val3).fontSize = 24f;
			((TMP_Text)val3).fontStyle = (FontStyles)1;
			((TMP_Text)val3).alignment = (TextAlignmentOptions)514;
			((TMP_Text)val3).enableWordWrapping = false;
			((TMP_Text)val3).overflowMode = (TextOverflowModes)0;
		}

		private static void RemoveButton()
		{
			if ((Object)(object)_callDealerButton != (Object)null)
			{
				LogDebug("Destroying Call Dealer button");
				Object.Destroy((Object)(object)_callDealerButton);
				_callDealerButton = null;
			}
		}

		private static void ResetState()
		{
			_targetParent = null;
			_gameObjectReference = null;
			_currentPathConfig = null;
			_callDealerButton = null;
			_dealerMoveStates.Clear();
		}

		private static void OnCallDealerButtonClicked()
		{
			//IL_0038: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			LogDebug("Call Dealer button clicked");
			try
			{
				Player player = GetPlayer();
				NPC selectedDealer = GetSelectedDealer();
				if ((Object)(object)player == (Object)null || (Object)(object)selectedDealer == (Object)null)
				{
					return;
				}
				Vector3 playerBasePosition = player.PlayerBasePosition;
				NPCScheduleManager componentInChildren = ((Component)selectedDealer).GetComponentInChildren<NPCScheduleManager>();
				if (TryExitBuilding(selectedDealer))
				{
					if ((Object)(object)componentInChildren != (Object)null)
					{
						componentInChildren.DisableSchedule();
						LogDebug("Disabled dealer's schedule for transit.");
					}
					int instanceID = ((Object)selectedDealer).GetInstanceID();
					_dealerMoveStates[instanceID] = new DealerMoveState(playerBasePosition, componentInChildren);
					if (ModSettings.ActivateDealerMessages.Value)
					{
						selectedDealer.SendTextMessage(DealerMessages.GetRandomCalledMessage());
					}
					MoveDealerToPlayer(selectedDealer);
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Error in button click handler: " + ex.Message + "\n" + ex.StackTrace);
			}
		}

		private static Player GetPlayer()
		{
			Player val = Object.FindObjectOfType<Player>();
			if ((Object)(object)val == (Object)null)
			{
				MelonLogger.Error("Failed to find Player object");
			}
			return val;
		}

		private static NPC GetSelectedDealer()
		{
			DealerManagementApp instance = PlayerSingleton<DealerManagementApp>.Instance;
			if ((Object)(object)((instance != null) ? instance.SelectedDealer : null) == (Object)null)
			{
				MelonLogger.Error("Selected dealer is null");
				return null;
			}
			return (NPC)(object)PlayerSingleton<DealerManagementApp>.Instance.SelectedDealer;
		}

		private static bool TryExitBuilding(NPC dealer)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				NPCEnterableBuilding currentBuilding = dealer.CurrentBuilding;
				if ((Object)(object)currentBuilding != (Object)null)
				{
					LogDebug($"Making dealer exit building: {currentBuilding.GUID}");
					Guid gUID = currentBuilding.GUID;
					dealer.ExitBuilding(((object)(Guid)(ref gUID)).ToString());
				}
				return true;
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Exception when trying to exit building: " + ex.Message);
				return false;
			}
		}

		private static void MoveDealerToPlayer(NPC dealer)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			int instanceID = ((Object)dealer).GetInstanceID();
			if (!_dealerMoveStates.TryGetValue(instanceID, out DealerMoveState value))
			{
				MelonLogger.Error("Move state not found for dealer - can't continue");
				return;
			}
			NPCMovement component = ((Component)dealer).GetComponent<NPCMovement>();
			if ((Object)(object)component == (Object)null)
			{
				MelonLogger.Error("Could not find NPCMovement component");
				return;
			}
			Vector3 position = ((Component)dealer).transform.position;
			float num = Vector3.Distance(position, value.TargetPosition);
			Action<WalkResult> callback = CreateMovementCallback(dealer);
			if (num <= 150f)
			{
				LogDebug($"Dealer is within {150f} units of target. Walking directly.");
				ExecuteMovement(component, value.TargetPosition, callback);
			}
			else
			{
				Vector3 val = FindOptimalWarpPosition(value.TargetPosition);
				LogDebug($"Warping dealer to position: {val}");
				component.Warp(val);
				ExecuteMovement(component, value.TargetPosition, callback);
			}
		}

		private static void ExecuteMovement(NPCMovement movement, Vector3 targetPosition, Action<WalkResult> callback)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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)
			if (movement.CanGetTo(targetPosition, 1f))
			{
				movement.SetDestination(targetPosition, callback, 1f, 1f);
				return;
			}
			Vector3? val = FindClosestWalkablePoint(movement, targetPosition);
			if (val.HasValue)
			{
				LogDebug($"Walking to closest strategic location at {val.Value}");
				movement.SetDestination(val.Value, callback, 1f, 1f);
			}
			else
			{
				MelonLogger.Warning("Cannot move to any location. Invoking completion directly.");
				callback?.Invoke((WalkResult)4);
			}
		}

		private static Action<WalkResult> CreateMovementCallback(NPC dealer)
		{
			NPC dealer2 = dealer;
			return Action<WalkResult>.op_Implicit((Action<WalkResult>)delegate(WalkResult result)
			{
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_005e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_0086: Unknown result type (might be due to invalid IL or missing references)
				//IL_010f: Unknown result type (might be due to invalid IL or missing references)
				int instanceID = ((Object)dealer2).GetInstanceID();
				if (_dealerMoveStates.TryGetValue(instanceID, out DealerMoveState value))
				{
					Vector3 position = ((Component)dealer2).transform.position;
					float num = Vector3.Distance(position, value.TargetPosition);
					Player player = GetPlayer();
					float num2 = (((Object)(object)player != (Object)null) ? Vector3.Distance(position, player.PlayerBasePosition) : float.MaxValue);
					LogDebug($"Walk result: {result}. Distance to target: {num}, distance to player: {num2}");
					if (IsCloseEnough(num, num2))
					{
						LogDebug("Dealer is close enough. Activating schedule.");
						if ((Object)(object)value.ScheduleManager != (Object)null)
						{
							MelonCoroutines.Start(HandleDealerArrival(value.ScheduleManager, dealer2));
						}
					}
					else
					{
						var (flag, flag2) = ShouldRetryMovement(result, value, num, num2);
						if (flag && value.RetryCount < 2)
						{
							value.RetryCount++;
							LogDebug($"Retrying movement (attempt {value.RetryCount}/{2})");
							MelonCoroutines.Start(RetryMovementAfterDelay(dealer2));
						}
						else if (flag2 && (Object)(object)value.ScheduleManager != (Object)null)
						{
							MelonCoroutines.Start(HandleDealerArrival(value.ScheduleManager, dealer2));
						}
					}
				}
			});
		}

		private static bool IsCloseEnough(float distanceToTarget, float distanceToPlayer)
		{
			return distanceToTarget <= 10f || distanceToPlayer <= (float)ModSettings.DealerInteractionDistance.Value;
		}

		private static (bool shouldRetry, bool shouldActivate) ShouldRetryMovement(WalkResult result, DealerMoveState moveState, float distanceToTarget, float distanceToPlayer)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected I4, but got Unknown
			if (1 == 0)
			{
			}
			(bool, bool) result2 = (int)result switch
			{
				0 => (moveState.RetryCount < 2, true), 
				4 => (moveState.RetryCount < 2, true), 
				1 => (moveState.RetryCount < 2 && distanceToTarget > 10f && distanceToPlayer > (float)ModSettings.DealerInteractionDistance.Value, true), 
				_ => (false, true), 
			};
			if (1 == 0)
			{
			}
			return result2;
		}

		private static IEnumerator RetryMovementAfterDelay(NPC dealer)
		{
			yield return (object)new WaitForSeconds(0.25f);
			MoveDealerToPlayer(dealer);
		}

		private static IEnumerator HandleDealerArrival(NPCScheduleManager scheduleManager, NPC dealerNPC)
		{
			if ((Object)(object)scheduleManager == (Object)null)
			{
				yield break;
			}
			LogDebug("Dealer has arrived. Waiting and keeping schedule disabled...");
			if (ModSettings.ActivateDealerMessages.Value)
			{
				dealerNPC.SendTextMessage(DealerMessages.GetRandomArrivedMessage());
			}
			float elapsedTime = 0f;
			Player player = GetPlayer();
			for (; elapsedTime < (float)ModSettings.DealerAwaitTime.Value; elapsedTime += 0.25f)
			{
				if (scheduleManager.ScheduleEnabled)
				{
					LogDebug("Schedule was enabled during wait - disabling it");
					scheduleManager.DisableSchedule();
				}
				if ((Object)(object)player != (Object)null && IsPlayerCloseToDealer(player, dealerNPC))
				{
					LogDebug("Player is close to dealer. Resetting wait timer.");
					elapsedTime = 0f;
				}
				yield return (object)new WaitForSeconds(0.25f);
			}
			LogDebug("Finished waiting. Enabling schedule.");
			scheduleManager.EnableSchedule();
			if (ModSettings.ActivateDealerMessages.Value)
			{
				dealerNPC.SendTextMessage(DealerMessages.GetRandomLeavingMessage());
			}
		}

		private static bool IsPlayerCloseToDealer(Player player, NPC dealer)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			float num = Vector3.Distance(player.PlayerBasePosition, ((Component)dealer).transform.position);
			return num <= (float)ModSettings.DealerInteractionDistance.Value;
		}

		private static Vector3 FindOptimalWarpPosition(Vector3 targetPosition)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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)
			List<Vector3> strategicPointsInRange = GetStrategicPointsInRange(targetPosition, 75f, 180f);
			if (strategicPointsInRange.Count > 0)
			{
				Vector3 val = strategicPointsInRange[0];
				LogDebug($"Found strategic point: {val} at distance {Vector3.Distance(targetPosition, val)}");
				return val;
			}
			return CalculateFallbackPosition(targetPosition);
		}

		private static List<Vector3> GetStrategicPointsInRange(Vector3 targetPosition, float minDistance, float maxDistance)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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)
			List<(float, Vector3)> list = new List<(float, Vector3)>();
			Vector3[] sTRATEGIC_LOCATIONS = STRATEGIC_LOCATIONS;
			foreach (Vector3 val in sTRATEGIC_LOCATIONS)
			{
				float num = Vector3.Distance(targetPosition, val);
				if (num >= minDistance && num <= maxDistance)
				{
					list.Add((num, val));
				}
			}
			list.Sort(((float distance, Vector3 point) a, (float distance, Vector3 point) b) => a.distance.CompareTo(b.distance));
			return list.Select<(float, Vector3), Vector3>(((float distance, Vector3 point) p) => p.point).ToList();
		}

		private static Vector3 CalculateFallbackPosition(Vector3 targetPosition)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = FindClosestStrategicPoint(targetPosition);
			float num = Vector3.Distance(targetPosition, val);
			if (num != 150f)
			{
				Vector3 val2 = val - targetPosition;
				Vector3 normalized = ((Vector3)(ref val2)).normalized;
				Vector3 val3 = targetPosition + normalized * 120f;
				LogDebug($"Generated fallback warp point at {val3}");
				return val3;
			}
			LogDebug($"Using closest strategic point: {val}");
			return val;
		}

		private static Vector3 FindClosestStrategicPoint(Vector3 position)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if (STRATEGIC_LOCATIONS.Length == 0)
			{
				return position;
			}
			return STRATEGIC_LOCATIONS.OrderBy((Vector3 point) => Vector3.Distance(position, point)).First();
		}

		private static Vector3? FindClosestWalkablePoint(NPCMovement movement, Vector3 targetPosition)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			NPCMovement movement2 = movement;
			float maxWalkDistance = 225f;
			return (from point in STRATEGIC_LOCATIONS
				where Vector3.Distance(targetPosition, point) < maxWalkDistance && movement2.CanGetTo(point, 1f)
				orderby Vector3.Distance(targetPosition, point)
				select point).FirstOrDefault();
		}

		private static void LogDebug(string message)
		{
			if (ModSettings.ActivateDebug.Value)
			{
				MelonLogger.Msg(message);
			}
		}
	}
	public class CallDealers : MelonMod
	{
		private static bool _isModActive;

		private static bool _hasModManagerIntegration;

		public override void OnInitializeMelon()
		{
			MelonLogger.Msg("Initializing SimpleCall mod settings");
			ModSettings.Initialize();
			_hasModManagerIntegration = MelonTypeBase<MelonMod>.RegisteredMelons.Any((MelonMod mod) => ((MelonBase)mod).Info.Name == "Mod Manager & Phone App");
			if (_hasModManagerIntegration)
			{
				ModSettings.InitializeModIntegration();
			}
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			if (!ModSettings.ActivateMod.Value)
			{
				return;
			}
			if (!(sceneName == "Main"))
			{
				if (sceneName == "Menu")
				{
					DeactivateMod();
				}
			}
			else
			{
				ActivateMod();
			}
		}

		public override void OnUpdate()
		{
			if (_isModActive && Input.GetKeyDown((KeyCode)110) && ModSettings.ActivatePositionLogging.Value)
			{
				ButtonManager.LogPlayerPosition();
			}
		}

		private static void ActivateMod()
		{
			if (!_isModActive)
			{
				MelonLogger.Msg("Mod has activated");
				ButtonManager.Initialize();
				_isModActive = true;
			}
		}

		private static void DeactivateMod()
		{
			if (_isModActive)
			{
				MelonLogger.Msg("Mod has deactivated");
				ButtonManager.Terminate();
				_isModActive = false;
			}
		}
	}
	public static class DealerMessages
	{
		private static readonly List<string> DealerCalledMessages = new List<string>
		{
			"Heard you. Coming through. Don’t waste my time.", "You better need me, 'cause I'm on my way.", "Got the ping. Hope it’s worth my legs.", "I’m rolling. Keep your block clean.", "Call came in. Moving out, eyes open.", "Alright, moving. Don’t be pulling some rookie shit.", "On my way. This better not be cold feet again.", "Dragging me out again? Fine. I’m coming.", "Coming through. You know the drill.", "Yeah yeah, I’m walking. Don't make it weird.",
			"Message got through. Keep your hands clean.", "I’m out. Keep the heat low till I get there.", "Moving up. Don’t let me find cops around.", "Call logged. On route — make it quick.", "Heading over. Hope you ain’t just bored.", "I’m on the move. You better be too.", "Coming in. You better not be dry.", "You owe me a smoke for this. On my way.", "Lace up, I’m getting close.", "Rolling. Got something good for me or nah?",
			"Eyes open. I'm coming in hot if I hear sirens.", "On the way. Got that sixth sense tingling.", "Okay. But this better not be another 'chat'.", "You know I don't jog for free. Be ready.", "Dragging me out again? What, your legs broke?", "Yeah, I’m coming. Hope this ain’t another fetch quest.", "Ugh, fine. I’ll play your little side mission.", "On my way. This better not be for one damn gram.", "Coming through. And no, I’m not bringing snacks.", "Hope this ain't some test, ‘cause I didn’t study.",
			"Okay, but if I die on the way, I'm haunting your ass.", "Y’all ever heard of fast travel? Just sayin’.", "Coming. Keep your pants on.", "You better not be naked again.", "Hope this ain’t a booty call.", "Walking hard... unlike you.", "I’m on the way. Hide the toys this time.", "I swear, if this is just for a dime bag...", "On my way. Zip it up before I get there.", "Gross. Be there soon.",
			"This better be worth pants.", "Smells illegal. I’m in.", "Fine. But no touching."
		};

		private static readonly List<string> DealerArrivedMessages = new List<string>
		{
			"I’m here. Let’s make it fast.", "Here now. Don’t make me regret this.", "Spot reached. What's the game?", "Made it. You got the gear or just vibes?", "I’m posted. You better not be empty-handed.", "Yo, I’m out front. Clock’s ticking.", "At the place. Let’s keep this tight.", "I’m here. No small talk.", "Here now. Show me what I walked for.", "On scene. Don't try funny business.",
			"Here. Let’s trade and bounce.", "You better have my cut. I'm waiting.", "Alright. Now impress me.", "Here. Don’t stare, hand it over.", "Yo, I showed. Now what?", "Made it. What we cookin’?", "Here now. No stalling.", "Let’s make this quick. I ain’t got forever.", "In position. Don’t make this messy.", "I’m parked. Bring it out.",
			"Oy. Let’s get to it.", "Knock knock. Let’s not drag this.", "Here. Hope this ain't a dry run again.", "Brought legs, now bring product.", "Here. Don’t make it weird. Or do. I don't judge.", "Made it. Took me longer than your last relationship.", "I'm here. Say the magic word: cash.", "Here now. Don’t start monologuing, I ain’t got time.", "Made it. Smells like regret and cheap cologne.", "Yo, I’m here. Let’s get weird.",
			"At the spot. Hope you brought more than vibes.", "Here. You look worse than last time.", "Show me the goods… and not that kind.", "I’m here. Pants stay on this time.", "Don’t touch me. Just hand it over.", "Here. Let’s do this before someone sees me with you.", "Smells like weed and bad decisions.", "I’m here. What the hell is that?", "Let’s get dirty. The business kind.", "I made it. Now pay me like I’m pretty."
		};

		private static readonly List<string> DealerLeavingMessages = new List<string>
		{
			"I’m ghost. Don’t call unless it’s gold.", "Outta here. Stay invisible.", "That’s it. Vanishing now.", "Done here. You ain’t seen me.", "I’m out. If pigs show, you never saw me.", "I bounce. You clean up.", "All good. Now keep your head down.", "Time’s up. Don’t be loud about this.", "Later. Don’t do dumb shit while I’m gone.", "I’m rolling out. Keep the streets cold.",
			"Peace. You better sell all that.", "Gone. Tell no one.", "I disappear now. You stay smart.", "That’s wrapped. Ghost mode on.", "Leaving. Try not to screw up.", "I’m off. Handle your biz right.", "Gotta move. You know nothing.", "Mission done. Back to the shadows.", "I vanish. So should your problems.", "Done here. Pretend I never came.",
			"Out. Next time, make it smoother.", "See ya. Watch for flashing lights.", "Finished. I'm smoke now.", "Clocked out. Keep low, stay sharp.", "I’m out. Try not to OD on nostalgia.", "Leaving now. And no, I’m not hugging you goodbye.", "I’m ghost. Don’t text me unless it’s life or death… or tacos.", "I’m off. Tell the devs to give me a car next update.", "Peace. Don’t get caught playing this at your grandma’s.", "Done here. Gonna go cry into my hoodie now.",
			"I’m out. Try not to walk into a wall again.", "Later. You smell like a side quest.", "I’m out. Clean up your mess.", "Leaving. And nah, I ain’t calling you.", "Bye. You reek of desperation.", "Peace. Try not to sniff everything you sell.", "Done. Till next time unfortunately.", "I’m out. You need Jesus."
		};

		private static readonly List<string> DealerFailedToReachMessages = new List<string>
		{
			"Can't reach you. Streets are a maze.", "Blocked in. This ain't happening unless you fix it.", "Something’s off. I can’t get to you.", "Dead end. You sure this is the right spot?", "Nah, route’s busted. You expecting me to fly?", "Road's cooked. Try calling again after cleaning this up.", "I ain’t teleporting, fix your setup.", "No way through. You playing games or what?", "Hit a wall. Literally.", "You might wanna check your map — I’m boxed in.",
			"Can’t get there. Looks like you dropped the call in a black hole.", "I’m stuck. Unless you got a shovel, this ain’t moving.", "Your call’s good, but the world’s got other ideas.", "That path? Not happening. Try another.", "I’m jammed up. Feels like bad code to me.", "You expecting miracles? I’m blocked hard.", "I’m frozen out. Something ain’t working right.", "Your GPS drunk or what? Can’t get to you.", "Something’s in the way. Could be the Matrix glitchin’."
		};

		private static readonly Random _rng = new Random();

		private const string Tag = "<b>SimpleCall</b>\n";

		public static string GetRandomCalledMessage()
		{
			return "<b>SimpleCall</b>\n" + DealerCalledMessages[_rng.Next(DealerCalledMessages.Count)];
		}

		public static string GetRandomArrivedMessage()
		{
			return "<b>SimpleCall</b>\n" + DealerArrivedMessages[_rng.Next(DealerArrivedMessages.Count)];
		}

		public static string GetRandomLeavingMessage()
		{
			return "<b>SimpleCall</b>\n" + DealerLeavingMessages[_rng.Next(DealerLeavingMessages.Count)];
		}

		public static string GetRandomFailedToReachMessage()
		{
			return "<b>SimpleCall</b>\n" + DealerFailedToReachMessages[_rng.Next(DealerFailedToReachMessages.Count)];
		}
	}
	public class ModSettings
	{
		private static MethodInfo _requestUIRefreshMethod;

		private static bool _isModManagerIntegrated;

		public static MelonPreferences_Category GeneralCategory { get; private set; }

		public static MelonPreferences_Category DebugCategory { get; private set; }

		public static MelonPreferences_Entry<bool> ActivateMod { get; private set; }

		public static MelonPreferences_Entry<bool> ActivateDealerMessages { get; private set; }

		public static MelonPreferences_Entry<int> DealerAwaitTime { get; private set; }

		public static MelonPreferences_Entry<int> DealerInteractionDistance { get; private set; }

		public static MelonPreferences_Entry<bool> ActivateDebug { get; private set; }

		public static MelonPreferences_Entry<bool> ActivatePositionLogging { get; private set; }

		public static void Initialize()
		{
			CreateGeneralSettings();
			CreateDebugSettings();
		}

		public static void InitializeModIntegration()
		{
			if (_isModManagerIntegrated)
			{
				return;
			}
			try
			{
				Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetType("ModManagerPhoneApp.ModSettingsEvents") != null);
				if (!(assembly == null))
				{
					_requestUIRefreshMethod = assembly.GetType("ModManagerPhoneApp.ModSettingsEvents")?.GetMethod("RequestUIRefresh");
					_isModManagerIntegrated = _requestUIRefreshMethod != null;
					if (_isModManagerIntegrated)
					{
						MelonLogger.Msg("Mod Manager integration initialized successfully");
					}
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Failed to initialize Mod Manager integration: " + ex.Message);
			}
		}

		private static void CreateGeneralSettings()
		{
			GeneralCategory = MelonPreferences.CreateCategory("SimpleCall_01_General", "General");
			ActivateMod = GeneralCategory.CreateEntry<bool>("ActivateMod", true, "Activate Mod", (string)null, false, false, (ValueValidator)null, (string)null);
			((MelonEventBase<LemonAction<bool, bool>>)(object)ActivateMod.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)OnActivateModChanged, 0, false);
			ActivateDealerMessages = GeneralCategory.CreateEntry<bool>("ActivateDealerMessages", true, "Activate Dealer Messages", (string)null, false, false, (ValueValidator)null, (string)null);
			DealerAwaitTime = GeneralCategory.CreateEntry<int>("DealerAwaitTime", 15, "Dealer Await Time (Default 15)", (string)null, false, false, (ValueValidator)null, (string)null);
			DealerInteractionDistance = GeneralCategory.CreateEntry<int>("DealerInteractionDistance", 3, "Dealer Interaction Distance (Default 3)", (string)null, false, false, (ValueValidator)null, (string)null);
			((MelonEventBase<LemonAction<bool, bool>>)(object)ActivateDealerMessages.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)delegate
			{
			}, 0, false);
			((MelonEventBase<LemonAction<int, int>>)(object)DealerAwaitTime.OnEntryValueChanged).Subscribe((LemonAction<int, int>)delegate
			{
			}, 0, false);
			((MelonEventBase<LemonAction<int, int>>)(object)DealerInteractionDistance.OnEntryValueChanged).Subscribe((LemonAction<int, int>)delegate
			{
			}, 0, false);
		}

		private static void CreateDebugSettings()
		{
			DebugCategory = MelonPreferences.CreateCategory("SimpleCall_02_Debug", "Debug");
			ActivateDebug = DebugCategory.CreateEntry<bool>("ActivateDebug", false, "Debug", (string)null, false, false, (ValueValidator)null, (string)null);
			ActivatePositionLogging = DebugCategory.CreateEntry<bool>("ActivatePositionLogging", false, "Position Logging (N key)", (string)null, false, false, (ValueValidator)null, (string)null);
			((MelonEventBase<LemonAction<bool, bool>>)(object)ActivateDebug.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)delegate
			{
			}, 0, false);
			((MelonEventBase<LemonAction<bool, bool>>)(object)ActivatePositionLogging.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)delegate
			{
			}, 0, false);
		}

		private static void OnActivateModChanged(bool oldValue, bool newValue)
		{
			if (newValue)
			{
				MelonLogger.Msg("Mod has been activated");
				ButtonManager.Initialize();
			}
			else
			{
				MelonLogger.Msg("Mod has been deactivated");
				ButtonManager.Terminate();
			}
		}

		public static void RequestUIRefresh()
		{
			if (!_isModManagerIntegrated)
			{
				return;
			}
			try
			{
				_requestUIRefreshMethod?.Invoke(null, null);
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Failed to request UI refresh: " + ex.Message);
			}
		}

		public static void Terminate()
		{
		}
	}
}