/* Do not remove the headers from this file! see /USAGE for more info. */ /* Do not remove the headers from this file! see /USAGE for more info. */ /* * Monster wandering module. * This module will allow monsters to wander in designated area, with * specified time intervals between movements. * Written by Tigran 03/27/98. */ //:MODULE // //The wander module designed to be included by NPC's which allows monsters //to wander throughout various areas in the gaming area. //:TODO //Something to have the NPC's open doors or unlcok doors. It is possible //that this belongs in a separate module. #define ZERO_RETURN 10 void add_hook(string tag, function hook); void remove_hook(string tag, function hook); void do_wander(); void do_game_command(string str); int query_attacking(); int player_did_arrive(string dir); void moving(); private mixed wander_time; private string array wander_area=({}); private nosave int call; private nosave int num_moves; private int max_moves; private nosave int counting_moves; private nosave function arrive_func=(:player_did_arrive:); private nosave function move_hook=(:moving:); //:FUNCTION set_wander_area //Set the area(s) that an NPC can wander in. If this is not set //it is assumed that the NPC can wander anywhere without area //restrictions. void set_wander_area(string array area...) { wander_area=clean_array(area); } //:FUNCTION add_wander_area //Add area(s) which an NPC can wander in. See set_wander_area() void add_wander_area(string array area...) { wander_area=clean_array(wander_area+({area})); } //:FUNCTION remove_wander_area //Remove area(s) which an NPC can wander in. See set_wander_area() void remove_wander_area(string array area...) { if(member_array(area,wander_area)) wander_area-=({area}); } //:FUNCTION clear_wander_area //Clear the area(s) in which an NPC can wander in. Effectively //this allows the NPC to wander anywhere. See set_wander_area() void clear_wander_area() { wander_area=({}); } //:FUNCTION query_wander_area //Returns an array of areas in which may wander. //See set_wander_area() string array query_wander_area() { return wander_area; } //:FUNCTION set_wander_time //Sets the time between an NPC's movements. // //If the argument is an int it sets the time in seconds. // //If the argument is a function pointer, the function //needs to evaluate to an int. The fpointer is evaluated //during runtime. void set_wander_time(mixed time) { if(!intp(time)&&!functionp(time)) return; wander_time=time; } //:FUNCTION query_wander_time //Returns an integer which is the amount of time to be used //for the interval between movements. It does not return //the time til the next movement. query_wander_time() //will not return 0, if the return is 0 or less //ZERO_RETURN (refer to the M_WANDER file) will be returned int query_wander_time() { int i; if(intp(wander_time)) i=wander_time; else i=evaluate(wander_time); if(i<2) return ZERO_RETURN; return i; } //:FUNCTION set_max_moves //Sets the maximum number of moves a monster will make without //running into a player. This prevents too many NPCs //moving around for no reason. If the argument is 0 it assumes //that the NPC will not stop moving, regardless of player //interaction void set_max_moves(int i) { max_moves=i; } //:FUNCTION query_max_moves //Returns the number of moves an NPC will make without player //interaction before stopping. int query_max_moves() { return max_moves; } private void reset_moves() { num_moves=0; //counting_moves=0; } private void start_move_count() { if(!max_moves) return; counting_moves=1; } //:FUNCTION cease_wandering //Stops an NPC from wandering. //start_wandering() is required to make the NPC move again void cease_wandering() { remove_call_out(call); call=0; environment()->remove_hook("person_arrived",arrive_func); } //:FUNCTION stop_wandering //Stops an NPC from wandering. //If you use this function the npc will start moving again if a PC enters the //room. void stop_wandering() { remove_call_out(call); call=0; environment()->add_hook("person_arrived",arrive_func); } //:FUNCTION start_wandering //Starts an NPC wandering void start_wandering() { if(call) return; if(!environment()) return; environment()->add_hook("person_arrived",arrive_func); call=call_out( (: do_wander :), query_wander_time() ); reset_moves(); } /* Hook function that is called after we move into the new location * Check here to see if there are other PC's in the room. If so reset the * count and continue moving. */ void moving() { environment()->add_hook("person_arrived",arrive_func); foreach(object ob in all_inventory(environment())) { if(ob->query_link()) { reset_moves(); break; } } } int player_did_arrive(string direction) { reset_moves(); if(this_body()->query_link()) start_wandering(); return 1; } private void move_me(string direction) { environment()->remove_hook("person_arrived",arrive_func); do_game_command(sprintf("go %s",direction)); if(!counting_moves) start_move_count(); num_moves++; if(counting_moves && (num_moves>=max_moves)) { stop_wandering(); return; } call=call_out( (: do_wander :), query_wander_time()); } private void do_wander() { string array directions; int i; string chosen_dir; string file; object dest; if(environment(this_object())) directions=environment(this_object())->query_exit_directions(); /* Stop if there are no directions (this takes care of blue prints*/ if(!directions||!i=sizeof(directions)) return; chosen_dir=directions[random(i)]; file=environment(this_object())->query_exit_destination(chosen_dir); /* If the file is null or a null string try to move again next time */ if(!file||file=="") { call=call_out( (: do_wander :), query_wander_time()); return; } /* If the destination is not loaded, do so */ dest=find_object(file); if(!dest) dest=load_object(file); /* If still no destination it won't load, try again next time */ if(!dest) { call=call_out( (: do_wander :), query_wander_time()); return; } /* Check if the npc has wander restrictions */ if(sizeof(wander_area)) { if(arrayp(wander_area)&&arrayp(dest->query_area())) { if(sizeof(wander_area&dest->query_area())) move_me(chosen_dir); else call=call_out( (: do_wander :), query_wander_time()); } else call=call_out( (: do_wander :), query_wander_time()); } else move_me(chosen_dir); return; } void mudlib_setup() { add_hook("move",move_hook); } mapping lpscript_attributes() { return (["wander_area" : ({ LPSCRIPT_LIST, "setup", "set_wander_area" }), "wander_time" : ({ LPSCRIPT_INT, "setup", "set_wander_time" }), "max_moves" : ({ LPSCRIPT_INT, "setup", "set_max_moves" }) ]); }