Decompiled source of MaxAxe v0.4.6
MaxAxe.dll
Decompiled a month 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.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using TMPro; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("MaxAxe")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("MaxAxe")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("9f8a1b6e-6d0e-4dab-bbd8-9ed433836544")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] internal sealed class ConfigurationManagerAttributes { public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput); public bool? ShowRangeAsPercent; public Action<ConfigEntryBase> CustomDrawer; public CustomHotkeyDrawerFunc CustomHotkeyDrawer; public bool? Browsable; public string Category; public object DefaultValue; public bool? HideDefaultButton; public bool? HideSettingName; public string Description; public string DispName; public int? Order; public bool? ReadOnly; public bool? IsAdvanced; public Func<object, string> ObjToStr; public Func<string, object> StrToObj; } namespace neobotics.ValheimMods; public class ConfigMock { public bool Value { get; set; } } internal class CustomDataWrapper { private Dictionary<string, string> playerData; private CustomDataWrapper instance; private Dictionary<string, string> Data { get; set; } public CustomDataWrapper(Dictionary<string, string> sourceData, string keyPrefix) { CustomDataWrapper customDataWrapper = this; playerData = sourceData; Data = new Dictionary<string, string>(); sourceData.Keys.ToList().ForEach(delegate(string key) { if (key.StartsWith(keyPrefix)) { customDataWrapper.Data.Add(key, sourceData[key]); } }); } public void Add(string key, string value) { Data.Add(key, value); playerData.Add(key, value); } public bool Remove(string key) { return Data.Remove(key) & playerData.Remove(key); } public void Set(string key, string value) { if (Data.ContainsKey(key)) { Data[key] = value; } else { Data.Add(key, value); } if (playerData.ContainsKey(key)) { playerData[key] = value; } else { playerData.Add(key, value); } } public string Get(string key) { if (Data.ContainsKey(key)) { return Data[key]; } return null; } public bool ContainsKey(string key) { return Data.ContainsKey(key); } public void PreSaveSync() { foreach (KeyValuePair<string, string> datum in Data) { if (!playerData.ContainsKey(datum.Key)) { playerData.Add(datum.Key, datum.Value); } } } } internal class CustomSkill { [HarmonyPatch(typeof(Skills), "Load")] private static class Skills_Load_Patch { private static void Prefix(Skills __instance) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown if (__instance?.m_skills != null && cSkillDef != null && !__instance.m_skills.Contains(cSkillDef)) { Logging.GetLogger().Debug("Adding custom skill definition"); Sprite prefabIcon = Utils.GetPrefabIcon(cIconPrefab); if ((Object)(object)prefabIcon != (Object)null) { cSkillDef.m_icon = prefabIcon; } cSkill = new Skill(cSkillDef); __instance.m_skills.Add(cSkillDef); } } private static void Postfix(Skills __instance, Dictionary<SkillType, Skill> ___m_skillData) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) if (__instance?.m_skills == null || ___m_skillData == null || cSkillDef == null) { return; } Logging.GetLogger().Debug("Skills Load Postfix"); if (!___m_skillData.ContainsKey(cSkillType)) { Logging.GetLogger().Debug("No custom skill in the player profile"); if (Cfg.useSkill.Value) { Logging.GetLogger().Debug("Adding custom skill to player profile"); cSkill.m_accumulator = 0f; cSkill.m_level = 0f; ___m_skillData.Add(cSkillType, cSkill); } } else { cSkill = ___m_skillData[cSkillType]; Logging.GetLogger().Debug("Custom skill is already in the player profile"); if (!Cfg.useSkill.Value) { Logging.GetLogger().Debug("...but it's not enabled"); ___m_skillData.Remove(cSkillType); } } } } [HarmonyPatch(typeof(Skills), "Save")] private static class Skills_Save_Patch { private static void Prefix(Skills __instance, ZPackage pkg, Dictionary<SkillType, Skill> ___m_skillData) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null) && ___m_skillData != null && ___m_skillData.Count != 0) { Logging.GetLogger().Debug("Skills Save Prefix"); if (!___m_skillData.ContainsKey(cSkillType)) { Logging.GetLogger().Debug("Saving custom skill"); ___m_skillData.Add(cSkillType, cSkill); } string value = $"{cSkill.m_level}:{cSkill.m_accumulator}"; if (__instance.m_player.m_customData.ContainsKey(saveName)) { __instance.m_player.m_customData[saveName] = value; } else { __instance.m_player.m_customData.Add(saveName, value); } } } private static void Postfix(Skills __instance, ZPackage pkg, Dictionary<SkillType, Skill> ___m_skillData) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null) && ___m_skillData != null && ___m_skillData.Count != 0) { Logging.GetLogger().Debug("Skills Save Postfix"); if (!Cfg.useSkill.Value) { Logging.GetLogger().Debug("Removing disabled custom skill from the player profile"); ___m_skillData.Remove(cSkillType); } } } } [HarmonyPatch(typeof(Skills), "RaiseSkill")] private static class Skills_RaiseSkill_Patch { [HarmonyPrefix] private static void Skills_RaiseSkill_Prefix(Skills __instance, ref SkillType skillType, float factor) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between I4 and Unknown if ((int)skillType == (int)cSkillType && !Cfg.useSkill.Value) { skillType = (SkillType)0; } } } [HarmonyPatch(typeof(Skills), "IsSkillValid")] private static class Skills_IsSkillValid_Patch { private static void Postfix(ref bool __result, SkillType type) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (!__result && type == cSkillType) { Logging.GetLogger().Debug("Skill type matches custom skill"); __result = true; } } } [HarmonyPatch(typeof(Skills), "CheatRaiseSkill")] private static class Skills_CheatRaiseSkill_Patch { private static bool Prefix(Skills __instance, string name, float value, Dictionary<SkillType, Skill> ___m_skillData) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected I4, but got Unknown Logging.GetLogger().Debug("Skills CheatRaiseSkill Prefix"); if (Cfg.useSkill.Value && name.ToLower().Equals(cSkillName.ToLower()) && ___m_skillData.TryGetValue(cSkillType, out var value2)) { Logging.GetLogger().Debug($"Skill {value2.m_info} found"); Skill obj = value2; obj.m_level += value; value2.m_level = Mathf.Clamp(value2.m_level, 0f, 100f); if (__instance.m_useSkillCap) { __instance.RebalanceSkills(cSkillType); } if (value2.m_info != null) { ((Character)Player.m_localPlayer).Message((MessageType)1, $"Skill increased {Utils.GetTranslated((int)value2.m_info.m_skill)}: {(int)value2.m_level}", 0, (Sprite)null); Console.instance.Print($"Skill {cSkillName} = {value2.m_level}"); } return false; } return true; } } [HarmonyPatch(typeof(Skills), "CheatResetSkill")] private static class Skills_CheatResetSkill_Patch { private static bool Prefix(string name, Skills __instance, Dictionary<SkillType, Skill> ___m_skillData) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected I4, but got Unknown Logging.GetLogger().Debug("Skills CheatResetSkill Prefix"); if (Cfg.useSkill.Value && name.ToLower().Equals(cSkillName.ToLower())) { if (___m_skillData.TryGetValue(cSkillType, out var value)) { value.m_accumulator = 0f; value.m_level = 0f; } Console.instance.Print("Skill " + Utils.GetTranslated((int)value.m_info.m_skill) + " reset"); return false; } return true; } } [HarmonyPatch(typeof(SkillsDialog), "Setup")] private static class SkillsDialog_Setup_Patch { private static void Postfix(Player player, ref List<GameObject> ___m_elements) { Logging logger = Logging.GetLogger(); logger.Debug("SkillsDialog Setup Postfix"); if (!Cfg.useSkill.Value) { return; } object obj; if (player == null) { obj = null; } else { Skills skills = ((Character)player).GetSkills(); obj = ((skills != null) ? skills.GetSkillList() : null); } List<Skill> list = (List<Skill>)obj; if (list == null) { logger.Debug("Can't get player skill list"); return; } int num = list.FindIndex((Skill s) => s.m_info == cSkillDef); if (num < 0) { logger.Debug("Can't find custom skill"); return; } GameObject val = ___m_elements[num]; if ((Object)(object)val == (Object)null) { logger.Debug("Skill game object is null"); return; } Transform obj2 = Utils.FindChild(val.transform, "name"); object obj3; if (obj2 == null) { obj3 = null; } else { Text component = ((Component)obj2).GetComponent<Text>(); obj3 = ((component != null) ? component.text : null); } if (obj3 == null) { logger.Debug("Can't find and set custom skill text"); } else { _ = cSkillName; } } } public static SkillType cSkillType = (SkillType)0; public static SkillDef cSkillDef = null; public static Skill cSkill = null; private static string cSkillName = ""; private static string cIconPrefab = null; private static string saveName; public static SkillType GetCustomSkillType() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return cSkillType; } public static SkillDef GetCustomSkillDef() { return cSkillDef; } public static Skill GetCustomSkill() { return cSkill; } public static void CheckForPreExistingCustomSkill(Player player) { if (cSkill == null || cSkill.m_level != 0f || cSkill.m_accumulator != 0f) { return; } Logging.GetLogger().Debug("Looking for pre-existing skill"); if (player.m_customData.TryGetValue(saveName, out var value)) { Logging.GetLogger().Debug("Found pre-existing skill values"); string[] array = value.Split(new char[1] { ':' }); if (array.Length == 2 && float.TryParse(array[0], out var result) && float.TryParse(array[1], out var result2)) { cSkill.m_level = result; cSkill.m_accumulator = result2; } } } public static void ToggleCustomSkill(bool enable) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; Skills val = ((localPlayer != null) ? ((Character)localPlayer).GetSkills() : null); if ((Object)(object)val == (Object)null) { return; } Dictionary<SkillType, Skill> skillData = val.m_skillData; if (skillData == null) { return; } if (enable) { if (skillData.ContainsKey(cSkillType)) { skillData[cSkillType] = cSkill; } else { skillData.Add(cSkillType, cSkill); } } else { skillData.Remove(cSkillType); } } public static void ConfigureSkillDef(string name, string descrip, string iconPrefabName) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) int num = Math.Abs(StringExtensionMethods.GetStableHashCode(name)); cSkillType = (SkillType)num; cSkillDef = new SkillDef(); cSkillDef.m_description = descrip; cSkillDef.m_increseStep = 1f; cSkillDef.m_skill = cSkillType; cSkillName = name; cIconPrefab = iconPrefabName; saveName = "NEObotics_" + cSkillName; Utils.SetTranslator(num, name); } } internal class DebugUtils { public static void ObjectInspector(object o) { if (o == null) { Debug.Log((object)"Object is null"); return; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; Type type = o.GetType(); Debug.Log((object)(o.ToString() + " Type " + type.Name)); PropertyInfo[] properties = type.GetProperties(bindingAttr); foreach (PropertyInfo propertyInfo in properties) { Debug.Log((object)$"{type.Name}.{propertyInfo.Name} = {propertyInfo.GetValue(o)}"); } FieldInfo[] fields = type.GetFields(bindingAttr); foreach (FieldInfo field in fields) { FieldPrinter(o, type, field); } } public static void MethodInspector(object o) { if (o == null) { Debug.Log((object)"Object is null"); return; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; Type type = o.GetType(); Debug.Log((object)(o.ToString() + " Type " + type.Name)); MethodInfo[] methods = type.GetMethods(bindingAttr); foreach (MethodInfo methodInfo in methods) { methodInfo.GetParameters(); string arg = string.Join(", ", (from x in methodInfo.GetParameters() select x.ParameterType?.ToString() + " " + x.Name).ToArray()); Debug.Log((object)$"{methodInfo.ReturnType} {methodInfo.Name} ({arg})"); } } private static void ItemDataInspector(ItemData item) { ObjectInspector(item); ObjectInspector(item.m_shared); } private static void FieldPrinter(object o, Type t, FieldInfo field) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown try { if (field.FieldType == typeof(ItemData)) { ItemData val = (ItemData)field.GetValue(o); if (val != null) { ItemDataInspector(val); } else { Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]"); } } else if (field.FieldType == typeof(Transform)) { Transform val2 = (Transform)field.GetValue(o); if ((Object)(object)val2 != (Object)null) { Debug.Log((object)("\tTransform.parent = " + ((Object)val2.parent).name)); } else { Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]"); } } else if (field.FieldType == typeof(EffectList)) { EffectList val3 = (EffectList)field.GetValue(o); if (val3 != null) { Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)}:"); EffectData[] effectPrefabs = val3.m_effectPrefabs; foreach (EffectData val4 in effectPrefabs) { Debug.Log((object)("\tEffectData.m_prefab = " + ((Object)val4.m_prefab).name)); } } else { Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)} [null]"); } } else { Debug.Log((object)$"{t.Name}.{field.Name} = {field.GetValue(o)}"); } } catch (Exception) { Debug.Log((object)("Exception accessing " + t?.Name + "." + field?.Name)); } } public static void GameObjectInspector(GameObject go) { Debug.Log((object)("\n\nInspecting GameObject " + ((Object)go).name)); ObjectInspector(go); Component[] componentsInChildren = go.GetComponentsInChildren<Component>(); foreach (Component val in componentsInChildren) { try { string obj = ((val != null) ? ((Object)val).name : null); object obj2; if (val == null) { obj2 = null; } else { Transform transform = val.transform; if (transform == null) { obj2 = null; } else { Transform parent = transform.parent; obj2 = ((parent != null) ? ((Object)parent).name : null); } } Debug.Log((object)("\n\nInspecting Component " + obj + " with parent " + (string?)obj2)); ObjectInspector(val); } catch (Exception) { } } } public static void ComponentInspector(Component c) { Debug.Log((object)("\n\nInspecting Component " + ((Object)c).name)); ObjectInspector(c); } public static void EffectsInspector(EffectList e) { EffectData[] effectPrefabs = e.m_effectPrefabs; Debug.Log((object)$"Effect list has effects {e.HasEffects()} count {effectPrefabs.Length}"); EffectData[] array = effectPrefabs; foreach (EffectData val in array) { Debug.Log((object)$"Effect Data {val} prefab name {((Object)val.m_prefab).name} prefab GameObject name {((Object)val.m_prefab.gameObject).name}"); } } public static void PrintInventory() { foreach (ItemData allItem in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems()) { Debug.Log((object)allItem.m_shared.m_name); } } public static void PrintAllObjects() { ZNetScene.instance.m_prefabs.ForEach(delegate(GameObject x) { Debug.Log((object)("GameObject " + ((Object)x).name)); }); } public static void PrintAllCharacters() { Character.GetAllCharacters().ForEach(delegate(Character x) { Debug.Log((object)("Character " + ((Object)x).name)); }); } } public class DelegatedConfigEntry<T> : DelegatedConfigEntryBase { private ConfigEntry<T> _entry; private EventHandler rootHandler; private Action<object, EventArgs> clientDelegate; private Logging Log; public ConfigEntry<T> ConfigEntry { get { return _entry; } set { _entry = value; if (_entry != null && rootHandler != null) { _entry.SettingChanged += rootHandler; } Name = ((ConfigEntryBase)_entry).Definition.Key; Section = ((ConfigEntryBase)_entry).Definition.Section; ServerValue = ((ConfigEntryBase)_entry).GetSerializedValue(); Log.Trace("Set " + Section + " " + Name + " to serialized value " + ServerValue); } } public T Value { get { return _entry.Value; } set { _entry.Value = value; } } public DelegatedConfigEntry(bool useServerDelegate = false) : this((Action<object, EventArgs>)null, useServerDelegate) { } public DelegatedConfigEntry(Action<object, EventArgs> delegateHandler, bool useServerDelegate = false) { Log = Logging.GetLogger(); Log.Trace("DelegatedConfigEntry"); if (delegateHandler != null) { clientDelegate = delegateHandler; } if (useServerDelegate) { Log.Trace("Configuring server delegate"); rootHandler = delegate(object s, EventArgs e) { ServerDelegate(s, e); }; ServerConfiguration.ServerDelegatedEntries.Add(this); } else if (clientDelegate != null) { rootHandler = delegate(object s, EventArgs e) { clientDelegate(s, e); }; } } private void ServerDelegate(object sender, EventArgs args) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown Logging.GetLogger().Trace("ServerDelegate"); _entry.SettingChanged -= rootHandler; ZNet instance = ZNet.instance; bool? flag = ((instance != null) ? new bool?(instance.IsServer()) : null); if (flag.HasValue) { if (flag == false) { if (ServerValue != null) { ((ConfigEntryBase)_entry).SetSerializedValue(ServerValue); } } else { ServerValue = ((ConfigEntryBase)_entry).GetSerializedValue(); ServerConfiguration.Instance.SendConfigToAllClients(sender, (SettingChangedEventArgs)args); } } if (clientDelegate != null) { clientDelegate(sender, args); } _entry.SettingChanged += rootHandler; } public void EnableHandler(bool setActive) { if (setActive) { _entry.SettingChanged += rootHandler; } else { _entry.SettingChanged -= rootHandler; } } public bool IsKeyPressed() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (ConfigEntry is ConfigEntry<KeyboardShortcut> val) { KeyboardShortcut value = val.Value; foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers) { if (!Input.GetKey(modifier)) { return false; } } if (!Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey)) { return false; } return true; } Log.Error("Keyboard read attempted on non-KeyboardShortcut config."); return false; } public bool IsKeyDown() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (ConfigEntry is ConfigEntry<KeyboardShortcut> val) { KeyboardShortcut value = val.Value; foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers) { if (!Input.GetKey(modifier)) { return false; } } if (!Input.GetKey(((KeyboardShortcut)(ref value)).MainKey)) { return false; } return true; } Log.Error("Keyboard read attempted on non-KeyboardShortcut config."); return false; } public bool IsKeyReleased() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (ConfigEntry is ConfigEntry<KeyboardShortcut> val) { KeyboardShortcut value = val.Value; foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers) { if (!Input.GetKeyUp(modifier)) { return false; } } if (!Input.GetKeyUp(((KeyboardShortcut)(ref value)).MainKey)) { return false; } return true; } Log.Error("Keyboard read attempted on non-KeyboardShortcut config."); return false; } } public class DelegatedConfigEntryBase { public string Name; public string Section; public string ServerValue; } internal class HarmonyHelper { public enum PatchType { Prefix, Postfix, Transpiler, Finalizer } private static Dictionary<string, string> detectionSet = new Dictionary<string, string>(); private static Dictionary<string, string> unpatchMods = new Dictionary<string, string>(); public static void GetDetectionSet(Dictionary<string, string> harmonyIds) { Logging logger = Logging.GetLogger(); foreach (KeyValuePair<string, string> harmonyId in harmonyIds) { if (Harmony.HasAnyPatches(harmonyId.Key)) { logger.Debug("Detected " + harmonyId.Value + " from Harmony"); if (!detectionSet.ContainsKey(harmonyId.Key)) { detectionSet.Add(harmonyId.Key, harmonyId.Value); } } else if (Chainloader.PluginInfos.ContainsKey(harmonyId.Key)) { logger.Debug("Detected " + harmonyId.Value + " from BepInEx"); if (!detectionSet.ContainsKey(harmonyId.Key)) { detectionSet.Add(harmonyId.Key, harmonyId.Value); } } } } public static void AddExclusion(string key) { if (detectionSet.ContainsKey(key)) { unpatchMods.Add(key, detectionSet[key]); } } public static void UnpatchMods(Harmony harmony) { Logging logger = Logging.GetLogger(); foreach (KeyValuePair<string, string> unpatchMod in unpatchMods) { logger.Warning("Not compatible with " + unpatchMod.Value); harmony.UnpatchAll(unpatchMod.Key); detectionSet.Remove(unpatchMod.Key); logger.Warning("Disabled " + unpatchMod.Value); } } public static bool IsModDetected(string key) { return detectionSet.ContainsKey(key); } public static bool IsModNameDetected(string value) { return detectionSet.ContainsValue(value); } public static bool TryGetDetectedModName(string key, out string mod) { return detectionSet.TryGetValue(key, out mod); } public static bool TryGetDetectedModKey(string value, out string key) { key = null; foreach (string key2 in detectionSet.Keys) { if (detectionSet[key2] == value) { key = key2; return true; } } return false; } public static string AddAnonymousPatch(string baseMethodName, PatchType patchType, string modName, string patchMethodName = null) { string text = null; int num = 0; Logging logger = Logging.GetLogger(); foreach (MethodBase item in Harmony.GetAllPatchedMethods().ToList()) { MethodBaseExtensions.HasMethodBody(item); Patches patchInfo = Harmony.GetPatchInfo(item); ReadOnlyCollection<Patch> readOnlyCollection = patchInfo.Prefixes; switch (patchType) { case PatchType.Postfix: readOnlyCollection = patchInfo.Postfixes; break; case PatchType.Prefix: readOnlyCollection = patchInfo.Prefixes; break; case PatchType.Transpiler: readOnlyCollection = patchInfo.Transpilers; break; case PatchType.Finalizer: readOnlyCollection = patchInfo.Finalizers; break; } foreach (Patch item2 in readOnlyCollection) { if (!item2.owner.StartsWith("harmony-auto") || !(item.Name == baseMethodName)) { continue; } if (patchMethodName != null) { if (item2.PatchMethod.Name == patchMethodName) { num++; text = item2.owner; } } else { num++; text = item2.owner; } } if (num == 1) { detectionSet.Add(text, modName); logger.Info($"Added unique anonymous {baseMethodName} {patchType}: {text} as {modName}"); } else if (num > 1) { text = null; logger.Warning($"Found multiple anonymous {baseMethodName} {patchType} entries. Can't identify correct patch to remove or modify."); } } if (num == 0) { logger.Info("No patch found for " + modName); } return text; } } public class Logging { public enum LogLevels { Critical, Error, Warning, Info, Debug, Trace } private static Logging _logger; public LogLevels LogLevel { get; set; } public string ModName { get; set; } private Logging(LogLevels level, string name) { LogLevel = level; ModName = name; } public static Logging GetLogger(LogLevels level, string name) { if (_logger == null) { _logger = new Logging(level, name); } return _logger; } public static Logging GetLogger() { if (_logger == null) { throw new NullReferenceException("Logger not initialized"); } return _logger; } public void Trace(string msg) { if (LogLevel >= LogLevels.Trace) { Debug.Log((object)Message(msg)); } } public void Debug(string msg) { if (LogLevel >= LogLevels.Debug) { Debug.Log((object)Message(msg)); } } public void Info(string msg) { if (LogLevel >= LogLevels.Info) { Debug.Log((object)Message(msg)); } } public void Warning(string msg) { if (LogLevel >= LogLevels.Warning) { Debug.LogWarning((object)Message(msg)); } } public void Error(string msg) { if (LogLevel >= LogLevels.Error) { Debug.LogWarning((object)Message(msg)); } } public void Error(Exception e) { Error(e, stackTrace: false); } public void Error(Exception e, bool stackTrace) { if (LogLevel >= LogLevels.Error) { Warning(Message(e.Message)); if (stackTrace) { Warning(e.StackTrace); } } } public void Critical(Exception e) { if (LogLevel >= LogLevels.Critical) { Debug(Message(e.Message)); Error(e.StackTrace); } } private string Message(string msg) { return ModName + ": " + msg; } public static void ChangeLogging(object s, EventArgs e) { SettingChangedEventArgs val = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null); GetLogger().Debug($"ChangeLog {val.ChangedSetting.Definition.Key} to {val.ChangedSetting.BoxedValue}"); GetLogger().LogLevel = Cfg.debugLevel.Value; } } public class ServerConfiguration { [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class ZNet_OnNewConnection_Patch { private static void Postfix(ZNet __instance, ZNetPeer peer) { Log.Debug("ZNet OnNewConnection postfix"); if (!__instance.IsServer()) { try { Log.Debug("PlayerChoice registered RPC_ClientConfigReceiver"); peer.m_rpc.Register<ZPackage>("ClientConfigReceiver." + GetPluginGuid(), (Action<ZRpc, ZPackage>)RPC_ClientConfigReceiver); return; } catch (Exception) { Log.Warning("Failed to register RPC"); return; } } try { SendConfigToClient(peer); } catch (Exception) { Log.Warning("Error sending server configuration to client"); } } } public static List<DelegatedConfigEntryBase> ServerDelegatedEntries = new List<DelegatedConfigEntryBase>(); private static ConfigFile LocalConfig; private static BaseUnityPlugin Mod; private static string ConfigFileName; private static ServerConfiguration _instance; private static Logging Log; public static bool IsSetup = false; private const string NOT_CONFIGURED = "ServerConfiguration not initialized. Setup first."; public static ServerConfiguration Instance { get { if (_instance == null) { _instance = new ServerConfiguration(); } return _instance; } } private ServerConfiguration() { } public void Setup(ConfigFile config, BaseUnityPlugin modInstance) { LocalConfig = config; Log = Logging.GetLogger(); Log.Trace("ServerConfiguration Setup"); Mod = modInstance; ConfigFileName = Path.GetFileName(LocalConfig.ConfigFilePath); IsSetup = true; } public void CreateConfigWatcher() { string configFilePath = LocalConfig.ConfigFilePath; string fileName = Path.GetFileName(LocalConfig.ConfigFilePath); Log.Trace("Configuration File Watcher Setup"); FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(configFilePath.Substring(0, configFilePath.Length - fileName.Length), fileName); fileSystemWatcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime; fileSystemWatcher.Changed += LoadConfig; fileSystemWatcher.Created += LoadConfig; fileSystemWatcher.IncludeSubdirectories = false; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } private void LoadConfig(object sender, FileSystemEventArgs e) { if (!File.Exists(LocalConfig.ConfigFilePath)) { return; } try { Log.Debug($"Loading configuration {e.ChangeType}"); LocalConfig.Reload(); } catch { Log.Error("Error loading configuration file " + ConfigFileName); } } public static string GetPluginGuid() { return Mod.Info.Metadata.GUID; } public static void RPC_ClientConfigReceiver(ZRpc zrpc, ZPackage package) { if (!IsSetup) { Log.Error("ServerConfiguration not initialized. Setup first."); return; } Log.Debug("ClientConfigReceiver"); string section; string name; while (package.GetPos() < package.Size()) { section = package.ReadString(); name = package.ReadString(); string text = package.ReadString(); Log.Trace("Reading " + section + " " + name + " value " + text + " from ZPackage"); DelegatedConfigEntryBase delegatedConfigEntryBase = ServerDelegatedEntries.Find((DelegatedConfigEntryBase e) => e.Name == name && e.Section == section); if (delegatedConfigEntryBase != null) { Log.Trace("Found DCEB on client and setting to server value " + text); delegatedConfigEntryBase.ServerValue = text; } ConfigEntryBase val = LocalConfig[section, name]; if (val != null) { Log.Trace("Found local CEB and setting underlying config value " + text); val.SetSerializedValue(text); } } } internal static void WriteConfigEntries(ZPackage zpkg) { foreach (DelegatedConfigEntryBase serverDelegatedEntry in ServerDelegatedEntries) { Log.Trace("Writing " + serverDelegatedEntry.Section + " " + serverDelegatedEntry.Name + " value " + serverDelegatedEntry.ServerValue + " to ZPackage"); zpkg.Write(serverDelegatedEntry.Section); zpkg.Write(serverDelegatedEntry.Name); zpkg.Write(serverDelegatedEntry.ServerValue); } } internal static void SendConfigToClient(ZNetPeer peer) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if (!IsSetup) { Log.Error("ServerConfiguration not initialized. Setup first."); return; } Log.Debug("ServerSendConfigToClient"); ZPackage val = new ZPackage(); WriteConfigEntries(val); peer.m_rpc.Invoke("ClientConfigReceiver." + GetPluginGuid(), new object[1] { val }); } public void SendConfigToAllClients(object o, SettingChangedEventArgs e) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown if (!IsSetup) { Log.Error("ServerConfiguration not initialized. Setup first."); } else if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && ZNet.instance.GetPeerConnections() > 0) { Log.Debug("SendConfigToAllClients"); ZPackage zpkg = new ZPackage(); WriteConfigEntries(zpkg); ((MonoBehaviour)Mod).StartCoroutine(_instance.Co_BroadcastConfig(zpkg)); } } private IEnumerator Co_BroadcastConfig(ZPackage zpkg) { Log.Debug("Co_BroadcastConfig"); List<ZNetPeer> connectedPeers = ZNet.instance.GetConnectedPeers(); foreach (ZNetPeer item in connectedPeers) { if (item != ZNet.instance.GetServerPeer()) { item.m_rpc.Invoke("ClientConfigReceiver." + GetPluginGuid(), new object[1] { zpkg }); } yield return null; } } } internal class Utils { public static TEnum Guardrails<TEnum>(string value, TEnum enumDefault) where TEnum : struct { if (Enum.TryParse<TEnum>(value, ignoreCase: true, out var result)) { return result; } return enumDefault; } public static int Guardrails(int value, int lbound, int ubound) { if (value < lbound) { return lbound; } if (value > ubound) { return ubound; } return value; } public static float Guardrails(float value, float lbound, float ubound) { if (value < lbound) { return lbound; } if (value > ubound) { return ubound; } return value; } public static string UnClonifiedName(string name) { if (name == null) { return null; } int num = name.IndexOf("(Clone)"); if (num < 1) { return name; } return name.Substring(0, num); } public static void SetTranslator(int id, string idText) { typeof(Localization).GetMethod("AddWord", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(Localization.instance, new object[2] { "skill_" + id, idText }); } public static string GetTranslated(int id) { Logging.GetLogger().Debug(string.Format("Got translation for id {0} to {1}", id, Localization.instance.Localize("skill_" + id))); return Localization.instance.Localize("$skill_" + id); } public static Sprite GetPrefabIcon(string prefabName) { Sprite result = null; GameObject prefab = GetPrefab(prefabName); ItemDrop val = default(ItemDrop); if ((Object)(object)prefab != (Object)null && prefab.TryGetComponent<ItemDrop>(ref val)) { result = val.m_itemData.GetIcon(); } return result; } public static Player GetPlayerByZDOID(ZDOID zid) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) foreach (Player allPlayer in Player.GetAllPlayers()) { ZDOID zDOID = ((Character)allPlayer).GetZDOID(); if (((ZDOID)(ref zDOID)).Equals(zid)) { return allPlayer; } } return null; } public static Character GetCharacterByZDOID(string cid) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) foreach (Character allCharacter in Character.GetAllCharacters()) { ZDOID zDOID = allCharacter.GetZDOID(); if (((object)(ZDOID)(ref zDOID)).ToString().Equals(cid)) { return allCharacter; } } return null; } public static Character GetCharacterByZDOID(ZDOID cid) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) foreach (Character allCharacter in Character.GetAllCharacters()) { ZDOID zDOID = allCharacter.GetZDOID(); if (((ZDOID)(ref zDOID)).Equals(cid)) { return allCharacter; } } return null; } public static ZNetPeer GetPeerByRPC(ZRpc rpc) { foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer.m_rpc == rpc) { return peer; } } return null; } public static List<GameObject> GetGameObjectsOfType(Type t) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) List<GameObject> list = new List<GameObject>(); Object[] array = Object.FindObjectsOfType(t); foreach (Object val in array) { list.Add(((Component)val).gameObject); } return list; } public static GameObject GetClosestGameObjectOfType(Type t, Vector3 point, float radius) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return GetGameObjectsOfTypeInRangeByDistance(t, point, radius)?[0]; } public static List<GameObject> GetGameObjectsOfTypeInRangeByDistance(Type t, Vector3 point, float radius) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) List<KeyValuePair<GameObject, float>> list = new List<KeyValuePair<GameObject, float>>(); List<GameObject> gameObjectsOfTypeInRange = GetGameObjectsOfTypeInRange(t, point, radius); if (gameObjectsOfTypeInRange.Count > 0) { foreach (GameObject item in gameObjectsOfTypeInRange) { list.Add(new KeyValuePair<GameObject, float>(item, Vector3.Distance(item.transform.position, point))); } list.Sort((KeyValuePair<GameObject, float> pair1, KeyValuePair<GameObject, float> pair2) => pair1.Value.CompareTo(pair2.Value)); return list.ConvertAll((KeyValuePair<GameObject, float> x) => x.Key); } return null; } public static List<GameObject> GetGameObjectsOfTypeInRange(Type t, Vector3 point, float radius) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) return (from x in GetGameObjectsOfType(t) where Vector3.Distance(x.transform.position, point) < radius select x).ToList(); } public static float GetPointDepth(Vector3 p) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) return ZoneSystem.instance.m_waterLevel - GetSolidHeight(p); } public static List<string> GetDelimitedStringAsList(string delimitedString, char delimiter) { List<string> list = new List<string>(); string[] array = delimitedString.Split(new char[1] { delimiter }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { list.Add(text.Trim()); } return list; } public static float GetSolidHeight(Vector3 p) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) int solidRayMask = ZoneSystem.instance.m_solidRayMask; float result = 0f; p.y += 1000f; RaycastHit val = default(RaycastHit); if (Physics.Raycast(p, Vector3.down, ref val, 2000f, solidRayMask) && !Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider.attachedRigidbody)) { result = ((RaycastHit)(ref val)).point.y; } return result; } public static Transform FindChild(Transform aParent, string aName) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown foreach (Transform item in aParent) { Transform val = item; if (((Object)val).name == aName) { return val; } Transform val2 = FindChild(val, aName); if ((Object)(object)val2 != (Object)null) { return val2; } } return null; } public static Transform FindParent(Transform go) { while ((Object)(object)go.parent != (Object)null) { go = go.parent; } return go; } public static GameObject GetPrefab(int prefabHash) { return GetPrefabByHash(prefabHash); } public static GameObject GetPrefabByHash(int prefabHash) { GameObject val = ObjectDB.instance.GetItemPrefab(prefabHash); Logging logger = Logging.GetLogger(); if ((Object)(object)val != (Object)null) { logger.Debug("Found prefab in ObjectDB"); } else { ZNetScene instance = ZNetScene.instance; val = ((instance != null) ? instance.GetPrefab(prefabHash) : null); if ((Object)(object)val != (Object)null) { logger.Debug("Found prefab in Scene"); } } return val; } public static GameObject GetPrefab(string prefabName) { GameObject val = ObjectDB.instance.GetItemPrefab(prefabName); Logging logger = Logging.GetLogger(); if ((Object)(object)val != (Object)null) { logger.Debug("Found " + prefabName + " in ObjectDB"); } else { ZNetScene instance = ZNetScene.instance; val = ((instance != null) ? instance.GetPrefab(prefabName) : null); if ((Object)(object)val != (Object)null) { logger.Debug("Found " + prefabName + " in Scene"); } } return val; } public static string SerializeFromDictionary<K, V>(string delimp, string delimc, IDictionary<K, V> dict) { if (dict == null) { return null; } IEnumerable<string> values = dict.Select(delegate(KeyValuePair<K, V> kvp) { KeyValuePair<K, V> keyValuePair = kvp; string? obj = keyValuePair.Key?.ToString(); string text = delimc; keyValuePair = kvp; return obj + text + keyValuePair.Value; }); return string.Join(delimp, values); } public static void DeserializeToDictionary<K, V>(string serializedString, string delimp, string delimc, ref IDictionary<K, V> dict) { if (dict == null) { return; } dict.Clear(); string[] separator = new string[1] { delimp }; string[] separator2 = new string[1] { delimc }; string[] array = serializedString.Split(separator, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(separator2, StringSplitOptions.RemoveEmptyEntries); if (array2.Length == 2) { dict.Add(TypedValue<K>(array2[0]), TypedValue<V>(array2[1])); } } } public static T TypedValue<T>(object a) { return (T)Convert.ChangeType(a, typeof(T)); } public static float TimeAdjustedRamp(float maxValue, float duration, float elapsedTime, float pctFromStartRise, float pctFromEndFall) { float num = elapsedTime / duration; if (num <= pctFromStartRise) { return maxValue * (num / pctFromStartRise); } if (num >= 1f - pctFromEndFall) { return maxValue * ((1f - num) / pctFromEndFall); } return maxValue; } public static bool CopyComponentToGameObject(Component original, ref GameObject destination) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown Logging logger = Logging.GetLogger(); Type type = ((object)original).GetType(); logger.Debug($"Original Type is {type}"); GameObject obj = destination; logger.Debug("Destination GameObject " + ((obj != null) ? ((Object)obj).name : null)); Component val = destination.GetComponent(type); if ((Object)(object)val == (Object)null) { val = destination.AddComponent(type); } if ((Object)(object)val == (Object)null) { logger.Debug("Destination component is null"); return false; } Component val2 = (Component)Activator.CreateInstance(type); if ((Object)(object)val2 == (Object)null) { logger.Debug("Destination component is null"); return false; } if ((Object)(object)val2 == (Object)null) { logger.Debug("Boxed component is null"); return false; } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { fieldInfo.SetValue(val2, fieldInfo.GetValue(original)); } val = val2; return true; } public static bool CopyObject(object original, object target) { Logging logger = Logging.GetLogger(); Type type = original.GetType(); Type type2 = target.GetType(); if (type == null) { logger.Warning("Copy Object: Source object is null"); Activator.CreateInstance(type); return false; } if (type2 == null) { logger.Warning("Copy Object: Destination object is null"); return false; } if (type2 != type) { logger.Warning("Copy Object: Source and destination components are different types"); return false; } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { fieldInfo.SetValue(target, fieldInfo.GetValue(original)); } return true; } } internal class AtgeirBuilder { public static SecondaryAttacks GetSecondaryAttacks(ItemData item) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) SecondaryAttacks secondaryAttacks = new SecondaryAttacks(); AttackPrototype attackPrototype = Prototypes.GetAttackPrototype("AtgeirBronze"); Logging logger = Logging.GetLogger(); logger.Debug("Using atgeir secondary melee attack"); secondaryAttacks.melee = item.m_shared.m_secondaryAttack.Clone(); logger.Debug("Creating atgeir secondary projectile attack"); secondaryAttacks.projectile = attackPrototype.secondaryAttack.Clone(); secondaryAttacks.projectile.m_attackType = (AttackType)2; secondaryAttacks.projectile.m_consumeItem = true; secondaryAttacks.projectile.m_projectileAccuracy = 1f; Prototypes.ConfigAttackForWeapon(secondaryAttacks.projectile, item, item.m_shared.m_secondaryAttack, 2f, 1f, 2f, 1.5f); secondaryAttacks.projectile.m_attackProjectile = null; return secondaryAttacks; } } public class AttackPrototype { public ItemData item; public Attack secondaryAttack; public Attack primaryAttack; public CharacterAnimEvent secondaryAnimationEvent; public CharacterAnimEvent primaryAnimationEvent; } internal class AxeBuilder2H { public static SecondaryAttacks GetSecondaryAttacks(ItemData item) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) SecondaryAttacks secondaryAttacks = new SecondaryAttacks(); AttackPrototype attackPrototype = Prototypes.GetAttackPrototype("Battleaxe"); AttackPrototype attackPrototype2 = Prototypes.GetAttackPrototype("PickaxeBronze"); Logging logger = Logging.GetLogger(); logger.Debug("Using 2H axe secondary melee attack"); secondaryAttacks.melee = item.m_shared.m_secondaryAttack.Clone(); logger.Debug("Creating 2H axe secondary projectile attack"); secondaryAttacks.projectile = attackPrototype.secondaryAttack.Clone(); secondaryAttacks.projectile.m_attackAnimation = attackPrototype2.primaryAttack.m_attackAnimation; secondaryAttacks.projectile.m_animEvent = attackPrototype2.primaryAnimationEvent; secondaryAttacks.projectile.m_attackType = (AttackType)2; secondaryAttacks.projectile.m_consumeItem = true; secondaryAttacks.projectile.m_projectileAccuracy = 1f; Prototypes.ConfigAttackForWeapon(secondaryAttacks.projectile, item, item.m_shared.m_attack, 1.5f, 1f, 2f, 1.5f, 2f); secondaryAttacks.projectile.m_attackProjectile = null; return secondaryAttacks; } } internal class AxeBuilder { public static SecondaryAttacks GetSecondaryAttacks(ItemData item) { SecondaryAttacks secondaryAttacks = new SecondaryAttacks(); AttackPrototype attackPrototype = Prototypes.GetAttackPrototype("SpearBronze"); Logging logger = Logging.GetLogger(); logger.Debug("Using axe secondary melee attack"); secondaryAttacks.melee = item.m_shared.m_secondaryAttack.Clone(); logger.Debug("Creating axe secondary projectile attack"); secondaryAttacks.projectile = attackPrototype.secondaryAttack.Clone(); Prototypes.ConfigAttackForWeapon(secondaryAttacks.projectile, item, item.m_shared.m_secondaryAttack); secondaryAttacks.projectile.m_attackProjectile = null; return secondaryAttacks; } } internal class Cfg { public static DelegatedConfigEntry<bool> enableAxes = null; public static DelegatedConfigEntry<bool> enableKnives = null; public static DelegatedConfigEntry<bool> enableSpears = null; public static DelegatedConfigEntry<bool> enableClubs = null; public static DelegatedConfigEntry<bool> enableSwords = null; public static DelegatedConfigEntry<bool> enablePickaxes = null; public static DelegatedConfigEntry<bool> weaponStones = null; public static DelegatedConfigEntry<bool> weaponWisps = null; public static DelegatedConfigEntry<bool> weaponEitr = null; public static DelegatedConfigEntry<bool> weaponEggs = null; public static DelegatedConfigEntry<bool> weaponTankards = null; public static DelegatedConfigEntry<bool> enableShields = null; public static DelegatedConfigEntry<bool> throwUnderhand = null; public static DelegatedConfigEntry<int> targetAdjustment = null; public static DelegatedConfigEntry<Logging.LogLevels> debugLevel = null; public static DelegatedConfigEntry<MaxAxe.Dynamics> gravity = null; public static DelegatedConfigEntry<bool> useSkill = null; public static DelegatedConfigEntry<string> externalExclude = null; public static DelegatedConfigEntry<bool> stackableWeapons = null; public static DelegatedConfigEntry<bool> mjolnirMode = null; public static DelegatedConfigEntry<bool> enablePolearms = null; public static DelegatedConfigEntry<bool> allow2Handed = null; public static ConfigEntry<bool> useMelee = null; public static ConfigEntry<bool> autoMelee = null; public static ConfigEntry<bool> autoEquip = null; public static ConfigEntry<bool> throwingStatus = null; public static ConfigEntry<MaxAxe.Finders> weaponFinder = null; public static ConfigEntry<Color> itemAmountColor = null; public static ConfigEntry<bool> forceSimpleTrail = null; public static ConfigEntry<bool> useKeyRelease = null; public static ConfigEntry<bool> disableIncompatible = null; public static ConfigEntry<bool> autoEquipShields = null; public static ConfigEntry<bool> saveSlotForFrostner = null; private static KeyCode[] keyModifiers = (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }; private static KeyboardShortcut toggleMeleeKeyDefault = new KeyboardShortcut((KeyCode)98, keyModifiers); public static DelegatedConfigEntry<KeyboardShortcut> toggleMeleeKey = null; private static KeyboardShortcut throwOneKeyDefault = new KeyboardShortcut((KeyCode)116, Array.Empty<KeyCode>()); public static DelegatedConfigEntry<KeyboardShortcut> throwOneKey = null; private static KeyboardShortcut throwShieldKeyDefault = new KeyboardShortcut((KeyCode)103, Array.Empty<KeyCode>()); public static DelegatedConfigEntry<KeyboardShortcut> throwShieldKey = null; public static void BepInExConfig(BaseUnityPlugin _instance) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected O, but got Unknown //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Expected O, but got Unknown //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Expected O, but got Unknown //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Expected O, but got Unknown //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Expected O, but got Unknown //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Expected O, but got Unknown //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Expected O, but got Unknown //IL_0357: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Expected O, but got Unknown //IL_03a8: Unknown result type (might be due to invalid IL or missing references) //IL_03b2: Expected O, but got Unknown //IL_03f9: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Expected O, but got Unknown //IL_044a: Unknown result type (might be due to invalid IL or missing references) //IL_0454: Expected O, but got Unknown //IL_049b: Unknown result type (might be due to invalid IL or missing references) //IL_04a5: Expected O, but got Unknown //IL_04f8: Unknown result type (might be due to invalid IL or missing references) //IL_0502: Expected O, but got Unknown //IL_0555: Unknown result type (might be due to invalid IL or missing references) //IL_055f: Expected O, but got Unknown //IL_05b2: Unknown result type (might be due to invalid IL or missing references) //IL_05bc: Expected O, but got Unknown //IL_060f: Unknown result type (might be due to invalid IL or missing references) //IL_0619: Expected O, but got Unknown //IL_066c: Unknown result type (might be due to invalid IL or missing references) //IL_0676: Expected O, but got Unknown //IL_06bd: Unknown result type (might be due to invalid IL or missing references) //IL_06c7: Expected O, but got Unknown //IL_070e: Unknown result type (might be due to invalid IL or missing references) //IL_0718: Expected O, but got Unknown //IL_076b: Unknown result type (might be due to invalid IL or missing references) //IL_0775: Expected O, but got Unknown //IL_07ab: Unknown result type (might be due to invalid IL or missing references) //IL_07b5: Expected O, but got Unknown //IL_0807: Unknown result type (might be due to invalid IL or missing references) //IL_0811: Expected O, but got Unknown //IL_0847: Unknown result type (might be due to invalid IL or missing references) //IL_0851: Expected O, but got Unknown //IL_0887: Unknown result type (might be due to invalid IL or missing references) //IL_0891: Expected O, but got Unknown //IL_08c7: Unknown result type (might be due to invalid IL or missing references) //IL_08d1: Expected O, but got Unknown //IL_0920: Unknown result type (might be due to invalid IL or missing references) //IL_092a: Expected O, but got Unknown //IL_0970: Unknown result type (might be due to invalid IL or missing references) //IL_097a: Expected O, but got Unknown //IL_09b0: Unknown result type (might be due to invalid IL or missing references) //IL_09ba: Expected O, but got Unknown //IL_09ef: Unknown result type (might be due to invalid IL or missing references) debugLevel = new DelegatedConfigEntry<Logging.LogLevels>(MaxAxe.LogChange); debugLevel.ConfigEntry = _instance.Config.Bind<Logging.LogLevels>("Utility", "LogLevel", Logging.LogLevels.Info, "Controls the level of information contained in the log. Set to 'Info' for normal use."); MaxAxe.Log.LogLevel = debugLevel.Value; useMelee = _instance.Config.Bind<bool>("General", "MeleeAttack", true, new ConfigDescription("When True, uses a melee secondary attack. Toggled in-game using the ToggleMeleeAttack key.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 30 } })); toggleMeleeKey = new DelegatedConfigEntry<KeyboardShortcut>(); toggleMeleeKey.ConfigEntry = _instance.Config.Bind<KeyboardShortcut>("General", "ToggleMeleeAttack", toggleMeleeKeyDefault, new ConfigDescription("Press this key to toggle in-game between Throw and Melee mode for enabled weapons.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 29 } })); throwOneKey = new DelegatedConfigEntry<KeyboardShortcut>(); throwOneKey.ConfigEntry = _instance.Config.Bind<KeyboardShortcut>("General", "ThrowOne", throwOneKeyDefault, new ConfigDescription("Press this key to throw the current weapon, regardless of Melee or Throw mode.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 28 } })); useKeyRelease = _instance.Config.Bind<bool>("General", "ThrowOnRelease", false, new ConfigDescription("Set to True to throw when the ThrowOne or ThrowShield keys are released instead of pressed.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 27 } })); throwShieldKey = new DelegatedConfigEntry<KeyboardShortcut>(); throwShieldKey.ConfigEntry = _instance.Config.Bind<KeyboardShortcut>("General", "ThrowShield", throwShieldKeyDefault, new ConfigDescription("Press this key to throw an equipped round shield.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 26 } })); throwUnderhand = new DelegatedConfigEntry<bool>(); throwUnderhand.ConfigEntry = _instance.Config.Bind<bool>("General", "UnderhandShield", false, new ConfigDescription("Set to True to throw your shield using an underhand throw. Shields must also be enabled.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 25 } })); enableAxes = new DelegatedConfigEntry<bool>(useServerDelegate: true); enableAxes.ConfigEntry = _instance.Config.Bind<bool>("General", "EnableAxes", true, new ConfigDescription("Set to True to enable secondary throwing attacks for one-handed axes.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 24 } })); enableClubs = new DelegatedConfigEntry<bool>(useServerDelegate: true); enableClubs.ConfigEntry = _instance.Config.Bind<bool>("General", "EnableClubs", true, new ConfigDescription("Set to True to enable secondary throwing attacks for blunt weapons & torches. Torches, stones, sledges & wooden clubs also get secondary melee attacks.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 23 } })); enableKnives = new DelegatedConfigEntry<bool>(useServerDelegate: true); enableKnives.ConfigEntry = _instance.Config.Bind<bool>("General", "EnableKnives", true, new ConfigDescription("Set to True to enable secondary throwing attacks for knives.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 22 } })); enablePolearms = new DelegatedConfigEntry<bool>(useServerDelegate: true); enablePolearms.ConfigEntry = _instance.Config.Bind<bool>("General", "EnablePolearms", true, new ConfigDescription("Set to True to enable secondary throwing attacks for polearms. AllowTwoHandedWeapons must also be true.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 21 } })); enableSpears = new DelegatedConfigEntry<bool>(useServerDelegate: true); enableSpears.ConfigEntry = _instance.Config.Bind<bool>("General", "EnableSpears", true, new ConfigDescription("Set to True to enable secondary melee attack for spears.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 20 } })); enableSwords = new DelegatedConfigEntry<bool>(useServerDelegate: true); enableSwords.ConfigEntry = _instance.Config.Bind<bool>("General", "EnableSwords", true, new ConfigDescription("Set to True to enable secondary throwing attacks for swords.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 19 } })); enablePickaxes = new DelegatedConfigEntry<bool>(useServerDelegate: true); enablePickaxes.ConfigEntry = _instance.Config.Bind<bool>("General", "EnablePickaxes", true, new ConfigDescription("Set to True to enable secondary throwing and melee attacks for pickaxes. AllowTwoHandedWeapons must also be true.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 18 } })); enableShields = new DelegatedConfigEntry<bool>(useServerDelegate: true); enableShields.ConfigEntry = _instance.Config.Bind<bool>("General", "EnableShields", true, new ConfigDescription("Set to True to enable throwing round shields, by using the ThrowShield key.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 17 } })); weaponStones = new DelegatedConfigEntry<bool>(MaxAxe.GroupsChange, useServerDelegate: true); weaponStones.ConfigEntry = _instance.Config.Bind<bool>("General", "WeaponStones", true, new ConfigDescription("Set to True to enable equipping and attacking with stones.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 16 } })); weaponWisps = new DelegatedConfigEntry<bool>(MaxAxe.GroupsChange, useServerDelegate: true); weaponWisps.ConfigEntry = _instance.Config.Bind<bool>("General", "WeaponWisps", true, new ConfigDescription("Set to True to enable equipping and attacking with Wisps.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 15 } })); weaponEitr = new DelegatedConfigEntry<bool>(MaxAxe.GroupsChange, useServerDelegate: true); weaponEitr.ConfigEntry = _instance.Config.Bind<bool>("General", "WeaponEitr", true, new ConfigDescription("Set to True to enable equipping and attacking with refined Eitr.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 14 } })); weaponEggs = new DelegatedConfigEntry<bool>(MaxAxe.GroupsChange, useServerDelegate: true); weaponEggs.ConfigEntry = _instance.Config.Bind<bool>("General", "WeaponEggs", true, new ConfigDescription("Set to True to enable equipping and attacking with Eggs.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 13 } })); weaponTankards = new DelegatedConfigEntry<bool>(MaxAxe.GroupsChange, useServerDelegate: true); weaponTankards.ConfigEntry = _instance.Config.Bind<bool>("General", "WeaponTankards", true, new ConfigDescription("Set to True to enable equipping and attacking with Tankards.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 12 } })); mjolnirMode = new DelegatedConfigEntry<bool>(useServerDelegate: true); mjolnirMode.ConfigEntry = _instance.Config.Bind<bool>("General", "MjolnirMode", false, new ConfigDescription("Set to True to enable Frostner returning to your hand after throwing.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 11 } })); allow2Handed = new DelegatedConfigEntry<bool>(useServerDelegate: true); allow2Handed.ConfigEntry = _instance.Config.Bind<bool>("General", "AllowTwoHandedWeapons", false, new ConfigDescription("Set to True to allow two-handed weapons to be thrown.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 10 } })); stackableWeapons = new DelegatedConfigEntry<bool>(MaxAxe.StackableChange, useServerDelegate: true); stackableWeapons.ConfigEntry = _instance.Config.Bind<bool>("General", "StackableWeapons", false, new ConfigDescription("Set to True to allow throwable weapons to stack. See documentation for details before enabling stackable weapons.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 9 } })); throwingStatus = _instance.Config.Bind<bool>("General", "ThrowingStatus", true, new ConfigDescription("Set to True to display a status effect if throwing is active.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 8 } })); useSkill = new DelegatedConfigEntry<bool>(MaxAxe.ToggleSkill, useServerDelegate: true); useSkill.ConfigEntry = _instance.Config.Bind<bool>("Skill", "UseThrowingSkill", false, new ConfigDescription("Set to True to enable the Throwing skill. Used in place of specific weapon skills to improve stats for all thrown items.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 7 } })); autoMelee = _instance.Config.Bind<bool>("General", "AutoMelee", false, new ConfigDescription("Set to True to automatically switch to melee mode after throwing a weapon, OR if last weapon in a stack (if StackableWeapons is True).", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 6 } })); autoEquip = _instance.Config.Bind<bool>("General", "AutoEquip", true, new ConfigDescription("Set to True to automatically equip another weapon after throwing a weapon.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 5 } })); autoEquipShields = _instance.Config.Bind<bool>("General", "AutoEquipShields", true, new ConfigDescription("Set to True to automatically equip shields after picking them up.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 4 } })); targetAdjustment = new DelegatedConfigEntry<int>(); targetAdjustment.ConfigEntry = _instance.Config.Bind<int>("General", "TargetAdjustment", -7, new ConfigDescription("Adjusts the throwing impact point in relation to the target reticle (the +). Set _instanced upon your 'typical' throwing distance. Default is -7.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-20, 20), new object[1] { new ConfigurationManagerAttributes { Order = 3 } })); gravity = new DelegatedConfigEntry<MaxAxe.Dynamics>(useServerDelegate: true); gravity.ConfigEntry = _instance.Config.Bind<MaxAxe.Dynamics>("Throwing Dynamics", "ThrowingMode", MaxAxe.Dynamics.Default, new ConfigDescription("Sets the type of weapon dynamics in flight. Better uses earth nominal gravity and applies inertia and drag to thrown weapons.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 2 } })); weaponFinder = _instance.Config.Bind<MaxAxe.Finders>("General", "WeaponFinder", MaxAxe.Finders.Wishbone, new ConfigDescription("Type of 'locator' effect added to thrown weapon to make it easier to find.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 1 } })); saveSlotForFrostner = _instance.Config.Bind<bool>("Utility", "SaveSpaceForFrostner", false, "Set to True to ensure autopickup doesn't use up the last inventory slot for a returning weapon. Only active if Mjolnir mode is also on."); itemAmountColor = _instance.Config.Bind<Color>("Utility", "ItemAmountColor", Color.yellow, "Color of item quantity text in hotbar and inventory."); forceSimpleTrail = _instance.Config.Bind<bool>("Utility", "ForceSimpleTrail", false, "Set to True for MaxAxe to use the 'simple' trail of earlier releases."); externalExclude = new DelegatedConfigEntry<string>(MaxAxe.ExcludeChange, useServerDelegate: true); externalExclude.ConfigEntry = _instance.Config.Bind<string>("Mod Compatibility", "ExcludePrefabs", "", "A comma delimited string of prefabs to exclude from being thrown. Example: PrefabNameA,PrefabNameB"); disableIncompatible = _instance.Config.Bind<bool>("Mod Compatibility", "DisableIncompatibleMods", true, "Automatically disable incompatible mods. Only those fully incompatible without a workaround will be disabled. See log file for warnings."); } } internal class ClubBuilder { public static SecondaryAttacks GetSecondaryAttacks(ItemData item) { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) SecondaryAttacks secondaryAttacks = new SecondaryAttacks(); AttackPrototype attackPrototype = Prototypes.GetAttackPrototype("SpearBronze"); AttackPrototype attackPrototype2 = Prototypes.GetAttackPrototype("MaceBronze"); Logging logger = Logging.GetLogger(); if (!string.IsNullOrEmpty(item.m_shared.m_secondaryAttack.m_attackAnimation)) { logger.Debug("Using club secondary melee attack"); secondaryAttacks.melee = item.m_shared.m_secondaryAttack.Clone(); } else { logger.Debug("Creating club secondary melee attack"); secondaryAttacks.melee = item.m_shared.m_attack.Clone(); Prototypes.ConfigAttackForWeapon(secondaryAttacks.melee, item, item.m_shared.m_attack, 2f, 2f, 2f, 2f, 2f); secondaryAttacks.melee.m_attackAnimation = attackPrototype2.secondaryAttack.m_attackAnimation; secondaryAttacks.melee.m_animEvent = attackPrototype2.secondaryAnimationEvent; secondaryAttacks.melee.m_attackType = attackPrototype2.secondaryAttack.m_attackType; secondaryAttacks.melee.m_attackAngle = attackPrototype2.secondaryAttack.m_attackAngle; } logger.Debug("Creating club secondary projectile attack"); secondaryAttacks.projectile = attackPrototype.secondaryAttack.Clone(); Prototypes.ConfigAttackForWeapon(secondaryAttacks.projectile, item, item.m_shared.m_secondaryAttack); secondaryAttacks.projectile.m_attackProjectile = null; return secondaryAttacks; } } public class DynamicProps { public float Vel { get; set; } public float Drag { get; set; } internal DynamicProps(float v, float d) { Vel = v; Drag = d; } } public class EffectGroup { public float scale { get; } public HashSet<string> effects { get; } public EffectGroup(float scale, HashSet<string> effects) { this.effects = effects; this.scale = scale; } } internal class EggBuilder { public static SecondaryAttacks GetSecondaryAttacks(ItemData item) { SecondaryAttacks secondaryAttacks = new SecondaryAttacks(); AttackPrototype attackPrototype = Prototypes.GetAttackPrototype("SpearBronze"); Logging logger = Logging.GetLogger(); secondaryAttacks.melee = null; logger.Debug("Creating egg secondary projectile attack"); secondaryAttacks.projectile = attackPrototype.secondaryAttack.Clone(); secondaryAttacks.projectile.m_attackStamina = 2f; secondaryAttacks.projectile.m_attackAnimation = attackPrototype.secondaryAttack.m_attackAnimation; secondaryAttacks.projectile.m_animEvent = attackPrototype.secondaryAnimationEvent; secondaryAttacks.projectile.m_attackProjectile = null; return secondaryAttacks; } } internal class Finder { private GameObject _finderEffect; private string PrefabName { get; } internal Vector3 Offset { get; } internal GameObject FinderEffect { get { if ((Object)(object)_finderEffect == (Object)null) { _finderEffect = Utils.GetPrefab(PrefabName); } return _finderEffect; } } internal Finder(string name, Vector3 offset) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) PrefabName = name; Offset = offset; } } internal class KnifeBuilder { public static SecondaryAttacks GetSecondaryAttacks(ItemData item) { SecondaryAttacks secondaryAttacks = new SecondaryAttacks(); AttackPrototype attackPrototype = Prototypes.GetAttackPrototype("SpearBronze"); Logging logger = Logging.GetLogger(); logger.Debug("Using knife secondary melee attack"); secondaryAttacks.melee = item.m_shared.m_secondaryAttack.Clone(); logger.Debug("Creating knife secondary projectile attack"); secondaryAttacks.projectile = attackPrototype.secondaryAttack.Clone(); Prototypes.ConfigAttackForWeapon(secondaryAttacks.projectile, item, item.m_shared.m_secondaryAttack); secondaryAttacks.projectile.m_attackProjectile = null; return secondaryAttacks; } } internal class MagicBuilder { public static SecondaryAttacks GetSecondaryAttacks(ItemData item) { SecondaryAttacks secondaryAttacks = new SecondaryAttacks(); AttackPrototype attackPrototype = Prototypes.GetAttackPrototype("SpearBronze"); Logging logger = Logging.GetLogger(); secondaryAttacks.melee = null; logger.Debug("Creating magic secondary projectile attack"); secondaryAttacks.projectile = attackPrototype.secondaryAttack.Clone(); secondaryAttacks.projectile.m_attackStamina = 3f; secondaryAttacks.projectile.m_attackAnimation = attackPrototype.secondaryAttack.m_attackAnimation; secondaryAttacks.projectile.m_animEvent = attackPrototype.secondaryAnimationEvent; secondaryAttacks.projectile.m_attackProjectile = null; return secondaryAttacks; } } [BepInPlugin("neobotics.valheim_mod.maxaxe", "MaxAxe", "0.4.6")] [BepInProcess("valheim.exe")] [BepInProcess("valheim_server.exe")] public class MaxAxe : BaseUnityPlugin { public enum Finders { Wishbone, Autopick, None } public enum Dynamics { Default, Better } [HarmonyPatch(typeof(Inventory), "HaveEmptySlot")] private static class Inventory_HaveEmptySlot_Patch { [HarmonyPostfix] private static void Inventory_HaveEmptySlot_Postfix(Inventory __instance, ref bool __result) { Player localPlayer = Player.m_localPlayer; if (__instance == ((Humanoid)(localPlayer?)).m_inventory && Cfg.mjolnirMode.Value && Cfg.saveSlotForFrostner.Value && ((Humanoid)localPlayer).GetCurrentWeapon() == ((Humanoid)localPlayer).m_unarmedWeapon.m_itemData && __instance.GetEmptySlots() <= 1) { Log.Debug("Saving space for returning weapons"); __result = false; } } } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(string), typeof(int), typeof(float), typeof(Vector2i), typeof(bool), typeof(int), typeof(int), typeof(long), typeof(string), typeof(Dictionary<string, string>), typeof(int), typeof(bool) })] private static class Inventory_AddItem_AddOnLoad_Patch { private static void Prefix(Inventory __instance, string name, int stack, float durability, Vector2i pos, bool equipped, int quality, int variant, long crafterID, string crafterName, Dictionary<string, string> customData) { Log.Trace($"AddItem_OnLoad prefix {name} stack {stack}"); if (stack > 1) { if (customData == null) { customData = new Dictionary<string, string>(); } customData.Add(Z_MAXAXE.ToString(), stack.ToString()); } } } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })] private static class Inventory_AddItem_AddNew_Patch { private static bool Prefix(Inventory __instance, ItemData item, string ___m_name, out bool __result) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) Log.Trace("InventoryAddItem_AddNew prefix " + __instance.GetName()); __result = true; if (item != null && !Cfg.stackableWeapons.Value && IsStackableWeapon(item) && item.m_stack > 1) { __result = false; int stack = item.m_stack; bool flag = false; for (int i = 0; i < stack; i++) { Vector2i val = __instance.FindEmptySlot(true); if (val.x >= 0) { flag = __instance.AddItem(item, 1, val.x, val.y); } if (!flag) { break; } } if (flag) { item.m_shared.m_maxStackSize = Math.Max(item.m_stack, 1); } return false; } return true; } } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData), typeof(int), typeof(int), typeof(int) })] private static class Inventory_AddItem_ToSlot_Patch { private static bool Prefix(Inventory __instance, ItemData item, ref int amount, int x, int y, string ___m_name) { Log.Trace("AddItem_ToSlot prefix " + __instance.GetName()); string key = Z_MAXAXE.ToString(); if (item != null && item.m_customData.TryGetValue(key, out var value)) { if (IsStackableWeapon(item)) { int num = (amount = (item.m_stack = int.Parse(value))); if (item.m_shared.m_maxStackSize < num) { item.m_shared.m_maxStackSize = num; } } item.m_customData.Remove(key); } if (item != null && Cfg.stackableWeapons.Value && stackables.ContainsKey(item.m_shared.m_name)) { ItemData itemAt = __instance.GetItemAt(x, y); if (itemAt == null) { if (Cfg.stackableWeapons.Value && stackables.ContainsKey(item.m_shared.m_name)) { item.m_shared.m_maxStackSize = stackables[item.m_shared.m_name]; } return true; } if (itemAt != null && item.m_durability <= 0f && itemAt.m_durability <= 0f) { return true; } if (itemAt != null && item.m_durability <= 0f) { return false; } if (itemAt != null && itemAt.m_durability <= 0f) { return false; } if (itemAt != null && item.m_durability > 0f && itemAt.m_durability > 0f) { itemAt.m_durability = Mathf.Min(item.m_durability, itemAt.m_durability); return true; } } return true; } } [HarmonyPatch(typeof(Inventory), "MoveItemToThis", new Type[] { typeof(Inventory), typeof(ItemData), typeof(int), typeof(int), typeof(int) })] private static class Inventory_MoveItemToThis_Slot_Patch { private static void Prefix(Inventory __instance, Inventory fromInventory, ItemData item, ref int amount, int x, int y, string ___m_name) { Log.Trace("MoveItemToThis_Slot to " + __instance.GetName() + " from " + fromInventory.GetName() + " item " + item?.m_shared.m_name); if (item != null && !Cfg.stackableWeapons.Value && IsStackableWeapon(item)) { amount = 1; } } } [HarmonyPatch(typeof(Inventory), "MoveItemToThis", new Type[] { typeof(Inventory), typeof(ItemData) })] private static class Inventory_MoveItemToThis_Patch { private static bool Prefix(Inventory __instance, Inventory fromInventory, ItemData item, string ___m_name) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) Log.Trace("MoveItemToThis to " + __instance.GetName() + " from " + ((fromInventory != null) ? fromInventory.GetName() : null) + " item " + item?.m_shared.m_name); if (item != null && !Cfg.stackableWeapons.Value && IsStackableWeapon(item) && item.m_stack > 1) { int stack = item.m_stack; bool flag = false; for (int i = 0; i < stack; i++) { Vector2i val = __instance.FindEmptySlot(true); if (val.x >= 0) { flag = __instance.MoveItemToThis(fromInventory, item, 1, val.x, val.y); } if (!flag) { break; } } if (flag) { item.m_shared.m_maxStackSize = Math.Max(item.m_stack, 1); } return false; } return true; } } [HarmonyPatch(typeof(VisEquipment), "AttachItem")] private static class VisEquipment_AttachItem_Patch { private static void Postfix(VisEquipment __instance, int itemHash, int variant, Transform joint, bool enableEquipEffects, GameObject __result) { if (shieldVariant != 0 && __instance.m_isPlayer) { ItemStyle componentInChildren = __result.GetComponentInChildren<ItemStyle>(); if (componentInChildren != null) { componentInChildren.Setup(shieldVariant); } shieldVariant = 0; } } } [HarmonyPatch(typeof(VisEquipment), "SetRightHandEquipped")] private static class VisEquipment_SetRightHandEquiped_Patch { [HarmonyAfter(new string[] { "blacks7ar.WeaponHolsterOverhaul" })] private static void Postfix(int hash, GameObject ___m_rightItemInstance, int ___m_currentRightItemHash, bool __result) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (TryGetActiveNonWeapon(hash, out var nonWeapon) && __result && (Object)(object)___m_rightItemInstance != (Object)null) { ___m_rightItemInstance.transform.localScale = nonWeapon.localScale; ___m_rightItemInstance.transform.localPosition = nonWeapon.rightHandOffset; MeshRenderer val = default(MeshRenderer); if (___m_rightItemInstance.TryGetComponent<MeshRenderer>(ref val)) { ((Renderer)val).enabled = true; } } } } [HarmonyPatch(typeof(VisEquipment), "SetLeftHandEquipped")] private static class VisEquipment_SetLeftHandEquiped_Patch { [HarmonyAfter(new string[] { "blacks7ar.WeaponHolsterOverhaul" })] private static void Postfix(int hash, GameObject ___m_leftItemInstance, bool __result) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (TryGetActiveNonWeapon(hash, out var nonWeapon) && __result && (Object)(object)___m_leftItemInstance != (Object)null) { ___m_leftItemInstance.transform.localScale = nonWeapon.localScale; ___m_leftItemInstance.transform.localPosition = nonWeapon.leftHandOffset; MeshRenderer val = default(MeshRenderer); if (___m_leftItemInstance.TryGetComponent<MeshRenderer>(ref val)) { ((Renderer)val).enabled = true; } } } } [HarmonyPatch(typeof(VisEquipment), "AttachBackItem")] private static class VisEquipment_AttachBackItem_Patch { [HarmonyAfter(new string[] { "blacks7ar.WeaponHolsterOverhaul" })] private static void Postfix(GameObject __result, int hash, int variant, bool rightHand) { Log.Debug("VisEquipment AttachBackItem postfix"); if (TryGetActiveNonWeapon(hash, out var _)) { Log.Debug("Attaching back item"); __result.SetActive(false); } } } [HarmonyPatch(typeof(SEMan), "GetHUDStatusEffects")] private static class Hud_GetHUDStatusEffects_Patch { private static void Prefix(List<StatusEffect> effects) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Invalid comparison between Unknown and I4 //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Invalid comparison between Unknown and I4 if (!Cfg.throwingStatus.Value || Cfg.useMelee.Value || ((Character)Player.m_localPlayer).InPlaceMode()) { return; } if ((Object)(object)throwingSE == (Object)null) { CreateThrowingStatusEffect(); } ItemData currentWeapon = ((Humanoid)Player.m_localPlayer).GetCurrentWeapon(); if (currentWeapon == null) { return; } if ((int)currentWeapon.m_shared.m_skillType == 11) { ((StatusEffect)throwingSE).m_icon = unarmedIcon; ((StatusEffect)throwingSE).m_flashIcon = false; } else { ((StatusEffect)throwingSE).m_icon = currentWeapon.GetIcon(); DelegatedConfigEntry<bool> dce; if (IsExcluded(currentWeapon) || ((int)currentWeapon.m_shared.m_itemType == 14 && !Cfg.allow2Handed.Value)) { ((StatusEffect)throwingSE).m_flashIcon = true; } else if (TryGetWeaponGroup(currentWeapon, out dce)) { ((StatusEffect)throwingSE).m_flashIcon = !dce.Value; } else if (IsActiveWeapon(currentWeapon)) { ((StatusEffect)throwingSE).m_flashIcon = false; } else { ((StatusEffect)throwingSE).m_flashIcon = true; } } effects.Add((StatusEffect)(object)throwingSE); } } [HarmonyPatch(typeof(Humanoid), "DrainEquipedItemDurability")] private static class Humanoid_DrainEquipedItemDurability_Patch { private static bool Prefix(Humanoid __instance, ItemData item, float dt) { //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) if (item != null && Cfg.stackableWeapons.Value && stackables.ContainsKey(item.m_shared.m_name) && item.m_stack > 1) { item.m_durability -= item.m_shared.m_durabilityDrain * dt; if (item.m_durability <= 0f && (Object)(object)item.m_lastProjectile == (Object)null) { Inventory inventory = __instance.m_inventory; ((Character)__instance).Message((MessageType)1, Localization.instance.Localize("$msg_broke", new string[1] { item.m_shared.m_name }), 0, item.GetIcon()); ItemData val = item.Clone(); val.m_equipped = false; Log.Debug("Removing broken item from stack"); inventory.RemoveItem(item, 1); item.m_durability = MaxLeveledDurability(item); Log.Debug("Set remaining stack durability to max"); if (!item.m_shared.m_destroyBroken) { List<ItemData> inventory2 = inventory.m_inventory; ItemData val2 = FindAvailableBrokenStack(inventory2, item); if (val2 != null) { val2.m_stack++; Log.Debug("Broken item added to existing stack"); } else if (inventory.HaveEmptySlot()) { Vector2i gridPos = inventory.FindEmptySlot(false); val.m_gridPos = gridPos; inventory2.Add(val); val.m_stack = 1; inventory.Changed(); Log.Debug("Broken item was added to new slot"); } else { wasDropped = true; __instance.DropItem(inventory, val, 1); Log.Debug("Broken item was dropped"); } } } return false; } return true; } } [HarmonyPatch(typeof(Humanoid), "StartAttack")] private static class Humanoid_StartAttack_Patch { [HarmonyPriority(700)] private static bool Prefix(Humanoid __instance, Character target, bool secondaryAttack, out StateResult __state, float ___m_timeSinceLastAttack, ref ItemData ___m_rightItem) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Invalid comparison between Unknown and I4 //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Invalid comparison between Unknown and I4 //IL_01a7: Unknown result type (might be due to invalid IL or missing references) __state = new StateResult(); Log.Trace("Humanoid_StartAttack_Patch prefix"); if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { Attack val = null; if (!((Character)__instance).InAttack() && secondaryAttack) { ItemData val2 = ___m_rightItem; if ((Object)(object)val2?.m_dropPrefab != (Object)null) { if ((Object)(object)returningWeapon != (Object)null) { return false; } if ((int)val2.m_shared.m_itemType == 5) { val2.m_shared.m_itemType = (ItemType)3; } if (Prototypes.IsConfigured(val2.m_shared.m_name) || IsThrowable(val2)) { Log.Debug("Humanoid StartAttack"); val = Prototypes.GetSecondaryAttack(val2, !IsThrow()); if (val == null || !((Object)(object)val2.m_dropPrefab != (Object)null)) { Log.Debug("Item does not have special attack"); return false; } Logging log = Log; GameObject dropPrefab = val2.m_dropPrefab; log.Debug("Attacking with prefab " + ((dropPrefab != null) ? ((Object)dropPrefab).name : null)); if ((int)val.m_attackType == 2 && ___m_timeSinceLastAttack < 0.3f) { Log.Trace("Aborting secondary spammed throwing attack"); return false; } if (((Object)val2.m_dropPrefab).name.StartsWith("Shield")) { ShieldBuilder.SetShieldThrowType(val, Cfg.throwUnderhand.Value); } if (((Object)val2.m_dropPrefab).name.Contains("Tankard")) { Log.Debug("Tankard secondary attack"); val2.m_shared.m_ammoType = null; tankardEffectList = val2.m_shared.m_startEffect; val2.m_shared.m_startEffect = emptyTankardEffectList; } val2.m_shared.m_secondaryAttack = val; Log.Debug($"Initiating {val.m_attackType} secondary attack"); if (EpicLootDetected()) { Log.Debug("Bypassing EpicLoot Humanoid StartAttack patch"); __state.Result = ReversePatches.HumanoidStartAttack.RunUnpatched(__instance, target, secondaryAttack); __state.UseState = true; } } else { Log.Debug("Using default secondary attack"); } } } } return true; } [HarmonyPriority(100)] private static void Postfix(Humanoid __instance, Character target, bool secondaryAttack, StateResult __state, ref bool __result, ref ItemData ___m_rightItem) { Log.Trace("Humanoid_StartAttack_Patch postfix"); if (__state.UseState) { __result = __state.Result; } } } [HarmonyPatch(typeof(Attack), "OnAttackTrigger")] private static class Attack_OnAttackTrigger_Patch { [HarmonyPrefix] private static void Attack_OnAttackTrigger_Prefix(Attack __instance, ItemData ___m_weapon, Humanoid ___m_character, out EffectData[] __state) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Invalid comparison between Unknown and I4 //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Invalid comparison between Unknown and I4 Log.Debug("Attack_OnAttackTrigger_Patch_Prefix"); __state = null; if ((Object)(object)___m_character == (Object)(object)Player.m_localPlayer && Cfg.allow2Handed.Value && (int)___m_weapon.m_shared.m_skillType == 3 && (int)___m_weapon.m_shared.m_itemType == 14 && __instance.m_attackAnimation != "swing_sledge") { __state = ___m_weapon.m_shared.m_triggerEffect.m_effectPrefabs.Clone() as EffectData[]; Log.Debug("Removing sledge AOE effects"); ___m_weapon.m_shared.m_triggerEffect.m_effectPrefabs = Prototypes.FilterEffectData(___m_weapon.m_shared.m_triggerEffect.m_effectPrefabs, sledgeAnimationExcludes); } } [HarmonyPostfix] private static void Attack_OnAttackTrigger_Postfix(Attack __instance, ItemData ___m_weapon, EffectData[] __state) { Log.Debug("Attack_OnAttackTrigger_Patch_Postfix"); if (__state != null) { Log.Debug("Replacing sledge AOE effects"); ___m_weapon.m_shared.m_triggerEffect.m_effectPrefabs = __state; } } } [HarmonyPatch(typeof(Attack), "ProjectileAttackTriggered")] [HarmonyPriority(700)] private static class Attack_ProjectileAttackTriggered_Patch { private static void Prefix(Attack __instance, ItemData ___m_weapon, Humanoid ___m_character) { Log.Trace("Attack_ProjectileAttackTriggered_Patch prefix"); if ((Object)(object)___m_character == (Object)(object)Player.m_localPlayer && ___m_weapon != null && Prototypes.IsConfigured(___m_weapon.m_shared.m_name) && IsThrow() && (Object)(object)__instance.m_attackProjectile == (Object)null && (Object)(object)___m_weapon?.m_dropPrefab != (Object)null) { __instance.m_attackProjectile = Prototypes.GetProjectileizedPrefab(___m_weapon, TryGetActiveNonWeapon(((Object)___m_weapon.m_dropPrefab).name, out var _)); } } } [HarmonyPatch(typeof(Attack), "FireProjectileBurst")] private static class Attack_FireProjectileBurst_Patch { [HarmonyPriority(100)] private static bool Prefix(Attack __instance, Character ___m_character, ItemData ___m_weapon, ref bool __state) { //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) Log.Trace("Attack_FireProjectileBurst_Patch prefix"); __state = false; if ((Object)(object)___m_character == (Object)(object)Player.m_localPlayer && ___m_weapon != null && Prototypes.IsConfigured(___m_weapon.m_shared.m_name) && IsThrow()) { Log.Debug("Attack_FireProjectileBurst"); if (!((Object)(object)__instance.m_attackProjectile != (Object)null) || !((Object)(object)__instance.m_attackProjectile.GetComponent<Projectile>() != (Object)null)) { Log.Warning("Projectile is missing or invalid"); __state = false; return false; } __state = true; returnSpeed = __instance.m_projectileVel; __instance.m_launchAngle = Cfg.targetAdjustment.Value; if (Cfg.gravity.Value == Dynamics.Better) { __instance.m_projectileVel = 28f; __instance.m_projectileVel -= ___m_weapon.m_shared.m_weight; __instance.m_launchAngle -= 5f * GetDragFactor(___m_weapon); } else { __instance.m_projectileVel = 20f; } if (Cfg.useSkill.Value) { Log.Debug("Using throwing skill"); throwingSkill = null; throwingSkill = new ThrowingSkillHelper(___m_character.GetSkillLevel(CustomSkill.GetCustomSkillType()), ___m_weapon.m_shared.m_skillType); __instance.m_skillAccuracy = true; __instance.m_projectileAccuracy = 0f; __instance.m_projectileAccuracyMin = 2f + (float)rand.NextDouble(); float num = Mathf.Lerp(0f, 3f, throwingSkill.ThrowingFactor); __instance.m_projectileVel += num; } else { __instance.m_skillAccuracy = false; } if (Log.LogLevel >= Logging.LogLevels.Trace) { Logging log = Log; object obj; if (__instance == null) { obj = null; } else { GameObject attackProjectile = __instance.m_attackProjectile; obj = ((attackProjectile != null) ? ((Object)attackProjectile).name : null); } log.Trace("Projectile m_attackProjectile " + (string?)obj + " is configured"); } if (EpicLootDetected()) { Log.Debug("Skipping other Attack FireProjectileBurst patches"); ReversePatches.FireProjectile_Burst.RunUnpatched(__instance); return false; } } return true; } [HarmonyPriority(700)] private static void Postfix(Attack __instance, Character ___m_character, ItemData ___m_weapon, ref bool __state) { Log.Trace("Attack_FireProjectileBurst_Patch postfix"); if (__state && ___m_weapon != null && IsThrow()) { ActivateProjectile(___m_weapon.m_lastProjectile.gameObject); } } } [HarmonyPatch(typeof(Projectile), "Setup")] private static class Projectile_Setup_Patch { private static void Postfix(Projectile __instance, Character owner, Vector3 velocity, float hitNoise, HitData hitData, ItemData item, ZNetView ___m_nview) { //IL_004e: 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_0094: Invalid comparison between Unknown and I4 //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Invalid comparison between Unknown and I4 //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) Log.Trace("Projectile_Setup_Patch postfix"); if (!((Object)(object)owner == (Object)(object)Player.m_localPlayer) || item == null) { return; } GameObject gameObject = ((Component)__instance).gameObject; if (TryGetActiveNonWeapon(item, out var nonWeapon)) { Log.Debug("Setting local scale for non-item types"); gameObject.transform.localScale = nonWeapon.localScale; } if (!Prototypes.IsConfigured(item.m_shared.m_name) || !IsThrow()) { return; } Log.Debug("Projectile Setup postfix"); if ((int)item.m_shared.m_skillType == 6) { Log.Debug("Set Shield orientation"); Transform transform = ((Component)__instance).transform; transform.rotation *= Quaternion.Euler(new Vector3(0f, 0f, Cfg.throwUnderhand.Value ? (-70f) : 15f)); __instance.m_rotateVisual = -720f; } if ((int)item.m_shared.m_itemType == 15) { Transform val = gameObject.transform.Find("attach").Find("equiped"); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(true); } } } } [HarmonyPatch(typeof(Skills), "GetSkillLevel")] private static class Skills_GetSkillLevel_Patch { [HarmonyPostfix] private static void Skills_GetSkillLevel_Postfix(Skills __instance, SkillType skillType, ref float __result, Player ___m_player) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)___m_player != (Object)(object)Player.m_localPlayer) && Cfg.useSkill.Value && throwingSkill != null && throwingSkill.CurrentAttackSkill == skillType && !(throwingSkill.ThrowingLevel <= 0f)) { __result = (__result + throwingSkill.ThrowingLevel * 2f) / 3f; } } } [HarmonyPatch(typeof(SEMan), "ModifyAttack")] private static class SEMan_ModifyAttack_Patch { private static void Postfix(SEMan __instance, ref SkillType skill, ref HitData hitData, Character ___m_character) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected I4, but got Unknown //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Invalid comparison between Unknown and I4 //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Invalid comparison between Unknown and I4 //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Invalid comparison between Unknown and I4 //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Invalid comparison between Unknown and I4 //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Invalid comparison between Unknown and I4 Log.Trace("SEMan_ModifyAttack_Patch_Postfix"); if (!((Object)(object)___m_character == (Object)(object)Player.m_localPlayer)) { return; } Character character = __instance.m_character; Character obj = ((character is Player) ? character : null); bool currentAttackIsSecondary = ((Humanoid)obj).m_currentAttackIsSecondary; Attack currentAttack = ((Humanoid)obj).m_currentAttack; ItemData val = ((currentAttack != null) ? currentAttack.GetWeapon() : null); if (!(currentAttack != null && val != null && currentAttackIsSecondary)) { return; }