[RESOLVED] View Range Script Wierdness...

Started by samsonite789, November 01, 2009, 10:12:49 pm

Previous topic - Next topic

samsonite789

November 01, 2009, 10:12:49 pm Last Edit: November 02, 2009, 11:43:23 am by samsonite789
I'm using NearFantastica's View Range script for enemy detection purposes and I've run into a strange little bug.  I've pored over it for a long time but I can't figure it out.  I was hoping someone might be able to help me with it.

In case anyone isn't familiar with the script, one of the usages of it is Enemies_View, which is a script call which detects if a player is within the VIEW range of an enemy.  Essentially, it draws a semi-circle in the direction the enemy is looking and if the player is in that semi-circle, it flips a self-switch or a switch.  Additionally, this function can determine whether or not the player is behind an impassable tile (which an enemy couldn't see through) and if so, does not detect the player.  This is done by setting the "block" parameter to "true".

Here is the script call:  
$view_range.enemies_view(ev_id, v_range, sw_id, s_sw_id, block)

So, when I use this script call, I notice something screwed up:  the enemy event will detect the player almost all the time, but strangely enough, it will NOT detect the player if the player is in a straight line from the enemy.  In other words, if the player is directly to the left, right, top, or bottom of the event, the player will not be detected even if the player is within the specified view range.  However, if the player steps OUT of the straight line from the event's view, the event will suddenly detect the player.  In both cases, there are no actual impassable tiles in the way of the enemy's view range, but this bug only occurs when the impassability parameter (block) is set to true.  I need this set to true, however, for the whole thing to work.

I realize this is hard to explain with just words, so I took a few screenshots to illustrate the problem:

For the enemy event, I have the following script call:
$view_range.enemies_view(12, 5, nil, "A", true)

When I'm well within the range and in a straight line from the event, nothing happens...


But when I step OUT of that line, all of a sudden it works:


As I said before, this only happens when the passability check is turned to true.  So, I looked at the method in the View Range script involving that check, and I have no idea what the problem might be.  Here's the method:
Spoiler: ShowHide
def vr_in_range?(element, object, range, pass_block = false)
   # Obtain Range
   x = (element.x - object.x) * (element.x - object.x)
   y = (element.y - object.y) * (element.y - object.y)
   # Obtain values to loop and counter value
   x_loops = x_count = (object.x - element.x).abs
   y_loops = y_count = (object.y - element.y).abs
   # Reset player's check location
   check_player_x = -1
   check_player_y = -1
   r = x + y
   if r <= (range * range)
     # Set the return flag
     rflag = true
     # If tiles can block view
     if pass_block
       # Horizontal Checks
       x_loops.times {
         x_playerchk = ((object.x - element.x) >= 0 ? element.x + x_count : element.x - x_count)
         x_passingchk = ((object.x - element.x) >= 0 ? (element.x + x_count)-1 : (element.x - x_count)+1)
         unless $game_player.passable?(x_passingchk, element.y , element.direction)
           # Change flag
           rflag = false
           # Set player check location
           check_player_x = object.x if x_playerchk == object.x
         end
         # Decrease counter
         x_count -= 1
       }      
       # Vertical Checks
       y_loops.times {
         y_playerchk = ((object.y - element.y) >= 0 ? element.y + y_count : element.y - y_count)
         y_passingchk = ((object.y - element.y) >= 0 ? (element.y + y_count)-1 : (element.y - y_count)+1)
         unless $game_player.passable?(element.x, y_passingchk , element.direction)
           # Change flag
           rflag = false
           # Set player check location
           check_player_y = object.y if y_playerchk == object.y
         end
         # Decrease counter
         y_count -= 1
       }                  
     end
     # Re-enable flag based on player position
     if check_player_x == object.x && check_player_y == object.y
       #print "uyui"
       r_flag = true
     end
     # Return system-determined flag      
     return rflag
   else
     # Return default flag
     return false
   end
 end


And here is the entire script for reference:
Spoiler: ShowHide
#==============================================================================
#  ** View Range Script v3 gamma
#------------------------------------------------------------------------------
#  Original version by:     Near Fantastica
#  Original date:           June 14, 2005
#
#  Modifications/edit by:   DerVVulfman
#  Modification date:       November 25, 2007
#
#==============================================================================
#
#  INTRODUCTION:
#  The original v3 View Range system allowed a more detailed detection between
#  player and event ranges than version 2. Adding the ability to use events to
#  detect the player  as well as enemy events  facing the player  added to its
#  usefullness.
#
#  Unfortunately, when version 2 was released (at least where I found it), the
#  instructions for the system's use  were only partially correct  and did not
#  inform the users that the system no longer used  the event's self-switches.
#  The newer version now used the RMXP Database's regular switches instead.
#
#  Though it was not my intention  to tangle with  the View Range system, luck
#  (and a few friends) nudged me into experimenting with this system.  As such
#  I have not only combined the use  of SelfSwitches 'AND' regular switches in
#  to the system, I have also added a couple more features for use.
#
#  The system now includes a routine  to check the range between two different
#  events which may be useful for 'collision detection' purposes. Also, I have
#  also altered the Event_Sound routine  so the user can set a lower volume or
#  pitch setting for targettable events.
#
#==============================================================================
#
#  THE FUNCTIONS:
#  
#  There are now four routines that you can use with this system  (or 5 if you
#  script a routine to use the vr_in_range? method). The four are listed below
#  detailing usage and proper syntax for you.
#
#--------------------------------------------------------------------------
#
#     Event View
#     ==========
#     This function checks to see if the player is within the range of an event
#     and turns on the properly designated switch.
#
#     Syntax:
#     $view_range.event_view(ev_id, v_range, sw_id, s_sw_id, block)
#
#     ev_id     - (Event ID)      
#                  This is the ID number of the event that the radius/range is
#                  based on.   If the player comes within the range of  'this'
#                  event, the system is triggered.
#
#     ev2_id    - (Event2 ID)
#                  This is the ID number of the event
#
#     v_range   - (View Range)    
#                  This is the range(in tiles) in which to perform the check.
#
#     sw_id     - (Switch ID) - Defaulted to 'nil'    
#                  The RMXP switch number to turn ON.  By default, this is set
#                  to 'nil'.  You must enter a valid Switch number to use.
#
#     s_sw_id   - (Self Switch ID) - Defaulted to 'nil'
#                  The 'Self-Switch' for the event to turn ON.   Proper values  
#                  to set are "A", "B", "C", or "D".   By default, this is set
#                  to 'nil'.  You must enter a valid Self-Switch to use.
#
#     block     - (Blocked by Tiles) - Defaulted to 'false'
#                  This is a 'true/false' switch  that determines  if the view
#                  range system is unable to see around impassable tiles.   By
#                  default,  this is set to 'false'.   If it is set to 'true',
#                  the view range system will not detect  the player  if it is
#                  behind an impassable tile or tiles.
#
#--------------------------------------------------------------------------
#
#     Event to Event View
#     ===================
#     This function checks to see if a single event is within the range of
#     another event and turns on the properly designated switch.  This new
#     routine may be useful for collision detection between events.
#
#     Syntax:
#     $view_range.event2event_view(ev_id, ev2_id, v_range, sw_id, s_sw_id, block)
#
#     ev_id     - (Event ID)      
#                  This is the ID number of the event that the radius/range is
#                  based on.   If the target event moves or appears within the
#                  range of 'this' event, the system is triggered.
#
#     ev2_id    - (Event2 ID)
#                  This is the  ID number  of the target event which to check.
#                  If  this  event finds  itself  within  range of  the  other
#                  event's area of effect, the system is triggered.
#
#     v_range   - (View Range)    
#                  This is the range(in tiles) in which to perform the check.
#
#     sw_id     - (Switch ID) - Defaulted to 'nil'    
#                  The RMXP switch number to turn ON.  By default, this is set
#                  to 'nil'.  You must enter a valid Switch number to use.
#
#     s_sw_id   - (Self Switch ID) - Defaulted to 'nil'
#                  The 'Self-Switch' for the event to turn ON.   Proper values  
#                  to set are "A", "B", "C", or "D".   By default, this is set
#                  to 'nil'.  You must enter a valid Self-Switch to use.
#
#     block     - (Blocked by Tiles) - Defaulted to 'false'
#                  This is a 'true/false' switch  that determines  if the view
#                  range system is unable to see around impassable tiles.   By
#                  default,  this is set to 'false'.   If it is set to 'true',
#                  the view range system  will not detect  the target event if
#                  it is behind an impassable tile or tiles.
#
#
#--------------------------------------------------------------------------
#
#     Enemies View
#     ============
#     This function checks to see if the player is within range of an event
#     that is facing him/her, and turns on the properly designated switch.
#
#     Syntax:
#     $view_range.enemies_view(ev_id, v_range, sw_id, s_sw_id, block)
#
#     ev_id     - (Event ID)      
#                  This is the ID number of the event that the radius/range is
#                  based on.   If the player is in front of 'this' event and
#                  within the set range, the system is triggered.
#
#     v_range   - (View Range)    
#                  This is the range(in tiles) in which to perform the check.
#
#     sw_id     - (Switch ID) - Defaulted to 'nil'    
#                  The RMXP switch number to turn ON.  By default, this is set
#                  to 'nil'.  You must enter a valid Switch number to use.
#
#     s_sw_id   - (Self Switch ID) - Defaulted to 'nil'
#                  The 'Self-Switch' for the event to turn ON.   Proper values  
#                  to set are "A", "B", "C", or "D".   By default, this is set
#                  to 'nil'.  You must enter a valid Self-Switch to use.
#
#     block     - (Blocked by Tiles) - Defaulted to 'false'
#                  This is a 'true/false' switch  that determines  if the view
#                  range system is unable to see around impassable tiles.   By
#                  default,  this is set to 'false'.   If it is set to 'true',
#                  the view range system will not detect  the player  if it is
#                  behind an impassable tile or tiles.
#
#--------------------------------------------------------------------------
#
#     Event Sound
#     ===========
#     This function checks  to see if the player  is within range  of an event
#     that is linked to a sound effect. The closer the player is to the event,
#     the louder the effect is played.
#
#     The maximum sound range  of this routine is eight (8) tiles.   It is not
#     recommended to overlap these events as this can cause massive lag on the
#     game/project as the system will attempt  to cycle through the overlapped
#     calls. Also note that this routine will override the map's default back-
#     ground sound effect.
#
#     Syntax:
#     $view_range.event_sound(ev_id, bgs_name, bgs_vol = 100, bgs_pitch = 100)
#
#     ev_id     - (Event ID)      
#                  This is the ID number of the event that the radius/range is
#                  based on.   If the player is in front of 'this' event and
#                  within the set range, the system is triggered.
#
#     bgs_name  - (Background Effect's Name)
#                  This is the filename of the background effect.  This effect
#                  is stored in the Audio\BGS folder.
#
#     bgs_vol   - (Background Effect's Volume)
#                  This is the volume setting of the background effect within
#                  a range of 1 to 100, with 100 being the loudest.
#
#     bgs_pitch - (Background Effect's Pitch)
#                  This is the pitch setting of the background effect within a
#                  range of 50 to 150, with 150 being the highest setting.
#
#==============================================================================
#
#  HOW IT DETERMINES THE RANGE:
#
#  The Range system works  by searching the area  of a circle for the player's
#  'x' and 'y' position.   The view range  is set in each event and is the ra-
#  dius of a circle.
#
#  The equation used is: radius^2 = (Px-Ex)^2 + (Py-Ey)^2
#  Where P = player, and E = event
#
#  If the radius  is less than or equal to the view range,  then the player is
#  inside the circular area.
#
#==============================================================================

 

#==============================================================================
# ** View Range
#------------------------------------------------------------------------------
#  This class is Near Fantastica's which checks distances between events.
#==============================================================================

class View_Range
 #--------------------------------------------------------------------------
 # * Object Initialization
 #--------------------------------------------------------------------------
 def initialize
   @playing_bgs = []
   @bgs = BGS.new
   @event_local_switch = ""
 end
 #--------------------------------------------------------------------------
 # * In Range?
 #     element     : element
 #     object      : object
 #     range       : range in tiles
 #     pass_block  : if terrain tiles can block view
 #--------------------------------------------------------------------------
 def vr_in_range?(element, object, range, pass_block = false)
   # Obtain Range
   x = (element.x - object.x) * (element.x - object.x)
   y = (element.y - object.y) * (element.y - object.y)
   # Obtain values to loop and counter value
   x_loops = x_count = (object.x - element.x).abs
   y_loops = y_count = (object.y - element.y).abs
   # Reset player's check location
   check_player_x = -1
   check_player_y = -1
   r = x + y
   if r <= (range * range)
     # Set the return flag
     rflag = true
     # If tiles can block view
     if pass_block
       # Horizontal Checks
       x_loops.times {
         x_playerchk = ((object.x - element.x) >= 0 ? element.x + x_count : element.x - x_count)
         x_passingchk = ((object.x - element.x) >= 0 ? (element.x + x_count)-1 : (element.x - x_count)+1)
         unless $game_player.passable?(x_passingchk, element.y , element.direction)
           # Change flag
           rflag = false
           # Set player check location
           check_player_x = object.x if x_playerchk == object.x
         end
         # Decrease counter
         x_count -= 1
       }      
       # Vertical Checks
       y_loops.times {
         y_playerchk = ((object.y - element.y) >= 0 ? element.y + y_count : element.y - y_count)
         y_passingchk = ((object.y - element.y) >= 0 ? (element.y + y_count)-1 : (element.y - y_count)+1)
         unless $game_player.passable?(element.x, y_passingchk , element.direction)
           # Change flag
           rflag = false
           # Set player check location
           check_player_y = object.y if y_playerchk == object.y
         end
         # Decrease counter
         y_count -= 1
       }                  
     end
     # Re-enable flag based on player position
     if check_player_x == object.x && check_player_y == object.y
       #print "uyui"
       r_flag = true
     end
     # Return system-determined flag      
     return rflag
   else
     # Return default flag
     return false
   end
 end
 #--------------------------------------------------------------------------
 # * View Switch
 #     ev_id       : event ID
 #     sw_id       : switch ID
 #     s_sw_id     : event's self switch ID
 #--------------------------------------------------------------------------  
 def view_switch(ev_id, sw_id = nil, s_sw_id = nil)
   $game_switches[sw_id] = true if sw_id != nil
   if s_sw_id != nil
     key=[$game_map.map_id, ev_id, s_sw_id]
     $game_self_switches[key] = true          
   end
   $game_map.need_refresh = true    
 end
 #--------------------------------------------------------------------------
 # * Event Sound
 #     ev_id       : Event ID
 #     bgs_name    : filename of background sound effect
 #     bgs_vol     : background effect's volume
 #     bgs_pitch   : background effect's pitch
 #--------------------------------------------------------------------------
 def event_sound(ev_id, bgs_name, bgs_vol = 100, bgs_pitch = 100)
   event = $game_map.events[ev_id]
   @bgs.name   = bgs_name
   @bgs.pitch  = bgs_pitch
   radius = ($game_player.x-event.x) * ($game_player.x-event.x) +
            ($game_player.y-event.y) * ($game_player.y-event.y)
   if radius > 64
     if @playing_bgs[event.id] !=  nil
        @playing_bgs[event.id] =   nil
        $game_system.bgs_fade(1)
       return
     end
   elsif radius <= 64 and radius > 49
     if @playing_bgs[event.id] == nil
       @bgs.volume = (bgs_vol * 30)/100
       @playing_bgs[event.id] = @bgs
       $game_system.bgs_play(@bgs)
       return
     end
     @bgs.volume = (bgs_vol * 30)/100
     if @bgs.volume != @playing_bgs[event.id].volume or
         @bgs.name != @playing_bgs[event.id].name
       @playing_bgs[event.id] = @bgs
       $game_system.bgs_play(@bgs)
       return
     end
   elsif radius <= 49 and radius > 36
     @bgs.volume = (bgs_vol * 40)/100
     @playing_bgs[event.id] = @bgs
     $game_system.bgs_play(@bgs)
     return
   elsif radius <= 36 and radius > 25
     @bgs.volume = (bgs_vol * 50)/100
     @playing_bgs[event.id] = @bgs
     $game_system.bgs_play(@bgs)
     return
   elsif radius <= 25 and radius > 16
     @bgs.volume = (bgs_vol * 60)/100
     @playing_bgs[event.id] = @bgs
     $game_system.bgs_play(@bgs)
     return
   elsif radius <= 16 and radius > 9
     @bgs.volume = (bgs_vol * 70)/100
     @playing_bgs[event.id] = @bgs
     $game_system.bgs_play(@bgs)
     return
   elsif radius <= 9 and radius > 4
     @bgs.volume = (bgs_vol * 80)/100
     @playing_bgs[event.id] = @bgs
     $game_system.bgs_play(@bgs)
     return
   elsif radius <= 4 and radius > 1
     @bgs.volume = (bgs_vol * 90)/100
     @playing_bgs[event.id] = @bgs
     $game_system.bgs_play(@bgs)
     return
   elsif radius = 1
     @bgs.volume = (bgs_vol * 100)/100
     @playing_bgs[event.id] = @bgs
     $game_system.bgs_play(@bgs)
     return
   end
 end
 #--------------------------------------------------------------------------
 # * Event View
 #     ev_id       : event ID
 #     v_range     : range in tiles
 #     sw_id       : switch ID
 #     s_sw_id     : event's self switch ID
 #     block       : View block (true/false)
 #--------------------------------------------------------------------------
 def event_view(ev_id, v_range, sw_id = nil, s_sw_id = nil, block = false)
   event = $game_map.events[ev_id]
   if vr_in_range?(event, $game_player, v_range, block)
     view_switch(ev_id, sw_id, s_sw_id)
   end
 end
 #--------------------------------------------------------------------------
 # * Event to Event View
 #     ev_id       : event ID
 #     ev2_id      : event ID of target
 #     v_range     : range in tiles
 #     sw_id       : switch ID
 #     s_sw_id     : event's self switch ID
 #     block       : View block (true/false)  
 #--------------------------------------------------------------------------
 def event2event_view(ev_id, ev2_id, v_range, sw_id = nil, s_sw_id = nil, block = false)
   event   = $game_map.events[ev_id]
   target  = $game_map.events[ev2_id]
   if vr_in_range?(event, target, v_range, block)
     view_switch(ev_id, sw_id, s_sw_id)
   end
 end
 #--------------------------------------------------------------------------
 # * Enemies View
 #     ev_id       : event ID
 #     v_range     : range in tiles
 #     sw_id       : switch ID
 #     s_sw_id     : event's self switch ID
 #     block       : View block (true/false)  
 #--------------------------------------------------------------------------
 def enemies_view(ev_id, v_range, sw_id= nil, s_sw_id = nil, block = false)
   event = $game_map.events[ev_id]
   if event.direction == 2 &&  $game_player.y >= event.y
     if vr_in_range?(event, $game_player, v_range, block)
       view_switch(ev_id, sw_id, s_sw_id)
     end
   end
   if event.direction == 4 &&  $game_player.x <= event.x
     if vr_in_range?(event, $game_player, v_range, block)
       view_switch(ev_id, sw_id, s_sw_id)
     end
   end
   if event.direction == 6 &&  $game_player.x >= event.x
     if vr_in_range?(event, $game_player, v_range, block)
       view_switch(ev_id, sw_id, s_sw_id)
     end
   end
   if event.direction == 8 &&  $game_player.y <= event.y
     if vr_in_range?(event, $game_player, v_range, block)
       view_switch(ev_id, sw_id, s_sw_id)
     end
   end
 end
end



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

class Scene_Title
 #--------------------------------------------------------------------------
 # * Frame Update
 #--------------------------------------------------------------------------
 alias vr_scene_title_update update
 def update
   $view_range = View_Range.new
   vr_scene_title_update
 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 :playing_bgs
end
 


#==============================================================================
# ** Background Sounds
#------------------------------------------------------------------------------
#  Data class for Background SE files.
#==============================================================================
class BGS
 #--------------------------------------------------------------------------
 # * Public Instance Variables
 #--------------------------------------------------------------------------
 attr_accessor :name
 attr_accessor :volume
 attr_accessor :pitch
 #--------------------------------------------------------------------------
 # * Object Initialization
 #--------------------------------------------------------------------------
 def initialize
   @name
   @volume
   @pitch
 end
end


I hope that clarifies that clarifies the problem as much as possible.  Anyone have any idea what's going on?

EDIT:  Solved by getting the newest version...doh...