Cancel no-blocking NPC walk if condition is met using repeatedly_execute

Started by Lewis, Sat 02/05/2020 20:42:24

Previous topic - Next topic

Lewis

Apols for the third new thread in a few days - I'm trying something new!

So, I'm trying to create a simple real-time combat engine with some very basic AI logic.

There's a lot of code in lots of places in the global script, and most of it isn't relevant to this question, so I won't put it all here. In short, I have an enemy character (cZombie) that has three AI 'states': 0) Patrol, 1) Attack, and 2) Dead. These are all controlled by calling functions from when different conditions are met. Specifically, I check in rep_ex to see if the zombie is moving, and if it isn't, it walks (noblock) to a random place on the screen. I also check with a custom function (and call it from rep_ex) to see if the player is within a certain distance of the zombie and, if they are, then the zombie begins to follow the player and ultimately attack them if they get right up close.

And it almost works. The problem is, when "is the player within a certain distance" returns true, the zombie waits until it has reached its next randomly generated coordinates before it begins to follow the player. In other words, I'm struggling to find a way to 'interrupt' the noblock walk instruction so that the zombie begins to immediately follow the player.

Here's the relevant rep_ex snippet:
Code: ags
//Check distance from player for attacks
    if (cPlayer.Room == cZombie.Room)
    {
      check_zombie_distance();
    }
    
    //Zombie patrolling the area
    if (zombie_state==0)
    {
      if (cZombie.Moving==false)
      {
        cZombie.Walk(Random(1280), Random(720), eNoBlock, eWalkableAreas);
      }
    }
    //Zombie chasing player
    else if (zombie_state==1)
    {
      cZombie.FollowCharacter(cPlayer);
    }


And then I have a custom function for checking the distance:

Code: ags
function check_zombie_distance()
{
  //Check if a zombie is nearby and should therefore change to state 1
  
  if ((cZombie.x - cPlayer.x < 400) && (cZombie.x - cPlayer.x > -400) && (cZombie.y - cPlayer.y < 300) && (cZombie.y - cPlayer.y > -300))
  {
    zombie_state=1;
  }
  
  
    //Check if a zombie is close and should therefore attack
  
  if ((cZombie.x - cPlayer.x < 30) && (cZombie.x - cPlayer.x > -30) && (cZombie.y - cPlayer.y < 30) && (cZombie.y - cPlayer.y > -30))
    {
      zombie_attack();
    }
}


I've checked around the forums and found some ideas (including a module) on how to allow a click to interrupt the player's own walk, which is the most similar query I've found, but haven't been able to find anything to fix this particular issue. Any help or pointers appreciated!

I am also suddenly conscious that any blocking scripts that are fired will block the rep_ex functionality so I suspect I'll also have to move all this to rep_ex_always and then find a way for the zombie attack to interrupt what would normally be blocking actions by the player. Work still to be done!
Returning to AGS after a hiatus. Co-director of Richard & Alice and The Charnel House Trilogy.

morganw

You can just do:

Code: ags
cZombie.StopMoving();
cZombie.FollowCharacter(cPlayer);

Lewis

Thanks, I knew it would be something simple.

In fact, what I needed to do specifically was ensure that cZombie.StopMoving(); was only called once from repeatedly_execute - otherwise the zombie never actually moved anywhere, as no sooner had it been instructed to follow the player, it was instructed to stop moving again.

So, I decided to use a dummy 'state' that is quickly cycled through:

Code: ags
if (zombie_state==1)
    {
      cZombie.StopMoving();
      cZombie.FollowCharacter(cPlayer, 1, 1);
      zombie_state=2;
    }


This worked a treat.
Returning to AGS after a hiatus. Co-director of Richard & Alice and The Charnel House Trilogy.

SMF spam blocked by CleanTalk