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 PraetorisClient v0.1.55
PraetorisClient.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Net.Security; using System.Net.Sockets; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Authentication; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using EpicLoot; using EpicLoot.Abilities; using EpicLoot.Adventure; using EpicLoot.CraftingV2; using EpicLootAPI; using EpicLootLeslieAlphaTest.src; using EpicLootLeslieAlphaTest.src.MagicEffectss; using EpicLootLeslieAlphaTest.src.StatusEffects; using EpicLootLeslieAlphaTest.src.StatusEffects.VFX; using EpicLootLeslieAlphaTest.src.Utilities; using EpicLoot_UnityLib; using GUIFramework; using HarmonyLib; using JetBrains.Annotations; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using PraetorisClient.CreatureOwnership; using PraetorisClient.ServerChestFeature; using Splatform; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.UI; using ValheimRcon; using ValheimRcon.Commands; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("PraetorisClient")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("PraetorisClient")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("3A303D15-4E60-4110-8EDF-EDF38560FBE2")] [assembly: AssemblyFileVersion("0.1.55")] [assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.55.0")] [module: UnverifiableCode] 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; } } } namespace EpicLootLeslieAlphaTest.src { [HarmonyPatch(typeof(EnchantingUIController), "BuildEnchantedRune")] internal class EnchantingUIControllerMod { [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown FieldInfo fieldInfo = AccessTools.Field(typeof(MagicItemEffectDefinitions), "AllDefinitions"); FieldInfo fieldInfo2 = AccessTools.Field(typeof(MagicItemEffect), "EffectValue"); CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldsfld, (object)fieldInfo, (string)null) }); int pos = val.Pos; val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Stfld, (object)fieldInfo2, (string)null) }); int pos2 = val.Pos; val.Start().Advance(pos).RemoveInstructions(pos2 - pos + 1); return val.InstructionEnumeration(); } [HarmonyPostfix] private static void Postfix(ref ItemData __result) { if (__result == null) { return; } MagicItem magicItem = ItemDataExtensions.GetMagicItem(__result); if (magicItem == null) { return; } foreach (MagicItemEffect effect in magicItem.Effects) { effect.EffectValue = (float)Math.Round(effect.EffectValue, 2); } ItemDataExtensions.SaveMagicItem(__result, magicItem); } } public static class EnchantingHelper { internal static bool AwaitingConfirmation; internal static float PendingDestroyChance; public static float RuneTooPowerfulEtchDestructionChance(ItemData item, ItemData rune) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) MagicItemEffect val = ItemDataExtensions.GetMagicItem(rune).Effects[0]; if (MagicItemEffectDefinitions.AllDefinitions[val.EffectType].ValuesPerRarity.GetValueDefForRarity(ItemDataExtensions.GetRarity(item)) != null) { float maxValue = MagicItemEffectDefinitions.AllDefinitions[val.EffectType].ValuesPerRarity.GetValueDefForRarity(ItemDataExtensions.GetRarity(item)).MaxValue; bool flag = val.EffectValue >= maxValue * 1.1f; float num = val.EffectValue / maxValue - 1f; Debug.LogWarning((object)$"[EpicLootAlpha] effectValue: {val.EffectValue}, maxDefault: {maxValue}, tooPowerful: {flag}"); if (flag) { return Mathf.Round(Mathf.Clamp(num * 100f, 10f, 90f) / 5f) * 5f; } } return 0f; } } [HarmonyPatch(typeof(EnchantingUIController), "RuneEnhanceItemAndReturnSuccess")] internal class RuneEnhanceItem_DestroyChance_Patch { [HarmonyPrefix] private static bool Prefix(ItemData item, ItemData rune, int enchantment, ref GameObject __result) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) MagicItemEffect val = ItemDataExtensions.GetMagicItem(rune).Effects[0]; if (MagicItemEffectDefinitions.AllDefinitions[val.EffectType].ValuesPerRarity.GetValueDefForRarity(ItemDataExtensions.GetRarity(item)) != null) { float num = EnchantingHelper.RuneTooPowerfulEtchDestructionChance(item, rune); if (num > 0f) { float num2 = Random.value * 100f; if (num > num2) { ((Humanoid)Player.m_localPlayer).UnequipItem(item, true); ((Humanoid)Player.m_localPlayer).GetInventory().RemoveItem(item); ((Humanoid)Player.m_localPlayer).GetInventory().RemoveItem(rune); ((Character)Player.m_localPlayer).Message((MessageType)2, $"You rolled {num2:F1} You are not worthy of the rune's power. The item and rune has been destroyed.", 0, (Sprite)null); __result = null; return false; } } } return true; } } public static class MagicEffects { public static void Init() { MagicItemEffectDefinition magicItemEffectDefinition = new MagicItemEffectDefinition("AncestralSlam", "Ancestral Slam", "Summons ancestral spirit to mirror your attacks for each enemy hit."); magicItemEffectDefinition.Requirements.AllowedItemTypes.Add("TwoHandedWeapon"); magicItemEffectDefinition.Requirements.AllowedSkillTypes.Add((SkillType)3); Helpers.Add(magicItemEffectDefinition.Requirements.AllowedRarities, ItemRarity.Epic, ItemRarity.Legendary, ItemRarity.Mythic); magicItemEffectDefinition.SelectionWeight = 1f; magicItemEffectDefinition.Register(); MagicItemEffectDefinition magicItemEffectDefinition2 = new MagicItemEffectDefinition("GlancingBlows", "Glancing Blows", "Increases your block value by 50%. Take addtional damage equal to 50% of all blocked or parried hits. This additional damage is only mitigate by player armor and is not reduced from player resistances."); magicItemEffectDefinition2.Requirements.ItemHasBlockPower = true; Helpers.Add(magicItemEffectDefinition2.Requirements.AllowedRarities, ItemRarity.Magic, ItemRarity.Rare, ItemRarity.Epic, ItemRarity.Legendary, ItemRarity.Mythic); magicItemEffectDefinition2.ValuesPerRarity.Magic.Set(1f, 1f); magicItemEffectDefinition2.ValuesPerRarity.Rare = new ValueDef(1f, 1f, 1f); magicItemEffectDefinition2.ValuesPerRarity.Epic = new ValueDef(1f, 1f, 1f); magicItemEffectDefinition2.ValuesPerRarity.Legendary = new ValueDef(1f, 1f, 1f); magicItemEffectDefinition2.ValuesPerRarity.Mythic = new ValueDef(1f, 1f, 1f); magicItemEffectDefinition2.SelectionWeight = 3f; magicItemEffectDefinition2.Register(); MagicItemEffectDefinition magicItemEffectDefinition3 = new MagicItemEffectDefinition("Retaliation", "Retaliation +{0}", "On block gain a stack of Relatliation. On Attack consumes a stack of Relataliation to increase the attack speed of your next attack string. All stacks of Retaliation expire after 5 seconds. Consuming or gaining a stack of Retaliation resets the expiration timer."); magicItemEffectDefinition3.Requirements.ItemHasBlockPower = true; Helpers.Add(magicItemEffectDefinition3.Requirements.AllowedRarities, ItemRarity.Magic, ItemRarity.Rare, ItemRarity.Epic, ItemRarity.Legendary, ItemRarity.Mythic); magicItemEffectDefinition3.ValuesPerRarity.Magic.Set(1f, 1f); magicItemEffectDefinition3.ValuesPerRarity.Rare = new ValueDef(2f, 2f, 1f); magicItemEffectDefinition3.ValuesPerRarity.Epic = new ValueDef(3f, 3f, 1f); magicItemEffectDefinition3.ValuesPerRarity.Legendary = new ValueDef(4f, 4f, 1f); magicItemEffectDefinition3.ValuesPerRarity.Mythic = new ValueDef(5f, 5f, 1f); magicItemEffectDefinition3.SelectionWeight = 5f; magicItemEffectDefinition3.Register(); MagicItemEffectDefinition magicItemEffectDefinition4 = new MagicItemEffectDefinition("Infusion", "Infusion +{0}%", "Cleanses certain status effects and adds <b><color=yellow>X</color></b>% of weapon damage as their respective type. Certain cleansed status effects grant addittional bonuses."); Helpers.Add(magicItemEffectDefinition4.Requirements.AllowedItemTypes, "OneHandedWeapon", "TwoHandedWeapon"); List<SkillType> allowedSkillTypes = magicItemEffectDefinition4.Requirements.AllowedSkillTypes; SkillType[] array = new SkillType[8]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); Helpers.Add(allowedSkillTypes, (SkillType[])(object)array); Helpers.Add(magicItemEffectDefinition4.Requirements.AllowedRarities, ItemRarity.Magic, ItemRarity.Rare, ItemRarity.Epic, ItemRarity.Legendary, ItemRarity.Mythic); magicItemEffectDefinition4.ValuesPerRarity.Magic.Set(2f, 4f); magicItemEffectDefinition4.ValuesPerRarity.Rare = new ValueDef(3f, 6f, 1f); magicItemEffectDefinition4.ValuesPerRarity.Epic = new ValueDef(4f, 8f, 1f); magicItemEffectDefinition4.ValuesPerRarity.Legendary = new ValueDef(5f, 10f, 1f); magicItemEffectDefinition4.ValuesPerRarity.Mythic = new ValueDef(6f, 12f, 1f); magicItemEffectDefinition4.SelectionWeight = 2f; magicItemEffectDefinition4.Ability = "Infusion"; AbilityProxyDefinition abilityProxyDefinition = new AbilityProxyDefinition("Infusion", AbilityActivationMode.Activated, typeof(Infusion.InfusionAbilityProxy)); abilityProxyDefinition.Ability.Cooldown = 120f; PrefabManager.OnPrefabsRegistered += delegate { EpicLoot.RegisterAsset("InfusionIcon", ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("SetEffect_MageArmor"))?.m_icon); }; abilityProxyDefinition.Ability.IconAsset = "InfusionIcon"; magicItemEffectDefinition4.Register(); MagicItemEffectDefinition magicItemEffectDefinition5 = new MagicItemEffectDefinition("Whirlwind", "Whirlwind", "Spin"); magicItemEffectDefinition5.Requirements.AllowedItemTypes.Add("TwoHandedWeapon"); magicItemEffectDefinition5.Requirements.AllowedSkillTypes.Add((SkillType)4); Helpers.Add(magicItemEffectDefinition5.Requirements.AllowedRarities, ItemRarity.Epic, ItemRarity.Legendary, ItemRarity.Mythic); magicItemEffectDefinition5.SelectionWeight = 1f; magicItemEffectDefinition5.Register(); MagicItemEffectDefinition magicItemEffectDefinition6 = new MagicItemEffectDefinition("Onslaught", "Onslaught +{0}%", "Grants Onslaught on last hit of an attack string and when hitting a staggered enemy. While in last hit of attack string during Onslaught you continue attacking using the last hit animation of your attack string. Each consecutive Onslaught hit deals {0}% increased damage per hit. Onslaught expires if an enemy has not been struck with an attack in last hit animation for 2 seconds."); Helpers.Add(magicItemEffectDefinition6.Requirements.AllowedItemTypes, "OneHandedWeapon", "TwoHandedWeapon"); magicItemEffectDefinition6.Requirements.AllowedSkillTypes.Add((SkillType)3); Helpers.Add(magicItemEffectDefinition6.Requirements.AllowedRarities, ItemRarity.Magic, ItemRarity.Rare, ItemRarity.Epic, ItemRarity.Legendary, ItemRarity.Mythic); magicItemEffectDefinition6.ValuesPerRarity.Magic.Set(5f, 8f); magicItemEffectDefinition6.ValuesPerRarity.Rare = new ValueDef(6f, 10f, 1f); magicItemEffectDefinition6.ValuesPerRarity.Epic = new ValueDef(7f, 12f, 1f); magicItemEffectDefinition6.ValuesPerRarity.Legendary = new ValueDef(8f, 14f, 1f); magicItemEffectDefinition6.ValuesPerRarity.Mythic = new ValueDef(9f, 16f, 1f); magicItemEffectDefinition6.SelectionWeight = 5f; magicItemEffectDefinition6.Register(); MagicItemEffectDefinition magicItemEffectDefinition7 = new MagicItemEffectDefinition("PerfectStrike", "Perfect Strike +{0}%", "Allows Perfect Strikes to be performed. When attack is repeated with perfect timing your next strike will deal {0}% increased damage."); magicItemEffectDefinition7.Requirements.AllowedItemTypes.Add("TwoHandedWeapon"); magicItemEffectDefinition7.Requirements.AllowedSkillTypes.Add((SkillType)7); Helpers.Add(magicItemEffectDefinition7.Requirements.AllowedRarities, ItemRarity.Magic, ItemRarity.Rare, ItemRarity.Epic, ItemRarity.Legendary, ItemRarity.Mythic); magicItemEffectDefinition7.ValuesPerRarity.Magic.Set(30f, 50f, 2f); magicItemEffectDefinition7.ValuesPerRarity.Rare = new ValueDef(40f, 60f, 2f); magicItemEffectDefinition7.ValuesPerRarity.Epic = new ValueDef(50f, 70f, 2f); magicItemEffectDefinition7.ValuesPerRarity.Legendary = new ValueDef(50f, 80f, 2f); magicItemEffectDefinition7.ValuesPerRarity.Mythic = new ValueDef(50f, 100f, 1f); magicItemEffectDefinition7.SelectionWeight = 5f; magicItemEffectDefinition7.Register(); } } [HarmonyPatch(typeof(EnchantingTableUIPanelBase), "OnMainButtonClicked")] internal class RuneUIMod_OnMainButtonClicked_Patch { private static bool Prefix(EnchantingTableUIPanelBase __instance) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_0128: 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_0143: Unknown result type (might be due to invalid IL or missing references) if (!(__instance is RuneUI)) { return true; } if ((bool)AccessTools.Field(typeof(EnchantingTableUIPanelBase), "_inProgress").GetValue(__instance)) { return true; } if ((int)AccessTools.Field(typeof(RuneUI), "_runeAction").GetValue(__instance) != 1) { return true; } if (EnchantingHelper.AwaitingConfirmation) { EnchantingHelper.AwaitingConfirmation = false; EnchantingHelper.PendingDestroyChance = 0f; return true; } Tuple<InventoryItemListElement, int> singleSelectedItem = ((MultiSelectItemList)AccessTools.Field(typeof(EnchantingTableUIPanelBase), "AvailableItems").GetValue(__instance)).GetSingleSelectedItem<InventoryItemListElement>(); if (((singleSelectedItem != null) ? singleSelectedItem.Item1.GetItem() : null) == null) { return true; } Tuple<InventoryItemListElement, int> singleSelectedItem2 = ((MultiSelectItemList)AccessTools.Field(typeof(RuneUI), "AvailableRunes").GetValue(__instance)).GetSingleSelectedItem<InventoryItemListElement>(); if (((singleSelectedItem2 != null) ? singleSelectedItem2.Item1.GetItem() : null) == null) { return true; } float num = EnchantingHelper.RuneTooPowerfulEtchDestructionChance(singleSelectedItem.Item1.GetItem(), singleSelectedItem2.Item1.GetItem()); if (num > 0f) { EnchantingHelper.AwaitingConfirmation = true; EnchantingHelper.PendingDestroyChance = num; Text val = (Text)AccessTools.Field(typeof(RuneUI), "Warning").GetValue(__instance); val.text = $"WARNING: {num:0}% chance to DESTROY your item!! Click Etch again to confirm."; ((Graphic)val).color = Color.red; return false; } return true; } } [HarmonyPatch(typeof(RuneUI), "DoMainAction")] internal class RuneUI_DoMainACtion_Patch { private static bool Prefix(RuneUI __instance) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) EnchantingHelper.AwaitingConfirmation = false; if ((int)AccessTools.Field(typeof(RuneUI), "_runeAction").GetValue(__instance) != 1) { return true; } Tuple<InventoryItemListElement, int> tuple = ((MultiSelectItemList)AccessTools.Field(typeof(EnchantingTableUIPanelBase), "AvailableItems").GetValue(__instance)).GetSelectedItems<InventoryItemListElement>().FirstOrDefault(); ((EnchantingTableUIPanelBase)__instance).Cancel(); if (((tuple != null) ? tuple.Item1.GetItem() : null) == null) { return false; } MultiSelectItemList val = (MultiSelectItemList)AccessTools.Field(typeof(RuneUI), "AvailableRunes").GetValue(__instance); ItemData item = val.GetSingleSelectedItem<InventoryItemListElement>().Item1.GetItem(); ItemData item2 = tuple.Item1.GetItem(); int num = (int)AccessTools.Field(typeof(RuneUI), "_selectedEnchantmentIndex").GetValue(__instance); FieldInfo fieldInfo = AccessTools.Field(typeof(RuneUI), "_successDialog"); GameObject val2 = (GameObject)fieldInfo.GetValue(__instance); if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)val2); } GameObject val3 = RuneUI.RuneEnchancedItem.Invoke(item2, item, num); if ((Object)(object)val3 != (Object)null) { fieldInfo.SetValue(__instance, val3); val3.SetActive(true); InventoryManagement.Instance.RemoveExactItem(item, 1); } else { fieldInfo.SetValue(__instance, null); AccessTools.Method(typeof(RuneUI), "Unlock", (Type[])null, (Type[])null).Invoke(__instance, null); } MultiSelectItemList val4 = (MultiSelectItemList)AccessTools.Field(typeof(RuneUI), "CostList").GetValue(__instance); val4.SetItems(new List<IListElement>()); ((EnchantingTableUIPanelBase)__instance).DeselectAll(); AccessTools.Method(typeof(RuneUI), "RefreshAvailableItems", (Type[])null, (Type[])null).Invoke(__instance, null); AccessTools.Field(typeof(RuneUI), "_selectedEnchantmentIndex").SetValue(__instance, -1); val4.SetItems(new List<IListElement>()); val.SetItems(new List<IListElement>()); return false; } } [HarmonyPatch(typeof(RuneUI), "Lock")] internal class RuneUI_Lock_Patch { private static void Postfix(RuneUI __instance) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown Button val = (Button)AccessTools.Field(typeof(EnchantingTableUIPanelBase), "MainButton").GetValue(__instance); if ((Object)(object)val != (Object)null) { ((Selectable)val).interactable = true; } } } } namespace EpicLootLeslieAlphaTest.src.Utilities { public static class Help { public static void CopyFieldsFrom<T, V>(this T target, V source) where T : Humanoid where V : Humanoid { Dictionary<string, FieldInfo> dictionary = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToDictionary((FieldInfo f) => f.Name); FieldInfo[] fields = typeof(V).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (dictionary.TryGetValue(fieldInfo.Name, out var value) && value.FieldType.IsAssignableFrom(fieldInfo.FieldType)) { value.SetValue(target, fieldInfo.GetValue(source)); } } } public static void Add<T>(this List<T> list, params T[] values) { list.AddRange(values); } public static void Remove<T>(this GameObject prefab) where T : Component { T val = default(T); if (prefab.TryGetComponent<T>(ref val)) { Object.DestroyImmediate((Object)(object)val); } } } public class HumanoidFactory { public static GameObject playerAncestor; private static bool Loaded; public static void Create() { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) if (Loaded) { return; } GameObject playerPrefab = Game.instance.m_playerPrefab; bool activeSelf = playerPrefab.activeSelf; playerPrefab.SetActive(false); Player component = playerPrefab.GetComponent<Player>(); playerAncestor = Object.Instantiate<GameObject>(playerPrefab); playerAncestor.Remove<AbilityController>(); playerAncestor.Remove<AdventureComponent>(); playerAncestor.Remove<Player>(); playerAncestor.Remove<PlayerController>(); playerAncestor.Remove<Talker>(); playerAncestor.Remove<Skills>(); playerAncestor.Remove<ZSyncTransform>(); ((Object)playerAncestor).name = "playerAncestorHashString"; playerAncestor.GetComponent<ZNetView>().m_persistent = false; playerAncestor.GetComponent<ZNetView>().m_type = (ObjectType)0; Humanoid obj = playerAncestor.AddComponent<Humanoid>(); obj.CopyFieldsFrom<Humanoid, Player>(component); ((Character)obj).m_animator = playerAncestor.GetComponentInChildren<Animator>(); ((Character)obj).m_zanim = playerAncestor.GetComponent<ZSyncAnimation>(); ((Character)obj).m_body = playerAncestor.GetComponent<Rigidbody>(); ((Character)obj).m_collider = playerAncestor.GetComponent<CapsuleCollider>(); obj.m_visEquipment = playerAncestor.GetComponent<VisEquipment>(); ((Character)obj).m_turnSpeed = 0f; ((Character)obj).m_animEvent = playerAncestor.GetComponentInChildren<CharacterAnimEvent>(); ((Character)obj).m_eye = Utils.FindChild(playerAncestor.transform, "EyePos", (IterativeSearchType)0); if ((Object)(object)playerAncestor.GetComponent<ZSyncAnimation>() != (Object)null) { playerAncestor.GetComponent<ZSyncAnimation>().m_animator = playerAncestor.GetComponent<Animator>(); playerAncestor.GetComponent<ZSyncAnimation>().m_nview = playerAncestor.GetComponent<ZNetView>(); } Rigidbody component2 = playerAncestor.GetComponent<Rigidbody>(); if ((Object)(object)component2 != (Object)null) { component2.isKinematic = false; component2.useGravity = false; component2.constraints = (RigidbodyConstraints)126; } Shader shader = Shader.Find("Sprites/Default"); Renderer[] componentsInChildren = playerAncestor.GetComponentsInChildren<Renderer>(true); foreach (Renderer obj2 in componentsInChildren) { Material[] materials = obj2.materials; materials[0].shader = shader; materials[0].mainTexture = null; materials[0].color = new Color(0.3f, 0.5f, 0.9f, 0.03f); materials[1].shader = shader; materials[1].mainTexture = null; materials[1].color = new Color(0.3f, 0.5f, 0.9f, 0f); materials[0].SetColor("_SkinColor", new Color(0.3f, 0.5f, 0.9f, 0.03f)); _ = materials[0].shader; obj2.materials = materials; } componentsInChildren = playerAncestor.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((val is SkinnedMeshRenderer) ? val : null); if (val2 != null && (Object)(object)val2.sharedMesh != (Object)null) { _ = ((Object)val2.sharedMesh).name; } else if (val is MeshRenderer) { MeshFilter component3 = ((Component)val).GetComponent<MeshFilter>(); if (component3 != null && (Object)(object)component3.sharedMesh != (Object)null) { _ = ((Object)component3.sharedMesh).name; } } } Collider[] componentsInChildren2 = playerAncestor.GetComponentsInChildren<Collider>(); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].enabled = false; } ZNetScene.instance.m_namedPrefabs[StringExtensionMethods.GetStableHashCode("playerAncestorHashString")] = playerAncestor; playerPrefab.SetActive(activeSelf); playerAncestor.SetActive(false); Loaded = true; } } public static class WA { public static bool IsHeavyWeapon(ItemData item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 AnimationState animationState = item.m_shared.m_animationState; if ((int)animationState != 8 && (int)animationState != 2 && (int)animationState != 7) { return (int)animationState == 13; } return true; } public static bool IsRangedWeapon(ItemData item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 AnimationState animationState = item.m_shared.m_animationState; if ((int)animationState != 3 && (int)animationState != 10 && (int)animationState != 12) { return (int)animationState == 14; } return true; } public static bool IsTwoHanded(ItemData item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 AnimationState animationState = item.m_shared.m_animationState; if ((int)animationState != 8 && (int)animationState != 2 && (int)animationState != 7 && (int)animationState != 13 && (int)animationState != 15 && (int)animationState != 11) { return (int)animationState == 0; } return true; } } } namespace EpicLootLeslieAlphaTest.src.StatusEffects { public static class SERegistry { public static void RegisterStatusEffects() { Register<SE_Retaliation>("SE_Retaliation"); Register<SE_Onslaught>("SE_Onslaught"); Register<SE_FireInfused>("SE_FireInfused"); Register<SE_FrostInfused>("SE_FrostInfused"); Register<SE_LightningInfused>("SE_LightningInfused"); Register<SE_PoisonInfused>("SE_PoisonInfused"); Register<SE_WindInfused>("SE_WindInfused"); } private static void Register<T>(string effectName) where T : StatusEffect { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown T val = ScriptableObject.CreateInstance<T>(); ((Object)(object)val).name = effectName; ((StatusEffect)val).m_name = effectName; ItemManager.Instance.AddStatusEffect(new CustomStatusEffect((StatusEffect)(object)val, false)); } } public class SE_FireInfused : SE_Stats { public const string EffectName = "SE_FireInfused"; private GameObject m_vfxInstance; private GameObject m_vfxInstance2; private ItemData weapon; private float infusedFireDamage; public float Efficacy { get; set; } public override void Setup(Character character) { //IL_00a2: 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) ((SE_Stats)this).Setup(character); if (!((Object)(object)Player.m_localPlayer == (Object)null)) { Efficacy = Infusion.Efficacy; GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("SwordDyrnwyn"); object icon; if (itemPrefab == null) { icon = null; } else { ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); icon = ((component != null) ? component.m_itemData.m_shared.m_icons[0] : null); } ((StatusEffect)this).m_icon = (Sprite)icon; ((StatusEffect)this).m_name = "Fire Infused"; ((StatusEffect)this).m_ttl = 120f; Player localPlayer = Player.m_localPlayer; weapon = ((localPlayer != null) ? ((Humanoid)localPlayer).GetCurrentWeapon() : null); if (weapon != null && !WA.IsRangedWeapon(weapon)) { DamageTypes damage = weapon.GetDamage(); float totalDamage = ((DamageTypes)(ref damage)).GetTotalDamage(); float num = (WA.IsHeavyWeapon(weapon) ? 2f : 1f); Logger.LogWarning((object)string.Format("[FireInfused] weapon base damage:{0} efficacy:{1} weapon multiplier:{2} added:{3} + {4} * {5}", totalDamage, Efficacy, num, totalDamage * Player.m_localPlayer.GetTotalActiveMagicEffectValue("Infusion", 0.01f), Player.m_localPlayer.GetTotalActiveMagicEffectValue("Infusion", 0.01f) * Efficacy, num)); infusedFireDamage += totalDamage * Player.m_localPlayer.GetTotalActiveMagicEffectValue("Infusion", 0.01f) + Efficacy * Player.m_localPlayer.GetTotalActiveMagicEffectValue("Infusion", 0.1f) * num; weapon.m_shared.m_damages.m_fire += infusedFireDamage; Logger.LogWarning((object)$"Added {infusedFireDamage} fire damage"); } } } public override void Stop() { ((StatusEffect)this).Stop(); if (weapon != null) { weapon.m_shared.m_damages.m_fire -= infusedFireDamage; } if ((Object)(object)m_vfxInstance != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance); } if ((Object)(object)m_vfxInstance2 != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance2); } } public override void UpdateStatusEffect(float dt) { ((SE_Stats)this).UpdateStatusEffect(dt); if (!((Object)(object)Player.m_localPlayer == (Object)null)) { if (((Humanoid)Player.m_localPlayer).GetCurrentWeapon() == weapon && (Object)(object)m_vfxInstance == (Object)null) { CreateVFX(); } else if (((Humanoid)Player.m_localPlayer).GetCurrentWeapon() != weapon && (Object)(object)m_vfxInstance != (Object)null) { DestroyVFX(); } } } private void CreateVFX() { VisEquipment visEquipment = ((Humanoid)Player.m_localPlayer).m_visEquipment; if (!WA.IsTwoHanded(weapon)) { m_vfxInstance = Object.Instantiate<GameObject>(InfusionVFX.FireInfusionVFX, visEquipment.m_rightHand); m_vfxInstance.SetActive(true); return; } m_vfxInstance = Object.Instantiate<GameObject>(InfusionVFX.FireInfusionVFX, visEquipment.m_rightHand); m_vfxInstance2 = Object.Instantiate<GameObject>(InfusionVFX.FireInfusionVFX, visEquipment.m_leftHand); m_vfxInstance.SetActive(true); m_vfxInstance2.SetActive(true); } private void DestroyVFX() { if ((Object)(object)m_vfxInstance != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance); m_vfxInstance = null; } if ((Object)(object)m_vfxInstance2 != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance2); m_vfxInstance2 = null; } } } public class SE_FrostInfused : SE_Stats { public const string EffectName = "SE_FrostInfused"; private GameObject m_vfxInstance; private GameObject m_vfxInstance2; private ItemData weapon; private float infusedFrostDamage; public float Efficacy { get; set; } public override void Setup(Character character) { //IL_00a2: 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) ((SE_Stats)this).Setup(character); if (!((Object)(object)Player.m_localPlayer == (Object)null)) { Efficacy = Infusion.Efficacy; GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("SwordMistwalker"); object icon; if (itemPrefab == null) { icon = null; } else { ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); icon = ((component != null) ? component.m_itemData.m_shared.m_icons[0] : null); } ((StatusEffect)this).m_icon = (Sprite)icon; ((StatusEffect)this).m_name = "Frost Infused"; ((StatusEffect)this).m_ttl = 120f; Player localPlayer = Player.m_localPlayer; weapon = ((localPlayer != null) ? ((Humanoid)localPlayer).GetCurrentWeapon() : null); if (weapon != null && !WA.IsRangedWeapon(weapon)) { DamageTypes damage = weapon.GetDamage(); float totalDamage = ((DamageTypes)(ref damage)).GetTotalDamage(); float num = (WA.IsHeavyWeapon(weapon) ? 2f : 1f); Logger.LogWarning((object)string.Format("[FrostInfused] weapon base damage:{0} efficacy:{1} weapon multiplier:{2} added:{3} + {4} * {5}", totalDamage, Efficacy, num, totalDamage * Player.m_localPlayer.GetTotalActiveMagicEffectValue("Infusion", 0.01f), Player.m_localPlayer.GetTotalActiveMagicEffectValue("Infusion", 0.01f) * Efficacy, num)); infusedFrostDamage += totalDamage * Player.m_localPlayer.GetTotalActiveMagicEffectValue("Infusion", 0.01f) + Efficacy * Player.m_localPlayer.GetTotalActiveMagicEffectValue("Infusion", 0.1f) * num; weapon.m_shared.m_damages.m_frost += infusedFrostDamage; Logger.LogWarning((object)$"Added {infusedFrostDamage} frost damage"); } } } public override void Stop() { ((StatusEffect)this).Stop(); if (weapon != null) { weapon.m_shared.m_damages.m_frost -= infusedFrostDamage; } if ((Object)(object)m_vfxInstance != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance); } if ((Object)(object)m_vfxInstance2 != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance2); } } public override void UpdateStatusEffect(float dt) { ((SE_Stats)this).UpdateStatusEffect(dt); if (!((Object)(object)Player.m_localPlayer == (Object)null)) { if (((Humanoid)Player.m_localPlayer).GetCurrentWeapon() == weapon && (Object)(object)m_vfxInstance == (Object)null) { CreateVFX(); } else if (((Humanoid)Player.m_localPlayer).GetCurrentWeapon() != weapon && (Object)(object)m_vfxInstance != (Object)null) { DestroyVFX(); } } } private void CreateVFX() { VisEquipment visEquipment = ((Humanoid)Player.m_localPlayer).m_visEquipment; if (!WA.IsTwoHanded(weapon)) { m_vfxInstance = Object.Instantiate<GameObject>(InfusionVFX.FrostInfusionVFX, visEquipment.m_rightHand); m_vfxInstance.SetActive(true); return; } m_vfxInstance = Object.Instantiate<GameObject>(InfusionVFX.FrostInfusionVFX, visEquipment.m_rightHand); m_vfxInstance2 = Object.Instantiate<GameObject>(InfusionVFX.FrostInfusionVFX, visEquipment.m_leftHand); m_vfxInstance.SetActive(true); m_vfxInstance2.SetActive(true); } private void DestroyVFX() { if ((Object)(object)m_vfxInstance != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance); m_vfxInstance = null; } if ((Object)(object)m_vfxInstance2 != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance2); m_vfxInstance2 = null; } } } public class SE_LightningInfused : SE_Stats { public const string EffectName = "SE_LightningInfused"; private GameObject m_vfxInstance; private GameObject m_vfxInstance2; private ItemData weapon; private float infusedLightningDamage; public float Efficacy { get; set; } public override void Setup(Character character) { //IL_00a2: 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) ((SE_Stats)this).Setup(character); if (!((Object)(object)Player.m_localPlayer == (Object)null)) { Efficacy = Infusion.Efficacy; GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("SwordNiedhoggLightning"); object icon; if (itemPrefab == null) { icon = null; } else { ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); icon = ((component != null) ? component.m_itemData.m_shared.m_icons[0] : null); } ((StatusEffect)this).m_icon = (Sprite)icon; ((StatusEffect)this).m_name = "Lightning Infused"; ((StatusEffect)this).m_ttl = 120f; Player localPlayer = Player.m_localPlayer; weapon = ((localPlayer != null) ? ((Humanoid)localPlayer).GetCurrentWeapon() : null); if (weapon != null && !WA.IsRangedWeapon(weapon)) { DamageTypes damage = weapon.GetDamage(); float totalDamage = ((DamageTypes)(ref damage)).GetTotalDamage(); float num = (WA.IsHeavyWeapon(weapon) ? 2f : 1f); Logger.LogWarning((object)string.Format("[LightningInfused] weapon base damage:{0} efficacy:{1} weapon multiplier:{2} added:{3} + {4} * {5}", totalDamage, Efficacy, num, totalDamage * Player.m_localPlayer.GetTotalActiveMagicEffectValue("Infusion", 0.01f), Player.m_localPlayer.GetTotalActiveMagicEffectValue("Infusion", 0.01f) * Efficacy, num)); infusedLightningDamage += totalDamage * Player.m_localPlayer.GetTotalActiveMagicEffectValue("Infusion", 0.01f) + Efficacy * Player.m_localPlayer.GetTotalActiveMagicEffectValue("Infusion", 0.1f) * num; weapon.m_shared.m_damages.m_lightning += infusedLightningDamage; Logger.LogWarning((object)$"Added {infusedLightningDamage} lightning damage"); } } } public override void Stop() { ((StatusEffect)this).Stop(); if (weapon != null) { weapon.m_shared.m_damages.m_lightning -= infusedLightningDamage; } if ((Object)(object)m_vfxInstance != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance); } if ((Object)(object)m_vfxInstance2 != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance2); } } public override void UpdateStatusEffect(float dt) { ((SE_Stats)this).UpdateStatusEffect(dt); if (!((Object)(object)Player.m_localPlayer == (Object)null)) { if (((Humanoid)Player.m_localPlayer).GetCurrentWeapon() == weapon && (Object)(object)m_vfxInstance == (Object)null) { CreateVFX(); } else if (((Humanoid)Player.m_localPlayer).GetCurrentWeapon() != weapon && (Object)(object)m_vfxInstance != (Object)null) { DestroyVFX(); } } } private void CreateVFX() { VisEquipment visEquipment = ((Humanoid)Player.m_localPlayer).m_visEquipment; if (!WA.IsTwoHanded(weapon)) { m_vfxInstance = Object.Instantiate<GameObject>(InfusionVFX.LightningInfusionVFX, visEquipment.m_rightHand); m_vfxInstance.SetActive(true); return; } m_vfxInstance = Object.Instantiate<GameObject>(InfusionVFX.LightningInfusionVFX, visEquipment.m_rightHand); m_vfxInstance2 = Object.Instantiate<GameObject>(InfusionVFX.LightningInfusionVFX, visEquipment.m_leftHand); m_vfxInstance.SetActive(true); m_vfxInstance2.SetActive(true); } private void DestroyVFX() { if ((Object)(object)m_vfxInstance != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance); m_vfxInstance = null; } if ((Object)(object)m_vfxInstance2 != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance2); m_vfxInstance2 = null; } } } public class SE_Onslaught : SE_Stats { public const string EffectName = "SE_Onslaught"; public int m_stacks; public int m_maxStacks = 9999; private float m_onslaughtHits; private const float m_expire = 2f; public override void Setup(Character character) { ((SE_Stats)this).Setup(character); if ((Object)(object)character.m_animator != (Object)null) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("MaceIron"); object icon; if (itemPrefab == null) { icon = null; } else { ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); icon = ((component != null) ? component.m_itemData.m_shared.m_icons[0] : null); } ((StatusEffect)this).m_icon = (Sprite)icon; ((StatusEffect)this).m_name = "Onslaught Hits"; ((StatusEffect)this).m_flashIcon = true; m_stacks++; } } public void AddStack() { ((StatusEffect)this).m_ttl = 2f; if (m_stacks < m_maxStacks) { m_stacks++; ((StatusEffect)this).m_time = 0f; } } public void ConsumeStack() { if (m_stacks > 0) { m_stacks--; ((StatusEffect)this).m_time = 0f; } } public override void UpdateStatusEffect(float dt) { ((SE_Stats)this).UpdateStatusEffect(dt); Player localPlayer = Player.m_localPlayer; if (!WA.IsRangedWeapon((localPlayer != null) ? ((Humanoid)localPlayer).GetCurrentWeapon() : null)) { if (m_stacks <= 0 && !((StatusEffect)this).m_character.InAttack()) { ((StatusEffect)this).m_character.GetSEMan().RemoveStatusEffect((StatusEffect)(object)this, false); } if (!((Character)Player.m_localPlayer).InAttack() && ((StatusEffect)this).m_time > 1.5f) { m_onslaughtHits = 0f; } } } public override void ModifyAttack(SkillType skill, ref HitData hitData) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) ((SE_Stats)this).ModifyAttack(skill, ref hitData); Logger.LogWarning((object)$"stacks{m_stacks}"); Character character = ((StatusEffect)this).m_character; int? num = ((Humanoid)(((character is Humanoid) ? character : null)?)).m_currentAttack?.m_currentAttackCainLevel; if (m_stacks > 0 && !(num < 2)) { m_onslaughtHits += 1f; Logger.LogWarning((object)$"{m_onslaughtHits}"); float num2 = 1f + m_onslaughtHits * Player.m_localPlayer.GetTotalActiveMagicEffectValue("Onslaught", 0.01f); hitData.ApplyModifier(num2); } } public override string GetIconText() { return $"{m_onslaughtHits}"; } } public class SE_PoisonInfused : SE_Stats { public const string EffectName = "SE_PoisonInfused"; private GameObject m_vfxInstance; private GameObject m_vfxInstance2; private ItemData weapon; private float infusedPoisonDamage; public float Efficacy { get; set; } public override void Setup(Character character) { //IL_00a2: 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) ((SE_Stats)this).Setup(character); if (!((Object)(object)Player.m_localPlayer == (Object)null)) { Efficacy = Infusion.Efficacy; GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("SwordNiedhoggNature"); object icon; if (itemPrefab == null) { icon = null; } else { ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); icon = ((component != null) ? component.m_itemData.m_shared.m_icons[0] : null); } ((StatusEffect)this).m_icon = (Sprite)icon; ((StatusEffect)this).m_name = "Poison Infused"; ((StatusEffect)this).m_ttl = 120f; Player localPlayer = Player.m_localPlayer; weapon = ((localPlayer != null) ? ((Humanoid)localPlayer).GetCurrentWeapon() : null); if (weapon != null && !WA.IsRangedWeapon(weapon)) { DamageTypes damage = weapon.GetDamage(); float totalDamage = ((DamageTypes)(ref damage)).GetTotalDamage(); float num = (WA.IsHeavyWeapon(weapon) ? 2f : 1f); Logger.LogWarning((object)string.Format("[PoisonInfused] weapon base damage:{0} efficacy:{1} weapon multiplier:{2} added:{3} + {4} * {5}", totalDamage, Efficacy, num, totalDamage * Player.m_localPlayer.GetTotalActiveMagicEffectValue("Infusion", 0.01f), Player.m_localPlayer.GetTotalActiveMagicEffectValue("Infusion", 0.01f) * Efficacy, num)); infusedPoisonDamage += totalDamage * Player.m_localPlayer.GetTotalActiveMagicEffectValue("Infusion", 0.01f) + Efficacy * Player.m_localPlayer.GetTotalActiveMagicEffectValue("Infusion", 0.1f) * num; weapon.m_shared.m_damages.m_poison += infusedPoisonDamage; Logger.LogWarning((object)$"Added {infusedPoisonDamage} poison damage"); } } } public override void Stop() { ((StatusEffect)this).Stop(); if (weapon != null) { weapon.m_shared.m_damages.m_poison -= infusedPoisonDamage; } if ((Object)(object)m_vfxInstance != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance); } if ((Object)(object)m_vfxInstance2 != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance2); } } public override void UpdateStatusEffect(float dt) { ((SE_Stats)this).UpdateStatusEffect(dt); if (!((Object)(object)Player.m_localPlayer == (Object)null)) { if (((Humanoid)Player.m_localPlayer).GetCurrentWeapon() == weapon && (Object)(object)m_vfxInstance == (Object)null) { CreateVFX(); } else if (((Humanoid)Player.m_localPlayer).GetCurrentWeapon() != weapon && (Object)(object)m_vfxInstance != (Object)null) { DestroyVFX(); } } } private void CreateVFX() { VisEquipment visEquipment = ((Humanoid)Player.m_localPlayer).m_visEquipment; if (!WA.IsTwoHanded(weapon)) { m_vfxInstance = Object.Instantiate<GameObject>(InfusionVFX.PoisonInfusionVFX, visEquipment.m_rightHand); m_vfxInstance.SetActive(true); return; } m_vfxInstance = Object.Instantiate<GameObject>(InfusionVFX.PoisonInfusionVFX, visEquipment.m_rightHand); m_vfxInstance2 = Object.Instantiate<GameObject>(InfusionVFX.PoisonInfusionVFX, visEquipment.m_leftHand); m_vfxInstance.SetActive(true); m_vfxInstance2.SetActive(true); } private void DestroyVFX() { if ((Object)(object)m_vfxInstance != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance); m_vfxInstance = null; } if ((Object)(object)m_vfxInstance2 != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance2); m_vfxInstance2 = null; } } } public class SE_Retaliation : SE_Stats { public const string EffectName = "SE_Retaliation"; public int m_stacks; public int m_maxStacks = 1; private const float m_expire = 5f; private float baseSpeed = 1f; private bool addedRetaliationSpeed; private bool amAttacking; private static readonly Dictionary<string, float> _animSpeeds = new Dictionary<string, float> { { "atgeir_attack", 1.2f }, { "atgeir_secondary", 2f }, { "knife_stab", 1.2f }, { "knife_secondary", 1.1f }, { "battleaxe_attack", 1.6f }, { "swing_axe", 1.2f }, { "swing_longsword", 1.2f }, { "mace_secondary", 1.35f }, { "spear_poke", 1.2f }, { "sword_secondary", 0.5f }, { "dualaxes", 1.1f }, { "dualaxes_secondary", 1.1f }, { "dual_knives", 1.1f }, { "dual_knives_secondary", 1.2f }, { "greatsword", 1.2f }, { "greatsword_secondary", 1.2f }, { "swing_sledge", 1.4f }, { "unarmed_attack", 2.2f } }; public override void Setup(Character character) { ((SE_Stats)this).Setup(character); if ((Object)(object)character.m_animator != (Object)null) { m_maxStacks = Mathf.RoundToInt(Player.m_localPlayer.GetTotalActiveMagicEffectValue("Retaliation")); baseSpeed = character.m_animator.speed; character.m_animator.speed = ((Retaliation.AttackType != null && _animSpeeds.TryGetValue(Retaliation.AttackType, out var value)) ? value : 1.2f); GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("ShieldBanded"); object icon; if (itemPrefab == null) { icon = null; } else { ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); icon = ((component != null) ? component.m_itemData.m_shared.m_icons[3] : null); } ((StatusEffect)this).m_icon = (Sprite)icon; ((StatusEffect)this).m_name = "Retaliation"; ((StatusEffect)this).m_flashIcon = true; } } public void AddStack() { ((StatusEffect)this).m_ttl = 5f; if (m_stacks < m_maxStacks) { m_stacks++; ((StatusEffect)this).m_time = 0f; } } public void ConsumeStack() { if (m_stacks > 0) { m_stacks--; ((StatusEffect)this).m_time = 0f; } } public override void UpdateStatusEffect(float dt) { ((SE_Stats)this).UpdateStatusEffect(dt); Player localPlayer = Player.m_localPlayer; if (!WA.IsRangedWeapon((localPlayer != null) ? ((Humanoid)localPlayer).GetCurrentWeapon() : null)) { if (!((StatusEffect)this).m_character.InAttack() && amAttacking) { ConsumeStack(); } amAttacking = ((StatusEffect)this).m_character.InAttack(); if ((Object)(object)((StatusEffect)this).m_character.m_animator != (Object)null && ((StatusEffect)this).m_character.m_animator.speed >= 5f && !addedRetaliationSpeed) { Animator animator = ((StatusEffect)this).m_character.m_animator; animator.speed += ((Retaliation.AttackType != null && _animSpeeds.TryGetValue(Retaliation.AttackType, out var value)) ? value : 1.2f); addedRetaliationSpeed = true; } if ((Object)(object)((StatusEffect)this).m_character.m_animator != (Object)null && ((StatusEffect)this).m_character.m_animator.speed < 5f) { ((StatusEffect)this).m_character.m_animator.speed = ((Retaliation.AttackType != null && _animSpeeds.TryGetValue(Retaliation.AttackType, out var value2)) ? value2 : 1.2f); } if (m_stacks > 0 && !((StatusEffect)this).m_character.InAttack()) { ((StatusEffect)this).m_character.m_animator.speed = baseSpeed; } if (m_stacks <= 0 && !((StatusEffect)this).m_character.InAttack()) { ((StatusEffect)this).m_character.GetSEMan().RemoveStatusEffect((StatusEffect)(object)this, false); } } } public override void Stop() { ((StatusEffect)this).Stop(); if ((Object)(object)((StatusEffect)this).m_character?.m_animator != (Object)null) { ((StatusEffect)this).m_character.m_animator.speed = baseSpeed; } } public override string GetIconText() { return $"{m_stacks}"; } } public class SE_WindInfused : SE_Stats { public const string EffectName = "SE_WindInfused"; private GameObject m_vfxInstance; private GameObject m_vfxInstance2; private ItemData weapon; private float infusedWindValue; private float baseSpeed = 1f; public override void Setup(Character character) { ((SE_Stats)this).Setup(character); if (!((Object)(object)Player.m_localPlayer == (Object)null)) { weapon = ((Humanoid)Player.m_localPlayer).GetCurrentWeapon(); baseSpeed = ((StatusEffect)this).m_character.m_animator.speed; ((StatusEffect)this).m_name = "Wind Infused"; ((StatusEffect)this).m_ttl = 120f; } } public override void Stop() { ((StatusEffect)this).Stop(); ((StatusEffect)this).m_character.m_animator.speed = baseSpeed; if ((Object)(object)m_vfxInstance != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance); } if ((Object)(object)m_vfxInstance2 != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance2); } } public override void UpdateStatusEffect(float dt) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) ((SE_Stats)this).UpdateStatusEffect(dt); if (!((Object)(object)Player.m_localPlayer == (Object)null)) { _ = ((Humanoid)Player.m_localPlayer).m_visEquipment.m_rightItemInstance; _ = weapon.m_shared.m_animationState; _ = ((Humanoid)Player.m_localPlayer).m_visEquipment.m_rightHand; _ = ((Humanoid)Player.m_localPlayer).m_visEquipment.m_leftHand; if (((Character)Player.m_localPlayer).InAttack() && ((Humanoid)Player.m_localPlayer).GetCurrentWeapon() == weapon && baseSpeed <= 3f * baseSpeed) { Animator animator = ((StatusEffect)this).m_character.m_animator; float num = (animator.speed += Player.m_localPlayer.GetTotalActiveMagicEffectValue("Infusion", 0.01f)); } if (((Humanoid)Player.m_localPlayer).GetCurrentWeapon() == weapon && (Object)(object)m_vfxInstance == (Object)null) { CreateVFX(); } else if (((Humanoid)Player.m_localPlayer).GetCurrentWeapon() != weapon && (Object)(object)m_vfxInstance != (Object)null) { DestroyVFX(); } } } private void CreateVFX() { VisEquipment visEquipment = ((Humanoid)Player.m_localPlayer).m_visEquipment; if (!WA.IsTwoHanded(weapon)) { m_vfxInstance = Object.Instantiate<GameObject>(InfusionVFX.WindInfusionVFX, visEquipment.m_rightHand); m_vfxInstance.SetActive(true); PlayAll(m_vfxInstance); return; } m_vfxInstance = Object.Instantiate<GameObject>(InfusionVFX.WindInfusionVFX, visEquipment.m_rightHand); m_vfxInstance2 = Object.Instantiate<GameObject>(InfusionVFX.WindInfusionVFX, visEquipment.m_leftHand); m_vfxInstance.SetActive(true); m_vfxInstance2.SetActive(true); PlayAll(m_vfxInstance); PlayAll(m_vfxInstance2); } private void PlayAll(GameObject vfx) { //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) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) Light componentInChildren = vfx.GetComponentInChildren<Light>(); if ((Object)(object)componentInChildren != (Object)null) { ((Component)componentInChildren).gameObject.SetActive(false); } ParticleSystem[] componentsInChildren = vfx.GetComponentsInChildren<ParticleSystem>(); foreach (ParticleSystem val in componentsInChildren) { if ((Object)(object)((Component)val).transform == (Object)(object)vfx.transform) { val.Stop(); continue; } MainModule main = val.main; ((MainModule)(ref main)).loop = true; ((MainModule)(ref main)).duration = 2f; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(0.7607843f, 1f, 0.57254905f, 1f)); val.Play(); } } private void DestroyVFX() { if ((Object)(object)m_vfxInstance != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance); m_vfxInstance = null; } if ((Object)(object)m_vfxInstance2 != (Object)null) { Object.Destroy((Object)(object)m_vfxInstance2); m_vfxInstance2 = null; } } } } namespace EpicLootLeslieAlphaTest.src.StatusEffects.VFX { public static class InfusionVFX { public static GameObject FireInfusionVFX; public static GameObject FrostInfusionVFX; public static GameObject LightningInfusionVFX; public static GameObject PoisonInfusionVFX; public static GameObject WindInfusionVFX; public static void Init() { FireInfusionVFX = BuildVFX(ZNetScene.instance.GetPrefab("Torch"), 0.1f); FrostInfusionVFX = BuildVFX(ZNetScene.instance.GetPrefab("vfx_Freezing"), 0.3f); LightningInfusionVFX = BuildVFX(ZNetScene.instance.GetPrefab("fx_Lightning"), 0.2f); PoisonInfusionVFX = BuildVFX(ZNetScene.instance.GetPrefab("vfx_Poison"), 0.2f); WindInfusionVFX = BuildVFX(ZNetScene.instance.GetPrefab("vfx_MeadSwimmer"), 0.08f); } private static GameObject BuildVFX(GameObject source, float scale) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0081: 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_00a1: 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) if ((Object)(object)source == (Object)null) { return null; } GameObject val = new GameObject("InfusionVFX_" + ((Object)source).name); val.SetActive(false); Object.DontDestroyOnLoad((Object)(object)val); if ((Object)(object)val.GetComponent<TimedDestruction>() != (Object)null) { Object.Destroy((Object)(object)val.GetComponent<TimedDestruction>()); } ParticleSystem[] componentsInChildren = source.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem val2 in componentsInChildren) { if (!((Object)(object)((Component)val2).transform == (Object)(object)source.transform)) { GameObject obj = Object.Instantiate<GameObject>(((Component)val2).gameObject, val.transform); obj.transform.localPosition = Vector3.zero; obj.transform.localRotation = Quaternion.identity; Transform transform = obj.transform; transform.localScale *= scale; } } return val; } } } namespace EpicLootLeslieAlphaTest.src.MagicEffectss { public class AncestralSlam { [HarmonyPatch(typeof(Attack), "OnAttackTrigger")] public class Attack_Trigger { public static void Prefix(Attack __instance) { if (__instance.m_character is Player) { _lastAttackCainLevel = __instance.m_currentAttackCainLevel; _lastAttackAnim = __instance.m_attackAnimation; _lastAttackRange = __instance.m_attackRange; _lastAttack = __instance; } } } [HarmonyPatch(typeof(Character), "Damage")] public class Character_Damage_SpawnClone_Patch { public static void Postfix(Character __instance, HitData hit) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_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_0085: 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_00a3: 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) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //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) if (((Humanoid)Player.m_localPlayer).GetCurrentWeapon() == null) { return; } ItemData currentWeapon = ((Humanoid)Player.m_localPlayer).GetCurrentWeapon(); if (currentWeapon != null && ItemDataExtensions.HasMagicEffect(currentWeapon, "AncestralSlam")) { Character attacker = hit.GetAttacker(); if (!((Object)(object)attacker == (Object)null) && !((Object)(object)attacker != (Object)(object)Player.m_localPlayer) && !ancestralClonesHASH.Contains(((Component)attacker).gameObject)) { Vector3 position = ((Component)__instance).transform.position; Vector3 val = position - ((Component)Player.m_localPlayer).transform.position; Vector3 normalized = ((Vector3)(ref val)).normalized; SpawnAncestralSlam(rotation: (normalized != Vector3.zero) ? Quaternion.LookRotation(normalized) : ((Component)Player.m_localPlayer).transform.rotation, position: position - normalized * 1.5f, weapon: currentWeapon); } } } } [HarmonyPatch(typeof(Character), "Damage")] public class Character_Clone_Damage_Patch { public static void Prefix(Character __instance, HitData hit) { //IL_0059: 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_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } ItemData currentWeapon = ((Humanoid)Player.m_localPlayer).GetCurrentWeapon(); if (currentWeapon == null || !ItemDataExtensions.HasMagicEffect(currentWeapon, "AncestralSlam")) { return; } Character attacker = hit.GetAttacker(); if (!((Object)(object)attacker == (Object)null) && ancestralClonesHASH.Contains(((Component)attacker).gameObject)) { float skillFactor = ((Character)Player.m_localPlayer).GetSkillFactor(currentWeapon.m_shared.m_skillType); float num = Random.Range(0.96f, 1.04f); DamageTypes damage = ((DamageTypes)(ref currentWeapon.m_shared.m_damages)).Clone(); if (_lastAttackCainLevel >= 2) { ((DamageTypes)(ref damage)).Modify((skillFactor * 0.75f + 0.25f) * 2f * num); } else { ((DamageTypes)(ref damage)).Modify((skillFactor * 0.75f + 0.25f) * num); } hit.m_damage = damage; } } } [HarmonyPatch(typeof(EnemyHud), "ShowHud")] internal class EnemyHud_ShowHud_Patch { private static bool Prefix(Character c) { return !ancestralClonesHASH.Contains(((Component)c).gameObject); } } private const float damageModifier = 1f; private static int _lastAttackCainLevel = 0; private static string _lastAttackAnim = ""; private static Attack _lastAttack = null; private static float _lastAttackRange = 2f; public static readonly HashSet<GameObject> ancestralClonesHASH = new HashSet<GameObject>(); internal static void SpawnAncestralSlam(Vector3 position, Quaternion rotation, ItemData weapon) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)HumanoidFactory.playerAncestor == (Object)null)) { GameObject val = Object.Instantiate<GameObject>(HumanoidFactory.playerAncestor, position, rotation); ancestralClonesHASH.Add(val); val.SetActive(true); bool flag = weapon.m_shared.m_secondaryAttack.m_attackAnimation == _lastAttackAnim; Humanoid component = val.GetComponent<Humanoid>(); component.m_rightItem = weapon.Clone(); val.GetComponent<Animator>(); ((Character)component).m_lookDir = rotation * Vector3.forward; ((Character)component).StartAttack((Character)null, flag); if (component.m_currentAttack != null) { Attack currentAttack = component.m_currentAttack; currentAttack.m_attackRange *= 1.2f; component.m_currentAttack.m_currentAttackCainLevel = _lastAttackCainLevel; } ((MonoBehaviour)component).StartCoroutine(DelayedDestruction(val.GetComponent<ZNetView>(), val, 2.5f)); } } private static IEnumerator DelayedDestruction(ZNetView zview, GameObject go, float attackTime) { yield return (object)new WaitForSeconds(attackTime + 0.5f); Character component = go.GetComponent<Character>(); if ((Object)(object)component != (Object)null) { EnemyHud instance = EnemyHud.instance; if (instance != null) { instance.RemoveCharacterHud(component); } Character.Instances.Remove((IMonoUpdater)(object)component); } ancestralClonesHASH.Remove(go); if ((Object)(object)zview != (Object)null && zview.IsOwner()) { ZNetScene.instance.Destroy(((Component)zview).gameObject); } } } public static class GlancingBlows { [HarmonyPatch(typeof(Humanoid), "BlockAttack")] public class Block_Attack_GlancingBlowsBlockAttackPrefix_Patch { public static void Prefix(HitData hit) { initialHitValue = hit.GetTotalBlockableDamage(); } } [HarmonyPatch(typeof(Humanoid), "BlockAttack")] public class Block_Attack_GlancingBlowsBlockAttackPostfix_Patch { public static void Postfix(HitData hit, Character attacker) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.HasActiveMagicEffect("GlancingBlows", out var _)) { float num = initialHitValue * 0.5f; float health = ((Character)Player.m_localPlayer).GetHealth(); float num2 = (float)Math.Round(num - ((Character)Player.m_localPlayer).GetBodyArmor(), 2); if (!((Character)Player.m_localPlayer).IsDead() && num2 > 0f) { ((Character)Player.m_localPlayer).SetHealth(health - num2); DamageText.instance.ShowText((TextType)0, ((Component)Player.m_localPlayer).transform.position, num2.ToString(), true); } } } } [HarmonyPatch(typeof(ItemData), "GetBlockPower", new Type[] { typeof(int), typeof(float) })] public class GlancingBlowsDamage_Patch { public static void Postfix(float skillFactor, ref float __result) { if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.HasActiveMagicEffect("GlancingBlows", out var _)) { __result *= 1.5f; } } } private static float effectValue = 1f; private static float initialHitValue = 0f; } public static class Infusion { public enum InfusionElement { Fire, Frost, Lightning, Poison, Wind, Blood } public class InfusionAbilityProxy : Proxy { public static IEnumerator RechargeAnimation(Player player, float duration) { ((Character)player).m_zanim.SetBool("recharge_lightningstaff", true); yield return (object)new WaitForSeconds(duration); ((Character)player).m_zanim.SetBool("recharge_lightningstaff", false); ((Character)player).m_zanim.SetTrigger("recharge_lightningstaff_done"); } public override void Activate() { if (IsOnCooldown() || (Object)(object)Player.m_localPlayer == (Object)null) { return; } SetCooldownEndTime(Proxy.GetTime() + Cooldown); List<StatusEffect> list = new List<StatusEffect>(((Character)Player.m_localPlayer).GetSEMan().GetStatusEffects()); isInfused = false; Dictionary<InfusionElement, float> dictionary = new Dictionary<InfusionElement, float>(); List<StatusEffect> list2 = new List<StatusEffect>(); for (int num = list.Count - 1; num >= 0; num--) { string text = ((Object)list[num]).name.ToLower(); foreach (var (value, key) in elementMap) { if (text.Contains(value)) { float efficacy = GetEfficacy(list[num]); list2.Add(list[num]); if (!dictionary.ContainsKey(key) || efficacy > dictionary[key]) { dictionary[key] = efficacy; } break; } } } ((MonoBehaviour)Player.m_localPlayer).StartCoroutine(DeferRemoveAndApply(list2, dictionary)); static IEnumerator DeferRemoveAndApply(List<StatusEffect> toRemove, Dictionary<InfusionElement, float> bestEfficacy) { foreach (StatusEffect item in toRemove) { ((Character)Player.m_localPlayer).GetSEMan().RemoveStatusEffect(item, false); } yield return null; foreach (KeyValuePair<InfusionElement, float> item2 in bestEfficacy) { Efficacy = item2.Value; ((Character)Player.m_localPlayer).GetSEMan().AddStatusEffect(StringExtensionMethods.GetStableHashCode($"SE_{item2.Key}Infused"), false, 0, 0f); isInfused = true; } if (isInfused) { ((MonoBehaviour)Player.m_localPlayer).StartCoroutine(RechargeAnimation(Player.m_localPlayer, 1f)); } if (!isInfused) { ((Character)Player.m_localPlayer).m_zanim.SetTrigger("emote_shrug"); } } } } private static bool isInfused = false; private static readonly List<(string keyword, InfusionElement element)> elementMap = new List<(string, InfusionElement)> { ("fire", InfusionElement.Fire), ("burn", InfusionElement.Fire), ("frost", InfusionElement.Frost), ("freez", InfusionElement.Frost), ("lightning", InfusionElement.Lightning), ("shock", InfusionElement.Lightning), ("poison", InfusionElement.Poison), ("wind", InfusionElement.Wind), ("aero", InfusionElement.Wind), ("moder", InfusionElement.Wind), ("leaf", InfusionElement.Wind), ("petal", InfusionElement.Wind), ("blood", InfusionElement.Blood) }; private static readonly Dictionary<string, Func<StatusEffect, float>> efficacyType = new Dictionary<string, Func<StatusEffect, float>> { { "Burning", (StatusEffect se) => ((SE_Burning)se).m_fireDamageLeft }, { "Frost", (StatusEffect se) => ((StatusEffect)(SE_Frost)se).m_ttl * 10f }, { "Lightning", (StatusEffect se) => (!(se.m_ttl > 0f) || ((Character)Player.m_localPlayer).m_lastHit == null) ? 0f : ((Character)Player.m_localPlayer).m_lastHit.m_damage.m_lightning }, { "Poison", (StatusEffect se) => ((SE_Poison)se).m_damageLeft } }; public static float Efficacy; private static float GetEfficacy(StatusEffect se) { Logger.LogWarning((object)$"GetEfficacy: {((Object)se).name} found {efficacyType.ContainsKey(((Object)se).name)}"); if (efficacyType.TryGetValue(((Object)se).name, out Func<StatusEffect, float> value)) { return value(se); } return 0f; } } public static class Onslaught { [HarmonyPatch(typeof(Character), "Damage")] public class Attack_Trigger_Patch { public static void Prefix(Character __instance, HitData hit) { Character attacker = hit.GetAttacker(); Humanoid val = (Humanoid)(object)((attacker is Humanoid) ? attacker : null); if (!((Object)(object)val == (Object)null) && !((Object)(object)Player.m_localPlayer != (Object)(object)val) && ItemDataExtensions.HasMagicEffect(((Humanoid)Player.m_localPlayer).GetCurrentWeapon(), "Onslaught") && ((val.m_currentAttack?.m_currentAttackCainLevel ?? (-1)) >= 2 || __instance.IsStaggering())) { SEMan sEMan = ((Character)Player.m_localPlayer).GetSEMan(); SE_Onslaught sE_Onslaught = sEMan.GetStatusEffect(StringExtensionMethods.GetStableHashCode("SE_Onslaught")) as SE_Onslaught; if ((Object)(object)sE_Onslaught != (Object)null) { sE_Onslaught.AddStack(); } else { (sEMan.AddStatusEffect(StringExtensionMethods.GetStableHashCode("SE_Onslaught"), false, 0, 0f) as SE_Onslaught).AddStack(); } } } } [HarmonyPatch(typeof(Attack), "Start")] public class Attack_Modify_Chain_Patch { public static void Postfix(Attack __instance, Humanoid character, ref bool __result) { if (!((Object)(object)character != (Object)(object)Player.m_localPlayer)) { SE_Onslaught sE_Onslaught = ((Character)character).GetSEMan().GetStatusEffect(StringExtensionMethods.GetStableHashCode("SE_Onslaught")) as SE_Onslaught; if (!((Object)(object)sE_Onslaught == (Object)null) && sE_Onslaught.m_stacks > 0 && ItemDataExtensions.HasMagicEffect(character.GetCurrentWeapon(), "Onslaught")) { __instance.m_currentAttackCainLevel = 2; __instance.m_zanim.SetTrigger(__instance.m_attackAnimation + "2"); sE_Onslaught.ConsumeStack(); } } } } } public static class PerfectStrike { [HarmonyPatch(typeof(Attack), "Start")] public static class Attack_PerfectStrikeAnimation_Patch { public static void Postfix(Attack __instance, Humanoid character) { if (!((Object)(object)character != (Object)(object)Player.m_localPlayer) && Player.m_localPlayer.HasActiveMagicEffect("PerfectStrike", out var _)) { if (isPerfectStrike) { int lastPerfectChain = ((_lastPerfectChain == 2) ? 1 : 2); __instance.m_currentAttackCainLevel = 2; __instance.m_zanim.SetTrigger(__instance.m_attackAnimation + lastPerfectChain); _lastPerfectChain = lastPerfectChain; _clicked = false; isPerfectStrike = false; _perfectDamagePending = true; } _currentAttack = __instance; _currentAnim = __instance.m_attackAnimation; _currentChain = __instance.m_currentAttackCainLevel; _currentAnimSpeed = __instance.m_speedFactor; _attackStartTime = Time.time; } } } [HarmonyPatch(typeof(PlayerController), "FixedUpdate")] public static class Input_AntiSpam_Patch { public static void Postfix(PlayerController __instance) { //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance.m_character != (Object)(object)Player.m_localPlayer || !Player.m_localPlayer.HasActiveMagicEffect("PerfectStrike", out var _)) { return; } if (!((Character)Player.m_localPlayer).InAttack()) { _clicked = false; _windowSFXplayed = false; if ((Object)(object)_windowVFXInstance != (Object)null) { Object.Destroy((Object)(object)_windowVFXInstance); _windowVFXInstance = null; } return; } float value = 0f; float num = 0f; float num2 = 0f; bool flag = _currentAnim != null && _attackDeltas.TryGetValue((_currentAnim, _currentChain, "default"), out value); if (flag) { num = value * 0.5f; num2 = value * 0.75f; } float num3 = Time.time - _attackStartTime; bool flag2 = _currentChain == 0 && _currentAnim != null && !_currentAnim.Contains("secondary"); if (flag && !flag2) { bool flag3 = num3 >= num && num3 <= num2; if (flag3 && (Object)(object)_windowVFXInstance == (Object)null) { if ((Object)(object)_cleanVFXPrefab == (Object)null) { GameObject prefab = ZNetScene.instance.GetPrefab("vfx_kiln_addore"); if ((Object)(object)prefab != (Object)null) { bool activeSelf = prefab.activeSelf; prefab.SetActive(false); _cleanVFXPrefab = Object.Instantiate<GameObject>(prefab); prefab.SetActive(activeSelf); Object.DestroyImmediate((Object)(object)_cleanVFXPrefab.GetComponent<ZNetView>()); } } if ((Object)(object)_cleanVFXPrefab != (Object)null) { GameObject rightItemInstance = ((Humanoid)Player.m_localPlayer).m_visEquipment.m_rightItemInstance; Transform val = (((Object)(object)rightItemInstance != (Object)null) ? rightItemInstance.transform : ((Humanoid)Player.m_localPlayer).m_visEquipment.m_rightHand); _windowVFXInstance = Object.Instantiate<GameObject>(_cleanVFXPrefab, val); _windowVFXInstance.SetActive(true); _windowVFXInstance.transform.localPosition = Vector3.zero; } } else if (!flag3 && (Object)(object)_windowVFXInstance != (Object)null) { Object.Destroy((Object)(object)_windowVFXInstance); _windowVFXInstance = null; } } if (ZInput.GetButtonDown("Attack")) { _nowClicked = Time.time; if (!_clicked) { _clicked = true; if (flag) { isPerfectStrike = num3 >= num && num3 <= num2; } } else { _ = isPerfectStrike; } } if (isPerfectStrike && !_windowSFXplayed && !flag2) { GameObject prefab2 = ZNetScene.instance.GetPrefab("sfx_perfectblock"); if ((Object)(object)prefab2 != (Object)null) { Object.Instantiate<GameObject>(prefab2, ((Component)Player.m_localPlayer).transform).transform.localPosition = Vector3.zero; _windowSFXplayed = true; } } if (Time.time - _nowClicked >= _clickSpam) { _clicked = false; } } } [HarmonyPatch(typeof(Character), "Damage")] public static class PerfectStrike_Damage_Patch { public static void Postfix(Character __instance, HitData hit) { if (_perfectDamagePending) { ((DamageTypes)(ref hit.m_damage)).Modify(Player.m_localPlayer.GetTotalActiveMagicEffectValue("PerfectStrike", 0.01f)); _perfectDamagePending = false; _windowSFXplayed = false; } } } private static float _attackStartTime; private static float _clickSpam = 0.25f; private static float _nowClicked; private static bool _clicked = false; private static bool _windowSFXplayed = false; private static int _lastPerfectChain = 0; private static bool isPerfectStrike = false; private static bool _perfectDamagePending = false; private static Attack _currentAttack; private static string _currentAnim; private static int _currentChain; private static float _currentAnimSpeed; private static GameObject _cleanVFXPrefab; private static GameObject _windowVFXInstance; private static readonly Dictionary<(string, int, string), float> _attackDeltas = new Dictionary<(string, int, string), float> { { ("battleaxe_attack", 0, "default"), 0.878f }, { ("battleaxe_attack", 0, "fast"), 0.599f }, { ("battleaxe_attack", 1, "default"), 1.04f }, { ("battleaxe_attack", 1, "fast"), 0.761f }, { ("battleaxe_attack", 2, "default"), 1.304f }, { ("battleaxe_attack", 2, "fast"), 1.078f }, { ("battleaxe_secondary", 0, "default"), 0.843f }, { ("greatsword", 0, "default"), 1.642f }, { ("greatsword", 0, "fast"), 1.258f }, { ("greatsword", 1, "default"), 0.839f }, { ("greatsword", 1, "fast"), 0.579f }, { ("greatsword", 2, "default"), 0.958f }, { ("greatsword", 2, "fast"), 0.682f }, { ("greatsword_secondary", 0, "default"), 2.125f }, { ("greatsword_secondary", 0, "fast"), 1.703f } }; } public static class Retaliation { [HarmonyPatch(typeof(Humanoid), "BlockAttack")] public class Block_Attack_Retaliate_Patch { public static void Postfix(Humanoid __instance, bool __result) { if (Player.m_localPlayer.HasActiveMagicEffect("Retaliation", out var _) && __result && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { SEMan sEMan = ((Character)__instance).GetSEMan(); SE_Retaliation sE_Retaliation = sEMan.GetStatusEffect(StringExtensionMethods.GetStableHashCode("SE_Retaliation")) as SE_Retaliation; if ((Object)(object)sE_Retaliation != (Object)null) { sE_Retaliation.AddStack(); } else { (sEMan.AddStatusEffect(StringExtensionMethods.GetStableHashCode("SE_Retaliation"), false, 0, 0f) as SE_Retaliation).AddStack(); } } } } [HarmonyPatch(typeof(Attack), "Start")] public class Humanoid_Attack_Patch { private static void Prefix(Attack __instance, Humanoid character) { if (!((Object)(object)character != (Object)(object)Player.m_localPlayer) && Player.m_localPlayer.HasActiveMagicEffect("Retaliation", out var _)) { AttackType = __instance.m_attackAnimation; } } } public static string AttackType; } public static class Whirlwind { [HarmonyPatch(typeof(CharacterAnimEvent), "CustomFixedUpdate")] [HarmonyPriority(0)] public static class Whirlwind_CharAnim_CFU_Patch { public static void Postfix(CharacterAnimEvent __instance) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance.m_character == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)__instance.m_character != (Object)(object)Player.m_localPlayer) { return; } InWhirlwind = ItemDataExtensions.HasMagicEffect(((Humanoid)Player.m_localPlayer).GetCurrentWeapon(), "Whirlwind") && (Object)(object)__instance.m_character != (Object)null && __instance.m_character.InAttack() && __instance.m_character.m_secondaryAttackHold && ((Humanoid)__instance.m_character).m_currentAttack.m_attackAnimation == "atgeir_secondary"; if (InWhirlwind) { if (__instance.m_animator.speed > 1f && __instance.m_animator.speed != 10f) { overFlowAnimSpeed = Mathf.Clamp(__instance.m_animator.speed - 2f, 0f, 0.4f); } __instance.m_animator.speed = 10f; WhirlwindDamage = true; __instance.m_character.m_attack = false; __instance.m_character.m_attackHold = false; } else if (!__instance.m_character.InAttack()) { WhirlwindDamage = false; overFlowAnimSpeed = 0f; } } } [HarmonyPatch(typeof(Character), "Damage")] public static class Whirlwind_Damage_Patch { public static void Prefix(Character __instance, HitData hit) { if (!((Object)(object)hit.GetAttacker() != (Object)(object)Player.m_localPlayer) && InWhirlwind) { ((DamageTypes)(ref hit.m_damage)).Modify(0.4f * (1f + overFlowAnimSpeed)); hit.m_staggerMultiplier = 1f; } } } [HarmonyPatch(typeof(Attack), "GetAttackStamina")] public static class Whirlwind_Stamina_Patch { public static void Postfix(ref float __result) { if (InWhirlwind) { __result *= 0.3f; } } } private static bool InWhirlwind; private static bool WhirlwindDamage; private static float overFlowAnimSpeed; } } namespace PraetorisClient { internal static class BotApiClient { public static IEnumerator PostLinkRoutine(LinkRequest link, Action<long, string, bool, string> sendResult) { string linkApiUrl = PraetorisClientPlugin.GetLinkApiUrl(); string botApiKey = PraetorisClientPlugin.GetBotApiKey(); if (string.IsNullOrWhiteSpace(linkApiUrl)) { sendResult(link.Sender, link.RequestId, arg3: false, "Link API URL is not configured on the server."); yield break; } if (string.IsNullOrWhiteSpace(botApiKey)) { sendResult(link.Sender, link.RequestId, arg3: false, "Bot API key is not configured on the server."); yield break; } string s = JsonLinkRequest(link); byte[] bytes = Encoding.UTF8.GetBytes(s); UnityWebRequest request = new UnityWebRequest(linkApiUrl, "POST") { uploadHandler = (UploadHandler)new UploadHandlerRaw(bytes), downloadHandler = (DownloadHandler)new DownloadHandlerBuffer() }; try { request.SetRequestHeader("Content-Type", "application/json"); request.SetRequestHeader("X-API-Key", botApiKey); request.SetRequestHeader("User-Agent", "PraetorisClient/0.1"); yield return request.SendWebRequest(); string text = ((request.downloadHandler != null) ? request.downloadHandler.text : ""); if ((int)request.result != 1 || request.responseCode < 200 || request.responseCode >= 300) { string text2 = ((!string.IsNullOrWhiteSpace(text)) ? text : (string.IsNullOrWhiteSpace(request.error) ? ("HTTP " + request.responseCode) : (request.error + " (HTTP " + request.responseCode + ")"))); PraetorisClientPlugin.Log.LogWarning((object)("Discord link API failed for " + link.PlayerId + ": " + text2)); sendResult(link.Sender, link.RequestId, arg3: false, text2); } else { string arg = (string.IsNullOrWhiteSpace(text) ? "Discord link complete." : text); PraetorisClientPlugin.Log.LogInfo((object)("Discord link API accepted " + link.PlayerId + ".")); sendResult(link.Sender, link.RequestId, arg3: true, arg); } } finally { ((IDisposable)request)?.Dispose(); } } private static string JsonLinkRequest(LinkRequest link) { return "{\"requestId\":\"" + EscapeJson(link.RequestId) + "\",\"code\":\"" + EscapeJson(link.Code) + "\",\"playerId\":\"" + EscapeJson(link.PlayerId) + "\",\"playerName\":\"" + EscapeJson(link.PlayerName) + "\",\"endpoint\":\"" + EscapeJson(link.Endpoint) + "\",\"platformDisplayName\":\"" + EscapeJson(link.PlatformDisplayName) + "\",\"receivedAtUtc\":\"" + EscapeJson(link.ReceivedAtUtc.ToString("O", CultureInfo.InvariantCulture)) + "\"}"; } private static string EscapeJson(string value) { return (value ?? "").Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\r", "\\r") .Replace("\n", "\\n"); } } internal static class LinkCommandHandler { private static readonly Regex CodePattern = new Regex("^[A-Za-z0-9_-]{4,64}$", RegexOptions.Compiled); public static bool TryHandle(Chat chat) { string text = (((Object)(object)((Terminal)chat).m_input != (Object)null) ? ((TMP_InputField)((Terminal)chat).m_input).text : ""); if (string.IsNullOrWhiteSpace(text)) { return false; } string text2 = PraetorisClientPlugin.LinkCommand.Value.Trim(); if (string.IsNullOrWhiteSpace(text2)) { text2 = "!link"; } string text3 = text.Trim(); if (!text3.Equals(text2, StringComparison.OrdinalIgnoreCase) && !text3.StartsWith(text2 + " ", StringComparison.OrdinalIgnoreCase)) { return false; } string text4 = ((text3.Length > text2.Length) ? text3.Substring(text2.Length).Trim() : ""); if (!CodePattern.IsMatch(text4)) { ((Terminal)chat).AddString("Usage: " + text2 + " CODE"); ClearInput(chat); return true; } if (!LinkRpc.TrySendRequest(text4, out string message)) { ((Terminal)chat).AddString(message); ClearInput(chat); return true; } ((Terminal)chat).AddString("Sending Discord link code to the server."); ClearInput(chat); return true; } private static void ClearInput(Chat chat) { if (!((Object)(object)((Terminal)chat).m_input == (Object)null)) { ((TMP_InputField)((Terminal)chat).m_input).text = ""; ((Component)((Terminal)chat).m_input).gameObject.SetActive(false); } } } internal static class LinkRpc { public static bool TrySendRequest(string code, out string message) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown message = ""; if ((Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null || ZNet.instance.IsServer() || (int)ZNet.GetConnectionStatus() != 2) { message = "You must be connected to a server before linking Discord."; return false; } string text = Guid.NewGuid().ToString("N"); ZPackage val = new ZPackage(); val.Write(text); val.Write(code); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "DiscordTools_LinkRequest", new object[1] { val }); return true; } public static void OnRequest(long sender, ZPackage pkg) { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } string requestId = pkg.ReadString(); string code = pkg.ReadString(); ZNetPeer val = PlayerResolver.FindPeerBySender(sender); if (val == null) { SendResult(sender, requestId, success: false, "The server could not identify your Valheim connection."); return; } PraetorisClientPlugin instance = PraetorisClientPlugin.Instance; if ((Object)(object)instance == (Object)null) { SendResult(sender, requestId, success: false, "PraetorisClient is not ready on the server."); return; } LinkRequest link = new LinkRequest { Sender = sender, RequestId = requestId, Code = code, PlayerId = PlayerResolver.StablePlayerId(val), PlayerName = (val.m_playerName ?? ""), Endpoint = PlayerResolver.SafeEndPoint(val), PlatformDisplayName = PlayerResolver.PlatformDisplayName(val), ReceivedAtUtc = DateTime.UtcNow }; PraetorisClientPlugin.Log.LogInfo((object)("Received Discord link code from " + PlayerResolver.DescribePeer(val) + ".")); ((MonoBehaviour)instance).StartCoroutine(BotApiClient.PostLinkRoutine(link, SendResult)); } public static void OnResult(long sender, ZPackage pkg) { if (!((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer()) { string text = pkg.ReadString(); bool flag = pkg.ReadBool(); string text2 = pkg.ReadString(); PraetorisClientPlugin.Log.LogInfo((object)("Discord link result " + text + ": " + text2)); Chat instance = Chat.instance; if (instance != null) { ((Terminal)instance).AddString(flag ? text2 : ("Discord link failed: " + text2)); } } } private static void SendResult(long target, string requestId, bool success, string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(requestId); val.Write(success); val.Write(message); ZRoutedRpc.instance.InvokeRoutedRPC(target, "DiscordTools_LinkResult", new object[1] { val }); } } internal sealed class LinkRequest { public long Sender; public string RequestId = ""; public string Code = ""; public string PlayerId = ""; public string PlayerName = ""; public string Endpoint = ""; public string PlatformDisplayName = ""; public DateTime ReceivedAtUtc; } internal static class PlayerResolver { public static List<ZNetPeer> FindPeers(string query) { List<ZNetPeer> list = new List<ZNetPeer>(); if ((Object)(object)ZNet.instance == (Object)null) { return list; } string text = Normalize(query); foreach (ZNetPeer connectedPeer in ZNet.instance.GetConnectedPeers()) { if (connectedPeer.IsReady()) { string value = SafeHostName(connectedPeer); string value2 = StablePlayerId(connectedPeer); if (Normalize(connectedPeer.m_playerName) == text || Normalize(value) == text || Normalize(value2) == text || (DigitsOnly(value) == DigitsOnly(query) && DigitsOnly(query).Length > 0)) { list.Add(connectedPeer); } } } if (list.Count > 0) { return list; } foreach (ZNetPeer connectedPeer2 in ZNet.instance.GetConnectedPeers()) { if (connectedPeer2.IsReady() && Normalize(connectedPeer2.m_playerName).Contains(text)) { list.Add(connectedPeer2); } } return list; } public static ZNetPeer? FindPeerBySender(long sender) { if ((Object)(object)ZNet.instance == (Object)null) { return null; } return ((IEnumerable<ZNetPeer>)ZNet.instance.GetConnectedPeers()).FirstOrDefault((Func<ZNetPeer, bool>)((ZNetPeer peer) => peer.m_uid == sender)); } public static bool TryGetPeerPlayerId(ZNetPeer peer, out long playerId) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) playerId = 0L; if (peer == null || ZDOMan.instance == null || ((ZDOID)(ref peer.m_characterID)).IsNone()) { return false; } ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID); if (zDO == null) { return false; } playerId = zDO.GetLong(ZDOVars.s_playerID, 0L); return playerId != 0; } public static bool TryGetSenderPlayerId(long sender, out long playerId, out ZNetPeer? peer) { playerId = 0L; peer = FindPeerBySender(sender); if (peer != null) { return TryGetPeerPlayerId(peer, out playerId); } if (sender == ZNet.GetUID() && (Object)(object)Game.instance != (Object)null) { playerId = Game.instance.GetPlayerProfile().GetPlayerID(); return playerId != 0; } return false; } public static string DescribePeer(ZNetPeer peer) { return peer.m_playerName + " (" + StablePlayerId(peer) + ")"; } public static string StablePlayerId(ZNetPeer peer) { string text = SafeHostName(peer); if (!string.IsNullOrWhiteSpace(text)) { return text; } return peer.m_uid.ToString(CultureInfo.InvariantCulture); } public static string SafeHostName(ZNetPeer peer) { try { ISocket socket = peer.m_socket; return ((socket != null) ? socket.GetHostName() : null) ?? ""; } catch { return ""; } } public static string SafeEndPoint(ZNetPeer peer) { try { ISocket socket = peer.m_socket; return ((socket != null) ? socket.GetEndPointString() : null) ?? ""; } catch { return ""; } } public static string PlatformDisplayName(ZNetPeer peer) { try { string value; return (peer.m_serverSyncedPlayerData != null && peer.m_serverSyncedPlayerData.TryGetValue("platformDisplayName", out value)) ? value : ""; } catch { return ""; } } private static string Normalize(string value) { return (value ?? "").Trim().ToLowerInvariant(); } private static string DigitsOnly(string value) { return new string((value ?? "").Where(char.IsDigit).ToArray()); } } [BepInPlugin("warpalicious.PraetorisClient", "PraetorisClient", "0.1.55")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class PraetorisClientPlugin : BaseUnityPlugin { private const string ModName = "PraetorisClient"; private const string ModVersion = "0.1.55"; private const string Author = "warpalicious"; private const string ModGUID = "warpalicious.PraetorisClient"; private const string LinkApiUrlEnv = "PRAETORISCLIENT_LINK_API_URL"; private const string BotApiKeyEnv = "PRAETORISCLIENT_BOT_API_KEY"; private readonly Harmony _harmony = new Harmony("warpalicious.PraetorisClient"); private DateTime _lastReloadTime; private FileSystemWatcher? _configWatcher; private const long ReloadDelayTicks = 10000000L; private static bool Loaded = false; public static readonly ManualLogSource Log = Logger.CreateLogSource("PraetorisClient"); internal static ConfigEntry<string> LinkApiUrl = null; internal static ConfigEntry<string> BotApiKey = null; internal static ConfigEntry<string> LinkCommand = null; internal static ConfigEntry<int> MetricMaxBatchRows = null; internal static ConfigEntry<float> MetricBatchIntervalSeconds = null; internal static ConfigEntry<bool> NetworkMetricHttpUploadPreferred = null; internal static ConfigEntry<bool> SuppressEnvironmentDamageText = null; internal static ConfigEntry<bool> FrameMetricsEnabled = null; internal static ConfigEntry<float> FrameMetricsSummaryIntervalSeconds = null; internal static ConfigEntry<float> FrameMetricsLongFrameThresholdMs = null; internal static ConfigEntry<bool> FrameMetricsLogLongFrames = null; internal static ConfigEntry<bool> SocketMetricsEnabled = null; internal static ConfigEntry<float> SocketMetricsSampleIntervalSeconds = null; internal static ConfigEntry<int> SocketMetricsSendQueueBudgetBytes = null; internal static ConfigEntry<bool> RpcProbeEnabled = null; internal static ConfigEntry<float> RpcProbeIntervalSeconds = null; internal static ConfigEntry<int> RpcProbePayloadBytes = null; internal static ConfigEntry<float> RpcProbeTimeoutSeconds = null; internal static ConfigEntry<bool> MeasurementDisableNetworkMetrics = null; internal static ConfigEntry<bool> MeasurementDisableNetworkMetricHttpUpload = null; internal static ConfigEntry<bool> DisableBoatWaterImpactDamage = null; internal static ConfigEntry<float> CreatureOwnerWardRadius = null; internal static ConfigEntry<float> CreatureOwnerWardUpdateIntervalSeconds = null; internal static ConfigEntry<bool> DebugCreatureOwnerWard = null; internal static ConfigEntry<bool> DebugServerChest = null; internal static ConfigEntry<bool> BlockPeerServerSyncConfigSync = null; internal static string TraceModGuid => "warpalicious.PraetorisClient"; internal static string TraceModName => "PraetorisClient"; internal static string TraceModVersion => "0.1.55"; public static PraetorisClientPlugin? Instance { get; private set; } internal static string GetLinkApiUrl() { string environmentVariable = Environment.GetEnvironmentVariable("PRAETORISCLIENT_LINK_API_URL"); if (!string.IsNullOrWhiteSpace(environmentVariable)) { return environmentVariable.Trim(); } return LinkApiUrl.Value; } internal static string GetBotApiKey() { string environmentVariable = Environment.GetEnvironmentVariable("PRAETORISCLIENT_BOT_API_KEY"); if (!string.IsNullOrWhiteSpace(environmentVariable)) { return environmentVariable.Trim(); } return BotApiKey.Value; } public void Awake() { PrefabManager.OnPrefabsRegistered += delegate { if (!Loaded) { HumanoidFactory.Create(); Loaded = true; } }; PrefabManager.OnPrefabsRegistered += delegate { InfusionVFX.Init(); }; MagicEffects.Init(); SERegistry.RegisterStatusEffects(); EpicLoot.RegisterAll(); Instance = this; BindConfig(); SynchronizationManager.OnConfigurationSynchronized += OnConfigurationSynchronized; CreatureOwnerWardPiece.Initialize(); CreatureOwnerWardCommand.Register(); ServerChestPiece.Initialize(); ServerChestCommand.Register(); if (Chainloader.PluginInfos.ContainsKey("org.tristan.rcon")) { ServerChestRconCommand.Register(); } SiegePortalTestCommand.Register(); FrameTimeMonitor.Initialize(); RpcTraceTelemetry.Initialize(); _harmony.PatchAll(Assembly.GetExecutingAssembly()); SocketMetricPatches.ApplyManualPatches(_harmony); SetupWatcher(); } private void Update() { if ((Object)(object)Game.instance == (Object)null) { RpcTraceTelemetry.BackgroundUpdate(); } } private void OnDestroy() { SynchronizationManager.OnConfigurationSynchronized -= OnConfigurationSynchronized; CreatureOwnerWardPiece.Shutdown(); ServerChestPiece.Shutdown(); try { _configWatcher?.Dispose(); _configWatcher = null; } catch (Exception ex) { Log.LogWarning((object)("Failed to dispose configuration watcher: " + ex.Message)); } try { RpcTraceTelemetry.Shutdown(); FrameTimeMonitor.Shutdown(); } catch (Exception ex2) { Log.LogWarning((object)("Failed to shut down telemetry: " + ex2.Message)); } try { ((BaseUnityPlugin)this).Config.Save(); } catch (Exception ex3) { Log.LogWarning((object)("Failed to save configuration during shutdown: " + ex3.Message)); } try { _harmony.UnpatchSelf(); } catch (Exception ex4) { Log.LogWarning((object)("Failed to unpatch PraetorisClient during shutdown: " + ex4.Message)); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void BindConfig() { LinkApiUrl = ((BaseUnityPlugin)this).Config.Bind<string>("BotApi", "LinkApiUrl", "", "Compatible bot Valheim link endpoint. Prefer the PRAETORISCLIENT_LINK_API_URL environment variable on dedicated servers."); BotApiKey = ((BaseUnityPlugin)this).Config.Bind<string>("BotApi", "ApiKey", "", "API key sent to the bot in the X-API-Key header. Prefer the PRAETORISCLIEN