ページ 11

【解決済】敵に攻撃してダメージを与えると経験値を取得するプラグインを作成していますが、少し問題点が……

Posted: 2020年4月15日(水) 20:12
by みたしや
敵を攻撃すると経験値を取得し、一定量攻撃の総ダメージが1000(レベルによって2000や3000にもなる)を超すとレベルが上がる(仲間全員、まだ仲間になってない人も含む。)といったプラグインを作成しています。
それに加えて倒した敵の経験値を貰い。
他にも人に話しかければ経験値を取得する事が出来る物です。

2点ほど問題を抱えておりまして……

・一つ目
ツクールMVのバージョン1.3.3では正常に動いていたものが
ツクールMVのバージョン1.6.2では可笑しな数値になってしまう事です。

動作してほしい物
・敵に攻撃してダメージ量(変数42)を維持してほしい。バトルが終わった後も継続してほしい。
・バトル中にレベルが上がったら、上がったままのステータスになっててほしい。

おかしい表示のされ方
・敵に与えたダメージを格納している変数42が戦闘終了時に0になってしまう。
・戦闘中にレベルが上がったはずなのに、戦闘終了後はレベルが上がっていない。
(レベル1のままで戦闘した場合、レベル1のまま戦闘終了。仲間にしていない人はレベルが上がっている。)
キャプチャ.jpg
キャプチャ2.jpg
キャプチャ3.jpg
キャプチャ4.jpg
プラグイン内で設定した変数は……
敵に与えたダメージ量を変数42 attackDamege
現在のレベルを表す変数41 level_Exp
レベルアップに必要な壁として exp_wall を設定しています。

構成を説明すると……

【敵に攻撃を与えた処理】→【attackExpで取得した変数量を割り振る処理】
【敵を倒した経験値を受け取る処理】→【attackExpで取得した変数量を割り振る処理】

【敵に攻撃を与えた処理】
Game_Action.prototype.executeHpDamageをいじっています。
独自に作ったthis.attackExp()に移動します。

コード: 全て選択

var _prevfunc = Game_Action.prototype.executeHpDamage;
  Game_Action.prototype.executeHpDamage = function(target, value) {
    _prevfunc.call(this, target, value);

    const attackDamege = $gameVariables.value(42);
    const level_Exp = $gameVariables.value(41);

    if (this.isSkill() && target.isEnemy()) {
      $gameVariables.setValue(42, attackDamege + value);

    }
    //経験値取得のソースへ
    this.attackExp();
  }

【敵を倒した経験値を受け取る処理】
倒した敵の経験値量が足されます。

コード: 全て選択

//敵を倒して経験値取得の処理
  Game_Actor.prototype.gainExp = function(exp) {
    const attackDamege = $gameVariables.value(42);
    const level_Exp = $gameVariables.value(41);
    var newExp = this.currentExp() + Math.round(exp * this.finalExpRate());
    $gameVariables.setValue(42, Math.round(exp * this.finalExpRate()));
    newExp = 0;
    this.changeExp(newExp, this.shouldDisplayLevelUp());

    //経験値取得のソースへ
    Game_Action.prototype.attackExp();
  };


【attackExpで取得した変数量を割り振る処理】
【敵に攻撃を与えた処理】、【敵を倒した経験値】の後に置かれています。

コード: 全て選択

  //attack_expの処理
  Game_Action.prototype.attackExp = function() {

    const attackDamege = $gameVariables.value(42);
    const level_Exp = $gameVariables.value(41);

    const exp_wall_1 = 1000;
    const exp_wall_2 = 2000;
    const exp_wall_3 = 5000;
    const exp_wall_4 = 9000;

    const party_member = 14;


    //第一段階の経験値が必要の壁
    if (attackDamege > exp_wall_1 && 0 < level_Exp && level_Exp <= 10) {

      $gameVariables.setValue(41, level_Exp + 1);
      $gameVariables.setValue(42, attackDamege - exp_wall_1);

      for (var n = 1; n < party_member; n++) {
        const oldlevel = $gameActors.actor(n).level;
        $gameActors.actor(n).changeLevel(oldlevel + 1, false)
        console.log($gameActors.actor(n).name() + "のレベルが上がりました");
        console.log($gameActors.actor(n).level);
      }

      //仲間のHPを全回復する
      $gameParty.members().forEach(function(actor) {
        Game_Interpreter.prototype.changeHp(actor, 9999, true);
      }.bind(this));

      //もう一度レベルアップ調整を行うか? の処理
      if (attackDamege > exp_wall_1) {
        this.attackExp();
        return true;
      } else {
        return false;
      }
    }
    
    ………
Game_Objectを探していますが、原因が分かりません。

↓続きます

Re: 敵に攻撃してダメージを与えると経験値を取得するプラグインを作成していますが、少し問題点が……

Posted: 2020年4月15日(水) 20:16
by みたしや
・二つ目
人に話しかければ経験値を取得する
時に可笑しな表示のされ方になってしまう。
キャプチャ5.jpg
キャプチャ6.jpg
プラグインコマンドで記述してargs[0]分だけ取得するという処理をしてほしいのですが……

一回目は40が代入されるが、二回目以降は加算されずに
attackExp()が関係しているのか何故か変数41が上昇してしまう。

コード: 全て選択

var _attackExp_pluginCommand = Game_Interpreter.prototype.pluginCommand
  Game_Interpreter.prototype.pluginCommand = function(command, args) {
    _attackExp_pluginCommand.call(this, command, args)
    if (command === "attack_Exp") {
      const attackDamege = $gameVariables.value(42);
      $gameVariables.setValue(42, attackDamege + args[0]);
      //経験値取得のソースへ
      Game_Action.prototype.attackExp();
    }
    return true;
  };
長文になりましたがどなたか解決できる方がいらっしゃいましたら
教えて頂けると助かります。
Attack_exp.js
(31.45 KiB) ダウンロード数: 7 回

こちらがプラグインになります。

また画像出力の問題はないと感じたので
今回は説明を省かせていただきます。

Re: 敵に攻撃してダメージを与えると経験値を取得するプラグインを作成していますが、少し問題点が……

Posted: 2020年4月15日(水) 21:32
by Plasma Dark
おお……1000行オーバーの超大作ですね。
一つずつ見ていきましょう。
敵に与えたダメージを格納している変数42が戦闘終了時に0になってしまう。
控えメンバーも経験値を獲得 の設定がOFFになっていませんか?
Game_Actor.prototype.gainExp 関数は戦闘に勝利した後、控え含む全メンバーに対して実行されます。
控えメンバーも経験値を獲得 の設定がOFFになっている場合、 Game_Actor.prototype.finalExpRate が返す値は 0 です。

Re: 敵に攻撃してダメージを与えると経験値を取得するプラグインを作成していますが、少し問題点が……

Posted: 2020年4月15日(水) 21:35
by Plasma Dark
戦闘中にレベルが上がったはずなのに、戦闘終了後はレベルが上がっていない。
Game_Actor.prototype.changeExp に 0 を渡しているようです。

Re: 敵に攻撃してダメージを与えると経験値を取得するプラグインを作成していますが、少し問題点が……

Posted: 2020年4月15日(水) 22:02
by Plasma Dark
プラグインコマンドで記述してargs[0]分だけ取得するという処理をしてほしいのですが……

一回目は40が代入されるが、二回目以降は加算されずに
attackExp()が関係しているのか何故か変数41が上昇してしまう。
args[0]は文字列型です。
1回目の実行で、変数42の値は "40" になります。
"40" + "40" = "4040" ですので、2回目の実行では変数42の値は "4040" になります。

その後の処理は複雑で追えていませんが、ひとまずargs[0]を数値型に変換してあげてみてはいかがでしょうか。

Re: 敵に攻撃してダメージを与えると経験値を取得するプラグインを作成していますが、少し問題点が……

Posted: 2020年4月15日(水) 23:05
by Plasma Dark
そして、あまりにもパワーのあるコードでしたので、経験値獲得部分だけ書き直した版をアップしておきます。
動作確認はしていませんので、これをそのまま用いることはおすすめしませんが、参考までにどうぞ。

まず、仕様としては、アクター個別の経験値システムを無視して全員に共通の経験値を持たせるということのように見えました。
つまり、経験値を獲得する主体は誰かというと、アクターではなくパーティである、としたほうが正しそうです。
(厳密には仲間になっていないアクターがパーティメンバーに含まれるわけではないのですが、今回はちょっとパーティの言葉の意味を広げています)

そのため、経験値獲得とそれに伴うレベルアップ処理を Game_Party にまとめました。
Game_Actionは戦闘中の行動を表すクラスですので、そのクラスに経験値獲得処理がまるごと書かれているよりはこちらのほうが意味が通りやすいでしょう。

他にも、必要経験値の記述を工夫して、冗長なレベルアップ処理をまとめたり、再帰を使わずにループで必要分だけレベルアップ処理を行ったりしています。

Re: 敵に攻撃してダメージを与えると経験値を取得するプラグインを作成していますが、少し問題点が……

Posted: 2020年4月16日(木) 13:05
by みたしや
Plasma Dark 様

パワーのあるソース作ってごめんなさい。
1000文字以上はMoguhunter様のActor_hudをまねて作っていたもので……
(動けばいいか。精神で作っているモノで効率性とか全く考えずに慣れるまで作っている物で……)

自分なりにPlasma Dark 様の助言を考慮しつつ、どこを直した方がいいか考えていたら……。

まさかソースも作り直していただけるとは!?
大切な時間を割いていただきまして本当にありがとうございます。
(実は、あきらめ半分で質問コーナーに投げて誰か解決してくれればいいかな~精神で待っていたので。)

提供していただきましたプログラムはソースでは動かなかった為。
【経験値処理用】と【画面表示用】の二つにファイルを分けたら動いたのでそのまま使いたいと思います。




:arrow: :arrow: :arrow: あと、もう一つだけお仕事を頼んでもいいですか?(調子に乗ってすいません。)

補足で付け忘れたのですが、【TMPlugin - スキルコスト拡張】を使いLVを消費して強力な技を出したかったので。
新たに(レベルを消費して超強力な技を出した後にプラグインコマンドを呼び出し、レベルがダウンする処理)を加えています。

 そこで問題となってしまったのが、レベルを消費したのに超強力な技(ダメージ10000)を出すとダメージが加算されて逆にレベルが上がってしまうという点です。

また、このソースの注釈に
回復されると経験値が減るが、それは正しい?
とありましたが、これは意図していない処理です。



この二つの問題を解決するため
【プレイヤーが使用するスキルのメモ欄に<noExpcount>と書いてあったら敵を攻撃してもカウントされない】
という物を加えたいと考えているのですが……
キャプチャ.JPG
と出力されてしまいます。

編集している部分のコードは

コード: 全て選択

  const _Game_Action_executeHpDamage = Game_Action.prototype.executeHpDamage;
  Game_Action.prototype.executeHpDamage = function(target, value) {
    _Game_Action_executeHpDamage.call(this, target, value);

    // スキルによって敵HPが変動した場合に経験値を変動させる
    // 回復されると経験値が減るが、それは正しい?
    if (this.isSkill() && target.isEnemy()) {

      //レベル消費技で敵に与えたダメージが入らないようにする。
      //スキル欄のメモ欄に noExpcount があった場合処理を飛ばす。
      const index = Window_BattleStatus.prototype.index();
      const skill = $dataSkills[index];
      if (skill.meta.noExpcount) {
        return false;
      }
      if (!skill.meta.noExpcount) {
        //攻撃すると経験値が入る。
        $gameParty.gainExp(value);
        return true;
      }

    }
    console.log("攻撃処理終了");
  }

と書いています。

メモ帳のmetaデータから出力するというやり方がよく分からない(やったことがない)ので
再度、スキルのメモ帳から<noExpcount>を検出する方法を教えて頂けると助かります。
よろしくお願いします。
Attack_exp_Refactor.js
(6.12 KiB) ダウンロード数: 1 回
↑一応、編集したソースを置いておきます。

Re: 敵に攻撃してダメージを与えると経験値を取得するプラグインを作成していますが、少し問題点が……

Posted: 2020年4月16日(木) 21:56
by Plasma Dark
パワーのあるソース作ってごめんなさい。
1000文字以上はMoguhunter様のActor_hudをまねて作っていたもので……
(動けばいいか。精神で作っているモノで効率性とか全く考えずに慣れるまで作っている物で……)
パワーがあるというのは必ずしも悪い意味ばかりではありません。
保守性は二の次にしてとりあえず動かしてやる、という情熱が感じられるので、私としては羨ましくもあります。

Sprite周りの記述から薄々そうだろうなとは思っていましたが、やはりMOGプラグインを参考にされてしまいましたか。
MOGプラグインは機能は大変優れているものが多いですが、コードの書き方は悪い見本を通り越して邪悪ですらあるので、真似しないほうが良いです。
とは言え、画像表示系のプラグインでパッとお手本になるものが思い浮かばないのですが……。
提供していただきましたプログラムはソースでは動かなかった為。
【経験値処理用】と【画面表示用】の二つにファイルを分けたら動いたのでそのまま使いたいと思います。
MOGプラグインと同じ書き方をしてしまうと、 strict モードを有効にした際に動かなくなるんでしょうね。
ちなみに、strictモードはよっぽど事情がない限り有効にしておくべきものです。
メモ帳のmetaデータから出力するというやり方がよく分からない(やったことがない)ので
再度、スキルのメモ帳から<noExpcount>を検出する方法を教えて頂けると助かります。
よろしくお願いします。
$dataSkills から取得するべきものであるという点はあっていますが、 $dataSkills はデータベース上に定義された全スキルのオブジェクトが配列になったものです。
インデックスとスキルIDが一致しているのですが、使用したスキルのIDをどうやって取得するか、というところが間違っています。

Game_Actionは戦闘中のバトラーの行動を表します。
デフォルトのRPGツクールMVの戦闘において、バトラー(戦闘の参加者)が行える行動は、スキルの使用かアイテムの使用の2択です。(データベースを見ればわかるように、通常攻撃も防御も内部的にはスキル扱いです)

行動で使用したスキルやアイテムのデータは、 Game_Action.prototype.item 関数で取得できます。
ですので、 this.item().meta.noExpcount と書けば取得できそうです。

コード: 全て選択

const _Game_Action_executeHpDamage = Game_Action.prototype.executeHpDamage;
Game_Action.prototype.executeHpDamage = function(target, value) {
  _Game_Action_executeHpDamage.call(this, target, value);
  if (this.isSkill() && target.isEnemy() && !this.item().meta.noExpcount) {
    $gameParty.gainExp(value);
  }
}

Re: 敵に攻撃してダメージを与えると経験値を取得するプラグインを作成していますが、少し問題点が……

Posted: 2020年4月17日(金) 20:41
by みたしや
Plasma Dark 様

再度、ご依頼を聞いていただきましてありがとうございます。無事にメモ欄から摘出する事が出来、動作も問題なく動きました。ありがとうございます。

質問することで、色々な仕組みが分かってきたので自分自身も楽しかったです。
また分からないところが出来たら、聞いていただきたいと思います。

PS.自分の変身した内容に誤字が多かったので、色々と読みにくかったと思います。ちゃんと読んで頂きましてありがとうございます。