RMRK is retiring.
Server is paid up for the rest of 2026, but the forum may go after that. See here for more information. Please archive or save anything you would like to keep before 2027.
Main Menu
  • Welcome to The RPG Maker Resource Kit.

Stealth/Field of Vision Script

Started by Yawgmothsbud, May 13, 2007, 05:25:52 PM

0 Members and 1 Guest are viewing this topic.

Yawgmothsbud

I'm looking for a script on which to base my stealth system; basically it makes it so that if certain NPC's "see" you, an event triggers. I tried to do it with eventing, but that quickly became insanely complicated. I'd heard that such a script might exist, but I have been unable to find one here, or on hbgames.org or creationasylum...anyone got one and feel like sharing, or know where I can find one?

tSwitch


the switch to be activated when the event see the hero. false if none
SWITCH = 35

class Game_Character
  attr_reader :cone
  attr_reader :prev_x
  attr_reader :prev_y
  attr_reader :prev_dir
  attr_accessor :sight

  alias conesys_gamecharacter_initialize initialize
 
  def initialize
    @cone = []
    @sight = 0
    conesys_gamecharacter_initialize
  end
 
  def get_cone(sight = 7)
    cone = []
    @sight = sight
    #This algorithim makes the cone using a 2d array
    case self.direction
    when 2 #down
      #adds the first square
      line = 1
      cone.push([self.x,self.y + 1])
      factor = 1
      #now comes the routine to make the cone
      while line < sight
        line += 1
        cone.push([self.x,self.y + line])
        1.upto(factor) do |a|
          cone.push([self.x - a,self.y + line])
          cone.push([self.x + a,self.y + line])
        end
        factor += 1
      end
    when 4 #left
      line = 1
      cone.push([self.x - 1,self.y])
      factor = 1
      #now comes the routine to make the cone
      while line < sight
        line += 1
        cone.push([self.x - line,self.y])
        1.upto(factor) do |a|
          cone.push([self.x - line,self.y - a])
          cone.push([self.x - line,self.y + a])
        end
        factor += 1
      end
      when 6 #right
      line = 1
      cone.push([self.x + 1,self.y])
      factor = 1
      #now comes the routine to make the cone
      while line < sight
        line += 1
        cone.push([self.x + line,self.y])
        1.upto(factor) do |a|
          cone.push([self.x + line,self.y - a])
          cone.push([self.x + line,self.y + a])
        end
        factor += 1
      end
    when 8 #up
      #adds the first square
      line = 1
      cone.push([self.x,self.y + 1])
      factor = 1
      #now comes the routine to make the cone
      while line < sight
        line += 1
        cone.push([self.x,self.y - line])
        1.upto(factor) do |a|
          cone.push([self.x - a,self.y - line])
          cone.push([self.x + a,self.y - line])
        end
        factor += 1
      end
    end

    cone_obstacles(cone)
  end
  #here any tile that is covered by an obstacle is removed
  #from the cone
  def cone_obstacles(cone)
    for i in 0..cone.length
      if cone[i] != nil
        if !$game_map.passable?(cone[i][0], cone[i][1], 0)
          case self.direction
          when 2 #down
            #the diference between the sight and the obstacle position
            limit = self.sight - (cone[i][1] - self.y)
            position = 1
            #to make the read easier
            index = cone.index([cone[i][0],cone[i][1] + 1])
            cone[index] = nil if index != nil
            factor = 1
            #now comes the routine to remove the bloked tiles
              while position < limit
              position += 1
              index = cone.index([cone[i][0],cone[i][1] + position])
              cone[index] = nil if index != nil
                1.upto(factor) do |a|
                  index = cone.index([cone[i][0] - a,cone[i][1] + position])
                  cone[index] = nil if index != nil
                  index = cone.index([cone[i][0] + a,cone[i][1] + position])
                  cone[index] = nil if index != nil
                end
              factor += 1
            end
          when 4 #left
            #the diference between the sight and the obstacle position
            limit = self.sight - (self.x - cone[i][0])
            position = 1
            #to make the read easier
            index = cone.index([cone[i][0] - 1,cone[i][1]])
            cone[index] = nil if index != nil
            factor = 1
            #now comes the routine to remove the bloked tiles
            while position < limit
              position += 1
              index = cone.index([cone[i][0] - position,cone[i][1]])
              cone[index] = nil if index != nil
                1.upto(factor) do |a|
                  index = cone.index([cone[i][0] - position,cone[i][1] - a])
                  cone[index] = nil if index != nil
                  index = cone.index([cone[i][0] - position,cone[i][1] + a])
                  cone[index] = nil if index != nil
                end
              factor += 1
            end
          when 6 #right
            #the diference between the sight and the obstacle position
            limit = self.sight - (cone[i][0] - self.x)
            position = 1
            #to make the read easier
            index = cone.index([cone[i][0] + 1,cone[i][1]])
            cone[index] = nil if index != nil
            factor = 1
            #now comes the routine to remove the bloked tiles
              while position < limit
              position += 1
              index = cone.index([cone[i][0] + position,cone[i][1]])
              cone[index] = nil if index != nil
                1.upto(factor) do |a|
                  index = cone.index([cone[i][0] + position,cone[i][1] - a])
                  cone[index] = nil if index != nil
                  index = cone.index([cone[i][0] + position,cone[i][1] + a])
                  cone[index] = nil if index != nil
                end
            factor += 1
            end
          when 8 #up
            #the diference between the sight and the obstacle position
            limit = self.sight - (self.y - cone[i][1])
            position = 1
            #to make the read easier
            index = cone.index([cone[i][0],cone[i][1] - 1])
            cone[index] = nil if index != nil
            factor = 1
            #now comes the routine to remove the bloked tiles
              while position < limit
              position += 1
              index = cone.index([cone[i][0],cone[i][1] - position])
              cone[index] = nil if index != nil
                1.upto(factor) do |a|
                  index = cone.index([cone[i][0] - a,cone[i][1] - position])
                  cone[index] = nil if index != nil
                  index = cone.index([cone[i][0] + a,cone[i][1] - position])
                  cone[index] = nil if index != nil
                end
              factor += 1
            end
          end
        end
      end
    end
    #update the variables used to check the need of a refresh
    @prev_x = self.x
    @prev_y = self.y
    @prev_dir = self.direction
    @cone = cone
  end

  def in_cone
    #return false if the event do not have a cone
    if cone != []
      #now it checks if the actual position of the hero is inside the cone
      for i in 0...cone.length
        if cone[i] != nil
          if $game_player.x == cone[i][0] && $game_player.y == cone[i][1]
            $game_switches[SWITCH] = true if SWITCH
            $game_map.need_refresh = true
            move_toward_player
          end
        end
      end
    end
  end
 
  def move_toward_player
    # Get difference in player coordinates
    sx = @x - $game_player.x
    sy = @y - $game_player.y
    # If coordinates are equal
    if sx == 0 and sy == 0
      return
    end
    #Now the 8-direction following
      #diagonal movements
    if sx > 0 && sy > 0;  move_upper_left
    elsif sx > 0 && sy < 0;  move_lower_left
    elsif sx < 0 && sy > 0;  move_upper_right
    elsif sx < 0 && sy < 0;  move_lower_right
      #normal movement
    elsif sx < 0 && sy == 0; move_right
    elsif sx > 0 && sy == 0; move_left
    elsif sx == 0 && sy < 0; move_down
    elsif sx == 0 && sy > 0; move_up
    end
  end
 
  #these modifications make the "hero touch" work better
  #thanks Linkin_T for the help
  def check_event_trigger_touch(x, y)
    return if not @stop_count > (40 - @move_frequency * 2) * (6 - @move_frequency)
    old_touch(x, y)
  end
  def check_event_trigger_auto
    return if not @stop_count > (40 - @move_frequency * 2) * (6 - @move_frequency)
    old_auto
  end
end

class Game_Event < Game_Character

  attr_reader :has_cone
  alias conesys_gameevent_initialize initialize
  alias old_touch check_event_trigger_touch
  alias old_auto check_event_trigger_auto
     
  def initialize(map_id, event)
    #a flag that tells if the event is cone-following-enabled or not
    @has_cone = false
    conesys_gameevent_initialize(map_id, event)
  end
 
    #start the cone routine.
  def add_cone(sight = 7)
    @has_cone = true
    get_cone(sight)
  end
    #stop the "cone following"
  def stop_cone
    @has_cone = false
  end
end

class Game_Player < Game_Character
 
  alias conesys_gameplayer_update update
 
  def update
    check_cone
    conesys_gameplayer_update
  end
 
  def check_cone
    #check if the event has a cone
    for i in $game_map.events.keys
      event = $game_map.events[i]
      if event.has_cone && $scene.is_a?(Scene_Map)
        #check if the player is inside the cone of vision and make the
        #event follow him
        event.in_cone
        #update the cone if the event moved or the direction is different
        if event.x != event.prev_x || event.y != event.prev_y || event.direction != event.prev_dir
          event.get_cone(event.sight)
        end
      end
    end
  end
end

Credit to Lobosque if used.

To set up a cone, you need to add
$game_map.events[EVENT NUMBER].add_cone(VIEW RANGE)
in a script command, put the event number and the range (in tiles) in the appropriate spots.

http://www.hbgames.org/forums/showthread.php?t=19301


FCF3a A+ C- D H- M P+ R T W- Z- Sf RLCT a cmn+++ d++ e++ f h+++ iw+++ j+ p sf+
Follow my project: MBlok | Find me on: Bandcamp | Twitter | Patreon

Yawgmothsbud

Woot, thanks a ton! I've been searching for quite awhile now...I can finally finish my assassin quests xD

ChaosSpartan28

#3
Solved? Add [Resolved] to the topic title.
Sig by MacGravel

Yawgmothsbud

#4
 Nope, need some troubleshooting: When I run the game, I get

?? NOMethodError ??

undefined method 'add_cone' for nil:NilClass

I added

$game_map.events[35].add_cone(4)

To an event and that caused it...obviously something isnt matching up...

I think I fixed it, but Im gonna keep this open for a bit in case I get into any more trouble... 8)

tSwitch

Quote from: Yawgmothsbud on May 13, 2007, 08:52:31 PM
Nope, need some troubleshooting: When I run the game, I get

?? NOMethodError ??

undefined method 'add_cone' for nil:NilClass

I added

$game_map.events[35].add_cone(4)

To an event and that caused it...obviously something isnt matching up...

I think I fixed it, but Im gonna keep this open for a bit in case I get into any more trouble... 8)
see that's weird, I never got that error at all.
did you try 035 instead of 35?


FCF3a A+ C- D H- M P+ R T W- Z- Sf RLCT a cmn+++ d++ e++ f h+++ iw+++ j+ p sf+
Follow my project: MBlok | Find me on: Bandcamp | Twitter | Patreon