[MV] 被ダメージ後に回復

皆さん、こんにちは!

自分のプロジェクトの開発中に作成した、RPG Maker MV用の小さなプラグインをもう一つ共有しようと思います。

このプラグインは、バトラーがHPダメージを受けた後に、ステートによってHPを自動的に回復させる機能を提供します。

元々はボス戦用、特に残りHPが少ないほど攻略が難しくなるボス向けに作成しました。しかし、敵キャラクターやアクター、あるいはダメージを受けた後に自動回復するカスタムメカニクスが必要な場合にも使用できます。

このメカニクスが他の開発者にも役立つかもしれないと考え、公開することにしました。

このプラグインは商用・非商用を問わず無料で使用できます。必要に応じて自由に修正してください。許可は不要です。

使用する場合は、プロジェクト内で「Melphilium」をクレジットしていただけると幸いです。

お役に立てば幸いです。ありがとうございます!

/*:
 * @plugindesc [MV] State Heal After Taking Damage v1.0
 * @author Melphilium
 *
 * @help
 * ============================================================================
 * 概要
 * ============================================================================
 *
 * ステートのメモ欄に以下のタグを追加してください:
 *
 *   <AfterDamageHeal:50>
 *   <AfterDamageHeal:25%>
 *
 * このステートが適用されている間、バトラーは以下の効果を受けます:
 *
 * - HPダメージを受けた後にHPが回復します。
 * - 固定値による回復と割合による回復の両方に対応しています。
 * - このメモタグを持つ複数のステートは積み重なります。
 * - バトラーがダメージで倒れない場合にのみ回復が発生します。
 *
 * ============================================================================
 * メモタグ
 * ============================================================================
 *
 * <AfterDamageHeal:50>
 * HPダメージを受けた後に50のHPを回復します。
 *
 * <AfterDamageHeal:25%>
 * HPダメージを受けた後にバトラーの最大HPの25%を回復します。
 *
 * ============================================================================
 * 使用例
 * ============================================================================
 *
 * ステート:
 * <AfterDamageHeal:100>
 *
 * バトラーが300のHPダメージを受けた場合。
 *
 * 結果:
 * ダメージ適用直後にHPが100回復します。
 *
 * --------------------------------------------------------------------------
 *
 * ステート:
 * <AfterDamageHeal:10%>
 *
 * バトラーがHPダメージを受けた場合。
 *
 * 結果:
 * ダメージ適用直後に、バトラーの最大HPの10%分だけHPが回復します。
 *
 * ============================================================================
 * 注意事項
 * ============================================================================
 *
 * - 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();

                    // バトルログを更新して回復効果を表示
                    if (BattleManager._logWindow) {
                        BattleManager._logWindow.displayHpDamage(target);
                    }
                }
                
            }, 600); // <- 時間遅延(ディレイ)
        }
    };

})();
「いいね!」 2

これは見栄えは良いですが、setTimeout を使うと順序がずれてしまうように思えるので、その方法を使わずに実装する方法を考えた方がいいと思います。バトルログウィンドウは既にタイミング処理を担っているので、おそらくそれを使って対応できるはずです。BattleManager._logWindow.displayHpDamage を呼び出す代わりに、BattleManager._logWindow.push を使うことで何とかなるかもしれません。最悪の場合、カスタム関数をログウィンドウの新しいメソッドとして追加し、そのメソッドを push する前に遅延処理を push することも可能です。

「いいね!」 1

提案ありがとうございます!元々は、ダメージ表示が回復表示で上書きされるのを防ぐために setTimeout を使っていましたが、バトルログキューを使う方がよりクリーンな解決策だと同意します。後で試してみて、SRPGプラグインとの互換性を保ちながら動作するようにしてみます。:pink_heart: