Advertisement
diamondandplatinum3

Give NPCs Random Positions When Entering a Map ~ RGSS3

Dec 10th, 2012
2,138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 14.97 KB | None | 0 0
  1. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  2. #             Give NPCs Random Positions When Entering a Map
  3. #             Author: DiamondandPlatinum3
  4. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5. #  Description:
  6. #
  7. #    This script allows you to set certain NPCs to have random positions
  8. #    when the game is setting up a map, this allows your NPCs to look somewhat
  9. #    less robot like. Whilst this can be done via events, this script also
  10. #    checks tile passability, so your NPCs won't end up on a roof if they're
  11. #    not supposed to.
  12. #
  13. #    Included is an event switch that turns off this feature, the purpose of
  14. #    turning off this feature is for cutscenes, wouldn't want a random NPC to
  15. #    be in your way now would we?
  16. #
  17. #    You may also use Regions to give your NPCs specific tiles they can
  18. #    randomise to.
  19. #
  20. #------------------------------------------------------------------------------
  21. #  Instructions:
  22. #
  23. #  ~  To give an NPC the ability to appear in random locations on the map, all
  24. #     you have to do is edit their event name to include either:
  25. #     <Random>, <RANDOM>, <random>, <RaNdOm>
  26. #
  27. #
  28. #  ~  If you wish to give the NPC a specific Region ID it can only randomise to
  29. #     you must add another tag just after the above with:
  30. #         <Region: ?>                     <= For Singular Regions
  31. #         <Region: [?, ?, ?, etc]>        <= For Multiple Regions
  32. #     Replacing the Question Mark(s) with a Valid Region ID(s).
  33. #
  34. #
  35. #  ~  Similarly you can also use the value of a variable to determine the
  36. #     RegionID if you'd prefer. To do so you must enter:
  37. #         <Region: \v[?]>                 <= For Singular Variables Containing a Region ID
  38. #         <Region: \v[?, ?, ?, etc]>      <= For Multiple Variables Containing a Region ID
  39. #     Replacing the Question Mark(s) with a Variable ID(s).
  40. #
  41. #
  42. #  ~  You can also a Tag to block any region(s).
  43. #       This will alow the event to randomise to any tile that does NOT
  44. #       contain this Region ID. To do so you must enter:
  45. #         <RegionBlock: ?>                <= For Singular Regions to Block
  46. #         <RegionBlock: [?, ?, ?, etc]>   <= For Multiple Regions to Block
  47. #
  48. #       You can also use variables with the RegionBlock the same as above:
  49. #         <RegionBlock: \v[?]>            <= For Singular Variables Containing a Region ID
  50. #         <RegionBlock: \v[?, ?, ?, etc]> <= For Multiple Variables Containing a Region ID
  51. #
  52. #
  53. #  ~  You may also use the first comment in their event list to do the same
  54. #     as above if you do not wish to edit the name.
  55. #
  56. #
  57. #
  58. #  ~  Example ScreenShots:
  59. #       NameTag:     http://i.imgur.com/gIGpPaz.png
  60. #       CommentTag:  http://i.imgur.com/GIxiT08.png
  61. #
  62. #       NameTag with Region:      http://i.imgur.com/HRMpiNx.png
  63. #       CommentTag with Region:   http://i.imgur.com/D2bz6Ed.png
  64. #
  65. #       NameTag with Region Variable:     http://i.imgur.com/3Y4JKT0.png
  66. #       CommentTag with Region Variable:  http://i.imgur.com/kIjN9qb.png
  67. #
  68. #       Multiple Regions:             http://i.imgur.com/mvBykmp.png
  69. #       Multiple Region Variables:    http://i.imgur.com/5yru4Xc.png
  70. #
  71. #       Block Regions:    http://i.imgur.com/bN2zVY3.png
  72. #
  73. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  74.  
  75.  
  76.  
  77. #==============================================================================
  78. # ** Game_Map
  79. #------------------------------------------------------------------------------
  80. #  This class handles maps. It includes scrolling and passage determination
  81. # functions. The instance of this class is referenced by $game_map.
  82. #==============================================================================
  83.  
  84. class Game_Map
  85.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  86.   # * Editable Region
  87.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  88.  
  89.   # Turn This Event Switch On To Stop Random Positioning, use for cutscenes
  90.   TURN_OFF_RANDOM_POSITIONING_EVENT_SWITCH_ID = 10
  91.  
  92.   # The problem with Randomising is that it will not always get you a good
  93.   # position every single time, or possibly the next few times. This can cause
  94.   # lag if the randomiser keeps picking awkward positions, so here you can set
  95.   # the maximum allowable rejections per NPC. Should the Randomiser exceed this
  96.   # limit, your NPC will stay in its original position
  97.   MAXIMUM_POSITION_REJECTIONS = 50
  98.   #--------------------------------------------------------------------------
  99.  
  100.  
  101.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  102.   # * Struct Setup
  103.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  104.   DP3MapRegionStruct                  = Struct.new(:region_id, :x, :y)
  105.   DP3RandomRegionRegex                = /<Region:\s?(\[?(?:\d+,?\s?)+\]?)>/im
  106.   DP3RandomRegionBlockRegex           = /<RegionBlock:\s?(\[?(?:\d+,?\s?)+\]?)>/im
  107.   DP3RandomRegionVariableRegex        = /<Region:\s?\\v(\[(?:\s?\d+,?\s?)+\])>/im
  108.   DP3RandomRegionBlockVariableRegex   = /<RegionBlock:\s?\\v(\[(?:\s?\d+,?\s?)+\])>/im
  109.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  110.   # *= Alias Listings
  111.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  112.   alias_method(:dp3_gamemap_setup_f98ha,           :setup )
  113.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  114.   # * Aliased Method: Setup
  115.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  116.   def setup( *args )
  117.     # Call Original Method
  118.     dp3_gamemap_setup_f98ha( *args )
  119.    
  120.     # Call New Method
  121.     dp3_randomise_event_positions() if !$game_switches[TURN_OFF_RANDOM_POSITIONING_EVENT_SWITCH_ID]
  122.   end
  123.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  124.   # * New Method:   Randomise Event Positions
  125.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  126.   def dp3_randomise_event_positions()  
  127.     tag = /<RANDOM>/im
  128.     @events.each_key do |key|
  129.       event = @events[key]
  130.       if dp3_get_event_first_comment(event) =~ tag || event.dp3_get_event_name() =~ tag
  131.         dp3_setupregionshash()
  132.         reg_id = dp3_check_event_for_region_tag(event)
  133.         if reg_id[0]
  134.           dp3_randomise_event_position_based_on_blocked_regions( event, reg_id[1] )
  135.         elsif reg_id[1] > 0
  136.           dp3_randomise_event_position_based_on_region( event, reg_id[1] )
  137.         else
  138.           dp3_randomise_event_position_based_on_passability( event )
  139.         end
  140.       end  
  141.     end  
  142.   end
  143.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  144.   # * New Method:   Setup Regions Hash
  145.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  146.   def dp3_setupregionshash()
  147.     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
  148.     dp3_create_regions_hash()
  149.     dp3_populate_regions_hash()
  150.   end
  151.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  152.   # * New Method:   Create Regions Hash
  153.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  154.   def dp3_create_regions_hash()
  155.     @dp3_regions_hash.clear if @dp3_regions_hash
  156.     @dp3_regions_hash = {}
  157.     @dp3_regions_hash[:map_id] = @map_id
  158.     for i in 1..63
  159.       @dp3_regions_hash[i] = []
  160.     end
  161.   end
  162.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  163.   # * New Method:   Populate Regions Hash
  164.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  165.   def dp3_populate_regions_hash()
  166.     for x in 0..(self.width)
  167.       for y in 0..(self.height)
  168.         reg_id = region_id( x, y )
  169.         next if reg_id == 0
  170.         @dp3_regions_hash[reg_id].push(DP3MapRegionStruct.new( reg_id, x, y ))
  171.       end
  172.     end
  173.   end
  174.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  175.   # * New Method:   Get Active Regions
  176.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  177.   def dp3_get_active_regions()
  178.     active_regions = Array.new()
  179.     @dp3_regions_hash.each_key do |reg_id|
  180.       if @dp3_regions_hash[reg_id].is_a?(Array)
  181.         active_regions.push(reg_id) unless @dp3_regions_hash[reg_id].empty?
  182.       end
  183.     end
  184.     return active_regions
  185.   end
  186.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  187.   # * New Method: Get Event All Comments
  188.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  189.   def dp3_get_event_first_comment( event )
  190.     comment = ""
  191.     unless event.list.nil?
  192.       if event.list[0].code == 108
  193.         event.list.each do |command|
  194.           break if command.code != 108 && command.code != 408
  195.           comment += command.parameters[0]
  196.         end
  197.       end
  198.     end
  199.     return comment
  200.   end
  201.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  202.   # * New Method:   Check Event For "Region Tag
  203.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  204.   def dp3_check_event_for_region_tag( event )
  205.     tag         = /<Region/im
  206.     comment_tag = dp3_get_event_first_comment(event)
  207.    
  208.     match_tag = ""
  209.     match_tag = comment_tag                 if comment_tag =~ tag
  210.     match_tag = event.dp3_get_event_name()  if match_tag == "" && event.dp3_get_event_name() =~ tag
  211.    
  212.     if match_tag != ""
  213.       methods = dp3_get_region_regex_checking_methods()
  214.       methods.each do |method|
  215.         result = method.call(match_tag)
  216.         return result if result[1].is_a?(Array) || result[1] != 0
  217.       end
  218.     end
  219.     return [false, 0]
  220.   end
  221.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  222.   # * New Method:   Get Region Regex Checking Methods
  223.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  224.   def dp3_get_region_regex_checking_methods()
  225.     return [      method(:dp3_check_region_regex),
  226.                   method(:dp3_check_regionvariable_regex),
  227.                   method(:dp3_check_regionblock_regex),
  228.                   method(:dp3_check_regionblockvariable_regex),     ]
  229.   end
  230.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  231.   # * New Method:   Check Region Regex
  232.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  233.   def dp3_check_region_regex(tag)
  234.     if tag =~ DP3RandomRegionRegex
  235.       region_ids = $1.scan(/\d+/).collect{ |i| i.to_i }
  236.       return [false, region_ids[rand(region_ids.size)]]
  237.     end
  238.     return [false, 0]
  239.   end
  240.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  241.   # * New Method:   Check Region Variable Regex
  242.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  243.   def dp3_check_regionvariable_regex(tag)
  244.     if tag =~ DP3RandomRegionVariableRegex
  245.       region_ids = $1.scan(/\d+/).collect{ |i| i.to_i }
  246.       return [false, $game_variables[region_ids[rand(region_ids.size)]]]
  247.     end
  248.     return [false, 0]
  249.   end
  250.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  251.   # * New Method:   Check Region Block Regex
  252.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  253.   def dp3_check_regionblock_regex(tag)
  254.     if tag =~ DP3RandomRegionBlockRegex
  255.       block_region_ids = $1.scan(/\d+/).collect{ |i| i.to_i }
  256.       return [true, block_region_ids]
  257.     end
  258.     return [false, 0]
  259.   end
  260.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  261.   # * New Method:   Check Region Block Variable Regex
  262.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  263.   def dp3_check_regionblockvariable_regex(tag)
  264.     if tag =~ DP3RandomRegionBlockVariableRegex
  265.       block_region_ids = $1.scan(/\d+/).collect{ |i| $game_variables[i.to_i] }
  266.       return [true, block_region_ids]
  267.     end
  268.     return [false, 0]
  269.   end
  270.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  271.   # * New Method:   Standable Position?
  272.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  273.   def dp3_standableposition?( event, x, y )
  274.     return false unless self.valid?(x, y)
  275.     return true if event.through
  276.     return self.airship_land_ok?( x, y ) && !event.collide_with_characters?(x, y)
  277.   end
  278.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  279.   # * New Method:   Randomise Event Position Based on Passability
  280.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  281.   def dp3_randomise_event_position_based_on_passability( event )
  282.     x = y = -1;
  283.     rejection_count = 0
  284.     while (!dp3_standableposition?( event, x, y )) do
  285.       return if rejection_count == MAXIMUM_POSITION_REJECTIONS
  286.       rejection_count += 1
  287.       x = rand(self.width)
  288.       y = rand(self.height)
  289.     end
  290.     event.moveto( x, y )
  291.   end
  292.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  293.   # * New Method:   Randomise Event Position Based on Region
  294.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  295.   def dp3_randomise_event_position_based_on_region( event, reg_id )
  296.     return if @dp3_regions_hash[reg_id].empty?
  297.    
  298.     x = y = -1;
  299.     rejection_count = 0
  300.     while (!dp3_standableposition?( event, x, y )) do
  301.       return if rejection_count == MAXIMUM_POSITION_REJECTIONS
  302.       rejection_count += 1
  303.       map_pos = @dp3_regions_hash[reg_id][rand(@dp3_regions_hash[reg_id].size)]
  304.       x = map_pos.x
  305.       y = map_pos.y
  306.     end
  307.     event.moveto( x, y )
  308.   end
  309.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  310.   # * New Method:   Randomise Event Position Based on Blocked Regions
  311.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  312.   def dp3_randomise_event_position_based_on_blocked_regions( event, blocked_regions )
  313.     x = y = -1;
  314.     current_region_id = 0
  315.     rejection_count = 0
  316.     while (!dp3_standableposition?( event, x, y ) || blocked_regions.include?(current_region_id)) do
  317.       return if rejection_count == MAXIMUM_POSITION_REJECTIONS
  318.       rejection_count += 1
  319.       x = rand(self.width)
  320.       y = rand(self.height)
  321.       current_region_id = region_id(x, y)
  322.     end
  323.     event.moveto( x, y )
  324.   end
  325. end
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336. #==============================================================================
  337. # ** Game_Event
  338. #------------------------------------------------------------------------------
  339. #  This class handles events. Functions include event page switching via
  340. # condition determinants and running parallel process events. Used within the
  341. # Game_Map class.
  342. #==============================================================================
  343.  
  344. class Game_Event < Game_Character
  345.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  346.   # * New Method: Get Original Event Name
  347.   #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  348.   def dp3_get_event_name()
  349.     return @event.name
  350.   end
  351. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement