Decompiled source of BigWillyMod v1.0.2

BigWillyMod.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading.Tasks;
using BigWillyMod;
using BigWillyMod.Items;
using BigWillyMod.NPCs;
using BigWillyMod.Quests;
using BigWillyMod.Services;
using BigWillyMod.Utils;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using S1API.Console;
using S1API.Economy;
using S1API.Entities;
using S1API.Entities.Customer;
using S1API.Entities.Dialogue;
using S1API.Entities.NPCs.Northtown;
using S1API.Entities.Relation;
using S1API.Entities.Schedule;
using S1API.GameTime;
using S1API.Graffiti;
using S1API.Internal.Abstraction;
using S1API.Internal.Utils;
using S1API.Items;
using S1API.Lifecycle;
using S1API.Map;
using S1API.Map.Buildings;
using S1API.Messaging;
using S1API.Products;
using S1API.Properties;
using S1API.Properties.Interfaces;
using S1API.Quests;
using S1API.Quests.Constants;
using S1API.Rendering;
using S1API.Saveables;
using S1API.Shops;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(Core), "BigWillyMod", "1.0.2", "Bars", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BigWillyMod")]
[assembly: AssemblyConfiguration("CrossCompat")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+586648b3e17bd7e3ebaabc451a94ef341333e147")]
[assembly: AssemblyProduct("BigWillyMod")]
[assembly: AssemblyTitle("BigWillyMod")]
[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 BigWillyMod
{
	public class Core : MelonMod
	{
		private bool _itemsInitialized = false;

		private bool _shopsInitialized = false;

		private static MelonPreferences_Category? _preferencesCategory;

		private static MelonPreferences_Entry<bool>? _debugLogsEntry;

		private static MelonPreferences_Entry<bool>? _liveNotificationsEntry;

		private static MelonPreferences_Entry<int>? _liveCheckIntervalEntry;

		public static Core? Instance { get; private set; }

		public static bool DebugLogsEnabled => _debugLogsEntry?.Value ?? false;

		public static bool LiveNotificationsEnabled => _liveNotificationsEntry?.Value ?? true;

		public static int LiveCheckIntervalMinutes => _liveCheckIntervalEntry?.Value ?? 10;

		public override void OnLateInitializeMelon()
		{
			Instance = this;
			_preferencesCategory = MelonPreferences.CreateCategory("BigWillyMod");
			_debugLogsEntry = _preferencesCategory.CreateEntry<bool>("DebugLogs", false, "Enable Debug Logs", "Show detailed debug messages in the console", false, false, (ValueValidator)null, (string)null);
			_liveNotificationsEntry = _preferencesCategory.CreateEntry<bool>("LiveNotifications", true, "Live Stream Notifications", "Send in-game text when Big Willy goes live on Twitch", false, false, (ValueValidator)null, (string)null);
			_liveCheckIntervalEntry = _preferencesCategory.CreateEntry<int>("LiveCheckInterval", 10, "Live Check Interval (minutes)", "How often to check if Big Willy is streaming", false, false, (ValueValidator)null, (string)null);
			_preferencesCategory.SaveToFile(false);
			GraffitiQuestTracker.Initialize();
			GameLifecycle.OnPreLoad += OnPreLoad;
			((MelonBase)this).LoggerInstance.Msg("BigWillyMod v1.0.2 initialized");
		}

		public override void OnApplicationQuit()
		{
			LiveStreamChecker.StopPolling();
			GraffitiQuestTracker.Cleanup();
			Instance = null;
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			if (sceneName == "Main")
			{
				if (!_shopsInitialized)
				{
				}
				LiveStreamChecker.StartPolling();
			}
			else if (sceneName == "Menu")
			{
				LiveStreamChecker.StopPolling();
				LiveStreamChecker.Reset();
				_itemsInitialized = false;
				_shopsInitialized = false;
			}
		}

		private void OnPreLoad()
		{
			if (!_itemsInitialized)
			{
				StaySillyCapCreator.Initialize();
				_itemsInitialized = true;
				((MelonBase)this).LoggerInstance.Msg("Adding Big Willy to your game...");
			}
		}
	}
}
namespace BigWillyMod.Services
{
	public static class LiveStreamChecker
	{
		[CompilerGenerated]
		private sealed class <PollStreamStatus>d__8 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			private Task<bool> <checkTask>5__1;

			private bool <isLive>5__2;

			private float <intervalSeconds>5__3;

			private Exception <ex>5__4;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<checkTask>5__1 = null;
				<ex>5__4 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0044: Expected O, but got Unknown
				//IL_0164: Unknown result type (might be due to invalid IL or missing references)
				//IL_016e: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(10f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					goto IL_0186;
				case 2:
					<>1__state = -1;
					break;
				case 3:
					{
						<>1__state = -1;
						<checkTask>5__1 = null;
						goto IL_0186;
					}
					IL_0186:
					<checkTask>5__1 = CheckTwitchLiveAsync();
					break;
				}
				if (!<checkTask>5__1.IsCompleted)
				{
					<>2__current = null;
					<>1__state = 2;
					return true;
				}
				<isLive>5__2 = false;
				try
				{
					<isLive>5__2 = <checkTask>5__1.Result;
				}
				catch (Exception ex)
				{
					<ex>5__4 = ex;
					DebugLog.Msg("[LiveStreamChecker] Error checking stream status: " + <ex>5__4.Message);
				}
				if (<isLive>5__2 && !_wasLiveLastCheck)
				{
					DebugLog.Msg("[LiveStreamChecker] Stream just went live!");
					if (!_notifiedThisSession)
					{
						SendLiveNotification();
						_notifiedThisSession = true;
					}
				}
				else if (!<isLive>5__2 && _wasLiveLastCheck)
				{
					DebugLog.Msg("[LiveStreamChecker] Stream ended, resetting notification flag");
					_notifiedThisSession = false;
				}
				_wasLiveLastCheck = <isLive>5__2;
				<intervalSeconds>5__3 = (float)Core.LiveCheckIntervalMinutes * 60f;
				<>2__current = (object)new WaitForSeconds(<intervalSeconds>5__3);
				<>1__state = 3;
				return true;
			}

			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 readonly HttpClient _httpClient;

		private static object? _pollingCoroutine;

		private static bool _wasLiveLastCheck;

		private static bool _notifiedThisSession;

		static LiveStreamChecker()
		{
			_httpClient = new HttpClient();
			_wasLiveLastCheck = false;
			_notifiedThisSession = false;
			_httpClient.Timeout = TimeSpan.FromSeconds(10.0);
		}

		public static void StartPolling()
		{
			if (_pollingCoroutine != null)
			{
				DebugLog.Msg("[LiveStreamChecker] Polling already running");
				return;
			}
			if (!Core.LiveNotificationsEnabled)
			{
				DebugLog.Msg("[LiveStreamChecker] Live notifications disabled, not starting polling");
				return;
			}
			_pollingCoroutine = MelonCoroutines.Start(PollStreamStatus());
			DebugLog.Msg("[LiveStreamChecker] Started polling for live streams");
		}

		public static void StopPolling()
		{
			if (_pollingCoroutine != null)
			{
				MelonCoroutines.Stop(_pollingCoroutine);
				_pollingCoroutine = null;
				DebugLog.Msg("[LiveStreamChecker] Stopped polling");
			}
		}

		public static void Reset()
		{
			_wasLiveLastCheck = false;
			_notifiedThisSession = false;
		}

		[IteratorStateMachine(typeof(<PollStreamStatus>d__8))]
		private static IEnumerator PollStreamStatus()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <PollStreamStatus>d__8(0);
		}

		private static async Task<bool> CheckTwitchLiveAsync()
		{
			try
			{
				string trimmed = (await _httpClient.GetStringAsync("https://decapi.me/twitch/uptime/itsbigwilly_")).Trim();
				if (trimmed.Equals("offline", StringComparison.OrdinalIgnoreCase))
				{
					DebugLog.Msg("[LiveStreamChecker] Stream check: offline");
					return false;
				}
				string[] uptimeIndicators = new string[3] { "second", "minute", "hour" };
				if (Array.Exists(uptimeIndicators, (string indicator) => trimmed.Contains(indicator, StringComparison.OrdinalIgnoreCase)))
				{
					DebugLog.Msg("[LiveStreamChecker] Stream check: LIVE (uptime: " + trimmed + ")");
					return true;
				}
				DebugLog.Msg("[LiveStreamChecker] Unexpected response, assuming offline: " + trimmed);
				return false;
			}
			catch (HttpRequestException ex4)
			{
				HttpRequestException ex3 = ex4;
				DebugLog.Error("[LiveStreamChecker] HTTP error checking Twitch: " + ex3.Message);
				DebugLog.Error("[LiveStreamChecker] Stack trace: " + ex3.StackTrace);
				return false;
			}
			catch (TaskCanceledException ex5)
			{
				TaskCanceledException ex2 = ex5;
				DebugLog.Error("[LiveStreamChecker] Twitch check timed out: " + ex2.Message);
				DebugLog.Error("[LiveStreamChecker] Stack trace: " + ex2.StackTrace);
				return false;
			}
			catch (Exception ex6)
			{
				Exception ex = ex6;
				DebugLog.Error("[LiveStreamChecker] Unexpected error: " + ex.Message);
				DebugLog.Error("[LiveStreamChecker] Stack trace: " + ex.StackTrace);
				return false;
			}
		}

		private static void SendLiveNotification()
		{
			try
			{
				NPC val = NPC.Get<BigWilly>();
				if (val == null)
				{
					DebugLog.Error("[LiveStreamChecker] BigWilly NPC not found, cannot send notification");
					return;
				}
				string text = "Yo! I'm live right now, come hang out! https://www.twitch.tv/itsbigwilly_";
				val.SendTextMessage(text, (Response[])null, 1f, true);
				DebugLog.Msg("[LiveStreamChecker] Sent live notification to player");
			}
			catch (Exception ex)
			{
				DebugLog.Error("[LiveStreamChecker] Failed to send notification: " + ex.Message);
				DebugLog.Error("[LiveStreamChecker] Stack trace: " + ex.StackTrace);
			}
		}
	}
}
namespace BigWillyMod.Items
{
	public static class StaySillyCapCreator
	{
		private const string ITEM_ID = "stay_silly_cap";

		private const string ITEM_NAME = "Stay Silly Cap";

		private const string ITEM_DESCRIPTION = "A custom cap that helps you stay silly at all times. Never take life too seriously!";

		private const string SOURCE_CAP_PATH = "avatar/accessories/head/cap/Cap";

		private const string CUSTOM_CAP_RESOURCE_PATH = "BigWillyMod/Accessories/StaySillyCap";

		public static void Initialize()
		{
			try
			{
				if (!CreateCustomAccessory())
				{
					MelonLogger.Error("[StaySillyCap] Failed to create custom accessory");
				}
				else if (!CreateClothingItem())
				{
					MelonLogger.Error("[StaySillyCap] Failed to create clothing item");
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[StaySillyCap] Initialization failed: " + ex.Message);
				MelonLogger.Error(ex.StackTrace);
			}
		}

		public static void AddToShops()
		{
			try
			{
				ItemDefinition itemDefinition = ItemManager.GetItemDefinition("stay_silly_cap");
				if (itemDefinition == (ItemDefinition)null)
				{
					MelonLogger.Error("[StaySillyCap] Item 'stay_silly_cap' not found in registry");
				}
				else
				{
					int num = ShopManager.AddToCompatibleShops(itemDefinition, (float?)null);
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[StaySillyCap] Failed to add to shops: " + ex.Message);
			}
		}

		private static bool CreateCustomAccessory()
		{
			try
			{
				if (RuntimeResourceRegistry.IsRegistered("BigWillyMod/Accessories/StaySillyCap"))
				{
					MelonLogger.Msg("[StaySillyCap] Custom accessory already registered at 'BigWillyMod/Accessories/StaySillyCap', skipping creation");
					return true;
				}
				Assembly executingAssembly = Assembly.GetExecutingAssembly();
				Texture2D val = TextureUtils.LoadTextureFromResource(executingAssembly, "BigWillyMod.Resources.StaySillyCap.stay_silly_cap_texture.png", (FilterMode)1, (TextureWrapMode)1);
				if ((Object)(object)val == (Object)null)
				{
					MelonLogger.Error("[StaySillyCap] Failed to load custom texture from resources");
					return false;
				}
				Dictionary<string, Texture2D> dictionary = new Dictionary<string, Texture2D>
				{
					{ "_MainTex", val },
					{ "_BaseMap", val },
					{ "_Albedo", val }
				};
				return AccessoryFactory.CreateAndRegisterAccessory("avatar/accessories/head/cap/Cap", "BigWillyMod/Accessories/StaySillyCap", "StaySillyCap", dictionary, (Color?)null);
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[StaySillyCap] Failed to create accessory: " + ex.Message);
				MelonLogger.Error(ex.StackTrace);
				return false;
			}
		}

		private static bool CreateClothingItem()
		{
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ClothingItemDefinitionBuilder val = ClothingItemCreator.CloneFrom("cap");
				if (val == null)
				{
					MelonLogger.Error("[StaySillyCap] Failed to clone base cap - 'cap' item not found");
					return false;
				}
				Assembly executingAssembly = Assembly.GetExecutingAssembly();
				Sprite val2 = ImageUtils.LoadImageFromResource(executingAssembly, "BigWillyMod.Resources.StaySillyCap.icon.png", 100f, (FilterMode)1);
				if (!RuntimeResourceRegistry.IsRegistered("BigWillyMod/Accessories/StaySillyCap"))
				{
					MelonLogger.Warning("[StaySillyCap] Custom accessory not registered at 'BigWillyMod/Accessories/StaySillyCap'. Model may not load correctly.");
				}
				ClothingItemDefinition val3 = val.WithBasicInfo("stay_silly_cap", "Stay Silly Cap", "A custom cap that helps you stay silly at all times. Never take life too seriously!").WithClothingAsset("BigWillyMod/Accessories/StaySillyCap").WithColorable(false)
					.WithDefaultColor((ClothingColor)0)
					.WithPricing(75f, 0.5f)
					.WithKeywords(new string[5] { "cap", "hat", "silly", "custom", "bigwilly" })
					.WithLabelColor(new Color(1f, 0.8f, 0.2f))
					.Build();
				if ((Object)(object)val2 != (Object)null)
				{
					((ItemDefinition)val3).Icon = val2;
				}
				if ((ItemDefinition)(object)val3 == (ItemDefinition)null)
				{
					MelonLogger.Error("[StaySillyCap] Failed to build clothing item");
					return false;
				}
				return true;
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[StaySillyCap] Failed to create clothing item: " + ex.Message);
				MelonLogger.Error(ex.StackTrace);
				return false;
			}
		}
	}
}
namespace BigWillyMod.NPCs
{
	public sealed class BigWilly : NPC
	{
		[Serializable]
		private class PersistedData
		{
			public bool QuestCompleted = false;
		}

		[SaveableField("BigWillyData")]
		private PersistedData _data = new PersistedData();

		public override bool IsPhysical => true;

		protected override void ConfigurePrefab(NPCPrefabBuilder builder)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			Building goblinHideBuilding = Building.Get<GoblinHideBuilding>();
			Building arcade = Building.Get<Arcade>();
			Building val = Building.Get<Casino>();
			builder.WithIdentity("big_willy", "BigWilly", "").WithAppearanceDefaults((Action<AvatarDefaultsBuilder>)delegate(AvatarDefaultsBuilder av)
			{
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0055: Unknown result type (might be due to invalid IL or missing references)
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_008b: 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_0146: Unknown result type (might be due to invalid IL or missing references)
				//IL_0166: Unknown result type (might be due to invalid IL or missing references)
				//IL_0186: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
				//IL_0206: Unknown result type (might be due to invalid IL or missing references)
				av.Gender = 0f;
				av.Height = 1f;
				av.Weight = 1f;
				av.SkinColor = new Color32((byte)223, (byte)189, (byte)161, byte.MaxValue);
				av.LeftEyeLidColor = new Color(0.875f, 0.741f, 0.631f);
				av.RightEyeLidColor = new Color(0.875f, 0.741f, 0.631f);
				av.EyeBallTint = new Color(1f, 0.655f, 0.655f);
				av.HairColor = new Color(0.122f, 0.075f, 0.043f);
				av.HairPath = "Avatar/Hair/bowlcut/BowlCut";
				av.EyeballMaterialIdentifier = "Default";
				av.PupilDilation = 1f;
				av.EyebrowScale = 1.169f;
				av.EyebrowThickness = 1.111f;
				av.EyebrowRestingHeight = 0.32419f;
				av.EyebrowRestingAngle = -10f;
				av.LeftEye = (0.39435f, 0.26935f);
				av.RightEye = (0.39435f, 0.26935f);
				av.WithFaceLayer("Avatar/Layers/Face/Face_SlightSmile", new Color(0f, 0f, 0f));
				av.WithBodyLayer("Avatar/Layers/Top/Overalls", new Color(0f, 0f, 0.502f));
				av.WithBodyLayer("Avatar/Layers/Top/FlannelButtonUp", new Color(0.863f, 0.078f, 0.235f));
				av.WithBodyLayer("Avatar/Layers/Bottom/CargoPants", new Color(0.149f, 0.149f, 0.149f));
				av.WithAccessoryLayer("Avatar/Accessories/Head/PorkpieHat/PorkpieHat", new Color(0.824f, 0.706f, 0.549f));
				av.WithAccessoryLayer("Avatar/Accessories/Feet/CombatBoots/CombatBoots", new Color(0.824f, 0.706f, 0.549f));
				av.WithAccessoryLayer("Avatar/Accessories/Head/SmallRoundGlasses/SmallRoundGlasses", new Color(0f, 0f, 0f));
			}).WithSpawnPosition(new Vector3(-35.7332f, -4.035f, 52.2295f))
				.EnsureCustomer()
				.WithCustomerDefaults((Action<CustomerDataBuilder>)delegate(CustomerDataBuilder cd)
				{
					cd.WithSpending(400f, 900f).WithOrdersPerWeek(1, 3).WithPreferredOrderDay((Day)0)
						.WithOrderTime(900)
						.WithStandards((CustomerStandard)2)
						.AllowDirectApproach(true)
						.WithMutualRelationRequirement(2.5f, 4f)
						.WithCallPoliceChance(0.15f)
						.WithDependence(0.1f, 1.1f)
						.WithAffinities((IEnumerable<ValueTuple<DrugType, float>>)new(DrugType, float)[2]
						{
							((DrugType)0, 0.45f),
							((DrugType)2, -0.2f)
						})
						.WithPreferredProperties((PropertyBase[])(object)new PropertyBase[3]
						{
							Property.CalorieDense,
							Property.ThoughtProvoking,
							Property.Laxative
						});
				})
				.WithRelationshipDefaults((Action<NPCRelationshipDataBuilder>)delegate(NPCRelationshipDataBuilder r)
				{
					r.WithDelta(1f).SetUnlocked(false).SetUnlockType((UnlockType)1)
						.WithConnections<KyleCooley, LudwigMeyer, AustinSteiner>();
				})
				.WithSchedule((Action<PrefabScheduleBuilder>)delegate(PrefabScheduleBuilder plan)
				{
					//IL_0032: 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_0081: 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_008b: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
					//IL_0127: Unknown result type (might be due to invalid IL or missing references)
					plan.EnsureDealSignal().StayInBuilding(goblinHideBuilding, 700, 100, (int?)null, (string)null).WalkTo(new Vector3(-61.2776f, 1.065f, 55.6136f), 900, true, 1f, false, (Vector3?)null, (string)null)
						.WalkTo(new Vector3(-64.553f, 1.065f, 48.3866f), 1000, true, 1f, false, (Vector3?)(Quaternion.Euler(0f, 220f, 0f) * Vector3.forward), (string)null)
						.WalkTo(new Vector3(-44.2771f, -2.935f, 136.0889f), 1330, true, 1f, false, (Vector3?)null, (string)null)
						.StayInBuilding(arcade, 1400, 100, (int?)null, (string)null)
						.UseSlotMachineUntilTime(1630, 2300, new Vector3(23.4776f, 1.8546f, 95.6571f), 10, 10f, true, 5f, (Building)null, (string)null)
						.WalkTo(new Vector3(93.5044f, -5.535f, 7.0331f), 2300, true, 1f, false, (Vector3?)null, (string)null)
						.StayInBuilding(goblinHideBuilding, 2330, 250, (int?)null, (string)null);
				})
				.WithInventoryDefaults((Action<RandomInventoryItemsBuilder>)delegate(RandomInventoryItemsBuilder inv)
				{
					inv.WithStartupItems(new string[3] { "donut", "horsesemen", "megabean" }).WithRandomCash(500, 5000).WithClearInventoryEachNight(false);
				});
		}

		protected override void OnLoaded()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			((Saveable)this).OnLoaded();
			BigWillyGraffitiQuest bigWillyGraffitiQuest = QuestRegistry.GetBigWillyGraffitiQuest();
			if (bigWillyGraffitiQuest != null && (int)bigWillyGraffitiQuest.QuestState == 2)
			{
				_data.QuestCompleted = true;
			}
		}

		protected override void OnCreated()
		{
			((NPC)this).OnCreated();
			((NPC)this).Appearance.Build();
			((NPC)this).Schedule.Enable();
			((NPC)this).Region = (Region)0;
			SetupDialogue();
		}

		private void SetupDialogue()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			try
			{
				BigWillyGraffitiQuest bigWillyGraffitiQuest = QuestRegistry.GetBigWillyGraffitiQuest();
				if (_data.QuestCompleted || (bigWillyGraffitiQuest != null && (int)bigWillyGraffitiQuest.QuestState == 2))
				{
					return;
				}
				BuildQuestDialogueContainer();
				((NPC)this).Dialogue.OnChoiceSelected("ACCEPT_HELP", (Action)delegate
				{
					//IL_0033: Unknown result type (might be due to invalid IL or missing references)
					//IL_0039: Invalid comparison between Unknown and I4
					try
					{
						int count = GraffitiManager.UntaggedSpraySurfaces.Count;
						BigWillyGraffitiQuest bigWillyGraffitiQuest5 = QuestRegistry.CreateBigWillyGraffitiQuest();
						if (bigWillyGraffitiQuest5 != null)
						{
							int requiredTagCount = Math.Min(Math.Max(count, 1), 5);
							bigWillyGraffitiQuest5.SetRequiredTagCount(requiredTagCount);
							if ((int)bigWillyGraffitiQuest5.QuestState != 1)
							{
								((Quest)bigWillyGraffitiQuest5).Begin();
							}
						}
						((NPC)this).Dialogue.JumpTo("BigWillyQuestDialogue", "QUEST_ACCEPTED", false);
					}
					catch (Exception ex5)
					{
						MelonLogger.Error("[BigWilly] Failed to start quest: " + ex5.Message);
						((NPC)this).Dialogue.JumpTo("BigWillyQuestDialogue", "EXIT", false);
					}
				});
				((NPC)this).Dialogue.OnChoiceSelected("ACCEPT_HAT", (Action)delegate
				{
					try
					{
						StaySillyCapCreator.Initialize();
						ItemDefinition itemDefinition = ItemManager.GetItemDefinition("stay_silly_cap");
						if (itemDefinition == (ItemDefinition)null)
						{
							MelonLogger.Error("[BigWilly] Failed to find 'stay_silly_cap' item definition!");
						}
						else
						{
							ConsoleHelper.AddItemToInventory("stay_silly_cap", (int?)1);
							_data.QuestCompleted = true;
							Saveable.RequestGameSave(false);
						}
						((NPC)this).Dialogue.JumpTo("BigWillyQuestDialogue", "GIVE_HAT_DIRECTLY", false);
					}
					catch (Exception ex4)
					{
						MelonLogger.Error("[BigWilly] Failed to give hat directly: " + ex4.Message);
						MelonLogger.Error(ex4.StackTrace);
						((NPC)this).Dialogue.JumpTo("BigWillyQuestDialogue", "EXIT", false);
					}
				});
				((NPC)this).Dialogue.OnChoiceSelected("TURN_IN", (Action)delegate
				{
					try
					{
						BigWillyGraffitiQuest bigWillyGraffitiQuest4 = QuestRegistry.GetBigWillyGraffitiQuest();
						if (bigWillyGraffitiQuest4 != null && bigWillyGraffitiQuest4.IsReadyToTurnIn)
						{
							if (((Quest)bigWillyGraffitiQuest4).QuestEntries.Count >= 2)
							{
								((Quest)bigWillyGraffitiQuest4).QuestEntries[1].Complete();
							}
							bigWillyGraffitiQuest4.GiveReward();
							_data.QuestCompleted = true;
							Saveable.RequestGameSave(false);
						}
						((NPC)this).Dialogue.JumpTo("BigWillyQuestDialogue", "TURN_IN_REWARD", false);
					}
					catch (Exception ex3)
					{
						MelonLogger.Error("[BigWilly] Failed to complete quest: " + ex3.Message);
						((NPC)this).Dialogue.JumpTo("BigWillyQuestDialogue", "EXIT", false);
					}
				});
				((NPC)this).Dialogue.OnChoiceSelected("THANKS", (Action)delegate
				{
					//IL_000c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0012: Invalid comparison between Unknown and I4
					try
					{
						BigWillyGraffitiQuest bigWillyGraffitiQuest3 = QuestRegistry.GetBigWillyGraffitiQuest();
						if (bigWillyGraffitiQuest3 != null && (int)bigWillyGraffitiQuest3.QuestState == 1)
						{
							((Quest)bigWillyGraffitiQuest3).Complete();
						}
					}
					catch (Exception ex2)
					{
						MelonLogger.Error("[BigWilly] Failed to complete quest in THANKS handler: " + ex2.Message);
					}
					((NPC)this).Dialogue.StopOverride();
				});
				((NPC)this).Dialogue.OnChoiceSelected("CHECK_PROGRESS", (Action)delegate
				{
					((NPC)this).Dialogue.JumpTo("BigWillyQuestDialogue", "PROGRESS_UPDATE", false);
				});
				((NPC)this).Dialogue.OnChoiceSelected("LEAVE", (Action)delegate
				{
					((NPC)this).Dialogue.JumpTo("BigWillyQuestDialogue", "LEAVE_RESPONSE", false);
				});
				((NPC)this).Dialogue.OnChoiceSelected("DECLINE", (Action)delegate
				{
					((NPC)this).Dialogue.JumpTo("BigWillyQuestDialogue", "DECLINE_RESPONSE", false);
				});
				((NPC)this).Dialogue.OnChoiceSelected("GOT_IT", (Action)delegate
				{
					((NPC)this).Dialogue.StopOverride();
				});
				((NPC)this).Dialogue.OnChoiceSelected("OK", (Action)delegate
				{
					//IL_0018: Unknown result type (might be due to invalid IL or missing references)
					//IL_001e: Invalid comparison between Unknown and I4
					BigWillyGraffitiQuest bigWillyGraffitiQuest2 = QuestRegistry.GetBigWillyGraffitiQuest();
					if ((_data.QuestCompleted || (bigWillyGraffitiQuest2 != null && (int)bigWillyGraffitiQuest2.QuestState == 2)) && (bigWillyGraffitiQuest2 == null || !bigWillyGraffitiQuest2.IsReadyToTurnIn))
					{
						if (!_data.QuestCompleted)
						{
							_data.QuestCompleted = true;
							Saveable.RequestGameSave(false);
						}
						((NPC)this).Dialogue.StopOverride();
					}
					else
					{
						((NPC)this).Dialogue.JumpTo("BigWillyQuestDialogue", "EXIT", false);
					}
				});
				((NPC)this).Dialogue.UseContainerOnInteract("BigWillyQuestDialogue");
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[BigWilly] Failed to setup dialogue: " + ex.Message);
				MelonLogger.Error(ex.StackTrace);
			}
		}

		public void RebuildQuestDialogue()
		{
			DebugLog.Msg("[BigWilly] RebuildQuestDialogue called - rebuilding dialogue container");
			BuildQuestDialogueContainer();
			((NPC)this).Dialogue.UseContainerOnInteract("BigWillyQuestDialogue");
		}

		private void BuildQuestDialogueContainer()
		{
			DebugLog.Msg("[BigWilly] BuildQuestDialogueContainer called");
			((NPC)this).Dialogue.BuildAndRegisterContainer("BigWillyQuestDialogue", (Action<DialogueContainerBuilder>)delegate(DialogueContainerBuilder c)
			{
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				BigWillyGraffitiQuest currentQuest = QuestRegistry.GetBigWillyGraffitiQuest();
				DebugLog.Msg(string.Format("[BigWilly] Building container - Quest: {0}, QuestCompleted flag: {1}", (currentQuest != null) ? "EXISTS" : "NULL", _data.QuestCompleted));
				if (currentQuest != null)
				{
					DebugLog.Msg($"[BigWilly] Quest state: {currentQuest.QuestState}, Tagged: {currentQuest.TaggedCount}/{currentQuest.RequiredTagCount}, ReadyToTurnIn: {currentQuest.IsReadyToTurnIn}");
				}
				c.AddNode("ENTRY", GetEntryDialogueText(), (Action<ChoiceList>)delegate(ChoiceList ch)
				{
					//IL_0056: Unknown result type (might be due to invalid IL or missing references)
					//IL_005c: Invalid comparison between Unknown and I4
					//IL_010e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0114: Invalid comparison between Unknown and I4
					//IL_0162: Unknown result type (might be due to invalid IL or missing references)
					//IL_0168: Invalid comparison between Unknown and I4
					//IL_021f: Unknown result type (might be due to invalid IL or missing references)
					DebugLog.Msg("[BigWilly] ENTRY node choices callback executing");
					if (_data.QuestCompleted)
					{
						DebugLog.Msg("[BigWilly] Quest completed path - adding OK choice");
						ch.Add("OK", "Thanks for the help!", "EXIT");
					}
					else if (currentQuest == null || (int)currentQuest.QuestState == 0)
					{
						DebugLog.Msg("[BigWilly] Quest inactive/null path");
						int count = GraffitiManager.UntaggedSpraySurfaces.Count;
						if (count == 0)
						{
							DebugLog.Msg("[BigWilly] No graffiti spots - offering hat directly");
							ch.Add("ACCEPT_HAT", "Sure, I'll take the hat!", "GIVE_HAT_DIRECTLY").Add("DECLINE", "Not right now", "DECLINE_RESPONSE");
						}
						else
						{
							DebugLog.Msg($"[BigWilly] {count} graffiti spots available - offering quest");
							ch.Add("ACCEPT_HELP", "Yeah, I'll spread the word", "QUEST_ACCEPTED").Add("DECLINE", "Not right now", "DECLINE_RESPONSE");
						}
					}
					else if ((int)currentQuest.QuestState == 2)
					{
						DebugLog.Msg("[BigWilly] Quest state is Completed - marking in saved state");
						_data.QuestCompleted = true;
						Saveable.RequestGameSave(false);
						ch.Add("OK", "Thanks for the help!", "EXIT");
					}
					else if ((int)currentQuest.QuestState == 1)
					{
						if (currentQuest.IsReadyToTurnIn)
						{
							DebugLog.Msg("[BigWilly] Quest active and ready to turn in - adding TURN_IN choice");
							ch.Add("TURN_IN", string.Format("I've tagged {0} {1}!", currentQuest.RequiredTagCount, (currentQuest.RequiredTagCount == 1) ? "spot" : "spots"), "TURN_IN_REWARD");
						}
						else
						{
							DebugLog.Msg("[BigWilly] Quest active but not ready - adding progress choices");
							ch.Add("CHECK_PROGRESS", "How am I doing?", "PROGRESS_UPDATE").Add("LEAVE", "I'll keep working on it", "LEAVE_RESPONSE");
						}
					}
					else
					{
						DebugLog.Warning($"[BigWilly] Unexpected quest state: {currentQuest.QuestState}");
						ch.Add("OK", "Okay", "EXIT");
					}
				});
				c.AddNode("QUEST_ACCEPTED", GetQuestAcceptedText(), (Action<ChoiceList>)delegate(ChoiceList ch)
				{
					ch.Add("GOT_IT", "Got it!", "EXIT");
				});
				c.AddNode("GIVE_HAT_DIRECTLY", "Stay silly, brother!", (Action<ChoiceList>)delegate(ChoiceList ch)
				{
					ch.Add("THANKS", "Thanks!", "EXIT");
				});
				c.AddNode("DECLINE_RESPONSE", "Alright, let me know if you change your mind!", (Action<ChoiceList>)null);
				c.AddNode("PROGRESS_UPDATE", GetProgressUpdateText(), (Action<ChoiceList>)null);
				c.AddNode("LEAVE_RESPONSE", "Thanks for helping spread the word!", (Action<ChoiceList>)null);
				c.AddNode("TURN_IN_REWARD", "Great work brother! Spreading the word like a pro. Here, take this cap.", (Action<ChoiceList>)delegate(ChoiceList ch)
				{
					ch.Add("THANKS", "Thanks!", "EXIT");
				});
				c.AddNode("EXIT", "Stay silly, brother!", (Action<ChoiceList>)null);
			});
		}

		private string GetEntryDialogueText()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Invalid comparison between Unknown and I4
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Invalid comparison between Unknown and I4
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			BigWillyGraffitiQuest bigWillyGraffitiQuest = QuestRegistry.GetBigWillyGraffitiQuest();
			DebugLog.Msg(string.Format("[BigWilly] GetEntryDialogueText - Quest: {0}, QuestCompleted: {1}", (bigWillyGraffitiQuest != null) ? "EXISTS" : "NULL", _data.QuestCompleted));
			if (bigWillyGraffitiQuest == null || (int)bigWillyGraffitiQuest.QuestState == 0)
			{
				int count = GraffitiManager.UntaggedSpraySurfaces.Count;
				if (count == 0)
				{
					DebugLog.Msg("[BigWilly] Entry text: No spots, offering hat");
					return "Hey brother, have you heard of the Stay Silly merchandise? Here, take this Stay Silly hat!";
				}
				DebugLog.Msg($"[BigWilly] Entry text: {count} spots, offering quest");
				return "Hey brother, I need your help spreading the word of the big willy business, think you can help me?";
			}
			if ((int)bigWillyGraffitiQuest.QuestState == 1)
			{
				if (bigWillyGraffitiQuest.IsReadyToTurnIn)
				{
					DebugLog.Msg("[BigWilly] Entry text: Quest ready to turn in");
					return "Hey brother! I see you've been busy spreading the word. Great work!";
				}
				DebugLog.Msg("[BigWilly] Entry text: Quest in progress");
				return "Hey brother! How's the tagging going?";
			}
			if ((int)bigWillyGraffitiQuest.QuestState == 2)
			{
				DebugLog.Msg("[BigWilly] Entry text: Quest completed");
				return "Looking silly, brother! Thanks for the help.";
			}
			DebugLog.Msg($"[BigWilly] Entry text: Unknown state {bigWillyGraffitiQuest.QuestState}");
			return "Hey brother, what's up?";
		}

		private string GetQuestAcceptedText()
		{
			BigWillyGraffitiQuest bigWillyGraffitiQuest = QuestRegistry.GetBigWillyGraffitiQuest();
			if (bigWillyGraffitiQuest != null)
			{
				int requiredTagCount = bigWillyGraffitiQuest.RequiredTagCount;
				return string.Format("Great! Tag {0} {1} with graffiti for Big Willy. I'll know when you're done!", requiredTagCount, (requiredTagCount == 1) ? "spot" : "spots");
			}
			return "Great! Tag some spots with graffiti for Big Willy. I'll know when you're done!";
		}

		private string GetProgressUpdateText()
		{
			BigWillyGraffitiQuest bigWillyGraffitiQuest = QuestRegistry.GetBigWillyGraffitiQuest();
			if (bigWillyGraffitiQuest != null)
			{
				int taggedCount = bigWillyGraffitiQuest.TaggedCount;
				int num = bigWillyGraffitiQuest.RequiredTagCount - taggedCount;
				if (num == 1)
				{
					return string.Format("Keep it up brother, you've tagged {0} {1}. Just one more to go!", taggedCount, (taggedCount == 1) ? "spot" : "spots");
				}
				return string.Format("Keep it up brother, you've tagged {0} {1}. Just {2} more to go!", taggedCount, (taggedCount == 1) ? "spot" : "spots", num);
			}
			return "Keep it up brother! Just a few more to go!";
		}
	}
}
namespace BigWillyMod.Quests
{
	public class BigWillyGraffitiQuest : Quest
	{
		[CompilerGenerated]
		private sealed class <UpdatePOIToNearestUntaggedSurfaceDelayed>d__23 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public BigWillyGraffitiQuest <>4__this;

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

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

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

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>4__this.UpdatePOIToNearestUntaggedSurface();
					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();
			}
		}

		[CompilerGenerated]
		private sealed class <WaitForBigWillyAndAttachToEntry>d__22 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public BigWillyGraffitiQuest <>4__this;

			private float <timeout>5__1;

			private float <waited>5__2;

			private float <checkInterval>5__3;

			private NPC <bigWilly>5__4;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0095: Unknown result type (might be due to invalid IL or missing references)
				//IL_009f: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<timeout>5__1 = 10f;
					<waited>5__2 = 0f;
					<checkInterval>5__3 = 1f;
					break;
				case 1:
					<>1__state = -1;
					<waited>5__2 += <checkInterval>5__3;
					<bigWilly>5__4 = null;
					break;
				}
				if (<waited>5__2 < <timeout>5__1)
				{
					<bigWilly>5__4 = NPC.Get<BigWilly>();
					if (<bigWilly>5__4 != null)
					{
						if (<>4__this._returnEntry != null)
						{
							<>4__this._returnEntry.SetPOIToNPC(<bigWilly>5__4);
						}
						return false;
					}
					<>2__current = (object)new WaitForSeconds(<checkInterval>5__3);
					<>1__state = 1;
					return true;
				}
				DebugLog.Msg("[BigWillyGraffitiQuest] Timeout waiting for Big Willy NPC to spawn. Quest entry created without NPC attachment.");
				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 const string QUEST_ID = "big_willy_graffiti_quest";

		[SaveableField("taggedSurfaces")]
		private HashSet<string> _taggedSurfaceIds = new HashSet<string>();

		[SaveableField("rewardGranted")]
		private bool _rewardGranted = false;

		[SaveableField("requiredTagCount")]
		private int _requiredTagCount = 5;

		private QuestEntry _tagEntry;

		private QuestEntry _returnEntry;

		public int RequiredTagCount => _requiredTagCount;

		protected override string Title => "Spread the Word";

		protected override string Description => "Big Willy needs your help spreading the word about his business! " + string.Format("Tag {0} {1} around town with graffiti to help promote Big Willy's enterprise. ", _requiredTagCount, (_requiredTagCount == 1) ? "spot" : "different spots") + string.Format("Once you've completed all {0} {1}, return to Big Willy to claim your reward.", _requiredTagCount, (_requiredTagCount == 1) ? "tag" : "tags");

		protected override bool AutoBegin => false;

		public int TaggedCount => _taggedSurfaceIds.Count;

		public bool IsReadyToTurnIn
		{
			get
			{
				bool flag = _taggedSurfaceIds.Count >= _requiredTagCount;
				DebugLog.Msg($"[BigWillyGraffitiQuest] IsReadyToTurnIn check: {flag} (Tagged: {_taggedSurfaceIds.Count}/{_requiredTagCount})");
				return flag;
			}
		}

		public QuestState QuestState => ((Quest)this).QuestState;

		public void SetRequiredTagCount(int count)
		{
			if (count <= 0)
			{
				MelonLogger.Warning("[BigWillyGraffitiQuest] Required tag count must be greater than 0, using 1");
				_requiredTagCount = 1;
			}
			else
			{
				_requiredTagCount = count;
			}
		}

		protected override void OnCreated()
		{
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Invalid comparison between Unknown and I4
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Invalid comparison between Unknown and I4
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Invalid comparison between Unknown and I4
			((Registerable)this).OnCreated();
			if (base.QuestEntries.Count == 0)
			{
				_tagEntry = ((Quest)this).AddEntry(string.Format("Tag {0} {1} for Big Willy ({2}/{3})", _requiredTagCount, (_requiredTagCount == 1) ? "spot" : "spots", _taggedSurfaceIds.Count, _requiredTagCount), (Vector3?)null);
				_tagEntry.Begin();
				MelonCoroutines.Start(UpdatePOIToNearestUntaggedSurfaceDelayed());
				_returnEntry = ((Quest)this).AddEntry("Return to Big Willy", (Vector3?)null);
				_returnEntry.SetState((QuestState)0);
				MelonCoroutines.Start(WaitForBigWillyAndAttachToEntry());
			}
			else
			{
				if (base.QuestEntries.Count >= 1)
				{
					_tagEntry = base.QuestEntries[0];
				}
				if (base.QuestEntries.Count >= 2)
				{
					_returnEntry = base.QuestEntries[1];
				}
				UpdateTagEntryText();
				if (_tagEntry != null && (int)_tagEntry.State == 1)
				{
					MelonCoroutines.Start(UpdatePOIToNearestUntaggedSurfaceDelayed());
				}
				MelonCoroutines.Start(WaitForBigWillyAndAttachToEntry());
				if (_taggedSurfaceIds.Count >= _requiredTagCount)
				{
					if (_tagEntry != null && (int)_tagEntry.State != 2)
					{
						_tagEntry.Complete();
					}
					if (_returnEntry != null && (int)_returnEntry.State == 0)
					{
						_returnEntry.SetState((QuestState)1);
						_returnEntry.Begin();
					}
				}
			}
			((Quest)this).OnComplete += HandleQuestComplete;
		}

		private void HandleQuestComplete()
		{
			if (!_rewardGranted)
			{
				GiveReward();
			}
			Saveable.RequestGameSave(false);
		}

		protected override void OnLoaded()
		{
			((Saveable)this).OnLoaded();
			if (base.QuestEntries.Count == 0)
			{
				_tagEntry = ((Quest)this).AddEntry(string.Format("Tag {0} {1} for Big Willy ({2}/{3})", _requiredTagCount, (_requiredTagCount == 1) ? "spot" : "spots", _taggedSurfaceIds.Count, _requiredTagCount), (Vector3?)null);
				_returnEntry = ((Quest)this).AddEntry("Return to Big Willy", (Vector3?)null);
				MelonCoroutines.Start(WaitForBigWillyAndAttachToEntry());
			}
			else
			{
				if (base.QuestEntries.Count >= 1)
				{
					_tagEntry = base.QuestEntries[0];
				}
				if (base.QuestEntries.Count >= 2)
				{
					_returnEntry = base.QuestEntries[1];
				}
				MelonCoroutines.Start(WaitForBigWillyAndAttachToEntry());
			}
		}

		public void RegisterTag(string surfaceGuid)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Invalid comparison between Unknown and I4
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Invalid comparison between Unknown and I4
			if (string.IsNullOrEmpty(surfaceGuid))
			{
				DebugLog.Warning("[BigWillyGraffitiQuest] Attempted to register tag with null/empty GUID");
			}
			else
			{
				if (_taggedSurfaceIds.Contains(surfaceGuid))
				{
					return;
				}
				_taggedSurfaceIds.Add(surfaceGuid);
				UpdateTagEntryText();
				Saveable.RequestGameSave(false);
				SendProgressTextMessage();
				if (_tagEntry != null && (int)_tagEntry.State == 1)
				{
					UpdatePOIToNearestUntaggedSurface();
				}
				if (_taggedSurfaceIds.Count >= _requiredTagCount)
				{
					if (_tagEntry != null && (int)_tagEntry.State != 2)
					{
						_tagEntry.Complete();
					}
					else if (_tagEntry == null)
					{
						DebugLog.Warning("[BigWillyGraffitiQuest] _tagEntry is null, cannot complete");
					}
					if (_returnEntry != null)
					{
						_returnEntry.SetState((QuestState)1);
						_returnEntry.Begin();
					}
					else
					{
						DebugLog.Warning("[BigWillyGraffitiQuest] _returnEntry is null, cannot activate!");
					}
					RebuildBigWillyDialogue();
					Saveable.RequestGameSave(false);
				}
			}
		}

		private void UpdateTagEntryText()
		{
			if (_tagEntry != null)
			{
				_tagEntry.Title = string.Format("Tag {0} {1} for Big Willy ({2}/{3})", _requiredTagCount, (_requiredTagCount == 1) ? "spot" : "spots", _taggedSurfaceIds.Count, _requiredTagCount);
			}
		}

		public void GiveReward()
		{
			if (_rewardGranted)
			{
				DebugLog.Msg("[BigWillyGraffitiQuest] Reward already granted, skipping.");
				return;
			}
			try
			{
				StaySillyCapCreator.Initialize();
				ItemDefinition itemDefinition = ItemManager.GetItemDefinition("stay_silly_cap");
				if (itemDefinition == (ItemDefinition)null)
				{
					MelonLogger.Error("[BigWillyGraffitiQuest] Failed to find 'stay_silly_cap' item definition!");
					return;
				}
				ConsoleHelper.AddItemToInventory("stay_silly_cap", (int?)1);
				_rewardGranted = true;
				Saveable.RequestGameSave(false);
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[BigWillyGraffitiQuest] Failed to give reward: " + ex.Message);
				MelonLogger.Error(ex.StackTrace);
			}
		}

		private void SendProgressTextMessage()
		{
			try
			{
				NPC val = NPC.Get<BigWilly>();
				if (val == null)
				{
					DebugLog.Msg("[BigWillyGraffitiQuest] Big Willy NPC not found, cannot send text message");
					return;
				}
				string text;
				if (_taggedSurfaceIds.Count >= _requiredTagCount)
				{
					text = string.Format("Brother! You've tagged all {0} {1}! Come see me and I'll give you something special!", _requiredTagCount, (_requiredTagCount == 1) ? "spot" : "spots");
				}
				else
				{
					int num = _requiredTagCount - _taggedSurfaceIds.Count;
					text = string.Format("Nice work brother! You've tagged {0} spot{1}. Just {2} more to go!", _taggedSurfaceIds.Count, (_taggedSurfaceIds.Count == 1) ? "" : "s", num);
				}
				val.SendTextMessage(text, (Response[])null, 1f, true);
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[BigWillyGraffitiQuest] Failed to send progress text message: " + ex.Message);
				MelonLogger.Error(ex.StackTrace);
			}
		}

		[IteratorStateMachine(typeof(<WaitForBigWillyAndAttachToEntry>d__22))]
		private IEnumerator WaitForBigWillyAndAttachToEntry()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForBigWillyAndAttachToEntry>d__22(0)
			{
				<>4__this = this
			};
		}

		[IteratorStateMachine(typeof(<UpdatePOIToNearestUntaggedSurfaceDelayed>d__23))]
		private IEnumerator UpdatePOIToNearestUntaggedSurfaceDelayed()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <UpdatePOIToNearestUntaggedSurfaceDelayed>d__23(0)
			{
				<>4__this = this
			};
		}

		private void UpdatePOIToNearestUntaggedSurface()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			if (_tagEntry == null)
			{
				return;
			}
			try
			{
				Player local = Player.Local;
				if (local == null)
				{
					DebugLog.Msg("[BigWillyGraffitiQuest] Player.Local is null, cannot update POI");
					return;
				}
				SpraySurface val = GraffitiManager.FindNearestUntaggedSurface(local.Position);
				if (val != null)
				{
					string item = val.GUID.ToString();
					if (!_taggedSurfaceIds.Contains(item))
					{
						_tagEntry.SetPOIToSpraySurface(val);
						return;
					}
					List<SpraySurface> list = (from s in GraffitiManager.GetUntaggedSpraySurfaces()
						where !_taggedSurfaceIds.Contains(s.GUID.ToString())
						select s).ToList();
					if (list.Count > 0)
					{
						SpraySurface val2 = null;
						float num = float.MaxValue;
						foreach (SpraySurface item2 in list)
						{
							float num2 = Vector3.Distance(local.Position, item2.Position);
							if (num2 < num)
							{
								num = num2;
								val2 = item2;
							}
						}
						if (val2 != null)
						{
							_tagEntry.SetPOIToSpraySurface(val2);
						}
					}
					else
					{
						DebugLog.Msg("[BigWillyGraffitiQuest] No untagged surfaces found to point to");
					}
				}
				else
				{
					DebugLog.Msg("[BigWillyGraffitiQuest] No untagged surfaces found in the game");
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[BigWillyGraffitiQuest] Failed to update POI to nearest untagged surface: " + ex.Message);
				MelonLogger.Error(ex.StackTrace);
			}
		}

		private void RebuildBigWillyDialogue()
		{
			try
			{
				NPC val = NPC.Get<BigWilly>();
				if (val is BigWilly bigWilly)
				{
					DebugLog.Msg("[BigWillyGraffitiQuest] Quest ready to turn in - rebuilding Big Willy's dialogue");
					bigWilly.RebuildQuestDialogue();
				}
				else
				{
					DebugLog.Warning("[BigWillyGraffitiQuest] Big Willy NPC not found, cannot rebuild dialogue");
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[BigWillyGraffitiQuest] Failed to rebuild Big Willy dialogue: " + ex.Message);
				MelonLogger.Error(ex.StackTrace);
			}
		}
	}
	public static class GraffitiQuestTracker
	{
		private static bool _subscribed;

		public static void Initialize()
		{
			if (!_subscribed)
			{
				GraffitiEvents.GraffitiCompleted += OnGraffitiCompleted;
				_subscribed = true;
			}
		}

		public static void Cleanup()
		{
			if (_subscribed)
			{
				GraffitiEvents.GraffitiCompleted -= OnGraffitiCompleted;
				_subscribed = false;
			}
		}

		private static void OnGraffitiCompleted(SpraySurface spraySurface)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Invalid comparison between Unknown and I4
			try
			{
				if (spraySurface == null)
				{
					return;
				}
				string surfaceGuid = spraySurface.GUID.ToString();
				BigWillyGraffitiQuest bigWillyGraffitiQuest = QuestRegistry.GetBigWillyGraffitiQuest();
				if (bigWillyGraffitiQuest != null && ((Quest)bigWillyGraffitiQuest).QuestEntries != null && ((Quest)bigWillyGraffitiQuest).QuestEntries.Count != 0)
				{
					QuestEntry val = ((Quest)bigWillyGraffitiQuest).QuestEntries[0];
					if ((int)val.State == 1)
					{
						bigWillyGraffitiQuest.RegisterTag(surfaceGuid);
					}
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[GraffitiQuestTracker] Error in OnGraffitiCompleted: " + ex.Message);
				MelonLogger.Error(ex.StackTrace);
			}
		}
	}
	public static class QuestRegistry
	{
		private static BigWillyGraffitiQuest? _cachedQuest;

		private static List<Quest> QuestManagerQuests => (List<Quest>)typeof(QuestManager).GetField("Quests", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);

		public static BigWillyGraffitiQuest? GetBigWillyGraffitiQuest()
		{
			if (_cachedQuest != null)
			{
				if (QuestManagerQuests.Contains((Quest)(object)_cachedQuest))
				{
					return _cachedQuest;
				}
				_cachedQuest = null;
			}
			Quest questByName = QuestManager.GetQuestByName("Spread the Word");
			if (questByName is BigWillyGraffitiQuest cachedQuest)
			{
				_cachedQuest = cachedQuest;
				return _cachedQuest;
			}
			for (int i = 0; i < QuestManagerQuests.Count; i++)
			{
				if (QuestManagerQuests[i] is BigWillyGraffitiQuest bigWillyGraffitiQuest)
				{
					_cachedQuest = bigWillyGraffitiQuest;
					return bigWillyGraffitiQuest;
				}
			}
			return null;
		}

		public static BigWillyGraffitiQuest CreateBigWillyGraffitiQuest()
		{
			BigWillyGraffitiQuest bigWillyGraffitiQuest = GetBigWillyGraffitiQuest();
			if (bigWillyGraffitiQuest != null)
			{
				return bigWillyGraffitiQuest;
			}
			Quest val = QuestManager.CreateQuest<BigWillyGraffitiQuest>((string)null);
			if (val is BigWillyGraffitiQuest bigWillyGraffitiQuest2)
			{
				_cachedQuest = bigWillyGraffitiQuest2;
				return bigWillyGraffitiQuest2;
			}
			MelonLogger.Error("[QuestRegistry] Failed to create BigWillyGraffitiQuest - wrong type returned");
			return null;
		}

		public static void ClearCache()
		{
			_cachedQuest = null;
		}
	}
}
namespace BigWillyMod.Utils
{
	public static class Constants
	{
		public static class Game
		{
			public const string GAME_STUDIO = "TVGS";

			public const string GAME_NAME = "Schedule I";
		}

		public static class LiveStream
		{
			public const string TWITCH_URL = "https://www.twitch.tv/itsbigwilly_";

			public const string CHECK_URL = "https://decapi.me/twitch/uptime/itsbigwilly_";
		}

		public const string MOD_NAME = "BigWillyMod";

		public const string MOD_VERSION = "1.0.2";

		public const string MOD_AUTHOR = "Bars";

		public const string PREFERENCES_CATEGORY = "BigWillyMod";
	}
	public static class DebugLog
	{
		public static void Msg(string message)
		{
			if (Core.DebugLogsEnabled)
			{
				MelonLogger.Msg(message);
			}
		}

		public static void Warning(string message)
		{
			MelonLogger.Warning(message);
		}

		public static void Error(string message)
		{
			MelonLogger.Error(message);
		}
	}
}