#==============================================================================
# ** TDS Quick Travel
#    Ver: 1.4
#------------------------------------------------------------------------------
#  * Description:
#  This script allows you to quickly travel to pre determined locations on a 
#  map.
#------------------------------------------------------------------------------
#  * Features: 
#  Quickly change locations on a map.
#------------------------------------------------------------------------------
#  * Instructions:
#
#  To add a quick travel location to a map use this in a script call:
#
#  add_map_quick_travel(id, name, map, map_id, x, y, dir)
#
#   id     = ID of the quick travel point. (It's order in the list)
#   name   = name of the quick travel location.
#   map    = map id to add quick travel location to.
#   map_id = map ID to quick travel to.
#   x      = X coordinate of the quick travel location on the map
#   y      = Y coordinate of the quick travel location on the map
#   dir    = facing direction after quick traveling (2: Down , 4: Left, 6: Right, 8: Up)  
#
#  To disable quick travel use this on a script call:
#
#    disable_map_quick_travel
#  
#  To enable quick travel use this on a script call:
#
#    disable_map_quick_travel
#
#  To call the quick travel selection menu press the "X" (A) key.
#
#  To call the quick travel menu from an event, use this on a script call:
#
#    call_map_quick_travel_menu
#
#------------------------------------------------------------------------------
#  * Notes:
#  None.
#------------------------------------------------------------------------------
# WARNING:
#
# Do not release, distribute or change my work without my expressed written 
# consent, doing so violates the terms of use of this work.
#
# If you really want to share my work please just post a link to the original
# site.
#
# * Not Knowing English or understanding these terms will not excuse you in any
#   way from the consequenses.
#==============================================================================
# * Import to Global Hash *
#==============================================================================
($imported ||= {})[:TDS_Quick_Travel] = true

#==============================================================================
# ** Game_System
#------------------------------------------------------------------------------
#  This class handles system-related data. Also manages vehicles and BGM, etc.
# The instance of this class is referenced by $game_system.
#==============================================================================

class Game_System
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_accessor :map_quick_travel
  attr_accessor :disable_quick_travel
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  alias tds_quick_travel_game_system_initialize                    initialize  
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    # Run Original Method
    tds_quick_travel_game_system_initialize     
    # Initialize Quick Travel Values
    init_quick_travel        
  end
  #--------------------------------------------------------------------------
  # * Initialize Map Quick Travel
  #--------------------------------------------------------------------------
  def init_quick_travel  
    # Disable Quick Travel Flag
    @disable_quick_travel = false
    # Make Map Quick Travel Hash
    @map_quick_travel = {}
  end  
  #--------------------------------------------------------------------------
  # * Determine if Map Quick Travel is possible
  #--------------------------------------------------------------------------
  def can_quick_travel?
    # Return false if map quick travel is disabled
    return false if @disable_quick_travel
    # Return false if Map has no quick travel points
    return false if !has_quick_travel?
    # Return true by default
    return true
  end
  #--------------------------------------------------------------------------
  # * Determine if Map has Quick Travel points
  #--------------------------------------------------------------------------
  def has_quick_travel?
    # Return false if Map Quick Travel List is nil or empty
    return false if @map_quick_travel[$game_map.map_id].nil?
    # Return true by default
    return true
  end  
  #--------------------------------------------------------------------------
  # * Get Quick Travel Map List
  #--------------------------------------------------------------------------
  def quick_travel_map_list
    # Get Map Quick Travel Points
    return @map_quick_travel[$game_map.map_id].keys.sort.collect {|id| @map_quick_travel[$game_map.map_id][id]}
  end
end


#==============================================================================
# ** Game_Interpreter
#------------------------------------------------------------------------------
#  An interpreter for executing event commands. This class is used within the
# Game_Map, Game_Troop, and Game_Event classes.
#==============================================================================

class Game_Interpreter
  #--------------------------------------------------------------------------
  # * Constants (Structs)
  #--------------------------------------------------------------------------
  # Quick Travel Settings Base
  Quick_Travel_Settings = Struct.new(:name, :map_id, :x, :y, :direction)        
  #--------------------------------------------------------------------------
  # * Enable or Disable Map Quick Travel
  #--------------------------------------------------------------------------
  def enable_map_quick_travel  ; $game_system.disable_quick_travel = false end  
  def disable_map_quick_travel ; $game_system.disable_quick_travel = true end
  #--------------------------------------------------------------------------
  # * Call Map Quick Travel Menu
  #--------------------------------------------------------------------------
  def call_map_quick_travel_menu
    # If on Scene Map and there are quick travel points
    if SceneManager.scene_is?(Scene_Map) and $game_system.has_quick_travel?
      # Call Quick Travel Menu Process
      SceneManager.scene.start_quick_travel_selection
    end
  end      
  #--------------------------------------------------------------------------
  # * Add Map Quick Travel
  #--------------------------------------------------------------------------
  def add_map_quick_travel(id, name, map, map_id, x, y, dir = 2)
    # Make Empty hash if necessary
    $game_system.map_quick_travel[map] ||= {}
    # Set Map Quick Travel Point
    $game_system.map_quick_travel[map][id] = Quick_Travel_Settings.new(name, map_id, x, y, dir)
  end   
  #--------------------------------------------------------------------------
  # * Remove Map Quick Travel
  #--------------------------------------------------------------------------
  def remove_map_quick_travel(map_id, id)
    # Return if there are quick travel points in the map
    return if $game_system.map_quick_travel[map_id].nil?
    # Delete Map Quick Travel Point
    $game_system.map_quick_travel[map_id].delete(id)
  end 
end


#==============================================================================
# ** Scene_Map
#------------------------------------------------------------------------------
#  This class performs the map screen processing.
#==============================================================================

class Scene_Map < Scene_Base
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  alias tds_quick_travel_scene_map_update                              update
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    # Update Quick Travel Input
    update_quick_travel_input   
    # Run Original Method
    tds_quick_travel_scene_map_update
  end
  #--------------------------------------------------------------------------
  # * Start Quick Travel SElection
  #--------------------------------------------------------------------------
  def start_quick_travel_selection
    # Make Scene Cover Sprite
    @scene_cover = Sprite.new
    @scene_cover.bitmap = Graphics.snap_to_bitmap
    @scene_cover.bitmap.blur      
    @scene_cover.opacity = 0      
    @scene_cover.tone.set(-30, -30, -30)
    @scene_cover.z = 5000
    # Make Quick Travel Window
    @quick_travel_list_window = Window_Quick_Travel_List.new
    @quick_travel_list_window.x = (Graphics.width - @quick_travel_list_window.width) / 2
    @quick_travel_list_window.y = (Graphics.height - @quick_travel_list_window.height) / 2      
    @quick_travel_list_window.z = 5100
    @quick_travel_list_window.openness = 0
    @quick_travel_list_window.open.activate.select(0)
    # Set Quick Travel Window Handlers
    @quick_travel_list_window.set_handler(:ok,     method(:on_quick_travel_selection_ok))
    @quick_travel_list_window.set_handler(:cancel, method(:on_quick_travel_selection_cancel))
    # Fade In Scene Cover
    15.times { Graphics.update ; @scene_cover.opacity += 17}
    # Quick Travel Selection Update Loop
    loop { 
      # Update Graphics, Input and Quick Travel Window
      Graphics.update ; Input.update ; @quick_travel_list_window.update
      # Break if Quick Travelis nil
      break if @quick_travel_list_window.nil?
    }
  end
  #--------------------------------------------------------------------------
  # * [OK] Quick Travel Selection
  #--------------------------------------------------------------------------
  def on_quick_travel_selection_ok
    # Get Transfer Information
    transfer = @quick_travel_list_window.selected_transfer 
    # Deactivate and Close Quick Travel List window
    @quick_travel_list_window.deactivate ; @quick_travel_list_window.close
    # Update Graphics and Fadeout Scene Cover
    10.times { Graphics.update ; @scene_cover.opacity -= 17 ; @quick_travel_list_window.update }
    # Dispose of Scene Cover
    @scene_cover.bitmap.dispose ; @scene_cover.dispose ; @scene_cover = nil
    # Dispose of Quick Travel List Window
    @quick_travel_list_window.dispose ; @quick_travel_list_window = nil
    # Start Transfer
    $game_player.reserve_transfer(transfer.map_id, transfer.x, transfer.y, transfer.direction)
    $game_temp.fade_type = 0
    # Update Input
    Input.update
  end
  #--------------------------------------------------------------------------
  # * [Cancel] Quick Travel Selection
  #--------------------------------------------------------------------------
  def on_quick_travel_selection_cancel
    # Deactivate and Close Quick Travel List window
    @quick_travel_list_window.deactivate ; @quick_travel_list_window.close
    # Update Graphics and Fadeout Scene Cover
    10.times { Graphics.update ; @scene_cover.opacity -= 17 ; @quick_travel_list_window.update }
    # Dispose of Scene Cover
    @scene_cover.bitmap.dispose ; @scene_cover.dispose ; @scene_cover = nil
    # Dispose of Quick Travel List Window
    @quick_travel_list_window.dispose ; @quick_travel_list_window = nil
    # Update Input
    Input.update
  end
  #--------------------------------------------------------------------------
  # * Update Quick Travel Input
  #--------------------------------------------------------------------------
  def update_quick_travel_input
    # Return if Interpreter is running or messages
    return if !$game_system.can_quick_travel? or $game_map.interpreter.running? or ($game_message.busy? or $game_message.visible)    
    # If Input Trigger A
    if Input.trigger?(:X)
      # Play Ok Sound
      Sound.play_ok
      # Start Quick Travel Selection
      start_quick_travel_selection
    end
  end
end


#==============================================================================
# ** Window_Quick_Travel_List
#------------------------------------------------------------------------------
#  This window handles Quick Travel List selection.
#==============================================================================

class Window_Quick_Travel_List < Window_Selectable
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_reader :quick_travel_list  
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    # Get Quick Travel List
    @quick_travel_list =  $game_system.quick_travel_map_list      
    # Get Max Text Width of Commands 
    @max_text_width = max_text_width
    # Create Window Contents
    super(0, 0, window_width, window_height)
    # Draw Window Contents
    refresh
  end
  #--------------------------------------------------------------------------
  # * Get Selected Transfer Information
  #--------------------------------------------------------------------------
  def selected_transfer ; @quick_travel_list[@index] end  
  #--------------------------------------------------------------------------
  # * Window Width and Height
  #--------------------------------------------------------------------------
  def window_width  ; [12 + max_text_width + (standard_padding * 2), Graphics.width].min end
  def window_height ; fitting_height(visible_line_number) end
  #--------------------------------------------------------------------------
  # * Max Columns
  #--------------------------------------------------------------------------
  def col_max ; 1 end
  #--------------------------------------------------------------------------
  # * Get Number of Items
  #--------------------------------------------------------------------------
  def item_max ; @quick_travel_list.size end 
  #--------------------------------------------------------------------------
  # * Get Number of Lines to Show
  #--------------------------------------------------------------------------
  def visible_line_number ; [[item_max + 1, 16].min, 2].max end
  #--------------------------------------------------------------------------
  # * Get Number of Rows Displayable on 1 Page
  #--------------------------------------------------------------------------
  def page_row_max ; super - 1 end
  #--------------------------------------------------------------------------
  # * Get Row Count
  #--------------------------------------------------------------------------
  def row_max ; super + 1 end
  #--------------------------------------------------------------------------
  # * Item Rect
  #--------------------------------------------------------------------------
  def item_rect(index) ; rect = super ; rect.y += line_height ; rect end  
  #--------------------------------------------------------------------------
  # * Find Max Text Width
  #--------------------------------------------------------------------------
  def max_text_width
    # Create Temporary Contents
    contents = Bitmap.new(1, 1)
    contents.font.size = Font.default_size
    contents.font.bold = Font.default_bold
    contents.font.italic = Font.default_italic    
    # Get Starting Width
    width = 0
    # Go Through Quick Travel List
    @quick_travel_list.each {|t| 
    # Set Max Width
    w = contents.text_size(t.name).width ; width += w if w > width 
    }
    # Dispose of Contents
    contents.dispose ; contents = nil
    # Return Max Text Width
    return [width, 230].max
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    super
    contents.font.color = system_color
    # Draw Quick Travel Header
    draw_text(0, 0, contents_width, line_height, "Quick travel list", 1)
  end
  #--------------------------------------------------------------------------
  # * Draw Item
  #--------------------------------------------------------------------------
  def draw_item(index)
    # Draw Quick Travel Point Name
    draw_text(item_rect_for_text(index), @quick_travel_list.at(index).name)
  end
end