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 GrappleHookSkill v1.0.1
GrappleHookSkill.dll
Decompiled 4 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ConditionalConfigSync; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("GrappleHookSkill")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("GrappleHookSkill")] [assembly: AssemblyTitle("GrappleHookSkill")] [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 GrappleHookSkill { [BepInPlugin("com.dreich.grapplehookskill", "Grapple Hook Skill", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class GrappleHookSkillPlugin : BaseUnityPlugin { public const string Guid = "com.dreich.grapplehookskill"; public const string Name = "Grapple Hook Skill"; public const string Version = "1.0.1"; internal const string ConfigSyncGuid = "_shudnal.ConditionalConfigSync"; internal static ManualLogSource Log; internal static bool ConfigSyncAvailable; private static ConfigEntry<bool> ConfigLockedEntry; private static ConfigEntry<bool> EnabledEntry; private static ConfigEntry<float> MinReloadMultiplierEntry; private static ConfigEntry<float> SkillGainPerShotEntry; internal static bool Enabled => EnabledEntry.Value; internal static float MinReloadMultiplier => MinReloadMultiplierEntry.Value; internal static float SkillGainPerShot => SkillGainPerShotEntry.Value; private void Awake() { //IL_00da: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; ConfigSyncAvailable = Chainloader.PluginInfos.ContainsKey("_shudnal.ConditionalConfigSync"); if (ConfigSyncAvailable) { ConfigSyncCompat.Initialize("com.dreich.grapplehookskill", "Grapple Hook Skill", "1.0.1"); } else { Log.LogInfo((object)"ConditionalConfigSync not found; configuration will not be synced from the server."); } ConfigLockedEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Lock Configuration", true, "If on, the configuration is locked and can be changed by server admins only. Requires ConditionalConfigSync."); if (ConfigSyncAvailable) { ConfigSyncCompat.AddLockingConfigEntry(ConfigLockedEntry); } EnabledEntry = BindShared("General", "Enabled", defaultValue: true, "Turns the Grapple Hook skill on or off: skill gain and the faster reload."); MinReloadMultiplierEntry = BindShared("Reload", "MinReloadMultiplier", 0.5f, "Reload time multiplier at skill level 100. Level 0 is always the normal reload time. 0.5 matches the crossbow (half the time at level 100); 0.2 would match the bow's draw time."); SkillGainPerShotEntry = BindShared("Skill", "SkillGainPerShot", 1f, "Skill experience gained each time you fire the grappling hook. Higher levels faster."); new Harmony("com.dreich.grapplehookskill").PatchAll(); } private ConfigEntry<T> BindShared<T>(string section, string key, T defaultValue, string description) { ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(section, key, defaultValue, description); if (ConfigSyncAvailable) { ConfigSyncCompat.AddConfigEntry<T>(val, serverControlled: true); } return val; } } internal static class ConfigSyncCompat { private static object configSync; [MethodImpl(MethodImplOptions.NoInlining)] internal static void Initialize(string guid, string name, string version) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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) //IL_002e: Expected O, but got Unknown configSync = (object)new ConfigSync(guid) { DisplayName = name, CurrentVersion = version, MinimumRequiredVersion = version, ModRequired = false, ModRequirementMode = (ModRequirementMode)1 }; } [MethodImpl(MethodImplOptions.NoInlining)] internal static void AddLockingConfigEntry(ConfigEntry<bool> entry) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) ((ConditionalConfigSync)(ConfigSync)configSync).AddLockingConfigEntry<bool>(entry); } [MethodImpl(MethodImplOptions.NoInlining)] internal static void AddConfigEntry<T>(ConfigEntry<T> entry, bool serverControlled) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) ((ConditionalConfigSync)(ConfigSync)configSync).AddConfigEntry<T>(entry, (ConfigSyncMode)((!serverControlled) ? 2 : 0)); } } internal static class GrappleSkill { public const string SkillName = "Grapple Hook"; private const string SkillDescription = "Skill with the grappling hook. The higher your level, the faster you reload it."; public static readonly SkillType Type = (SkillType)StableId("com.dreich.grapplehookskill.GrappleHook"); private static readonly Dictionary<string, bool> HookCache = new Dictionary<string, bool>(); private static readonly MethodInfo AddWordMethod = typeof(Localization).GetMethod("AddWord", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(string), typeof(string) }, null); private static readonly FieldInfo TranslationsField = FindTranslationsField(); private static bool warned; private static string WordKey => "skill_" + (int)Type; private static int StableId(string text) { int num = 5381; foreach (char c in text) { num = num * 33 + c; } return (num & 0x7FFFFFFF) | 0x100; } private static FieldInfo FindTranslationsField() { FieldInfo fieldInfo = null; FieldInfo[] fields = typeof(Localization).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo2 in fields) { if (!(fieldInfo2.FieldType != typeof(Dictionary<string, string>))) { if (fieldInfo2.Name == "m_translations") { return fieldInfo2; } if (fieldInfo == null) { fieldInfo = fieldInfo2; } } } return fieldInfo; } public static void EnsureWord() { try { Localization instance = Localization.instance; if (instance != null) { if (AddWordMethod != null) { AddWordMethod.Invoke(instance, new object[2] { WordKey, "Grapple Hook" }); } else if (TranslationsField != null && TranslationsField.GetValue(instance) is Dictionary<string, string> dictionary) { dictionary[WordKey] = "Grapple Hook"; } else if (!warned) { warned = true; GrappleHookSkillPlugin.Log.LogWarning((object)("Could not find a way to add the skill name; it will show as $" + WordKey + ".")); } } } catch (Exception ex) { GrappleHookSkillPlugin.Log.LogWarning((object)("Could not add skill name: " + ex.Message)); } } public static void Register(Skills skills) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Invalid comparison between Unknown and I4 //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Invalid comparison between Unknown and I4 if ((Object)(object)skills == (Object)null || skills.m_skills == null) { return; } Sprite val = null; foreach (SkillDef skill in skills.m_skills) { if (skill.m_skill == Type) { EnsureWord(); return; } if ((int)skill.m_skill == 14 && (Object)(object)skill.m_icon != (Object)null) { val = skill.m_icon; } else if ((Object)(object)val == (Object)null && (int)skill.m_skill == 8) { val = skill.m_icon; } } SkillDef val2 = new SkillDef(); val2.m_skill = Type; val2.m_icon = val; val2.m_description = "Skill with the grappling hook. The higher your level, the faster you reload it."; val2.m_increseStep = 1f; skills.m_skills.Add(val2); EnsureWord(); } public static bool IsGrappleHook(ItemData item) { if (item == null || item.m_shared == null) { return false; } string key = item.m_shared.m_name ?? ""; if (HookCache.TryGetValue(key, out var value)) { return value; } value = Detect(item); HookCache[key] = value; return value; } private static bool Detect(ItemData item) { try { GameObject attackProjectile = item.m_shared.m_attack.m_attackProjectile; if ((Object)(object)attackProjectile != (Object)null) { Projectile component = attackProjectile.GetComponent<Projectile>(); if ((Object)(object)component != (Object)null && (Object)(object)component.m_spawnOnHit != (Object)null && (Object)(object)component.m_spawnOnHit.GetComponent<GrapplingPoint>() != (Object)null) { return true; } } } catch (Exception) { } string name = item.m_shared.m_name; if (name != null) { return name.IndexOf("grapp", StringComparison.OrdinalIgnoreCase) >= 0; } return false; } } [HarmonyPatch(typeof(Skills), "Awake")] internal static class SkillsAwakePatch { private static void Postfix(Skills __instance) { GrappleSkill.Register(__instance); } } [HarmonyPatch(typeof(Skills), "IsSkillValid")] internal static class IsSkillValidPatch { private static void Postfix(SkillType __0, ref bool __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (__0 == GrappleSkill.Type) { __result = true; } } } [HarmonyPatch(typeof(SkillsDialog), "Setup")] internal static class SkillsDialogPatch { private static void Prefix() { GrappleSkill.EnsureWord(); } } [HarmonyPatch(typeof(Skills), "RaiseSkill")] internal static class RaiseSkillPatch { private static void Prefix(SkillType __0) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (__0 == GrappleSkill.Type) { GrappleSkill.EnsureWord(); } } } [HarmonyPatch(typeof(ItemData), "GetWeaponLoadingTime")] internal static class ReloadTimePatch { private static void Postfix(ItemData __instance, ref float __result) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) if (GrappleHookSkillPlugin.Enabled && __instance.m_shared != null && __instance.m_shared.m_attack != null && __instance.m_shared.m_attack.m_requiresReload && GrappleSkill.IsGrappleHook(__instance)) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { float reloadTime = __instance.m_shared.m_attack.m_reloadTime; float skillFactor = ((Character)localPlayer).GetSkillFactor(GrappleSkill.Type); __result = Mathf.Lerp(reloadTime, reloadTime * GrappleHookSkillPlugin.MinReloadMultiplier, skillFactor); } } } } [HarmonyPatch(typeof(Attack), "OnAttackTrigger")] internal static class FirePatch { private static readonly FieldInfo CharacterField = AccessTools.Field(typeof(Attack), "m_character"); private static readonly FieldInfo WeaponField = AccessTools.Field(typeof(Attack), "m_weapon"); private static void Postfix(Attack __instance) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (GrappleHookSkillPlugin.Enabled && !(CharacterField == null) && !(WeaponField == null)) { object? value = CharacterField.GetValue(__instance); Character val = (Character)((value is Character) ? value : null); if (!((Object)(object)val == (Object)null) && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && GrappleSkill.IsGrappleHook((ItemData)/*isinst with value type is only supported in some contexts*/)) { val.RaiseSkill(GrappleSkill.Type, GrappleHookSkillPlugin.SkillGainPerShot); } } } } }