Decompiled source of TraderBrothers v1.0.0

plugins\TraderBrothers\TraderBrothers.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("TraderBrothers")]
[assembly: AssemblyDescription("Adds three placeable traders for materials, supplies, meads, and potions.")]
[assembly: AssemblyCompany("LEGIOmods")]
[assembly: AssemblyProduct("TraderBrothers")]
[assembly: AssemblyCopyright("Copyright 2026 LEGIOmods")]
[assembly: ComVisible(false)]
[assembly: Guid("99c4e7f2-f33a-4b8e-be32-83619c66d3cc")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyMetadata("AI_Assisted_Creation", "This assembly was partially or fully created with the assistance of Generative AI for code, localization, documentation, and package preparation.")]
[assembly: AssemblyMetadata("AI_Model_Vendor", "OpenAI")]
[assembly: AssemblyMetadata("AI_Agent", "OpenAI Codex")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TraderBrothers
{
	[BepInPlugin("domen.valheim.traderbrothers", "TraderBrothers", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal sealed class TraderBrothersPlugin : BaseUnityPlugin
	{
		private sealed class TraderBrothersIdleAnimation : MonoBehaviour
		{
			private static readonly int[] IdleHashes = new int[5]
			{
				Animator.StringToHash("Idle"),
				Animator.StringToHash("idle"),
				Animator.StringToHash("Idle1"),
				Animator.StringToHash("Base Layer.Idle"),
				Animator.StringToHash("Base Layer.idle")
			};

			public Animator Animator;

			private void Awake()
			{
				if ((Object)(object)Animator == (Object)null)
				{
					Animator = ((Component)this).GetComponentInChildren<Animator>(true);
				}
			}

			private void Start()
			{
				if ((Object)(object)Animator != (Object)null)
				{
					((Behaviour)Animator).enabled = true;
					Animator.speed = 1f;
					Animator.cullingMode = (AnimatorCullingMode)0;
				}
				((MonoBehaviour)this).InvokeRepeating("RefreshIdle", 0.5f, 3f);
			}

			private void Update()
			{
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)Animator == (Object)null)
				{
					return;
				}
				((Behaviour)Animator).enabled = true;
				Animator.speed = 1f;
				Animator.cullingMode = (AnimatorCullingMode)0;
				if (!Animator.IsInTransition(0))
				{
					AnimatorStateInfo currentAnimatorStateInfo = Animator.GetCurrentAnimatorStateInfo(0);
					if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).length > 0f && ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime >= 0.98f)
					{
						Animator.Play(((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash, 0, 0f);
					}
				}
			}

			private void RefreshIdle()
			{
				if ((Object)(object)Animator == (Object)null)
				{
					return;
				}
				((Behaviour)Animator).enabled = true;
				Animator.speed = 1f;
				int[] idleHashes = IdleHashes;
				foreach (int num in idleHashes)
				{
					if (Animator.HasState(0, num))
					{
						Animator.CrossFade(num, 0.25f, 0);
						break;
					}
				}
			}
		}

		private sealed class TraderBrothersIdleSound : MonoBehaviour
		{
			public EffectList IdleSound;

			public float Interval = 8f;

			public float Chance = 0.45f;

			private void Start()
			{
				((MonoBehaviour)this).InvokeRepeating("TryPlaySound", Random.Range(2f, Interval), Mathf.Max(1f, Interval));
			}

			private void TryPlaySound()
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				if (IdleSound != null && IdleSound.HasEffects() && Random.value <= Chance)
				{
					IdleSound.Create(((Component)this).transform.position, ((Component)this).transform.rotation, ((Component)this).transform, 1f, -1);
				}
			}
		}

		private sealed class TraderBrothersInteractable : MonoBehaviour, Interactable
		{
			public Trader Trader;

			public string DisplayName;

			public string GetHoverText()
			{
				return L(DisplayName) + "\n[<color=yellow><b>$KEY_Use</b></color>] " + L("$traderbrothers_trade");
			}

			public string GetHoverName()
			{
				return L(DisplayName);
			}

			public bool Interact(Humanoid user, bool hold, bool alt)
			{
				if (hold || (Object)(object)Trader == (Object)null)
				{
					return false;
				}
				EnsureTrades(Trader);
				StoreGui.instance.Show(Trader);
				return true;
			}

			public bool UseItem(Humanoid user, ItemData item)
			{
				return false;
			}
		}

		[HarmonyPatch(typeof(StoreGui), "OnBuyItem")]
		private static class StoreGuiOnBuyItemPatch
		{
			private static bool Prefix(StoreGui __instance)
			{
				return !TrySellScrap(__instance);
			}
		}

		[HarmonyPatch(typeof(StoreGui), "UpdateBuyButton")]
		private static class StoreGuiUpdateBuyButtonPatch
		{
			private static void Postfix(StoreGui __instance)
			{
				Trader value = Traverse.Create((object)__instance).Field("m_trader").GetValue<Trader>();
				bool flag = IsScrapDealer(value);
				bool flag2 = IsKnownOnlyTrader(value);
				if (flag || flag2)
				{
					Button value2 = Traverse.Create((object)__instance).Field("m_buyButton").GetValue<Button>();
					if ((Object)(object)value2 == (Object)null)
					{
						return;
					}
					TradeItem value3 = Traverse.Create((object)__instance).Field("m_selectedItem").GetValue<TradeItem>();
					if (flag)
					{
						((Selectable)value2).interactable = (Object)(object)value3?.m_prefab != (Object)null && PlayerItemCount(value3.m_prefab) > 0;
					}
					TMP_Text componentInChildren = ((Component)value2).GetComponentInChildren<TMP_Text>(true);
					if ((Object)(object)componentInChildren != (Object)null)
					{
						componentInChildren.text = (flag ? L("$traderbrothers_sell") : L("$traderbrothers_buy_button"));
					}
				}
				EnsureTraderHint(__instance);
			}
		}

		[HarmonyPatch(typeof(StoreGui), "UpdateSellButton")]
		private static class StoreGuiUpdateSellButtonPatch
		{
			private static void Postfix(StoreGui __instance)
			{
				if (IsScrapDealer(Traverse.Create((object)__instance).Field("m_trader").GetValue<Trader>()))
				{
					Button value = Traverse.Create((object)__instance).Field("m_sellButton").GetValue<Button>();
					if ((Object)(object)value != (Object)null)
					{
						((Selectable)value).interactable = false;
					}
					EnsureTraderHint(__instance);
				}
			}
		}

		[HarmonyPatch]
		private static class StoreGuiFillListPatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(typeof(StoreGui), "FillList", (Type[])null, (Type[])null);
			}

			private static bool Prepare()
			{
				return TargetMethod() != null;
			}

			private static void Postfix(StoreGui __instance)
			{
				Trader value = Traverse.Create((object)__instance).Field("m_trader").GetValue<Trader>();
				if (!IsScrapDealer(value))
				{
					return;
				}
				try
				{
					List<GameObject> value2 = Traverse.Create((object)__instance).Field("m_itemList").GetValue<List<GameObject>>();
					List<TradeItem> availableItems = value.GetAvailableItems();
					if (value2 != null && availableItems != null)
					{
						int num = Mathf.Min(value2.Count, availableItems.Count);
						for (int i = 0; i < num; i++)
						{
							int num2 = PlayerItemCount(availableItems[i].m_prefab);
							SetAvailabilityVisual(value2[i], num2 > 0, num2);
						}
						ResetScrapScrollTop(__instance);
					}
				}
				catch (Exception ex)
				{
					Log.LogDebug((object)("Scrap Dealer availability display skipped: " + ex.Message));
				}
			}
		}

		[HarmonyPatch(typeof(Trader), "GetAvailableItems")]
		private static class TraderAvailableItemsPatch
		{
			private static void Prefix(Trader __instance)
			{
				EnsureTrades(__instance);
			}

			private static void Postfix(Trader __instance, ref List<TradeItem> __result)
			{
				if (__result == null)
				{
					return;
				}
				if (IsScrapDealer(__instance))
				{
					__result = (from item in __result.Where((TradeItem item) => IsKnown(item.m_prefab)).Select((TradeItem item, int index) => new
						{
							Item = item,
							Index = index,
							Count = PlayerItemCount(item.m_prefab)
						})
						orderby item.Count > 0 descending, item.Index
						select item.Item).ToList();
				}
				else if (IsKnownOnlyTrader(__instance))
				{
					__result = __result.Where((TradeItem item) => IsKnown(item.m_prefab)).ToList();
				}
			}
		}

		private sealed class TradeSpec
		{
			public string PrefabName { get; }

			public int Stack { get; }

			public int Price { get; }

			public TradeSpec(string prefabName, int stack, int price)
			{
				PrefabName = prefabName;
				Stack = stack;
				Price = price;
			}
		}

		public const string PluginGuid = "domen.valheim.traderbrothers";

		public const string PluginName = "TraderBrothers";

		public const string PluginVersion = "1.0.0";

		internal const string ScrapDealerPrefab = "TraderBrothers_ScrapDealer";

		internal const string MineForemanPrefab = "TraderBrothers_MineForeman";

		internal const string BarkeeperPrefab = "TraderBrothers_Barkeeper";

		internal static ManualLogSource Log;

		private static CustomLocalization localization;

		private Harmony harmony;

		private bool registered;

		private static readonly Dictionary<string, List<TradeSpec>> TradeSpecs = new Dictionary<string, List<TradeSpec>>();

		private const string ScrapDealerNameToken = "$traderbrothers_scrapdealer";

		private const string MineForemanNameToken = "$traderbrothers_mineforeman";

		private const string BarkeeperNameToken = "$traderbrothers_barkeeper";

		private const string ScrapDealerDescriptionToken = "$traderbrothers_scrapdealer_desc";

		private const string MineForemanDescriptionToken = "$traderbrothers_mineforeman_desc";

		private const string BarkeeperDescriptionToken = "$traderbrothers_barkeeper_desc";

		private const string TradeToken = "$traderbrothers_trade";

		private const string SellToken = "$traderbrothers_sell";

		private const string BuyToken = "$traderbrothers_buy_button";

		private const string NotEnoughToken = "$traderbrothers_not_enough";

		private const string CoinsToken = "$traderbrothers_coins";

		private const string ShiftSellStackToken = "$traderbrothers_shift_sell_stack";

		private static readonly Color ScrapGreen = new Color(0.2f, 0.78f, 0.23f, 1f);

		private static readonly Color RogueGrey = new Color(0.72f, 0.74f, 0.76f, 1f);

		private static readonly Color WarmBark = new Color(0.52f, 0.34f, 0.2f, 1f);

		private static readonly TradeSpec[] ScrapBuySpecs = new TradeSpec[142]
		{
			S("Wood", 1),
			S("Stone", 1),
			S("Coal", 2),
			S("Resin", 1),
			S("Feathers", 2),
			S("BoneFragments", 1),
			S("LeatherScraps", 1),
			S("FineWood", 2),
			S("RoundLog", 2),
			S("ElderBark", 3),
			S("YggdrasilWood", 4),
			S("Blackwood", 4),
			S("Raspberry", 1),
			S("Mushroom", 1),
			S("Dandelion", 1),
			S("Thistle", 2),
			S("MushroomYellow", 2),
			S("Blueberries", 2),
			S("Cloudberry", 2),
			S("RoyalJelly", 5),
			S("Fiddlehead", 4),
			S("MushroomSmokePuff", 4),
			S("SeedCarrot", 1),
			S("SeedTurnip", 1),
			S("SeedOnion", 1),
			S("BeechSeeds", 1),
			S("FirCone", 1),
			S("PineCone", 1),
			S("Honey", 2),
			S("Carrot", 1),
			S("Turnip", 1),
			S("Onion", 2),
			S("Flax", 2),
			S("Barley", 2),
			S("MushroomJotunPuffs", 4),
			S("MushroomMagecap", 4),
			S("VineberryCluster", 4),
			S("Flint", 1),
			S("DeerHide", 2),
			S("CopperOre", 3),
			S("TinOre", 3),
			S("Copper", 5),
			S("Tin", 5),
			S("Bronze", 12),
			S("BearHide", 6),
			S("BearPaw", 8),
			S("Ectoplasm", 5),
			S("GreydwarfEye", 1),
			S("SurtlingCore", 8),
			S("TrollHide", 4),
			S("Chitin", 5),
			S("SerpentScale", 8),
			S("IronScrap", 4),
			S("Iron", 7),
			S("Bloodbag", 3),
			S("Chain", 10),
			S("Entrails", 2),
			S("Guck", 3),
			S("IronOre", 4),
			S("Ooze", 3),
			S("Root", 5),
			S("SharpeningStone", 5),
			S("SilverOre", 5),
			S("Silver", 8),
			S("Obsidian", 4),
			S("Crystal", 5),
			S("Fenring_CultistClaw", 8),
			S("Fenring_CultistHair", 5),
			S("FreezeGland", 4),
			S("JuteRed", 4),
			S("WolfFang", 5),
			S("WolfPelt", 4),
			S("BlackMetalScrap", 5),
			S("BlackMetal", 9),
			S("BarleyFlour", 3),
			S("LinenThread", 4),
			S("LoxPelt", 5),
			S("Needle", 4),
			S("Tar", 5),
			S("VileRibcage", 8),
			S("CopperScrap", 4),
			S("BlackMarble", 3),
			S("Bilebag", 6),
			S("BlackCore", 22),
			S("BloodClot", 5),
			S("JuteBlue", 5),
			S("Carapace", 5),
			S("DvergrNeedle", 35),
			S("Mandible", 6),
			S("MechanicalSpring", 10),
			S("Eitr", 8),
			S("Sap", 4),
			S("ScaleHide", 5),
			S("Softtissue", 6),
			S("Wisp", 8),
			S("FlametalOreNew", 6),
			S("FlametalNew", 10),
			S("Grausten", 2),
			S("GemstoneRed", 15),
			S("GemstoneBlue", 15),
			S("GemstoneGreen", 15),
			S("AsksvinBladder", 5),
			S("AsksvinHide", 5),
			S("AsksvinNeck", 5),
			S("AsksvinPelvis", 5),
			S("AsksvinRibcage", 5),
			S("AsksvinSkull", 8),
			S("BonemawTooth", 8),
			S("CelestialFeather", 8),
			S("CeramicPlate", 6),
			S("CharcoalResin", 5),
			S("CharredBone", 4),
			S("CharredCogwheel", 6),
			S("CharredSkull", 8),
			S("MoltenCore", 18),
			S("MorgenHeart", 10),
			S("MorgenSinew", 8),
			S("Pot_Shard", 4),
			S("ProustitePowder", 8),
			S("BronzeScrap", 5),
			S("ShieldCore", 18),
			S("SulfurStone", 5),
			S("TrophyBoar", 20),
			S("TrophyDeer", 20),
			S("TrophyNeck", 20),
			S("TrophyGreydwarf", 25),
			S("TrophyGreydwarfBrute", 35),
			S("TrophyGreydwarfShaman", 35),
			S("TrophyFrostTroll", 80),
			S("TrophyDraugr", 45),
			S("TrophyDraugrElite", 70),
			S("TrophySurtling", 55),
			S("TrophyWolf", 65),
			S("TrophyFenring", 85),
			S("TrophyDeathsquito", 75),
			S("TrophyGoblin", 70),
			S("TrophyLox", 90),
			S("TrophySeeker", 90),
			S("TrophyGjall", 120),
			S("TrophySeekerBrute", 130),
			S("TrophyMorgen", 150),
			S("TrophyAsksvin", 120)
		};

		private void Awake()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			RegisterLocalizations();
			harmony = new Harmony("domen.valheim.traderbrothers");
			harmony.PatchAll();
			PrefabManager.OnVanillaPrefabsAvailable += RegisterPrefabs;
		}

		private void OnDestroy()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterPrefabs;
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		private static void RegisterLocalizations()
		{
			localization = LocalizationManager.Instance.GetLocalization();
			AddToken("$traderbrothers_scrapdealer", "Scrap Dealer", "Schrotthändler");
			AddToken("$traderbrothers_mineforeman", "Mine Foreman", "Minenvorarbeiter");
			AddToken("$traderbrothers_barkeeper", "Barkeeper", "Barkeeper");
			AddToken("$traderbrothers_scrapdealer_desc", "Buys junk for coins.", "Kauft nutzlosen Kram gegen Münzen.");
			AddToken("$traderbrothers_mineforeman_desc", "Sells known raw materials in supply packs.", "Verkauft bekannte Rohstoffe in Vorratspaketen.");
			AddToken("$traderbrothers_barkeeper_desc", "Sells known meads and potions.", "Verkauft bekannte Tränke und Met.");
			AddToken("$traderbrothers_trade", "Trade", "Handeln");
			AddToken("$traderbrothers_sell", "Sell", "Verkaufen");
			AddToken("$traderbrothers_buy_button", "Buy", "Kaufen");
			AddToken("$traderbrothers_not_enough", "Not enough", "Nicht genug");
			AddToken("$traderbrothers_coins", "coins", "Münzen");
			AddToken("$traderbrothers_shift_sell_stack", "Shift = sell stack", "Shift = Stack verkaufen");
			AddToken("$traderbrothers_talk_1", "Hmm.", "Hmm.");
			AddToken("$traderbrothers_talk_2", "What do you need?", "Was darf es sein?");
			AddToken("$traderbrothers_talk_3", "Good goods, fair price.", "Gute Ware, guter Preis.");
			AddToken("$traderbrothers_greet_1", "Come closer.", "Komm näher.");
			AddToken("$traderbrothers_greet_2", "Trade?", "Handel?");
			AddToken("$traderbrothers_bye_1", "Until next time.", "Bis bald.");
			AddToken("$traderbrothers_bye_2", "Bring coins.", "Bring Münzen mit.");
			AddToken("$traderbrothers_starttrade", "Take a look.", "Schau dich um.");
			AddToken("$traderbrothers_buy", "Good trade.", "Guter Handel.");
			AddToken("$traderbrothers_random_sell", "I can use that.", "Das kann ich brauchen.");
		}

		private static void AddToken(string token, string english, string german)
		{
			try
			{
				string text = token.TrimStart(new char[1] { '$' });
				CustomLocalization obj = localization;
				string text2 = "English";
				obj.AddTranslation(ref text2, ref text, english);
				CustomLocalization obj2 = localization;
				text2 = "German";
				obj2.AddTranslation(ref text2, ref text, german);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("Localization token failed: " + token + " - " + ex.Message));
				}
			}
		}

		private static string L(string token)
		{
			string text = token switch
			{
				"$traderbrothers_scrapdealer" => "Scrap Dealer", 
				"$traderbrothers_mineforeman" => "Mine Foreman", 
				"$traderbrothers_barkeeper" => "Barkeeper", 
				"$traderbrothers_scrapdealer_desc" => "Buys junk for coins.", 
				"$traderbrothers_mineforeman_desc" => "Sells known raw materials in supply packs.", 
				"$traderbrothers_barkeeper_desc" => "Sells known meads and potions.", 
				"$traderbrothers_sell" => "Sell", 
				"$traderbrothers_buy_button" => "Buy", 
				"$traderbrothers_not_enough" => "Not enough", 
				"$traderbrothers_coins" => "coins", 
				"$traderbrothers_shift_sell_stack" => "Shift = sell stack", 
				"$traderbrothers_trade" => "Trade", 
				_ => token, 
			};
			try
			{
				string text2 = ((localization != null) ? localization.TryTranslate(token) : token);
				return (string.IsNullOrEmpty(text2) || text2 == token) ? text : text2;
			}
			catch
			{
				return text;
			}
		}

		private static string LocalizeItemName(string itemName)
		{
			try
			{
				string text = ((localization != null) ? localization.TryTranslate(itemName) : itemName);
				return string.IsNullOrEmpty(text) ? itemName : text;
			}
			catch
			{
				return itemName;
			}
		}

		private void RegisterPrefabs()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			if (!registered)
			{
				RegisterTraderPiece("TraderBrothers_ScrapDealer", "Troll", "$traderbrothers_scrapdealer", "$traderbrothers_scrapdealer_desc", 0.33f, ScrapGreen, BuildScrapTrades);
				RegisterTraderPiece("TraderBrothers_MineForeman", "Dverger", "$traderbrothers_mineforeman", "$traderbrothers_mineforeman_desc", 1f, RogueGrey, BuildMineTrades);
				RegisterTraderPiece("TraderBrothers_Barkeeper", "gd_king", "$traderbrothers_barkeeper", "$traderbrothers_barkeeper_desc", 0.35f, WarmBark, BuildBarkeeperTrades);
				registered = true;
				PrefabManager.OnVanillaPrefabsAvailable -= RegisterPrefabs;
				Log.LogInfo((object)"TraderBrothers: traders registered.");
			}
		}

		private static void RegisterTraderPiece(string prefabName, string basePrefabName, string displayName, string description, float scale, Color tint, Action<Trader> fillTrades)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Expected O, but got Unknown
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Expected O, but got Unknown
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Expected O, but got Unknown
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Expected O, but got Unknown
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Expected O, but got Unknown
			GameObject val = PrefabManager.Instance.CreateClonedPrefab(prefabName, basePrefabName);
			if ((Object)(object)val == (Object)null)
			{
				Log.LogWarning((object)("Base prefab not found: " + basePrefabName));
				return;
			}
			((Object)val).name = prefabName;
			val.transform.localScale = Vector3.one * scale;
			Sprite icon = CreateIcon(tint);
			EffectList idleSound = CaptureIdleSound(val);
			RemoveMovement(val);
			EnsureStaticPiece(val, displayName, description, icon);
			TintRenderers(val, tint);
			if (prefabName == "TraderBrothers_Barkeeper")
			{
				RemoveElderAmbientEffects(val);
				EnsureIdleAnimation(val);
			}
			if (prefabName == "TraderBrothers_ScrapDealer")
			{
				EnsureIdleSound(val, idleSound, 8f, 0.45f);
			}
			Trader val2 = val.GetComponent<Trader>() ?? val.AddComponent<Trader>();
			val2.m_name = displayName;
			((Behaviour)val2).enabled = false;
			val2.m_standRange = 3.5f;
			val2.m_greetRange = 7f;
			val2.m_byeRange = 8f;
			val2.m_randomTalkInterval = 18f;
			val2.m_randomTalk = new List<string> { "$traderbrothers_talk_1", "$traderbrothers_talk_2", "$traderbrothers_talk_3" };
			val2.m_randomGreets = new List<string> { "$traderbrothers_greet_1", "$traderbrothers_greet_2" };
			val2.m_randomGoodbye = new List<string> { "$traderbrothers_bye_1", "$traderbrothers_bye_2" };
			val2.m_randomStartTrade = new List<string> { "$traderbrothers_starttrade" };
			val2.m_randomBuy = new List<string> { "$traderbrothers_buy" };
			val2.m_randomSell = new List<string> { "$traderbrothers_random_sell" };
			val2.m_items = new List<TradeItem>();
			val2.m_useItems = new List<TraderUseItem>();
			CopyVanillaTraderEffects(val2);
			TradeSpecs[prefabName] = new List<TradeSpec>();
			fillTrades(val2);
			EnsureInteractionTarget(val, val2, displayName);
			PieceManager instance = PieceManager.Instance;
			PieceConfig val3 = new PieceConfig();
			val3.Name = displayName;
			val3.Description = description;
			val3.PieceTable = "Hammer";
			val3.Category = "Misc";
			val3.Icon = icon;
			val3.Requirements = (RequirementConfig[])(object)new RequirementConfig[3]
			{
				new RequirementConfig("FineWood", 10, 0, true),
				new RequirementConfig("Bronze", 5, 0, true),
				new RequirementConfig("Coins", 5, 0, true)
			};
			instance.AddPiece(new CustomPiece(val, false, val3));
		}

		private static EffectList CaptureIdleSound(GameObject prefab)
		{
			BaseAI componentInChildren = prefab.GetComponentInChildren<BaseAI>(true);
			if ((Object)(object)componentInChildren == (Object)null || componentInChildren.m_idleSound == null || !componentInChildren.m_idleSound.HasEffects())
			{
				return null;
			}
			return componentInChildren.m_idleSound;
		}

		private static void EnsureStaticPiece(GameObject prefab, string displayName, string description, Sprite icon)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			(prefab.GetComponent<ZNetView>() ?? prefab.AddComponent<ZNetView>()).m_persistent = true;
			Piece obj = prefab.GetComponent<Piece>() ?? prefab.AddComponent<Piece>();
			obj.m_name = displayName;
			obj.m_description = description;
			obj.m_icon = icon;
			obj.m_enabled = true;
			obj.m_category = (PieceCategory)0;
			obj.m_canBeRemoved = true;
			obj.m_groundOnly = true;
			obj.m_clipGround = true;
			obj.m_canRotate = true;
			WearNTear obj2 = prefab.GetComponent<WearNTear>() ?? prefab.AddComponent<WearNTear>();
			obj2.m_health = 10000f;
			obj2.m_noRoofWear = true;
			obj2.m_noSupportWear = true;
			obj2.m_staticPosition = true;
			obj2.m_materialType = (MaterialType)1;
			obj2.m_ashDamageImmune = true;
			obj2.m_damages.m_blunt = (DamageModifier)3;
			obj2.m_damages.m_slash = (DamageModifier)3;
			obj2.m_damages.m_pierce = (DamageModifier)3;
			obj2.m_damages.m_chop = (DamageModifier)0;
			obj2.m_damages.m_pickaxe = (DamageModifier)0;
			obj2.m_damages.m_fire = (DamageModifier)3;
			obj2.m_damages.m_frost = (DamageModifier)3;
			obj2.m_damages.m_lightning = (DamageModifier)3;
			obj2.m_damages.m_poison = (DamageModifier)3;
			obj2.m_damages.m_spirit = (DamageModifier)3;
		}

		private static Sprite CreateIcon(Color color)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_000c: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
			Color val2 = Color.Lerp(Color.black, color, 0.35f);
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num = ((float)j - 32f) / 32f;
					float num2 = ((float)i - 32f) / 32f;
					float num3 = Mathf.Sqrt(num * num + num2 * num2);
					Color val3 = (Color)((num3 < 0.78f) ? Color.Lerp(color, Color.white, Mathf.Clamp01(0.25f - num2 * 0.2f)) : new Color(0f, 0f, 0f, 0f));
					if (num3 > 0.62f && num3 < 0.78f)
					{
						val3 = val2;
					}
					val.SetPixel(j, i, val3);
				}
			}
			val.Apply();
			Object.DontDestroyOnLoad((Object)(object)val);
			Sprite obj = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 100f);
			Object.DontDestroyOnLoad((Object)(object)obj);
			return obj;
		}

		private static void RemoveMovement(GameObject prefab)
		{
			DestroyComponentsByName(prefab, "CharacterDrop", "MonsterAI", "AnimalAI", "BaseAI", "Tameable", "Procreation", "Growup", "Humanoid", "Character", "CharacterAnimEvent", "NpcTalk", "FootStep", "LevelEffects", "Ragdoll", "SpawnArea", "CreatureSpawner", "EnvZone", "MusicLocation");
			MonoBehaviour[] componentsInChildren = prefab.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					string name = ((object)val).GetType().Name;
					if (name.EndsWith("AI", StringComparison.Ordinal) || name.IndexOf("Boss", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						DestroyImmediateSafe((Object)(object)val);
					}
				}
			}
			Rigidbody[] componentsInChildren2 = prefab.GetComponentsInChildren<Rigidbody>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
		}

		private static void TintRenderers(GameObject prefab, Color color)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Material[] materials = componentsInChildren[i].materials;
				foreach (Material val in materials)
				{
					if (!((Object)(object)val == (Object)null))
					{
						if (val.HasProperty("_Color"))
						{
							val.color = Color.Lerp(val.color, color, 0.55f);
						}
						if (val.HasProperty("_MainColor"))
						{
							val.SetColor("_MainColor", Color.Lerp(val.GetColor("_MainColor"), color, 0.55f));
						}
						if (val.HasProperty("_EmissionColor"))
						{
							val.EnableKeyword("_EMISSION");
							val.SetColor("_EmissionColor", color * 0.18f);
						}
					}
				}
			}
		}

		private static void DestroyComponentsByName(GameObject prefab, params string[] typeNames)
		{
			foreach (string text in typeNames)
			{
				MonoBehaviour[] componentsInChildren = prefab.GetComponentsInChildren<MonoBehaviour>(true);
				foreach (MonoBehaviour val in componentsInChildren)
				{
					if ((Object)(object)val != (Object)null && ((object)val).GetType().Name == text)
					{
						DestroyImmediateSafe((Object)(object)val);
					}
				}
			}
		}

		private static void RemoveElderAmbientEffects(GameObject prefab)
		{
			ParticleSystem[] componentsInChildren = prefab.GetComponentsInChildren<ParticleSystem>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			Light[] componentsInChildren2 = prefab.GetComponentsInChildren<Light>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
		}

		private static void EnsureIdleAnimation(GameObject prefab)
		{
			(prefab.GetComponent<TraderBrothersIdleAnimation>() ?? prefab.AddComponent<TraderBrothersIdleAnimation>()).Animator = prefab.GetComponentInChildren<Animator>(true);
		}

		private static void EnsureIdleSound(GameObject prefab, EffectList idleSound, float interval, float chance)
		{
			if (idleSound != null && idleSound.HasEffects())
			{
				TraderBrothersIdleSound obj = prefab.GetComponent<TraderBrothersIdleSound>() ?? prefab.AddComponent<TraderBrothersIdleSound>();
				obj.IdleSound = idleSound;
				obj.Interval = interval;
				obj.Chance = chance;
			}
		}

		private static void EnsureHeldPickaxe(GameObject prefab)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			Transform val = FindHand(prefab.transform);
			if ((Object)(object)val == (Object)null)
			{
				val = prefab.transform;
			}
			Transform val2 = val.Find("TraderBrothers_Pickaxe");
			if ((Object)(object)val2 != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)((Component)val2).gameObject);
			}
			GameObject obj = TryClonePickaxeVisual() ?? CreateSimplePickaxe();
			((Object)obj).name = "TraderBrothers_Pickaxe";
			obj.transform.SetParent(val, false);
			obj.transform.localPosition = new Vector3(0.05f, 0.02f, 0.08f);
			obj.transform.localRotation = Quaternion.Euler(78f, 12f, 92f);
			obj.transform.localScale = Vector3.one * 0.55f;
			StripToolGameplay(obj);
			TintRenderers(obj, new Color(0.65f, 0.08f, 0.06f, 1f));
		}

		private static Transform FindHand(Transform root)
		{
			string[] array = new string[11]
			{
				"RightHand", "Right hand", "Hand.R", "hand.r", "r_hand", "RightHand_Attach", "LeftHand", "Left hand", "Hand.L", "hand.l",
				"l_hand"
			};
			Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				string name = ((Object)val).name;
				string[] array2 = array;
				foreach (string value in array2)
				{
					if (name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return val;
					}
				}
			}
			componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			foreach (Transform val2 in componentsInChildren)
			{
				if (((Object)val2).name.IndexOf("hand", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return val2;
				}
			}
			return null;
		}

		private static GameObject TryClonePickaxeVisual()
		{
			string[] array = new string[4] { "PickaxeIron", "PickaxeBronze", "PickaxeAntler", "PickaxeStone" };
			foreach (string text in array)
			{
				ObjectDB instance = ObjectDB.instance;
				object obj = ((instance != null) ? instance.GetItemPrefab(text) : null);
				if (obj == null)
				{
					ZNetScene instance2 = ZNetScene.instance;
					obj = ((instance2 != null) ? instance2.GetPrefab(text) : null);
				}
				GameObject val = (GameObject)obj;
				if ((Object)(object)val != (Object)null)
				{
					return Object.Instantiate<GameObject>(val);
				}
			}
			return null;
		}

		private static GameObject CreateSimplePickaxe()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("TraderBrothers_Pickaxe");
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)2);
			((Object)obj).name = "Handle";
			obj.transform.SetParent(val.transform, false);
			obj.transform.localScale = new Vector3(0.035f, 0.55f, 0.035f);
			obj.transform.localRotation = Quaternion.Euler(0f, 0f, 0f);
			GameObject obj2 = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)obj2).name = "Head";
			obj2.transform.SetParent(val.transform, false);
			obj2.transform.localPosition = new Vector3(0f, 0.55f, 0f);
			obj2.transform.localScale = new Vector3(0.7f, 0.06f, 0.08f);
			GameObject obj3 = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)obj3).name = "Spike";
			obj3.transform.SetParent(val.transform, false);
			obj3.transform.localPosition = new Vector3(0.38f, 0.55f, 0f);
			obj3.transform.localRotation = Quaternion.Euler(0f, 0f, -20f);
			obj3.transform.localScale = new Vector3(0.26f, 0.04f, 0.055f);
			Collider[] componentsInChildren = val.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			return val;
		}

		private static void StripToolGameplay(GameObject obj)
		{
			Collider[] componentsInChildren = obj.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			Rigidbody[] componentsInChildren2 = obj.GetComponentsInChildren<Rigidbody>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			ZNetView[] componentsInChildren3 = obj.GetComponentsInChildren<ZNetView>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren3[i]);
			}
			ItemDrop[] componentsInChildren4 = obj.GetComponentsInChildren<ItemDrop>(true);
			for (int i = 0; i < componentsInChildren4.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren4[i]);
			}
			MonoBehaviour[] componentsInChildren5 = obj.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren5)
			{
				if ((Object)(object)val != (Object)null && ((object)val).GetType().Name != "TraderBrothersIdleAnimation" && ((object)val).GetType().Name != "TraderBrothersIdleSound")
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}

		private static void EnsureInteractionTarget(GameObject prefab, Trader trader, string displayName)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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_00bf: 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)
			AttachInteractable(prefab, trader, displayName);
			Collider[] componentsInChildren = prefab.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				AttachInteractable(((Component)componentsInChildren[i]).gameObject, trader, displayName);
			}
			Transform val = prefab.transform.Find("TraderBrothers_Interaction");
			if ((Object)(object)val != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
			}
			GameObject val2 = new GameObject("TraderBrothers_Interaction");
			val2.transform.SetParent(prefab.transform, false);
			float num = Mathf.Max(0.01f, prefab.transform.localScale.x);
			val2.transform.localPosition = new Vector3(0f, 1.2f / num, 0f);
			val2.transform.localScale = Vector3.one / num;
			int num2 = LayerMask.NameToLayer("character");
			if (num2 >= 0)
			{
				val2.layer = num2;
			}
			CapsuleCollider obj = val2.AddComponent<CapsuleCollider>();
			obj.radius = 0.9f;
			obj.height = 2.4f;
			obj.center = Vector3.zero;
			((Collider)obj).isTrigger = false;
			AttachInteractable(val2, trader, displayName);
		}

		private static void AttachInteractable(GameObject target, Trader trader, string displayName)
		{
			TraderBrothersInteractable obj = target.GetComponent<TraderBrothersInteractable>() ?? target.AddComponent<TraderBrothersInteractable>();
			obj.Trader = trader;
			obj.DisplayName = displayName;
		}

		private static void BuildScrapTrades(Trader trader)
		{
			TradeSpec[] scrapBuySpecs = ScrapBuySpecs;
			foreach (TradeSpec tradeSpec in scrapBuySpecs)
			{
				AddBuy(trader, tradeSpec.PrefabName, 1, tradeSpec.Price);
			}
		}

		private static void CopyVanillaTraderEffects(Trader trader)
		{
			ZNetScene instance = ZNetScene.instance;
			object obj = ((instance != null) ? instance.GetPrefab("Haldor") : null);
			if (obj == null)
			{
				ZNetScene instance2 = ZNetScene.instance;
				obj = ((instance2 != null) ? instance2.GetPrefab("Hildir") : null);
			}
			Trader val = ((obj != null) ? ((GameObject)obj).GetComponent<Trader>() : null);
			if (!((Object)(object)val == (Object)null))
			{
				trader.m_randomTalkFX = val.m_randomTalkFX;
				trader.m_randomGreetFX = val.m_randomGreetFX;
				trader.m_randomGoodbyeFX = val.m_randomGoodbyeFX;
				trader.m_randomStartTradeFX = val.m_randomStartTradeFX;
				trader.m_randomBuyFX = val.m_randomBuyFX;
				trader.m_randomSellFX = val.m_randomSellFX;
			}
		}

		private static void BuildMineTrades(Trader trader)
		{
			AddBuy(trader, "Wood", 50, 120);
			AddBuy(trader, "FineWood", 50, 180);
			AddBuy(trader, "RoundLog", 50, 180);
			AddBuy(trader, "ElderBark", 50, 240);
			AddBuy(trader, "YggdrasilWood", 50, 320);
			AddBuy(trader, "Blackwood", 50, 150);
			AddBuy(trader, "Stone", 50, 120);
			AddBuy(trader, "Coal", 50, 45);
			AddBuy(trader, "Resin", 50, 35);
			AddBuy(trader, "Feathers", 50, 45);
			AddBuy(trader, "CopperOre", 10, 160);
			AddBuy(trader, "TinOre", 10, 160);
			AddBuy(trader, "IronScrap", 10, 220);
			AddBuy(trader, "IronOre", 10, 220);
			AddBuy(trader, "SilverOre", 10, 260);
			AddBuy(trader, "BlackMetalScrap", 10, 300);
			AddBuy(trader, "CopperScrap", 10, 220);
			AddBuy(trader, "FlametalOreNew", 10, 360);
			AddBuy(trader, "BronzeScrap", 10, 260);
		}

		private static void BuildBarkeeperTrades(Trader trader)
		{
			AddBuy(trader, "BarleyWine", 1, 55);
			AddBuy(trader, "MeadFrostResist", 1, 55);
			AddBuy(trader, "MeadHealthMinor", 1, 35);
			AddBuy(trader, "MeadHealthMedium", 1, 50);
			AddBuy(trader, "MeadHealthMajor", 1, 80);
			AddBuy(trader, "MeadHealthLingering", 1, 100);
			AddBuy(trader, "MeadStaminaMinor", 1, 35);
			AddBuy(trader, "MeadStaminaMedium", 1, 50);
			AddBuy(trader, "MeadStaminaLingering", 1, 85);
			AddBuy(trader, "MeadEitrMinor", 1, 55);
			AddBuy(trader, "MeadEitrLingering", 1, 100);
			AddBuy(trader, "MeadPoisonResist", 1, 50);
			AddBuy(trader, "MeadTasty", 1, 25);
			AddBuy(trader, "MeadTrollPheromones", 1, 25);
			AddBuy(trader, "MeadBzerker", 1, 80);
			AddBuy(trader, "MeadBugRepellent", 1, 65);
			AddBuy(trader, "MeadSwimmer", 1, 30);
			AddBuy(trader, "MeadHasty", 1, 70);
			AddBuy(trader, "MeadStrength", 1, 60);
			AddBuy(trader, "MeadTamer", 1, 45);
			AddBuy(trader, "MeadLightfoot", 1, 70);
		}

		private static void AddSellPair(Trader trader, string prefabName, int unitPrice, int stack)
		{
			AddBuy(trader, prefabName, 1, unitPrice);
			AddStackSell(trader, prefabName, unitPrice);
		}

		private static TradeSpec S(string prefabName, int unitPrice)
		{
			return new TradeSpec(prefabName, 1, unitPrice);
		}

		private static void AddStackSell(Trader trader, string prefabName, int unitPrice)
		{
			string key = ((Object)((Component)trader).gameObject).name.Replace("(Clone)", string.Empty);
			if (!TradeSpecs.TryGetValue(key, out var value))
			{
				value = new List<TradeSpec>();
				TradeSpecs[key] = value;
			}
			value.Add(new TradeSpec(prefabName, -1, unitPrice));
		}

		private static void AddBuy(Trader trader, string prefabName, int stack, int price)
		{
			string key = ((Object)((Component)trader).gameObject).name.Replace("(Clone)", string.Empty);
			if (!TradeSpecs.TryGetValue(key, out var value))
			{
				value = new List<TradeSpec>();
				TradeSpecs[key] = value;
			}
			value.Add(new TradeSpec(prefabName, stack, price));
		}

		private static void EnsureTrades(Trader trader)
		{
			if ((Object)(object)trader == (Object)null || trader.m_items == null || trader.m_items.Count > 0)
			{
				return;
			}
			string key = ((Object)((Component)trader).gameObject).name.Replace("(Clone)", string.Empty);
			if (!TradeSpecs.TryGetValue(key, out var value))
			{
				return;
			}
			foreach (TradeSpec item in value)
			{
				AddTradeItem(trader, item.PrefabName, item.Stack, item.Price);
			}
		}

		private static void AddTradeItem(Trader trader, string prefabName, int stack, int price)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			ObjectDB instance = ObjectDB.instance;
			object obj = ((instance != null) ? instance.GetItemPrefab(prefabName) : null);
			if (obj == null)
			{
				ZNetScene instance2 = ZNetScene.instance;
				obj = ((instance2 != null) ? instance2.GetPrefab(prefabName) : null);
			}
			ItemDrop val = ((obj != null) ? ((GameObject)obj).GetComponent<ItemDrop>() : null);
			if ((Object)(object)val == (Object)null)
			{
				Log.LogWarning((object)("Item prefab not found: " + prefabName));
				return;
			}
			if (stack <= 0)
			{
				stack = Mathf.Max(1, val.m_itemData.m_shared.m_maxStackSize);
				price = Mathf.CeilToInt((float)(price * stack) * 1.1f);
			}
			trader.m_items.Add(new TradeItem
			{
				m_prefab = val,
				m_stack = stack,
				m_price = price,
				m_requiredGlobalKey = string.Empty
			});
		}

		private static bool IsScrapDealer(Trader trader)
		{
			if ((Object)(object)trader != (Object)null)
			{
				return ((Object)((Component)trader).gameObject).name.StartsWith("TraderBrothers_ScrapDealer", StringComparison.Ordinal);
			}
			return false;
		}

		private static bool IsKnownOnlyTrader(Trader trader)
		{
			if ((Object)(object)trader != (Object)null)
			{
				if (!((Object)((Component)trader).gameObject).name.StartsWith("TraderBrothers_MineForeman", StringComparison.Ordinal))
				{
					return ((Object)((Component)trader).gameObject).name.StartsWith("TraderBrothers_Barkeeper", StringComparison.Ordinal);
				}
				return true;
			}
			return false;
		}

		private static bool IsKnown(ItemDrop item)
		{
			Player localPlayer = Player.m_localPlayer;
			string text = item?.m_itemData.m_shared.m_name;
			if (!((Object)(object)localPlayer == (Object)null) && !string.IsNullOrEmpty(text))
			{
				return localPlayer.IsMaterialKnown(text);
			}
			return true;
		}

		private static bool TrySellScrap(StoreGui store)
		{
			Trader value = Traverse.Create((object)store).Field("m_trader").GetValue<Trader>();
			if (!IsScrapDealer(value))
			{
				return false;
			}
			TradeItem value2 = Traverse.Create((object)store).Field("m_selectedItem").GetValue<TradeItem>();
			ItemDrop sellItem = value2?.m_prefab;
			Player localPlayer = Player.m_localPlayer;
			Inventory val = ((localPlayer != null) ? ((Humanoid)localPlayer).GetInventory() : null);
			if ((Object)(object)sellItem == (Object)null || (Object)(object)localPlayer == (Object)null || val == null)
			{
				return true;
			}
			List<ItemData> list = (from item in val.GetAllItems()
				where item != null && IsSameItem(item, sellItem)
				select item).ToList();
			int num = list.Sum((ItemData item) => item.m_stack);
			bool flag = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
			int num2 = Mathf.Max(1, sellItem.m_itemData.m_shared.m_maxStackSize);
			int num3 = ((!flag) ? 1 : Mathf.Min(num, num2));
			if (num < num3)
			{
				((Character)localPlayer).Message((MessageType)2, L("$traderbrothers_not_enough") + " " + LocalizeItemName(sellItem.m_itemData.m_shared.m_name), 0, sellItem.m_itemData.GetIcon());
				return true;
			}
			int num4 = num3;
			foreach (ItemData item in list)
			{
				int num5 = Mathf.Min(item.m_stack, num4);
				val.RemoveItem(item, num5);
				num4 -= num5;
				if (num4 <= 0)
				{
					break;
				}
			}
			int num6 = (flag ? Mathf.CeilToInt((float)(value2.m_price * num3) * 1.1f) : value2.m_price);
			ObjectDB instance = ObjectDB.instance;
			object obj = ((instance != null) ? instance.GetItemPrefab("Coins") : null);
			if (obj == null)
			{
				ZNetScene instance2 = ZNetScene.instance;
				obj = ((instance2 != null) ? instance2.GetPrefab("Coins") : null);
			}
			GameObject val2 = (GameObject)obj;
			if ((Object)(object)val2 != (Object)null)
			{
				val.AddItem(val2, num6);
			}
			((Character)localPlayer).Message((MessageType)2, "+" + num6 + " " + L("$traderbrothers_coins"), 0, sellItem.m_itemData.GetIcon());
			RefreshScrapStore(store, value);
			TryTraderSold(value);
			return true;
		}

		private static void TryTraderSold(Trader trader)
		{
			try
			{
				if (trader != null)
				{
					trader.OnSold();
				}
			}
			catch (Exception ex)
			{
				Log.LogDebug((object)("Scrap Dealer OnSold skipped: " + ex.Message));
			}
		}

		private static void RefreshScrapStore(StoreGui store, Trader trader)
		{
			if ((Object)(object)store == (Object)null || (Object)(object)trader == (Object)null)
			{
				return;
			}
			try
			{
				((MonoBehaviour)store).StartCoroutine(RefreshScrapStoreNextFrame(store, trader));
			}
			catch (Exception ex)
			{
				Log.LogDebug((object)("Scrap Dealer UI refresh skipped: " + ex.Message));
			}
		}

		private static IEnumerator RefreshScrapStoreNextFrame(StoreGui store, Trader trader)
		{
			yield return null;
			if (!((Object)(object)store == (Object)null) && !((Object)(object)trader == (Object)null) && TryHideStore(store))
			{
				yield return null;
				store.Show(trader);
				yield return null;
				ResetScrapScrollTop(store);
				TryFinalizeScrapStoreRefresh(store);
			}
		}

		private static bool TryHideStore(StoreGui store)
		{
			try
			{
				Traverse.Create((object)store).Method("Hide", Array.Empty<object>()).GetValue();
				return true;
			}
			catch (Exception ex)
			{
				Log.LogDebug((object)("Scrap Dealer UI hide before refresh skipped: " + ex.Message));
				return false;
			}
		}

		private static void TryFinalizeScrapStoreRefresh(StoreGui store)
		{
			try
			{
				Traverse.Create((object)store).Method("UpdateBuyButton", Array.Empty<object>()).GetValue();
				EnsureTraderHint(store);
				ResetScrapScrollTop(store);
			}
			catch (Exception ex)
			{
				Log.LogDebug((object)("Scrap Dealer UI refresh after sale skipped: " + ex.Message));
			}
		}

		private static void ResetScrapScrollTop(StoreGui store)
		{
			if ((Object)(object)store == (Object)null)
			{
				return;
			}
			ScrollRect[] componentsInChildren = ((Component)store).GetComponentsInChildren<ScrollRect>(true);
			foreach (ScrollRect val in componentsInChildren)
			{
				val.verticalNormalizedPosition = 1f;
				if ((Object)(object)val.verticalScrollbar != (Object)null)
				{
					val.verticalScrollbar.value = 1f;
				}
			}
		}

		private static bool IsSameItem(ItemData item, ItemDrop prefab)
		{
			if ((Object)(object)item.m_dropPrefab != (Object)null && ((Object)item.m_dropPrefab).name == ((Object)((Component)prefab).gameObject).name)
			{
				return true;
			}
			if (item.m_shared != null && prefab.m_itemData.m_shared != null)
			{
				return item.m_shared.m_name == prefab.m_itemData.m_shared.m_name;
			}
			return false;
		}

		private static int PlayerItemCount(ItemDrop itemPrefab)
		{
			Player localPlayer = Player.m_localPlayer;
			Inventory val = ((localPlayer != null) ? ((Humanoid)localPlayer).GetInventory() : null);
			if (val == null || (Object)(object)itemPrefab == (Object)null)
			{
				return 0;
			}
			return (from item in val.GetAllItems()
				where item != null && IsSameItem(item, itemPrefab)
				select item).Sum((ItemData item) => item.m_stack);
		}

		private static void DestroyImmediateSafe(Object obj)
		{
			if (obj != (Object)null)
			{
				Object.DestroyImmediate(obj);
			}
		}

		private static void EnsureTraderHint(StoreGui store)
		{
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)store == (Object)null)
			{
				return;
			}
			bool flag = IsScrapDealer(Traverse.Create((object)store).Field("m_trader").GetValue<Trader>());
			Button value = Traverse.Create((object)store).Field("m_sellButton").GetValue<Button>();
			if ((Object)(object)value == (Object)null)
			{
				return;
			}
			Transform val = ((Component)value).transform.parent ?? ((Component)value).transform;
			Transform val2 = val.Find("TraderBrothers_ShiftHint");
			TMP_Text val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<TMP_Text>() : null);
			if (!flag)
			{
				if ((Object)(object)val3 != (Object)null)
				{
					((Component)val3).gameObject.SetActive(false);
				}
				return;
			}
			if ((Object)(object)val3 == (Object)null)
			{
				TMP_Text val4 = ((Component)value).GetComponentInChildren<TMP_Text>(true) ?? Traverse.Create((object)store).Field("m_coinText").GetValue<TMP_Text>();
				if ((Object)(object)val4 == (Object)null)
				{
					return;
				}
				val3 = Object.Instantiate<TMP_Text>(val4, val, false);
				((Object)val3).name = "TraderBrothers_ShiftHint";
				((Graphic)val3).raycastTarget = false;
				val3.fontSize = Mathf.Max(12f, val4.fontSize * 0.45f);
				val3.alignment = (TextAlignmentOptions)514;
				((Graphic)val3).color = new Color(1f, 0.86f, 0.33f, 1f);
				RectTransform component = ((Component)val3).GetComponent<RectTransform>();
				RectTransform component2 = ((Component)value).GetComponent<RectTransform>();
				if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null)
				{
					component.anchorMin = component2.anchorMin;
					component.anchorMax = component2.anchorMax;
					component.pivot = component2.pivot;
					component.anchoredPosition = component2.anchoredPosition + new Vector2(0f, -66f);
					component.sizeDelta = new Vector2(Mathf.Max(190f, component2.sizeDelta.x + 80f), 32f);
					((Transform)component).localScale = Vector3.one;
				}
			}
			val3.text = L("$traderbrothers_shift_sell_stack");
			((Component)val3).gameObject.SetActive(true);
		}

		private static void SetAvailabilityVisual(GameObject row, bool available, int playerCount)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)row == (Object)null)
			{
				return;
			}
			CanvasGroup obj = row.GetComponent<CanvasGroup>() ?? row.AddComponent<CanvasGroup>();
			obj.alpha = (available ? 1f : 0.38f);
			obj.interactable = true;
			obj.blocksRaycasts = true;
			Graphic[] componentsInChildren = row.GetComponentsInChildren<Graphic>(true);
			foreach (Graphic obj2 in componentsInChildren)
			{
				Color color = obj2.color;
				color.a = (available ? 1f : Mathf.Min(color.a, 0.55f));
				obj2.color = color;
			}
			TMP_Text val = FindItemLabel(row);
			if ((Object)(object)val != (Object)null)
			{
				string text = val.text ?? string.Empty;
				int num = text.LastIndexOf("  x", StringComparison.Ordinal);
				if (num >= 0)
				{
					text = text.Substring(0, num);
				}
				val.text = text + "  x" + playerCount;
			}
		}

		private static TMP_Text FindItemLabel(GameObject row)
		{
			TMP_Text result = null;
			int num = int.MinValue;
			TMP_Text[] componentsInChildren = row.GetComponentsInChildren<TMP_Text>(true);
			foreach (TMP_Text val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !string.IsNullOrWhiteSpace(val.text))
				{
					string text = val.text.Trim();
					int num2 = text.Length;
					if (int.TryParse(text, out var _))
					{
						num2 -= 100;
					}
					if (text.IndexOf("coin", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("münz", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						num2 -= 50;
					}
					if (num2 > num)
					{
						result = val;
						num = num2;
					}
				}
			}
			return result;
		}
	}
}