Chaos Project

RPG Maker => RPG Maker Scripts => Script Troubleshooting => Topic started by: CriticalHit on April 24, 2020, 10:28:33 pm

Title: [Resolved] RMXP Blizz ABS Enemy Seeing Through Walls
Post by: CriticalHit on April 24, 2020, 10:28:33 pm
Hi,

I am developing a game using RPG Maker XP with Blizz ABS that relies on stealth. I've noticed that enemies see through walls sometimes even though I set up the wall terrain tag on the tile they are seeing through. They only seem to see through walls at certain points which is very odd and I can't account for it.
I made a test project with a clean copy of RMXP and Blizz ABS and experience the same odd seeing through walls issue.I put this project in a Github repository to demonstrate my issue:
https://github.com/antlaw0/Test-Project
The enemy detects the player on the spots on the ground where I put grass.
How can I make the enemy not see through walls?

Thank you
Title: Re: RMXP Blizz ABS Enemy Seeing Through Walls
Post by: KK20 on April 25, 2020, 02:06:14 am
Good job finding this bug. There is definitely something wrong with the wall algorithm:
    #--------------------------------------------------------------------------
    # wall?
    #  char - the character
    #  x    - x-coordinate
    #  y    - y-coordinate
    #  Checks if between the char and the target is a "wall". Walls prevent
    #  perception.
    #--------------------------------------------------------------------------
    def wall?(char, x, y)
      # abort instantly if not using this option
      return false if Config::WALL_TAGS.size == 0
      # get pixel movement rate
      pix = $BlizzABS.pixel
      # get coordinate difference
      dx, dy = (x-char.x)/pix, (y-char.y)/pix
      # if x difference is not 0 and x difference is greater
      if dx != 0 && dx.abs > dy.abs
        # return any wall tile between
        return (0..dx.abs).any? {|i| Config::WALL_TAGS.include?($game_map.
            terrain_tag(char.x/pix+dx.sgn*i, char.y/pix+(i.to_f*dy/dx).round))}
      # if y difference is not 0 and y difference is greater
      elsif dy != 0 && dy.abs > dx.abs
        # return any wall tile between
        return (0..dy.abs).any? {|i| Config::WALL_TAGS.include?($game_map.
            terrain_tag(char.x/pix+(i.to_f*dx/dy).round, char.y/pix+dy.sgn*i))}
      end
      # no wall between
      return false
    end
For the bottom right corner in your demo, the (dx, dy) is (3, 3). Because dx == dy, the two if-statements are ignored, and the method returns false.

For the bottom left area, we're running through this part of the method:
        # return any wall tile between
        return (0..dx.abs).any? {|i| Config::WALL_TAGS.include?($game_map.
            terrain_tag(char.x/pix+dx.sgn*i, char.y/pix+(i.to_f*dy/dx).round))}
The problem is that, as the loop iterates, it is checking the tile to the left and UP, starting from the enemy's position.
Your event is at (9, 7). When i = 1, it checks if tile (8, 6) is a wall, which it isn't. It should be checking (8, 8 ) instead.

Not currently in a position to fix it, but letting you know why it's behaving that way.
Title: Re: RMXP Blizz ABS Enemy Seeing Through Walls
Post by: winkio on April 25, 2020, 12:26:11 pm
replacing the method with this one should fix it, but I haven't tested it
    #--------------------------------------------------------------------------
    # wall?
    #  char - the character
    #  x    - x-coordinate
    #  y    - y-coordinate
    #  Checks if between the char and the target is a "wall". Walls prevent
    #  perception.
    #--------------------------------------------------------------------------
    def wall?(char, x, y)
      # abort instantly if not using this option
      return false if Config::WALL_TAGS.size == 0
      # get pixel movement rate
      pix = $BlizzABS.pixel
      # get coordinate difference
      dx, dy = (x-char.x)/pix, (y-char.y)/pix
      # if x difference is not 0 and x difference is greater
      if dx != 0 && dx.abs >= dy.abs
        # return any wall tile between
        return (0..dx.abs).any? {|i| Config::WALL_TAGS.include?($game_map.
            terrain_tag(char.x/pix+dx.sgn*i, char.y/pix+(i.to_f*dy/dx.abs).round))}
      # if y difference is not 0 and y difference is greater
      elsif dy != 0 && dy.abs > dx.abs
        # return any wall tile between
        return (0..dy.abs).any? {|i| Config::WALL_TAGS.include?($game_map.
            terrain_tag(char.x/pix+(i.to_f*dx/dy.abs).round, char.y/pix+dy.sgn*i))}
      end
      # no wall between
      return false
    end

I made the first if block use >= instead of >, and then for the slopes used the absolute value of the denominator so that the signs would match correctly.
Title: Re: RMXP Blizz ABS Enemy Seeing Through Walls
Post by: CriticalHit on April 26, 2020, 09:11:09 pm
Thanks for the response. I replaced the method with the code you posted and it works fine so far- enemies are not detecting the player on the sections of grass any more.
My plan is to implement this new method into my game and test it more thoroughly over the next couple of days before marking this issue as resolved.