#===============================================================================
# Achievements
# Version 2.23
# Author game_guy
#-------------------------------------------------------------------------------
# Intro:
# A full blown achievement system. Keep track of events your players pull off
# and make them feel like they've really achieved something. Easy to setup,
# plenty of options to configure it the way you want.
#
# Features:
# -Image/Text Achievement Notification
# -Show all achievements or only ones you unlocked
# -Change text font, size, and color
# -Option to keep track of score
# -Modify notification position
# -Modify text position if using an image
# -Modify popup time
# -Play sound when you unlock an achievement
# -Set return scene, scene you go to when exiting achievements menu
# -Custom queue system allowing you to display multiple achievements at a time
# -Much more compatible
# -Quickly open up achievements without interupting the current scene
# -Block scenes from the Quick Open
# -See if user has a specific achievement
# -See how many achievements the player has
# -Custom Icon Size Support
#
# Instructions:
# -Go down to Begin Config and edit all of your options there.
# -Instructions for creating achievements are also in the Config.
# -To gain an achievement, use Awards.gain(award_id)
# -Award id is set when creating awards.
# -To see if a user has an award use Awards.has?(award_id)
# -To see how many the player has use Awards.count
# -To open up the real achievements scene use
#  $scene = Scene_Achievements.new
#
# Compatibility:
# -Not tested with SDK.
# -Should work with everything.
# -May corrupt old save games.
# 
# Credits:
# -game_guy ~ For creating it.
# -jragyn00 ~ For the new layout.
# -GAX72 ~ For test achievement image.
#===============================================================================

module Awards
#===============================================================
# Begin Config
#===============================================================
  #----------------------------------------------------------------------------
  # If true, it'll show all unlocked and locked achievements, else it'll just
  # show unlocked achievements
  #----------------------------------------------------------------------------
  Show_All      = true
  #----------------------------------------------------------------------------
  # If Show_All is on, all locked icons will be displayed with the below
  # icon
  #----------------------------------------------------------------------------
  Locked_Icon   = "locked"
  #----------------------------------------------------------------------------
  # This replaces the achievments description if Show_All is on and the
  # achievement is marked as hidden.
  #----------------------------------------------------------------------------
  Hidden_Info   = "This achievement is hidden. Unlock it to find out more."
  #----------------------------------------------------------------------------
  # The scene you go to when you exit the achievements menu
  #----------------------------------------------------------------------------
  Return_Scene  = Scene_Menu
  #----------------------------------------------------------------------------
  # If set to an Input key, it will open up a quick view window to view all
  # achievements, can be opened up from anywhere, and doesn't interupt the
  # current scene. Set to nil to turn it off.
  #----------------------------------------------------------------------------
  Quick_Access  = Input::A
  #----------------------------------------------------------------------------
  # Add scenes here that you want quick access blocked on. Example, 
  # Scene_Title, wouldn't want users to view achievements there. Kinda odd.
  #----------------------------------------------------------------------------
  Block_Scenes  = [Scene_Title, Scene_Gameover, Scene_File, Scene_Register,
                   Scene_Login, Scene_Servers]
  #----------------------------------------------------------------------------
  # Keep track of score?
  #----------------------------------------------------------------------------
  Track_Score   = true
  #----------------------------------------------------------------------------
  # Text for "Score"
  #----------------------------------------------------------------------------
  Score_Text    = "Points"
  #----------------------------------------------------------------------------
  # Variable to store the score in. (hehe)
  #----------------------------------------------------------------------------
  Variable_Id   = 5
  #----------------------------------------------------------------------------
  # Font name
  # Place your font in string tags "font_here"
  # Or leave it as is to leave the default font.
  #----------------------------------------------------------------------------
  Text_Font     = Font.default_name
  #----------------------------------------------------------------------------
  # Font color : Color.new(red, green, blue)
  #----------------------------------------------------------------------------
  Text_Color    = Color.new(255, 255, 255)
  #----------------------------------------------------------------------------
  # Font size
  #----------------------------------------------------------------------------
  Text_Size     = 24
  #----------------------------------------------------------------------------
  # Where will the award show up on the screen. [X, Y]
  #----------------------------------------------------------------------------
  Award_Place   = [16, 16]
  #----------------------------------------------------------------------------
  # Use background image behind text?
  #----------------------------------------------------------------------------
  Use_Image     = true
  #----------------------------------------------------------------------------
  # File used to display behind the text.
  #----------------------------------------------------------------------------
  Image_File    = "award_background"
  #----------------------------------------------------------------------------
  # Offset for text drawn over the image. [X, Y]
  #----------------------------------------------------------------------------
  Image_Offset  = [72, 0]
  #----------------------------------------------------------------------------
  # Draw icon on notification image?
  #----------------------------------------------------------------------------
  Draw_Icon     = true
  #----------------------------------------------------------------------------
  # Offset for icon drawn over the image. [X, Y]
  #----------------------------------------------------------------------------
  Icon_Offset   = [20, 20]
  #----------------------------------------------------------------------------
  # Custom icon size. If you change these values, you'll have to change
  # Icon_Row and Icon_QuickRow. [WIDTH, HEIGHT]
  #----------------------------------------------------------------------------
  Icon_Size     = [24, 24]
  #----------------------------------------------------------------------------
  # How many icons are displayed in one column (across).
  #----------------------------------------------------------------------------
  Icon_Column   = 10
  #----------------------------------------------------------------------------
  # How many icons are in one column (across) in the Quick View scene.
  #----------------------------------------------------------------------------
  Icon_QColumn  = 8
  #----------------------------------------------------------------------------
  # Time the "Unlocked Achievement" pop up stays on screen in frames.
  #----------------------------------------------------------------------------
  Popup_Time    = 60
  #----------------------------------------------------------------------------
  # Sound played when an achievement pops up. ["sound", volume, pitch]
  #----------------------------------------------------------------------------
  Popup_Sound   = ["114-Remedy02", 100, 0]
  Award = []
  #----------------------------------------------------------------------------
  # To add a new award, add a new line:
  # Award[id] = ["name", "description", "icon", score_amount, hidden]
  # score_amount must be set even if Track_Score is off
  # hidden must be set even if Show_All is off
  # If you use Show_All and you want the description of achievements to be
  # hidden, set hidden to true. If its false, it'll tell the name and 
  # description.
  #----------------------------------------------------------------------------
  Award[0] = ["New Game", "Start a new game!", "037-Item06", 10, false]
  Award[1] = ["Award 1", "Talk to guy 1.", "046-Skill03", 10, true]
  Award[2] = ["Award 2", "Talk to guy 1.", "046-Skill03", 10, false]
  Award[3] = ["500 Damage", "Deal 500 damage in one attack.", "004-Weapon04", 5, false]
  Award[4] = ["Am I rich?", "Have 1,000,000 gold at one time.", "035-Item04", 10, false]
  Award[5] = ["Window Shopper", "Spend 1,000,000 gold.", "032-Item01", 10, false]
  Award[6] = ["Longer Description", "OMGAR this has a longer description but carries on to the next line. I'm so sexy.", "033-Item02", 0, false]
  Award[7] = ["Log Jumper", "Jump over the log.", "048-Skill05", 5, false]
  Award[8] = ["Super Log Jumper", "Jump over the log 5 times", "048-Skill05", 25, false]
  Award[9] = ["I am hidden!", "Learn about hidden achievements.", "034-Item03", 10, true]
  Award[10] = ["GRRR!!!", "Brave enough to talk to a lion!", "019-Accessory04", 5, false]
  Award[11] = ["Invisible", "Found and talked to invisible person.", "049-Skill06", 50, false]
  Award[12] = ["Swiftly!", "Learn about the Quick Scene!", "020-Accessory05", 100, false]
#===============================================================
# End Config
#===============================================================
  def self.gain(id)
    return if $game_system.awards.include?(id)
    if Awards::Award[id] != nil
      $game_system.gain_award(id)
    end
  end
  def self.has?(id)
    return $game_system.awards.include?(id)
  end
  def self.count
    return $game_system.awards.size
  end
end

$gg_achievements = 2.23
#===============================================================================
# Sprite_Award
#-------------------------------------------------------------------------------
# Draws unlocked achievement.
#===============================================================================
class Sprite_Award < Sprite
  def initialize(award)
    super(nil)
    @award = award
    self.bitmap = Bitmap.new(1, 1)
    self.bitmap.font.size = Awards::Text_Size
    @text_width = self.bitmap.text_size(@award[0]).width + 8
    @text_height = self.bitmap.text_size(@award[0]).height
    self.bitmap.dispose
    if Awards::Use_Image
      @pic = RPG::Cache.picture(Awards::Image_File)
      @pic_width = @pic.width > @text_width ? @pic.width : @text_width
      @pic_height = @pic.height > @text_height ? @pic.height : @text_height
      self.bitmap = Bitmap.new(@pic_width, @pic_height)
      if Awards::Draw_Icon
        @icon = RPG::Cache.icon(@award[2])
      end
    else
      self.bitmap = Bitmap.new(@text_width, @text_height)
    end
    self.bitmap.font.color = Awards::Text_Color
    self.bitmap.font.name = Awards::Text_Font
    self.bitmap.font.size = Awards::Text_Size
    self.z = 20000
    self.x = Awards::Award_Place[0]
    self.y = Awards::Award_Place[1]
    refresh
  end
  def refresh
    self.bitmap.clear
    x = 0
    y = 0
    if @pic != nil
      self.bitmap.blt(0, 0, @pic, Rect.new(0, 0, @pic.width, @pic.height))
      x = Awards::Image_Offset[0]
      y = Awards::Image_Offset[1]
      if @icon != nil
        icon_off = Awards::Icon_Offset
        self.bitmap.blt(icon_off[0], icon_off[1], @icon, Rect.new(0, 0, 
            Awards::Icon_Size[0], Awards::Icon_Size[1]))
      end
    end
    text = @award[0]
    if @text_width + x > self.bitmap.width
      text = self.bitmap.slice_text(@award[0], self.bitmap.width - x)
      text.each_index {|i|
        self.bitmap.draw_text(x, y + i * @text_height + 4, 
            @text_width, @text_height, text[i])}
    else
      self.bitmap.draw_text(x, y, @text_width, @text_height, text)
    end
  end
  def dispose
    super
    if self.bitmap != nil
      self.bitmap.dispose
    end
  end
end
#===============================================================================
# Graphics
#-------------------------------------------------------------------------------
# **added method to control and draw all queued achievements.
#===============================================================================
module Graphics
  class << self
    alias gg_upd_awards_queue_lat update
  end
  def self.update
    @frame = 0 if @frame == nil
    if $game_system != nil && $game_system.queue.size > 0 && @frame < 1
      award = Awards::Award[$game_system.queue[0]]
      if award != nil
        @sprite = Sprite_Award.new(award)
        @frame = Awards::Popup_Time
        Audio.se_play("Audio/SE/#{Awards::Popup_Sound[0]}", 
          Awards::Popup_Sound[1], Awards::Popup_Sound[2])
      end
    end
    if @frame > 0
      @frame -= 1 
      if @frame < 1
        @sprite.dispose
        $game_system.queue.shift
      end
    end
    gg_upd_awards_queue_lat
  end
end
#===============================================================================
# Game_System
#-------------------------------------------------------------------------------
# **modded to keep track of queued and obtained achievements.
#===============================================================================
class Game_System
  attr_accessor :awards
  attr_accessor :queue
  alias gg_init_awards_sys_lat initialize
  def initialize
    @awards = []
    @queue = []
    gg_init_awards_sys_lat
  end
  def gain_award(id)
    return if @awards.include?(id) || Awards::Award[id] == nil
    if Awards::Track_Score
      $game_variables[Awards::Variable_Id] += Awards::Award[id][3]
    end
    @awards.push(id)
    @queue.push(id)
  end
end
#===============================================================================
# Bitmap
#===============================================================================
class Bitmap
  
  def slice_text(text, width)
    words = text.split(' ')
    return words if words.size == 1
    result, current_text = [], words.shift
    words.each_index {|i|
        if self.text_size("#{current_text} #{words[i]}").width > width
          result.push(current_text)
          current_text = words[i]
        else
          current_text = "#{current_text} #{words[i]}"
        end
        result.push(current_text) if i >= words.size - 1}
    return result
  end
  
end

#===============================================================================
# Window_QuickHelp
#===============================================================================
class Window_QuickHelp < Window_Base
  def initialize
    super(64, 32, 512, 160)
    self.contents = Bitmap.new(width - 32, height - 32)
    self.z = 10000
  end
  def set_award(award)
    @award = award
    refresh
  end
  def refresh
    self.contents.clear
    self.contents.draw_text(0, 0, 512 / 2, 32, @award[0][0])
    if Awards::Track_Score
      text = "#{@award[0][3]} #{Awards::Score_Text}"
      self.contents.draw_text(0, 0, 512 - 32, 32, text, 2)
      text = "Total #{Awards::Score_Text}: #{$game_variables[Awards::Variable_Id]}"
      self.contents.draw_text(0, 32, 512 - 32, 32, text, 2)
    end
    text = self.contents.slice_text(@award[0][1], 512 - 32)
    if @award[0][4] && !$game_system.awards.include?(@award[1])
      text = self.contents.slice_text(Awards::Hidden_Info, 512 - 32)
    end
    text.each_index {|i|
      self.contents.draw_text(0, 64 + i * 32, 512 - 32, 32, text[i])}
  end
end
#===============================================================================
# Window_QuickAwards
#===============================================================================
class Window_QuickAwards < Window_Selectable
  def initialize
    super(64, 128 + 64, 512, 320 - 64)
    @column_max = Awards::Icon_QColumn
    self.z = 10000
    refresh
    self.index = 0
  end
  def item
    return @data[self.index]
  end
  def refresh
    if self.contents != nil
      self.contents.dispose
      self.contents = nil
    end
    @data = []
    $game_system.awards.each {|i|
      @data.push([Awards::Award[i], i])}
    if Awards::Show_All
      @data = []
      @locked = []
      @unlocked = []
      Awards::Award.each_index {|i|
        if Awards::Award[i] != nil
          if $game_system.awards.include?(i)
            @unlocked.push([Awards::Award[i], i])
          else
            @locked.push([Awards::Award[i], i])
          end
        end}
      @unlocked.each {|i| @data.push(i)}
      @locked.each {|i| @data.push(i)}
    end
    @item_max = @data.size
    if @item_max > 0
      self.contents = Bitmap.new(width - 32, row_max * Awards::Icon_Size[1])
      for i in 0...@item_max
        draw_item(i)
      end
    end
  end
  def draw_item(index)
    item = @data[index]
    width = Awards::Icon_Size[0] < 32 ? 32 : Awards::Icon_Size[0]
    height = Awards::Icon_Size[1] < 32 ? 32 : Awards::Icon_Size[1]
    x = 4 + index % @column_max * (width + 32)
    y = index / @column_max * (height + 4)
    rect = Rect.new(x, y, self.width / @column_max - 32, height)
    self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
    if $game_system.awards.include?(item[1])
      bitmap = RPG::Cache.icon(item[0][2])
    else
      bitmap = RPG::Cache.icon(Awards::Locked_Icon)
    end
    self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, Awards::Icon_Size[0], 
        Awards::Icon_Size[1]))
  end
  def update_help
    @help_window.set_award(self.item)
  end
  def update_cursor_rect
    if @index < 0
      self.cursor_rect.empty
      return
    end
    row = @index / @column_max
    if row < self.top_row
      self.top_row = row
    end
    if row > self.top_row + (self.page_row_max - 1)
      self.top_row = row - (self.page_row_max - 1)
    end
    cursor_width = Awards::Icon_Size[0] < 32 ? 32 : Awards::Icon_Size[0]
    cursor_height = Awards::Icon_Size[1] < 32 ? 32 : Awards::Icon_Size[1]
    x = @index % @column_max * (cursor_width + 32)
    y = @index / @column_max * (Awards::Icon_Size[1] + 4) - self.oy
    self.cursor_rect.set(x, y, cursor_width, cursor_height + 4)
  end
end
#===============================================================================
# QScene_Awards
#===============================================================================
class QScene_Awards
  def initialize
    @awards = Window_QuickAwards.new
    @help = Window_QuickHelp.new
    @awards.help_window = @help
    loop do
      Graphics.update
      Input.update_old
      update
      if Input.trigger?(Input::B)
        $game_system.se_play($data_system.cancel_se)
        break
      end
    end
    @awards.dispose
    @help.dispose
  end
  def update
    @awards.update
    @help.update
  end
end
#===============================================================================
# Input
#===============================================================================
module Input
  class << self
    alias gg_init_quick_awards_lat update
  end
  def self.update_old
    gg_init_quick_awards_lat
  end
  def self.check_blocked
    Awards::Block_Scenes.each {|s|
      return true if $scene.is_a?(s)}
    return false
  end
  def self.update
    if Awards::Quick_Access != nil && Input.trigger?(Awards::Quick_Access) &&
          @scene == nil && !self.check_blocked
      if defined?(RMXOS) && $game_temp.chat_active == true
          return gg_init_quick_awards_lat
      end
      $game_system.se_play($data_system.decision_se)
      @scene = QScene_Awards.new
      @scene = nil
    end
    gg_init_quick_awards_lat
  end
end

#===============================================================================
# Window_Award
#===============================================================================
class Window_Award < Window_Base
  def initialize
    super(0, 320, 640, 160)
    self.contents = Bitmap.new(width - 32, height - 32)
  end
  def set_award(award)
    @award = award
    refresh
  end
  def refresh
    self.contents.clear
    self.contents.draw_text(0, 0, 640 / 2, 32, @award[0][0])
    if Awards::Track_Score
      text = "#{@award[0][3]} #{Awards::Score_Text}"
      self.contents.draw_text(0, 0, 640 - 32, 32, text, 2)
      text = "Total #{Awards::Score_Text}: #{$game_variables[Awards::Variable_Id]}"
      self.contents.draw_text(0, 32, 640 - 32, 32, text, 2)
    end
    text = self.contents.slice_text(@award[0][1], 640 - 32)
    if @award[0][4] && !$game_system.awards.include?(@award[1])
      text = self.contents.slice_text(Awards::Hidden_Info, 640 - 32)
    end
    text.each_index {|i|
      self.contents.draw_text(0, 64 + i * 32, 640 - 32, 32, text[i])}
  end
end
#===============================================================================
# Window_Awards
#===============================================================================
class Window_Awards < Window_Selectable
  def initialize
    super(0, 0, 640, 320)
    @column_max = Awards::Icon_Column
    refresh
    self.index = 0
  end
  def item
    return @data[self.index]
  end
  def refresh
    if self.contents != nil
      self.contents.dispose
      self.contents = nil
    end
    @data = []
    $game_system.awards.each {|i|
      @data.push([Awards::Award[i], i])}
    if Awards::Show_All
      @data = []
      @locked = []
      @unlocked = []
      Awards::Award.each_index {|i|
        if Awards::Award[i] != nil
          if $game_system.awards.include?(i)
            @unlocked.push([Awards::Award[i], i])
          else
            @locked.push([Awards::Award[i], i])
          end
        end}
      @unlocked.each {|i| @data.push(i)}
      @locked.each {|i| @data.push(i)}
    end
    @item_max = @data.size
    if @item_max > 0
      height = Awards::Icon_Size[1] < 32 ? 32 : Awards::Icon_Size[1]
      self.contents = Bitmap.new(width - 32, row_max * height)
      for i in 0...@item_max
        draw_item(i)
      end
    end
  end
  def draw_item(index)
    item = @data[index]
    width = Awards::Icon_Size[0] < 32 ? 32 : Awards::Icon_Size[0]
    height = Awards::Icon_Size[1] < 32 ? 32 : Awards::Icon_Size[1]
    x = 4 + index % @column_max * (width + 32)
    y = index / @column_max * (height + 4)
    rect = Rect.new(x, y, self.width / @column_max - 32, Awards::Icon_Size[1])
    self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
    if $game_system.awards.include?(item[1])
      bitmap = RPG::Cache.icon(item[0][2])
    else
      bitmap = RPG::Cache.icon(Awards::Locked_Icon)
    end
    self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, Awards::Icon_Size[0], 
      Awards::Icon_Size[1]))
  end
  def update_help
    @help_window.set_award(self.item)
  end
  def update_cursor_rect
    if @index < 0
      self.cursor_rect.empty
      return
    end
    row = @index / @column_max
    if row < self.top_row
      self.top_row = row
    end
    if row > self.top_row + (self.page_row_max - 1)
      self.top_row = row - (self.page_row_max - 1)
    end
    cursor_width = Awards::Icon_Size[0] < 32 ? 32 : Awards::Icon_Size[0]
    cursor_height = Awards::Icon_Size[1] < 32 ? 32 : Awards::Icon_Size[1]
    x = @index % @column_max * (cursor_width + 32)
    y = @index / @column_max * (cursor_height + 4) - self.oy
    self.cursor_rect.set(x, y, cursor_width, cursor_height)
  end
end
#===============================================================================
# Scene_Achievements
#===============================================================================
class Scene_Achievements
  def main
    @help = Window_Award.new
    @awards = Window_Awards.new
    @awards.help_window = @help
    Graphics.transition
    loop do
      Graphics.update
      Input.update
      update
      if $scene != self
        break
      end
    end
    Graphics.freeze
    @help.dispose
    @awards.dispose
  end
  def update
    @awards.update
    @help.update
    if Input.trigger?(Input::B)
      $game_system.se_play($data_system.cancel_se)
      $scene = Awards::Return_Scene.new
      return
    end
  end
end