Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RestedRites v0.2.0
RestedRites.dll
Decompiled 3 days ago
The result has been truncated due to the large size, download it to view full contents!
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