NPC Searching for nearest guard

Error message

Deprecated function: implode(): Passing glue string after array is deprecated. Swap the parameters in drupal_get_feeds() (line 394 of /var/www/pied-piper.ermarian.net/includes/common.inc).
AuthorTopic: NPC Searching for nearest guard
Apprentice
Member # 7374
Profile #0
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)?
Posts: 16 | Registered: Friday, August 11 2006 07:00
Lifecrafter
Member # 6193
Profile Homepage #1
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.

--------------------
"NOW PASS ME MY BOOTS. I HAVE AN APPOINTMENT WITH A FACE." -Nikki

Frostbite: Get It While It's...... Hot?
Posts: 900 | Registered: Monday, August 8 2005 07:00
Apprentice
Member # 7374
Profile #2
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?
Posts: 16 | Registered: Friday, August 11 2006 07:00
Infiltrator
Member # 5576
Profile Homepage #3
Assuming that you have variables i, dist, and num, I think that this should work:
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.

[ Saturday, December 01, 2007 18:41: Message edited by: Niemand ]

--------------------
Überraschung des Dosenöffners!
"On guard, you musty sofa!"
Posts: 627 | Registered: Monday, March 7 2005 08:00
Shaper
Member # 7472
Profile Homepage #4
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):
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:
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) == x) && (dist_to_char(i) < d)) { // Check whether the creature is a guard or not (replace x with the creature number of a guard in your scenario) 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.
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.
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!
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.

--------------------
Scenarios need reviews! Please rate these scenarios at the CSR after playing them!
AmnesiaEl PresidenteWhere the Rivers MeetA Visit to the Madhouse
AvatarAphobiaIMAGINE THIS SCENARIO
Posts: 2686 | Registered: Friday, September 8 2006 07:00
Lifecrafter
Member # 6193
Profile Homepage #5
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.)

--------------------
"NOW PASS ME MY BOOTS. I HAVE AN APPOINTMENT WITH A FACE." -Nikki

Frostbite: Get It While It's...... Hot?
Posts: 900 | Registered: Monday, August 8 2005 07:00
Infiltrator
Member # 5576
Profile Homepage #6
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.

--------------------
Überraschung des Dosenöffners!
"On guard, you musty sofa!"
Posts: 627 | Registered: Monday, March 7 2005 08:00
Apprentice
Member # 7374
Profile #7
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 :) ).

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:
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?

[ Sunday, December 02, 2007 00:45: Message edited by: Armed_Defender ]
Posts: 16 | Registered: Friday, August 11 2006 07:00
Shaper
Member # 7472
Profile Homepage #8
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.

--------------------
Scenarios need reviews! Please rate these scenarios at the CSR after playing them!
AmnesiaEl PresidenteWhere the Rivers MeetA Visit to the Madhouse
AvatarAphobiaIMAGINE THIS SCENARIO
Posts: 2686 | Registered: Friday, September 8 2006 07:00
Off With Their Heads
Member # 4045
Profile Homepage #9
Why wouldn't you just reverse the order of the subtraction? That's the same as multiplying by -1.

Also, you'll want parentheses like so: my_loc_x() and my_loc_y(). (In addition to the fact that it won't work for the reason named above.)

[ Sunday, December 02, 2007 10:12: Message edited by: Kelandon ]

--------------------
Arancaytar: Every time you ask people to compare TM and Kel, you endanger the poor, fluffy kittens.
Smoo: Get ready to face the walls!
Ephesos: In conclusion, yarr.

Kelandon's Pink and Pretty Page!!: the authorized location for all things by me
The Archive of all released BoE scenarios ever
Posts: 7968 | Registered: Saturday, February 28 2004 08:00
Apprentice
Member # 7374
Profile #10
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?
Posts: 16 | Registered: Friday, August 11 2006 07:00
Law Bringer
Member # 4153
Profile Homepage #11
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.

--------------------
TM: "I want BoA to grow. Evolve where the food ladder has rungs to be reached."

Gamble with Gaea, and she eats your dice.
Posts: 4130 | Registered: Friday, March 26 2004 08:00
Infiltrator
Member # 5576
Profile Homepage #12
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.

--------------------
Überraschung des Dosenöffners!
"On guard, you musty sofa!"
Posts: 627 | Registered: Monday, March 7 2005 08:00
Off With Their Heads
Member # 4045
Profile Homepage #13
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.

--------------------
Arancaytar: Every time you ask people to compare TM and Kel, you endanger the poor, fluffy kittens.
Smoo: Get ready to face the walls!
Ephesos: In conclusion, yarr.

Kelandon's Pink and Pretty Page!!: the authorized location for all things by me
The Archive of all released BoE scenarios ever
Posts: 7968 | Registered: Saturday, February 28 2004 08:00
Apprentice
Member # 7374
Profile #14
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:
if (get_ran(1,1,100) == < ((get_flag(1,1) / 20) * 100 ) this would give me (hopefully) the percentage chance the player has of being successful. (get_flag(1,1) would be the level of skill the player had out of 20)

Oh well I guess I'll have to be more inventive :P .

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.
Posts: 16 | Registered: Friday, August 11 2006 07:00