/* -*- LPC -*- */ /* * $Locker: $ * $Id: shadow.c,v 1.1 1998/01/06 04:42:56 ceres Exp $ * $Log: shadow.c,v $ * Revision 1.1 1998/01/06 04:42:56 ceres * Initial revision * */ /* * This is based on the 'sneak' system. I know that the following system is * somewhat convoluted, but its the best system I could come up with for * various reasons not least among which is that this way I needed to add * no code to the player or room objects which keeps memory usage down * for the majority who are not shadowing anyone. * -- Ceres July 1997 */ #include "path.h" #include <tasks.h> inherit "/std/effect_shadow"; #define COST 7 #define SKILL "covert.stealth" #define HSKILL "covert.hiding.person" #define TC(X) tell_object(find_player("ceres"), X) int level, out_of_hiding, moving, sneak_removed, dont_unsneak; string skill, oldskill; object shadowee; void set_sneak(); void set_hide(); // this is used to calculate the current sneaking level for when someone // wants to view it. int query_shadow_level() { return level; } object query_shadow_victim() { return shadowee; } // called when the person starts shadowing void start_shadowing(object who, int lev) { level = lev; dont_unsneak = 1; shadowee = who; set_hide(); dont_unsneak = 0; } void stop_shadowing() { remove_this_effect(); } void hide_callback() { out_of_hiding = 1; if(query_verb() == "hide" || query_verb() == "sneak") { tell_object(player, "Attempting to remain hidden you stop sneaking.\n"); return; } if(!moving) { if(player == previous_object() ) tell_object(player, "You come out of hiding.\n"); else tell_object(player, "You have been noticed.\n" ); tell_room( environment(player), "You notice $a_short:"+ file_name( player ) +"$ nearby.\n", player ); } } void shadow_callback() { if(!dont_unsneak) sneak_removed++; } string calc_skill(object who) { string s; if(environment(who)->query_property("location")) s = SKILL + "."+ environment(who)->query_property("location"); else s = SKILL + ".outside"; return s; } void set_sneak() { int bonus; bonus = (player->query_skill_bonus(HSKILL) * level) / 3; player->add_hide_invis( "sneaking", 0, bonus, ({this_object(), "shadow_callback"})); } void set_hide() { int bonus; bonus = (player->query_skill_bonus(HSKILL) * level) / 3; player->add_hide_invis( "hiding", 0, bonus, ({this_object(), "hide_callback"})); } // used to charge people for sneaking // the out_of_hiding and moving variables are needed coz exit_command // a. gets called a lot even when not moving // b. automatically takes you out of hiding even though you haven't been // spotted in this case. varargs int exit_command(string word, mixed verb, object thing) { int retval; set_sneak(); moving = 1; retval = player->exit_command(word, verb, thing); moving = 0; if(retval) { // reduce their gps if(player->query_specific_gp("covert") < COST * level) { tell_object(player, "You can't concentrate sufficiently to shadow " "anymore.\n"); remove_this_effect(); return 1; } else if(sneak_removed) { remove_this_effect(); return 1; } tell_object(player, "You shadow "+shadowee->the_short()+" "+word+".\n"); player->adjust_gp(-(COST * level)); out_of_hiding = 0; } dont_unsneak = 1; player->remove_hide_invis("sneaking"); dont_unsneak = 0; if(!out_of_hiding) { set_hide(); } return retval; } // function called by /global/events:event_enter to perform a taskmaster // test for the shadower. void sneak_task(object who) { mapping hide_invis; string location; int perception; hide_invis = player->query_hide_invis(); if(hide_invis["sneaking"]) { // set their perception. perception = who->query_skill_bonus("other.perception"); switch(who->check_dark((int)environment(who)->query_light())) { case -2: case 2: perception /= 4; break; case -1: case 1: perception /= 2; break; default: break; } player->query_skill_bonus(calc_skill(player)); switch(TASKER->attempt_task(perception, hide_invis["sneaking"][1], 40)) { case AWARD: if(player->add_skill_level(calc_skill(player), 1)) { if(environment(player)->query_property("location")) location = environment(who)->query_property("location"); else location = "outside"; tell_object(player, "%^YELLOW%^You "+ ({ "understand", "comprehend", "realise", "appreciate" })[ random( 4 ) ] + " the methods of shadowing "+ location +" more fully." "%^RESET%^\n" ); } } } } // function called by /global/events:event_enter to perform a taskmaster // test for the person entering. void perception_task(object who) { mapping hide_invis; int perception; hide_invis = player->query_hide_invis(); if(player->query_visible(who)) { return; } if(hide_invis["hiding"]) { // set their perception. perception = who->query_skill_bonus("other.perception"); switch(who->check_dark((int)environment(who)->query_light())) { case -2: case 2: perception /= 4; break; case -1: case 1: perception /= 2; break; default: break; } switch(TASKER->attempt_task(hide_invis["hiding"][1], perception, 50)) { case AWARD: who->add_skill_level("other.perception", 1); tell_object(who, "%^YELLOW%^You feel very alert.%^RESET%^\n" ); } } } int attack_by(object ob) { call_out("stop_shadowing", 1); return player->attack_by(ob); } int attack_ob(object ob) { call_out("stop_shadowing", 1); return player->attack_ob(ob); } void do_shadow(object to) { string *direc; int i, found; direc = (environment(player))->query_dest_dir(to); if(sizeof(direc)) { for(i=0; i<sizeof(direc)-1; i+=2) if(direc[i+1] == file_name(to) || direc[i+1] == file_name(to)+".c" || direc[i+1] == file_name(to)+".r") { found = 1; break; } if(found) { if(environment(player)->query_door_open(direc[i]) == 0) { tell_object(player, "You decide not to follow through a closed " "door.\n"); stop_shadowing(); return; } else this_object()->exit_command(direc[i]); return; } } } void event_exit(object ob, string mess, object to) { player->event_exit(ob, mess, to); if(!shadowee) { tell_object(player, "Your victim seems to have disappeared.\n"); stop_shadowing(); } if(environment(shadowee) != environment(ob)) { tell_object(player, "You seem to have lost your target.\n"); stop_shadowing(); } if(ob == shadowee && shadowee->query_visible(player)) call_out("do_shadow", 0, to); }