[Script] BIG MAPS

Share resources for RPG Maker XP. Uploads must be your own work or have permission to share. Do not share game rips.
Post Reply
User avatar
DerVVulfman
Posts: 31
Joined: Sat Dec 08, 2018 4:25 am
Location: PG, Maryland
Contact:

[Script] BIG MAPS

Post by DerVVulfman » Sun Dec 16, 2018 4:27 am

BIG MAPS
Version: 1.1

Introduction
This allows you to chain multiple maps together to make one hellacious big honkin' map!

All seamless, it creates a single map in memory based on the maps you merge together. Save, load, teleport between, so far, it all works!


Script

Code: Select all

#==============================================================================
# ** BIG MAPS
#------------------------------------------------------------------------------
#    by DerVVulfman
#    version 1.1
#    07-16-2017 (mm/dd/yyyy)
#    RGSS / RPGMaker XP
#==============================================================================
#
#  This allows you to chain multiple maps together to make one hellacious big
#  honkin' map!
#
#                                == * == * ==
#
#  BRANCHES &  Standard use of both 'Conditional Branches' and 'Control
#  CONTROL     Variables' is unhampered by this system.
#  VARIABLES:  Performing both with an event to acquire event data (such as
#              map ID, position, facing direction) only functions on events
#              made within its 'individual map' A map event cannot test the
#              data of  another event  if the  target event  was made  on a
#              different map.
#              EX:  Event 1 on map 3 cannot get data from Event 4 on map 2.
#                   Event 1 on map 3 'can' get data from Event 2 on map 3.
#
#
#  TELEPORT:   Standard teleporting between normal maps remains unchanged.
#              Teleporting to a 'big map' has special attributes:
#              1) Setting coordinates to one  of the  individual maps in a
#                 'big map' permitted.  Placement is adjusted accordingly.
#              2) Using variables to teleport into a 'big map' works.  You
#                 can set  the individual map ID and x/y coordinates.   If
#                 the X/Y coodinates  are outside  of the  individual map, 
#                 it may place the player into the next adjoining map.
# 
#
#  SET EVENT   See Teleport.  Functionally the same for events, except the
#  LOCATION:   event cannot leave the 'big map'.  No Map ID to set/define.
#              Swapping two events limited to those defined in the indivi-
#              dual map.   Cannot swap events  defined in  different maps.
#
#
#  ANIMATIONS: Unhampered by this system.   The editor's  dropdown menu to
#              set an animation  only permites those events  in that given
#              map.   An event on one map cannot apply  an animation to an
#              event created on another.
#
#
#                                == * == * ==
#
#  INCLUDED:  A warning system that tests the following:
#             1) If a map is defined in two or more 'big maps' 
#             2) If a map is defined more than once in a single 'big map'
#             3) If a big map is incorrectly defined by the following
#                a) Incorrect dimensions provided
#                b) Insufficient maps to fill defined big map dimensions
#             4) If maps within a big map do not use the same tileset (*)
#
#  (*) NOTE:  All map data regarding tileset, fog, etc. are derived from the
#             first map loaded.   Ensure all maps use the same tileset data.
#
#
#------------------------------------------------------------------------------
#
#  KNOWN / TESTED WITH THE FOLLOWING:
#
#  * Auto Populate by Charlie Fleed  - Functional   Must be below Big Maps. 
#  * Tileset Swap by ccoa            - Functional.  Must be above Big Maps.
#  * MGC Mode7 Edit by DerVVulfman   - Functional.  Can be above or below.   **
#    (Until the bitmap render limit is reached)
#  * Fog of War by Wachunga          - Functional.  Must be below Big Maps.  **
#  * Passable Minimap by Squall      - Partial.     Only events show right
#  * Minimap DVV by DerVVulfman      - Functional.  Can be above or below.   **
#  * Dynamic Maps by Near Fantastica - Failed.      A new system needed.    ***
#
#                                == * == * ==
#
#   ** Special map codes defined  by these systems must be in the name of any
#      map where the player  may enter/teleport.  Save Games retain settings.
#
#  *** Dynamic Maps permits events and settings to be stored/saved before one
#      leaves the map.   On returning,  the previously saved data is restored,
#      beneficial for features such as Fog of War.
#
#      
#==============================================================================



#==============================================================================
# ** BigMaps
#------------------------------------------------------------------------------
#  This module handles map configuration properties, and the map test switch.
#==============================================================================

module BigMaps
  
  # Creates the map array.  Do not remove. -----------------------------------
  Map = {} # Do not touch ----------------------------------------------------
  # --------------------------------------------------------------------------
  
  # Testing Switch
  # ==============
  # If true, runs system test prior to game execution.
  # Must be off/false for encrypted projects.
  #
    Test = true
  
    
  # MAP LIST        Hor Ver       List of BigMaps
  # =========       === ===       ============
  #
    Map['f']  = [ [   3,  3 ]  ,   [ 1, 2, 3,       # Assumes first three on top
                                     4, 5, 6,       # Assumes next three in mid.
                                     7, 8, 9 ] ]    # Assuming last three below

                                     
end



#==============================================================================
# ** BigMaps
#------------------------------------------------------------------------------
#  This module handles routines executed without the need of the Game_Map
#  class being loaded to test validity of Big Map data
#==============================================================================

module BigMaps
  #--------------------------------------------------------------------------
  # * Map Test
  #     map_id : Map ID
  #--------------------------------------------------------------------------
  def self.map_test(map_id)
    # Clear return flag
    returnval = nil
    # Cycle through all BigMaps defined
    BigMaps::Map.each {|mapset|
      # Set up a blank array (storage for BigMapset data)
      map_array   = []
      map_dims    = []
      map_ids     = []
      map_key     = mapset[0]
      map_array   = mapset[1]
      map_dims    = map_array[0]
      map_ids     = map_array[1]
      # Test map dimensions against list of BigMaps
      returnval   = true if (map_dims[0] * map_dims[1]) == map_ids.size
      # Exit if Dimensions not matching list of BigMaps
      return nil if returnval == false
      # Clear return flag
      returnval = nil
      counter   = 0
      # Cycle through map dimensions
      for y in 0..map_dims[1]-1
        for x in 0..map_dims[0]-1
          # Acquire the map key if the map array has the current map
          returnval = map_key if map_id == map_ids[counter]
          counter += 1
        end
      end
      # End Method
      return returnval
    }
  end
  #--------------------------------------------------------------------------
  # * Warning Test
  #--------------------------------------------------------------------------
  def self.warnings
    # Cycle through project's maps for duplicates
    mappins = load_data(sprintf("Data/MapInfos.rxdata"))
    mappins.each  {|map|
      maptest = 0
      BigMaps::Map.each {|set|
      unless set[1].nil?
        unless set[1].size != 2
          # Run Through Each Increaing Times if object is equal
          times = 0
          set[1][1].each {|element| times += 1 if element == map[0].to_i}
          maptest += 1 if times > 0
          if times > 1
            print "Project map is used more than once in a single big map.\n"+
                  "Map ID: " + map[0].to_s + " / Bigmap set: " + set[0].to_s
          end
        end
      end
      }        
      if maptest > 1
        print "Project map is in more than one big map.\n"+
              "Map ID: " + map[0].to_s
      end
    }    
    # Cycle through big maps for data errors
    BigMaps::Map.each {|set|
      if set[1].nil?
        p "Invalid set data detected for set " + set[0].to_s
      else
        if set[1].size != 2
          p "Invalid set data detected for set " + set[0].to_s
        else
          if set[1][0].size != 2
            "Invalid set dimensional data for set " + set[0].to_s
          else
            mapgrid = set[1][0][0] * set[1][0][1]
            if mapgrid < 2
              p "Invalid Big Map dimensions for set " + set[0].to_s
            else
              if mapgrid != set[1][1].size
                p "maps != dimension requirements for set " + set[0].to_s
              else
                failflag = false
                for i in set[1][1]
                  flag = FileTest.file?(sprintf("Data/Map%03d.rxdata", i)) 
                  failflag = true if flag == false
                end
                if failflag == true
                  p "missing maps used within set " + set[0].to_s  
                else
                  mid   = set[1][1][0]
                  map   = load_data(sprintf("Data/Map%03d.rxdata", mid))
                  mapx  = map.data.xsize
                  mapy  = map.data.ysize
                  mapfail = false
                  for i in set[1][1]
                    map = load_data(sprintf("Data/Map%03d.rxdata", i)) 
                    mapfail = true if mapx != map.data.xsize 
                    mapfail = true if mapy != map.data.ysize 
                  end
                  if mapfail
                    p "map sizes differ for set " + set[0].to_s  
                  else
                    mid     = set[1][1][0]
                    map     = load_data(sprintf("Data/Map%03d.rxdata", mid))
                    ts      = map.tileset_id
                    mapfail = false
                    for i in set[1][1]
                      map = load_data(sprintf("Data/Map%03d.rxdata", i)) 
                      mapfail = true  if ts != map.tileset_id
                    end
                    if mapfail
                      p "Tilesets differ between maps in set "+ set[0].to_s
                    end
                  end
                end
              end
            end
          end
        end
      end
    }    
  end
end



#==============================================================================
# ** BigMaps Automated Data Test
#------------------------------------------------------------------------------
#  Run before everything else, this checks every big map configured to ensure
#  proper data entries were made.
#==============================================================================

BigMaps.warnings if BigMaps::Test



#==============================================================================
# ** RPG
#------------------------------------------------------------------------------
#  A module containing RPGXP's data structures and more.
#==============================================================================

module RPG
  #============================================================================
  # ** Event
  #----------------------------------------------------------------------------
  #  Data class for map events.
  #============================================================================

  class Event
    #------------------------------------------------------------------------
    # * Update Events
    #------------------------------------------------------------------------
    def update_events_for_bigmaps(orig_map_id, ofs_x, ofs_y, ofs_id)
      @pages.each {|page|
        update_page_events(page, orig_map_id, ofs_x, ofs_y, ofs_id)
      }
    end
    #------------------------------------------------------------------------
    # * Update Data in Event Pages
    #------------------------------------------------------------------------
    def update_page_events(page, orig_map_id, ofs_x, ofs_y, ofs_id)
      page.list.each {|cmd|
        params = cmd.parameters
        case cmd.code
        # Conditional branch:  Option 6 (Event Facing Direction)
        when 111 ; params[1] += ofs_id if params[0] == 6 && params[1] > 0
        # Control Variable:  Option 6 (Acquiring map data for Selected Event)
        when 122 ; params[4] += ofs_id if params[3] == 6 && params[4] > 0
        # Set event location 
        when 202
          params[0] += ofs_id if params[0] > 0
          # swap with character
          if params[1] == 2 && params[2] > 0
            params[2] += ofs_id 
          # move to position by direct designation
          elsif params[1] == 0
            params[2] += ofs_x
            params[3] += ofs_y
          end
        # When Show Animation or Move Route
        when 207, 209
          params[0] += ofs_id if params[0] > 0
        end               
      }
    end
  end
end



#==============================================================================
# ** Game_Map
#------------------------------------------------------------------------------
#  This class handles the map. It includes scrolling and passable determining
#  functions. Refer to "$game_map" for the instance of this class.
#==============================================================================

class Game_Map
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_accessor :oldbigmap_id             # ID of previous map if 'big map'
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  alias bigmaps_gm_width width
  alias bigmaps_gm_height height
  alias bigmaps_gm_setup setup
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    @map_id         = 0
    @display_x      = 0
    @display_y      = 0
    @oldbigmap_id   = 0
  end
  #--------------------------------------------------------------------------
  # * Setup
  #     map_id : map ID
  #--------------------------------------------------------------------------
  def setup(map_id)
    # Test and exit if teleporting within same big map and big map is valid
    map_key1 = BigMaps.map_test(@oldbigmap_id)
    map_key2 = BigMaps.map_test(map_id)
    return if map_key1 == map_key2 && map_key2 != nil
    # Erase revised width/height
    @new_width  = nil
    @new_height = nil
    # Perform the original call
    bigmaps_gm_setup(map_id)
    # Test if big map
    map_key = BigMaps.map_test(map_id)
    # Exit unless bigmap
    return if map_key.nil?
    # Generate big map
    bigmaps_gm_generate(map_key, map_id)
    @map.width  ||= @new_width 
    @map.height ||= @new_height
    @map.width  = @new_width
    @map.height = @new_height
  end
  #--------------------------------------------------------------------------
  # * Get Width
  #--------------------------------------------------------------------------
  def width
    @new_width || bigmaps_gm_width
  end
  #--------------------------------------------------------------------------
  # * Get Height
  #--------------------------------------------------------------------------
  def height
    @new_height || bigmaps_gm_height
  end
  #--------------------------------------------------------------------------
  # * Generate Big Map
  #     map_key : key for specified big map hash array
  #     map_id  : map ID
  #--------------------------------------------------------------------------
  def bigmaps_gm_generate(map_key, map_id)
    # Acquire big map data
    map_data        = []
    map_data        = BigMaps::Map[map_key]
    # Obtain first map from array
    bigmap          = load_data(sprintf("Data/Map%03d.rxdata", map_data[1][0]))
    # Define new 'big map' size
    map_xsize       = map_data[0][0] * bigmap.data.xsize
    map_ysize       = map_data[0][1] * bigmap.data.ysize
    # Resize the map
    @new_width  = map_xsize
    @new_height = map_ysize
    @map.data.resize(map_xsize, map_ysize, @map.data.zsize)
    # Reset values for target map loop
    counter = 0  # Counter
    ox      = 0  # Original X Offset
    oy      = 0  # Original Y Offset
    evsize  = 0  # Size/Number of events
    # Set map event data
    @events = {}
    # Cycle through Big Map data
    for y in 0..(map_data[0][1])-1
      for x in 0..(map_data[0][0])-1
        # Acquire map ID and advance counter
        mid = map_data[1][counter]
        counter += 1
        # Acquire current map to add
        bigmap = load_data(sprintf("Data/Map%03d.rxdata", mid)) 
        # Add/Increase Encounters from map data
        bigmaps_gm_generate_enc(bigmap.encounter_list)
        # Draw new map from map data
        bigmaps_gm_generate_tiles(bigmap.data, ox, oy)
        # Add Events from map data, increasing event size for offset
        newsize = bigmaps_gm_generate_events(bigmap.events, mid, ox, oy, evsize)
        evsize  = newsize
        # Advance offxet X
        ox += bigmap.data.xsize
      end
      # Advance offxet Y (Resetting offset X)
      oy += bigmap.data.ysize
      ox = 0
    end    
  end
  #--------------------------------------------------------------------------
  # * Add Tiles into Big Map
  #     map_data : individual map tile/size data
  #     ox       : x-location drawing offset
  #     oy       : y-location drawing offset
  #--------------------------------------------------------------------------
  def bigmaps_gm_generate_tiles(map_data, ox, oy)
    for z in [2, 1, 0]
      for x in 0 ... map_data.xsize
        for y in 0 ... map_data.ysize
          @map.data[ox + x, oy + y, z] = map_data[x, y, z]
        end
      end
    end
  end  
  #--------------------------------------------------------------------------
  # * Add to Big Map Encounter List
  #     new_enc_list : individual map encounter list
  #--------------------------------------------------------------------------
  def bigmaps_gm_generate_enc(new_enc_list)
    @map.encounter_list.concat(new_enc_list)
  end  
  #--------------------------------------------------------------------------
  # * Generate Big Map Events
  #     events      :
  #     orig_map_id :
  #     ofs_x       :
  #     ofs_y       :
  #     ofs_evt     : 
  #--------------------------------------------------------------------------
  def bigmaps_gm_generate_events(events, orig_map_id, ofs_x, ofs_y, ofs_evt)
    # Set temp map event data
    new_events = {}
    # Calculate returned event list size (return if unchanged)
    sizer = ofs_evt + events.size unless events.nil?
    return sizer if events.nil?
    # Cycle through each new event
    events.each {|id, event|
      # Set new event ID
      new_id    = id + ofs_evt
      event.id  = new_id
      # Adjust new event coords
      event.x += ofs_x
      event.y += ofs_y
      # Update general event data
      event.update_events_for_bigmaps(orig_map_id, ofs_x, ofs_y, ofs_evt)
      # Push into temp map event array
      new_events[new_id]  = event
    }
    # Set up events in map
    bigmaps_gm_generate_events_setup(new_events)
    # End Method with new size
    return sizer
  end  
  #--------------------------------------------------------------------------
  # * Add the Map Events
  #     events : events added to map event list
  #--------------------------------------------------------------------------
  def bigmaps_gm_generate_events_setup(events)
    events.each do |i, event|
      @events[i] = Game_Event.new(@map_id, event)
    end
  end  
end



#==============================================================================
# ** Interpreter
#------------------------------------------------------------------------------
#  This interpreter runs event commands. This class is used within the
#  Game_System class and the Game_Event class.
#==============================================================================

class Interpreter
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  alias bigmaps_inter_command_201 command_201
  #--------------------------------------------------------------------------
  # * Transfer Player
  #--------------------------------------------------------------------------
  def command_201
    # Perform the original call with effective state
    effective = bigmaps_inter_command_201
    # Reset old map value
    $game_map.oldbigmap_id  = 0
    # Skip all this if not teleporting to a biggun
    map_key = BigMaps.map_test($game_temp.player_new_map_id)
    return if map_key.nil?
    # Define old map being left as 'big map' by ID
    $game_map.oldbigmap_id = $game_map.map_id
    # Reset values for target map loop
    counter   = 0  # Counter
    ox        = 0  # Original X Offset
    oy        = 0  # Original Y Offset
    map_data  = BigMaps::Map[map_key]
    # Get initial data from 1st map for individual map sizes
    bigmap    = load_data(sprintf("Data/Map%03d.rxdata", map_data[1][0])) 
    # Cycle through Big Map data
    for y in 0..(map_data[0][1])-1
      for x in 0..(map_data[0][0])-1
        # Acquire map ID and advance counter
        mid = map_data[1][counter]
        counter += 1
        # If it is the target Map ID
        if mid == $game_temp.player_new_map_id
          # Redefine new coordinates
          $game_temp.player_new_x += ox
          $game_temp.player_new_y += oy
        end
        # Advance offxet X
        ox += bigmap.data.xsize
      end
      # Advance offxet Y (Resetting offset X)
      oy += bigmap.data.ysize
      ox = 0
    end     
    # Exit Method Effective
    return effective
  end
end



#==============================================================================
# ** Scene_Title
#------------------------------------------------------------------------------
#  This class performs title screen processing.
#==============================================================================

class Scene_Title
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  alias bigmap_stitle_command_new_game command_new_game
  #--------------------------------------------------------------------------
  # * Command: New Game
  #--------------------------------------------------------------------------
  def command_new_game
    # Reset new start coordinate for big maps
    command_new_game_bigmap
    # Perform the original call
    bigmap_stitle_command_new_game
  end
  #--------------------------------------------------------------------------
  # * Adjust New Game Start for Big Map
  #--------------------------------------------------------------------------
  def command_new_game_bigmap
    # Test if big map and exit otherwise
    map_key   = BigMaps.map_test($data_system.start_map_id)
    return if map_key.nil?
    # Reset values for target map loop
    counter   = 0  # Counter
    ox        = 0  # Original X Offset
    oy        = 0  # Original Y Offset
    map_data  = BigMaps::Map[map_key]
    # Get initial data from 1st map for individual map sizes
    bigmap    = load_data(sprintf("Data/Map%03d.rxdata", map_data[1][0])) 
    # Cycle through Big Map data
    for y in 0..(map_data[0][1])-1
      for x in 0..(map_data[0][0])-1
        # Acquire map ID and advance counter
        mid = map_data[1][counter]
        counter += 1
        # If it is the target Map ID
        if mid == $data_system.start_map_id
          # Redefine new coordinates
          $data_system.start_x += ox
          $data_system.start_y += oy
        end
        # Advance offxet X
        ox += bigmap.data.xsize
      end
      # Advance offxet Y (Resetting offset X)
      oy += bigmap.data.ysize
      ox = 0
    end 
  end
end

Instructions
Well, it's pretty much setting up hashes after you draw the different maps you want to staple together.

Each hash holds two sub-arrays, the first is an array indicating how many maps across by how many maps down, while the second is a list of all the maps that get stitched together.

Oh, and I included a 'TEST' system. If on, it will let you know if you didn't properly configure your big-maps, or added the same maps into two or more big-maps! TURN IT OFF IF YOU ENCRYPT YOUR GAME!!! It uses a Ruby command that doesn't work with the Encrypted Archive format.

FAQ
Had to do something other than music related. Tired ears.


Compatibility
Well, it may be incompatible with some map scripts, especially the big systems. Amazingly, I did get it to work with some entertaining scripts.
  • Auto Populate by Charlie Fleed
  • Tileset Swap by ccoa
  • MGC Mode7 Edit by DerVVulfman (until the bitmap render limit is reached)
  • Fog of War by Wachunga (dynamic fogs require Dynamic Maps and patch provided)
  • Dynamic Maps (with patch provided below)
  • The Lycan ABS by DerVVulfman
  • Minimap DVV by DerVVulfman
  • Passability Minimap by Squall (but only the Events properly show, tilesets not properly rendered)

Simple Patches
If I (or anyone) comes up with a patch to fix an incompatibility issue, you can find them here.

Code: Select all

#==============================================================================
# ** BIG MAPS / Dynamic Map Patch
#------------------------------------------------------------------------------
#    by DerVVulfman
#    version 1.0
#    07-23-2017 (mm/dd/yyyy)
#    RGSS / RPGMaker XP
#==============================================================================
#
#  A simple patch  that allows the Map module  defined by Near Fantastica's
#  dynamic maps system  to recognize Big Maps.  If a Big Map is recognized,
#  the patch will use the 1st defined map in the Big Map as its data index.
#
#  Just paste this below 'Dynamic Maps' so the Map module is replaced.
#
#==============================================================================


module Map
  #--------------------------------------------------------------------------
  # * Set Map
  #     map    : map data
  #     map_id : Map ID
  #--------------------------------------------------------------------------  
  def Map.set_map(map, map_id)
    map_list  = []
    map_key   = BigMaps.map_test(map_id)
    unless map_key.nil?
      map_list  = BigMaps::Map[map_key]    
      map_id    = map_list[1][0]
    end
    @map_data[map_id] = map
  end
  #--------------------------------------------------------------------------
  # * Get Map
  #     map_id : Map ID
  #--------------------------------------------------------------------------  
  def Map.data(map_id)
    map_list  = []
    map_key   = BigMaps.map_test(map_id)
    unless map_key.nil?
      map_list  = BigMaps::Map[map_key]    
      map_id    = map_list[1][0]
    end
    return @map_data[map_id]
  end
end

Credits and Thanks
Er.. me? And my little test subject who loved it (Trade Secret).


Author's Notes
Damn, that's a big map. Did ya just make a 2000x2000 tile map????


Terms and Conditions
Free for use, even in commercial projects.
Up is down. Left is right. And sideways is straight ahead.
Image

Post Reply