# ======================================================
#  「ヘイト上昇&低下ステート」スクリプトver.1.0
# ======================================================
# ■更新履歴
# ver.1.0(2011/3/31)
# ・新規作成
# ======================================================
# ■概要
# 「単体攻撃」及び「ランダム単体攻撃」の対象に
# 必ず含まれる・含まれないステートを作成できます。
# （全体攻撃は通常通り全員でくらいます。）
# 
# ■基本的な使い方
# スクリプト内の設定項目にヘイト上昇・ヘイト低下の扱いを受ける
# ステートのIDを記入します。（複数個可能）
# またオプションで、ヘイト関連ステートが付加されたターンの
# 攻撃対象も変更されるようになるかどうかの設定をできます。
# 
# ■機能解説
# ・「ヘイト上昇ステート」のバトラーは優先的に単体攻撃対象になります。
# 　複数のバトラーが上昇ステートにかかっている場合、
# 　そのバトラー達の中から対象が選択されます。
# ・「ヘイト低下ステート」のバトラーは単体攻撃対象になりません。
# 　ただし全員がヘイト低下ステートになっている場合は、
# 　通常通り全員の中から対象が選択されます。
# ・敵にヘイト関連ステートが付加された場合、
# 　こちらの単体攻撃の選択及びランダム攻撃の対象が
# 　敵と同じように制限されます。
# ・回想領域さん(http://kaisouryouiki.web.fc2.com/)の
# 　コマンドインデックス記憶スクリプトに対応しています。
# 　というかバグ回避で敵選択位置が記憶されないようになっています。
# 
# ■再定義している箇所
# class Window_TargetEnemy内
# 　initialize           （オブジェクト初期化）
# class Game_Unit内
# 　random_target        （ターゲットのランダムな決定）
# ■エイリアスしている箇所
# class Game_Unit内
#   smooth_targett       （ターゲットのスムーズな決定）
# 
# 同じ箇所を再定義やエイリアスしているスクリプトとは
# 競合する可能性があります。
# 
# ======================================================
module Nukumizu_Hate
  # ■ヘイト上昇ステートのID
  HATEUP_STATE_ID   = [17,18]
  # ■ヘイト低下ステートのID
  HATEDOWN_STATE_ID = [19,20]
  # ■ターン中にヘイト系ステートが付加された場合、
  # 　そのターンの攻撃にも影響を及ぼすか？
  # 　(trueでそのターンのターゲットも強制的に変更される。
  #　　falseでそのターンのターゲットには影響を及ぼさない。)
  HATE_FAST = true
end

$rsi = {} if $rsi == nil
class Scene_Battle < Scene_Base
  attr_accessor :active_battler
end
#==============================================================================
# ■ Window_TargetEnemy
#------------------------------------------------------------------------------
# 　バトル画面で、行動対象の敵キャラを選択するウィンドウです。
#==============================================================================
class Window_TargetEnemy < Window_Command
  #--------------------------------------------------------------------------
  # ● オブジェクト初期化　　■再定義
  #--------------------------------------------------------------------------
  def initialize
    commands = []
    @enemies = []
    hateup_commands = []
    hateup_enemies = []
    hatedown_commands = []
    hatedown_enemies = []
    for enemy in $game_troop.members
      next unless enemy.exist?
      if enemy.hatedown?      # ヘイト低下ステートが付加されている場合
        hatedown_commands.push(enemy.name) # ヘイト低下者専用の配列へ
        hatedown_enemies.push(enemy)
      elsif enemy.hateup?     # ヘイト上昇ステートが付加されている場合
        hateup_commands.push(enemy.name) # ヘイト上昇者専用の配列へ
        hateup_enemies.push(enemy)
      else                    # ヘイトステートが付加されていない場合
        commands.push(enemy.name) # 通常の配列へ
        @enemies.push(enemy)
      end
    end
    if hateup_enemies != [] # ヘイト上昇者専用の配列に何か入っている場合
      commands = hateup_commands # 通常配列にヘイト上昇配列を上書き
      @enemies = hateup_enemies
    elsif @enemies == [] # 存在者全員がヘイト低下で配列が両方空の場合
      commands = hatedown_commands # 通常配列にヘイト低下配列を上書き
      @enemies = hatedown_enemies
    end
    if $rsi["コマンドインデックス記憶"] == true # コマンド記憶
      $scene.active_battler.last_enemy = nil
    end
    super(416, commands, 2, 4)
  end
end

#==============================================================================
# ■ Game_Unit
#------------------------------------------------------------------------------
# 　ユニットを扱うクラスです。このクラスは Game_Party クラスと Game_Troop クラ
# スのスーパークラスとして使用されます。
#==============================================================================

class Game_Unit
  #--------------------------------------------------------------------------
  # ● ターゲットのランダムな決定　　■再定義
  #--------------------------------------------------------------------------
  def random_target
    roulette = []
    hateup_roulette = []
    hatedown_roulette = []
    for member in existing_members
      if member.hatedown?  # ヘイト低下ステートにかかっている場合
         member.odds.times do
          hatedown_roulette.push(member)
        end
      elsif member.hateup?  # ヘイト上昇ステートにかかっている場合
        member.odds.times do
          hateup_roulette.push(member)
        end
      else
        member.odds.times do
          roulette.push(member)
        end
      end
    end
    if hateup_roulette != [] # ヘイト上昇者専用の配列に何か入っている場合
      roulette = hateup_roulette
    elsif roulette == [] # 存在者全員がヘイト低下で配列が両方空の場合
      roulette = hatedown_roulette
    end
    return roulette.size > 0 ? roulette[rand(roulette.size)] : nil
  end
  #--------------------------------------------------------------------------
  # ● ターゲットのスムーズな決定　　■エイリアス
  #     index : インデックス
  #--------------------------------------------------------------------------
  alias hate_smooth_target smooth_target
  def smooth_target(index)
    if Nukumizu_Hate::HATE_FAST # ヘイトステ付加ターン影響がONかどうか
      unless members.include?($scene.active_battler) # 味方へのスキルかどうか
        hate_member = hate_existing_members # ヘイトを考慮した配列取得
        if hate_member[1] == true # ヘイトが影響していた場合
          member = members[index]
          if member != nil and member.exist? # 元々の対象が存在するか
            if hate_member[0].include?(member) # 元々の対象が配列に存在するか
              return member # 元々の対象を返す
            end
          end
          roulette = hate_member[0]
          return roulette.size > 0 ? roulette[rand(roulette.size)] : nil
        end
      end
    end
    hate_smooth_target(index) # 通常の処理へ
  end
  #--------------------------------------------------------------------------
  # ● ヘイトステートを考慮した生存しているメンバーの配列とフラグ取得　■新規
  #--------------------------------------------------------------------------
  def hate_existing_members
    result      = []
    hateup_result = []
    hatedown_result = []
    hate_flg    = false
    for battler in members
      next unless battler.exist?
      if battler.hatedown?  # ヘイト低下ステートにかかっているか？
        hate_flg = true
        hatedown_result.push(battler)
      elsif battler.hateup?  # ヘイト上昇ステートにかかっているか？
        hate_flg = true
        hateup_result.push(battler)
      else
        result.push(battler)
      end
    end
    if hate_flg == true     # ヘイト上昇・低下ステ者がいる場合
      if hateup_result != []  # ヘイト上昇者が居る場合
        return [hateup_result,true]
      elsif result == []  # 全員がヘイト低下者の場合
        return [hatedown_result,true]
      else
        return [result,true]
      end
    else
      return [result,false]  # ヘイトステの者が誰もいない場合
    end
  end
end

#==============================================================================
# ■ Game_Battler
#------------------------------------------------------------------------------
# 　バトラーを扱うクラスです。このクラスは Game_Actor クラスと Game_Enemy クラ
# スのスーパークラスとして使用されます。
#==============================================================================

class Game_Battler
  #--------------------------------------------------------------------------
  # ● ヘイト上昇ステートの付加チェック　　■新規
  #--------------------------------------------------------------------------
  def hateup?
    for id in Nukumizu_Hate::HATEUP_STATE_ID
      return true if self.states.include?($data_states[id])
    end
    return false
  end
  #--------------------------------------------------------------------------
  # ● ヘイト低下ステートの付加チェック　　■新規
  #--------------------------------------------------------------------------
  def hatedown?
    for id in Nukumizu_Hate::HATEDOWN_STATE_ID
      return true if self.states.include?($data_states[id])
    end
    return false
  end
end