ツクールmzの二刀流攻撃について

whitykoala

ユーザー
最近、ツクールmzで、二刀流のアクターを作成しました。
攻撃するときに、2本の武器で同時に攻撃しているような感じがします。
スキルの中には、「2本で同時攻撃」というものがあってもいいとは思います。
私のイメージとしましては、違和感があるのです。

①基準の攻撃力に、2本の武器が加算されている。そのため、すごく高い攻撃力になっていること
②冒頭で述べたように、2本の武器による1回攻撃になっていること

このような仕組みを、
①右手と左手それぞれに、攻撃力を設定できるようにしてほしいです
②①を受けて、右手と左手の武器で、別々に攻撃できるようにしてほしいです

このようなことができるプラグインはあるのでしょうか。
それとも、プラグインの範疇をこえているのでしょうか。
よろしくお願いします。
 
私も今全く同じ悩みを抱えているので、どなたか実現できないでしょうか。
「Battle Core VisuStella MZ」は私も試しましたが、機能が非常に多いのとすべて英語表記なので私には難しそうです…
盾禁止にして双剣などの二刀流専用武器を用意してやれば簡易的にはできるのですが、やはり一般の武器を二つ装備したく。
よろしくお願いします。
 
プラグインを作ってもらえたら一番良いのでしょうけれど・・・
システムとして面白そうだったので、デフォとスクリプトでできる方法を考えるだけ考えてみました。
構想だけおいとくので、興味がわいた方がいらっしゃったら実装してみてください。
(ただし、構想だけなので、実装が可能かどうかはわかりません)

攻撃を武器から直接行うのではなく、武器に設定したスキルから行います。

武器の特徴から、攻撃スキルを設定する。
このスキルはコモンイベントを呼び出すだけのスキル。
実際に攻撃行動を行うスキルは、別に作成する。
攻撃用のスキルの計算式は変数を指定。

コモンイベントの内容
・右手の装備品を調べる
・装備品の攻撃力を調べる
・ここで実際のダメージ数値を計算してもいいし、スキルの計算式を使ってもいい
・攻撃用のスキルを発動させる
・左手の装備品を調べる
・装備品の攻撃力を調べる
・ここで実際のダメージ数値を計算してもいいし、スキルの計算式を使ってもいい
・攻撃用のスキルを発動させる

これで、左右の武器の攻撃力が違う2回攻撃になるのではないかと思った。
装備品を調べるのは、デフォでもできるけど、スクリプト使った方が速そう。
武器の攻撃力の取得は、デフォじゃ難しいかな。まあなんかスクリプトあるんちゃうかな。

サイドビューだと、モーションが魔法待機とかになっちゃうのやだなーとかある場合
くろうどさんのスキルモーションを攻撃モーションに変更
をお借りするとかでいけないかしら。

同じく、コモンイベントを起動するだけのスキルだと無駄に一歩前に出るとかの問題もあるので
武器の攻撃力の計算を戦闘開始時とかに取得しておいて
最初の一歩前に出るのは、右武器の計算で攻撃しておいて
左武器の攻撃は、右武器の攻撃スキルからコモンを呼んでやるとかでもいいかもしれない。
(コモンイベントを起動するだけのスキルだと、効果なしメッセージもでちゃうので
 通常は、効果のないダミーステートを100%付与させて回避するんだけど
 こっちの方法なら、それも回避できるので一石二鳥でもあるが)

左右の攻撃力の差が武器の性能に寄らずランダムでもよければ
攻撃スキルを連続攻撃のスキルに変更するステートを作って
任意のタイミングで左右に武器を装備してるかを調べて付与すればよいだけなんだろうけれど。

あー、サスケさんの装備変更時、コモンイベントを起動プラグインとかよさげじゃないですか?
装備変更時に、変数に攻撃力取得やらステート付与やらしておけばよいん。

と、まあ考えるだけ考えてみました。
考えるのは楽しかったけど、そこそこ面倒くさいので
誰かプラグイン作ってくれちゃったりすることを祈ります。
 
一応、前回の調べにて検証が手間だったためスルーしていたMV用プラグインもあります。Victor Sant様の「VE - Dual Wield」です。
海外のフォーラムに飛びます
利用規約
 二刀流をカスタマイズするプラグインとして、ツクールMVではムノクラ様による翻訳版も再配布されています。

 ツクールMV用のためそのままでは利用できませんが、意外と軽微な修正で動いたのでこちらもご提案いたします。なお、影響範囲は不明であるため、予期せぬ不具合があるかもしれません。
 検証環境は以下になります。

RPGツクールMZ v1.8.1
RPGツクールMV コアスクリプト v.1.6.2
VE_BasicModule.js v1.23(前提プラグイン。こちらの修正は必要ありません)
VE_DualWield.js v1.04

・アクターにスロットタイプ「二刀流」のみ設定


 導入にあたって改変が必須となるため、任意のテキストエディタをご用意ください。Javascriptファイル(拡張子「.js」)の編集ができるものだと捗ります(メモ帳でも可。その場合は「.txt」で編集してから拡張子を変更します)。

 初めに導入するプラグイン2種にアノテーションを追加します。ファイル内に「/*」から始まるコメントがありますので「@plugindesc ...」の上あたりに「@target MZ」を追加してください。以下のコードは「VE_BasicModule.js」にアノテーションを追加した例です。
コード:
/*:
 * ==============================================================================
 * @target MZ
 * @plugindesc v1.23 - Plugin with base code required for all Victor Engine plugins.
 * @author Victor Sant
 *
 このアノテーションの追加はツクールMZのプラグインリスト内で警告文を表示させないために行うので機能上は必須ではありませんが、まあ気になると思うので推奨いたします:smile:

 次に、このままではゲーム内でエラーが発生するため「VE_DualWield.js」の390行あたりにある「(function() {」より下に追加のコードを書き込みます。
コード:
    // RPG Maker MZ v.1.8.1 rmmz_sprites.js
    Sprite_Battler.prototype.mainSprite = function() {
        return this;
    };
コード:
    // RPG Maker MV v.1.6.2 rpg_windows.js
    Window_Base.prototype.textPadding = function() {
        return 6;
    };
コード:
    // RPG Maker MV v.1.6.2 rpg_windows.js
    Window_Selectable.prototype.itemRectForText = function(index) {
        var rect = this.itemRect(index);
        rect.x += this.textPadding();
        rect.width -= this.textPadding() * 2;
        return rect;
    };
 主にツクールMVでは存在するもののツクールMZには存在しない関数の追加です。「Sprite_Battler.prototype.mainSprite」についてはツクールMZの同関数と同じ名前の関数が「VE_BasicModule.js」内に存在したため、「VE_DualWield.js」で再度上書きしてツクールMZと同じ処理にします。

 今回の検証ではこれでwhitykoala様のご要望である「①右手と左手それぞれに、攻撃力を設定できるようにする」「②①を受けて、右手と左手の武器で、別々に攻撃できるようにする」という点については実装できました。


 ただし「VE_DualWield.js」には特殊な仕様があり、このプラグインによって「二刀流」の特徴を持つアクターは「右手→左手」の順に攻撃を行うのですが、右手の攻撃でエネミーを倒した時にそれが最後のエネミーではなかった場合は、倒した敵の座標に左手攻撃を行ってしまいます。まあまあ不自然な挙動ですが、そういう仕様のようです。
 そして、この仕様を変更する方法が2つあります。
①右手攻撃でエネミーを倒した時、左手攻撃を実行しない。
②右手で攻撃した後、左手がランダムなエネミーを攻撃する。

 順当に行けば①だと思いますが、②もアイデアとして使えなくもなさそうな気がします。ただし今回の検証では両立できません。

 というわけで①の仕様にするための変更ですが、まずは「VE_DualWield.js」内の「BattleManager.startAction」を改変します。改変後、以下のようになります。
コード:
    // 改変後のコード。
    VictorEngine.DualWield.startAction = BattleManager.startAction;
    BattleManager.startAction = function() {

        // 追加したコード。
        this._beforeTroopCount = $gameTroop.aliveMembers().length;

        this.setDualWieldAction();
        VictorEngine.DualWield.startAction.call(this);
        this.setSecondAttack();
    };
 これはアクターが選択されたコマンドによって行動を開始する処理です。ここに現在のエネミーの数を「this._beforeTroopCount」という新規のプロパティその1に代入する処理を追加しました。

 次に、「VE_DualWield.js」内の「BattleManager.endAction」を改変して作業完了です。改変後、以下のようになります。
コード:
    // 改変後のコード。
    VictorEngine.DualWield.endAction = BattleManager.endAction;
    BattleManager.endAction = function() {

        // 追加したコード。
        this._afterTloopCount = $gameTroop.aliveMembers().length;
        if (this._beforeTroopCount == this._afterTloopCount) {
            this._isSecondAttack = true;
        }

        if (this._canFollowUp) {
            this.startFollowUpAction();

        // 改変したコード。
        } else if (this._canSecondAttack && this._isSecondAttack) {

            this.startDualWieldAction();
        } else {
            this._isSecondAttack = false;
            this._dualWieldAction = null;
            VictorEngine.DualWield.endAction.call(this);
        }
    };
 これはアクターの行動を終了する処理です。「VE_DualWield.js」ではこの段階でプロパティに応じて行動を変化させているようです。
 元々は「this._canSecondAttack」プロパティが true の時、「this.startDualWieldAction();」を実行して2回目の攻撃を行っていますが、追加したコードによってここでも現在のエネミーの数を新規のプロパティその2に代入し、追加したプロパティ同士を比較してエネミーの数に変化が無かった時のみ、2回目の攻撃を判別するプロパティを true にして 2回目の攻撃を行うように改変しました。
 要するに右手で倒したらそこで行動終了ですよ。左手は添えるだけ。



 ②の方は簡単な変更です。①の改変を行わず、「VE_DualWield.js」内の「Game_Action.prototype.setDualWieldTargets」を空にします。
コード:
    // 空にします。
    Game_Action.prototype.setDualWieldTargets = function(targets) {
     
    };
 これは2回目の攻撃を行うエネミーを1回目に攻撃したエネミーに指定する処理ですが、空にしたら2回目はランダムな敵を狙うようになりました。こちらは検証の副産物です。



 これにて以上となります。これらのプラグインの影響範囲がどこまで及ぶかはわかりませんが、少々の改変で実装はできます。ただ、プラグインが持っている他の機能を活用しようとすると修正範囲も広がりますので注意が必要です。
 以下に検証時の動作を示す画像を添付しておきますので、よろしければご検討ください。

①右手と左手で攻撃力が分割されています。どちらも(基礎能力 + 武器攻撃力)です。
②右手攻撃のダメージ(攻撃力20)です。この攻撃に続けて左手攻撃を行います。
③左手攻撃のダメージ(攻撃力519)です。アニメーションは左手武器に設定したものが再生されます。
 

Attachments

  • 2024-10-27-01.png
    2024-10-27-01.png
    224.1 KB · 閲覧: 18
  • 2024-10-27-02.png
    2024-10-27-02.png
    772.2 KB · 閲覧: 19
  • 2024-10-27-03.png
    2024-10-27-03.png
    692.3 KB · 閲覧: 20
最後に編集:
スレ主ではありませんが、私につきましてはこちらで解決しましたので御礼申し上げます。
ゆわか様、ハゲメクラチビゴミムシオシ様、貴重な時間割いて対応いただき、誠にありがとうございます。
結論から言いますと、ハゲメクラチビゴミムシオシ様のご紹介いただいた方法で解決しました。

大変丁寧に説明されていたので、ほとんど迷うことなく実装できました。
また、今回は特にタグを使用せずとも特徴だけで二刀流の動作ができましたが、
せっかくいろいろ用意されているようなので後で試してみたいと思います。

二刀流の際は最終ダメージを0.75倍にするといった調整機能もついているようなので、
二刀流が強すぎてしまう問題もこれで解決しそうです。

なお、「VE_BasicModule.js」への「@target MZ」の追加の部分についてですが、
私の場合はシステムが日本語なので、「/*:ja」の下あたりに記述する必要がありました。

大変丁寧な説明、本当にありがとうございました。
最後にwhitykoala様、スレ主でないのに勝手に入ってきてしまい申し訳ありませんでした。
whitykoala様の課題が解決することを願っております。

ーーーーーーーー追記ーーーーーーーー
一点注意すべき点が見つかったのでメモ代わりに追記します。
この方法では内部的には2つの武器と攻撃力を合算した値を持っている。(つまりデフォルトの二刀流と一緒)
実際ステータス画面ではそのような値が表示されている。
スキルでa.atkを計算式に入れる時には、何も考えずに設定すると二刀流のキャラだけ異常にスキルの効果が
強くなってしまうため、何らかの工夫は必要。
 
最後に編集:
こんばんは。
私も、ハゲメクラチビゴミムシオシ様の方法を使って、二刀流個別攻撃を実装できました。
ありがとうございます。
少し気になることがあります。
バトルログにおいて、左手の攻撃のときに、
右手の攻撃のときの「○○のこうげき」が残って表示されています。
 
お二方とも無事に実装できたようでよかったです。

少し気になることがあります。
バトルログにおいて、左手の攻撃のときに、
右手の攻撃のときの「○○のこうげき」が残って表示されています。
 実は私も気になっていたところです。
 残念ながら私の戦闘ログに関する知識がほとんど無かったため、検証時は「2回行動したと解釈できるか?」くらいの認識でいましたが、直せるなら直したいところですね。

 というわけで簡単に検証してみましたが、以下のコードどちらかを「VE_DualWield.js」内の「BattleManager.endAction」に追加することで解消されました。
① this._logWindow.clear();
 戦闘ログを消去するコードです。ただし、戦闘ログ自体が一瞬消えるため点滅を起こしているような挙動となります。この場合は特徴の「攻撃追加回数」で連続攻撃した時と異なる挙動となるため気になる人は気になるかもしれません。

② this._logWindow._lines.pop();
 こちらはJavascript用語を交えて解説いたしますと、戦闘ログに表示されるメッセージは配列になっており、Javascriptの配列を操作するメソッドを用いてちょっとした制御が行えます。
 詳細には「this._logWindow」が戦闘ログのオブジェクトであり、続く「._lines」が戦闘ログのメッセージを表示するプロパティかつ配列であり、最後の「.pop()」が配列の一番後ろにある要素を取り除き、戻り値として返します。ただし、この記法では戻り値を利用しないため、配列から要素を取り除くのみで終わります。
 要するに、このコードは実行された時点での最後の戦闘ログを取り除きます。こちらでは戦闘ログ自体が消えることなく、右手攻撃のメッセージが取り除かれました。

 上記のコードを追加する場所は以下になります。
コード:
    // VE_DualWield.js
    VictorEngine.DualWield.endAction = BattleManager.endAction;
    BattleManager.endAction = function() {
        this._afterTloopCount = $gameTroop.aliveMembers().length;
        if (this._beforeTroopCount == this._afterTloopCount) {
            this._isSecondAttack = true;
        }
        if (this._canFollowUp) {
            this.startFollowUpAction();
        } else if (this._canSecondAttack && this._isSecondAttack) {

            // ココ!
            this._logWindow._lines.pop();

            this.startDualWieldAction();
        } else {
            this._isSecondAttack = false;
            this._dualWieldAction = null;
            VictorEngine.DualWield.endAction.call(this);
        }
    };
 2回目の攻撃を行う「this.startDualWieldAction()」の直前に配置してください。

 これで戦闘ログの挙動が改善されると思いますのでお試しください。以下に右手攻撃後、左手攻撃を行った時の画像を添付しておきます。
 

Attachments

  • 2024-10-29.png
    2024-10-29.png
    725.6 KB · 閲覧: 13
すみません。
新規プロジェクトで試してみたところ、
確かに動作したのですが、
New RPG Project様の
NRP_DynamicAnimationMZ v1.22
NRP_DynamicMotionMZ v1.255
を入れると競合してしまいました(添付ファイル)。
ホーム - エクスプローラー 2025_01_06 (月) 16_48_37.png

できれば共存させたいのですが、
競合対策をご教授くださいますでしょうか?

Dynamic系のプラグインは外せないので、
難しいようなら共存は諦めます。
何卒よろしくお願いいたします。
 
すみません。
新規プロジェクトで試してみたところ、
確かに動作したのですが、
New RPG Project様の
NRP_DynamicAnimationMZ v1.22
NRP_DynamicMotionMZ v1.255
を入れると競合してしまいました(添付ファイル)。View attachment 18969
できれば共存させたいのですが、
競合対策をご教授くださいますでしょうか?

Dynamic系のプラグインは外せないので、
難しいようなら共存は諦めます。
何卒よろしくお願いいたします。
 真白灰様、はじめまして。
 「NRP_DynamicAnimationMZ」と「NRP_DynamicMotionMZ」を併用する場合は「NRP_DynamicMotionMZ」のプラグインパラメータ「表示優先度の有効化」を false にしていただくとエラーは解消されるかと思います。
 プラグインファイルの改変による対策については、 Javascript の厳格モードに起因するエラーであるため私も知識が無く、検証に多大な時間がかかる恐れがあります(エラー内容としては、バトラーの Z 座標を設定するプロパティに Setter が定義されていないことが原因のようです)。

 その他の注意点としては、データベース 1 番の「通常攻撃」用のスキルに <D-Motion> タグや <D-Animation> タグを設定すると、左手武器による攻撃は右手武器のアニメーションが再生されてしまうため通常攻撃のモーション設定は非推奨です。

 申し訳ありませんが現状でわかるのはここまでです。ひとまずはプラグインパラメータの設定をお試しいただければと思います。
 
ご教授いただいたとおりにプラグインパラメータをいじったところ、
うまくいきました。
主人公が二刀流で通常攻撃する機会もあるため、両立できて非常に嬉しいです!
誠にありがとうございました!
 
度々すみません。

VE_DualWieldが装備ステータスの表示をいじるプラグインと競合してしまうので、
それらを外したのですが、一つ問題があります。

他のステータス画面では攻撃力の下に
運の名前を変えて流用した射撃というパラメータを表示しているのですが、
VE_DualWieldではデフォルト通り運が一番下に表示されてしまいます。
右手攻撃力、左手攻撃力の下に運を表示させたいです。

改変のコードをご教授ください。
自分でもやってみたのですがうまくいかず…
よろしくお願いいたします。

もし難しい場合には他のステータス画面の表示順をデフォに戻します。
 
VE_DualWieldが装備ステータスの表示をいじるプラグインと競合してしまうので、
それらを外したのですが、一つ問題があります。

他のステータス画面では攻撃力の下に
運の名前を変えて流用した射撃というパラメータを表示しているのですが、
VE_DualWieldではデフォルト通り運が一番下に表示されてしまいます。
右手攻撃力、左手攻撃力の下に運を表示させたいです。

改変のコードをご教授ください。
自分でもやってみたのですがうまくいかず…
よろしくお願いいたします。

もし難しい場合には他のステータス画面の表示順をデフォに戻します。
 こんにちは。
「VE_DualWield.js」利用時の装備画面におけるステータス表示順についてですが、仕様上は左手側の攻撃力表示を追加しているのみでパラメータの表示処理はデフォルト仕様に準じているため、トリアコンタン様制作のパラメータ並び順プラグイン「ParamOrder.js」を併用して解決を試みました。
 検証環境は以下になります。

RPGツクールMZ v1.8.1
VE_BasicModule.js v1.23
VE_DualWield.js v1.04(このスレッドで改変済みのもの)
ParamOrder.js v1.0.1


 まず、今回のケースにおいて改変するプラグインは「VE_DualWield.js」のみです。ですが、「ParamOrder.js」の導入を前提とした改変を行うため、「ParamOrder.js」導入後、プラグインリストでは以下のような並びにしてください。

2025-01-12-01.png

「ParamOrder.js」を「VE_DualWield.js」より上に配置します。処理順序の都合でこの並びにする必要があります。

 次に、攻撃力の下に運を表示したいとのことなので「ParamOrder.js」のプラグインパラメータ「並び順リスト」を以下のように設定します。

2025-01-12-02.png

 パラメータの数はそのままに、「運」を「攻撃力」の下に配置します。

「ParamOrder.js」の設定は以上で完了です。しかし、現時点では仕様が噛み合わず、パラメータ名が設定した通りの並び順になりません。ですが、パラメータの数値は設定通りの並びに変わっているはずです。


 次は「VE_DualWield.js」のプラグインファイルを改変します。作業内容は2つです。
 まずはWindow_EquipStatusオブジェクトにメソッドを追加します。以下のコードをプラグインファイルのコード内に追加してください。

コード:
    // 新規に追加するコード。
    Window_EquipStatus.prototype.convertParamName = function(i) {
        const paramId = this.convertParamId(i === 2 ? i + 5 : i === 3 ? i - 1 : i);
        return paramId;
    };
 このコードは並びがおかしくなっているパラメータの名前の配列番号を修正します。この中の this.convertParamId(...) で「ParamOrder.js」にて定義されているメソッドを実行するため「ParamOrder.js」の導入が前提となります。
 このメソッドは戻り値を返すメソッドなのでパラメータを描画する処理の中で実行される必要があります。そのため次は以下のメソッドを改変します。

コード:
    // VE_DualWield.js v1.04
    VictorEngine.DualWield.drawParamName = Window_EquipStatus.prototype.drawParamName;
    Window_EquipStatus.prototype.drawParamName = function(x, y, i) {
        if (VictorEngine.Parameters.DualWield.SeparatedAttack) {
            var right = VictorEngine.Parameters.DualWield.RightHandPrefix + ' ';
            var left = VictorEngine.Parameters.DualWield.LeftHandPrefix + ' ';
            var name = i === 0 ? right : i === 1 ? left : ''
            this.changeTextColor(this.systemColor());
            this.drawText(name + TextManager.param(i === 0 ? 2 : i + 1), x, y, 120);
        } else {
            VictorEngine.DualWield.drawParamName.call(this, x, y, i);
        }
    };
 このメソッドの中の this.drawText(...) でパラメータ名が描画されるので、先ほど追加したメソッドを利用したコードに改変します。改変後、以下のようになります。

Rich (BB code):
    // 改変後のコード。
    VictorEngine.DualWield.drawParamName = Window_EquipStatus.prototype.drawParamName;
    Window_EquipStatus.prototype.drawParamName = function(x, y, i) {
        if (VictorEngine.Parameters.DualWield.SeparatedAttack) {
            var right = VictorEngine.Parameters.DualWield.RightHandPrefix + ' ';
            var left = VictorEngine.Parameters.DualWield.LeftHandPrefix + ' ';
            var name = i === 0 ? right : i === 1 ? left : ''
            this.changeTextColor(this.systemColor());

            // 赤字の部分を改変しています。
            this.drawText(name + TextManager.param(i === 0 ?
                2 : this.convertParamName(i) + 1), x, y, 120);

        } else {
            VictorEngine.DualWield.drawParamName.call(this, x, y, i);
        }
    };
 この改変によって今回ご要望のパラメータ順に入れ替わるはずです。仕組みとしては、パラメータの並び順は配列で管理されているため、並び順がおかしくなっている箇所のみパラメータの ID を増減して調整しています。



 改変作業は以上になります。以下に改変後の動作を示す画像を添付しておきますのでお試しください。

①「ParamOrder.js」の設定のみ行った状態です。パラメータ名はデフォルトのままですが数値の並び順は入れ替わっていることが確認できます。
②パラメータの並び順が変更された上で、パラメータが正しく増加することを確認できます。
 

Attachments

  • 2025-01-12-03.png
    2025-01-12-03.png
    250.8 KB · 閲覧: 6
  • 2025-01-12-04.png
    2025-01-12-04.png
    251.4 KB · 閲覧: 6
本当に何度もすみません。

バグ(?)報告です。
①右手攻撃でエネミーを倒した時、左手攻撃を実行しない。
を選択して改変を行ったのですが、
稀に右手攻撃後、敵が生存しているのに左手攻撃を実行しないことがあります。
敵のHPがギリギリ右手攻撃で倒せそうなラインだと起こるようです。
新規プロジェクトにて確認しました。

元のプラグインの作者様ではないので
対応が難しい場合は仰ってくださいね。
 
バグ(?)報告です。
①右手攻撃でエネミーを倒した時、左手攻撃を実行しない。
を選択して改変を行ったのですが、
稀に右手攻撃後、敵が生存しているのに左手攻撃を実行しないことがあります。
敵のHPがギリギリ右手攻撃で倒せそうなラインだと起こるようです。
新規プロジェクトにて確認しました。
 調査してみた結果、恐らくこちらは私の改変コードによる不具合のようですね。真白灰様が確認されている不具合と同一の現象であるかは確認が難しい所ですが、私の方で再現性 100% と思われる状態で不具合を発生させることができたので対処を試みます。
 検証での不具合発生時の処理の流れとしては以下のようになっています。

①右手攻撃によってエネミーが倒される。
②左手攻撃をスルーするように改変しているため BattleManager.startDualWieldAction() が実行されない。
this._canSecondAttack プロパティが true のままとなり、次回の攻撃で BattleManager.startAction() から実行される BattleManager.setSecondAttack() の処理内容がスルーされてしまう。
④内部的には BattleManager.startDualWieldAction() が実行されているため、左手攻撃自体は暗黙に行われているが、上記③の影響で Game_Action() オブジェクトにスキルが設定されていないので左手攻撃を行っていないように見えている。

 このような感じでした。条件が揃えば確実に上記のようになるのですが、現象を確認するための不確定要素としては右手攻撃でエネミーが倒された後、次回の右手攻撃で選択したエネミーは右手攻撃によって倒されない必要があり、右手攻撃で確実にエネミーを倒せてしまう状態では不具合が確認できないため設計のミスに気付けませんでした。申し訳ありません。
 ちなみに、この不具合は一撃で倒せるエネミーと HP を多めに設定して一撃で倒せないエネミーを用意することで容易に再現できます。

 この不具合の修正には BattleManager.startAction() を修正する必要があります。以下のように修正をお願いいたします。

Rich (BB code):
    // VE_DualWield.js v1.04(このスレッドで改変したもの)
    VictorEngine.DualWield.startAction = BattleManager.startAction;
    BattleManager.startAction = function() {
        this._beforeTroopCount = $gameTroop.aliveMembers().length;

        // 追加したコード。
        this._canSecondAttack = false;

        this.setDualWieldAction();
        VictorEngine.DualWield.startAction.call(this);
        this.setSecondAttack();
    };
 this._canSecondAttack プロパティは BattleManager.setSecondAttack() のみが true を代入する仕組みとなっているため、それが実行される前に false を代入しておくことで意図せず処理がスルーされることを防ぎます。
 本来「VE_DualWield.js」では右手攻撃でエネミーを倒した時、不可視のエネミーのクローンに対して左手攻撃を行いプロパティをリセットしています。その流れを変更したことによって不具合が発生していました。同じ現象であれば上記によって発生しなくなるはずなので、お手数ですが修正をお願いいたします。

 また何か不具合があればお教えください。確約はできませんが多分直せます。
 
度々すみません。
VE_DualWieldは装備画面のステータス表示にも干渉していると思うのですが、
最大HPと最大MPも他のパラメータと同じように装備による変動前→変動後を表示したいです。
位置は攻撃力の上です。

上述のように射撃(運)の位置をいじっているため、それを崩さないようにお願いします。
 
最近フォーラムから離れ気味で確認が遅くなりました。申し訳ありません。

VE_DualWieldは装備画面のステータス表示にも干渉していると思うのですが、
最大HPと最大MPも他のパラメータと同じように装備による変動前→変動後を表示したいです。
位置は攻撃力の上です。

上述のように射撃(運)の位置をいじっているため、それを崩さないようにお願いします。
 #14での改変からさらに最大HPと最大MPの項目を装備画面に追加したいとのことですね。
 前回と同様、以下の環境で改変を行っていきます。

RPGツクールMZ v1.8.1
VE_BasicModule.js v1.23
VE_DualWield.js v1.04(このスレッドで改変済みのもの)
ParamOrder.js v1.0.1


 まず表示するパラメータを増やしたいところですが、「VE_DualWield.js」と「ParamOrder.js」の利用で既存の処理が複雑化してしまっているため、今回はシンプルにもともとのパラメータ表示位置をずらして空いた場所に最大HPと最大MPを別途表示する感じにしていきます。
 改変するプラグインは「VE_DualWield.js」のみです。

 はじめに「VE_DualWield.js」の以下のコードを改変します。
コード:
    // VE_DualWield.js v1.04
    Window_EquipStatus.prototype.drawDualWieldParameters = function(i) {
        if (i < 2 && this._actor.isDualWield()) {
            var index = this._actor.isLeftHanded() ? i === 0 ? 2 : 1 : i + 1;
            this._actor = this._copy;
            this._tempActor = this._temp;
            this._actor.ignoreEquipment(index);
            if (this._tempActor) {
                this._tempActor.ignoreEquipment(index);
            }
        } else {
            this._actor = this._originalActor;
            this._tempActor = this._originalTemp;
        }
        this.drawItem(0, (this.lineHeight() - 4) * (1 + i) - 2, i);
    }
 このコードは二刀流によるパラメータ表示などを行うためのもので、最下部の drawItem メソッドにて全体の表示位置を変更できます。

 最大HP・MPを攻撃力の上に表示したいので、パラメータのY座標を下げるために以下のように改変します。
Rich (BB code):
    // 改変後のコード。
    Window_EquipStatus.prototype.drawDualWieldParameters = function(i) {
        if (i < 2 && this._actor.isDualWield()) {
            var index = this._actor.isLeftHanded() ? i === 0 ? 2 : 1 : i + 1;
            this._actor = this._copy;
            this._tempActor = this._temp;
            this._actor.ignoreEquipment(index);
            if (this._tempActor) {
                this._tempActor.ignoreEquipment(index);
            }
        } else {
            this._actor = this._originalActor;
            this._tempActor = this._originalTemp;
        }

    // 改変箇所。
    this.drawItem(0, (this.lineHeight() - 4) * 2 + (this.lineHeight() - 4) * (1 + i), i);

    }
 Y座標の引数が変わっています。計算がややこしくなっていますが、[開始位置]+[一行の高さ]ですね。
 この改変によって以下の画像のように空白ができました。

2025-10-16-01.png

 次は空いたスペースに最大HPと最大MPの項目を追加します。



 先述した通り、既存のパラメータの表示処理が複雑化してしまっているので、追加のメソッドを「VE_DualWield.js」のプラグインファイル内に定義していきます。といっても、だいたいはコアスクリプトと同じようなコードとなっています。

 以下の5つのメソッドをプラグイン内に追加してください。
コード:
    // 追加するメソッドその1。
    Window_EquipStatus.prototype.drawMaxHpMp = function() {
        for (let i = 0; i < 2; i++) {
            const x = this.itemPadding();
            const y = this.lineHeight() - 4;
            this.drawHpMp(0, y * (i + 1), 0 + i);
        }
    };
 パラメータを並べて表示する処理です。最大HPのパラメータのIDが[0]、最大MPのパラメータのIDが[1]となっているため、for文による繰り返し処理で順番に指定される仕組みです。

コード:
    // 追加するメソッドその2。
    Window_EquipStatus.prototype.drawHpMp = function(x, y, paramId) {
        const paramX = this.paramX();
        const paramWidth = this.paramWidth();
        const rightArrowWidth = this.rightArrowWidth();
        this.drawMaxHpMpParamName(x, y, paramId);
        if (this._actor) {
            this.drawCurrentMaxHpMpParam(paramX, y, paramId);
        }
        this.drawRightArrow(paramX + paramWidth, y);
        if (this._tempActor) {
            this.drawNewMaxHpMpParam(paramX + paramWidth + rightArrowWidth, y, paramId);
        }
    };
 これはパラメータの変動前と変動後を表示する処理です。以下の3つのメソッドを用いてパラメータ名・現在の値・変動後の値を表示します。

コード:
    // 追加するメソッドその3。
    Window_EquipStatus.prototype.drawMaxHpMpParamName = function(x, y, paramId) {
        const width = this.paramX() - this.itemPadding() * 2;
        this.changeTextColor(ColorManager.systemColor());
        this.drawText(TextManager.param(paramId), x, y, width);
    };
 パラメータ名を表示する処理です。

コード:
    // 追加するメソッドその4。
    Window_EquipStatus.prototype.drawCurrentMaxHpMpParam = function(x, y, paramId) {
        const paramWidth = this.paramWidth();
        this.resetTextColor();
        this.drawText(this._actor.param(paramId), x, y, paramWidth, "right");
    };
 パラメータの現在の値を表示する処理です。

コード:
    // 追加するメソッドその5。
    Window_EquipStatus.prototype.drawNewMaxHpMpParam = function(x, y, paramId) {
        const paramWidth = this.paramWidth();
        const newValue = this._tempActor.param(paramId);
        const diffvalue = newValue - this._actor.param(paramId);
        this.changeTextColor(ColorManager.paramchangeTextColor(diffvalue));
        this.drawText(newValue, x, y, paramWidth, "right");
    };
 変動後のパラメータを表示する処理です。

 以上のメソッドを追加することで、最大HPと最大MPを表示する準備が整いました。最後に以下のコードを改変します。
コード:
    // VE_DualWield.js v1.04
    VictorEngine.DualWield.refresh = Window_EquipStatus.prototype.refresh;
    Window_EquipStatus.prototype.refresh = function() {
        if (VictorEngine.Parameters.DualWield.SeparatedAttack) {
            this.contents.clear();
            if (this._actor) {
                this.drawActorName(this._actor, this.textPadding(), 0);
                this.prepareStatusCopy();
                var dualwield = this._actor.isDualWield();
                for (var i = 0; i < 7; i++) {
                    this.drawDualWieldParameters(i);
                }
                this.clearStatusCopy();
            }
        } else {
            VictorEngine.DualWield.refresh.call(this)
        }
    };
 これはウィンドウ内の情報を再表示するための処理です。内部的には操作する度に動いています。
 この中に先ほど追加したメソッドを以下のように追加します。

Rich (BB code):
    // 改変後のコード。
    VictorEngine.DualWield.refresh = Window_EquipStatus.prototype.refresh;
    Window_EquipStatus.prototype.refresh = function() {
        if (VictorEngine.Parameters.DualWield.SeparatedAttack) {
            this.contents.clear();
            if (this._actor) {
                this.drawActorName(this._actor, this.textPadding(), 0);
                this.prepareStatusCopy();
                var dualwield = this._actor.isDualWield();

                // 改変箇所。
                this.drawMaxHpMp();

                for (var i = 0; i < 7; i++) {
                    this.drawDualWieldParameters(i);
                }
                this.clearStatusCopy();
            }
        } else {
            VictorEngine.DualWield.refresh.call(this)
        }
    };
 追加したメソッドその1を処理に加えました。これで最大HPと最大MPが装備画面に表示されます。

 雑な画像ですが、以下のようにこれまでのパラメータの表示を保持しつつ、最大HPと最大MPが攻撃力の上に追加で表示され、かつパラメータの変動後の値も正しく動作していることが確認できます。

2025-10-16-02.png


 以上となります。恐らく不具合は無いかと思われますが、こちらにてお試しください。
 
Back
トップ