【RGSS3】faida様の敵行動用のターンカウントについて

Rento
記事: 8
登録日時: 2021年3月25日(木) 02:18

【RGSS3】faida様の敵行動用のターンカウントについて

投稿記事by Rento » 2021年3月25日(木) 02:39

http://faida.blog92.fc2.com/blog-entry-177.html

faida様の ☆enemy_turn_count(敵行動用のターンカウントを敵別にする)について
条件に該当する行動がない場合、条件に該当するターンまでカウントを加算し
新たに戦闘行動を選択するには、どのように記述すればよいでしょうか。


ターン経過毎に 1→2→3→1→2→3 のスキルを使用するエネミーが
1のスキルを封印された場合、

【現在の挙動】
行動しない→2→3→行動しない→2→3→行動しない→・・・

【理想の状態】
2→3→2→3→2→3→・・・


封印された状態を条件に2→3→2→3のローテーションで戦闘行動を追加したりもしてみましたが
封印解除のタイミングで 1→2→2→3 等イレギュラーなローテーションに移行したりもあり
悩んでおります。

どなたかご教示いただきたく、何卒宜しくお願い致します。

名無し蛙
記事: 302
登録日時: 2015年11月23日(月) 02:46

Re: 【RGSS3】faida様の敵行動用のターンカウントについて

投稿記事by 名無し蛙 » 2021年3月25日(木) 16:12

どうもこんにちは
まず大前提なんですけど元のスクリプトが機能していませんね…
①行動作成処理から半端に移植した為、行動再作成処理が実行されない
②そもそも行動再作成処理をしても元の行動作成処理がそのままなので上書きされて意味が無い

競合リスクがやや高くなりますがScene_Battle#process_actionに処理を挿入するのが自然だと思います

コード: 全て選択

class Game_Enemy < Game_Battler
  #--------------------------------------------------------------------------
  # ○ オブジェクト初期化
  #--------------------------------------------------------------------------
  alias :etc_initialize :initialize
  def initialize(index, enemy_id)
    etc_initialize(index, enemy_id)
    @turn_count = 0
  end
  #--------------------------------------------------------------------------
  # ○ 行動条件合致判定[ターン数]
  #--------------------------------------------------------------------------
  def conditions_met_turns?(param1, param2)
    n = @turn_count # ☆
    if param2 == 0
      n == param1
    else
      n > 0 && n >= param1 && n % param2 == param1 % param2
    end
  end
  #--------------------------------------------------------------------------
  # ○ 戦闘行動の作成
  #--------------------------------------------------------------------------
  alias :etc_make_actions :make_actions
  def make_actions
    etc_make_actions
    @turn_count += 1
  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
    remake_actions # ☆
    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
  #--------------------------------------------------------------------------
  # ● 戦闘行動の再作成
  #--------------------------------------------------------------------------
  def remake_actions
    trial_count = 5
    until @subject.current_action && @subject.current_action.valid? && 0 <= trial_count do
      @subject.make_actions
      trial_count -= 1
    end
  end
end
ターンカウントの個別化に加えて行動直前に最大5回だけ行動作成を試行しています
改造としては単純な部類なので後は適宜使いやすく修正してください
faida
記事: 272
登録日時: 2015年12月17日(木) 16:44

Re: 【RGSS3】faida様の敵行動用のターンカウントについて

投稿記事by faida » 2021年3月25日(木) 18:52

こんばんは。

そもそもこれ、大前提として「1ターンの間に2回以上行動する場合」のスクリプトですので、
行動再作成処理が実行されるのが2回以上行動の2回目以降なのは(当時では)正常な動作です。
あと、行動作成処理のほうではなく「行動条件」のほうを再定義しているため、
上書きはされていないと思います。
それを「機能していない」って言い切られると困るんですが……まあ「機能していない」スクリプト書くほうが悪いんでそこは受け止めます。
Rento様のおっしゃるような仕様で、かつどのエネミーに関しても
1ターンの間に2回以上行動することがない、または2回以上行動しても
1ターンの間にローテーションが進まないようにしたいのであれば、
名無し蛙様のスクリプトが最適だと思います。
紛らわしい名称で大変申し訳ありません。

※追記
だとしても行動不能時にターンカウントを進めず、そのままの状態というのは
好みの分かれる仕様かなと思ったので修正しておきます。

コード: 全て選択

# 設定項目:行動不可時にターンカウントを進める
COUNT_TURN_NOT_MOVABLE = true

class Game_Enemy
  #--------------------------------------------------------------------------
  # ● オブジェクト初期化
  #--------------------------------------------------------------------------
  alias etc_initialize initialize
  def initialize(index, enemy_id)
    etc_initialize(index, enemy_id)
    @turn_count = 0
  end
  #--------------------------------------------------------------------------
  # ● 現在の戦闘行動を除去
  #--------------------------------------------------------------------------
  alias etc_remove_current_action remove_current_action
  def remove_current_action
    etc_remove_current_action
    @turn_count += 1
    reset_actions
  end
  #--------------------------------------------------------------------------
  # ● 行動条件合致判定[ターン数]
  #--------------------------------------------------------------------------
  def conditions_met_turns?(param1, param2)
    n = @turn_count # ☆
    if param2 == 0
      n == param1
    else
      n > 0 && n >= param1 && n % param2 == param1 % param2
    end
  end
  #--------------------------------------------------------------------------
  # ● 戦闘行動の作成
  #--------------------------------------------------------------------------
  alias etc_make_actions make_actions
  def make_actions
    etc_make_actions
    @turn_count += 1 if COUNT_TURN_NOT_MOVABLE && @actions.empty?
  end
  #--------------------------------------------------------------------------
  # ● 戦闘行動の再作成
  #--------------------------------------------------------------------------
  def reset_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
------------------------------------------------------------------
自作の(改造でない)スクリプト、プラグイン素材に
関しては、リードミーもしくは作中に
「faida」と記名していただければ
利用可能です。
名無し蛙
記事: 302
登録日時: 2015年11月23日(月) 02:46

Re: 【RGSS3】faida様の敵行動用のターンカウントについて

投稿記事by 名無し蛙 » 2021年3月25日(木) 19:47

あーなるほど
普通に使用したら@actionsは空になるだろうと思ったんですけど使用に際して前提条件があったんですか
確かに複数回行動の二回目以降には適用されますね
個別ターンカウントなんて何に使うんだろうと思っていたんですけど二回行動敵を想定していたと
スクリプトの意図を誤読した事を謹んでお詫びして訂正いたします
Rento
記事: 8
登録日時: 2021年3月25日(木) 02:18

Re: 【RGSS3】faida様の敵行動用のターンカウントについて

投稿記事by Rento » 2021年3月26日(金) 03:18

名無し蛙様
faida様

早々にアドバイスとスクリプト案や修正まで頂き、ありがとうございます!
私自身もスクリプトの意図・内容を誤認しており、お二方がお話された内容から
誤った認識だった旨理解することができました。


改めてお伺いなのですが、


【例】1ターンに複数回追加行動を行うエネミーが下記行動パターン
(ターンカウントに基づいたローテーション)で行動。行動条件はそれぞれn+8x

【挙動】攻撃→魔法→攻撃→魔法→特技1→魔法→魔法→特技1→最初に戻る



上記エネミーがスキルの行動条件を満たさない場合(封印等)、当該スクリプトでは下記のような
挙動・判定を行うものではないという事でしょうか。


【例】魔法を封じられ行動選択が無い場合、ターンカウントを加算しローテーションをすっとばして改めて判定

【挙動】攻撃→   攻撃→   特技1→   魔法→特技1→最初に戻る

(DQ3のバ○モスやまほうおばば(1回行動ですが)のような挙動)



拙い説明で申しわけございません。
恐れ入りますが、ご確認いただけましたら幸いです。
何卒宜しくお願い致します。
名無し蛙
記事: 302
登録日時: 2015年11月23日(月) 02:46

Re: 【RGSS3】faida様の敵行動用のターンカウントについて

投稿記事by 名無し蛙 » 2021年3月26日(金) 17:47

行動前再設定に加えて複数回行動まで絡む感じですか

エネミーの行動内容は通常、ターン開始時に決定されるので
ターン開始~行動実行までの状態変化に対応する場合は行動直前にも行動内容の設定が必要になります。
①ターンカウントの個別化②複数回行動の対応③実行直前の設定の三つの要素を満たす必要があり
現状私のコードは①③、faida氏のコードは①②しか条件を満たしていないと思います。
これはあっちを立てればこっちが立たずなので
どちらをベースにするにせよ三つ目を上乗せするのはちょっと骨が折れますね。
いっそ完全に行動ルーチンを特殊化した方が楽なのでは。とりあえず実装の一例です。
対象エネミーのメモ欄に<ローテーションルーチン>と記述する事で行動を特殊化します

コード: 全て選択

# 試行回数
TRIAL_COUNT = 8

module EnemyEx
  #--------------------------------------------------------------------------
  # ○ 行動速度の決定
  #--------------------------------------------------------------------------
  def make_speed
    @speed = agi + rand(5 + agi / 4)
  end
  #--------------------------------------------------------------------------
  # ○ 行動条件合致判定[ターン数]
  #--------------------------------------------------------------------------
  def conditions_met_turns?(param1, param2)
    n = @turn_count # ☆
    if param2 == 0
      n == param1
    else
      n > 0 && n >= param1 && n % param2 == param1 % param2
    end
  end
  #--------------------------------------------------------------------------
  # ○ 戦闘行動の作成
  #--------------------------------------------------------------------------
  def make_actions
    clear_actions
    return unless movable?
    @actions = Array.new(make_action_times) { Game_Action.new(self) }
  end
  #--------------------------------------------------------------------------
  # ● 現在行動の設定
  #--------------------------------------------------------------------------
  def setting_current_action
    action_list = []
    TRIAL_COUNT.times do
      action_list = enemy.actions.select {|a| action_valid?(a) }
      @turn_count += 1
      action_list.empty? ? next : break
    end
    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 }
    current_action.set_enemy_action(select_enemy_action(action_list, rating_zero))
  end
end

class Game_Enemy < Game_Battler
  #--------------------------------------------------------------------------
  # ○ オブジェクト初期化
  #--------------------------------------------------------------------------
  alias :etc_initialize :initialize
  def initialize(index, enemy_id)
    etc_initialize(index, enemy_id)
    if enemy.note.include?("<ローテーションルーチン>")
      extend EnemyEx
      @turn_count = 0 # 実装上module側のinitializeに移せない
    end
  end
end

class Game_Action
  #--------------------------------------------------------------------------
  # ○ 行動準備
  #--------------------------------------------------------------------------
  alias :etc_prepare :prepare
  def prepare
    subject.setting_current_action if @subject.is_a?(EnemyEx)
    etc_prepare
  end
end
Rento
記事: 8
登録日時: 2021年3月25日(木) 02:18

Re: 【RGSS3】faida様の敵行動用のターンカウントについて

投稿記事by Rento » 2021年3月27日(土) 08:24

名無し蛙様
faida様

何度も修正スクリプト作成や、わかりやすくご説明いただいた事感謝致します。
おかげさまで理想通りの挙動とする事ができ感無量でございます。

また、faida様のスクリプトは以前から利用させていただいており、
この場を借りて改めてお礼申し上げます。本当にありがとうございます。

“VX / Ace:質問” へ戻る