#======================================================================
# 脚本来自[url]www.66rpg.com[/url],使用或转载请保留此信息
# 功能:多状态动画同时显示
# 版本:2.01
# 作者:后知后觉 2011-3-2
# 使用方法:插入Main前即可
# 冲突可能:只要在你的脚本编辑器内没有对 RPG::Sprite 或 Sprite_Battler 类
#           以下三个方法做出过别的定义 则就有较大的兼容性
#           loop_animation
#           dispose_loop_animation
#           update_loop_animation
#----------------------------------------------------------------
# 使用方法:
 
# 在状态库和动画库的名称开头,加上XM,便使该ID动画Z坐标下降
 
# 普通动画z坐标为self.z
 
# 状态动画z坐标为self.z + 6,  动画名字中包含"SM"二字为人物动画
 
# 状态动画z坐标为self.z - 200,动画名字中包含"XM"二字为状态动画
 
# 优先级为 SM动画(self.z + 6) > 普通动画(self.z) > XM动画(self.z - 200)
#----------------------------------------------------------------
 
module RPG
  class Sprite < ::Sprite
    if @hzhj_alias_method_for_state_animation.nil?
      alias hzhj_old_ini_for_state_animation initialize
      alias hzhj_old_update_for_state_animation update
      alias hzhj_old_x_for_state_animation x=
      alias hzhj_old_y_for_state_animation y=
      @hzhj_alias_method_for_state_animation = true
    end
    def initialize(*args)
      @hzhj_loop_animations = []
      @hzhj_loop_sprites = {}
      @hzhj_loop_index = {}
      hzhj_old_ini_for_state_animation(*args)
    end
    def animation(animation, hit, user=nil)
      dispose_animation
      @_animation = animation
      return if @_animation == nil
      @_animation_hit = hit
      @_animation_duration = @_animation.frame_max
      animation_name = @_animation.animation_name
      animation_hue = @_animation.animation_hue
 
      #----------------------------------------------------------------
      # #【战斗图色相关联动画色相】
      unless user.nil?
        if user.is_a?(Game_Actor)
          if ANIMATION_ACTOR.keys.include?(user.id) 
            animation_hue = user.battler_hue if ANIMATION_ACTOR[user.id].include?(animation.id)
          end
        else
          if ANIMATION_ENEMY.keys.include?(user.id) 
            animation_hue = user.battler_hue if ANIMATION_ENEMY[user.id].include?(animation.id)
          end
        end
      end      
      #----------------------------------------------------------------
 
      bitmap = RPG::Cache.animation(animation_name, animation_hue)
      if @@_reference_count.include?(bitmap)
        @@_reference_count[bitmap] += 1
      else
        @@_reference_count[bitmap] = 1
      end
      @_animation_sprites = []
      if @_animation.position != 3 or not @@_animations.include?(animation)
        for i in 0..15
          sprite = ::Sprite.new(self.viewport)
          sprite.bitmap = bitmap
          sprite.visible = false
 
          # 当战斗者为角色的情况
          if @battler.is_a?(Game_Actor)
             self.z = @battler.s_y + 100
          # 当战斗者为敌人的情况
          elsif @battler.is_a?(Game_Enemy)
             self.z = @battler.screen_y + 100
          else
             self.z = 10+1000 # 平时【非战斗】
          end         
          # 默认动画 Z坐标★★★★★★★★★★★★★★★★★
          sprite.z = self.z
 
          @_animation_sprites.push(sprite)
        end
        unless @@_animations.include?(animation)
          @@_animations.push(animation)
        end
      end
      update_animation
    end
 
    def loop_animation(animation)
      return if @hzhj_loop_animations.include?(animation)
      if animation.nil?
        dispose_loop_animation
        return
      end
      @hzhj_loop_animations.push(animation)
      @hzhj_loop_index[animation] = 0
      animation_name = animation.animation_name
      animation_hue = animation.animation_hue
      bitmap = RPG::Cache.animation(animation_name, animation_hue)
      if @@_reference_count.include?(bitmap)
        @@_reference_count[bitmap] += 1
      else
        @@_reference_count[bitmap] = 1
      end
      loop_animation_sprites = []
      for i in 0..15
        sprite = ::Sprite.new(self.viewport)
        sprite.bitmap = bitmap
 
        # 当战斗者为角色的情况
        if @battler.is_a?(Game_Actor)
           self.z = @battler.s_y + 100
        # 当战斗者为敌人的情况
        elsif @battler.is_a?(Game_Enemy)
           self.z = @battler.screen_y + 100
        else
           self.z = 10
        end
        # 默认动画 Z坐标★★★★★★★★★★★★★★★★★ 
        sprite.z = self.z
        # 调整动画名字前面带 "SM" 的动画的 Z坐标★★★★★★★★★★★★★★★★★
        sprite.z = self.z + 1 if animation.name.include?("SM")
 
        sprite.visible = false
        loop_animation_sprites.push(sprite)
      end
      @hzhj_loop_sprites[animation] = loop_animation_sprites
      update_loop_animation
    end
    def dispose_loop_animation
      if not @hzhj_loop_animations.empty?
        for sprites in @hzhj_loop_sprites.values
          next if sprites.nil?
          sprite = sprites[0]
          if sprite != nil
            @@_reference_count[sprite.bitmap] -= 1
            if @@_reference_count[sprite.bitmap] == 0
              sprite.bitmap.dispose
            end
          end
          for sprite in sprites
            sprite.dispose
          end
        end
        @hzhj_loop_index.clear
        @hzhj_loop_sprites.clear
        @hzhj_loop_animations.clear
      end
    end
    def update
      hzhj_old_update_for_state_animation
      # 调整状态动画的刷新速度,修改 Graphics.frame_count % 2 == 0
      if not @hzhj_loop_animations.empty? and (Graphics.frame_count % 2 == 0)
        update_loop_animation
        for animation in @hzhj_loop_animations
          @hzhj_loop_index[animation] += 1
          @hzhj_loop_index[animation] %= animation.frame_max
        end
      end
    end
    def update_loop_animation
      # 死亡时状态动画的可见度
      if @xiaoshi2 != nil and @xiaoshi2 > 255
        @xiaoshi2 = 1
        for animation in @hzhj_loop_animations
          frame_index = @hzhj_loop_index[animation]
          cell_data = animation.frames[frame_index].cell_data
          position = animation.position
          sprites = @hzhj_loop_sprites[animation]
          animation_set_sprites(sprites, cell_data, position, true)
        end
      else
        for animation in @hzhj_loop_animations
          frame_index = @hzhj_loop_index[animation]
          cell_data = animation.frames[frame_index].cell_data
          position = animation.position
          sprites = @hzhj_loop_sprites[animation]
          hzhj = animation.name.clone
          animation_set_sprites(sprites, cell_data, position, false, hzhj)
          for timing in animation.timings
            if timing.frame == frame_index
              animation_process_timing(timing, true)
            end
          end
        end
      end
    end
    def x=(new_x)
      sx = new_x - self.x
      if sx != 0
        if not @hzhj_loop_animations.empty?
          for animation in @hzhj_loop_animations
            for i in 0..15
              @hzhj_loop_sprites[animation][i].x += sx
            end
          end
        end
      end
      hzhj_old_x_for_state_animation(new_x)
    end
    def y=(new_y)
      sy = new_y - self.y
      if sy != 0
        if not @hzhj_loop_animations.empty?
          for animation in @hzhj_loop_animations
            for i in 0..15
              @hzhj_loop_sprites[animation][i].y += sy
            end
          end
        end
      end
      hzhj_old_y_for_state_animation(new_y)
    end
    def stop_loop_animation(animation)
      return if not @hzhj_loop_animations.include?(animation)
      if not @battler.nil?
        for i in @battler.states
          next if $data_states[i].nil?
          if $data_states[i].animation_id == animation.id
            return
          end
        end
      end
      sprites = @hzhj_loop_sprites[animation]
      sprite = sprites[0]
      if sprite != nil
        @@_reference_count[sprite.bitmap] -= 1
        if @@_reference_count[sprite.bitmap] == 0
          sprite.bitmap.dispose
        end
      end
      for sprite in sprites
        sprite.dispose
      end
      @hzhj_loop_index[animation] = 0
      @hzhj_loop_sprites[animation] = nil
      @hzhj_loop_animations.delete(animation)
    end
    def animation_set_sprites(sprites, cell_data, position,kds = false, hzhj = nil)
      if kds
        for i in 0..15
          sprites[i].visible = false
        end
        return
      end
      for i in 0..15
        sprite = sprites[i]
        pattern = cell_data[i, 0]
        if sprite == nil or pattern == nil or pattern == -1
          sprite.visible = false if sprite != nil
          next
        end
        sprite.visible = true
        sprite.src_rect.set(pattern % 5 * 192, pattern / 5 * 192, 192, 192)
        if position == 3
          if self.viewport != nil
            sprite.x = self.viewport.rect.width / 2
            sprite.y = self.viewport.rect.height - 160
          else
            sprite.x = 320
            sprite.y = 240
          end
        else
          sprite.x = self.x - self.ox + self.src_rect.width / 2
          sprite.y = self.y - self.oy + self.src_rect.height / 2
          sprite.y -= self.src_rect.height / 4 if position == 0
          sprite.y += self.src_rect.height / 4 if position == 2
        end
        sprite.x += cell_data[i, 1]
        sprite.y += cell_data[i, 2]
 
        # 当战斗者为角色的情况
        if @battler.is_a?(Game_Actor)
           self.z = @battler.s_y + 100
        # 当战斗者为敌人的情况   
        elsif @battler.is_a?(Game_Enemy)
           self.z = @battler.screen_y + 100
        else
           self.z = 10
        end
 
        if position == 1 and not hzhj.nil? and hzhj[0, 2] == "XM"
        # 调整动画名字前面带 "XM" 的动画的 Z坐标 显示在战斗图下方  
          sprite.z = self.z - 200
        end
 
        # > 粗暴式修正,有调试需求改下方增加的数值 <
        if position == 1 and not hzhj.nil? and hzhj[0, 2] == "SM"
        # 调整动画名字前面带 "SM" 的动画的 Z坐标 显示在战斗图上方  
          z_plus = 6 # 最佳值
          sprite.z = self.z + z_plus
        end
 
        sprite.ox = 96
        sprite.oy = 96
        sprite.zoom_x = cell_data[i, 3] / 100.0
        sprite.zoom_y = cell_data[i, 3] / 100.0
        sprite.angle = cell_data[i, 4]
        sprite.mirror = (cell_data[i, 5] == 1)
        sprite.opacity = cell_data[i, 6] * self.opacity / 255.0
        sprite.blend_type = cell_data[i, 7]
      end
    end
  end
end
#==============================================================================
# ■ Game_Battler
#==============================================================================
 
class Game_Battler
  if @hzhj_alias_method_for_state_animation.nil?
    alias hzhj_old_ini_gb_state_animation initialize
    alias hzhj_old_add_state add_state
    alias hzhj_old_remove_state remove_state
    @hzhj_alias_method_for_state_animation = true
  end
  #--------------------------------------------------------------------------
  # ● 定义实例变量
  #--------------------------------------------------------------------------
  attr_reader   :hzhj_add_state_id
  attr_reader   :hzhj_remove_state_id
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize
    @hzhj_add_state_id = []
    @hzhj_remove_state_id = []
    hzhj_old_ini_gb_state_animation
  end
  #--------------------------------------------------------------------------
  # ● 附加状态
  #--------------------------------------------------------------------------
  def add_state(state_id, force = false)
    old_states = @states.clone
    hzhj_old_add_state(state_id, force)
    return if old_states == @states
    zjdzt = (@states | old_states) & @states
    jsdzt = (@states | old_states) & old_states
    for i in zjdzt
      if $data_states[i].animation_id > 0
        if not @hzhj_add_state_id.include?(i)
          @hzhj_add_state_id.push(i)
        end
      end
    end
    for i in jsdzt
      if $data_states[i].animation_id > 0
        if not @hzhj_remove_state_id.include?(i)
          @hzhj_remove_state_id.push(i)
        end
      end
    end
  end
  #--------------------------------------------------------------------------
  # ● 解除状态
  #--------------------------------------------------------------------------
  def remove_state(state_id, force = false)
    old_states = @states.clone
    hzhj_old_remove_state(state_id, force)
    return if old_states == @states
    zjdzt = (@states | old_states) & @states
    jsdzt = (@states | old_states) & old_states
    for i in zjdzt
      if $data_states[i].animation_id > 0
        if not @hzhj_add_state_id.include?(i)
          @hzhj_add_state_id.push(i)
        end
      end
    end
    for i in jsdzt
      if $data_states[i].animation_id > 0
        if not @hzhj_remove_state_id.include?(i)
          @hzhj_remove_state_id.push(i)
        end
      end
    end
  end
end
#==============================================================================
# ■ Sprite_Battler
#==============================================================================
 
class Sprite_Battler < RPG::Sprite
  if @hzhj_alias_sb_for_state_animation.nil?
    alias hzhj_old_init_sb_for_state_animation initialize
    alias hzhj_old_update_sb_for_state_animation update
    @hzhj_alias_sb_for_state_animation = true
  end
  #--------------------------------------------------------------------------
  # ● 初始化
  #--------------------------------------------------------------------------
  def initialize(*args)
    hzhj_old_init_sb_for_state_animation(*args)
    if not @battler.nil?
      @battler.hzhj_add_state_id.clear
      @battler.hzhj_remove_state_id.clear
      for i in @battler.states
        next if $data_states[i].nil?
        next if $data_states[i].animation_id == 0
        next if $data_animations[$data_states[i].animation_id].nil?
        @battler.hzhj_add_state_id.push(i)
      end
    end
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def update
    hzhj_old_update_sb_for_state_animation
    if not @battler.nil?
      if @battler.damage.nil?
        if not @battler.hzhj_add_state_id.empty?
          for i in @battler.hzhj_add_state_id
            if @battler.state?(i)
              animation_id = $data_states[i].animation_id
              animation = $data_animations[animation_id]
              loop_animation(animation) if not animation.nil?
            end
          end
          @battler.hzhj_add_state_id.clear
        end
        if not @battler.hzhj_remove_state_id.empty?
          for i in @battler.hzhj_remove_state_id
            if not @battler.state?(i)
              animation_id = $data_states[i].animation_id
              animation = $data_animations[animation_id]
              stop_loop_animation(animation) if not animation.nil?
            end
          end
          @battler.hzhj_remove_state_id.clear
        end
      end
    end
  end
end