Save-Point
Wrap Map - Printable Version

+- Save-Point (https://www.save-point.org)
+-- Forum: Material Development (https://www.save-point.org/forum-8.html)
+--- Forum: Scripts Database (https://www.save-point.org/forum-39.html)
+---- Forum: RPGMaker XP (RGSS) Engine (https://www.save-point.org/forum-116.html)
+---- Thread: Wrap Map (/thread-2305.html)



Wrap Map - Dirtie - 12-07-2008

Wrap Map
Version 2
By Dirtie

Code:
#==============================================================================
# ? Wrap_Map V2
#------------------------------------------------------------------------------
# ?By Dirtie.
#   Allows chosen map(s) to "wrap-around", ie. go continuously.
#   Just add "_wrap" to the end of the map name for the map you want to be wrapped.
#   Many thanks to Rataime for all the event code, Dubealex for helping me out,
#   Deke for the map checker script, and to everyone else that contributed.
#==============================================================================

#--------------------------------------------------------------------------
# ? CLASS Game_Temp (edit)
#      Script to check for "_wrap" in the map name.
#      This is taken and modified from Deke's Day/Night and Time System script.
#      If you would like to use something other than "_wrap" to check for,
#      change _wrap to whatever you want on lines 30 and 34
#--------------------------------------------------------------------------
class Game_Temp

  attr_reader    :map_infos
  attr_reader    :outside_array

  alias wrap_original_game_temp_initialize initialize

  def initialize
    wrap_original_game_temp_initialize
    @map_infos = load_data("Data/MapInfos.rxdata")
    @outside_array=Array.new
    for key in @map_infos.keys
      @outside_array[key]=@map_infos[key].name.include?("_wrap")
    end
    for key in @map_infos.keys
      @map_infos[key] = @map_infos[key].name
      @map_infos[key].delete!("_wrap")
    end
  end

end

#--------------------------------------------------------------------------
# ? CLASS Game_Map (edit)
#      First, sets up the variable "wrap" for use in the event script later.
#      Then checks to see if "_wrap" is in the map name;
#      If not, uses default scrolling options for respective edge of map.
#      If so, tells viewport to keep scrolling in the respective direction when actor is near edge of map.
#--------------------------------------------------------------------------
class Game_Map

  attr_accessor :wrap

  alias wrap_original_game_map_scroll_left scroll_left
  alias wrap_original_game_map_scroll_right scroll_right
  alias wrap_original_game_map_scroll_up scroll_up
  alias wrap_original_game_map_scroll_down scroll_down

# Left
  def scroll_left(distance)
    unless $game_temp.outside_array[$game_map.map_id]
      wrap_original_game_map_scroll_left(distance)
    else
      @display_x = [@display_x - distance].max
    end
  end

# Right
  def scroll_right(distance)
    unless $game_temp.outside_array[$game_map.map_id]
      wrap_original_game_map_scroll_right(distance)
    else
      @display_x = [@display_x + distance].min
    end
  end

# Top
  def scroll_up(distance)
    unless $game_temp.outside_array[$game_map.map_id]
      wrap_original_game_map_scroll_up(distance)
    else
      @display_y = [@display_y - distance].max
    end
  end

# Bottom
  def scroll_down(distance)
    unless $game_temp.outside_array[$game_map.map_id]
      wrap_original_game_map_scroll_down(distance)
    else
      @display_y = [@display_y + distance].min
   end
  end

end

#--------------------------------------------------------------------------
# ? CLASS Game_Player (edit)
#      Makes sure viewport stays centered on player, particularly when teleporting near edges.
#--------------------------------------------------------------------------
class Game_Player

  alias wrap_original_game_player_center center

  def center(x, y)
    unless $game_temp.outside_array[$game_map.map_id]
      wrap_original_game_player_center(x, y)
    else
      max_x = ($game_map.width + 20) * 128
      max_y = ($game_map.height + 15) * 128
      $game_map.display_x = [-20 * 128, [x * 128 - CENTER_X, max_x].min].max
      $game_map.display_y = [-15 * 128, [y * 128 - CENTER_Y, max_y].min].max
    end
  end

end

#--------------------------------------------------------------------------
# ? CLASS Check_Coordinates
#      Checks for coordinates and keyboard input, then teleports if conditions are met.
#--------------------------------------------------------------------------
class Check_Coordinates

#------------------------------------------------------------------------
# ? Handles left edge
#------------------------------------------------------------------------
  def refresh_left
    unless $game_temp.outside_array[$game_map.map_id]
    else
      if $game_player.real_x == 0
        if Input.press?(Input::LEFT)
          def $game_player.passable?(x, y, d)
            return true
          end
          @left_trigger = true
        end
      end
    end
  end
  
#------------------------------------------------------------------------
# ? Handles right edge
#------------------------------------------------------------------------
  def refresh_right
    unless $game_temp.outside_array[$game_map.map_id]
    else
      @map_width_max = ($game_map.width - 1) * 128
      if $game_player.real_x == @map_width_max
        if Input.press?(Input::RIGHT)
          def $game_player.passable?(x, y, d)
            return true
          end
          @right_trigger = true
        end
      end
    end
  end

#------------------------------------------------------------------------
# ? Handles top edge
#------------------------------------------------------------------------
  def refresh_top
    unless $game_temp.outside_array[$game_map.map_id]
    else
      if $game_player.real_y == 0
        if Input.press?(Input::UP)
          def $game_player.passable?(x, y, d)
            return true
          end
          @top_trigger = true
        end
      end
    end
  end

#------------------------------------------------------------------------
# ? Handles bottom edge
#------------------------------------------------------------------------
  def refresh_bottom
    unless $game_temp.outside_array[$game_map.map_id]
    else
      @map_height_max = ($game_map.height - 1) * 128
      if $game_player.real_y == @map_height_max
        if Input.press?(Input::DOWN)
          def $game_player.passable?(x, y, d)
            return true
          end
          @bottom_trigger = true
        end
      end
    end
  end

#------------------------------------------------------------------------
# ? Left teleport
#------------------------------------------------------------------------
  def left_trigger
    if @left_trigger == true
      if $game_player.real_x == -128
        $game_player.moveto(($game_map.width - 1), $game_player.y)
        def $game_player.passable?(x, y, d)
          new_x = x + (d == 6 ? 1 : d == 4 ? -1 : 0)
          new_y = y + (d == 2 ? 1 : d == 8 ? -1 : 0)
          unless $game_map.valid?(new_x, new_y)
            return false
          end
          if $DEBUG and Input.press?(Input::CTRL)
            return true
          end
          super
        end
        @left_trigger = false
      end
    end
  end

#------------------------------------------------------------------------
# ? Right teleport
#------------------------------------------------------------------------
  def right_trigger
    if @right_trigger == true
      if $game_player.real_x == ($game_map.width * 128)
        $game_player.moveto(0, $game_player.y)
        def $game_player.passable?(x, y, d)
          new_x = x + (d == 6 ? 1 : d == 4 ? -1 : 0)
          new_y = y + (d == 2 ? 1 : d == 8 ? -1 : 0)
          unless $game_map.valid?(new_x, new_y)
            return false
          end
          if $DEBUG and Input.press?(Input::CTRL)
            return true
          end
          super
        end
        @right_trigger = false
      end
    end
  end

#------------------------------------------------------------------------
# ? Top teleport
#------------------------------------------------------------------------
  def top_trigger
    if @top_trigger == true
      if $game_player.real_y == -128
        $game_player.moveto($game_player.x, ($game_map.height - 1))
        def $game_player.passable?(x, y, d)
          new_x = x + (d == 6 ? 1 : d == 4 ? -1 : 0)
          new_y = y + (d == 2 ? 1 : d == 8 ? -1 : 0)
          unless $game_map.valid?(new_x, new_y)
            return false
          end
          if $DEBUG and Input.press?(Input::CTRL)
            return true
          end
          super
        end
        @top_trigger = false
      end
    end
  end

#------------------------------------------------------------------------
# ? Bottom teleport
#------------------------------------------------------------------------
  def bottom_trigger
    if @bottom_trigger == true
      if $game_player.real_y == ($game_map.height * 128)
        $game_player.moveto($game_player.x, 0)
        def $game_player.passable?(x, y, d)
          new_x = x + (d == 6 ? 1 : d == 4 ? -1 : 0)
          new_y = y + (d == 2 ? 1 : d == 8 ? -1 : 0)
          unless $game_map.valid?(new_x, new_y)
            return false
          end
          if $DEBUG and Input.press?(Input::CTRL)
            return true
          end
          super
        end
        @bottom_trigger = false
      end
    end
  end

end

#--------------------------------------------------------------------------
# ? CLASS Sprite_Duplicate
#      A copy of the Sprite_Character class, with some adjustments made.
#      Used to create the duplicate event sprites.
#--------------------------------------------------------------------------
class Sprite_Duplicate < RPG::Sprite

  attr_accessor :character # @character is the original event
  
  def initialize(viewport, character = nil, x = 0, y = 0)
    @x = x
    @y = y
    super(viewport)
    @character = character
    @z=@character.screen_z
    update
  end

  def update
    super
    if @tile_id != @character.tile_id or
      @character_name != @character.character_name or
      @character_hue != @character.character_hue
        @tile_id = @character.tile_id
        @character_name = @character.character_name
        @character_hue = @character.character_hue
        if @tile_id >= 384
          self.bitmap = RPG::Cache.tile($game_map.tileset_name, @tile_id, @character.character_hue)
          self.src_rect.set(0, 0, 32, 32)
          self.ox = 16
          self.oy = 32
        else
          self.bitmap = RPG::Cache.character(@character.character_name, @character.character_hue)
          @cw = bitmap.width / 4
          @ch = bitmap.height / 4
          self.ox = @cw / 2
          self.oy = @ch
        end
    end
    self.visible = (not @character.transparent)
    if @tile_id == 0
      sx = @character.pattern * @cw
      sy = (@character.direction - 2) / 2 * @ch
      self.src_rect.set(sx, sy, @cw, @ch)
    end
    # The coordinates of the duplicate event sprite. They are relative to the original event,
    # so the duplicates will move and act as the original does; except the z coordinate,
    # as when the original sprite would be of range, the duplicate would not appear.
    self.x = @character.screen_x + @x
    self.y = @character.screen_y + @y
    self.z = @z
    self.opacity = @character.opacity
    self.blend_type = @character.blend_type
    self.bush_depth = @character.bush_depth
    if @character.animation_id != 0
      animation = $data_animations[@character.animation_id]
      animation(animation, true)
      @character.animation_id = 0
    end
  end

end

#--------------------------------------------------------------------------
# ? CLASS Sprite_Character (edit)
#      Used to create the duplicate sprites.
#--------------------------------------------------------------------------
class Sprite_Character < RPG::Sprite

  alias wrap_original_sprite_character_initialize initialize
  alias wrap_original_sprite_character_update update

  def initialize(viewport, character = nil)
    unless $game_temp.outside_array[$game_map.map_id]
      wrap_original_sprite_character_initialize(viewport, character)
    else
      @character = character
      super(viewport)
      if $game_map.wrap == nil
        $game_map.wrap = []
      end
      # 8 duplicates are created, stored in the $game_map.wrap array
      if character.is_a?(Game_Event)
        $game_map.wrap.push(Sprite_Duplicate.new(viewport, character, (-$game_map.width * 32), 0))
        $game_map.wrap.push(Sprite_Duplicate.new(viewport, character, 0, (-$game_map.height * 32)))
        $game_map.wrap.push(Sprite_Duplicate.new(viewport, character, ($game_map.width * 32), 0))
        $game_map.wrap.push(Sprite_Duplicate.new(viewport, character, 0, ($game_map.height * 32)))
        $game_map.wrap.push(Sprite_Duplicate.new(viewport, character, (-$game_map.width * 32), (-$game_map.height * 32)))
        $game_map.wrap.push(Sprite_Duplicate.new(viewport, character, ($game_map.width * 32), ($game_map.height * 32)))
        $game_map.wrap.push(Sprite_Duplicate.new(viewport, character, (-$game_map.width * 32), ($game_map.height * 32)))
        $game_map.wrap.push(Sprite_Duplicate.new(viewport, character, ($game_map.width * 32), (-$game_map.height * 32)))
      end
      wrap_original_sprite_character_initialize(viewport, @character)
    end
  end

#------------------------------------------------------------------------
# ? Updates each sprite in the $game_map.wrap array
#------------------------------------------------------------------------
  def update
    unless $game_temp.outside_array[$game_map.map_id]
      wrap_original_sprite_character_update
    else
      wrap_original_sprite_character_update
      if $game_map.wrap != [] and character.is_a?(Game_Player)
        for duplicate in $game_map.wrap
          if duplicate != nil
            duplicate.update
          end
        end
      end
    end
  end

end

#--------------------------------------------------------------------------
# ? CLASS Spriteset_Map (edit)
#      Prevents "disposed sprite" errors
#--------------------------------------------------------------------------

class Spriteset_Map

  alias wrap_original_spriteset_map_initialize initialize

  def initialize
    $game_map.wrap=nil
    wrap_original_spriteset_map_initialize
  end
  
end

#--------------------------------------------------------------------------
# ? CLASS Scene_Save edit
#      Prevent save errors
#--------------------------------------------------------------------------
class Scene_Save < Scene_File

  alias wrap_original_scene_save_write_save_data write_save_data

  def write_save_data(file)
    $game_map.wrap = nil
    wrap_original_scene_save_write_save_data(file)
  end
  
end

#--------------------------------------------------------------------------
# ? CLASS Scene Map (edit)
#      Initiates a loop for the methods of the Check_Coordinates class
#--------------------------------------------------------------------------
class Scene_Map

  $coordinate_check = Check_Coordinates.new
  
  alias wrap_original_scene_map_update update
  
  def update
    unless $game_temp.outside_array[$game_map.map_id]
      wrap_original_scene_map_update
    else
      $coordinate_check.refresh_left
      $coordinate_check.refresh_right
      $coordinate_check.refresh_top
      $coordinate_check.refresh_bottom
      $coordinate_check.left_trigger
      $coordinate_check.right_trigger
      $coordinate_check.top_trigger
      $coordinate_check.bottom_trigger
      wrap_original_scene_map_update
    end
  end

end