Jump to content

NPC Searching for nearest guard


Recommended Posts

Does anyone know if it's possible to make a normal NPC actively search out the nearest character whose script is "guard.txt" after witnessing a crime done by the player.

 

For example, the player breaks into someones house and steals some items of value not theirs, an NPC witnesses this, so, instead of the town becoming hostile straight away, i want the NPC to run away to the nearest guard, then the town becoming hostile.

 

Is there a call that will make the NPC do this (or list of calls)?

Link to comment
Share on other sites

There is no way for a creature to 'know' what script another NPC is running (By which I mean there is no 'get_script()' call) but you could do something like add all the town's guards to a group, then search that group for the nearest guard and have the creature run to it.

 

The biggest problem I see here is the problem of knowing who the witness is. There is no 'saw_crime()' call, so the only way to know if a crime has been committed (and observed) is to check the town's crime level. Unfortunately this doesn't tell you WHO observed the crime. At first I thought this would make what you want impossible, but as I wrote this I thought of a possible workaround. When the crime level changes, check to see what NPCs are within sight of the party. Pass a message to these NPCs, which will tell them to run to the nearest guard. When they are within, say, 1 space of a guard, make the town hostile.

Link to comment
Share on other sites

Question: How would I get the NPC to search for the nearest guard?

 

Would it work if I, in the NPC's script, made the call can_see_char (i think this is it, but i'm not sure) whenever the crime level goes up, and if it has, and the NPC sees the player, make the NPC run. Maybe if i set guards who don't move randomly at places in the town then made the NPC run to the nearest on of those. Would this be possible?

Link to comment
Share on other sites

Assuming that you have variables i, dist, and num, I think that this should work:

Code:
i = 6;dist = 1000;num = -1;while(i < 120){		if(char_ok(i) && can_see_char(i) && creature_type(i) == 4 && dist_to_char(i)<dist){		num = i;		dist = dist_to_char(i);	}	}
The way that it works is that it goes through all the NPCs in the town, which is creatures 6-120, and for each one checks if it is alive, visible, is creature type 4 (Guard), and is closer than the closest known guard. All of these are true, the guard's number is stored to num and the distance to it is stored in dist. So, when the loop finishes, num will be the number of the nearest guard, or -1 if there were no living, visible guards, and dist will be the distance to the guard or 1000 if no guard was found.

 

Of, course, this snippet just tells you who the nearest guard is. If it gives you a guard, have the creature run to it, if not you'll need to do something else. I would reccommend that you put several waypoints in your town, form which guards are likely to be visible. So if an npc sees a crime but no guards, it can pick a nearby waypoint and run there to look for guards.

 

EDIT: Added a line break in the code.

Link to comment
Share on other sites

I demonstrate better then I explain, so here's how I would do it:

 

First, a check to see if the creature sees the party (I'm working off the assumption that any creature other than guards can run to the guards; just ignore the my_current_message() call for now, I'll explain it later):

Code:
if (((get_crime_level() > 0) && (can_see_char(1000) == 2)) || (my_current_message() == 3)) {
Then, I check to see which guard is closest by using the following:

Code:
      i = 6;      g = -1; // This variable contains the creature number of the closest guard.      d = 99; // This variable contains the distance the above was found at.      while (i < 86) { // This loop checks every creature to see if it fits the criteria.            if (char_ok(i) == 1) { // Make sure the character is alive and well to prevent odd errors.                  if ((creature_type(i) == 4) && (dist_to_char(i) < d)) { // Check whether the creature is a guard or not and whether it's closer                                                                          // than the currently selected creature.                        g = i; // Set the guard to run to to this creature.                        d = dist_to_char(i); } // Set the distance this guard was at.                  }            i = i + 1; }
Okay, after that mouthful, all that's left to do is go after the guard, right?

 

Not yet. You may or may not have seen the coming problem, but what happens when the party moves about while the crime level is elevated? Since the conditional only specified that if the crime level is elevated and the character can see the party, after the crime is committed, everyone who sees the party from then on will run for the guards. So why not just reset the crime level once the character runs for the guards? Because that creates a new (but mercifully) smaller problem: If multiple people witness a crime, only one will run for the guards. Which leads to my solution: remember that my_current_message call I told you to ignore? This is where it comes in handy.

Code:
      i = 0;      while (can_see_char(i) == 0) {// Make sure to select a visible party member to broadcast from.            i = i + 1; }      broadcast_message_from_x_y(char_loc_x(i),char_loc_y(i),3,99);      // Broadcasts the message 3 from the guilty party's location.      change_crime_level(-1 * (get_crime_level())) // Reset crime level.
Phew. While not 100% foolproof, that should do the trick. So, lace up your running shoes and put on that training montage music from the original Rocky Balboa movie... We're going for the guards!

Code:
      stop_moving(ME); // Make sure previous move orders don't interfere.      set_mobility(ME,1); // Make sure I can actually move.      approach_char(ME,g,1); } // And, at long last, this gets the character running for the guard.
Of course, this'll experience problems if there's no viable path to a guard. Like, for example, a closed door. But that's up to you to figure out.

 

By the way, here's the code all put together:

Code:
if (((get_crime_level() > 0) && (can_see_char(1000) == 2)) || (my_current_message() == 3)) {      i = 6;      g = -1; // This variable contains the creature number of the closest guard.      d = 99; // This variable contains the distance the above was found at.      while (i < 86) { // This loop checks every creature to see if it fits the criteria.            if (char_ok(i) == 1) { // Make sure the character is alive and well to prevent odd errors.                  if ((creature_type(i) == 4) && (dist_to_char(i) < d)) { // Check whether the creature is a guard or not and whether it's closer                                                                          // than the currently selected creature.                        g = i; // Set the guard to run to to this creature.                        d = dist_to_char(i); } // Set the distance this guard was at.                  }            i = i + 1; }      i = 0;      while (can_see_char(i) == 0) {// Make sure to select a visible party member to broadcast from.            i = i + 1; }      broadcast_message_from_x_y(char_loc_x(i),char_loc_y(i),3,99);      // Broadcasts the message 3 from the guilty party's location.      change_crime_level(-1 * (get_crime_level())) // Reset crime level.      stop_moving(ME); // Make sure previous move orders don't interfere.      set_mobility(ME,1); // Make sure I can actually move.      approach_char(ME,g,1); } // And, at long last, this gets the character running for the guard.
EDIT: Somehow, I managed to leave out a critical part of the code. (Now fixed)
Link to comment
Share on other sites

Messages make me nervous. I'd personally just reset the crime level in the town start_state, but that's just me. I have had bad experiences with messages.

 

Also I'd change it from "nearest visible guard" to "nearest guard", just for the sake of simplicity. Otherwise you'll have to use Niemand's idea, to have waypoints outdoors to get the creature to run outside (where it is likely to see a guard). Kind of a pain.

 

Lastly, while Nioca's code will get the character to run to a guard, it doesn't actually alert the guard yet. My advice is to check if the NPC is within about 3 spaces of the guard, then set the town to hostile (Perhaps a print_str("Townsman has called the guards!") for good measure. Also I'd advise adding a check to Nioca's code to make sure the town isn't already hostile before NPCs run to alert the guards (Basically if you don't do this, any NPC that sees the party slaughtering the guards is going to run over and alert them. Which makes no sense.)

Link to comment
Share on other sites

Messages are nothing to fear, just stick to using them simply. My rule is to check for messages first and act on them before doing anything else, and it's worked pretty well. One of the best things that you can do with messages is to literally make a message propagate among npcs. I did something like that in AVM, where any brigand who hates the party alerts any other brigands he meets to hate the party also. This way you never need to 'set the town hostile', you just let the news propagate through the town and guards and towns people can do whatever they do if they know that the party is a bunch of criminals.

 

This can be used for the problem by having a townsperson who has seen a crime committed continuously broadcast a message while doing whatever is necessary to seek out a guard. Then when it gets in range of the guard, if the guard listens for that message type, it will be alerted as soon as it sees the townsperson come running. Of course, as Lazarus points out you don't need townspeople alerting guards who already know what's going on, so you could have them seek guards who don;t know, and if none remain just run away from the party or something.

Link to comment
Share on other sites

Wow eek , thanks for all the help everyone, i wasn't expecting this many replies lol. It's a bit late at the moment so i'll have to get around to doing this tomorrow but hopefully it all works out. Thanks again for all the help and i'll post anymore problems i run into (which i'm sure there'll be lots smile ).

 

Also, one more thing: can the BoA engine handle multiplying by negatives? For example, This is part of a terrain script i'm working on:

Code:
 move_to_new_town(my_loc_x,((my_loc_y - 47) * -1),get_memory_cell(9)); 
Is that possible, or do i have to do it some other way?
Link to comment
Share on other sites

Well I put both Niemands' and Niocas' scripts in, but then I realized that, for what I had in mind to work, i'd need a call to return the value of which direction an NPC is facing. Like a 'character_facing(ME)' call. I tried that but of course that returned a bunch of errors, so is there any call to do this?

 

I think with messages I should be alright (with the help of the docs of course).

 

Quote:
Multiplying by negatives is fine, but I do have to tell you that the move_to_new_town call only works when it's used in a state activated by the party stepping into a special rectangle.
What call could I use in a terrain script instead of move_to_new_town?
Link to comment
Share on other sites

Quote:
I'd need a call to return the value of which direction an NPC is facing
1) There is no way to find out which way an NPC is facing. You can set the value, but not retrieve it.
2) Why do you need this? Do you want NPCs to only notice crimes if facing the party? If so I'm afraid that there's no good way. Other than that, I can't think of any reason you would need this.
Link to comment
Share on other sites

Quote:
Originally written by Ephesos:
Quote:
Originally written by Armed_Defender:
What call could I use in a terrain script instead of move_to_new_town?
To the best of our collective knowledge, there is no workaround for this problem.
You can do all sorts of ugly things like setting flags and moving the party (Exodus does this sometimes, and Bahs did, too), but they're ugly.
Link to comment
Share on other sites

Quote:
Orginally written by Niemand:
1) There is no way to find out which way an NPC is facing. You can set the value, but not retrieve it.
2) Why do you need this? Do you want NPCs to only notice crimes if facing the party? If so I'm afraid that there's no good way. Other than that, I can't think of any reason you would need this.
Well, my intention was to make it possible for the party to steel from an unsuspecting NPC if the player was to sneak up behind them while their back is turned. To find out whether they the player was successful i would use:
Quote:
Originally written by Ephesos:
To the best of our collective knowledge, there is no workaround for this problem.
Ok well, there goes another idea. I'll just do it through specials, which would probably be easier in the long run.

Well I can still use Niemands' and Niocas' scripts for my original idea lol.

Thanks again for all your help everyone.
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...