#==============================================================================
#                   「アバターシステム」(ACE) ver.2.0
#   製作者:奈々(なな)
#   へぷたなすくろーる http://heptanas.mamagoto.com/
#
#   ◇使用規約
#   使用される場合はスクリプト作成者として「奈々」を明記して下さい。
#   このスクリプトを改変したり、改変したものを配布するなどは自由ですが
#   その場合も元のスクリプトの作成者として名前は載せて下さい。
#   その他、詳しい利用規約はブログを参照して下さい。
#
#------------------------------------------------------------------------------
#
#   「アバター画像」を組み合わせた歩行グラフィックを表示します。
#   アバター画像は、アクターの装備品やステートなどに応じて変更でき
#   画像を重ねるため、キャラクターの「着せ替え」や「装備」を手軽に表現できます。
#   具体的な使い方やテクニックなどは、ブログの記事を参考にして下さい。
#   
#   
#   <画像ファイルを用意する>
#   ・ダミー画像(識別用)
#   「avatar_actor_base」または「$avatar_actor_base」という歩行グラを用意します。
#   この歩行グラを指定したアクターは、歩行グラの変わりにアバターが表示されます。
#   (avatar_actor_base自体は表示されませんので、透明にする必要はありません)
#   また、この画像のサイズがアバターのサイズの基準となります。
#   
#   イベントキャラクターなどに、アクターのアバターを表示したい場合は
#   「avatar_actor_1」という歩行グラを用意して指定すれば
#   1番のアクターのアバターが表示されます。
#   
#   
#   ・アバター画像(表示用)
#   初期設定でフォルダを指定できます。
#   アバター画像の名前は自由で、$の付いた1キャラ分の画像も使えます。
#   キャラサイズはavatar_actor_baseと同じになるようにして下さい。
#   
#   avatar_actor_baseとアバター画像の両方が8キャラ仕様の場合は
#   インデックス番号に対応したアバターが表示されます。
#   これによって性別や体型の違いなどバリエーションを用意できます。
#   
#   
#   ・インデックスの変更
#   デフォルトでも一応出来ますが、些か使い勝手が悪いので用意してあります。
#   イベントコマンドのスクリプトで
#   n7_change_c_index("アクターID", "インデックス")
#   を入力すると、アクターの歩行グラのインデックスのみを変更できます。
#   
#   
#   <アバター画像を設定する>
#   ・アバターの仕組み
#   アバター画像を重ねて、リアルタイムで生成される歩行グラが、アバターです。
#   重ね方の順番は「レイヤ番号」で指定し、大きい方が上になります。
#   また同じレイヤ番号が指定されている場合は、優先順位に従って上書きされます。
#   
#   未指定のレイヤは飛ばされるため、いきなり100番を指定しても重くはなりません。
#   (むしろレイヤ番号は、ある程度飛ばし飛ばしで設定したほうが後々修正が利きます)
#   
#   アバター画像の指定は共通で、メモ欄に↓のタグを書きます。
#   <アバター "レイヤ番号" "ファイル名">
#   例えば「<アバター 0 Actor1>」なら0番レイヤにActor1.pngを設定します。
#   複数タグを書くことで、1項目に何枚でも設定可能です。
#   
#   
#   ・基本アバターの設定
#   アクター毎のアバター画像で、要するに顔や体など「裸」に相当するものです。
#   アクターのメモ欄でアバター画像を指定すると
#   ゲーム開始時の基本アバターが設定できます。
#   
#   また、イベントコマンドのスクリプトで
#   n7_cab("アクターID", "レイヤ番号", "ファイル名")
#   を入力すると基本アバターが変更できます。
#   ※このファイル名は""で囲ってください。例:n7_cab(1,0,"Avatar1")
#   
#   
#   ・追加アバターの設定
#   ステート・装備・スキル・クラスのメモ欄でアバター画像を指定すると
#   アクターがそれを身につけている場合に適用されます。
#   同レイヤの優先順位は、ステート>装備>スキル>クラス>基本アバターです。
#   
#   
#   ・アバター画像の不透明度指定
#   タグやコマンドではアバター画像の不透明度を指定できます。
#   これによって半透明のエフェクトや、画像の色合成も可能になります。
#   
#   <アバター "レイヤ番号" "ファイル名" "不透明度">
#   n7_cab("アクターID", "レイヤ番号", "ファイル名" "不透明度")
#   0だと透明、255だと指定なしと同じく不透明です。
#   
#
#==============================================================================
# ◇初期設定
module N7_Avatar
  
  AVATAR_FOLDER = "Graphics/Characters/"
  #アバター画像のフォルダ。歩行グラと同じなら「"Graphics/Characters/"」。
  
  DEBUG_MODE = false
  #動作チェック用、基本的にfalseのまま変更しない。
  
end


#==============================================================================
# ■ RPG::BaseItem
#------------------------------------------------------------------------------
#  アクター・装備・ステートなどを総括して扱うデータクラス。
#==============================================================================

class RPG::BaseItem
  #--------------------------------------------------------------------------
  # ● アバター画像
  #--------------------------------------------------------------------------
  def avatar_graphics
    avatar = []
    @note.scan(/<アバター\s+(\d+)\s+(.+)>/){|s|
      avatar[$1.to_i] = [$2.to_s, 255]
    }
    @note.scan(/<アバター\s+(\d+)\s+(.+)\s+(\d+)>/){|s|
      avatar[$1.to_i] = [$2.to_s, $3.to_i]
    }
    return avatar
  end
end


#==============================================================================
# ■ Game_Actor
#------------------------------------------------------------------------------
#  アクターを扱うクラスです。このクラスは Game_Actors クラス($game_actors)
# の内部で使用され、Game_Party クラス($game_party)からも参照されます。
#==============================================================================

class Game_Actor < Game_Battler
  #--------------------------------------------------------------------------
  # ● 公開インスタンス変数
  #--------------------------------------------------------------------------
  attr_accessor :avatar_base               # 基本アバター
  #--------------------------------------------------------------------------
  # ● セットアップ
  #--------------------------------------------------------------------------
  alias avatar_setup setup
  def setup(actor_id)
    avatar_setup(actor_id)
    @avatar_base = Array.new
    actor.avatar_graphics.each.with_index{|graphic,i|
      avatar_base[i] = graphic if graphic
    }
  end
  #--------------------------------------------------------------------------
  # ● アバター画像配列(結合)
  #--------------------------------------------------------------------------
  def avatar_mix
    avatar = @avatar_base.dup
    
    self.class.avatar_graphics.each.with_index{|graphic,i|
      avatar[i] = graphic if graphic
    }
    
    skills.each{|skill|
      next unless skill
      skill.avatar_graphics.each.with_index{|graphic,i|
        avatar[i] = graphic if graphic
      }
    }
    
    equips.each{|equip|
      next unless equip
      equip.avatar_graphics.each.with_index{|graphic,i|
        avatar[i] = graphic if graphic
      }
    }
    
    states.each{|state|
      next unless state
      state.avatar_graphics.each.with_index{|graphic,i|
        avatar[i] = graphic if graphic
      }
    }
    
    p avatar if N7_Avatar::DEBUG_MODE
    return avatar
  end
  #--------------------------------------------------------------------------
  # ● 歩行グラフィックの強制指定
  #--------------------------------------------------------------------------
  def character_name
    if @character_name == "avatar_actor_base"
      "avatar_actor_" + @actor_id.to_s
    elsif @character_name == "$avatar_actor_base"
      "$avatar_actor_" + @actor_id.to_s
    else
      @character_name
    end
  end
end


#==============================================================================
# ■ Cache
#------------------------------------------------------------------------------
#  各種グラフィックを読み込み、Bitmap オブジェクトを作成、保持するモジュール
# です。読み込みの高速化とメモリ節約のため、作成した Bitmap オブジェクトを内部
# のハッシュに保存し、同じビットマップが再度要求されたときに既存のオブジェクト
# を返すようになっています。
#==============================================================================

module Cache
  #--------------------------------------------------------------------------
  # ● 歩行グラフィックの取得
  #--------------------------------------------------------------------------
  def self.character(filename)
    p "歩行グラフィックの取得" if N7_Avatar::DEBUG_MODE
    if filename[/avatar_actor_(\d+)/] || filename[/\$avatar_actor_(\d+)/]
      load_avatar($game_actors[$1.to_i], filename)
    elsif filename[/avatar_party_(\d+)/] || filename[/\$avatar_party_(\d+)/]
      filename[/party/] = "actor"
      load_avatar($game_party.members[$1.to_i], filename)
    else
      load_bitmap("Graphics/Characters/", filename)
    end
  end
  #--------------------------------------------------------------------------
  # ● アバターグラフィックの取得
  #--------------------------------------------------------------------------
  def self.load_avatar(actor, filename)
    p "アバターグラフィックの取得" if N7_Avatar::DEBUG_MODE
    
    if filename[0,1] == "$"
      bitmap1 = load_bitmap("Graphics/Characters/", "$avatar_actor_base").dup
    else
      bitmap1 = load_bitmap("Graphics/Characters/", "avatar_actor_base").dup
    end
    bitmap1.clear
    actor.avatar_mix.each{|avatar|
      if avatar
        bitmap2 = load_bitmap(N7_Avatar::AVATAR_FOLDER, avatar[0])
        bitmap1.blt(0, 0, bitmap2, bitmap2.rect, avatar[1]) 
        if avatar[0,1] == "$" && filename[0,1] != "$"
          bitmap1.blt(bitmap2.width, 0, bitmap2, bitmap2.rect, avatar[1])
          bitmap1.blt(bitmap2*2.width, 0, bitmap2, bitmap2.rect, avatar[1])
          bitmap1.blt(bitmap2*3.width, 0, bitmap2, bitmap2.rect, avatar[1])
          bitmap1.blt(0, bitmap2.height, bitmap2, bitmap2.rect, avatar[1])
          bitmap1.blt(bitmap2.width, bitmap2.height, bitmap2, bitmap2.rect, avatar[1])
          bitmap1.blt(bitmap2.width*2, bitmap2.height, bitmap2, bitmap2.rect, avatar[1])
          bitmap1.blt(bitmap2.width*3, bitmap2.height, bitmap2, bitmap2.rect, avatar[1])
        end
      end
    }
    return bitmap1
  end
end


#==============================================================================
# ■ Game_Interpreter
#------------------------------------------------------------------------------
#  イベントコマンドを実行するインタプリタです。このクラスは Game_Map クラス、
# Game_Troop クラス、Game_Event クラスの内部で使用されます。
#==============================================================================

class Game_Interpreter
  #--------------------------------------------------------------------------
  # ● 基本アバターを変更する
  #--------------------------------------------------------------------------
  def n7_cab(actor_id, layer, filename = nil, opacity = 255)
    $game_actors[actor_id].avatar_base[layer] = filename ? [filename, opacity] : nil

    $nana_avatar_refresh = true
    Fiber.yield
    $nana_avatar_refresh = false
  end
  #--------------------------------------------------------------------------
  # ● アクターの画像インデックスだけ変更
  #--------------------------------------------------------------------------
  def n7_change_c_index(actor_id, index)
    actor = $game_actors[actor_id]
    actor.set_graphic(actor.character_name, index, actor.face_name, actor.face_index)
    $game_player.refresh
  end
end

#==============================================================================
# ■ Sprite_Character
#------------------------------------------------------------------------------
#  キャラクター表示用のスプライトです。Game_Character クラスのインスタンスを
# 監視し、スプライトの状態を自動的に変化させます。
#==============================================================================

class Sprite_Character < Sprite_Base
  #--------------------------------------------------------------------------
  # ● グラフィックの変更判定
  #--------------------------------------------------------------------------
  def graphic_changed?
    @tile_id != @character.tile_id ||
    @character_name != @character.character_name ||
    @character_index != @character.character_index ||
    (@character_name[/avatar_actor_/] && $nana_avatar_refresh)
  end
end