Decompiled source of DeathAndTaxes v1.0.3

plugins/DeathAndTaxes.dll

Decompiled 2 weeks ago
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.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("SirCookie")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ddfaeaf10c98b2ec8d6e1896fa6174c50c2348a9")]
[assembly: AssemblyProduct("DeathAndTaxes")]
[assembly: AssemblyTitle("DeathAndTaxes")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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 DeathAndTaxes
{
	public static class Compat
	{
		public const string ChestButlerGuid = "eksolutions.chestbutler";

		public const string ChestButlerBarName = "psort_bar";

		public const string ServersideQoLAutoStoreGuid = "ArgusMagnus.ServersideQoL.AutoStore";

		public static bool ChestButlerInstalled => Chainloader.PluginInfos.ContainsKey("eksolutions.chestbutler");

		public static void PatchServersideQoL(Harmony harmony)
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			if (!Chainloader.PluginInfos.ContainsKey("ArgusMagnus.ServersideQoL.AutoStore"))
			{
				return;
			}
			try
			{
				Type type = AccessTools.TypeByName("ServersideQoL.Processors.ContainerRegistryProcessor");
				Type type2 = AccessTools.TypeByName("ServersideQoL.Processor");
				MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "GetStateCore", (Type[])null, (Type[])null) : null);
				MethodInfo methodInfo2 = ((type2 != null) ? AccessTools.Method(type2, "InitializePrefabInfoInternal", (Type[])null, (Type[])null) : null);
				if (methodInfo == null || methodInfo2 == null)
				{
					Logger.LogWarning((object)"[DeathAndTaxes] ServersideQoL found but not the expected code; AutoStore may store into tribute tables");
					return;
				}
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Compat), "NoAutoStoreIntoTables", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(Compat), "NoAutoSortOfTables", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Logger.LogInfo((object)"[DeathAndTaxes] ServersideQoL AutoStore: tribute tables excluded from auto pickup, stacking and sorting");
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("[DeathAndTaxes] Couldn't adjust ServersideQoL AutoStore: " + ex.Message));
			}
		}

		private static void NoAutoStoreIntoTables(Container container, object __result)
		{
			if (__result != null && Object.op_Implicit((Object)(object)container) && TributeDefinitions.ForPiece(((Object)((Component)container).gameObject).name) != null)
			{
				PropertyInfo propertyInfo = AccessTools.Property(__result.GetType(), "AutoStorePickupRange");
				if (propertyInfo != null && !object.Equals(propertyInfo.GetValue(__result), 0f))
				{
					propertyInfo.SetValue(__result, 0f);
				}
			}
		}

		private static bool NoAutoSortOfTables(object __instance, object prefabInfo, ref bool __result)
		{
			if (__instance == null || __instance.GetType().FullName != "ServersideQoL.AutoStore.ContainerProcessor")
			{
				return true;
			}
			string value = Traverse.Create(prefabInfo).Property("PrefabName", (object[])null).GetValue<string>();
			if (value == null || TributeDefinitions.ForPiece(value) == null)
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch]
	internal static class NewTrophies
	{
		public const string LordReto = "TrophyLordReto";

		private const string LordRetoCreature = "Charred_Melee_Dyrnwyn";

		private const string LordRetoBase = "TrophyCharredMelee";

		private static readonly Color LordRetoTint = new Color(1f, 0.55f, 0.15f);

		public static void Add()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_0031: 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)
			CustomItem val = new CustomItem("TrophyLordReto", "TrophyCharredMelee", new ItemConfig
			{
				Name = "Lord Reto trophy",
				Description = "The skull still burns with the pride of the one who held Dyrnwyn."
			});
			Tint(val.ItemPrefab, LordRetoTint);
			SharedData shared = val.ItemDrop.m_itemData.m_shared;
			if (shared.m_icons != null && shared.m_icons.Length != 0 && Object.op_Implicit((Object)(object)shared.m_icons[0]))
			{
				shared.m_icons = (Sprite[])(object)new Sprite[1] { TintSprite(shared.m_icons[0], LordRetoTint) };
			}
			ItemManager.Instance.AddItem(val);
		}

		[HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")]
		[HarmonyPostfix]
		private static void AddLordRetoDrop(CharacterDrop __instance, List<KeyValuePair<GameObject, int>> __result)
		{
			if (__result != null && ((Object)__instance).name.StartsWith("Charred_Melee_Dyrnwyn"))
			{
				GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab("TrophyLordReto") : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					__result.Add(new KeyValuePair<GameObject, int>(val, 1));
				}
			}
		}

		private static void Tint(GameObject prefab, Color tint)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				Material[] sharedMaterials = val.sharedMaterials;
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					if (Object.op_Implicit((Object)(object)sharedMaterials[j]))
					{
						Material val2 = new Material(sharedMaterials[j]);
						if (val2.HasProperty("_Color"))
						{
							val2.color *= tint;
						}
						if (val2.HasProperty("_EmissionColor"))
						{
							val2.SetColor("_EmissionColor", val2.GetColor("_EmissionColor") * tint);
						}
						sharedMaterials[j] = val2;
					}
				}
				val.sharedMaterials = sharedMaterials;
			}
		}

		private static Sprite TintSprite(Sprite source, Color tint)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			Rect textureRect = source.textureRect;
			int num = (int)((Rect)(ref textureRect)).width;
			int num2 = (int)((Rect)(ref textureRect)).height;
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)source.texture).width, ((Texture)source.texture).height, 0, (RenderTextureFormat)0);
			RenderTexture active = RenderTexture.active;
			Graphics.Blit((Texture)(object)source.texture, temporary);
			RenderTexture.active = temporary;
			Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false);
			val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)num, (float)num2), 0, 0);
			RenderTexture.active = active;
			RenderTexture.ReleaseTemporary(temporary);
			Color[] pixels = val.GetPixels();
			for (int i = 0; i < pixels.Length; i++)
			{
				pixels[i] = new Color(pixels[i].r * tint.r, pixels[i].g * tint.g, pixels[i].b * tint.b, pixels[i].a);
			}
			val.SetPixels(pixels);
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num2), new Vector2(0.5f, 0.5f), source.pixelsPerUnit);
		}
	}
	[HarmonyPatch]
	internal static class Patches
	{
		[HarmonyPatch(typeof(Player), "HaveRequirements", new Type[]
		{
			typeof(Piece),
			typeof(RequirementMode)
		})]
		[HarmonyPostfix]
		private static void HaveRequirements(Player __instance, Piece piece, RequirementMode mode, ref bool __result)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			if ((int)mode == 1 && Object.op_Implicit((Object)(object)piece))
			{
				TributeDefinition tributeDefinition = TributeDefinitions.ForPiece(((Object)piece).name);
				if (tributeDefinition != null)
				{
					__result = HasItem(__instance, tributeDefinition.BossTrophy);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "OnInventoryChanged")]
		[HarmonyPostfix]
		private static void RecheckRecipes(Player __instance)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !__instance.m_isLoading && TributeDefinitions.All.Any((TributeDefinition d) => !__instance.m_knownRecipes.Contains(d.DisplayName) && HasItem(__instance, d.BossTrophy)))
			{
				__instance.UpdateKnownRecipesList();
			}
		}

		private static bool HasItem(Player player, string prefab)
		{
			return ((Humanoid)player).GetInventory().GetAllItems().Any((ItemData i) => Object.op_Implicit((Object)(object)i.m_dropPrefab) && ((Object)i.m_dropPrefab).name == prefab);
		}

		[HarmonyPatch(typeof(Game), "Start")]
		[HarmonyPostfix]
		private static void RegisterRpcs()
		{
			TableLimit.Register();
		}

		[HarmonyPatch(typeof(Player), "TryPlacePiece")]
		[HarmonyPrefix]
		private static bool LimitTables(Player __instance, Piece piece, ref bool __result)
		{
			if (TableLimit.AllowPlacing(__instance, piece))
			{
				return true;
			}
			__result = false;
			return false;
		}

		[HarmonyPatch(typeof(Player), "TryPlacePiece")]
		[HarmonyPostfix]
		private static void CountPlacedTable(Piece piece, bool __result)
		{
			if (__result)
			{
				TableLimit.OnPlaced(piece);
			}
		}

		[HarmonyPatch(typeof(Player), "SetupPlacementGhost")]
		[HarmonyPostfix]
		private static void FacePlayerWhenBuilding(Player __instance)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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)
			GameObject placementGhost = __instance.m_placementGhost;
			if (Object.op_Implicit((Object)(object)placementGhost) && Object.op_Implicit((Object)(object)placementGhost.GetComponent<TributeTable>()))
			{
				TableLimit.Request();
				Vector3 val = Vector3.ProjectOnPlane((Object.op_Implicit((Object)(object)GameCamera.instance) ? ((Component)GameCamera.instance).transform : ((Component)__instance).transform).forward, Vector3.up);
				if (!(((Vector3)(ref val)).sqrMagnitude < 0.0001f))
				{
					Quaternion val2 = Quaternion.LookRotation(val);
					float y = ((Quaternion)(ref val2)).eulerAngles.y;
					__instance.m_placeRotation = Mathf.RoundToInt(y / __instance.m_placeRotationDegrees);
				}
			}
		}

		[HarmonyPatch(typeof(Container), "GetHoverText")]
		[HarmonyPostfix]
		private static void GetHoverText(Container __instance, ref string __result)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			TributeTable component = ((Component)__instance).GetComponent<TributeTable>();
			if (Object.op_Implicit((Object)(object)component) && (!__instance.m_checkGuardStone || PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, false, false)))
			{
				__result = component.GetHoverText();
			}
		}

		[HarmonyPatch(typeof(Container), "StackAll")]
		[HarmonyPrefix]
		private static bool StackAll(Container __instance)
		{
			return !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<TributeTable>());
		}

		[HarmonyPatch(typeof(Container), "TakeAll")]
		[HarmonyPrefix]
		private static void TakeAll(Container __instance)
		{
			TributeTable component = ((Component)__instance).GetComponent<TributeTable>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.Enforce();
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "OnStackAll")]
		[HarmonyPrefix]
		private static bool OnStackAll(InventoryGui __instance)
		{
			Container currentContainer = __instance.m_currentContainer;
			TributeTable tributeTable = (Object.op_Implicit((Object)(object)currentContainer) ? ((Component)currentContainer).GetComponent<TributeTable>() : null);
			if (!Object.op_Implicit((Object)(object)tributeTable))
			{
				return true;
			}
			__instance.SetupDragItem((ItemData)null, (Inventory)null, 1);
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				tributeTable.OfferAll((Humanoid)(object)Player.m_localPlayer);
			}
			return false;
		}

		[HarmonyPatch(typeof(InventoryGui), "Show")]
		[HarmonyPostfix]
		private static void ShowInventory(InventoryGui __instance)
		{
			TributePanel.Ensure(__instance);
		}

		[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
		[HarmonyPrefix]
		private static bool OnSelectedItem(InventoryGui __instance, InventoryGrid grid, ItemData item, Modifier mod)
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Invalid comparison between Unknown and I4
			Container currentContainer = __instance.m_currentContainer;
			TributeTable tributeTable = (Object.op_Implicit((Object)(object)currentContainer) ? ((Component)currentContainer).GetComponent<TributeTable>() : null);
			if (!Object.op_Implicit((Object)(object)tributeTable))
			{
				return true;
			}
			Player localPlayer = Player.m_localPlayer;
			Inventory inventory = currentContainer.GetInventory();
			ItemData dragItem = __instance.m_dragItem;
			if ((Object)(object)grid == (Object)(object)__instance.m_containerGrid && dragItem != null)
			{
				if (__instance.m_dragInventory != inventory)
				{
					if (tributeTable.IsTrophy(dragItem))
					{
						tributeTable.Offer((Humanoid)(object)localPlayer, __instance.m_dragInventory, dragItem, __instance.m_dragAmount);
					}
					else
					{
						((Character)localPlayer).Message((MessageType)2, "Only trophies can be offered here", 0, (Sprite)null, false);
					}
				}
				__instance.SetupDragItem((ItemData)null, (Inventory)null, 1);
				return false;
			}
			if ((Object)(object)grid == (Object)(object)__instance.m_playerGrid && (int)mod == 2 && item != null)
			{
				if (tributeTable.IsTrophy(item))
				{
					tributeTable.Offer((Humanoid)(object)localPlayer, ((Humanoid)localPlayer).GetInventory(), item, item.m_stack);
				}
				else
				{
					((Character)localPlayer).Message((MessageType)2, "Only trophies can be offered here", 0, (Sprite)null, false);
				}
				return false;
			}
			if ((Object)(object)grid == (Object)(object)__instance.m_playerGrid && dragItem != null && __instance.m_dragInventory == inventory && item != null && item.m_shared.m_name != dragItem.m_shared.m_name)
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool AddItem(Inventory __instance, ref bool __result)
		{
			return Allow(__instance, ref __result);
		}

		[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
		{
			typeof(ItemData),
			typeof(Vector2i)
		})]
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool AddItemAt(Inventory __instance, ref bool __result)
		{
			return Allow(__instance, ref __result);
		}

		[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
		{
			typeof(ItemData),
			typeof(int),
			typeof(int),
			typeof(int),
			typeof(bool)
		})]
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool AddItemAmountAt(Inventory __instance, ref bool __result)
		{
			return Allow(__instance, ref __result);
		}

		private static bool Allow(Inventory inventory, ref bool result)
		{
			if (TributeTable.AllowsAdd(inventory))
			{
				return true;
			}
			result = false;
			return false;
		}
	}
	[BepInPlugin("SirCookie.DeathAndTaxes", "Death & Taxes", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "SirCookie.DeathAndTaxes";

		public const string PluginName = "Death & Taxes";

		public const string PluginVersion = "1.0.1";

		private Harmony m_harmony;

		private void Awake()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			MigrateOldConfig();
			Settings.Bind(((BaseUnityPlugin)this).Config);
			Settings.Changed += TributeTable.OnSettingsChanged;
			PrefabManager.OnVanillaPrefabsAvailable += AddPieces;
			m_harmony = new Harmony("SirCookie.DeathAndTaxes");
			m_harmony.PatchAll();
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new TrophyKitCommand());
			Logger.LogInfo((object)"Death & Taxes 1.0.1 loaded");
		}

		private static void RenderIcon(GameObject prefab)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			Piece piece = prefab.GetComponent<Piece>();
			RenderRequest val = new RenderRequest(prefab)
			{
				Rotation = Quaternion.Euler(14f, 0f, 0f) * Quaternion.Euler(0f, 205f, 0f),
				Width = 128,
				Height = 128
			};
			RenderManager.Instance.EnqueueRender(val, (Action<Sprite>)delegate(Sprite sprite)
			{
				if (Object.op_Implicit((Object)(object)sprite) && Object.op_Implicit((Object)(object)piece))
				{
					piece.m_icon = sprite;
				}
				else
				{
					Logger.LogWarning((object)("No build menu icon rendered for " + ((Object)prefab).name));
				}
			});
		}

		private void MigrateOldConfig()
		{
			string text = Path.Combine(Paths.ConfigPath, "SirCookie.LordOfBiomes.cfg");
			if (File.Exists(text) && ((BaseUnityPlugin)this).Config.Keys.Count <= 0 && !(File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath) ? File.ReadAllText(((BaseUnityPlugin)this).Config.ConfigFilePath) : "").Contains("["))
			{
				File.Copy(text, ((BaseUnityPlugin)this).Config.ConfigFilePath, overwrite: true);
				((BaseUnityPlugin)this).Config.Reload();
				Logger.LogInfo((object)"Settings taken over from SirCookie.LordOfBiomes.cfg");
			}
		}

		private void Start()
		{
			Compat.PatchServersideQoL(m_harmony);
		}

		private void Update()
		{
			Settings.ReloadIfChanged();
		}

		private void OnDestroy()
		{
			Settings.StopWatching();
		}

		private void AddPieces()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= AddPieces;
			NewTrophies.Add();
			TributeDefinition[] all = TributeDefinitions.All;
			for (int i = 0; i < all.Length; i++)
			{
				AddTribute(all[i]);
			}
		}

		private static void AddTribute(TributeDefinition def)
		{
			//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)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			PieceConfig val = new PieceConfig
			{
				Name = def.DisplayName,
				Description = def.Description,
				PieceTable = PieceTables.Hammer,
				Category = PieceCategories.Misc
			};
			val.AddRequirement(new RequirementConfig(def.BuildMaterial, def.BuildAmount, 0, true));
			foreach (string startTrophy in def.StartTrophies)
			{
				val.AddRequirement(new RequirementConfig(startTrophy, 1, 0, true));
			}
			CustomPiece val2 = new CustomPiece(def.PieceName, def.BaseTable, val);
			GameObject piecePrefab = val2.PiecePrefab;
			TributeModel.Build(piecePrefab, def);
			RenderIcon(piecePrefab);
			piecePrefab.GetComponent<Piece>().m_randomInitBuildRotation = false;
			Container val3 = piecePrefab.AddComponent<Container>();
			val3.m_name = def.TableName;
			val3.m_width = def.GridWidth;
			val3.m_height = def.GridHeight;
			val3.m_privacy = (PrivacySetting)2;
			val3.m_checkGuardStone = true;
			GameObject prefab = PrefabManager.Instance.GetPrefab("piece_chest_wood");
			Container val4 = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<Container>() : null);
			if (Object.op_Implicit((Object)(object)val4))
			{
				val3.m_bkg = val4.m_bkg;
				val3.m_openEffects = val4.m_openEffects;
				val3.m_closeEffects = val4.m_closeEffects;
			}
			piecePrefab.AddComponent<TributeTable>();
			PieceManager.Instance.AddPiece(val2);
		}
	}
	public enum Progression
	{
		Linear,
		Logarithmic
	}
	public static class Settings
	{
		public static ConfigEntry<float> BaseHoursPerStack;

		public static ConfigEntry<float> FinalHoursPerStack;

		public static ConfigEntry<Progression> ProgressionMode;

		public static ConfigEntry<bool> OverclockEnabled;

		public static ConfigEntry<int> MaxTablesPerPlayer;

		public static ConfigEntry<bool> OfferFromChests;

		public static ConfigEntry<float> ChestRange;

		public static ConfigEntry<bool> NoRoofAllowed;

		private static ConfigEntry<float> s_noRoofPenalty;

		private static ConfigEntry<int> s_overclockMultiplier;

		private const string ProductionSection = "01 - Production";

		private const string BuildingSection = "02 - Building";

		private const string OverclockSection = "03 - Overclock";

		private static readonly Dictionary<string, string> RenamedSections = new Dictionary<string, string>
		{
			{ "1 - Production", "01 - Production" },
			{ "2 - Overclock", "03 - Overclock" },
			{ "3 - Overclock", "03 - Overclock" },
			{ "3 - Meadows", "04 - Meadows" },
			{ "4 - Black Forest", "05 - Black Forest" },
			{ "5 - Building", "02 - Building" },
			{ "6 - Swamp", "06 - Swamp" },
			{ "7 - Mountains", "07 - Mountains" },
			{ "8 - Plains", "08 - Plains" },
			{ "9 - Mistlands", "09 - Mistlands" }
		};

		private static ConfigFile s_config;

		private static FileSystemWatcher s_watcher;

		private static long s_changedAtTicks;

		public static float StartHours => Mathf.Max(0.01f, BaseHoursPerStack.Value);

		public static float FinalHours => Mathf.Clamp(FinalHoursPerStack.Value, 0.01f, StartHours);

		public static int OverclockMultiplier => Mathf.Clamp(s_overclockMultiplier.Value, 2, 5);

		public static float NoRoofSpeed => Mathf.Pow(4f, Mathf.Clamp01(s_noRoofPenalty.Value) - 1f);

		public static event Action Changed;

		public static void Bind(ConfigFile config)
		{
			BaseHoursPerStack = config.Bind<float>("01 - Production", "Base hours per stack", 10f, Server("Hours a tribute table needs to fill one full stack of each resource, with only the trophies from its build cost."));
			FinalHoursPerStack = config.Bind<float>("01 - Production", "Final hours per stack", 1f, Server("Hours per full stack once the table holds the maximum number of trophies. Can't be slower than the base rate."));
			ProgressionMode = config.Bind<Progression>("01 - Production", "Progression", Progression.Logarithmic, Server("How the time per stack moves from the base to the final rate as trophies are added. Logarithmic: early trophies help most. Linear: every trophy takes off the same time."));
			NoRoofAllowed = config.Bind<bool>("01 - Production", "No roof allowed", false, Server("Let tables produce without a roof, at a lower speed (see No roof penalty). Off: a table needs a roof and its clock stops without one."));
			s_noRoofPenalty = config.Bind<float>("01 - Production", "No roof penalty", 0.5f, Server("Speed without a roof when that is allowed: 0 = four times slower, 0.5 = half speed, 1 = no penalty (speed = 4 ^ (value - 1)).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f)));
			OverclockEnabled = config.Bind<bool>("03 - Overclock", "Enable overclocking", true, Server("Show the 'Remind them!' button: spend a boss trophy to speed up a table for one hour."));
			s_overclockMultiplier = config.Bind<int>("03 - Overclock", "Overclock multiplier", 2, Server("Production speed while reminded (2 = twice as fast). Between 2 and 5.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 5)));
			TributeDefinition[] all = TributeDefinitions.All;
			foreach (TributeDefinition tributeDefinition in all)
			{
				tributeDefinition.ResourcesConfig = config.Bind<string>(tributeDefinition.ConfigSection, "Generated resources", string.Join(", ", tributeDefinition.AvailableResources), Server("Comma-separated list of what this table generates (the window keeps its own order). Only these can be used: " + string.Join(", ", tributeDefinition.AvailableResources) + ". Any other item name is ignored; this list can't add new resources."));
			}
			MaxTablesPerPlayer = config.Bind<int>("02 - Building", "Tables per player", 1, Server("How many tables of each type (Meadows, Black Forest, ...) one player may build. 0 = no limit. Tables that already exist keep working; only building new ones is refused.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100)));
			OfferFromChests = config.Bind<bool>("02 - Building", "Add trophies from nearby chests", true, Server("\"Add trophies\" (and clicking a trophy slot) also takes matching trophies from nearby chests the player may open, after the player's own inventory. Chests someone has open, tombstones and tribute tables are skipped."));
			ChestRange = config.Bind<float>("02 - Building", "Chest range", 20f, Server("How far (metres from the table) chests may be for \"Add trophies from nearby chests\".", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f)));
			MigrateOldSections(config);
			config.SettingChanged += delegate
			{
				Settings.Changed?.Invoke();
			};
			Watch(config);
		}

		private static void MigrateOldSections(ConfigFile config)
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			Dictionary<ConfigDefinition, string> value = Traverse.Create((object)config).Property("OrphanedEntries", (object[])null).GetValue<Dictionary<ConfigDefinition, string>>();
			if (value == null)
			{
				return;
			}
			List<ConfigDefinition> list = value.Keys.Where((ConfigDefinition k) => k.Section == "2 - Meadows" || RenamedSections.ContainsKey(k.Section)).ToList();
			if (list.Count == 0)
			{
				return;
			}
			string text = (File.Exists(config.ConfigFilePath) ? File.ReadAllText(config.ConfigFilePath) : "");
			foreach (ConfigDefinition item in list)
			{
				if (RenamedSections.TryGetValue(item.Section, out var value2) && !text.Contains("[" + value2 + "]"))
				{
					ConfigDefinition val = new ConfigDefinition(value2, item.Key);
					if (config.ContainsKey(val))
					{
						config[val].SetSerializedValue(value[item]);
					}
				}
				value.Remove(item);
			}
			config.Save();
			Debug.Log((object)"[DeathAndTaxes] Moved the settings to the renamed sections");
		}

		private static ConfigDescription Server(string description, AcceptableValueBase range = null)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			return new ConfigDescription("[Server] " + description + " On a server, the server's value is used for everyone.", range, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} });
		}

		private static void Watch(ConfigFile config)
		{
			s_config = config;
			try
			{
				s_watcher = new FileSystemWatcher(Path.GetDirectoryName(config.ConfigFilePath), Path.GetFileName(config.ConfigFilePath))
				{
					NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite)
				};
				FileSystemEventHandler value = delegate
				{
					s_changedAtTicks = DateTime.UtcNow.Ticks;
				};
				s_watcher.Changed += value;
				s_watcher.Created += value;
				s_watcher.Renamed += delegate
				{
					s_changedAtTicks = DateTime.UtcNow.Ticks;
				};
				s_watcher.EnableRaisingEvents = true;
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[DeathAndTaxes] Can't watch the config file, edits need a restart: " + ex.Message));
			}
		}

		public static void ReloadIfChanged()
		{
			long num = s_changedAtTicks;
			if (num == 0L || DateTime.UtcNow.Ticks - num < 10000000)
			{
				return;
			}
			s_changedAtTicks = 0L;
			if ((Object.op_Implicit((Object)(object)ZNet.instance) && !ZNet.instance.IsServer()) || !File.Exists(s_config.ConfigFilePath))
			{
				return;
			}
			try
			{
				s_config.Reload();
				Debug.Log((object)"[DeathAndTaxes] Settings reloaded from the config file");
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[DeathAndTaxes] Couldn't reload the config file: " + ex.Message));
			}
		}

		public static void StopWatching()
		{
			s_watcher?.Dispose();
			s_watcher = null;
		}
	}
	public static class TableLimit
	{
		private const string RpcRequest = "DeathAndTaxes_TableCountRequest";

		private const string RpcReply = "DeathAndTaxes_TableCountReply";

		private const float RequestCooldown = 2f;

		private static ZRoutedRpc s_rpc;

		private static readonly Dictionary<string, int> s_counts = new Dictionary<string, int>();

		private static bool s_known;

		private static float s_requestedAt = -100f;

		public static void Register()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null && instance != s_rpc)
			{
				s_rpc = instance;
				s_counts.Clear();
				s_known = false;
				instance.Register<long>("DeathAndTaxes_TableCountRequest", (Action<long, long>)OnRequest);
				instance.Register<ZPackage>("DeathAndTaxes_TableCountReply", (Action<long, ZPackage>)OnReply);
			}
		}

		public static void Request(bool force = false)
		{
			Player localPlayer = Player.m_localPlayer;
			if (s_rpc != null && Object.op_Implicit((Object)(object)localPlayer) && Settings.MaxTablesPerPlayer.Value > 0 && (force || !(Time.time - s_requestedAt < 2f)))
			{
				s_requestedAt = Time.time;
				s_rpc.InvokeRoutedRPC(s_rpc.GetServerPeerID(), "DeathAndTaxes_TableCountRequest", new object[1] { localPlayer.GetPlayerID() });
			}
		}

		private static void OnRequest(long sender, long playerId)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer())
			{
				return;
			}
			ZPackage val = new ZPackage();
			val.Write(TributeDefinitions.All.Length);
			TributeDefinition[] all = TributeDefinitions.All;
			foreach (TributeDefinition tributeDefinition in all)
			{
				List<ZDO> list = new List<ZDO>();
				int num = 0;
				while (!ZDOMan.instance.GetAllZDOsWithPrefabIterative(tributeDefinition.PieceName, list, ref num))
				{
				}
				int num2 = 0;
				foreach (ZDO item in list)
				{
					if (item.GetLong(ZDOVars.s_creator, 0L) == playerId)
					{
						num2++;
					}
				}
				val.Write(tributeDefinition.PieceName);
				val.Write(num2);
			}
			s_rpc.InvokeRoutedRPC(sender, "DeathAndTaxes_TableCountReply", new object[1] { val });
		}

		private static void OnReply(long sender, ZPackage pkg)
		{
			int num = pkg.ReadInt();
			for (int i = 0; i < num; i++)
			{
				string key = pkg.ReadString();
				s_counts[key] = pkg.ReadInt();
			}
			s_known = true;
		}

		public static bool AllowPlacing(Player player, Piece piece)
		{
			int value = Settings.MaxTablesPerPlayer.Value;
			TributeDefinition tributeDefinition = (Object.op_Implicit((Object)(object)piece) ? TributeDefinitions.ForPiece(((Object)piece).name) : null);
			if (tributeDefinition == null || value <= 0)
			{
				return true;
			}
			if (!s_known)
			{
				Request(force: true);
				((Character)player).Message((MessageType)2, "Counting your tribute tables, try again in a moment", 0, (Sprite)null, false);
				return false;
			}
			s_counts.TryGetValue(tributeDefinition.PieceName, out var value2);
			if (value2 < value)
			{
				return true;
			}
			Request();
			((Character)player).Message((MessageType)2, string.Format("You can only have {0} {1} {2}", value, tributeDefinition.DisplayName, (value == 1) ? "table" : "tables"), 0, (Sprite)null, false);
			return false;
		}

		public static void OnPlaced(Piece piece)
		{
			TributeDefinition tributeDefinition = (Object.op_Implicit((Object)(object)piece) ? TributeDefinitions.ForPiece(((Object)piece).name) : null);
			if (tributeDefinition != null)
			{
				s_counts.TryGetValue(tributeDefinition.PieceName, out var value);
				s_counts[tributeDefinition.PieceName] = value + 1;
			}
		}
	}
	public class Offering
	{
		public string Prefab;

		public float U;

		public float V;

		public float Yaw;

		public float Tilt;

		public float MaxSize;

		public bool AlongWall;

		public float Lift;

		public Offering(string prefab, float u, float v, float yaw = 0f, float tilt = 0f, float maxSize = 1f, bool alongWall = false, float lift = 0f)
		{
			Prefab = prefab;
			U = u;
			V = v;
			Yaw = yaw;
			Tilt = tilt;
			MaxSize = maxSize;
			AlongWall = alongWall;
			Lift = lift;
		}
	}
	public class WallTrophy
	{
		public string Trophy;

		public int Row;

		public float Height;

		public float Size;

		public float Turn;

		public bool Center;

		public WallTrophy(string trophy, int row, float height, float size = 1f, float turn = 0f, bool center = false)
		{
			Trophy = trophy;
			Row = row;
			Height = height;
			Size = size;
			Turn = turn;
			Center = center;
		}
	}
	public enum Rarity
	{
		Common,
		Uncommon,
		Rare,
		Unique
	}
	public static class Rarities
	{
		private static readonly float[][] Weights = new float[4][]
		{
			new float[1] { 1f },
			new float[2] { 0.35f, 0.65f },
			new float[3] { 0.15f, 0.35f, 0.5f },
			new float[4] { 0.1f, 0.2f, 0.25f, 0.45f }
		};

		public static int MaxPerTrophy(Rarity rarity)
		{
			return rarity switch
			{
				Rarity.Common => 10, 
				Rarity.Uncommon => 5, 
				Rarity.Rare => 3, 
				_ => 1, 
			};
		}

		public static float Weight(Rarity resourceTier, Rarity trophyRarity)
		{
			float[] array = Weights[(int)resourceTier];
			if ((int)trophyRarity >= array.Length)
			{
				return 0f;
			}
			return array[(int)trophyRarity];
		}

		public static string Color(Rarity rarity)
		{
			return rarity switch
			{
				Rarity.Common => "#D8D8D8", 
				Rarity.Uncommon => "#6ED36E", 
				Rarity.Rare => "#5AA9FF", 
				_ => "#FFB84D", 
			};
		}
	}
	public class TributeTier
	{
		public Rarity Rarity;

		public string[] Trophies;

		public string[] Resources;

		public int UnlockAt;

		public int MaxPerTrophy => Rarities.MaxPerTrophy(Rarity);

		public int MaxTrophies => Trophies.Length * MaxPerTrophy;

		public int StartCount => (Rarity == Rarity.Common) ? 1 : 0;
	}
	public struct ResourceSlot
	{
		public string Resource;

		public int Tier;

		public int X;

		public int Y;
	}
	public class TributeDefinition
	{
		public string PieceName;

		public string DisplayName;

		public string TableName;

		public string Description;

		public string BossTrophy;

		public string BaseTable;

		public string BuildMaterial;

		public string LookFrom;

		public Color LookTint = Color.white;

		public float LookGray;

		public float LookWhite;

		public float TrophyScale;

		public bool AlignPlaques;

		public int BuildAmount;

		public float WallHeightAboveTable;

		public Vector2 Footprint;

		public TributeTier[] Tiers;

		public WallTrophy[] Wall;

		public string ConfigSection;

		public Offering[] Offerings;

		public string[] TooManyTrophies;

		public string[] Reminded;

		private string[] m_available;

		public ConfigEntry<string> ResourcesConfig;

		private string m_parsedResources;

		private string[] m_enabledResources;

		private ResourceSlot[] m_layout;

		private int m_gridWidth;

		public string[] AvailableResources => m_available ?? (m_available = Tiers.SelectMany((TributeTier t) => t.Resources).ToArray());

		public IEnumerable<string> AllTrophies => Tiers.SelectMany((TributeTier t) => t.Trophies);

		public IEnumerable<string> StartTrophies => Tiers.Where((TributeTier t) => t.StartCount > 0).SelectMany((TributeTier t) => t.Trophies);

		public float StartScore
		{
			get
			{
				TributeTier tributeTier = Tiers.FirstOrDefault((TributeTier t) => t.StartCount > 0);
				return Mathf.Clamp((tributeTier != null && tributeTier.MaxTrophies > 0) ? ((float)(tributeTier.Trophies.Length * tributeTier.StartCount) / (float)tributeTier.MaxTrophies) : 0.1f, 0.01f, 0.99f);
			}
		}

		public string[] EnabledResources
		{
			get
			{
				Parse();
				return m_enabledResources;
			}
		}

		public ResourceSlot[] Layout
		{
			get
			{
				Parse();
				return m_layout;
			}
		}

		public int GridWidth
		{
			get
			{
				Parse();
				return m_gridWidth;
			}
		}

		public int GridHeight => Tiers.Length;

		public int TierOfTrophy(string trophy)
		{
			return Array.FindIndex(Tiers, (TributeTier t) => t.Trophies.Contains(trophy));
		}

		public int RowOf(int tier)
		{
			return Tiers.Length - 1 - tier;
		}

		public float Score(int tier, Func<string, int> trophyCount)
		{
			Rarity rarity = Tiers[tier].Rarity;
			float num = 0f;
			TributeTier[] tiers = Tiers;
			foreach (TributeTier tributeTier in tiers)
			{
				float num2 = Rarities.Weight(rarity, tributeTier.Rarity);
				if (num2 > 0f && tributeTier.MaxTrophies > 0)
				{
					num += num2 * (float)tributeTier.Trophies.Sum(trophyCount) / (float)tributeTier.MaxTrophies;
				}
			}
			return Mathf.Clamp01(num);
		}

		public float HoursPerStack(float score)
		{
			float startHours = Settings.StartHours;
			float finalHours = Settings.FinalHours;
			float startScore = StartScore;
			float num = ((Settings.ProgressionMode.Value == Progression.Linear) ? ((score - startScore) / (1f - startScore)) : (Mathf.Log(Mathf.Max(score, startScore) / startScore) / Mathf.Log(1f / startScore)));
			return Mathf.Lerp(startHours, finalHours, Mathf.Clamp01(num));
		}

		private void Parse()
		{
			string text = ((ResourcesConfig != null) ? (ResourcesConfig.Value ?? "") : string.Join(",", AvailableResources));
			if (m_layout != null && text == m_parsedResources)
			{
				return;
			}
			List<string> list = new List<string>();
			string[] array = text.Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string text2 in array)
			{
				string name = text2.Trim();
				string text3 = AvailableResources.FirstOrDefault((string r) => string.Equals(r, name, StringComparison.OrdinalIgnoreCase));
				if (text3 == null)
				{
					if (name.Length > 0)
					{
						Debug.LogWarning((object)("[DeathAndTaxes] '" + name + "' can't be generated by " + TableName + ", ignored"));
					}
				}
				else if (!list.Contains(text3))
				{
					list.Add(text3);
				}
			}
			if (list.Count == 0)
			{
				list.AddRange(AvailableResources);
			}
			List<ResourceSlot> list2 = new List<ResourceSlot>();
			int num = 1;
			for (int num2 = 0; num2 < Tiers.Length; num2++)
			{
				int val = 0;
				array = Tiers[num2].Resources;
				foreach (string text4 in array)
				{
					if (list.Contains(text4))
					{
						list2.Add(new ResourceSlot
						{
							Resource = text4,
							Tier = num2,
							X = val++,
							Y = RowOf(num2)
						});
					}
				}
				num = Math.Max(num, val);
			}
			m_parsedResources = text;
			m_enabledResources = list.ToArray();
			m_gridWidth = num;
			m_layout = list2.ToArray();
		}
	}
	public static class TributeDefinitions
	{
		public static readonly TributeDefinition Meadows = new TributeDefinition
		{
			PieceName = "tribute_meadows",
			DisplayName = "Tribute - Meadows",
			TableName = "Tribute - Meadows",
			Description = "All fear you now, these wretches bring offerings to their new lord.",
			BossTrophy = "TrophyEikthyr",
			BaseTable = "piece_table",
			BuildMaterial = "Wood",
			BuildAmount = 10,
			WallHeightAboveTable = 1.4f,
			Tiers = new TributeTier[1]
			{
				new TributeTier
				{
					Rarity = Rarity.Common,
					Trophies = new string[3] { "TrophyBoar", "TrophyDeer", "TrophyNeck" },
					Resources = new string[7] { "Wood", "Mushroom", "Flint", "Dandelion", "Raspberry", "LeatherScraps", "Feathers" }
				}
			},
			Wall = new WallTrophy[3]
			{
				new WallTrophy("TrophyBoar", 0, 0.65f),
				new WallTrophy("TrophyDeer", 0, 0.8f),
				new WallTrophy("TrophyNeck", 0, 0.65f)
			},
			ConfigSection = "04 - Meadows",
			TooManyTrophies = new string[2] { "Should you go to the Black Forest?", "Having a power fantasy with black metal gear?" },
			Offerings = new Offering[22]
			{
				new Offering("Wood", 0.5f, 0.92f, 0f, 0f, 1.5f, alongWall: true),
				new Offering("Mushroom", 0.07f, 0.62f, 15f, 90f, 0.18f),
				new Offering("Mushroom", 0.16f, 0.52f, 105f, 90f, 0.18f),
				new Offering("Mushroom", 0.08f, 0.42f, 230f, 90f, 0.18f),
				new Offering("Raspberry", 0.07f, 0.18f, 40f, 0f, 0.1f),
				new Offering("Raspberry", 0.15f, 0.22f, 160f, 0f, 0.1f),
				new Offering("Raspberry", 0.11f, 0.13f, 250f, 0f, 0.1f),
				new Offering("Raspberry", 0.11f, 0.27f, 95f, 0f, 0.1f),
				new Offering("Raspberry", 0.04f, 0.25f, 300f, 0f, 0.1f),
				new Offering("Raspberry", 0.18f, 0.15f, 10f, 0f, 0.1f),
				new Offering("Raspberry", 0.11f, 0.2f, 200f, 0f, 0.1f, alongWall: false, 0.06f),
				new Offering("Raspberry", 0.08f, 0.23f, 130f, 0f, 0.1f, alongWall: false, 0.05f),
				new Offering("Flint", 0.4f, 0.55f, 10f, 0f, 0.45f),
				new Offering("Flint", 0.56f, 0.45f, 75f, 15f, 0.45f),
				new Offering("Flint", 0.47f, 0.28f, 150f, -10f, 0.45f),
				new Offering("Feathers", 0.7f, 0.62f, 40f, 0f, 0.3f),
				new Offering("Feathers", 0.75f, 0.47f, 150f, 0f, 0.28f),
				new Offering("LeatherScraps", 0.88f, 0.7f, 30f, 0f, 0.32f),
				new Offering("LeatherScraps", 0.94f, 0.55f, 110f, 0f, 0.28f),
				new Offering("Dandelion", 0.87f, 0.34f, 80f, 90f, 0.25f),
				new Offering("Dandelion", 0.8f, 0.27f, 20f, 90f, 0.25f),
				new Offering("Dandelion", 0.92f, 0.22f, 145f, 75f, 0.25f)
			}
		};

		public static readonly TributeDefinition BlackForest = new TributeDefinition
		{
			PieceName = "tribute_blackforest",
			DisplayName = "Tribute - Black Forest",
			TableName = "Tribute - Black Forest",
			Description = "The trees tremble at your passage. The forest sends tribute to its lord.",
			BossTrophy = "TrophyTheElder",
			BaseTable = "piece_table_oak",
			BuildMaterial = "RoundLog",
			BuildAmount = 10,
			Footprint = new Vector2(3f, 1.25f),
			WallHeightAboveTable = 2.5f,
			Tiers = new TributeTier[4]
			{
				new TributeTier
				{
					Rarity = Rarity.Common,
					Trophies = new string[3] { "TrophyGreydwarf", "TrophySkeleton", "TrophyFrostTroll" },
					Resources = new string[6] { "Resin", "Stone", "Blueberries", "Thistle", "BoneFragments", "GreydwarfEye" }
				},
				new TributeTier
				{
					Rarity = Rarity.Uncommon,
					Trophies = new string[3] { "TrophyGreydwarfBrute", "TrophyGreydwarfShaman", "TrophyBjorn" },
					Resources = new string[4] { "RoundLog", "Amber", "DeerHide", "MushroomYellow" },
					UnlockAt = 6
				},
				new TributeTier
				{
					Rarity = Rarity.Rare,
					Trophies = new string[2] { "TrophySkeletonPoison", "TrophyGhost" },
					Resources = new string[3] { "BjornHide", "TrollHide", "TinOre" },
					UnlockAt = 2
				},
				new TributeTier
				{
					Rarity = Rarity.Unique,
					Trophies = new string[1] { "TrophySkeletonHildir" },
					Resources = new string[1] { "CopperOre" },
					UnlockAt = 1
				}
			},
			Wall = new WallTrophy[9]
			{
				new WallTrophy("TrophyGreydwarf", 0, 0.455f, 1.5f),
				new WallTrophy("TrophySkeleton", 0, 0.455f, 2f),
				new WallTrophy("TrophyFrostTroll", 0, 0.455f),
				new WallTrophy("TrophyGreydwarfBrute", 1, 0.673f),
				new WallTrophy("TrophyGreydwarfShaman", 1, 0.673f),
				new WallTrophy("TrophyBjorn", 1, 0.673f),
				new WallTrophy("TrophySkeletonPoison", 2, 0.89f, 2f),
				new WallTrophy("TrophySkeletonHildir", 2, 0.915f, 3f),
				new WallTrophy("TrophyGhost", 2, 0.89f, 3f)
			},
			ConfigSection = "05 - Black Forest",
			TooManyTrophies = new string[7] { "No more victims in the forest!", "Do you think this is Pandora?", "How have you found even more?", "Consider dying in the swamp.", "Iron is much better than bronze.", "Is it not time to end this bronze age of yours?", "It isn't 2020 anymore, you are not halfway." },
			Offerings = new Offering[16]
			{
				new Offering("RoundLog", 0.5f, 0.92f, 0f, 0f, 1.2f, alongWall: true),
				new Offering("GreydwarfEye", 0.085f, 0.45f, 0f, 0f, 0.2f),
				new Offering("GreydwarfEye", 0.145f, 0.42f, 120f, 0f, 0.2f),
				new Offering("GreydwarfEye", 0.115f, 0.44f, 240f, 0f, 0.2f, alongWall: false, 0.12f),
				new Offering("Amber", 0.26f, 0.42f, 20f, 0f, 0.28f),
				new Offering("Amber", 0.34f, 0.42f, 140f, 0f, 0.28f),
				new Offering("Amber", 0.3f, 0.42f, 75f, 0f, 0.24f, alongWall: false, 0.12f),
				new Offering("Thistle", 0.47f, 0.45f, 70f, 90f, 0.7f),
				new Offering("Thistle", 0.53f, 0.28f, 155f, 90f, 0.7f),
				new Offering("MushroomYellow", 0.66f, 0.55f, 20f, 0f, 0.4f),
				new Offering("Blueberries", 0.7f, 0.28f, 0f, 0f, 0.2f),
				new Offering("Blueberries", 0.77f, 0.3f, 80f, 0f, 0.2f),
				new Offering("Blueberries", 0.73f, 0.13f, 160f, 0f, 0.2f),
				new Offering("Blueberries", 0.8f, 0.15f, 250f, 0f, 0.2f),
				new Offering("Stone", 0.89f, 0.7f, 30f, 0f, 0.64f),
				new Offering("Stone", 0.93f, 0.35f, 110f, 0f, 0.52f)
			}
		};

		public static readonly TributeDefinition Swamp = new TributeDefinition
		{
			PieceName = "tribute_swamp",
			DisplayName = "Tribute - Swamp",
			TableName = "Tribute - Swamp",
			Description = "The dead rise only to kneel. The mire gives up its treasures to its lord.",
			BossTrophy = "TrophyBonemass",
			BaseTable = "piece_table_oak",
			BuildMaterial = "ElderBark",
			BuildAmount = 10,
			LookGray = 0.75f,
			LookTint = new Color(1.15f, 1.15f, 1.15f),
			TrophyScale = 0.33f,
			AlignPlaques = true,
			Footprint = new Vector2(3f, 1.25f),
			WallHeightAboveTable = 3f,
			Tiers = new TributeTier[4]
			{
				new TributeTier
				{
					Rarity = Rarity.Common,
					Trophies = new string[3] { "TrophyDraugr", "TrophyLeech", "TrophySkeleton" },
					Resources = new string[4] { "ElderBark", "Entrails", "Bloodbag", "Coal" }
				},
				new TributeTier
				{
					Rarity = Rarity.Uncommon,
					Trophies = new string[3] { "TrophySurtling", "TrophyBlob", "TrophyWraith" },
					Resources = new string[3] { "Guck", "Ooze", "Chain" },
					UnlockAt = 6
				},
				new TributeTier
				{
					Rarity = Rarity.Rare,
					Trophies = new string[2] { "TrophyDraugrElite", "TrophyAbomination" },
					Resources = new string[3] { "Root", "SurtlingCore", "AmberPearl" },
					UnlockAt = 2
				},
				new TributeTier
				{
					Rarity = Rarity.Unique,
					Trophies = new string[1] { "TrophyKvastur" },
					Resources = new string[1] { "IronScrap" },
					UnlockAt = 1
				}
			},
			Wall = new WallTrophy[9]
			{
				new WallTrophy("TrophyDraugr", 0, 0.38f, 3.375f),
				new WallTrophy("TrophyLeech", 0, 0.38f, 1.5f),
				new WallTrophy("TrophySkeleton", 0, 0.38f, 2.36f),
				new WallTrophy("TrophySurtling", 1, 0.617f, 3.2f),
				new WallTrophy("TrophyBlob", 1, 0.617f, 4.5f),
				new WallTrophy("TrophyWraith", 1, 0.617f, 0.92f),
				new WallTrophy("TrophyDraugrElite", 2, 0.853f, 3.375f),
				new WallTrophy("TrophyKvastur", 2, 0.89f, 1.05f, 90f),
				new WallTrophy("TrophyAbomination", 2, 0.853f)
			},
			ConfigSection = "06 - Swamp",
			Offerings = new Offering[14]
			{
				new Offering("ElderBark", 0.5f, 0.92f, 0f, 0f, 1.2f, alongWall: true),
				new Offering("Bloodbag", 0.08f, 0.45f, 20f, 0f, 0.25f),
				new Offering("Bloodbag", 0.15f, 0.4f, 140f, 0f, 0.25f),
				new Offering("Bloodbag", 0.11f, 0.43f, 260f, 0f, 0.22f, alongWall: false, 0.12f),
				new Offering("Entrails", 0.26f, 0.5f, 60f, 0f, 0.35f),
				new Offering("Entrails", 0.3f, 0.25f, 200f, 0f, 0.32f),
				new Offering("Guck", 0.45f, 0.45f, 0f, 0f, 0.35f),
				new Offering("Ooze", 0.55f, 0.3f, 90f, 0f, 0.25f),
				new Offering("Ooze", 0.5f, 0.18f, 210f, 0f, 0.25f),
				new Offering("Chain", 0.68f, 0.45f, 30f, 90f, 0.5f),
				new Offering("AmberPearl", 0.72f, 0.18f, 0f, 0f, 0.12f),
				new Offering("IronScrap", 0.87f, 0.65f, 30f, 0f, 0.45f),
				new Offering("IronScrap", 0.92f, 0.4f, 120f, 0f, 0.4f),
				new Offering("SurtlingCore", 0.84f, 0.25f, 45f, 0f, 0.2f)
			}
		};

		public static readonly TributeDefinition Mountains = new TributeDefinition
		{
			PieceName = "tribute_mountains",
			DisplayName = "Tribute - Mountains",
			TableName = "Tribute - Mountains",
			Description = "Even the wolves lower their heads. The peaks send tribute to their lord.",
			BossTrophy = "TrophyDragonQueen",
			BaseTable = "piece_table_oak",
			BuildMaterial = "Stone",
			BuildAmount = 10,
			LookGray = 1f,
			LookWhite = 0.4f,
			LookTint = new Color(0.9f, 0.9f, 0.9f),
			TrophyScale = 0.41f,
			AlignPlaques = true,
			Footprint = new Vector2(3f, 1.25f),
			WallHeightAboveTable = 2.5f,
			Tiers = new TributeTier[4]
			{
				new TributeTier
				{
					Rarity = Rarity.Common,
					Trophies = new string[3] { "TrophyWolf", "TrophyFenring", "TrophyDraugr" },
					Resources = new string[5] { "Obsidian", "WolfPelt", "WolfFang", "WolfMeat", "WolfClaw" }
				},
				new TributeTier
				{
					Rarity = Rarity.Uncommon,
					Trophies = new string[3] { "TrophyUlv", "TrophyCultist", "TrophyHatchling" },
					Resources = new string[3] { "WolfHairBundle", "FreezeGland", "JuteRed" },
					UnlockAt = 6
				},
				new TributeTier
				{
					Rarity = Rarity.Rare,
					Trophies = new string[1] { "TrophySGolem" },
					Resources = new string[1] { "Crystal" },
					UnlockAt = 1
				},
				new TributeTier
				{
					Rarity = Rarity.Unique,
					Trophies = new string[1] { "TrophyCultist_Hildir" },
					Resources = new string[1] { "SilverOre" },
					UnlockAt = 1
				}
			},
			Wall = new WallTrophy[8]
			{
				new WallTrophy("TrophyWolf", 0, 0.455f, 2f),
				new WallTrophy("TrophyFenring", 0, 0.455f, 1f, 0f, center: true),
				new WallTrophy("TrophyDraugr", 0, 0.455f),
				new WallTrophy("TrophyUlv", 1, 0.69f),
				new WallTrophy("TrophyHatchling", 1, 0.69f, 2f),
				new WallTrophy("TrophyCultist", 1, 0.69f),
				new WallTrophy("TrophySGolem", 2, 0.89f),
				new WallTrophy("TrophyCultist_Hildir", 2, 0.915f)
			},
			ConfigSection = "07 - Mountains",
			Offerings = new Offering[10]
			{
				new Offering("WolfPelt", 0.5f, 0.9f, 0f, 0f, 1.2f, alongWall: true),
				new Offering("Obsidian", 0.08f, 0.5f, 20f, 0f, 0.35f),
				new Offering("Obsidian", 0.15f, 0.3f, 140f, 0f, 0.3f),
				new Offering("WolfFang", 0.27f, 0.45f, 60f, 90f, 0.25f),
				new Offering("WolfFang", 0.32f, 0.3f, 200f, 90f, 0.25f),
				new Offering("WolfMeat", 0.45f, 0.45f, 30f, 0f, 0.35f),
				new Offering("FreezeGland", 0.56f, 0.25f, 0f, 0f, 0.2f),
				new Offering("WolfClaw", 0.66f, 0.45f, 110f, 0f, 0.3f),
				new Offering("Crystal", 0.8f, 0.6f, 15f, 0f, 0.45f),
				new Offering("SilverOre", 0.9f, 0.3f, 70f, 0f, 0.4f)
			}
		};

		public static readonly TributeDefinition Plains = new TributeDefinition
		{
			PieceName = "tribute_plains",
			DisplayName = "Tribute - Plains",
			TableName = "Tribute - Plains",
			Description = "The fulings have learned whose land this is. The plains pay their tithe to their lord.",
			BossTrophy = "TrophyGoblinKing",
			BaseTable = "piece_table_oak",
			BuildMaterial = "FineWood",
			BuildAmount = 10,
			LookGray = 0.6f,
			LookWhite = 0.35f,
			LookTint = new Color(1f, 0.95f, 0.8f),
			AlignPlaques = true,
			Footprint = new Vector2(3f, 1.25f),
			WallHeightAboveTable = 3f,
			TrophyScale = 0.34f,
			Tiers = new TributeTier[4]
			{
				new TributeTier
				{
					Rarity = Rarity.Common,
					Trophies = new string[2] { "TrophyGoblin", "TrophyGrowth" },
					Resources = new string[4] { "Tar", "Cloudberry", "FineWood", "RottenMeat" }
				},
				new TributeTier
				{
					Rarity = Rarity.Uncommon,
					Trophies = new string[3] { "TrophyDeathsquito", "TrophyGoblinBrute", "TrophyGoblinShaman" },
					Resources = new string[4] { "Needle", "Flax", "Barley", "AmberPearl" },
					UnlockAt = 6
				},
				new TributeTier
				{
					Rarity = Rarity.Rare,
					Trophies = new string[2] { "TrophyLox", "TrophyBjornUndead" },
					Resources = new string[3] { "LoxPelt", "Ruby", "UndeadBjornRibcage" },
					UnlockAt = 2
				},
				new TributeTier
				{
					Rarity = Rarity.Unique,
					Trophies = new string[2] { "TrophyGoblinBruteBrosBrute", "TrophyGoblinBruteBrosShaman" },
					Resources = new string[1] { "BlackMetalScrap" },
					UnlockAt = 2
				}
			},
			Wall = new WallTrophy[9]
			{
				new WallTrophy("TrophyGoblin", 0, 0.38f, 3.5f),
				new WallTrophy("TrophyGrowth", 0, 0.38f, 3.5f),
				new WallTrophy("TrophyDeathsquito", 1, 0.617f, 3f),
				new WallTrophy("TrophyGoblinBrute", 1, 0.617f, 1.2f),
				new WallTrophy("TrophyGoblinShaman", 1, 0.617f, 2.7f),
				new WallTrophy("TrophyLox", 2, 0.853f),
				new WallTrophy("TrophyGoblinBruteBrosBrute", 2, 0.89f, 1.3f),
				new WallTrophy("TrophyGoblinBruteBrosShaman", 2, 0.89f, 3.8f),
				new WallTrophy("TrophyBjornUndead", 2, 0.853f, 1.5f)
			},
			ConfigSection = "08 - Plains",
			Offerings = new Offering[12]
			{
				new Offering("Flax", 0.5f, 0.9f, 0f, 0f, 1.2f, alongWall: true),
				new Offering("Cloudberry", 0.07f, 0.45f, 0f, 0f, 0.12f),
				new Offering("Cloudberry", 0.12f, 0.4f, 120f, 0f, 0.12f),
				new Offering("Cloudberry", 0.1f, 0.5f, 240f, 0f, 0.12f),
				new Offering("Barley", 0.24f, 0.45f, 70f, 90f, 0.6f),
				new Offering("Barley", 0.28f, 0.3f, 160f, 90f, 0.6f),
				new Offering("Tar", 0.43f, 0.4f, 0f, 0f, 0.3f),
				new Offering("Needle", 0.55f, 0.25f, 45f, 90f, 0.3f),
				new Offering("RottenMeat", 0.62f, 0.5f, 30f, 0f, 0.3f),
				new Offering("Ruby", 0.73f, 0.25f, 0f, 0f, 0.12f),
				new Offering("BlackMetalScrap", 0.85f, 0.6f, 30f, 0f, 0.45f),
				new Offering("BlackMetalScrap", 0.92f, 0.35f, 120f, 0f, 0.4f)
			}
		};

		public static readonly TributeDefinition Mistlands = new TributeDefinition
		{
			PieceName = "tribute_mistlands",
			DisplayName = "Tribute - Mistlands",
			TableName = "Tribute - Mistlands",
			Description = "Out of the mist they crawl, bearing gifts. The hive serves a new lord.",
			BossTrophy = "TrophySeekerQueen",
			BaseTable = "piece_table_oak",
			BuildMaterial = "YggdrasilWood",
			BuildAmount = 10,
			LookGray = 1f,
			LookWhite = 0.15f,
			LookTint = new Color(0.75f, 0.85f, 1f),
			AlignPlaques = true,
			Footprint = new Vector2(3f, 1.25f),
			WallHeightAboveTable = 3f,
			TrophyScale = 0.29f,
			Tiers = new TributeTier[3]
			{
				new TributeTier
				{
					Rarity = Rarity.Common,
					Trophies = new string[2] { "TrophyTick", "TrophySeeker" },
					Resources = new string[5] { "YggdrasilWood", "BlackMarble", "JuteBlue", "Carapace", "Mandible" }
				},
				new TributeTier
				{
					Rarity = Rarity.Uncommon,
					Trophies = new string[2] { "TrophySeekerBrute", "TrophyHare" },
					Resources = new string[5] { "RoyalJelly", "ScaleHide", "HareMeat", "BugMeat", "Bilebag" },
					UnlockAt = 6
				},
				new TributeTier
				{
					Rarity = Rarity.Rare,
					Trophies = new string[2] { "TrophyDvergr", "TrophyGjall" },
					Resources = new string[3] { "Softtissue", "Sap", "GiantBloodSack" },
					UnlockAt = 2
				}
			},
			Wall = new WallTrophy[6]
			{
				new WallTrophy("TrophyTick", 0, 0.38f, 3.9f),
				new WallTrophy("TrophySeeker", 0, 0.38f, 0.72f),
				new WallTrophy("TrophySeekerBrute", 1, 0.617f),
				new WallTrophy("TrophyHare", 1, 0.617f, 4.1f),
				new WallTrophy("TrophyDvergr", 2, 0.853f, 3.7f),
				new WallTrophy("TrophyGjall", 2, 0.853f, 0.8f)
			},
			ConfigSection = "09 - Mistlands",
			Offerings = new Offering[9]
			{
				new Offering("YggdrasilWood", 0.5f, 0.92f, 0f, 0f, 1.2f, alongWall: true),
				new Offering("Carapace", 0.1f, 0.45f, 20f, 0f, 0.4f),
				new Offering("Mandible", 0.22f, 0.3f, 120f, 0f, 0.3f),
				new Offering("RoyalJelly", 0.33f, 0.5f, 0f, 0f, 0.2f),
				new Offering("Sap", 0.45f, 0.35f, 60f, 0f, 0.25f),
				new Offering("JuteBlue", 0.57f, 0.5f, 30f, 90f, 0.4f),
				new Offering("Bilebag", 0.68f, 0.25f, 90f, 0f, 0.25f),
				new Offering("ScaleHide", 0.82f, 0.6f, 15f, 0f, 0.45f),
				new Offering("GiantBloodSack", 0.9f, 0.3f, 200f, 0f, 0.25f)
			}
		};

		public static readonly TributeDefinition Ashlands = new TributeDefinition
		{
			PieceName = "tribute_ashlands",
			DisplayName = "Tribute - Ashlands",
			TableName = "Tribute - Ashlands",
			Description = "From the ashes they bow. Even the burning dead pay tribute to their lord.",
			BossTrophy = "TrophyFader",
			BaseTable = "piece_table_oak",
			BuildMaterial = "Blackwood",
			BuildAmount = 10,
			LookGray = 1f,
			LookTint = new Color(0.35f, 0.33f, 0.33f),
			AlignPlaques = true,
			Footprint = new Vector2(3f, 1.25f),
			WallHeightAboveTable = 3f,
			TrophyScale = 0.35f,
			Tiers = new TributeTier[4]
			{
				new TributeTier
				{
					Rarity = Rarity.Common,
					Trophies = new string[3] { "TrophyCharredArcher", "TrophyCharredMage", "TrophyCharredMelee" },
					Resources = new string[8] { "Blackwood", "Grausten", "CharredBone", "Charredskull", "SulfurStone", "CharcoalResin", "Fiddleheadfern", "MushroomSmokePuff" }
				},
				new TributeTier
				{
					Rarity = Rarity.Uncommon,
					Trophies = new string[4] { "TrophyBlob_Lava", "TrophyFallenValkyrie", "TrophyAsksvin", "TrophyDvergr" },
					Resources = new string[5] { "ProustitePowder", "CelestialFeather", "MoltenCore", "MorgenSinew", "MorgenHeart" },
					UnlockAt = 6
				},
				new TributeTier
				{
					Rarity = Rarity.Rare,
					Trophies = new string[3] { "TrophyMorgen", "TrophyBonemawSerpent", "TrophyVolture" },
					Resources = new string[3] { "AskBladder", "AskHide", "BonemawSerpentTooth" },
					UnlockAt = 2
				},
				new TributeTier
				{
					Rarity = Rarity.Unique,
					Trophies = new string[1] { "TrophyLordReto" },
					Resources = new string[4] { "FlametalOreNew", "GemstoneBlue", "GemstoneGreen", "GemstoneRed" },
					UnlockAt = 1
				}
			},
			Wall = new WallTrophy[11]
			{
				new WallTrophy("TrophyCharredArcher", 0, 0.38f, 1.33f),
				new WallTrophy("TrophyCharredMage", 0, 0.38f, 1.56f),
				new WallTrophy("TrophyCharredMelee", 0, 0.38f, 3.4f),
				new WallTrophy("TrophyBlob_Lava", 1, 0.617f, 3.4f),
				new WallTrophy("TrophyFallenValkyrie", 1, 0.617f, 1.3f),
				new WallTrophy("TrophyAsksvin", 1, 0.617f, 2.2f),
				new WallTrophy("TrophyDvergr", 1, 0.617f),
				new WallTrophy("TrophyMorgen", 2, 0.853f, 1.8f),
				new WallTrophy("TrophyBonemawSerpent", 2, 0.853f, 0.43f),
				new WallTrophy("TrophyLordReto", 2, 0.89f, 3.6f),
				new WallTrophy("TrophyVolture", 2, 0.853f)
			},
			ConfigSection = "10 - Ashlands",
			Offerings = new Offering[12]
			{
				new Offering("Blackwood", 0.5f, 0.92f, 0f, 0f, 1.2f, alongWall: true),
				new Offering("Charredskull", 0.08f, 0.45f, 30f, 0f, 0.25f),
				new Offering("CharredBone", 0.18f, 0.3f, 120f, 90f, 0.35f),
				new Offering("SulfurStone", 0.3f, 0.5f, 0f, 0f, 0.3f),
				new Offering("MushroomSmokePuff", 0.4f, 0.28f, 60f, 0f, 0.2f),
				new Offering("MoltenCore", 0.52f, 0.45f, 0f, 0f, 0.25f),
				new Offering("CelestialFeather", 0.63f, 0.28f, 45f, 0f, 0.3f),
				new Offering("GemstoneRed", 0.72f, 0.5f, 0f, 0f, 0.15f),
				new Offering("GemstoneBlue", 0.76f, 0.4f, 60f, 0f, 0.15f),
				new Offering("GemstoneGreen", 0.7f, 0.35f, 120f, 0f, 0.15f),
				new Offering("FlametalOreNew", 0.88f, 0.55f, 30f, 0f, 0.45f),
				new Offering("Grausten", 0.92f, 0.25f, 110f, 0f, 0.35f)
			}
		};

		public static readonly TributeDefinition[] All = new TributeDefinition[7] { Meadows, BlackForest, Swamp, Mountains, Plains, Mistlands, Ashlands };

		public static TributeDefinition ForPiece(string pieceName)
		{
			TributeDefinition[] all = All;
			foreach (TributeDefinition tributeDefinition in all)
			{
				if (pieceName.StartsWith(tributeDefinition.PieceName))
				{
					return tributeDefinition;
				}
			}
			return null;
		}
	}
	public static class TributeModel
	{
		private const string WallPrefab = "woodwall";

		private const string StandPrefab = "itemstand";

		private const float TrophyFill = 0.85f;

		private const float TrophyMargin = 0.03f;

		private const float WallOverlap = 0.02f;

		private static readonly Dictionary<string, float> s_trophyScale = new Dictionary<string, float>();

		public const string DecorName = "lob_decor";

		public const string TrophyPrefix = "trophy_";

		private static readonly string[] PieceStateParts = new string[2] { "worn", "broken" };

		private static readonly string[] SkippedParts = new string[4] { "worn", "broken", "attach", "attachobj" };

		private static float PlaqueScale
		{
			get
			{
				TributeDefinition[] all = TributeDefinitions.All;
				foreach (TributeDefinition tributeDefinition in all)
				{
					if (!(tributeDefinition.TrophyScale > 0f) || tributeDefinition.Wall == null)
					{
						continue;
					}
					WallTrophy[] wall = tributeDefinition.Wall;
					foreach (WallTrophy wallTrophy in wall)
					{
						if (wallTrophy.Trophy == "TrophyHatchling")
						{
							return tributeDefinition.TrophyScale * wallTrophy.Size;
						}
					}
				}
				return 0.82f;
			}
		}

		public static void Build(GameObject prefab, TributeDefinition def)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_00ab: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: 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_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = prefab.transform;
			int layer = prefab.layer;
			if (def.Footprint != Vector2.zero)
			{
				FitTable(transform, def.Footprint);
			}
			Bounds b = SourceBounds(transform, SkippedParts);
			Transform val = NewChild(transform, "lob_decor", layer);
			if (((Bounds)(ref b)).size.z > ((Bounds)(ref b)).size.x)
			{
				val.localRotation = Quaternion.Euler(0f, 90f, 0f);
			}
			Bounds table = TransformBounds(b, Matrix4x4.Rotate(Quaternion.Inverse(val.localRotation)));
			float y = ((Bounds)(ref table)).max.y;
			float wallTop = y + def.WallHeightAboveTable;
			float num = BuildWall(val, table, wallTop, layer);
			BuildTrophies(val, def, table, num, wallTop, layer);
			BuildOfferings(val, def, table, num, layer);
			if (!string.IsNullOrEmpty(def.LookFrom))
			{
				ApplyLook(transform, val, def.LookFrom);
			}
			if (def.LookTint != Color.white || def.LookGray > 0f || def.LookWhite > 0f)
			{
				TintLook(transform, val, def.LookTint, def.LookGray, def.LookWhite);
			}
			Debug.Log((object)$"[DeathAndTaxes] Built {((Object)prefab).name} model: table {((Bounds)(ref table)).size} top {y:0.00}, wall front z {num:0.00}");
		}

		private static void FitTable(Transform root, Vector2 footprint)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			Bounds val = SourceBounds(root, SkippedParts);
			bool num = ((Bounds)(ref val)).size.z > ((Bounds)(ref val)).size.x;
			float num2 = (num ? ((Bounds)(ref val)).size.z : ((Bounds)(ref val)).size.x);
			float num3 = (num ? ((Bounds)(ref val)).size.x : ((Bounds)(ref val)).size.z);
			float num4 = footprint.x / num2;
			float num5 = footprint.y / num3;
			Vector3 val2 = (num ? new Vector3(num5, 1f, num4) : new Vector3(num4, 1f, num5));
			foreach (Transform item in ((IEnumerable)root).Cast<Transform>().ToList())
			{
				ScaleInParent(item, val2);
			}
			BoxCollider[] components = ((Component)root).GetComponents<BoxCollider>();
			foreach (BoxCollider obj in components)
			{
				obj.center = Vector3.Scale(obj.center, val2);
				obj.size = Vector3.Scale(obj.size, val2);
			}
			Collider[] components2 = ((Component)root).GetComponents<Collider>();
			foreach (Collider val3 in components2)
			{
				if (!(val3 is BoxCollider))
				{
					Debug.LogWarning((object)("[DeathAndTaxes] " + ((Object)root).name + ": " + ((object)val3).GetType().Name + " on the root isn't resized"));
				}
			}
			LODGroup[] componentsInChildren = ((Component)root).GetComponentsInChildren<LODGroup>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].RecalculateBounds();
			}
			Debug.Log((object)($"[DeathAndTaxes] {((Object)root).name}: base table {num2:0.00} x {num3:0.00} m scaled by {num4:0.00} x {num5:0.00} " + $"to {footprint.x:0.##} x {footprint.y:0.##} m"));
		}

		private static void ScaleInParent(Transform t, Vector3 scale)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			t.localPosition = Vector3.Scale(t.localPosition, scale);
			Quaternion r = t.localRotation;
			t.localScale = Vector3.Scale(t.localScale, new Vector3(Along(Vector3.right), Along(Vector3.up), Along(Vector3.forward)));
			float Along(Vector3 axis)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//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)
				Vector3 val = r * axis;
				Vector3 val2 = new Vector3(val.x * scale.x, val.y * scale.y, val.z * scale.z);
				return ((Vector3)(ref val2)).magnitude;
			}
		}

		private static float BuildWall(Transform decor, Bounds table, float wallTop, int layer)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_0024: 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_008d: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: 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_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: 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_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = PrefabManager.Instance.GetPrefab("woodwall");
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				Debug.LogWarning((object)"[DeathAndTaxes] Missing woodwall, no back wall");
				return ((Bounds)(ref table)).max.z;
			}
			Bounds b = SourceBounds(prefab.transform, SkippedParts);
			bool flag = ((Bounds)(ref b)).size.z > ((Bounds)(ref b)).size.x;
			Quaternion val = Quaternion.Euler(0f, flag ? 270f : 180f, 0f);
			float num = (flag ? ((Bounds)(ref b)).size.z : ((Bounds)(ref b)).size.x);
			float num2 = wallTop - ((Bounds)(ref table)).min.y;
			Vector3 val2 = (flag ? new Vector3(1f, num2 / ((Bounds)(ref b)).size.y, ((Bounds)(ref table)).size.x / num) : new Vector3(((Bounds)(ref table)).size.x / num, num2 / ((Bounds)(ref b)).size.y, 1f));
			Bounds val3 = TransformBounds(b, Matrix4x4.TRS(Vector3.zero, val, val2));
			Vector3 val4 = default(Vector3);
			((Vector3)(ref val4))..ctor(((Bounds)(ref table)).center.x - ((Bounds)(ref val3)).center.x, ((Bounds)(ref table)).min.y - ((Bounds)(ref val3)).min.y, ((Bounds)(ref table)).max.z - ((Bounds)(ref val3)).min.z - 0.02f);
			Transform val5 = NewChild(decor, "wall", layer);
			val5.localPosition = val4;
			val5.localRotation = val;
			val5.localScale = val2;
			CopyRenderers(prefab.transform, val5, SkippedParts, layer);
			BoxCollider obj = ((Component)NewChild(decor, "wall_collider", layer)).gameObject.AddComponent<BoxCollider>();
			obj.center = ((Bounds)(ref val3)).center + val4;
			obj.size = ((Bounds)(ref val3)).size;
			return ((Bounds)(ref val3)).min.z + val4.z;
		}

		private static void BuildTrophies(Transform decor, TributeDefinition def, Bounds table, float wallFront, float wallTop, int layer)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_00be: 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)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: 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_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_0471: Unknown result type (might be due to invalid IL or missing references)
			//IL_0490: Unknown result type (might be due to invalid IL or missing references)
			//IL_04dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0667: Unknown result type (might be due to invalid IL or missing references)
			//IL_066c: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0611: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_06cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0702: Unknown result type (might be due to invalid IL or missing references)
			//IL_0743: Unknown result type (might be due to invalid IL or missing references)
			//IL_074a: Unknown result type (might be due to invalid IL or missing references)
			//IL_074f: Unknown result type (might be due to invalid IL or missing references)
			//IL_071f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0760: Unknown result type (might be due to invalid IL or missing references)
			//IL_076e: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = PrefabManager.Instance.GetPrefab("itemstand");
			ItemStand val = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<ItemStand>() : null);
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.m_attachOther))
			{
				Debug.LogWarning((object)"[DeathAndTaxes] Missing itemstand, no trophies on the wall");
				return;
			}
			Bounds val2 = SourceBounds(((Component)val).transform, SkippedParts);
			Matrix4x4 m = Relative(((Component)val).transform, val.m_attachOther);
			Vector3 val3 = Vector4.op_Implicit(((Matrix4x4)(ref m)).GetColumn(3)) - ((Bounds)(ref val2)).center;
			Vector3 val4 = ((Mathf.Abs(val3.x) > Mathf.Abs(val3.z)) ? new Vector3(Mathf.Sign(val3.x), 0f, 0f) : new Vector3(0f, 0f, Mathf.Sign(val3.z)));
			Quaternion val5 = Quaternion.LookRotation(Vector3.back) * Quaternion.Inverse(Quaternion.LookRotation(val4));
			Bounds val6 = TransformBounds(val2, Matrix4x4.Rotate(val5));
			WallTrophy[] wall = def.Wall;
			int num = wall.Length;
			List<Transform> list = new List<Transform>();
			List<Bounds> list2 = new List<Bounds>();
			for (int i = 0; i < num; i++)
			{
				Transform val7 = NewChild(decor, "trophy_" + wall[i].Trophy, layer);
				Transform val8 = NewChild(val7, "stand", layer);
				val8.localRotation = Quaternion.Euler(0f, 0f, wall[i].Turn) * val5;
				CopyRenderers(((Component)val).transform, val8, SkippedParts, layer);
				GameObject prefab2 = PrefabManager.Instance.GetPrefab(wall[i].Trophy);
				GameObject val9 = (Object.op_Implicit((Object)(object)prefab2) ? ItemStand.GetAttachPrefab(prefab2) : null);
				if (Object.op_Implicit((Object)(object)val9))
				{
					Transform obj = NewChild(val8, "attach", layer);
					SetLocal(obj, m);
					ItemData itemData = prefab2.GetComponent<ItemDrop>().m_itemData;
					List<OrientationSettings> list3 = new List<OrientationSettings>();
					val.GetOrientationSettings(itemData, ref list3);
					OrientationSettings val10 = list3[0];
					Transform val11 = NewChild(obj, "trophy", layer);
					val11.localPosition = val9.transform.localPosition + val10.m_position;
					val11.localRotation = val9.transform.localRotation * Quaternion.Euler(val10.m_rotation);
					val11.localScale = Vector3.Scale(Vector3.Scale(val9.transform.localScale, itemData.GetScale(1f)), val10.m_scale);
					CopyRenderers(ItemStand.GetAttachGameObject(val9).transform, val11, new string[0], layer);
					if (wall[i].Center && val11.childCount > 0)
					{
						Bounds val12 = SourceBounds(val7, new string[1] { "attach" });
						Bounds val13 = TransformBounds(SourceBounds(val11, new string[0]), Relative(val7, val11));
						Vector3 val14 = ((Bounds)(ref val12)).center - ((Bounds)(ref val13)).center;
						val14.z = 0f;
						val11.localPosition += val11.parent.InverseTransformVector(val7.TransformVector(val14));
					}
					if (val11.childCount == 0)
					{
						Debug.LogWarning((object)("[DeathAndTaxes] " + wall[i].Trophy + ": nothing copied from its stand model:\n" + DescribeHierarchy(val9.transform)));
					}
				}
				else
				{
					Debug.LogWarning((object)("[DeathAndTaxes] No wall model for " + wall[i].Trophy));
				}
				list.Add(val7);
				list2.Add(SourceBounds(val7, new string[0]));
			}
			float y = ((Bounds)(ref table)).min.y;
			float[] array = new float[num];
			for (int j = 0; j < num; j++)
			{
				array[j] = Mathf.Lerp(y, wallTop, wall[j].Height);
			}
			float num2 = 1f;
			float[] array2 = new float[num];
			int k;
			for (k = 0; k < num; k++)
			{
				List<int> list4 = (from num9 in Enumerable.Range(0, num)
					where wall[num9].Row == wall[k].Row
					select num9).ToList();
				float num3 = ((Bounds)(ref table)).size.x / (float)list4.Count;
				array2[k] = ((Bounds)(ref table)).center.x + ((float)list4.IndexOf(k) - (float)(list4.Count - 1) / 2f) * num3;
				float num4 = wallTop - 0.03f - array[k];
				float num5 = array[k] - (((Bounds)(ref table)).max.y + 0.03f);
				foreach (int item in Enumerable.Range(0, num))
				{
					if (wall[item].Row == wall[k].Row + 1)
					{
						num4 = Mathf.Min(num4, (array[item] - array[k]) / 2f);
					}
					if (wall[item].Row == wall[k].Row - 1)
					{
						num5 = Mathf.Min(num5, (array[k] - array[item]) / 2f);
					}
				}
				Bounds val15 = list2[k];
				float num6 = Mathf.Min(wall[k].Size, 1f);
				num2 = Mathf.Min(new float[3]
				{
					num2,
					num3 * 0.85f / (((Bounds)(ref val15)).size.x * num6),
					2f * Mathf.Min(num4, num5) / (((Bounds)(ref val15)).size.y * num6)
				});
			}
			if (def.TrophyScale > 0f)
			{
				num2 = def.TrophyScale;
			}
			for (int num7 = 0; num7 < num; num7++)
			{
				Bounds val16 = list2[num7];
				float num8 = num2 * wall[num7].Size;
				if (s_trophyScale.TryGetValue(wall[num7].Trophy, out var value))
				{
					num8 = value;
				}
				else
				{
					s_trophyScale[wall[num7].Trophy] = num8;
				}
				list[num7].localScale = Vector3.one * num8;
				ResizePlaque(list[num7].Find("stand"), val2, num8);
				list[num7].localPosition = new Vector3(array2[num7] - ((Bounds)(ref val16)).center.x * num8, array[num7] - (def.AlignPlaques ? (Quaternion.Euler(0f, 0f, wall[num7].Turn) * ((Bounds)(ref val6)).center).y : ((Bounds)(ref val16)).center.y) * num8, wallFront - ((Bounds)(ref val6)).max.z * num8);
			}
			Debug.Log((object)($"[DeathAndTaxes] Trophy scale {num2:0.00} (wall top {wallTop:0.00} m, sizes " + string.Join(", ", list2.Select(delegate(Bounds b)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				Vector3 size = ((Bounds)(ref b)).size;
				return ((Vector3)(ref size)).ToString("0.00");
			})) + ")"));
		}

		private static void ResizePlaque(Transform standT, Bounds plaqueBounds, float s)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_009c: 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_00d4: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Expected O, but got Unknown
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: 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_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)standT) || s <= 0f)
			{
				return;
			}
			float num = PlaqueScale / s;
			if (Mathf.Abs(num - 1f) < 0.001f)
			{
				return;
			}
			Transform val = standT.Find("attach");
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			Vector3 extents = ((Bounds)(ref plaqueBounds)).extents;
			Vector3 val2 = val.localPosition - ((Bounds)(ref plaqueBounds)).center;
			Vector3 val3 = ((extents.x <= extents.y && extents.x <= extents.z) ? new Vector3(Mathf.Sign(val2.x), 0f, 0f) : ((extents.z <= extents.y) ? new Vector3(0f, 0f, Mathf.Sign(val2.z)) : new Vector3(0f, Mathf.Sign(val2.y), 0f)));
			float num2 = Vector3.Dot(new Vector3(Mathf.Abs(val3.x), Mathf.Abs(val3.y), Mathf.Abs(val3.z)), extents);
			Vector3 val4 = ((Bounds)(ref plaqueBounds)).center - val3 * num2;
			foreach (Transform item in standT)
			{
				Transform val5 = item;
				if (!((Object)(object)val5 == (Object)(object)val))
				{
					val5.localPosition = val4 + (val5.localPosition - val4) * num;
					val5.localScale *= num;
				}
			}
			val.localPosition += val3 * (2f * num2 * (num - 1f));
		}

		private static bool IsPlaquePart(Transform t, Transform decor)
		{
			Transform val = t;
			while (Object.op_Implicit((Object)(object)val) && (Object)(object)val != (Object)(object)decor)
			{
				if (((Object)val).name == "attach")
				{
					return false;
				}
				if (((Object)val).name == "stand")
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		private static void BuildOfferings(Transform decor, TributeDefinition def, Bounds table, float wallFront, int layer)
		{
			//IL_000b: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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)
			//IL_00b4: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: 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_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: 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_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: 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)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			if (def.Offerings == null)
			{
				return;
			}
			float num = Mathf.Min(((Bounds)(ref table)).max.z, wallFront);
			List<string> list = new List<string>();
			Offering[] offerings = def.Offerings;
			foreach (Offering offering in offerings)
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab(offering.Prefab);
				if