using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("OneHitChop")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1+f6c501c5a653d458f732558fbc5bea257707e744")] [assembly: AssemblyProduct("OneHitChop")] [assembly: AssemblyTitle("OneHitChop")] [assembly: AssemblyVersion("1.0.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace OneHitChop { [HarmonyPatch] internal static class ChopPatches { private const float HealthMargin = 2f; [HarmonyPatch(typeof(TreeBase), "Damage")] [HarmonyPrefix] private static void TreeBaseDamage(TreeBase __instance, HitData hit) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (ShouldBoost(hit)) { float health = ReadHealth((Component)(object)__instance, __instance.m_health); ApplyOneHit(hit, health, __instance.m_damageModifiers); } } [HarmonyPatch(typeof(TreeLog), "Damage")] [HarmonyPrefix] private static void TreeLogDamage(TreeLog __instance, HitData hit) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (Plugin.AffectLogs.Value && ShouldBoost(hit)) { float health = ReadHealth((Component)(object)__instance, __instance.m_health); ApplyOneHit(hit, health, __instance.m_damages); } } [HarmonyPatch(typeof(Destructible), "Damage")] [HarmonyPrefix] private static void DestructibleDamage(Destructible __instance, HitData hit) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (Plugin.AffectStumps.Value && (int)__instance.m_destructibleType == 2 && ShouldBoost(hit)) { float health = ReadHealth((Component)(object)__instance, __instance.m_health); ApplyOneHit(hit, health, __instance.m_damages); } } private static bool ShouldBoost(HitData hit) { if (!Plugin.ModEnabled.Value || hit == null) { return false; } if (hit.m_damage.m_chop <= 0f) { return false; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { return (Object)(object)hit.GetAttacker() == (Object)(object)localPlayer; } return false; } private static float ReadHealth(Component target, float fallback) { ZNetView component = target.GetComponent(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return fallback; } float num = component.GetZDO().GetFloat(ZDOVars.s_health, fallback); if (!(num > 0f)) { return fallback; } return num; } private static void ApplyOneHit(HitData hit, float health, DamageModifiers modifiers) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) float num = ResistanceFactor(((DamageModifiers)(ref modifiers)).GetModifier((DamageType)8)); if (!(num <= 0f)) { float num2 = (health + 2f) / num; if (hit.m_damage.m_chop < num2) { hit.m_damage.m_chop = num2; } if (Plugin.IgnoreToolTier.Value) { hit.m_toolTier = short.MaxValue; hit.m_itemWorldLevel = byte.MaxValue; } } } private static float ResistanceFactor(DamageModifier modifier) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected I4, but got Unknown switch (modifier - 1) { case 6: return 0.75f; case 0: return 0.5f; case 4: return 0.25f; case 7: return 1.25f; case 1: return 1.5f; case 5: return 2f; case 2: case 3: return 0f; default: return 1f; } } } [BepInPlugin("matheba.onehitchop", "OneHitChop", "1.0.1")] [BepInProcess("valheim.exe")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static ConfigEntry ModEnabled; internal static ConfigEntry ToggleKey; internal static ConfigEntry ShowToggleMessage; internal static ConfigEntry AffectLogs; internal static ConfigEntry AffectStumps; internal static ConfigEntry IgnoreToolTier; private readonly Harmony _harmony = new Harmony("matheba.onehitchop"); private void Awake() { //IL_0045: 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 = ((BaseUnityPlugin)this).Logger; ModEnabled = ((BaseUnityPlugin)this).Config.Bind("1 - General", "One-hit chopping", false, "Turns one-hit chopping on and off. Applies only to your own character, on your client."); ToggleKey = ((BaseUnityPlugin)this).Config.Bind("1 - General", "Toggle hotkey", new KeyboardShortcut((KeyCode)290, Array.Empty()), "Key that turns the mod on and off in game. Ignored while you are typing in chat or the console."); ShowToggleMessage = ((BaseUnityPlugin)this).Config.Bind("1 - General", "Show on-screen message", true, "Shows a centre-screen message when you toggle the mod with the hotkey."); AffectLogs = ((BaseUnityPlugin)this).Config.Bind("2 - Targets", "Fallen logs", true, "Also breaks the log a felled tree drops in a single hit."); AffectStumps = ((BaseUnityPlugin)this).Config.Bind("2 - Targets", "Stumps and bushes", true, "Also breaks stumps, saplings and choppable bushes in a single hit."); IgnoreToolTier = ((BaseUnityPlugin)this).Config.Bind("2 - Targets", "Ignore axe tier requirement", false, "Lets you chop trees that normally need a better axe, such as oak and birch. Leave this off to keep normal game progression."); _harmony.PatchAll(typeof(ChopPatches)); Log.LogInfo((object)string.Format("{0} {1} loaded. Enabled: {2}, hotkey: {3}", "OneHitChop", "1.0.1", ModEnabled.Value, ToggleKey.Value)); } private void OnDestroy() { _harmony.UnpatchSelf(); } private void Update() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = ToggleKey.Value; if (((KeyboardShortcut)(ref value)).IsDown() && !IsTyping()) { ModEnabled.Value = !ModEnabled.Value; Log.LogInfo((object)("One-hit chopping: " + (ModEnabled.Value ? "on" : "off"))); if (ShowToggleMessage.Value && (Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)2, ModEnabled.Value ? "One-hit chopping: ON" : "One-hit chopping: OFF", 0, (Sprite)null); } } } private static bool IsTyping() { if (Console.IsVisible() || TextInput.IsVisible()) { return true; } if ((Object)(object)Chat.instance != (Object)null) { return Chat.instance.HasFocus(); } return false; } } internal static class PluginInfo { internal const string Guid = "matheba.onehitchop"; internal const string Name = "OneHitChop"; internal const string Version = "1.0.1"; } }