rpg_**.jsの気になるところを書くスレ

しぐれん

ユーザー
ツクールMVの本体スクリプトはどれも非常に明快でわかりやすいです。
しかし、非情に冥界でよくわからない書き方になっていたり、肝心なところで処理をフックするタイミングが存在しなくて辛いという局面もあります。

愚痴ばかり書いても仕方ないですが、「ここをこうしてほしい」という話をまとめておけば、今後の改善につながるかもしれないと思います。
なので、「こんなことを書いたらよくない」などと思わず書いてみましょう。
 

しぐれん

ユーザー
Scene_Battle.changeInputWindow、ターン処理の最中でエフェクトが飛び交っている最中でも
endCommandSelection()を呼び続けるのやめてほしい。
1回だけ呼びだす処理に直せないものか。
状態が変更されたタイミングを捕まえるのって難しいけど、なんとかしたい感じがある。
せめて、入力開始と入力終了は取得できるようにしたい。
(こういう本体スクリプトへのプルリクエストって、どこで受け付けているんだろうか)

追記
isAnyInputWindowActive()の再定義がいつも面倒。
Scene_BattleにWindowを追加すると、いつもこれで困る。
addSelectWindowとかで、activeが変動するwindowをまとめて登録できないか?
 
最後に編集:
どうも、しぐれんさん。
なかなか言い出しにくいことを書いてくれてありがとうございます。

ひとまず、ひとつだけ書きますね。
Game_Picture クラスは、Game_Screen クラスで管理されていて、1~100番のIDで管理されていますが、
そのIDは、Game_Picture 側には管理されてないんですよね。
よって、「このピクチャのIDを知りたい」って場合、常に$gameScreen を呼び出す手間がかかって大変でした。

もちろん、こうなった理由はわかります。ピクチャは、マップと戦闘で異なる値を使っていて(1~100と101~200)、
そこに起因する混乱を避けたかったんでしょう。
しかし、Sprite_Picture を操作したくなったとき、この仕様はきわめて不便に感じました。
おかげでプラグインがえらく冗長になってしまいました。

「無用な混乱を避けるため」という尾島氏の意図は理解できるので僕はこれを責めません、
しかし、それが原因でプラグイン作者が不便を強いられるケースがあることは考慮してほしかったです。

[余談]
この手の「ツクール製品に対する批判」は、どうしても委縮してしまいます。
でも、改善のためなら……と思い、胃薬飲みながら書かせていただきました。
 

しぐれん

ユーザー
>サスケさん
$gameScreenを調べないといけないのは、クラスの設計的によくない予感がしますね。
勝手に番号を追加するわけにも行かないですし…
ただ、勝手に番号を追加するとしたら、どういう実装になるのでしょう?
プラグイン作者が手間取るのも、一つの混乱ではないかと思います。

序盤で投稿した処理について、以下のコードで修正ができました。
これで、入力が完了したとき1回だけendCommandSelection()が呼び出せます。
githubの使い方もわかってきたので、コミュニティ版にpull requestを投げるのも検討しているのですが、どうなんでしょう。

PHP:
const Scene_Battle_selectNextCommand = Scene_Battle.prototype.selectNextCommand;
Scene_Battle.prototype.selectNextCommand = function() {
    Scene_Battle_selectNextCommand.call(this);
    if(!BattleManager.isInputting()){
        this.endCommandSelection();
    }
};
Scene_Battle.prototype.changeInputWindow = function() {
    if (BattleManager.isInputting()) {
        if (BattleManager.actor()) {
            this.startActorCommandSelection();
        } else {
            this.startPartyCommandSelection();
        }
    } else {
//        this.endCommandSelection();
    }
};
 

尾角つの

ユーザー
>しぐれん様
すみません、コミュニティにそれを投稿するのはちょっとまってください。
私が今制作したATBのシステムで、changeInputWindowでendCommandSelectionを行う事を前提とした部分があるために、そこに手を入れられると大変困ります><

でも、最初からそういう風になってなければよかったのですけどね……
 

尾角つの

ユーザー
ちょっと慌てててすみません。
詳しく言うと、デフォルトでは入力終了時にコマンド終了となるのですが、自作のATBだとコマンドを中断する際にもコマンド入力終了となっております。
バトルマネージャー上で中断処理を行い(入力状態をfalseに)、その後、バトルシーン上のchangeInputWindowでその状態を判別して処理、となっております。
 
最後に編集:

尾角つの

ユーザー
ちょっと、スレの内容を中断させたらまずいかなとも思ったので、バトル周りで気になったところを僕も少し。

先の、isAnyInputWindowActiveではATB作るときに少し思うところがありました。
ウィンドウを全部手作業で判定するより、バトルシーン作成時に
this._inputWindows = [];
して、入力ウィンドウをそれにいれる形にできたらなあと考えてます。
ATBの中断処理の際にも、手作業で全部の入力ウィンドウを判定して非アクティブ化する処理があるので、他の方の素材使うときにまた手作業で処理加えなきゃいけないなぁと……入力ウィンドウを共通化できたらすごい楽です。

あとは、アクターが全行動終了した際に、processTurn内でアクション終了処理あるのですが、あの部分を個別化したら、他者さんのプラグイン(主にYanfly Battle Engine Core)と競合回避しやすいなぁと考えてます。

BattleManager.processTurn = function() {
var subject = this._subject;
var action = subject.currentAction();
if (action) {
action.prepare();
if (action.isValid()) {
this.startAction();
}
subject.removeCurrentAction();
} else {
this.endAllActions(); // ←ここ
}
};

そしてそのなか(アクター行動終了)の最後で次の行動者を取得してるのですが、個人的に取得せずに、nullの方がありがたいなぁと思いました。
this._subject = this.getNextSubject(); → this._subject = null;
updateTurn 内で次の行動者は取得されてるので問題ないよなぁとも思ってるのですが、ただ、ここを改変したら他の方の設計(主にYanfly Battle Engine Core)に問題が出そうな気がしたので、endAllActions に個別化するだけでも競合取りやすくて助かるところです。
(他の方でも、この中(endAllActionsに当たる箇所)だけを改変されてる方をちらほら見かけてます。)
 
最後に編集:

尾角つの

ユーザー
ちょうどいいので、自作のATBを参考用に公開します……
レイアウト周りを全く実装してなくてテストが終わってない中途半端品、多分自作のレイアウトプラグインはMITでは配布しないと思うので、使えないプラグインですが、実装の参考になればと思います。
 

Attachments

しぐれん

ユーザー
>尾角つのさん
endAllActionsの個別化は、確かに欲しいですね。
logWindowにも同様のメソッドが欲しいところ。

endCommandSelection()の移動は破壊的変更でしたが、これをいれずに処理する方法を見つけました。
(別の場所に、入力が完了したときの処理を追加する)

他だと、
BattleManager.startAction()にある、
subject.useItem(action.item());ですね。
このuseItemは戦闘時以外でも使われているため、再定義しづらいです。
BattleManagerにフックポイントが欲しいです。

Battlerから画面上のスプライトを取得する手段がないのもなかなか辛い話です。
YEP_BattleEnegineCoreにBattleManager.getSprite()というメソッドがあるんですが、これは本体にも欲しいですね。
色々な人が似たような機能を作ると大変ですし。
 

尾角つの

ユーザー
endCommandSelectionの処理見つかってよかったです!
僕も、不必要に何度も呼び出されてるのは少し気になってはいましたので……根本的な変更が必要だけど、でも変更できないもどかしさがある箇所な気もします。ちゃんと動くので気にしない派ですが(笑)

startAction の useItem はATBのゲージ消費するときに、「あ、ここでは使えない!」ってなったので、遠回りな処理で対応したりしてます><
ここも、互換性の問題ありそうですし、たしかに、フックほしいです!

バトルスプライト取得は意図的に取得しないような実装になってる気もします。(DoとViewを分けてる……?)
アクターのアクションも遠回しに動き状態設定してから、それをスプライトで読んで動かすという感じでしょうか。
スプライトとバトラーが常に同一キャラとは限らない作りだったので、メンバー変更などを行ったときにバグる可能性を回避しているのかもしれないですね……
これから、レイアウト作るのにちょっと苦戦しそうです><
 
最後に編集:

尾角つの

ユーザー
あ……デフォルトと関係ないですが、自作ATBでendCommandSelectionが何度も呼び出されるのは自分のせいでした(激汗)
修正版置いときます……;;
(こういうスレあると気づけて助かります……)
 

Attachments

剣崎宗二

ユーザー
お疲れ様です。最近プラグイン作っていて気になった事態が1点あったので。
Game_Actionのtargetindex辺りの処理を見ればわかるのですが、
Game_Actorは_actorIdがPrimaryKey(認識ID)になっているのに対し、Game_Enemyは相当する要素がなくGame_TroopのindexOfを使ってます。

これは色々と面倒くさい事態に繋がりやすく、一番簡単な所では何かしらの理由でGame_Troopをソートした場合ズレる。
他にも、例えば「前ターンの状態に戻す」のような機能の為に前のターンの状態を記録した場合、それが現在のターンに於ける度の敵なのかの繋がりを示す要素がないのです。(オブジェクトをindexOfする場合、要素が一つでも違ってると該当せずという結果になります)

Game_Troop生成の際、存在する全Game_EnemyにIdを振ってもいいと思うのですけどね…
現在何番まで振ったか、と言うフィールドを保持しておき、何かしらの理由で新規にGame_Troopにメンバー追加をする際はその番号を++して振る等。

以上、個人意見でした。
 

しぐれん

ユーザー
BattleManager.applyAction()が欲しいと一瞬思ったのですが、Game_Action.apply()をフックしてBattleManagerを呼びだせばいいと気づくの巻き。
アクション終了直後はGame_ActionResultに大量の情報があるので、色々と使い勝手がいいんですよね。

>剣崎宗二さん
戦闘中にエネミーがソートされるのを想定していなかったから、こうなっているんでしょうね。
これはTroop生成の時にできますし、案外可能な気がします。
 

剣崎宗二

ユーザー
>しぐれんさん
target.result()に有用な情報が多く入ってるのは同意ですね。結構早くclearされてしまうので救出する必要はありますが・・・

EnemyIdの件は寧ろ「事前の状態をセーブする」方で困ってる事が多いですね。スキル連鎖の時もそれで結構頭の痛い事になってましたし。
 

しぐれん

ユーザー
Game_Interpreter.prototype.command111(条件分岐の処理)ですが、まさか判定とジャンプを同一関数内でやっていたとは。
判定部分だけ別の関数にして欲しかったです。
フックするタイミングがないので、改造しようがないですね。
 
トップ