=begin
Marrend's Teleport script.

This script should emulate the "teleport" style of skill or item in RPG Maker
2K/2K3.

The intention of this script is that a Skill or Item would call it. Hense,
the way to start this up would be to create a common event and insert the
following Script:

SceneManager.call(Scene_Teleport)

If a location is to be unlocked later, the script to use would be...

$locales.set_lock(i, true)

...where "i" represents the item in the location array to make available.


This script is sub-divided into four sections as follows.
  Section 1: Locale
    General location data is defined here.
  Section 2: Locales
    Array of Locale data is to be made here.
  Section 3: Scene_Teleport
    Where it all comes together, and the magic (as it were) happens.
  Section 4: DataManager
    Edits to include location data on starting, saving, and loading the game.
=end


# Section 1: Locale
class Locale
  # This class will keep track of whatever variables we need to teleport.
  attr_accessor :map_id   # Map ID
  attr_accessor :x        # X coordinate
  attr_accessor :y        # Y coordinate
  attr_accessor :lock     # Location locked/unlocked attribute.
  attr_accessor :face     # Character facing after teleport.
  attr_accessor :name     # Location display name.
  
  def initialize
    # Initializes variables.
    @map_id = 0
    @x = 0
    @y = 0
    @lock = true
    @face = 2
    @name = "Undefined"
  end
  
  def set_map_id(index)
    # Sets the Map ID.
    @map_id = index
  end
  
  def set_x(pos)
    # Sets the X coordinate.
    @x = pos
  end
  
  def set_y(pos)
    # Sets the Y coordinate.
    @y = pos
  end
      
  def set_lock(lock)
    # Sets whether or not the location is available
    # or not. Default value is true.
    @lock = lock
  end
  
  def set_face(angle)
    # Sets the facing of the character after teleport.
    # With this function, the possible values are the same as the ones
    # resulting from Set Varibles -> Character facing.
    # So 2 is down, 4 is left, 6 is right and 8 is up.
    # Default value is down (2)
    @face = angle
  end
  
  def get_name
    # Gets the display name for a location.
    if @map_id != 0
      if @lock == true
        map = load_data(sprintf("Data/Map%03d.rvdata2", @map_id))
        @name = map.display_name
        # Note that name stays "Undefined" when map_id is 0. This is mostly
        # to emulate Lloyd's Beacon-like effects, should one choose to go
        # that route.
      else
        @name = "Location locked!"
      end
    end
  end
  
  def add(index, pos_x, pos_y, lock = true, face = 2)
    # A quicker method to add locales than going function-by-function.
    set_map_id(index)
    set_x(pos_x)
    set_y(pos_y)
    set_lock(lock)
    set_face(face)
    get_name
  end
    
  def teleport
    # Performs the teleport operation. Not EXACTLY the self-same that the
    # Transfer Player event command uses, but for our purposes, close enough.
    $game_player.reserve_transfer(@map_id, @x, @y, @face)
    $game_player.perform_transfer
  end
end


# Section 2: Locales
class Locales
  attr_reader :data # Location array.
  
  def initialize
    @data = []
    set_array
  end
  
  def add_locale(id, x, y, lock = true, face = 2)
    # Adds a locale to the locals array.
    index = @data.size
    @data[index] = Locale.new
    @data[index].add(id, x, y, lock, face)
  end

  def set_array    
    # Example
    # ID = map_id; Place = (x, y); locked; default (down)
    # add_locale(map_id, x, y, false)
  end

  def set(index, id, x, y, lock = true, face = 2)
    # Replaces one location data for another. Mostly for Llody's Beacon-like
    # effects.
    @data[index].add(id, x, y, lock, face)
  end
  
  def set_lock(index, lock)
    # Locks, or unlocks, a location.
    @data[index].set_lock(lock)
    @data[index].get_name
  end
end


# Section 3: Scene_Teleport
class Window_Locale < Window_Command
  # Window processing for Item/Skill use of the Locale class.
  def initialize
    super(0, window_y)
    @list = []
    self.index = 0
    activate
    refresh
  end
  
  def window_y
    (Graphics.height - window_height) / 2
  end
    
  def window_width
    return Graphics.width
  end

  def window_height
    # This value can be bigger/smaller based on how many locations you
    # actually have verses your screen size. The window does have
    # up/down loop capacity!
    fitting_height(10)
  end
  
  def make_item_list
    i = 0
    while i < $locales.data.size
      add_command($locales.data[i].name, :locale, $locales.data[i].lock)
      i += 1
    end
  end
  
  def item_max
    @list.size
  end
  
  def refresh
    make_item_list
    create_contents
    draw_all_items
  end
end

class Scene_Teleport < Scene_MenuBase
  # Scene processing for Item and/or Skill use of the Locale class.
  attr_accessor :window # The command window.

  def start
    super
    create_locale_window
  end

  def create_locale_window
    @window = Window_Locale.new()
    @window.set_handler(:ok, method(:on_ok))
    @window.set_handler(:cancel, method(:return_scene))
  end
  
  def on_ok    
    i = @window.index
    if $locales.data[i].lock == true
      Sound.play_ok
      $locales.data[i].teleport
      sfx = RPG::SE.new("Up1", 80)
      sfx.play
      return_scene
    end
  end
end


# Section 4: DataManager
module DataManager
  # Creates the global variable "$locales".
  def self.create_game_objects
    $game_temp          = Game_Temp.new
    $game_system        = Game_System.new
    $game_timer         = Game_Timer.new
    $game_message       = Game_Message.new
    $game_switches      = Game_Switches.new
    $game_variables     = Game_Variables.new
    $game_self_switches = Game_SelfSwitches.new
    $game_actors        = Game_Actors.new
    $game_party         = Game_Party.new
    $game_troop         = Game_Troop.new
    $game_map           = Game_Map.new
    $game_player        = Game_Player.new    
    $locales            = Locales.new
  end
  
  def self.make_save_contents
    # Makes "$locales" able to be saved.
    contents = {}
    contents[:system]        = $game_system
    contents[:timer]         = $game_timer
    contents[:message]       = $game_message
    contents[:switches]      = $game_switches
    contents[:variables]     = $game_variables
    contents[:self_switches] = $game_self_switches
    contents[:actors]        = $game_actors
    contents[:party]         = $game_party
    contents[:troop]         = $game_troop
    contents[:map]           = $game_map
    contents[:player]        = $game_player
    contents[:locales]       = $locales
  end

  def self.extract_save_contents(contents)
    # Includes data extraction for "$locales".
    $game_system        = contents[:system]
    $game_timer         = contents[:timer]
    $game_message       = contents[:message]
    $game_switches      = contents[:switches]
    $game_variables     = contents[:variables]
    $game_self_switches = contents[:self_switches]
    $game_actors        = contents[:actors]
    $game_party         = contents[:party]
    $game_troop         = contents[:troop]
    $game_map           = contents[:map]
    $game_player        = contents[:player]
    $locales            = contents[:locales]
  end
end