Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ShiftingWares v1.0.0
plugins/ShiftingWares/ShiftingWares.dll
Decompiled 3 hours agousing System; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace ShiftingWares; [BepInPlugin("felih.ShiftingWares", "Shifting Wares", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string GUID = "felih.ShiftingWares"; public const string NAME = "Shifting Wares"; public const string VERSION = "1.0.0"; internal static ManualLogSource Log; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<int> RotationDays; internal static ConfigEntry<float> PriceMultiplier; internal static ConfigEntry<bool> ShowCountdown; internal static ConfigEntry<bool> DetailedLog; private void Awake() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Expected O, but got Unknown //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Expected O, but got Unknown //IL_0117: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Enabled", true, "Haldor brings a few travel wares on top of his usual goods, and they change every few days."); RotationDays = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "RotationDays", 3, new ConfigDescription("In-game days between new travel wares.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), new object[0])); PriceMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "PriceMultiplier", 1f, new ConfigDescription("Scales the price of the travel wares.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), new object[0])); ShowCountdown = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "ShowCountdown", true, "Show the days left until new travel wares when you look at Haldor."); DetailedLog = ((BaseUnityPlugin)this).Config.Bind<bool>("9 - Debug", "DetailedLog", false, "Writes the chosen wares to the BepInEx log."); ((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("1 - General", "ShownPercent")); ((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("1 - General", "MinShown")); new Harmony("felih.ShiftingWares").PatchAll(typeof(Plugin).Assembly); Log.LogInfo((object)"Shifting Wares 1.0.0 loaded"); } } internal class Stage { internal string key; internal int unit; internal int stack; internal string[] items; internal Stage(string key, int unit, int stack, params string[] items) { this.key = key; this.unit = unit; this.stack = stack; this.items = items; } } internal static class Wares { private const int MinWares = 3; private const int MaxWares = 5; private const float GearChance = 0.5f; private static readonly Stage[] Stages = new Stage[7] { new Stage(null, 2, 20, "Feathers", "LeatherScraps", "Resin", "Honey", "Raspberry", "Flint", "DeerHide", "NeckTail"), new Stage("defeated_eikthyr", 3, 15, "TrollHide", "Blueberries", "MushroomYellow", "CarrotSeeds", "Thistle", "GreydwarfEye", "FineWood", "RoundLog"), new Stage("defeated_gdking", 4, 10, "Guck", "Root", "Entrails", "Bloodbag", "TurnipSeeds", "Chitin", "ElderBark", "Ooze"), new Stage("defeated_bonemass", 6, 10, "WolfPelt", "Obsidian", "Crystal", "WolfFang", "OnionSeeds", "FreezeGland", "JuteRed"), new Stage("defeated_dragon", 8, 10, "Needle", "Barley", "Flax", "Tar", "Cloudberry", "LoxPelt"), new Stage("defeated_goblinking", 12, 5, "Carapace", "SoftTissue", "RoyalJelly", "Sap", "MushroomJotunPuffs", "MushroomMagecap", "Mandible", "ScaleHide"), new Stage("defeated_queen", 16, 5, "CharredBone", "AskHide", "Grausten", "MushroomSmokePuff", "Vineberry", "FiddleheadFern", "VoltureFeather") }; private static readonly int[] GearPrice = new int[7] { 400, 400, 700, 1100, 1600, 2200, 3000 }; private static readonly string[] GearExtra = new string[4] { "SledgeDemolisher", "MaceSilver", "SpearChitin", "BowDraugrFang" }; private static readonly string[][] StageMats = new string[7][] { new string[0], new string[5] { "Copper", "Tin", "Bronze", "CopperOre", "TinOre" }, new string[3] { "Iron", "IronScrap", "IronOre" }, new string[3] { "Silver", "SilverOre", "DragonEgg" }, new string[3] { "BlackMetal", "BlackMetalScrap", "DragonTear" }, new string[6] { "Eitr", "YggdrasilWood", "BlackCore", "Wisp", "DvergrNeedle", "Copper_Mistlands" }, new string[6] { "Flametal", "FlametalNew", "FlametalOre", "FlametalOreNew", "CelestialFeather", "MoltenCore" } }; private static Dictionary<string, int> _matStage; private static List<KeyValuePair<ItemDrop, int>> _gear; private static int _cachePeriod = -1; private static string _cacheKeys; private static readonly List<TradeItem> _cache = new List<TradeItem>(); private static readonly HashSet<string> _missingLogged = new HashSet<string>(); internal static bool IsHaldor(Trader t) { if (!Plugin.Enabled.Value || (Object)(object)t == (Object)null) { return false; } if (!Low(t.m_name).Contains("haldor")) { return Low(Utils.GetPrefabName(((Component)t).gameObject)).Contains("haldor"); } return true; } private static string Low(string s) { if (!string.IsNullOrEmpty(s)) { return s.ToLowerInvariant(); } return ""; } internal static int Day() { if ((Object)(object)EnvMan.instance == (Object)null || (Object)(object)ZNet.instance == (Object)null) { return 0; } return EnvMan.instance.GetDay(); } internal static int Period() { return Day() / Mathf.Max(1, Plugin.RotationDays.Value); } internal static int DaysLeft() { int num = Mathf.Max(1, Plugin.RotationDays.Value); return num - Day() % num; } private static bool Open(Stage s) { if (s.key != null) { if ((Object)(object)ZoneSystem.instance != (Object)null) { return ZoneSystem.instance.GetGlobalKey(s.key); } return false; } return true; } internal static List<TradeItem> Current(Trader t) { int num = Period(); string text = ""; for (int i = 0; i < Stages.Length; i++) { text += (Open(Stages[i]) ? "1" : "0"); } if (num == _cachePeriod && text == _cacheKeys) { return _cache; } _cachePeriod = num; _cacheKeys = text; _cache.Clear(); if ((Object)(object)ObjectDB.instance == (Object)null) { _cachePeriod = -1; return _cache; } HashSet<string> hashSet = new HashSet<string>(); foreach (TradeItem item in t.m_items) { if ((Object)(object)item.m_prefab != (Object)null) { hashSet.Add(((Object)((Component)item.m_prefab).gameObject).name); } } int num2 = -1; for (int j = 0; j < Stages.Length; j++) { if (Open(Stages[j])) { num2 = j; } } List<KeyValuePair<TradeItem, int>> list = new List<KeyValuePair<TradeItem, int>>(); for (int k = 0; k <= num2; k++) { Stage stage = Stages[k]; if (!Open(stage)) { continue; } int value = ((k == num2) ? 4 : ((k != num2 - 1) ? 1 : 2)); string[] items = stage.items; foreach (string text2 in items) { if (hashSet.Contains(text2)) { continue; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text2); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val == (Object)null) { if (Plugin.DetailedLog.Value && _missingLogged.Add(text2)) { Plugin.Log.LogInfo((object)("[wares] no item prefab " + text2)); } } else { list.Add(new KeyValuePair<TradeItem, int>(Make(val, stage), value)); } } } Random random = new Random(Seed() ^ (num * 7919) ^ 0x5A17); int num3 = random.Next(3, 6); while (_cache.Count < num3 && list.Count > 0) { int num4 = 0; foreach (KeyValuePair<TradeItem, int> item2 in list) { num4 += item2.Value; } int num5 = random.Next(num4); for (int m = 0; m < list.Count; m++) { num5 -= list[m].Value; if (num5 < 0) { _cache.Add(list[m].Key); list.RemoveAt(m); break; } } } if (random.NextDouble() < 0.5) { List<KeyValuePair<ItemDrop, int>> list2 = new List<KeyValuePair<ItemDrop, int>>(); int num6 = 0; foreach (KeyValuePair<ItemDrop, int> item3 in Gear()) { if (item3.Value <= num2 && !hashSet.Contains(((Object)((Component)item3.Key).gameObject).name)) { list2.Add(item3); num6 += ((item3.Value == num2) ? 4 : ((item3.Value != num2 - 1) ? 1 : 2)); } } if (list2.Count > 0) { int num7 = random.Next(num6); foreach (KeyValuePair<ItemDrop, int> item4 in list2) { num7 -= ((item4.Value == num2) ? 4 : ((item4.Value != num2 - 1) ? 1 : 2)); if (num7 < 0) { TradeItem val2 = Make(item4.Key, Stages[item4.Value]); val2.m_stack = 1; val2.m_price = Mathf.Max(1, Mathf.RoundToInt((float)GearPrice[item4.Value] * Plugin.PriceMultiplier.Value)); _cache.Add(val2); break; } } } } if (Plugin.DetailedLog.Value) { List<string> list3 = new List<string>(); foreach (TradeItem item5 in _cache) { list3.Add(((Object)((Component)item5.m_prefab).gameObject).name + " x" + item5.m_stack + " " + item5.m_price); } Plugin.Log.LogInfo((object)("[wares] day " + Day() + " period " + num + " stages " + text + ": " + string.Join(", ", list3.ToArray()))); } return _cache; } private static List<KeyValuePair<ItemDrop, int>> Gear() { //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Invalid comparison between Unknown and I4 //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Invalid comparison between Unknown and I4 //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Invalid comparison between Unknown and I4 //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Invalid comparison between Unknown and I4 //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Invalid comparison between Unknown and I4 if (_gear != null) { return _gear; } _gear = new List<KeyValuePair<ItemDrop, int>>(); _matStage = new Dictionary<string, int>(); for (int i = 0; i < Stages.Length; i++) { string[] items = Stages[i].items; foreach (string key in items) { _matStage[key] = i; } } for (int k = 0; k < StageMats.Length; k++) { string[] array = StageMats[k]; foreach (string key2 in array) { _matStage[key2] = k; } } HashSet<string> hashSet = new HashSet<string>(GearExtra); HashSet<string> hashSet2 = new HashSet<string>(); foreach (Recipe recipe in ObjectDB.instance.m_recipes) { if ((Object)(object)recipe == (Object)null || (Object)(object)recipe.m_item == (Object)null || !recipe.m_enabled || recipe.m_resources == null) { continue; } ItemType itemType = recipe.m_item.m_itemData.m_shared.m_itemType; if ((int)itemType != 3 && (int)itemType != 14 && (int)itemType != 22 && (int)itemType != 4 && (int)itemType != 5) { continue; } string name = ((Object)((Component)recipe.m_item).gameObject).name; bool flag = false; int num = 0; Requirement[] resources = recipe.m_resources; foreach (Requirement val in resources) { if (val != null && !((Object)(object)val.m_resItem == (Object)null)) { string name2 = ((Object)((Component)val.m_resItem).gameObject).name; if (name2 == "YmirRemains") { flag = true; } if (_matStage.TryGetValue(name2, out var value) && value > num) { num = value; } } } if ((flag || hashSet.Contains(name)) && hashSet2.Add(name)) { _gear.Add(new KeyValuePair<ItemDrop, int>(recipe.m_item, num)); } } if (Plugin.DetailedLog.Value) { List<string> list = new List<string>(); foreach (KeyValuePair<ItemDrop, int> item in _gear) { list.Add(((Object)((Component)item.Key).gameObject).name + "(" + item.Value + ")"); } Plugin.Log.LogInfo((object)("[wares] gear pool: " + string.Join(", ", list.ToArray()))); } return _gear; } private static TradeItem Make(ItemDrop drop, Stage s) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown SharedData shared = drop.m_itemData.m_shared; int num = Mathf.Clamp(s.stack, 1, Mathf.Max(1, shared.m_maxStackSize)); int num2 = Mathf.Max(s.unit, shared.m_value * 2); int price = Mathf.Max(1, Mathf.RoundToInt((float)(num2 * num) * Plugin.PriceMultiplier.Value)); TradeItem val = new TradeItem(); val.m_prefab = drop; val.m_stack = num; val.m_price = price; val.m_requiredGlobalKey = ""; val.m_buyKey = ""; val.m_name = ""; val.m_tooltip = ""; val.m_buyPlayerEffects = new EffectList(); return val; } private static int Seed() { if (WorldGenerator.instance != null) { return WorldGenerator.instance.GetSeed(); } return 0; } } [HarmonyPatch(typeof(Trader), "GetAvailableItems")] internal static class Trader_GetAvailableItems { private static void Postfix(Trader __instance, List<TradeItem> __result) { try { if (__result != null && Wares.IsHaldor(__instance)) { __result.AddRange(Wares.Current(__instance)); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("GetAvailableItems: " + ex.Message)); } } } [HarmonyPatch(typeof(Trader), "GetHoverText")] internal static class Trader_GetHoverText { private static void Postfix(Trader __instance, ref string __result) { if (Plugin.ShowCountdown.Value && Wares.IsHaldor(__instance)) { int num = Wares.DaysLeft(); __result = __result + "\n<color=#bbbbbb>New travel wares " + ((num == 1) ? "tomorrow" : ("in " + num + " days")) + "</color>"; } } } [HarmonyPatch(typeof(StoreGui), "Show")] internal static class StoreGui_Show { private static int _seen = -1; private static void Postfix(Trader trader) { if (Wares.IsHaldor(trader) && !((Object)(object)Player.m_localPlayer == (Object)null)) { int num = Wares.Period(); if (_seen >= 0 && _seen != num) { ((Character)Player.m_localPlayer).Message((MessageType)2, Localization.instance.Localize(trader.m_name) + " brought new travel wares", 0, (Sprite)null, false); } _seen = num; } } }