Decompiled source of RestedRites v0.2.0

RestedRites.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
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.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using RestedRites.Configuration;
using RestedRites.Patches;
using RestedRites.Rites;
using RestedRites.Services;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using VikingLib.Combat;
using VikingLib.Stats;
using VikingLib.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("DigitalVikings")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0+c05c3751c97a6aa7a877084159d1a357b045d2d1")]
[assembly: AssemblyProduct("RestedRites")]
[assembly: AssemblyTitle("RestedRites")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RestedRites
{
	[BepInPlugin("com.digitalvikings.restedrites", "RestedRites", "0.2.0")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class RestedRitesPlugin : BaseUnityPlugin
	{
		public const string ModGuid = "com.digitalvikings.restedrites";

		public const string ModName = "RestedRites";

		public const string ModVersion = "0.2.0";

		internal static ManualLogSource Log;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"RestedRites v0.2.0 initializing...");
			ModConfig.Init(((BaseUnityPlugin)this).Config);
			PowerCalculator.Initialize();
			RestedRitesStatAdapter.Init();
			_harmony = new Harmony("com.digitalvikings.restedrites");
			_harmony.PatchAll();
			HookJotunnSync();
			Log.LogInfo((object)"RestedRites v0.2.0 loaded successfully.");
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private void HookJotunnSync()
		{
			SynchronizationManager.OnConfigurationSynchronized += delegate
			{
				Log.LogInfo((object)"Server configuration synchronized successfully. Reloading power table and reapplying active Rested Rites modifiers...");
				PowerCalculator.ReloadTable();
				SERestedPatch.ReapplyCustomModifiers(Player.m_localPlayer);
			};
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}
namespace RestedRites.Services
{
	public class AttunedEntry
	{
		public string PrefabName { get; }

		public AttunedEntry(string prefabName)
		{
			PrefabName = prefabName;
		}

		public override string ToString()
		{
			return PrefabName;
		}

		public static AttunedEntry? Parse(string raw)
		{
			if (string.IsNullOrWhiteSpace(raw))
			{
				return null;
			}
			string text = raw.Split(':')[0].Trim();
			if (!string.IsNullOrEmpty(text))
			{
				return new AttunedEntry(text);
			}
			return null;
		}
	}
	public static class AttunementManager
	{
		public const string CustomDataKey = "RestedRites_AttunedTrophies";

		public const int MaxStoredTrophies = 4;

		public static int GetMaxSlots(int comfortLevel)
		{
			return PowerCalculator.GetActiveSlots(comfortLevel);
		}

		public static int GetRequiredComfortForSlot(int slotIndex)
		{
			if (slotIndex <= 0)
			{
				return 1;
			}
			for (int i = 1; i <= 24; i++)
			{
				if (PowerCalculator.GetSlotPercent(slotIndex, i) > 0.001f)
				{
					return i;
				}
			}
			return 24;
		}

		public static List<AttunedEntry> GetAttunedEntries(Player player)
		{
			List<AttunedEntry> list = new List<AttunedEntry>();
			if ((Object)(object)player == (Object)null || player.m_customData == null)
			{
				return list;
			}
			if (player.m_customData.TryGetValue("RestedRites_AttunedTrophies", out var value) && !string.IsNullOrWhiteSpace(value))
			{
				string[] array = value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				foreach (string raw in array)
				{
					AttunedEntry entry = AttunedEntry.Parse(raw);
					if (entry != null && !list.Any((AttunedEntry e) => string.Equals(e.PrefabName, entry.PrefabName, StringComparison.OrdinalIgnoreCase)))
					{
						list.Add(entry);
						if (list.Count >= 4)
						{
							break;
						}
					}
				}
			}
			return list;
		}

		public static List<AttunedEntry> GetActiveEntries(Player player, int playerComfort)
		{
			int maxSlots = GetMaxSlots(playerComfort);
			return GetAttunedEntries(player).Take(maxSlots).ToList();
		}

		public static List<string> GetAttunedTrophies(Player player)
		{
			return (from e in GetAttunedEntries(player)
				select e.PrefabName).ToList();
		}

		public static void SetAttunedEntries(Player player, List<AttunedEntry> entries)
		{
			if ((Object)(object)player == (Object)null || player.m_customData == null)
			{
				return;
			}
			if (entries == null || entries.Count == 0)
			{
				player.m_customData.Remove("RestedRites_AttunedTrophies");
				return;
			}
			List<AttunedEntry> source = entries.Take(4).ToList();
			player.m_customData["RestedRites_AttunedTrophies"] = string.Join(",", source.Select((AttunedEntry e) => e.ToString()));
		}

		public static bool IsAttuned(Player player, string trophyPrefab)
		{
			if (string.IsNullOrEmpty(trophyPrefab))
			{
				return false;
			}
			return GetAttunedEntries(player).Any((AttunedEntry e) => string.Equals(e.PrefabName, trophyPrefab, StringComparison.OrdinalIgnoreCase));
		}

		public static bool IsActive(Player player, string trophyPrefab, int playerComfort)
		{
			if (string.IsNullOrEmpty(trophyPrefab))
			{
				return false;
			}
			return GetActiveEntries(player, playerComfort).Any((AttunedEntry e) => string.Equals(e.PrefabName, trophyPrefab, StringComparison.OrdinalIgnoreCase));
		}

		public static bool TryGetActivePower(Player? player, TrophyId id, out float power)
		{
			power = 0f;
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			SEMan sEMan = ((Character)player).GetSEMan();
			StatusEffect obj = ((sEMan != null) ? sEMan.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Rested")) : null);
			SE_Rested val = (SE_Rested)(object)((obj is SE_Rested) ? obj : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			int comfortLevel = SERestedPatch.GetComfortLevel(val);
			if (PowerCalculator.GetActiveSlots(comfortLevel) <= 0)
			{
				return false;
			}
			List<AttunedEntry> activeEntries = GetActiveEntries(player, comfortLevel);
			if (activeEntries.Count == 0)
			{
				return false;
			}
			for (int i = 0; i < activeEntries.Count; i++)
			{
				if (RiteDatabase.TryGetRite(activeEntries[i].PrefabName, out TrophyRite rite) && rite.Id == id)
				{
					power = PowerCalculator.CalculatePower(rite.BaseMagnitude, comfortLevel, i);
					return true;
				}
			}
			return false;
		}

		public static Dictionary<SetId, int> GetActiveSetCounts(Player? player)
		{
			Dictionary<SetId, int> dictionary = new Dictionary<SetId, int>();
			if ((Object)(object)player == (Object)null)
			{
				return dictionary;
			}
			SEMan sEMan = ((Character)player).GetSEMan();
			StatusEffect obj = ((sEMan != null) ? sEMan.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Rested")) : null);
			SE_Rested val = (SE_Rested)(object)((obj is SE_Rested) ? obj : null);
			if ((Object)(object)val == (Object)null)
			{
				return dictionary;
			}
			int comfortLevel = SERestedPatch.GetComfortLevel(val);
			foreach (AttunedEntry activeEntry in GetActiveEntries(player, comfortLevel))
			{
				if (RiteDatabase.TryGetRite(activeEntry.PrefabName, out TrophyRite rite) && SetDatabase.TryGetSetForTrophy(rite.Id, out TrophySet set))
				{
					dictionary[set.Id] = ((!dictionary.TryGetValue(set.Id, out var value)) ? 1 : (value + 1));
				}
			}
			return dictionary;
		}

		public static bool HasActiveSetBonus(Player? player, SetId setId, int piecesRequired)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			SEMan sEMan = ((Character)player).GetSEMan();
			StatusEffect obj = ((sEMan != null) ? sEMan.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Rested")) : null);
			SE_Rested val = (SE_Rested)(object)((obj is SE_Rested) ? obj : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			int comfortLevel = SERestedPatch.GetComfortLevel(val);
			List<AttunedEntry> activeEntries = GetActiveEntries(player, comfortLevel);
			int num = 0;
			foreach (AttunedEntry item in activeEntries)
			{
				if (RiteDatabase.TryGetRite(item.PrefabName, out TrophyRite rite) && SetDatabase.TryGetSetForTrophy(rite.Id, out TrophySet set) && set.Id == setId)
				{
					num++;
					if (num >= piecesRequired)
					{
						return true;
					}
				}
			}
			return false;
		}

		public static bool AttuneTrophy(Player player, string trophyPrefab, out string message)
		{
			if ((Object)(object)player == (Object)null)
			{
				message = "Player not found.";
				return false;
			}
			if (!RiteDatabase.TryGetRite(trophyPrefab, out TrophyRite rite))
			{
				message = "'" + trophyPrefab + "' is not a recognized trophy rite.";
				return false;
			}
			List<AttunedEntry> attunedEntries = GetAttunedEntries(player);
			int num = attunedEntries.FindIndex((AttunedEntry e) => string.Equals(e.PrefabName, trophyPrefab, StringComparison.OrdinalIgnoreCase));
			if (num >= 0)
			{
				AttunedEntry item = attunedEntries[num];
				attunedEntries.RemoveAt(num);
				attunedEntries.Insert(0, item);
				SetAttunedEntries(player, attunedEntries);
				SERestedPatch.ReapplyCustomModifiers(player);
				message = "Attuned: " + rite.DisplayName + " (" + rite.CreatureName + ")";
				return true;
			}
			attunedEntries.Insert(0, new AttunedEntry(trophyPrefab));
			if (attunedEntries.Count > 4)
			{
				attunedEntries.RemoveRange(4, attunedEntries.Count - 4);
			}
			SetAttunedEntries(player, attunedEntries);
			SERestedPatch.ReapplyCustomModifiers(player);
			message = "Attuned: " + rite.DisplayName + " (" + rite.CreatureName + ")";
			return true;
		}

		public static string FormatTooltip(Player player, int playerComfort)
		{
			List<AttunedEntry> attunedEntries = GetAttunedEntries(player);
			int maxSlots = GetMaxSlots(playerComfort);
			int num = Math.Min(attunedEntries.Count, maxSlots);
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append($"\n\n<color=#FFD700><b>Attuned Rites ({num}/{maxSlots} Active • Comfort {playerComfort}, {attunedEntries.Count}/{4} Stored):</b></color>");
			if (attunedEntries.Count == 0)
			{
				stringBuilder.Append("\n<color=#A0A0A0>• None active. Mount trophies on Item Stands and press Shift+E to attune.</color>");
				return stringBuilder.ToString();
			}
			for (int i = 0; i < num; i++)
			{
				AttunedEntry attunedEntry = attunedEntries[i];
				float slotPercent = PowerCalculator.GetSlotPercent(i, playerComfort);
				string text = ((i == 0) ? "Anchor" : $"Slot {i + 1}");
				if (RiteDatabase.TryGetRite(attunedEntry.PrefabName, out TrophyRite rite))
				{
					string formattedDescription = rite.GetFormattedDescription(playerComfort, i);
					stringBuilder.Append($"\n• <color=#00FFFF>{rite.DisplayName}</color> ({rite.CreatureName}) <color=#FFD700>[{text}: {slotPercent:0.#}%]</color>: <color=#80FF80>{formattedDescription}</color>");
				}
				else
				{
					stringBuilder.Append($"\n• <color=#00FFFF>{attunedEntry.PrefabName}</color> <color=#FFD700>[{text}: {slotPercent:0.#}%]</color>: <color=#80FF80>Active</color>");
				}
			}
			for (int j = num; j < maxSlots; j++)
			{
				float slotPercent2 = PowerCalculator.GetSlotPercent(j, playerComfort);
				string arg = ((j == 0) ? "Anchor" : $"Slot {j + 1}");
				stringBuilder.Append($"\n<color=#80FF80>• {arg} ({slotPercent2:0.#}% Power): Empty (Mount trophy & Shift+E to attune)</color>");
			}
			for (int k = num; k < attunedEntries.Count; k++)
			{
				AttunedEntry attunedEntry2 = attunedEntries[k];
				int requiredComfortForSlot = GetRequiredComfortForSlot(k);
				if (RiteDatabase.TryGetRite(attunedEntry2.PrefabName, out TrophyRite rite2))
				{
					stringBuilder.Append($"\n<color=#A0A0A0>• {rite2.DisplayName} ({rite2.CreatureName}): Stored (Requires Comfort {requiredComfortForSlot}+)</color>");
				}
				else
				{
					stringBuilder.Append($"\n<color=#A0A0A0>• {attunedEntry2.PrefabName}: Stored (Requires Comfort {requiredComfortForSlot}+)</color>");
				}
			}
			Dictionary<SetId, int> dictionary = new Dictionary<SetId, int>();
			for (int l = 0; l < num; l++)
			{
				if (RiteDatabase.TryGetRite(attunedEntries[l].PrefabName, out TrophyRite rite3) && SetDatabase.TryGetSetForTrophy(rite3.Id, out TrophySet set))
				{
					dictionary[set.Id] = ((!dictionary.TryGetValue(set.Id, out var value)) ? 1 : (value + 1));
				}
			}
			if (dictionary.Count > 0)
			{
				stringBuilder.Append("\n\n<color=#FFD700><b>Set Synergies:</b></color>");
				foreach (KeyValuePair<SetId, int> item in dictionary)
				{
					if (SetDatabase.TryGetSet(item.Key, out TrophySet set2))
					{
						int value2 = item.Value;
						int num2 = set2.Members.Length;
						stringBuilder.Append($"\n• <color=#00FFFF>{set2.Name}</color> ({value2}/{num2} Pieces):");
						if (set2.TwoPieceBonus != null)
						{
							string text2 = ((value2 >= 2) ? "<color=#80FF80>[ACTIVE]</color>" : "<color=#A0A0A0>[Requires 2]</color>");
							string text3 = ((value2 >= 2) ? "#80FF80" : "#A0A0A0");
							stringBuilder.Append("\n   <color=" + text3 + ">(2) " + set2.TwoPieceBonus + " " + text2 + "</color>");
						}
						if (set2.ThreePieceBonus != null)
						{
							string text4 = ((value2 >= 3) ? "<color=#80FF80>[ACTIVE]</color>" : "<color=#A0A0A0>[Requires 3]</color>");
							string text5 = ((value2 >= 3) ? "#80FF80" : "#A0A0A0");
							stringBuilder.Append("\n   <color=" + text5 + ">(3) " + set2.ThreePieceBonus + " " + text4 + "</color>");
						}
						if (set2.FourPieceBonus != null)
						{
							string text6 = ((value2 >= 4) ? "<color=#80FF80>[ACTIVE]</color>" : "<color=#A0A0A0>[Requires 4]</color>");
							string text7 = ((value2 >= 4) ? "#80FF80" : "#A0A0A0");
							stringBuilder.Append("\n   <color=" + text7 + ">(4) " + set2.FourPieceBonus + " " + text6 + "</color>");
						}
					}
				}
			}
			return stringBuilder.ToString();
		}
	}
	public static class FeedbackManager
	{
		private class TrophyEmissionFlasher : MonoBehaviour
		{
			private Renderer[] _renderers = Array.Empty<Renderer>();

			private MaterialPropertyBlock _propBlock;

			private Light? _flashLight;

			private static readonly int EmissionColorId = Shader.PropertyToID("_EmissionColor");

			private static readonly int ColorId = Shader.PropertyToID("_Color");

			private Color _targetColor;

			private float _duration;

			private float _elapsed;

			private void Awake()
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Expected O, but got Unknown
				_propBlock = new MaterialPropertyBlock();
				DiscoverRenderers();
			}

			public void DiscoverRenderers(ItemStand? stand = null)
			{
				List<Renderer> list = new List<Renderer>();
				list.AddRange(((Component)this).GetComponentsInChildren<Renderer>(true));
				if ((Object)(object)stand != (Object)null)
				{
					if ((Object)(object)stand.m_attachOther != (Object)null)
					{
						list.AddRange(((Component)stand.m_attachOther).GetComponentsInChildren<Renderer>(true));
					}
					if ((Object)(object)stand.m_dropSpawnPoint != (Object)null)
					{
						list.AddRange(((Component)stand.m_dropSpawnPoint).GetComponentsInChildren<Renderer>(true));
					}
				}
				if ((Object)(object)stand != (Object)null)
				{
					Renderer[] standRenderers = ((Component)stand).GetComponents<Renderer>();
					list.RemoveAll((Renderer r) => Array.IndexOf(standRenderers, r) >= 0);
				}
				_renderers = list.ToArray();
				for (int num = 0; num < _renderers.Length; num++)
				{
					Renderer val = _renderers[num];
					if (!((Object)(object)val != (Object)null))
					{
						continue;
					}
					Material[] sharedMaterials = val.sharedMaterials;
					foreach (Material val2 in sharedMaterials)
					{
						if ((Object)(object)val2 != (Object)null)
						{
							val2.EnableKeyword("_EMISSION");
						}
					}
				}
			}

			public void Flash(ItemStand stand, Color color, float duration)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0096: Unknown result type (might be due to invalid IL or missing references)
				_targetColor = color;
				_duration = Mathf.Max(0.1f, duration);
				_elapsed = 0f;
				DiscoverRenderers(stand);
				if ((Object)(object)_flashLight == (Object)null)
				{
					_flashLight = ((Component)this).gameObject.GetComponent<Light>();
					if ((Object)(object)_flashLight == (Object)null)
					{
						_flashLight = ((Component)this).gameObject.AddComponent<Light>();
					}
					_flashLight.type = (LightType)2;
					_flashLight.range = 2f;
					_flashLight.shadows = (LightShadows)0;
				}
				_flashLight.color = color;
				_flashLight.intensity = 0f;
				((Behaviour)_flashLight).enabled = true;
				((Behaviour)this).enabled = true;
			}

			private void Update()
			{
				_elapsed += Time.deltaTime;
				float num = _elapsed / _duration;
				if (num >= 1f)
				{
					SetIntensity(0f);
					if ((Object)(object)_flashLight != (Object)null)
					{
						((Behaviour)_flashLight).enabled = false;
					}
					((Behaviour)this).enabled = false;
				}
				else
				{
					float num2 = Mathf.Sin(num * MathF.PI);
					SetIntensity(num2);
					if ((Object)(object)_flashLight != (Object)null)
					{
						_flashLight.intensity = num2 * 1.5f;
					}
				}
			}

			private void SetIntensity(float factor)
			{
				//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_0043: Unknown result type (might be due to invalid IL or missing references)
				if (_renderers == null)
				{
					return;
				}
				Color val = _targetColor * factor;
				for (int i = 0; i < _renderers.Length; i++)
				{
					Renderer val2 = _renderers[i];
					if ((Object)(object)val2 != (Object)null)
					{
						val2.GetPropertyBlock(_propBlock);
						_propBlock.SetColor(EmissionColorId, val);
						val2.SetPropertyBlock(_propBlock);
					}
				}
			}

			private void OnDisable()
			{
				SetIntensity(0f);
				if ((Object)(object)_flashLight != (Object)null)
				{
					((Behaviour)_flashLight).enabled = false;
				}
			}
		}

		private static readonly FieldRef<ItemStand, GameObject> ItemStandVisualItemRef = AccessTools.FieldRefAccess<ItemStand, GameObject>("m_visualItem");

		public static GameObject? SpawnEffect(string primaryPrefab, Vector3 position, Quaternion rotation, params string[] fallbacks)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return SpawnEffect(primaryPrefab, position, rotation, 0f, fallbacks);
		}

		public static GameObject? SpawnEffect(string primaryPrefab, Vector3 position, Quaternion rotation, float durationSeconds, params string[] fallbacks)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableSensoryFeedback.Value || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return null;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(primaryPrefab);
			if ((Object)(object)prefab == (Object)null && fallbacks != null)
			{
				for (int i = 0; i < fallbacks.Length; i++)
				{
					prefab = ZNetScene.instance.GetPrefab(fallbacks[i]);
					if ((Object)(object)prefab != (Object)null)
					{
						break;
					}
				}
			}
			if ((Object)(object)prefab != (Object)null)
			{
				GameObject val = Object.Instantiate<GameObject>(prefab, position, rotation);
				if ((Object)(object)val != (Object)null)
				{
					if (durationSeconds > 0.01f)
					{
						ParticleSystem[] componentsInChildren = val.GetComponentsInChildren<ParticleSystem>();
						foreach (ParticleSystem obj in componentsInChildren)
						{
							MainModule main = obj.main;
							float simulationSpeed = Mathf.Max(1f, 1.5f / durationSeconds);
							((MainModule)(ref main)).simulationSpeed = simulationSpeed;
							((MainModule)(ref main)).maxParticles = Math.Min(((MainModule)(ref main)).maxParticles, 15);
							EmissionModule emission = obj.emission;
							((EmissionModule)(ref emission)).rateOverTimeMultiplier = ((EmissionModule)(ref emission)).rateOverTimeMultiplier * 0.4f;
						}
						TimedDestruction component = val.GetComponent<TimedDestruction>();
						if ((Object)(object)component != (Object)null)
						{
							((MonoBehaviour)component).CancelInvoke();
						}
						Object.Destroy((Object)(object)val, durationSeconds);
					}
					else if ((Object)(object)val.GetComponent<TimedDestruction>() == (Object)null)
					{
						Object.Destroy((Object)(object)val, 5f);
					}
				}
				return val;
			}
			return null;
		}

		public static void TriggerAttunement(ItemStand stand, string riteName)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: 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)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableSensoryFeedback.Value || (Object)(object)stand == (Object)null)
			{
				return;
			}
			Vector3 position = ((Component)stand).transform.position;
			GameObject val = ItemStandVisualItemRef.Invoke(stand);
			if ((Object)(object)val == (Object)null && (Object)(object)stand.m_attachOther != (Object)null && stand.m_attachOther.childCount > 0)
			{
				val = ((Component)stand.m_attachOther.GetChild(0)).gameObject;
			}
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)stand).gameObject;
			}
			if ((Object)(object)val != (Object)null)
			{
				TrophyEmissionFlasher trophyEmissionFlasher = val.GetComponent<TrophyEmissionFlasher>();
				if ((Object)(object)trophyEmissionFlasher == (Object)null)
				{
					trophyEmissionFlasher = val.AddComponent<TrophyEmissionFlasher>();
				}
				trophyEmissionFlasher.Flash(stand, new Color(1f, 0.8f, 0.35f), 0.8f);
			}
			if (stand.m_effects != null && stand.m_effects.HasEffects())
			{
				stand.m_effects.Create(position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			}
			else
			{
				SpawnEffect("sfx_lore", position, Quaternion.identity, "sfx_build_hammer_stone");
			}
			if (ModConfig.EnableCombatFloatingText.Value && (Object)(object)DamageText.instance != (Object)null)
			{
				DamageText.instance.ShowText((TextType)7, position + Vector3.up * 0.6f, "* Attuned: " + riteName + " *", false);
			}
		}

		public static void TriggerStaminaBurst(Player player)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (ModConfig.EnableSensoryFeedback.Value && !((Object)(object)player == (Object)null))
			{
				SpawnEffect("vfx_StaminaUpgrade", ((Component)player).transform.position, Quaternion.identity, "vfx_MeadStrength");
				SpawnEffect("sfx_Potion_stamina_Start", ((Component)player).transform.position, Quaternion.identity);
			}
		}

		public static void TriggerBloodboundStrike(Vector3 hitPoint, Vector3 fallbackPoint = default(Vector3))
		{
			//IL_000d: 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_0031: 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_001b: 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_0038: 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_002e: 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)
			if (ModConfig.EnableSensoryFeedback.Value)
			{
				Vector3 position = ((hitPoint != Vector3.zero) ? hitPoint : ((fallbackPoint != Vector3.zero) ? fallbackPoint : Vector3.zero));
				SpawnEffect("fx_crit", position, Quaternion.identity, "vfx_corpse_destruction_hit");
			}
		}

		public static void TriggerCarapaceWard(Player player, Vector3 hitPoint)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_002c: 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_0033: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			if (ModConfig.EnableSensoryFeedback.Value && !((Object)(object)player == (Object)null))
			{
				Vector3 position = ((hitPoint != Vector3.zero) ? hitPoint : ((Character)player).GetCenterPoint());
				SpawnEffect("vfx_blocked", position, Quaternion.identity);
				SpawnEffect("fx_StaffShield_Hit", ((Component)player).transform.position, Quaternion.identity);
				SpawnEffect("sfx_metal_blocked_overlay", position, Quaternion.identity);
				if (ModConfig.EnableCombatFloatingText.Value && (Object)(object)DamageText.instance != (Object)null)
				{
					DamageText.instance.ShowText((TextType)6, ((Component)player).transform.position + Vector3.up * 0.5f, "CARAPACE WARD (-80%)", true);
				}
			}
		}

		public static void TriggerCarapaceCounter(Character target, float reflectedDamage)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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)
			if (ModConfig.EnableSensoryFeedback.Value && !((Object)(object)target == (Object)null))
			{
				SpawnEffect("fx_StaffShield_Hit", ((Component)target).transform.position, Quaternion.identity);
				if (ModConfig.EnableCombatFloatingText.Value && (Object)(object)DamageText.instance != (Object)null)
				{
					DamageText.instance.ShowText((TextType)2, target.GetHeadPoint() + Vector3.up * 0.3f, reflectedDamage, false);
				}
			}
		}

		public static void TriggerLastStand(Player player, float healAmount)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			if (ModConfig.EnableSensoryFeedback.Value && !((Object)(object)player == (Object)null))
			{
				SpawnEffect("vfx_HealthUpgrade", ((Component)player).transform.position, Quaternion.identity, "vfx_Potion_health_medium");
				SpawnEffect("sfx_dverger_heal_finish", ((Component)player).transform.position, Quaternion.identity);
				if (ModConfig.EnableCombatFloatingText.Value && (Object)(object)DamageText.instance != (Object)null)
				{
					DamageText.instance.ShowText((TextType)4, ((Character)player).GetHeadPoint() + Vector3.up * 0.5f, healAmount, true);
				}
			}
		}

		public static void TriggerHeal(Player player, float healAmount)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if (ModConfig.EnableSensoryFeedback.Value && !((Object)(object)player == (Object)null) && ModConfig.EnableCombatFloatingText.Value && (Object)(object)DamageText.instance != (Object)null)
			{
				DamageText.instance.ShowText((TextType)4, ((Character)player).GetHeadPoint() + Vector3.up * 0.4f, healAmount, true);
			}
		}

		public static void TriggerTarProc(Character? target)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (ModConfig.EnableSensoryFeedback.Value && !((Object)(object)target == (Object)null))
			{
				SpawnEffect("vfx_blobtar_hit", target.GetCenterPoint(), Quaternion.identity);
			}
		}

		public static void TriggerFrostProc(Character? target)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (ModConfig.EnableSensoryFeedback.Value && !((Object)(object)target == (Object)null))
			{
				SpawnEffect("vfx_Frost", target.GetCenterPoint(), Quaternion.identity);
			}
		}

		public static void TriggerSpeedBoost(Player player)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if (ModConfig.EnableSensoryFeedback.Value && !((Object)(object)player == (Object)null))
			{
				SpawnEffect("sfx_frozenking_charge_whoosh", ((Component)player).transform.position, Quaternion.identity, "sfx_club_swing");
			}
		}

		public static void TriggerBrennaFireburst(Vector3 position, float damage, Player attacker)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableSensoryFeedback.Value)
			{
				return;
			}
			SpawnEffect("vfx_FireballHit", position, Quaternion.identity, "vfx_corpse_destruction_hit");
			if (!(damage > 0.1f))
			{
				return;
			}
			Collider[] array = Physics.OverlapSphere(position, 4f);
			HashSet<Character> hashSet = new HashSet<Character>();
			foreach (Collider val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Character componentInParent = ((Component)val).GetComponentInParent<Character>();
					if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent != (Object)(object)attacker && !componentInParent.IsPlayer() && !componentInParent.IsTamed() && hashSet.Add(componentInParent))
					{
						HitData val2 = new HitData();
						val2.m_damage.m_fire = damage;
						val2.m_point = componentInParent.GetCenterPoint();
						Vector3 val3 = ((Component)componentInParent).transform.position - position;
						val2.m_dir = ((Vector3)(ref val3)).normalized;
						val2.SetAttacker((Character)(object)attacker);
						componentInParent.Damage(val2);
					}
				}
			}
		}

		public static void TriggerGeirrhafaFrostFog(Vector3 position, Player player)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableSensoryFeedback.Value || (Object)(object)player == (Object)null)
			{
				return;
			}
			SpawnEffect("vfx_BombBlob_explode_frost", position, Quaternion.identity, "vfx_Frost");
			Collider[] array = Physics.OverlapSphere(position, 3.5f);
			HashSet<Character> hashSet = new HashSet<Character>();
			foreach (Collider val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Character componentInParent = ((Component)val).GetComponentInParent<Character>();
				if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent != (Object)(object)player && !componentInParent.IsPlayer() && !componentInParent.IsTamed() && hashSet.Add(componentInParent))
				{
					SEMan sEMan = componentInParent.GetSEMan();
					if (sEMan != null)
					{
						sEMan.AddStatusEffect(StringExtensionMethods.GetStableHashCode("Frost"), true, 0, 0f, (short)(-1));
					}
				}
			}
		}

		public static void TriggerShamanicWard(Player player, string debuffName)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0076: 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_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)
			if (ModConfig.EnableSensoryFeedback.Value && !((Object)(object)player == (Object)null))
			{
				SpawnEffect("fx_StaffShield_Hit", ((Component)player).transform.position, Quaternion.identity);
				SpawnEffect("sfx_lore", ((Component)player).transform.position, Quaternion.identity);
				if (ModConfig.EnableCombatFloatingText.Value && (Object)(object)DamageText.instance != (Object)null)
				{
					DamageText.instance.ShowText((TextType)7, ((Character)player).GetHeadPoint() + Vector3.up * 0.5f, "WARDED: " + debuffName, true);
				}
			}
		}
	}
	public static class RestedRitesStatAdapter
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static DamagePhaseHandler <0>__OnAttackerModifiers;

			public static Action<DamageContext> <1>__OnHitTaken;

			public static Action<DamageContext> <2>__OnLethalHit;

			public static Action<Character, Character, DamageContext> <3>__OnKill;

			public static Action<Character, Character, DamageContext> <4>__OnCriticalHit;

			public static DamagePhaseHandler <5>__OnPostHitProcs;

			public static CustomGlossaryCategoryProvider <6>__ProvideGlossaryCategory;
		}

		public const string OwnerKey = "RestedRites";

		private static bool _initialized;

		private static bool s_bloodboundEmpowered;

		public static void Init()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Expected O, but got Unknown
			if (!_initialized)
			{
				_initialized = true;
				object obj = <>O.<0>__OnAttackerModifiers;
				if (obj == null)
				{
					DamagePhaseHandler val = OnAttackerModifiers;
					<>O.<0>__OnAttackerModifiers = val;
					obj = (object)val;
				}
				DamagePipeline.RegisterHandler((DamagePhase)1, 50, (DamagePhaseHandler)obj);
				DamagePipeline.OnHitTaken += OnHitTaken;
				DamagePipeline.OnLethalHit += OnLethalHit;
				DamagePipeline.OnKill += OnKill;
				DamagePipeline.OnCriticalHit += OnCriticalHit;
				object obj2 = <>O.<5>__OnPostHitProcs;
				if (obj2 == null)
				{
					DamagePhaseHandler val2 = OnPostHitProcs;
					<>O.<5>__OnPostHitProcs = val2;
					obj2 = (object)val2;
				}
				DamagePipeline.RegisterHandler((DamagePhase)6, 50, (DamagePhaseHandler)obj2);
				object obj3 = <>O.<6>__ProvideGlossaryCategory;
				if (obj3 == null)
				{
					CustomGlossaryCategoryProvider val3 = ProvideGlossaryCategory;
					<>O.<6>__ProvideGlossaryCategory = val3;
					obj3 = (object)val3;
				}
				CharacterStatsGlossaryPanel.RegisterCustomCategory("Rested Rites", (CustomGlossaryCategoryProvider)obj3, 50);
			}
		}

		public static void SyncPlayer(Player? player)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || !ModConfig.ModEnabled.Value)
			{
				if ((Object)(object)player != (Object)null)
				{
					CharacterStatManager.RemoveModifiersByOwner((Character)(object)player, (object)"RestedRites");
				}
				return;
			}
			SEMan sEMan = ((Character)player).GetSEMan();
			if (sEMan == null)
			{
				CharacterStatManager.RemoveModifiersByOwner((Character)(object)player, (object)"RestedRites");
				return;
			}
			StatusEffect statusEffect = sEMan.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Rested"));
			SE_Rested val = (SE_Rested)(object)((statusEffect is SE_Rested) ? statusEffect : null);
			if ((Object)(object)val == (Object)null)
			{
				CharacterStatManager.RemoveModifiersByOwner((Character)(object)player, (object)"RestedRites");
				return;
			}
			int comfortLevel = SERestedPatch.GetComfortLevel(val);
			List<AttunedEntry> activeEntries = AttunementManager.GetActiveEntries(player, comfortLevel);
			List<StatModifier> list = new List<StatModifier>(64);
			for (int i = 0; i < activeEntries.Count; i++)
			{
				if (!RiteDatabase.TryGetRite(activeEntries[i].PrefabName, out TrophyRite rite))
				{
					continue;
				}
				foreach (StatModifier item in rite.CreateModifiers(player, comfortLevel, i, "RestedRites"))
				{
					list.Add(item);
				}
			}
			foreach (KeyValuePair<SetId, int> activeSetCount in AttunementManager.GetActiveSetCounts(player))
			{
				if (!SetDatabase.TryGetSet(activeSetCount.Key, out TrophySet set))
				{
					continue;
				}
				foreach (StatModifier item2 in set.CreateModifiers(player, activeSetCount.Value, "RestedRites"))
				{
					list.Add(item2);
				}
			}
			CharacterStatManager.ReplaceModifiersByOwner((Character)(object)player, (object)"RestedRites", (IEnumerable<StatModifier>)list);
		}

		private static void OnAttackerModifiers(DamageContext ctx)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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)
			Character attacker = ctx.Attacker;
			Player val = (Player)(object)((attacker is Player) ? attacker : null);
			if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer))
			{
				if (s_bloodboundEmpowered && AttunementManager.HasActiveSetBonus(val, SetId.TheBloodbound, 3))
				{
					s_bloodboundEmpowered = false;
					ctx.AddMultiplier(2f, "The Bloodbound (Empowered)", (DamageType?)null);
					FeedbackManager.TriggerBloodboundStrike(ctx.Hit.m_point);
				}
				if (AttunementManager.HasActiveSetBonus(val, SetId.ThePlainsTribe, 4))
				{
					ctx.AddExtraDamageFromPhysical((DamageType)5, 0.15f, "The Plains Tribe (4pc)");
				}
				if (ctx.Hit.m_ranged && AttunementManager.HasActiveSetBonus(val, SetId.TheCharredDuo, 2) && (ctx.GetTotalElementalDamage() > 0.01f || ctx.GetDamage((DamageType)8) > 0.01f || ctx.GetDamage((DamageType)9) > 0.01f))
				{
					ctx.AddIncreasedPercent(0.25f, "The Charred Duo", (DamageType?)null);
				}
			}
		}

		private static void OnHitTaken(DamageContext ctx)
		{
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			Character target = ctx.Target;
			Player val = (Player)(object)((target is Player) ? target : null);
			if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			if (AttunementManager.TryGetActivePower(val, TrophyId.SeekerSoldier, out var power))
			{
				float num = ((power > 0.01f) ? (75f / power) : 75f);
				if (ProcCooldownManager.TryTrigger((Character)(object)val, "RestedRites_CarapaceWard", num, false))
				{
					float totalDamage = ctx.GetTotalDamage();
					ctx.AddMultiplier(0.2f, "Carapace Ward", (DamageType?)(DamageType)0);
					ctx.AddMultiplier(0.2f, "Carapace Ward", (DamageType?)(DamageType)1);
					ctx.AddMultiplier(0.2f, "Carapace Ward", (DamageType?)(DamageType)2);
					FeedbackManager.TriggerCarapaceWard(val, ctx.Hit.m_point);
					((Character)val).Message((MessageType)1, $"Carapace Ward absorbed 80% damage! ({num:F0}s CD)", 0, (Sprite)null, false);
					if ((Object)(object)ctx.Attacker != (Object)null && AttunementManager.HasActiveSetBonus(val, SetId.TheHiveChitin, 3) && DamagePipeline.ReflectDamage((Character)(object)val, ctx.Attacker, ctx, 0.5f, (DamageType?)(DamageType)0, "Carapace Counter"))
					{
						FeedbackManager.TriggerCarapaceCounter(ctx.Attacker, totalDamage * 0.5f);
						((Character)val).Message((MessageType)1, "<color=#00FFFF><b>Carapace Counter: Reflected 50% damage!</b></color>", 0, (Sprite)null, false);
					}
				}
			}
			if ((Object)(object)ctx.Attacker != (Object)null && !ctx.Hit.m_ranged && AttunementManager.HasActiveSetBonus(val, SetId.TheGelatinousHorde, 3))
			{
				DamagePipeline.ApplyOnHitStatus(ctx.Attacker, "Frost", 0f, 4f, (Character)(object)val);
			}
		}

		private static void OnLethalHit(DamageContext ctx)
		{
			Character target = ctx.Target;
			Player val = (Player)(object)((target is Player) ? target : null);
			if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer || !AttunementManager.TryGetActivePower(val, TrophyId.Vile, out var power))
			{
				return;
			}
			float num = (AttunementManager.HasActiveSetBonus(val, SetId.TheDraugrRevenants, 3) ? 300f : 600f);
			if (ProcCooldownManager.TryTrigger((Character)(object)val, "RestedRites_LastStand", num, true))
			{
				ctx.DefyDeath("Death Defiance");
				float num2 = ((Character)val).GetMaxHealth() * (power / 100f);
				((Character)val).Heal(num2, true);
				FeedbackManager.TriggerLastStand(val, num2);
				if (AttunementManager.HasActiveSetBonus(val, SetId.TheDraugrRevenants, 3))
				{
					((Character)val).AddStamina(((Character)val).GetMaxStamina());
					((Character)val).Message((MessageType)2, "<color=#00FFFF><b>Last Stand: Defied Death & Restored Stamina!</b></color>", 0, (Sprite)null, false);
				}
				else
				{
					((Character)val).Message((MessageType)2, "<color=#FFD700><b>Last Stand: Defied Death!</b></color>", 0, (Sprite)null, false);
				}
			}
		}

		private static void OnKill(Character attacker, Character victim, DamageContext ctx)
		{
			Player val = (Player)(object)((attacker is Player) ? attacker : null);
			if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && AttunementManager.HasActiveSetBonus(val, SetId.TheBloodbound, 3))
			{
				s_bloodboundEmpowered = true;
				((Character)val).Message((MessageType)1, "<color=#FF4500><b>Bloodbound: Next attack deals 2x damage!</b></color>", 0, (Sprite)null, false);
			}
		}

		private static void OnCriticalHit(Character attacker, Character victim, DamageContext ctx)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			Player val = (Player)(object)((attacker is Player) ? attacker : null);
			if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && AttunementManager.TryGetActivePower(val, TrophyId.Brenna, out var power))
			{
				float damage = ctx.GetTotalDamage() * (power / 100f);
				FeedbackManager.TriggerBrennaFireburst((ctx.Hit.m_point != Vector3.zero) ? ctx.Hit.m_point : (((Object)(object)victim != (Object)null) ? victim.GetCenterPoint() : ((Component)val).transform.position), damage, val);
			}
		}

		private static void OnPostHitProcs(DamageContext ctx)
		{
			Character attacker = ctx.Attacker;
			Player val = (Player)(object)((attacker is Player) ? attacker : null);
			if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			Character target = ctx.Target;
			if (AttunementManager.TryGetActivePower(val, TrophyId.Fenring, out var _))
			{
				FeedbackManager.TriggerSpeedBoost(val);
			}
			if ((Object)(object)target != (Object)null && AttunementManager.TryGetActivePower(val, TrophyId.Growth, out var power2))
			{
				float num = (ctx.Hit.m_ranged ? power2 : 40f);
				if (Random.Range(0f, 100f) < num)
				{
					DamagePipeline.ApplyOnHitStatus(target, "Tarred", 0f, 8f, (Character)(object)val);
					FeedbackManager.TriggerTarProc(target);
				}
			}
			if ((Object)(object)target != (Object)null && AttunementManager.TryGetActivePower(val, TrophyId.FrostBlob, out var power3))
			{
				float num2 = (ctx.Hit.m_ranged ? power3 : 40f);
				if (Random.Range(0f, 100f) < num2)
				{
					DamagePipeline.ApplyOnHitStatus(target, "Frost", 0f, 8f, (Character)(object)val);
					FeedbackManager.TriggerFrostProc(target);
				}
			}
		}

		private static IEnumerable<(string Label, string FormattedValue)>? ProvideGlossaryCategory(Player player)
		{
			if ((Object)(object)player == (Object)null || !ModConfig.ModEnabled.Value)
			{
				return null;
			}
			List<AttunedEntry> attunedEntries = AttunementManager.GetAttunedEntries(player);
			if (attunedEntries.Count == 0)
			{
				return null;
			}
			SEMan sEMan = ((Character)player).GetSEMan();
			StatusEffect obj = ((sEMan != null) ? sEMan.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Rested")) : null);
			SE_Rested val = (SE_Rested)(object)((obj is SE_Rested) ? obj : null);
			bool flag = (Object)(object)val != (Object)null;
			int num = (flag ? SERestedPatch.GetComfortLevel(val) : SERestedPatch.GetPlayerComfort(player));
			int activeSlots = PowerCalculator.GetActiveSlots(num);
			int num2 = (flag ? Math.Min(attunedEntries.Count, activeSlots) : 0);
			List<(string, string)> list = new List<(string, string)>();
			string item = (flag ? $"{num2}/{activeSlots} Active (Comfort {num} • {ModConfig.ProgressionType.Value} Model)" : $"Inactive (Requires Rested • Comfort {num})");
			list.Add(("Attunement Status", item));
			for (int i = 0; i < attunedEntries.Count; i++)
			{
				if (RiteDatabase.TryGetRite(attunedEntries[i].PrefabName, out TrophyRite rite))
				{
					bool num3 = flag && i < num2;
					float slotPercent = PowerCalculator.GetSlotPercent(i, num);
					string arg = ((i == 0) ? "Anchor" : $"Slot {i + 1}");
					string text = (num3 ? rite.GetFormattedDescription(num, i) : rite.GetBaseDescription());
					string text2 = (num3 ? $"{arg} ({slotPercent:0.#}%)" : (flag ? "Requires Higher Comfort" : "Requires Rested"));
					list.Add(("• " + rite.DisplayName + " (" + rite.CreatureName + ")", text + " [" + text2 + "]"));
				}
			}
			if (flag)
			{
				foreach (KeyValuePair<SetId, int> activeSetCount in AttunementManager.GetActiveSetCounts(player))
				{
					if (SetDatabase.TryGetSet(activeSetCount.Key, out TrophySet set))
					{
						int value = activeSetCount.Value;
						List<string> list2 = new List<string>();
						if (value >= 2 && set.TwoPieceBonus != null)
						{
							list2.Add("(2) " + set.TwoPieceBonus);
						}
						if (value >= 3 && set.ThreePieceBonus != null)
						{
							list2.Add("(3) " + set.ThreePieceBonus);
						}
						if (value >= 4 && set.FourPieceBonus != null)
						{
							list2.Add("(4) " + set.FourPieceBonus);
						}
						if (list2.Count > 0)
						{
							list.Add(($"• Set: {set.Name} ({value}/{set.Members.Length})", string.Join(" | ", list2)));
						}
					}
				}
			}
			return list;
		}
	}
}
namespace RestedRites.Rites
{
	public static class PowerCalculator
	{
		public const int MaxComfortLevels = 24;

		public const int MaxSlots = 4;

		private static readonly float[,] s_table = new float[25, 4];

		private static bool s_initialized = false;

		public static void Initialize()
		{
			ReloadTable();
		}

		public static void ReloadTable()
		{
			ParseTable(ModConfig.ProgressionType.Value switch
			{
				ProgressionModel.Reservoir => "1: 100.0, 0.0, 0.0, 0.0\n2: 100.0, 7.5, 0.0, 0.0\n3: 100.0, 15.0, 0.0, 0.0\n4: 100.0, 22.5, 0.0, 0.0\n5: 100.0, 30.0, 0.0, 0.0\n6: 100.0, 37.5, 0.0, 0.0\n7: 100.0, 45.0, 0.0, 0.0\n8: 100.0, 50.0, 2.5, 0.0\n9: 100.0, 50.0, 10.0, 0.0\n10: 100.0, 50.0, 17.5, 0.0\n11: 100.0, 50.0, 25.0, 0.0\n12: 100.0, 50.0, 32.5, 0.0\n13: 100.0, 52.5, 37.5, 0.0\n14: 100.0, 55.0, 42.5, 0.0\n15: 100.0, 55.0, 42.5, 7.5\n16: 100.0, 55.0, 42.5, 15.0\n17: 100.0, 55.0, 42.5, 22.5\n18: 100.0, 55.0, 42.5, 30.0\n19: 100.0, 57.5, 45.0, 32.5\n20: 100.0, 60.0, 47.5, 35.0\n21: 100.0, 62.5, 50.0, 37.5\n22: 100.0, 65.0, 52.5, 40.0\n23: 100.0, 67.5, 55.0, 42.5\n24: 100.0, 70.0, 57.5, 45.0", 
				ProgressionModel.Uniform => "1: 100.0, 0.0, 0.0, 0.0\n2: 53.8, 53.8, 0.0, 0.0\n3: 57.5, 57.5, 0.0, 0.0\n4: 61.3, 61.3, 0.0, 0.0\n5: 65.0, 65.0, 0.0, 0.0\n6: 68.8, 68.8, 0.0, 0.0\n7: 72.5, 72.5, 0.0, 0.0\n8: 50.8, 50.8, 50.8, 0.0\n9: 53.3, 53.3, 53.3, 0.0\n10: 55.8, 55.8, 55.8, 0.0\n11: 58.3, 58.3, 58.3, 0.0\n12: 60.8, 60.8, 60.8, 0.0\n13: 63.3, 63.3, 63.3, 0.0\n14: 65.8, 65.8, 65.8, 0.0\n15: 51.3, 51.3, 51.3, 51.3\n16: 53.1, 53.1, 53.1, 53.1\n17: 55.0, 55.0, 55.0, 55.0\n18: 56.9, 56.9, 56.9, 56.9\n19: 58.8, 58.8, 58.8, 58.8\n20: 60.6, 60.6, 60.6, 60.6\n21: 62.5, 62.5, 62.5, 62.5\n22: 64.4, 64.4, 64.4, 64.4\n23: 66.3, 66.3, 66.3, 66.3\n24: 68.1, 68.1, 68.1, 68.1", 
				ProgressionModel.Custom => string.IsNullOrWhiteSpace(ModConfig.CustomProgressionTable.Value) ? "1: 100.0, 0.0, 0.0, 0.0\n2: 100.0, 7.5, 0.0, 0.0\n3: 100.0, 15.0, 0.0, 0.0\n4: 100.0, 22.5, 0.0, 0.0\n5: 100.0, 30.0, 0.0, 0.0\n6: 100.0, 37.5, 0.0, 0.0\n7: 100.0, 45.0, 0.0, 0.0\n8: 100.0, 50.0, 2.5, 0.0\n9: 100.0, 50.0, 10.0, 0.0\n10: 100.0, 50.0, 17.5, 0.0\n11: 100.0, 50.0, 25.0, 0.0\n12: 100.0, 50.0, 32.5, 0.0\n13: 100.0, 52.5, 37.5, 0.0\n14: 100.0, 55.0, 42.5, 0.0\n15: 100.0, 55.0, 42.5, 7.5\n16: 100.0, 55.0, 42.5, 15.0\n17: 100.0, 55.0, 42.5, 22.5\n18: 100.0, 55.0, 42.5, 30.0\n19: 100.0, 57.5, 45.0, 32.5\n20: 100.0, 60.0, 47.5, 35.0\n21: 100.0, 62.5, 50.0, 37.5\n22: 100.0, 65.0, 52.5, 40.0\n23: 100.0, 67.5, 55.0, 42.5\n24: 100.0, 70.0, 57.5, 45.0" : ModConfig.CustomProgressionTable.Value, 
				_ => "1: 100.0, 0.0, 0.0, 0.0\n2: 100.0, 7.5, 0.0, 0.0\n3: 100.0, 15.0, 0.0, 0.0\n4: 100.0, 22.5, 0.0, 0.0\n5: 100.0, 30.0, 0.0, 0.0\n6: 100.0, 37.5, 0.0, 0.0\n7: 100.0, 45.0, 0.0, 0.0\n8: 100.0, 50.0, 2.5, 0.0\n9: 100.0, 50.0, 10.0, 0.0\n10: 100.0, 50.0, 17.5, 0.0\n11: 100.0, 50.0, 25.0, 0.0\n12: 100.0, 50.0, 32.5, 0.0\n13: 100.0, 52.5, 37.5, 0.0\n14: 100.0, 55.0, 42.5, 0.0\n15: 100.0, 55.0, 42.5, 7.5\n16: 100.0, 55.0, 42.5, 15.0\n17: 100.0, 55.0, 42.5, 22.5\n18: 100.0, 55.0, 42.5, 30.0\n19: 100.0, 57.5, 45.0, 32.5\n20: 100.0, 60.0, 47.5, 35.0\n21: 100.0, 62.5, 50.0, 37.5\n22: 100.0, 65.0, 52.5, 40.0\n23: 100.0, 67.5, 55.0, 42.5\n24: 100.0, 70.0, 57.5, 45.0", 
			});
			s_initialized = true;
		}

		private static void ParseTable(string raw)
		{
			Array.Clear(s_table, 0, s_table.Length);
			string[] array = raw.Split(new char[2] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
			int num = 1;
			string[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				string text = array2[i].Trim();
				if (string.IsNullOrEmpty(text) || text.StartsWith("#") || text.StartsWith("//"))
				{
					continue;
				}
				int num2 = text.IndexOf(':');
				string[] array3 = ((num2 >= 0) ? text.Substring(num2 + 1) : text).Split(new char[3] { ',', ';', ' ' }, StringSplitOptions.RemoveEmptyEntries);
				for (int j = 0; j < 4 && j < array3.Length; j++)
				{
					if (float.TryParse(array3[j], NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
					{
						s_table[num, j] = Mathf.Clamp(result, 0f, 100f);
					}
				}
				num++;
				if (num > 24)
				{
					break;
				}
			}
		}

		public static int ClampComfort(int comfort)
		{
			if (comfort < 1)
			{
				return 1;
			}
			if (comfort > 24)
			{
				return 24;
			}
			return comfort;
		}

		public static int GetActiveSlots(int comfort)
		{
			if (!s_initialized)
			{
				ReloadTable();
			}
			int num = ClampComfort(comfort);
			int num2 = 0;
			for (int i = 0; i < 4; i++)
			{
				if (s_table[num, i] > 0.001f)
				{
					num2++;
				}
			}
			return num2;
		}

		public static float GetSlotPercent(int slotIndex, int comfort)
		{
			if (!s_initialized)
			{
				ReloadTable();
			}
			if (slotIndex < 0 || slotIndex >= 4)
			{
				return 0f;
			}
			int num = ClampComfort(comfort);
			return s_table[num, slotIndex];
		}

		public static float GetSlotMultiplier(int slotIndex, int comfort)
		{
			return GetSlotPercent(slotIndex, comfort) * 0.01f * ModConfig.CommonScalingFactor.Value;
		}

		public static float CalculatePower(float basePower, int comfort, int slotIndex = 0)
		{
			return basePower * GetSlotMultiplier(slotIndex, comfort);
		}

		public static float CalculatePowerMultiplier(int comfort, int slotIndex = 0)
		{
			return GetSlotMultiplier(slotIndex, comfort);
		}
	}
	public static class RiteDatabase
	{
		private static readonly Dictionary<string, TrophyRite> ByPrefab;

		private static readonly Dictionary<TrophyId, TrophyRite> ById;

		private static RiteModifierFactory Flat(PhysicalStat stat, string label)
		{
			return (Player p, float val, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Flat(stat, val, label, (Func<Character, bool>)null, owner) };
		}

		private static RiteModifierFactory Increased(StatToken stat, string label, float factor = 0.01f)
		{
			return (Player p, float val, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Increased(stat, val * factor, label, (Func<Character, bool>)null, owner) };
		}

		private static RiteModifierFactory Multiplier(BaseStatToken stat, string label, float factor = 0.01f)
		{
			return (Player p, float val, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Multiplier(stat, 1f + val * factor, label, (Func<Character, bool>)null, owner) };
		}

		private static RiteModifierFactory Resistance(ResistanceStat stat, string label, float factor = 0.01f)
		{
			return (Player p, float val, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Multiplier((BaseStatToken)(object)stat, Math.Max(0f, 1f - val * factor), label, (Func<Character, bool>)null, owner) };
		}

		static RiteDatabase()
		{
			ByPrefab = new Dictionary<string, TrophyRite>(StringComparer.OrdinalIgnoreCase);
			ById = new Dictionary<TrophyId, TrophyRite>();
			Register(new TrophyRite(TrophyId.Boar, "TrophyBoar", "Gluttonous Digestion", "Boar", "Meadows", 50f, "%", "+{0}{1} Food Duration", Increased((StatToken)(object)CharacterStats.FoodDurationMultiplier, "Gluttonous Digestion")));
			Register(new TrophyRite(TrophyId.Deer, "TrophyDeer", "Stag's Stride", "Deer", "Meadows", 60f, "%", "+{0}{1} Stamina Regeneration Rate", Increased((StatToken)(object)CharacterStats.StaminaRegen, "Stag's Stride")));
			Register(new TrophyRite(TrophyId.Neck, "TrophyNeck", "Forager's Eye", "Neck", "Meadows", 25f, "%", "{0}{1} Double Gather Chance", Increased((StatToken)(object)CharacterStats.ForagingYield, "Forager's Eye")));
			Register(new TrophyRite(TrophyId.Greydwarf, "TrophyGreydwarf", "Timberjack", "Greydwarf", "Black Forest", 40f, "%", "+{0}{1} Wood Chopping Damage", Increased((StatToken)(object)CharacterStats.DamageChop, "Timberjack")));
			Register(new TrophyRite(TrophyId.GreydwarfBrute, "TrophyGreydwarfBrute", "Brute Force", "Greydwarf Brute", "Black Forest", 30f, "%", "+{0}{1} Blunt Damage Dealt", Increased((StatToken)(object)CharacterStats.DamageBlunt, "Brute Force")));
			Register(new TrophyRite(TrophyId.GreydwarfShaman, "TrophyGreydwarfShaman", "Regrowth", "Greydwarf Shaman", "Black Forest", 50f, "%", "+{0}{1} Health Regeneration", Increased((StatToken)(object)CharacterStats.HealthRegen, "Regrowth")));
			Register(new TrophyRite(TrophyId.Skeleton, "TrophySkeleton", "Deadeye", "Skeleton", "Black Forest", 30f, "%", "+{0}{1} Ranged Damage Dealt", Increased((StatToken)(object)CharacterStats.DamageRanged, "Deadeye"), "TrophySkeletonHildir"));
			Register(new TrophyRite(TrophyId.RancidRemains, "TrophySkeletonPoison", "Festering Touch", "Rancid Remains", "Black Forest", 40f, "%", "+{0}{1} Physical Hit as Poison DoT (5s)", Increased((StatToken)(object)CharacterStats.DamagePoison, "Festering Touch")));
			Register(new TrophyRite(TrophyId.Troll, "TrophyFrostTroll", "Giant's Reach", "Troll", "Black Forest", 20f, "%", "+{0}{1} Melee Reach", Multiplier((BaseStatToken)(object)CharacterStats.MeleeReach, "Giant's Reach"), "TrophyForestTroll"));
			Register(new TrophyRite(TrophyId.Ghost, "TrophyGhost", "Ethereal Form", "Ghost", "Black Forest", 25f, "%", "-{0}{1} Physical Damage Taken", Resistance(CharacterStats.ResistancePhysical, "Ethereal Form")));
			Register(new TrophyRite(TrophyId.Abomination, "TrophyAbomination", "Ancient Slumber", "Abomination", "Swamp", 1f, "m", "+{0}{1} Rested Duration per Comfort Level", null));
			Register(new TrophyRite(TrophyId.Blob, "TrophyBlob", "Gelatinous", "Blob", "Swamp", 60f, "HP", "+{0} Max Health", Flat(CharacterStats.MaxHealth, "Gelatinous")));
			Register(new TrophyRite(TrophyId.Draugr, "TrophyDraugr", "Ambush", "Draugr", "Swamp", 2f, "x", "+{0}x Sneak Attack Multiplier", Increased((StatToken)(object)CharacterStats.DamageSneak, "Ambush", 1f), "TrophyDraugrFem"));
			Register(new TrophyRite(TrophyId.DraugrElite, "TrophyDraugrElite", "Warrior's Edge", "Draugr Elite", "Swamp", 30f, "%", "+{0}{1} Slashing Damage Dealt", Increased((StatToken)(object)CharacterStats.DamageSlashing, "Warrior's Edge")));
			Register(new TrophyRite(TrophyId.Leech, "TrophyLeech", "Sanguine Harvest", "Leech", "Swamp", 6f, "HP", "+{0} HP on Kill", Flat(CharacterStats.HealthOnKill, "Sanguine Harvest")));
			Register(new TrophyRite(TrophyId.Surtling, "TrophySurtling", "Fireward", "Surtling", "Swamp", 30f, "%", "-{0}{1} Fire Damage Taken", Resistance(CharacterStats.ResistanceFire, "Fireward")));
			Register(new TrophyRite(TrophyId.Wraith, "TrophyWraith", "Gliding Shroud", "Wraith", "Swamp", 90f, "%", "-{0}{1} Fall Damage & +50% Jump Height", (Player p, float val, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[2]
			{
				StatModifier.Multiplier((BaseStatToken)(object)CharacterStats.ResistanceFall, Math.Max(0f, 1f - val * 0.01f), "Gliding Shroud", (Func<Character, bool>)null, owner),
				StatModifier.Increased((StatToken)(object)CharacterStats.JumpHeight, 0.5f * (val / 90f), "Gliding Shroud", (Func<Character, bool>)null, owner)
			}));
			Register(new TrophyRite(TrophyId.Bat, "TrophyBat", "Nocturnal Hunter", "Bat", "Mountains", 35f, "%", "+{0}{1} Damage at Night", Increased((StatToken)(object)CharacterStats.DamageAtNight, "Nocturnal Hunter")));
			Register(new TrophyRite(TrophyId.Cultist, "TrophyCultist", "Inner Flame", "Cultist", "Mountains", 70f, "%", "+{0}{1} Eitr Regeneration", Increased((StatToken)(object)CharacterStats.EitrRegen, "Inner Flame"), "TrophyCultistHildir"));
			Register(new TrophyRite(TrophyId.Drake, "TrophyHatchling", "Frostveil", "Drake", "Mountains", 30f, "%", "-{0}{1} Frost Damage Taken", Resistance(CharacterStats.ResistanceFrost, "Frostveil")));
			Register(new TrophyRite(TrophyId.Fenring, "TrophyFenring", "Predator's Rush", "Fenring", "Mountains", 35f, "%", "+{0}{1} Move Speed for 4s on Hit", null));
			Register(new TrophyRite(TrophyId.StoneGolem, "TrophySGolem", "Crag Shatter", "Stone Golem", "Mountains", 40f, "%", "+{0}{1} Pickaxe Damage to Stone & Ore", Increased((StatToken)(object)CharacterStats.DamagePickaxe, "Crag Shatter")));
			Register(new TrophyRite(TrophyId.Ulv, "TrophyUlv", "Feral Haste", "Ulv", "Mountains", 15f, "%", "+{0}{1} Melee Attack Swing Speed", Increased((StatToken)(object)CharacterStats.AttackSpeed, "Feral Haste")));
			Register(new TrophyRite(TrophyId.Wolf, "TrophyWolf", "Pack Pace", "Wolf", "Mountains", 20f, "%", "+{0}{1} Movement Speed", (Player p, float val, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[2]
			{
				StatModifier.Increased((StatToken)(object)CharacterStats.JogSpeed, val * 0.01f, "Pack Pace", (Func<Character, bool>)null, owner),
				StatModifier.Increased((StatToken)(object)CharacterStats.RunSpeed, val * 0.01f, "Pack Pace", (Func<Character, bool>)null, owner)
			}));
			Register(new TrophyRite(TrophyId.Deathsquito, "TrophyDeathSquito", "Needle Sting", "Deathsquito", "Plains", 30f, "%", "+{0}{1} Piercing Damage Dealt", Increased((StatToken)(object)CharacterStats.DamagePiercing, "Needle Sting")));
			Register(new TrophyRite(TrophyId.Fuling, "TrophyGoblin", "Opportunist", "Fuling", "Plains", 50f, "%", "+{0}{1} Damage vs Staggered Targets", Increased((StatToken)(object)CharacterStats.DamageAgainstStaggered, "Opportunist")));
			Register(new TrophyRite(TrophyId.FulingBerserker, "TrophyGoblinBrute", "Unbridled Fury", "Fuling Berserker", "Plains", 40f, "%", "+{0}{1} Stagger Buildup Dealt", Increased((StatToken)(object)CharacterStats.StaggerDamage, "Unbridled Fury"), "TrophyGoblinBruteBrosShaman"));
			Register(new TrophyRite(TrophyId.FulingShaman, "TrophyGoblinShaman", "Totemic Endurance", "Fuling Shaman", "Plains", 60f, "Stamina", "+{0} Max Stamina", Flat(CharacterStats.MaxStamina, "Totemic Endurance")));
			Register(new TrophyRite(TrophyId.Growth, "TrophyGrowth", "Tar Coating", "Growth", "Plains", 75f, "%", "{0}{1} Heavy / 40% Light Tar Proc Chance (8s)", null));
			Register(new TrophyRite(TrophyId.Lox, "TrophyLox", "Laborer's Mettle", "Lox", "Plains", 100f, "%", "+{0}{1} Tool Stamina Efficiency", Increased((StatToken)(object)CharacterStats.ToolStaminaEfficiency, "Laborer's Mettle")));
			Register(new TrophyRite(TrophyId.Vile, "TrophyBjornUndead", "Last Stand", "Vile", "Plains", 35f, "%", "Survive Lethal Blow with {0}{1} Max HP (10m CD)", null));
			Register(new TrophyRite(TrophyId.Serpent, "TrophySerpent", "Leviathan Glide", "Serpent", "Ocean", 100f, "%", "+{0}{1} Swim Speed", Increased((StatToken)(object)CharacterStats.SwimSpeed, "Leviathan Glide")));
			Register(new TrophyRite(TrophyId.Hare, "TrophyHare", "Bunny's Hop", "Hare", "Mistlands", 100f, "%", "+{0}{1} Jump Stamina Efficiency", Increased((StatToken)(object)CharacterStats.JumpEfficiency, "Bunny's Hop")));
			Register(new TrophyRite(TrophyId.Gjall, "TrophyGjall", "Gjall's Inferno", "Gjall", "Mistlands", 30f, "%", "+{0}{1} Elemental Magic Damage", Increased((StatToken)(object)CharacterStats.DamageElementalMagic, "Gjall's Inferno")));
			Register(new TrophyRite(TrophyId.Seeker, "TrophySeeker", "Razor Precision", "Seeker", "Mistlands", 25f, "%", "+{0}{1} Critical Strike Chance", (Player p, float val, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Flat(CharacterStats.CriticalStrikeChance, val * 0.01f, "Razor Precision", (Func<Character, bool>)null, owner) }));
			Register(new TrophyRite(TrophyId.SeekerSoldier, "TrophySeekerBrute", "Carapace Ward", "Seeker Soldier", "Mistlands", 1f, "s", "-80% Damage on First Hit ({0}{1} CD)", null));
			Register(new TrophyRite(TrophyId.Tick, "TrophyTick", "Spare Vitality", "Tick", "Mistlands", 50f, "%", "+{0}{1} Blood Magic Health Efficiency", Increased((StatToken)(object)CharacterStats.AttackHealthEfficiency, "Spare Vitality")));
			Register(new TrophyRite(TrophyId.Dvergr, "TrophyDvergr", "Dvergr's Wisdom", "Dvergr", "Mistlands", 50f, "%", "+{0}{1} Skill Experience Gain", null));
			Register(new TrophyRite(TrophyId.Asksvin, "TrophyAsksvin", "Cavalry Charge", "Asksvin", "Ashlands", 40f, "%", "+{0}{1} Mount Speed & Efficiency", (Player p, float val, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[2]
			{
				StatModifier.Increased((StatToken)(object)CharacterStats.RidingSpeed, val * 0.01f, "Cavalry Charge", (Func<Character, bool>)null, owner),
				StatModifier.Increased((StatToken)(object)CharacterStats.RidingStaminaEfficiency, val * 0.01f, "Cavalry Charge", (Func<Character, bool>)null, owner)
			}));
			Register(new TrophyRite(TrophyId.BonemawSerpent, "TrophyBonemawSerpent", "Sea Drake's Wake", "Bonemaw Serpent", "Ashlands", 45f, "%", "+{0}{1} Ship Sailing Speed", Increased((StatToken)(object)CharacterStats.ShipSailSpeed, "Sea Drake's Wake")));
			Register(new TrophyRite(TrophyId.FallenValkyrie, "TrophyFallenValkyrie", "Valkyrie's Aether", "Fallen Valkyrie", "Ashlands", 60f, "Eitr", "+{0} Max Eitr", Flat(CharacterStats.MaxEitr, "Valkyrie's Aether")));
			Register(new TrophyRite(TrophyId.CharredMarksman, "TrophyCharredArcher", "Snapdraw", "Charred Marksman", "Ashlands", 45f, "%", "+{0}{1} Draw & Reload Speed", (Player p, float val, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[2]
			{
				StatModifier.Increased((StatToken)(object)CharacterStats.BowDrawSpeed, val * 0.01f, "Snapdraw", (Func<Character, bool>)null, owner),
				StatModifier.Increased((StatToken)(object)CharacterStats.CrossbowReloadSpeed, val * 0.01f, "Snapdraw", (Func<Character, bool>)null, owner)
			}));
			Register(new TrophyRite(TrophyId.Morgen, "TrophyMorgen", "Morgen's Cull", "Morgen", "Ashlands", 50f, "%", "+{0}{1} Damage vs Low Health (<35% HP)", Increased((StatToken)(object)CharacterStats.DamageExecute, "Morgen's Cull")));
			Register(new TrophyRite(TrophyId.Volture, "TrophyVolture", "Wingshield", "Volture", "Ashlands", 75f, "%", "+{0}{1} Block Stamina Efficiency", Increased((StatToken)(object)CharacterStats.BlockStaminaEfficiency, "Wingshield")));
			Register(new TrophyRite(TrophyId.CharredWarlock, "TrophyCharredMage", "Cinder Shield", "Charred Warlock", "Ashlands", 20f, "%", "-{0}{1} Elemental Damage Taken", Resistance(CharacterStats.ResistanceElemental, "Cinder Shield")));
			Register(new TrophyRite(TrophyId.CharredWarrior, "TrophyCharredMelee", "Juggernaut", "Charred Warrior", "Ashlands", 25f, "%", "+{0}{1} 2-Handed Weapon Damage", Increased((StatToken)(object)CharacterStats.DamageTwoHanded, "Juggernaut")));
			Register(new TrophyRite(TrophyId.Bear, "TrophyBjorn", "Ursine Ferocity", "Bear", "Deep North", 50f, "%", "+{0}{1} Berserk Damage (<35% HP)", Increased((StatToken)(object)CharacterStats.DamageBerserk, "Ursine Ferocity")));
			Register(new TrophyRite(TrophyId.Seal, "TrophySeal", "Aquatic Endurance", "Seal", "Deep North", 100f, "%", "+{0}{1} Swim Stamina Efficiency", Increased((StatToken)(object)CharacterStats.SwimEfficiency, "Aquatic Endurance")));
			Register(new TrophyRite(TrophyId.Moose, "TrophyMoose", "Draft Hauler", "Moose", "Deep North", 75f, "%", "+{0}{1} Cart Cargo Efficiency", Increased((StatToken)(object)CharacterStats.CartWeightEfficiency, "Draft Hauler")));
			Register(new TrophyRite(TrophyId.Mole, "TrophyMole", "Subterranean Greed", "Mole", "Deep North", 30f, "%", "+{0}{1} Mining Yield & Drop Rolls", Increased((StatToken)(object)CharacterStats.MiningYield, "Subterranean Greed")));
			Register(new TrophyRite(TrophyId.Barka, "TrophyBarka", "Frosted Hide", "Barka", "Deep North", 25f, "Armor", "+{0} Base Armor", Flat(CharacterStats.BodyArmor, "Frosted Hide")));
			Register(new TrophyRite(TrophyId.FrostBlob, "TrophyBlob_Frost", "Numbing Touch", "Frost Blob", "Deep North", 75f, "%", "{0}{1} Heavy / 40% Light Chill Attack Proc (8s)", null));
			Register(new TrophyRite(TrophyId.LavaBlob, "TrophyBlob_Lava", "Furnace Core", "Lava Blob", "Deep North", 25f, "%", "+{0}{1} Cooking Extra Yield", Increased((StatToken)(object)CharacterStats.CookingYield, "Furnace Core")));
			Register(new TrophyRite(TrophyId.JotunnWarrior, "TrophyJotunWarrior", "Titan's Swat", "Jötunn Warrior", "Deep North", 60f, "%", "+{0}{1} Knockback Force Dealt", Increased((StatToken)(object)CharacterStats.KnockbackDealt, "Titan's Swat")));
			Register(new TrophyRite(TrophyId.JotunnWitch, "TrophyJotunWitch", "Rime Weaver", "Jötunn Witch", "Deep North", 35f, "%", "+{0}{1} Eitr Spell Efficiency", Increased((StatToken)(object)CharacterStats.AttackEitrEfficiency, "Rime Weaver")));
			Register(new TrophyRite(TrophyId.Brenna, "TrophySkeletonHildir", "Brenna's Pyre", "Brenna", "Hildir's Request", 35f, "%", "Crits/Sneak Hits trigger a Fireball Blast ({0}{1} AoE Fire)", null));
			Register(new TrophyRite(TrophyId.Geirrhafa, "TrophyCultist_Hildir", "Mountain Prowler", "Geirrhafa", "Hildir's Request", 35f, "%", "+{0}{1} Dodge Stamina Efficiency", Increased((StatToken)(object)CharacterStats.DodgeEfficiency, "Mountain Prowler")));
			Register(new TrophyRite(TrophyId.Zil, "TrophyGoblinBruteBrosShaman", "Shamanic Aegis", "Zil", "Hildir's Request", 12f, "%", "+{0}{1} Physical & Elemental Damage Reduction", (Player p, float val, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[2]
			{
				StatModifier.Multiplier((BaseStatToken)(object)CharacterStats.ResistancePhysical, Math.Max(0f, 1f - val * 0.01f), "Shamanic Aegis", (Func<Character, bool>)null, owner),
				StatModifier.Multiplier((BaseStatToken)(object)CharacterStats.ResistanceElemental, Math.Max(0f, 1f - val * 0.01f), "Shamanic Aegis", (Func<Character, bool>)null, owner)
			}));
			Register(new TrophyRite(TrophyId.Steil, "TrophyGoblinBruteBrosBrute", "Unstoppable Poise", "Steil", "Hildir's Request", 75f, "%", "+{0}{1} Stagger Poise Threshold", Increased((StatToken)(object)CharacterStats.StaggerResistance, "Unstoppable Poise")));
		}

		public static void Register(TrophyRite rite)
		{
			ById[rite.Id] = rite;
			ByPrefab[rite.PrefabName] = rite;
			string[] alternatePrefabs = rite.AlternatePrefabs;
			foreach (string text in alternatePrefabs)
			{
				if (!string.IsNullOrEmpty(text))
				{
					ByPrefab[text] = rite;
				}
			}
		}

		public static bool TryGetRite(string prefabName, out TrophyRite rite)
		{
			return ByPrefab.TryGetValue(prefabName, out rite);
		}

		public static bool TryGetRite(TrophyId id, out TrophyRite rite)
		{
			return ById.TryGetValue(id, out rite);
		}

		public static IEnumerable<TrophyRite> GetAllRites()
		{
			return ById.Values;
		}
	}
	public static class SetDatabase
	{
		private static readonly Dictionary<SetId, TrophySet> SetsById;

		private static readonly Dictionary<TrophyId, TrophySet> SetByTrophy;

		public static bool IsNearTree(Vector3 pos, float radius)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			Collider[] array = Physics.OverlapSphere(pos, radius);
			foreach (Collider val in array)
			{
				if ((Object)(object)val != (Object)null && ((Object)(object)((Component)val).GetComponentInParent<TreeBase>() != (Object)null || (Object)(object)((Component)val).GetComponentInParent<TreeLog>() != (Object)null))
				{
					return true;
				}
			}
			return false;
		}

		static SetDatabase()
		{
			SetsById = new Dictionary<SetId, TrophySet>();
			SetByTrophy = new Dictionary<TrophyId, TrophySet>();
			Register(new TrophySet(SetId.PioneersOfTheWilds, "Pioneers of the Wilds", new TrophyId[4]
			{
				TrophyId.Boar,
				TrophyId.Deer,
				TrophyId.Neck,
				TrophyId.Hare
			}, "+15% Sprint Stamina Efficiency when carry weight is below 50%", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Increased((StatToken)(object)CharacterStats.SprintEfficiency, 0.15f, "Pioneers of the Wilds (2pc)", (Func<Character, bool>)delegate(Character c)
			{
				Player val = (Player)(object)((c is Player) ? c : null);
				return val != null && ((Humanoid)val).GetInventory().GetTotalWeight() < val.GetMaxCarryWeight() * 0.5f;
			}, owner) }, "+5% Double gather & drop roll yield", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Increased((StatToken)(object)CharacterStats.ForagingYield, 0.05f, "Pioneers of the Wilds (3pc)", (Func<Character, bool>)null, owner) }, "+25% Movement Speed", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[2]
			{
				StatModifier.Increased((StatToken)(object)CharacterStats.JogSpeed, 0.25f, "Pioneers of the Wilds (4pc)", (Func<Character, bool>)null, owner),
				StatModifier.Increased((StatToken)(object)CharacterStats.RunSpeed, 0.25f, "Pioneers of the Wilds (4pc)", (Func<Character, bool>)null, owner)
			}));
			Register(new TrophySet(SetId.TheRestlessBarrow, "The Restless Barrow", new TrophyId[4]
			{
				TrophyId.Skeleton,
				TrophyId.RancidRemains,
				TrophyId.Ghost,
				TrophyId.Wraith
			}, "-35% Piercing damage taken", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Multiplier((BaseStatToken)(object)CharacterStats.ResistancePiercing, 0.65f, "The Restless Barrow (2pc)", (Func<Character, bool>)null, owner) }, "+1.0x Sneak attack damage multiplier", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Increased((StatToken)(object)CharacterStats.DamageSneak, 1f, "The Restless Barrow (3pc)", (Func<Character, bool>)null, owner) }, "+20% Sneak movement speed & +35% Sneak Stamina Efficiency", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[2]
			{
				StatModifier.Increased((StatToken)(object)CharacterStats.CrouchSpeed, 0.2f, "The Restless Barrow (4pc)", (Func<Character, bool>)null, owner),
				StatModifier.Increased((StatToken)(object)CharacterStats.SneakEfficiency, 0.35f, "The Restless Barrow (4pc)", (Func<Character, bool>)null, owner)
			}));
			Register(new TrophySet(SetId.TheEarthshakers, "The Earthshakers", new TrophyId[4]
			{
				TrophyId.Troll,
				TrophyId.StoneGolem,
				TrophyId.Morgen,
				TrophyId.JotunnWarrior
			}, "+40% Pickaxe damage to rocks, ore deposits, and barriers", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Increased((StatToken)(object)CharacterStats.DamagePickaxe, 0.4f, "The Earthshakers (2pc)", (Func<Character, bool>)null, owner) }, "+25% Knockback force dealt & stagger power", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[2]
			{
				StatModifier.Increased((StatToken)(object)CharacterStats.KnockbackDealt, 0.25f, "The Earthshakers (3pc)", (Func<Character, bool>)null, owner),
				StatModifier.Increased((StatToken)(object)CharacterStats.StaggerDamage, 0.25f, "The Earthshakers (3pc)", (Func<Character, bool>)null, owner)
			}, "+35% Multi-target cleave damage efficiency", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Increased((StatToken)(object)CharacterStats.CleaveEfficiency, 0.35f, "The Earthshakers (4pc)", (Func<Character, bool>)null, owner) }));
			Register(new TrophySet(SetId.ThePlainsTribe, "The Plains Tribe", new TrophyId[4]
			{
				TrophyId.Fuling,
				TrophyId.Surtling,
				TrophyId.Wolf,
				TrophyId.Growth
			}, "+25% Damage vs tarred, slowed, or staggered enemies", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Increased((StatToken)(object)CharacterStats.DamageAgainstAfflicted, 0.25f, "The Plains Tribe (2pc)", (Func<Character, bool>)null, owner) }, "+25 Max Stamina & +20% Dodge Stamina Efficiency", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[2]
			{
				StatModifier.Flat(CharacterStats.MaxStamina, 25f, "The Plains Tribe (3pc)", (Func<Character, bool>)null, owner),
				StatModifier.Increased((StatToken)(object)CharacterStats.DodgeEfficiency, 0.2f, "The Plains Tribe (3pc)", (Func<Character, bool>)null, owner)
			}, "Adds +15% Fire damage to all physical damage dealt"));
			Register(new TrophySet(SetId.BeastmastersOfTheHearth, "Beastmasters of the Hearth", new TrophyId[4]
			{
				TrophyId.Lox,
				TrophyId.Asksvin,
				TrophyId.Bear,
				TrophyId.Moose
			}, "+75% Stamina regeneration while standing completely still", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Increased((StatToken)(object)CharacterStats.StaminaRegen, 0.75f, "Beastmasters of the Hearth (2pc)", (Func<Character, bool>)delegate(Character c)
			{
				//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)
				Vector3 velocity = c.GetVelocity();
				return ((Vector3)(ref velocity)).sqrMagnitude < 0.05f;
			}, owner) }, "+75% Cart Cargo Efficiency & +25% Tool Stamina Efficiency", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[2]
			{
				StatModifier.Increased((StatToken)(object)CharacterStats.CartWeightEfficiency, 0.75f, "Beastmasters of the Hearth (3pc)", (Func<Character, bool>)null, owner),
				StatModifier.Increased((StatToken)(object)CharacterStats.ToolStaminaEfficiency, 0.25f, "Beastmasters of the Hearth (3pc)", (Func<Character, bool>)null, owner)
			}, "+50% Mount Stamina Efficiency and +20% Mount Speed", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[2]
			{
				StatModifier.Increased((StatToken)(object)CharacterStats.RidingStaminaEfficiency, 0.5f, "Beastmasters of the Hearth (4pc)", (Func<Character, bool>)null, owner),
				StatModifier.Increased((StatToken)(object)CharacterStats.RidingSpeed, 0.2f, "Beastmasters of the Hearth (4pc)", (Func<Character, bool>)null, owner)
			}));
			Register(new TrophySet(SetId.WeaversOfEitr, "Weavers of Eitr", new TrophyId[4]
			{
				TrophyId.Cultist,
				TrophyId.Gjall,
				TrophyId.FallenValkyrie,
				TrophyId.JotunnWitch
			}, "+15% Eitr regeneration & +10% Spell Eitr Efficiency", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[2]
			{
				StatModifier.Increased((StatToken)(object)CharacterStats.EitrRegen, 0.15f, "Weavers of Eitr (2pc)", (Func<Character, bool>)null, owner),
				StatModifier.Increased((StatToken)(object)CharacterStats.AttackEitrEfficiency, 0.1f, "Weavers of Eitr (2pc)", (Func<Character, bool>)null, owner)
			}, "+30 Max Eitr", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Flat(CharacterStats.MaxEitr, 30f, "Weavers of Eitr (3pc)", (Func<Character, bool>)null, owner) }, "+25% Spell Eitr Efficiency", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Increased((StatToken)(object)CharacterStats.AttackEitrEfficiency, 0.25f, "Weavers of Eitr (4pc)", (Func<Character, bool>)null, owner) }));
			Register(new TrophySet(SetId.ChildrenOfTheForest, "Children of the Forest", new TrophyId[3]
			{
				TrophyId.Greydwarf,
				TrophyId.GreydwarfBrute,
				TrophyId.GreydwarfShaman
			}, "+20% Wood yield from trees", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Increased((StatToken)(object)CharacterStats.WoodcuttingYield, 0.2f, "Children of the Forest (2pc)", (Func<Character, bool>)null, owner) }, "+20% Health regeneration within 20m of any tree", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Increased((StatToken)(object)CharacterStats.HealthRegen, 0.2f, "Children of the Forest (3pc)", (Func<Character, bool>)((Character c) => IsNearTree(((Component)c).transform.position, 20f)), owner) }));
			Register(new TrophySet(SetId.TheDraugrRevenants, "The Draugr Revenants", new TrophyId[3]
			{
				TrophyId.Draugr,
				TrophyId.DraugrElite,
				TrophyId.Vile
			}, "+40% Stagger buildup on sneak attacks", null, "50% Cooldown reduction on Last Stand (down to 5m) & restores full stamina"));
			Register(new TrophySet(SetId.TheGelatinousHorde, "The Gelatinous Horde", new TrophyId[3]
			{
				TrophyId.Blob,
				TrophyId.FrostBlob,
				TrophyId.LavaBlob
			}, "+25% Jump height & -50% fall damage", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[2]
			{
				StatModifier.Increased((StatToken)(object)CharacterStats.JumpHeight, 0.25f, "The Gelatinous Horde (2pc)", (Func<Character, bool>)null, owner),
				StatModifier.Multiplier((BaseStatToken)(object)CharacterStats.ResistanceFall, 0.5f, "The Gelatinous Horde (2pc)", (Func<Character, bool>)null, owner)
			}, "Slime Splash: Melee hits suffered emit slime chilling attackers"));
			Register(new TrophySet(SetId.TheBloodbound, "The Bloodbound", new TrophyId[3]
			{
				TrophyId.Bat,
				TrophyId.Leech,
				TrophyId.CharredWarrior
			}, "+20 Stamina restored on kill", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Flat(CharacterStats.StaminaOnKill, 20f, "The Bloodbound (2pc)", (Func<Character, bool>)null, owner) }, "2x Damage on your next attack after killing an enemy"));
			Register(new TrophySet(SetId.TheHiveChitin, "The Hive Chitin", new TrophyId[3]
			{
				TrophyId.Seeker,
				TrophyId.SeekerSoldier,
				TrophyId.Tick
			}, "+15 Base Armor", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Flat(CharacterStats.BodyArmor, 15f, "The Hive Chitin (2pc)", (Func<Character, bool>)null, owner) }, "Carapace Counter: Reflect 50% damage when Carapace Ward triggers"));
			Register(new TrophySet(SetId.UndergroundDelvers, "Underground Delvers", new TrophyId[3]
			{
				TrophyId.Dvergr,
				TrophyId.Mole,
				TrophyId.Barka
			}, "+100% Tool and Weapon Durability Efficiency", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Increased((StatToken)(object)CharacterStats.DurabilityEfficiency, 1f, "Underground Delvers (2pc)", (Func<Character, bool>)null, owner) }, "+20% Mining yield & +10 Armor in caves and crypts", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[2]
			{
				StatModifier.Increased((StatToken)(object)CharacterStats.MiningYield, 0.2f, "Underground Delvers (3pc)", (Func<Character, bool>)null, owner),
				StatModifier.Flat(CharacterStats.BodyArmor, 10f, "Underground Delvers (3pc)", (Func<Character, bool>)delegate(Character c)
				{
					Player val = (Player)(object)((c is Player) ? c : null);
					return val != null && ((Character)val).InInterior();
				}, owner)
			}));
			Register(new TrophySet(SetId.TidecallersOfTheAbyss, "Tidecallers of the Abyss", new TrophyId[3]
			{
				TrophyId.Serpent,
				TrophyId.BonemawSerpent,
				TrophyId.Seal
			}, "+50% Swim Stamina Efficiency & +30% damage reduction in water", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[3]
			{
				StatModifier.Increased((StatToken)(object)CharacterStats.SwimEfficiency, 0.5f, "Tidecallers of the Abyss (2pc)", (Func<Character, bool>)null, owner),
				StatModifier.Multiplier((BaseStatToken)(object)CharacterStats.ResistancePhysical, 0.7f, "Tidecallers of the Abyss (2pc)", (Func<Character, bool>)((Character c) => c.InWater()), owner),
				StatModifier.Multiplier((BaseStatToken)(object)CharacterStats.ResistanceElemental, 0.7f, "Tidecallers of the Abyss (2pc)", (Func<Character, bool>)((Character c) => c.InWater()), owner)
			}, "+15% Ship sailing speed", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Increased((StatToken)(object)CharacterStats.ShipSailSpeed, 0.15f, "Tidecallers of the Abyss (3pc)", (Func<Character, bool>)null, owner) }));
			Register(new TrophySet(SetId.WingsOfPrey, "Wings of Prey", new TrophyId[3]
			{
				TrophyId.Drake,
				TrophyId.Deathsquito,
				TrophyId.Volture
			}, "+15% Piercing damage & +20% Shield Block Stamina Efficiency", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[3]
			{
				StatModifier.Increased((StatToken)(object)CharacterStats.DamagePiercing, 0.15f, "Wings of Prey (2pc)", (Func<Character, bool>)null, owner),
				StatModifier.Increased((StatToken)(object)CharacterStats.BlockStaminaEfficiency, 0.2f, "Wings of Prey (2pc)", (Func<Character, bool>)null, owner),
				StatModifier.Increased((StatToken)(object)CharacterStats.BowDrawStaminaEfficiency, 0.2f, "Wings of Prey (2pc)", (Func<Character, bool>)null, owner)
			}, "Dive Bomb: Attacks from mid-air or elevation deal +35% damage", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Increased((StatToken)(object)CharacterStats.DamageWhileAirborne, 0.35f, "Wings of Prey (3pc)", (Func<Character, bool>)null, owner) }));
			Register(new TrophySet(SetId.TheGoblinChieftains, "The Goblin Chieftains", new TrophyId[2]
			{
				TrophyId.FulingBerserker,
				TrophyId.FulingShaman
			}, "+15 Stamina restored upon staggering an enemy", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Flat(CharacterStats.StaminaOnCauseStagger, 15f, "The Goblin Chieftains (2pc)", (Func<Character, bool>)null, owner) }));
			Register(new TrophySet(SetId.TheFenrisKin, "The Fenris Kin", new TrophyId[2]
			{
				TrophyId.Fenring,
				TrophyId.Ulv
			}, "+30% Damage on the 3rd hit of weapon combo chains", (Player p, object owner) => (IEnumerable<StatModifier>)(object)new StatModifier[1] { StatModifier.Increased((StatToken)(object)CharacterStats.DamageComboFinisher, 0.3f, "The Fenris Kin (2pc)", (Func<Character, bool>)null, owner) }));
			Register(new TrophySet(SetId.TheCharredDuo, "The Charred Duo", new TrophyId[2]
			{
				TrophyId.CharredMarksman,
				TrophyId.CharredWarlock
			}, "+25% Damage dealt with elemental arrows"));
		}

		private static void Register(TrophySet set)
		{
			SetsById[set.Id] = set;
			TrophyId[] members = set.Members;
			foreach (TrophyId key in members)
			{
				SetByTrophy[key] = set;
			}
		}

		public static IEnumerable<TrophySet> GetAllSets()
		{
			return SetsById.Values;
		}

		public static bool TryGetSet(SetId id, out TrophySet set)
		{
			return SetsById.TryGetValue(id, out set);
		}

		public static bool TryGetSetForTrophy(TrophyId trophy, out TrophySet set)
		{
			return SetByTrophy.TryGetValue(trophy, out set);
		}
	}
	public enum SetId
	{
		PioneersOfTheWilds,
		TheRestlessBarrow,
		TheEarthshakers,
		ThePlainsTribe,
		BeastmastersOfTheHearth,
		WeaversOfEitr,
		ChildrenOfTheForest,
		TheDraugrRevenants,
		TheGelatinousHorde,
		TheBloodbound,
		TheHiveChitin,
		UndergroundDelvers,
		TidecallersOfTheAbyss,
		WingsOfPrey,
		TheGoblinChieftains,
		TheFenrisKin,
		TheCharredDuo
	}
	public enum TrophyId
	{
		Boar,
		Deer,
		Neck,
		Greydwarf,
		GreydwarfBrute,
		GreydwarfShaman,
		Skeleton,
		RancidRemains,
		Troll,
		Ghost,
		Abomination,
		Blob,
		Draugr,
		DraugrElite,
		Leech,
		Surtling,
		Wraith,
		Bat,
		Cultist,
		Drake,
		Fenring,
		StoneGolem,
		Ulv,
		Wolf,
		Deathsquito,
		Fuling,
		FulingBerserker,
		FulingShaman,
		Growth,
		Lox,
		Vile,
		Serpent,
		Hare,
		Gjall,
		Seeker,
		SeekerSoldier,
		Tick,
		Dvergr,
		Asksvin,
		BonemawSerpent,
		FallenValkyrie,
		CharredMarksman,
		Morgen,
		Volture,
		CharredWarlock,
		CharredWarrior,
		Bear,
		Seal,
		Moose,
		Mole,
		Barka,
		FrostBlob,
		LavaBlob,
		JotunnWarrior,
		JotunnWitch,
		Brenna,
		Geirrhafa,
		Zil,
		Steil
	}
	public delegate IEnumerable<StatModifier> RiteModifierFactory(Player player, float power, object owner);
	public class TrophyRite
	{
		public TrophyId Id { get; }

		public string PrefabName { get; }

		public string[] AlternatePrefabs { get; }

		public string DisplayName { get; }

		public string CreatureName { get; }

		public string Category { get; }

		public float BaseMagnitude { get; }

		public string StatUnit { get; }

		public string DescriptionFormat { get; }

		public RiteModifierFactory? ModifierFactory { get; }

		public TrophyRite(TrophyId id, string prefabName, string displayName, string creatureName, string category, float baseMagnitude, string statUnit, string descriptionFormat, RiteModifierFactory? modifierFactory = null, params string[] alternatePrefabs)
		{
			Id = id;
			PrefabName = prefabName;
			DisplayName = displayName;
			CreatureName = creatureName;
			Category = category;
			BaseMagnitude = baseMagnitude;
			StatUnit = statUnit;
			DescriptionFormat = descriptionFormat;
			ModifierFactory = modifierFactory;
			AlternatePrefabs = alternatePrefabs ?? Array.Empty<string>();
		}

		public float GetCalculatedMagnitude(int playerComfort, int slotIndex = 0)
		{
			return PowerCalculator.CalculatePower(BaseMagnitude, playerComfort, slotIndex);
		}

		public string GetFormattedDescription(int playerComfort, int slotIndex = 0)
		{
			if (Id == TrophyId.SeekerSoldier)
			{
				float calculatedMagnitude = GetCalculatedMagnitude(playerComfort, slotIndex);
				float num = ((calculatedMagnitude > 0.01f) ? (75f / calculatedMagnitude) : 75f);
				return string.Format(DescriptionFormat, num.ToString("F0"), StatUnit);
			}
			if (Id == TrophyId.Abomination)
			{
				return string.Format(DescriptionFormat, "1", StatUnit);
			}
			float calculatedMagnitude2 = GetCalculatedMagnitude(playerComfort, slotIndex);
			string arg = ((calculatedMagnitude2 >= 10f) ? Math.Round(calculatedMagnitude2).ToString("F0") : calculatedMagnitude2.ToString("F1"));
			return string.Format(DescriptionFormat, arg, StatUnit);
		}

		public string GetBaseDescription()
		{
			if (Id == TrophyId.SeekerSoldier)
			{
				return string.Format(DescriptionFormat, "75", StatUnit);
			}
			float baseMagnitude = BaseMagnitude;
			string arg = ((baseMagnitude >= 10f) ? Math.Round(baseMagnitude).ToString("F0") : baseMagnitude.ToString("F1"));
			return string.Format(DescriptionFormat, arg, StatUnit);
		}

		public IEnumerable<StatModifier> CreateModifiers(Player player, int playerComfort, object owner)
		{
			return CreateModifiers(player, playerComfort, 0, owner);
		}

		public IEnumerable<StatModifier> CreateModifiers(Player player, int playerComfort, int slotIndex, object owner)
		{
			if (ModifierFactory == null)
			{
				yield break;
			}
			float calculatedMagnitude = GetCalculatedMagnitude(playerComfort, slotIndex);
			foreach (StatModifier item in ModifierFactory(player, calculatedMagnitude, owner))
			{
				yield return item;
			}
		}
	}
	public delegate IEnumerable<StatModifier> SetBonusModifierFactory(Player player, object owner);
	public sealed class TrophySet
	{
		public SetId Id { get; }

		public string Name { get; }

		public TrophyId[] Members { get; }

		public string? TwoPieceBonus { get; }

		public string? ThreePieceBonus { get; }

		public string? FourPieceBonus { get; }

		public SetBonusModifierFactory? TwoPieceModifiers { get; }

		public SetBonusModifierFactory? ThreePieceModifiers { get; }

		public SetBonusModifierFactory? FourPieceModifiers { get; }

		public TrophySet(SetId id, string name, TrophyId[] members, string? twoPieceBonus = null, SetBonusModifierFactory? twoPieceModifiers = null, string? threePieceBonus = null, SetBonusModifierFactory? threePieceModifiers = null, string? fourPieceBonus = null, SetBonusModifierFactory? fourPieceModifiers = null)
		{
			Id = id;
			Name = name;
			Members = members;
			TwoPieceBonus = twoPieceBonus;
			TwoPieceModifiers = twoPieceModifiers;
			ThreePieceBonus = threePieceBonus;
			ThreePieceModifiers = threePieceModifiers;
			FourPieceBonus = fourPieceBonus;
			FourPieceModifiers = fourPieceModifiers;
		}

		public bool Contains(TrophyId trophyId)
		{
			for (int i = 0; i < Members.Length; i++)
			{
				if (Members[i] == trophyId)
				{
					return true;
				}
			}
			return false;
		}

		public bool HasBonus(int activeCount, int pieceTier)
		{
			return activeCount >= pieceTier;
		}

		public IEnumerable<StatModifier> CreateModifiers(Player player, int activeCount, object owner)
		{
			if (activeCount >= 2 && TwoPieceModifiers != null)
			{
				foreach (StatModifier item in TwoPieceModifiers(player, owner))
				{
					yield return item;
				}
			}
			if (activeCount >= 3 && ThreePieceModifiers != null)
			{
				foreach (StatModifier item2 in ThreePieceModifiers(player, owner))
				{
					yield return item2;
				}
			}
			if (activeCount < 4 || FourPieceModifiers == null)
			{
				yield break;
			}
			foreach (StatModifier item3 in FourPieceModifiers(player, owner))
			{
				yield return item3;
			}
		}
	}
}
namespace RestedRites.Patches
{
	[HarmonyPatch(typeof(Hud))]
	public static class HudPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("UpdateStatusEffects")]
		public static void UpdateStatusEffects_Postfix(Hud __instance, List<StatusEffect> statusEffects, List<RectTransform> ___m_statusEffects)
		{
			if (!ModConfig.ModEnabled.Value || statusEffects == null || ___m_statusEffects == null)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			for (int i = 0; i < statusEffects.Count; i++)
			{
				StatusEffect obj = statusEffects[i];
				SE_Rested val = (SE_Rested)(object)((obj is SE_Rested) ? obj : null);
				if (val == null || i >= ___m_statusEffects.Count)
				{
					continue;
				}
				RectTransform val2 = ___m_statusEffects[i];
				if (!((Object)(object)val2 == (Object)null))
				{
					SERestedPatch.ApplyCustomModifiers(val, localPlayer);
					Transform obj2 = ((Transform)val2).Find("Name");
					TMP_Text val3 = ((obj2 != null) ? ((Component)obj2).GetComponent<TMP_Text>() : null);
					if ((Object)(object)val3 != (Object)null && !string.IsNullOrEmpty(((StatusEffect)val).m_name))
					{
						val3.text = ((Localization.instance != null) ? Localization.instance.Localize(((StatusEffect)val).m_name) : ((StatusEffect)val).m_name);
					}
					Transform obj3 = ((Transform)val2).Find("Icon");
					Image val4 = ((obj3 != null) ? ((Component)obj3).GetComponent<Image>() : null);
					if ((Object)(object)val4 != (Object)null)
					{
						((Graphic)val4).raycastTarget = true;
					}
					UITooltip val5 = ((Component)val2).GetComponent<UITooltip>();
					if ((Object)(object)val5 == (Object)null)
					{
						val5 = ((Component)val2).gameObject.AddComponent<UITooltip>();
					}
					SERestedPatch.GetComfortLevel(val);
					val5.m_topic = ((Localization.instance != null) ? Localization.instance.Localize(((StatusEffect)val).m_name) : ((StatusEffect)val).m_name);
					val5.m_text = SERestedPatch.FormatRestedTooltip(val);
					break;
				}
			}
		}
	}
	[HarmonyPatch(typeof(ItemStand))]
	public static class ItemStandPatch
	{
		public static GameObject? GetAttachedItemPrefabObject(ItemStand stand)
		{
			if ((Object)(object)stand == (Object)null)
			{
				return null;
			}
			int attachedItem = stand.GetAttachedItem();
			if (attachedItem != 0 && (Object)(object)ObjectDB.instance != (Object)null)
			{
				return ObjectDB.instance.GetItemPrefab(attachedItem);
			}
			return null;
		}

		public static string GetAttachedItemPrefab(ItemStand stand)
		{
			GameObject attachedItemPrefabObject = GetAttachedItemPrefabObject(stand);
			if (!((Object)(object)attachedItemPrefabObject != (Object)null))
			{
				return string.Empty;
			}
			return CleanPrefabName(((Object)attachedItemPrefabObject).name);
		}

		private static string CleanPrefabName(string raw)
		{
			if (string.IsNullOrEmpty(raw))
			{
				return string.Empty;
			}
			return raw.Replace("(Clone)", "").Trim();
		}

		[HarmonyPostfix]
		[HarmonyPatch("GetHoverText")]
		public static void GetHoverText_Postfix(ItemStand __instance, ref string __result)
		{
			if (!ModConfig.ModEnabled.Value || (Object)(object)__instance == (Object)null || !__instance.HaveAttachment())
			{
				return;
			}
			GameObject attachedItemPrefabObject = GetAttachedItemPrefabObject(__instance);
			if ((Object)(object)attachedItemPrefabObject == (Object)null)
			{
				return;
			}
			string text = CleanPrefabName(((Object)attachedItemPrefabObject).name);
			if (string.IsNullOrEmpty(text) || !RiteDatabase.TryGetRite(text, out TrophyRite rite))
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				StringBuilder stringBuilder = new StringBuilder();
				string text2 = ((Localization.instance != null) ? Localization.instance.Localize(__instance.m_name) : "Item stand");
				ItemDrop component = attachedItemPrefabObject.GetComponent<ItemDrop>();
				string text3 = ((component != null && component.m_itemData?.m_shared?.m_name != null && Localization.instance != null) ? Localization.instance.Localize(component.m_itemData.m_shared.m_name) : (rite.CreatureName + " trophy"));
				stringBuilder.Append(text2 + " (" + text3 + ")");
				stringBuilder.Append("\n[<color=yellow><b>$ui_hold $KEY_Use</b></color>] $piece_itemstand_take");
				int