#include #define USE_FOLLOW /* Experimental "follow" code, see player.c also */ #define MAX_FOLLOWERS 10 #define USE_WETCODE /* Experimental "wet" code */ /* #define USE_MULTS /* Experimental multipliers (turned off) */ #define KILL_NEUTRAL_ALIGNMENT 100 #define ADJ_ALIGNMENT(al) ((-al - KILL_NEUTRAL_ALIGNMENT)/4) #define NAME_OF_GHOST "some mist" /* * If you are going to copy this file, in the purpose of changing * it a little to your own need, beware: * * First try one of the following: * * 1. Do clone_object(), and then configur it. This object is specially * prepared for configuration. * * 2. If you still is not pleased with that, create a new empty * object, and make an inheritance of this objet on the first line. * This will automatically copy all variables and functions from the * original object. Then, add the functions you want to change. The * original function can still be accessed with '::' prepended on the name. * * The maintainer of this LPmud might become sad with you if you fail * to do any of the above. Ask other wizards if you are doubtful. * * The reason of this, is that the above saves a lot of memory. */ /* * Include this file in objects that "lives". * The following variables are defined here: * ....... */ inherit "/obj/property"; #ifdef USE_FOLLOW static object follow_list; /* Objects following us */ static object follow_ob; /* Object we are following */ #endif static int time_to_heal;/* Count down variable. */ int money; /* Amount of money on player. */ string name; /* Name of object. */ string msgin, msgout; /* Messages when entering or leaving a room. */ static int is_npc; int brief; int level; /* Level of monster. */ static int armour_class; /* What armour class of monster. */ int hit_point; /* Number of hit points of monster. */ int max_hp, max_sp; int experience; /* Experience points of monster. */ string mmsgout; /* Message when leaving magically. */ string mmsgin; /* Message when arriving magically. */ static object attacker_ob; /* Name of player attacking us. */ static object alt_attacker_ob; /* Name of other player also attacking us. */ static int weapon_class; /* How good weapon. Used to calculate damage. */ static object name_of_weapon; /* To see if we are wielding a weapon. */ static object head_armour; /* What armour we have. */ int ghost; /* Used for monsters that can leave a ghost. */ static int local_weight; /* weight of items */ static object hunted, hunter; /* used in the hunt mode */ static int hunting_time; /* How long we will stay in hunting mode. */ static string cap_name; /* Capital version of "name". */ int spell_points; /* Current spell points. */ static string spell_name; static int spell_cost, spell_dam; int age; /* Number of heart beats of this character. */ int is_invis; /* True when player is invisible */ int frog; /* If the player is a frog */ int whimpy; /* Automatically run when low on HP */ string auto_load; /* Special automatically loaded objects. */ int dead; /* Are we alive or dead? */ string flags; /* Bit field of flags */ /* * All characters have an aligment, depending on how good or chaotic * they are. * This value is updated when killing other players. */ int alignment; int gender; /* 0 means neuter ("it"), 1 male ("he"), 2 female ("she") */ /* Some functions to set moving messages. */ #define WARRAY ({ "east", "west", "north", "south", "out", "in", "northeast", "southeast", "northwest", "southwest", "up", "down" }) setmout(m) { if (interactive(this_object()) && this_object()->query_level() >= 20 && this_player() != this_object() && this_player()->query_level() <= this_object()->query_level()) return 0; msgout = m; return 1; } setmin(m) { if (interactive(this_object()) && this_object()->query_level() >= 20 && this_player() != this_object() && this_player()->query_level() <= this_object()->query_level()) return 0; msgin = m; return 1; } setmmout(m) { if (interactive(this_object()) && this_object()->query_level() >= 20 && this_player() != this_object() && this_player()->query_level() <= this_object()->query_level()) return 0; mmsgout = m; return 1; } setmmin(m) { if (interactive(this_object()) && this_object()->query_level() >= 20 && this_player() != this_object() && this_player()->query_level() <= this_object()->query_level()) return 0; mmsgin = m; return 1; } query_msgin() { return msgin; } query_msgout() { return msgout; } query_mmsgin() { return mmsgin; } query_mmsgout() { return mmsgout; } /* * Character stat variables. */ int Str, Int, Con, Dex; /* * The following routines are defined for usage: * stop_fight Stop a fight. Good for scroll of taming etc. * hit_player Called when fighting. * transfer_all_to: Transfer all objects to dest. * move_player: Called by the object that moves the monster. * query_name: Gives the name to external objects. * attacked_by Tells us who are attacking us. * show_stats Dump local status. * stop_wielding Called when we drop a weapon. * stop_wearing Called when we drop an armour. * query_level Give our level to external objects. * query_value Always return 0. Can't sell this object. * query_npc Return 1 if npc otherwise 0. * get Always return 0. Can't take this object. * attack Should be called from heart_beat. Will maintain attack. * query_attack * drop_all_money Used when the object dies. * wield Called by weapons. * wear Called by armour. * add_weight Used when picking up things. * heal_self Enable wizards to heal this object. * can_put_and_get Can look at inventory, but not take things from it. * attack_object Called when starting to attack an object. * test_if_any_here For monsters. Call this one if you suspect no enemy * is here any more. * Return 1 if anyone there, 0 if none. * force_us Force us to do a command. * query_spell_points Return how much spell points the character has. * reduce_hit_point Reduce hit points, but not below 0. */ query_living() { return 1; } /* * This routine is called from objects that moves the player. * Special: direction "X" means teleport. * The argument is "how#where". * The second optional argument is an object to move the player to. * If the second argument exists, then the first argument is taken * as the movement message only. */ move_player(dir_dest, optional_dest_ob) { return real_move_player(dir_dest, optional_dest_ob, 0); } static real_move_player(dir_dest, optional_dest_ob, nonlocal) { string dir, dest; object ob; object old_room; int is_light, i; if (!optional_dest_ob) { if (sscanf(dir_dest, "%s#%s", dir, dest) != 2) { tell_object(this_object(), "Move to bad dir/dest\n"); return 0; } } else { dir = dir_dest; dest = optional_dest_ob; } #ifdef USE_FOLLOW follow_update(); #endif hunting_time -= 1; if (hunting_time == 0) { if (hunter) call_other(hunter, "stop_hunter"); hunter = 0; hunted = 0; } if (attacker_ob && present(attacker_ob)) { hunting_time = 10; if (!hunter) tell_object(this_object(), "You are now hunted by " + call_other(attacker_ob, "query_name", 0) + ".\n"); hunter = attacker_ob; } is_light = set_light(0); if(is_light < 0) is_light = 0; if(is_light) { if (!msgout) msgout = "leaves"; if (ghost) say(NAME_OF_GHOST + " " + msgout + " " + dir + ".\n"); else if (dir == "X" && !is_invis) { if (!mmsgout) mmsgout = "disappears in a puff of smoke"; say(cap_name + " " + mmsgout + ".\n"); } else if (!is_invis) say(cap_name + " " + msgout + " " + dir + ".\n"); } move_object(this_object(), dest); is_light = set_light(0); if(is_light < 0) is_light = 0; if (level >= 20) { if (!optional_dest_ob) tell_object(this_object(), "/" + dest + "\n"); } if(is_light) { if (!msgin) msgin = "arrives"; if (ghost) say(NAME_OF_GHOST + " " + msgin + ".\n"); else if (dir == "X" && !is_invis) { if (!mmsgin) mmsgin = "arrives in a puff of smoke"; say(cap_name + " " + mmsgin + ".\n"); } else if (!is_invis) say(cap_name + " " + msgin + ".\n"); } if (hunted && present(hunted)) attack_object(hunted); if (hunter && present(hunter)) call_other(hunter, "attack_object", this_object()); if (!is_npc) { if (environment()->dark("move_player",brief)) return 1; if (!is_light) tell_object(this_object(), "A dark room.\n"); else display_look(environment(this_object()), nonlocal, brief); } #ifdef USE_FOLLOW /* Make the players/NPCs follow me unless I'm teleporting, is invisible or is a ghost */ if (dir != "X" && !is_invis && !ghost) do_follow(dir_dest, optional_dest_ob, dest); #endif return 1; } /* * This function is called from other players when they want to make * damage to us. We return how much damage we received, which will * change the attackers score. This routine is probably called from * heart_beat() from another player. * Compare this function to reduce_hit_point(dam). */ hit_player(dam,ignore_flag) { object party,o; int old_hp,e; string tmp; if (!is_npc && !query_ip_number(this_object())) { /* This player is linkdead. */ write("You cannot fight with statues!\n"); stop_fight(); if (this_player()) this_player()->stop_fight(); return 0; } if (ignore_flag) { log_file("IGNOREFLAG", ctime(time()) + ": " + query_real_name() + " was hit (" + dam + ") by " + this_player()->query_real_name() + "\n"); if (previous_object()) log_file("IGNOREFLAG", "previous_object() = " + file_name(previous_object()) + " (" + previous_object()->query_real_name() + ")\n"); } if (!ignore_flag && environment(this_object()) && environment(this_object())->query_haven()) { write("You try to hit " + query_name() + " but reconsider.\n"); tell_object(this_object(), this_player()->query_name() + " tries to hit you, but reconsiders.\n"); stop_fight(); this_player()->stop_fight(); return 0; } if (this_player() != this_object() /* When entering a room with hunter in it! */ && !ignore_flag && !is_npc && this_player() && !this_player()->query_npc()) { /* A player trying to hit another player */ log_file("PLAYERKILLING", ctime(time()) + ": " + query_real_name() + " was hit (" + dam + ") by " + this_player()->query_real_name() + "\n"); if (previous_object()) log_file("PLAYERKILLING", "previous_object() = " + file_name(previous_object()) + " (" + previous_object()->query_real_name() + ")\n"); if ( !environment(this_object()) || ( !environment(this_object())->query_playerkilling() && (!query_playerkilling() || !this_player()->query_playerkilling()))) { write("You try to hit " + query_name() + " but your conscience stops you.\n"); tell_object(this_object(), this_player()->query_name() + " tries to hit you, but " + this_player()->query_possessive() + " conscience stops " + this_player()->query_objective() + ".\n"); log_file("PLAYERKILLING", "DENIED.\n"); stop_fight(); this_player()->stop_fight(); return 0; } } if (!attacker_ob) set_heart_beat(1); if (!attacker_ob && this_player() != this_object()) attacker_ob = this_player(); else if (!alt_attacker_ob && attacker_ob != this_player() && this_player() != this_object()) alt_attacker_ob = this_player(); /* Don't damage wizards too much ! */ if (level >= 20 && !is_npc && dam >= hit_point) { tell_object(this_object(), "Your wizardhood protects you from death.\n"); return 0; } if(ghost) return 0; /* Or someone who is dead */ dam -= random(armour_class + 1); if (dam <= 0) return 0; if (dam > hit_point+1) dam = hit_point+1; hit_point = hit_point - dam; if (hit_point<0) { object corpse; /* This is how I think "second_life" should have worked from the start. * If "real_second_life" exists and returns non-zero, * the monster doesn't die at all! -- Padrone, July 6, 1992 */ old_hp = hit_point; /* Can be changed in "real_second_life"! */ if (call_other(this_object(), "real_second_life")) { dam += old_hp; /* Subtract excess damage, hp is less than 0 */ if (hit_point < 0) hit_point = 0; return dam; } /* We died ! */ if (is_invis) call_other(this_object(),"vis"); if (hunter) call_other(hunter, "stop_hunter"); hunter = 0; hunted = 0; experience = 2 * experience / 3; /* Nice, isn't it ? */ hit_point = 10; /* The player killing us will update his alignment ! */ /* If he exist */ if(attacker_ob) { call_other(attacker_ob, "add_alignment", ADJ_ALIGNMENT(alignment)); party = present("party object",attacker_ob); if(party) catch(party->share_exp(experience/50)); else attacker_ob->add_exp(experience/50); } dead = 1; corpse = clone_object("obj/corpse"); call_other(corpse, "set_name", name); transfer_all_to(corpse); move_object(corpse, environment(this_object())); if(o=present("DEATH_SAVE",this_object())) { /* profezzorn 930617 */ tmp=file_name(o); catch(e=o->save_me_from_death(this_object())); if(e) { dead=0; log_file("KILLED",query_real_name()+" died, but was saved by "+tmp+".\n"); if(o) destruct(o); return; } } if (environment()) catch(environment()->living_died(corpse)); if(previous_object() && previous_object()!=this_object() && previous_object()!=environment()) catch(previous_object()->kill_callback(corpse)); if(!attacker_ob && interactive(this_object())) { log_file("KILLED", "BUG!! No attacker_ob, prev_obj = " + file_name(previous_object()) + " by "+ creator(previous_object())+"\n"); } if (!call_other(this_object(), "second_life", 0)) { say(cap_name + " died.\n"); /* Mats 910903 */ destruct(this_object()); } if (!is_npc && interactive(this_object())) save_object("players/" + name); } return dam; } transfer_all_to(dest) { object ob; object next_ob; ob = first_inventory(this_object()); while(ob) { next_ob = next_inventory(ob); if (ob->query_weapon() && ob == name_of_weapon) { /* New-style weapon */ ob->unwield(); stop_wielding(); } /* Beware that drop() might destruct the object. */ if (!call_other(ob, "drop", 1) && ob) move_object(ob, dest); ob = next_ob; } local_weight = 0; if (money == 0) return; ob = clone_object("obj/money"); call_other(ob, "set_money", money); move_object(ob, dest); money = 0; } query_name() { if (ghost) return NAME_OF_GHOST; return cap_name; } query_alignment() { return alignment; } query_npc() { return is_npc; } /* * This routine is called when we are attacked by a player. */ attacked_by(ob) { if (!attacker_ob) { attacker_ob = ob; set_heart_beat(1); return; } if (!alt_attacker_ob) { alt_attacker_ob = ob; return; } } show_stats() { int i; string short_desc; short_desc=short(); if (!short_desc) /* Oros 910423 */ short_desc=name; write(capitalize(short_desc) + "\nLevel: " + level + "\nCoins: " + money + "\nHp: " + hit_point + " (max: " + max_hp + ")" + "\nSpell " + spell_points + " (max: " + max_sp + ")"); write("\nEp: "); write(experience); write("\nAc: "); write(armour_class); write("\nArmour: " + (!head_armour?"None":head_armour->rec_short())); write("\nWc: "); write(weapon_class); write("\nWeapon: " + (!name_of_weapon?"None":name_of_weapon->query_name())); write("\nCarry: " + local_weight + "/" + (query_str() + 10)); if (attacker_ob) write("\nAttack: " + attacker_ob->query_name()); if (alt_attacker_ob) write("\nAlt attack:" + alt_attacker_ob->query_name()); write("\nAlign: " + alignment + "\n"); write("Gender: " + query_gender_string() + "\n"); if (i = this_object()->query_quests()) write("Quests: " + i + "\n"); if (i = this_object()->query_quest_points()) write("Quest points (currently): " + i + "\n"); if (i = this_object()->query_my_quest_max()) write("My_Quest_Max: " + i + "\n"); if (i = this_object()->query_puzzles()) write("Puzzles: " + i + "\n"); if (i = this_object()->query_playerkilling()) write("Playerkiller: Yes\n"); write(query_stats()); #ifdef USE_MULTS write(query_stat_mults()); #endif show_age(); } stop_wielding() { if (!name_of_weapon) { return 0; } call_other(name_of_weapon, "un_wield", dead); name_of_weapon = 0; weapon_class = 0; return 1; } silent_stop_wearing(name) { if(!head_armour) { /* This should not happen ! */ log_file("wearing_bug", "armour not worn!\n"); write("This is a bug, no head_armour\n"); return; } head_armour = call_other(head_armour, "remove_link", name); if(head_armour && objectp(head_armour)) armour_class = call_other(head_armour, "tot_ac"); else { armour_class = 0; head_armour = 0; } } stop_wearing(name) { silent_stop_wearing(name); if (!is_npc) if(!dead) say(cap_name + " removes " + name + ".\n"); } query_dead() { return dead; } /* Angmar 920809 */ query_level() { return level; } /* This object is not worth anything in the shop ! */ query_value() { return 0; } /* It is never possible to pick up a player ! */ get() { return 0; } /* * Return true if there still is a fight. */ attack() { int tmp; int whit; string name_of_attacker,hit_array; if (!attacker_ob) { spell_cost = 0; return 0; } name_of_attacker = call_other(attacker_ob, "query_name", 0); if (!name_of_attacker || name_of_attacker == NAME_OF_GHOST || environment(attacker_ob) != environment(this_object())) { if (!hunter && name_of_attacker && !call_other(attacker_ob, "query_ghost", 0)) { tell_object(this_object(), "You are now hunting " + call_other(attacker_ob, "query_name", 0) + ".\n"); hunted = attacker_ob; hunting_time = 10; } attacker_ob = 0; if (!alt_attacker_ob) return 0; attacker_ob = alt_attacker_ob; alt_attacker_ob = 0; if (attack()) { if (!attacker_ob) return 0; tell_object(this_object(), "You turn to attack " + attacker_ob->query_name() + ".\n"); return 1; } return 0; } if (spell_cost) { spell_points -= spell_cost; tell_object(attacker_ob, "You are hit by a " + spell_name + ".\n"); write("You cast a " + spell_name + ".\n"); } if(name_of_weapon) whit = call_other(name_of_weapon,"hit",attacker_ob); if(whit != "miss") { tmp = ((weapon_class + whit) * 2 + query_dex()) / 3; if (tmp == 0) tmp = 1; if (attacker_ob && call_other(attacker_ob, "query_name", 0) != NAME_OF_GHOST) tmp = call_other(attacker_ob, "hit_player", random(tmp) + spell_dam); } else tmp = 0; /* tmp -= spell_dam; if (!is_npc) if (name_of_weapon && tmp > 20 && random(100) < tmp - 20) { tell_object(this_object(), "CRACK!\nYour weapon broke!\n"); log_file("BAD_SWORD", name_of_weapon->short() + ", " + creator(name_of_weapon) + "\n"); spell_cost = 0; spell_dam = 0; destruct(name_of_weapon); weapon_class = 0; return 1; } tmp += spell_dam; */ hit_array = 0; if (tmp == 0) { spell_cost = 0; spell_dam = 0; if (name_of_weapon) hit_array = name_of_weapon->get_hit_lines(0,attacker_ob,this_object()); if (!pointerp(hit_array) || sizeof(hit_array) != 3) { tell_object(this_object(), "You missed.\n"); say(cap_name + " missed " + name_of_attacker + ".\n"); } else { tell_object(attacker_ob,hit_array[0]); tell_object(this_object(),hit_array[1]); say(hit_array[2],attacker_ob); } return 1; } if(tmp<0) { log_file("NEGATIVE_DAMAGE",sprintf("on: %O by: %s , %s\n",attacker_ob,query_real_name(),ctime(time()))); } experience += tmp; tmp -= spell_dam; spell_cost = 0; spell_dam = 0; /* Does the enemy still live ? */ if (attacker_ob && call_other(attacker_ob, "query_name", 0) != NAME_OF_GHOST) { string how, what; if (name_of_weapon) { hit_array = name_of_weapon->get_hit_lines(tmp,attacker_ob,this_object()); if (pointerp(hit_array) && sizeof(hit_array) == 3) { tell_object(attacker_ob,hit_array[0]); tell_object(this_object(),hit_array[1]); say(hit_array[2],attacker_ob); return 1; } } how = " to small fragments"; what = "massacre"; if (tmp < 30) { how = " with a bone crushing sound"; what = "smash"; } if (tmp < 20) { how = " very hard"; what = "hit"; } if (tmp < 10) { how = " hard"; what = "hit"; } if (tmp < 5) { how = ""; what = "hit"; } if (tmp < 3) { how = ""; what = "grazed"; } if (tmp == 1) { how = " in the stomach"; what = "tickled"; } tell_object(this_object(), "You " + what + " " + name_of_attacker + how + ".\n"); tell_object(attacker_ob, cap_name + " " + what + " you" + how + ".\n"); say(cap_name + " " + what + " " + name_of_attacker + how + ".\n", attacker_ob); return 1; } tell_object(this_object(), "You killed " + name_of_attacker + ".\n"); attacker_ob = alt_attacker_ob; alt_attacker_ob = 0; if (attacker_ob) return 1; } query_attack() { /* Changed by Herder */ return attacker_ob; /* OLD if (attacker_ob) return 1; return 0; */ } query_alt_attack() { return alt_attacker_ob; } drop_all_money(verbose) { drop_money(money, !verbose); } drop_money(howmuch, silent) { object mon; if (howmuch < 0) { if (!silent) tell_object(this_object(), "You don't have negative coins.\n"); return 0; } if (money < howmuch) { if (!silent) tell_object(this_object(), "You don't have that much money.\n"); return 0; } mon = clone_object("obj/money"); mon->set_money(howmuch); move_object(mon, environment()); if (!silent) if (howmuch == 1) { say(cap_name + " drops a gold coin.\n"); tell_object(this_object(), "You drop a gold coin.\n"); } else if (howmuch == money) { say(cap_name + " drops " + howmuch + " gold coins.\n"); tell_object(this_object(), "You drop all your money.\n"); } else { say(cap_name + " drops " + howmuch + " gold coins.\n"); tell_object(this_object(), "You drop " + howmuch + " gold coins.\n"); } money -= howmuch; return 1; } /* Wield a weapon. */ wield(w) { int retcode; retcode = silent_wield(w); if (!retcode) write("You cannot wield that!\n"); else write("Ok.\n"); return retcode; } silent_wield(w) { int wc; string str; /*Qqqq 930804 Added cursed ability on weapons*/ if (name_of_weapon && (str = name_of_weapon->query_property("cursed"))) { if (stringp(str)) write(str); else write("You can't unwield it, it seems to be cursed.\n"); return 0; } wc = w->query_class(); if (!wc) { wc = w->weapon_class(); if (!wc) return 0; } if (w->query_weapon()) if (!w->wield()) return 0; if (name_of_weapon) stop_wielding(); weapon_class = wc; name_of_weapon = w; return 1; } query_wield() { /* Lpd 920121 */ return query_wielded(); } query_wielded() { /* Anvil 910423 */ return name_of_weapon ? ({ name_of_weapon }) : 0; } /* Wear some armour. */ wear(a) { object old; if(head_armour) { old = call_other(head_armour, "test_type", call_other(a, "query_type")); if(old) return old; old = head_armour; call_other(a, "link", old); } head_armour = a; /* Calculate new ac */ armour_class = call_other(head_armour, "tot_ac"); say(cap_name + " wears " + call_other(a, "query_name", 0) + ".\n"); write("Ok.\n"); return 0; } silent_wear(a) { object old; if(head_armour) { old = call_other(head_armour, "test_type", call_other(a, "query_type")); if(old) return old; old = head_armour; call_other(a, "link", old); } head_armour = a; /* Calculate new ac */ armour_class = call_other(head_armour, "tot_ac"); return 0; } query_head_armour() { return head_armour; } add_weight(w) { if (w + local_weight > query_str() + 10 && level < 20) return 0; local_weight += w; return 1; } query_weight() { return local_weight; } heal_self(h) { if (h <= 0) return; hit_point += h; if (hit_point > max_hp) hit_point = max_hp; spell_points += h; if (spell_points > max_sp) spell_points = max_sp; } restore_spell_points(h) { spell_points += h; if (spell_points > max_sp) spell_points = max_sp; } can_put_and_get(str) { return str != 0; } attack_object(ob) { if (call_other(ob, "query_ghost", 0)) return; set_heart_beat(1); /* For monsters, start the heart beat */ if (attacker_ob == ob) { attack(); return; } if (alt_attacker_ob == ob) { alt_attacker_ob = attacker_ob; attacker_ob = ob; attack(); return; } if (!alt_attacker_ob) alt_attacker_ob = attacker_ob; attacker_ob = ob; call_other(attacker_ob, "attacked_by", this_object()); attack(); } query_ghost() { return ghost; } zap_object(ob) { log_file("ZAP",sprintf("%s zapped %O, %s\n",query_real_name(),ob,ctime(time()))); call_other(ob, "attacked_by", this_object()); say(cap_name + " summons a flash from the sky.\n"); write("You summon a flash from the sky.\n"); experience += call_other(ob, "hit_player", 100000); write("There is a big clap of thunder.\n\n"); } missile_object(ob) { if (spell_points < 10) { write("Too low on power.\n"); return; } spell_name = "magic missile"; spell_dam = random(20); spell_cost = 10; attacker_ob = ob; } shock_object(ob) { if (spell_points < 15) { write("Too low on power.\n"); return; } spell_name = "shock"; spell_dam = random(30); spell_cost = 15; attacker_ob = ob; } fire_ball_object(ob) { if (spell_points < 20) { write("Too low on power.\n"); return; } spell_name = "fire ball"; spell_dam = random(40); spell_cost = 20; attacker_ob = ob; } /* * If no one is here (except ourself), then turn off the heart beat. */ test_if_any_here() { object ob; ob = environment(); if (!ob) return 0; ob = first_inventory(environment()); while(ob) { if (ob != this_object() && living(ob) && !call_other(ob, "query_npc")) return 1; ob = next_inventory(ob); } return 0; } show_age() { int i; write("age:\t"); i = age; if (i/43200) { write(i/43200 + " days "); i = i - (i/43200)*43200; } if (i/1800) { write(i/1800 + " hours "); i = i - (i/1800)*1800; } if (i/30) { write(i/30 + " minutes "); i = i - (i/30)*30; } write(i*2 + " seconds.\n"); } stop_hunter() { if (hunter != 0) { hunter = 0; tell_object(this_object(), "You are no longer hunted.\n"); } } /* * This function remains only because of compatibility, as command() now * can be called with an object as argument. */ force_us(string cmd) { if (!this_player(1) || this_player(1)->query_level() <= level || query_ip_number(this_player(1)) == 0) { tell_object(this_object(), this_player()->query_name() + " failed to force you to " + cmd + "\n"); return; } return command(cmd); } /* This is used by the shop etc. */ add_money(m) { #ifdef LOG_EXP if (this_player() && this_player() != this_object() && query_ip_number(this_player()) && query_ip_number(this_object()) && level < 20 && m >= ROOM_EXP_LIMIT) log_file("EXPERIENCE", ctime(time()) + " " +name + "(" + level + ") " + m + " money by " + this_player()->query_real_name() + "(" + this_player()->query_level() + ")\n"); #endif if (!intp(m)) return 0; money = money + m; if (level <= 19 && !is_npc) add_worth(m); } query_money() { return money; } query_exp() { return experience; } query_frog() { return frog; } frog_curse(arg) { if (arg) { if (frog) return 1; tell_object(this_object(), "You turn into a frog !\n"); frog = 1; if (interactive(this_object())) this_object()->drop_all(1); return 1; } tell_object(this_object(), "You turn HUMAN again.\n"); frog = 0; return 0; } run_away() { /* out and exit added by Pell 910627 */ /* ne se sw nw added by Mats 921124 */ /* warray made local variable by Profezzorn 930514 */ object here; int i, j,storlek; string *warray; warray=WARRAY; here = environment(); i = 0; j = random(storlek = sizeof(warray)); while(i= storlek) j = 0; command(warray[j]); } if (here == environment()) { say(cap_name + " tried, but failed to run away.\n", this_object()); tell_object(this_object(), "Your legs tried to run away, but failed.\n"); } else { tell_object(this_object(), "Your legs run "+warray[j]+" with you!\n"); } } int query_hp() { return hit_point; } int query_wimpy() { return whimpy; } string query_current_room() { return file_name(environment(this_object())); } int query_spell_points() { return spell_points; } int query_max_sp() { /*Added by Qqqq 920111*/ return max_sp; } int query_max_hp() { /* Angmar 901104 */ return max_hp; } void stop_fight() { attacker_ob = alt_attacker_ob; alt_attacker_ob = 0; } int query_wc() { return weapon_class; } int query_ac() { return armour_class; } reduce_hit_point(dam) { object o; if(this_player()!=this_object()) { log_file("REDUCE_HP",query_name()+" ("+dam+" hp) by "); if(!this_player()) log_file("REDUCE_HP","?\n"); else { log_file("REDUCE_HP",this_player()->query_name()); o=previous_object(); if (o) log_file("REDUCE_HP", " " + file_name(o) + ", " + o->short() + " (" + creator(o) + ")\n"); else log_file("REDUCE_HP", " ??\n"); } } /* this will detect illegal use of reduce_hit_point in weapons */ hit_point -= dam; if (hit_point <= 0) hit_point = 1; /* if(hit_point > max_hp) hit_point = max_hp; */ return hit_point; } query_age() { return age; } /*----------- Most of the gender handling here: ------------*/ query_gender() { return gender; } query_neuter() { return !gender; } query_male() { return gender == 1; } query_female() { return gender == 2; } set_gender(g) { if (g == 0 || g == 1 || g == 2) gender = g; } set_neuter() { gender = 0; } set_male() { gender = 1; } set_female() { gender = 2; } query_gender_string() { if (!gender) return "neuter"; else if (gender == 1) return "male"; else return "female"; } query_pronoun() { if (!gender) return "it"; else if (gender == 1) return "he"; else return "she"; } query_possessive() { if (!gender) return "its"; else if (gender == 1) return "his"; else return "her"; } query_objective() { if (!gender) return "it"; else if (gender == 1) return "him"; else return "her"; } /* * Flags manipulations. You are not supposed to do this arbitrarily. * Every wizard can allocate a few bits from the administrator, which * he then may use. If you mainpulate bits that you don't know what they * are used for, unexpected things can happen. */ set_flag(n) { if (flags == 0) flags = ""; #ifdef LOG_FLAGS log_file("FLAGS", name + " bit " + n + " set\n"); if (previous_object()) { if (this_player() && this_player() != this_object() && query_ip_number(this_player())) log_file("FLAGS", "Done by " + this_player()->query_real_name() + " using " + file_name(previous_object()) + ".\n"); } #endif flags = set_bit(flags, n); } test_flag(n) { if (flags == 0) flags = ""; return test_bit(flags, n); } clear_flag(n) { if (flags == 0) flags = ""; #ifdef LOG_FLAGS log_file("FLAGS", name + " bit " + n + " cleared\n"); if (previous_object()) { if (this_player() && this_player() != this_object() && query_ip_number(this_player())) log_file("FLAGS", "Done by " + this_player()->query_real_name() + " using " + file_name(previous_object()) + ".\n"); } #endif flags = clear_bit(flags, n); return 1; } query_stats() { #ifdef USE_MULTS return sprintf("Str:%7d (%2d)\nInt:%7d (%2d)\nCon:%7d (%2d)\nDex:%7d (%2d)\n", query_str(),Str,query_int(),Int,query_con(),Con,query_dex(),Dex); #else return sprintf("Str: %d\nInt: %d\nCon: %d\nDex: %d\n", query_str(),query_int(),query_con(),query_dex()); #endif } /* All the *_Mult stuff added by Milamber */ int Str_Mult=10,Int_Mult=10,Con_Mult=10,Dex_Mult=10; #define Q_S_M(ST) sprintf("ST : %6d.%d\n", ST / 10 , ST % 10) string query_stat_mults() { return (Q_S_M(Str_Mult)+ Q_S_M(Int_Mult)+ Q_S_M(Con_Mult)+ Q_S_M(Dex_Mult)); } #ifdef USE_MULTS query_str() { return (Str*Str_Mult)/10; } query_int() { return (Int*Int_Mult)/10; } query_con() { return (Con*Con_Mult)/10; } query_dex() { return (Dex*Dex_Mult)/10; } #else query_str() { return Str; } query_int() { return Int; } query_con() { return Con; } query_dex() { return Dex; } #endif query_real_str() { return Str; } query_real_int() { return Int; } query_real_con() { return Con; } query_real_dex() { return Dex; } query_str_mult() { return Str_Mult; } query_int_mult() { return Int_Mult; } query_con_mult() { return Con_Mult; } query_dex_mult() { return Dex_Mult; } set_str_mult(i) { #ifdef LOG_SET_MULT log_file("MULT", cap_name + ": str_mult set to " + i + "\n"); if (previous_object()) { log_file("MULT", "Done by " + (this_player()?this_player()->query_real_name():"Noone") + " using " +file_name(previous_object()) + ".\n"); } #endif Str_Mult=i; } set_int_mult(i) { #ifdef LOG_SET_MULT log_file("MULT", cap_name + ": int_mult set to " + i + "\n"); if (previous_object()) { log_file("MULT", "Done by " + (this_player()?this_player()->query_real_name():"Noone") + " using " +file_name(previous_object()) + ".\n"); } #endif Int_Mult=i; max_sp = 42 + query_int() * 8; if(spell_points>max_sp) spell_points=max_sp; } set_con_mult(i) { #ifdef LOG_SET_MULT log_file("MULT", cap_name + ": con_mult set to " + i + "\n"); if (previous_object()) { log_file("MULT", "Done by " + (this_player()?this_player()->query_real_name():"Noone") + " using " +file_name(previous_object()) + ".\n"); } #endif Con_Mult=i; max_hp = 42 + query_con() * 8; if(hit_point>max_hp) hit_point=max_hp; } set_dex_mult(i) { #ifdef LOG_SET_MULT log_file("MULT", cap_name + ": dex_mult set to " + i + "\n"); if (previous_object()) { log_file("MULT", "Done by " + (this_player()?this_player()->query_real_name():"Noone") + " using " +file_name(previous_object()) + ".\n"); } #endif Dex_Mult=i; } void reset_mults() { set_str_mult(10); set_int_mult(10); set_con_mult(10); set_dex_mult(10); } set_str(i) { if (i<1 || i > 20) return; Str = i; } set_int(i) { if (i<1 || i > 20) return; Int = i; max_sp = 42 + query_int() * 8; } set_con(i) { if (i<1 || i > 20) return; Con = i; max_hp = 42 + query_con() * 8; } set_dex(i) { if (i<1 || i > 20) return; Dex = i; } /* Oros 911208 -- Added because of problem with commanders room and 3.0 */ d_comm() { if(this_player() && interactive(this_player()) && (this_player()->query_level() > 21)) disable_commands(); } e_comm() { enable_commands(); } /* Experimental support for "follow" */ #ifdef USE_FOLLOW static is_follower(ob) { int i; if (follow_list) for (i = 0; i < sizeof(follow_list); i++) if (follow_list[i] == ob) return i; return -1; } query_followers() { return follow_list; } /* If argument 'ob' exists, check if that object is following us else return the object we are following */ query_follow(ob) { if (!ob) return follow_ob; if (is_follower(ob) != -1) return ob; return 0; } /* If argument 'ob' exists, follow that object else register caller as a follower to us */ start_follow(ob) { int i; object ob2; if (ob) { /* Get serious, we can't follow ourself, can we? */ if (ob == this_object()) return 0; /* Check for follow loops */ ob2 = ob; while ((ob2 = ob2->query_follow()) && ob2 != this_object()) ; if (ob2) return 0; if (ob->start_follow() == 0) return 0; follow_ob = ob; return ob; } else { ob = previous_object(); /* Get serious, we can't follow ourself, can we? */ if (!ob || ob == this_object()) return 0; if (is_follower(ob) != -1) return 0; if (!follow_list) follow_list = allocate(MAX_FOLLOWERS); for (i = 0; i < sizeof(follow_list); i++) if (follow_list[i] == 0) { follow_list[i] = ob; return ob; } } return 0; } /* If argument 'ob' exists, stop it from following us else stop following someone */ stop_follow(ob) { int i; if (ob) { /* Remove it from our follower-list */ i = is_follower(ob); if (i == -1) return 0; follow_list[i] = 0; /* Is it following us? */ if (ob->query_follow() != this_object()) return 0; /* Make it stop following us */ if (ob->stop_follow() == 0) return 0; return ob; } else { /* Stop following someone */ if (!follow_ob) return 0; ob = follow_ob; follow_ob = 0; /* Are we in it's follow-list? */ if (ob->query_follow(this_object()) == 0) return 0; /* Remove us from it's follow-list */ if (ob->stop_follow(this_object()) == 0) return 0; return ob; } return 0; } /* Make sure only players/NPCs in the same room are in the follow list */ static follow_update() { int i, c; c = 0; if (follow_list) for (i = 0; i < sizeof(follow_list); i++) { if (follow_list[i]) { /* Follower isn't in the same room */ if (environment(follow_list[i]) != environment(this_object())) stop_follow(follow_list[i]); /* Follower isn't following us! Strange.. */ else if (follow_list[i]->query_follow() != this_object()) stop_follow(follow_list[i]); else c++; } } if (c == 0) follow_list = 0; return c; } /* Make the players/NPCs follow me */ static do_follow(dir_dest, optional_dest_ob, dest) { int i, c; c = 0; if (follow_list) for (i = 0; i < sizeof(follow_list); i++) if (follow_list[i]) if (dest->query_prevent_follow(follow_list[i])) follow_list[i]->stop_follow(); else { follow_list[i]->follow_player(dir_dest, optional_dest_ob); c++; } return c; } /* Handle remote follow trigger */ follow_player(dir_dest, optional_dest_ob) { /* Only the object we are following may call this function */ if (query_follow() != previous_object()) return 0; tell_object(this_object(), "You follow " + capitalize(previous_object()->query_real_name()) + ".\n"); return real_move_player(dir_dest, optional_dest_ob, 1); } #endif #ifdef USE_WETCODE int wet_time; query_wet() { return wet_time; } set_wet(time) { if (!time) time = 360; if (wet_time == 0 && interactive(this_object())) call_out("say_wet", 1, time); set_heart_beat(1); wet_time = time; return 1; } say_wet(time) { if (time > 1000) tell_object(this_object(), "Suddenly, you are very wet!\n"); else if (time > 600) tell_object(this_object(), "You get soaking wet.\n"); else if (time > 400) tell_object(this_object(), "You get wet all over.\n"); else if (time > 200) tell_object(this_object(), "You get wet.\n"); else tell_object(this_object(), "You get rather wet.\n"); } reset_wet(arg) { wet_time = 0; tell_object(this_object(), "You are dry again.\n"); } #endif display_look(ob, nonlocal, brief) { string desc; int i; if ((brief || nonlocal) && ob->short()) tell_object(this_object(), capitalize(ob->short()) + ".\n"); else { desc = ob->query_long_desc(); if (desc) tell_object(this_object(), desc); else ob->long(); } for (i=0, ob=first_inventory(ob); ob; ob = next_inventory(ob)) { if (ob != this_object()) { string short_str; short_str = ob->short(); if (short_str && stringp(short_str)) tell_object(this_object(), capitalize(short_str) + ".\n"); } /* if (i++ > 40) { tell_object(this_object(), "*** TRUNCATED\n"); break; }*/ } } query_real_name() { return name; }