06-05-2020, 03:08 AM 
(This post was last modified: 09-02-2020, 03:44 AM by DerVVulfman.
 Edit Reason: Map Shift Buffer and Border Fix
)
	
	
	Charlie's Mini-Map Extended
Version 2.1
Based on the 'Passability Mini-map by Charlie Fleed v 0.4.4"
Version 2.1
Based on the 'Passability Mini-map by Charlie Fleed v 0.4.4"
Introduction
Plenty and in the script.
Cached Folders:
Of the graphics used by the script, the Event's sprites and the mini-map's optional background image are stored within the Graphics\PassObjs folder. Both this and the Graphics\Passmaps folder can be encrypted with the rest of your encrypted/compressed game.
Map-Size Limitations:
The size of the generated/used map is limited to the maximum image size that RPGMaker XP can use. Under normal circumstances, you should have absolutely no problem as the maximum size is roughly 12,000 x 12,000 pixel size. But the system, if used with the BIG MAPS system by DerVVulfman, you will be limited. The largest minimap you can generate can cover a 'Big Map' that is 2,500 tiles across and 2,500 tiles deep. That is a big map, certainly larger than the default 500x500 size you're normally limited. But it is a limit none-the-less.
 Part 1: Header and Configuration
  			Code:
#==============================================================================
# ** Charlie's Mini-Map Config
#    Based on the 'Passability Mini-map by Charlie Fleed v 0.4.4"
#------------------------------------------------------------------------------
#    by DerVVulfman
#    version 2.1
#    09-01-2020 (mm/dd/yyyy)
#    RGSS / RPGMaker XP
#==============================================================================
#
#                     INSTRUCTIONS and CONFIGURATION
#
#==============================================================================
#
#  A fair amount of the mechanics of the system had been altered,  though the
#  way it functions is much the same.   It now uses an updated version of the 
#  ZLib and Bitmap.make_png methods.  And the configuration values are now in
#  within a new PassMap module.
#
#  Of major changes, is how the system recognizes certain events,  no longer
#  having separate methods to distinguish 'Enemy' and 'Teleport' events from
#  others within a custom list.  All event objects, including the Player it-
#  self, are now defined in a MAP_Events hash.
#
#  Of much more importance, the generated minimaps can now be cached into an
#  encrypted/compressed project.  This way, a game developer can very easily
#  replace the hum drum maps  with beautiful renders  of his/her own without
#  worry of them being lost.
#
#  Also, the Zoom feature has been altered.   While the Zoom setting (origi-
#  nally set by MAP_ZOOM) controls the magnification of the minimap,  it did
#  not allow different magnifications  for different maps.  Now the zoom can
#  be set within the name  of the map itself,  it being  a numeric value set
#  within brackets like:  FortBlaga [CF2].  The CF stands for Charlie Fleed,
#  and separates it from being mistaken for codes used by other systems.
#
#------------------------------------------------------------------------------
#
#  Instructions:
#
#  Minimaps are generated and stored within the Graphics\PassMap folder.
#  All others, sprites or backgrounds are in the Graphics\PassObjs folder.
#
#  Use the commands show_passmap and hide_passmap to make the minimap appear
#  and disappear, the last setting will be saved within your savefile.
#
#  The system allows you to have a pre-determined default zoom setting. But
#  you can have custom minimap zoom settings per map. You do this by entering
#  the numeric value in a set of brackets, currently formatted as [CF#].
#  The CF within the brackets is a configurable setting, the CF being the
#  initials of Charlie Fleed. High numeric values may be recommended for large
#  scaled maps, though more map content outside the visible viewport may be
#  revealed.  Decimal values are permitted, such as 0.5. But the entry can
#  not be '0' or less than zero.
#
#  You may also designate maps that never have a minimap, this by entering
#  a setting such as [MMap Off] within the map's name.  The MMap Off text
#  is also something you can configure.
#
#  Key names for events may be placed  within the event's name,  or entered 
#  within a comment as the first entry in the event's List of Commands.  IF
#  the key name is used within a comment,  the contents  of the comment may
#  only be the key name. However, the event's name is flexible and may hold
#  additional text besides the mini-map object key (such as "Enemy Beowulf"
#  if the list of minimap events has an MAP_Events["Enemy"] entry.
#
#  If an event has a 'No Map' comment in its List of Commands,  it is hidden
#  from the minimap.  However,  this is page dependent.  If a switch changes
#  the event's page to one without the comment, it may be revealed.
#
#------------------------------------------------------------------------------
#
#  Sprites:
#
#  In general, the event-based objects drawn in the minimap may be either
#  colored rectangles, or actual bitmap sprites which you may supply by
#  placing them within your Graphics\PassObjs folder.  It is recommended
#  that these be small graphics, roughly 8x8px. A single object, usually
#  something like a colored circle, square, triangle or something that
#  will stand out.
#
#  These sprites do not change in appearance other than vanishing from the
#  screen if the event is erased or a suitable code or page-change happens.
#  However, it is possible to depict the facing direction of a sprite.
#
#  Sprites may depict four facing directions, but the graphic for the sprite
#  must be available.  This sprite graphic will be 4 times wider than it is
#  in height, With this image, you can draw four different images of equal
#  size within, the first image facing up, the second left, the third right
#  and the fourth image facing down.
#
#  For those familiar with Selwyn's Passable Minimap, it is the same basic
#  set of circumstances for the Player sprite. However, this option is ex-
#  tended towards all events with this system.
#
#==============================================================================
module PassMap
  # --------------------------------------------------------------------------
  MAP_Events = {} # Do Not Touch
  # --------------------------------------------------------------------------
  
  # APPEARANCE
  # ==========
  # This handles the default placement and size of the minimap window
  # including its opacity and default zoom-out scaling of the map.
  #
    MAP_X         = 16    # X-Coordinates
    MAP_Y         = 368   # Y-Coordinates
    MAP_H         = 96    # Height (in pixels)
    MAP_W         = 128   # Width (in pixels)
    OPACITY       = 250   # General Opacity (0-255)
    ZOOM          = 0.625 # Zoom Out
                          #  * Higher values zooms out/shrinks the map more
                          #  * Can be floating point values like 0.5
                          #  * Cannot be 0 or negative values
  # MAP POSITION SHIFTING
  # =====================
  # The system has a feature that lets the mini-map shift from one edge of
  # the screen to another if the player gets too close to the edge of the
  # map, a feature perhaps desired if the mini-map may be hampering the
  # visibility of the actual game screen itself.
  #
    HORIZ_SHIFT = true    # Shift position based on player's horizontal position
    VERT_SHIFT  = false   # Shift position based on player's vertical position
    DIST_SHIFT  = 2       # Allowed number of tiles from center before shift
  # ANTI-LAG VIEWPORT
  # =================
  # The system has a rudimentary anti-lag to prevent the slowdown of the
  # system if there are hundreds of events in your map.  This feature sets
  # an area where your events may be updated, basically along the lines of
  # the tile-size of your viewpoort.  This tile size is typically the default
  # (typically a 20x15 tile window), The system includes a buffer to allow
  # updating beyond this range. Larger buffer settings may slow down the
  # system.
  #
    HORIZONTAL          = 20      # Tiles across in the game window
    VERTICAL            = 15      # Tiles high in game window
    BUFFER              = 2       # Extra tiles outside the game window
  # BACKGROUND
  # ==========
  # This handles the background image shown behind the rendered mini-
  # map. The background image is stored within the PassObjs folder,
  # this assuming one is set
  #
    BACK_IMAGE    = "passmap bg"  # Use "" if no background used
    BACK_OPACITY  = 255           # Background Image opacity (0-255)
  # GENERATED TILES
  # ====================  
  # This handles the colors of the initial passable minimap that is
  # generated and saved in your 'Passmaps' folder
  #
    BLOCKED_TILE_COLOR  = Color.new(0,0,0,255)        # Black (cannot cross)
    PASSABLE_TILE_COLOR = Color.new(200,200,200,255)  # Pale White (can cross)
  # HIDE MINIMAP OPTIONS
  # ====================
  # This defines how you can show or hide the minimap. It determines if the
  # message system hides it or if it can be hidden by an RMXP switch.  This
  # assumes you are not using the above mentioned 'hide_passmap' command.
  #
    MESSAGES      = true    # Does Message System hide Minimap
    VISIBLE_START = true   # Is the minimap on at game start?  ****
    SWITCH_ON     = true    # Does an RMXP switch hide Minimap
    SWITCH_ID     = 12      # ID of RMXP switch that hides
    
    #  SwitchStart turns on/off the inherit visibility  of the mini-map
    #  which may be controlled by the 'hide_passmap' and 'show_passmap'
    #  script calls.  If this visibility is set to false and turned off,
    #  the SWITCH_ON / SWITCH_ID entries will have no effect. This visi-
    #  bility must be turned on and engaged for the 'Switch' options to
    #  be effective.
    
  # MINIMAP MAP NAME OPTIONS
  # ========================
  # This defines overriding features for your minimaps per each individual
  # map.  These are flags which you may embed within the map's name, and 
  # will override all other options.  Within the actual map name, these
  # must be kept within brackets [].
  # 
    MM_HIDE       = 'MMap Off'    # Maps with this do not have minimaps
    MM_ZOOM       = 'CF'          # Maps with this and a numeric value
                                  # will have a pre-adjusted zoom.
    
  # EVENT LISTS
  # ===========
  # This defines the way events are rendered within the minimap. Each entry
  # is specific tag used by events.  This tag may be the name of an event
  # (ie the name in the top-left corner of the event editor), or it may be
  # the first comment in the event's list of commands.
  #
  # Of special note, you do define the player in this list (the first entry).
  # And it is compatible with Near Fantastica's SBABS Allies system which 
  # uses an 'Ally' key.
  #
  # Each entry has three parameters:  Image, Color, TileSize
  # Images are small graphics (like 8x8px) stored in the PassObjs folder.
  # Colors are defined with the Color class.
  # TileSize is a numeric value from 2 to 16, a value which determines the 
  # size of a rectangle drawn on the map.
  #
  # If an image is used, the Color and TileSize are ignored. But either way,
  # the size of the image/block is the same regardless of the 'zoom'factor
  # of the map.
  #                           Image       Color                    TSize
  # =====================     ==========  ======================   =====
    MAP_Events["Player"]   =  ["TheDude", Color.new(0,0,255,255),   4 ]
    MAP_Events["NPC"]      =  ["",        Color.new(0,128,255,255), 4 ]
    MAP_Events["Ally"]     =  ["",        Color.new(0,128,255,255), 8 ]
    MAP_Events["Chest"]    =  ["",        Color.new(250,128,0),     8 ]
    MAP_Events["Enemy"]    =  ["Enemy",   Color.new(255,0,0,255),   4 ]
    MAP_Events["Fred"]     =  ["",        Color.new(0,255,0,255),   4 ]
  
  
end Part 2: The Main Engine
  			Code:
#==============================================================================
# ** Charlie's Mini-Map Extended
#    Based on the 'Passability Mini-map by Charlie Fleed v 0.4.4"
#------------------------------------------------------------------------------
#    by DerVVulfman
#    version 2.1
#    09-01-2020 (mm/dd/yyyy)
#    RGSS / RPGMaker XP
#==============================================================================
#
#                              MAIN ENGINE
#
#==============================================================================
#==============================================================================
# ** Zlib     
#------------------------------------------------------------------------------
#  This module handles data compression, its library having been written by 
#  Jean-loup Gailly and Mark Adler. 
#==============================================================================
module Zlib
  #============================================================================
  # ** Png_File     
  #----------------------------------------------------------------------------
  #  This class performs generation of PNG formatted bitmap image files
  #============================================================================
  class Png_File < GzipWriter
    #--------------------------------------------------------------------------
    # * Make PNG
    #     bitmap : bitmap being created
    #     mode   : mode (0=safe / 1=rapid)
    #--------------------------------------------------------------------------
    def make_png(bitmap, mode = 0)
      # Save Bitmap & Mode
      @bitmap, @mode = bitmap, mode
      # Create & Save PNG
      self.write(make_header)
      self.write(make_ihdr)
      self.write(make_idat)
      self.write(make_iend)
    end
    #--------------------------------------------------------------------------
    # * Make Header
    #--------------------------------------------------------------------------
    def make_header
      return [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a].pack('C*')
    end
    #--------------------------------------------------------------------------
    # * Make IHDR
    #--------------------------------------------------------------------------
    def make_ihdr
      ih_size               = [13].pack("N")
      ih_sign               = 'IHDR'
      ih_width              = [@bitmap.width].pack('N')
      ih_height             = [@bitmap.height].pack('N')
      ih_bit_depth          = [8].pack('C')
      ih_color_type         = [6].pack('C')
      ih_compression_method = [0].pack('C')
      ih_filter_method      = [0].pack('C')
      ih_interlace_method   = [0].pack('C')
      string = ih_sign + ih_width + ih_height + ih_bit_depth + ih_color_type +
               ih_compression_method + ih_filter_method + ih_interlace_method
      ih_crc = [Zlib.crc32(string)].pack('N')
      return ih_size + string + ih_crc
    end
    #--------------------------------------------------------------------------
    # * Make IDAT
    #--------------------------------------------------------------------------
    def make_idat
      header  = "\x49\x44\x41\x54"
      data    = @mode == 0 ? make_bitmap_data0 : make_bitmap_data1
      data    = Zlib::Deflate.deflate(data, 8)
      crc     = [Zlib.crc32(header + data)].pack('N')
      size    = [data.length].pack('N')
      return size + header + data + crc
    end
    #--------------------------------------------------------------------------
    # * Make Bitmap Data 0
    #--------------------------------------------------------------------------
    def make_bitmap_data0
      gz = Zlib::GzipWriter.open('hoge.gz')
      t_Fx = 0
      w = @bitmap.width
      h = @bitmap.height
      data = []
      for y in 0...h
        data.push(0)
        for x in 0...w
          t_Fx += 1
          if t_Fx % 10000 == 0
            Graphics.update
          end
          if t_Fx % 100000 == 0
            s = data.pack("C*")
            gz.write(s)
            data.clear
          end
          color = @bitmap.get_pixel(x, y)
          red   = color.red
          green = color.green
          blue  = color.blue
          alpha = color.alpha
          data.push(red)
          data.push(green)
          data.push(blue)
          data.push(alpha)
        end
      end
      s = data.pack("C*")
      gz.write(s)
      gz.close   
      data.clear
      gz = Zlib::GzipReader.open('hoge.gz')
      data = gz.read
      gz.close
      File.delete('hoge.gz')
      return data
    end
    #--------------------------------------------------------------------------
    # * Make Bitmap Data Mode 1
    #--------------------------------------------------------------------------
    def make_bitmap_data1
      w = @bitmap.width
      h = @bitmap.height
      data = []
      for y in 0...h
        data.push(0)
        for x in 0...w
          color = @bitmap.get_pixel(x, y)
          red   = color.red
          green = color.green
          blue  = color.blue
          alpha = color.alpha
          data.push(red)
          data.push(green)
          data.push(blue)
          data.push(alpha)
        end
      end
      return data.pack("C*")
    end
    #--------------------------------------------------------------------------
    # * Make IEND
    #--------------------------------------------------------------------------
    def make_iend
      ie_size = [0].pack('N')
      ie_sign = 'IEND'
      ie_crc  = [Zlib.crc32(ie_sign)].pack('N')
      return ie_size + ie_sign + ie_crc
    end
  end
end
#==============================================================================
# ** Bitmap
#------------------------------------------------------------------------------
#  The bitmap class. Bitmaps are expressions of so-called graphics.  Sprites
#  (Sprite) and other objects must be used to display bitmaps on the screen.
#==============================================================================
class Bitmap
  #-------------------------------------------------------------------------
  # * Name      : Make PNG
  #   Info      : Saves Bitmap to File
  #   Author    : Wheeler (Initial Date: 2006-11-28)
  #   Found     : http://www.66rpg.com/htm/news624.htm (Chinese - Now 404)
  #   Call Info : Zero to Three Arguments
  #               Name : Name of filenam
  #               Path : Directory in Game Folder
  #               Mode : Mode of Writing
  #-------------------------------------------------------------------------
  def make_png(name = 'like', path = '', mode = 0)
    Dir.make_dir(path) if path != ''
    Zlib::Png_File.open('temp.gz')   { |gz| gz.make_png(self, mode) }
    Zlib::GzipReader.open('temp.gz') { |gz| $read = gz.read }
    f = File.open(path + name + '.png', 'wb')
    f.write($read)
    f.close
    File.delete('temp.gz')
  end
end
#==============================================================================
# ** RPG::MapInfo
#------------------------------------------------------------------------------
#  Data class for map information.
#==============================================================================
class RPG::MapInfo
  #--------------------------------------------------------------------------
  # * Obtain map name without additional bracket code
  #--------------------------------------------------------------------------
  def name
    return @name.gsub(/\[.*\]/) {""}
  end
  #--------------------------------------------------------------------------
  # * Obtain map name - include all prefix code
  #--------------------------------------------------------------------------
  def name_cfpmm
    return @name
  end
end
#==============================================================================
# ** RPG::Cache
#------------------------------------------------------------------------------
#  The module that loads each of RPGXP's graphic formats, creates a Bitmap
#  object, and retains it.
#==============================================================================
module RPG::Cache
  #------------------------------------------------------------------------
  # * Passable Minimap Maps
  #     filename : filename of the cached bitmap
  #------------------------------------------------------------------------
  def self.passmaps(filename)
    begin
      self.load_bitmap("Graphics/Passmaps/", filename)
    end
  end
  #------------------------------------------------------------------------
  # * Passable Minimap Backgrounds
  #     filename : filename of the cached bitmap
  #------------------------------------------------------------------------
  def self.passobjs(filename)
    begin
      self.load_bitmap("Graphics/PassObjs/", filename)
    end
  end  
end
#==============================================================================
# ** Game_Temp
#------------------------------------------------------------------------------
#  This class handles temporary data that is not included with save data.
#  Refer to "$game_temp" for the instance of this class.
#==============================================================================
class Game_Temp
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_accessor :redraw_passmap           # Redraw pass map trigger
  attr_accessor :refresh_passmap          # Refresh pass map trigger
  attr_accessor :scene_visible            # Scene map visibility flag
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  alias game_temp_passmap_cf_initialize initialize
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    # Original call
    game_temp_passmap_cf_initialize
    # New variables
    @redraw_passmap   = false
    @refresh_passmap  = false
    @scene_visible    = false
  end
end
#==============================================================================
# ** Game_System
#------------------------------------------------------------------------------
#  This class handles data surrounding the system. Backround music, etc.
#  is managed here as well. Refer to "$game_system" for the instance of 
#  this class.
#==============================================================================
class Game_System
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_accessor :minimap_visible          # Minimap visibility flag
  attr_accessor :minimap_opacity          # Minimap opacity setting
  attr_accessor :minimap_map_off          # Minimap disabled on map
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  alias game_system_passmap_cf_initialize initialize
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    # Original call
    game_system_passmap_cf_initialize
    # New variables
    @minimap_visible  = PassMap::VISIBLE_START
    @minimap_opacity  = PassMap::OPACITY
  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 :minimap_zoom             # zoom effect
  #--------------------------------------------------------------------------
  # * Alias Settings
  #--------------------------------------------------------------------------
  alias game_map_passmap_cf_setup setup
  #--------------------------------------------------------------------------
  # * Setup
  #     map_id : map ID
  #--------------------------------------------------------------------------
  def setup(map_id)
    # Create zoom, allowing zoom per map
    @minimap_zoom = PassMap::ZOOM
    test = setup_zoom_test(map_id)
    @minimap_zoom = test unless test.nil?
    setup_minimap_off(map_id)
    # Original call
    game_map_passmap_cf_setup(map_id)
    # New variables
    $game_temp.refresh_passmap  = true
  end
  #--------------------------------------------------------------------------
  # * Setup Charlie Fleed Map On/Off
  #     map_id : map ID
  #--------------------------------------------------------------------------
  def setup_minimap_off(map_id)
    map_data = load_data("Data/MapInfos.rxdata")[map_id]
    $game_system.minimap_map_off=map_data.name_cfpmm.include?(PassMap::MM_HIDE)
  end
  #--------------------------------------------------------------------------
  # * Setup Charlie Fleed Map Zoom
  #     map_id : map ID
  #--------------------------------------------------------------------------
  def setup_zoom_test(map_id)
    map_data = load_data("Data/MapInfos.rxdata")[map_id]
    map_data.name_cfpmm =~ /\[#{PassMap::MM_ZOOM}(.*?)\]/
    name3 = $1
    return nil if name3.nil?
    name3 = name3.to_f
    # Ensure no invalid value
    name3 = 1.0 if name3 <= 0
    return name3
  end
end
#==============================================================================
# ** Game_Event
#------------------------------------------------------------------------------
#  This class deals with events. It handles functions including event page 
#  switching via condition determinants, and running parallel process events.
#  It's used within the Game_Map class.
#==============================================================================
class Game_Event < Game_Character
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_reader   :event                    # event
  #--------------------------------------------------------------------------
  # * If a minimap event
  #--------------------------------------------------------------------------
  def minimap_tested?(comparestring)
    # Exit if no map
    return false if no_map?
    # Confirm if event's name matches
    return true if @event.name =~ comparestring
    # Cycle through events
    for p in @event.pages
      for command in p.list
        next unless command.code == 108
        return true if command.parameters[0] == comparestring
      end
    end
    return false
  end
  #--------------------------------------------------------------------------
  # * If flagged for no visibility on map
  #--------------------------------------------------------------------------
  def no_map?
    # Show no map if no event page content
    return true if @page.nil?
    # Cycle through event page
    for command in @page.list
      # Skip unless a comment exists
      next unless command.code == 108
      # Show no map if comment shows blocked
      return true if command.parameters[0] == "No Map"
    end
    # Snow map exists
    return false
  end
end
#==============================================================================
# ** Map_Objects
#------------------------------------------------------------------------------
#  This class deals with minimap objects. It handles rendering of map events
#  on the minimap itself, recognizing both the Game_Event and Game_Player
#  class and optionally the Game_Ally class if it exists within the game.
#  It is used within the Passability_Map class
#==============================================================================
class Map_Objects < Sprite
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    @valid_objects = []
    # Push Events
    for object in $game_map.events.values
      next if object.nil?
      # If a keyword Events
      for key in PassMap::MAP_Events.keys
        @valid_objects.push(object) if object.minimap_tested?(key)
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    # Dispose if it exists
    update_erase
    # Define config values used
    zoom = $game_map.minimap_zoom
    # Determine bitmap area
    self.bitmap   = Bitmap.new(4 * $game_map.width/zoom,
                               4 * $game_map.height/zoom)
    # Determine player position
    @player_x     = (4 * $game_player.real_x / 128.0) / zoom
    @player_y     = (4 * $game_player.real_y/ 128.0) / zoom
    # Determine avg size of tile
    tilesize      = 4 / zoom
    # Player center determinant
    self.ox       = [[0 ,
                    @player_x - self.viewport.rect.width/ 2 + tilesize/2].max,
                    4 * $game_map.width / zoom - self.viewport.rect.width].min
    self.oy       = [[0,
                    @player_y - self.viewport.rect.height / 2].max,
                    4 * $game_map.height / zoom - self.viewport.rect.height].min
    # Draw Events on map
    update_event_objects
    update_event_allies
    update_event_player
  end
  #--------------------------------------------------------------------------
  # * Frame Update : Erase Events
  #--------------------------------------------------------------------------  
  def update_erase
    self.bitmap.dispose unless self.bitmap.nil?
  end
  #--------------------------------------------------------------------------
  # * Frame Update : Handle Specific Events
  #--------------------------------------------------------------------------  
  def update_event_objects
    # Zoom and Tile Size
    zoom = $game_map.minimap_zoom
    tilesize  = 4 / zoom
    # Limited Viewport Params
    horiz = (PassMap::HORIZONTAL + PassMap::BUFFER) * 6
    vert  = (PassMap::VERTICAL + PassMap::BUFFER) * 6
    # Cycle through all events on the map
    for object in @valid_objects
      # Skip non-existant objects
      next if object.nil?
      # Acquire position
      object_x  = (4 * object.real_x / 128.0) / zoom
      object_y  = (4 * object.real_y / 128.0) / zoom      
      next if object_x < @player_x - horiz
      next if object_x > @player_x + horiz
      next if object_y < @player_y - vert
      next if object_y > @player_y + vert
      # Acquire facing direction
      dir = object.direction
      # If a keyword matches
      for key in PassMap::MAP_Events.keys
        next unless object.minimap_tested?(key)
        # Perform event drawing update
        update_event(object_x, object_y, dir, key)
        # Break from loop and go to next event
        break
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Frame Update : Handle Allies
  #--------------------------------------------------------------------------
  def update_event_allies
    # Zoom and Tile Size
    zoom = $game_map.minimap_zoom
    tilesize  = 4 / zoom
    # Limited Viewport Params
    horiz = (PassMap::HORIZONTAL + PassMap::BUFFER) * zoom
    vert  = (PassMap::VERTICAL + PassMap::BUFFER) * zoom
    # Define key for player
    key       = "Ally"
    return unless PassMap::MAP_Events.has_key?(key)
    # Only if NF Allies detected
    return if $game_allies.nil?
    # Cycle through all NF allies on map
    for ally in $game_allies.values
      # Skip of no ally
      next if ally.nil?
      # Acquire position
      object_x  = (4 * ally.real_x / 128.0) / zoom
      object_y  = (4 * ally.real_y / 128.0) / zoom      
      next if object_x < @player_x - horiz
      next if object_x > @player_x + horiz
      next if object_y < @player_y - vert
      next if object_y > @player_y + vert
      # Acquire facing direction
      dir = object.direction
      # Perform event drawing update
      update_event(object_x, object_y, dir, key)
    end
  end
  #--------------------------------------------------------------------------
  # * Frame Update : Handle Player
  #     object_x : player x-position
  #     object_y : player y-position
  #--------------------------------------------------------------------------
  def update_event_player
    # Define key for player
    key       = "Player"
    return unless PassMap::MAP_Events.has_key?(key)
    # Acquire facing direction
    dir = $game_player.direction
    # Perform event drawing update
    update_event(@player_x, @player_y, dir, key)
  end
  #--------------------------------------------------------------------------
  # * Frame Update : Handle Basic Event Drawing
  #     object_x : object x-position
  #     object_y : object y-position
  #     dir      : object facing direction
  #     key      : key
  #--------------------------------------------------------------------------
  def update_event(object_x, object_y, dir, key)
    # Acquire settings
    image     = PassMap::MAP_Events[key][0]
    tile_clr  = PassMap::MAP_Events[key][1]
    fill_size = PassMap::MAP_Events[key][2]
    # Fill size stays between 2 to 16
    fill_size = [16, ([2,  fill_size].max)].min
    unless image.nil? or image == ""
      # Blit image
      bitmap = RPG::Cache.passobjs(image)
      # If a 4-way directional sprite
      if bitmap.width == bitmap.height * 4
        map_4blit(object_x, object_y, dir, bitmap )
      # Otherwise if a single block sprite
      else
        map_1blit(object_x, object_y, bitmap)
      end
    else
      map_fill(object_x, object_y, tile_clr, fill_size)
    end    
  end
  #--------------------------------------------------------------------------
  # * Blit Sprite on map (4-Way version
  #     object_x : x-coordinates on minimap
  #     object_y : y-coordinates on minimap
  #     dir      : Facing Direction
  #     bitmap   : bitmap image
  #--------------------------------------------------------------------------
  def map_4blit(object_x, object_y, dir, bitmap )
    # Zoom and Tile Size
    zoom = $game_map.minimap_zoom
    tilesize  = 4 / zoom
    # Bitmap Width (1/4th the height)
    width = bitmap.width / 4
    # Get Frame of 4-frame sprite
    x_pos = (dir / 2 - 1) * bitmap.height
    # Create new bitmap rectangle, using settings
    bit_rect = Rect.new(x_pos, 0, width, bitmap.height)
    x = ([0, object_x - 0.5 * width].max) + (tilesize/2)
    y = ([0, object_y - 0.5 * bitmap.height].max)
    # Blit Sprite on Map
    self.bitmap.blt(x, y, bitmap, bit_rect, 128)
  end
  #--------------------------------------------------------------------------
  # * Blit Sprite on map
  #     object_x : x-coordinates on minimap
  #     object_y : y-coordinates on minimap
  #     bitmap   : bitmap image
  #--------------------------------------------------------------------------
  def map_1blit(object_x, object_y, bitmap)
    # Zoom and Tile Size
    zoom = $game_map.minimap_zoom
    tilesize  = 4 / zoom
    # Set position
    x = ([0, object_x - 0.5 * bitmap.width].max) + (tilesize / 2)
    y = ([0, object_y - 0.5 * bitmap.height].max)
    # Blit Sprite on Map
    self.bitmap.blt(x,y, bitmap, bitmap.rect, 128)      
  end
  #--------------------------------------------------------------------------
  # * Fill Rectangle on map
  #     object_x  : x-coordinates on minimap
  #     object_y  : y-coordinates on minimap
  #     color     : bitmap image
  #     fill_size : pixel size of filled block
  #--------------------------------------------------------------------------
  def map_fill(object_x, object_y, color, fill_size)
    # Zoom and Tile Size
    zoom = $game_map.minimap_zoom
    tilesize  = 4 / zoom
    # Set position
    x = ([0, object_x - 0.5 * fill_size].max) + (tilesize / 2)
    y = ([0, object_y - 0.5 * fill_size].max)
    # Fill Rectangle on Map
    self.bitmap.fill_rect(x, y, fill_size, fill_size, color)
  end
  #--------------------------------------------------------------------------
  # * Get Height
  #--------------------------------------------------------------------------
  def height
    zoom = $game_map.minimap_zoom
    return [ 4 * $game_map.height / zoom, self.viewport.rect.height ].min
  end
  #--------------------------------------------------------------------------
  # * Get Width
  #--------------------------------------------------------------------------
  def width
    zoom = $game_map.minimap_zoom
    return [ 4 * $game_map.width / zoom, self.viewport.rect.width ].min
  end
end
#==============================================================================
# ** Passability_Map
#------------------------------------------------------------------------------
#  This class actively renders the minimap utilizing game map passage data,
#  and brings it together with events rendered by the Map_Objects class.
#  It is used within the Scene_Map class.
#==============================================================================
class Passability_Map < Sprite
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_accessor :objects                  # Map Objects
  #--------------------------------------------------------------------------
  # * Object Initialization
  #     viewport  : viewport
  #--------------------------------------------------------------------------
  def initialize(viewport)
    super(viewport)
    # Do not initialize if map excluded
    return if $game_system.minimap_map_off    
    # Acquire Event Object on map
    @objects  = Map_Objects.new(viewport)
    # Set Minimap Opacity
    self.opacity  = $game_system.minimap_opacity
    # Determine Minimap visibility
    self.visible  = cf_passmap_viewport_visible
  end
  #--------------------------------------------------------------------------
  # * Create a new minimap and make cached png file
  #--------------------------------------------------------------------------
  def renew
    @map  = Bitmap.new( 4 * $game_map.width, 4 * $game_map.height)
    for x in 0...$game_map.width
      Graphics.update
      for y in 0...$game_map.height
        temp = 0
        @map.fill_rect(x * 4, y * 4, 4, 4, PassMap::PASSABLE_TILE_COLOR)
        if !$game_map.passable?(x, y, 2) # DOWN
          @map.fill_rect(x*4, y*4+3, 4, 1, PassMap::BLOCKED_TILE_COLOR)
          temp += 1
        end
        if !$game_map.passable?(x, y, 4) # LEFT
          @map.fill_rect(x*4, y*4, 1, 4, PassMap::BLOCKED_TILE_COLOR)
          temp += 1
        end
        if !$game_map.passable?(x, y, 6) # RIGHT
          @map.fill_rect(x*4+3, y*4, 1, 4, PassMap::BLOCKED_TILE_COLOR)
          temp += 1
        end
        if !$game_map.passable?(x, y, 8) # UP
          @map.fill_rect(x*4, y*4, 4, 1, PassMap::BLOCKED_TILE_COLOR)
          temp += 1
        end
        if temp == 4
          @map.fill_rect(x*4+1, y*4+1, 2, 2, PassMap::BLOCKED_TILE_COLOR)
        end
      end
    end
    # Create named PNG file from bitmap created
    @map.make_png(@name_map)
  end    
  #--------------------------------------------------------------------------
  # * Draw minimap and visually load
  #--------------------------------------------------------------------------
  def redraw
    # Zoom and Tile Size
    zoom = $game_map.minimap_zoom
    # Hide until drawn
    self.visible = false
    # Execute Map renewal
    renew
    # Define the size and set the minimap bitmap
    self.bitmap = Bitmap.new(@map.width / zoom, @map.height / zoom)
    self.bitmap.stretch_blt(self.bitmap.rect, @map, @map.rect, 255)
    # Handle reveal
    self.visible = cf_passmap_viewport_visible
  end
  #------------------------------------------------------------------------
  # * Refresh
  #------------------------------------------------------------------------
  def refresh
    # Do not refresh if map excluded
    return if $game_system.minimap_map_off    
    # Zoom
    zoom = $game_map.minimap_zoom
    # Create the Passmap Folder if it doesn't exist
    begin
      Dir.mkdir 'Graphics/Passmaps'
    rescue
      # Do nothing.
    end
    # Test if big map if Big Map system in project
    map_key = nil
    if Game_Map.method_defined? :old_big_event 
      map_key = BigMaps.map_test($game_map.map_id)
    end
    # If a normal map
    if map_key.nil?
      # Load normal map name and cache loading name
      @name_map = "Graphics/Passmaps/pass_map_" + $game_map.map_id.to_s
      loadname  = "pass_map_" + $game_map.map_id.to_s
    else
      # Load bigmap map name and cache loading name
      @name_map = "Graphics/Passmaps/pass_map_" + map_key
      loadname  = "pass_map_" + map_key
    end
    # Load the cached minimap if it exists
    begin
      @map = RPG::Cache.passmaps(loadname)
    rescue
      renew
    end
    # Define the size and set the minimap bitmap
    self.bitmap = Bitmap.new( @map.width/zoom, @map.height/zoom )
    self.bitmap.stretch_blt(self.bitmap.rect, @map, @map.rect)
    # Refresh map objects
    @objects.refresh
  end  
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    # Do not update if map excluded
    return if $game_system.minimap_map_off    
    # Zoom and Tile Size
    zoom      = $game_map.minimap_zoom
    tilesize  = 4 / zoom    
    # Exit unless map exists
    return if @map.nil?
    # Handle Visinility
    self.visible = cf_passmap_viewport_visible
    # Set Object Visibility to match
    @objects.visible = self.visible
    # Exit if not visible
    return if not self.visible
    # Acquire player coords
    player_x  =  (4 * $game_player.real_x / 128.0) / zoom
    player_y  =  (4 * $game_player.real_y / 128.0) / zoom
    # Set minimap center
    self.ox   = [[0, player_x - self.viewport.rect.width / 2 + tilesize/2].max,
                  @map.width / zoom - self.viewport.rect.width].min
    self.oy   = [[0, player_y - self.viewport.rect.height / 2 + tilesize/2].max,
                  @map.height / zoom - self.viewport.rect.height].min
    # Update event objects
    @objects.update
    # Set minimap opacity
    self.opacity      = $game_system.minimap_opacity
    # Set object event opacity
    @objects.opacity  = self.opacity
  end
  #--------------------------------------------------------------------------
  # * Minimap Visibility
  #--------------------------------------------------------------------------
  def cf_passmap_viewport_visible
    # Map tag override
    return false if $game_system.minimap_map_off
    # Remaining optional on/off systems
    return ($game_system.minimap_visible and
      ((not PassMap::MESSAGES) or (not $game_temp.message_window_showing)) and
      ((not PassMap::SWITCH_ON) or (not $game_switches[PassMap::SWITCH_ID])))
  end  
  #--------------------------------------------------------------------------
  # * Get Height
  #--------------------------------------------------------------------------
  def height
    zoom = $game_map.minimap_zoom
    return [@map.height / zoom, self.viewport.rect.height].min
  end
  #--------------------------------------------------------------------------
  # * Get Width
  #--------------------------------------------------------------------------
  def width
    zoom = $game_map.minimap_zoom
    return [@map.width / zoom, self.viewport.rect.width].min
  end  
end
#==============================================================================
# ** Interpreter
#------------------------------------------------------------------------------
#  This interpreter runs event commands. This class is used within the
#  Game_System class and the Game_Event class.
#==============================================================================
class Interpreter
  #--------------------------------------------------------------------------
  # * Redraw Passmap Command (actively recreats & overwrites previous render)
  #--------------------------------------------------------------------------
  def redraw_passmap
    $game_temp.redraw_passmap = true
  end
  #--------------------------------------------------------------------------
  # * Hide Passmap Command
  #--------------------------------------------------------------------------
  def hide_passmap
    $game_system.minimap_visible = false
    return
  end
  #--------------------------------------------------------------------------
  # * Show Passmap Command
  #--------------------------------------------------------------------------
  def show_passmap
    $game_system.minimap_visible = true
    return
  end
end
#==============================================================================
# ** Scene_Map
#------------------------------------------------------------------------------
#  This class performs map screen processing.
#==============================================================================
class Scene_Map
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_accessor :map                      # Field Map
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  alias scene_map_passmap_cf_main main
  alias scene_map_passmap_cf_update update
  #--------------------------------------------------------------------------
  # * Main Processing
  #--------------------------------------------------------------------------
  def main
    # Passable Minimap Initialization
    cf_passmap_initialize
    # Original call
    scene_map_passmap_cf_main
    # Passable Minimap Disposal
    cf_passmap_dispose
  end
  #--------------------------------------------------------------------------
  # * Main Processing : Passable Minimap Initialization
  #--------------------------------------------------------------------------
  def cf_passmap_initialize
    # Configured values
    map_x = PassMap::MAP_X
    map_y = PassMap::MAP_Y
    map_h = PassMap::MAP_H
    map_w = PassMap::MAP_W
    # Generate Viewport
    generate_viewport(map_x, map_y, map_h, map_w)
  end
  #--------------------------------------------------------------------------
  # * Main Processing : Generate MiniMap Viewport
  #--------------------------------------------------------------------------
  def generate_viewport(map_x, map_y, map_h, map_w)
    # Do not perform if map has no minimap
    if $game_system.minimap_map_off    
      @map.objects.update_erase unless @map.nil?
      return 
    end
    # Dispose of old viewport
    cf_passmap_dispose
    Graphics.update
    # Create the viewport
    @map_viewport         = Viewport.new(map_x, map_y, map_w, map_h)
    @map_viewport.z       = 9999
    @map_viewport.visible = cf_passmap_viewport_visible
    @map                  = Passability_Map.new(@map_viewport)
    @map.refresh
    # Exit unless there is a background image
    return if PassMap::BACK_IMAGE.nil?
    return if PassMap::BACK_IMAGE == ""
    # Set Background Viewport
    @map_bg_viewport = Viewport.new(map_x - 8, map_y - 8,
                                    @map.width + 16, @map.height + 16)
    @map_bg_viewport.z  = 9998
    # Set Background visible
    @map_bg_viewport.visible  = cf_passmap_viewport_visible
    # Create background image, including scale  
    @map_bg         = Sprite.new(@map_bg_viewport)
    @map_bg.bitmap  = RPG::Cache.passobjs(PassMap::BACK_IMAGE)
    @map_bg.opacity = PassMap::BACK_OPACITY
    @map_bg.zoom_x  = 1.0 * (@map_bg_viewport.rect.width)/@map_bg.bitmap.width
    @map_bg.zoom_y  = 1.0 * (@map_bg_viewport.rect.height)/@map_bg.bitmap.height
    # Refresh map and background
    cf_passmap_update_refresh(map_x, map_y)
    # Update game screen
    Graphics.update
  end
  #--------------------------------------------------------------------------
  # * Main Processing : Passable Minimap Disposal
  #--------------------------------------------------------------------------
  def cf_passmap_dispose
    # Dispose of minimap background
    if PassMap::BACK_IMAGE != ""
      @map_bg.dispose           unless @map_bg.nil?
      @map_bg_viewport.dispose  unless @map_bg_viewport.nil?
    end
    # Dispose of minimap
    @map.dispose                unless @map.nil?
    @map_viewport.dispose       unless @map_viewport.nil?
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    # Ensure visible
    $game_temp.scene_visible = true
    # Original call
    scene_map_passmap_cf_update
    # Determine if restart
    restart = false
    if @oldmap_id != $game_map.map_id
      restart = true
      @oldmap_id = $game_map.map_id
    end
    # Verify Minimap placement
    cf_passmap_placement(restart)
    # Passable Minimap processing
    cf_passmap_update
  end
  #--------------------------------------------------------------------------
  # * Frame Update : Passable Minimap placement based on player on map
  #--------------------------------------------------------------------------
  def cf_passmap_placement(restart=false)
    # Set test values
    map_width     = $game_map.width
    map_height    = $game_map.height
    map_x         = PassMap::MAP_X
    map_y         = PassMap::MAP_Y
    dist          = PassMap::DIST_SHIFT
    # Assume no repositioning
    reposition = restart
    # Handle Vertical Shift
    if PassMap::HORIZ_SHIFT == true
      # If defaulted to the left side
      if PassMap::MAP_X  < 320
        # Shift to right if near left edge of map
        if $game_player.x < (10 - dist)
          map_x = 640 - ( PassMap::MAP_X + PassMap::MAP_W )
          @ignore_x = false
        # Shift to left if near left edge of map
        elsif ($game_player.x - dist ) >= (map_width - 10)
          @ignore_x = false
        else
          @ignore_x = true
        end
      end
      # If defaulted to the right side
      if  PassMap::MAP_X >= 320
        # Shift to left if near right edge of map
        if ($game_player.x - dist) >= (map_width - 10 )
          map_x = 640 - ( PassMap::MAP_X + PassMap::MAP_W )
          @ignore_x = false
        # Shift to right if near right edge of map
        elsif $game_player.x < (10 - dist)  
          @ignore_x = false
        else
          @ignore_x = true
        end
      end
    end
    # Handle Vertical Shift
    if PassMap::VERT_SHIFT == true
      # If defaulted to the top side
      if PassMap::MAP_Y < 240
        # Shift to bottom if near top edge
        if $game_player.y < 7 - dist
          map_y = 480 - ( PassMap::MAP_Y + PassMap::MAP_H )
          @ignore_y = false
        # Shift to top edge if near bottom
        elsif ($game_player.y - dist) >= (map_height - 7)
          @ignore_y = false
        else
          @ignore_y = true
        end
      end
      # If defaulted to the bottom
      if PassMap::MAP_Y >= 240
        # Shift to bottom if near top edge
        if ($game_player.y - dist) >= (map_height - 7)
          map_y = 480 - ( PassMap::MAP_Y + PassMap::MAP_H )
          @ignore_y = false
        # Shift to top edge if near bottom
        elsif $game_player.y < 7 - dist
          @ignore_y = false
        else
          @ignore_y = true
        end
      end
    end    
    # Test if change performed
    unless @ignore_x == true
      if @old_x != map_x
        @old_x = map_x            unless map_x.nil?
        @old_x = PassMap::MAP_X   if @old_x.nil?
        reposition = true
      end
    end
    unless @ignore_y == true
      if @old_y != map_y
        @old_y = map_y
        @old_y = map_y            unless map_y.nil?
        @old_y = PassMap::MAP_Y   if @old_y.nil?
        reposition = true
      end
    end
    # Exit unless change is performed
    return unless reposition == true
    # Configured values
    map_h = PassMap::MAP_H
    map_w = PassMap::MAP_W
    # Generate Viewport
    generate_viewport(map_x, map_y, map_h, map_w)
  end
  #--------------------------------------------------------------------------
  # * Frame Update : Passable Minimap processing
  #--------------------------------------------------------------------------
  def cf_passmap_update
    # Hide if current map excluded
    if $game_system.minimap_map_off
      return if @map.nil?
      @map.visible = false
      @map_bg_viewport.visible = false
      return
    end
    # With minimap on, initialize system if not already done
    return cf_passmap_initialize if @map.nil?
    # Make sure Mini-Map Visible
    @map_viewport.visible = cf_passmap_viewport_visible
    # Make background visible if it exists
    if PassMap::BACK_IMAGE != ""
      @map_bg_viewport.visible = cf_passmap_viewport_visible
    end
    # Redraw map if necessary
    if $game_temp.redraw_passmap
      @map.redraw
      $game_temp.redraw_passmap = false
    end
    # refresh map if necessary
    if $game_temp.refresh_passmap
      # Process refresh including background
      cf_passmap_update_refresh
      $game_temp.refresh_passmap = false
    end
    # Update the map
    @map.update  
  end
  #--------------------------------------------------------------------------
  # * Frame Update : Passable Minimap refresh
  #     x : x-position of border
  #     y : y-position of border
  #--------------------------------------------------------------------------
  def cf_passmap_update_refresh(x=nil, y=nil)
    # Make sure border is properly moved.
    if @old_x != x
      @old_x = x              unless x.nil?
      @old_x = PassMap::MAP_X if @old_x.nil?
    end
    if @old_y != y
      @old_y = y              unless y.nil?
      @old_y = PassMap::MAP_Y if @old_y.nil?
    end
    # Refresh as normal
    @map.refresh
    # Exit unless there is a background
    return if PassMap::BACK_IMAGE == ""
    # Define Rect
    rect_w = @map.width  + 16
    rect_h = @map.height + 16
    rect_x = @old_x - 8
    rect_y = @old_y - 8
    # Set rect
    @map_bg_viewport.rect.width   = rect_w
    @map_bg_viewport.rect.height  = rect_h
    @map_bg_viewport.rect.x       = rect_x
    @map_bg_viewport.rect.y       = rect_y
    # Set background Zoom
    @map_bg.zoom_x = 1.0 * (@map_bg_viewport.rect.width)/@map_bg.bitmap.width
    @map_bg.zoom_y = 1.0 * (@map_bg_viewport.rect.height)/@map_bg.bitmap.height
  end
  #--------------------------------------------------------------------------
  # * Minimap Visibility
  #--------------------------------------------------------------------------
  def cf_passmap_viewport_visible
    # Map tag override
    return false if $game_system.minimap_map_off
    return false if !$game_temp.scene_visible
    # Remaining optional on/off systems
    return ($game_system.minimap_visible and
      ((not PassMap::MESSAGES) or (not $game_temp.message_window_showing)) and
      ((not PassMap::SWITCH_ON) or (not $game_switches[PassMap::SWITCH_ID])))
  end
endCredits and Thanks
Obvious thanks to Charlie Fleed for the original version. Credits also go to Wheeler for the original November 2006 system that generates PNG files, his identity at the time unknown.
Up is down, left is right and sideways is straight ahead. - Cord "Circle of Iron", 1978 (written by Bruce Lee and James Coburn... really...)
	  Above are clickable links

 
 
 Charlie's Mini-Map Extended
 Charlie's Mini-Map Extended
 
 
![[Image: QrnbKlx.jpg]](https://i.imgur.com/QrnbKlx.jpg)
![[Image: sGz1ErF.png]](https://i.imgur.com/sGz1ErF.png)
![[Image: liM4ikn.png]](https://i.imgur.com/liM4ikn.png)
![[Image: fdzKgZA.png]](https://i.imgur.com/fdzKgZA.png)
![[Image: sj0H81z.png]](https://i.imgur.com/sj0H81z.png)
![[Image: QL7oRau.png]](https://i.imgur.com/QL7oRau.png)
![[Image: uSqjY09.png]](https://i.imgur.com/uSqjY09.png)
![[Image: GAA3qE9.png]](https://i.imgur.com/GAA3qE9.png)
![[Image: 2Hmnx1G.png]](https://i.imgur.com/2Hmnx1G.png)
![[Image: BwtNdKw.png%5B]](https://i.imgur.com/BwtNdKw.png%5B)


 
![[Image: SP1-Scripter.png]](https://www.save-point.org/images/userbars/SP1-Scripter.png)
![[Image: SP1-Writer.png]](https://www.save-point.org/images/userbars/SP1-Writer.png)
![[Image: SP1-Poet.png]](https://www.save-point.org/images/userbars/SP1-Poet.png)
![[Image: SP1-PixelArtist.png]](https://www.save-point.org/images/userbars/SP1-PixelArtist.png)
![[Image: SP1-Reporter.png]](https://i.postimg.cc/GmxWbHyL/SP1-Reporter.png)

 
 