Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of OreSpreadQoL v1.0.2
OreSpreadQoL.dll
Decompiled 12 hours agousing System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ConditionalConfigSync; using HarmonyLib; using UnityEngine; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.0.0.0")] namespace OreSpreadQoL; [BepInPlugin("community.valheim.OreSpreadQoL", "Ore Spread QoL", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "community.valheim.OreSpreadQoL"; public const string PluginName = "Ore Spread QoL"; public const string PluginVersion = "1.0.0"; internal static ConfigSync Sync; internal static ConfigEntry<KeyboardShortcut> BypassKey; internal static ConfigEntry<bool> DebugLogging; internal static SyncedConfigEntry<bool> EnableLevelMode; internal static SyncedConfigEntry<float> MinDistance; internal static SyncedConfigEntry<bool> CopperEnabled; internal static SyncedConfigEntry<float> CopperMaxDistance; internal static SyncedConfigEntry<bool> IronEnabled; internal static SyncedConfigEntry<float> IronMaxDistance; internal static SyncedConfigEntry<bool> SilverEnabled; internal static SyncedConfigEntry<float> SilverMaxDistance; internal static SyncedConfigEntry<bool> SoftTissueEnabled; internal static SyncedConfigEntry<float> SoftTissueMaxDistance; internal static SyncedConfigEntry<bool> BlackMarbleEnabled; internal static SyncedConfigEntry<float> BlackMarbleMaxDistance; internal static SyncedConfigEntry<bool> StoneEnabled; internal static SyncedConfigEntry<float> StoneMaxDistance; internal static SyncedConfigEntry<bool> FlametalEnabled; internal static SyncedConfigEntry<float> FlametalMaxDistance; internal static SyncedConfigEntry<bool> OtherEnabled; internal static SyncedConfigEntry<float> OtherMaxDistance; private Harmony _harmony; private void Awake() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Expected O, but got Unknown ConfigSync val = new ConfigSync("community.valheim.OreSpreadQoL"); ((ConditionalConfigSync)val).DisplayName = "Ore Spread QoL"; ((ConditionalConfigSync)val).CurrentVersion = "1.0.0"; ((ConditionalConfigSync)val).MinimumRequiredVersion = "1.0.0"; ((ConditionalConfigSync)val).ModRequired = true; Sync = val; BypassKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "BypassKey", new KeyboardShortcut((KeyCode)308, (KeyCode[])(object)new KeyCode[0]), "Hold this key while mining to use vanilla mining for that swing. This is client-local and is not synced."); DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLogging", false, "Enable debug diagnostics in BepInEx\\LogOutput.log. Client-local and not synced. Leave this off for normal play."); EnableLevelMode = ServerBool("General", "EnableLevelMode", defaultValue: true, "Scale spread radius with Pickaxes skill, like PickaxeMaster. At skill 0 use MinDistance; at skill 100 use the resource MaxDistance."); MinDistance = ServerFloat("General", "MinDistance", 1f, 0f, 50f, "Minimum spread radius at Pickaxes skill 0 when EnableLevelMode is enabled."); CopperEnabled = ServerBool("Copper", "Enabled", defaultValue: true, "Enable damage spreading for segmented copper deposits."); CopperMaxDistance = ServerFloat("Copper", "MaxDistance", 15f, 0f, 50f, "Copper spread radius at Pickaxes skill 100, or fixed radius when Level Mode is disabled."); IronEnabled = ServerBool("Iron", "Enabled", defaultValue: true, "Enable damage spreading for muddy scrap piles."); IronMaxDistance = ServerFloat("Iron", "MaxDistance", 1.5f, 0f, 50f, "Muddy scrap pile spread radius at Pickaxes skill 100, or fixed radius when Level Mode is disabled."); SilverEnabled = ServerBool("Silver", "Enabled", defaultValue: true, "Enable damage spreading for segmented silver veins."); SilverMaxDistance = ServerFloat("Silver", "MaxDistance", 4f, 0f, 50f, "Silver spread radius at Pickaxes skill 100, or fixed radius when Level Mode is disabled."); SoftTissueEnabled = ServerBool("Soft Tissue", "Enabled", defaultValue: true, "Enable damage spreading for giant-brain soft tissue mining."); SoftTissueMaxDistance = ServerFloat("Soft Tissue", "MaxDistance", 3.5f, 0f, 50f, "Soft tissue spread radius at Pickaxes skill 100, or fixed radius when Level Mode is disabled."); BlackMarbleEnabled = ServerBool("Black Marble", "Enabled", defaultValue: true, "Enable damage spreading for petrified giant bone / black marble mining."); BlackMarbleMaxDistance = ServerFloat("Black Marble", "MaxDistance", 2.5f, 0f, 50f, "Black marble spread radius at Pickaxes skill 100, or fixed radius when Level Mode is disabled."); StoneEnabled = ServerBool("Stone", "Enabled", defaultValue: true, "Enable damage spreading for ordinary segmented rocks."); StoneMaxDistance = ServerFloat("Stone", "MaxDistance", 15f, 0f, 50f, "Large segmented stone-deposit spread radius at Pickaxes skill 100, or fixed radius when Level Mode is disabled. Small non-segmented rocks remain vanilla."); FlametalEnabled = ServerBool("Flametal", "Enabled", defaultValue: true, "Enable damage spreading for current Flametal ore veins (LeviathanLava / MineRock)."); FlametalMaxDistance = ServerFloat("Flametal", "MaxDistance", 2f, 0f, 50f, "Current Flametal ore-vein spread radius at Pickaxes skill 100, or fixed radius when Level Mode is disabled."); OtherEnabled = ServerBool("Other", "Enabled", defaultValue: true, "Enable damage spreading for other segmented MineRock5 resources."); OtherMaxDistance = ServerFloat("Other", "MaxDistance", 1.5f, 0f, 50f, "Fallback spread radius at Pickaxes skill 100, or fixed radius when Level Mode is disabled."); _harmony = new Harmony("community.valheim.OreSpreadQoL"); _harmony.PatchAll(); } private SyncedConfigEntry<bool> ServerBool(string section, string name, bool defaultValue, string description) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown return ((ConditionalConfigSync)Sync).AddConfigEntry<bool>(((BaseUnityPlugin)this).Config, section, name, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, new object[0]), (ConfigSyncMode)0, true); } private SyncedConfigEntry<float> ServerFloat(string section, string name, float defaultValue, float min, float max, string description) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown return ((ConditionalConfigSync)Sync).AddConfigEntry<float>(((BaseUnityPlugin)this).Config, section, name, defaultValue, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), new object[0]), (ConfigSyncMode)0, true); } private void OnDestroy() { if (_harmony != null) { _harmony.UnpatchSelf(); } } } [HarmonyPatch(typeof(MineRock5), "Damage")] internal static class MineRock5DamagePatch { private static readonly FieldInfo NViewField = AccessTools.Field(typeof(MineRock5), "m_nview"); private static bool _redistributing; private static int _debugHits; private static bool Prefix(MineRock5 __instance, HitData hit) { //IL_0028: 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) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected O, but got Unknown //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || hit == null || _redistributing) { return true; } if (Plugin.BypassKey != null) { KeyboardShortcut value = Plugin.BypassKey.Value; if (((KeyboardShortcut)(ref value)).IsPressed()) { return true; } } Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if ((Object)(object)val == (Object)null) { val = TryResolvePlayerFromAttackerId(hit); } float effectiveRadius = GetEffectiveRadius(__instance, val); if (effectiveRadius <= 0f || hit.m_damage.m_pickaxe <= 0f) { return true; } Collider[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<Collider>(); if (componentsInChildren == null || componentsInChildren.Length == 0) { return true; } float radiusSq = effectiveRadius * effectiveRadius; Vector3 hitPoint = hit.m_point; List<Collider> list = componentsInChildren.Where(delegate(Collider c) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)c != (Object)null) { Vector3 val4 = hitPoint; Bounds bounds2 = c.bounds; Vector3 val5 = val4 - ((Bounds)(ref bounds2)).center; return ((Vector3)(ref val5)).sqrMagnitude <= radiusSq; } return false; }).ToList(); DebugHit(__instance, val, effectiveRadius, componentsInChildren.Length, list.Count, hit); if (list.Count <= 1) { return true; } float pickaxe = hit.m_damage.m_pickaxe / (float)list.Count; _redistributing = true; try { foreach (Collider item in list) { HitData val2 = new HitData(); val2.m_damage = new DamageTypes { m_pickaxe = pickaxe }; Bounds bounds = item.bounds; val2.m_point = ((Bounds)(ref bounds)).center; val2.m_hitCollider = item; val2.m_dir = hit.m_dir; val2.m_attacker = hit.m_attacker; val2.m_pushForce = hit.m_pushForce; val2.m_toolTier = hit.m_toolTier; HitData val3 = val2; MineRock5 componentInParent = ((Component)item).GetComponentInParent<MineRock5>(); if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent != (Object)(object)__instance) { componentInParent.Damage(val3); } else { __instance.Damage(val3); } } } finally { _redistributing = false; } return false; } private static float GetEffectiveRadius(MineRock5 rock, Player player) { GetResourceSettings(rock, out var enabled, out var maxDistance); if (!enabled || maxDistance <= 0f) { return 0f; } if (Plugin.EnableLevelMode == null || !Plugin.EnableLevelMode.Value) { return maxDistance; } float num = ((Plugin.MinDistance != null) ? Plugin.MinDistance.Value : 1f); num = Mathf.Clamp(num, 0f, maxDistance); float num2 = (((Object)(object)player != (Object)null) ? Mathf.Clamp01(((Character)player).GetSkillFactor((SkillType)12)) : 0f); return Mathf.Lerp(num, maxDistance, num2); } private static Player TryResolvePlayerFromAttackerId(HitData hit) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) try { Type type = AccessTools.TypeByName("ZNetScene"); if (type == null) { return null; } PropertyInfo propertyInfo = AccessTools.Property(type, "instance"); object obj = ((propertyInfo != null) ? propertyInfo.GetValue(null, null) : null); if (obj == null) { return null; } MethodInfo methodInfo = AccessTools.Method(type, "FindInstance", (Type[])null, (Type[])null); if (methodInfo == null) { return null; } object obj2 = methodInfo.Invoke(obj, new object[1] { hit.m_attacker }); Component val = (Component)((obj2 is Component) ? obj2 : null); if ((Object)(object)val != (Object)null) { return val.GetComponent<Player>(); } GameObject val2 = (GameObject)((obj2 is GameObject) ? obj2 : null); return ((Object)(object)val2 != (Object)null) ? val2.GetComponent<Player>() : null; } catch { return null; } } private static void DebugHit(MineRock5 rock, Player player, float radius, int totalColliders, int affectedColliders, HitData hit) { if (Plugin.DebugLogging != null && Plugin.DebugLogging.Value && _debugHits < 12) { _debugHits++; string text = (((Object)(object)rock != (Object)null && (Object)(object)((Component)rock).gameObject != (Object)null) ? ((Object)((Component)rock).gameObject).name : "<null>"); string text2 = (((Object)(object)rock != (Object)null) ? rock.m_name : "<null>"); string hierarchyIdentity = GetHierarchyIdentity(rock); string networkPrefabIdentity = GetNetworkPrefabIdentity(rock); string materialIdentity = GetMaterialIdentity(rock); string dropIdentity = GetDropIdentity(rock); GetDropStats(rock, out var dropMin, out var dropMax, out var dropChance, out var dropCount); Logger.CreateLogSource("Ore Spread QoL").LogInfo((object)("Mining debug #" + _debugHits + ": object='" + text + "' m_name='" + text2 + "' hierarchy='" + hierarchyIdentity + "' prefab='" + networkPrefabIdentity + "' materials='" + materialIdentity + "' drops='" + dropIdentity + "' health=" + (((Object)(object)rock != (Object)null) ? rock.m_health.ToString("0.##") : "?") + " minTier=" + (((Object)(object)rock != (Object)null) ? rock.m_minToolTier.ToString() : "?") + " dropChance=" + dropChance.ToString("0.###") + " dropMin=" + dropMin + " dropMax=" + dropMax + " dropCount=" + dropCount + " radius=" + radius.ToString("0.00") + " totalColliders=" + totalColliders + " affected=" + affectedColliders + " attackerPlayer=" + (((Object)(object)player != (Object)null) ? "yes" : "no") + " pickaxeDamage=" + hit.m_damage.m_pickaxe.ToString("0.00"))); } } private static void GetResourceSettings(MineRock5 rock, out bool enabled, out float maxDistance) { string text = (((Object)(object)rock != (Object)null) ? (rock.m_name ?? string.Empty) : string.Empty); string text2 = (((Object)(object)rock != (Object)null && (Object)(object)((Component)rock).gameObject != (Object)null) ? (((Object)((Component)rock).gameObject).name ?? string.Empty) : string.Empty); string hierarchyIdentity = GetHierarchyIdentity(rock); string networkPrefabIdentity = GetNetworkPrefabIdentity(rock); string materialIdentity = GetMaterialIdentity(rock); string dropIdentity = GetDropIdentity(rock); GetDropStats(rock, out var dropMin, out var dropMax, out var dropChance, out var _); int num = (((Object)(object)rock != (Object)null) ? rock.m_minToolTier : (-999)); string value = networkPrefabIdentity + " " + text + " " + text2 + " " + hierarchyIdentity + " " + materialIdentity + " " + dropIdentity; if (Contains(materialIdentity, "rock_copper_internal") || Contains(materialIdentity, "rock1_copper") || Contains(dropIdentity, "copperore") || Contains(value, "rock4_copper") || Contains(value, "copper deposit")) { enabled = Plugin.CopperEnabled.Value; maxDistance = Plugin.CopperMaxDistance.Value; } else if (Contains(materialIdentity, "mudpile_ironscrap") || Contains(materialIdentity, "mudpile") || Contains(dropIdentity, "ironscrap") || Contains(value, "mudpile") || Contains(value, "mud pile")) { enabled = Plugin.IronEnabled.Value; maxDistance = Plugin.IronMaxDistance.Value; } else if (Contains(materialIdentity, "rock_silver_internal") || Contains(dropIdentity, "silverore") || Contains(value, "silver")) { enabled = Plugin.SilverEnabled.Value; maxDistance = Plugin.SilverMaxDistance.Value; } else if (Contains(materialIdentity, "giant_brain") || Contains(dropIdentity, "softtissue") || Contains(value, "softtissue") || Contains(value, "soft_tissue") || Contains(value, "giant_brain") || Contains(value, "giantbrain")) { enabled = Plugin.SoftTissueEnabled.Value; maxDistance = Plugin.SoftTissueMaxDistance.Value; } else if (Contains(materialIdentity, "giant_skeleton_exterior") || Contains(materialIdentity, "giant_skeleton_interior") || Contains(dropIdentity, "blackmarble") || Contains(value, "blackmarble") || Contains(value, "black_marble") || Contains(value, "giant_ribs") || Contains(value, "giant_skull") || Contains(value, "giant_bone") || Contains(value, "giantbone")) { enabled = Plugin.BlackMarbleEnabled.Value; maxDistance = Plugin.BlackMarbleMaxDistance.Value; } else if (Contains(dropIdentity, "flametal") || Contains(value, "flametal")) { enabled = Plugin.FlametalEnabled.Value; maxDistance = Plugin.FlametalMaxDistance.Value; } else if (num == 0 && Nearly(dropChance, 1f) && dropMin == 2 && dropMax == 4) { enabled = Plugin.CopperEnabled.Value; maxDistance = Plugin.CopperMaxDistance.Value; } else if (num == 0 && dropChance > 0f && dropChance <= 0.35f && dropMin == 1 && dropMax == 1) { enabled = Plugin.IronEnabled.Value; maxDistance = Plugin.IronMaxDistance.Value; } else if (num == 2 && Nearly(dropChance, 1f) && dropMin == 2 && dropMax == 3) { enabled = Plugin.SilverEnabled.Value; maxDistance = Plugin.SilverMaxDistance.Value; } else if (num >= 3 && Nearly(dropChance, 0.5f) && dropMin == 1 && dropMax == 1) { enabled = Plugin.SoftTissueEnabled.Value; maxDistance = Plugin.SoftTissueMaxDistance.Value; } else if (num >= 3 && Nearly(dropChance, 1f) && dropMin == 2 && dropMax == 4) { enabled = Plugin.BlackMarbleEnabled.Value; maxDistance = Plugin.BlackMarbleMaxDistance.Value; } else if (num >= 3 && Nearly(dropChance, 1f) && dropMin == 4 && dropMax == 8) { enabled = Plugin.FlametalEnabled.Value; maxDistance = Plugin.FlametalMaxDistance.Value; } else if (Contains(materialIdentity, "rock_internal") || Contains(dropIdentity, "stone") || Contains(value, "rock") || (num < 3 && Nearly(dropChance, 1f) && dropMin == 4 && dropMax == 8)) { enabled = Plugin.StoneEnabled.Value; maxDistance = Plugin.StoneMaxDistance.Value; } else { enabled = Plugin.OtherEnabled.Value; maxDistance = Plugin.OtherMaxDistance.Value; } } private static string GetNetworkPrefabIdentity(MineRock5 rock) { if ((Object)(object)rock == (Object)null || NViewField == null) { return string.Empty; } try { object value = NViewField.GetValue(rock); if (value == null) { return string.Empty; } MethodInfo methodInfo = AccessTools.Method(value.GetType(), "GetPrefabName", (Type[])null, (Type[])null); if (methodInfo == null) { return string.Empty; } object obj = methodInfo.Invoke(value, null); return (obj as string) ?? string.Empty; } catch { return string.Empty; } } private static string GetHierarchyIdentity(MineRock5 rock) { if ((Object)(object)rock == (Object)null || (Object)(object)((Component)rock).transform == (Object)null) { return string.Empty; } try { List<string> list = new List<string>(); Transform val = ((Component)rock).transform; int num = 0; while ((Object)(object)val != (Object)null && num++ < 12) { if (!string.IsNullOrEmpty(((Object)val).name)) { list.Add(((Object)val).name); } val = val.parent; } return string.Join("/", list.ToArray()); } catch { return string.Empty; } } private static string GetMaterialIdentity(MineRock5 rock) { if ((Object)(object)rock == (Object)null) { return string.Empty; } try { FieldInfo fieldInfo = AccessTools.Field(typeof(MineRock5), "m_meshRenderer"); Renderer val = (Renderer)((fieldInfo != null) ? /*isinst with value type is only supported in some contexts*/: null); List<string> list = new List<string>(); if ((Object)(object)val != (Object)null) { Material[] sharedMaterials = val.sharedMaterials; if (sharedMaterials != null) { Material[] array = sharedMaterials; foreach (Material val2 in array) { if ((Object)(object)val2 != (Object)null && !string.IsNullOrEmpty(((Object)val2).name)) { list.Add(((Object)val2).name); } } } } Renderer[] componentsInChildren = ((Component)rock).GetComponentsInChildren<Renderer>(); if (componentsInChildren != null) { Renderer[] array2 = componentsInChildren; foreach (Renderer val3 in array2) { if ((Object)(object)val3 == (Object)null) { continue; } Material[] sharedMaterials2 = val3.sharedMaterials; if (sharedMaterials2 == null) { continue; } Material[] array3 = sharedMaterials2; foreach (Material val4 in array3) { if ((Object)(object)val4 != (Object)null && !string.IsNullOrEmpty(((Object)val4).name) && !list.Contains(((Object)val4).name)) { list.Add(((Object)val4).name); } } } } return string.Join(",", list.ToArray()); } catch { return string.Empty; } } private static string GetDropIdentity(MineRock5 rock) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rock == (Object)null) { return string.Empty; } try { DropTable dropItems = rock.m_dropItems; if (dropItems == null || dropItems.m_drops == null) { return string.Empty; } List<string> list = new List<string>(); foreach (DropData drop in dropItems.m_drops) { if ((Object)(object)drop.m_item != (Object)null && !string.IsNullOrEmpty(((Object)drop.m_item).name)) { list.Add(((Object)drop.m_item).name); } } return string.Join(",", list.ToArray()); } catch { return string.Empty; } } private static void GetDropStats(MineRock5 rock, out int dropMin, out int dropMax, out float dropChance, out int dropCount) { dropMin = -1; dropMax = -1; dropChance = -1f; dropCount = 0; if ((Object)(object)rock == (Object)null || rock.m_dropItems == null) { return; } try { DropTable dropItems = rock.m_dropItems; dropMin = dropItems.m_dropMin; dropMax = dropItems.m_dropMax; dropChance = dropItems.m_dropChance; dropCount = ((dropItems.m_drops != null) ? dropItems.m_drops.Count : 0); } catch { } } private static bool Nearly(float a, float b) { return Mathf.Abs(a - b) <= 0.011f; } private static bool Contains(string value, string fragment) { if (!string.IsNullOrEmpty(value)) { return value.IndexOf(fragment, StringComparison.OrdinalIgnoreCase) >= 0; } return false; } } [HarmonyPatch(typeof(MineRock), "Damage")] internal static class MineRockFlametalDamagePatch { private static readonly FieldInfo NViewField = AccessTools.Field(typeof(MineRock), "m_nview"); private static readonly FieldInfo HitAreasField = AccessTools.Field(typeof(MineRock), "m_hitAreas"); private static readonly MethodInfo GetAreaIndexMethod = AccessTools.Method(typeof(MineRock), "GetAreaIndex", new Type[1] { typeof(Collider) }, (Type[])null); private static bool _redistributing; private static int _debugHits; private static bool Prefix(MineRock __instance, HitData hit) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Expected O, but got Unknown //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || hit == null || _redistributing) { return true; } if (Plugin.BypassKey != null) { KeyboardShortcut value = Plugin.BypassKey.Value; if (((KeyboardShortcut)(ref value)).IsPressed()) { return true; } } if (!IsModernFlametal(__instance)) { return true; } if (Plugin.FlametalEnabled == null || !Plugin.FlametalEnabled.Value) { return true; } Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if ((Object)(object)val == (Object)null) { val = TryResolvePlayerFromAttackerId(hit); } float effectiveRadius = GetEffectiveRadius(val); if (effectiveRadius <= 0f || hit.m_damage.m_pickaxe <= 0f) { return true; } Collider[] array = ((HitAreasField != null) ? (HitAreasField.GetValue(__instance) as Collider[]) : null); if (array == null || array.Length == 0) { return true; } float num = effectiveRadius * effectiveRadius; Vector3 point = hit.m_point; int num2 = -1; try { if ((Object)(object)hit.m_hitCollider != (Object)null && GetAreaIndexMethod != null) { object obj = GetAreaIndexMethod.Invoke(__instance, new object[1] { hit.m_hitCollider }); if (obj is int) { num2 = (int)obj; } } } catch { num2 = -1; } if (num2 < 0 || num2 >= array.Length) { DebugHit(__instance, val, effectiveRadius, array.Length, 0, num2, -1f, hit); return true; } Dictionary<int, Collider> dictionary = new Dictionary<int, Collider>(); float num3 = float.MaxValue; for (int i = 0; i < array.Length; i++) { Collider val2 = array[i]; if (!((Object)(object)val2 == (Object)null) && val2.enabled && !((Object)(object)((Component)val2).gameObject == (Object)null) && ((Component)val2).gameObject.activeInHierarchy) { Bounds bounds = val2.bounds; float num4 = ((Bounds)(ref bounds)).SqrDistance(point); if (num4 < num3) { num3 = num4; } if (!(num4 > num) || i == num2) { dictionary[i] = val2; } } } if (!dictionary.ContainsKey(num2) && (Object)(object)array[num2] != (Object)null) { dictionary[num2] = array[num2]; } float nearestBoundsDistance = ((num3 < float.MaxValue) ? Mathf.Sqrt(num3) : (-1f)); DebugHit(__instance, val, effectiveRadius, array.Length, dictionary.Count, num2, nearestBoundsDistance, hit); if (dictionary.Count <= 1) { return true; } float pickaxe = hit.m_damage.m_pickaxe / (float)dictionary.Count; _redistributing = true; try { foreach (Collider value2 in dictionary.Values) { HitData val3 = new HitData(); val3.m_damage = new DamageTypes { m_pickaxe = pickaxe }; Bounds bounds2 = value2.bounds; val3.m_point = ((Bounds)(ref bounds2)).center; val3.m_hitCollider = value2; val3.m_radius = 0f; val3.m_dir = hit.m_dir; val3.m_attacker = hit.m_attacker; val3.m_pushForce = hit.m_pushForce; val3.m_toolTier = hit.m_toolTier; val3.m_hitType = hit.m_hitType; HitData val4 = val3; __instance.Damage(val4); } } finally { _redistributing = false; } return false; } private static float GetEffectiveRadius(Player player) { float num = ((Plugin.FlametalMaxDistance != null) ? Plugin.FlametalMaxDistance.Value : 2f); if (num <= 0f) { return 0f; } if (Plugin.EnableLevelMode == null || !Plugin.EnableLevelMode.Value) { return num; } float num2 = ((Plugin.MinDistance != null) ? Plugin.MinDistance.Value : 1f); num2 = Mathf.Clamp(num2, 0f, num); float num3 = (((Object)(object)player != (Object)null) ? Mathf.Clamp01(((Character)player).GetSkillFactor((SkillType)12)) : 0f); return Mathf.Lerp(num2, num, num3); } private static bool IsModernFlametal(MineRock rock) { if ((Object)(object)rock == (Object)null) { return false; } string text = rock.m_name ?? string.Empty; string text2 = (((Object)(object)((Component)rock).gameObject != (Object)null) ? (((Object)((Component)rock).gameObject).name ?? string.Empty) : string.Empty); string hierarchyIdentity = GetHierarchyIdentity(rock); string networkPrefabIdentity = GetNetworkPrefabIdentity(rock); string dropIdentity = GetDropIdentity(rock); string value = text + " " + text2 + " " + hierarchyIdentity + " " + networkPrefabIdentity + " " + dropIdentity; if (!Contains(value, "LeviathanLava") && !Contains(text, "flametalore")) { return Contains(dropIdentity, "FlametalOreNew"); } return true; } private static Player TryResolvePlayerFromAttackerId(HitData hit) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) try { Type type = AccessTools.TypeByName("ZNetScene"); if (type == null) { return null; } PropertyInfo propertyInfo = AccessTools.Property(type, "instance"); object obj = ((propertyInfo != null) ? propertyInfo.GetValue(null, null) : null); if (obj == null) { return null; } MethodInfo methodInfo = AccessTools.Method(type, "FindInstance", (Type[])null, (Type[])null); if (methodInfo == null) { return null; } object obj2 = methodInfo.Invoke(obj, new object[1] { hit.m_attacker }); Component val = (Component)((obj2 is Component) ? obj2 : null); if ((Object)(object)val != (Object)null) { return val.GetComponent<Player>(); } GameObject val2 = (GameObject)((obj2 is GameObject) ? obj2 : null); return ((Object)(object)val2 != (Object)null) ? val2.GetComponent<Player>() : null; } catch { return null; } } private static string GetNetworkPrefabIdentity(MineRock rock) { if ((Object)(object)rock == (Object)null || NViewField == null) { return string.Empty; } try { object value = NViewField.GetValue(rock); if (value == null) { return string.Empty; } MethodInfo methodInfo = AccessTools.Method(value.GetType(), "GetPrefabName", (Type[])null, (Type[])null); if (methodInfo == null) { return string.Empty; } object obj = methodInfo.Invoke(value, null); return (obj as string) ?? string.Empty; } catch { return string.Empty; } } private static string GetHierarchyIdentity(MineRock rock) { if ((Object)(object)rock == (Object)null || (Object)(object)((Component)rock).transform == (Object)null) { return string.Empty; } try { List<string> list = new List<string>(); Transform val = ((Component)rock).transform; int num = 0; while ((Object)(object)val != (Object)null && num++ < 12) { if (!string.IsNullOrEmpty(((Object)val).name)) { list.Add(((Object)val).name); } val = val.parent; } return string.Join("/", list.ToArray()); } catch { return string.Empty; } } private static string GetDropIdentity(MineRock rock) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rock == (Object)null || rock.m_dropItems == null || rock.m_dropItems.m_drops == null) { return string.Empty; } try { List<string> list = new List<string>(); foreach (DropData drop in rock.m_dropItems.m_drops) { if ((Object)(object)drop.m_item != (Object)null && !string.IsNullOrEmpty(((Object)drop.m_item).name)) { list.Add(((Object)drop.m_item).name); } } return string.Join(",", list.ToArray()); } catch { return string.Empty; } } private static void DebugHit(MineRock rock, Player player, float radius, int totalColliders, int affectedAreas, int directAreaIndex, float nearestBoundsDistance, HitData hit) { if (Plugin.DebugLogging != null && Plugin.DebugLogging.Value && _debugHits < 12) { _debugHits++; string text = (((Object)(object)rock != (Object)null && (Object)(object)((Component)rock).gameObject != (Object)null) ? ((Object)((Component)rock).gameObject).name : "<null>"); string text2 = (((Object)(object)rock != (Object)null) ? rock.m_name : "<null>"); string hierarchyIdentity = GetHierarchyIdentity(rock); string networkPrefabIdentity = GetNetworkPrefabIdentity(rock); string dropIdentity = GetDropIdentity(rock); Logger.CreateLogSource("Ore Spread QoL").LogInfo((object)("Flametal debug #" + _debugHits + ": object='" + text + "' m_name='" + text2 + "' hierarchy='" + hierarchyIdentity + "' prefab='" + networkPrefabIdentity + "' drops='" + dropIdentity + "' radius=" + radius.ToString("0.00") + " totalHitAreas=" + totalColliders + " directArea=" + directAreaIndex + " nearestBoundsDistance=" + nearestBoundsDistance.ToString("0.00") + " affectedAreas=" + affectedAreas + " attackerPlayer=" + (((Object)(object)player != (Object)null) ? "yes" : "no") + " pickaxeDamage=" + hit.m_damage.m_pickaxe.ToString("0.00"))); } } private static bool Contains(string value, string fragment) { if (!string.IsNullOrEmpty(value)) { return value.IndexOf(fragment, StringComparison.OrdinalIgnoreCase) >= 0; } return false; } }