【解決済】(VXace)敵キャラの行動パターンをターン途中で変更

しょこら
記事: 6
登録日時: 2018年4月04日(水) 13:40

【解決済】(VXace)敵キャラの行動パターンをターン途中で変更

投稿記事by しょこら » 2018年4月04日(水) 14:19

お世話になっております。今回、初めてリクエストをさせていただきます。

敵キャラが味方の補助や自身のスキルでMPが100以上になった場合に
同ターン内にMP100消費のスキルを発動させたいのですが
行動パターンがターン開始時に決定されてしまうようで上手くいきません。

流れとしては
1.味方や自身のスキルで敵AのMPが100以上になる
2.その敵Aがそのターン内でまだ行動可能な場合、
 決定されていた行動を1回分キャンセルしてMP消費100のスキルを発動させたい

といった具合です。
バトルイベントで擬似的な動きができないか色々試したのですがどうしても上手くいきません。
それ以外にも味方の状況などで行動パターンを変化させたい状況があり、バトルイベントでは限界でした。
変数やスイッチを使って色々な状況の条件分岐を作るところまではできるのですが
やはりターン内で敵の行動パターンを変更する事だけができません……
どなたかこういった流れにする事が可能であれば、何卒よろしくお願いいたします。
最後に編集したユーザー しょこら on 2018年4月05日(木) 21:57 [ 編集 1 回目 ]

TOMO
記事: 183
登録日時: 2015年11月16日(月) 20:12
連絡を取る:

Re: (VXace)敵キャラの行動パターンをターン途中で変更

投稿記事by TOMO » 2018年4月04日(水) 16:37

多分「敵キャラの変身」で行けると思う
faida
記事: 216
登録日時: 2015年12月17日(木) 16:44

Re: (VXace)敵キャラの行動パターンをターン途中で変更

投稿記事by faida » 2018年4月04日(水) 19:55

無理矢理解決するならバトルイベントの条件合致判定を改造するとか。

コード: 全て選択

  #--------------------------------------------------------------------------
  # ● バトルイベント(ページ)の条件合致判定
  #--------------------------------------------------------------------------
  def conditions_met?(page)
    (中略)
    if c.switch_valid   # スイッチ
      if c.switch_id == 100 # ここから。使わないスイッチIDにしてください
        enemy = $game_troop.members[0] # 1番目の敵キャラ
        return false if enemy.mp < 100 || enemy.actions.empty?
      else
        return false if !$game_switches[c.switch_id]
      end # ここまで
    end
    return true         # 条件合致
  end
例では「スイッチ100がON」を「1番目の敵キャラのMPが100以上かつ未行動」にしています。
このスイッチIDは他のバトルイベントで使用しないIDにしてください。
他の解決方法なら、行動直前に行動を決めるようにするとかはできますけどね。

※お持ち帰り用

コード: 全て選択

class Game_Troop < Game_Unit
  #--------------------------------------------------------------------------
  # ● バトルイベント(ページ)の条件合致判定
  #--------------------------------------------------------------------------
  def conditions_met?(page)
    c = page.condition
    if !c.turn_ending && !c.turn_valid && !c.enemy_valid &&
       !c.actor_valid && !c.switch_valid
      return false      # 条件未設定…実行しない
    end
    if @event_flags[page]
      return false      # 実行済み
    end
    if c.turn_ending    # ターン終了時
      return false unless BattleManager.turn_end?
    end
    if c.turn_valid     # ターン数
      n = @turn_count
      a = c.turn_a
      b = c.turn_b
      return false if (b == 0 && n != a)
      return false if (b > 0 && (n < 1 || n < a || n % b != a % b))
    end
    if c.enemy_valid    # 敵キャラ
      enemy = $game_troop.members[c.enemy_index]
      return false if enemy == nil
      return false if enemy.hp_rate * 100 > c.enemy_hp
    end
    if c.actor_valid    # アクター
      actor = $game_actors[c.actor_id]
      return false if actor == nil
      return false if actor.hp_rate * 100 > c.actor_hp
    end
    if c.switch_valid   # スイッチ
      if c.switch_id == 100 # ここから。使わないスイッチIDにしてください
        enemy = $game_troop.members[0] # 1番目の敵キャラ
        return false if enemy.mp < 100 || enemy.actions.empty?
      else
        return false if !$game_switches[c.switch_id]
      end # ここまで
    end
    return true         # 条件合致
  end
end
---------------------------------------------
自作の(改造でない)スクリプト素材に
関しては、リードミーもしくは作中に
「faida」と記名していただければ
利用可能です。
ショウ
記事: 117
登録日時: 2016年8月10日(水) 19:52

Re: (VXace)敵キャラの行動パターンをターン途中で変更

投稿記事by ショウ » 2018年4月04日(水) 22:18

aceは今入れてないから確認出来ないのでVXの話になるけど多分似た様な方法で
出来ると思うので参考資料程度に。
自分は以前敵の順番が来たタイミングで行動決定されるように出来ないか
四苦八苦した事があったんだけど、通常コマンド選択後に敵の行動が決定されて、
バトルイベント→敵味方行動&バトルイベント(ターン中の条件合致)→バトルイベント(ターン終了時設定)
の順で実行される様になってます。
この”敵味方行動”の部分がスクリプトではprocess_action(戦闘行動の処理)に当たる様で、
ここの処理中にもう一度敵に行動決定(make_action)をさせる事で敵の行動が
来たタイミングでその敵が何をするか選ぶようになります。
その際そのターン中のHPやスイッチなどの変化も含めて選ぶようになります。
具体的にはこんな感じ
Scene_Battleの中の↓
#--------------------------------------------------------------------------
# ● 戦闘行動の処理
#--------------------------------------------------------------------------
def process_action
return if judge_win_loss
return if $game_temp.next_scene != nil
set_next_active_battler
if @active_battler == nil
turn_end
return
end
return if @active_battler.dead?
@message_window.clear
wait(5)
@active_battler.white_flash = true
unless @active_battler.action.forcing
@active_battler.make_action if !@active_battler.actor?#追加
@active_battler.action.prepare
end
if @active_battler.action.valid?
execute_action
end
unless @active_battler.action.forcing
@message_window.clear
remove_states_auto
display_current_state
end
@active_battler.white_flash = false
@message_window.clear
end
#追加と書いてある行が順番が来た時それが敵の場合行動を設定するという処理です。
自分は今の所これで特に問題なく動作していますが、相性の悪いスクリプトなども
あるかも…
行動順序作成後に行動を再設定する様なものなんで敵のスキルの速度補正が多分半分死んでます…
自分は速度補正使ってないので影響は無いですが。
(まぁやり方次第ではそれも敵の行動操作に利用出来なくもないでしょうが)
良い参考になれば幸いです。
しょこら
記事: 6
登録日時: 2018年4月04日(水) 13:40

Re: (VXace)敵キャラの行動パターンをターン途中で変更

投稿記事by しょこら » 2018年4月05日(木) 01:04

みなさん、ご返信ありがとうございます。

>TOMO様
敵キャラの変身の発想はありませんでした。
MP回復スキル発動後にイベントを発生させ、MP100以上の条件に合致した場合に
同一IDの敵キャラに変身させるイベントコマンドを使用したところ、
同ターンでMP100のスキルを使用してくれました。

ただ、最優先でMP100消費のスキルを使用するように設定している為か
残りの行動回数が2回だった場合、MP100のスキルを使用した1度の行動だけで行動が終了してしまいます。
・(敵A→敵B“mp100消費”→敵B) となるはずが (敵A→敵B“mp100消費”)で止まってしまう

こちらも変身で解決はできそうなのですが変身させる都合上、
対応する敵グループと敵キャラの数だけイベントを作成しなければならない為、
何とか最小限の作成で動作させたいです。

変身そのものは同じIDの敵キャラに変身すればいいみたいなので
同じIDの敵キャラに変身するスクリプトがあればイベントコマンドからその処理ができると思ったのですが
調べてもenemy_index(敵グループid) を enemy.transform(敵キャラid)といったものしか見つかりません。
どうにかしてスクリプト上で同じ敵キャラidを取得させて変身する方法はありますでしょうか。


>faida様
ありがとうございます。
条件そのものは変数を使って敵キャラのMPを代入してその変数を条件分岐に使っていました。
そちらのスクリプトのおかげでその手間がなくなりました、ありがとうございます。
ただ、やはりMPを使いきった場合に上記の行動が終了してしまう弊害は発生してしまうようです。
他の解決法としての行動直前に行動を決めるようにするというのはどういった方法でしょうか?


>ショウ様
ありがとうございます。
さっそくScene_Battleの戦闘行動に関連する部分を参照してみたのですが
@active_battlerのような記述がなく、仕様が変更されているみたいです……
わざわざ解説していただいたのに申し訳ありません……
ショウ
記事: 117
登録日時: 2016年8月10日(水) 19:52

Re: (VXace)敵キャラの行動パターンをターン途中で変更

投稿記事by ショウ » 2018年4月05日(木) 01:38

仕様が変わってるのは当たり前です。
そのおかげでRGSS2が使いまわせなかったんです。
しかし気になってACEを入れてみた所、
言葉が変わってるだけでやっている事はさほど変わらない様です。
BattleManagerの中↓
def self.next_subject
loop do
$game_troop.make_actions#追加
battler = @action_battlers.shift
return nil unless battler
next unless battler.index && battler.alive?
return battler
end
end
#追加の部分の$game_troop.make_actionsが@active_battler.make_action if !@active_battler.actor?
に当たる様です。
これでとりあえずHPの変化で試したところ(スライムにHPが0~99%の時だけ攻撃するように設定して)
行動直前で行動が再設定されてスライムがターン中ダメージを受けなかった場合は何もせず、
行動前にスライムがダメージを受けた場合は設定が合致し攻撃するようになりました。
なお変身後に二回行動の二回目で何もしてくれないのは、
おそらく変身による行動の再設定が変身したタイミングで行われるからだと思われます。
つまり変身直後のそのターン中は二回目もMP100消費のスキル以外行動の選択肢に入っていないので
MP不足で不発に終わっているのかと。
しょこら
記事: 6
登録日時: 2018年4月04日(水) 13:40

Re: (VXace)敵キャラの行動パターンをターン途中で変更

投稿記事by しょこら » 2018年4月05日(木) 02:35

>ショウ様
ありがとうございます!わざわざACEまで入れていただいて……
スクリプトにそちらを記述したところ、こちらでも動作を確認しました。
支援を受けてMPが100になった瞬間にスキルを発動してくれます。

ただ、行動回数を追加している敵キャラがこちらが全滅するまで
1ターン中に何度も行動を繰り返すようになってしまいました。
こちらの解決法はありますでしょうか。質問ばかりで申し訳ありません。
ショウ
記事: 117
登録日時: 2016年8月10日(水) 19:52

Re: (VXace)敵キャラの行動パターンをターン途中で変更

投稿記事by ショウ » 2018年4月05日(木) 03:18

ん??行動回数追加100%を付けて試したところちゃんと二回しか行動しませんでしたよ。
まず$game_troop.make_actionsを記述する場所を間違えてないか確認してみてください。
また他のスクリプトを入れている場合それが影響しているのかもしれません、
試しに新規プロジェクトで試してみてください。
faida
記事: 216
登録日時: 2015年12月17日(木) 16:44

Re: (VXace)敵キャラの行動パターンをターン途中で変更

投稿記事by faida » 2018年4月05日(木) 09:32

複数回行動ということを想定していませんでしたね。すみません。
余談になりますが、イベントコマンドで「戦闘行動の強制」をすると、その後の行動はすべてキャンセルされます。
覚えておいて損はないでしょう。

本題に入りますが、ショウ様の提示した方法が「行動直前に行動を決めるようにする」方法です。
ただ、$game_troop.make_actionsをするたびに「敵全体の」行動が再作成されます。
あと、行動回数追加確率が100%でない場合は、これが行われるたびに回数が変わる可能性があります。
まあ今の所ほとんど関係のない仕様なんですが。

で、ショウ様がRGSS2で提示した箇所は、RGSS3だとこちらですね。

コード: 全て選択

class Scene_Battle < Scene_Base
  #--------------------------------------------------------------------------
  # ● 戦闘行動の処理
  #--------------------------------------------------------------------------
  def process_action
    return if scene_changing?
    if !@subject || !@subject.current_action
      @subject = BattleManager.next_subject
    end
    return turn_end unless @subject
    if @subject.current_action
      # ここに追加する
      @subject.current_action.prepare
      if @subject.current_action.valid?
        @status_window.open
        execute_action
      end
      @subject.remove_current_action
    end
    process_action_end unless @subject.current_action
  end
end
ですが、先ほども申し上げました通り、行動回数追加確率が100%でないと行動回数が変わり、
ここに追加した場合は最悪エラー落ちすることがあります。
なので、「行動回数を変えない」で「行動内容を変える」コマンドを追加して、対処したほうがよろしいかと。
あと、ここに追加するメリットがもう一つあって、「MP不足でも臨機応変に行動を変える」というのが挙げられます。

コード: 全て選択

class Game_Enemy < Game_Battler
  #--------------------------------------------------------------------------
  # ● 戦闘行動の再作成
  #--------------------------------------------------------------------------
  def remake_actions
    return if @actions.empty?
    action_list = enemy.actions.select {|a| action_valid?(a) }
    return if action_list.empty?
    rating_max = action_list.collect {|a| a.rating }.max
    rating_zero = rating_max - 3
    action_list.reject! {|a| a.rating <= rating_zero }
    @actions.each do |action|
      action.set_enemy_action(select_enemy_action(action_list, rating_zero))
    end
  end
end

class Scene_Battle < Scene_Base
  #--------------------------------------------------------------------------
  # ● 戦闘行動の処理
  #--------------------------------------------------------------------------
  def process_action
    return if scene_changing?
    if !@subject || !@subject.current_action
      @subject = BattleManager.next_subject
    end
    return turn_end unless @subject
    if @subject.current_action
      @subject.remake_actions if @subject.enemy?
      @subject.current_action.prepare
      if @subject.current_action.valid?
        @status_window.open
        execute_action
      end
      @subject.remove_current_action
    end
    process_action_end unless @subject.current_action
  end
end
まぁ方法の一つとしてとらえていただければ。

ちなみに「同キャラに変身させるスクリプトコマンド」は

コード: 全て選択

id = $game_troop.members[0].id
$game_troop.members[0].transform(id)
です。理屈は簡単ですね。
---------------------------------------------
自作の(改造でない)スクリプト素材に
関しては、リードミーもしくは作中に
「faida」と記名していただければ
利用可能です。
ショウ
記事: 117
登録日時: 2016年8月10日(水) 19:52

Re: (VXace)敵キャラの行動パターンをターン途中で変更

投稿記事by ショウ » 2018年4月05日(木) 14:40

RGSS3ではそういう仕様があるんですね(よし買っといてほぼ詰んでたし便乗して勉強しようw)
ただ自分も気になって試したところprocess_actionの所に入れた場合敵の行動が来たら
フリーズしてしまいました。(%関係なく何度トライしても…無限ループの時みたいな挙動で)
四つ上でやってる方法でBattleManagerのself.next_subjectに入れた場合は想定通り動くんですが。
100%以外にしても行動回数が増えるといった事は起きませんし行動回数が増える状況になりうる
特殊な条件があるのでしょうか?

追記
あ、process_actionに入れる場合$game_troop.make_actionsじゃなくて
@subject.make_actions if @subject.enemy?にしたら想定通り動きました。
RGSS2における@active_battler.make_action if !@active_battler.actor?はこっちの方が近いのかな?
字面的にも動作的にもこっちの方がVXで自分がやってる処理に近そう。
多分@subjectがRGSS2の@activeに近いもので、
@subjectにBattleManager.next_subjectで次行動するキャラが代入されてって感じの処理なのかな?
それに$game_troop.make_actionsはなんとなくgame_troopだし多分敵全体なんだろうなぁとは思ってたし…
最後に編集したユーザー ショウ on 2018年4月05日(木) 15:37 [ 編集 4 回目 ]

“VX / Ace:スクリプト素材のリクエスト” へ戻る