using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SunhavenMods.Shared;
using TrinketFortune.Patches;
using UnityEngine;
using UnityEngine.SceneManagement;
using Wish;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("TrinketFortune")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+79057c8571b97b27a9323b455b8f88a51829b688")]
[assembly: AssemblyProduct("TrinketFortune")]
[assembly: AssemblyTitle("TrinketFortune")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[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 ConfigFileHelper
{
public static ConfigFile CreateNamedConfig(string pluginGuid, string configFileName, Action<string> logWarning = null)
{
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Expected O, but got Unknown
string text = Path.Combine(Paths.ConfigPath, configFileName);
string text2 = Path.Combine(Paths.ConfigPath, pluginGuid + ".cfg");
try
{
if (!File.Exists(text) && File.Exists(text2))
{
File.Copy(text2, text);
}
}
catch (Exception ex)
{
logWarning?.Invoke("[Config] Migration to " + configFileName + " failed: " + ex.Message);
}
return new ConfigFile(text, true);
}
public static bool ReplacePluginConfig(BaseUnityPlugin plugin, ConfigFile newConfig, Action<string> logWarning = null)
{
if ((Object)(object)plugin == (Object)null || newConfig == null)
{
return false;
}
try
{
Type typeFromHandle = typeof(BaseUnityPlugin);
PropertyInfo property = typeFromHandle.GetProperty("Config", BindingFlags.Instance | BindingFlags.Public);
if (property != null && property.CanWrite)
{
property.SetValue(plugin, newConfig, null);
return true;
}
FieldInfo field = typeFromHandle.GetField("<Config>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
field.SetValue(plugin, newConfig);
return true;
}
FieldInfo[] fields = typeFromHandle.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo in fields)
{
if (fieldInfo.FieldType == typeof(ConfigFile))
{
fieldInfo.SetValue(plugin, newConfig);
return true;
}
}
}
catch (Exception ex)
{
logWarning?.Invoke("[Config] ReplacePluginConfig failed: " + ex.Message);
}
return false;
}
}
public static class SharedCodeRevision
{
public const string Value = "2026.07.28";
}
public sealed class ModHealthReport
{
public string PluginGuid { get; set; }
public string DisplayName { get; set; }
public string PluginVersion { get; set; }
public string SharedCodeRevision { get; set; }
public string IntegrationSummary { get; set; }
public string Mode { get; set; }
public string CharacterName { get; set; }
public bool? DataLoaded { get; set; }
public string LastPersistenceOutcome { get; set; }
public string LastError { get; set; }
public DateTime ReportedUtc { get; set; }
public ModHealthReport Clone()
{
return new ModHealthReport
{
PluginGuid = PluginGuid,
DisplayName = DisplayName,
PluginVersion = PluginVersion,
SharedCodeRevision = SharedCodeRevision,
IntegrationSummary = IntegrationSummary,
Mode = Mode,
CharacterName = CharacterName,
DataLoaded = DataLoaded,
LastPersistenceOutcome = LastPersistenceOutcome,
LastError = LastError,
ReportedUtc = ReportedUtc
};
}
public void AppendDiagnosticDump(StringBuilder sb)
{
if (sb != null)
{
sb.AppendLine("guid: " + (PluginGuid ?? "—"));
sb.AppendLine("name: " + (DisplayName ?? "—"));
sb.AppendLine("version: " + (PluginVersion ?? "—"));
sb.AppendLine("shared: " + (SharedCodeRevision ?? "—"));
sb.AppendLine("integrations: " + (IntegrationSummary ?? "—"));
sb.AppendLine("mode: " + (Mode ?? "—"));
sb.AppendLine("character: " + (string.IsNullOrEmpty(CharacterName) ? "—" : CharacterName));
sb.AppendLine("data loaded: " + (DataLoaded.HasValue ? DataLoaded.Value.ToString() : "—"));
sb.AppendLine("last save: " + (LastPersistenceOutcome ?? "—"));
sb.AppendLine("last error: " + (LastError ?? "—"));
sb.AppendLine("reported: " + ((ReportedUtc == default(DateTime)) ? "—" : ReportedUtc.ToLocalTime().ToString("u")));
}
}
}
public static class ModDiagnostics
{
private static readonly Dictionary<string, ModHealthReport> ReportsByPluginGuid = new Dictionary<string, ModHealthReport>(StringComparer.OrdinalIgnoreCase);
private static readonly object Lock = new object();
public static void ReportStartup(ModHealthReport report)
{
if (report == null || string.IsNullOrWhiteSpace(report.PluginGuid))
{
return;
}
report.ReportedUtc = DateTime.UtcNow;
if (string.IsNullOrEmpty(report.SharedCodeRevision))
{
report.SharedCodeRevision = "2026.07.28";
}
lock (Lock)
{
ReportsByPluginGuid[report.PluginGuid] = report.Clone();
}
}
public static void ReportRuntime(string pluginGuid, Action<ModHealthReport> update)
{
if (string.IsNullOrWhiteSpace(pluginGuid) || update == null)
{
return;
}
lock (Lock)
{
if (!ReportsByPluginGuid.TryGetValue(pluginGuid, out ModHealthReport value))
{
value = new ModHealthReport
{
PluginGuid = pluginGuid
};
ReportsByPluginGuid[pluginGuid] = value;
}
update(value);
value.ReportedUtc = DateTime.UtcNow;
}
}
public static ModHealthReport GetReport(string pluginGuid)
{
if (string.IsNullOrWhiteSpace(pluginGuid))
{
return null;
}
lock (Lock)
{
ModHealthReport value;
return ReportsByPluginGuid.TryGetValue(pluginGuid, out value) ? value.Clone() : null;
}
}
public static IReadOnlyList<ModHealthReport> GetAllReports()
{
lock (Lock)
{
return ReportsByPluginGuid.Values.Select((ModHealthReport r) => r.Clone()).ToList();
}
}
public static string FormatHealthLogLine(ModHealthReport report)
{
if (report == null)
{
return "[Health] (empty report)";
}
string text = (string.IsNullOrEmpty(report.DisplayName) ? report.PluginGuid : report.DisplayName);
string text2 = (string.IsNullOrEmpty(report.PluginVersion) ? "?" : report.PluginVersion);
string text3 = (string.IsNullOrEmpty(report.SharedCodeRevision) ? "?" : report.SharedCodeRevision);
string text4 = (string.IsNullOrEmpty(report.IntegrationSummary) ? "—" : report.IntegrationSummary);
string text5 = (string.IsNullOrEmpty(report.Mode) ? "—" : report.Mode);
string text6 = (string.IsNullOrEmpty(report.CharacterName) ? "—" : report.CharacterName);
string text7 = ((!report.DataLoaded.HasValue) ? "—" : (report.DataLoaded.Value ? "loaded" : "none"));
string text8 = (string.IsNullOrEmpty(report.LastPersistenceOutcome) ? "—" : report.LastPersistenceOutcome);
return "[Health] " + text + " v" + text2 + " | shared " + text3 + " | integrations: " + text4 + " | mode: " + text5 + " | character: " + text6 + " | data: " + text7 + " | save: " + text8;
}
public static void LogStartupHealth(ManualLogSource log, ModHealthReport report)
{
ReportStartup(report);
if (log != null)
{
log.LogInfo((object)FormatHealthLogLine(report));
}
}
public static void LogModStartup(ManualLogSource log, string pluginGuid, string displayName, string pluginVersion, string integrationSummary, string mode = "startup", bool? dataLoaded = false, string lastPersistenceOutcome = "—")
{
LogStartupHealth(log, new ModHealthReport
{
PluginGuid = pluginGuid,
DisplayName = displayName,
PluginVersion = pluginVersion,
SharedCodeRevision = "2026.07.28",
IntegrationSummary = integrationSummary,
Mode = mode,
DataLoaded = dataLoaded,
LastPersistenceOutcome = lastPersistenceOutcome
});
}
}
public static class SuitePluginGuids
{
public const string DevTools = "com.azraelgodking.havendevtools";
public const string SenpaisChest = "com.azraelgodking.senpaischest";
public const string BirthdayReminder = "com.azraelgodking.squirrelsbirthdayreminder";
public const string HavensBirthright = "com.azraelgodking.havensbirthright";
public const string Smut = "com.azraelgodking.sunhavenmuseumutilitytracker";
public const string SunhavenTodo = "com.azraelgodking.sunhaventodo";
public const string TheVault = "com.azraelgodking.thevault";
public const string HavensAlmanac = "com.azraelgodking.havensalmanac";
public const string FasterRaces = "com.azraelgodking.fasterraces";
public const string TrinketFortune = "com.azraelgodking.trinketfortune";
public const string CropOptimizer = "com.azraelgodking.cropoptimizer";
public const string HavensRespec = "com.azraelgodking.havensrespec";
public const string GiftingAssistant = "com.azraelgodking.giftingassistant";
}
public static class ModHealthIntegrationSummary
{
public static string Build(params (string label, string pluginGuid)[] integrations)
{
if (integrations == null || integrations.Length == 0)
{
return "standalone";
}
Dictionary<string, PluginInfo> pluginInfos = Chainloader.PluginInfos;
if (pluginInfos == null)
{
return "standalone";
}
List<string> list = new List<string>(integrations.Length);
for (int i = 0; i < integrations.Length; i++)
{
var (text, text2) = integrations[i];
if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(text2) && pluginInfos.ContainsKey(text2))
{
list.Add(text);
}
}
if (list.Count != 0)
{
return string.Join(", ", list);
}
return "standalone";
}
}
}
namespace TrinketFortune
{
public static class Config
{
public static ConfigEntry<bool> Enabled;
public static ConfigEntry<float> MuseumProgressBonusPercent;
public static ConfigEntry<float> MinimumMuseumProgress;
public static ConfigEntry<float> MaxBonusChancePercent;
public static void Bind(ConfigFile config)
{
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Expected O, but got Unknown
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Expected O, but got Unknown
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Expected O, but got Unknown
Enabled = config.Bind<bool>("General", "Enabled", true, "Enable Trinket Fortune. When enabled, odds of unowned fishing trinkets increase as you complete the aquarium.");
MuseumProgressBonusPercent = config.Bind<float>("General", "MuseumProgressBonusPercent", 5f, new ConfigDescription("Bonus to unowned trinket/fish odds per 10% aquarium completion (e.g. 5 = +5% per 10%). Applied on top of base drop chance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>()));
MinimumMuseumProgress = config.Bind<float>("General", "MinimumMuseumProgress", 0.2f, new ConfigDescription("Museum progress below this has no bonus (0.2 = 20% donated). Prevents bonus at very low completion.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
MaxBonusChancePercent = config.Bind<float>("General", "MaxBonusChancePercent", 75f, new ConfigDescription("Maximum bonus chance cap (%). Clamps the computed bonus regardless of aquarium progress. E.g. 75 = never more than a 75% bonus chance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
}
}
public static class DonationHelper
{
private const string SmutGuid = "com.azraelgodking.sunhavenmuseumutilitytracker";
private static object _donationManager;
private static MethodInfo _hasDonatedByGameId;
private static MethodInfo _getSectionStatsMethod;
private static MethodInfo _getAllSectionsMethod;
private static object _aquariumSection;
private static float _lastResolveAttemptRealtime;
private const float ResolveRetrySeconds = 10f;
private static FieldInfo _lootLevelField;
private static PropertyInfo _lootLevelProperty;
private static bool _lootLevelResolved;
private static bool _lootLevelLoggedMissing;
public static bool IsAvailable
{
get
{
EnsureResolved();
if (_donationManager != null)
{
return _hasDonatedByGameId != null;
}
return false;
}
}
static DonationHelper()
{
_lastResolveAttemptRealtime = -100f;
EnsureResolved(force: true);
}
private static void EnsureResolved(bool force = false)
{
if (!force && _donationManager != null && _hasDonatedByGameId != null)
{
return;
}
float realtimeSinceStartup = Time.realtimeSinceStartup;
if (!force && realtimeSinceStartup - _lastResolveAttemptRealtime < 10f)
{
return;
}
_lastResolveAttemptRealtime = realtimeSinceStartup;
if (Chainloader.PluginInfos == null || !Chainloader.PluginInfos.TryGetValue("com.azraelgodking.sunhavenmuseumutilitytracker", out var value) || (Object)(object)((value != null) ? value.Instance : null) == (Object)null)
{
return;
}
try
{
MethodInfo method = ((object)value.Instance).GetType().GetMethod("GetDonationManager", BindingFlags.Static | BindingFlags.Public);
if (!(method == null))
{
_donationManager = method.Invoke(null, null);
if (_donationManager != null)
{
_hasDonatedByGameId = _donationManager.GetType().GetMethod("HasDonatedByGameId", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(int) }, null);
}
}
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogDebug((object)("DonationHelper: SMUT bind failed: " + ex.Message));
}
}
}
public static bool HasDonatedByGameId(int gameItemId)
{
EnsureResolved();
if (_donationManager == null || _hasDonatedByGameId == null)
{
return false;
}
try
{
return (bool)_hasDonatedByGameId.Invoke(_donationManager, new object[1] { gameItemId });
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogDebug((object)$"DonationHelper: HasDonatedByGameId failed for {gameItemId}: {ex.Message}");
}
return false;
}
}
public static int PickBiasedFishingMuseumItem()
{
if (!Config.Enabled.Value)
{
return 0;
}
List<int> fishingMuseumItems = FishingRod.fishingMuseumItems;
if (fishingMuseumItems == null || fishingMuseumItems.Count == 0)
{
return 0;
}
if (!IsAvailable)
{
return 0;
}
List<int> list = new List<int>(fishingMuseumItems.Count);
for (int i = 0; i < fishingMuseumItems.Count; i++)
{
int num = fishingMuseumItems[i];
if (!HasDonatedByGameId(num))
{
list.Add(num);
}
}
if (list.Count == 0)
{
return fishingMuseumItems[Random.Range(0, fishingMuseumItems.Count)];
}
float aquariumProgress = GetAquariumProgress();
if (aquariumProgress < Config.MinimumMuseumProgress.Value * 100f)
{
return fishingMuseumItems[Random.Range(0, fishingMuseumItems.Count)];
}
float num2 = Mathf.Min(Config.MuseumProgressBonusPercent.Value * (aquariumProgress / 10f), Config.MaxBonusChancePercent.Value);
if (Random.Range(0f, 100f) < num2)
{
return list[Random.Range(0, list.Count)];
}
return fishingMuseumItems[Random.Range(0, fishingMuseumItems.Count)];
}
public static float GetAquariumProgressPercent()
{
return GetAquariumProgress();
}
private static float GetAquariumProgress()
{
if (TryGetSmutAquariumProgress(out var percent))
{
return percent;
}
return GetGameSaveAquariumProgress();
}
private static bool TryGetSmutAquariumProgress(out float percent)
{
percent = 0f;
EnsureResolved();
if (_donationManager == null)
{
return false;
}
try
{
EnsureAquariumSectionResolved();
if (_aquariumSection == null || _getSectionStatsMethod == null)
{
return false;
}
object obj = _getSectionStatsMethod.Invoke(_donationManager, new object[1] { _aquariumSection });
if (obj == null)
{
return false;
}
Type type = obj.GetType();
FieldInfo fieldInfo = type.GetField("Item1") ?? type.GetField("donated");
FieldInfo fieldInfo2 = type.GetField("Item2") ?? type.GetField("total");
if (fieldInfo == null || fieldInfo2 == null)
{
return false;
}
int num = (int)fieldInfo.GetValue(obj);
int num2 = (int)fieldInfo2.GetValue(obj);
if (num2 <= 0)
{
return false;
}
percent = (float)num / (float)num2 * 100f;
return true;
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogDebug((object)("DonationHelper: SMUT aquarium progress failed: " + ex.Message));
}
return false;
}
}
private static void EnsureAquariumSectionResolved()
{
if ((_aquariumSection != null && _getSectionStatsMethod != null) || _donationManager == null)
{
return;
}
Type type = _donationManager.GetType();
_getSectionStatsMethod = type.GetMethod("GetSectionStats", BindingFlags.Instance | BindingFlags.Public);
if (_getSectionStatsMethod == null)
{
return;
}
Type type2 = type.Assembly.GetType("SunHavenMuseumUtilityTracker.Data.MuseumContent");
if (type2 == null)
{
return;
}
_getAllSectionsMethod = type2.GetMethod("GetAllSections", BindingFlags.Static | BindingFlags.Public);
if (!(_getAllSectionsMethod?.Invoke(null, null) is IEnumerable enumerable))
{
return;
}
foreach (object item in enumerable)
{
if (item != null && string.Equals(item.GetType().GetProperty("Id")?.GetValue(item) as string, "aquarium", StringComparison.OrdinalIgnoreCase))
{
_aquariumSection = item;
break;
}
}
}
private static float GetGameSaveAquariumProgress()
{
try
{
int num = 0;
int num2 = 0;
Type type = Type.GetType("Wish.GameSave, SunHaven.Core");
if (type == null)
{
return 0f;
}
PropertyInfo property = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public);
if (property == null)
{
return 0f;
}
object value = property.GetValue(null);
if (value == null)
{
return 0f;
}
MethodInfo method = type.GetMethod("GetProgressIntWorld", new Type[1] { typeof(string) });
if (method == null)
{
return 0f;
}
foreach (var item2 in MuseumCurator.aquaticMuseumProgress)
{
string text = item2.Item1 + "complete";
int item = item2.Item2;
int num3 = (int)method.Invoke(value, new object[1] { text });
num += item;
num2 += num3;
}
return (num > 0) ? ((float)num2 / (float)num * 100f) : 0f;
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogDebug((object)("DonationHelper: aquarium progress fallback used due to reflection error: " + ex.Message));
}
return 0f;
}
}
public static FishData PickBiasedFish(RandomFishArray array, float level)
{
if (!Config.Enabled.Value || array == null || array.Length == 0)
{
return null;
}
if (!IsAvailable)
{
return null;
}
List<FishData> list = new List<FishData>();
for (int i = 0; i < array.Length; i++)
{
FishLoot val = array.drops[i];
if (!((Object)(object)val?.fish == (Object)null) && IsLootEligibleAtLevel(val, level) && !HasDonatedByGameId(((ItemData)val.fish).id))
{
list.Add(val.fish);
}
}
if (list.Count == 0)
{
return null;
}
float aquariumProgress = GetAquariumProgress();
if (aquariumProgress < Config.MinimumMuseumProgress.Value * 100f)
{
return null;
}
float num = Mathf.Min(Config.MuseumProgressBonusPercent.Value * (aquariumProgress / 10f), Config.MaxBonusChancePercent.Value);
if (Random.Range(0f, 100f) >= num)
{
return null;
}
return list[Random.Range(0, list.Count)];
}
private static bool IsLootEligibleAtLevel(object loot, float level)
{
if (loot == null)
{
return false;
}
EnsureLootLevelMember(loot.GetType());
object obj = null;
try
{
if (_lootLevelField != null)
{
obj = _lootLevelField.GetValue(loot);
}
else
{
if (!(_lootLevelProperty != null))
{
return true;
}
obj = _lootLevelProperty.GetValue(loot);
}
}
catch
{
return true;
}
if (obj == null)
{
return true;
}
try
{
float num = Convert.ToSingle(obj);
return level + 0.001f >= num;
}
catch
{
return true;
}
}
private static void EnsureLootLevelMember(Type lootType)
{
if (_lootLevelResolved || lootType == null)
{
return;
}
_lootLevelResolved = true;
string[] array = new string[5] { "useLevel", "level", "minLevel", "requiredLevel", "fishingLevel" };
foreach (string name in array)
{
_lootLevelField = lootType.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (_lootLevelField != null)
{
return;
}
_lootLevelProperty = lootType.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (_lootLevelProperty != null)
{
return;
}
}
if (!_lootLevelLoggedMissing)
{
_lootLevelLoggedMissing = true;
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogDebug((object)("[TrinketFortune] No level gate on " + lootType.Name + "; fish bias uses full drop list."));
}
}
}
}
[BepInPlugin("com.azraelgodking.trinketfortune", "Trinket Fortune", "2.1.1")]
public class Plugin : BaseUnityPlugin
{
public static class PluginInfo
{
public const string PLUGIN_GUID = "com.azraelgodking.trinketfortune";
public const string PLUGIN_NAME = "Trinket Fortune";
public const string PLUGIN_VERSION = "2.1.1";
}
private Harmony _harmony;
private bool _applicationQuitting;
public static ManualLogSource Log { get; private set; }
private void Awake()
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
ConfigFile val = CreateNamedConfig();
ConfigFileHelper.ReplacePluginConfig((BaseUnityPlugin)(object)this, val, (Action<string>)Log.LogWarning);
Config.Bind(val);
_harmony = new Harmony("com.azraelgodking.trinketfortune");
FishingTrinketPatches.ApplyPatches(_harmony);
Log.LogInfo((object)"Trinket Fortune v2.1.1 loaded. Fishing loot bias active when S.M.U.T. is installed.");
ModDiagnostics.LogModStartup(Log, "com.azraelgodking.trinketfortune", "Trinket Fortune", "2.1.1", ModHealthIntegrationSummary.Build(("DevTools", "com.azraelgodking.havendevtools"), ("SMUT", "com.azraelgodking.sunhavenmuseumutilitytracker")), "startup", false);
}
private void OnApplicationQuit()
{
_applicationQuitting = true;
}
private void OnDestroy()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
Scene activeScene = SceneManager.GetActiveScene();
string text = ((Scene)(ref activeScene)).name ?? string.Empty;
string text2 = text.ToLowerInvariant();
if (_applicationQuitting || !Application.isPlaying || text2.Contains("menu") || text2.Contains("title"))
{
ManualLogSource log = Log;
if (log != null)
{
log.LogInfo((object)("[Lifecycle] Plugin OnDestroy during expected teardown (scene: " + text + ")"));
}
}
else
{
ManualLogSource log2 = Log;
if (log2 != null)
{
log2.LogWarning((object)("[Lifecycle] Plugin OnDestroy outside expected teardown (scene: " + text + ")"));
}
}
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
private static ConfigFile CreateNamedConfig()
{
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Expected O, but got Unknown
string text = Path.Combine(Paths.ConfigPath, "TrinketFortune.cfg");
string text2 = Path.Combine(Paths.ConfigPath, "com.azraelgodking.trinketfortune.cfg");
try
{
if (!File.Exists(text) && File.Exists(text2))
{
File.Copy(text2, text);
}
}
catch (Exception ex)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogWarning((object)("[Config] Migration to TrinketFortune.cfg failed: " + ex.Message));
}
}
return new ConfigFile(text, true);
}
public static string GetDevToolsSummary()
{
if (Config.Enabled == null)
{
return "Not ready";
}
bool flag = Chainloader.PluginInfos != null && Chainloader.PluginInfos.ContainsKey("com.azraelgodking.sunhavenmuseumutilitytracker");
string text = (DonationHelper.IsAvailable ? "S.M.U.T. donations linked" : (flag ? "S.M.U.T. installed (load a save for donation data)" : "standalone mode"));
if (!Config.Enabled.Value)
{
return "Disabled in config | " + text;
}
float aquariumProgressPercent = DonationHelper.GetAquariumProgressPercent();
return $"Aquarium: {aquariumProgressPercent:F1}% | Bonus {Config.MuseumProgressBonusPercent.Value}% per 10% | " + $"Min {Config.MinimumMuseumProgress.Value:P0} | Cap {Config.MaxBonusChancePercent.Value}% | {text}";
}
}
}
namespace TrinketFortune.Patches
{
public static class FishingTrinketPatches
{
public static void ApplyPatches(Harmony harmony)
{
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Expected O, but got Unknown
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_0152: Expected O, but got Unknown
MethodInfo methodInfo = null;
MethodInfo[] methods = typeof(Utilities).GetMethods(BindingFlags.Static | BindingFlags.Public);
foreach (MethodInfo methodInfo2 in methods)
{
if (methodInfo2.Name != "RandomItem" || !methodInfo2.IsGenericMethodDefinition)
{
continue;
}
ParameterInfo[] parameters = methodInfo2.GetParameters();
if (parameters.Length != 1)
{
continue;
}
Type parameterType = parameters[0].ParameterType;
if (parameterType.IsGenericType && !(parameterType.GetGenericTypeDefinition() != typeof(IList<>)))
{
try
{
methodInfo = methodInfo2.MakeGenericMethod(typeof(int));
}
catch
{
}
if (methodInfo != null)
{
break;
}
}
}
if (methodInfo != null)
{
HarmonyMethod val = new HarmonyMethod(typeof(FishingTrinketPatches), "RandomItem_Prefix", (Type[])null);
harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
Plugin.Log.LogInfo((object)"Patched Utilities.RandomItem<int> for fishing museum items");
}
else
{
Plugin.Log.LogWarning((object)"Could not find Utilities.RandomItem for museum item bias");
}
MethodInfo method = typeof(RandomFishArray).GetMethod("RandomItem", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(float) }, null);
if (method != null)
{
harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(typeof(FishingTrinketPatches), "RandomFishArray_RandomItem_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
Plugin.Log.LogInfo((object)"Patched RandomFishArray.RandomItem for fish bias");
}
else
{
Plugin.Log.LogWarning((object)"Could not find RandomFishArray.RandomItem");
}
}
private static bool RandomItem_Prefix<T>(IList<T> list, ref T __result)
{
if (!Config.Enabled.Value)
{
return true;
}
if (typeof(T) != typeof(int))
{
return true;
}
if (list == null || list != FishingRod.fishingMuseumItems)
{
return true;
}
int num = DonationHelper.PickBiasedFishingMuseumItem();
if (num == 0)
{
return true;
}
__result = (T)(object)num;
return false;
}
private static void RandomFishArray_RandomItem_Postfix(RandomFishArray __instance, float level, ref FishData __result)
{
FishData val = DonationHelper.PickBiasedFish(__instance, level);
if ((Object)(object)val != (Object)null)
{
__result = val;
}
}
}
}