# =====================================================================
# [ステート特殊消去]＆[ステート引き受け]＆[ステート押し付け]スクリプト
# =====================================================================
# FF11のディスペルやイレース、サクリファイスやオーラスティール風の
# 特殊な形でステートを消したり移したりするスキルを作成できます。
# 新規メソッドとエイリアスのみなので、挿入部分は下の方で大丈夫です。
# 
# ■[ステート特殊消去]の使い方
# スキルのメモ欄に以下の例のような記述をする。
# 例：<ステート特殊消去:1:3>
# ・この場合STATES_TYPEの「タイプ1」のステート群の中から「3つ」ランダム消去。
# ・ランダム消去の数が対象にかかっている該当ステートの総数以上の場合でも構わない。
# 　数の指定の部分を種類異常にすれば該当ステートを全て消すという風に出来る。
# ・STATES_TYPEの内容次第で敵の強化だけを複数消すディスペル風スキルや、
# 　味方の弱体だけ消すイレース風スキルを作成できる。
# 
# ■[ステート引き受け]の使い方
# 例：<ステート引き受け:1:2>
# ・この場合STATES_TYPEで設定した「タイプ1」のステート群の中から
# 　「2つ」をランダムで「対象者から使用者へ」移し変える。
# ・味方から不利なステートを引き受ければサクリファイスのように、
# 　逆に敵から有利なステートを引き受ければオーラスティールのように使える。
# 
# ■[ステート押し付け]の使い方
# 例：<ステート押し付け:2:1>
# ・この場合STATES_TYPEで設定した「タイプ2」のステート群の中から
# 　「1つ」をランダムで「使用者から対象者へ」移し変える。
# ・不利なステートを敵に押し付けたり、
# 　味方へ自分の強化ステートを受け渡したりできる。
# 
# 
# ※ちなみに「引き受け」や「押し付け」と言っても処理的には
# 　一方のステートを消してもう一方に同じステートを新たにかけているだけなので、
# 　経過ターンなどが引き継がれる仕様ではありません。
# 
module NUKUMIZU
  STATES_TYPE = [[],
  # タイプ毎に消したいステート番号を下の[]内に記入
  
  # タイプ1　ディスペル型(有利な効果を打ち消す)
  [9,10,11,12],
  # タイプ2　イレース型(不利な効果を打ち消す)
  [13,14,15,16]
  # 以下、タイプ3以降必要ならば↓に追加可能。
  
  ]#←STATES_TYPEを綴じる役目なのでこれは消さずにつけておく。
  
  # メモ欄用キーワード設定
  DISPEL_NAME = [[],
  # ＜消去タイプ１＞該当するステートを消す。
  # 例：<ステート特殊消去:(タイプ):(数)>
  "ステート特殊消去",
  # ＜消去タイプ２＞該当するステートを対象から「使用者に移し変える」。
  # 例：<ステート引き受け:(タイプ):(数)>
  "ステート引き受け",
  # ＜消去タイプ３＞該当するステートを使用者から「対象に移し変える」。
  # 例：<ステート押し付け:(タイプ):(数)>
  "ステート押し付け"
  ]
end

#==============================================================================
# 変数を外部から参照できるように設定
#==============================================================================
class Scene_Battle < Scene_Base
  attr_accessor :active_battler
end
class Game_Actor < Game_Battler
  attr_accessor :me_added_states
  attr_accessor :me_removed_states
end
class Game_Enemy < Game_Battler
  attr_accessor :me_added_states
  attr_accessor :me_removed_states
end
#==============================================================================
# ■ Game_Battler
#------------------------------------------------------------------------------
# 　バトラーを扱うクラスです。このクラスは Game_Actor クラスと Game_Enemy クラ
# スのスーパークラスとして使用されます。
#==============================================================================
class Game_Battler
  #--------------------------------------------------------------------------
  # ● 行動効果の保持用変数をクリア　(エイリアス)
  #--------------------------------------------------------------------------
  alias dispel_clear_action_results clear_action_results
  def clear_action_results
    dispel_clear_action_results
    @me_added_states    = []
    @me_removed_states  = []
  end
  #--------------------------------------------------------------------------
  # ● ステート変化の適用　　　　　(エイリアス)
  #     obj : スキル、アイテム、または攻撃者
  #--------------------------------------------------------------------------
  alias dispel_apply_state_changes apply_state_changes
  def apply_state_changes(obj)
    dispel_apply(obj)                        # 独自処理呼び出し
    dispel_apply_state_changes(obj)          # 本来の処理を呼び戻す
  end
  #--------------------------------------------------------------------------
  # ● 消去タイプを判定　(新規)
  #--------------------------------------------------------------------------
  def dispel_type_check(obj)
    result = []
    result.push(1) if obj.note.include?("#{NUKUMIZU::DISPEL_NAME[1]}")
    result.push(2) if obj.note.include?("#{NUKUMIZU::DISPEL_NAME[2]}")
    result.push(3) if obj.note.include?("#{NUKUMIZU::DISPEL_NAME[3]}")
    return [0,0,0] if result == []
    obj.note.scan(/<#{NUKUMIZU::DISPEL_NAME[result[0]]}:(\d+):(\d+)>/)
    result.push($1.to_i)
    result.push($2.to_i)
    return result
  end
  #--------------------------------------------------------------------------
  # ● 特殊なステート変化の適用　　　　　(新規)
  #     obj : スキル、アイテム、または攻撃者
  #--------------------------------------------------------------------------
  def dispel_apply(obj)
    return if obj.class != RPG::Skill # スキルじゃない場合
    return if elements_max_rate(obj.element_set) <= 0 # 倍率0属性じゃないか
    type = dispel_type_check(obj)  # 別メソッドでタイプを判定
    return if type[0] == 0  # スキルのメモにキーワードがあるか
    return if NUKUMIZU::STATES_TYPE[type[1]] == nil #設定されてるタイプか
    dispel_type = type[0]
    states_type = type[1]
    repeat      = type[2]
    battler     = $scene.active_battler
    # 対象のステートをかかっているだけ配列化
    removed = []
    for i in NUKUMIZU::STATES_TYPE[states_type]
      if dispel_type != 3# タイプ3のステート押し付けか判断
        if state?(i)
          removed.push(i)
        end
      else
        if battler.state?(i)
          removed.push(i)
        end
      end
    end
    # 配列化した中からランダムでステート解除(はがす数だけ繰り返す)
    unless removed == []
      for i in 1..repeat
        break if removed == [] # 解除する物が残っていない場合ループ終了
        # 配列からランダム選出
        if removed.size > 1
          removed_target = rand(removed.size-1)+1
        else
          removed_target = 0
        end
        removed_states_id = removed[removed_target]
        
        if dispel_type == 1# タイプ1:ステート消去のみ
          remove_state(removed_states_id)
          @removed_states.push(removed_states_id)
        end
        if dispel_type == 2# タイプ1:ステート引き受け
          unless battler.state?(removed_states_id)
            remove_state(removed_states_id)
            @removed_states.push(removed_states_id)
            battler.add_state(removed_states_id)
            battler.me_added_states.push(removed_states_id)
          else
            repeat += 1 # 使用者に該当のステが付いて無い場合繰り返し回数加算
          end
        end
        if dispel_type == 3# タイプ3のステート押し付け
          unless state?(removed_states_id)
            battler.remove_state(removed_states_id)
            battler.me_removed_states.push(removed_states_id)
            add_state(removed_states_id)
            @added_states.push(removed_states_id)
          else
            repeat += 1 # 対象に該当のステが付いてない場合繰り返し回数加算
          end
        end
        removed.delete_at(removed_target)  # 処理したステを配列から除去
      end
    end
  end
  #--------------------------------------------------------------------------
  # ● 「行動者の」直前の行動でステートに対して何らかの働きかけがあったかを判定
  #--------------------------------------------------------------------------
  def me_states_active?
    return true unless @me_added_states.empty?
    return true unless @me_removed_states.empty?
    return false
  end
end

#==============================================================================
# ■ Scene_Battle
#------------------------------------------------------------------------------
# 　バトル画面の処理を行うクラスです。
#==============================================================================
class Scene_Battle < Scene_Base
  #--------------------------------------------------------------------------
  # ● 戦闘行動の実行 : スキル
  #--------------------------------------------------------------------------
  alias nukumizu_execute_action_skill execute_action_skill
  def execute_action_skill
    nukumizu_execute_action_skill # 本来の処理
    
    me = $scene.active_battler  # 現在の行動者代入
    unless me.skipped
      if me.me_added_states != [] or me.me_removed_states != []
        line_number = @message_window.line_number
        wait(5)
        display_me_state_changes(me, obj = nil)
        if line_number != @message_window.line_number
          wait(20)
        end
        @message_window.back_to(line_number)
      end
    end
  end
  #--------------------------------------------------------------------------
  # ● 「行動者の」ステート変化の表示まとめ
  #     target : 対象者
  #     obj    : スキルまたはアイテム
  #--------------------------------------------------------------------------
  def display_me_state_changes(target, obj = nil)
    if @message_window.line_number < 4
      @message_window.add_instant_text("")
    end
    display_me_added_states(target, obj)
    display_me_removed_states(target, obj)
    if @message_window.last_instant_text.empty?
      @message_window.back_one
    else
      wait(10)
    end
  end
  #--------------------------------------------------------------------------
  # ● 「行動者に」付加されたステートの実際の表示
  #     target : 使用者
  #     obj    : スキルまたはアイテム
  #--------------------------------------------------------------------------
  def display_me_added_states(target, obj = nil)
    return if target.me_added_states == nil
    return unless target.me_states_active?
    for state in target.me_added_states
      state = ($data_states[state])
      if target.actor?
        next if state.message1.empty?
        text = target.name + state.message1
      else
        next if state.message2.empty?
        text = target.name + state.message2
      end
      if state.id == 1                      # 戦闘不能
        target.perform_collapse
      end
      @message_window.replace_instant_text(text)
      wait(20)
    end
  end
  #--------------------------------------------------------------------------
  # ● 「行動者の」解除されたステートの実際の表示
  #     target : 対象者
  #     obj    : スキルまたはアイテム
  #--------------------------------------------------------------------------
  def display_me_removed_states(target, obj = nil)
    return if target.me_removed_states == nil
    return unless target.me_states_active?
    for state in target.me_removed_states
      state = ($data_states[state])
      next if state.message4.empty?
      text = target.name + state.message4
      @message_window.replace_instant_text(text)
      wait(20)
    end
  end
end