/*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ***************************************************************************/ /* MurkMUD++ - A Windows compatible, C++ compatible Merc 2.2 Mud. \author Jon A. Lambert \date 01/02/2007 \version 1.5 \remarks This source code copyright (C) 2005, 2006, 2007 by Jon A. Lambert All rights reserved. Use governed by the MurkMUD++ public license found in license.murk++ */ #include "os.hpp" #include "config.hpp" #include "globals.hpp" #include "io.hpp" #include "utils.hpp" #include "pcdata.hpp" #include "affect.hpp" #include "area.hpp" #include "room.hpp" #include "mobproto.hpp" #include "objproto.hpp" #include "exit.hpp" #include "extra.hpp" #include "object.hpp" #include "descriptor.hpp" #include "ban.hpp" #include "shop.hpp" #include "reset.hpp" #include "note.hpp" #include "database.hpp" #include "world.hpp" // Temp externs extern Room *find_location (Character * ch, const std::string & arg); extern Character *find_keeper (Character * ch); extern int get_cost (Character * keeper, Object * obj, bool fBuy); extern std::string extra_bit_name (int extra_flags); extern void obj_cast_spell (int sn, int level, Character * ch, Character * victim, Object * obj); extern void talk_channel (Character * ch, const std::string & argument, int channel, const char *verb); extern void multi_hit(Character *ch, Character *victim, int dt); extern void say_spell (Character * ch, int sn); extern void raw_kill (Character * victim); extern bool is_same_group (Character * ach, Character * bch); extern std::string affect_loc_name (int location); extern std::string affect_bit_name (int vector); extern void mprog_bribe_trigger (Character * mob, Character * ch, int amount); extern void mprog_speech_trigger (const std::string & txt, Character * mob); extern void mprog_give_trigger (Character * mob, Character * ch, Object * obj); extern Object *create_money (int amount); extern void note_attach (Character * ch); extern void note_remove (Character * ch, Note * pnote); extern void damage(Character *ch, Character *victim, int dam, int dt); extern void check_killer (Character * ch, Character * victim); extern std::string get_extra_descr (const std::string & name, std::list<ExtraDescription *> & ed); extern bool is_safe (Character * ch, Character * victim); extern void disarm (Character * ch, Character * victim); void Character::do_areas (std::string argument) { send_to_char (g_world->list_areas()); return; } void Character::do_memory (std::string argument) { char buf[MAX_STRING_LENGTH]; snprintf (buf, sizeof buf, "Affects %5d\r\n", Affect::top_affect); send_to_char (buf); snprintf (buf, sizeof buf, "Areas %5d\r\n", Area::top_area); send_to_char (buf); snprintf (buf, sizeof buf, "ExDes %5d\r\n", ExtraDescription::top_ed); send_to_char (buf); snprintf (buf, sizeof buf, "Exits %5d\r\n", Exit::top_exit); send_to_char (buf); snprintf (buf, sizeof buf, "Mobs %5d\r\n", MobPrototype::top_mob); send_to_char (buf); snprintf (buf, sizeof buf, "Objs %5d\r\n", ObjectPrototype::top_obj); send_to_char (buf); snprintf (buf, sizeof buf, "Resets %5d\r\n", Reset::top_reset); send_to_char (buf); snprintf (buf, sizeof buf, "Rooms %5d\r\n", Room::top_room); send_to_char (buf); snprintf (buf, sizeof buf, "Shops %5d\r\n", Shop::top_shop); send_to_char (buf); return; } void Character::do_kill (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Kill whom?\r\n"); return; } Character *victim; if ((victim = get_char_room (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (!victim->is_npc ()) { if (!IS_SET (victim->actflags, PLR_KILLER) && !IS_SET (victim->actflags, PLR_THIEF)) { send_to_char ("You must MURDER a player.\r\n"); return; } } else { if (victim->is_affected (AFF_CHARM) && victim->master != NULL) { send_to_char ("You must MURDER a charmed creature.\r\n"); return; } } if (victim == this) { send_to_char ("You hit yourself. Ouch!\r\n"); multi_hit (this, this, TYPE_UNDEFINED); return; } if (is_safe (this, victim)) return; if (is_affected (AFF_CHARM) && master == victim) { act ("$N is your beloved master.", NULL, victim, TO_CHAR); return; } if (position == POS_FIGHTING) { send_to_char ("You do the best you can!\r\n"); return; } wait_state (1 * PULSE_VIOLENCE); check_killer (this, victim); multi_hit (this, victim, TYPE_UNDEFINED); return; } void Character::do_murde (std::string argument) { send_to_char ("If you want to MURDER, spell it out.\r\n"); return; } void Character::do_murder (std::string argument) { std::string arg, buf; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Murder whom?\r\n"); return; } Character *victim; if ((victim = get_char_room (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (victim == this) { send_to_char ("Suicide is a mortal sin.\r\n"); return; } if (is_safe (this, victim)) return; if (is_affected (AFF_CHARM) && master == victim) { act ("$N is your beloved master.", NULL, victim, TO_CHAR); return; } if (position == POS_FIGHTING) { send_to_char ("You do the best you can!\r\n"); return; } wait_state (1 * PULSE_VIOLENCE); buf += "Help! I am being attacked by " + name + "!"; victim->do_shout (buf); check_killer (this, victim); multi_hit (this, victim, TYPE_UNDEFINED); return; } void Character::do_backstab (std::string argument) { std::string arg; if (!is_npc () && level < skill_table[skill_lookup("backstab")].skill_level[klass]) { send_to_char ("You better leave the assassin trade to thieves.\r\n"); return; } one_argument (argument, arg); if (arg.empty()) { send_to_char ("Backstab whom?\r\n"); return; } Character *victim; if ((victim = get_char_room (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (victim == this) { send_to_char ("How can you sneak up on yourself?\r\n"); return; } if (is_safe (this, victim)) return; Object *obj; if ((obj = get_eq_char (WEAR_WIELD)) == NULL || obj->value[3] != 11) { send_to_char ("You need to wield a piercing weapon.\r\n"); return; } if (victim->fighting != NULL) { send_to_char ("You can't backstab a fighting person.\r\n"); return; } if (victim->hit < victim->max_hit) { act ("$N is hurt and suspicious ... you can't sneak up.", NULL, victim, TO_CHAR); return; } check_killer (this, victim); int bck = skill_lookup("backstab"); wait_state (skill_table[bck].beats); if (!victim->is_awake () || is_npc () || number_percent () < pcdata->learned[bck]) multi_hit (this, victim, bck); else damage (this, victim, 0, bck); return; } void Character::do_flee (std::string argument) { if (fighting == NULL) { if (position == POS_FIGHTING) position = POS_STANDING; send_to_char ("You aren't fighting anyone.\r\n"); return; } Room *now_in; Room* was_in = in_room; for (int attempt = 0; attempt < 6; attempt++) { Exit *pexit; int door; door = number_door (); if ((pexit = was_in->exit[door]) == 0 || pexit->to_room == NULL || IS_SET (pexit->exit_info, EX_CLOSED) || (is_npc () && (IS_SET (pexit->to_room->room_flags, ROOM_NO_MOB) || (IS_SET (actflags, ACT_STAY_AREA) && pexit->to_room->area != in_room->area)))) continue; move_char (door); if ((now_in = in_room) == was_in) continue; in_room = was_in; act ("$n has fled!", NULL, NULL, TO_ROOM); in_room = now_in; if (!is_npc ()) { send_to_char ("You flee from combat! You lose 25 exps.\r\n"); gain_exp(-25); } stop_fighting(true); return; } send_to_char ("You failed! You lose 10 exps.\r\n"); gain_exp(-10); return; } void Character::do_rescue (std::string argument) { if (!is_npc () && level < skill_table[skill_lookup("rescue")].skill_level[klass]) { send_to_char ("You better leave the heroic acts to warriors.\r\n"); return; } std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Rescue whom?\r\n"); return; } Character *victim; if ((victim = get_char_room (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (victim == this) { send_to_char ("What about fleeing instead?\r\n"); return; } if (!is_npc () && victim->is_npc ()) { send_to_char ("Doesn't need your help!\r\n"); return; } if (fighting == victim) { send_to_char ("Too late.\r\n"); return; } Character *fch; if ((fch = victim->fighting) == NULL) { send_to_char ("That person is not fighting right now.\r\n"); return; } int rsc = skill_lookup("rescue"); wait_state (skill_table[rsc].beats); if (!is_npc () && number_percent () > pcdata->learned[rsc]) { send_to_char ("You fail the rescue.\r\n"); return; } act ("You rescue $N!", NULL, victim, TO_CHAR); act ("$n rescues you!", NULL, victim, TO_VICT); act ("$n rescues $N!", NULL, victim, TO_NOTVICT); fch->stop_fighting(false); victim->stop_fighting(false); check_killer (this, fch); set_fighting(fch); fch->set_fighting(this); return; } void Character::do_kick (std::string argument) { if (!is_npc () && level < skill_table[skill_lookup("kick")].skill_level[klass]) { send_to_char ("You better leave the martial arts to fighters.\r\n"); return; } Character *victim; if ((victim = fighting) == NULL) { send_to_char ("You aren't fighting anyone.\r\n"); return; } int kck = skill_lookup("kick"); wait_state (skill_table[kck].beats); if (is_npc () || number_percent () < pcdata->learned[kck]) damage (this, victim, number_range (1, level), kck); else damage (this, victim, 0, kck); return; } void Character::do_disarm (std::string argument) { if (!is_npc () && level < skill_table[skill_lookup("disarm")].skill_level[klass]) { send_to_char ("You don't know how to disarm opponents.\r\n"); return; } if (get_eq_char (WEAR_WIELD) == NULL) { send_to_char ("You must wield a weapon to disarm.\r\n"); return; } Character *victim; if ((victim = fighting) == NULL) { send_to_char ("You aren't fighting anyone.\r\n"); return; } if (victim->get_eq_char (WEAR_WIELD) == NULL) { send_to_char ("Your opponent is not wielding a weapon.\r\n"); return; } wait_state (skill_table[skill_lookup("disarm")].beats); int percent = number_percent () + victim->level - level; if (is_npc () || percent < pcdata->learned[skill_lookup("disarm")] * 2 / 3) disarm (this, victim); else send_to_char ("You failed.\r\n"); return; } void Character::do_sla (std::string argument) { send_to_char ("If you want to SLAY, spell it out.\r\n"); return; } void Character::do_slay (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Slay whom?\r\n"); return; } Character *victim; if ((victim = get_char_room (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (this == victim) { send_to_char ("Suicide is a mortal sin.\r\n"); return; } if (!victim->is_npc () && victim->level >= level) { send_to_char ("You failed.\r\n"); return; } act ("You slay $M in cold blood!", NULL, victim, TO_CHAR); act ("$n slays you in cold blood!", NULL, victim, TO_VICT); act ("$n slays $N in cold blood!", NULL, victim, TO_NOTVICT); raw_kill (victim); return; } void Character::do_cast (std::string argument) { /* * Only MOBprogrammed mobs not charmed can cast spells * like PC's */ if (is_npc () && (!pIndexData->progtypes || is_affected (AFF_CHARM))) return; std::string arg1, arg2; target_name = one_argument (argument, arg1); one_argument (target_name, arg2); if (arg1.empty()) { send_to_char ("Cast which what where?\r\n"); return; } int sn; if ((sn = skill_lookup (arg1)) < 0 || (!is_npc () && level < skill_table[sn].skill_level[klass])) { send_to_char ("You can't do that.\r\n"); return; } if (position < skill_table[sn].minimum_position) { send_to_char ("You can't concentrate enough.\r\n"); return; } int mn = mana_cost (sn); /* * Locate targets. */ Character *victim = NULL; Object *obj; void *vo = NULL; switch (skill_table[sn].target) { default: bug_printf ("Do_cast: bad target for sn %d.", sn); return; case TAR_IGNORE: break; case TAR_CHAR_OFFENSIVE: if (arg2.empty()) { if ((victim = fighting) == NULL) { send_to_char ("Cast the spell on whom?\r\n"); return; } } else { if ((victim = get_char_room (arg2)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } } vo = (void *) victim; break; case TAR_CHAR_DEFENSIVE: if (arg2.empty()) { victim = this; } else { if ((victim = get_char_room (arg2)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } } vo = (void *) victim; break; case TAR_CHAR_SELF: if (!arg2.empty() && !is_name (arg2, name)) { send_to_char ("You cannot cast this spell on another.\r\n"); return; } vo = (void *) this; break; case TAR_OBJ_INV: if (arg2.empty()) { send_to_char ("What should the spell be cast upon?\r\n"); return; } if ((obj = get_obj_carry (arg2)) == NULL) { send_to_char ("You are not carrying that.\r\n"); return; } vo = (void *) obj; break; } if (!is_npc () && mana < mn) { send_to_char ("You don't have enough mana.\r\n"); return; } if (str_cmp (skill_table[sn].name, "ventriloquate")) say_spell (this, sn); wait_state (skill_table[sn].beats); if (!is_npc () && number_percent () > pcdata->learned[sn]) { send_to_char ("You lost your concentration.\r\n"); mana -= mn / 2; } else { mana -= mn; (this->*(skill_table[sn].spell_fun)) (sn, level, vo); } if (skill_table[sn].target == TAR_CHAR_OFFENSIVE && victim->master != this && victim != this) { Character *vch; CharIter rch, next; for (rch = in_room->people.begin(); rch != in_room->people.end(); rch = next) { vch = *rch; next = ++rch; if (victim == vch && victim->fighting == NULL) { multi_hit (victim, this, TYPE_UNDEFINED); break; } } } return; } /* Date stamp idea comes from Alander of ROM */ void Character::do_note (std::string argument) { if (is_npc ()) return; std::string arg, buf1; argument = one_argument (argument, arg); smash_tilde (argument); if (arg.empty()) { do_note ("read"); return; } char buf[MAX_STRING_LENGTH]; int vnum; int anum; if (!str_cmp (arg, "list")) { vnum = 0; for (std::list<Note*>::iterator p = note_list.begin(); p != note_list.end(); p++) { if ((*p)->is_note_to (this)) { snprintf (buf, sizeof buf, "[%3d%s] %s: %s\r\n", vnum, ((*p)->date_stamp > last_note && str_cmp ((*p)->sender, name)) ? "N" : " ", (*p)->sender.c_str(), (*p)->subject.c_str()); buf1.append(buf); vnum++; } } send_to_char (buf1); return; } if (!str_cmp (arg, "read")) { bool fAll; if (!str_cmp (argument, "all")) { fAll = true; anum = 0; } else if (argument.empty() || !str_prefix (argument, "next")) /* read next unread note */ { vnum = 0; for (std::list<Note*>::iterator p = note_list.begin(); p != note_list.end(); p++) { if ((*p)->is_note_to (this) && str_cmp (name, (*p)->sender) && last_note < (*p)->date_stamp) { snprintf (buf, sizeof buf, "[%3d] %s: %s\r\n%s\r\nTo: %s\r\n", vnum, (*p)->sender.c_str(), (*p)->subject.c_str(), (*p)->date.c_str(), (*p)->to_list.c_str()); buf1.append(buf); buf1.append((*p)->text); last_note = std::max (last_note, (*p)->date_stamp); send_to_char (buf1); return; } else vnum++; } send_to_char ("You have no unread notes.\r\n"); return; } else if (is_number (argument)) { fAll = false; anum = std::atoi (argument.c_str()); } else { send_to_char ("Note read which number?\r\n"); return; } vnum = 0; for (std::list<Note*>::iterator p = note_list.begin(); p != note_list.end(); p++) { if ((*p)->is_note_to (this) && (vnum++ == anum || fAll)) { snprintf (buf, sizeof buf, "[%3d] %s: %s\r\n%s\r\nTo: %s\r\n", vnum - 1, (*p)->sender.c_str(), (*p)->subject.c_str(), (*p)->date.c_str(), (*p)->to_list.c_str()); buf1.append(buf); buf1.append((*p)->text); send_to_char (buf1); last_note = std::max (last_note, (*p)->date_stamp); return; } } send_to_char ("No such note.\r\n"); return; } if (!str_cmp (arg, "+")) { note_attach (this); strncpy (buf, pnote->text.c_str(), sizeof buf); if (strlen (buf) + argument.size() >= MAX_STRING_LENGTH - 200) { send_to_char ("Note too long.\r\n"); return; } strncat (buf, argument.c_str(), sizeof buf - argument.size()); strncat (buf, "\r\n", sizeof buf - strlen("\r\n")); pnote->text = buf; send_to_char ("Ok.\r\n"); return; } if (!str_cmp (arg, "subject")) { note_attach (this); pnote->subject = argument; send_to_char ("Ok.\r\n"); return; } if (!str_cmp (arg, "to")) { note_attach (this); pnote->to_list = argument; send_to_char ("Ok.\r\n"); return; } if (!str_cmp (arg, "clear")) { if (pnote != NULL) { delete pnote; pnote = NULL; } send_to_char ("Ok.\r\n"); return; } if (!str_cmp (arg, "show")) { if (pnote == NULL) { send_to_char ("You have no note in progress.\r\n"); return; } snprintf (buf, sizeof buf, "%s: %s\r\nTo: %s\r\n", pnote->sender.c_str(), pnote->subject.c_str(), pnote->to_list.c_str()); send_to_char (buf); send_to_char (pnote->text); return; } if (!str_cmp (arg, "post") || !str_prefix (arg, "send")) { if (pnote == NULL) { send_to_char ("You have no note in progress.\r\n"); return; } if (!str_cmp (pnote->to_list, "")) { send_to_char ("You need to provide a recipient (name, all, or immortal).\r\n"); return; } if (!str_cmp (pnote->subject, "")) { send_to_char ("You need to provide a subject.\r\n"); return; } pnote->date = g_world->get_time_text(); pnote->date_stamp = g_world->get_current_time(); note_list.push_back(pnote); std::ofstream notefile; notefile.open (NOTE_FILE, std::ofstream::out | std::ofstream::app | std::ofstream::binary); if (!notefile.is_open()) { std::perror (NOTE_FILE); } else { notefile << "Sender " << pnote->sender << "~\n"; notefile << "Date " << pnote->date << "~\n"; notefile << "Stamp " << pnote->date_stamp << "\n"; notefile << "To " << pnote->to_list << "~\n"; notefile << "Subject " << pnote->subject << "~\n"; notefile << "Text\n" << pnote->text << "~\n\n"; notefile.close(); } pnote = NULL; send_to_char ("Ok.\r\n"); return; } if (!str_cmp (arg, "remove")) { if (!is_number (argument)) { send_to_char ("Note remove which number?\r\n"); return; } anum = std::atoi (argument.c_str()); vnum = 0; std::list<Note*>::iterator next; for (std::list<Note*>::iterator p = note_list.begin(); p != note_list.end(); p = next) { Note* curr = *p; next = ++p; if (curr->is_note_to (this) && vnum++ == anum) { note_remove (this, curr); send_to_char ("Ok.\r\n"); return; } } send_to_char ("No such note.\r\n"); return; } send_to_char ("Huh? Type 'help note' for usage.\r\n"); return; } void Character::do_auction (std::string argument) { talk_channel (this, argument, CHANNEL_AUCTION, "auction"); return; } void Character::do_chat (std::string argument) { talk_channel (this, argument, CHANNEL_CHAT, "chat"); return; } /* * Alander's new channels. */ void Character::do_music (std::string argument) { talk_channel (this, argument, CHANNEL_MUSIC, "music"); return; } void Character::do_question (std::string argument) { talk_channel (this, argument, CHANNEL_QUESTION, "question"); return; } void Character::do_answer (std::string argument) { talk_channel (this, argument, CHANNEL_QUESTION, "answer"); return; } void Character::do_shout (std::string argument) { talk_channel (this, argument, CHANNEL_SHOUT, "shout"); wait_state (12); return; } void Character::do_yell (std::string argument) { talk_channel (this, argument, CHANNEL_YELL, "yell"); return; } void Character::do_immtalk (std::string argument) { talk_channel (this, argument, CHANNEL_IMMTALK, "immtalk"); return; } void Character::do_say (std::string argument) { if (argument.empty()) { send_to_char ("Say what?\r\n"); return; } act ("$n says '$T'.", NULL, argument.c_str(), TO_ROOM); act ("You say '$T'.", NULL, argument.c_str(), TO_CHAR); mprog_speech_trigger (argument, this); return; } void Character::do_tell (std::string argument) { if (!is_npc () && IS_SET (actflags, PLR_SILENCE)) { send_to_char ("Your message didn't get through.\r\n"); return; } std::string arg; argument = one_argument (argument, arg); if (arg.empty() || argument.empty()) { send_to_char ("Tell whom what?\r\n"); return; } /* * Can tell to PC's anywhere, but NPC's only in same room. * -- Furey */ Character *victim; if ((victim = get_char_world (arg)) == NULL || (victim->is_npc () && victim->in_room != in_room)) { send_to_char ("They aren't here.\r\n"); return; } if (!is_immortal() && !victim->is_awake ()) { act ("$E can't hear you.", 0, victim, TO_CHAR); return; } act ("You tell $N '$t'.", argument.c_str(), victim, TO_CHAR); int savepos = victim->position; victim->position = POS_STANDING; act ("$n tells you '$t'.", argument.c_str(), victim, TO_VICT); victim->position = savepos; victim->reply = this; return; } void Character::do_reply (std::string argument) { if (!is_npc () && IS_SET (actflags, PLR_SILENCE)) { send_to_char ("Your message didn't get through.\r\n"); return; } Character *victim; if ((victim = reply) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (!is_immortal() && !victim->is_awake ()) { act ("$E can't hear you.", 0, victim, TO_CHAR); return; } act ("You tell $N '$t'.", argument.c_str(), victim, TO_CHAR); int savepos = victim->position; victim->position = POS_STANDING; act ("$n tells you '$t'.", argument.c_str(), victim, TO_VICT); victim->position = savepos; victim->reply = this; return; } void Character::do_emote (std::string argument) { if (!is_npc () && IS_SET (actflags, PLR_NO_EMOTE)) { send_to_char ("You can't show your emotions.\r\n"); return; } if (argument.empty()) { send_to_char ("Emote what?\r\n"); return; } if (isalpha(argument[argument.size()-1])) argument += "."; act ("$n $T", NULL, argument.c_str(), TO_ROOM); act ("$n $T", NULL, argument.c_str(), TO_CHAR); return; } void Character::do_bug (std::string argument) { append_file (BUG_FILE, argument); send_to_char ("Ok. Thanks.\r\n"); return; } void Character::do_idea (std::string argument) { append_file (IDEA_FILE, argument); send_to_char ("Ok. Thanks.\r\n"); return; } void Character::do_typo (std::string argument) { append_file (TYPO_FILE, argument); send_to_char ("Ok. Thanks.\r\n"); return; } void Character::do_rent (std::string argument) { send_to_char ("There is no rent here. Just save and quit.\r\n"); return; } void Character::do_qui (std::string argument) { send_to_char ("If you want to QUIT, you have to spell it out.\r\n"); return; } void Character::do_quit (std::string argument) { if (is_npc ()) return; if (position == POS_FIGHTING) { send_to_char ("No way! You are fighting.\r\n"); return; } if (position < POS_STUNNED) { send_to_char ("You're not DEAD yet.\r\n"); return; } send_to_char ("Had I but time--as this fell sergeant, Death,\r\nIs strict in his arrest--O, I could tell you--\r\nBut let it be.\r\n"); act ("$n has left the game.", NULL, NULL, TO_ROOM); log_printf ("%s has quit.", name.c_str()); /* * After extract_char the this is no longer valid! */ save_char_obj(); Descriptor *d = desc; extract_char (true); if (d != NULL) d->close_socket(); return; } void Character::do_save (std::string argument) { if (is_npc ()) return; if (level < 2) { send_to_char ("You must be at least second level to save.\r\n"); return; } save_char_obj(); send_to_char ("Ok.\r\n"); return; } void Character::do_gag (std::string argument) { if (is_npc ()) return; std::string arg; one_argument (argument, arg); if (arg.empty()) { if (pcdata->gag_list.empty()) { send_to_char ("No gags set.\r\n"); return; } std::string buf("Gag list\r\n"); for (std::list<std::string>::iterator gag = pcdata->gag_list.begin(); gag != pcdata->gag_list.end(); gag++) { buf.append((*gag) + "\r\n"); } send_to_char (buf); return; } std::string gagname = capitalize(arg); if (!str_cmp(name, gagname)) { send_to_char ("You can't gag yourself.\r\n"); return; } std::list<std::string>::iterator fnd; fnd = std::find(pcdata->gag_list.begin(), pcdata->gag_list.end(), gagname); if (fnd != pcdata->gag_list.end()) { pcdata->gag_list.remove(gagname); send_to_char ("Gag removed.\r\n"); } else { pcdata->gag_list.push_back(gagname); send_to_char ("Gag added.\r\n"); } return; } void Character::do_follow (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Follow whom?\r\n"); return; } Character *victim; if ((victim = get_char_room (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (is_affected (AFF_CHARM) && master != NULL) { act ("But you'd rather follow $N!", NULL, master, TO_CHAR); return; } if (victim == this) { if (master == NULL) { send_to_char ("You already follow yourself.\r\n"); return; } stop_follower(); return; } if ((level - victim->level < -5 || level - victim->level > 5) && !is_hero()) { send_to_char ("You are not of the right caliber to follow.\r\n"); return; } if (master != NULL) stop_follower(); add_follower(victim); return; } void Character::do_order (std::string argument) { std::string arg; argument = one_argument (argument, arg); if (arg.empty() || argument.empty()) { send_to_char ("Order whom to do what?\r\n"); return; } if (is_affected (AFF_CHARM)) { send_to_char ("You feel like taking, not giving, orders.\r\n"); return; } Character *victim; bool fAll; if (!str_cmp (arg, "all")) { fAll = true; victim = NULL; } else { fAll = false; if ((victim = get_char_room (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (victim == this) { send_to_char ("Aye aye, right away!\r\n"); return; } if (!victim->is_affected (AFF_CHARM) || victim->master != this) { send_to_char ("Do it yourself!\r\n"); return; } } Character *och; bool found = false; CharIter rch, next; for (rch = in_room->people.begin(); rch != in_room->people.end(); rch = next) { och = *rch; next = ++rch; if (och->is_affected (AFF_CHARM) && och->master == this && (fAll || och == victim)) { found = true; act ("$n orders you to '$t'.", argument.c_str(), och, TO_VICT); och->interpret (argument); } } if (found) send_to_char ("Ok.\r\n"); else send_to_char ("You have no followers here.\r\n"); return; } void Character::do_group (std::string argument) { char buf[MAX_STRING_LENGTH]; std::string arg; one_argument (argument, arg); if (arg.empty()) { Character *ldr = (leader != NULL) ? leader : this; snprintf (buf, sizeof buf, "%s's group:\r\n", ldr->describe_to(this).c_str()); send_to_char (buf); CharIter c; for (c = char_list.begin(); c != char_list.end(); c++) { if (is_same_group (*c, this)) { snprintf (buf, sizeof buf, "[%2d %s] %-16s %4d/%4d hp %4d/%4d mana %4d/%4d mv %5d xp\r\n", (*c)->level, (*c)->is_npc () ? "Mob" : class_table[(*c)->klass].who_name, capitalize ((*c)->describe_to(this)).c_str(), (*c)->hit, (*c)->max_hit, (*c)->mana, (*c)->max_mana, (*c)->move, (*c)->max_move, (*c)->exp); send_to_char (buf); } } return; } Character *victim; if ((victim = get_char_room (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (master != NULL || (leader != NULL && leader != this)) { send_to_char ("But you are following someone else!\r\n"); return; } if (victim->master != this && this != victim) { act ("$N isn't following you.", NULL, victim, TO_CHAR); return; } if (is_same_group (victim, this) && this != victim) { victim->leader = NULL; act ("$n removes $N from $s group.", NULL, victim, TO_NOTVICT); act ("$n removes you from $s group.", NULL, victim, TO_VICT); act ("You remove $N from your group.", NULL, victim, TO_CHAR); return; } if (level - victim->level < -5 || level - victim->level > 5) { act ("$N cannot join $n's group.", NULL, victim, TO_NOTVICT); act ("You cannot join $n's group.", NULL, victim, TO_VICT); act ("$N cannot join your group.", NULL, victim, TO_CHAR); return; } victim->leader = this; act ("$N joins $n's group.", NULL, victim, TO_NOTVICT); act ("You join $n's group.", NULL, victim, TO_VICT); act ("$N joins your group.", NULL, victim, TO_CHAR); return; } /* * 'Split' originally by Gnort, God of Chaos. */ void Character::do_split (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Split how much?\r\n"); return; } int amount = std::atoi (arg.c_str()); if (amount < 0) { send_to_char ("Your group wouldn't like that.\r\n"); return; } if (amount == 0) { send_to_char ("You hand out zero coins, but no one notices.\r\n"); return; } if (gold < amount) { send_to_char ("You don't have that much gold.\r\n"); return; } int members = 0; CharIter gch; for (gch = in_room->people.begin(); gch != in_room->people.end(); gch++) { if (is_same_group (*gch, this)) members++; } if (members < 2) { send_to_char ("Just keep it all.\r\n"); return; } int share = amount / members; int extra = amount % members; if (share == 0) { send_to_char ("Don't even bother, cheapskate.\r\n"); return; } gold -= amount; gold += share + extra; char buf[MAX_STRING_LENGTH]; snprintf (buf, sizeof buf, "You split %d gold coins. Your share is %d gold coins.\r\n", amount, share + extra); send_to_char (buf); snprintf (buf, sizeof buf, "$n splits %d gold coins. Your share is %d gold coins.", amount, share); for (gch = in_room->people.begin(); gch != in_room->people.end(); gch++) { if (*gch != this && is_same_group (*gch, this)) { act (buf, NULL, *gch, TO_VICT); (*gch)->gold += share; } } return; } void Character::do_gtell (std::string argument) { char buf[MAX_STRING_LENGTH]; if (argument.empty()) { send_to_char ("Tell your group what?\r\n"); return; } if (IS_SET (actflags, PLR_NO_TELL)) { send_to_char ("Your message didn't get through!\r\n"); return; } /* * Note use of send_to_char, so gtell works on sleepers. */ snprintf (buf, sizeof buf, "%s tells the group '%s'.\r\n", name.c_str(), argument.c_str()); for (CharIter c = char_list.begin(); c != char_list.end(); c++) { if (is_same_group (*c, this)) (*c)->send_to_char (buf); } return; } void Character::do_look (std::string argument) { if (!is_npc () && desc == NULL) return; if (position < POS_SLEEPING) { send_to_char ("You can't see anything but stars!\r\n"); return; } if (position == POS_SLEEPING) { send_to_char ("You can't see anything, you're sleeping!\r\n"); return; } if (!check_blind()) return; if (!is_npc () && !IS_SET (actflags, PLR_HOLYLIGHT) && in_room->is_dark()) { send_to_char ("It is pitch black ... \r\n"); show_char_to_char (in_room->people); return; } std::string arg1, arg2; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); if (arg1.empty() || !str_cmp (arg1, "auto")) { /* 'look' or 'look auto' */ send_to_char (in_room->name); send_to_char ("\r\n"); if (!is_npc () && IS_SET (actflags, PLR_AUTOEXIT)) do_exits ("auto"); if (arg1.empty() || (!is_npc () && !IS_SET (actflags, PLR_BRIEF))) send_to_char (in_room->description); show_list_to_char (in_room->contents, false, false); show_char_to_char (in_room->people); return; } char buf[MAX_STRING_LENGTH]; Object *obj; std::string pdesc; if (!str_cmp (arg1, "i") || !str_cmp (arg1, "in")) { /* 'look in' */ if (arg2.empty()) { send_to_char ("Look in what?\r\n"); return; } if ((obj = get_obj_here (arg2)) == NULL) { send_to_char ("You do not see that here.\r\n"); return; } switch (obj->item_type) { default: send_to_char ("That is not a container.\r\n"); break; case ITEM_DRINK_CON: if (obj->value[1] <= 0) { send_to_char ("It is empty.\r\n"); break; } snprintf (buf, sizeof buf, "It's %s full of a %s liquid.\r\n", obj->value[1] < obj->value[0] / 4 ? "less than" : obj->value[1] < 3 * obj->value[0] / 4 ? "about" : "more than", liq_table[obj->value[2]].liq_color); send_to_char (buf); break; case ITEM_CONTAINER: case ITEM_CORPSE_NPC: case ITEM_CORPSE_PC: if (IS_SET (obj->value[1], CONT_CLOSED)) { send_to_char ("It is closed.\r\n"); break; } act ("$p contains:", obj, NULL, TO_CHAR); show_list_to_char (obj->contains, true, true); break; } return; } Character *victim; if ((victim = get_char_room (arg1)) != NULL) { show_char_to_char_1 (victim); return; } ObjIter o; for (o = carrying.begin(); o != carrying.end(); o++) { if (can_see_obj(*o)) { pdesc = get_extra_descr (arg1, (*o)->extra_descr); if (!pdesc.empty()) { send_to_char (pdesc); return; } pdesc = get_extra_descr (arg1, (*o)->pIndexData->extra_descr); if (!pdesc.empty()) { send_to_char (pdesc); return; } } if (is_name (arg1, (*o)->name)) { send_to_char ((*o)->description); return; } } for (o = in_room->contents.begin(); o != in_room->contents.end(); o++) { if (can_see_obj(*o)) { pdesc = get_extra_descr (arg1, (*o)->extra_descr); if (!pdesc.empty()) { send_to_char (pdesc); return; } pdesc = get_extra_descr (arg1, (*o)->pIndexData->extra_descr); if (!pdesc.empty()) { send_to_char (pdesc); return; } } if (is_name (arg1, (*o)->name)) { send_to_char ((*o)->description); return; } } pdesc = get_extra_descr (arg1, in_room->extra_descr); if (!pdesc.empty()) { send_to_char (pdesc); return; } int door; if (!str_cmp (arg1, "n") || !str_cmp (arg1, "north")) door = 0; else if (!str_cmp (arg1, "e") || !str_cmp (arg1, "east")) door = 1; else if (!str_cmp (arg1, "s") || !str_cmp (arg1, "south")) door = 2; else if (!str_cmp (arg1, "w") || !str_cmp (arg1, "west")) door = 3; else if (!str_cmp (arg1, "u") || !str_cmp (arg1, "up")) door = 4; else if (!str_cmp (arg1, "d") || !str_cmp (arg1, "down")) door = 5; else { send_to_char ("You do not see that here.\r\n"); return; } /* 'look direction' */ Exit *pexit; if ((pexit = in_room->exit[door]) == NULL) { send_to_char ("Nothing special there.\r\n"); return; } if (!pexit->description.empty()) send_to_char (pexit->description); else send_to_char ("Nothing special there.\r\n"); if (!pexit->name.empty() && pexit->name[0] != ' ') { if (IS_SET (pexit->exit_info, EX_CLOSED)) { act ("The $d is closed.", NULL, pexit->name.c_str(), TO_CHAR); } else if (IS_SET (pexit->exit_info, EX_ISDOOR)) { act ("The $d is open.", NULL, pexit->name.c_str(), TO_CHAR); } } return; } void Character::do_examine (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Examine what?\r\n"); return; } do_look (arg); Object *obj; if ((obj = get_obj_here (arg)) != NULL) { switch (obj->item_type) { default: break; case ITEM_DRINK_CON: case ITEM_CONTAINER: case ITEM_CORPSE_NPC: case ITEM_CORPSE_PC: send_to_char ("When you look inside, you see:\r\n"); std::string buf = "in " + arg; do_look (buf); } } return; } /* * Thanks to Zrin for auto-exit part. */ void Character::do_exits (std::string argument) { if (!check_blind()) return; char buf[MAX_STRING_LENGTH]; buf[0] = '\0'; bool fAuto = !str_cmp (argument, "auto"); strncpy (buf, fAuto ? "[Exits:" : "Obvious exits:\r\n", sizeof buf); bool found = false; for (int door = 0; door <= 5; door++) { Exit *pexit; if ((pexit = in_room->exit[door]) != NULL && pexit->to_room != NULL && !IS_SET (pexit->exit_info, EX_CLOSED)) { found = true; if (fAuto) { strncat (buf, " ", sizeof(buf) - strlen(" ")); strncat (buf, dir_name[door].c_str(), sizeof(buf) - dir_name[door].size()); } else { snprintf (buf + strlen(buf), sizeof(buf) - strlen(buf), "%-5s - %s\r\n", capitalize (dir_name[door]).c_str(), pexit->to_room->is_dark() ? "Too dark to tell" : pexit->to_room->name.c_str()); } } } if (!found) strncat (buf, fAuto ? " none" : "None.\r\n", sizeof(buf) - strlen("None.\r\n")); if (fAuto) strncat (buf, "]\r\n", sizeof(buf) - strlen("]\r\n")); send_to_char (buf); return; } void Character::do_score (std::string argument) { char buf[MAX_STRING_LENGTH]; snprintf (buf, sizeof buf, "You are %s%s, level %d, %d years old (%d hours).\r\n", name.c_str(), is_npc () ? "" : pcdata->title.c_str(), level, get_age(), (get_age() - 17) * 2); send_to_char (buf); if (get_trust () != level) { snprintf (buf, sizeof buf, "You are trusted at level %d.\r\n", get_trust ()); send_to_char (buf); } snprintf (buf, sizeof buf, "You have %d/%d hit, %d/%d mana, %d/%d movement, %d practices.\r\n", hit, max_hit, mana, max_mana, move, max_move, practice); send_to_char (buf); snprintf (buf, sizeof buf, "You are carrying %d/%d items with weight %d/%d kg.\r\n", carry_number, can_carry_n(), carry_weight, can_carry_w()); send_to_char (buf); snprintf (buf, sizeof buf, "Str: %d Int: %d Wis: %d Dex: %d Con: %d.\r\n", get_curr_str(), get_curr_int(), get_curr_wis(), get_curr_dex(), get_curr_con()); send_to_char (buf); snprintf (buf, sizeof buf, "You have scored %d exp, and have %d gold coins.\r\n", exp, gold); send_to_char (buf); snprintf (buf, sizeof buf, "Autoexit: %s. Autoloot: %s. Autosac: %s.\r\n", (!is_npc () && IS_SET (actflags, PLR_AUTOEXIT)) ? "yes" : "no", (!is_npc () && IS_SET (actflags, PLR_AUTOLOOT)) ? "yes" : "no", (!is_npc () && IS_SET (actflags, PLR_AUTOSAC)) ? "yes" : "no"); send_to_char (buf); snprintf (buf, sizeof buf, "Wimpy set to %d hit points.\r\n", wimpy); send_to_char (buf); if (!is_npc ()) { snprintf (buf, sizeof buf, "Page pausing set to %d lines of text.\r\n", pcdata->pagelen); send_to_char (buf); } if (!is_npc () && pcdata->condition[COND_DRUNK] > 10) send_to_char ("You are drunk.\r\n"); if (!is_npc () && pcdata->condition[COND_THIRST] == 0) send_to_char ("You are thirsty.\r\n"); if (!is_npc () && pcdata->condition[COND_FULL] == 0) send_to_char ("You are hungry.\r\n"); switch (position) { case POS_DEAD: send_to_char ("You are DEAD!!\r\n"); break; case POS_MORTAL: send_to_char ("You are mortally wounded.\r\n"); break; case POS_INCAP: send_to_char ("You are incapacitated.\r\n"); break; case POS_STUNNED: send_to_char ("You are stunned.\r\n"); break; case POS_SLEEPING: send_to_char ("You are sleeping.\r\n"); break; case POS_RESTING: send_to_char ("You are resting.\r\n"); break; case POS_STANDING: send_to_char ("You are standing.\r\n"); break; case POS_FIGHTING: send_to_char ("You are fighting.\r\n"); break; } if (level >= 25) { snprintf (buf, sizeof buf, "AC: %d. ", get_ac()); send_to_char (buf); } send_to_char ("You are "); if (get_ac() >= 101) send_to_char ("WORSE than naked!\r\n"); else if (get_ac() >= 80) send_to_char ("naked.\r\n"); else if (get_ac() >= 60) send_to_char ("wearing clothes.\r\n"); else if (get_ac() >= 40) send_to_char ("slightly armored.\r\n"); else if (get_ac() >= 20) send_to_char ("somewhat armored.\r\n"); else if (get_ac() >= 0) send_to_char ("armored.\r\n"); else if (get_ac() >= -20) send_to_char ("well armored.\r\n"); else if (get_ac() >= -40) send_to_char ("strongly armored.\r\n"); else if (get_ac() >= -60) send_to_char ("heavily armored.\r\n"); else if (get_ac() >= -80) send_to_char ("superbly armored.\r\n"); else if (get_ac() >= -100) send_to_char ("divinely armored.\r\n"); else send_to_char ("invincible!\r\n"); if (level >= 15) { snprintf (buf, sizeof buf, "Hitroll: %d Damroll: %d.\r\n", get_hitroll(), get_damroll()); send_to_char (buf); } if (level >= 10) { snprintf (buf, sizeof buf, "Alignment: %d. ", alignment); send_to_char (buf); } send_to_char ("You are "); if (alignment > 900) send_to_char ("angelic.\r\n"); else if (alignment > 700) send_to_char ("saintly.\r\n"); else if (alignment > 350) send_to_char ("good.\r\n"); else if (alignment > 100) send_to_char ("kind.\r\n"); else if (alignment > -100) send_to_char ("neutral.\r\n"); else if (alignment > -350) send_to_char ("mean.\r\n"); else if (alignment > -700) send_to_char ("evil.\r\n"); else if (alignment > -900) send_to_char ("demonic.\r\n"); else send_to_char ("satanic.\r\n"); if (!affected.empty()) { send_to_char ("You are affected by:\r\n"); AffIter af; for (af = affected.begin(); af != affected.end(); af++) { snprintf (buf, sizeof buf, "Spell: '%s'", skill_table[(*af)->type].name); send_to_char (buf); if (level >= 20) { snprintf (buf, sizeof buf, " modifies %s by %d for %d hours", affect_loc_name ((*af)->location).c_str(), (*af)->modifier, (*af)->duration); send_to_char (buf); } send_to_char (".\r\n"); } } return; } void Character::do_time (std::string argument) { char buf[MAX_STRING_LENGTH]; std::string wt = g_world->world_time(); snprintf (buf, sizeof buf, "%sMerc started up at %s\r\nThe system time is %s\r\n", wt.c_str(), str_boot_time.c_str(), g_world->get_time_text() ); send_to_char (buf); return; } void Character::do_weather (std::string argument) { if (!is_outside()) { send_to_char ("You can't see the weather indoors.\r\n"); return; } send_to_char (g_world->world_weather()); return; } void Character::do_help (std::string argument) { sqlite3_stmt *stmt = NULL; if (argument.empty()) argument = "summary"; char *sql = sqlite3_mprintf("SELECT level, keyword, text FROM helps WHERE level <= %d", level); if (sqlite3_prepare(g_db->database, sql, -1, &stmt, 0) != SQLITE_OK) { bug_printf("Could not prepare statement: '%s' Error: %s", sql, sqlite3_errmsg(g_db->database)); sqlite3_free(sql); return; } while (sqlite3_step(stmt) == SQLITE_ROW) { int lvl = sqlite3_column_int( stmt, 0 ); std::string keyword = (const char*)sqlite3_column_text( stmt, 1 ); std::string text = (const char*)sqlite3_column_text( stmt, 2 ); if (is_name (argument, keyword)) { if (lvl >= 0 && str_cmp (argument, "imotd")) { send_to_char (keyword); send_to_char ("\r\n"); } send_to_char (text); sqlite3_finalize(stmt); sqlite3_free(sql); return; } } sqlite3_finalize(stmt); sqlite3_free(sql); send_to_char ("No help on that word.\r\n"); return; } /* * New 'who' command originally by Alander of Rivers of Mud. */ void Character::do_who (std::string argument) { int iClass; bool rgfClass[CLASS_MAX]; /* * Set default arguments. */ int iLevelLower = 0; int iLevelUpper = MAX_LEVEL; bool fClassRestrict = false; bool fImmortalOnly = false; for (iClass = 0; iClass < CLASS_MAX; iClass++) rgfClass[iClass] = false; /* * Parse arguments. */ int nNumber = 0; for (;;) { std::string arg; argument = one_argument (argument, arg); if (arg.empty()) break; if (is_number (arg)) { switch (++nNumber) { case 1: iLevelLower = std::atoi (arg.c_str()); break; case 2: iLevelUpper = std::atoi (arg.c_str()); break; default: send_to_char ("Only two level numbers allowed.\r\n"); return; } } else { if (arg.size() < 3) { send_to_char ("Classes must be longer than that.\r\n"); return; } /* * Look for classes to turn on. */ int iClass; arg.erase(3); if (!str_cmp (arg, "imm")) { fImmortalOnly = true; } else { fClassRestrict = true; for (iClass = 0; iClass < CLASS_MAX; iClass++) { if (!str_cmp (arg, class_table[iClass].who_name)) { rgfClass[iClass] = true; break; } } if (iClass == CLASS_MAX) { send_to_char ("That's not a class.\r\n"); return; } } } } /* * Now show matching chars. */ int nMatch = 0; char buf[MAX_STRING_LENGTH]; buf[0] = '\0'; for (DescIter d = descriptor_list.begin(); d != descriptor_list.end(); d++) { Character *wch; char const *klass; /* * Check for match against restrictions. * Don't use trust as that exposes trusted mortals. */ if ((*d)->connected != CON_PLAYING || !can_see((*d)->character)) continue; wch = ((*d)->original != NULL) ? (*d)->original : (*d)->character; if (wch->level < iLevelLower || wch->level > iLevelUpper || (fImmortalOnly && wch->level < LEVEL_HERO) || (fClassRestrict && !rgfClass[wch->klass])) continue; nMatch++; /* * Figure out what to print for class. */ klass = class_table[wch->klass].who_name; switch (wch->level) { default: break; case MAX_LEVEL - 0: klass = "GOD"; break; case MAX_LEVEL - 1: klass = "SUP"; break; case MAX_LEVEL - 2: klass = "DEI"; break; case MAX_LEVEL - 3: klass = "ANG"; break; } /* * Format it up. */ snprintf (buf + strlen(buf), sizeof(buf) - strlen(buf), "[%2d %s] %s%s%s%s\r\n", wch->level, klass, IS_SET (wch->actflags, PLR_KILLER) ? "(KILLER) " : "", IS_SET (wch->actflags, PLR_THIEF) ? "(THIEF) " : "", wch->name.c_str(), wch->pcdata->title.c_str()); } char buf2[MAX_STRING_LENGTH]; snprintf (buf2, sizeof buf2, "You see %d player%s in the game.\r\n", nMatch, nMatch == 1 ? "" : "s"); strncat (buf, buf2, sizeof(buf) - sizeof(buf2)); send_to_char (buf); return; } void Character::do_inventory (std::string argument) { send_to_char ("You are carrying:\r\n"); show_list_to_char (carrying, true, true); return; } void Character::do_equipment (std::string argument) { send_to_char ("You are using:\r\n"); bool found = false; for (int iWear = 0; iWear < MAX_WEAR; iWear++) { Object *obj; if ((obj = get_eq_char (iWear)) == NULL) continue; send_to_char (where_name[iWear]); if (can_see_obj(obj)) { send_to_char (obj->format_obj_to_char (this, true)); send_to_char ("\r\n"); } else { send_to_char ("something.\r\n"); } found = true; } if (!found) send_to_char ("Nothing.\r\n"); return; } void Character::do_compare (std::string argument) { std::string arg1, arg2; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); if (arg1.empty()) { send_to_char ("Compare what to what?\r\n"); return; } Object *obj1; if ((obj1 = get_obj_carry (arg1)) == NULL) { send_to_char ("You do not have that item.\r\n"); return; } Object *obj2 = NULL; if (arg2.empty()) { ObjIter o; for (o = carrying.begin(); o != carrying.end(); o++) { obj2 = *o; if (obj2->wear_loc != WEAR_NONE && can_see_obj(obj2) && obj1->item_type == obj2->item_type && (obj1->wear_flags & obj2->wear_flags & ~ITEM_TAKE) != 0) break; } if (obj2 == NULL) { send_to_char ("You aren't wearing anything comparable.\r\n"); return; } } else { if ((obj2 = get_obj_carry (arg2)) == NULL) { send_to_char ("You do not have that item.\r\n"); return; } } const char* msg = NULL; int value1 = 0; int value2 = 0; if (obj1 == obj2) { msg = "You compare $p to itself. It looks about the same."; } else if (obj1->item_type != obj2->item_type) { msg = "You can't compare $p and $P."; } else { switch (obj1->item_type) { default: msg = "You can't compare $p and $P."; break; case ITEM_ARMOR: value1 = obj1->value[0]; value2 = obj2->value[0]; break; case ITEM_WEAPON: value1 = obj1->value[1] + obj1->value[2]; value2 = obj2->value[1] + obj2->value[2]; break; } } if (msg == NULL) { if (value1 == value2) msg = "$p and $P look about the same."; else if (value1 > value2) msg = "$p looks better than $P."; else msg = "$p looks worse than $P."; } act (msg, obj1, obj2, TO_CHAR); return; } void Character::do_credits (std::string argument) { do_help ("diku"); return; } void Character::do_where (std::string argument) { std::string arg; char buf[MAX_STRING_LENGTH]; Character *victim; bool found = false; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Players near you:\r\n"); for (DescIter d = descriptor_list.begin(); d != descriptor_list.end(); d++) { if ((*d)->connected == CON_PLAYING && (victim = (*d)->character) != NULL && !victim->is_npc () && victim->in_room != NULL && victim->in_room->area == in_room->area && can_see(victim)) { found = true; snprintf (buf, sizeof buf, "%-28s %s\r\n", victim->name.c_str(), victim->in_room->name.c_str()); send_to_char (buf); } } if (!found) send_to_char ("None\r\n"); } else { for (CharIter c = char_list.begin(); c != char_list.end(); c++) { victim = *c; if (victim->in_room != NULL && victim->in_room->area == in_room->area && !victim->is_affected (AFF_HIDE) && !victim->is_affected (AFF_SNEAK) && can_see(victim) && is_name (arg, victim->name)) { found = true; snprintf (buf, sizeof buf, "%-28s %s\r\n", victim->describe_to(this).c_str(), victim->in_room->name.c_str()); send_to_char (buf); break; } } if (!found) act ("You didn't find any $T.", NULL, arg.c_str(), TO_CHAR); } return; } void Character::do_consider (std::string argument) { std::string arg, msg, buf; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Consider killing whom?\r\n"); return; } Character *victim; if ((victim = get_char_room (arg)) == NULL) { send_to_char ("They're not here.\r\n"); return; } if (!victim->is_npc ()) { send_to_char ("The gods do not accept this type of sacrafice.\r\n"); return; } int diff = victim->level - level; if (diff <= -10) msg = "You can kill $N naked and weaponless."; else if (diff <= -5) msg = "$N is no match for you."; else if (diff <= -2) msg = "$N looks like an easy kill."; else if (diff <= 1) msg = "The perfect match!"; else if (diff <= 4) msg = "$N says 'Do you feel lucky, punk?'."; else if (diff <= 9) msg = "$N laughs at you mercilessly."; else msg = "Death will thank you for your gift."; act (msg, NULL, victim, TO_CHAR); /* additions by king@tinuviel.cs.wcu.edu */ int hpdiff = (hit - victim->hit); if (((diff >= 0) && (hpdiff <= 0)) || ((diff <= 0) && (hpdiff >= 0))) { send_to_char ("Also,"); } else { send_to_char ("However,"); } if (hpdiff >= 101) buf = " you are currently much healthier than $E."; if (hpdiff <= 100) buf = " you are currently healthier than $E."; if (hpdiff <= 50) buf = " you are currently slightly healthier than $E."; if (hpdiff <= 25) buf = " you are a teensy bit healthier than $E."; if (hpdiff <= 0) buf = " $E is a teensy bit healthier than you."; if (hpdiff <= -25) buf = " $E is slightly healthier than you."; if (hpdiff <= -50) buf = " $E is healthier than you."; if (hpdiff <= -100) buf = " $E is much healthier than you."; act (buf, NULL, victim, TO_CHAR); return; } void Character::do_title (std::string argument) { if (is_npc ()) return; if (argument.empty()) { send_to_char ("Change your title to what?\r\n"); return; } if (argument.size() > 50) argument.erase(50); smash_tilde (argument); set_title(argument); send_to_char ("Ok.\r\n"); } void Character::do_description (std::string argument) { if (!argument.empty()) { std::string buf; smash_tilde (argument); if (argument[0] == '+') { if (!description.empty()) buf = description; argument.erase(0,1); argument.erase(0, argument.find_first_not_of(" ")); } if (buf.size() + argument.size() >= MAX_STRING_LENGTH - 2) { send_to_char ("Description too long.\r\n"); return; } buf.append(argument); buf.append("\r\n"); description = buf; } send_to_char ("Your description is:\r\n"); send_to_char (!description.empty() ? description.c_str() : "(None).\r\n"); return; } void Character::do_report (std::string argument) { char buf[MAX_INPUT_LENGTH]; snprintf (buf, sizeof buf, "You report: %d/%d hp %d/%d mana %d/%d mv %d xp.\r\n", hit, max_hit, mana, max_mana, move, max_move, exp); send_to_char (buf); snprintf (buf, sizeof buf, "$n reports: %d/%d hp %d/%d mana %d/%d mv %d xp.", hit, max_hit, mana, max_mana, move, max_move, exp); act (buf, NULL, NULL, TO_ROOM); return; } void Character::do_practice (std::string argument) { if (is_npc ()) return; if (level < 3) { send_to_char ("You must be third level to practice. Go train instead!\r\n"); return; } char buf[MAX_STRING_LENGTH]; std::string buf1; int sn; if (argument.empty()) { int col; col = 0; for (sn = 0; sn < MAX_SKILL; sn++) { if (skill_table[sn].name == NULL) break; if (level < skill_table[sn].skill_level[klass]) continue; snprintf (buf, sizeof buf, "%18s %3d%% ", skill_table[sn].name, pcdata->learned[sn]); buf1.append(buf); if (++col % 3 == 0) buf1.append("\r\n"); } if (col % 3 != 0) buf1.append("\r\n"); snprintf (buf, sizeof buf, "You have %d practice sessions left.\r\n", practice); buf1.append(buf); send_to_char (buf1); } else { int adept; if (!is_awake ()) { send_to_char ("In your dreams, or what?\r\n"); return; } CharIter mob; for (mob = in_room->people.begin(); mob != in_room->people.end(); mob++) { if ((*mob)->is_npc () && IS_SET ((*mob)->actflags, ACT_PRACTICE)) break; } if (mob == in_room->people.end()) { send_to_char ("You can't do that here.\r\n"); return; } if (practice <= 0) { send_to_char ("You have no practice sessions left.\r\n"); return; } if ((sn = skill_lookup (argument)) < 0 || (!is_npc () && level < skill_table[sn].skill_level[klass])) { send_to_char ("You can't practice that.\r\n"); return; } adept = is_npc () ? 100 : class_table[klass].skill_adept; if (pcdata->learned[sn] >= adept) { snprintf (buf, sizeof buf, "You are already an adept of %s.\r\n", skill_table[sn].name); send_to_char (buf); } else { practice--; pcdata->learned[sn] += int_app[get_curr_int()].learn; if (pcdata->learned[sn] < adept) { act ("You practice $T.", NULL, skill_table[sn].name, TO_CHAR); act ("$n practices $T.", NULL, skill_table[sn].name, TO_ROOM); } else { pcdata->learned[sn] = adept; act ("You are now an adept of $T.", NULL, skill_table[sn].name, TO_CHAR); act ("$n is now an adept of $T.", NULL, skill_table[sn].name, TO_ROOM); } } } return; } /* * 'Wimpy' originally by Dionysos. */ void Character::do_wimpy (std::string argument) { std::string arg; int wpy; one_argument (argument, arg); if (arg.empty()) wpy = max_hit / 5; else wpy = std::atoi (arg.c_str()); if (wpy < 0) { send_to_char ("Your courage exceeds your wisdom.\r\n"); return; } if (wpy > max_hit) { send_to_char ("Such cowardice ill becomes you.\r\n"); return; } wimpy = wpy; char buf[MAX_STRING_LENGTH]; snprintf (buf, sizeof buf, "Wimpy set to %d hit points.\r\n", wimpy); send_to_char (buf); return; } void Character::do_password (std::string argument) { if (is_npc ()) return; std::string arg1; std::string arg2; char *pwdnew; char *p; char cEnd; /* * Can't use one_argument here because it smashes case. * So we just steal all its code. Bleagh. */ std::string::iterator argp = argument.begin(); arg1.erase(); while (argp != argument.end() && isspace (*argp)) argp++; cEnd = ' '; if (*argp == '\'' || *argp == '"') cEnd = *argp++; while (argp != argument.end()) { if (*argp == cEnd) { break; } arg1.append(1, *argp); argp++; } argp = argument.begin(); arg2.erase(); while (argp != argument.end() && isspace (*argp)) argp++; cEnd = ' '; if (*argp == '\'' || *argp == '"') cEnd = *argp++; while (argp != argument.end()) { if (*argp == cEnd) { break; } arg2.append(1, *argp); argp++; } if (arg1.empty() || arg2.empty()) { send_to_char ("Syntax: password <old> <new>.\r\n"); return; } char buf[MAX_STRING_LENGTH]; // Needed for Windows crypt strncpy(buf,arg1.c_str(), sizeof buf); if (strcmp (crypt (buf, pcdata->pwd.c_str()), pcdata->pwd.c_str())) { wait_state (40); send_to_char ("Wrong password. Wait 10 seconds.\r\n"); return; } if (arg2.size() < 5) { send_to_char ("New password must be at least five characters long.\r\n"); return; } /* * No tilde allowed because of player file format. */ strncpy(buf,arg2.c_str(), sizeof buf); pwdnew = crypt (buf, name.c_str()); for (p = pwdnew; *p != '\0'; p++) { if (*p == '~') { send_to_char ("New password not acceptable, try again.\r\n"); return; } } pcdata->pwd = pwdnew; save_char_obj(); send_to_char ("Ok.\r\n"); return; } void Character::do_socials (std::string argument) { char buf[MAX_STRING_LENGTH]; int col = 0; sqlite3_stmt *stmt = NULL; if (sqlite3_prepare(g_db->database, "SELECT name FROM socials ORDER BY name ASC", -1, &stmt, 0) != SQLITE_OK) { bug_printf("Could not prepare statement: %s", sqlite3_errmsg(g_db->database)); return; } while (sqlite3_step(stmt) == SQLITE_ROW) { snprintf (buf, sizeof buf, "%-12s", sqlite3_column_text( stmt, 0 )); send_to_char (buf); if (++col % 6 == 0) send_to_char ("\r\n"); } if (col % 6 != 0) send_to_char ("\r\n"); sqlite3_finalize(stmt); return; } /* * Contributed by Alander. */ void Character::do_commands (std::string argument) { char buf[MAX_STRING_LENGTH]; std::string buf1; int cmd; int col; col = 0; for (cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++) { if (cmd_table[cmd].level < LEVEL_HERO && cmd_table[cmd].level <= get_trust ()) { snprintf (buf, sizeof buf, "%-12s", cmd_table[cmd].name); buf1.append(buf); if (++col % 6 == 0) buf1.append("\r\n"); } } if (col % 6 != 0) buf1.append("\r\n"); send_to_char (buf1); return; } void Character::do_channels (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { if (!is_npc () && IS_SET (actflags, PLR_SILENCE)) { send_to_char ("You are silenced.\r\n"); return; } send_to_char ("Channels:"); send_to_char (!IS_SET (deaf, CHANNEL_AUCTION) ? " +AUCTION" : " -auction"); send_to_char (!IS_SET (deaf, CHANNEL_CHAT) ? " +CHAT" : " -chat"); if (is_hero()) { send_to_char (!IS_SET (deaf, CHANNEL_IMMTALK) ? " +IMMTALK" : " -immtalk"); } send_to_char (!IS_SET (deaf, CHANNEL_MUSIC) ? " +MUSIC" : " -music"); send_to_char (!IS_SET (deaf, CHANNEL_QUESTION) ? " +QUESTION" : " -question"); send_to_char (!IS_SET (deaf, CHANNEL_SHOUT) ? " +SHOUT" : " -shout"); send_to_char (!IS_SET (deaf, CHANNEL_YELL) ? " +YELL" : " -yell"); send_to_char (".\r\n"); } else { bool fClear; int bit; if (arg[0] == '+') fClear = true; else if (arg[0] == '-') fClear = false; else { send_to_char ("Channels -channel or +channel?\r\n"); return; } if (!str_cmp (arg.substr(1), "auction")) bit = CHANNEL_AUCTION; else if (!str_cmp (arg.substr(1), "chat")) bit = CHANNEL_CHAT; else if (!str_cmp (arg.substr(1), "immtalk")) bit = CHANNEL_IMMTALK; else if (!str_cmp (arg.substr(1), "music")) bit = CHANNEL_MUSIC; else if (!str_cmp (arg.substr(1), "question")) bit = CHANNEL_QUESTION; else if (!str_cmp (arg.substr(1), "shout")) bit = CHANNEL_SHOUT; else if (!str_cmp (arg.substr(1), "yell")) bit = CHANNEL_YELL; else { send_to_char ("Set or clear which channel?\r\n"); return; } if (fClear) REMOVE_BIT (deaf, bit); else SET_BIT (deaf, bit); send_to_char ("Ok.\r\n"); } return; } /* * Contributed by Grodyn. */ void Character::do_config (std::string argument) { if (is_npc ()) return; std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("[ Keyword ] Option\r\n"); send_to_char (IS_SET (actflags, PLR_AUTOEXIT) ? "[+AUTOEXIT ] You automatically see exits.\r\n" : "[-autoexit ] You don't automatically see exits.\r\n"); send_to_char (IS_SET (actflags, PLR_AUTOLOOT) ? "[+AUTOLOOT ] You automatically loot corpses.\r\n" : "[-autoloot ] You don't automatically loot corpses.\r\n"); send_to_char (IS_SET (actflags, PLR_AUTOSAC) ? "[+AUTOSAC ] You automatically sacrifice corpses.\r\n" : "[-autosac ] You don't automatically sacrifice corpses.\r\n"); send_to_char (IS_SET (actflags, PLR_BLANK) ? "[+BLANK ] You have a blank line before your prompt.\r\n" : "[-blank ] You have no blank line before your prompt.\r\n"); send_to_char (IS_SET (actflags, PLR_BRIEF) ? "[+BRIEF ] You see brief descriptions.\r\n" : "[-brief ] You see long descriptions.\r\n"); send_to_char (IS_SET (actflags, PLR_COMBINE) ? "[+COMBINE ] You see object lists in combined format.\r\n" : "[-combine ] You see object lists in single format.\r\n"); send_to_char (IS_SET (actflags, PLR_PROMPT) ? "[+PROMPT ] You have a prompt.\r\n" : "[-prompt ] You don't have a prompt.\r\n"); send_to_char (IS_SET (actflags, PLR_TELNET_GA) ? "[+TELNETGA ] You receive a telnet GA sequence.\r\n" : "[-telnetga ] You don't receive a telnet GA sequence.\r\n"); send_to_char (IS_SET (actflags, PLR_SILENCE) ? "[+SILENCE ] You are silenced.\r\n" : ""); send_to_char (!IS_SET (actflags, PLR_NO_EMOTE) ? "" : "[-emote ] You can't emote.\r\n"); send_to_char (!IS_SET (actflags, PLR_NO_TELL) ? "" : "[-tell ] You can't use 'tell'.\r\n"); } else { bool fSet; int bit; if (arg[0] == '+') fSet = true; else if (arg[0] == '-') fSet = false; else { send_to_char ("Config -option or +option?\r\n"); return; } if (!str_cmp (arg.substr(1), "autoexit")) bit = PLR_AUTOEXIT; else if (!str_cmp (arg.substr(1), "autoloot")) bit = PLR_AUTOLOOT; else if (!str_cmp (arg.substr(1), "autosac")) bit = PLR_AUTOSAC; else if (!str_cmp (arg.substr(1), "blank")) bit = PLR_BLANK; else if (!str_cmp (arg.substr(1), "brief")) bit = PLR_BRIEF; else if (!str_cmp (arg.substr(1), "combine")) bit = PLR_COMBINE; else if (!str_cmp (arg.substr(1), "prompt")) bit = PLR_PROMPT; else if (!str_cmp (arg.substr(1), "telnetga")) bit = PLR_TELNET_GA; else { send_to_char ("Config which option?\r\n"); return; } if (fSet) SET_BIT (actflags, bit); else REMOVE_BIT (actflags, bit); send_to_char ("Ok.\r\n"); } return; } void Character::do_wizlist (std::string argument) { do_help ("wizlist"); return; } void Character::do_spells (std::string argument) { char buf[MAX_STRING_LENGTH]; std::string buf1; if ((!is_npc () && !class_table[klass].fMana) || is_npc ()) { send_to_char ("You do not know how to cast spells!\r\n"); return; } int col = 0; for (int sn = 0; sn < MAX_SKILL; sn++) { if (skill_table[sn].name == NULL) break; if ((level < skill_table[sn].skill_level[klass]) || (skill_table[sn].skill_level[klass] > LEVEL_HERO)) continue; snprintf (buf, sizeof buf, "%18s %3dpts ", skill_table[sn].name, mana_cost (sn)); buf1.append(buf); if (++col % 3 == 0) buf1.append("\r\n"); } if (col % 3 != 0) buf1.append("\r\n"); send_to_char (buf1); return; } void Character::do_slist (std::string argument) { if ((!is_npc () && !class_table[klass].fMana) || is_npc ()) { send_to_char ("You do not need any stinking spells!\r\n"); return; } std::string buf1; buf1.append("ALL Spells available for your class.\r\n\r\n"); buf1.append("Lv Spells\r\n\r\n"); for (int lvl = 1; lvl < LEVEL_IMMORTAL; lvl++) { int col = 0; bool pSpell = true; char buf[MAX_STRING_LENGTH]; for (int sn = 0; sn < MAX_SKILL; sn++) { if (skill_table[sn].name == NULL) break; if (skill_table[sn].skill_level[klass] != lvl) continue; if (pSpell) { snprintf (buf, sizeof buf, "%2d:", level); buf1.append(buf); pSpell = false; } if (++col % 5 == 0) buf1.append(" "); snprintf (buf, sizeof buf, "%18s", skill_table[sn].name); buf1.append(buf); if (col % 4 == 0) buf1.append("\r\n"); } if (col % 4 != 0) buf1.append("\r\n"); } send_to_char (buf1); return; } /* by passing the conf command - Kahn */ void Character::do_autoexit (std::string argument) { (IS_SET (actflags, PLR_AUTOEXIT) ? do_config ("-autoexit") : do_config ("+autoexit")); } void Character::do_autoloot (std::string argument) { (IS_SET (actflags, PLR_AUTOLOOT) ? do_config ("-autoloot") : do_config ("+autoloot")); } void Character::do_autosac (std::string argument) { (IS_SET (actflags, PLR_AUTOSAC) ? do_config ("-autosac") : do_config ("+autosac")); } void Character::do_blank (std::string argument) { (IS_SET (actflags, PLR_BLANK) ? do_config ("-blank") : do_config ("+blank")); } void Character::do_brief (std::string argument) { (IS_SET (actflags, PLR_BRIEF) ? do_config ("-brief") : do_config ("+brief")); } void Character::do_combine (std::string argument) { (IS_SET (actflags, PLR_COMBINE) ? do_config ("-combine") : do_config ("+combine")); } void Character::do_pagelen (std::string argument) { char buf[MAX_STRING_LENGTH]; std::string arg; int lines; one_argument (argument, arg); if (arg.empty()) lines = 20; else lines = std::atoi (arg.c_str()); if (lines < 1) { send_to_char ("Negative or Zero values for a page pause is not legal.\r\n"); return; } pcdata->pagelen = lines; snprintf (buf, sizeof buf, "Page pause set to %d lines.\r\n", lines); send_to_char (buf); return; } /* Do_prompt from Morgenes from Aldara Mud */ void Character::do_prompt (std::string argument) { if (argument.empty()) { (IS_SET (actflags, PLR_PROMPT) ? do_config ("-prompt") : do_config ("+prompt")); return; } std::string buf; if (!strcmp (argument.c_str(), "all")) buf = "<%hhp %mm %vmv> "; else { smash_tilde (argument); if (argument.size() > 50) argument.erase(50); buf = argument; } prompt = buf; send_to_char ("Ok.\r\n"); return; } void Character::do_auto (std::string argument) { do_config (""); return; } void Character::do_north (std::string argument) { move_char (DIR_NORTH); return; } void Character::do_east (std::string argument) { move_char (DIR_EAST); return; } void Character::do_south (std::string argument) { move_char (DIR_SOUTH); return; } void Character::do_west (std::string argument) { move_char (DIR_WEST); return; } void Character::do_up (std::string argument) { move_char (DIR_UP); return; } void Character::do_down (std::string argument) { move_char (DIR_DOWN); return; } void Character::do_open (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Open what?\r\n"); return; } Object *obj; if ((obj = get_obj_here (arg)) != NULL) { /* 'open object' */ if (obj->item_type != ITEM_CONTAINER) { send_to_char ("That's not a container.\r\n"); return; } if (!IS_SET (obj->value[1], CONT_CLOSED)) { send_to_char ("It's already open.\r\n"); return; } if (!IS_SET (obj->value[1], CONT_CLOSEABLE)) { send_to_char ("You can't do that.\r\n"); return; } if (IS_SET (obj->value[1], CONT_LOCKED)) { send_to_char ("It's locked.\r\n"); return; } REMOVE_BIT (obj->value[1], CONT_CLOSED); send_to_char ("Ok.\r\n"); act ("$n opens $p.", obj, NULL, TO_ROOM); return; } int door; if ((door = find_door (arg)) >= 0) { /* 'open door' */ Room *to_room; Exit *pexit; Exit *pexit_rev; pexit = in_room->exit[door]; if (!IS_SET (pexit->exit_info, EX_CLOSED)) { send_to_char ("It's already open.\r\n"); return; } if (IS_SET (pexit->exit_info, EX_LOCKED)) { send_to_char ("It's locked.\r\n"); return; } REMOVE_BIT (pexit->exit_info, EX_CLOSED); act ("$n opens the $d.", NULL, pexit->name.c_str(), TO_ROOM); send_to_char ("Ok.\r\n"); /* open the other side */ if ((to_room = pexit->to_room) != NULL && (pexit_rev = to_room->exit[rev_dir[door]]) != NULL && pexit_rev->to_room == in_room) { REMOVE_BIT (pexit_rev->exit_info, EX_CLOSED); CharIter rch; for (rch = to_room->people.begin(); rch != to_room->people.end(); rch++) (*rch)->act ("The $d opens.", NULL, pexit_rev->name.c_str(), TO_CHAR); } } return; } void Character::do_close (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Close what?\r\n"); return; } Object *obj; if ((obj = get_obj_here (arg)) != NULL) { /* 'close object' */ if (obj->item_type != ITEM_CONTAINER) { send_to_char ("That's not a container.\r\n"); return; } if (IS_SET (obj->value[1], CONT_CLOSED)) { send_to_char ("It's already closed.\r\n"); return; } if (!IS_SET (obj->value[1], CONT_CLOSEABLE)) { send_to_char ("You can't do that.\r\n"); return; } SET_BIT (obj->value[1], CONT_CLOSED); send_to_char ("Ok.\r\n"); act ("$n closes $p.", obj, NULL, TO_ROOM); return; } int door; if ((door = find_door (arg)) >= 0) { /* 'close door' */ Room *to_room; Exit *pexit; Exit *pexit_rev; pexit = in_room->exit[door]; if (IS_SET (pexit->exit_info, EX_CLOSED)) { send_to_char ("It's already closed.\r\n"); return; } SET_BIT (pexit->exit_info, EX_CLOSED); act ("$n closes the $d.", NULL, pexit->name.c_str(), TO_ROOM); send_to_char ("Ok.\r\n"); /* close the other side */ if ((to_room = pexit->to_room) != NULL && (pexit_rev = to_room->exit[rev_dir[door]]) != 0 && pexit_rev->to_room == in_room) { SET_BIT (pexit_rev->exit_info, EX_CLOSED); CharIter rch; for (rch = to_room->people.begin(); rch != to_room->people.end(); rch++) (*rch)->act ("The $d closes.", NULL, pexit_rev->name.c_str(), TO_CHAR); } } return; } void Character::do_lock (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Lock what?\r\n"); return; } Object *obj; if ((obj = get_obj_here (arg)) != NULL) { /* 'lock object' */ if (obj->item_type != ITEM_CONTAINER) { send_to_char ("That's not a container.\r\n"); return; } if (!IS_SET (obj->value[1], CONT_CLOSED)) { send_to_char ("It's not closed.\r\n"); return; } if (obj->value[2] < 0) { send_to_char ("It can't be locked.\r\n"); return; } if (!has_key(obj->value[2])) { send_to_char ("You lack the key.\r\n"); return; } if (IS_SET (obj->value[1], CONT_LOCKED)) { send_to_char ("It's already locked.\r\n"); return; } SET_BIT (obj->value[1], CONT_LOCKED); send_to_char ("*Click*\r\n"); act ("$n locks $p.", obj, NULL, TO_ROOM); return; } int door; if ((door = find_door (arg)) >= 0) { /* 'lock door' */ Room *to_room; Exit *pexit; Exit *pexit_rev; pexit = in_room->exit[door]; if (!IS_SET (pexit->exit_info, EX_CLOSED)) { send_to_char ("It's not closed.\r\n"); return; } if (pexit->key < 0) { send_to_char ("It can't be locked.\r\n"); return; } if (!has_key(pexit->key)) { send_to_char ("You lack the key.\r\n"); return; } if (IS_SET (pexit->exit_info, EX_LOCKED)) { send_to_char ("It's already locked.\r\n"); return; } SET_BIT (pexit->exit_info, EX_LOCKED); send_to_char ("*Click*\r\n"); act ("$n locks the $d.", NULL, pexit->name.c_str(), TO_ROOM); /* lock the other side */ if ((to_room = pexit->to_room) != NULL && (pexit_rev = to_room->exit[rev_dir[door]]) != 0 && pexit_rev->to_room == in_room) { SET_BIT (pexit_rev->exit_info, EX_LOCKED); } } return; } void Character::do_unlock (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Unlock what?\r\n"); return; } Object *obj; if ((obj = get_obj_here (arg)) != NULL) { /* 'unlock object' */ if (obj->item_type != ITEM_CONTAINER) { send_to_char ("That's not a container.\r\n"); return; } if (!IS_SET (obj->value[1], CONT_CLOSED)) { send_to_char ("It's not closed.\r\n"); return; } if (obj->value[2] < 0) { send_to_char ("It can't be unlocked.\r\n"); return; } if (!has_key(obj->value[2])) { send_to_char ("You lack the key.\r\n"); return; } if (!IS_SET (obj->value[1], CONT_LOCKED)) { send_to_char ("It's already unlocked.\r\n"); return; } REMOVE_BIT (obj->value[1], CONT_LOCKED); send_to_char ("*Click*\r\n"); act ("$n unlocks $p.", obj, NULL, TO_ROOM); return; } int door; if ((door = find_door (arg)) >= 0) { /* 'unlock door' */ Room *to_room; Exit *pexit; Exit *pexit_rev; pexit = in_room->exit[door]; if (!IS_SET (pexit->exit_info, EX_CLOSED)) { send_to_char ("It's not closed.\r\n"); return; } if (pexit->key < 0) { send_to_char ("It can't be unlocked.\r\n"); return; } if (!has_key(pexit->key)) { send_to_char ("You lack the key.\r\n"); return; } if (!IS_SET (pexit->exit_info, EX_LOCKED)) { send_to_char ("It's already unlocked.\r\n"); return; } REMOVE_BIT (pexit->exit_info, EX_LOCKED); send_to_char ("*Click*\r\n"); act ("$n unlocks the $d.", NULL, pexit->name.c_str(), TO_ROOM); /* unlock the other side */ if ((to_room = pexit->to_room) != NULL && (pexit_rev = to_room->exit[rev_dir[door]]) != NULL && pexit_rev->to_room == in_room) { REMOVE_BIT (pexit_rev->exit_info, EX_LOCKED); } } return; } void Character::do_pick (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Pick what?\r\n"); return; } wait_state (skill_table[skill_lookup("pick lock")].beats); /* look for guards */ CharIter rch; for (rch = in_room->people.begin(); rch != in_room->people.end(); rch++) { if ((*rch)->is_npc () && (*rch)->is_awake () && level + 5 < (*rch)->level) { act ("$N is standing too close to the lock.", NULL, *rch, TO_CHAR); return; } } if (!is_npc () && number_percent () > pcdata->learned[skill_lookup("pick lock")]) { send_to_char ("You failed.\r\n"); return; } Object *obj; if ((obj = get_obj_here (arg)) != NULL) { /* 'pick object' */ if (obj->item_type != ITEM_CONTAINER) { send_to_char ("That's not a container.\r\n"); return; } if (!IS_SET (obj->value[1], CONT_CLOSED)) { send_to_char ("It's not closed.\r\n"); return; } if (obj->value[2] < 0) { send_to_char ("It can't be unlocked.\r\n"); return; } if (!IS_SET (obj->value[1], CONT_LOCKED)) { send_to_char ("It's already unlocked.\r\n"); return; } if (IS_SET (obj->value[1], CONT_PICKPROOF)) { send_to_char ("You failed.\r\n"); return; } REMOVE_BIT (obj->value[1], CONT_LOCKED); send_to_char ("*Click*\r\n"); act ("$n picks $p.", obj, NULL, TO_ROOM); return; } int door; if ((door = find_door (arg)) >= 0) { /* 'pick door' */ Room *to_room; Exit *pexit; Exit *pexit_rev; pexit = in_room->exit[door]; if (!IS_SET (pexit->exit_info, EX_CLOSED)) { send_to_char ("It's not closed.\r\n"); return; } if (pexit->key < 0) { send_to_char ("It can't be picked.\r\n"); return; } if (!IS_SET (pexit->exit_info, EX_LOCKED)) { send_to_char ("It's already unlocked.\r\n"); return; } if (IS_SET (pexit->exit_info, EX_PICKPROOF)) { send_to_char ("You failed.\r\n"); return; } REMOVE_BIT (pexit->exit_info, EX_LOCKED); send_to_char ("*Click*\r\n"); act ("$n picks the $d.", NULL, pexit->name.c_str(), TO_ROOM); /* pick the other side */ if ((to_room = pexit->to_room) != NULL && (pexit_rev = to_room->exit[rev_dir[door]]) != NULL && pexit_rev->to_room == in_room) { REMOVE_BIT (pexit_rev->exit_info, EX_LOCKED); } } return; } void Character::do_stand (std::string argument) { switch (position) { case POS_SLEEPING: if (is_affected (AFF_SLEEP)) { send_to_char ("You can't wake up!\r\n"); return; } send_to_char ("You wake and stand up.\r\n"); act ("$n wakes and stands up.", NULL, NULL, TO_ROOM); position = POS_STANDING; break; case POS_RESTING: send_to_char ("You stand up.\r\n"); act ("$n stands up.", NULL, NULL, TO_ROOM); position = POS_STANDING; break; case POS_STANDING: send_to_char ("You are already standing.\r\n"); break; case POS_FIGHTING: send_to_char ("You are already fighting!\r\n"); break; } return; } void Character::do_rest (std::string argument) { switch (position) { case POS_SLEEPING: send_to_char ("You are already sleeping.\r\n"); break; case POS_RESTING: send_to_char ("You are already resting.\r\n"); break; case POS_STANDING: send_to_char ("You rest.\r\n"); act ("$n rests.", NULL, NULL, TO_ROOM); position = POS_RESTING; break; case POS_FIGHTING: send_to_char ("You are already fighting!\r\n"); break; } return; } void Character::do_sleep (std::string argument) { switch (position) { case POS_SLEEPING: send_to_char ("You are already sleeping.\r\n"); break; case POS_RESTING: case POS_STANDING: send_to_char ("You sleep.\r\n"); act ("$n sleeps.", NULL, NULL, TO_ROOM); position = POS_SLEEPING; break; case POS_FIGHTING: send_to_char ("You are already fighting!\r\n"); break; } return; } void Character::do_wake (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { do_stand (argument); return; } if (!is_awake ()) { send_to_char ("You are asleep yourself!\r\n"); return; } Character *victim; if ((victim = get_char_room (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (victim->is_awake ()) { act ("$N is already awake.", NULL, victim, TO_CHAR); return; } if (victim->is_affected (AFF_SLEEP)) { act ("You can't wake $M!", NULL, victim, TO_CHAR); return; } act ("You wake $M.", NULL, victim, TO_CHAR); act ("$n wakes you.", NULL, victim, TO_VICT); victim->position = POS_STANDING; return; } void Character::do_sneak (std::string argument) { Affect af; int snk = skill_lookup("sneak"); send_to_char ("You attempt to move silently.\r\n"); affect_strip (snk); if (is_npc () || number_percent () < pcdata->learned[snk]) { af.type = snk; af.duration = level; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_SNEAK; affect_to_char(&af); } return; } void Character::do_hide (std::string argument) { send_to_char ("You attempt to hide.\r\n"); if (is_affected (AFF_HIDE)) REMOVE_BIT (affected_by, AFF_HIDE); if (is_npc () || number_percent () < pcdata->learned[skill_lookup("hide")]) SET_BIT (affected_by, AFF_HIDE); return; } /* * Contributed by Alander. */ void Character::do_visible (std::string argument) { affect_strip (skill_lookup("invis")); affect_strip (skill_lookup("mass invis")); affect_strip (skill_lookup("sneak")); REMOVE_BIT (affected_by, AFF_HIDE); REMOVE_BIT (affected_by, AFF_INVISIBLE); REMOVE_BIT (affected_by, AFF_SNEAK); send_to_char ("Ok.\r\n"); return; } void Character::do_recall (std::string argument) { char buf[MAX_STRING_LENGTH]; Room *location; act ("$n prays for transportation!", 0, 0, TO_ROOM); if ((location = get_room_index (ROOM_VNUM_TEMPLE)) == NULL) { send_to_char ("You are completely lost.\r\n"); return; } if (in_room == location) return; if (IS_SET (in_room->room_flags, ROOM_NO_RECALL) || is_affected (AFF_CURSE)) { send_to_char ("God has forsaken you.\r\n"); return; } if (fighting != NULL) { int lose; if (number_percent() <= 50) { wait_state (4); lose = (desc != NULL) ? 50 : 100; gain_exp(0 - lose); snprintf (buf, sizeof buf, "You failed! You lose %d exps.\r\n", lose); send_to_char (buf); return; } lose = (desc != NULL) ? 100 : 200; gain_exp(0 - lose); snprintf (buf, sizeof buf, "You recall from combat! You lose %d exps.\r\n", lose); send_to_char (buf); stop_fighting(true); } move /= 2; act ("$n disappears.", NULL, NULL, TO_ROOM); char_from_room(); char_to_room(location); act ("$n appears in the room.", NULL, NULL, TO_ROOM); do_look ("auto"); return; } void Character::do_train (std::string argument) { if (is_npc ()) return; std::string buf; sh_int ability; const char *pOutput; /* * Check for trainer. */ CharIter mob; for (mob = in_room->people.begin(); mob != in_room->people.end(); mob++) { if ((*mob)->is_npc () && IS_SET ((*mob)->actflags, ACT_TRAIN)) break; } if (mob == in_room->people.end()) { send_to_char ("You can't do that here.\r\n"); return; } if (argument.empty()) { buf = "You have " + itoa(practice, 10) + " practice sessions.\r\n"; send_to_char (buf); argument = "foo"; } int cost = 5; if (!str_cmp (argument, "str")) { if (class_table[klass].attr_prime == APPLY_STR) cost = 3; ability = pcdata->get_perm(argument); pOutput = "strength"; } else if (!str_cmp (argument, "int")) { if (class_table[klass].attr_prime == APPLY_INT) cost = 3; ability = pcdata->get_perm(argument); pOutput = "intelligence"; } else if (!str_cmp (argument, "wis")) { if (class_table[klass].attr_prime == APPLY_WIS) cost = 3; ability = pcdata->get_perm(argument); pOutput = "wisdom"; } else if (!str_cmp (argument, "dex")) { if (class_table[klass].attr_prime == APPLY_DEX) cost = 3; ability = pcdata->get_perm(argument); pOutput = "dexterity"; } else if (!str_cmp (argument, "con")) { if (class_table[klass].attr_prime == APPLY_CON) cost = 3; ability = pcdata->get_perm(argument); pOutput = "constitution"; } else { buf = "You can train:"; buf.append(pcdata->trainable_list()); if (buf[buf.size() - 1] != ':') { buf.append(".\r\n"); send_to_char (buf); } else { /* * This message dedicated to Jordan ... you big stud! */ act ("You have nothing left to train, you $T!", NULL, sex == SEX_MALE ? "big stud" : sex == SEX_FEMALE ? "hot babe" : "wild thing", TO_CHAR); } return; } if (ability >= 18) { act ("Your $T is already at maximum.", NULL, pOutput, TO_CHAR); return; } if (cost > practice) { send_to_char ("You don't have enough practices.\r\n"); return; } practice -= cost; pcdata->set_perm(argument, ability+1); act ("Your $T increases!", NULL, pOutput, TO_CHAR); act ("$n's $T increases!", NULL, pOutput, TO_ROOM); return; } void Character::do_get (std::string argument) { std::string arg1; std::string arg2; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); /* Get type. */ if (arg1.empty()) { send_to_char ("Get what?\r\n"); return; } Object *obj; Object *container; bool found; if (arg2.empty()) { if (str_cmp (arg1, "all") && str_prefix ("all.", arg1)) { /* 'get obj' */ obj = get_obj_list (arg1, in_room->contents); if (obj == NULL) { act ("I see no $T here.", NULL, arg1.c_str(), TO_CHAR); return; } get_obj (obj, NULL); } else { /* 'get all' or 'get all.obj' */ found = false; ObjIter o, onext; for (o = in_room->contents.begin(); o != in_room->contents.end(); o = onext) { obj = *o; onext = ++o; if ((arg1[3] == '\0' || is_name (&arg1[4], obj->name)) && can_see_obj(obj)) { found = true; get_obj (obj, NULL); } } if (!found) { if (arg1[3] == '\0') send_to_char ("I see nothing here.\r\n"); else act ("I see no $T here.", NULL, &arg1[4], TO_CHAR); } } } else { /* 'get ... container' */ if (!str_cmp (arg2, "all") || !str_prefix ("all.", arg2)) { send_to_char ("You can't do that.\r\n"); return; } if ((container = get_obj_here (arg2)) == NULL) { act ("I see no $T here.", NULL, arg2.c_str(), TO_CHAR); return; } switch (container->item_type) { default: send_to_char ("That's not a container.\r\n"); return; case ITEM_CONTAINER: case ITEM_CORPSE_NPC: break; case ITEM_CORPSE_PC: { std::string nm; std::string pd; if (is_npc ()) { send_to_char ("You can't do that.\r\n"); return; } pd = container->short_descr; pd = one_argument (pd, nm); pd = one_argument (pd, nm); pd = one_argument (pd, nm); if (str_cmp (nm, name) && !is_immortal()) { bool fGroup; fGroup = false; CharIter c; for (c = char_list.begin(); c != char_list.end(); c++) { if (!(*c)->is_npc () && is_same_group (this, *c) && !str_cmp (nm, (*c)->name)) { fGroup = true; break; } } if (!fGroup) { send_to_char ("You can't do that.\r\n"); return; } } } } if (IS_SET (container->value[1], CONT_CLOSED)) { act ("The $d is closed.", NULL, container->name.c_str(), TO_CHAR); return; } if (str_cmp (arg1, "all") && str_prefix ("all.", arg1)) { /* 'get obj container' */ obj = get_obj_list (arg1, container->contains); if (obj == NULL) { act ("I see nothing like that in the $T.", NULL, arg2.c_str(), TO_CHAR); return; } get_obj (obj, container); } else { /* 'get all container' or 'get all.obj container' */ found = false; ObjIter o, onext; for (o = container->contains.begin(); o != container->contains.end(); o = onext) { obj = *o; onext = ++o; if ((arg1[3] == '\0' || is_name (&arg1[4], obj->name)) && can_see_obj(obj)) { found = true; get_obj (obj, container); } } if (!found) { if (arg1[3] == '\0') act ("I see nothing in the $T.", NULL, arg2.c_str(), TO_CHAR); else act ("I see nothing like that in the $T.", NULL, arg2.c_str(), TO_CHAR); } } } return; } void Character::do_put (std::string argument) { std::string arg1; std::string arg2; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); if (arg1.empty() || arg2.empty()) { send_to_char ("Put what in what?\r\n"); return; } if (!str_cmp (arg2, "all") || !str_prefix ("all.", arg2)) { send_to_char ("You can't do that.\r\n"); return; } Object *container; if ((container = get_obj_here (arg2)) == NULL) { act ("I see no $T here.", NULL, arg2.c_str(), TO_CHAR); return; } if (container->item_type != ITEM_CONTAINER) { send_to_char ("That's not a container.\r\n"); return; } if (IS_SET (container->value[1], CONT_CLOSED)) { act ("The $d is closed.", NULL, container->name.c_str(), TO_CHAR); return; } Object *obj; if (str_cmp (arg1, "all") && str_prefix ("all.", arg1)) { /* 'put obj container' */ if ((obj = get_obj_carry (arg1)) == NULL) { send_to_char ("You do not have that item.\r\n"); return; } if (obj == container) { send_to_char ("You can't fold it into itself.\r\n"); return; } if (!can_drop_obj (obj)) { send_to_char ("You can't let go of it.\r\n"); return; } if (obj->get_obj_weight() + container->get_obj_weight() > container->value[0]) { send_to_char ("It won't fit.\r\n"); return; } obj->obj_from_char(); obj->obj_to_obj (container); act ("$n puts $p in $P.", obj, container, TO_ROOM); act ("You put $p in $P.", obj, container, TO_CHAR); } else { /* 'put all container' or 'put all.obj container' */ ObjIter o, onext; for (o = carrying.begin(); o != carrying.end(); o = onext) { obj = *o; onext = ++o; if ((arg1[3] == '\0' || is_name (&arg1[4], obj->name)) && can_see_obj(obj) && obj->wear_loc == WEAR_NONE && obj != container && can_drop_obj (obj) && obj->get_obj_weight() + container->get_obj_weight() <= container->value[0]) { obj->obj_from_char (); obj->obj_to_obj (container); act ("$n puts $p in $P.", obj, container, TO_ROOM); act ("You put $p in $P.", obj, container, TO_CHAR); } } } return; } void Character::do_drop (std::string argument) { std::string arg; argument = one_argument (argument, arg); if (arg.empty()) { send_to_char ("Drop what?\r\n"); return; } Object *obj; bool found; if (is_number (arg)) { /* 'drop NNNN coins' */ int amount; amount = std::atoi (arg.c_str()); argument = one_argument (argument, arg); if (amount <= 0 || (str_cmp (arg, "coins") && str_cmp (arg, "coin"))) { send_to_char ("Sorry, you can't do that.\r\n"); return; } if (gold < amount) { send_to_char ("You haven't got that many coins.\r\n"); return; } gold -= amount; ObjIter o, onext; for (o = in_room->contents.begin(); o != in_room->contents.end(); o = onext) { obj = *o; onext = ++o; switch (obj->pIndexData->vnum) { case OBJ_VNUM_MONEY_ONE: amount += 1; obj->extract_obj (); break; case OBJ_VNUM_MONEY_SOME: amount += obj->value[0]; obj->extract_obj (); break; } } create_money (amount)->obj_to_room (in_room); act ("$n drops some gold.", NULL, NULL, TO_ROOM); send_to_char ("OK.\r\n"); return; } if (str_cmp (arg, "all") && str_prefix ("all.", arg)) { /* 'drop obj' */ if ((obj = get_obj_carry (arg)) == NULL) { send_to_char ("You do not have that item.\r\n"); return; } if (!can_drop_obj (obj)) { send_to_char ("You can't let go of it.\r\n"); return; } obj->obj_from_char(); obj->obj_to_room (in_room); act ("$n drops $p.", obj, NULL, TO_ROOM); act ("You drop $p.", obj, NULL, TO_CHAR); } else { /* 'drop all' or 'drop all.obj' */ found = false; ObjIter o, onext; for (o = carrying.begin(); o != carrying.end(); o = onext) { obj = *o; onext = ++o; if ((arg[3] == '\0' || is_name (&arg[4], obj->name)) && can_see_obj(obj) && obj->wear_loc == WEAR_NONE && can_drop_obj (obj)) { found = true; obj->obj_from_char(); obj->obj_to_room(in_room); act ("$n drops $p.", obj, NULL, TO_ROOM); act ("You drop $p.", obj, NULL, TO_CHAR); } } if (!found) { if (arg[3] == '\0') act ("You are not carrying anything.", NULL, arg.c_str(), TO_CHAR); else act ("You are not carrying any $T.", NULL, &arg[4], TO_CHAR); } } return; } void Character::do_give (std::string argument) { std::string arg1; std::string arg2; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); if (arg1.empty() || arg2.empty()) { send_to_char ("Give what to whom?\r\n"); return; } Character *victim; Object *obj; if (is_number (arg1)) { /* 'give NNNN coins victim' */ int amount; amount = std::atoi (arg1.c_str()); if (amount <= 0 || (str_cmp (arg2, "coins") && str_cmp (arg2, "coin"))) { send_to_char ("Sorry, you can't do that.\r\n"); return; } argument = one_argument (argument, arg2); if (arg2.empty()) { send_to_char ("Give what to whom?\r\n"); return; } if ((victim = get_char_room (arg2)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (gold < amount) { send_to_char ("You haven't got that much gold.\r\n"); return; } gold -= amount; victim->gold += amount; act ("$n gives you some gold.", NULL, victim, TO_VICT); act ("$n gives $N some gold.", NULL, victim, TO_NOTVICT); act ("You give $N some gold.", NULL, victim, TO_CHAR); send_to_char ("OK.\r\n"); mprog_bribe_trigger (victim, this, amount); return; } if ((obj = get_obj_carry (arg1)) == NULL) { send_to_char ("You do not have that item.\r\n"); return; } if (obj->wear_loc != WEAR_NONE) { send_to_char ("You must remove it first.\r\n"); return; } if ((victim = get_char_room (arg2)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (!can_drop_obj (obj)) { send_to_char ("You can't let go of it.\r\n"); return; } if (victim->carry_number + obj->get_obj_number() > victim->can_carry_n()) { act ("$N has $S hands full.", NULL, victim, TO_CHAR); return; } if (victim->carry_weight + obj->get_obj_weight() > victim->can_carry_w()) { act ("$N can't carry that much weight.", NULL, victim, TO_CHAR); return; } if (!victim->can_see_obj(obj)) { act ("$N can't see it.", NULL, victim, TO_CHAR); return; } obj->obj_from_char (); obj->obj_to_char (victim); MOBtrigger = false; act ("$n gives $p to $N.", obj, victim, TO_NOTVICT); act ("$n gives you $p.", obj, victim, TO_VICT); act ("You give $p to $N.", obj, victim, TO_CHAR); mprog_give_trigger (victim, this, obj); return; } void Character::do_fill (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Fill what?\r\n"); return; } Object *obj; if ((obj = get_obj_carry (arg)) == NULL) { send_to_char ("You do not have that item.\r\n"); return; } bool found = false; ObjIter o; for (o = in_room->contents.begin(); o != in_room->contents.end(); o++) { if ((*o)->item_type == ITEM_FOUNTAIN) { found = true; break; } } if (!found) { send_to_char ("There is no fountain here!\r\n"); return; } if (obj->item_type != ITEM_DRINK_CON) { send_to_char ("You can't fill that.\r\n"); return; } if (obj->value[1] != 0 && obj->value[2] != 0) { send_to_char ("There is already another liquid in it.\r\n"); return; } if (obj->value[1] >= obj->value[0]) { send_to_char ("Your container is full.\r\n"); return; } act ("You fill $p.", obj, NULL, TO_CHAR); obj->value[2] = 0; obj->value[1] = obj->value[0]; return; } void Character::do_drink (std::string argument) { std::string arg; Object *obj = NULL; int amount; int liquid; one_argument (argument, arg); if (arg.empty()) { ObjIter o; for (o = in_room->contents.begin(); o != in_room->contents.end(); o++) { obj = *o; if (obj->item_type == ITEM_FOUNTAIN) break; } if (obj == NULL) { send_to_char ("Drink what?\r\n"); return; } } else { if ((obj = get_obj_here (arg)) == NULL) { send_to_char ("You can't find it.\r\n"); return; } } if (!is_npc () && pcdata->condition[COND_DRUNK] > 10) { send_to_char ("You fail to reach your mouth. *Hic*\r\n"); return; } switch (obj->item_type) { default: send_to_char ("You can't drink from that.\r\n"); break; case ITEM_FOUNTAIN: if (!is_npc ()) pcdata->condition[COND_THIRST] = 48; act ("$n drinks from the fountain.", NULL, NULL, TO_ROOM); send_to_char ("You are not thirsty.\r\n"); break; case ITEM_DRINK_CON: if (obj->value[1] <= 0) { send_to_char ("It is already empty.\r\n"); return; } if ((liquid = obj->value[2]) >= LIQ_MAX) { bug_printf ("Do_drink: bad liquid number %d.", liquid); liquid = obj->value[2] = 0; } act ("$n drinks $T from $p.", obj, liq_table[liquid].liq_name, TO_ROOM); act ("You drink $T from $p.", obj, liq_table[liquid].liq_name, TO_CHAR); amount = number_range (3, 10); amount = std::min (amount, obj->value[1]); gain_condition (COND_DRUNK, amount * liq_table[liquid].liq_affect[COND_DRUNK]); gain_condition (COND_FULL, amount * liq_table[liquid].liq_affect[COND_FULL]); gain_condition (COND_THIRST, amount * liq_table[liquid].liq_affect[COND_THIRST]); if (!is_npc () && pcdata->condition[COND_DRUNK] > 10) send_to_char ("You feel drunk.\r\n"); if (!is_npc () && pcdata->condition[COND_FULL] > 40) send_to_char ("You are full.\r\n"); if (!is_npc () && pcdata->condition[COND_THIRST] > 40) send_to_char ("You do not feel thirsty.\r\n"); if (obj->value[3] != 0) { /* The shit was poisoned ! */ Affect af; act ("$n chokes and gags.", NULL, NULL, TO_ROOM); send_to_char ("You choke and gag.\r\n"); af.type = skill_lookup("poison"); af.duration = 3 * amount; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_POISON; affect_join (&af); } obj->value[1] -= amount; if (obj->value[1] <= 0) { send_to_char ("The empty container vanishes.\r\n"); obj->extract_obj (); } break; } return; } void Character::do_eat (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Eat what?\r\n"); return; } Object *obj; if ((obj = get_obj_carry (arg)) == NULL) { send_to_char ("You do not have that item.\r\n"); return; } if (!is_immortal()) { if (obj->item_type != ITEM_FOOD && obj->item_type != ITEM_PILL) { send_to_char ("That's not edible.\r\n"); return; } if (!is_npc () && pcdata->condition[COND_FULL] > 40) { send_to_char ("You are too full to eat more.\r\n"); return; } } act ("$n eats $p.", obj, NULL, TO_ROOM); act ("You eat $p.", obj, NULL, TO_CHAR); switch (obj->item_type) { case ITEM_FOOD: if (!is_npc ()) { int condition; condition = pcdata->condition[COND_FULL]; gain_condition (COND_FULL, obj->value[0]); if (condition == 0 && pcdata->condition[COND_FULL] > 0) send_to_char ("You are no longer hungry.\r\n"); else if (pcdata->condition[COND_FULL] > 40) send_to_char ("You are full.\r\n"); } if (obj->value[3] != 0) { /* The shit was poisoned! */ Affect af; act ("$n chokes and gags.", 0, 0, TO_ROOM); send_to_char ("You choke and gag.\r\n"); af.type = skill_lookup("poison"); af.duration = 2 * obj->value[0]; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_POISON; affect_join (&af); } break; case ITEM_PILL: obj_cast_spell (obj->value[1], obj->value[0], this, this, NULL); obj_cast_spell (obj->value[2], obj->value[0], this, this, NULL); obj_cast_spell (obj->value[3], obj->value[0], this, this, NULL); break; } obj->extract_obj (); return; } void Character::do_wear (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Wear, wield, or hold what?\r\n"); return; } Object *obj; if (!str_cmp (arg, "all")) { ObjIter o, onext; for (o = carrying.begin(); o != carrying.end(); o = onext) { obj = *o; onext = ++o; if (obj->wear_loc == WEAR_NONE && can_see_obj(obj)) wear_obj (obj, false); } return; } else { if ((obj = get_obj_carry (arg)) == NULL) { send_to_char ("You do not have that item.\r\n"); return; } wear_obj (obj, true); } return; } void Character::do_remove (std::string argument) { std::string arg; Object *obj; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Remove what?\r\n"); return; } if ((obj = get_obj_wear (arg)) == NULL) { send_to_char ("You do not have that item.\r\n"); return; } remove_obj (obj->wear_loc, true); return; } void Character::do_sacrifice (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty() || !str_cmp (arg, name)) { act ("$n offers $mself to God, who graciously declines.", NULL, NULL, TO_ROOM); send_to_char ("God appreciates your offer and may accept it later."); return; } Object* obj = get_obj_list (arg, in_room->contents); if (obj == NULL) { send_to_char ("You can't find it.\r\n"); return; } if (!obj->can_wear(ITEM_TAKE)) { act ("$p is not an acceptable sacrifice.", obj, 0, TO_CHAR); return; } send_to_char ("God gives you one gold coin for your sacrifice.\r\n"); gold += 1; act ("$n sacrifices $p to God.", obj, NULL, TO_ROOM); obj->extract_obj (); return; } void Character::do_quaff (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Quaff what?\r\n"); return; } Object *obj; if ((obj = get_obj_carry (arg)) == NULL) { send_to_char ("You do not have that potion.\r\n"); return; } if (obj->item_type != ITEM_POTION) { send_to_char ("You can quaff only potions.\r\n"); return; } act ("$n quaffs $p.", obj, NULL, TO_ROOM); act ("You quaff $p.", obj, NULL, TO_CHAR); obj_cast_spell (obj->value[1], obj->value[0], this, this, NULL); obj_cast_spell (obj->value[2], obj->value[0], this, this, NULL); obj_cast_spell (obj->value[3], obj->value[0], this, this, NULL); obj->extract_obj (); return; } void Character::do_recite (std::string argument) { std::string arg1; std::string arg2; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); Object *scroll; if ((scroll = get_obj_carry (arg1)) == NULL) { send_to_char ("You do not have that scroll.\r\n"); return; } if (scroll->item_type != ITEM_SCROLL) { send_to_char ("You can recite only scrolls.\r\n"); return; } Character *victim; Object *obj = NULL; if (arg2.empty()) { victim = this; } else { if ((victim = get_char_room (arg2)) == NULL && (obj = get_obj_here (arg2)) == NULL) { send_to_char ("You can't find it.\r\n"); return; } } act ("$n recites $p.", scroll, NULL, TO_ROOM); act ("You recite $p.", scroll, NULL, TO_CHAR); obj_cast_spell (scroll->value[1], scroll->value[0], this, victim, obj); obj_cast_spell (scroll->value[2], scroll->value[0], this, victim, obj); obj_cast_spell (scroll->value[3], scroll->value[0], this, victim, obj); scroll->extract_obj (); return; } void Character::do_brandish (std::string argument) { Character *vch; Object *staff; if ((staff = get_eq_char (WEAR_HOLD)) == NULL) { send_to_char ("You hold nothing in your hand.\r\n"); return; } if (staff->item_type != ITEM_STAFF) { send_to_char ("You can brandish only with a staff.\r\n"); return; } int sn; if ((sn = staff->value[3]) < 0 || sn >= MAX_SKILL || skill_table[sn].spell_fun == NULL) { bug_printf ("Do_brandish: bad sn %d.", sn); return; } wait_state (2 * PULSE_VIOLENCE); if (staff->value[2] > 0) { act ("$n brandishes $p.", staff, NULL, TO_ROOM); act ("You brandish $p.", staff, NULL, TO_CHAR); CharIter rch, next; for (rch = in_room->people.begin(); rch != in_room->people.end(); rch = next) { vch = *rch; next = ++rch; switch (skill_table[sn].target) { default: bug_printf ("Do_brandish: bad target for sn %d.", sn); return; case TAR_IGNORE: if (vch != this) continue; break; case TAR_CHAR_OFFENSIVE: if (is_npc () ? vch->is_npc () : !vch->is_npc ()) continue; break; case TAR_CHAR_DEFENSIVE: if (is_npc () ? !vch->is_npc () : vch->is_npc ()) continue; break; case TAR_CHAR_SELF: if (vch != this) continue; break; } obj_cast_spell (staff->value[3], staff->value[0], this, vch, NULL); } } if (--staff->value[2] <= 0) { act ("$n's $p blazes bright and is gone.", staff, NULL, TO_ROOM); act ("Your $p blazes bright and is gone.", staff, NULL, TO_CHAR); staff->extract_obj (); } return; } void Character::do_zap (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty() && fighting == NULL) { send_to_char ("Zap whom or what?\r\n"); return; } Object *wand; if ((wand = get_eq_char (WEAR_HOLD)) == NULL) { send_to_char ("You hold nothing in your hand.\r\n"); return; } if (wand->item_type != ITEM_WAND) { send_to_char ("You can zap only with a wand.\r\n"); return; } Character *victim; Object *obj = NULL; if (arg.empty()) { if (fighting != NULL) { victim = fighting; } else { send_to_char ("Zap whom or what?\r\n"); return; } } else { if ((victim = get_char_room (arg)) == NULL && (obj = get_obj_here (arg)) == NULL) { send_to_char ("You can't find it.\r\n"); return; } } wait_state (2 * PULSE_VIOLENCE); if (wand->value[2] > 0) { if (victim != NULL) { act ("$n zaps $N with $p.", wand, victim, TO_ROOM); act ("You zap $N with $p.", wand, victim, TO_CHAR); } else { act ("$n zaps $P with $p.", wand, obj, TO_ROOM); act ("You zap $P with $p.", wand, obj, TO_CHAR); } obj_cast_spell (wand->value[3], wand->value[0], this, victim, obj); } if (--wand->value[2] <= 0) { act ("$n's $p explodes into fragments.", wand, NULL, TO_ROOM); act ("Your $p explodes into fragments.", wand, NULL, TO_CHAR); wand->extract_obj (); } return; } void Character::do_steal (std::string argument) { std::string arg1, arg2, buf; Character *victim; Object *obj; int percent; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); if (arg1.empty() || arg2.empty()) { send_to_char ("Steal what from whom?\r\n"); return; } if ((victim = get_char_room (arg2)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (victim == this) { send_to_char ("That's pointless.\r\n"); return; } wait_state (skill_table[skill_lookup("steal")].beats); percent = number_percent () + (victim->is_awake () ? 10 : -50); if (level + 5 < victim->level || victim->position == POS_FIGHTING || !victim->is_npc () || (!is_npc () && percent > pcdata->learned[skill_lookup("steal")])) { /* * Failure. */ send_to_char ("Oops.\r\n"); act ("$n tried to steal from you.\r\n", NULL, victim, TO_VICT); act ("$n tried to steal from $N.\r\n", NULL, victim, TO_NOTVICT); buf = name + " is a bloody thief!"; victim->do_shout (buf); if (!is_npc ()) { if (victim->is_npc ()) { multi_hit (victim, this, TYPE_UNDEFINED); } else { log_printf (buf.c_str()); if (!IS_SET (actflags, PLR_THIEF)) { SET_BIT (actflags, PLR_THIEF); send_to_char ("*** You are now a THIEF!! ***\r\n"); save_char_obj(); } } } return; } if (!str_cmp (arg1, "coin") || !str_cmp (arg1, "coins") || !str_cmp (arg1, "gold")) { int amount; amount = victim->gold * number_range (1, 10) / 100; if (amount <= 0) { send_to_char ("You couldn't get any gold.\r\n"); return; } gold += amount; victim->gold -= amount; buf = "Bingo! You got " + itoa(amount, 10) + " gold coins.\r\n"; send_to_char (buf); return; } if ((obj = victim->get_obj_carry (arg1)) == NULL) { send_to_char ("You can't find it.\r\n"); return; } if (!can_drop_obj (obj) || IS_SET (obj->extra_flags, ITEM_INVENTORY) || obj->level > level) { send_to_char ("You can't pry it away.\r\n"); return; } if (carry_number + obj->get_obj_number() > can_carry_n()) { send_to_char ("You have your hands full.\r\n"); return; } if (carry_weight + obj->get_obj_weight() > can_carry_w()) { send_to_char ("You can't carry that much weight.\r\n"); return; } obj->obj_from_char (); obj->obj_to_char (this); send_to_char ("Ok.\r\n"); return; } void Character::do_buy (std::string argument) { std::string arg; argument = one_argument (argument, arg); if (arg.empty()) { send_to_char ("Buy what?\r\n"); return; } if (IS_SET (in_room->room_flags, ROOM_PET_SHOP)) { std::string buf; Character *pet; Room *pRoomIndexNext; Room *in_rm; if (is_npc ()) return; pRoomIndexNext = get_room_index (in_room->vnum + 1); if (pRoomIndexNext == NULL) { bug_printf ("Do_buy: bad pet shop at vnum %d.", in_room->vnum); send_to_char ("Sorry, you can't buy that here.\r\n"); return; } in_rm = in_room; in_room = pRoomIndexNext; pet = get_char_room (arg); in_room = in_rm; if (pet == NULL || !IS_SET (pet->actflags, ACT_PET)) { send_to_char ("Sorry, you can't buy that here.\r\n"); return; } if (IS_SET (actflags, PLR_BOUGHT_PET)) { send_to_char ("You already bought one pet this level.\r\n"); return; } if (gold < 10 * pet->level * pet->level) { send_to_char ("You can't afford it.\r\n"); return; } if (level < pet->level) { send_to_char ("You're not ready for this pet.\r\n"); return; } gold -= 10 * pet->level * pet->level; pet = pet->pIndexData->create_mobile(); SET_BIT (actflags, PLR_BOUGHT_PET); SET_BIT (pet->actflags, ACT_PET); SET_BIT (pet->affected_by, AFF_CHARM); argument = one_argument (argument, arg); if (!arg.empty()) { buf = pet->name + " " + arg; pet->name = buf; } buf = pet->description + "A neck tag says 'I belong to " + name + "'.\r\n"; pet->description = buf; pet->char_to_room(in_room); pet->add_follower(this); send_to_char ("Enjoy your pet.\r\n"); act ("$n bought $N as a pet.", NULL, pet, TO_ROOM); return; } else { Character *keeper; Object *obj; int cost; if ((keeper = find_keeper (this)) == NULL) return; obj = keeper->get_obj_carry (arg); cost = get_cost (keeper, obj, true); if (cost <= 0 || !can_see_obj(obj)) { keeper->act ("$n tells you 'I don't sell that -- try 'list''.", NULL, this, TO_VICT); reply = keeper; return; } if (gold < cost) { keeper->act ("$n tells you 'You can't afford to buy $p'.", obj, this, TO_VICT); reply = keeper; return; } if (obj->level > level) { keeper->act ("$n tells you 'You can't use $p yet'.", obj, this, TO_VICT); reply = keeper; return; } if (carry_number + obj->get_obj_number() > can_carry_n()) { send_to_char ("You can't carry that many items.\r\n"); return; } if (carry_weight + obj->get_obj_weight() > can_carry_w()) { send_to_char ("You can't carry that much weight.\r\n"); return; } act ("$n buys $p.", obj, NULL, TO_ROOM); act ("You buy $p.", obj, NULL, TO_CHAR); gold -= cost; keeper->gold += cost; if (IS_SET (obj->extra_flags, ITEM_INVENTORY)) obj = obj->pIndexData->create_object(obj->level); else obj->obj_from_char (); obj->obj_to_char (this); return; } } void Character::do_list (std::string argument) { char buf[MAX_STRING_LENGTH]; std::string buf1; if (IS_SET (in_room->room_flags, ROOM_PET_SHOP)) { Room *pRoomIndexNext; bool found; pRoomIndexNext = get_room_index (in_room->vnum + 1); if (pRoomIndexNext == NULL) { bug_printf ("Do_list: bad pet shop at vnum %d.", in_room->vnum); send_to_char ("You can't do that here.\r\n"); return; } found = false; CharIter pet; for (pet = pRoomIndexNext->people.begin(); pet != pRoomIndexNext->people.end(); pet++) { if (IS_SET ((*pet)->actflags, ACT_PET)) { if (!found) { found = true; buf1.append("Pets for sale:\r\n"); } snprintf (buf, sizeof buf, "[%2d] %8d - %s\r\n", (*pet)->level, 10 * (*pet)->level * (*pet)->level, (*pet)->short_descr.c_str()); buf1.append(buf); } } if (!found) send_to_char ("Sorry, we're out of pets right now.\r\n"); send_to_char (buf1); return; } else { std::string arg; Character *keeper; Object *obj; int cost = 0; bool found; one_argument (argument, arg); if ((keeper = find_keeper (this)) == NULL) return; found = false; ObjIter o; for (o = keeper->carrying.begin(); o != keeper->carrying.end(); o++) { obj = *o; if (obj->wear_loc == WEAR_NONE && can_see_obj(obj) && (cost = get_cost (keeper, obj, true)) > 0 && (arg.empty() || is_name (arg, obj->name))) { if (!found) { found = true; buf1.append("[Lv Price] Item\r\n"); } snprintf (buf, sizeof buf, "[%2d %5d] %s.\r\n", obj->level, cost, capitalize (obj->short_descr).c_str()); buf1.append(buf); } } if (!found) { if (arg.empty()) send_to_char ("You can't buy anything here.\r\n"); else send_to_char ("You can't buy that here.\r\n"); return; } send_to_char (buf1); return; } } void Character::do_sell (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Sell what?\r\n"); return; } Character *keeper; if ((keeper = find_keeper (this)) == NULL) return; Object *obj; if ((obj = get_obj_carry (arg)) == NULL) { keeper->act ("$n tells you 'You don't have that item'.", NULL, this, TO_VICT); reply = keeper; return; } if (!can_drop_obj (obj)) { send_to_char ("You can't let go of it.\r\n"); return; } int cost; if ((cost = get_cost (keeper, obj, false)) <= 0) { keeper->act ("$n looks uninterested in $p.", obj, this, TO_VICT); return; } char buf[MAX_STRING_LENGTH]; act ("$n sells $p.", obj, NULL, TO_ROOM); snprintf (buf, sizeof buf, "You sell $p for %d gold piece%s.", cost, cost == 1 ? "" : "s"); act (buf, obj, NULL, TO_CHAR); gold += cost; keeper->gold -= cost; if (keeper->gold < 0) keeper->gold = 0; if (obj->item_type == ITEM_TRASH) { obj->extract_obj (); } else { obj->obj_from_char (); obj->obj_to_char (keeper); } return; } void Character::do_value (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Value what?\r\n"); return; } Character *keeper; if ((keeper = find_keeper (this)) == NULL) return; Object *obj; if ((obj = get_obj_carry (arg)) == NULL) { keeper->act ("$n tells you 'You don't have that item'.", NULL, this, TO_VICT); reply = keeper; return; } if (!can_drop_obj (obj)) { send_to_char ("You can't let go of it.\r\n"); return; } int cost; if ((cost = get_cost (keeper, obj, false)) <= 0) { keeper->act ("$n looks uninterested in $p.", obj, this, TO_VICT); return; } char buf[MAX_STRING_LENGTH]; snprintf (buf, sizeof buf, "$n tells you 'I'll give you %d gold coins for $p'.", cost); keeper->act (buf, obj, this, TO_VICT); reply = keeper; return; } void Character::do_wizhelp (std::string argument) { char buf[MAX_STRING_LENGTH]; std::string buf1; int col = 0; for (int cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++) { if (cmd_table[cmd].level >= LEVEL_HERO && cmd_table[cmd].level <= get_trust ()) { snprintf (buf, sizeof buf, "%-12s", cmd_table[cmd].name); buf1.append(buf); if (++col % 6 == 0) buf1.append("\r\n"); } } if (col % 6 != 0) buf1.append("\r\n"); send_to_char (buf1); return; } void Character::do_bamfin (std::string argument) { if (!is_npc ()) { smash_tilde (argument); pcdata->bamfin = argument; send_to_char ("Ok.\r\n"); } return; } void Character::do_bamfout (std::string argument) { if (!is_npc ()) { smash_tilde (argument); pcdata->bamfout = argument; send_to_char ("Ok.\r\n"); } return; } void Character::do_deny (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Deny whom?\r\n"); return; } Character *victim; if ((victim = get_char_world (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (victim->is_npc ()) { send_to_char ("Not on NPC's.\r\n"); return; } if (victim->get_trust () >= get_trust ()) { send_to_char ("You failed.\r\n"); return; } SET_BIT (victim->actflags, PLR_DENY); victim->send_to_char ("You are denied access!\r\n"); send_to_char ("OK.\r\n"); victim->do_quit (""); return; } void Character::do_disconnect (std::string argument) { // :WARNING: There is a bug in this routine! The mud will crash if you // disconnect the descriptor that immediately follows yours in // descriptor_list. close_socket() invalidates the iterator in // 'process input' in game_loop. // FIXED by adding deepdenext iterator std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Disconnect whom?\r\n"); return; } Character *victim; if ((victim = get_char_world (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (victim->desc == NULL) { act ("$N doesn't have a descriptor.", NULL, victim, TO_CHAR); return; } DescIter d = std::find(descriptor_list.begin(),descriptor_list.end(),victim->desc); if (d != descriptor_list.end()) { (*d)->close_socket(); send_to_char ("Ok.\r\n"); return; } bug_printf ("Do_disconnect: desc not found."); send_to_char ("Descriptor not found!\r\n"); return; } void Character::do_pardon (std::string argument) { std::string arg1, arg2; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); if (arg1.empty() || arg2.empty()) { send_to_char ("Syntax: pardon <character> <killer|thief>.\r\n"); return; } Character *victim; if ((victim = get_char_world (arg1)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (victim->is_npc ()) { send_to_char ("Not on NPC's.\r\n"); return; } if (!str_cmp (arg2, "killer")) { if (IS_SET (victim->actflags, PLR_KILLER)) { REMOVE_BIT (victim->actflags, PLR_KILLER); send_to_char ("Killer flag removed.\r\n"); victim->send_to_char ("You are no longer a KILLER.\r\n"); } return; } if (!str_cmp (arg2, "thief")) { if (IS_SET (victim->actflags, PLR_THIEF)) { REMOVE_BIT (victim->actflags, PLR_THIEF); send_to_char ("Thief flag removed.\r\n"); victim->send_to_char ("You are no longer a THIEF.\r\n"); } return; } send_to_char ("Syntax: pardon <character> <killer|thief>.\r\n"); return; } void Character::do_echo (std::string argument) { if (argument.empty()) { send_to_char ("Echo what?\r\n"); return; } for (DescIter d = descriptor_list.begin(); d != descriptor_list.end(); d++) { if ((*d)->connected == CON_PLAYING) { (*d)->character->send_to_char (argument + "\r\n"); } } return; } void Character::do_recho (std::string argument) { if (argument.empty()) { send_to_char ("Recho what?\r\n"); return; } for (DescIter d = descriptor_list.begin(); d != descriptor_list.end(); d++) { if ((*d)->connected == CON_PLAYING && (*d)->character->in_room == in_room) { (*d)->character->send_to_char (argument + "\r\n"); } } return; } void Character::do_transfer (std::string argument) { std::string arg1, arg2; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); if (arg1.empty()) { send_to_char ("Transfer whom (and where)?\r\n"); return; } if (!str_cmp (arg1, "all")) { for (DescIter d = descriptor_list.begin(); d != descriptor_list.end(); d++) { if ((*d)->connected == CON_PLAYING && (*d)->character != this && (*d)->character->in_room != NULL && can_see((*d)->character)) { char buf[MAX_STRING_LENGTH]; snprintf (buf, sizeof buf, "%s %s", (*d)->character->name.c_str(), arg2.c_str()); do_transfer (buf); } } return; } /* * Thanks to Grodyn for the optional location parameter. */ Room *location; if (arg2.empty()) { location = in_room; } else { if ((location = find_location (this, arg2)) == NULL) { send_to_char ("No such location.\r\n"); return; } if (location->is_private()) { send_to_char ("That room is private right now.\r\n"); return; } } Character *victim; if ((victim = get_char_world (arg1)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (victim->in_room == NULL) { send_to_char ("They are in limbo.\r\n"); return; } if (victim->fighting != NULL) victim->stop_fighting(true); victim->act ("$n disappears in a mushroom cloud.", NULL, NULL, TO_ROOM); victim->char_from_room(); victim->char_to_room(location); victim->act ("$n arrives from a puff of smoke.", NULL, NULL, TO_ROOM); if (this != victim) act ("$n has transferred you.", NULL, victim, TO_VICT); victim->do_look ("auto"); send_to_char ("Ok.\r\n"); } void Character::do_at (std::string argument) { std::string arg; argument = one_argument (argument, arg); if (arg.empty() || argument.empty()) { send_to_char ("At where what?\r\n"); return; } Room *location; if ((location = find_location (this, arg)) == NULL) { send_to_char ("No such location.\r\n"); return; } if (location->is_private()) { send_to_char ("That room is private right now.\r\n"); return; } Room* original = in_room; char_from_room(); char_to_room(location); interpret (argument); /* * See if 'this' still exists before continuing! * Handles 'at XXXX quit' case. */ CharIter c; for (c = char_list.begin(); c != char_list.end(); c++) { if (*c == this) { char_from_room(); char_to_room(original); break; } } return; } void Character::do_goto (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Goto where?\r\n"); return; } Room *location; if ((location = find_location (this, arg)) == NULL) { send_to_char ("No such location.\r\n"); return; } if (location->is_private()) { send_to_char ("That room is private right now.\r\n"); return; } if (fighting != NULL) stop_fighting (true); act ("$n $T.", NULL, (pcdata != NULL && !pcdata->bamfout.empty()) ? pcdata->bamfout.c_str() : "leaves in a swirling mist", TO_ROOM); char_from_room(); char_to_room(location); act ("$n $T.", NULL, (pcdata != NULL && !pcdata->bamfin.empty()) ? pcdata->bamfin.c_str() : "appears in a swirling mist", TO_ROOM); do_look ("auto"); return; } void Character::do_rstat (std::string argument) { std::string arg, buf1; one_argument (argument, arg); Room* location = arg.empty() ? in_room : find_location (this, arg); if (location == NULL) { send_to_char ("No such location.\r\n"); return; } if (in_room != location && location->is_private()) { send_to_char ("That room is private right now.\r\n"); return; } char buf[MAX_STRING_LENGTH]; snprintf (buf, sizeof buf, "Name: '%s.'\r\nArea: '%s'.\r\n", location->name.c_str(), location->area->name.c_str()); buf1.append(buf); snprintf (buf, sizeof buf, "Vnum: %d. Sector: %d. Light: %d.\r\n", location->vnum, location->sector_type, location->light); buf1.append(buf); snprintf (buf, sizeof buf, "Room flags: %d.\r\nDescription:\r\n%s", location->room_flags, location->description.c_str()); buf1.append(buf); if (!location->extra_descr.empty()) { buf1.append("Extra description keywords: '"); std::list<ExtraDescription *>::iterator ed; for (ed = location->extra_descr.begin(); ed != location->extra_descr.end(); ed++) { buf1.append((*ed)->keyword); buf1.append(" "); } if (buf1[buf1.size() - 1] == ' ') buf1.erase(buf1.size() - 1); buf1.append("'.\r\n"); } buf1.append("Characters:"); std::string tmp; CharIter rch; for (rch = location->people.begin(); rch != location->people.end(); rch++) { buf1.append(" "); one_argument ((*rch)->name, tmp); buf1.append(tmp); } buf1.append(".\r\nObjects: "); ObjIter o; for (o = location->contents.begin(); o != location->contents.end(); o++) { buf1.append(" "); one_argument ((*o)->name, tmp); buf1.append(tmp); } buf1.append(".\r\n"); for (int door = 0; door <= 5; door++) { Exit *pexit; if ((pexit = location->exit[door]) != NULL) { snprintf (buf, sizeof buf, "Door: %d. To: %d. Key: %d. Exit flags: %d.\r\nKeyword: '%s'. Description: %s", door, pexit->to_room != NULL ? pexit->to_room->vnum : 0, pexit->key, pexit->exit_info, pexit->name.c_str(), !pexit->description.empty() ? pexit->description.c_str() : "(none).\r\n"); buf1.append(buf); } } send_to_char (buf1); return; } void Character::do_ostat (std::string argument) { std::string arg, buf1; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Ostat what?\r\n"); return; } Object *obj; if ((obj = get_obj_world (arg)) == NULL) { send_to_char ("Nothing like that in hell, earth, or heaven.\r\n"); return; } char buf[MAX_STRING_LENGTH]; snprintf (buf, sizeof buf, "Name: %s.\r\n", obj->name.c_str()); buf1.append(buf); snprintf (buf, sizeof buf, "Vnum: %d. Type: %s.\r\n", obj->pIndexData->vnum, obj->item_type_name().c_str()); buf1.append(buf); snprintf (buf, sizeof buf, "Short description: %s.\r\nLong description: %s\r\n", obj->short_descr.c_str(), obj->description.c_str()); buf1.append(buf); snprintf (buf, sizeof buf, "Wear bits: %d. Extra bits: %s.\r\n", obj->wear_flags, extra_bit_name (obj->extra_flags).c_str()); buf1.append(buf); snprintf (buf, sizeof buf, "Number: %d/%d. Weight: %d/%d.\r\n", 1, obj->get_obj_number(), obj->weight, obj->get_obj_weight()); buf1.append(buf); snprintf (buf, sizeof buf, "Cost: %d. Timer: %d. Level: %d.\r\n", obj->cost, obj->timer, obj->level); buf1.append(buf); snprintf (buf, sizeof buf, "In room: %d. In object: %s. Carried by: %s. Wear_loc: %d.\r\n", obj->in_room == NULL ? 0 : obj->in_room->vnum, obj->in_obj == NULL ? "(none)" : obj->in_obj->short_descr.c_str(), obj->carried_by == NULL ? "(none)" : obj->carried_by->name.c_str(), obj->wear_loc); buf1.append(buf); snprintf (buf, sizeof buf, "Values: %d %d %d %d.\r\n", obj->value[0], obj->value[1], obj->value[2], obj->value[3]); buf1.append(buf); if (!obj->extra_descr.empty() || !obj->pIndexData->extra_descr.empty()) { buf1.append("Extra description keywords: '"); std::list<ExtraDescription *>::iterator ed; for (ed = obj->extra_descr.begin(); ed != obj->extra_descr.end(); ed++) { buf1.append((*ed)->keyword); buf1.append(" "); } for (ed = obj->pIndexData->extra_descr.begin(); ed != obj->pIndexData->extra_descr.end(); ed++) { buf1.append((*ed)->keyword); buf1.append(" "); } if (buf1[buf1.size() - 1] == ' ') buf1.erase(buf1.size() - 1); buf1.append("'.\r\n"); } AffIter af; for (af = obj->affected.begin(); af != obj->affected.end(); af++) { snprintf (buf, sizeof buf, "Affects %s by %d.\r\n", affect_loc_name ((*af)->location).c_str(), (*af)->modifier); buf1.append(buf); } for (af = obj->pIndexData->affected.begin(); af != obj->pIndexData->affected.end(); af++) { snprintf (buf, sizeof buf, "Affects %s by %d.\r\n", affect_loc_name ((*af)->location).c_str(), (*af)->modifier); buf1.append(buf); } send_to_char (buf1); return; } void Character::do_mstat (std::string argument) { std::string arg, buf1; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Mstat whom?\r\n"); return; } Character *victim; if ((victim = get_char_world (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } char buf[MAX_STRING_LENGTH]; snprintf (buf, sizeof buf, "Name: %s.\r\n", victim->name.c_str()); buf1.append(buf); snprintf (buf, sizeof buf, "Vnum: %d. Sex: %s. Room: %d.\r\n", victim->is_npc () ? victim->pIndexData->vnum : 0, victim->sex == SEX_MALE ? "male" : victim->sex == SEX_FEMALE ? "female" : "neutral", victim->in_room == NULL ? 0 : victim->in_room->vnum); buf1.append(buf); snprintf (buf, sizeof buf, "Str: %d. Int: %d. Wis: %d. Dex: %d. Con: %d.\r\n", victim->get_curr_str(), victim->get_curr_int(), victim->get_curr_wis(), victim->get_curr_dex(), victim->get_curr_con()); buf1.append(buf); snprintf (buf, sizeof buf, "Hp: %d/%d. Mana: %d/%d. Move: %d/%d. Practices: %d.\r\n", victim->hit, victim->max_hit, victim->mana, victim->max_mana, victim->move, victim->max_move, victim->practice); buf1.append(buf); snprintf (buf, sizeof buf, "Lv: %d. Class: %d. Align: %d. AC: %d. Gold: %d. Exp: %d.\r\n", victim->level, victim->klass, victim->alignment, victim->get_ac(), victim->gold, victim->exp); buf1.append(buf); snprintf (buf, sizeof buf, "Hitroll: %d. Damroll: %d. Position: %d. Wimpy: %d.\r\n", victim->get_hitroll(), victim->get_damroll(), victim->position, victim->wimpy); buf1.append(buf); if (!victim->is_npc ()) { snprintf (buf, sizeof buf, "Page Lines: %d.\r\n", victim->pcdata->pagelen); buf1.append(buf); } snprintf (buf, sizeof buf, "Fighting: %s.\r\n", victim->fighting ? victim->fighting->name.c_str() : "(none)"); buf1.append(buf); if (!victim->is_npc ()) { snprintf (buf, sizeof buf, "Thirst: %d. Full: %d. Drunk: %d. Saving throw: %d.\r\n", victim->pcdata->condition[COND_THIRST], victim->pcdata->condition[COND_FULL], victim->pcdata->condition[COND_DRUNK], victim->saving_throw); buf1.append(buf); } snprintf (buf, sizeof buf, "Carry number: %d. Carry weight: %d.\r\n", victim->carry_number, victim->carry_weight); buf1.append(buf); snprintf (buf, sizeof buf, "Age: %d. Played: %d. Timer: %d. Act: %d.\r\n", victim->get_age(), (int) victim->played, victim->timer, victim->actflags); buf1.append(buf); snprintf (buf, sizeof buf, "Master: %s. Leader: %s. Affected by: %s.\r\n", victim->master ? victim->master->name.c_str() : "(none)", victim->leader ? victim->leader->name.c_str() : "(none)", affect_bit_name (victim->affected_by).c_str()); buf1.append(buf); snprintf (buf, sizeof buf, "Short description: %s.\r\nLong description: %s", victim->short_descr.c_str(), !victim->long_descr.empty() ? victim->long_descr.c_str() : "(none).\r\n"); buf1.append(buf); if (victim->is_npc () && victim->spec_fun != 0) buf1.append("Mobile has spec fun.\r\n"); AffIter af; for (af = victim->affected.begin(); af != victim->affected.end(); af++) { snprintf (buf, sizeof buf, "Spell: '%s' modifies %s by %d for %d hours with bits %s.\r\n", skill_table[(int) (*af)->type].name, affect_loc_name ((*af)->location).c_str(), (*af)->modifier, (*af)->duration, affect_bit_name ((*af)->bitvector).c_str() ); buf1.append(buf); } send_to_char (buf1); return; } void Character::do_mfind (std::string argument) { std::string arg, buf1; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Mfind whom?\r\n"); return; } bool fAll = !str_cmp (arg, "all"); bool found = false; int nMatch = 0; MobPrototype *pMobIndex; char buf[MAX_STRING_LENGTH]; /* * Yeah, so iterating over all vnum's takes 10,000 loops. * Get_mob_index is fast, and I don't feel like threading another link. * Do you? * -- Furey */ for (int vn = 0; nMatch < MobPrototype::top_mob; vn++) { if ((pMobIndex = get_mob_index (vn)) != NULL) { nMatch++; if (fAll || is_name (arg, pMobIndex->name)) { found = true; snprintf (buf, sizeof buf, "[%5d] %s\r\n", pMobIndex->vnum, capitalize (pMobIndex->short_descr).c_str()); buf1.append(buf); } } } if (!found) { send_to_char ("Nothing like that in hell, earth, or heaven.\r\n"); return; } send_to_char (buf1); return; } void Character::do_ofind (std::string argument) { std::string arg, buf1; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Ofind what?\r\n"); return; } bool fAll = !str_cmp (arg, "all"); bool found = false; int nMatch = 0; char buf[MAX_STRING_LENGTH]; ObjectPrototype *pObjIndex; /* * Yeah, so iterating over all vnum's takes 10,000 loops. * Get_obj_index is fast, and I don't feel like threading another link. * Do you? * -- Furey */ for (int vn = 0; nMatch < ObjectPrototype::top_obj; vn++) { if ((pObjIndex = get_obj_index (vn)) != NULL) { nMatch++; if (fAll || is_name (arg, pObjIndex->name)) { found = true; snprintf (buf, sizeof buf, "[%5d] %s\r\n", pObjIndex->vnum, capitalize (pObjIndex->short_descr).c_str()); buf1.append(buf); } } } if (!found) { send_to_char ("Nothing like that in hell, earth, or heaven.\r\n"); return; } send_to_char (buf1); return; } void Character::do_mwhere (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Mwhere whom?\r\n"); return; } char buf[MAX_STRING_LENGTH]; bool found = false; for (CharIter c = char_list.begin(); c != char_list.end(); c++) { if ((*c)->is_npc () && (*c)->in_room != NULL && is_name (arg, (*c)->name)) { found = true; snprintf (buf, sizeof buf, "[%5d] %-28s [%5d] %s\r\n", (*c)->pIndexData->vnum, (*c)->short_descr.c_str(), (*c)->in_room->vnum, (*c)->in_room->name.c_str()); send_to_char (buf); } } if (!found) { act ("You didn't find any $T.", NULL, arg.c_str(), TO_CHAR); return; } return; } void Character::do_hotboo (std::string argument) { send_to_char ("If you want to HOTBOOT, spell it out.\r\n"); return; } void Character::do_hotboot (std::string argument) { #if !defined(WIN32) || defined(__DMC__) send_to_char ("Hotboot not supported.\r\n"); #else extern bool write_to_descriptor (SOCKET desc, const char *txt, int length); std::string usr_msg("Hotboot by "); usr_msg.append(name); usr_msg.append(". Stand by...\r\n"); int count_users = 0; for (DescIter d = descriptor_list.begin(); d != descriptor_list.end(); d++) { if (!(*d)->character || (*d)->connected > CON_PLAYING) { write_to_descriptor ((*d)->descriptor, "The server is hotbooting. Please recreate in a few minutes.\r\n", 0); (*d)->close_socket(); } else { count_users++; } } char cmd[MAX_INPUT_LENGTH]; snprintf(cmd, sizeof cmd, "murk %d hotboot", g_port); STARTUPINFO start_info; PROCESS_INFORMATION proc_info; WSAPROTOCOL_INFO proto_info; // Get current console parameters GetStartupInfo(&start_info); // This event will be set when we are ready for copyover void * file_event = CreateEvent(NULL, TRUE, FALSE, "file_created"); if (file_event == NULL) { win_errprint("Error creating event, file_created"); return; } // We will wait on this event before shutting down void * shutdown_event = CreateEvent(NULL, TRUE, FALSE, "ok_to_shutdown"); if (shutdown_event == NULL) { win_errprint("Error creating event, ok_to_shutdown"); CloseHandle(file_event); return; } // Start running a new server if (CreateProcess(NULL, cmd, NULL, NULL, TRUE, NULL, NULL, NULL, &start_info, &proc_info) == NULL) { win_errprint("Error creating new process"); CloseHandle(file_event); CloseHandle(shutdown_event); return; } std::FILE* fp; if ((fp = std::fopen ("hotboot.$$$", "w+b")) == NULL) { send_to_char ("Hotboot aborted.\r\n"); win_errprint("Error creating hotboot file"); return; } fwrite(&count_users, sizeof(int),1,fp); // write number of users // duplicate and save the listening sockets info if (WSADuplicateSocket(g_listen, proc_info.dwProcessId, &proto_info) == SOCKET_ERROR) { bug_printf ("Error duplicating listening socket : %d.", WSAGetLastError()); } fwrite(&proto_info,sizeof(WSAPROTOCOL_INFO),1,fp); closesocket(g_listen); for (DescIter d = descriptor_list.begin(); d != descriptor_list.end(); d++) { if (WSADuplicateSocket((*d)->descriptor, proc_info.dwProcessId, &proto_info) == SOCKET_ERROR) { bug_printf ("Error duplicating user socket : %d.", WSAGetLastError()); } Character * ch = (*d)->original ? (*d)->original : (*d)->character; if (ch->level == 1) { ch->level += 1; ch->advance_level(); } ch->save_char_obj(); write_to_descriptor ((*d)->descriptor, usr_msg.c_str(), 0); char chname[25]; strcpy(chname,ch->name.c_str()); fwrite(&proto_info,sizeof(WSAPROTOCOL_INFO),1,fp); fwrite(chname,sizeof(chname),1,fp); closesocket((*d)->descriptor); } fclose (fp); // Indicate we are done with the copyover file if (SetEvent(file_event) == NULL) { win_errprint("Error setting file_event"); } // Wait for child server to tell us its ok to shutdown if (WaitForSingleObject(shutdown_event, INFINITE) == WAIT_FAILED) { win_errprint("Error waiting on shutdown_event"); } // cleanup event handles CloseHandle(file_event); CloseHandle(shutdown_event); WIN32CLEANUP g_db->shutdown(); std::exit(0); #endif return; } void Character::do_shutdow (std::string argument) { send_to_char ("If you want to SHUTDOWN, spell it out.\r\n"); return; } void Character::do_shutdown (std::string argument) { std::string buf("Shutdown by "); buf.append(name); buf.append("."); append_file (SHUTDOWN_FILE, buf); buf.append("\r\n"); do_echo (buf); merc_down = true; return; } void Character::do_switch (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Switch into whom?\r\n"); return; } if (desc == NULL) return; if (desc->original != NULL) { send_to_char ("You are already switched.\r\n"); return; } Character *victim; if ((victim = get_char_world (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (victim == this) { send_to_char ("Ok.\r\n"); return; } /* * Pointed out by Da Pub (What Mud) */ if (!victim->is_npc ()) { send_to_char ("You cannot switch into a player!\r\n"); return; } if (victim->desc != NULL) { send_to_char ("Character in use.\r\n"); return; } desc->character = victim; desc->original = this; victim->desc = desc; desc = NULL; victim->send_to_char ("Ok.\r\n"); return; } void Character::do_return (std::string argument) { if (desc == NULL) return; if (desc->original == NULL) { send_to_char ("You aren't switched.\r\n"); return; } send_to_char ("You return to your original body.\r\n"); desc->character = desc->original; desc->original = NULL; desc->character->desc = desc; desc = NULL; return; } void Character::do_mload (std::string argument) { std::string arg; MobPrototype *pMobIndex; Character *victim; one_argument (argument, arg); if (arg.empty() || !is_number (arg)) { send_to_char ("Syntax: mload <vnum>.\r\n"); return; } if ((pMobIndex = get_mob_index (std::atoi (arg.c_str()))) == NULL) { send_to_char ("No mob has that vnum.\r\n"); return; } victim = pMobIndex->create_mobile (); victim->char_to_room(in_room); act ("$n has created $N!", NULL, victim, TO_ROOM); send_to_char ("Ok.\r\n"); return; } void Character::do_oload (std::string argument) { std::string arg1, arg2; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); if (arg1.empty() || !is_number (arg1)) { send_to_char ("Syntax: oload <vnum> <level>.\r\n"); return; } int lvl; if (arg2.empty()) { lvl = get_trust (); } else { /* * New feature from Alander. */ if (!is_number (arg2)) { send_to_char ("Syntax: oload <vnum> <level>.\r\n"); return; } lvl = std::atoi (arg2.c_str()); if (lvl < 0 || lvl > get_trust ()) { send_to_char ("Limited to your trust level.\r\n"); return; } } ObjectPrototype *pObjIndex; if ((pObjIndex = get_obj_index (std::atoi (arg1.c_str()))) == NULL) { send_to_char ("No object has that vnum.\r\n"); return; } Object *obj = pObjIndex->create_object(lvl); if (obj->can_wear(ITEM_TAKE)) { obj->obj_to_char (this); } else { obj->obj_to_room (in_room); act ("$n has created $p!", obj, NULL, TO_ROOM); } send_to_char ("Ok.\r\n"); return; } void Character::do_purge (std::string argument) { std::string arg; Character *victim; Object *obj; one_argument (argument, arg); if (arg.empty()) { /* 'purge' */ CharIter rch, rnext; for (rch = in_room->people.begin(); rch != in_room->people.end(); rch = rnext) { victim = *rch; rnext = ++rch; if (victim->is_npc () && victim != this) victim->extract_char (true); } ObjIter o, onext; for (o = in_room->contents.begin(); o != in_room->contents.end(); o = onext) { obj = *o; onext = ++o; obj->extract_obj (); } act ("$n purges the room!", NULL, NULL, TO_ROOM); send_to_char ("Ok.\r\n"); return; } if ((victim = get_char_world (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (!victim->is_npc ()) { send_to_char ("Not on PC's.\r\n"); return; } act ("$n purges $N.", NULL, victim, TO_NOTVICT); victim->extract_char (true); return; } void Character::do_advance (std::string argument) { std::string arg1, arg2; Character *victim; int lvl; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); if (arg1.empty() || arg2.empty() || !is_number (arg2)) { send_to_char ("Syntax: advance <char> <level>.\r\n"); return; } if ((victim = get_char_room (arg1)) == NULL) { send_to_char ("That player is not here.\r\n"); return; } if (victim->is_npc ()) { send_to_char ("Not on NPC's.\r\n"); return; } if ((lvl = std::atoi (arg2.c_str())) < 1 || lvl > 40) { send_to_char ("Level must be 1 to 40.\r\n"); return; } if (lvl > get_trust ()) { send_to_char ("Limited to your trust level.\r\n"); return; } /* * Lower level: * Reset to level 1. * Then raise again. * Currently, an imp can lower another imp. * -- Swiftest */ if (lvl <= victim->level) { int sn; send_to_char ("Lowering a player's level!\r\n"); victim->send_to_char ("**** OOOOHHHHHHHHHH NNNNOOOO ****\r\n"); victim->level = 1; victim->exp = 1000; victim->max_hit = 10; victim->max_mana = 100; victim->max_move = 100; for (sn = 0; sn < MAX_SKILL; sn++) victim->pcdata->learned[sn] = 0; victim->practice = 0; victim->hit = victim->max_hit; victim->mana = victim->max_mana; victim->move = victim->max_move; victim->advance_level(); } else { send_to_char ("Raising a player's level!\r\n"); victim->send_to_char ("**** OOOOHHHHHHHHHH YYYYEEEESSS ****\r\n"); } for (int iLevel = victim->level; iLevel < lvl; iLevel++) { victim->send_to_char ("You raise a level!! "); victim->level += 1; victim->advance_level(); } victim->exp = 1000 * std::max (1, victim->level); victim->trust = 0; return; } void Character::do_trust (std::string argument) { std::string arg1, arg2; Character *victim; int lvl; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); if (arg1.empty() || arg2.empty() || !is_number (arg2)) { send_to_char ("Syntax: trust <char> <level>.\r\n"); return; } if ((victim = get_char_room (arg1)) == NULL) { send_to_char ("That player is not here.\r\n"); return; } if ((lvl = std::atoi (arg2.c_str())) < 0 || lvl > 40) { send_to_char ("Level must be 0 (reset) or 1 to 40.\r\n"); return; } if (lvl > get_trust ()) { send_to_char ("Limited to your trust.\r\n"); return; } victim->trust = lvl; return; } void Character::do_restore (std::string argument) { std::string arg; Character *victim; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Restore whom?\r\n"); return; } if ((victim = get_char_world (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } victim->hit = victim->max_hit; victim->mana = victim->max_mana; victim->move = victim->max_move; victim->update_pos(); act ("$n has restored you.", NULL, victim, TO_VICT); send_to_char ("Ok.\r\n"); return; } void Character::do_freeze (std::string argument) { std::string arg; Character *victim; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Freeze whom?\r\n"); return; } if ((victim = get_char_world (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (victim->is_npc ()) { send_to_char ("Not on NPC's.\r\n"); return; } if (victim->get_trust () >= get_trust ()) { send_to_char ("You failed.\r\n"); return; } if (IS_SET (victim->actflags, PLR_FREEZE)) { REMOVE_BIT (victim->actflags, PLR_FREEZE); victim->send_to_char ("You can play again.\r\n"); send_to_char ("FREEZE removed.\r\n"); } else { SET_BIT (victim->actflags, PLR_FREEZE); victim->send_to_char ("You can't do ANYthing!\r\n"); send_to_char ("FREEZE set.\r\n"); } victim->save_char_obj(); return; } void Character::do_noemote (std::string argument) { std::string arg; Character *victim; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Noemote whom?\r\n"); return; } if ((victim = get_char_world (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (victim->is_npc ()) { send_to_char ("Not on NPC's.\r\n"); return; } if (victim->get_trust () >= get_trust ()) { send_to_char ("You failed.\r\n"); return; } if (IS_SET (victim->actflags, PLR_NO_EMOTE)) { REMOVE_BIT (victim->actflags, PLR_NO_EMOTE); victim->send_to_char ("You can emote again.\r\n"); send_to_char ("NO_EMOTE removed.\r\n"); } else { SET_BIT (victim->actflags, PLR_NO_EMOTE); victim->send_to_char ("You can't emote!\r\n"); send_to_char ("NO_EMOTE set.\r\n"); } return; } void Character::do_notell (std::string argument) { std::string arg; Character *victim; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Notell whom?"); return; } if ((victim = get_char_world (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (victim->is_npc ()) { send_to_char ("Not on NPC's.\r\n"); return; } if (victim->get_trust () >= get_trust ()) { send_to_char ("You failed.\r\n"); return; } if (IS_SET (victim->actflags, PLR_NO_TELL)) { REMOVE_BIT (victim->actflags, PLR_NO_TELL); victim->send_to_char ("You can tell again.\r\n"); send_to_char ("NO_TELL removed.\r\n"); } else { SET_BIT (victim->actflags, PLR_NO_TELL); victim->send_to_char ("You can't tell!\r\n"); send_to_char ("NO_TELL set.\r\n"); } return; } void Character::do_silence (std::string argument) { std::string arg; Character *victim; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Silence whom?"); return; } if ((victim = get_char_world (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (victim->is_npc ()) { send_to_char ("Not on NPC's.\r\n"); return; } if (victim->get_trust () >= get_trust ()) { send_to_char ("You failed.\r\n"); return; } if (IS_SET (victim->actflags, PLR_SILENCE)) { REMOVE_BIT (victim->actflags, PLR_SILENCE); victim->send_to_char ("You can use channels again.\r\n"); send_to_char ("SILENCE removed.\r\n"); } else { SET_BIT (victim->actflags, PLR_SILENCE); victim->send_to_char ("You can't use channels!\r\n"); send_to_char ("SILENCE set.\r\n"); } return; } void Character::do_peace (std::string argument) { CharIter rch; for (rch = in_room->people.begin(); rch != in_room->people.end(); rch++) { if ((*rch)->fighting != NULL) (*rch)->stop_fighting (true); } send_to_char ("Ok.\r\n"); return; } void Character::do_ban (std::string argument) { std::string buf; std::string arg; if (is_npc ()) return; one_argument (argument, arg); if (arg.empty()) { buf = "Banned sites:\r\n"; for (std::list<Ban*>::iterator p = ban_list.begin(); p != ban_list.end(); p++) { buf.append((*p)->name); buf.append("\r\n"); } send_to_char (buf); return; } for (std::list<Ban*>::iterator p = ban_list.begin(); p != ban_list.end(); p++) { if (!str_cmp (arg, (*p)->name)) { send_to_char ("That site is already banned!\r\n"); return; } } Ban *pban = new Ban(arg); ban_list.push_back(pban); send_to_char ("Ok.\r\n"); return; } void Character::do_allow (std::string argument) { std::string arg; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Remove which site from the ban list?\r\n"); return; } std::list<Ban*>::iterator next, curr; for (std::list<Ban*>::iterator pban = ban_list.begin(); pban != ban_list.end(); pban = next) { curr = pban; next = ++pban; if (!str_cmp (arg, (*curr)->name)) { delete *curr; ban_list.erase(curr); send_to_char ("Ok.\r\n"); return; } } send_to_char ("Site is not banned.\r\n"); return; } void Character::do_wizlock (std::string argument) { wizlock = !wizlock; if (wizlock) send_to_char ("Game wizlocked.\r\n"); else send_to_char ("Game un-wizlocked.\r\n"); return; } void Character::do_slookup (std::string argument) { char buf[MAX_STRING_LENGTH]; std::string arg; int sn; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Slookup what?\r\n"); return; } if (!str_cmp (arg, "all")) { std::string buf1; for (sn = 0; sn < MAX_SKILL; sn++) { if (skill_table[sn].name == NULL) break; snprintf (buf, sizeof buf, "Sn: %4d Skill/spell: '%s'\r\n", sn, skill_table[sn].name); buf1.append(buf); } send_to_char (buf1); } else { if ((sn = skill_lookup (arg)) < 0) { send_to_char ("No such skill or spell.\r\n"); return; } snprintf (buf, sizeof buf, "Sn: %4d Skill/spell: '%s'\r\n", sn, skill_table[sn].name); send_to_char (buf); } return; } void Character::do_sset (std::string argument) { std::string arg1, arg2, arg3; Character *victim; int value; int sn; bool fAll; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); argument = one_argument (argument, arg3); if (arg1.empty() || arg2.empty() || arg3.empty()) { send_to_char ("Syntax: sset <victim> <skill> <value>\r\n"); send_to_char ("or: sset <victim> all <value>\r\n"); send_to_char ("Skill being any skill or spell.\r\n"); return; } if ((victim = get_char_world (arg1)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (victim->is_npc ()) { send_to_char ("Not on NPC's.\r\n"); return; } fAll = !str_cmp (arg2, "all"); sn = 0; if (!fAll && (sn = skill_lookup (arg2)) < 0) { send_to_char ("No such skill or spell.\r\n"); return; } /* * Snarf the value. */ if (!is_number (arg3)) { send_to_char ("Value must be numeric.\r\n"); return; } value = std::atoi (arg3.c_str()); if (value < 0 || value > 100) { send_to_char ("Value range is 0 to 100.\r\n"); return; } if (fAll) { for (sn = 0; sn < MAX_SKILL; sn++) { if (skill_table[sn].name != NULL) victim->pcdata->learned[sn] = value; } } else { victim->pcdata->learned[sn] = value; } return; } void Character::do_mset (std::string argument) { std::string arg1, arg2, arg3; char buf[MAX_STRING_LENGTH]; Character *victim; int value, max; smash_tilde (argument); argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); arg3 = argument; if (arg1.empty() || arg2.empty() || arg3.empty()) { send_to_char ("Syntax: mset <victim> <field> <value>\r\n"); send_to_char ("or: mset <victim> <string> <value>\r\n"); send_to_char ("\r\n"); send_to_char ("Field being one of:\r\n"); send_to_char (" str int wis dex con sex class level\r\n"); send_to_char (" gold hp mana move practice align\r\n"); send_to_char (" thirst drunk full"); send_to_char ("\r\n"); send_to_char ("String being one of:\r\n"); send_to_char (" name short long description title spec\r\n"); return; } if ((victim = get_char_world (arg1)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } /* * Snarf the value (which need not be numeric). */ value = is_number (arg3) ? std::atoi (arg3.c_str()) : -1; /* * Set something. */ if (!str_cmp (arg2, "str")) { if (victim->is_npc ()) { send_to_char ("Not on NPC's.\r\n"); return; } if (class_table[klass].attr_prime == APPLY_STR) max = 25; else max = 18; if (value < 3 || value > max) { snprintf (buf, sizeof buf, "Strength range is 3 to %d.\r\n", max); send_to_char (buf); return; } victim->pcdata->set_perm("str", value); return; } if (!str_cmp (arg2, "int")) { if (victim->is_npc ()) { send_to_char ("Not on NPC's.\r\n"); return; } if (class_table[klass].attr_prime == APPLY_INT) max = 25; else max = 18; if (value < 3 || value > max) { snprintf (buf, sizeof buf, "Intelligence range is 3 to %d.\r\n", max); send_to_char (buf); return; } victim->pcdata->set_perm("int", value); return; } if (!str_cmp (arg2, "wis")) { if (victim->is_npc ()) { send_to_char ("Not on NPC's.\r\n"); return; } if (class_table[klass].attr_prime == APPLY_WIS) max = 25; else max = 18; if (value < 3 || value > max) { snprintf (buf, sizeof buf, "Wisdom range is 3 to %d.\r\n", max); send_to_char (buf); return; } victim->pcdata->set_perm("wis", value); return; } if (!str_cmp (arg2, "dex")) { if (victim->is_npc ()) { send_to_char ("Not on NPC's.\r\n"); return; } if (class_table[klass].attr_prime == APPLY_DEX) max = 25; else max = 18; if (value < 3 || value > max) { snprintf (buf, sizeof buf, "Dexterity range is 3 to %d.\r\n", max); send_to_char (buf); return; } victim->pcdata->set_perm("dex", value); return; } if (!str_cmp (arg2, "con")) { if (victim->is_npc ()) { send_to_char ("Not on NPC's.\r\n"); return; } if (class_table[klass].attr_prime == APPLY_CON) max = 25; else max = 18; if (value < 3 || value > max) { snprintf (buf, sizeof buf, "Constitution range is 3 to %d.\r\n", max); send_to_char (buf); return; } victim->pcdata->set_perm("con", value); return; } if (!str_cmp (arg2, "sex")) { if (value < 0 || value > 2) { send_to_char ("Sex range is 0 to 2.\r\n"); return; } victim->sex = value; return; } if (!str_cmp (arg2, "class")) { if (value < 0 || value >= CLASS_MAX) { char buf[MAX_STRING_LENGTH]; snprintf (buf, sizeof buf, "Class range is 0 to %d.\n", CLASS_MAX - 1); send_to_char (buf); return; } victim->klass = value; return; } if (!str_cmp (arg2, "level")) { if (!victim->is_npc ()) { send_to_char ("Not on PC's.\r\n"); return; } if (value < 0 || value > 50) { send_to_char ("Level range is 0 to 50.\r\n"); return; } victim->level = value; return; } if (!str_cmp (arg2, "gold")) { victim->gold = value; return; } if (!str_cmp (arg2, "hp")) { if (value < -10 || value > 30000) { send_to_char ("Hp range is -10 to 30,000 hit points.\r\n"); return; } victim->max_hit = value; return; } if (!str_cmp (arg2, "mana")) { if (value < 0 || value > 30000) { send_to_char ("Mana range is 0 to 30,000 mana points.\r\n"); return; } victim->max_mana = value; return; } if (!str_cmp (arg2, "move")) { if (value < 0 || value > 30000) { send_to_char ("Move range is 0 to 30,000 move points.\r\n"); return; } victim->max_move = value; return; } if (!str_cmp (arg2, "practice")) { if (value < 0 || value > 100) { send_to_char ("Practice range is 0 to 100 sessions.\r\n"); return; } victim->practice = value; return; } if (!str_cmp (arg2, "align")) { if (value < -1000 || value > 1000) { send_to_char ("Alignment range is -1000 to 1000.\r\n"); return; } victim->alignment = value; return; } if (!str_cmp (arg2, "thirst")) { if (victim->is_npc ()) { send_to_char ("Not on NPC's.\r\n"); return; } if (value < 0 || value > 100) { send_to_char ("Thirst range is 0 to 100.\r\n"); return; } victim->pcdata->condition[COND_THIRST] = value; return; } if (!str_cmp (arg2, "drunk")) { if (victim->is_npc ()) { send_to_char ("Not on NPC's.\r\n"); return; } if (value < 0 || value > 100) { send_to_char ("Drunk range is 0 to 100.\r\n"); return; } victim->pcdata->condition[COND_DRUNK] = value; return; } if (!str_cmp (arg2, "full")) { if (victim->is_npc ()) { send_to_char ("Not on NPC's.\r\n"); return; } if (value < 0 || value > 100) { send_to_char ("Full range is 0 to 100.\r\n"); return; } victim->pcdata->condition[COND_FULL] = value; return; } if (!str_cmp (arg2, "name")) { if (!victim->is_npc ()) { send_to_char ("Not on PC's.\r\n"); return; } victim->name = arg3; return; } if (!str_cmp (arg2, "short")) { victim->short_descr = arg3; return; } if (!str_cmp (arg2, "long")) { victim->long_descr = arg3; return; } if (!str_cmp (arg2, "title")) { if (victim->is_npc ()) { send_to_char ("Not on NPC's.\r\n"); return; } victim->set_title(arg3); return; } if (!str_cmp (arg2, "spec")) { if (!victim->is_npc ()) { send_to_char ("Not on PC's.\r\n"); return; } if ((victim->spec_fun = spec_lookup (arg3)) == 0) { send_to_char ("No such spec fun.\r\n"); return; } return; } /* * Generate usage message. */ do_mset (""); return; } void Character::do_oset (std::string argument) { std::string arg1, arg2, arg3; Object *obj; int value; smash_tilde (argument); argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); arg3 = argument; if (arg1.empty() || arg2.empty() || arg3.empty()) { send_to_char ("Syntax: oset <object> <field> <value>\r\n"); send_to_char ("or: oset <object> <string> <value>\r\n"); send_to_char ("\r\n"); send_to_char ("Field being one of:\r\n"); send_to_char (" value0 value1 value2 value3\r\n"); send_to_char (" extra wear level weight cost timer\r\n"); send_to_char ("\r\n"); send_to_char ("String being one of:\r\n"); send_to_char (" name short long ed\r\n"); return; } if ((obj = get_obj_world (arg1)) == NULL) { send_to_char ("Nothing like that in hell, earth, or heaven.\r\n"); return; } /* * Snarf the value (which need not be numeric). */ value = std::atoi (arg3.c_str()); /* * Set something. */ if (!str_cmp (arg2, "value0") || !str_cmp (arg2, "v0")) { obj->value[0] = value; return; } if (!str_cmp (arg2, "value1") || !str_cmp (arg2, "v1")) { obj->value[1] = value; return; } if (!str_cmp (arg2, "value2") || !str_cmp (arg2, "v2")) { obj->value[2] = value; return; } if (!str_cmp (arg2, "value3") || !str_cmp (arg2, "v3")) { obj->value[3] = value; return; } if (!str_cmp (arg2, "extra")) { obj->extra_flags = value; return; } if (!str_cmp (arg2, "wear")) { obj->wear_flags = value; return; } if (!str_cmp (arg2, "level")) { obj->level = value; return; } if (!str_cmp (arg2, "weight")) { obj->weight = value; return; } if (!str_cmp (arg2, "cost")) { obj->cost = value; return; } if (!str_cmp (arg2, "timer")) { obj->timer = value; return; } if (!str_cmp (arg2, "name")) { obj->name = arg3; return; } if (!str_cmp (arg2, "short")) { obj->short_descr = arg3; return; } if (!str_cmp (arg2, "long")) { obj->description = arg3; return; } if (!str_cmp (arg2, "ed")) { ExtraDescription *ed; argument = one_argument (argument, arg3); if (argument.empty()) { send_to_char ("Syntax: oset <object> ed <keyword> <string>\r\n"); return; } ed = new ExtraDescription(); ed->keyword = arg3; ed->description = argument; obj->extra_descr.push_back(ed); return; } /* * Generate usage message. */ do_oset (""); return; } void Character::do_rset (std::string argument) { std::string arg1, arg2, arg3; Room *location; int value; smash_tilde (argument); argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); arg3 = argument; if (arg1.empty() || arg2.empty() || arg3.empty()) { send_to_char ("Syntax: rset <location> <field> value\r\n"); send_to_char ("\r\n"); send_to_char ("Field being one of:\r\n"); send_to_char (" flags sector\r\n"); return; } if ((location = find_location (this, arg1)) == NULL) { send_to_char ("No such location.\r\n"); return; } /* * Snarf the value. */ if (!is_number (arg3)) { send_to_char ("Value must be numeric.\r\n"); return; } value = std::atoi (arg3.c_str()); /* * Set something. */ if (!str_cmp (arg2, "flags")) { location->room_flags = value; return; } if (!str_cmp (arg2, "sector")) { location->sector_type = value; return; } /* * Generate usage message. */ do_rset (""); return; } void Character::do_users (std::string argument) { char buf[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; int count; count = 0; buf[0] = '\0'; buf2[0] = '\0'; for (DescIter d = descriptor_list.begin(); d != descriptor_list.end(); d++) { if ((*d)->character != NULL && can_see((*d)->character)) { count++; snprintf (buf + strlen(buf), sizeof(buf) - strlen(buf), "[%3d %2d] %s@%s\r\n", (*d)->descriptor, (*d)->connected, (*d)->original ? (*d)->original->name.c_str() : (*d)->character ? (*d)->character->name.c_str() : "(none)", (*d)->host.c_str()); } } snprintf (buf2, sizeof buf2, "%d user%s\r\n", count, count == 1 ? "" : "s"); strncat (buf, buf2, sizeof buf - sizeof buf2); send_to_char (buf); return; } /* * Thanks to Grodyn for pointing out bugs in this function. */ void Character::do_force (std::string argument) { std::string arg; int trst; int cmd; argument = one_argument (argument, arg); if (arg.empty() || argument.empty()) { send_to_char ("Force whom to do what?\r\n"); return; } /* * Look for command in command table. */ trst = get_trust (); for (cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++) { if (argument[0] == cmd_table[cmd].name[0] && !str_prefix (argument, cmd_table[cmd].name) && (cmd_table[cmd].level > trst && cmd_table[cmd].level != 41)) { send_to_char ("You cant even do that yourself!\r\n"); return; } } if (!str_cmp (arg, "all")) { Character *vch; CharIter c, next; for (c = char_list.begin(); c != char_list.end(); c = next) { vch = *c; next = ++c; if (!vch->is_npc () && vch->get_trust () < get_trust ()) { MOBtrigger = false; act ("$n forces you to '$t'.", argument.c_str(), vch, TO_VICT); vch->interpret (argument); } } } else { Character *victim; if ((victim = get_char_world (arg)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (victim == this) { send_to_char ("Aye aye, right away!\r\n"); return; } if (victim->get_trust () >= get_trust ()) { send_to_char ("Do it yourself!\r\n"); return; } MOBtrigger = false; act ("$n forces you to '$t'.", argument.c_str(), victim, TO_VICT); victim->interpret (argument); } send_to_char ("Ok.\r\n"); return; } void Character::do_holylight (std::string argument) { if (is_npc ()) return; if (IS_SET (actflags, PLR_HOLYLIGHT)) { REMOVE_BIT (actflags, PLR_HOLYLIGHT); send_to_char ("Holy light mode off.\r\n"); } else { SET_BIT (actflags, PLR_HOLYLIGHT); send_to_char ("Holy light mode on.\r\n"); } return; } /* Wizify and Wizbit sent in by M. B. King */ void Character::do_wizify (std::string argument) { std::string arg1; Character *victim; argument = one_argument (argument, arg1); if (arg1.empty()) { send_to_char ("Syntax: wizify <name>\r\n"); return; } if ((victim = get_char_world (arg1)) == NULL) { send_to_char ("They aren't here.\r\n"); return; } if (victim->is_npc ()) { send_to_char ("Not on mobs.\r\n"); return; } victim->wizbit = !victim->wizbit; if (victim->wizbit) { act ("$N wizified.\r\n", NULL, victim, TO_CHAR); act ("$n has wizified you!\r\n", NULL, victim, TO_VICT); } else { act ("$N dewizzed.\r\n", NULL, victim, TO_CHAR); act ("$n has dewizzed you!\r\n", NULL, victim, TO_VICT); } victim->do_save (""); return; } /* Idea from Talen of Vego's do_where command */ void Character::do_owhere (std::string argument) { char buf[MAX_STRING_LENGTH]; std::string arg; bool found = false; Object *in_obj; int obj_counter = 1; one_argument (argument, arg); if (arg.empty()) { send_to_char ("Syntax: owhere <object>.\r\n"); return; } else { ObjIter o; for (o = object_list.begin(); o != object_list.end(); o++) { if (!can_see_obj(*o) || !is_name (arg, (*o)->name)) continue; found = true; for (in_obj = *o; in_obj->in_obj != NULL; in_obj = in_obj->in_obj) ; if (in_obj->carried_by != NULL) { snprintf (buf, sizeof buf, "[%2d] %s carried by %s.\r\n", obj_counter, (*o)->short_descr.c_str(), in_obj->carried_by->describe_to(this).c_str()); } else { snprintf (buf, sizeof buf, "[%2d] %s in %s.\r\n", obj_counter, (*o)->short_descr.c_str(), (in_obj->in_room == NULL) ? "somewhere" : in_obj->in_room->name.c_str()); } obj_counter++; buf[0] = toupper (buf[0]); send_to_char (buf); } } if (!found) send_to_char ("Nothing like that in hell, earth, or heaven.\r\n"); return; }