[MV] 受伤后恢复

大家好!

我想分享另一个我在开发自己的项目时制作的小型 RPG Maker MV 插件。

该插件允许状态在战斗者受到 HP 伤害后自动恢复 HP。

我最初是为 Boss 战创建这个插件的,特别是那些在接近死亡时变得更难击败的 Boss。不过,它也可以用于敌人、角色或任何需要在受到伤害后自动回血自定义机制。

我认为这个机制对其他开发者可能有用,所以决定分享出来。

该插件允许免费用于商业和非商业用途。你可以随意修改它——无需许可。

如果你决定使用它,我希望你能在你的项目中注明 “Melphilium”。

希望你觉得它有用。谢谢!

/*:
 * @plugindesc [MV] 受到伤害后状态回血 v1.0
 * @author Melphilium
 *
 * @help
 * ============================================================================
 * 概述
 * ============================================================================
 *
 * 在状态(State)中添加以下注释标签(notetag):
 *
 *   <AfterDamageHeal:50>
 *   <AfterDamageHeal:25%>
 *
 * 当战斗者受到此状态影响时:
 *
 * - 在受到 HP 伤害后恢复 HP。
 * - 支持固定数值和百分比回血。
 * - 多个带有此注释标签的状态会叠加效果。
 * - 仅当战斗者在伤害后存活时才会触发回血。
 *
 * ============================================================================
 * 注释标签
 * ============================================================================
 *
 * <AfterDamageHeal:50>
 * 在受到 HP 伤害后恢复 50 HP。
 *
 * <AfterDamageHeal:25%>
 * 在受到 HP 伤害后恢复战斗者最大 HP 的 25%。
 *
 * ============================================================================
 * 示例
 * ============================================================================
 *
 * 状态:
 * <AfterDamageHeal:100>
 *
 * 战斗者受到 300 HP 伤害。
 *
 * 结果:
 * 伤害生效后立即恢复 100 HP。
 *
 * --------------------------------------------------------------------------
 *
 * 状态:
 * <AfterDamageHeal:10%>
 *
 * 战斗者受到 HP 伤害。
 *
 * 结果:
 * 伤害生效后立即恢复战斗者最大 HP 的 10%。
 *
 * ============================================================================
 * 注意事项
 * ============================================================================
 *
 * - 仅在受到 HP 伤害时触发。
 * - 如果伤害为 0,则不触发。
 * - 如果战斗者因该伤害被击败,则不触发。
 * - 多个状态的恢复效果会叠加。
 *
 * ============================================================================
 * 兼容性
 * ============================================================================
 *
 * RPG Maker MV
 *
 * ============================================================================
 * 使用条款
 * ============================================================================
 *
 * 允许免费用于商业和非商业用途。
 *
 * 你可以随意修改此插件。
 *
 * 无需许可。
 *
 * 署名:Melphilium
 *
 * ============================================================================
 * 版本历史
 * ============================================================================
 *
 * v1.0
 * - 首次发布。
 */

(function() {

    const _Game_Action_executeHpDamage =
        Game_Action.prototype.executeHpDamage;

    Game_Action.prototype.executeHpDamage = function(target, value) {

        // 先执行原始伤害逻辑
        _Game_Action_executeHpDamage.call(this, target, value);

        // 仅在真正受到 HP 伤害时触发
        if (value <= 0) return;

        // 如果目标已死亡则不触发
        if (target.isDead()) return;

        let totalHeal = 0;

        target.states().forEach(state => {

            if (!state || !state.note) return;

            const match = state.note.match(
                /<AfterDamageHeal\s*:\s*(\d+)(%)?>/i
            );

            if (match) {

                const amount = Number(match[1]);
                const isPercent = !!match[2];

                if (isPercent) {
                    totalHeal += Math.floor(target.mhp * amount / 100);
                } else {
                    totalHeal += amount;
                }
            }
        });

        if (totalHeal > 0) {
            
            // 使用 setTimeout 提供延迟
            // 下面的 600 表示 600 毫秒(0.6 秒)。
            setTimeout(function() {
                
                // 重新检查
                if (!target.isDead()) {
                    
                    // 清除结果以避免回血弹窗冲突
                    target.clearResult();
                    
                    // 执行回血
                    target.gainHp(totalHeal);
                    target.startDamagePopup();
                    target.refresh();

                    // 更新战斗日志以显示 HP 恢复效果
                    if (BattleManager._logWindow) {
                        BattleManager._logWindow.displayHpDamage(target);
                    }
                }
                
            }, 600); // <- 时间延迟
        }
    };

})();
2 个赞

这看起来不错,但我认为你应该想办法不使用 setTimeout,因为这可能会导致执行顺序错乱。战斗日志窗口已经处理了计时问题,所以它可能可以帮你解决这个问题——与其调用 BattleManager._logWindow.displayHpDamage,你或许可以使用 BattleManager._logWindow.push 来实现。在最坏的情况下,你的自定义函数可以作为新方法添加到日志窗口中,在推送延迟后调用它。

1 个赞

谢谢你的建议!我最初使用 setTimeout 来防止伤害弹出窗口被治疗弹出窗口覆盖,但我同意使用战斗日志队列会是更优雅的解决方案。我稍后会尝试一下,看看能否在保持与 SRPG 插件兼容的同时实现它。:pink_heart: