【解決済み】スキルの「連続回数」設定時、「身代わり」の挙動

湯喜乃湯
記事: 35
登録日時: 2016年1月10日(日) 16:05
お住まい: Tokyo
連絡を取る:

【解決済み】スキルの「連続回数」設定時、「身代わり」の挙動

投稿記事by 湯喜乃湯 » 2016年12月28日(水) 01:50

いつもお世話になっております。ペコリ

例えば、以下のようなスキルを作った場合・・・
スキル「剣による3回攻撃」
効果範囲「敵単体」
連続回数「3回」

この場合、連続攻撃の途中で敵が戦闘不能になれば、そこで攻撃が終了するというのがデフォルトの仕組みで、ここまでは、自分の制作意図通りなので問題無いのですが・・・

「身代わり」ステートが付加された敵がこの連続攻撃を代わりに受けた場合、身代わりを行った敵が倒れた後も連続攻撃が継続してしまいます。
最悪、「身代わり」ステートが複数の敵に付加されている場合は、次々に身代わりした敵が倒れていき、結果的には「全体攻撃」のようになってしまいます。
元々「敵単体」に対するスキルなのに、「身代わり」が作動すると効果範囲があやふやな状況になってしまうのがなんとも・・・

「身代わり」作動時にも、身代わりした敵が倒れた場合には攻撃が終了するような方法はありますか?
既存システムの応用、スクリプト、どちらでも構いません。
ご教授の程、宜しくお願い致します。
最後に編集したユーザー 湯喜乃湯 on 2016年12月29日(木) 19:29 [ 編集 1 回目 ]

faida
記事: 224
登録日時: 2015年12月17日(木) 16:44

Re: スキルの「連続回数」設定時、「身代わり」の挙動

投稿記事by faida » 2016年12月28日(水) 14:22

まず身代わりがどうやって判定されているか見てみましょうか。
スクリプトエディタでctrl+shift+Fの「全体検索」を使い、「身代わり」で検索するといくつか候補が出てきます。
その中で「身代わりの適用」をチェックします。

コード: 全て選択

  #--------------------------------------------------------------------------
  # ● 身代わりの適用
  #--------------------------------------------------------------------------
  def apply_substitute(target, item)
    (略)
  end
この処理は(関係ないので簡略化しますが)身代わり条件を満たしていれば身代わり候補を探し、
身代わり条件を満たしていない、もしくは身代わり候補がいない場合は元々の対象を返すという処理です。
この処理がどこで使われているか、「apply_substitute」で全体検索すると、
この処理の本体ともう一か所しか出てこないので、もう一か所のほうをチェックします。

コード: 全て選択

  #--------------------------------------------------------------------------
  # ● スキル/アイテムの発動
  #--------------------------------------------------------------------------
  def invoke_item(target, item)
    if rand < target.item_cnt(@subject, item)
      invoke_counter_attack(target, item)
    elsif rand < target.item_mrf(@subject, item)
      invoke_magic_reflection(target, item)
    else
      apply_item_effects(apply_substitute(target, item), item) # これ
    end
    @subject.last_target_index = target.index
  end
これが使われている場所です。さらにこの処理の上の処理では、

コード: 全て選択

  #--------------------------------------------------------------------------
  # ● スキル/アイテムの使用
  #--------------------------------------------------------------------------
  def use_item
    item = @subject.current_action.item
    (中略)
    targets = @subject.current_action.make_targets.compact
    show_animation(targets, item.animation_id)
    targets.each {|target| item.repeats.times { invoke_item(target, item) } } # ここ
  end
ここで先ほどチェックした処理が行われています。# ここ の行を細かく見ていくと、
「選ばれた(プレイヤーが選択した、もしくはランダムな)ターゲット一人ひとりに」「スキルの連続回数の数だけ」
「スキルを使う」という処理になっていることが分かります。

……で、ここで重要なところは「連続回数の数スキルを使っている間、ターゲットは保持される」ということです。
つまり連続攻撃の最中で何度身代わりが死のうが、本来のターゲットを狙い続けるということですね。
これは湯喜乃湯さんが挙げられた状況にピッタリです。

もう少しわかりやすく示すなら、本来の敵をA、かばう敵をBとすると、
最初は [A, A, A] Bによるかばうが発動すると [B, A, A]
で、[A(発動済), A, A] になる。これを後ろの2つにも繰り返す、というわけです。
……なんだかわかりにくくなっちゃいましたね。

じゃあどうしようという話ですね。先ほどの例で挙げると、
Bによるかばうが発動した時に [B, B, B] になればいいわけです。
あくまで一例なのですが、このようにしてみます。

コード: 全て選択

  #--------------------------------------------------------------------------
  # ● スキル/アイテムの使用
  #--------------------------------------------------------------------------
  def use_item
    (中略)
    targets.each {|target| invoke_item(target, item) } # ①
  end
  #--------------------------------------------------------------------------
  # ● スキル/アイテムの発動
  #--------------------------------------------------------------------------
  def invoke_item(target, item)
    ori_target = target # ②
    item.repeats.times { # ①
      if rand < target.item_cnt(@subject, item) # ④
        invoke_counter_attack(target, item)
      elsif rand < target.item_mrf(@subject, item) # ④
        invoke_magic_reflection(target, item)
      else
        target = apply_substitute(target, item) if ori_target == target # ③
        apply_item_effects(target, item)
      end
    } # ①
    @subject.last_target_index = ori_target.index # ⑤
  end
①まず、連続回数による繰り返しを内部の処理に持っていきます。
②次に、本来の対象をバックアップで残して、
③本来の対象と「今の(身代わりによって変更されているかもしれない)対象」を比較し、それで変更が無かったら
身代わり候補を探します。
④その時、反撃とか反射とかは今の対象のパラメータで決定されます。
⑤ラストターゲットは本来の対象を選択します。


だいぶ長くなってしまいましたが、こんな感じでどうでしょう。
なお、このスクリプトは「デフォルト戦闘」でのみ動作保証しております。


※お持ち帰りして素材欄に貼っ付ける用

コード: 全て選択

#==============================================================================
# ■ Scene_Battle
#==============================================================================

class Scene_Battle < Scene_Base
  #--------------------------------------------------------------------------
  # ● スキル/アイテムの使用
  #--------------------------------------------------------------------------
  def use_item
    item = @subject.current_action.item
    @log_window.display_use_item(@subject, item)
    @subject.use_item(item)
    refresh_status
    targets = @subject.current_action.make_targets.compact
    show_animation(targets, item.animation_id)
    targets.each {|target| invoke_item(target, item) }
  end
  #--------------------------------------------------------------------------
  # ● スキル/アイテムの発動
  #--------------------------------------------------------------------------
  def invoke_item(target, item)
    ori_target = target
    item.repeats.times {
      if rand < target.item_cnt(@subject, item)
        invoke_counter_attack(target, item)
      elsif rand < target.item_mrf(@subject, item)
        invoke_magic_reflection(target, item)
      else
        target = apply_substitute(target, item) if ori_target == target
        apply_item_effects(target, item)
      end
    }
    @subject.last_target_index = ori_target.index
  end
end
---------------------------------------------
自作の(改造でない)スクリプト素材に
関しては、リードミーもしくは作中に
「faida」と記名していただければ
利用可能です。
湯喜乃湯
記事: 35
登録日時: 2016年1月10日(日) 16:05
お住まい: Tokyo
連絡を取る:

Re: スキルの「連続回数」設定時、「身代わり」の挙動

投稿記事by 湯喜乃湯 » 2016年12月28日(水) 16:58

>faidaさん
もうね・・・ホント、年末のお忙しい時期に、恐縮というかなんというか・・・

まず、理解するのに結構時間が掛かりそうなので、取り急ぎ御礼のお言葉のみを

大感謝だすx10!!

そして、理解や導入やテストが完了次第、改めてご報告させて頂きます。
(今、家に来ている親族と飲んでしまっているので・・・馬鹿脳が、尚更回っとらん状況になっております)

恐れ入りますが、1,2日程時間を下され。
すびばせん!!すびばせん!!すびばせん!!(土下座)
湯喜乃湯
記事: 35
登録日時: 2016年1月10日(日) 16:05
お住まい: Tokyo
連絡を取る:

Re: スキルの「連続回数」設定時、「身代わり」の挙動

投稿記事by 湯喜乃湯 » 2016年12月29日(木) 19:29

>faidaさん
教えて頂いたスクリプトを導入し、テストしてみました。
いやぁ、要望通りの挙動が実現し、感激です。

で、今回せっかく丁寧にスクリプトの解説を付けて頂いたので、こりゃあ勉強せにゃ男がすたると思って頑張ったんですが・・・
おっさん脳だと、すんげぇ時間が掛かりそうです。

デフォルトだと、連続攻撃の際に元のターゲットである[A]を保持し続けてしまうので、身代わりになる[B]が倒れても攻撃はさらに[A]に・・・
といった解説は理解出来たのですが、解説中の要所要所が該当するスクリプトの解読になると、もはやもう・・・

かっこつけて、「なるほど、スクリプトの内容はだいたい分かりました(キリッ)」なんて言ってみたかったんですけどね。
現実は厳しい。
地道に、時間を掛けて勉強してみます。

ともあれ、問題が解決出来た事に狂喜乱舞しとります。
改めまして、ありがとうございました!!&文字通り今年はお世話になりました、良いお年を!!

これにて、このトピックは解決済みとさせて頂きます。

“VX / Ace:質問” へ戻る