using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("AdvancedTreeChop")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("AdvancedTreeChop")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("33474395-a0a6-499b-8b7d-43808ac9bab9")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] [BepInPlugin("hadegs.valheim.advancedtreechop", "AdvancedTreeChop", "1.0.0")] public class AdvancedTreeChop : BaseUnityPlugin { [HarmonyPatch(typeof(TreeBase), "Damage")] private class TreeBasePatch { private static void Postfix(TreeBase __instance, HitData hit) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if (!((Object)(object)val == (Object)null)) { DoTreeChop(((Component)__instance).transform.position, hit, GetTreeRadius(val)); } } } [HarmonyPatch(typeof(TreeLog), "Damage")] private class TreeLogPatch { private static void Postfix(TreeLog __instance, HitData hit) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if (!((Object)(object)val == (Object)null)) { DoTreeChop(((Component)__instance).transform.position, hit, GetTreeRadius(val)); } } } internal static ConfigEntry modEnabled; internal static ConfigEntry toggleMode; internal static ConfigEntry modifierKey; internal static ConfigEntry baseTreeRadius; internal static ConfigEntry progressiveRadius; internal static ConfigEntry skillRadiusMultiplier; internal static ConfigEntry useStamina; internal static ConfigEntry useDurability; private const float MAX_RADIUS = 40f; private const int MAX_TREE_NODES = 15; private static bool toggleActive; private static bool isProcessing; private void Awake() { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_012b: Unknown result type (might be due to invalid IL or missing references) modEnabled = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "Enable AdvancedTreeChop"); toggleMode = ((BaseUnityPlugin)this).Config.Bind("General", "ToggleMode", false, "Toggle instead of holding key"); modifierKey = ((BaseUnityPlugin)this).Config.Bind("General", "ModifierKey", (KeyCode)308, "Tree chop key"); baseTreeRadius = ((BaseUnityPlugin)this).Config.Bind("Radius", "TreeRadius", 5f, new ConfigDescription("Base radius for trees", (AcceptableValueBase)(object)new AcceptableValueRange(3f, 15f), Array.Empty())); progressiveRadius = ((BaseUnityPlugin)this).Config.Bind("Progression", "EnableProgressiveRadius", true, "Scale radius with Woodcutting skill"); skillRadiusMultiplier = ((BaseUnityPlugin)this).Config.Bind("Progression", "SkillRadiusMultiplier", 0.05f, "Radius increase per Woodcutting skill level"); useStamina = ((BaseUnityPlugin)this).Config.Bind("Balance", "UseStamina", true, "Consume stamina for extra tree hits"); useDurability = ((BaseUnityPlugin)this).Config.Bind("Balance", "UseDurability", true, "Consume durability for extra tree hits"); new Harmony("hadegs.valheim.advancedtreechop").PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"AdvancedTreeChop 1.0.0 loaded"); } private void Update() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (modEnabled.Value && toggleMode.Value && Input.GetKeyDown(modifierKey.Value)) { toggleActive = !toggleActive; ((BaseUnityPlugin)this).Logger.LogInfo((object)("AdvancedTreeChop " + (toggleActive ? "ON" : "OFF"))); } } private static bool TreeChopActive() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (!modEnabled.Value) { return false; } return toggleMode.Value ? toggleActive : Input.GetKey(modifierKey.Value); } private static float GetTreeRadius(Player player) { float num = baseTreeRadius.Value; if (progressiveRadius.Value) { float skillLevel = ((Character)player).GetSkillLevel((SkillType)13); num += skillLevel * skillRadiusMultiplier.Value; } return Mathf.Min(num, 40f); } private static bool CanApplyExtraHit(Player player, ItemData tool) { if (useStamina.Value && player.GetStamina() <= 0f) { return false; } if (useDurability.Value && tool.m_durability <= 0f) { return false; } return true; } private static void DoTreeChop(Vector3 center, HitData hit, float radius) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (isProcessing || !TreeChopActive()) { return; } Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if ((Object)(object)val == (Object)null) { return; } ItemData currentWeapon = ((Humanoid)val).GetCurrentWeapon(); if (currentWeapon == null || currentWeapon.GetDamage().m_chop <= 0f) { return; } isProcessing = true; int num = 0; Collider[] array = Physics.OverlapSphere(center, radius); Collider[] array2 = array; foreach (Collider val2 in array2) { if (num >= 15) { break; } IDestructible componentInParent = ((Component)val2).GetComponentInParent(); if (componentInParent != null) { if (!CanApplyExtraHit(val, currentWeapon)) { break; } HitData val3 = hit.Clone(); componentInParent.Damage(val3); num++; } } isProcessing = false; } }