battleにおいてtargetindexを取得したいです

返信する
maker-b
記事: 112
登録日時: 2016年3月27日(日) 22:03
連絡する:

battleにおいてtargetindexを取得したいです

投稿記事 by maker-b »

皆様
大変お世話になっております。
現在、FF12のようなガンビットプラグインを作成しております。

ガンビットを装備することで、actorがそのガンビット通りの動きをするというオートバトルに近いかたちです。
ガンビットプラグインは
相手を指定する「ガンビット」部分と行動を決定する「アクション」を組み合わせて設定する予定にしておりますが

この相手を指定する部分のコードをどうするのか悩んでいます。

オブジェクトGame_Actionのプロパティ TargetIndex に値を入れれば良い、という部分までは理解しておりますが
その値を導き出すロジックの書き方をアドバイスいただけないでしょうか。

わかりにくいので、具体的に例を出すと
ガンビット<HPが最も低い敵>
と設定した場合、(これは、防具のmetaデータを読み込むことで解決予定です)

0 防具metaデータから<ガンビット:HPが最も低い敵>を読み込む

1 すべてのエネミーのHPを比較して、最もHPが低いエネミーのIDを取得する

2 Game_Actionオブジェクトのtargetindexプロパティに値をセットする

というスクリプトです。
0と2は自力で解決できそうなので、本ご質問は1部分になります。

お知恵をいただけるとありがたいです。
アバター
Plasma Dark
記事: 736
登録日時: 2020年2月08日(土) 02:29
連絡する:

Re: battleにおいてtargetindexを取得したいです

投稿記事 by Plasma Dark »

コード: 全て選択

Game_Unit.prototype.minHpAndAliveTarget = function() {
  return this.aliveMembers().reduce((a, b) => {
    return a && a.hp < b.hp ? a : b;
  }, null);
};
こんな感じで最もHPの低い かつ 生きている対象を取得できるんじゃないかと思います。
Game_Actionの_targetIndexに入れるべきはIDではなくindexであることに注意してください。
Game_ActorやGame_Enemyにはindexメソッドが定義されており、それで取得できるので、ランダムにターゲットを決める際の処理と似たような感じでできるんじゃないでしょうか。
最後に編集したユーザー Plasma Dark [ 2020年10月01日(木) 18:21 ], 累計 1 回
maker-b
記事: 112
登録日時: 2016年3月27日(日) 22:03
連絡する:

【解決済み】Re: battleにおいてtargetindexを取得したいです

投稿記事 by maker-b »

Plasma Dark 様

早速のご回答ありがとうございます!
頂いたコードを参考に暫定で完成しました!

引数target には、ベタの計算式が入っているものとし、

コード: 全て選択

    Game_Actor.prototype.makeGambitTroop = function(target){//ガンビットのEVALをそのまま実行して、targetを返す
        return $gameTroop.members().indexOf(eval(target));
    }

    Game_Actor.prototype.makeGambitParty = function(target){//ガンビットのEVALをそのまま実行して、targetを返す
        return $gameParty.members().indexOf(eval(target));
    }
evalは速度、セキュリティ面からもあまりおすすめじゃないようですが・・・
アバター
Plasma Dark
記事: 736
登録日時: 2020年2月08日(土) 02:29
連絡する:

Re: battleにおいてtargetindexを取得したいです

投稿記事 by Plasma Dark »

evalは速度、セキュリティ面からもあまりおすすめじゃないようですが・・・
そうですね。おすすめはしません。
複雑な判定が入らない前提であれば、独自の記法を定義して正規表現か何かで読んでしまうのが一番手軽だと思います。

具体的な実装がわからないので想像で話しますが、以下のような感じでevalを避ける実装は可能であるかと思います。
防具のmetaに <gunbitTarget: minHpAndAlive> などと定義し、もしそうであった場合に $gameTroop.minHpAndAliveTarget() で取得するとか。
maker-b
記事: 112
登録日時: 2016年3月27日(日) 22:03
連絡する:

Re: battleにおいてtargetindexを取得したいです

投稿記事 by maker-b »

Plasma Dark 様

即レスありがとうございます!
非常に参考になります。
そうですね、ある程度、ガンビットの種類が整ってきたら、そのやり方のほうが賢いですよね。。。
勉強になります!

ちなみに、

コード: 全て選択

aliveMembers().reduce((a, b) => {
    return a && a.hp > b.hp ? a : b;
  }, null);
頂いたこのコードを活用して、最大HPが80%を下回ったtarget(複数の場合は最も差があるtarget)を選定したいとおもっていますが
もし、お時間いただけるようでしたら、お教えいただけるとありがたいです。
reduceの使い方をネットでしらべましたが、いまいち・・・ピンとこず、すみません。
アバター
Plasma Dark
記事: 736
登録日時: 2020年2月08日(土) 02:29
連絡する:

Re: battleにおいてtargetindexを取得したいです

投稿記事 by Plasma Dark »

頂いたこのコードを活用して、最大HPが80%を下回ったtarget(複数の場合は最も差があるtarget)を選定したいとおもっていますが
HPが最大のN%未満 かつ まだ戦闘不能になっていないメンバーのうち、最も残りHP割合の低いメンバーを返す関数(該当者なしの場合はnullを返す)を定義してみます。

コード: 全て選択

/**
  * 戦闘不能でない、最もHP割合の低いメンバーを返す
  * @return {Game_Battler|null}
  */
Game_Unit.prototype.minHpRateAndAliveMember = function() {
  return this.aliveMembers().reduce((a, b) => {
    return a && a.hpRate() < b.hpRate() ? a : b;
  }, null);
};

/**
  * 戦闘不能でなく、HP割合が一定未満かつ、最も低いメンバーを返す
  * 該当者なしの場合はnullを返す
  * @param {number} threshold 閾値
  * @return {Game_Battler|null}
  */
Game_Unit.prototype.hpRateLessThanAndAliveMember = function(threshold) {
  const member = this.minHpRateAndAliveMember();
  return member && member.hpRate < threshold ? member : null;
};
Array.prototype.reduce は慣れるまでちょっとわかりにくいかもしれません。
例えば、配列の中の値を順番に同じように処理していって最終的に1つの値を得たい場合に使います。すべて足した合計が欲しいとか、そういう場合に使うものです。

今回のコードでは、順番にHPを比較して小さいほうを結果として残す、を繰り返しているので、最終的にHPが最小の対象が得られるというわけです。
最後に編集したユーザー Plasma Dark [ 2020年10月01日(木) 18:22 ], 累計 1 回
maker-b
記事: 112
登録日時: 2016年3月27日(日) 22:03
連絡する:

Re: battleにおいてtargetindexを取得したいです

投稿記事 by maker-b »

Plasma Dark 様

早速のご回答ありがとうございます!
大変参考になります。
やはり、evalではなく、ガンビット単位で関数を作っていったほうが安全っぽいですね・・・

コード: 全て選択

this.aliveMembers().reduce((a, b) => { return a && a.hpRate() > b.hpRate() ? a : b;}, null);
reduceの説明もありがとうございます。
いただいたコードを熟読しました。
reduce構文は
配列.reduce(function(累積値, 要素) { })
ということらしいですね。
return以降の計算を、配列内で総当りする、というイメージでしょうか?
この場合、
配列 一番目と二番目のメンバーのjprateを比較し、 一番目のレートが高ければ 採用!
次にすすむ、二番目のレートが高ければ、それを採用、次に進む、という意味ですよね?

もっと勉強します!
ありがとうございます!
アバター
Plasma Dark
記事: 736
登録日時: 2020年2月08日(土) 02:29
連絡する:

Re: battleにおいてtargetindexを取得したいです

投稿記事 by Plasma Dark »

rate低いほう採用しないと仕様と逆になっちゃうので、これまでの書き込みのコードの不等号逆にしました。不等号逆転、よくやっちゃうんですよね。
返信する

“MZ:質問”に戻る