using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using RunesOfRefinement.Config;
using RunesOfRefinement.GUI;
using RunesOfRefinement.Items;
using RunesOfRefinement.Patches;
using RunesOfRefinement.Systems;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("RunesOfRefinement")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("PickTeam")]
[assembly: AssemblyProduct("RunesOfRefinement")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("3f480584-8125-43c3-acb4-3621017202b6")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = "")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 RunesOfRefinement
{
[BepInPlugin("com.pickteam.RunesOfRefinement", "RunesOfRefinement", "0.5.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
internal class RunesOfRefinement : BaseUnityPlugin
{
public const string ModGUID = "com.pickteam.RunesOfRefinement";
public const string ModName = "RunesOfRefinement";
public const string ModVersion = "0.5.0";
private Harmony harmony;
private CustomLocalization localization;
private FileSystemWatcher _configWatcher;
private void Awake()
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Expected O, but got Unknown
ModConfig.Init(((BaseUnityPlugin)this).Config);
harmony = new Harmony("com.pickteam.RunesOfRefinement");
harmony.CreateClassProcessor(typeof(BiomeDropPatch)).Patch();
TooltipPatch.Register(harmony);
StatPatches.Register(harmony);
OutOfCombatStaminaPatch.Register(harmony);
CursorApply.Register(harmony);
localization = LocalizationManager.Instance.GetLocalization();
LocalizationManager.Instance.AddLocalization(localization);
LocaleLoader.LoadAll(localization);
PrefabManager.OnVanillaPrefabsAvailable += AddContent;
SynchronizationManager.OnConfigurationSynchronized += OnConfigSync;
SynchronizationManager.OnAdminStatusChanged += OnAdminStatusChanged;
SetupConfigWatcher();
Logger.LogInfo((object)"RunesOfRefinement v0.5.0 loaded");
}
private void Update()
{
CursorApply.UpdateCursorPosition();
}
private void AddContent()
{
Spheres.Create();
Omens.Create();
PrefabManager.OnVanillaPrefabsAvailable -= AddContent;
}
private void OnDestroy()
{
Harmony obj = harmony;
if (obj != null)
{
obj.UnpatchSelf();
}
SynchronizationManager.OnConfigurationSynchronized -= OnConfigSync;
SynchronizationManager.OnAdminStatusChanged -= OnAdminStatusChanged;
_configWatcher?.Dispose();
}
private void OnConfigSync(object sender, ConfigurationSynchronizationEventArgs e)
{
Logger.LogInfo((object)("RunesOfRefinement: configuration " + (e.InitialSynchronization ? "initially synced" : "re-synced") + " from server"));
}
private void OnAdminStatusChanged()
{
Logger.LogInfo((object)string.Format("{0}: admin status = {1}", "RunesOfRefinement", SynchronizationManager.Instance.PlayerIsAdmin));
}
private void SetupConfigWatcher()
{
string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
string directoryName = Path.GetDirectoryName(configFilePath);
string fileName = Path.GetFileName(configFilePath);
_configWatcher = new FileSystemWatcher(directoryName, fileName)
{
NotifyFilter = (NotifyFilters.Size | NotifyFilters.LastWrite),
EnableRaisingEvents = true
};
_configWatcher.Changed += delegate
{
((BaseUnityPlugin)this).Config.Reload();
Logger.LogInfo((object)"RunesOfRefinement: config file changed — reloaded");
};
}
}
}
namespace RunesOfRefinement.Config
{
public static class ModConfig
{
public static ConfigEntry<float> DropRateMultiplier;
public static ConfigEntry<float> OmenDropRateMultiplier;
public static ConfigEntry<bool> EnableMythicProperties;
public static ConfigEntry<float> AffixValueMultiplier;
public static ConfigEntry<bool> EnableOutOfCombatStamina;
public static ConfigEntry<bool> EnableTooltipColors;
public static ConfigEntry<bool> EnableReforgeEffects;
public static void Init(ConfigFile config)
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Expected O, but got Unknown
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Expected O, but got Unknown
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Expected O, but got Unknown
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Expected O, but got Unknown
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Expected O, but got Unknown
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Expected O, but got Unknown
//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Expected O, but got Unknown
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Expected O, but got Unknown
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_013a: Unknown result type (might be due to invalid IL or missing references)
//IL_0143: Expected O, but got Unknown
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
//IL_014d: Expected O, but got Unknown
config.SaveOnConfigSet = true;
DropRateMultiplier = config.Bind<float>("DropRates", "SphereDropMultiplier", 1f, new ConfigDescription("Multiplier for all sphere/rune drop rates (1.0 = default, 2.0 = double).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), new object[1] { (object)new ConfigurationManagerAttributes
{
IsAdminOnly = true
} }));
OmenDropRateMultiplier = config.Bind<float>("DropRates", "OmenDropMultiplier", 1f, new ConfigDescription("Multiplier for all omen drop rates.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), new object[1] { (object)new ConfigurationManagerAttributes
{
IsAdminOnly = true
} }));
EnableMythicProperties = config.Bind<bool>("Features", "EnableMythicProperties", true, new ConfigDescription("Enable or disable mythic (legendary) active properties.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
{
IsAdminOnly = true
} }));
AffixValueMultiplier = config.Bind<float>("Balance", "AffixValueMultiplier", 1f, new ConfigDescription("Multiplier for rolled affix values (1.0 = default, 0.5 = half power).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), new object[1] { (object)new ConfigurationManagerAttributes
{
IsAdminOnly = true
} }));
EnableOutOfCombatStamina = config.Bind<bool>("Gameplay", "EnableOutOfCombatStamina", true, new ConfigDescription("When enabled, stamina is not consumed while out of combat (not sensed or targeted).", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
{
IsAdminOnly = true
} }));
EnableTooltipColors = config.Bind<bool>("Visual", "EnableTooltipColors", true, "Enable colored text in item tooltips for rune modifiers.");
EnableReforgeEffects = config.Bind<bool>("Visual", "EnableReforgeEffects", true, "Enable visual/sound effects when reforging at the Enchantment Altar.");
}
}
}
namespace RunesOfRefinement.GUI
{
internal static class CursorApply
{
[HarmonyPatch(typeof(InventoryGui), "SetupDragItem")]
private static class LeftClickPatch
{
[HarmonyPostfix]
private static void Postfix(InventoryGui __instance)
{
if (IsHolding && !((Object)(object)__instance.m_dragGo == (Object)null) && __instance.m_dragItem != null)
{
ItemData dragItem = __instance.m_dragItem;
GameObject dropPrefab = dragItem.m_dropPrefab;
string prefabName = ((dropPrefab != null) ? ((Object)dropPrefab).name : null) ?? "";
if (EssenceLogic.IsOmen(prefabName))
{
_heldOmen = dragItem;
__instance.SetupDragItem((ItemData)null, (Inventory)null, 1);
UpdateCursorVisual();
}
}
}
}
[HarmonyPatch(typeof(InventoryGrid), "OnRightClick")]
private static class RightClickPatch
{
[HarmonyPrefix]
private static bool Prefix(InventoryGrid __instance, UIInputHandler element)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: 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)
GameObject gameObject = ((Component)element).gameObject;
Vector2i buttonPos = __instance.GetButtonPos(gameObject);
ItemData itemAt = __instance.m_inventory.GetItemAt(buttonPos.x, buttonPos.y);
if (!IsHolding)
{
if (itemAt == null)
{
return true;
}
GameObject dropPrefab = itemAt.m_dropPrefab;
string prefabName = ((dropPrefab != null) ? ((Object)dropPrefab).name : null) ?? "";
if (EssenceLogic.IsSphere(prefabName))
{
Hold(itemAt);
return false;
}
return true;
}
if (itemAt == null)
{
Cancel();
return false;
}
GameObject dropPrefab2 = itemAt.m_dropPrefab;
string prefabName2 = ((dropPrefab2 != null) ? ((Object)dropPrefab2).name : null) ?? "";
if (EssenceLogic.IsSphere(prefabName2))
{
Hold(itemAt);
return false;
}
if (EssenceLogic.IsOmen(prefabName2))
{
_heldOmen = itemAt;
InventoryGui instance = InventoryGui.instance;
if (instance != null)
{
instance.SetupDragItem((ItemData)null, (Inventory)null, 1);
}
UpdateCursorVisual();
return false;
}
TryApply(itemAt, __instance.m_inventory);
return false;
}
}
[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
private static class GridHighlightPatch
{
[HarmonyPostfix]
private static void Postfix(InventoryGrid __instance)
{
//IL_0132: Unknown result type (might be due to invalid IL or missing references)
//IL_012b: Unknown result type (might be due to invalid IL or missing references)
if (!IsHolding)
{
return;
}
ItemData heldSphere = _heldSphere;
object obj;
if (heldSphere == null)
{
obj = null;
}
else
{
GameObject dropPrefab = heldSphere.m_dropPrefab;
obj = ((dropPrefab != null) ? ((Object)dropPrefab).name : null);
}
if (obj == null)
{
obj = "";
}
string spherePrefab = (string)obj;
int width = __instance.m_inventory.m_width;
foreach (ItemData allItem in __instance.m_inventory.GetAllItems())
{
if (!EssenceLogic.IsEquipment(allItem))
{
continue;
}
int num = allItem.m_gridPos.y * width + allItem.m_gridPos.x;
if (num < 0 || num >= __instance.m_elements.Count)
{
continue;
}
Element val = __instance.m_elements[num];
Transform val2 = val.m_go.transform.Find("selected");
if (!((Object)(object)val2 == (Object)null))
{
Image component = ((Component)val2).GetComponent<Image>();
if (!((Object)(object)component == (Object)null))
{
bool flag = EssenceLogic.CanApply(allItem, spherePrefab);
((Component)val2).gameObject.SetActive(true);
((Graphic)component).color = (flag ? HighlightValid : HighlightInvalid);
}
}
}
}
}
private static ItemData _heldSphere;
private static ItemData _heldOmen;
private static GameObject _cursorGo;
private static Image _cursorIcon;
private static Image _cursorOmenIcon;
private static readonly Color HighlightValid = new Color(0.2f, 1f, 0.2f, 0.35f);
private static readonly Color HighlightInvalid = new Color(1f, 0.2f, 0.2f, 0.25f);
private static readonly Color CursorBg = new Color(0.1f, 0.05f, 0.02f, 0.92f);
public static bool IsHolding => _heldSphere != null;
public static void Hold(ItemData sphere, ItemData omen = null)
{
_heldSphere = sphere;
_heldOmen = omen;
if ((Object)(object)InventoryGui.instance != (Object)null)
{
InventoryGui.instance.SetupDragItem((ItemData)null, (Inventory)null, 1);
}
EnsureCursor();
UpdateCursorVisual();
GameObject dropPrefab = sphere.m_dropPrefab;
string obj = ((dropPrefab != null) ? ((Object)dropPrefab).name : null);
object obj2;
if (omen == null)
{
obj2 = "";
}
else
{
GameObject dropPrefab2 = omen.m_dropPrefab;
obj2 = " + " + ((dropPrefab2 != null) ? ((Object)dropPrefab2).name : null);
}
Logger.LogInfo((object)("[RoR] Cursor-hold: " + obj + (string?)obj2));
}
public static void Cancel()
{
_heldSphere = null;
_heldOmen = null;
if ((Object)(object)_cursorGo != (Object)null)
{
_cursorGo.SetActive(false);
}
}
public static void TryApply(ItemData target, Inventory targetInventory)
{
if (_heldSphere == null || target == null)
{
return;
}
Player localPlayer = Player.m_localPlayer;
if ((Object)(object)localPlayer == (Object)null)
{
return;
}
Inventory inventory = ((Humanoid)localPlayer).GetInventory();
if (!inventory.ContainsItem(_heldSphere))
{
ShowMessage("$ror_msg_missing_items");
Cancel();
return;
}
if (!EssenceLogic.IsEquipment(target))
{
ShowMessage("$ror_msg_not_equipment");
return;
}
GameObject dropPrefab = _heldSphere.m_dropPrefab;
string spherePrefab = ((dropPrefab != null) ? ((Object)dropPrefab).name : null) ?? "";
ItemData heldOmen = _heldOmen;
object obj;
if (heldOmen == null)
{
obj = null;
}
else
{
GameObject dropPrefab2 = heldOmen.m_dropPrefab;
obj = ((dropPrefab2 != null) ? ((Object)dropPrefab2).name : null);
}
if (obj == null)
{
obj = "";
}
string omenPrefab = (string)obj;
EssenceLogic.ApplyResult applyResult = EssenceLogic.Apply(target, _heldSphere, _heldOmen);
if (applyResult.Success)
{
inventory.RemoveOneItem(_heldSphere);
if (_heldOmen != null)
{
inventory.RemoveOneItem(_heldOmen);
}
PlayEffect(localPlayer);
RuneEffectManager.Invalidate();
ItemData val = ((IEnumerable<ItemData>)inventory.GetAllItems()).FirstOrDefault((Func<ItemData, bool>)delegate(ItemData i)
{
GameObject dropPrefab4 = i.m_dropPrefab;
return (((dropPrefab4 != null) ? ((Object)dropPrefab4).name : null) ?? "") == spherePrefab;
});
ItemData heldOmen2 = null;
if (omenPrefab != "")
{
heldOmen2 = ((IEnumerable<ItemData>)inventory.GetAllItems()).FirstOrDefault((Func<ItemData, bool>)delegate(ItemData i)
{
GameObject dropPrefab3 = i.m_dropPrefab;
return (((dropPrefab3 != null) ? ((Object)dropPrefab3).name : null) ?? "") == omenPrefab;
});
}
if (val != null)
{
_heldSphere = val;
_heldOmen = heldOmen2;
UpdateCursorVisual();
}
else
{
Cancel();
}
}
ShowMessage(applyResult.MessageKey);
}
public static void UpdateCursorPosition()
{
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
if (!IsHolding)
{
return;
}
if (Input.GetKeyDown((KeyCode)27))
{
Cancel();
return;
}
if ((Object)(object)_cursorGo != (Object)null && _cursorGo.activeSelf)
{
_cursorGo.transform.position = Input.mousePosition + new Vector3(32f, -32f, 0f);
}
Player localPlayer = Player.m_localPlayer;
if ((Object)(object)localPlayer == (Object)null || !((Humanoid)localPlayer).GetInventory().ContainsItem(_heldSphere))
{
Cancel();
}
}
private static void EnsureCursor()
{
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Expected O, but got Unknown
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: Expected O, but got Unknown
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
//IL_0148: Unknown result type (might be due to invalid IL or missing references)
//IL_014f: Expected O, but got Unknown
//IL_017c: Unknown result type (might be due to invalid IL or missing references)
//IL_0193: Unknown result type (might be due to invalid IL or missing references)
//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_cursorGo != (Object)null)
{
_cursorGo.SetActive(true);
return;
}
InventoryGui instance = InventoryGui.instance;
Transform val = ((instance != null) ? ((Component)instance).transform.root : null);
if (!((Object)(object)val == (Object)null))
{
_cursorGo = new GameObject("RoR_CursorApply");
_cursorGo.transform.SetParent(val, false);
RectTransform val2 = _cursorGo.AddComponent<RectTransform>();
val2.sizeDelta = new Vector2(52f, 52f);
Image val3 = _cursorGo.AddComponent<Image>();
((Graphic)val3).color = CursorBg;
GameObject val4 = new GameObject("Icon");
val4.transform.SetParent(_cursorGo.transform, false);
RectTransform val5 = val4.AddComponent<RectTransform>();
val5.anchorMin = new Vector2(0f, 0f);
val5.anchorMax = new Vector2(1f, 1f);
val5.offsetMin = new Vector2(4f, 4f);
val5.offsetMax = new Vector2(-4f, -4f);
_cursorIcon = val4.AddComponent<Image>();
_cursorIcon.preserveAspect = true;
GameObject val6 = new GameObject("OmenIcon");
val6.transform.SetParent(_cursorGo.transform, false);
RectTransform val7 = val6.AddComponent<RectTransform>();
val7.anchorMin = new Vector2(1f, 0f);
val7.anchorMax = new Vector2(1f, 0f);
val7.pivot = new Vector2(1f, 0f);
val7.sizeDelta = new Vector2(22f, 22f);
val7.anchoredPosition = new Vector2(2f, -2f);
_cursorOmenIcon = val6.AddComponent<Image>();
_cursorOmenIcon.preserveAspect = true;
val6.SetActive(false);
Canvas val8 = _cursorGo.AddComponent<Canvas>();
val8.overrideSorting = true;
val8.sortingOrder = 9999;
_cursorGo.AddComponent<GraphicRaycaster>();
_cursorGo.SetActive(true);
}
}
private static void UpdateCursorVisual()
{
if (!((Object)(object)_cursorGo == (Object)null) && _heldSphere != null)
{
_cursorIcon.sprite = _heldSphere.GetIcon();
((Behaviour)_cursorIcon).enabled = (Object)(object)_cursorIcon.sprite != (Object)null;
if (_heldOmen != null)
{
_cursorOmenIcon.sprite = _heldOmen.GetIcon();
((Behaviour)_cursorOmenIcon).enabled = (Object)(object)_cursorOmenIcon.sprite != (Object)null;
((Component)_cursorOmenIcon).gameObject.SetActive(true);
}
else
{
((Component)_cursorOmenIcon).gameObject.SetActive(false);
}
}
}
private static void ShowMessage(string key)
{
string text = Localization.instance.Localize(key);
MessageHud instance = MessageHud.instance;
if (instance != null)
{
instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false);
}
}
private static void PlayEffect(Player player)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: 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_0077: Unknown result type (might be due to invalid IL or missing references)
if (ModConfig.EnableReforgeEffects.Value)
{
Vector3 position = ((Component)player).transform.position;
ZNetScene instance = ZNetScene.instance;
GameObject val = ((instance != null) ? instance.GetPrefab("sfx_build_hammer_metal") : null);
if ((Object)(object)val != (Object)null)
{
Object.Instantiate<GameObject>(val, position, Quaternion.identity);
}
ZNetScene instance2 = ZNetScene.instance;
GameObject val2 = ((instance2 != null) ? instance2.GetPrefab("vfx_FireAddFuel") : null);
if ((Object)(object)val2 != (Object)null)
{
Object.Instantiate<GameObject>(val2, position, Quaternion.identity);
}
}
}
public static void Register(Harmony harmony)
{
harmony.CreateClassProcessor(typeof(LeftClickPatch)).Patch();
harmony.CreateClassProcessor(typeof(RightClickPatch)).Patch();
harmony.CreateClassProcessor(typeof(GridHighlightPatch)).Patch();
}
}
}
namespace RunesOfRefinement.Patches
{
[HarmonyPatch(typeof(CharacterDrop), "Start")]
internal static class BiomeDropPatch
{
private struct DropEntry
{
public string Prefab;
public float Chance;
}
private static readonly Dictionary<Biome, List<DropEntry>> BiomeDrops = new Dictionary<Biome, List<DropEntry>>
{
[(Biome)1] = new List<DropEntry>
{
new DropEntry
{
Prefab = "RoR_OrbOfTransmutation",
Chance = 0.025f
},
new DropEntry
{
Prefab = "RoR_OrbOfAugmentation",
Chance = 0.015f
}
},
[(Biome)8] = new List<DropEntry>
{
new DropEntry
{
Prefab = "RoR_OrbOfTransmutation",
Chance = 0.015f
},
new DropEntry
{
Prefab = "RoR_OrbOfAugmentation",
Chance = 0.015f
},
new DropEntry
{
Prefab = "RoR_RegalOrb",
Chance = 0.008f
}
},
[(Biome)2] = new List<DropEntry>
{
new DropEntry
{
Prefab = "RoR_OrbOfAugmentation",
Chance = 0.01f
},
new DropEntry
{
Prefab = "RoR_RegalOrb",
Chance = 0.012f
},
new DropEntry
{
Prefab = "RoR_ExaltedOrb",
Chance = 0.008f
},
new DropEntry
{
Prefab = "RoR_ChaosOrb",
Chance = 0.008f
},
new DropEntry
{
Prefab = "RoR_VaalOrb",
Chance = 0.005f
}
},
[(Biome)4] = new List<DropEntry>
{
new DropEntry
{
Prefab = "RoR_RegalOrb",
Chance = 0.008f
},
new DropEntry
{
Prefab = "RoR_ExaltedOrb",
Chance = 0.01f
},
new DropEntry
{
Prefab = "RoR_OrbOfAlchemy",
Chance = 0.006f
},
new DropEntry
{
Prefab = "RoR_ChaosOrb",
Chance = 0.008f
},
new DropEntry
{
Prefab = "RoR_VaalOrb",
Chance = 0.004f
},
new DropEntry
{
Prefab = "RoR_OmenOfElements",
Chance = 0.005f
},
new DropEntry
{
Prefab = "RoR_OmenOfProtector",
Chance = 0.005f
},
new DropEntry
{
Prefab = "RoR_OmenOfOrder",
Chance = 0.005f
},
new DropEntry
{
Prefab = "RoR_OmenSinistral",
Chance = 0.003f
},
new DropEntry
{
Prefab = "RoR_OmenDextral",
Chance = 0.003f
}
},
[(Biome)16] = new List<DropEntry>
{
new DropEntry
{
Prefab = "RoR_ExaltedOrb",
Chance = 0.008f
},
new DropEntry
{
Prefab = "RoR_OrbOfAlchemy",
Chance = 0.006f
},
new DropEntry
{
Prefab = "RoR_ChaosOrb",
Chance = 0.006f
},
new DropEntry
{
Prefab = "RoR_OrbOfAnnulment",
Chance = 0.004f
},
new DropEntry
{
Prefab = "RoR_VaalOrb",
Chance = 0.004f
},
new DropEntry
{
Prefab = "RoR_OmenOfElements",
Chance = 0.003f
},
new DropEntry
{
Prefab = "RoR_OmenOfProtector",
Chance = 0.003f
},
new DropEntry
{
Prefab = "RoR_OmenOfOrder",
Chance = 0.003f
},
new DropEntry
{
Prefab = "RoR_OmenSinistral",
Chance = 0.002f
},
new DropEntry
{
Prefab = "RoR_OmenDextral",
Chance = 0.002f
},
new DropEntry
{
Prefab = "RoR_OmenWhittling",
Chance = 0.002f
},
new DropEntry
{
Prefab = "RoR_OmenAbundance",
Chance = 0.002f
}
},
[(Biome)512] = new List<DropEntry>
{
new DropEntry
{
Prefab = "RoR_ExaltedOrb",
Chance = 0.005f
},
new DropEntry
{
Prefab = "RoR_ChaosOrb",
Chance = 0.005f
},
new DropEntry
{
Prefab = "RoR_OrbOfAnnulment",
Chance = 0.004f
},
new DropEntry
{
Prefab = "RoR_DivineOrb",
Chance = 0.003f
},
new DropEntry
{
Prefab = "RoR_VaalOrb",
Chance = 0.005f
},
new DropEntry
{
Prefab = "RoR_OmenOfElements",
Chance = 0.003f
},
new DropEntry
{
Prefab = "RoR_OmenOfProtector",
Chance = 0.003f
},
new DropEntry
{
Prefab = "RoR_OmenOfOrder",
Chance = 0.003f
},
new DropEntry
{
Prefab = "RoR_OmenSinistral",
Chance = 0.002f
},
new DropEntry
{
Prefab = "RoR_OmenDextral",
Chance = 0.002f
},
new DropEntry
{
Prefab = "RoR_OmenWhittling",
Chance = 0.002f
},
new DropEntry
{
Prefab = "RoR_OmenAbundance",
Chance = 0.002f
},
new DropEntry
{
Prefab = "RoR_OmenCorruption",
Chance = 0.001f
},
new DropEntry
{
Prefab = "RoR_OmenPerfection",
Chance = 0.001f
},
new DropEntry
{
Prefab = "RoR_OmenGreaterAnnul",
Chance = 0.001f
}
}
};
private static void Postfix(CharacterDrop __instance)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Expected O, but got Unknown
Biome key = Heightmap.FindBiome(((Component)__instance).transform.position);
if (!BiomeDrops.TryGetValue(key, out var value))
{
return;
}
foreach (DropEntry item in value)
{
GameObject prefab = PrefabManager.Instance.GetPrefab(item.Prefab);
if (!((Object)(object)prefab == (Object)null))
{
__instance.m_drops.Add(new Drop
{
m_prefab = prefab,
m_amountMin = 1,
m_amountMax = 1,
m_chance = item.Chance,
m_onePerPlayer = false,
m_levelMultiplier = false
});
}
}
}
}
internal static class TooltipPatch
{
public static void Register(Harmony harmony)
{
//IL_0138: Unknown result type (might be due to invalid IL or missing references)
//IL_013f: Expected O, but got Unknown
//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
//IL_0201: Expected O, but got Unknown
MethodInfo methodInfo = AccessTools.Method(typeof(ItemData), "GetTooltip", new Type[5]
{
typeof(ItemData),
typeof(int),
typeof(bool),
typeof(float),
typeof(int)
}, (Type[])null);
if (methodInfo == null)
{
methodInfo = AccessTools.Method(typeof(ItemData), "GetTooltip", new Type[4]
{
typeof(ItemData),
typeof(int),
typeof(bool),
typeof(float)
}, (Type[])null);
}
if (methodInfo == null)
{
methodInfo = AccessTools.Method(typeof(ItemData), "GetTooltip", new Type[4]
{
typeof(ItemData),
typeof(int),
typeof(bool),
typeof(int)
}, (Type[])null);
}
if (methodInfo != null)
{
HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(TooltipPatch), "GetTooltipStaticPostfix", (Type[])null, (Type[])null));
harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
Logger.LogInfo((object)"TooltipPatch applied (static GetTooltip)");
return;
}
MethodInfo methodInfo2 = AccessTools.Method(typeof(ItemData), "GetTooltip", new Type[1] { typeof(int) }, (Type[])null);
if (methodInfo2 == null)
{
methodInfo2 = AccessTools.Method(typeof(ItemData), "GetTooltip", new Type[3]
{
typeof(int),
typeof(bool),
typeof(float)
}, (Type[])null);
}
if (methodInfo2 != null)
{
HarmonyMethod val2 = new HarmonyMethod(AccessTools.Method(typeof(TooltipPatch), "GetTooltipInstancePostfix", (Type[])null, (Type[])null));
harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
Logger.LogInfo((object)"TooltipPatch applied (instance GetTooltip)");
}
else
{
Logger.LogWarning((object)"TooltipPatch: Could not find GetTooltip method to patch");
}
}
private static void GetTooltipStaticPostfix(ItemData __0, ref string __result)
{
AppendModifiers(__0, ref __result);
}
private static void GetTooltipInstancePostfix(ItemData __instance, ref string __result)
{
AppendModifiers(__instance, ref __result);
}
private static void AppendModifiers(ItemData item, ref string tooltip)
{
//IL_004f: 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)
if (item == null || !ModifierData.HasAnyModifiers(item) || !ModConfig.EnableTooltipColors.Value)
{
return;
}
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine();
stringBuilder.AppendLine();
ItemRarity rarity = ModifierData.GetRarity(item);
string text = ColorUtility.ToHtmlStringRGB(RarityHelper.GetColor(rarity));
string text2 = rarity switch
{
ItemRarity.Magic => Localization.instance.Localize("$ror_rarity_magic"),
ItemRarity.Rare => Localization.instance.Localize("$ror_rarity_rare"),
_ => Localization.instance.Localize("$ror_rarity_normal"),
};
string text3 = (ModifierData.IsCorrupted(item) ? (" <color=#" + ColorUtility.ToHtmlStringRGB(RarityHelper.CorruptedColor) + ">(" + Localization.instance.Localize("$ror_corrupted") + ")</color>") : "");
int itemTier = EssenceLogic.GetItemTier(item);
string text4 = Localization.instance.Localize($"$ror_tier_{itemTier}");
string text5 = " <color=#AAAAAA>[" + text4 + "]</color>";
stringBuilder.AppendLine("<color=#" + text + ">" + text2 + text3 + text5 + ":</color>");
List<RolledAffix> affixes = ModifierData.GetAffixes(item);
affixes.Sort(delegate(RolledAffix a, RolledAffix b)
{
AffixDefinition affixDefinition3 = AffixPool.Get(a.AffixId);
AffixDefinition affixDefinition4 = AffixPool.Get(b.AffixId);
int num = ((affixDefinition3 == null || affixDefinition3.Slot != 0) ? 1 : 0);
int value = ((affixDefinition4 == null || affixDefinition4.Slot != 0) ? 1 : 0);
return num.CompareTo(value);
});
foreach (RolledAffix item2 in affixes)
{
AffixDefinition affixDefinition = AffixPool.Get(item2.AffixId);
if (affixDefinition != null)
{
string text6 = Localization.instance.Localize(affixDefinition.NameToken);
string text7 = string.Format(Localization.instance.Localize(affixDefinition.DescToken), item2.Value);
string rollQualityColor = AffixPool.GetRollQualityColor(item2);
stringBuilder.AppendLine("<color=" + rollQualityColor + ">" + text6 + ": " + text7 + "</color>");
}
}
RolledAffix mythicAffix = ModifierData.GetMythicAffix(item);
if (mythicAffix != null)
{
AffixDefinition affixDefinition2 = AffixPool.Get(mythicAffix.AffixId);
if (affixDefinition2 != null)
{
string text8 = Localization.instance.Localize(affixDefinition2.NameToken);
string text9 = string.Format(Localization.instance.Localize(affixDefinition2.DescToken), mythicAffix.Value);
stringBuilder.AppendLine("<color=#D966FF>" + text8 + ": " + text9 + "</color>");
}
}
tooltip += stringBuilder.ToString();
}
}
internal static class StatPatches
{
[HarmonyPatch(typeof(ItemData), "GetDamage", new Type[]
{
typeof(int),
typeof(float)
})]
internal static class WeaponDamagePatch
{
private static void Postfix(ItemData __instance, ref DamageTypes __result)
{
if (!ModifierData.HasAnyModifiers(__instance))
{
return;
}
RuneEffectManager.WeaponModifiers weaponModifiers = RuneEffectManager.GetWeaponModifiers(__instance);
if (weaponModifiers.DamagePercent > 0f)
{
float num = 1f + weaponModifiers.DamagePercent / 100f;
__result.m_blunt *= num;
__result.m_slash *= num;
__result.m_pierce *= num;
}
__result.m_fire += weaponModifiers.FireDamage;
__result.m_frost += weaponModifiers.FrostDamage;
__result.m_lightning += weaponModifiers.LightningDamage;
__result.m_poison += weaponModifiers.PoisonDamage;
__result.m_spirit += weaponModifiers.SpiritDamage;
if (weaponModifiers.ArmorIgnore > 0f)
{
__result.m_damage += weaponModifiers.ArmorIgnore;
}
if (weaponModifiers.HeimdallDamagePercent > 0f)
{
float num2 = 1f + weaponModifiers.HeimdallDamagePercent / 100f;
__result.m_blunt *= num2;
__result.m_slash *= num2;
__result.m_pierce *= num2;
__result.m_fire *= num2;
__result.m_frost *= num2;
__result.m_lightning *= num2;
__result.m_poison *= num2;
__result.m_spirit *= num2;
}
if (!(__result.m_chop > 0f) && !(__result.m_pickaxe > 0f))
{
return;
}
RuneEffectManager.ToolModifiers toolModifiers = RuneEffectManager.GetToolModifiers(__instance);
if (toolModifiers.MiningPercent > 0f && __result.m_pickaxe > 0f)
{
__result.m_pickaxe *= 1f + toolModifiers.MiningPercent / 100f;
}
if (toolModifiers.ChoppingPercent > 0f && __result.m_chop > 0f)
{
__result.m_chop *= 1f + toolModifiers.ChoppingPercent / 100f;
}
if (toolModifiers.ToolDamagePercent > 0f)
{
if (__result.m_chop > 0f)
{
__result.m_chop *= 1f + toolModifiers.ToolDamagePercent / 100f;
}
if (__result.m_pickaxe > 0f)
{
__result.m_pickaxe *= 1f + toolModifiers.ToolDamagePercent / 100f;
}
}
}
}
[HarmonyPatch(typeof(ItemData), "GetArmor", new Type[]
{
typeof(int),
typeof(float)
})]
internal static class ArmorBonusPatch
{
private static void Postfix(ItemData __instance, ref float __result)
{
if (ModifierData.HasAnyModifiers(__instance))
{
__result += RuneEffectManager.GetArmorBonus(__instance);
}
}
}
[HarmonyPatch(typeof(Player), "Update")]
internal static class PlayerUpdatePatch
{
private static void Postfix(Player __instance)
{
if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
{
RuneEffectManager.Recalculate(__instance);
}
}
}
[HarmonyPatch(typeof(Player), "AddNoise")]
internal static class NoiseReductionPatch
{
private static void Prefix(ref float range)
{
if (RuneEffectManager.NoiseReductionPercent > 0f)
{
range *= 1f - RuneEffectManager.NoiseReductionPercent / 100f;
}
}
}
[HarmonyPatch(typeof(Player), "GetTotalFoodValue")]
internal static class FoodValueBonusPatch
{
private static void Postfix(ref float hp, ref float stamina)
{
if (RuneEffectManager.MaxHealthBonus > 0f)
{
hp += RuneEffectManager.MaxHealthBonus;
}
if (RuneEffectManager.MaxStaminaBonus > 0f)
{
stamina += RuneEffectManager.MaxStaminaBonus;
}
}
}
[HarmonyPatch(typeof(SEMan), "ModifyStaminaRegen")]
internal static class StaminaRegenPatch
{
private static void Postfix(ref float staminaMultiplier)
{
if (RuneEffectManager.StaminaRegenPercent > 0f)
{
staminaMultiplier += RuneEffectManager.StaminaRegenPercent / 100f;
}
}
}
[HarmonyPatch(typeof(SEMan), "ModifyHealthRegen")]
internal static class HealthRegenPatch
{
private static void Postfix(ref float regenMultiplier)
{
if (RuneEffectManager.HpRegenPercent > 0f)
{
regenMultiplier += RuneEffectManager.HpRegenPercent / 100f;
}
}
}
[HarmonyPatch(typeof(SEMan), "ModifyEitrRegen")]
internal static class EitrRegenPatch
{
private static void Postfix(ref float eitrMultiplier)
{
if (RuneEffectManager.EitrRegenPercent > 0f)
{
eitrMultiplier += RuneEffectManager.EitrRegenPercent / 100f;
}
}
}
[HarmonyPatch(typeof(Player), "GetEquipmentMovementModifier")]
internal static class MoveSpeedPatch
{
private static void Postfix(ref float __result)
{
if (RuneEffectManager.MoveSpeedPercent > 0f)
{
__result += RuneEffectManager.MoveSpeedPercent / 100f;
}
}
}
[HarmonyPatch(typeof(SEMan), "ModifyMaxCarryWeight")]
internal static class CarryWeightPatch
{
private static void Postfix(ref float limit)
{
if (RuneEffectManager.CarryWeightBonus > 0f)
{
limit += RuneEffectManager.CarryWeightBonus;
}
}
}
[HarmonyPatch(typeof(Character), "Stagger")]
internal static class StaggerResistPatch
{
private static bool Prefix(Character __instance)
{
if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
{
return true;
}
if (RuneEffectManager.StaggerResistPercent <= 0f)
{
return true;
}
return Random.Range(0f, 100f) > RuneEffectManager.StaggerResistPercent;
}
}
[HarmonyPatch(typeof(ItemData), "GetMaxDurability", new Type[] { typeof(int) })]
internal static class DurabilityPatch
{
private static void Postfix(ItemData __instance, ref float __result)
{
if (!ModifierData.HasAnyModifiers(__instance))
{
return;
}
foreach (RolledAffix affix in ModifierData.GetAffixes(__instance))
{
if (affix.AffixId == "durability")
{
__result += affix.Value;
}
}
}
}
[HarmonyPatch(typeof(Minimap), "UpdateExplore")]
internal static class ExplorerPatch
{
private static void Prefix(Minimap __instance)
{
if (RuneEffectManager.ExplorerPercent > 0f)
{
__instance.m_exploreRadius = 100f * (1f + RuneEffectManager.ExplorerPercent / 100f);
}
}
}
[HarmonyPatch(typeof(Skills), "RaiseSkill")]
internal static class ValhallaPatch
{
private static void Prefix(ref float factor)
{
if (RuneEffectManager.MythicValhallaXpPercent > 0f)
{
factor *= 1f + RuneEffectManager.MythicValhallaXpPercent / 100f;
}
}
}
[HarmonyPatch(typeof(Character), "Damage")]
internal static class CombatPatch
{
private static bool _inLightningStrike;
private static void Postfix(Character __instance, HitData hit)
{
if (_inLightningStrike)
{
return;
}
Character attacker = hit.GetAttacker();
if ((Object)(object)attacker == (Object)null)
{
return;
}
Player val = (Player)(object)((attacker is Player) ? attacker : null);
if (!((Object)(object)val == (Object)null) && !((Object)(object)val != (Object)(object)Player.m_localPlayer))
{
float totalDamage = hit.GetTotalDamage();
if (RuneEffectManager.LifestealPercent > 0f && totalDamage > 0f)
{
float num = totalDamage * RuneEffectManager.LifestealPercent / 100f;
((Character)val).Heal(num, true);
}
if (RuneEffectManager.StaminaOnKill > 0f && __instance.IsDead())
{
((Character)val).AddStamina(RuneEffectManager.StaminaOnKill);
}
if (RuneEffectManager.MythicLightningChance > 0f && Random.Range(0f, 100f) < RuneEffectManager.MythicLightningChance)
{
TriggerLightningStrike(__instance, val);
}
}
}
private static void TriggerLightningStrike(Character target, Player attacker)
{
//IL_000e: 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_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Expected O, but got Unknown
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: 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_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
_inLightningStrike = true;
try
{
Vector3 position = ((Component)target).transform.position;
ZNetScene instance = ZNetScene.instance;
GameObject val = ((instance != null) ? instance.GetPrefab("fx_eikthyr_forceField") : null);
if ((Object)(object)val != (Object)null)
{
Object.Instantiate<GameObject>(val, position + Vector3.up * 0.5f, Quaternion.identity);
}
HitData val2 = new HitData();
val2.m_damage.m_lightning = 30f;
val2.m_point = position;
Vector3 val3 = position - ((Component)attacker).transform.position;
val2.m_dir = ((Vector3)(ref val3)).normalized;
val2.SetAttacker((Character)(object)attacker);
target.Damage(val2);
target.Stagger(val2.m_dir);
}
finally
{
_inLightningStrike = false;
}
}
}
[HarmonyPatch(typeof(Character), "SetHealth")]
internal static class UndyingPatch
{
private static float _lastUndyingProc;
private static void Prefix(Character __instance, ref float health)
{
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || RuneEffectManager.MythicUndyingPercent <= 0f || health > 0f)
{
return;
}
float time = Time.time;
if (!(time - _lastUndyingProc < 60f))
{
health = __instance.GetMaxHealth() * RuneEffectManager.MythicUndyingPercent / 100f;
_lastUndyingProc = time;
ZNetScene instance = ZNetScene.instance;
GameObject val = ((instance != null) ? instance.GetPrefab("vfx_Potion_health_medium") : null);
if ((Object)(object)val != (Object)null)
{
Object.Instantiate<GameObject>(val, ((Component)__instance).transform.position, Quaternion.identity);
}
Logger.LogInfo((object)"Mythic Undying triggered — survived lethal blow!");
}
}
}
[HarmonyPatch(typeof(Character), "RPC_Damage")]
internal static class HitModifierPatch
{
private static void Prefix(Character __instance, HitData hit)
{
Character attacker = hit.GetAttacker();
if ((Object)(object)attacker == (Object)null)
{
return;
}
Player val = (Player)(object)((attacker is Player) ? attacker : null);
if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer)
{
return;
}
ItemData currentWeapon = ((Humanoid)val).GetCurrentWeapon();
if (currentWeapon != null && ModifierData.HasAnyModifiers(currentWeapon))
{
RuneEffectManager.WeaponModifiers weaponModifiers = RuneEffectManager.GetWeaponModifiers(currentWeapon);
if (weaponModifiers.KnockbackPercent > 0f)
{
hit.m_pushForce *= 1f + weaponModifiers.KnockbackPercent / 100f;
}
float num = weaponModifiers.BackstabBonusPercent + weaponModifiers.CritStrikePercent;
if (num > 0f)
{
hit.m_backstabBonus += num / 100f;
}
}
if (RuneEffectManager.MythicBerserkerPercent > 0f && ((Character)val).GetHealthPercentage() <= 0.3f)
{
float num2 = 1f + RuneEffectManager.MythicBerserkerPercent / 100f;
hit.m_damage.m_damage *= num2;
hit.m_damage.m_blunt *= num2;
hit.m_damage.m_slash *= num2;
hit.m_damage.m_pierce *= num2;
}
}
}
[HarmonyPatch(typeof(Character), "Damage")]
internal static class DamageResistancePatch
{
private static void Prefix(Character __instance, HitData hit)
{
if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
{
if (RuneEffectManager.FireResistance > 0f)
{
hit.m_damage.m_fire *= 1f - Mathf.Clamp01(RuneEffectManager.FireResistance / 100f);
}
if (RuneEffectManager.FrostResistance > 0f)
{
hit.m_damage.m_frost *= 1f - Mathf.Clamp01(RuneEffectManager.FrostResistance / 100f);
}
if (RuneEffectManager.PoisonResistance > 0f)
{
hit.m_damage.m_poison *= 1f - Mathf.Clamp01(RuneEffectManager.PoisonResistance / 100f);
}
if (RuneEffectManager.ShieldAegisPercent > 0f)
{
float num = 1f - Mathf.Clamp01(RuneEffectManager.ShieldAegisPercent / 100f);
hit.m_damage.m_damage *= num;
hit.m_damage.m_blunt *= num;
hit.m_damage.m_slash *= num;
hit.m_damage.m_pierce *= num;
hit.m_damage.m_fire *= num;
hit.m_damage.m_frost *= num;
hit.m_damage.m_lightning *= num;
hit.m_damage.m_poison *= num;
hit.m_damage.m_spirit *= num;
}
}
}
}
[HarmonyPatch(typeof(CharacterAnimEvent), "CustomFixedUpdate")]
internal static class AttackSpeedPatch
{
private static void Postfix(Character ___m_character, Animator ___m_animator)
{
if ((Object)(object)___m_character != (Object)(object)Player.m_localPlayer || !___m_character.InAttack())
{
return;
}
Player val = (Player)(object)((___m_character is Player) ? ___m_character : null);
if ((Object)(object)val == (Object)null)
{
return;
}
ItemData currentWeapon = ((Humanoid)val).GetCurrentWeapon();
if (currentWeapon != null && ModifierData.HasAnyModifiers(currentWeapon))
{
RuneEffectManager.WeaponModifiers weaponModifiers = RuneEffectManager.GetWeaponModifiers(currentWeapon);
if (weaponModifiers.AttackSpeedPercent > 0f)
{
___m_animator.speed *= 1f + weaponModifiers.AttackSpeedPercent / 100f;
}
if (RuneEffectManager.MythicBerserkerPercent > 0f && ((Character)val).GetHealthPercentage() <= 0.3f)
{
___m_animator.speed *= 1f + RuneEffectManager.MythicBerserkerPercent / 100f;
}
RuneEffectManager.ToolModifiers toolModifiers = RuneEffectManager.GetToolModifiers(currentWeapon);
if (toolModifiers.SwingSpeedPercent > 0f)
{
___m_animator.speed *= 1f + toolModifiers.SwingSpeedPercent / 100f;
}
}
}
}
[HarmonyPatch(typeof(Humanoid), "BlockAttack")]
internal static class FrostShieldPatch
{
private static void Postfix(Humanoid __instance, HitData hit, bool __result)
{
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Expected O, but got Unknown
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
if (!__result || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || RuneEffectManager.MythicFrostSlowPercent <= 0f)
{
return;
}
Character attacker = hit.GetAttacker();
if (!((Object)(object)attacker == (Object)null) && !((Object)(object)attacker == (Object)(object)__instance))
{
HitData val = new HitData();
val.m_damage.m_frost = RuneEffectManager.MythicFrostSlowPercent;
val.m_point = ((Component)attacker).transform.position;
Vector3 val2 = ((Component)attacker).transform.position - ((Component)__instance).transform.position;
val.m_dir = ((Vector3)(ref val2)).normalized;
val.SetAttacker((Character)(object)__instance);
attacker.Damage(val);
ZNetScene instance = ZNetScene.instance;
GameObject val3 = ((instance != null) ? instance.GetPrefab("vfx_ColdBall_launch") : null);
if ((Object)(object)val3 != (Object)null)
{
Object.Instantiate<GameObject>(val3, ((Component)attacker).transform.position + Vector3.up, Quaternion.identity);
}
}
}
}
[HarmonyPatch(typeof(Skills), "RaiseSkill")]
internal static class ToolMasteryPatch
{
private static void Prefix(SkillType skillType, ref float factor)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Invalid comparison between Unknown and I4
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Invalid comparison between Unknown and I4
if (!(RuneEffectManager.ToolMasteryPercent <= 0f) && ((int)skillType == 13 || (int)skillType == 12))
{
factor *= 1f + RuneEffectManager.ToolMasteryPercent / 100f;
}
}
}
[HarmonyPatch(typeof(Attack), "GetAttackStamina")]
internal static class ToolStaminaPatch
{
private static void Postfix(Attack __instance, ref float __result)
{
Humanoid character = __instance.m_character;
Player val = (Player)(object)((character is Player) ? character : null);
if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer)
{
return;
}
ItemData weapon = __instance.m_weapon;
if (weapon != null && ModifierData.HasAnyModifiers(weapon))
{
RuneEffectManager.ToolModifiers toolModifiers = RuneEffectManager.GetToolModifiers(weapon);
if (toolModifiers.StaminaReductionPercent > 0f)
{
__result *= 1f - Mathf.Clamp01(toolModifiers.StaminaReductionPercent / 100f);
}
RuneEffectManager.WeaponModifiers weaponModifiers = RuneEffectManager.GetWeaponModifiers(weapon);
if (weaponModifiers.DamagePercent > 0f)
{
__result *= 1.05f;
}
}
}
}
[HarmonyPatch(typeof(ItemData), "GetBlockPower", new Type[]
{
typeof(int),
typeof(float)
})]
internal static class ShieldBlockPowerPatch
{
internal static bool IsParrying;
private static void Postfix(ItemData __instance, ref float __result)
{
if (ModifierData.HasAnyModifiers(__instance))
{
RuneEffectManager.ShieldModifiers shieldModifiers = RuneEffectManager.GetShieldModifiers(__instance);
if (shieldModifiers.FortressPercent > 0f)
{
__result *= 1f + shieldModifiers.FortressPercent / 100f;
}
if (IsParrying && shieldModifiers.ParryBonusPercent > 0f)
{
__result *= 1f + shieldModifiers.ParryBonusPercent / 100f;
}
}
}
}
[HarmonyPatch(typeof(Humanoid), "BlockAttack")]
internal static class ShieldBlockAttackPatch
{
private static bool _wasParry;
private static void Prefix(Humanoid __instance)
{
if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
{
_wasParry = __instance.m_blockTimer != -1f;
ShieldBlockPowerPatch.IsParrying = _wasParry;
}
}
private static void Postfix(Humanoid __instance, HitData hit, bool __result)
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Invalid comparison between Unknown and I4
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Expected O, but got Unknown
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
ShieldBlockPowerPatch.IsParrying = false;
if (!__result || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
{
return;
}
ItemData leftItem = __instance.m_leftItem;
if (leftItem == null || (int)leftItem.m_shared.m_itemType != 5 || !ModifierData.HasAnyModifiers(leftItem))
{
return;
}
RuneEffectManager.ShieldModifiers shieldModifiers = RuneEffectManager.GetShieldModifiers(leftItem);
Character attacker = hit.GetAttacker();
if (shieldModifiers.ThornsDamage > 0f && (Object)(object)attacker != (Object)null && (Object)(object)attacker != (Object)(object)__instance)
{
HitData val = new HitData();
val.m_damage.m_blunt = shieldModifiers.ThornsDamage;
val.m_point = ((Component)attacker).transform.position;
Vector3 val2 = ((Component)attacker).transform.position - ((Component)__instance).transform.position;
val.m_dir = ((Vector3)(ref val2)).normalized;
val.SetAttacker((Character)(object)__instance);
attacker.Damage(val);
}
if (shieldModifiers.ResilienceStamina > 0f && _wasParry)
{
Player val3 = (Player)(object)((__instance is Player) ? __instance : null);
if (val3 != null)
{
((Character)val3).AddStamina(shieldModifiers.ResilienceStamina);
}
}
}
}
[HarmonyPatch(typeof(Player), "GetSkillFactor")]
internal static class WeaponSkillPatch
{
private static void Postfix(Player __instance, SkillType skill, ref float __result)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)__instance == (Object)null))
{
AddSkillBonusFromItem(((Humanoid)__instance).m_rightItem, skill, ref __result);
AddSkillBonusFromItem(((Humanoid)__instance).m_leftItem, skill, ref __result);
}
}
private static void AddSkillBonusFromItem(ItemData item, SkillType skill, ref float result)
{
//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 (item != null && ModifierData.HasAnyModifiers(item) && item.m_shared.m_skillType == skill)
{
RuneEffectManager.WeaponModifiers weaponModifiers = RuneEffectManager.GetWeaponModifiers(item);
if (weaponModifiers.SkillBonus > 0f)
{
result += weaponModifiers.SkillBonus / 100f;
}
}
}
}
public static void Register(Harmony harmony)
{
TryPatch(harmony, typeof(WeaponDamagePatch));
TryPatch(harmony, typeof(ArmorBonusPatch));
TryPatch(harmony, typeof(HitModifierPatch));
TryPatch(harmony, typeof(DamageResistancePatch));
TryPatch(harmony, typeof(AttackSpeedPatch));
TryPatch(harmony, typeof(PlayerUpdatePatch));
TryPatch(harmony, typeof(NoiseReductionPatch));
TryPatch(harmony, typeof(CombatPatch));
TryPatch(harmony, typeof(FoodValueBonusPatch));
TryPatch(harmony, typeof(StaminaRegenPatch));
TryPatch(harmony, typeof(HealthRegenPatch));
TryPatch(harmony, typeof(EitrRegenPatch));
TryPatch(harmony, typeof(MoveSpeedPatch));
TryPatch(harmony, typeof(CarryWeightPatch));
TryPatch(harmony, typeof(StaggerResistPatch));
TryPatch(harmony, typeof(DurabilityPatch));
TryPatch(harmony, typeof(ExplorerPatch));
TryPatch(harmony, typeof(ValhallaPatch));
TryPatch(harmony, typeof(UndyingPatch));
TryPatch(harmony, typeof(FrostShieldPatch));
TryPatch(harmony, typeof(ToolMasteryPatch));
TryPatch(harmony, typeof(ToolStaminaPatch));
TryPatch(harmony, typeof(ShieldBlockPowerPatch));
TryPatch(harmony, typeof(ShieldBlockAttackPatch));
TryPatch(harmony, typeof(WeaponSkillPatch));
}
private static void TryPatch(Harmony harmony, Type patchClass)
{
try
{
harmony.CreateClassProcessor(patchClass).Patch();
Logger.LogInfo((object)("StatPatch applied: " + patchClass.Name));
}
catch (Exception ex)
{
Logger.LogWarning((object)("StatPatch skipped " + patchClass.Name + ": " + ex.Message));
}
}
}
[HarmonyPatch(typeof(Player), "UseStamina")]
internal static class OutOfCombatStaminaPatch
{
private static readonly HashSet<string> IgnoredCreatures = new HashSet<string> { "Deer" };
private const float CombatRange = 25f;
private const float IgnoredCreatureCombatRange = 10f;
private const float CacheInterval = 1f;
private static float _lastCheckTime;
private static bool _lastResult;
private static readonly float CombatRangeSqr = 625f;
private static readonly float IgnoredRangeSqr = 100f;
public static void Register(Harmony harmony)
{
try
{
harmony.CreateClassProcessor(typeof(OutOfCombatStaminaPatch)).Patch();
Logger.LogInfo((object)"Patch applied: OutOfCombatStaminaPatch");
}
catch (Exception ex)
{
Logger.LogWarning((object)("Patch skipped OutOfCombatStaminaPatch: " + ex.Message));
}
}
private static void Prefix(ref Player __instance, ref float v)
{
if (ModConfig.EnableOutOfCombatStamina.Value)
{
float time = Time.time;
if (time - _lastCheckTime > 1f)
{
_lastCheckTime = time;
_lastResult = __instance.IsSensed() || IsTargetedByHostile(__instance);
}
if (!_lastResult)
{
v = 0f;
}
}
}
private static bool IsTargetedByHostile(Player player)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Expected O, but got Unknown
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
Vector3 position = ((Component)player).transform.position;
foreach (BaseAI instance in BaseAI.Instances)
{
BaseAI val = instance;
if ((Object)(object)val == (Object)null || (Object)(object)val.GetTargetCreature() != (Object)(object)player)
{
continue;
}
Vector3 val2 = ((Component)val).transform.position - position;
float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
string prefabName = Utils.GetPrefabName(((Component)val).gameObject);
if (IgnoredCreatures.Contains(prefabName))
{
if (sqrMagnitude <= IgnoredRangeSqr)
{
return true;
}
}
else if (sqrMagnitude <= CombatRangeSqr)
{
return true;
}
}
return false;
}
}
}
namespace RunesOfRefinement.Systems
{
public enum ItemRarity
{
Normal,
Magic,
Rare
}
public static class RarityHelper
{
public static readonly Color NormalColor = Color.white;
public static readonly Color MagicColor = new Color(0.53f, 0.81f, 0.98f);
public static readonly Color RareColor = new Color(1f, 0.95f, 0.3f);
public static readonly Color CorruptedColor = new Color(0.85f, 0.2f, 0.2f);
public static Color GetColor(ItemRarity rarity)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_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)
return (Color)(rarity switch
{
ItemRarity.Magic => MagicColor,
ItemRarity.Rare => RareColor,
_ => NormalColor,
});
}
public static int MaxPrefixes(ItemRarity rarity)
{
return rarity switch
{
ItemRarity.Magic => 1,
ItemRarity.Rare => 3,
_ => 0,
};
}
public static int MaxSuffixes(ItemRarity rarity)
{
return rarity switch
{
ItemRarity.Magic => 1,
ItemRarity.Rare => 3,
_ => 0,
};
}
public static int MaxAffixSlots(ItemRarity rarity)
{
return MaxPrefixes(rarity) + MaxSuffixes(rarity);
}
}
public enum AffixTarget
{
Weapon,
Armor,
Tool,
Shield,
Any
}
public enum AffixCategory
{
Offensive,
Defensive,
Utility,
Elemental,
Mythic
}
public enum AffixSlot
{
Prefix,
Suffix
}
public class AffixDefinition
{
public string Id;
public string NameToken;
public string DescToken;
public AffixTarget Target;
public AffixCategory Category;
public AffixSlot Slot;
public float MinValue;
public float MaxValue;
public bool IsMythic;
}
public class RolledAffix
{
public string AffixId;
public float Value;
public override string ToString()
{
return AffixId + ":" + Value.ToString("F2", CultureInfo.InvariantCulture);
}
public static RolledAffix Parse(string s)
{
string[] array = s.Split(new char[1] { ':' });
return new RolledAffix
{
AffixId = array[0],
Value = float.Parse(array[1], CultureInfo.InvariantCulture)
};
}
}
public static class AffixPool
{
private static readonly Random Rng = new Random();
internal static readonly float[][] TierScale = new float[6][]
{
new float[2] { 0f, 0.25f },
new float[2] { 0.15f, 0.4f },
new float[2] { 0.3f, 0.55f },
new float[2] { 0.45f, 0.7f },
new float[2] { 0.6f, 0.85f },
new float[2] { 0.8f, 1f }
};
public static readonly List<AffixDefinition> All = new List<AffixDefinition>
{
new AffixDefinition
{
Id = "heavy_blade",
NameToken = "$affix_heavy_blade",
DescToken = "$affix_heavy_blade_desc",
Target = AffixTarget.Weapon,
Category = AffixCategory.Offensive,
Slot = AffixSlot.Prefix,
MinValue = 3f,
MaxValue = 10f
},
new AffixDefinition
{
Id = "armor_pierce",
NameToken = "$affix_armor_pierce",
DescToken = "$affix_armor_pierce_desc",
Target = AffixTarget.Weapon,
Category = AffixCategory.Offensive,
Slot = AffixSlot.Prefix,
MinValue = 2f,
MaxValue = 8f
},
new AffixDefinition
{
Id = "crit_strike",
NameToken = "$affix_crit_strike",
DescToken = "$affix_crit_strike_desc",
Target = AffixTarget.Weapon,
Category = AffixCategory.Offensive,
Slot = AffixSlot.Prefix,
MinValue = 3f,
MaxValue = 12f
},
new AffixDefinition
{
Id = "backstab_bonus",
NameToken = "$affix_backstab_bonus",
DescToken = "$affix_backstab_bonus_desc",
Target = AffixTarget.Weapon,
Category = AffixCategory.Offensive,
Slot = AffixSlot.Prefix,
MinValue = 10f,
MaxValue = 40f
},
new AffixDefinition
{
Id = "elem_fire",
NameToken = "$affix_elem_fire",
DescToken = "$affix_elem_fire_desc",
Target = AffixTarget.Weapon,
Category = AffixCategory.Elemental,
Slot = AffixSlot.Prefix,
MinValue = 3f,
MaxValue = 15f
},
new AffixDefinition
{
Id = "elem_frost",
NameToken = "$affix_elem_frost",
DescToken = "$affix_elem_frost_desc",
Target = AffixTarget.Weapon,
Category = AffixCategory.Elemental,
Slot = AffixSlot.Prefix,
MinValue = 3f,
MaxValue = 15f
},
new AffixDefinition
{
Id = "elem_lightning",
NameToken = "$affix_elem_lightning",
DescToken = "$affix_elem_lightning_desc",
Target = AffixTarget.Weapon,
Category = AffixCategory.Elemental,
Slot = AffixSlot.Prefix,
MinValue = 3f,
MaxValue = 15f
},
new AffixDefinition
{
Id = "elem_poison",
NameToken = "$affix_elem_poison",
DescToken = "$affix_elem_poison_desc",
Target = AffixTarget.Weapon,
Category = AffixCategory.Elemental,
Slot = AffixSlot.Prefix,
MinValue = 3f,
MaxValue = 15f
},
new AffixDefinition
{
Id = "elem_spirit",
NameToken = "$affix_elem_spirit",
DescToken = "$affix_elem_spirit_desc",
Target = AffixTarget.Weapon,
Category = AffixCategory.Elemental,
Slot = AffixSlot.Prefix,
MinValue = 3f,
MaxValue = 15f
},
new AffixDefinition
{
Id = "swift",
NameToken = "$affix_swift",
DescToken = "$affix_swift_desc",
Target = AffixTarget.Weapon,
Category = AffixCategory.Offensive,
Slot = AffixSlot.Suffix,
MinValue = 1f,
MaxValue = 5f
},
new AffixDefinition
{
Id = "warrior_of_north",
NameToken = "$affix_warrior_of_north",
DescToken = "$affix_warrior_of_north_desc",
Target = AffixTarget.Weapon,
Category = AffixCategory.Utility,
Slot = AffixSlot.Suffix,
MinValue = 2f,
MaxValue = 8f
},
new AffixDefinition
{
Id = "bloodthirsty",
NameToken = "$affix_bloodthirsty",
DescToken = "$affix_bloodthirsty_desc",
Target = AffixTarget.Weapon,
Category = AffixCategory.Utility,
Slot = AffixSlot.Suffix,
MinValue = 1f,
MaxValue = 4f
},
new AffixDefinition
{
Id = "momentum",
NameToken = "$affix_momentum",
DescToken = "$affix_momentum_desc",
Target = AffixTarget.Weapon,
Category = AffixCategory.Utility,
Slot = AffixSlot.Suffix,
MinValue = 3f,
MaxValue = 10f
},
new AffixDefinition
{
Id = "knockback",
NameToken = "$affix_knockback",
DescToken = "$affix_knockback_desc",
Target = AffixTarget.Weapon,
Category = AffixCategory.Offensive,
Slot = AffixSlot.Suffix,
MinValue = 10f,
MaxValue = 40f
},
new AffixDefinition
{
Id = "hardened",
NameToken = "$affix_hardened",
DescToken = "$affix_hardened_desc",
Target = AffixTarget.Armor,
Category = AffixCategory.Defensive,
Slot = AffixSlot.Prefix,
MinValue = 2f,
MaxValue = 8f
},
new AffixDefinition
{
Id = "fortified",
NameToken = "$affix_fortified",
DescToken = "$affix_fortified_desc",
Target = AffixTarget.Armor,
Category = AffixCategory.Defensive,
Slot = AffixSlot.Prefix,
MinValue = 5f,
MaxValue = 25f
},
new AffixDefinition
{
Id = "frost_resist",
NameToken = "$affix_frost_resist",
DescToken = "$affix_frost_resist_desc",
Target = AffixTarget.Armor,
Category = AffixCategory.Defensive,
Slot = AffixSlot.Prefix,
MinValue = 5f,
MaxValue = 30f
},
new AffixDefinition
{
Id = "fire_resist",
NameToken = "$affix_fire_resist",
DescToken = "$affix_fire_resist_desc",
Target = AffixTarget.Armor,
Category = AffixCategory.Defensive,
Slot = AffixSlot.Prefix,
MinValue = 5f,
MaxValue = 30f
},
new AffixDefinition
{
Id = "poison_resist",
NameToken = "$affix_poison_resist",
DescToken = "$affix_poison_resist_desc",
Target = AffixTarget.Armor,
Category = AffixCategory.Defensive,
Slot = AffixSlot.Prefix,
MinValue = 5f,
MaxValue = 30f
},
new AffixDefinition
{
Id = "unfazed",
NameToken = "$affix_unfazed",
DescToken = "$affix_unfazed_desc",
Target = AffixTarget.Armor,
Category = AffixCategory.Defensive,
Slot = AffixSlot.Prefix,
MinValue = 5f,
MaxValue = 20f
},
new AffixDefinition
{
Id = "sturdy_build",
NameToken = "$affix_sturdy_build",
DescToken = "$affix_sturdy_build_desc",
Target = AffixTarget.Armor,
Category = AffixCategory.Utility,
Slot = AffixSlot.Suffix,
MinValue = 5f,
MaxValue = 20f
},
new AffixDefinition
{
Id = "regeneration",
NameToken = "$affix_regeneration",
DescToken = "$affix_regeneration_desc",
Target = AffixTarget.Armor,
Category = AffixCategory.Utility,
Slot = AffixSlot.Suffix,
MinValue = 3f,
MaxValue = 12f
},
new AffixDefinition
{
Id = "stealth",
NameToken = "$affix_stealth",
DescToken = "$affix_stealth_desc",
Target = AffixTarget.Armor,
Category = AffixCategory.Utility,
Slot = AffixSlot.Suffix,
MinValue = 5f,
MaxValue = 15f
},
new AffixDefinition
{
Id = "sprinter",
NameToken = "$affix_sprinter",
DescToken = "$affix_sprinter_desc",
Target = AffixTarget.Armor,
Category = AffixCategory.Utility,
Slot = AffixSlot.Suffix,
MinValue = 2f,
MaxValue = 8f
},
new AffixDefinition
{
Id = "hp_regen",
NameToken = "$affix_hp_regen",
DescToken = "$affix_hp_regen_desc",
Target = AffixTarget.Armor,
Category = AffixCategory.Defensive,
Slot = AffixSlot.Suffix,
MinValue = 5f,
MaxValue = 20f
},
new AffixDefinition
{
Id = "carry_weight",
NameToken = "$affix_carry_weight",
DescToken = "$affix_carry_weight_desc",
Target = AffixTarget.Armor,
Category = AffixCategory.Utility,
Slot = AffixSlot.Suffix,
MinValue = 10f,
MaxValue = 50f
},
new AffixDefinition
{
Id = "tool_mining",
NameToken = "$affix_tool_mining",
DescToken = "$affix_tool_mining_desc",
Target = AffixTarget.Tool,
Category = AffixCategory.Offensive,
Slot = AffixSlot.Prefix,
MinValue = 5f,
MaxValue = 25f
},
new AffixDefinition
{
Id = "tool_chopping",
NameToken = "$affix_tool_chopping",
DescToken = "$affix_tool_chopping_desc",
Target = AffixTarget.Tool,
Category = AffixCategory.Offensive,
Slot = AffixSlot.Prefix,
MinValue = 5f,
MaxValue = 25f
},
new AffixDefinition
{
Id = "tool_sharpened",
NameToken = "$affix_tool_sharpened",
DescToken = "$affix_tool_sharpened_desc",
Target = AffixTarget.Tool,
Category = AffixCategory.Offensive,
Slot = AffixSlot.Prefix,
MinValue = 3f,
MaxValue = 15f
},
new AffixDefinition
{
Id = "tool_lightweight",
NameToken = "$affix_tool_lightweight",
DescToken = "$affix_tool_lightweight_desc",
Target = AffixTarget.Tool,
Category = AffixCategory.Utility,
Slot = AffixSlot.Suffix,
MinValue = 2f,
MaxValue = 8f
},
new AffixDefinition
{
Id = "tool_mastery",
NameToken = "$affix_tool_mastery",
DescToken = "$affix_tool_mastery_desc",
Target = AffixTarget.Tool,
Category = AffixCategory.Utility,
Slot = AffixSlot.Suffix,
MinValue = 5f,
MaxValue = 25f
},
new AffixDefinition
{
Id = "tool_efficient",
NameToken = "$affix_tool_efficient",
DescToken = "$affix_tool_efficient_desc",
Target = AffixTarget.Tool,
Category = AffixCategory.Utility,
Slot = AffixSlot.Suffix,
MinValue = 3f,
MaxValue = 12f
},
new AffixDefinition
{
Id = "shield_fortress",
NameToken = "$affix_shield_fortress",
DescToken = "$affix_shield_fortress_desc",
Target = AffixTarget.Shield,
Category = AffixCategory.Defensive,
Slot = AffixSlot.Prefix,
MinValue = 5f,
MaxValue = 20f
},
new AffixDefinition
{
Id = "shield_thorns",
NameToken = "$affix_shield_thorns",
DescToken = "$affix_shield_thorns_desc",
Target = AffixTarget.Shield,
Category = AffixCategory.Defensive,
Slot = AffixSlot.Prefix,
MinValue = 3f,
MaxValue = 12f
},
new AffixDefinition
{
Id = "shield_parry",
NameToken = "$affix_shield_parry",
DescToken = "$affix_shield_parry_desc",
Target = AffixTarget.Shield,
Category = AffixCategory.Defensive,
Slot = AffixSlot.Prefix,
MinValue = 10f,
MaxValue = 30f
},
new AffixDefinition
{
Id = "shield_aegis",
NameToken = "$affix_shield_aegis",
DescToken = "$affix_shield_aegis_desc",
Target = AffixTarget.Shield,
Category = AffixCategory.Defensive,
Slot = AffixSlot.Suffix,
MinValue = 2f,
MaxValue = 8f
},
new AffixDefinition
{
Id = "shield_resilience",
NameToken = "$affix_shield_resilience",
DescToken = "$affix_shield_resilience_desc",
Target = AffixTarget.Shield,
Category = AffixCategory.Utility,
Slot = AffixSlot.Suffix,
MinValue = 3f,
MaxValue = 10f
},
new AffixDefinition
{
Id = "shield_bulwark",
NameToken = "$affix_shield_bulwark",
DescToken = "$affix_shield_bulwark_desc",
Target = AffixTarget.Shield,
Category = AffixCategory.Defensive,
Slot = AffixSlot.Suffix,
MinValue = 2f,
MaxValue = 8f
},
new AffixDefinition
{
Id = "durability",
NameToken = "$affix_durability",
DescToken = "$affix_durability_desc",
Target = AffixTarget.Any,
Category = AffixCategory.Utility,
Slot = AffixSlot.Suffix,
MinValue = 50f,
MaxValue = 200f
},
new AffixDefinition
{
Id = "eitr_regen",
NameToken = "$affix_eitr_regen",
DescToken = "$affix_eitr_regen_desc",
Target = AffixTarget.Armor,
Category = AffixCategory.Utility,
Slot = AffixSlot.Suffix,
MinValue = 5f,
MaxValue = 20f
},
new AffixDefinition
{
Id = "explorer",
NameToken = "$affix_explorer",
DescToken = "$affix_explorer_desc",
Target = AffixTarget.Armor,
Category = AffixCategory.Utility,
Slot = AffixSlot.Suffix,
MinValue = 5f,
MaxValue = 25f
},
new AffixDefinition
{
Id = "mythic_lightning_strike",
NameToken = "$affix_mythic_lightning",
DescToken = "$affix_mythic_lightning_desc",
Target = AffixTarget.Weapon,
Category = AffixCategory.Mythic,
Slot = AffixSlot.Prefix,
MinValue = 3f,
MaxValue = 7f,
IsMythic = true
},
new AffixDefinition
{
Id = "mythic_frost_shield",
NameToken = "$affix_mythic_frost_shield",
DescToken = "$affix_mythic_frost_shield_desc",
Target = AffixTarget.Armor,
Category = AffixCategory.Mythic,
Slot = AffixSlot.Prefix,
MinValue = 20f,
MaxValue = 40f,
IsMythic = true
},
new AffixDefinition
{
Id = "mythic_heimdall",
NameToken = "$affix_mythic_heimdall",
DescToken = "$affix_mythic_heimdall_desc",
Target = AffixTarget.Weapon,
Category = AffixCategory.Mythic,
Slot = AffixSlot.Prefix,
MinValue = 8f,
MaxValue = 15f,
IsMythic = true
},
new AffixDefinition
{
Id = "mythic_undying",
NameToken = "$affix_mythic_undying",
DescToken = "$affix_mythic_undying_desc",
Target = AffixTarget.Armor,
Category = AffixCategory.Mythic,
Slot = AffixSlot.Prefix,
MinValue = 15f,
MaxValue = 30f,
IsMythic = true
},
new AffixDefinition
{
Id = "mythic_berserker",
NameToken = "$affix_mythic_berserker",
DescToken = "$affix_mythic_berserker_desc",
Target = AffixTarget.Weapon,
Category = AffixCategory.Mythic,
Slot = AffixSlot.Prefix,
MinValue = 5f,
MaxValue = 12f,
IsMythic = true
},
new AffixDefinition
{
Id = "mythic_valhalla",
NameToken = "$affix_mythic_valhalla",
DescToken = "$affix_mythic_valhalla_desc",
Target = AffixTarget.Armor,
Category = AffixCategory.Mythic,
Slot = AffixSlot.Prefix,
MinValue = 3f,
MaxValue = 8f,
IsMythic = true
}
};
public static AffixDefinition Get(string id)
{
return All.FirstOrDefault((AffixDefinition a) => a.Id == id);
}
public static RolledAffix RollRandom(AffixTarget target, AffixSlot? slotConstraint = null, AffixCategory? forceCategory = null, HashSet<string> exclude = null, int tier = 6)
{
List<AffixDefinition> list = All.Where((AffixDefinition a) => !a.IsMythic && (a.Target == target || a.Target == AffixTarget.Any || (target == AffixTarget.Tool && a.Target == AffixTarget.Weapon) || (target == AffixTarget.Shield && a.Target == AffixTarget.Armor)) && (!slotConstraint.HasValue || a.Slot == slotConstraint) && (!forceCategory.HasValue || a.Category == forceCategory) && (exclude == null || !exclude.Contains(a.Id))).ToList();
if (list.Count == 0)
{
return null;
}
AffixDefinition def = list[Rng.Next(list.Count)];
return Roll(def, tier);
}
public static RolledAffix RollWithLimits(AffixTarget target, int curPrefixes, int maxPrefixes, int curSuffixes, int maxSuffixes, AffixCategory? forceCategory = null, HashSet<string> exclude = null, int tier = 6)
{
bool flag = curPrefixes < maxPrefixes;
bool flag2 = curSuffixes < maxSuffixes;
if (!flag && !flag2)
{
return null;
}
AffixSlot? slotConstraint = null;
if (flag && !flag2)
{
slotConstraint = AffixSlot.Prefix;
}
else if (flag2 && !flag)
{
slotConstraint = AffixSlot.Suffix;
}
return RollRandom(target, slotConstraint, forceCategory, exclude, tier);
}
public static RolledAffix RollElemental(AffixTarget target, int tier = 6)
{
return RollRandom(target, null, AffixCategory.Elemental, null, tier);
}
public static int CountPrefixes(List<RolledAffix> affixes)
{
return affixes.Count(delegate(RolledAffix a)
{
AffixDefinition affixDefinition = Get(a.AffixId);
return affixDefinition != null && affixDefinition.Slot == AffixSlot.Prefix;
});
}
public static int CountSuffixes(List<RolledAffix> affixes)
{
return affixes.Count(delegate(RolledAffix a)
{
AffixDefinition affixDefinition = Get(a.AffixId);
return affixDefinition != null && affixDefinition.Slot == AffixSlot.Suffix;
});
}
public static RolledAffix RollMythic(AffixTarget target, int tier = 6)
{
List<AffixDefinition> list = All.Where((AffixDefinition a) => a.IsMythic && (a.Target == target || a.Target == AffixTarget.Any || (target == AffixTarget.Tool && a.Target == AffixTarget.Weapon) || (target == AffixTarget.Shield && a.Target == AffixTarget.Armor))).ToList();
if (list.Count == 0)
{
return null;
}
AffixDefinition def = list[Rng.Next(list.Count)];
return Roll(def, tier);
}
public static RolledAffix RerollValue(RolledAffix existing, int tier = 6)
{
AffixDefinition affixDefinition = Get(existing.AffixId);
if (affixDefinition == null)
{
return existing;
}
return Roll(affixDefinition, tier);
}
public static RolledAffix MaxRollValue(RolledAffix existing, int tier = 6)
{
AffixDefinition affixDefinition = Get(existing.AffixId);
if (affixDefinition == null)
{
return existing;
}
tier = Mathf.Clamp(tier, 1, 6);
float num = affixDefinition.MaxValue - affixDefinition.MinValue;
float num2 = affixDefinition.MinValue + num * TierScale[tier - 1][1];
num2 = Mathf.Round(num2 * 10f) / 10f;
return new RolledAffix
{
AffixId = affixDefinition.Id,
Value = num2
};
}
public static string GetRollQualityColor(RolledAffix affix)
{
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_0170: Unknown result type (might be due to invalid IL or missing references)
//IL_0149: Unknown result type (might be due to invalid IL or missing references)
//IL_015d: Unknown result type (might be due to invalid IL or missing references)
//IL_0164: Unknown result type (might be due to invalid IL or missing references)
//IL_0169: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
AffixDefinition affixDefinition = Get(affix.AffixId);
if (affixDefinition == null)
{
return "#CCCCCC";
}
float num = affixDefinition.MaxValue - affixDefinition.MinValue;
float num2 = ((num > 0f) ? Mathf.Clamp01((affix.Value - affixDefinition.MinValue) / num) : 0.5f);
Color val;
if (num2 < 0.25f)
{
float num3 = num2 / 0.25f;
val = Color.Lerp(new Color(0.55f, 0.55f, 0.55f), Color.white, num3);
}
else if (num2 < 0.5f)
{
float num4 = (num2 - 0.25f) / 0.25f;
val = Color.Lerp(Color.white, new Color(0.4f, 1f, 0.6f), num4);
}
else if (num2 < 0.75f)
{
float num5 = (num2 - 0.5f) / 0.25f;
val = Color.Lerp(new Color(0.4f, 1f, 0.6f), new Color(0.4f, 0.7f, 1f), num5);
}
else
{
float num6 = (num2 - 0.75f) / 0.25f;
val = Color.Lerp(new Color(0.4f, 0.7f, 1f), new Color(1f, 0.85f, 0.3f), num6);
}
return "#" + ColorUtility.ToHtmlStringRGB(val);
}
private static RolledAffix Roll(AffixDefinition def, int tier = 6)
{
tier = Mathf.Clamp(tier, 1, 6);
float num = def.MaxValue - def.MinValue;
float num2 = def.MinValue + num * TierScale[tier - 1][0];
float num3 = def.MinValue + num * TierScale[tier - 1][1];
float num4 = (float)((double)num2 + Rng.NextDouble() * (double)(num3 - num2));
num4 = Mathf.Round(num4 * 10f) / 10f;
return new RolledAffix
{
AffixId = def.Id,
Value = num4
};
}
}
public static class ModifierData
{
private const string KeyRarity = "ror_rarity";
private const string KeyAffixCount = "ror_affix_count";
private const string KeyAffixPrefix = "ror_affix_";
private const string KeyMythicAffix = "ror_mythic_affix";
private const string KeyCorrupted = "ror_corrupted";
public static ItemRarity GetRarity(ItemData item)
{
if (item.m_customData.TryGetValue("ror_rarity", out var value))
{
switch (value)
{
case "magic":
return ItemRarity.Magic;
case "rare":
return ItemRarity.Rare;
case "mythic":
return ItemRarity.Rare;
}
}
return ItemRarity.Normal;
}
public static void SetRarity(ItemData item, ItemRarity rarity)
{
switch (rarity)
{
case ItemRarity.Magic:
item.m_customData["ror_rarity"] = "magic";
break;
case ItemRarity.Rare:
item.m_customData["ror_rarity"] = "rare";
break;
default:
item.m_customData["ror_rarity"] = "normal";
break;
}
}
public static List<RolledAffix> GetAffixes(ItemData item)
{
List<RolledAffix> list = new List<RolledAffix>();
if (!item.m_customData.TryGetValue("ror_affix_count", out var value))
{
return list;
}
if (!int.TryParse(value, out var result))
{
return list;
}
for (int i = 0; i < result; i++)
{
if (item.m_customData.TryGetValue("ror_affix_" + i, out var value2))
{
list.Add(RolledAffix.Parse(value2));
}
}
return list;
}
public static void SetAffixes(ItemData item, List<RolledAffix> affixes)
{
if (item.m_customData.TryGetValue("ror_affix_count", out var value) && int.TryParse(value, out var result))
{
for (int i = 0; i < result; i++)
{
item.m_customData.Remove("ror_affix_" + i);
}
}
item.m_customData["ror_affix_count"] = affixes.Count.ToString();
for (int j = 0; j < affixes.Count; j++)
{
item.m_customData["ror_affix_" + j] = affixes[j].ToString();
}
}
public static RolledAffix GetMythicAffix(ItemData item)
{
if (item.m_customData.TryGetValue("ror_mythic_affix", out var value))
{
return RolledAffix.Parse(value);
}
return null;
}
public static void SetMythicAffix(ItemData item, RolledAffix affix)
{
item.m_customData["ror_mythic_affix"] = affix.ToString();
}
public static bool IsCorrupted(ItemData item)
{
return item.m_customData.ContainsKey("ror_corrupted");
}
public static void SetCorrupted(ItemData item, bool corrupted)
{
if (corrupted)
{
item.m_customData["ror_corrupted"] = "1";
}
else
{
item.m_customData.Remove("ror_corrupted");
}
}
public static bool HasAnyModifiers(ItemData item)
{
return item.m_customData.ContainsKey("ror_rarity");
}
}
public static class RuneEffectManager
{
public class WeaponModifiers
{
public float DamagePercent;
public float AttackSpeedPercent;
public float ArmorIgnore;
public float SkillBonus;
public float LifestealPercent;
public float FireDamage;
public float FrostDamage;
public float LightningDamage;
public float PoisonDamage;
public float SpiritDamage;
public float CritStrikePercent;
public float BackstabBonusPercent;
public float KnockbackPercent;
public float StaminaOnKill;
public float DurabilityBonus;
public float LightningStrikeChance;
public float HeimdallDamagePercent;
public float BerserkerPercent;
}
public class ToolModifiers
{
public float MiningPercent;
public float ChoppingPercent;
public float ToolDamagePercent;
public float SwingSpeedPercent;
public float MasteryPercent;
public float StaminaReductionPercent;
public float DurabilityBonus;
}
public class ShieldModifiers
{
public float FortressPercent;
public float ThornsDamage;
public float ParryBonusPercent;
public float AegisPercent;
public float ResilienceStamina;
public float BulwarkArmor;
public float DurabilityBonus;
}
private static float _bonusDamagePercent;
private static float _armorIgnore;
private static float _attackSpeedPercent;
private static float _lifestealPercent;
private static float _weaponSkillBonus;
private static float _fireDamage;
private static float _frostDamage;
private static float _lightningDamage;
private static float _poisonDamage;
private static float _spiritDamage;
private static float _critStrikePercent;
private static float _backstabBonusPercent;
private static float _knockbackPercent;
private static float _staminaOnKill;
private static float _bonusArmorFlat;
private static float _maxStaminaBonus;
private static float _staminaRegenPercent;
private static float _noiseReductionPercent;
private static float _maxHealthBonus;
private static float _frostResistance;
private static float _fireResistance;
private static float _poisonResistance;
private static float _staggerResistPercent;
private static float _moveSpeedPercent;
private static float _hpRegenPercent;
private static float _carryWeightBonus;
private static float _durabilityBonus;
private static float _eitrRegenPercent;
private static float _explorerPercent;
private static float _mythicLightningChance;
private static float _mythicFrostSlowPercent;
private static float _mythicHeimdallDamagePercent;
private static float _mythicUndyingPercent;
private static float _mythicBerserkerPercent;
private static float _mythicValhallaXpPercent;
private static float _toolMiningPercent;
private static float _toolChoppingPercent;
private static float _toolDamagePercent;
private static float _toolSwingSpeedPercent;
private static float _toolMasteryPercent;
private static float _toolEfficiencyPercent;
private static float _shieldFortressPercent;
private static float _shieldThorns;
private static float _shieldParryPercent;
private static float _shieldAegisPercent;
private static float _shieldResilienceStamina;
private static float _shieldBulwarkArmor;
private static int _lastEquipHash;
public static float BonusDamagePercent => _bonusDamagePercent;
public static float BonusArmorFlat => _bonusArmorFlat;
public static float ArmorIgnore => _armorIgnore;
public static float AttackSpeedPercent => _attackSpeedPercent;
public static float LifestealPercent => _lifestealPercent;
public static float WeaponSkillBonus => _weaponSkillBonus;
public static float MaxStaminaBonus => _maxStaminaBonus;
public static float StaminaRegenPercent => _staminaRegenPercent;
public static float NoiseReductionPercent => _noiseReductionPercent;
public static float MaxHealthBonus => _maxHealthBonus;
public static float FrostResistance => _frostResistance;
public static float FireResistance => _fireResistance;
public static float PoisonResistance => _poisonResistance;
public static float FireDamage => _fireDamage;
public static float FrostDamage => _frostDamage;
public static float LightningDamage => _lightningDamage;
public static float PoisonDamage => _poisonDamage;
public static float SpiritDamage => _spiritDamage;
public static float CritStrikePercent => _critStrikePercent;
public static float BackstabBonusPercent => _backstabBonusPercent;
public static float KnockbackPercent => _knockbackPercent;
public static float StaminaOnKill => _staminaOnKill;
public static float StaggerResistPercent => _staggerResistPercent;
public static float MoveSpeedPercent => _moveSpeedPercent;
public static float HpRegenPercent => _hpRegenPercent;
public static float CarryWeightBonus => _carryWeightBonus;
public static float DurabilityBonus => _durabilityBonus;
public static float EitrRegenPercent => _eitrRegenPercent;
public static float ExplorerPercent => _explorerPercent;
public static float MythicLightningChance => _mythicLightningChance;
public static float MythicFrostSlowPercent => _mythicFrostSlowPercent;
public static float MythicHeimdallDamagePercent => _mythicHeimdallDamagePercent;
public static float MythicUndyingPercent => _mythicUndyingPercent;
public static float MythicBerserkerPercent => _mythicBerserkerPercent;
public static float MythicValhallaXpPercent => _mythicValhallaXpPercent;
public static float ToolMiningPercent => _toolMiningPercent;
public static float ToolChoppingPercent => _toolChoppingPercent;
public static float ToolDamagePercent => _toolDamagePercent;
public static float ToolSwingSpeedPercent => _toolSwingSpeedPercent;
public static float ToolMasteryPercent => _toolMasteryPercent;
public static float ToolEfficiencyPercent => _toolEfficiencyPercent;
public static float ShieldFortressPercent => _shieldFortressPercent;
public static float ShieldThorns => _shieldThorns;
public static float ShieldParryPercent => _shieldParryPercent;
public static float ShieldAegisPercent => _shieldAegisPercent;
public static float ShieldResilienceStamina => _shieldResilienceStamina;
public static float ShieldBulwarkArmor => _shieldBulwarkArmor;
public static WeaponModifiers GetWeaponModifiers(ItemData weapon)
{
WeaponModifiers weaponModifiers = new WeaponModifiers();
if (weapon == null || !ModifierData.HasAnyModifiers(weapon))
{
return weaponModifiers;
}
foreach (RolledAffix affix in ModifierData.GetAffixes(weapon))
{
switch (affix.AffixId)
{
case "heavy_blade":
weaponModifiers.DamagePercent += affix.Value;
break;
case "swift":
weaponModifiers.AttackSpeedPercent += affix.Value;
break;
case "armor_pierce":
weaponModifiers.ArmorIgnore += affix.Value;
break;
case "warrior_of_north":
weaponModifiers.SkillBonus += affix.Value;
break;
case "bloodthirsty":
weaponModifiers.LifestealPercent += affix.Value;
break;
case "elem_fire":
weaponModifiers.FireDamage += affix.Value;
break;
case "elem_frost":
weaponModifiers.FrostDamage += affix.Value;
break;
case "elem_lightning":
weaponModifiers.LightningDamage += affix.Value;
break;
case "elem_poison":
weaponModifiers.PoisonDamage += affix.Value;
break;
case "elem_spirit":
weaponModifiers.SpiritDamage += affix.Value;
break;
case "crit_strike":
weaponModifiers.CritStrikePercent += affix.Value;
break;
case "backstab_bonus":
weaponModifiers.BackstabBonusPercent += affix.Value;
break;
case "knockback":
weaponModifiers.KnockbackPercent += affix.Value;
break;
case "momentum":
weaponModifiers.StaminaOnKill += affix.Value;
break;
case "durability":
weaponModifiers.DurabilityBonus += affix.Value;
break;
}
}
RolledAffix mythicAffix = ModifierData.GetMythicAffix(weapon);
if (mythicAffix != null)
{
switch (mythicAffix.AffixId)
{
case "mythic_lightning_strike":
weaponModifiers.LightningStrikeChance = mythicAffix.Value;
break;
case "mythic_heimdall":
weaponModifiers.HeimdallDamagePercent = mythicAffix.Value;
break;
case "mythic_berserker":
weaponModifiers.BerserkerPercent = mythicAffix.Value;
break;
}
}
return weaponModifiers;
}
public static float GetArmorBonus(ItemData armor)
{
if (armor == null || !ModifierData.HasAnyModifiers(armor))
{
return 0f;
}
float num = 0f;
foreach (RolledAffix affix in ModifierData.GetAffixes(armor))
{
if (affix.AffixId == "hardened")
{
num += affix.Value;
}
if (affix.AffixId == "shield_bulwark")
{
num += affix.Value;
}
}
return num;
}
public static ToolModifiers GetToolModifiers(ItemData tool)
{
ToolModifiers toolModifiers = new ToolModifiers();
if (tool == null || !ModifierData.HasAnyModifiers(tool))
{
return toolModifiers;
}
foreach (RolledAffix affix in ModifierData.GetAffixes(tool))
{
switch (affix.AffixId)
{
case "tool_mining":
toolModifiers.MiningPercent += affix.Value;
break;
case "tool_chopping":
toolModifiers.ChoppingPercent += affix.Value;
break;
case "tool_sharpened":
toolModifiers.ToolDamagePercent += affix.Value;
break;
case "tool_lightweight":
toolModifiers.SwingSpeedPercent += affix.Value;
break;
case "tool_mastery":
toolModifiers.MasteryPercent += affix.Value;
break;
case "tool_efficient":
toolModifiers.StaminaReductionPercent += affix.Value;
break;
case "durability":
toolModifiers.DurabilityBonus += affix.Value;
break;
}
}
return toolModifiers;
}
public static ShieldModifiers GetShieldModifiers(ItemData shield)
{
ShieldModifiers shieldModifiers = new ShieldModifiers();
if (shield == null || !ModifierData.HasAnyModifiers(shield))
{
return shieldModifiers;
}
foreach (RolledAffix affix in ModifierData.GetAffixes(shield))
{
switch (affix.AffixId)
{
case "shield_fortress":
shieldModifiers.FortressPercent += affix.Value;
break;
case "shield_thorns":
shieldModifiers.ThornsDamage += affix.Value;
break;
case "shield_parry":
shieldModifiers.ParryBonusPercent += affix.Value;
break;
case "shield_aegis":
shieldModifiers.AegisPercent += affix.Value;
break;
case "shield_resilience":
shieldModifiers.ResilienceStamina += affix.Value;
break;
case "shield_bulwark":
shieldModifiers.BulwarkArmor += affix.Value;
break;
case "durability":
shieldModifiers.DurabilityBonus += affix.Value;
break;
}
}
return shieldModifiers;
}
public static void Recalculate(Player player)
{
if ((Object)(object)player == (Object)null)
{
return;
}
int num = ComputeEquipHash(player);
if (num == _lastEquipHash)
{
return;
}
_lastEquipHash = num;
_bonusDamagePercent = 0f;
_bonusArmorFlat = 0f;
_armorIgnore = 0f;
_attackSpeedPercent = 0f;
_lifestealPercent = 0f;
_weaponSkillBonus = 0f;
_maxStaminaBonus = 0f;
_staminaRegenPercent = 0f;
_noiseReductionPercent = 0f;
_maxHealthBonus = 0f;
_frostResistance = 0f;
_fireResistance = 0f;
_poisonResistance = 0f;
_fireDamage = 0f;
_frostDamage = 0f;
_lightningDamage = 0f;
_poisonDamage = 0f;
_spiritDamage = 0f;
_critStrikePercent = 0f;
_backstabBonusPercent = 0f;
_knockbackPercent = 0f;
_staminaOnKill = 0f;
_staggerResistPercent = 0f;
_moveSpeedPercent = 0f;
_hpRegenPercent = 0f;
_carryWeightBonus = 0f;
_durabilityBonus = 0f;
_eitrRegenPercent = 0f;
_explorerPercent = 0f;
_mythicLightningChance = 0f;
_mythicFrostSlowPercent = 0f;
_mythicHeimdallDamagePercent = 0f;
_mythicUndyingPercent = 0f;
_mythicBerserkerPercent = 0f;
_mythicValhallaXpPercent = 0f;
_toolMiningPercent = 0f;
_toolChoppingPercent = 0f;
_toolDamagePercent = 0f;
_toolSwingSpeedPercent = 0f;
_toolMasteryPercent = 0f;
_toolEfficiencyPercent = 0f;
_shieldFortressPercent = 0f;
_shieldThorns = 0f;
_shieldParryPercent = 0f;
_shieldAegisPercent = 0f;
_shieldResilienceStamina = 0f;
_shieldBulwarkArmor = 0f;
Inventory inventory = ((Humanoid)player).GetInventory();
if (inventory == null)
{
return;
}
foreach (ItemData equippedItem in inventory.GetEquippedItems())
{
if (EssenceLogic.IsEquipment(equippedItem) && ModifierData.HasAnyModifiers(equippedItem))
{
ProcessAffixes(ModifierData.GetAffixes(equippedItem));
ProcessMythic(ModifierData.GetMythicAffix(equippedItem));
}
}
}
public static void Invalidate()
{
_lastEquipHash = -1;
}
private static int ComputeEquipHash(Player player)
{
int num = 17;
Inventory inventory = ((Humanoid)player).GetInventory();
if (inventory == null)
{
return num;
}
foreach (ItemData equippedItem in inventory.GetEquippedItems())
{
if (EssenceLogic.IsEquipment(equippedItem))
{
num = num * 31 + equippedItem.m_gridPos.x;
num = num * 31 + equippedItem.m_gridPos.y;
num = num * 31 + (equippedItem.m_shared?.m_name?.GetHashCode()).GetValueOrDefault();
if (equippedItem.m_customData.TryGetValue("ror_affix_count", out var value))
{
num = num * 31 + value.GetHashCode();
}
if (equippedItem.m_customData.TryGetValue("ror_rarity", out var value2))
{
num = num * 31 + value2.GetHashCode();
}
if (equippedItem.m_customData.TryGetValue("ror_corrupted",