#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# Give NPCs Random Positions When Entering a Map
# Author: DiamondandPlatinum3
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# Description:
#
# This script allows you to set certain NPCs to have random positions
# when the game is setting up a map, this allows your NPCs to look somewhat
# less robot like. Whilst this can be done via events, this script also
# checks tile passability, so your NPCs won't end up on a roof if they're
# not supposed to.
#
# Included is an event switch that turns off this feature, the purpose of
# turning off this feature is for cutscenes, wouldn't want a random NPC to
# be in your way now would we?
#
# You may also use Regions to give your NPCs specific tiles they can
# randomise to.
#
#------------------------------------------------------------------------------
# Instructions:
#
# ~ To give an NPC the ability to appear in random locations on the map, all
# you have to do is edit their event name to include either:
# <Random>, <RANDOM>, <random>, <RaNdOm>
#
#
# ~ If you wish to give the NPC a specific Region ID it can only randomise to
# you must add another tag just after the above with:
# <Region: ?> <= For Singular Regions
# <Region: [?, ?, ?, etc]> <= For Multiple Regions
# Replacing the Question Mark(s) with a Valid Region ID(s).
#
#
# ~ Similarly you can also use the value of a variable to determine the
# RegionID if you'd prefer. To do so you must enter:
# <Region: \v[?]> <= For Singular Variables Containing a Region ID
# <Region: \v[?, ?, ?, etc]> <= For Multiple Variables Containing a Region ID
# Replacing the Question Mark(s) with a Variable ID(s).
#
#
# ~ You can also a Tag to block any region(s).
# This will alow the event to randomise to any tile that does NOT
# contain this Region ID. To do so you must enter:
# <RegionBlock: ?> <= For Singular Regions to Block
# <RegionBlock: [?, ?, ?, etc]> <= For Multiple Regions to Block
#
# You can also use variables with the RegionBlock the same as above:
# <RegionBlock: \v[?]> <= For Singular Variables Containing a Region ID
# <RegionBlock: \v[?, ?, ?, etc]> <= For Multiple Variables Containing a Region ID
#
#
# ~ You may also use the first comment in their event list to do the same
# as above if you do not wish to edit the name.
#
#
#
# ~ Example ScreenShots:
# NameTag: [url]http://i.imgur.com/gIGpPaz.png[/url]
# CommentTag: [url]http://i.imgur.com/GIxiT08.png[/url]
#
# NameTag with Region: [url]http://i.imgur.com/HRMpiNx.png[/url]
# CommentTag with Region: [url]http://i.imgur.com/D2bz6Ed.png[/url]
#
# NameTag with Region Variable: [url]http://i.imgur.com/3Y4JKT0.png[/url]
# CommentTag with Region Variable: [url]http://i.imgur.com/kIjN9qb.png[/url]
#
# Multiple Regions: [url]http://i.imgur.com/mvBykmp.png[/url]
# Multiple Region Variables: [url]http://i.imgur.com/5yru4Xc.png[/url]
#
# Block Regions: [url]http://i.imgur.com/bN2zVY3.png[/url]
#
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#==============================================================================
# ** Game_Map
#------------------------------------------------------------------------------
# This class handles maps. It includes scrolling and passage determination
# functions. The instance of this class is referenced by $game_map.
#==============================================================================
class Game_Map
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * Editable Region
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# Turn This Event Switch Off To Stop Random Positioning, use for cutscenes
TURN_OFF_RANDOM_POSITIONING_EVENT_SWITCH_ID = 10
# The problem with Randomising is that it will not always get you a good
# position every single time, or possibly the next few times. This can cause
# lag if the randomiser keeps picking awkward positions, so here you can set
# the maximum allowable rejections per NPC. Should the Randomiser exceed this
# limit, your NPC will stay in its original position
MAXIMUM_POSITION_REJECTIONS = 50
#--------------------------------------------------------------------------
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * Struct Setup
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
DP3MapRegionStruct = Struct.new(:region_id, :x, :y)
DP3RandomRegionRegex = /<Region:\s?(\[?(?:\d+,?\s?)+\]?)>/im
DP3RandomRegionBlockRegex = /<RegionBlock:\s?(\[?(?:\d+,?\s?)+\]?)>/im
DP3RandomRegionVariableRegex = /<Region:\s?\\v(\[(?:\s?\d+,?\s?)+\])>/im
DP3RandomRegionBlockVariableRegex = /<RegionBlock:\s?\\v(\[(?:\s?\d+,?\s?)+\])>/im
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# *= Alias Listings
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
alias_method(:dp3_gamemap_setup_f98ha, :setup )
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * Aliased Method: Setup
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def setup( *args )
# Call Original Method
dp3_gamemap_setup_f98ha( *args )
# Call New Method
dp3_randomise_event_positions() if $game_switches[TURN_OFF_RANDOM_POSITIONING_EVENT_SWITCH_ID]
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * New Method: Randomise Event Positions
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def dp3_randomise_event_positions()
tag = /<RANDOM>/im
@events.each_key do |key|
event = @events[key]
if dp3_get_event_first_comment(event) =~ tag || event.dp3_get_event_name() =~ tag
dp3_setupregionshash()
reg_id = dp3_check_event_for_region_tag(event)
if reg_id[0]
dp3_randomise_event_position_based_on_blocked_regions( event, reg_id[1] )
elsif reg_id[1] > 0
dp3_randomise_event_position_based_on_region( event, reg_id[1] )
else
dp3_randomise_event_position_based_on_passability( event )
end
end
end
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * New Method: Setup Regions Hash
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def dp3_setupregionshash()
return if !@dp3_regions_hash.nil? && @dp3_regions_hash[:map_id] == @map_id # No need to do it again if we've already got it
dp3_create_regions_hash()
dp3_populate_regions_hash()
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * New Method: Create Regions Hash
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def dp3_create_regions_hash()
@dp3_regions_hash.clear if @dp3_regions_hash
@dp3_regions_hash = {}
@dp3_regions_hash[:map_id] = @map_id
for i in 1..63
@dp3_regions_hash[i] = []
end
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * New Method: Populate Regions Hash
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def dp3_populate_regions_hash()
for x in 0..(self.width)
for y in 0..(self.height)
reg_id = region_id( x, y )
next if reg_id == 0
@dp3_regions_hash[reg_id].push(DP3MapRegionStruct.new( reg_id, x, y ))
end
end
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * New Method: Get Active Regions
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def dp3_get_active_regions()
active_regions = Array.new()
@dp3_regions_hash.each_key do |reg_id|
if @dp3_regions_hash[reg_id].is_a?(Array)
active_regions.push(reg_id) unless @dp3_regions_hash[reg_id].empty?
end
end
return active_regions
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * New Method: Get Event All Comments
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def dp3_get_event_first_comment( event )
comment = ""
unless event.list.nil?
if event.list[0].code == 108
event.list.each do |command|
break if command.code != 108 && command.code != 408
comment += command.parameters[0]
end
end
end
return comment
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * New Method: Check Event For "Region Tag
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def dp3_check_event_for_region_tag( event )
tag = /<Region/im
comment_tag = dp3_get_event_first_comment(event)
match_tag = ""
match_tag = comment_tag if comment_tag =~ tag
match_tag = event.dp3_get_event_name() if match_tag == "" && event.dp3_get_event_name() =~ tag
if match_tag != ""
methods = dp3_get_region_regex_checking_methods()
methods.each do |method|
result = method.call(match_tag)
return result if result[1].is_a?(Array) || result[1] != 0
end
end
return [false, 0]
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * New Method: Get Region Regex Checking Methods
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def dp3_get_region_regex_checking_methods()
return [ method(:dp3_check_region_regex),
method(:dp3_check_regionvariable_regex),
method(:dp3_check_regionblock_regex),
method(:dp3_check_regionblockvariable_regex), ]
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * New Method: Check Region Regex
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def dp3_check_region_regex(tag)
if tag =~ DP3RandomRegionRegex
region_ids = $1.scan(/\d+/).collect{ |i| i.to_i }
return [false, region_ids[rand(region_ids.size)]]
end
return [false, 0]
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * New Method: Check Region Variable Regex
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def dp3_check_regionvariable_regex(tag)
if tag =~ DP3RandomRegionVariableRegex
region_ids = $1.scan(/\d+/).collect{ |i| i.to_i }
return [false, $game_variables[region_ids[rand(region_ids.size)]]]
end
return [false, 0]
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * New Method: Check Region Block Regex
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def dp3_check_regionblock_regex(tag)
if tag =~ DP3RandomRegionBlockRegex
block_region_ids = $1.scan(/\d+/).collect{ |i| i.to_i }
return [true, block_region_ids]
end
return [false, 0]
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * New Method: Check Region Block Variable Regex
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def dp3_check_regionblockvariable_regex(tag)
if tag =~ DP3RandomRegionBlockVariableRegex
block_region_ids = $1.scan(/\d+/).collect{ |i| $game_variables[i.to_i] }
return [true, block_region_ids]
end
return [false, 0]
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * New Method: Standable Position?
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def dp3_standableposition?( event, x, y )
return false unless self.valid?(x, y)
return true if event.through
return self.airship_land_ok?( x, y ) && !event.collide_with_characters?(x, y)
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * New Method: Randomise Event Position Based on Passability
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def dp3_randomise_event_position_based_on_passability( event )
x = y = -1;
rejection_count = 0
while (!dp3_standableposition?( event, x, y )) do
return if rejection_count == MAXIMUM_POSITION_REJECTIONS
rejection_count += 1
x = rand(self.width)
y = rand(self.height)
end
event.moveto( x, y )
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * New Method: Randomise Event Position Based on Region
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def dp3_randomise_event_position_based_on_region( event, reg_id )
return if @dp3_regions_hash[reg_id].empty?
x = y = -1;
rejection_count = 0
while (!dp3_standableposition?( event, x, y )) do
return if rejection_count == MAXIMUM_POSITION_REJECTIONS
rejection_count += 1
map_pos = @dp3_regions_hash[reg_id][rand(@dp3_regions_hash[reg_id].size)]
x = map_pos.x
y = map_pos.y
end
event.moveto( x, y )
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * New Method: Randomise Event Position Based on Blocked Regions
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def dp3_randomise_event_position_based_on_blocked_regions( event, blocked_regions )
x = y = -1;
current_region_id = 0
rejection_count = 0
while (!dp3_standableposition?( event, x, y ) || blocked_regions.include?(current_region_id)) do
return if rejection_count == MAXIMUM_POSITION_REJECTIONS
rejection_count += 1
x = rand(self.width)
y = rand(self.height)
current_region_id = region_id(x, y)
end
event.moveto( x, y )
end
end
#==============================================================================
# ** Game_Event
#------------------------------------------------------------------------------
# This class handles events. Functions include event page switching via
# condition determinants and running parallel process events. Used within the
# Game_Map class.
#==============================================================================
class Game_Event < Game_Character
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# * New Method: Get Original Event Name
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def dp3_get_event_name()
return @event.name
end
end