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<bool> modEnabled;
internal static ConfigEntry<bool> toggleMode;
internal static ConfigEntry<KeyCode> modifierKey;
internal static ConfigEntry<float> baseTreeRadius;
internal static ConfigEntry<bool> progressiveRadius;
internal static ConfigEntry<float> skillRadiusMultiplier;
internal static ConfigEntry<bool> useStamina;
internal static ConfigEntry<bool> 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<bool>("General", "Enabled", true, "Enable AdvancedTreeChop");
toggleMode = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ToggleMode", false, "Toggle instead of holding key");
modifierKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "ModifierKey", (KeyCode)308, "Tree chop key");
baseTreeRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Radius", "TreeRadius", 5f, new ConfigDescription("Base radius for trees", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 15f), Array.Empty<object>()));
progressiveRadius = ((BaseUnityPlugin)this).Config.Bind<bool>("Progression", "EnableProgressiveRadius", true, "Scale radius with Woodcutting skill");
skillRadiusMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Progression", "SkillRadiusMultiplier", 0.05f, "Radius increase per Woodcutting skill level");
useStamina = ((BaseUnityPlugin)this).Config.Bind<bool>("Balance", "UseStamina", true, "Consume stamina for extra tree hits");
useDurability = ((BaseUnityPlugin)this).Config.Bind<bool>("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<IDestructible>();
if (componentInParent != null)
{
if (!CanApplyExtraHit(val, currentWeapon))
{
break;
}
HitData val3 = hit.Clone();
componentInParent.Damage(val3);
num++;
}
}
isProcessing = false;
}
}