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 BetterGrapplingHook v1.0.0
BetterGrapplingHook.dll
Decompiled 3 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; 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("BetterGrapplingHook")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Valheim BepInEx plugin: removes the Grappling Hook stamina cost, cuts its reload to near-instant, and extends its rope.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+f6898482133345310e70e3a421d37d4a1b23361e")] [assembly: AssemblyProduct("BetterGrapplingHook")] [assembly: AssemblyTitle("BetterGrapplingHook")] [assembly: AssemblyVersion("1.0.0.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 BetterGrapplingHook { [BepInPlugin("carrome.bettergrapplinghook", "Better GrapplingHook", "1.0.0")] public class BetterGrapplingHookPlugin : BaseUnityPlugin { public const string PluginGuid = "carrome.bettergrapplinghook"; public const string PluginName = "Better GrapplingHook"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Log; internal static ConfigEntry<float> StaminaCost; internal static ConfigEntry<float> ReloadTime; internal static ConfigEntry<float> RopeLengthMultiplier; private Harmony _harmony; private void Awake() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; StaminaCost = ((BaseUnityPlugin)this).Config.Bind<float>("Stamina", "StaminaCost", 0f, new ConfigDescription("Stamina cost per shot. Vanilla is 15.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); ReloadTime = ((BaseUnityPlugin)this).Config.Bind<float>("Reload", "ReloadTime", 0.1f, new ConfigDescription("Reload duration in seconds. Vanilla is 2s of reload on top of 1.1s of block time; this replaces the reload and removes the block entirely.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>())); RopeLengthMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Rope", "RopeLengthMultiplier", 1.5f, new ConfigDescription("Scales how far the rope can stretch before it snaps. Vanilla is 60 while pulling and 70 while hanging; 1.5 gives 90 and 105.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f), Array.Empty<object>())); _harmony = new Harmony("carrome.bettergrapplinghook"); _harmony.PatchAll(typeof(ObjectDbPatch)); Log.LogInfo((object)"Better GrapplingHook 1.0.0 loaded."); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } [HarmonyPatch(typeof(ObjectDB))] internal static class ObjectDbPatch { private sealed class AttackDefaults { public float ReloadTime; public float BlockReloadTime; public float AttackStamina; } private static readonly Dictionary<Attack, AttackDefaults> AttackOriginals = new Dictionary<Attack, AttackDefaults>(); private static readonly Dictionary<GrapplingPoint, float> MaxLengthOriginals = new Dictionary<GrapplingPoint, float>(); private static bool _logged; [HarmonyPostfix] [HarmonyPatch("UpdateRegisters")] private static void UpdateRegistersPostfix(ObjectDB __instance) { if (__instance.m_items == null || __instance.m_items.Count == 0) { return; } ApplyRopeLength(); foreach (GameObject item in __instance.m_items) { if (item == null || ((Object)item).name == null || !((Object)item).name.ToLowerInvariant().Contains("grappling")) { continue; } SharedData val = item.GetComponent<ItemDrop>()?.m_itemData?.m_shared; if (val != null) { ApplyAttack(val.m_attack); ApplyAttack(val.m_secondaryAttack); if (!_logged) { _logged = true; LogResult(((Object)item).name, val.m_attack); } } } } private static void ApplyRopeLength() { GrapplingPoint[] array = Resources.FindObjectsOfTypeAll<GrapplingPoint>(); foreach (GrapplingPoint val in array) { if (!((Object)(object)val == (Object)null)) { if (!MaxLengthOriginals.TryGetValue(val, out var value)) { value = val.m_maxLength; MaxLengthOriginals[val] = value; } val.m_maxLength = value * BetterGrapplingHookPlugin.RopeLengthMultiplier.Value; } } } private static void ApplyAttack(Attack attack) { if (attack != null) { if (!AttackOriginals.TryGetValue(attack, out var value)) { value = new AttackDefaults { ReloadTime = attack.m_reloadTime, BlockReloadTime = attack.m_blockReloadTime, AttackStamina = attack.m_attackStamina }; AttackOriginals[attack] = value; } attack.m_attackStamina = BetterGrapplingHookPlugin.StaminaCost.Value; attack.m_reloadTime = BetterGrapplingHookPlugin.ReloadTime.Value; attack.m_blockReloadTime = 0f; } } private static void LogResult(string prefabName, Attack attack) { if (attack == null || !AttackOriginals.TryGetValue(attack, out var value)) { return; } List<string> list = new List<string>(); foreach (KeyValuePair<GrapplingPoint, float> maxLengthOriginal in MaxLengthOriginals) { list.Add(((Object)((Component)maxLengthOriginal.Key).gameObject).name + " " + F(maxLengthOriginal.Value) + " -> " + F(maxLengthOriginal.Key.m_maxLength)); } BetterGrapplingHookPlugin.Log.LogInfo((object)(prefabName + ": stamina " + F(value.AttackStamina) + " -> " + F(attack.m_attackStamina) + ", reload " + F(value.ReloadTime) + "s -> " + F(attack.m_reloadTime) + "s, blockReload " + F(value.BlockReloadTime) + "s -> " + F(attack.m_blockReloadTime) + "s")); BetterGrapplingHookPlugin.Log.LogInfo((object)("rope: " + string.Join(", ", list.ToArray()))); } private static string F(float value) { return value.ToString("0.###", CultureInfo.InvariantCulture); } } }