仕様かバグか分からないもの

Kpoal2017-06-03に開始した「ゲーム制作」の中の討論

  1. Kpoal

    Kpoal ユーザー

    これに対して私と剣崎宗二さんで、
    二通りの修正プラグインを出しました。

    上の方でも書いた通り、
    「戦闘行動の強制」によってフェイズが'turn'に巻き戻ってしまうのは
    恐らくどうしようもない事なので、それ以外の部分でこのバグを防いだ形になります。

    私のもの(BugFix_New_turnend_update.js)は、
    ターン終了時処理の中にあったステートのターンカウント進行などを
    次ターンの始めに移動させるという事をしています。
    「戦闘行動の強制」によって何度ターン終了処理が呼び出されようと、
    中身がカラッポなら問題ない。
    これらの処理は次のターンの始め、プレイヤーがコマンドを入力する直前に一度行えばいい
    という考えです。

    これを使えば、バグを回避できるだけでなく
    「防御解除→敵の溜め攻撃」という
    理不尽な事態も防ぐというのが一応のメリットにはなるのですが、
    HP再生とHP取得の順番が逆になってしまう問題も生じますし、
    元の処理順を組み替えている事になるので新たなバグの発生するリスクが非常に高いものになっています。
    自分で作っておいてなんですが、あまり勧められたものではありません。
    後、内容の都合上プラグイン同士の競合もしやすいです。


    一方、剣崎宗二さんの作ってくださったもの(BugFix_New_turnend_update2.js)は、
    this._newturnという新しいフラグを導入して、
    このフラグがONになっているときだけターン終了処理を実行するという条件を付け加える事をしています。
    これにより、処理順は変えないまま
    ターン終了処理をするのは1ターンに1度だけ、となるようにできています。

    処理順を変えず、元の仕様そのままにバグだけを取り除いた形になるので
    新しくバグが出る可能性は低いですし、
    競合もしにくいので基本的にはこちらを使っていただいた方がいいと私は思っています。
     
    #41
  2. Kpoal

    Kpoal ユーザー

    そういえば、VXAceでは
    「『戦闘の処理』を使った連戦時、コモンイベント呼び出しのあるスキルでとどめを刺すと、
    次の戦闘の初めにコモンイベントが実行される

    というバグがありました。

    面倒なバグだったものの
    イベントコマンドを駆使して回避する手順を確立していたためすっかり忘れていたのですが、
    今回改めて調べてみたところ、MV版でも同様に発生する事が分かりました。

    バグの発生条件は、
    「一つのイベントページ内で、二つ以上の『戦闘の処理』がある、いわゆる連戦時」
    で、
    「最後の一体の敵に、コモンイベント呼び出しの効果を持つスキルのダメージでとどめを刺す」
    ことです。
    こうすると、その戦闘では戦闘終了の処理が優先されるため、
    呼び出されたコモンイベントは呼び出し待機状態のまま実行されず、
    イベントコマンドで次の戦闘に入った際に遅れてそれが実行される、という仕組みの様です。
    この仕組みのため、二つの連戦の間にいくつイベントコマンドを挟んでいようが関係なく発生します。

    回避する方法としては、まず二つの『戦闘の処理』を同一ページにせず、
    セルフスイッチを使うなどして改ページしてやる事。
    こうするとページ切り替えの際に一旦イベント実行自由な瞬間が生まれるため、
    そこで呼び出し待機状態が解消されるようです。

    他にも、戦闘終了時に解除されるステートを利用した方法もあり、
    自分はこちらを使っているのですが、
    面倒なのでお勧めはしません。

    そして今回プラグインも作ってみました。
    内容は「戦闘終了時に呼び出し待機中のコモンイベントを解消する」
    というだけの簡単なものですが、
    これで他のバグを引き起こさないかという不安はあります。
     

    添付ファイル:

    #42
    神無月サスケ がいいね!しました
  3. Kpoal

    Kpoal ユーザー

    VXAce版での修正用スクリプトも組んでみたのですが、
    競合回避の方法がよく分かりませんでした。
    (self.で始まるものを再定義せずに変更するにはどうしたらいいんでしょう?)
    もし分かる方がいらっしゃれば教えていただきたいです。
    コード:
    module BattleManager
      #--------------------------------------------------------------------------
      # ● 戦闘終了
      #     result : 結果(0:勝利 1:逃走 2:敗北)
      #--------------------------------------------------------------------------
      def self.battle_end(result)
        $game_temp.clear_common_event
        @phase = nil
        @event_proc.call(result) if @event_proc
        $game_party.on_battle_end
        $game_troop.on_battle_end
        SceneManager.exit if $BTEST
      end
    end
     
    #43
    神無月サスケ がいいね!しました
  4. うなぎおおとろ

    うなぎおおとろ ユーザー

    こんな感じにすればいけますよ。

    コード:
    module BattleManager
      class << self
        alias _battle_end battle_end
      end
    
      def self.battle_end(result)
        $game_temp.clear_common_event
        _battle_end(result)
      end
    end
    
     
    #44
    Kpoal神無月サスケ がいいね!しています
  5. Kpoal

    Kpoal ユーザー

    >うなぎおおとろさん
    ありがとうございます。
    module内のclassの扱い方について、大変勉強になりました。


    それではここらでまた、
    ツクールの仕様とそれに伴うバグについて一点紹介させていただきます。

    まず知っている方もいると思いますが、
    スキルのダメージ計算式には、VXAceなら;(セミコロン)、MVなら,(カンマ)で区切る事で、
    任意のコマンドを書き込むことができるという仕様があります。

    例)
    ●VXAce
    攻撃と同時に、行動者のアクターIDを変数1番に取得
    →v[1]=a.id;4*a.atk-2*b.def

    MPを全消費してMP*10をダメージに追加
    →$x=a.mp;a.mp=0;$x*10+2*a.mat-2*b.mdf

    スキル使用者にステート5番を付与しつつ攻撃
    →a.add_state(5);4*a.atk-2*b.def

    使用者のTPを1:5のレートでMPに変換
    →$tm=[a.tp*5,a.mmp-a.mp].min;a.tp-=$tm/5;$tm
    (スキルタイプ:MP回復)

    ●MV
    攻撃と同時に、行動者のアクターIDを変数1番に取得
    →v[1]=a._actorId,a.atk * 4 - b.def * 2

    攻撃と同時に、行動した敵のindexを変数1番に取得
    →v[1]=this._subjectEnemyIndex,a.atk * 4 - b.def * 2

    MPを全消費してMP*10をダメージに追加
    →x=a.mp,a.gainMp(-a.mp),x*10+a.atk * 4 - b.def * 2

    攻撃と同時に自身のHPを0に
    →a.gainHp(-a.hp),1000+a.atk * 4 - b.def * 2

    スキル使用者にステート5番を付与しつつ攻撃
    a.addState(5),a.atk * 4 - b.def * 2

    等、他にもいろいろと
    本来スクリプトやプラグインを追加しなければできない事が
    デフォルトの仕様だけでできてしまうのです。
    (スキルが命中しなければ実行されないという問題もありますが)

    これは便利な仕様ですし、自分もよく利用しているのですが、
    実はこれには意外な落とし穴というかバグがあります。
    それは、
    セミコロンやカンマを利用して特殊な処理を持たせたスキルを覚えたアクターが、
    自動戦闘の特徴を持っている場合、毎ターン開始時にその特殊処理が勝手に実行されてしまう

    というものです。

    例えば上で紹介したMP全消費スキル。
    これを覚えたアクターが装備品でも何でも自動戦闘の特徴を持った場合、
    ターンの開始時にそのスキルが選ばれたかどうかに関わらず、
    必ずそのアクターのMPが0になるという現象が発生するのです。

    これは自動戦闘の行動決定処理の都合によるもので、
    自動戦闘では毎ターンの始めに覚えている全スキルで仮想的にダメージを作成し、
    そのダメージ量から行動内容を決定します。
    この「仮想的にダメージを作成する」ときに、
    ダメージ計算式に含まれているコマンドも実行されるため、
    こういった現象が発生してしまうわけです。

    という事で、この問題を解決するためのプラグインを
    VXAce用、MV用でそれぞれ作成してみました。

    一般的なバグ修正プラグインとは異なり、
    この仕様を利用したスキルを使っていなければ入れる必要のない修正ですが、
    必要な方はご利用下さい。

    ※特殊処理を持ったスキルは仮想ダメージ作成を行わずに、
    必ず評価値が0になるようにするというものなので、
    厳密にはバグ修正とは違いますが。
    コード:
    #===========================================================
    #●特殊ダメージ式バグ修正スクリプト for VXAce
    #  作成 KPoal
    #  ver 1.01 2017/12/02
    #===========================================================
    #  自動戦闘特徴を持つアクターが
    #  ダメージ計算式に";"を含む特殊処理を挟むスキルを覚えていたとき、
    #  毎ターン開始時に特殊処理が
    #  勝手に実行されてしまうバグを修正します。
    #===========================================================
    
      SP_Skill_usingRate = 0.0
    
    class Game_Action
      #--------------------------------------------------------------------------
      # ● スキル/アイテムの評価(ターゲット指定)
      #    自動戦闘の行動選択時、特殊計算式を持つスキルの評価値を定数にする。
      #--------------------------------------------------------------------------
      alias evaluate_special_item_with_target evaluate_item_with_target
      def evaluate_item_with_target(target)
         if /;/ =~ item.damage.formula
           return SP_Skill_usingRate
         else
           evaluate_special_item_with_target(target)
        end
      end
    end
     

    添付ファイル:

    #45
    メルサイア, チョコワ部, ネコタ他1人 がいいね!しています

このページを共有