Example #1
0
 private static void UseStamina_Postfix(Player __instance, float __state, ref float ___m_stamina)
 {
     if (BetterStaminaPlugin.enableStaminaLogging != null && BetterStaminaPlugin.enableStaminaLogging.Value && (___m_stamina - __state) != 0f)
     {
         BetterStaminaPlugin.DebugLog($"UseStamina(): source - {new StackFrame(2).GetMethod().Name}; change - {___m_stamina - __state}");
     }
 }
Example #2
0
    private static bool GetStaminaUsage_Prefix(Attack __instance, Humanoid ___m_character, float ___m_attackStamina, ItemDrop.ItemData ___m_weapon, ref float __result)
    {
        if (Player.m_localPlayer == null || (UnityEngine.Object)Player.m_localPlayer != (UnityEngine.Object)___m_character)
        {
            // Do default logic for non-local players
            return(true);
        }

        if ((double)___m_attackStamina <= 0.0)
        {
            __result = 0.0f;
            return(false);
        }

        double attackStamina = (double)___m_attackStamina;

        EasingFunctions.Function easeFunc = EasingFunctions.GetEasingFunction(EasingFunctions.Ease.EaseOutSine);
        float interpFactor = easeFunc(1f, BetterStaminaPlugin.weaponMaxSkillAttackStaminaCost.Value, ___m_character.GetSkillFactor(___m_weapon.m_shared.m_skillType));

        __result = (float)(attackStamina * interpFactor);

        if (BetterStaminaPlugin.enableSkillStaminaLogging != null && BetterStaminaPlugin.enableSkillStaminaLogging.Value)
        {
            string callingMethodName = new StackFrame(2).GetMethod().Name;
            if (callingMethodName.Contains("Update"))
            {
                float originalStaminaReduction = (float)(attackStamina * (1f - BetterStaminaPlugin.weaponMaxSkillAttackStaminaCost.Value /*0.330000013113022 */) * (double)___m_character.GetSkillFactor(___m_weapon.m_shared.m_skillType));
                float originalCalculation      = (float)(attackStamina - originalStaminaReduction);
                BetterStaminaPlugin.DebugLog($"Attack.GetStaminaUsage(): Cost - {__result}; Original: {originalCalculation}; Custom: {__result}; skill: {___m_character.GetSkillFactor(___m_weapon.m_shared.m_skillType)}({___m_weapon.m_shared.m_skillType});");
            }
        }

        // Skip original function
        return(false);
    }
Example #3
0
    private static void UpdateStatusEffect(StatusEffect se, bool onPlayer = false)
    {
        string playerString = onPlayer ? " on local player " : " in ObjectDB ";

        if (se is SE_Stats stats)
        {
            switch (se.m_name)
            {
            case "$se_cold_name":
                BetterStaminaPlugin.DebugLog($"[{Localization.instance.Localize(se.m_name)}] Updating m_staminaRegenMultiplier{playerString}from {stats.m_staminaRegenMultiplier} to {BetterStaminaPlugin.coldStaminaRegenMultiplier.Value}");
                stats.m_staminaRegenMultiplier = BetterStaminaPlugin.coldStaminaRegenMultiplier.Value;
                break;

            case "$se_wet_name":
                BetterStaminaPlugin.DebugLog($"[{Localization.instance.Localize(se.m_name)}] Updating m_staminaRegenMultiplier{playerString}from {stats.m_staminaRegenMultiplier} to {BetterStaminaPlugin.wetStaminaRegenMultiplier.Value}");
                stats.m_staminaRegenMultiplier = BetterStaminaPlugin.wetStaminaRegenMultiplier.Value;
                break;

            case "$se_rested_name":
                BetterStaminaPlugin.DebugLog($"[{Localization.instance.Localize(se.m_name)}] Updating m_staminaRegenMultiplier{playerString}from {stats.m_staminaRegenMultiplier} to {BetterStaminaPlugin.restedStaminaRegenMultiplier.Value}");
                stats.m_staminaRegenMultiplier = BetterStaminaPlugin.restedStaminaRegenMultiplier.Value;

                SE_Rested ser = se as SE_Rested;
                BetterStaminaPlugin.DebugLog($"[{Localization.instance.Localize(se.m_name)}] Updating m_TTLPerComfortLevel{playerString}from {ser.m_TTLPerComfortLevel} to {BetterStaminaPlugin.restedDurationPerComfortLvl.Value}");
                ser.m_TTLPerComfortLevel = BetterStaminaPlugin.restedDurationPerComfortLvl.Value;
                break;
            }
        }
    }
Example #4
0
    static IEnumerable <CodeInstruction> OnSwimming_Transpiler(IEnumerable <CodeInstruction> instructions)
    {
        BetterStaminaPlugin.DebugTranspilerLog($"######## OnSwimming_Transpiler START ########");
        var codes = new List <CodeInstruction>(instructions);

        for (var i = 0; i < codes.Count; i++)
        {
            CodeInstruction instr = codes[i];

            BetterStaminaPlugin.DebugTranspilerLog($"{i} {instr}");

            if (instr.opcode == OpCodes.Call)
            {
                String instrString = instr.ToString();
                if (instrString.Contains("Mathf::Lerp"))
                {
                    int insertIndex = i;
                    BetterStaminaPlugin.DebugTranspilerLog($">>> Deleting instruction {insertIndex} {codes[insertIndex].ToString()}:");
                    codes.RemoveAt(i);

                    BetterStaminaPlugin.DebugTranspilerLog($">>> Inserting instruction at {insertIndex}:");
                    BetterStaminaPlugin.DebugTranspilerLog($"Old: { codes[insertIndex].ToString()}");
                    codes.Insert(insertIndex, new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(SkillPatches), "GetSwimmingStaminaDrain")));
                    BetterStaminaPlugin.DebugTranspilerLog($"New: { codes[insertIndex].ToString()}");

                    BetterStaminaPlugin.DebugTranspilerLog($">>> Inserting instruction at {insertIndex}:");
                    BetterStaminaPlugin.DebugTranspilerLog($"Old: { codes[insertIndex].ToString()}");
                    codes.Insert(insertIndex, new CodeInstruction(OpCodes.Ldarg_0));
                    BetterStaminaPlugin.DebugTranspilerLog($"New: { codes[insertIndex].ToString()}");
                    break;
                }
            }
        }

        BetterStaminaPlugin.DebugTranspilerLog($"");
        BetterStaminaPlugin.DebugTranspilerLog($"#############################################################");
        BetterStaminaPlugin.DebugTranspilerLog($"######## MODIFIED INSTRUCTIONS - {codes.Count} ########");
        BetterStaminaPlugin.DebugTranspilerLog($"#############################################################");
        BetterStaminaPlugin.DebugTranspilerLog($"");

        for (var i = 0; i < codes.Count; i++)
        {
            CodeInstruction instr = codes[i];

            BetterStaminaPlugin.DebugTranspilerLog($"{i} {instr}");
        }

        BetterStaminaPlugin.DebugTranspilerLog($"######## OnSwimming_Transpiler END ########");
        BetterStaminaPlugin.DebugTranspilerLog($"");

        return(codes);
    }
Example #5
0
    static IEnumerable <CodeInstruction> CheckRun_Transpiler(IEnumerable <CodeInstruction> instructions)
    {
        BetterStaminaPlugin.DebugTranspilerLog($"######## CheckRun_Transpiler START ########");
        var codes = new List <CodeInstruction>(instructions);

        for (var i = 0; i < codes.Count; i++)
        {
            CodeInstruction instr = codes[i];

            BetterStaminaPlugin.DebugTranspilerLog($"{i} {instr}");

            if (instr.opcode == OpCodes.Call)
            {
                String instrString = instr.ToString();
                if (instrString.Contains("Mathf::Lerp"))         // Looking for this line: float drain = this.m_runStaminaDrain * Mathf.Lerp(1f, 0.5f, this.m_skills.GetSkillFactor(Skills.SkillType.Run));
                {
                    int insertIndex = i;
                    BetterStaminaPlugin.DebugTranspilerLog($">>> Deleting instruction {insertIndex} {codes[insertIndex].ToString()}:");
                    codes.RemoveAt(i);

                    BetterStaminaPlugin.DebugTranspilerLog($">>> Inserting instruction at {insertIndex}:");
                    BetterStaminaPlugin.DebugTranspilerLog($"Old: { codes[insertIndex].ToString()}");
                    codes.Insert(insertIndex, new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(SkillPatches), "GetRunStaminaSkillFactor")));
                    BetterStaminaPlugin.DebugTranspilerLog($"New: { codes[insertIndex].ToString()}");

                    BetterStaminaPlugin.DebugTranspilerLog($">>> Inserting instruction at {insertIndex}:");
                    BetterStaminaPlugin.DebugTranspilerLog($"Old: { codes[insertIndex].ToString()}");
                    codes.Insert(insertIndex, new CodeInstruction(OpCodes.Ldarg_0));
                    BetterStaminaPlugin.DebugTranspilerLog($"New: { codes[insertIndex].ToString()}");
                    break;
                }
            }
        }

        BetterStaminaPlugin.DebugTranspilerLog($"");
        BetterStaminaPlugin.DebugTranspilerLog($"#############################################################");
        BetterStaminaPlugin.DebugTranspilerLog($"######## MODIFIED INSTRUCTIONS - {codes.Count} ########");
        BetterStaminaPlugin.DebugTranspilerLog($"#############################################################");
        BetterStaminaPlugin.DebugTranspilerLog($"");

        for (var i = 0; i < codes.Count; i++)
        {
            CodeInstruction instr = codes[i];

            BetterStaminaPlugin.DebugTranspilerLog($"{i} {instr}");
        }

        BetterStaminaPlugin.DebugTranspilerLog($"######## CheckRun_Transpiler END ########");
        BetterStaminaPlugin.DebugTranspilerLog($"");

        return(codes);
    }
Example #6
0
    public static float GetSwimmingStaminaDrain(float drainMax, float drainMin, float skillFactor, Player playerInst)
    {
        if (Player.m_localPlayer != null && (UnityEngine.Object)Player.m_localPlayer == (UnityEngine.Object)playerInst)
        {
            EasingFunctions.Function easeFunc = EasingFunctions.GetEasingFunction(EasingFunctions.Ease.EaseOutSine);
            float interpFactor = easeFunc(BetterStaminaPlugin.swimMaxStaminaCost.Value, BetterStaminaPlugin.swimMinStaminaCost.Value, skillFactor);

            if (BetterStaminaPlugin.enableSkillStaminaLogging != null && BetterStaminaPlugin.enableSkillStaminaLogging.Value)
            {
                BetterStaminaPlugin.DebugLog($"SwimStamina: Usage change: {Mathf.Lerp(drainMax, drainMin, skillFactor)} - {interpFactor}; skill: {playerInst.GetSkillFactor(Skills.SkillType.Swim)};");
            }

            return(interpFactor);
        }

        return(Mathf.Lerp(drainMax, drainMin, skillFactor));
    }
Example #7
0
    public static float GetUpdatedHoldBowStaminaDrain(float weaponStaminaDrain, Player playerInst)
    {
        if (Player.m_localPlayer != null && (UnityEngine.Object)Player.m_localPlayer == (UnityEngine.Object)playerInst)
        {
            EasingFunctions.Function easeFunc = EasingFunctions.GetEasingFunction(EasingFunctions.Ease.EaseOutSine);
            float interpFactor          = easeFunc(1f, BetterStaminaPlugin.bowMaxSkillHoldStaminaCost.Value, playerInst.GetSkillFactor(Skills.SkillType.Bows));
            float newWeaponStaminaDrain = weaponStaminaDrain * interpFactor;

            if (BetterStaminaPlugin.enableSkillStaminaLogging != null && BetterStaminaPlugin.enableSkillStaminaLogging.Value)
            {
                BetterStaminaPlugin.DebugLog($"BowHoldStamina: Usage change: {weaponStaminaDrain} - {newWeaponStaminaDrain}; Mathf.Lerp: {Mathf.Lerp(1f, BetterStaminaPlugin.bowMaxSkillHoldStaminaCost.Value, playerInst.GetSkillFactor(Skills.SkillType.Blocking))}; Custom: {interpFactor}; skill: {playerInst.GetSkillFactor(Skills.SkillType.Bows)};");
            }

            return(newWeaponStaminaDrain);
        }

        return(weaponStaminaDrain);
    }
Example #8
0
    private static void OnJump_Prefix(Player __instance, Skills ___m_skills)
    {
        defaultJumpStaminaUsage = __instance.m_jumpStaminaUsage;

        if (Player.m_localPlayer == null || (UnityEngine.Object)Player.m_localPlayer != (UnityEngine.Object)__instance)
        {
            return;
        }

        EasingFunctions.Function easeFunc = EasingFunctions.GetEasingFunction(EasingFunctions.Ease.EaseOutSine);
        float interpFactor = easeFunc(1f, BetterStaminaPlugin.jumpMaxSkillStaminaCost.Value, ___m_skills.GetSkillFactor(Skills.SkillType.Jump));

        __instance.m_jumpStaminaUsage = __instance.m_jumpStaminaUsage * interpFactor;

        if (BetterStaminaPlugin.enableSkillStaminaLogging != null && BetterStaminaPlugin.enableSkillStaminaLogging.Value)
        {
            BetterStaminaPlugin.DebugLog($"OnJump: Usage change: {defaultJumpStaminaUsage} - {__instance.m_jumpStaminaUsage}; Mathf.Lerp: {Mathf.Lerp(1f, BetterStaminaPlugin.jumpMaxSkillStaminaCost.Value, ___m_skills.GetSkillFactor(Skills.SkillType.Jump))}; Custom: {interpFactor}; skill: {___m_skills.GetSkillFactor(Skills.SkillType.Jump)};");
        }
    }
Example #9
0
    private static void UpdateDodge_Prefix(Player __instance, Skills ___m_skills, float ___m_queuedDodgeTimer)
    {
        defaultStaminaUsage = __instance.m_dodgeStaminaUsage;

        if (Player.m_localPlayer == null || (UnityEngine.Object)Player.m_localPlayer != (UnityEngine.Object)__instance)
        {
            return;
        }

        EasingFunctions.Function easeFunc = EasingFunctions.GetEasingFunction(EasingFunctions.Ease.EaseOutSine);
        float interpFactor = easeFunc(1f, BetterStaminaPlugin.dodgeMaxSkillStaminaCost.Value, ___m_skills.GetSkillFactor(Skills.SkillType.Jump));

        __instance.m_dodgeStaminaUsage = __instance.m_dodgeStaminaUsage * interpFactor;

        if (BetterStaminaPlugin.enableSkillStaminaLogging != null && BetterStaminaPlugin.enableSkillStaminaLogging.Value &&
            (double)___m_queuedDodgeTimer > 0.0 && __instance.IsOnGround() && (!__instance.IsDead() && !__instance.InAttack()) && (!__instance.IsEncumbered() && !__instance.InDodge()))
        {
            BetterStaminaPlugin.DebugLog($"UpdateDoge: Usage change: {defaultStaminaUsage} - {__instance.m_dodgeStaminaUsage}; Mathf.Lerp: {Mathf.Lerp(1f, BetterStaminaPlugin.dodgeMaxSkillStaminaCost.Value, ___m_skills.GetSkillFactor(Skills.SkillType.Jump))}; Custom: {interpFactor}; skill: {___m_skills.GetSkillFactor(Skills.SkillType.Jump)};");
        }
    }
Example #10
0
    private static float CalculateNewStamina(Player __instance, bool ___m_wallRunning, float ___m_staminaRegen, float ___m_stamina, SEMan ___m_seman, ref float ___m_staminaRegenTimer, float dt)
    {
        float num1 = 1f;

        if (__instance.IsBlocking())
        {
            num1 *= 0.8f;
        }
        if (((__instance.IsSwiming() && !__instance.IsOnGround() || (__instance.InAttack() || __instance.InDodge()) ? 1 : (___m_wallRunning ? 1 : 0)) | (__instance.IsEncumbered() ? 1 : 0)) != 0)
        {
            num1 = 0.0f;
        }

        float maxStamina        = __instance.GetMaxStamina();
        float missingStaminaMod = (float)(1.0 - (double)___m_stamina / (double)maxStamina);
        float num2 = (___m_staminaRegen + missingStaminaMod * ___m_staminaRegen * __instance.m_staminaRegenTimeMultiplier) * num1;
        float staminaMultiplier = 1f;

        ___m_seman.ModifyStaminaRegen(ref staminaMultiplier);
        float num3 = num2 * staminaMultiplier;

        ___m_staminaRegenTimer -= dt;

        float returnStamina = ___m_stamina;

        if ((double)___m_stamina < (double)maxStamina && (double)___m_staminaRegenTimer <= 0.0)
        {
            returnStamina = Mathf.Min(maxStamina, ___m_stamina + num3 * dt);
        }

        float staminaChange = returnStamina - ___m_stamina;

        if (Mathf.Abs(staminaChange) > 0f)
        {
            BetterStaminaPlugin.DebugLog($"StaminaChangeThisFrame: {num3}(dt-{staminaChange}), base regen - {___m_staminaRegen}; activity mult - {num1}; base mult - {__instance.m_staminaRegenTimeMultiplier}; missing mult - {missingStaminaMod}; SE mult - {staminaMultiplier}");
        }

        return(returnStamina);
    }
Example #11
0
    private static void BlockAttack_Prefix(Humanoid __instance)
    {
        if (Player.m_localPlayer != null && (UnityEngine.Object)Player.m_localPlayer == (UnityEngine.Object)__instance)
        {
            defaultBlockStaminaDrain = __instance.m_blockStaminaDrain;

            Skills playerSkills = (Skills)BetterStaminaPlugin.playerSkillsField.GetValue(Player.m_localPlayer);
            if (playerSkills == null)
            {
                return;
            }

            EasingFunctions.Function easeFunc = EasingFunctions.GetEasingFunction(EasingFunctions.Ease.EaseOutSine);
            float interpFactor = easeFunc(1f, BetterStaminaPlugin.blockMaxSkillStaminaCost.Value, playerSkills.GetSkillFactor(Skills.SkillType.Blocking));

            __instance.m_blockStaminaDrain = __instance.m_blockStaminaDrain * interpFactor;

            if (BetterStaminaPlugin.enableSkillStaminaLogging != null && BetterStaminaPlugin.enableSkillStaminaLogging.Value)
            {
                BetterStaminaPlugin.DebugLog($"BlockAttack: Usage change: {defaultBlockStaminaDrain} - {__instance.m_blockStaminaDrain}; Mathf.Lerp: {Mathf.Lerp(1f, BetterStaminaPlugin.blockMaxSkillStaminaCost.Value, playerSkills.GetSkillFactor(Skills.SkillType.Blocking))}; Custom: {interpFactor}; skill: {playerSkills.GetSkillFactor(Skills.SkillType.Blocking)};");
            }
        }
    }
Example #12
0
    public static float GetRunStaminaSkillFactor(float drainMax, float drainMin, float skillFactor, Player playerInst)
    {
        drainMin = BetterStaminaPlugin.runMaxSkillStaminaCost.Value;

        if (Player.m_localPlayer != null && (UnityEngine.Object)Player.m_localPlayer == (UnityEngine.Object)playerInst)
        {
            if (playerInst.GetCurrentWeapon() != null)
            {
                drainMin = BetterStaminaPlugin.runWithWeapMaxSkillStaminaCost.Value;
            }

            EasingFunctions.Function easeFunc = EasingFunctions.GetEasingFunction(EasingFunctions.Ease.EaseOutSine);
            float interpFactor = easeFunc(drainMax, drainMin, skillFactor);

            if (BetterStaminaPlugin.enableSkillStaminaLogging != null && BetterStaminaPlugin.enableSkillStaminaLogging.Value)
            {
                BetterStaminaPlugin.DebugLog($"RunStamina: Skill factor change: {Mathf.Lerp(drainMax, drainMin, skillFactor)} - {interpFactor}");
            }

            return(interpFactor);
        }

        return(Mathf.Lerp(drainMax, drainMin, skillFactor));
    }
Example #13
0
    public static void UpdateWeaponStats(ObjectDB __instance)
    {
        foreach (GameObject gameObject in __instance.m_items)
        {
            ItemDrop itemDrop = gameObject.GetComponent <ItemDrop>();
            if (itemDrop != null)
            {
                if (itemDrop.m_itemData != null)
                {
                    if (itemDrop.m_itemData.m_shared != null)
                    {
                        if (itemDrop.m_itemData.m_shared.m_itemType == ItemDrop.ItemData.ItemType.OneHandedWeapon ||
                            itemDrop.m_itemData.m_shared.m_itemType == ItemDrop.ItemData.ItemType.TwoHandedWeapon ||
                            itemDrop.m_itemData.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Shield ||
                            itemDrop.m_itemData.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Bow ||
                            itemDrop.m_itemData.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Torch ||
                            itemDrop.m_itemData.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Ammo ||
                            itemDrop.m_itemData.m_shared.m_itemType == ItemDrop.ItemData.ItemType.Tool)
                        {
                            if (//itemDrop.gameObject.name.StartsWith("Axe") ||
                                //itemDrop.gameObject.name.StartsWith("Atgeir") ||
                                //itemDrop.gameObject.name.StartsWith("Battleaxe") ||
                                itemDrop.gameObject.name.StartsWith("Bow"))
                            //itemDrop.gameObject.name.StartsWith("Cultivator") ||
                            //itemDrop.gameObject.name.StartsWith("Club") ||
                            //itemDrop.gameObject.name.StartsWith("Hammer") ||
                            //itemDrop.gameObject.name.StartsWith("Hoe") ||
                            //itemDrop.gameObject.name.StartsWith("Knife") ||
                            //itemDrop.gameObject.name.StartsWith("Mace") ||
                            //itemDrop.gameObject.name.StartsWith("Pickaxe") ||
                            //itemDrop.gameObject.name.StartsWith("Shield") ||
                            //itemDrop.gameObject.name.StartsWith("Sledge") ||
                            //itemDrop.gameObject.name.StartsWith("Spear") ||
                            //itemDrop.gameObject.name.StartsWith("Sword") ||
                            //itemDrop.gameObject.name.StartsWith("Torch") ||
                            //itemDrop.gameObject.name.StartsWith("Arrow") ||
                            //itemDrop.gameObject.name.StartsWith("Fishing") ||
                            //itemDrop.gameObject.name.StartsWith("BombOoze"))
                            {
                                if (itemDrop.m_itemData.m_shared.m_attack != null)
                                {
                                    BetterStaminaPlugin.DebugLog($"Updating {itemDrop.gameObject.name} m_attackStamina from {itemDrop.m_itemData.m_shared.m_attack.m_attackStamina} to {BetterStaminaPlugin.bowAttackCost.Value}");
                                    itemDrop.m_itemData.m_shared.m_attack.m_attackStamina = BetterStaminaPlugin.bowAttackCost.Value;
                                }

//                                 if (itemDrop.m_itemData.m_shared.m_secondaryAttack != null)
//                                 {
//                                     string itemKey = itemDrop.gameObject.name + "_second";
//                                     if (!weaponStaminaStats.ContainsKey(itemKey))
//                                     {
//                                         BetterStaminaPlugin.DebugLog($"[ObjectDB] [2] Creating entry for {itemKey} ({itemDrop.m_itemData.m_shared.m_itemType}): Stamina - {itemDrop.m_itemData.m_shared.m_secondaryAttack.m_attackStamina}");
//                                         ConfigEntry<float> newItem = config.Bind("5.Weapons", itemKey, itemDrop.m_itemData.m_shared.m_secondaryAttack.m_attackStamina, "");
//                                         weaponStaminaStats.Add(itemKey, newItem);
//                                     }
//                                     else
//                                     {
//                                         BetterStaminaPlugin.DebugLog($"[ObjectDB] [2] Updating values for {itemKey} ({itemDrop.m_itemData.m_shared.m_itemType}): Stamina - {itemDrop.m_itemData.m_shared.m_secondaryAttack.m_attackStamina}");
//                                         itemDrop.m_itemData.m_shared.m_secondaryAttack.m_attackStamina = weaponStaminaStats[itemKey].Value;
//                                     }
//                                 }
                            }
                        }
                    }
                }
            }
        }
    }
Example #14
0
    static IEnumerable <CodeInstruction> PlayerAttackInput_Transpiler(IEnumerable <CodeInstruction> instructions)
    {
        BetterStaminaPlugin.DebugTranspilerLog($"######## PlayerAttackInput_Patch START ########");
        var codes = new List <CodeInstruction>(instructions);

        for (var i = 0; i < codes.Count; i++)
        {
            CodeInstruction instr = codes[i];

            BetterStaminaPlugin.DebugTranspilerLog($"{i} {instr}");

            if (instr.opcode == OpCodes.Callvirt)
            {
                String instrString = instr.ToString();
                if (instrString.Contains("UseStamina"))         // Looking for this line: this.UseStamina(currentWeapon.m_shared.m_holdStaminaDrain * dt);
                {
                    int foundCorrectUseStaminaIndex = -1;
                    for (var j = i - 1; j >= i - 5; j--)          // Verify that this UseStamina() call uses m_holdStaminaDrain by checking for it being loaded on the stack within last 5 instructions
                    {
                        BetterStaminaPlugin.DebugTranspilerLog($"^{j} {codes[j].ToString()}");

                        if (codes[j].opcode == OpCodes.Ldfld)
                        {
                            instrString = codes[j].ToString();
                            if (instrString.Contains("holdStaminaDrain"))
                            {
                                BetterStaminaPlugin.DebugTranspilerLog($">>> Found load holdStaminaDrain instruction at {j}:");
                                foundCorrectUseStaminaIndex = j;
                                break;
                            }
                        }
                    }

                    if (foundCorrectUseStaminaIndex >= 0)
                    {
                        int insertIndex = foundCorrectUseStaminaIndex + 1;
                        BetterStaminaPlugin.DebugTranspilerLog($">>> Inserting instruction at {insertIndex}:");
                        BetterStaminaPlugin.DebugTranspilerLog($"Old: { codes[insertIndex].ToString()}");
                        codes.Insert(insertIndex, new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(SkillPatches), "GetUpdatedHoldBowStaminaDrain")));
                        BetterStaminaPlugin.DebugTranspilerLog($"New: { codes[insertIndex].ToString()}");

                        BetterStaminaPlugin.DebugTranspilerLog($">>> Inserting instruction at {insertIndex}:");
                        BetterStaminaPlugin.DebugTranspilerLog($"Old: { codes[insertIndex].ToString()}");
                        codes.Insert(insertIndex, new CodeInstruction(OpCodes.Ldarg_0));
                        BetterStaminaPlugin.DebugTranspilerLog($"New: { codes[insertIndex].ToString()}");
                        break;
                    }
                }
            }
        }

        BetterStaminaPlugin.DebugTranspilerLog($"");
        BetterStaminaPlugin.DebugTranspilerLog($"#############################################################");
        BetterStaminaPlugin.DebugTranspilerLog($"######## MODIFIED INSTRUCTIONS - {codes.Count} ########");
        BetterStaminaPlugin.DebugTranspilerLog($"#############################################################");
        BetterStaminaPlugin.DebugTranspilerLog($"");

        for (var i = 0; i < codes.Count; i++)
        {
            CodeInstruction instr = codes[i];

            BetterStaminaPlugin.DebugTranspilerLog($"{i} {instr}");
        }

        BetterStaminaPlugin.DebugTranspilerLog($"######## PlayerAttackInput_Patch END ########");
        BetterStaminaPlugin.DebugTranspilerLog($"");

        return(codes);
    }