Curious Artila Armed_Defender Posted December 1, 2007 Posted December 1, 2007 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)? Quote
Unflappable Drayk Lazarus. Posted December 1, 2007 Posted December 1, 2007 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. Quote
Curious Artila Armed_Defender Posted December 1, 2007 Author Posted December 1, 2007 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? Quote
Well-Actually War Trall Niemand Posted December 2, 2007 Posted December 2, 2007 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. Quote
Understated Ur-Drakon Nioca Posted December 2, 2007 Posted December 2, 2007 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) Quote
Unflappable Drayk Lazarus. Posted December 2, 2007 Posted December 2, 2007 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.) Quote
Well-Actually War Trall Niemand Posted December 2, 2007 Posted December 2, 2007 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. Quote
Curious Artila Armed_Defender Posted December 2, 2007 Author Posted December 2, 2007 Wow , 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: 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? Quote
Understated Ur-Drakon Nioca Posted December 2, 2007 Posted December 2, 2007 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. Quote
Magnificent Ornk Kelandon Posted December 2, 2007 Posted December 2, 2007 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.) Quote
Curious Artila Armed_Defender Posted December 2, 2007 Author Posted December 2, 2007 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? Quote
Magnificent Ornk Ephesos Posted December 2, 2007 Posted December 2, 2007 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. Quote
Well-Actually War Trall Niemand Posted December 2, 2007 Posted December 2, 2007 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. Quote
Magnificent Ornk Kelandon Posted December 2, 2007 Posted December 2, 2007 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. Quote
Curious Artila Armed_Defender Posted December 2, 2007 Author Posted December 2, 2007 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. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.