Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Monster Encounters?

Thanks in advance for reading.

I seem to recall, possibly in RM2k3, that you could 'zone' maps, allowing for different monsters to be encountered in different areas of the same map. See, i'm hoping to build large maps to give a greater sense of exploration, but would like to have tougher monsters being encountered further away from the entrances to villages and towns. Example: You'd only encounter 1 or 2 wolves at a time along a road, but when wandering off the road and into the woods or fields you might encounter up to 4 at a time. Is this still possible in RMXP? Either through the 'zone' system again (if that's what it's called) or even through invisible event tiles that trigger when they're walked across, changing the types of monster encounters the map has. I can't find a way of doing either of these things, but if anyone with more expertise can shed some light here, it'd be greatly appreciated. 
:blush:

Many thanks.
 
Sadly, RMXP has no direct way of changing what monsters you encounter on a given map. 

However, there are some interesting indirect ways.  One option is to no-fade teleport the player on to a different, apparently identical map with different encounter settings.

Another is to make the enemy troops have more opponents in them, tagged "Appear Halfway."  Have an event in that troop that checks if a switch is on or a variable is above a certain value, and bring the extra enemies in if that's the case.  (You can also use this trick to make harder fights for higher-level characters.)

I made some screenshots of this for the later example.  Do you want to see them?
 
The first idea sounds golden, certainly for what i'm interested in here. And as for the second idea, i'm very intrigued! Could make for some interesting end-game content, and i'm always eager to learn, so i'd love to see those screenshots! Thanks for the help
:smile:
 

Sero

Member

I know a way. You can use an ABS. But the enemies are not in groups. So you would encounter say, 10 wolves if you keep then near each other.
I don't know if this was helpful or not. But you can put certain amounts of enemies in a group in certain parts.
 
-Silver-":jx20txf3 said:
The first idea sounds golden, certainly for what i'm interested in here. And as for the second idea, i'm very intrigued! Could make for some interesting end-game content, and i'm always eager to learn, so i'd love to see those screenshots! Thanks for the help
:smile:

Here we go-- had to take a moment to comb through my screenshot archives.  (Man, I've got too many of those.  Photobucket's going to come after me with an axe, one of these days...)

Anyway, here's the basic idea:
http://i234.photobucket.com/albums/ee103/UnkaJosh/VariableEnemies.png[/img]

Just make the enemies Appear Halfway, and you can set those variables equal to somebody's level, or the Terrain Tags that they're standing on (a cool trick, IMHO), or whatever.
 
Unka Josh - that's awesome! Really great way to extend the exp on offer, and I completely understand how to script it thanks to that screenshot. Thanks a million =)

Sero - ABS? I'm assuming that stands for Active Battle System, and by that, you mean an encounter system where you only start a battle when you 'walk in to' a monster on the field, rather than random encounters? That would make sense, since each monster visible on the map could have its own event - starting a battle with 2 wolves along a road, and 5 if that monster has been placed way off track. The trouble with that option is that I have little experience, and therefore little skill (trust me, i've tried =P) with spriting, and since all my monsters are self-created and drawn, I would have to create monster sprites myself too... It would also require creating a script for the monsters to respawn after a certain amount of time as well. It's a real shame that 'zonation' tool wasn't carried over. It was sooo useful =(

Thanks for the input though, both of you! The more ideas the merrier!  :lol:
 
-Silver-,
would this be something you could use...?  It is a script made by "SephirothSpawn" called:  "Encounter Control", you can specify which areas of a map you want certain monsters to be encountered in.  You can also set the area in shapes ie: Circle or Rectangle.  Again, it allows you to view in the debugger the regions on the map.

Hope this helps you out:

  Encounter Control v2.1
Code:
#==============================================================================
# ** Encounter Control
#------------------------------------------------------------------------------
# SephirothSpawn
# Version 2.1
# 2007-07-30
# SDK : Version 2.0+, Part I
#------------------------------------------------------------------------------
# * Version History :
#
#   Version 1 ---------------------------------------------------- (2006-08-12)
#    Version 1.01 ------------------------------------------------ (2006-10-23)
#     - Bug Fix : Fixed Erase Event
#   Version 2 ---------------------------------------------------- (2007-03-16)
#    - Update : Updated Entire Code
#    Version 2.1 ------------------------------------------------- (2007-07-30)
#     - Update : Added Conditionals for battle to begin. 
#                Added Weather Encounters.
#------------------------------------------------------------------------------
# * Requirements :
#
#   Method & Class Library (2.1+)
#------------------------------------------------------------------------------
# * Description :
#
#   This script was designed to give you more control of random encounters.
#   Encounter Control allows you give terrain tags, circular regions and
#   rectangular regions groups of enemies, instead of just map encounters.
#   Additionally, it allows you to view in the debugger the regions on the map.
#   You may now also let weather patterns effect encounters as well.
#
#   As a bonus, you can make it so certain conditions have to true before
#   encounters can happen.
#------------------------------------------------------------------------------
# * Instructions :
#
#   Place The Script Below the SDK and Above Main.
#
#   Creating Encounter Regions with Events
#    - Comment : Enc Ctrl <type>(<params>) [<troops>]
#
#    <type>   : CIRC or RECT
#    <params> : When CIRC : X, Y, Radius
#               When Rect : X, Y, Width, Height
#    <troops> : troop_id, ...
#------------------------------------------------------------------------------
# * Customization :
#
#   Direct Encounter Regions
#
#   Direct_Regions = { 
#     map_id => { [x, y] => [troop_id, ...], ... },
#     ...
#   }
#   Rectangle Encounter Regions
#
#   Rect_Regions = { 
#     map_id => { [x, y, width, height] => [troop_id, ...], ... },
#     ...
#   }
#   Circle Encounter Regions
#
#   Circ_Regions = { 
#     map_id => { [x, y, radius] => [troop_id, ...], ... },
#     ...
#   }
#   Terrain Encounter Regions
#
#   Tern_Regions = { 
#     map_id => { terrain_tag => [troop_id, ...], ... },
#     ...
#   }
#   Weather Encounter
#
#   Weather_Encs = { 
#     map_id => { weather_id => [troop_id, ...], ... },
#     ...
#   }
#------------------------------------------------------------------------------
# * Syntax :
#
# * Changing Encounter Conditions (Must be met to encounter)
#
#   Changing Terraisn you must be on
#    - $game_system.enc_conditions.terrains = [terrain_id, ...]
#
#   Changing Required Weathers
#    - $game_system.enc_conditions.weathers = [weather_type, ...]
#
#   Variable Conditions where 1 must be met
#    - $game_system.enc_conditions.variables_one = { variable_id => [x], ...}
#
#    [x] = [<operator>, n]
#
#    <operator> : 0 - <, 1 - <=, 2 - ==, 3 - >=, 4 - >
#
#   Variable Conditions where all must be met
#    - $game_system.enc_conditions.variables_all = { variable_id => [x], ...}
#
#    [x] = [<operator>, n]
#
#    <operator> : 0 - <, 1 - <=, 2 - ==, 3 - >=, 4 - >
#
#   Switch Conditions where 1 must be met
#    - $game_system.enc_conditions.switches_one = { switch_id => <bool>, ...}
#
#    <bool> : true or false
#
#   Switch Conditions where all must be met
#    - $game_system.enc_conditions.switches_all = { switch_id => <bool>, ...}
#
#    <bool> : true or false
#
#   Switch Condition where script must be evaluated as true
#    - $game_system.enc_conditions.call_script = 'code' or nil
#==============================================================================

#------------------------------------------------------------------------------
# * SDK Log Script
#------------------------------------------------------------------------------
SDK.log('Encounter Control', 'SephirothSpawn', 2.1, '2007-07-30')
SDK.check_requirements(2, [], {'Method & Class Library' => 2.1}) 

#------------------------------------------------------------------------------
# * Begin SDK Enable Test
#------------------------------------------------------------------------------
if SDK.enabled?('Encounter Control')

#==============================================================================
# ** Ecounter Control
#==============================================================================

module Encounter_Control
  #--------------------------------------------------------------------------
  # * Drct Encounter Regions
  #
  #   Direct_Regions = { 
  #     map_id => { [x, y] => [troop_id, ...], ... },
  #     ...
  #   }
  #--------------------------------------------------------------------------
  # * Rect Encounter Regions
  #
  #   Rect_Regions = { 
  #     map_id => { [x, y, width, height] => [troop_id, ...], ... },
  #     ...
  #   }
  #--------------------------------------------------------------------------
  # * Circle Encounter Regions
  #
  #   Circ_Regions = { 
  #     map_id => { [x, y, radius] => [troop_id, ...], ... },
  #     ...
  #   }
  #--------------------------------------------------------------------------
  # * Terrain Encounter Regions
  #
  #   Tern_Regions = { 
  #     map_id => { terrain_tag => [troop_id, ...], ... },
  #     ...
  #   }
  #--------------------------------------------------------------------------
  # * Weather Encounter
  #
  #   Weather_Encs = { 
  #     map_id => { weather_id => [troop_id, ...], ... },
  #     ...
  #   }
  #--------------------------------------------------------------------------
  Drct_Regions = {}
  Rect_Regions = {}
  Circ_Regions = {}
  Tern_Regions = {}
  Weather_Encs = {}
  # Defaults For All Non-Defined Maps
  Drct_Regions.default = {}
  Rect_Regions.default = {}
  Circ_Regions.default = {}
  Tern_Regions.default = {}
  Weather_Encs.default = {}
  
  #==========================================================================
  # ** Encounter Conditionals
  #==========================================================================
  
  class Encounter_Conditionals
    #------------------------------------------------------------------------
    # * Public Instance Variables
    #------------------------------------------------------------------------
    attr_accessor :terrains
    attr_accessor :weathers
    attr_accessor :variables_one
    attr_accessor :variables_all
    attr_accessor :switches_one
    attr_accessor :switches_all
    attr_accessor :call_script
    #------------------------------------------------------------------------
    # * Object Initialization
    #------------------------------------------------------------------------
    def initialize
      @terrains       = []
      @weathers       = []
      @variables_one  = {} 
      @variables_all  = {}
      @switches_one   = {}
      @switches_all   = {}
      @call_script    = nil
    end
    #------------------------------------------------------------------------
    # * Can Encounter? Test
    #------------------------------------------------------------------------
    def can_encounter?
      # Return False Unless Terrains Include Current Player Terrain
      return false unless @terrains.include?($game_player.terrain_tag)
      # Return False Unless Weathers Include Current Weather Type
      return false unless @weathers.include?($game_screen.weather_type)
      # Return False Unless Variables One Set
      return false unless v1?
      # Return False Unless Variables All Set
      return false unless va?
      # Return False Unless Switches One set
      return false unless s1?
      # Return False Unless Switches All Set
      return false unless sa?
      # If Nil Call Script
      if @call_script.nil?
        # Return True
        return true
      end
      # Return Inverse Of Call Script Result
      return !(eval @call_script)
    end
    #------------------------------------------------------------------------
    # * Variables One? Test
    #------------------------------------------------------------------------
    def v1?
      @variables_one.each do |variable_id, parameters|
        case parameters[0]
        when 0
          return true if $game_variables[variable_id] <  parameters[1]
        when 1
          return true if $game_variables[variable_id] <= parameters[1]
        when 2
          return true if $game_variables[variable_id] == parameters[1]
        when 3
          return true if $game_variables[variable_id] >= parameters[1]
        when 4
          return true if $game_variables[variable_id] >  parameters[1]
        end
      end
      return false
    end
    #------------------------------------------------------------------------
    # * Variables All? Test
    #------------------------------------------------------------------------
    def va?
      @variables_one.each do |variable_id, parameters|
        case parameters[0]
        when 0
          return false unless $game_variables[variable_id] <  parameters[1]
        when 1
          return false unless $game_variables[variable_id] <= parameters[1]
        when 2
          return false unless $game_variables[variable_id] == parameters[1]
        when 3
          return false unless $game_variables[variable_id] >= parameters[1]
        when 4
          return false unless $game_variables[variable_id] >  parameters[1]
        end
      end
      return true
    end
    #------------------------------------------------------------------------
    # * Switches One? Test
    #------------------------------------------------------------------------
    def so?
      @switches.each do |switch_id, boolean|
        return true if $game_switches[switch_id] == boolean
      end
      return false
    end
    #------------------------------------------------------------------------
    # * Switches All? Test
    #------------------------------------------------------------------------
    def sa?
      @switches.each do |switch_id, boolean|
        return false unless $game_switches[switch_id] == boolean
      end
      return true
    end
  end
  
  #--------------------------------------------------------------------------
  # * Check For Encounter Regions
  #--------------------------------------------------------------------------
  def self.encounters(x, y, map_id = $game_map.map_id)
    # Loads Search Data
    searches = self.load_searches
    # Key
    key = [map_id, x, y]
    # If Search Holds Information
    if searches.has_key?(key)
      # Load Search Info
      encounters = searches[key]
    # If No Search Info Recorded
    else
      # Starts Encounters
      encounters = []
      # Checks Direct Locations
      Drct_Regions[map_id].each do |xy, troops|
        encounters << troops if x == xy[0] && y == xy[0]
      end
      # Checks Rect Regions
      Rect_Regions[map_id].each do |xywh, troops|
        x1, y1 = xywh[0],      xywh[1]
        x2, y2 = x1 + xywh[2], y1 + xywh[3]
        encounters << troops if x >= x1 && x <= x2 && y >= y1 && y <= y2
      end
      # Checks Circular Regions
      Circ_Regions[map_id].each do |xyr, troops|
        _x, _y, r = xyr[0], xyr[1], xyr[2]
        x_, y_ = (_x - x) ** 2, (_y - y) ** 2
        encounters << troops if (x + y) <= (r ** 2)
      end
      # Checks Terrain Regions
      Tern_Regions[map_id].each do |terrain, troops|
        encounters << troops if $game_map.terrain_tag(x, y) == terrain
      end
      # Save Encounters
      self.save_searches(key, encounters)
    end
    # Check Weather Encounters
    Weather_Encs[map_id].each do |weather_id, troops|
      encounters << troops if $game_system.weather_type == weather_id
    end
    # Organize Encounter
    encounters.flatten!
    encounters.uniq!
    encounters.sort!
    # Return Encounters
    return encounters
  end
  #--------------------------------------------------------------------------
  # * Save Encounter Searches
  #--------------------------------------------------------------------------
  def self.save_searches(key, result)
    # Collects Saved Searches
    searches = self.load_searches
    # Saves Search Result
    searches[key] = result
    # Resaves Searches to File
    save_data(searches, 'Data/Encounter Region Searches.rxdata')    
  end
  #--------------------------------------------------------------------------
  # * Load Encounter Searches
  #--------------------------------------------------------------------------
  def self.load_searches
    # Test For Saved Searches File
    unless FileTest.exist?('Data/Encounter Region Searches.rxdata')
      # Creates Search Rxdata File
      save_data({}, 'Data/Encounter Region Searches.rxdata')
      return {}
    end
    # Returns Searches
    return load_data('Data/Encounter Region Searches.rxdata')
  end
end

#==============================================================================
# ** Game_System
#==============================================================================

class Game_System
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_reader :enc_conditions
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  alias_method :seph_enccontrol_gmsys_init, :initialize
  alias_method :seph_enccontrol_gmsys_encd, :encounter_disabled
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    # Original Initialization
    seph_enccontrol_gmsys_init
    # Create Enccounter Conditions
    @enc_conditions = Encounter_Control::Encounter_Conditionals.new
  end
  #--------------------------------------------------------------------------
  # * Encounter Disabled
  #--------------------------------------------------------------------------
  def encounter_disabled
    # Return True if Original True
    return true if seph_enccontrol_gmsys_encd
    # Return Can Encounter
    return !@enc_conditions.can_encounter?
  end
end

#==============================================================================
# ** Game_Event
#==============================================================================

class Game_Event < Game_Character
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  alias_method :seph_enccontrol_gmevt_refresh, :refresh
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    # Original Refresh
    seph_enccontrol_gmevt_refresh
    # Clear Encounter Areas
    @circle_encounter_areas, @rect_encounter_areas = {}, {}
    # Return if No List or Erased
    return if @list.nil? || @erased
    # Pass Through Event Commands
    for ec in @list
      # Skip If Not Comment Line
      next unless [108, 408].include?(ec.code)
      # Next If Not Comment Doesn't Include ENC CTRL
      next unless ec.parameters[0].upcase.include?('ENC CTRL')
      # Collect Troop List For Area
      ec.parameters[0].dup.gsub(/\[(.+?)\]/, '')
      troops = $1.split.collect! {|x| x.to_i}
      # Test For Circular Range
      if ec.parameters[0].upcase.include?('CIRC')
        ec.parameters[0].dup.gsub(/\((.+?)\)/, '')
        unless $1.nil?
          circ = eval "[#{$1}]"
          # Stores Enc List
          @circle_encounter_areas[circ] = troops
        end
      end
      # Test For Rect Boundaries
      if ec.parameters[0].upcase.include?('RECT')
        ec.parameters[0].dup.gsub(/\((.+?)\)/, '')
        unless $1.nil?
          rect = eval "[#{$1}]"
          # Stores Enc List
          @rect_encounter_areas[rect] = troops
        end
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Circle Encounter Areas
  #--------------------------------------------------------------------------
  def seph_circle_enconter_areas
    return @circle_encounter_areas
  end
  #--------------------------------------------------------------------------
  # * Rect Encounter Areas
  #--------------------------------------------------------------------------
  def seph_rect_encounter_areas
    return @rect_encounter_areas
  end
end

#==============================================================================
# ** Game_Map
#==============================================================================

class Game_Map
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_accessor :include_map_encounters
  attr_accessor :include_ec_encoutners
  attr_accessor :include_event_encounters
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  alias_method :seph_enccntrl_gmmap_in, :initialize  
  alias_method :seph_enccntrl_gmmap_el, :encounter_list
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    # Encounter Control Variable Initialization
    @include_map_encounters   = true
    @include_ec_encounters    = true
    @include_event_encounters = true
    # Original Initialization
    seph_enccntrl_gmmap_in
  end
  #--------------------------------------------------------------------------
  # * Get Encounter List
  #--------------------------------------------------------------------------
  def encounter_list
    # Create Blank List
    list = []
    # Add Default Encounter List if Map Encounters on
    list << seph_enccntrl_gmmap_el if @include_map_encounters
    # Add Encounter Countrol List if EC on
    x, y = $game_player.x, $game_player.y
    list << Encounter_Control.encounters(x, y) if @include_ec_encounters
    # Add Event Encounter List if Event Encounters on
    list << event_encounters_list
    # Return Organized List
    return list.flatten.uniq.sort
  end
  #--------------------------------------------------------------------------
  # * Get Event Encounter List
  #--------------------------------------------------------------------------
  def event_encounters_list
    # Return Empty List if Turned Off
    return [] unless @include_event_encounters
    # Create List
    list = []
    # Gets Player X & Y
    px, py = $game_player.x, $game_player.y
    # Pass Through All Events
    for event in @events.values
      # Checks Circular Ranges Of Event
      event.seph_circle_enconter_areas.each do |xyr, l|
        list << l if VR.in_range?(px, py, xyr[0], xyr[1], xyr[2])
      end
      # Checks Rect Ranges of Event
      event.seph_rect_encounter_areas.each do |r, l|
        list << l if VR.in_rect_range?(px, py, r[0], r[1], r[2], r[3])
      end
    end
    # Return Encounter List
    return list
  end
end

#==============================================================================
# ** Spriteset_Map
#==============================================================================

if $DEBUG

class Spriteset_Map
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  alias seph_encctrl_gmmap_init initialize
  alias seph_encctrl_gmmap_update update
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    # Original Initialization
    seph_encctrl_gmmap_init
    # Creates Flash Data Table & Flash Tile Flag
    if @tilemap.flash_data.nil?
      @tilemap.flash_data = Table.new($game_map.width, $game_map.height)
    end
    @seph_encctrl_tilesflashing = false
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    # Original Update
    seph_encctrl_gmmap_update
    # If A Button Is Pressed
    if Input.trigger?(Input::A)
      # If Tiles Flashing
      if @seph_encctrl_tilesflashing
        # Unflashes All Map Tiles
        for x in 0...$game_map.width
          for y in 0...$game_map.height
            @tilemap.flash_data[x, y] = 0
          end
        end
        # Turns Flashing Flag Off
        @seph_encctrl_tilesflashing = false
        # Clear Used Colors List
        @flashtile_colors.clear
      # If Tiles Not Flashing
      else
        # Sets Up Colors Array (To Prevent Matching Colors
        @flashtile_colors = []
        # Checks All Events
        for event in $game_map.events.values
          # Flashes All Circular Ranges
          event.seph_circle_enconter_areas.keys.each do |xyr|
            seph_flash_circular_range(xyr)
          end
          # Flashes All Rect Ranges
          event.seph_rect_encounter_areas.keys.each do |rect|
            seph_flash_rect_range(rect)
          end
          # Turns Flashing Flag On
          @seph_encctrl_tilesflashing = true
        end
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Flash Circular Range
  #--------------------------------------------------------------------------
  def seph_flash_circular_range(xyr)
    # Gets Flash Color
    c = get_random_color while c.nil? || @flashtile_colors.include?(c)
    # Gets Circle Parameters
    x, y, r = *xyr
    # Flashes Tiles Within Range
    for i in (x - r)..(x + r)
      sa = (x - i).abs
      x_ = i < x ? x - sa : i == x ? x : x + sa
      y_ = Integer((r ** 2 - sa ** 2) ** 0.5)
      for j in (y - y_)..(y + y_)
        @tilemap.flash_data[i, j] = c
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Flash Rect Range
  #--------------------------------------------------------------------------
  def seph_flash_rect_range(rect)
    # Gets Flash Color
    c = get_random_color while c.nil? || @flashtile_colors.include?(c)
    # Gets Rect Parameters
    for x in 0...rect[2]
      for y in 0...rect[3]
        @tilemap.flash_data[rect[0] + x, rect[1] + y] = c
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Get Random Color
  #--------------------------------------------------------------------------
  def get_random_color
    # Generate Random Colors
    r, g, b = rand(18) * 15, rand(18) * 15, rand(18) * 15
    # Return Hex Format
    return eval "0x#{(r * 100 + g * 10 + b).to_s(16)}"
  end
end

end

#--------------------------------------------------------------------------
# * End SDK Enable Test
#--------------------------------------------------------------------------
end

Fenwick
 
Thanks for all the great ideas, you've all been more than useful.

I'm going to go with Unka Josh's no-fade map transition idea, simply because I understand how to make that one work =P
Fenwick - That's a great script, but I just can't get it to work. Read into it a lot as well, getting a hold of the SDK and the other required script, but I always run into a Syntax error or something when I try using it. Shame really, but since Seph's demo download link isn't working anymore, I don't have a reference for where i'm going wrong. So until i'm better versed in the arts of this program and Ruby scripting i'll stick to Unka Josh's suggestion. Maybe one day the penny will drop and i'll see where I was going wrong!
  :smile:

Thanks again!
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top