#◆◇◆◇◆  ☆ 多重追加アニメーション ver 1.02  ◇◆◇◆◇
# ☆ マスタースクリプト ver 2.00 以降専用
#  サポート掲示板 [url]http://www2.ezbbs.net/21/minto-aaa/[/url]
#   by みんと

=begin

更新履歴

ver 1.02(2009/11/24)
・イベントの解放に時間がかかる仕様を変更

ver 1.01(2008/09/07)
・F12リセットでエラー落ちするミスを修正


セクション指定上下関係

アクティブ・アニメシェイク
↓
A・C・A・システム
↓
このスクリプト

説明

デフォルトでは、
戦闘アニメ表示中に、新たなアニメを表示した場合、
表示中のアニメが消えてしまいますが、
多重表示できるアニメ表示機能を追加します。

設定には
アニメーションに「強さが 0」の「画面のフラッシュ」を設定してください。
そのフレームで、アニメを追加します。
アニメのIDはフラッシュの赤、青、緑の合計値になります。
なので、事実上、ID_765番までのアニメを追加表示できます。

フラッシュの条件も機能しますので、
ヒットした場合のみの追加エフェクト、
ミスした場合のみのエフェクトなど、
バリエーションが広がります。

なお、追加にACAシステムが反映されないのは仕様となっています。
(動きがおかしくなってしまうので)

またデフォルトのアニメの表示機能自体はそのままです。
マップでも反映されます。

=end

#==============================================================================
# ☆ MINTO
#------------------------------------------------------------------------------
#   様々なフラグを扱うメインモジュールです。
#==============================================================================

module MINTO
  
  # 多重追加アニメーションを有効化( true で有効 / false で無効 )
  RGSS["Array_Anima"] = true
    
end

if MINTO::RGSS["Array_Anima"]

#==============================================================================
# ☆ Mint_Cache
#------------------------------------------------------------------------------
#   様々なキャッシュを扱うモジュールです。
#==============================================================================

module Mint_Cache
  # キャッシュを初期化
  @cache = {}
  #-------------------------------------------------------------------------
  # ● ビットマップのロード
  #    folder_name : 読み込むフォルダ
  #    filename    : 読み込むファイル
  #    hue         : 色相の情報
  #-------------------------------------------------------------------------
  def self.load_bitmap(folder_name, filename, hue = 0)
    # ハッシュ用のパスを設定
    path = folder_name + filename
    # 未作成のアニメかそのアニメが解放されている場合
    if not @cache.include?(path) or @cache[path].disposed?
      # ファイルネームが空文字以外の場合
      if filename != ""
        # ファイルからビットマップを作成
        @cache[path] = Bitmap.new(path)
      else
        # ビットマップを作成
        @cache[path] = Bitmap.new(32, 32)
      end
    end
    # 色相の変換が無い場合
    if hue == 0
      # 元の画像ファイルを渡す
      return @cache[path]
    else
      # ハッシュ用のキーを取得
      key = [path, hue]
      # キャッシュに存在しないかすでに解放されている場合
      if not @cache.include?(key) or @cache[key].disposed?
        # キャッシュに複製を渡す
        @cache[key] = @cache[path].clone
        # 色相を変更
        @cache[key].hue_change(hue)
      end
      # 画像のファイルを渡す
      return @cache[key]
    end
  end
  #-------------------------------------------------------------------------
  # ● アニメーションの読み込み
  #    filename    : 読み込むファイル
  #    hue         : 色相の情報
  #-------------------------------------------------------------------------
  def self.animation(filename, hue)
    # 対象ファイルを読み込んで渡す
    return self.load_bitmap("Graphics/Animations/", filename, hue)
  end
  #-------------------------------------------------------------------------
  # ● クリア
  #-------------------------------------------------------------------------
  def self.clear
    # キャッシュの内容をクリア
    @cache = {}
  end
end
#==============================================================================
# ■ RPG::Sprite
#------------------------------------------------------------------------------
#   ゲームで戦闘中に使用されるスプライト表示を管理するクラスです。
#==============================================================================

module RPG
  class Sprite < ::Sprite
    #-----------------------------------------------------------------------
    # ● 配列アニメーション作成
    #    animation : 渡されたアニメーション
    #    hit       : ヒットフラグ
    #-----------------------------------------------------------------------
    def array_animation(animation, hit)
      # 無効なアニメの場合
      if animation == nil then
        # 処理を返す
        return
      end
      # アニメを配列の先頭に追加
      @_array_animation.unshift(animation)
      # ヒットフラグの先頭に追加
      @_array_animation_hit.unshift(hit)
      # 更新カウントの先頭に追加
      @_array_animation_duration.unshift(animation.frame_max)
      # アニメの名前を取得
      animation_name = animation.animation_name
      # アニメの色調情報を取得
      animation_hue = animation.animation_hue
      # アニメの画像をキャッシュからロード
      bitmap = Mint_Cache.animation(animation_name, animation_hue)
      # アニメのスプライトを作成して先頭に追加
      @_array_animation_sprite.unshift(sprite_set_array(bitmap))
    end
    #------------------------------------------------------------------------
    # ● スプライトセット
    #    bitmap : 読み込んだ画像
    #------------------------------------------------------------------------
    def sprite_set_array(bitmap)
      # 配列を初期化
      animation_sprites = []
      # スプライトを新規作成
      sprite = ::Sprite.new(self.viewport)
      sprite.bitmap = bitmap
      sprite.visible = false
      animation_sprites.push(sprite)
      sprite = ::Sprite.new(self.viewport)
      sprite.bitmap = bitmap
      sprite.visible = false
      animation_sprites.push(sprite)
      sprite = ::Sprite.new(self.viewport)
      sprite.bitmap = bitmap
      sprite.visible = false
      animation_sprites.push(sprite)
      sprite = ::Sprite.new(self.viewport)
      sprite.bitmap = bitmap
      sprite.visible = false
      animation_sprites.push(sprite)
      sprite = ::Sprite.new(self.viewport)
      sprite.bitmap = bitmap
      sprite.visible = false
      animation_sprites.push(sprite)
      sprite = ::Sprite.new(self.viewport)
      sprite.bitmap = bitmap
      sprite.visible = false
      animation_sprites.push(sprite)
      sprite = ::Sprite.new(self.viewport)
      sprite.bitmap = bitmap
      sprite.visible = false
      animation_sprites.push(sprite)
      sprite = ::Sprite.new(self.viewport)
      sprite.bitmap = bitmap
      sprite.visible = false
      animation_sprites.push(sprite)
      sprite = ::Sprite.new(self.viewport)
      sprite.bitmap = bitmap
      sprite.visible = false
      animation_sprites.push(sprite)
      sprite = ::Sprite.new(self.viewport)
      sprite.bitmap = bitmap
      sprite.visible = false
      animation_sprites.push(sprite)
      sprite = ::Sprite.new(self.viewport)
      sprite.bitmap = bitmap
      sprite.visible = false
      animation_sprites.push(sprite)
      sprite = ::Sprite.new(self.viewport)
      sprite.bitmap = bitmap
      sprite.visible = false
      animation_sprites.push(sprite)
      sprite = ::Sprite.new(self.viewport)
      sprite.bitmap = bitmap
      sprite.visible = false
      animation_sprites.push(sprite)
      sprite = ::Sprite.new(self.viewport)
      sprite.bitmap = bitmap
      sprite.visible = false
      animation_sprites.push(sprite)
      sprite = ::Sprite.new(self.viewport)
      sprite.bitmap = bitmap
      sprite.visible = false
      animation_sprites.push(sprite)
      sprite = ::Sprite.new(self.viewport)
      sprite.bitmap = bitmap
      sprite.visible = false
      animation_sprites.push(sprite)
      # スプライトを返す
      return animation_sprites
    end
    #------------------------------------------------------------------------
    # ● 配列アニメの更新
    #------------------------------------------------------------------------
    def update_array_anima
      # 現在表示中のアニメの数だけ繰り返す
      (0...@_array_animation_duration.size).each do |i|
        # グラフィックカウントが偶数の場合
        if (Graphics.frame_count % 2 == 0) then
          # アニメを取得
          anima = @_array_animation[i]
          # 無効なアニメの場合
          if anima == nil then
            # 次の処理へ以降
            next
          end
          # アニメーションカウントを減らす
          @_array_animation_duration[i] -= 1
          # アニメのスプライトを取得
          sprite = @_array_animation_sprite[i]
          # アニメのヒットフラグを取得
          hit = @_array_animation_hit[i]
          # アニメカウントが1以上の場合
          if @_array_animation_duration[i] >= 1 then
            # 現在のフレームを取得
            frame_index = anima.frame_max - @_array_animation_duration[i]
            # アニメのセルのデータを取得
            cell_data = anima.frames[frame_index].cell_data
            # アニメのポジションデータを取得
            position = anima.position
            # 生成先のオブジェクトに応じて分岐
            case self
            # マップキャラクターの場合
            when Sprite_Character then
              # アニメを動かす
              animation_set_sprites(sprite, cell_data, position)
            # 戦闘キャラの場合
            else
              # ターゲット二体目以降ではない場合
              if self.battler != nil and not self.battler.all_anime then
                # アニメを動かす
                animation_set_sprites(sprite, cell_data, position)
              end
            end
            # アニメの効果を進める
            anima.timings.each do |timing|
              # タイミングのフレームと現在のフレームが等しい場合
              if timing.frame == frame_index-1 then
                # アニメの効果を適用
                animation_process_timing(timing, hit)
              end
            end
          # アニメのカウントが0の場合
          else
            # アニメを解放
            dispose_array_animation(i)
          end
        end
      end
    end
    #-----------------------------------------------------------------------
    # ● 配列アニメを解放
    #    index : 求められたアニメのインデックス
    #-----------------------------------------------------------------------
    def dispose_array_animation(index)
      # アニメが有効な場合
      if @_array_animation[index] != nil then
        # セルスプライトを順番に処理
        @_array_animation_sprite[index].each do |sprite|
          # セルスプライトを解放
          sprite.dispose
        end
        # アニメを空にする
        @_array_animation[index] = nil
        @_array_animation_sprite[index] = nil
        @_array_animation_duration[index] = nil
        @_array_animation_hit[index] = nil
        # 無効な配列を除外
        @_array_animation.compact!
        @_array_animation_sprite.compact!
        @_array_animation_duration.compact!
        @_array_animation_hit.compact!
      end
      # インデックスが -1 の場合
      if index == -1 then
        # 表示中のアニメ分だけ繰り返す
        (0...@_array_animation_sprite.size).each do |i|
          # 対象インデックスのアニメを解放
          dispose_array_animation(i)
        end
      end
    end
    #------------------------------------------------------------------------
    # ● 追加アニメの効果適用
    #    timing : SEなどのタイミングデータ
    #    hit    : アニメのヒットフラグ改造BY:SOULSAGA 20210314
    #------------------------------------------------------------------------
    def abb_anima_effect(timing, hit)
      红色=timing.flash_color.red.to_s
      绿色=timing.flash_color.green.to_s
      蓝色=timing.flash_color.blue.to_s
      动画2=红色+绿色
      动画3=红色+绿色+蓝色
      动画2=动画2.to_i
      动画3=动画3.to_i
      # 条件が ヒット で攻撃がヒットした場合か、
      # 条件が ミス で攻撃がミスだった場合、
      # もしくは条件が なし だった場合
      if (timing.condition == 0) or
        (timing.condition == 1 and hit == true) or
        (timing.condition == 2 and hit == false)
        # 強さが0の画面のフラッシュが設定されている場合
        if timing.flash_color.alpha == 0 and timing.flash_scope == 2 then
          # 追加アニメのIDを取得(フラッシュの赤、青、緑の合計値)
          anima_id = timing.flash_color.red
          anima_id += timing.flash_color.green
          anima_id += timing.flash_color.blue
          anima_id = timing.flash_duration == 2 ? 动画2 : timing.flash_duration == 3 ? 动画3 : anima_id 
          # アニメーションを読み込む
          anima = Data_Animations.data[anima_id]
          # 配列アニメを実行
          array_animation(anima, hit)
        end
      end
    end
  end
end
#==============================================================================
# ■ Game_Battler (分割定義 1)
#------------------------------------------------------------------------------
#  バトラーを扱うクラスです。このクラスは Game_Actor クラスと Game_Enemy クラ
# スのスーパークラスとして使用されます。
#==============================================================================

class Game_Battler
  #--------------------------------------------------------------------------
  # ● 公開インスタンス変数
  #--------------------------------------------------------------------------
  attr_accessor :all_anime                # ターゲット二体目以降フラグ
end
#==============================================================================
# ■ Sprite_Battler
#------------------------------------------------------------------------------
#  バトラー表示用のスプライトです。Game_Battler クラスのインスタンスを監視し、
# スプライトの状態を自動的に変化させます。
#==============================================================================

class Sprite_Battler < RPG::Sprite
  #--------------------------------------------------------------------------
  # ● オブジェクト初期化
  #     viewport : ビューポート
  #     battler  : バトラー (Game_Battler)
  #    alias     : initialize_Array_Anima
  #--------------------------------------------------------------------------
  alias initialize_Array_Anima initialize
  def initialize(viewport, battler = nil)
    # 元の処理を実行
    initialize_Array_Anima(viewport, battler)
    @_array_animation = []
    @_array_animation_sprite = []
    @_array_animation_duration = []
    @_array_animation_hit = []
  end
  #--------------------------------------------------------------------------
  # ● 解放
  #    alias : dispose_Array_Anima
  #--------------------------------------------------------------------------
  alias dispose_Array_Anima dispose
  def dispose
    # 元の処理を実行
    dispose_Array_Anima
    # 配列アニメを全て解放
    dispose_array_animation(-1)
    # キャッシュを解放
    Mint_Cache.clear
  end
  #--------------------------------------------------------------------------
  # ● フレーム更新
  #    alias : update_Array_Anima
  #--------------------------------------------------------------------------
  alias update_Array_Anima update
  def update
    # 元の処理を実行
    update_Array_Anima
    # 配列アニメを更新
    update_array_anima
  end
  #-------------------------------------------------------------------------
  # ● エフェクト表示中判定
  #-------------------------------------------------------------------------
  def effect?
    # スーパークラスを実行
    bool = super
    bool or @_array_animation_duration.size > 0
  end
  #--------------------------------------------------------------------------
  # ● アニメーション・プロセスタイミング
  #    timing : SEなどのデータ
  #    hit    : ヒットフラグ
  #--------------------------------------------------------------------------
  def animation_process_timing(timing, hit)
    # 追加アニメ判定
    abb_anima_effect(timing, hit)
    # スーパークラスメソッドを実行
    super(timing, hit)
    # アクティブ・アニメシェイクが有効ではない場合
    if not MINTO::RGSS["Active_Shake"] then
      # 処理を返す
      return
    end
    # 条件が ヒット で攻撃がヒットした場合か、
    # 条件が ミス で攻撃がミスだった場合、
    # もしくは条件が なし だった場合
    if (timing.condition == 0) or
      (timing.condition == 1 and hit == true) or
      (timing.condition == 2 and hit == false)
      # 対象無しのフラッシュが設定されている場合
      if timing.flash_scope == 0 then
        # フラッシュの赤と緑が0の場合
        if timing.flash_color.red == 0 and timing.flash_color.green == 0 then
          # シェイクの強さ(フラッシュの強さ)
          s_alpha = [timing.flash_color.alpha.to_i, 9].min
          # シェイクの早さ(フラッシュの青)
          s_speed = [timing.flash_color.blue.to_i, 9].min
          # シェイクの時間(フラッシュの時間)
          s_thyme = timing.flash_duration.to_i * 2
          # 画面をシェイク
          $game_screen.start_shake(s_alpha, s_speed, s_thyme)
        end
      end
    end
  end
end
#==============================================================================
# ■ Sprite_Character
#------------------------------------------------------------------------------
#  キャラクター表示用のスプライトです。Game_Character クラスのインスタンスを
# 監視し、スプライトの状態を自動的に変化させます。
#==============================================================================

class Sprite_Character < RPG::Sprite
 #--------------------------------------------------------------------------
  # ● オブジェクト初期化
  #     viewport  : ビューポート
  #     character : キャラクター (Game_Character)
  #     alias     : initialize_Array_Anima
  #--------------------------------------------------------------------------
  alias initialize_Array_Anima initialize
  def initialize(viewport, character = nil)
    @_array_animation = []
    @_array_animation_sprite = []
    @_array_animation_duration = []
    @_array_animation_hit = []
    # 元の処理を実行
    initialize_Array_Anima(viewport, character)
  end
  #--------------------------------------------------------------------------
  # ● 解放
  #--------------------------------------------------------------------------
  def dispose
    super
    # 配列アニメを全て解放
    dispose_array_animation(-1)
    # キャッシュを解放
    Mint_Cache.clear
  end
  #--------------------------------------------------------------------------
  # ● フレーム更新
  #    alias : update_Array_Anima
  #--------------------------------------------------------------------------
  alias update_Array_Anima update
  def update
    # 元の処理を実行
    update_Array_Anima
    # 配列アニメを更新
    update_array_anima
  end
  #--------------------------------------------------------------------------
  # ● アニメーション・プロセスタイミング
  #    timing : SEなどのデータ
  #    hit    : ヒットフラグ
  #--------------------------------------------------------------------------
  def animation_process_timing(timing, hit)
    # 追加アニメ判定
    abb_anima_effect(timing, hit)
    # スーパークラスメソッドを実行
    super(timing, hit)
    # アクティブ・アニメシェイクが有効ではない場合
    if not MINTO::RGSS["Active_Shake"] then
      # 処理を返す
      return
    end
    # 条件が ヒット で攻撃がヒットした場合か、
    # 条件が ミス で攻撃がミスだった場合、
    # もしくは条件が なし だった場合
    if (timing.condition == 0) or
      (timing.condition == 1 and hit == true) or
      (timing.condition == 2 and hit == false)
      # 対象無しのフラッシュが設定されている場合
      if timing.flash_scope == 0 then
        # フラッシュの赤と緑が0の場合
        if timing.flash_color.red == 0 and timing.flash_color.green == 0 then
          # シェイクの強さ(フラッシュの強さ)
          s_alpha = [timing.flash_color.alpha.to_i, 9].min
          # シェイクの早さ(フラッシュの青)
          s_speed = [timing.flash_color.blue.to_i, 9].min
          # シェイクの時間(フラッシュの時間)
          s_thyme = timing.flash_duration.to_i * 2
          # 画面をシェイク
          $game_screen.start_shake(s_alpha, s_speed, s_thyme)
        end
      end
    end
  end
end

end