Decompiled source of SquirrelsBirthdayReminder v1.1.2
BirthdayReminder.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
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.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using BirthdayReminder.Data; using BirthdayReminder.Integration; using BirthdayReminder.UI; using HarmonyLib; using Microsoft.CodeAnalysis; using SunhavenMods.Shared; using SunhavenTodo; using SunhavenTodo.Data; using UnityEngine; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("BirthdayReminder")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+54235fa387ce65f1ea7f743eb7e9b44371b337da")] [assembly: AssemblyProduct("BirthdayReminder")] [assembly: AssemblyTitle("BirthdayReminder")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SunhavenMods.Shared { public static class VersionChecker { public class VersionCheckResult { public bool Success { get; set; } public bool UpdateAvailable { get; set; } public string CurrentVersion { get; set; } public string LatestVersion { get; set; } public string ModName { get; set; } public string NexusUrl { get; set; } public string Changelog { get; set; } public string ErrorMessage { get; set; } } private class VersionCheckRunner : MonoBehaviour { public void StartCheck(string pluginGuid, string currentVersion, Action<VersionCheckResult> onComplete) { ((MonoBehaviour)this).StartCoroutine(CheckVersionCoroutine(pluginGuid, currentVersion, onComplete)); } private IEnumerator CheckVersionCoroutine(string pluginGuid, string currentVersion, Action<VersionCheckResult> onComplete) { VersionCheckResult result = new VersionCheckResult { CurrentVersion = currentVersion }; UnityWebRequest www = UnityWebRequest.Get("https://azraelgodking.github.io/SunhavenMod/versions.json"); try { www.timeout = 10; yield return www.SendWebRequest(); if ((int)www.result == 2 || (int)www.result == 3) { result.Success = false; result.ErrorMessage = "Network error: " + www.error; LogWarning(result.ErrorMessage); onComplete?.Invoke(result); Object.Destroy((Object)(object)((Component)this).gameObject); yield break; } try { string json = www.downloadHandler.text; string modPattern = "\"" + Regex.Escape(pluginGuid) + "\"\\s*:\\s*\\{([^}]+)\\}"; Match modMatch = Regex.Match(json, modPattern, RegexOptions.Singleline); if (!modMatch.Success) { result.Success = false; result.ErrorMessage = "Mod '" + pluginGuid + "' not found in versions.json"; LogWarning(result.ErrorMessage); onComplete?.Invoke(result); Object.Destroy((Object)(object)((Component)this).gameObject); yield break; } string modJson = modMatch.Groups[1].Value; result.LatestVersion = ExtractJsonString(modJson, "version"); result.ModName = ExtractJsonString(modJson, "name"); result.NexusUrl = ExtractJsonString(modJson, "nexus"); result.Changelog = ExtractJsonString(modJson, "changelog"); if (string.IsNullOrEmpty(result.LatestVersion)) { result.Success = false; result.ErrorMessage = "Could not parse version from response"; LogWarning(result.ErrorMessage); onComplete?.Invoke(result); Object.Destroy((Object)(object)((Component)this).gameObject); yield break; } result.Success = true; result.UpdateAvailable = CompareVersions(currentVersion, result.LatestVersion) < 0; if (result.UpdateAvailable) { Log("Update available for " + result.ModName + ": " + currentVersion + " -> " + result.LatestVersion); } else { Log(result.ModName + " is up to date (v" + currentVersion + ")"); } } catch (Exception ex) { result.Success = false; result.ErrorMessage = "Parse error: " + ex.Message; LogError(result.ErrorMessage); } } finally { ((IDisposable)www)?.Dispose(); } onComplete?.Invoke(result); Object.Destroy((Object)(object)((Component)this).gameObject); } private string ExtractJsonString(string json, string key) { string pattern = "\"" + key + "\"\\s*:\\s*(?:\"([^\"]*)\"|null)"; Match match = Regex.Match(json, pattern); return match.Success ? match.Groups[1].Value : null; } } private const string VersionsUrl = "https://azraelgodking.github.io/SunhavenMod/versions.json"; private static ManualLogSource _logger; public static void CheckForUpdate(string pluginGuid, string currentVersion, ManualLogSource logger = null, Action<VersionCheckResult> onComplete = null) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) _logger = logger; VersionCheckRunner versionCheckRunner = new GameObject("VersionChecker").AddComponent<VersionCheckRunner>(); Object.DontDestroyOnLoad((Object)(object)((Component)versionCheckRunner).gameObject); versionCheckRunner.StartCheck(pluginGuid, currentVersion, onComplete); } public static int CompareVersions(string v1, string v2) { if (string.IsNullOrEmpty(v1) || string.IsNullOrEmpty(v2)) { return 0; } v1 = v1.TrimStart('v', 'V'); v2 = v2.TrimStart('v', 'V'); string[] array = v1.Split(new char[1] { '.' }); string[] array2 = v2.Split(new char[1] { '.' }); int num = Math.Max(array.Length, array2.Length); for (int i = 0; i < num; i++) { int result; int num2 = ((i < array.Length && int.TryParse(array[i], out result)) ? result : 0); int result2; int num3 = ((i < array2.Length && int.TryParse(array2[i], out result2)) ? result2 : 0); if (num2 < num3) { return -1; } if (num2 > num3) { return 1; } } return 0; } internal static void Log(string message) { ManualLogSource logger = _logger; if (logger != null) { logger.LogInfo((object)("[VersionChecker] " + message)); } } internal static void LogWarning(string message) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)("[VersionChecker] " + message)); } } internal static void LogError(string message) { ManualLogSource logger = _logger; if (logger != null) { logger.LogError((object)("[VersionChecker] " + message)); } } } public static class VersionCheckerExtensions { public static void NotifyUpdateAvailable(this VersionChecker.VersionCheckResult result, ManualLogSource logger = null) { if (!result.UpdateAvailable) { return; } string text = result.ModName + " update available: v" + result.LatestVersion; try { Type type = ReflectionHelper.FindWishType("NotificationStack"); if (type != null) { Type type2 = ReflectionHelper.FindType("SingletonBehaviour`1", "Wish"); if (type2 != null) { Type type3 = type2.MakeGenericType(type); object obj = type3.GetProperty("Instance")?.GetValue(null); if (obj != null) { MethodInfo method = type.GetMethod("SendNotification", new Type[5] { typeof(string), typeof(int), typeof(int), typeof(bool), typeof(bool) }); if (method != null) { method.Invoke(obj, new object[5] { text, 0, 1, false, true }); return; } } } } } catch (Exception ex) { if (logger != null) { logger.LogWarning((object)("Failed to send native notification: " + ex.Message)); } } if (logger != null) { logger.LogWarning((object)("[UPDATE AVAILABLE] " + text)); } if (!string.IsNullOrEmpty(result.NexusUrl) && logger != null) { logger.LogWarning((object)("Download at: " + result.NexusUrl)); } } } public static class ReflectionHelper { public static readonly BindingFlags AllBindingFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy; public static Type FindType(string typeName, params string[] namespaces) { Type type = AccessTools.TypeByName(typeName); if (type != null) { return type; } foreach (string text in namespaces) { type = AccessTools.TypeByName(text + "." + typeName); if (type != null) { return type; } } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { type = assembly.GetTypes().FirstOrDefault((Type t) => t.Name == typeName || t.FullName == typeName); if (type != null) { return type; } } catch (ReflectionTypeLoadException) { } } return null; } public static Type FindWishType(string typeName) { return FindType(typeName, "Wish"); } public static object GetStaticValue(Type type, string memberName) { if (type == null) { return null; } PropertyInfo property = type.GetProperty(memberName, AllBindingFlags); if (property != null && property.GetMethod != null) { return property.GetValue(null); } FieldInfo field = type.GetField(memberName, AllBindingFlags); if (field != null) { return field.GetValue(null); } return null; } public static object GetSingletonInstance(Type type) { if (type == null) { return null; } string[] array = new string[5] { "Instance", "instance", "_instance", "Singleton", "singleton" }; string[] array2 = array; foreach (string memberName in array2) { object staticValue = GetStaticValue(type, memberName); if (staticValue != null) { return staticValue; } } return null; } public static object GetInstanceValue(object instance, string memberName) { if (instance == null) { return null; } Type type = instance.GetType(); while (type != null) { PropertyInfo property = type.GetProperty(memberName, AllBindingFlags); if (property != null && property.GetMethod != null) { return property.GetValue(instance); } FieldInfo field = type.GetField(memberName, AllBindingFlags); if (field != null) { return field.GetValue(instance); } type = type.BaseType; } return null; } public static bool SetInstanceValue(object instance, string memberName, object value) { if (instance == null) { return false; } Type type = instance.GetType(); while (type != null) { PropertyInfo property = type.GetProperty(memberName, AllBindingFlags); if (property != null && property.SetMethod != null) { property.SetValue(instance, value); return true; } FieldInfo field = type.GetField(memberName, AllBindingFlags); if (field != null) { field.SetValue(instance, value); return true; } type = type.BaseType; } return false; } public static object InvokeMethod(object instance, string methodName, params object[] args) { if (instance == null) { return null; } Type type = instance.GetType(); Type[] array = args?.Select((object a) => a?.GetType() ?? typeof(object)).ToArray() ?? Type.EmptyTypes; MethodInfo methodInfo = AccessTools.Method(type, methodName, array, (Type[])null); if (methodInfo == null) { methodInfo = type.GetMethod(methodName, AllBindingFlags); } if (methodInfo == null) { return null; } return methodInfo.Invoke(instance, args); } public static object InvokeStaticMethod(Type type, string methodName, params object[] args) { if (type == null) { return null; } Type[] array = args?.Select((object a) => a?.GetType() ?? typeof(object)).ToArray() ?? Type.EmptyTypes; MethodInfo methodInfo = AccessTools.Method(type, methodName, array, (Type[])null); if (methodInfo == null) { methodInfo = type.GetMethod(methodName, AllBindingFlags); } if (methodInfo == null) { return null; } return methodInfo.Invoke(null, args); } public static FieldInfo[] GetAllFields(Type type) { if (type == null) { return Array.Empty<FieldInfo>(); } FieldInfo[] fields = type.GetFields(AllBindingFlags); IEnumerable<FieldInfo> second; if (!(type.BaseType != null) || !(type.BaseType != typeof(object))) { second = Enumerable.Empty<FieldInfo>(); } else { IEnumerable<FieldInfo> allFields = GetAllFields(type.BaseType); second = allFields; } return fields.Concat(second).Distinct().ToArray(); } public static PropertyInfo[] GetAllProperties(Type type) { if (type == null) { return Array.Empty<PropertyInfo>(); } PropertyInfo[] properties = type.GetProperties(AllBindingFlags); IEnumerable<PropertyInfo> second; if (!(type.BaseType != null) || !(type.BaseType != typeof(object))) { second = Enumerable.Empty<PropertyInfo>(); } else { IEnumerable<PropertyInfo> allProperties = GetAllProperties(type.BaseType); second = allProperties; } return (from p in properties.Concat(second) group p by p.Name into g select g.First()).ToArray(); } public static T TryGetValue<T>(object instance, string memberName, T defaultValue = default(T)) { try { object instanceValue = GetInstanceValue(instance, memberName); if (instanceValue is T result) { return result; } if (instanceValue != null && typeof(T).IsAssignableFrom(instanceValue.GetType())) { return (T)instanceValue; } return defaultValue; } catch { return defaultValue; } } } } namespace BirthdayReminder { [BepInPlugin("com.azraelgodking.squirrelsbirthdayreminder", "A Squirrel's Birthday Reminder", "1.1.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { [CompilerGenerated] private static class <>O { public static UnityAction <0>__OnOvernightComplete; } private static BirthdayManager _staticManager; private static BirthdayHUD _staticHUD; private static GameObject _hudObject; private static float _staticHUDPositionX = -1f; private static float _staticHUDPositionY = -1f; private static TodoIntegration _todoIntegration; private ConfigEntry<bool> _enabled; private ConfigEntry<float> _hudPositionX; private ConfigEntry<float> _hudPositionY; private ConfigEntry<KeyCode> _toggleKey; private ConfigEntry<bool> _showGiftHints; private ConfigEntry<bool> _useNativeNotifications; private ConfigEntry<bool> _debugMode; private ConfigEntry<bool> _checkForUpdates; private ConfigEntry<float> _uiScale; private static float _staticUIScale = 1f; private static string _currentCharacterName; private static bool _isCharacterLoaded; private BirthdayManager _manager; private BirthdayHUD _hud; private Harmony _harmony; private static bool _overnightHooked = false; private static UnityAction _overnightCallback; private static GameObject _persistentRunner; private static PersistentRunner _persistentRunnerComponent; private static KeyCode _staticToggleKey = (KeyCode)98; private static bool _staticDebugMode = false; private static bool _staticUseNativeNotifications = true; private static Type _notificationStackType; private static PropertyInfo _notificationStackInstance; private static MethodInfo _sendNotificationMethod; private static bool _notificationSystemInitialized = false; public static Plugin Instance { get; private set; } public static ManualLogSource Log { get; private set; } public static KeyCode StaticToggleKey => _staticToggleKey; public static bool StaticDebugMode => _staticDebugMode; public static bool StaticUseNativeNotifications => _staticUseNativeNotifications; public static string CurrentCharacter => _currentCharacterName; public static bool IsCharacterLoaded => _isCharacterLoaded; private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)"Loading A Squirrel's Birthday Reminder v1.1.2"); BindConfiguration(); CreatePersistentRunner(); InitializeManager(); ApplyPatches(); InitializeIntegrations(); SceneManager.sceneLoaded += OnSceneLoaded; if (_checkForUpdates.Value) { VersionChecker.CheckForUpdate("com.azraelgodking.squirrelsbirthdayreminder", "1.1.2", Log, delegate(VersionChecker.VersionCheckResult result) { result.NotifyUpdateAvailable(Log); }); } Log.LogInfo((object)"A Squirrel's Birthday Reminder loaded successfully!"); } private void BindConfiguration() { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Expected O, but got Unknown _enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable birthday reminders"); _hudPositionX = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "PositionX", -1f, "HUD X position (-1 for default)"); _staticHUDPositionX = _hudPositionX.Value; _hudPositionY = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "PositionY", -1f, "HUD Y position (-1 for default)"); _staticHUDPositionY = _hudPositionY.Value; _toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Hotkeys", "ToggleKey", (KeyCode)98, "Key to toggle the birthday HUD (with Ctrl)"); _staticToggleKey = _toggleKey.Value; _toggleKey.SettingChanged += delegate { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) _staticToggleKey = _toggleKey.Value; }; _showGiftHints = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowGiftHints", true, "Show gift preferences in the birthday reminder"); _useNativeNotifications = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "UseNativeNotifications", true, "Show birthday notifications using the game's native notification system"); _debugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugMode", false, "Enable debug mode for testing (Ctrl+Shift+B to add test birthday)"); _staticDebugMode = _debugMode.Value; _debugMode.SettingChanged += delegate { _staticDebugMode = _debugMode.Value; }; _staticUseNativeNotifications = _useNativeNotifications.Value; _useNativeNotifications.SettingChanged += delegate { _staticUseNativeNotifications = _useNativeNotifications.Value; }; _checkForUpdates = ((BaseUnityPlugin)this).Config.Bind<bool>("Updates", "CheckForUpdates", true, "Check for mod updates on startup"); _uiScale = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "UIScale", 1f, new ConfigDescription("Scale factor for the birthday HUD (1.0 = default, 1.5 = 50% larger)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2.5f), Array.Empty<object>())); _staticUIScale = Mathf.Clamp(_uiScale.Value, 0.5f, 2.5f); _uiScale.SettingChanged += delegate { _staticUIScale = Mathf.Clamp(_uiScale.Value, 0.5f, 2.5f); _staticHUD?.SetScale(_staticUIScale); }; } private void CreatePersistentRunner() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if (!((Object)(object)_persistentRunner != (Object)null) || !((Object)(object)_persistentRunnerComponent != (Object)null)) { _persistentRunner = new GameObject("BirthdayReminder_PersistentRunner"); Object.DontDestroyOnLoad((Object)(object)_persistentRunner); ((Object)_persistentRunner).hideFlags = (HideFlags)61; _persistentRunnerComponent = _persistentRunner.AddComponent<PersistentRunner>(); Log.LogInfo((object)"[PersistentRunner] Created"); } } private void InitializeManager() { _manager = new BirthdayManager(); _staticManager = _manager; } private void InitializeIntegrations() { try { if (Chainloader.PluginInfos.ContainsKey("com.azraelgodking.sunhaventodo")) { _todoIntegration = new TodoIntegration(_staticManager); } else { Log.LogInfo((object)"[Integrations] SunhavenTodo not found - birthday todos disabled"); } } catch (Exception ex) { Log.LogWarning((object)("[Integrations] Error initializing: " + ex.Message)); } } private void ApplyPatches() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Expected O, but got Unknown _harmony = new Harmony("com.azraelgodking.squirrelsbirthdayreminder"); try { Type type = AccessTools.TypeByName("Wish.Player"); if (type != null) { MethodInfo methodInfo = AccessTools.Method(type, "InitializeAsOwner", (Type[])null, (Type[])null); if (methodInfo != null) { MethodInfo methodInfo2 = AccessTools.Method(typeof(PlayerPatches), "OnPlayerInitialized", (Type[])null, (Type[])null); _harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Applied player initialization patch"); } } Type type2 = AccessTools.TypeByName("Wish.NPCAI"); if (type2 != null) { Type type3 = AccessTools.TypeByName("Wish.Item"); if (type3 != null) { MethodInfo methodInfo3 = AccessTools.Method(type2, "Gift", new Type[1] { type3 }, (Type[])null); if (methodInfo3 != null) { MethodInfo methodInfo4 = AccessTools.Method(typeof(GiftPatches), "OnGiftGiven", (Type[])null, (Type[])null); _harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(methodInfo4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Applied gift tracking patch (NPCAI.Gift)"); } else { Log.LogWarning((object)"Could not find NPCAI.Gift(Item) method - gift tracking will not work"); } } else { Log.LogWarning((object)"Could not find Wish.Item type - gift tracking will not work"); } } else { Log.LogWarning((object)"Could not find NPCAI type - gift tracking will not work"); } } catch (Exception ex) { Log.LogWarning((object)("Failed to apply patches: " + ex.Message)); } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { Log.LogInfo((object)("[BirthdayReminder] Scene loaded: " + ((Scene)(ref scene)).name)); if (((Scene)(ref scene)).name == "MainMenu" || ((Scene)(ref scene)).name == "Bootstrap") { Log.LogInfo((object)"[BirthdayReminder] Main menu detected - hiding HUD and resetting state"); _staticHUD?.Hide(); _isCharacterLoaded = false; _currentCharacterName = null; } else { EnsureUIComponentsExist(); TryHookOvernightEvent(); } } public static void ResetOvernightHook() { _overnightHooked = false; _overnightCallback = null; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"[BirthdayReminder] Overnight hook reset"); } } public static void TryHookOvernightEvent() { //IL_006b: 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_0076: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Expected O, but got Unknown //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Expected O, but got Unknown if (_overnightHooked) { return; } try { Type type = AccessTools.TypeByName("Wish.DayCycle"); if (type != null) { FieldInfo fieldInfo = AccessTools.Field(type, "OnDayStart"); if (fieldInfo != null) { object? value = fieldInfo.GetValue(null); UnityAction val = (UnityAction)((value is UnityAction) ? value : null); object obj = <>O.<0>__OnOvernightComplete; if (obj == null) { UnityAction val2 = OnOvernightComplete; <>O.<0>__OnOvernightComplete = val2; obj = (object)val2; } _overnightCallback = (UnityAction)obj; if (val != null) { val = (UnityAction)Delegate.Combine((Delegate?)(object)val, (Delegate?)(object)_overnightCallback); fieldInfo.SetValue(null, val); } else { fieldInfo.SetValue(null, _overnightCallback); } _overnightHooked = true; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"Hooked into DayCycle.OnDayStart event"); } return; } } Type type2 = AccessTools.TypeByName("Wish.UIHandler"); if (type2 == null) { return; } object singletonInstance = GetSingletonInstance(type2); if (singletonInstance == null) { return; } FieldInfo fieldInfo2 = AccessTools.Field(type2, "OnCompleteOvernight"); if (fieldInfo2 != null) { object? value2 = fieldInfo2.GetValue(singletonInstance); UnityAction val3 = (UnityAction)((value2 is UnityAction) ? value2 : null); object obj2 = <>O.<0>__OnOvernightComplete; if (obj2 == null) { UnityAction val4 = OnOvernightComplete; <>O.<0>__OnOvernightComplete = val4; obj2 = (object)val4; } _overnightCallback = (UnityAction)obj2; if (val3 != null) { val3 = (UnityAction)Delegate.Combine((Delegate?)(object)val3, (Delegate?)(object)_overnightCallback); fieldInfo2.SetValue(singletonInstance, val3); } else { fieldInfo2.SetValue(singletonInstance, _overnightCallback); } _overnightHooked = true; ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)"Hooked into OnCompleteOvernight event"); } } } catch (Exception ex) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogWarning((object)("Failed to hook overnight event: " + ex.Message)); } } } private static void OnOvernightComplete() { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"[BirthdayReminder] Day started - checking for birthdays"); } _staticManager?.CheckTodaysBirthdays(); if (_staticManager != null && _staticManager.HasBirthdays) { EnsureUIComponentsExist(); _staticHUD?.Show(); SendAllBirthdayNotifications(); return; } _staticHUD?.Hide(); ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)"[BirthdayReminder] No birthdays today - HUD hidden"); } } public static void EnsureUIComponentsExist() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown try { if ((Object)(object)_persistentRunner == (Object)null || (Object)(object)_persistentRunnerComponent == (Object)null) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"[EnsureUI] Recreating PersistentRunner..."); } _persistentRunner = new GameObject("BirthdayReminder_PersistentRunner"); Object.DontDestroyOnLoad((Object)(object)_persistentRunner); ((Object)_persistentRunner).hideFlags = (HideFlags)61; _persistentRunnerComponent = _persistentRunner.AddComponent<PersistentRunner>(); ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)"[EnsureUI] PersistentRunner recreated"); } } if ((Object)(object)_staticHUD == (Object)null) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogInfo((object)"[EnsureUI] Creating BirthdayHUD..."); } _hudObject = new GameObject("BirthdayReminder_HUD"); Object.DontDestroyOnLoad((Object)(object)_hudObject); _staticHUD = _hudObject.AddComponent<BirthdayHUD>(); _staticHUD.Initialize(_staticManager); _staticHUD.SetScale(_staticUIScale); if (_staticHUDPositionX >= 0f && _staticHUDPositionY >= 0f) { _staticHUD.SetPosition(_staticHUDPositionX, _staticHUDPositionY); } _staticHUD.OnPositionChanged = delegate(float x, float y) { _staticHUDPositionX = x; _staticHUDPositionY = y; Plugin instance = Instance; if (instance != null) { ConfigEntry<float> hudPositionX = instance._hudPositionX; if (hudPositionX != null) { ((ConfigEntryBase)hudPositionX).SetSerializedValue(x.ToString()); } } Plugin instance2 = Instance; if (instance2 != null) { ConfigEntry<float> hudPositionY = instance2._hudPositionY; if (hudPositionY != null) { ((ConfigEntryBase)hudPositionY).SetSerializedValue(y.ToString()); } } }; ManualLogSource log4 = Log; if (log4 != null) { log4.LogInfo((object)"[EnsureUI] BirthdayHUD created"); } } if ((Object)(object)Instance != (Object)null) { Instance._hud = _staticHUD; } } catch (Exception ex) { ManualLogSource log5 = Log; if (log5 != null) { log5.LogError((object)("[EnsureUI] Error: " + ex.Message)); } } } private void Update() { //IL_005e: 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_018a: Unknown result type (might be due to invalid IL or missing references) bool flag = Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305); bool flag2 = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303); bool flag3 = Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307); if (flag && !flag2 && !flag3 && Input.GetKeyDown(_toggleKey.Value)) { Log.LogInfo((object)"[Hotkey] Ctrl+B pressed - toggling HUD"); EnsureUIComponentsExist(); _staticHUD?.Toggle(); Log.LogInfo((object)$"[Hotkey] HUD visible: {_staticHUD?.IsVisible ?? false}, Birthdays: {(_staticManager?.TodaysBirthdays?.Count).GetValueOrDefault()}"); } if (flag && flag3 && !flag2 && Input.GetKeyDown(_toggleKey.Value)) { Log.LogInfo((object)"[TEST] Ctrl+Alt+B pressed - adding test birthday"); DebugAddTestBirthday(); } if (flag && flag3 && !flag2 && Input.GetKeyDown((KeyCode)97)) { Log.LogInfo((object)"[TEST] Ctrl+Alt+A pressed - loading all birthdays"); DebugLoadAllBirthdays(); } if (_debugMode.Value && flag && flag2 && Input.GetKeyDown(_toggleKey.Value)) { DebugAddTestBirthday(); } if (_debugMode.Value && flag && flag2 && Input.GetKeyDown((KeyCode)114)) { DebugRefreshBirthdays(); } if (_debugMode.Value && flag && flag2 && Input.GetKeyDown((KeyCode)99)) { DebugClearBirthdays(); } if (_debugMode.Value && flag && flag2 && Input.GetKeyDown((KeyCode)97)) { DebugLoadAllBirthdays(); } if (_debugMode.Value && flag && flag2 && Input.GetKeyDown((KeyCode)108)) { Log.LogInfo((object)"[DEBUG] Ctrl+Shift+L pressed - dumping Lynn's NPC info..."); _staticManager?.DebugDumpNPCInfo(); } } public static BirthdayManager GetManager() { return _staticManager; } public static BirthdayHUD GetHUD() { return _staticHUD; } public static TodoIntegration GetTodoIntegration() { return _todoIntegration; } private static void InitializeNotificationSystem() { if (_notificationSystemInitialized) { return; } _notificationSystemInitialized = true; try { _notificationStackType = AccessTools.TypeByName("Wish.NotificationStack"); if (_notificationStackType == null) { ManualLogSource log = Log; if (log != null) { log.LogDebug((object)"[Notifications] NotificationStack type not found"); } return; } Type type = AccessTools.TypeByName("Wish.SingletonBehaviour`1"); if (type != null) { Type type2 = type.MakeGenericType(_notificationStackType); _notificationStackInstance = type2.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public); } _sendNotificationMethod = AccessTools.Method(_notificationStackType, "SendNotification", new Type[5] { typeof(string), typeof(int), typeof(int), typeof(bool), typeof(bool) }, (Type[])null); if (_sendNotificationMethod != null) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)"[Notifications] Native notification system initialized"); } } else { ManualLogSource log3 = Log; if (log3 != null) { log3.LogDebug((object)"[Notifications] SendNotification method not found"); } } } catch (Exception ex) { ManualLogSource log4 = Log; if (log4 != null) { log4.LogDebug((object)("[Notifications] Error initializing: " + ex.Message)); } } } public static void SendBirthdayNotification(string npcName, int itemId = 0) { if (!_staticUseNativeNotifications) { return; } InitializeNotificationSystem(); if (_sendNotificationMethod == null || _notificationStackInstance == null) { ManualLogSource log = Log; if (log != null) { log.LogDebug((object)"[Notifications] Cannot send - system not available"); } return; } try { object value = _notificationStackInstance.GetValue(null); if (value == null) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogDebug((object)"[Notifications] NotificationStack instance is null"); } return; } string text = "It's " + npcName + "'s birthday today!"; _sendNotificationMethod.Invoke(value, new object[5] { text, itemId, 1, false, true }); ManualLogSource log3 = Log; if (log3 != null) { log3.LogInfo((object)("[Notifications] Sent birthday notification for " + npcName)); } } catch (Exception ex) { ManualLogSource log4 = Log; if (log4 != null) { log4.LogDebug((object)("[Notifications] Error sending notification: " + ex.Message)); } } } public static void SendAllBirthdayNotifications() { if (!_staticUseNativeNotifications || _staticManager == null || !_staticManager.HasBirthdays) { return; } foreach (BirthdayDisplayInfo todaysBirthday in _staticManager.TodaysBirthdays) { if (!todaysBirthday.HasBeenGifted) { SendBirthdayNotification(todaysBirthday.NPCName); } } } private static object GetSingletonInstance(Type targetType) { try { Type type = AccessTools.TypeByName("Wish.SingletonBehaviour`1"); if (type != null) { Type type2 = type.MakeGenericType(targetType); return AccessTools.Property(type2, "Instance")?.GetValue(null); } return AccessTools.Property(targetType, "Instance")?.GetValue(null); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogDebug((object)("[BirthdayReminder] GetSingletonInstance: " + ex.Message)); } return null; } } public static void CheckBirthdays() { _staticManager?.CheckTodaysBirthdays(); } public static void OnCharacterChanged(string newCharacterName) { if (_currentCharacterName != newCharacterName) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("[BirthdayReminder] Character changed: " + (_currentCharacterName ?? "None") + " -> " + newCharacterName)); } _currentCharacterName = newCharacterName; _staticManager?.ResetForNewCharacter(newCharacterName); _todoIntegration?.Reset(); _staticHUD?.Hide(); _isCharacterLoaded = true; } } private void DebugAddTestBirthday() { Log.LogInfo((object)"[DEBUG] Adding test birthday..."); EnsureUIComponentsExist(); _staticManager?.DebugAddTestBirthday("Test NPC", "Loves: Diamonds, Gold"); if (_staticManager != null && _staticManager.HasBirthdays) { _staticHUD?.Show(); Log.LogInfo((object)"[DEBUG] Test birthday added and HUD shown"); } } private void DebugRefreshBirthdays() { Log.LogInfo((object)"[DEBUG] Ctrl+Shift+R pressed - Manual refresh triggered"); EnsureUIComponentsExist(); _staticManager?.ManualRefresh(); Log.LogInfo((object)$"[DEBUG] Found {_staticManager?.TodaysBirthdays.Count ?? 0} birthdays"); _staticHUD?.Show(); } private void DebugClearBirthdays() { Log.LogInfo((object)"[DEBUG] Clearing all birthdays..."); _staticManager?.DebugClearBirthdays(); _staticHUD?.Hide(); Log.LogInfo((object)"[DEBUG] Birthdays cleared and HUD hidden"); } private void DebugLoadAllBirthdays() { Log.LogInfo((object)"[DEBUG] Loading all NPC birthdays..."); EnsureUIComponentsExist(); _staticManager?.DebugLoadAllBirthdays(); if (_staticManager != null && _staticManager.HasBirthdays) { _staticHUD?.Show(); Log.LogInfo((object)$"[DEBUG] Loaded {_staticManager.TodaysBirthdays.Count} birthdays"); } } private void OnDestroy() { Log.LogWarning((object)"[CRITICAL] Plugin OnDestroy called!"); } } public static class PlayerPatches { private static string _lastCharacterName; public static void OnPlayerInitialized(object __instance) { try { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[PlayerPatches] Player initialized - checking character..."); } string characterName = GetCharacterName(__instance); if (_lastCharacterName != characterName) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)("[PlayerPatches] Character: " + characterName)); } Plugin.OnCharacterChanged(characterName); _lastCharacterName = characterName; } Plugin.EnsureUIComponentsExist(); Plugin.ResetOvernightHook(); Plugin.TryHookOvernightEvent(); Plugin.GetManager()?.CheckTodaysBirthdays(); BirthdayManager manager = Plugin.GetManager(); if (manager != null && manager.HasBirthdays) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogInfo((object)$"[PlayerPatches] Found {manager.TodaysBirthdays.Count} birthdays - showing HUD"); } Plugin.GetHUD()?.Show(); return; } ManualLogSource log4 = Plugin.Log; if (log4 != null) { log4.LogInfo((object)"[PlayerPatches] No birthdays found today - HUD will not show automatically"); } ManualLogSource log5 = Plugin.Log; if (log5 != null) { log5.LogInfo((object)"[PlayerPatches] Use Ctrl+Alt+B to add a test birthday for testing"); } } catch (Exception ex) { ManualLogSource log6 = Plugin.Log; if (log6 != null) { log6.LogError((object)("Error in OnPlayerInitialized: " + ex.Message)); } } } private static string GetCharacterName(object player) { try { Type type = AccessTools.TypeByName("Wish.GameSave"); if (type != null) { Type type2 = AccessTools.TypeByName("Wish.SingletonBehaviour`1"); if (type2 != null) { Type type3 = type2.MakeGenericType(type); object obj = AccessTools.Property(type3, "Instance")?.GetValue(null); if (obj != null) { object obj2 = AccessTools.Property(type, "CurrentSave")?.GetValue(obj); if (obj2 != null) { object obj3 = AccessTools.Property(obj2.GetType(), "characterData")?.GetValue(obj2); if (obj3 != null) { string text = AccessTools.Property(obj3.GetType(), "characterName")?.GetValue(obj3) as string; if (!string.IsNullOrEmpty(text)) { return text; } } } } } } if (player != null) { string text2 = AccessTools.Property(player.GetType(), "playerName")?.GetValue(player) as string; if (!string.IsNullOrEmpty(text2)) { return text2; } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("Failed to get character name: " + ex.Message)); } } return "Unknown"; } } public static class GiftPatches { public static void OnGiftGiven(object __instance, object __0) { try { if (__instance == null) { return; } Type type = __instance.GetType(); string npcName = (AccessTools.Property(type, "OriginalName") ?? AccessTools.Property(type, "ActualNPCName") ?? AccessTools.Property(type, "NPCName") ?? AccessTools.Property(type, "npcName") ?? AccessTools.Property(type, "Name"))?.GetValue(__instance)?.ToString(); if (string.IsNullOrEmpty(npcName)) { return; } BirthdayManager manager = Plugin.GetManager(); if (manager == null || !manager.HasBirthdays) { return; } BirthdayDisplayInfo birthdayDisplayInfo = manager.TodaysBirthdays.Find((BirthdayDisplayInfo b) => string.Equals(b.NPCName, npcName, StringComparison.OrdinalIgnoreCase) || (b.NPCName != null && b.NPCName.Contains("+" + npcName))); if (birthdayDisplayInfo != null && !birthdayDisplayInfo.HasBeenGifted) { manager.MarkGifted(npcName); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[BirthdayReminder] Marked " + npcName + " as gifted on their birthday!")); } Plugin.GetTodoIntegration()?.OnGiftGiven(npcName); } } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("Error tracking gift: " + ex.Message)); } } } } public class PersistentRunner : MonoBehaviour { private void Update() { CheckHotkeys(); } private void CheckHotkeys() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) bool flag = Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305); bool flag2 = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303); bool flag3 = Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307); if (flag && !flag2 && !flag3 && Input.GetKeyDown(Plugin.StaticToggleKey)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[PersistentRunner] Ctrl+B pressed - toggling HUD"); } Plugin.EnsureUIComponentsExist(); Plugin.GetHUD()?.Toggle(); } if (flag && flag3 && !flag2 && Input.GetKeyDown(Plugin.StaticToggleKey)) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)"[PersistentRunner] Ctrl+Alt+B pressed - adding test birthday"); } Plugin.EnsureUIComponentsExist(); Plugin.GetManager()?.DebugAddTestBirthday("Test NPC", "Loves: Diamonds, Gold"); BirthdayHUD hUD = Plugin.GetHUD(); BirthdayManager manager = Plugin.GetManager(); if (manager != null && manager.HasBirthdays && (Object)(object)hUD != (Object)null) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogInfo((object)$"[PersistentRunner] Showing HUD - birthdays: {Plugin.GetManager()?.TodaysBirthdays?.Count}"); } hUD.Show(); ManualLogSource log4 = Plugin.Log; if (log4 != null) { log4.LogInfo((object)$"[PersistentRunner] HUD visible: {hUD.IsVisible}"); } } else { ManualLogSource log5 = Plugin.Log; if (log5 != null) { log5.LogWarning((object)$"[PersistentRunner] Cannot show HUD - manager: {Plugin.GetManager() != null}, hud: {(Object)(object)hUD != (Object)null}"); } } } if (Plugin.StaticDebugMode && flag && flag2 && Input.GetKeyDown((KeyCode)114)) { ManualLogSource log6 = Plugin.Log; if (log6 != null) { log6.LogInfo((object)"[PersistentRunner] Ctrl+Shift+R pressed - Manual refresh"); } Plugin.EnsureUIComponentsExist(); Plugin.GetManager()?.ManualRefresh(); Plugin.GetHUD()?.Show(); } if (Plugin.StaticDebugMode && flag && flag2 && Input.GetKeyDown((KeyCode)99)) { ManualLogSource log7 = Plugin.Log; if (log7 != null) { log7.LogInfo((object)"[PersistentRunner] Ctrl+Shift+C pressed - Clearing birthdays"); } Plugin.GetManager()?.DebugClearBirthdays(); Plugin.GetHUD()?.Hide(); } } private void OnDestroy() { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[PersistentRunner] OnDestroy called - this should NOT happen!"); } } } public static class PluginInfo { public const string PLUGIN_GUID = "com.azraelgodking.squirrelsbirthdayreminder"; public const string PLUGIN_NAME = "A Squirrel's Birthday Reminder"; public const string PLUGIN_VERSION = "1.1.2"; } } namespace BirthdayReminder.UI { public class BirthdayHUD : MonoBehaviour { private const int WINDOW_ID = 98770; private const int GIFT_WINDOW_ID = 98771; private const float BASE_WINDOW_WIDTH = 320f; private const float BASE_MIN_HEIGHT = 100f; private const float BASE_MAX_HEIGHT = 500f; private const float BASE_HEADER_HEIGHT = 28f; private const float BASE_ITEM_HEIGHT = 65f; private const float BASE_GIFT_WINDOW_WIDTH = 300f; private const float BASE_GIFT_WINDOW_HEIGHT = 400f; private float _scale = 1f; private BirthdayManager _manager; private bool _isVisible; private Rect _windowRect; private float _showTimer; private const float AUTO_HIDE_DELAY = 15f; private bool _showGiftPopup; private Rect _giftPopupRect; private BirthdayDisplayInfo _selectedNPC; private Vector2 _giftScrollPosition; public Action<float, float> OnPositionChanged; private readonly Color _bgColor = new Color(0.18f, 0.14f, 0.12f, 0.95f); private readonly Color _headerColor = new Color(0.75f, 0.35f, 0.45f, 1f); private readonly Color _borderColor = new Color(0.85f, 0.65f, 0.5f, 1f); private readonly Color _textLight = new Color(0.95f, 0.92f, 0.88f); private readonly Color _textDark = new Color(0.25f, 0.2f, 0.15f); private readonly Color _giftedColor = new Color(0.5f, 0.85f, 0.5f); private readonly Color _ungiftedColor = new Color(1f, 0.75f, 0.3f); private readonly Color _hintColor = new Color(0.75f, 0.7f, 0.65f); private readonly Color _lovedColor = new Color(0.95f, 0.45f, 0.55f); private readonly Color _likedColor = new Color(0.55f, 0.7f, 0.95f); private readonly Color _universalColor = new Color(0.85f, 0.75f, 0.45f); private bool _stylesInitialized; private GUIStyle _windowStyle; private GUIStyle _headerStyle; private GUIStyle _nameStyle; private GUIStyle _giftedStyle; private GUIStyle _hintStyle; private GUIStyle _closeButtonStyle; private GUIStyle _moreButtonStyle; private GUIStyle _giftItemStyle; private GUIStyle _sectionHeaderStyle; private GUIStyle _universalItemStyle; private GUIStyle _statusMessageStyle; private GUIStyle _itemBoxStyle; private GUIStyle _statusGiftedStyle; private GUIStyle _statusUngiftedStyle; private GUIStyle _nameGiftedStyle; private GUIStyle _nameUngiftedStyle; private GUIStyle _lovedSectionStyle; private GUIStyle _likedSectionStyle; private GUIStyle _universalSubHeaderStyle; private GUIStyle _lovedBulletStyle; private GUIStyle _likedBulletStyle; private GUIStyle _universalBulletStyle; private Texture2D _windowBackground; private Texture2D _headerBackground; private Texture2D _itemBackground; private Texture2D _separatorTex; private float WindowWidth => 320f * _scale; private float MinHeight => 100f * _scale; private float MaxHeight => 500f * _scale; private float HeaderHeight => 28f * _scale; private float ItemHeight => 65f * _scale; private float GiftWindowWidth => 300f * _scale; private float GiftWindowHeight => 400f * _scale; public bool IsVisible => _isVisible; private int ScaledFont(int baseSize) { return Mathf.Max(8, Mathf.RoundToInt((float)baseSize * _scale)); } private float Scaled(float value) { return value * _scale; } private int ScaledInt(float value) { return Mathf.RoundToInt(value * _scale); } private void Awake() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) _windowRect = new Rect(100f, 100f, WindowWidth, MinHeight); _isVisible = false; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[BirthdayHUD] Awake called - isVisible set to false (waiting for player init)"); } } public void Initialize(BirthdayManager manager) { //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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) //IL_008e: Unknown result type (might be due to invalid IL or missing references) _manager = manager; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[BirthdayHUD] Initialize called, manager: {manager != null}, screen: ({Screen.width}x{Screen.height})"); } if (Screen.width > 0 && Screen.height > 0) { _windowRect = new Rect((float)Screen.width - WindowWidth - Scaled(20f), Scaled(80f), WindowWidth, MinHeight); ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)$"[BirthdayHUD] Default position set to ({((Rect)(ref _windowRect)).x}, {((Rect)(ref _windowRect)).y})"); } } else { _windowRect = new Rect(100f, 100f, WindowWidth, MinHeight); ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogInfo((object)"[BirthdayHUD] Using fallback position (100, 100) - screen not ready"); } } if (_manager != null) { _manager.OnBirthdaysUpdated += OnBirthdaysUpdated; } } public void SetPosition(float x, float y) { if (Screen.width > 0 && Screen.height > 0) { if (x >= 0f) { ((Rect)(ref _windowRect)).x = Mathf.Clamp(x, 0f, (float)Screen.width - ((Rect)(ref _windowRect)).width); } if (y >= 0f) { ((Rect)(ref _windowRect)).y = Mathf.Clamp(y, 0f, (float)Screen.height - ((Rect)(ref _windowRect)).height); } } } public (float x, float y) GetPosition() { return (((Rect)(ref _windowRect)).x, ((Rect)(ref _windowRect)).y); } public void SetScale(float scale) { _scale = Mathf.Clamp(scale, 0.5f, 2.5f); _stylesInitialized = false; EnsureOnScreen(); } public void Show() { _isVisible = true; _showTimer = 0f; EnsureOnScreen(); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[BirthdayHUD] Show() called - isVisible: {_isVisible}, pos: ({((Rect)(ref _windowRect)).x}, {((Rect)(ref _windowRect)).y}), screen: ({Screen.width}x{Screen.height}), birthdays: {(_manager?.TodaysBirthdays?.Count).GetValueOrDefault()}"); } } private void EnsureOnScreen() { if (Screen.width <= 0 || Screen.height <= 0) { return; } if (((Rect)(ref _windowRect)).x < 0f || ((Rect)(ref _windowRect)).y < 0f || ((Rect)(ref _windowRect)).x > (float)(Screen.width - 50) || ((Rect)(ref _windowRect)).y > (float)(Screen.height - 50)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[BirthdayHUD] Resetting position - was ({((Rect)(ref _windowRect)).x}, {((Rect)(ref _windowRect)).y})"); } ((Rect)(ref _windowRect)).x = (float)Screen.width - WindowWidth - Scaled(20f); ((Rect)(ref _windowRect)).y = Scaled(80f); } ((Rect)(ref _windowRect)).x = Mathf.Clamp(((Rect)(ref _windowRect)).x, 0f, (float)Screen.width - ((Rect)(ref _windowRect)).width); ((Rect)(ref _windowRect)).y = Mathf.Clamp(((Rect)(ref _windowRect)).y, 0f, (float)Screen.height - ((Rect)(ref _windowRect)).height); } public void Hide() { _isVisible = false; } public void Toggle() { if (_isVisible) { Hide(); } else { Show(); } } private void OnBirthdaysUpdated() { if (_manager != null && _manager.HasBirthdays) { Show(); } else { Hide(); } } private void Update() { _manager?.CheckForDateChange(Time.unscaledDeltaTime); if (!_isVisible) { return; } _manager?.UpdateStatusMessage(Time.unscaledDeltaTime); if (_manager != null && !_manager.HasUngiftedBirthdays) { _showTimer += Time.unscaledDeltaTime; if (_showTimer >= 15f) { Hide(); } } else { _showTimer = 0f; } } private void OnGUI() { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Expected O, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Expected O, but got Unknown //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) if (_isVisible) { if (!_stylesInitialized) { InitializeStyles(); } int num = ((_manager != null && _manager.TodaysBirthdays != null) ? _manager.TodaysBirthdays.Count : 0); float num2 = HeaderHeight + Scaled(12f); num2 = ((num != 0) ? (num2 + (float)num * ItemHeight) : (num2 + Scaled(40f))); num2 += Scaled(16f); ((Rect)(ref _windowRect)).width = WindowWidth; ((Rect)(ref _windowRect)).height = Mathf.Clamp(num2, MinHeight, MaxHeight); Rect windowRect = _windowRect; DrawShadow(_windowRect, 4); GUI.depth = -800; _windowRect = GUI.Window(98770, _windowRect, new WindowFunction(DrawWindow), "", _windowStyle); ((Rect)(ref _windowRect)).x = Mathf.Clamp(((Rect)(ref _windowRect)).x, 0f, (float)Screen.width - ((Rect)(ref _windowRect)).width); ((Rect)(ref _windowRect)).y = Mathf.Clamp(((Rect)(ref _windowRect)).y, 0f, (float)Screen.height - ((Rect)(ref _windowRect)).height); if (_showGiftPopup && _selectedNPC != null) { DrawShadow(_giftPopupRect, 4); GUI.depth = -900; _giftPopupRect = GUI.Window(98771, _giftPopupRect, new WindowFunction(DrawGiftPopup), "", _windowStyle); ((Rect)(ref _giftPopupRect)).x = Mathf.Clamp(((Rect)(ref _giftPopupRect)).x, 0f, (float)Screen.width - ((Rect)(ref _giftPopupRect)).width); ((Rect)(ref _giftPopupRect)).y = Mathf.Clamp(((Rect)(ref _giftPopupRect)).y, 0f, (float)Screen.height - ((Rect)(ref _giftPopupRect)).height); } if (Math.Abs(((Rect)(ref _windowRect)).x - ((Rect)(ref windowRect)).x) > 0.1f || Math.Abs(((Rect)(ref _windowRect)).y - ((Rect)(ref windowRect)).y) > 0.1f) { OnPositionChanged?.Invoke(((Rect)(ref _windowRect)).x, ((Rect)(ref _windowRect)).y); } } } private void DrawShadow(Rect rect, int offset) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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) Color color = default(Color); ((Color)(ref color))..ctor(0f, 0f, 0f, 0.3f); Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref rect)).x + (float)offset, ((Rect)(ref rect)).y + (float)offset, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height); GUI.color = color; GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture); GUI.color = Color.white; } private void DrawWindow(int windowId) { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) DrawBorder(((Rect)(ref _windowRect)).width, ((Rect)(ref _windowRect)).height, Mathf.Max(1, ScaledInt(2f))); GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); string text = _manager?.CurrentDateFormatted ?? ""; string title = (string.IsNullOrEmpty(text) ? "Birthday Today!" : ("Birthday Today! - " + text)); DrawHeader(title, ((Rect)(ref _windowRect)).width); DrawBirthdays(); GUILayout.EndVertical(); GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref _windowRect)).width - Scaled(24f), HeaderHeight)); } private void DrawBorder(float width, float height, int borderSize) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) GUI.color = _borderColor; GUI.DrawTexture(new Rect(0f, 0f, width, (float)borderSize), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(0f, height - (float)borderSize, width, (float)borderSize), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(0f, 0f, (float)borderSize, height), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(width - (float)borderSize, 0f, (float)borderSize, height), (Texture)(object)Texture2D.whiteTexture); GUI.color = Color.white; } private void DrawHeader(string title, float width) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) Rect val = default(Rect); ((Rect)(ref val))..ctor(0f, 0f, width, HeaderHeight); if ((Object)(object)_headerBackground != (Object)null) { GUI.DrawTexture(val, (Texture)(object)_headerBackground); } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Space(Scaled(10f)); GUILayout.Label("[*]", _headerStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(Scaled(24f)), GUILayout.Height(HeaderHeight) }); GUILayout.Label(title, _headerStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(HeaderHeight) }); GUILayout.FlexibleSpace(); if (GUILayout.Button("X", _closeButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(Scaled(24f)), GUILayout.Height(Scaled(24f)) })) { if (title.Contains("Gifts")) { _showGiftPopup = false; _selectedNPC = null; } else { Hide(); } } GUILayout.Space(Scaled(6f)); GUILayout.EndHorizontal(); } private void DrawBirthdays() { GUILayout.Space(Scaled(6f)); if (_manager != null && _manager.HasStatusMessage) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); GUILayout.Label(_manager.StatusMessage, _statusMessageStyle, Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.Space(Scaled(4f)); } if (_manager == null || _manager.TodaysBirthdays == null || _manager.TodaysBirthdays.Count == 0) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); GUILayout.Label("No birthdays today", _hintStyle, Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); } else { foreach (BirthdayDisplayInfo todaysBirthday in _manager.TodaysBirthdays) { DrawBirthdayItem(todaysBirthday); } } GUILayout.Space(Scaled(6f)); } private void DrawBirthdayItem(BirthdayDisplayInfo birthday) { GUILayout.BeginVertical(_itemBoxStyle, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUIStyle val = (birthday.HasBeenGifted ? _statusGiftedStyle : _statusUngiftedStyle); GUILayout.Label(birthday.HasBeenGifted ? "[OK]" : "[!!]", val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(Scaled(40f)) }); GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUIStyle val2 = (birthday.HasBeenGifted ? _nameGiftedStyle : _nameUngiftedStyle); GUILayout.Label(birthday.NPCName, val2, Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); if ((birthday.AllLovedGifts.Count > 0 || birthday.AllLikedGifts.Count > 0) && GUILayout.Button("Gifts", _moreButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(Scaled(50f)), GUILayout.Height(Scaled(20f)) })) { OpenGiftPopup(birthday); } GUILayout.EndHorizontal(); if (!birthday.HasBeenGifted && !string.IsNullOrEmpty(birthday.GiftHint)) { GUILayout.Space(Scaled(2f)); GUILayout.Label(birthday.GiftHint, _hintStyle, Array.Empty<GUILayoutOption>()); } GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.EndVertical(); } private void OpenGiftPopup(BirthdayDisplayInfo birthday) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_005a: Unknown result type (might be due to invalid IL or missing references) _selectedNPC = birthday; _showGiftPopup = true; _giftScrollPosition = Vector2.zero; _giftPopupRect = new Rect(((Rect)(ref _windowRect)).x + ((Rect)(ref _windowRect)).width + Scaled(10f), ((Rect)(ref _windowRect)).y, GiftWindowWidth, GiftWindowHeight); if (((Rect)(ref _giftPopupRect)).x + GiftWindowWidth > (float)Screen.width) { ((Rect)(ref _giftPopupRect)).x = ((Rect)(ref _windowRect)).x - GiftWindowWidth - Scaled(10f); } } private void DrawGiftPopup(int windowId) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) DrawBorder(GiftWindowWidth, GiftWindowHeight, ScaledInt(2f)); GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); Rect val = default(Rect); ((Rect)(ref val))..ctor(0f, 0f, GiftWindowWidth, HeaderHeight); if ((Object)(object)_headerBackground != (Object)null) { GUI.DrawTexture(val, (Texture)(object)_headerBackground); } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Space(Scaled(10f)); GUILayout.Label(_selectedNPC.NPCName + "'s Gifts", _headerStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(HeaderHeight) }); GUILayout.FlexibleSpace(); if (GUILayout.Button("X", _closeButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(Scaled(24f)), GUILayout.Height(Scaled(24f)) })) { _showGiftPopup = false; _selectedNPC = null; } GUILayout.Space(Scaled(6f)); GUILayout.EndHorizontal(); _giftScrollPosition = GUILayout.BeginScrollView(_giftScrollPosition, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(GiftWindowHeight - HeaderHeight - Scaled(10f)) }); GUILayout.Space(Scaled(6f)); DrawSectionHeader("LOVED GIFTS", _lovedColor); GUILayout.Space(Scaled(4f)); foreach (string allLovedGift in _selectedNPC.AllLovedGifts) { DrawGiftItem(allLovedGift, _lovedColor); } if (BirthdayCache.UniversalLoved.Count > 0) { GUILayout.Space(Scaled(4f)); DrawSubHeader("Universal Loved:", _universalColor); foreach (string item in BirthdayCache.UniversalLoved) { DrawGiftItem(item, _universalColor); } } GUILayout.Space(Scaled(8f)); DrawSeparator(); GUILayout.Space(Scaled(8f)); DrawSectionHeader("LIKED GIFTS", _likedColor); GUILayout.Space(Scaled(4f)); foreach (string allLikedGift in _selectedNPC.AllLikedGifts) { DrawGiftItem(allLikedGift, _likedColor); } if (BirthdayCache.UniversalLiked.Count > 0) { GUILayout.Space(Scaled(4f)); DrawSubHeader("Universal Liked:", _universalColor); foreach (string item2 in BirthdayCache.UniversalLiked) { DrawGiftItem(item2, _universalColor); } } GUILayout.Space(Scaled(10f)); GUILayout.EndScrollView(); GUILayout.EndVertical(); GUI.DragWindow(new Rect(0f, 0f, GiftWindowWidth - Scaled(24f), HeaderHeight)); } private void DrawSectionHeader(string text, Color color) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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) GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Space(Scaled(8f)); GUIStyle val = ((color == _lovedColor) ? _lovedSectionStyle : ((!(color == _likedColor)) ? _sectionHeaderStyle : _likedSectionStyle)); GUILayout.Label(text, val, Array.Empty<GUILayoutOption>()); GUILayout.EndHorizontal(); } private void DrawSubHeader(string text, Color color) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Space(Scaled(12f)); GUILayout.Label(text, _universalSubHeaderStyle, Array.Empty<GUILayoutOption>()); GUILayout.EndHorizontal(); } private void DrawGiftItem(string gift, Color bulletColor) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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) GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Space(Scaled(16f)); GUIStyle val = ((bulletColor == _lovedColor) ? _lovedBulletStyle : ((!(bulletColor == _likedColor)) ? _universalBulletStyle : _likedBulletStyle)); GUILayout.Label("•", val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(Scaled(12f)) }); GUILayout.Label(gift, _giftItemStyle, Array.Empty<GUILayoutOption>()); GUILayout.EndHorizontal(); } private void DrawSeparator() { //IL_0036: 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_0062: 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_0091: Unknown result type (might be due to invalid IL or missing references) GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Space(Scaled(20f)); float num = GiftWindowWidth - Scaled(40f); Rect rect = GUILayoutUtility.GetRect(num, 1f); GUI.color = new Color(_borderColor.r, _borderColor.g, _borderColor.b, 0.4f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, num, 1f), (Texture)(object)Texture2D.whiteTexture); GUI.color = Color.white; GUILayout.EndHorizontal(); } private void InitializeStyles() { if (_stylesInitialized) { return; } try { CreateTextures(); CreateStyles(); _stylesInitialized = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[BirthdayHUD] Styles initialized successfully"); } } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogError((object)("[BirthdayHUD] Failed to initialize styles: " + ex.Message)); } _windowStyle = GUI.skin.box; _stylesInitialized = true; } } private void CreateTextures() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) _windowBackground = MakeTex(4, 4, _bgColor); _headerBackground = MakeGradientTex(4, 8, _headerColor, new Color(_headerColor.r * 0.7f, _headerColor.g * 0.7f, _headerColor.b * 0.7f, 1f)); _itemBackground = MakeTex(4, 4, new Color(0.25f, 0.2f, 0.18f, 0.6f)); _separatorTex = MakeTex(1, 1, _borderColor); } private void CreateStyles() { //IL_0026: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_0074: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown //IL_00e7: Expected O, but got Unknown //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010b: 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_0123: Expected O, but got Unknown //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Expected O, but got Unknown //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Expected O, but got Unknown //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Expected O, but got Unknown //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Expected O, but got Unknown //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Expected O, but got Unknown //IL_030b: Expected O, but got Unknown //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_0320: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_033a: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Expected O, but got Unknown //IL_0357: Expected O, but got Unknown //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Expected O, but got Unknown //IL_039a: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_03b6: Expected O, but got Unknown //IL_03bd: Unknown result type (might be due to invalid IL or missing references) //IL_03c2: Unknown result type (might be due to invalid IL or missing references) //IL_03c9: Unknown result type (might be due to invalid IL or missing references) //IL_03d4: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: Unknown result type (might be due to invalid IL or missing references) //IL_03e9: Expected O, but got Unknown //IL_03ea: Unknown result type (might be due to invalid IL or missing references) //IL_03ef: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Unknown result type (might be due to invalid IL or missing references) //IL_042e: Unknown result type (might be due to invalid IL or missing references) //IL_0438: Expected O, but got Unknown //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_0466: Unknown result type (might be due to invalid IL or missing references) //IL_0470: Expected O, but got Unknown //IL_0476: Expected O, but got Unknown //IL_047d: Unknown result type (might be due to invalid IL or missing references) //IL_0482: Unknown result type (might be due to invalid IL or missing references) //IL_0489: Unknown result type (might be due to invalid IL or missing references) //IL_0494: Unknown result type (might be due to invalid IL or missing references) //IL_049c: Unknown result type (might be due to invalid IL or missing references) //IL_04b0: Expected O, but got Unknown //IL_04b7: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_04c3: Unknown result type (might be due to invalid IL or missing references) //IL_04ce: Unknown result type (might be due to invalid IL or missing references) //IL_04d6: Unknown result type (might be due to invalid IL or missing references) //IL_04ea: Expected O, but got Unknown //IL_04f1: Unknown result type (might be due to invalid IL or missing references) //IL_04f6: Unknown result type (might be due to invalid IL or missing references) //IL_0522: Unknown result type (might be due to invalid IL or missing references) //IL_052d: Unknown result type (might be due to invalid IL or missing references) //IL_0535: Unknown result type (might be due to invalid IL or missing references) //IL_0549: Expected O, but got Unknown //IL_0550: Unknown result type (might be due to invalid IL or missing references) //IL_0555: Unknown result type (might be due to invalid IL or missing references) //IL_055c: Unknown result type (might be due to invalid IL or missing references) //IL_0567: Unknown result type (might be due to invalid IL or missing references) //IL_056f: Unknown result type (might be due to invalid IL or missing references) //IL_0583: Expected O, but got Unknown //IL_058a: Unknown result type (might be due to invalid IL or missing references) //IL_058f: Unknown result type (might be due to invalid IL or missing references) //IL_0596: Unknown result type (might be due to invalid IL or missing references) //IL_05a6: Expected O, but got Unknown //IL_05ad: Unknown result type (might be due to invalid IL or missing references) //IL_05b2: Unknown result type (might be due to invalid IL or missing references) //IL_05b9: Unknown result type (might be due to invalid IL or missing references) //IL_05c9: Expected O, but got Unknown //IL_05d0: Unknown result type (might be due to invalid IL or missing references) //IL_05d5: Unknown result type (might be due to invalid IL or missing references) //IL_05dc: Unknown result type (might be due to invalid IL or missing references) //IL_05e7: Unknown result type (might be due to invalid IL or missing references) //IL_05ef: Unknown result type (might be due to invalid IL or missing references) //IL_0603: Expected O, but got Unknown //IL_060a: Unknown result type (might be due to invalid IL or missing references) //IL_060f: Unknown result type (might be due to invalid IL or missing references) //IL_0616: Unknown result type (might be due to invalid IL or missing references) //IL_0626: Expected O, but got Unknown //IL_062d: Unknown result type (might be due to invalid IL or missing references) //IL_0632: Unknown result type (might be due to invalid IL or missing references) //IL_0639: Unknown result type (might be due to invalid IL or missing references) //IL_0649: Expected O, but got Unknown //IL_0650: Unknown result type (might be due to invalid IL or missing references) //IL_0655: Unknown result type (might be due to invalid IL or missing references) //IL_065c: Unknown result type (might be due to invalid IL or missing references) //IL_066c: Expected O, but got Unknown int num = Mathf.Max(1, ScaledInt(4f)); int num2 = Mathf.Max(1, ScaledInt(2f)); GUIStyle val = new GUIStyle(); val.normal.background = _windowBackground; val.normal.textColor = _textLight; val.padding = new RectOffset(num, num, num, num); val.border = new RectOffset(num2, num2, num2, num2); _windowStyle = val; GUIStyle val2 = new GUIStyle { fontSize = ScaledFont(13), fontStyle = (FontStyle)1 }; val2.normal.textColor = Color.white; val2.alignment = (TextAnchor)3; val2.padding = new RectOffset(ScaledInt(2f), ScaledInt(2f), ScaledInt(2f), ScaledInt(2f)); _headerStyle = val2; GUIStyle val3 = new GUIStyle { fontSize = ScaledFont(12), fontStyle = (FontStyle)1 }; val3.normal.textColor = _textLight; val3.alignment = (TextAnchor)3; _nameStyle = val3; GUIStyle val4 = new GUIStyle(_nameStyle) { fontStyle = (FontStyle)2 }; val4.normal.textColor = new Color(_textLight.r, _textLight.g, _textLight.b, 0.5f); _giftedStyle = val4; GUIStyle val5 = new GUIStyle { fontSize = ScaledFont(10), fontStyle = (FontStyle)2 }; val5.normal.textColor = _hintColor; val5.alignment = (TextAnchor)0; val5.wordWrap = true; _hintStyle = val5; GUIStyle val6 = new GUIStyle { fontSize = ScaledFont(14), fontStyle = (FontStyle)1 }; val6.normal.textColor = new Color(1f, 0.9f, 0.9f); val6.hover.textColor = Color.white; val6.alignment = (TextAnchor)4; _closeButtonStyle = val6; GUIStyle val7 = new GUIStyle(GUI.skin.button) { fontSize = ScaledFont(10), fontStyle = (FontStyle)1 }; val7.normal.textColor = _borderColor; val7.normal.background = MakeTex(1, 1, new Color(0.3f, 0.25f, 0.22f, 0.8f)); val7.hover.textColor = Color.white; val7.hover.background = MakeTex(1, 1, new Color(0.5f, 0.35f, 0.3f, 0.9f)); val7.alignment = (TextAnchor)4; val7.padding = new RectOffset(ScaledInt(4f), ScaledInt(4f), ScaledInt(2f), ScaledInt(2f)); val7.margin = new RectOffset(0, 0, 0, 0); _moreButtonStyle = val7; GUIStyle val8 = new GUIStyle { fontSize = ScaledFont(11) }; val8.normal.textColor = _textLight; val8.alignment = (TextAnchor)3; val8.wordWrap = true; val8.padding = new RectOffset(0, 0, 1, 1); _giftItemStyle = val8; GUIStyle val9 = new GUIStyle { fontSize = ScaledFont(11), fontStyle = (FontStyle)1 }; val9.normal.textColor = _textLight; val9.alignment = (TextAnchor)3; _sectionHeaderStyle = val9; GUIStyle val10 = new GUIStyle(_giftItemStyle); val10.normal.textColor = _universalColor; _universalItemStyle = val10; GUIStyle val11 = new GUIStyle(_hintStyle); val11.normal.textColor = _giftedColor; val11.fontStyle = (FontStyle)1; val11.alignment = (TextAnchor)4; _statusMessageStyle = val11; GUIStyle val12 = new GUIStyle(); val12.normal.background = _itemBackground; val12.padding = new RectOffset(ScaledInt(8f), ScaledInt(8f), ScaledInt(6f), ScaledInt(6f)); val12.margin = new RectOffset(ScaledInt(6f), ScaledInt(6f), ScaledInt(2f), ScaledInt(2f)); _itemBoxStyle = val12; GUIStyle val13 = new GUIStyle(_nameStyle); val13.normal.textColor = _giftedColor; val13.fontStyle = (FontStyle)1; val13.fontSize = ScaledFont(13); _statusGiftedStyle = val13; GUIStyle val14 = new GUIStyle(_nameStyle); val14.normal.textColor = _ungiftedColor; val14.fontStyle = (FontStyle)1; val14.fontSize = ScaledFont(13); _statusUngiftedStyle = val14; GUIStyle val15 = new GUIStyle(_nameStyle); val15.normal.textColor = new Color(_textLight.r, _textLight.g, _textLight.b, 0.5f); val15.fontStyle = (FontStyle)2; val15.fontSize = ScaledFont(13); _nameGiftedStyle = val15; GUIStyle val16 = new GUIStyle(_nameStyle); val16.normal.textColor = _textLight; val16.fontStyle = (FontStyle)1; val16.fontSize = ScaledFont(13); _nameUngiftedStyle = val16; GUIStyle val17 = new GUIStyle(_sectionHeaderStyle); val17.normal.textColor = _lovedColor; _lovedSectionStyle = val17; GUIStyle val18 = new GUIStyle(_sectionHeaderStyle); val18.normal.textColor = _likedColor; _likedSectionStyle = val18; GUIStyle val19 = new GUIStyle(_hintStyle); val19.normal.textColor = _universalColor; val19.fontStyle = (FontStyle)1; val19.fontSize = ScaledFont(9); _universalSubHeaderStyle = val19; GUIStyle val20 = new GUIStyle(_giftItemStyle); val20.normal.textColor = _lovedColor; _lovedBulletStyle = val20; GUIStyle val21 = new GUIStyle(_giftItemStyle); val21.normal.textColor = _likedColor; _likedBulletStyle = val21; GUIStyle val22 = new GUIStyle(_giftItemStyle); val22.normal.textColor = _universalColor; _universalBulletStyle = val22; } private Texture2D MakeTex(int width, int height, Color color) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown Color[] array = (Color[])(object)new Color[width * height]; for (int i = 0; i < array.Length; i++) { array[i] = color; } Texture2D val = new Texture2D(width, height); val.SetPixels(array); val.Apply(); return val; } private Texture2D MakeGradientTex(int width, int height, Color topColor, Color bottomColor) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_001f: 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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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) Texture2D val = new Texture2D(width, height); Color[] array = (Color[])(object)new Color[width * height]; for (int i = 0; i < height; i++) { float num = (float)i / (float)(height - 1); Color val2 = Color.Lerp(bottomColor, topColor, num); for (int j = 0; j < width; j++) { array[i * width + j] = val2; } } val.SetPixels(array); val.Apply(); return val; } private void OnDestroy() { if (_manager != null) { _manager.OnBirthdaysUpdated -= OnBirthdaysUpdated; } } } } namespace BirthdayReminder.Integration { public class TodoIntegration { private readonly BirthdayManager _birthdayManager; private readonly Dictionary<string, string> _birthdayTodoIds = new Dictionary<string, string>(); public TodoIntegration(BirthdayManager birthdayManager) { _birthdayManager = birthdayManager; _birthdayManager.OnBirthdaysUpdated += OnBirthdaysUpdated; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[TodoIntegration] Initialized - birthday todos will sync with Sun Haven Todo"); } } public void OnGiftGiven(string npcName) { try { TodoManager todoManager = Plugin.GetTodoManager(); if (todoManager == null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[TodoIntegration] OnGiftGiven: TodoManager is null, cannot complete todo for " + npcName)); } return; } if (!_birthdayTodoIds.TryGetValue(npcName, out var todoId)) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)("[TodoIntegration] OnGiftGiven: No tracked todo for " + npcName)); } return; } TodoItem val = todoManager.GetAllTodos().FirstOrDefault((Func<TodoItem, bool>)((TodoItem t) => t.Id == todoId)); if (val == null) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogWarning((object)("[TodoIntegration] OnGiftGiven: Todo " + todoId + " not found for " + npcName)); } _birthdayTodoIds.Remove(npcName); } else if (!val.IsCompleted) { todoManager.ToggleComplete(todoId); ManualLogSource log4 = Plugin.Log; if (log4 != null) { log4.LogInfo((object)("[TodoIntegration] Completed birthday todo for " + npcName + " (direct path)")); } } else { ManualLogSource log5 = Plugin.Log; if (log5 != null) { log5.LogInfo((object)("[TodoIntegration] Todo for " + npcName + " already completed")); } } } catch (Exception ex) { ManualLogSource log6 = Plugin.Log; if (log6 != null) { log6.LogWarning((object)("[TodoIntegration] Error completing todo on gift: " + ex.Message)); } } } private void OnBirthdaysUpdated() { try { TodoManager todoManager = Plugin.GetTodoManager(); if (todoManager == null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)"[TodoIntegration] OnBirthdaysUpdated: TodoManager is null"); } return; } List<BirthdayDisplayInfo> todaysBirthdays = _birthdayManager.TodaysBirthdays; if (todaysBirthdays == null || todaysBirthdays.Count == 0) { CleanupBirthdayTodos(todoManager); return; } HashSet<string> currentNPCs = new HashSet<string>(todaysBirthdays.Select((BirthdayDisplayInfo b) => b.NPCName)); List<string> list = _birthdayTodoIds.Keys.Where((string k) => !currentNPCs.Contains(k)).ToList(); foreach (string item in list) { RemoveBirthdayTodo(todoManager, item); } foreach (BirthdayDisplayInfo item2 in todaysBirthdays) { if (item2.HasBeenGifted) { CompleteBirthdayTodo(todoManager, item2.NPCName); } else { EnsureBirthdayTodo(todoManager, item2); } } } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[TodoIntegration] Error syncing birthdays: " + ex.Message)); } } } private void EnsureBirthdayTodo(TodoManager todoManager, BirthdayDisplayInfo birthday) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown if (!_birthdayTodoIds.ContainsKey(birthday.NPCName)) { string text = "Give " + birthday.NPCName + " a birthday gift!"; string text2 = ((!string.IsNullOrEmpty(birthday.GiftHint)) ? birthday.GiftHint : "It's their birthday today!"); TodoItem val = new TodoItem(text, text2, (TodoPriority)2, (TodoCategory)6); todoManager.AddTodo(val); _birthdayTodoIds[birthday.NPCName] = val.Id; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[TodoIntegration] Added birthday todo for " + birthday.NPCName + " (id: " + val.Id + ")")); } } } private void CompleteBirthdayTodo(TodoManager todoManager, string npcName) { if (!_birthdayTodoIds.TryGetValue(npcName, out var todoId)) { return; } TodoItem val = todoManager.GetAllTodos().FirstOrDefault((Func<TodoItem, bool>)((TodoItem t) => t.Id == todoId)); if (val != null && !val.IsCompleted) { todoManager.ToggleComplete(todoId); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[TodoIntegration] Completed birthday todo for " + npcName + " (event path)")); } } } private void RemoveBirthdayTodo(TodoManager todoManager, string npcName) { if (_birthdayTodoIds.TryGetValue(npcName, out var value)) { todoManager.RemoveTodo(value); _birthdayTodoIds.Remove(npcName); } } private void CleanupBirthdayTodos(TodoManager todoManager) { foreach (KeyValuePair<string, string> item in _birthdayTodoIds.ToList()) { todoManager.RemoveTodo(item.Value); } _birthdayTodoIds.Clear(); } public void Reset() { _birthdayTodoIds.Clear(); } } } namespace BirthdayReminder.Data { public static class BirthdayCache { public static readonly List<string> UniversalLoved; public static readonly List<string> UniversalLiked; private static readonly List<NPCBirthday> _allBirthdays; public static IReadOnlyList<NPCBirthday> AllBirthdays => _allBirthdays; static BirthdayCache() { UniversalLoved = new List<string> { "Blue Rose Bouquet", "Red Rose Bouquet", "Black Diamond", "Havenite" }; UniversalLiked = new List<string> { "BLT", "Caribbean Green Soup", "Cheeseburger", "Cheesecake", "Cinnamon Apple Pie", "Diamond", "Pizza", "Pot Pie", "Red Veggie Soup", "Shimmeroot Treat", "Spicy Ramen", "Spring Roll", "Tomato Salad" }; _allBirthdays = new List<NPCBirthday> { CreateBirthday("Darius", "Spring", 1, new string[18] { "Blue Rose Bouquet", "Devilfin", "Enchanted Glorite Bar", "Enhanced Glorite Bar", "Forgotten Bouquet of Hyacinth", "Forgotten Bouquet of Orchids", "Forgotten Bouquet of Peonies", "Forgotten Bouquet of Roses", "Forgotten Bouquet of Tulips", "Ghost Pepper", "Glorite Bar", "Glorite Ore", "Glorite Sword", "Red Rose Bouquet", "Steak", "Sunite Sword", "Sweet and Spicy Shrimp", "Withercake" }, new string[21] { "Adamant Sword", "Armoranth", "Bone Gift", "Cinnaberry", "Copper Sword", "Darkness Essence", "Diamond", "Ghostly Great Sword", "Iron Sword", "Legendary Great Sword", "Legendary Hammer", "Lightning Hammer", "Mithril Sword", "Orchid", "Pepper", "Pepper Great Sword", "Potato Hammer", "Red Velvet Cake", "Red Velvet Cupcake", "Spicy Ramen", "Spiked Salmon" }), CreateBirthday("Lynn", "Spring", 10, new string[19] { "Anvil", "Cream Seltzer", "Creamy Beef Stew", "Creamy Mushroom Soup", "Egg Hash", "Forgotten Bouquet of Hyacinth", "Forgotten Bouquet of Orchids", "Forgotten Bouquet of Peonies", "Forgotten Bouquet of Roses", "Forgotten Bouquet of Tulips", "Glorite Bar", "Hot Chocolate", "Mana Anvil", "Mithril Bar", "Monster Anvil", "Pot Pie", "Stuffed Casserole", "Sunite Bar", "Withergate Anvil" }, new string[10] { "Adamant Bar", "Apple Juice", "Copper Bar", "Fizzy Seltzer", "Glass of Pure Water", "Iron Bar", "Milk", "Mithril Bar", "Pickled Veggie Salad", "Veggie Kebab" }), CreateBirthday("Nathaniel", "Spring", 13, new string[36] { "Adamant Sword", "City Guard Chest Plate", "City Guard Gloves", "City Guard Helmet", "City Guard Pants", "Copper Sword", "Cream Seltzer", "Creamy Mushroom Soup", "Dragon Mail Boots", "Dragon Mail Cape", "Dragon Mail Chest Plate", "Dragon Mail Gloves", "Dragon Mail Helmet", "Enchanted Light Boots", "Enchanted Light Chest", "Enchanted Light Gloves", "Enchanted Light Helmet", "Forgotten Bouquet of Hyacinth", "Forgotten Bouquet of Orchids", "Forgotten Bouquet of Peonies", "Forgotten Bouquet of Roses", "Forgotten Bouquet of Tulips", "Glorite Sword", "Hearty Pie", "Iron Sword", "Lasagna", "Legendary Great Sword", "Legendary Hammer", "Mashed Potatoes", "Mithril Sword", "Multiplate Chest", "Multiplate Helmet", "Multiplate Pants", "Pot Pie", "Steak", "Sunite Sword" }, new string[15] { "Adamant Helmet", "Apple Juice", "Armoranth", "Copper Helmet", "Copper Ore", "Ghostly Great Sword", "Iron Helmet", "Iron Ore", "Lightning Hammer", "Milk", "Mithril Helmet", "Pepper Great Sword", "Potato Hammer", "Sunite Helmet", "Veggie Kebab" }), CreateBirthday("Wesley", "Spring", 18, new string[24] { "Blue Roses Honey", "Cooled Lava Honey", "Daisy Honey", "Forgotten Bouquet of Hyacinth", "Forgotten Bouquet of Orchids", "Forgotten Bouquet of Peonies", "Forgotten Bouquet of Roses", "Forgotten Bouquet of Tulips", "Grapes", "Hibiscus Honey", "Honey", "Honeybrew", "Honeycomb Cake", "Honeyglazed Apple", "Lavender Honey", "Lily Honey", "Lotus Honey", "Orchid Honey", "Red Roses Honey", "Snobfish", "Sun Flower Honey", "Tulip Honey", "Walk Choy", "Walk Choy Pet" }, new string[25] { "Advanced Compost", "Advanced Earth Fertilizer", "Advanced Fire Fertilizer", "Advanced Magic Fertilizer", "Advanced Water Fertilizer", "Bubble Tea", "Compost", "Dragon Tea", "Earth Dragon Tea", "Elven Compost", "Fire Dragon Tea", "Grape Juice", "Honeysuckle", "Indiglow Tea", "Lily", "Mana Fertilizer", "Simple Earth Fertilizer", "Simple Fire Fertilizer", "Simple Magic Fertilizer", "Simple Sand Fertilizer", "Simple Water Fertilizer", "Slime Fertilizer", "Tea", "Water Dragon Tea", "Wind Chime Tea" }), CreateBirthday("Claude", "Spring", 24, new string[14] { "Apple Pie", "Forgotten Bouquet of Hyacinth", "Forgotten Bouquet of Orchids", "Forgotten Bouquet of Peonies", "Forgotten Bouquet of Roses", "Forgotten Bouquet of Tulips", "Red Veggie Soup", "Tomato", "Tomato Bread", "Tomato Juice", "Tomato Salad", "Tomato Soup", "Vampire Piranha", "Vampire Squid" }, new string[7] { "Apple", "Apple Juice", "Cinnamon Apple Pie", "Claude's Performance Record", "Record Player", "Red Veggie Soup", "Spaghetti" }), CreateBirthday("Liam", "Summer", 5, new string[18] { "Chef Hat (Black)", "Chef Hat (Blue)", "Chef Hat (Pink)", "Chef Hat (Red)", "Chef Hat (White)", "Coffee", "Demon Coffee", "Forgotten Bouquet of Hyacinth", "Forgotten Bouquet of Orchids", "Forgotten Bouquet of Peonies", "Forgotten Bouquet of Roses", "Forgotten Bouquet of Tulips", "Giant Blue Bunny Plushie", "Giant Pink Bunny Plushie", "Giant Pink Teddy Plushie", "Giant Purple Teddy Plushie", "Giant Teddy Plushie", "Hot Chocolate" }, new string[12] { "Almond Croissant", "Barley", "Cinnamon Spice Latte", "Coal", "Cookies", "Fire Crystal", "Flour", "Hearty Pie", "Log", "Scythe", "Sunflower", "Wheat" }), CreateBirthday("Shang", "Summer", 9, new string[26] { "Adamant Key", "Adamant Ring", "Adamant Sword", "Advanced Attack Potion", "Advanced Defense Potion", "Blunted Swordfish", "Earth Dragon Tea", "Fire Dragon Tea", "Forgotten Bouquet of Hyacinth", "Forgotten Bouquet of Orchids", "Forgotten Bouquet of Peonies", "Forgotten Bouquet of Roses", "Forgotten Bouquet of Tulips", "Glorite Sword", "Hearty Armor Pie", "Hearty Pie", "Incredible Attack Potion", "Incredible Defe