【RGSS3】faida様作『瀕死時に××』の機能拡張

せくもん
記事: 36
登録日時: 2018年6月09日(土) 21:48

【RGSS3】faida様作『瀕死時に××』の機能拡張

投稿記事by せくもん » 2019年8月28日(水) 21:33

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

[url]
viewtopic.php?f=46&t=2666
[/url]

↑のトピックにてfaidaさんが作成されたスクリプトに下記の機能を追加したいと思いました。

①発動する効果に『ステートの解除』を追加
②発動条件に『TPが満タンになった時』を追加
③発動条件に『そのバトラーが敵を倒した時』を追加

コード: 全て選択

=begin
◆概要
瀕死時に効果を発動したり特徴を付加したりします。

◆機能
・メモ欄に<瀕死時効果 id, n>と記入すると、瀕死時に以下の効果を発揮します。
idが0…指定コモンイベント予約(予約するだけ)
    1…HPをn回復 2…HPをn%回復 3、4は1、2のMP版 5…IDnのステート付加
    6…IDnのステート解除 7…パラメータnの弱体解除しつつ強化付加(2段階)
・メモ欄に<瀕死時特徴 [code, data_id, value]>と記入すると、
その特徴を付加します。
・ステートのメモ欄に<瀕死付加時アニメ id>と記入すると、瀕死付加時のみ
そのアニメを再生します。
・地味にコモンイベント複数予約のおまけつき。

◆仕様
・特徴が分かりづらいのは仕様です。わかりやすいようにリメイク予定。

◆使用上の注意
・★……エイリアス ●……再定義 ○……新規定義

◆作者:faida @faida3983

◆更新履歴
ver1.0 : 公開
ver1.1 : 拙作「ログ出力」に対応
ver1.2 : 戦闘途中からアクターが加入する場合のエラー修正
     ステートごとにアニメ指定できるように

=end

module FAI_CECF
  # 設定項目:コモンイベント予約時にアクターID(か敵の並び順)を代入する変数ID
  # 代入しない場合は0
  COMMON_EVENT_VAR_ID = 1
  # 設定項目:HP回復時に表示するアニメーション(表示しない場合は0)
  HP_RECOVER_ANI_ID = 37
  # 設定項目:MP回復時に表示するアニメーション(表示しない場合は0)
  MP_RECOVER_ANI_ID = 38
  # 設定項目:指定なしステート付加時に表示するアニメーション(表示しない場合は0)
  ADD_STATE_ANI_ID = 43
  # 設定項目:強化付加時に表示するアニメーション(表示しない場合は0)
  ADD_BUFF_ANI_ID = 43
  # 設定項目:強化付加時に持続するターン数
  # "$game_variables[2]"ってやると(変数ID2)ターン続きます。
  ADD_BUFF_TURN = "5"
  # 設定項目:無効化するスイッチID(使用しない場合は0)
  FORBID_SW_ID = 0
end

class RPG::BaseItem
  #--------------------------------------------------------------------------
  # ● 瀕死時に効果を発動
  #--------------------------------------------------------------------------
  def crisis_effects
    return @crisis_effects if @crisis_effects
    @crisis_effects = []
    note.each_line{|line|
      if line =~ /<瀕死時効果\s*(\d+)\s*\,\s*(\d+)>/
        @crisis_effects << [$1.to_i, $2.to_i]
        @crisis_effects[-1][1]/=100.0 if [2,4].include?(@crisis_effects[-1][0])
      end
    }
    @crisis_effects
  end
  #--------------------------------------------------------------------------
  # ● 瀕死時に特徴を付加
  #--------------------------------------------------------------------------
  def crisis_features
    return @crisis_features if @crisis_features
    @crisis_features = []
    note.each_line{|line|
      if line =~ /<瀕死時特徴\s*(\[.+\])>/
        @crisis_features << eval($1)
      end
    }
    @crisis_features
  end
end

class RPG::State
  #--------------------------------------------------------------------------
  # ● 瀕死付加時に再生されるアニメ
  #--------------------------------------------------------------------------
  def crisis_add_anime
    return @crisis_add_anime if @crisis_add_anime
    @crisis_add_anime = FAI_CECF::ADD_STATE_ANI_ID
    @crisis_add_anime = $1.to_i if note =~ /<瀕死付加時アニメ\s*(\d+)>/
    @crisis_add_anime
  end
end

#==============================================================================
# ■ Game_Temp
#==============================================================================

class Game_Temp
  include FAI_CECF
  #--------------------------------------------------------------------------
  # ○ 公開インスタンス変数
  #--------------------------------------------------------------------------
  attr_accessor :reserved_ce_battlers        # なんか
  #--------------------------------------------------------------------------
  # ★ オブジェクト初期化
  #--------------------------------------------------------------------------
  alias fai_cecf_initialize initialize
  def initialize
    fai_cecf_initialize
    @reserved_common_event_ids = []
    @reserved_ce_battlers = []
  end
  #--------------------------------------------------------------------------
  # ★ コモンイベントの呼び出しを予約
  #--------------------------------------------------------------------------
  alias fai_cecf_reserve_common_event reserve_common_event
  def reserve_common_event(common_event_id)
    if @common_event_id > 0
      return @reserved_common_event_ids << common_event_id
    end
    fai_cecf_reserve_common_event(common_event_id)
  end
  #--------------------------------------------------------------------------
  # ★ コモンイベントの呼び出し予約をクリア
  #--------------------------------------------------------------------------
  alias fai_cecf_clear_common_event clear_common_event
  def clear_common_event
    fai_cecf_clear_common_event
    if !@reserved_common_event_ids.empty?
      fai_cecf_reserve_common_event(@reserved_common_event_ids.shift)
    end
  end
end

class Game_BattlerBase
  include FAI_CECF
  #--------------------------------------------------------------------------
  # ★ オブジェクト初期化
  #--------------------------------------------------------------------------
  alias fai_cecf_initialize initialize
  def initialize
    fai_cecf_initialize
    @crisis_effects = []
  end
  #--------------------------------------------------------------------------
  # ●
  #--------------------------------------------------------------------------
  def crisis_effects
    feature_objects.collect{|obj|obj.crisis_effects}.flatten(1)
  end
  #--------------------------------------------------------------------------
  # ●
  #--------------------------------------------------------------------------
  def crisis_features
    return [] if !$game_party.in_battle
    return [] if FORBID_SW_ID > 0 && $game_switches[FORBID_SW_ID]
    return [] if hp == 0 || !@mhp || hp >= @mhp / 4
    feature_objects.collect{|obj|obj.crisis_features}.flatten(1).collect{|arr|
      RPG::BaseItem::Feature.new(arr[0], arr[1], arr[2])
    }
  end
  #--------------------------------------------------------------------------
  # ★
  #--------------------------------------------------------------------------
  alias fai_cecf_all_features all_features
  def all_features
    fai_cecf_all_features + crisis_features
  end
  #--------------------------------------------------------------------------
  # ★ リフレッシュ
  #--------------------------------------------------------------------------
  alias fai_cecf_refresh refresh
  def refresh
    fai_cecf_refresh
    @mhp = mhp
  end
end

class Game_Battler < Game_BattlerBase
  include FAI_CECF
  #--------------------------------------------------------------------------
  # ★ ステートの付加
  #--------------------------------------------------------------------------
  alias fai_cecf_add_state add_state
  def add_state(state_id)
    cf = self.crisis_effects
    fai_cecf_add_state(state_id)
    if cf != self.crisis_effects
      a = self.crisis_effects; cf.each{|eff|i = a.index(eff); a[i] = nil if i}
      @crisis_effects += a.compact
    end
  end
  #--------------------------------------------------------------------------
  # ★ 戦闘開始処理
  #--------------------------------------------------------------------------
  alias fai_cecf_on_battle_start on_battle_start
  def on_battle_start
    fai_cecf_on_battle_start
    init_crisis_effects
  end
  #--------------------------------------------------------------------------
  # ● 瀕死時効果の初期化
  #--------------------------------------------------------------------------
  def init_crisis_effects
    @crisis_effects = self.crisis_effects
  end
  #--------------------------------------------------------------------------
  # ● idの数字で発動する効果を分岐
  #--------------------------------------------------------------------------
  def check_crisis_effects
    return if FORBID_SW_ID > 0 && $game_switches[FORBID_SW_ID]
    return if hp >= mhp / 4 || hp == 0
    @crisis_effects.each_with_index{|arr|
      case arr[0]
      when 0
        if COMMON_EVENT_VAR_ID > 0
          $game_temp.reserved_ce_battlers <<  i = actor? ? id : -index
        end
        $game_temp.reserve_common_event(arr[1])
      when 1
        self.hp += arr[1]
        self.animation_id = HP_RECOVER_ANI_ID if HP_RECOVER_ANI_ID > 0
      when 2
        self.hp += arr[1] * mhp
        self.animation_id = HP_RECOVER_ANI_ID if HP_RECOVER_ANI_ID > 0
      when 3
        self.mp += arr[1]
        self.animation_id = MP_RECOVER_ANI_ID if MP_RECOVER_ANI_ID > 0
      when 4
        self.mp += arr[1] * mmp
        self.animation_id = MP_RECOVER_ANI_ID if MP_RECOVER_ANI_ID > 0
      when 5
        add_state(arr[1])
        anime_id = $data_states[arr[1]].crisis_add_anime
        self.animation_id = anime_id if anime_id > 0
      when 6
        remove_state(arr[1])
        anime_id = $data_states[arr[1]].crisis_add_anime
        self.animation_id = anime_id if anime_id > 0
      when 7
        remove_buff(arr[1]) if @buffs[arr[1]] < 0
        add_buff(arr[1], 1); add_buff(arr[1], eval(ADD_BUFF_TURN))
        self.animation_id = ADD_BUFF_ANI_ID if ADD_BUFF_ANI_ID > 0
      end
      @crisis_effects[@crisis_effects.index(arr)] = nil
    }
    @crisis_effects.compact!
  end
end

class Game_Party < Game_Unit
  #--------------------------------------------------------------------------
  # ● アクターを加える
  #--------------------------------------------------------------------------
  alias fai_cecf_add_actor add_actor
  def add_actor(actor_id)
    $game_actors[actor_id].init_crisis_effects unless @actors.include?(actor_id)
    fai_cecf_add_actor(actor_id)
  end
end

class Game_Interpreter
  include FAI_CECF
  #--------------------------------------------------------------------------
  # ★ 呼び出し予約されたコモンイベントを検出/セットアップ
  #--------------------------------------------------------------------------
  alias fai_cecf_setup_reserved_common_event setup_reserved_common_event
  def setup_reserved_common_event
    if $game_temp.common_event_reserved?
      if !$game_temp.reserved_ce_battlers.empty?
        n = $game_temp.reserved_ce_battlers.shift
        $game_variables[COMMON_EVENT_VAR_ID] = n
      end
    end
    fai_cecf_setup_reserved_common_event
  end
end

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

class Scene_Battle < Scene_Base
  #--------------------------------------------------------------------------
  # ★ イベントの処理
  #--------------------------------------------------------------------------
  alias fai_cecf_process_event process_event
  def process_event
    fai_cecf_process_event
    all_battle_members.each{|a|a.check_crisis_effects}
  end
  #--------------------------------------------------------------------------
  # ★ 戦闘行動の処理
  #--------------------------------------------------------------------------
  alias fai_cecf_process_action process_action
  def process_action
    fai_cecf_process_action
    all_battle_members.each{|a|a.check_crisis_effects}
  end
end



この内、①だけは何とか追加出来たのですが②、③に関してはスクリプトの記述方法が分からず
『● idの数字で発動する効果を分岐』の

return if hp >= mhp / 4 || hp == 0 の部分を

return if tp == 100 等に変えてみたみたのですがTPが溜まっていない戦闘開始時に

いきなり効果が発動したりして上手くいきません。
どなたかお知恵を貸していただけませんでしょうか?

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

Re: 【RGSS3】faida様作『瀕死時に××』の機能拡張

投稿記事by faida » 2019年8月28日(水) 23:38

こんばんは。
まずは、スクリプトのご利用ありがとうございます。

このスクリプトの構造は、
A.HPが変化しそうなタイミングで
B.条件をチェックして効果を発動する
という2段階に分かれています。

②の要望はB.に相当するところ(せくもんさんの目を付けたところ)なんですが、
「return if ~」のところに書いてある条件は「発動しない条件」なんですね。
なので、「return if tp == 100」と記入すると、「tpが100の時、発動しない」ので、
戦闘開始時(バトル開始時のイベント後)にいきなり発動するわけですね。
それを防ぐには、「return if tp < 100」とする必要があるわけです。

③の要望はA.に相当するところですね。
ただ、条件は「そのバトラーが敵を倒したとき」なので、
それが発生しそうな場所と、その時用に処理を追加する必要がありそうです。

コード: 全て選択

 
  #--------------------------------------------------------------------------
  # ☆ ダメージの処理
  #--------------------------------------------------------------------------
  alias fai_cecf_execute_damage execute_damage
  def execute_damage(user)
    fai_cecf_execute_damage(user)
    user.defeat_crisis_effects if self.dead?
  end
  #--------------------------------------------------------------------------
  # ○ idの数字で発動する効果を分岐(敵倒した用)
  #--------------------------------------------------------------------------
  def defeat_crisis_effects
    return if FORBID_SW_ID > 0 && $game_switches[FORBID_SW_ID]
    @crisis_effects.each_with_index{|arr|
      case arr[0]
      when 0
        if COMMON_EVENT_VAR_ID > 0
          $game_temp.reserved_ce_battlers <<  i = actor? ? id : -index
        end
        $game_temp.reserve_common_event(arr[1])
      when 1
        (中略)
      end
    }
  end


返信を書いていて思ったのは、せくもんさんはおそらく
「瀕死時」と「TP満タン時」と「敵を倒したとき」では
効果を分けたいのではないかということです。
もしそうだとするならば、現状の構造では多分不可能です。
ちょっと大規模な改修か、新たに追加する機能を搭載した
スクリプトを作成する必要がありそうです。

こんなところでしょうか。
暇があったらご要望に沿ってスクリプトを書き直しますが、
今のところはこんな感じです。
---------------------------------------------
自作の(改造でない)スクリプト素材に
関しては、リードミーもしくは作中に
「faida」と記名していただければ
利用可能です。
せくもん
記事: 36
登録日時: 2018年6月09日(土) 21:48

Re: 【RGSS3】faida様作『瀕死時に××』の機能拡張

投稿記事by せくもん » 2019年8月29日(木) 21:25

faida様、ご返答ありがとうございます。
スクリプト作成者ご本人からご返答いただけるとは、とてもありがたいです。

ご説明いただいた方法を試したところ、とりあえず「TP満タン時」に
効果を発動させる事は上手くいきました。ありがとうございました。

>返信を書いていて思ったのは、せくもんさんはおそらく
>「瀕死時」と「TP満タン時」と「敵を倒したとき」では
>効果を分けたいのではないかということです。

そうですね。当初は1つのスクリプトに纏められないなら内容が同じで
発動条件だけ異なる3つのスクリプトを用意すれば良いのでは?とも考えましたが
『不可能』という事は、それはそれで何か不具合が生じるのですね。
何か上手い解決法は無いか、もう少し考えてみます。

どうもありがとうございました。
faida
記事: 236
登録日時: 2015年12月17日(木) 16:44

Re: 【RGSS3】faida様作『瀕死時に××』の機能拡張

投稿記事by faida » 2019年8月31日(土) 18:17

こんばんは。
せくもんさんのおっしゃる通りにスクリプトを3つに分けるなら、
そこまで大きな不具合は出ないと思います。
ただ、発動条件だけを変えて3つのスクリプトに分ける場合、
それでもちょっとだけ不具合が出るような気がしています。
それは「@crisis_effects」です。

この「@crisis_effects」というインスタンス変数には、
・戦闘開始時(とステート付加時)に効果をセット
・発動条件を満たしたら中身を全て発動した後中身をクリア
という操作があります。

この変数の名前を各スクリプトで変えないと、
一つの条件を満たしたときに全部発動してしまうという
不具合が発生すると思います。
なので、分けるならそこも、ですね。

私は、スクリプトを1つのまま改造するものだと思っていたので、
条件によって効果を分けるなら、どの条件でどの効果を発動するか
条件分岐しなくてはならない、という意味で、
「現状の構造では不可能」と書きました。
ただ、それはそれで面白そうなので、
時間があれば実装したいと考えていますが。

何か不明点等あればおっしゃってください。
---------------------------------------------
自作の(改造でない)スクリプト素材に
関しては、リードミーもしくは作中に
「faida」と記名していただければ
利用可能です。
せくもん
記事: 36
登録日時: 2018年6月09日(土) 21:48

Re: 【RGSS3】faida様作『瀕死時に××』の機能拡張

投稿記事by せくもん » 2019年8月31日(土) 21:51

faida様、ご返答ありがとうございます。

>この変数の名前を各スクリプトで変えないと、
>一つの条件を満たしたときに全部発動してしまうという
>不具合が発生すると思います。
>なので、分けるならそこも、ですね。

つまり、メモ欄に書く記述を<TP満タン時効果 id, n>に替えつつ
スクリプト全文を@crisis_effectsで検索して該当箇所を
@tpmax_effects等に書き換えれば良いのでしょうか?
それでしたら、なんとか自力で解決出来そうです。


あと2点ほどお伺いしたいのですが
①前回の返信で教えていただいた『敵を倒した時』のコードは(中略)の部分を書き足せば
 そのまま使えるのでしょうか?それとも元のコードに追加する必要があるのでしょうか?

②idの2番、4番の効果が発動した際にHPやMPが『100.0』みたいな表記になるのですが
 小数点以下を切り捨てて整数の値に修正するには、どの様に記述すれば良いでしょうか?


以上、ご返答いただけるとありがたいです。
faida
記事: 236
登録日時: 2015年12月17日(木) 16:44

Re: 【RGSS3】faida様作『瀕死時に××』の機能拡張

投稿記事by faida » 2019年9月02日(月) 21:52

①元のコードに追加する形となりますが、元のコードには
瀕死時に××する処理が残っているので、それを無効化する必要があります。
「check_crisis_effects」を呼び出している箇所を削除すると
上手くいくかもしれません。

②不具合ですね。申し訳ありません。

コード: 全て選択

(arr[1] * mhp).to_i
のように、整数化する必要がありました。
元スクリプトも後で修正します。
---------------------------------------------
自作の(改造でない)スクリプト素材に
関しては、リードミーもしくは作中に
「faida」と記名していただければ
利用可能です。

“VX / Ace:質問” へ戻る