/*************************************************************************** * 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. * * * * Envy Diku Mud improvements copyright (C) 1994 by Michael Quan, David * * Love, Guilherme 'Willie' Arnold, and Mitchell Tse. * * * * EnvyMud 2.0 improvements copyright (C) 1995 by Michael Quan and * * Mitchell Tse. * * * * EnvyMud 2.2 improvements copyright (C) 1996, 1997 by Michael Quan. * * * * In order to use any part of this Envy Diku Mud, you must comply with * * the original Diku license in 'license.doc', the Merc license in * * 'license.txt', as well as the Envy license in 'license.nvy'. * * 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. * ***************************************************************************/ #if defined( macintosh ) #include <types.h> #else #include <sys/types.h> #endif #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "merc.h" #include "olc.h" /* JPG Following list should match merc.h Equipment wear loc list * * However, any unused locations need to be left in as placeholders * - Veygoth */ char * const where_name [] = { "&+y<invalid location> &n", // 0 "&+y<worn on finger> &n", // 1 "&+y<worn on finger> &n", // 2 "&+y<worn around neck> &n", // 3 "&+y<worn around neck> &n", // 4 "&+y<worn on body> &n", // 5 "&+y<worn on head> &n", // 6 "&+y<worn on legs> &n", // 7 "&+y<worn on feet> &n", // 8 "&+y<worn on hands> &n", // 9 "&+y<worn on arms> &n", // 10 "&+y<worn as shield> &n", // 11 "&+y<worn about body> &n", // 12 "&+y<worn about waist> &n", // 13 "&+y<worn around wrist> &n", // 14 "&+y<worn around wrist> &n", // 15 "&+y<primary hand> &n", // 16 "&+y<held> &n", // 17 "&+y<secondary hand> &n", // 18 "&+y<worn on eyes> &n", // 19 "&+y<worn on face> &n", // 20 "&+y<worn in left ear> &n", // 21 "&+y<worn in right ear> &n", // 22 "&+y<worn as badge> &n", // 23 "&+y<worn on back> &n", // 24 "&+y<attached to belt> &n", // 25 "&+y<attached to belt> &n", // 26 "&+y<attached to belt> &n", // 27 "&+y<worn as quiver> &n" // 28 }; const int topdown_eq [MAX_WEAR] = { 0, 23, 6, 19, 21, 22, 20, 3, 4, 5, 12, 13, 25, 10, 14, 15, 9, 1, 2, 11, 16, 18, 17, 25, 26, 27, 7, 8 }; /* * Local functions. */ char * format_obj_to_char args( ( OBJ_DATA *obj, CHAR_DATA *ch, bool fShort ) ); void show_list_to_char args( ( OBJ_DATA *list, CHAR_DATA *ch, bool fShort, bool fShowNothing ) ); void show_char_to_char_0 args( ( CHAR_DATA *victim, CHAR_DATA *ch ) ); void show_char_to_char_1 args( ( CHAR_DATA *victim, CHAR_DATA *ch ) ); void show_char_to_char args( ( CHAR_DATA *list, CHAR_DATA *ch ) ); char *format_obj_to_char( OBJ_DATA *obj, CHAR_DATA *ch, bool fShort ) { static char buf [ MAX_STRING_LENGTH ]; buf[0] = '\0'; if( IS_OBJ_STAT( obj, ITEM_NOSHOW ) && IS_IMMORTAL( ch )) strcat( buf, "(Noshow) " ); else if( IS_OBJ_STAT( obj, ITEM_NOSHOW )) return buf; if ( IS_OBJ_STAT( obj, ITEM_INVIS) ) strcat( buf, "(Invis) " ); if ( ( IS_AFFECTED( ch, AFF_DETECT_EVIL ) || ( IS_SET( race_table[ ch->race ].race_abilities, RACE_DETECT_ALIGN ) && IS_GOOD( ch ) ) ) && IS_OBJ_STAT( obj, ITEM_EVIL ) ) strcat( buf, "(Red Aura) " ); if ( ( IS_AFFECTED( ch, AFF_DETECT_GOOD ) || ( IS_SET( race_table[ ch->race ].race_abilities, RACE_DETECT_ALIGN ) && IS_EVIL( ch ) ) ) && IS_OBJ_STAT( obj, ITEM_BLESS ) ) strcat( buf, "(Blue Aura) " ); if ( IS_AFFECTED( ch, AFF_DETECT_MAGIC ) && IS_OBJ_STAT( obj, ITEM_MAGIC ) ) strcat( buf, "(Magical) " ); if ( IS_OBJ_STAT( obj, ITEM_GLOW ) ) strcat( buf, "(Glowing) " ); if ( IS_OBJ_STAT( obj, ITEM_HUM ) ) strcat( buf, "(Humming) " ); if ( IS_OBJ_STAT( obj, ITEM_POISONED ) ) strcat( buf, "(Poisoned) " ); strcat ( buf, ""); if ( fShort ) { if ( obj->short_descr ) strcat( buf, obj->short_descr ); } else { if ( obj->description ) strcat( buf, obj->description ); } strcat ( buf, "&n"); return buf; } /* * Show a list to a character. * Can coalesce duplicated items. */ void show_list_to_char( OBJ_DATA *list, CHAR_DATA *ch, bool fShort, bool fShowNothing ) { OBJ_DATA *obj; char buf [ MAX_STRING_LENGTH ]; char buf1[ MAX_STRING_LENGTH * 4 ]; char **prgpstrShow; char *pstrShow; int *prgnShow; int nShow; int iShow; int count; bool fCombine; if ( !ch->desc || !list ) return; buf1[0] = '\0'; /* * Alloc space for output lines. */ count = 0; for ( obj = list; obj; obj = obj->next_content ) { if ( obj->deleted ) continue; count++; } prgpstrShow = alloc_mem( count * sizeof( char * ) ); prgnShow = alloc_mem( count * sizeof( int ) ); nShow = 0; /* * Format the list of objects. */ for ( obj = list; obj; obj = obj->next_content ) { if ( obj->wear_loc == WEAR_NONE && can_see_obj( ch, obj ) ) { pstrShow = format_obj_to_char( obj, ch, fShort ); fCombine = FALSE; if ( IS_NPC( ch ) || IS_SET( ch->act, PLR_COMBINE ) ) { /* * Look for duplicates, case sensitive. * Matches tend to be near end so run loop backwords. */ for ( iShow = nShow - 1; iShow >= 0; iShow-- ) { if ( !strcmp( prgpstrShow[iShow], pstrShow ) ) { prgnShow[iShow]++; fCombine = TRUE; break; } } } /* * Couldn't combine, or didn't want to. */ if ( !fCombine ) { prgpstrShow [nShow] = str_dup( pstrShow ); prgnShow [nShow] = 1; nShow++; } } } /* * Output the formatted list. */ for ( iShow = 0; iShow < nShow; iShow++ ) { if ( IS_NPC( ch ) || IS_SET( ch->act, PLR_COMBINE ) ) { if ( prgnShow[iShow] != 1 ) { sprintf( buf, "(%d) ", prgnShow[iShow] ); strcat( buf1, buf ); } } strcat( buf1, prgpstrShow[iShow] ); strcat( buf1, "\n\r" ); free_string( prgpstrShow[iShow] ); } if ( fShowNothing && nShow == 0 ) { if ( IS_NPC( ch ) || IS_SET( ch->act, PLR_COMBINE ) ) strcat( buf1, " " ); strcat( buf1, "Nothing.\n\r" ); } /* * Clean up. */ free_mem( prgpstrShow, count * sizeof( char * ) ); free_mem( prgnShow, count * sizeof( int ) ); send_to_char( buf1, ch ); return; } void show_char_to_char_0( CHAR_DATA *victim, CHAR_DATA *ch ) { char buf [ MAX_STRING_LENGTH ]; buf[0] = '\0'; if ( !victim || !ch ) return; if ( victim->rider && victim->rider->in_room == ch->in_room ) return; if ( !IS_NPC( victim ) && IS_SET( victim->act, PLR_WIZINVIS ) && get_trust( victim ) < get_trust( ch ) ) strcat( buf, "(Wizinvis) " ); if ( IS_AFFECTED( victim, AFF_INVISIBLE ) ) strcat( buf, "(Invis) " ); if ( IS_AFFECTED( victim, AFF_HIDE ) ) strcat( buf, "(Hide) " ); if ( IS_AFFECTED( victim, AFF_CHARM ) ) strcat( buf, "(Charmed) " ); if ( IS_AFFECTED( victim, AFF_PASS_DOOR ) || ( IS_SET( race_table[ victim->race ].race_abilities, RACE_PASSDOOR ) && ( !str_cmp( race_table[victim->race].name, "Undead" ) || !str_cmp( race_table[victim->race].name, "Vampire" ) ) ) ) strcat( buf, "(Translucent) "); if ( IS_AFFECTED( victim, AFF_FAERIE_FIRE ) ) strcat( buf, "(Pink Aura) " ); if ( IS_EVIL( victim ) && ( IS_AFFECTED( ch, AFF_DETECT_EVIL ) || ( IS_SET( race_table[ ch->race ].race_abilities, RACE_DETECT_ALIGN ) && IS_GOOD( ch ) ) ) ) strcat( buf, "(Red Aura) " ); if ( IS_GOOD( victim ) && ( IS_AFFECTED( ch, AFF_DETECT_GOOD ) || ( IS_SET( race_table[ ch->race ].race_abilities, RACE_DETECT_ALIGN ) && IS_EVIL( ch ) ) ) ) strcat( buf, "(Golden Aura) "); if ( IS_AFFECTED( victim, AFF_SANCTUARY ) || IS_SET( race_table[ victim->race ].race_abilities, RACE_SANCT ) ) strcat( buf, "(White Aura) " ); if ( IS_AFFECTED( victim, AFF_FLAMING ) ) strcat( buf, "(Black Aura) " ); if ( !IS_NPC( victim ) && IS_SET( victim->act, PLR_AFK ) ) strcat( buf, "[AFK] " ); strcat ( buf, "" ); if ( victim->position == POS_STANDING && victim->long_descr[0] != '\0' ) { strcat( buf, victim->long_descr ); strcat( buf, "" ); send_to_char( buf, ch ); return; } strcat( buf, PERS( victim, ch ) ); if ( !IS_NPC( victim ) && !IS_SET( ch->act, PLR_BRIEF ) ) strcat( buf, victim->pcdata->title ); switch ( victim->position ) { case POS_DEAD: strcat( buf, " is DEAD!!" ); break; case POS_MORTAL: strcat( buf, " is mortally wounded" ); break; case POS_INCAP: strcat( buf, " is incapacitated" ); break; case POS_STUNNED: strcat( buf, " is lying here stunned" ); break; case POS_SLEEPING: strcat( buf, " is sleeping here" ); break; case POS_RESTING: strcat( buf, " is resting here" ); break; case POS_STANDING: strcat( buf, " is here" ); break; case POS_SITTING: strcat( buf, " is sitting here" ); break; case POS_KNEELING: strcat( buf, " is kneeling here" ); break; case POS_RECLINING:strcat( buf, " is lying here" ); break; case POS_FIGHTING: strcat( buf, " is here," ); if ( !victim->fighting ) strcat( buf, " fighting thin air??" ); break; } // This code is to handle people sitting or prone in a fight. if( victim->fighting ) { strcat( buf, " fighting " ); if( victim->fighting == ch ) strcat( buf, "YOU!" ); else if ( victim->in_room == victim->fighting->in_room ) strcat( buf, PERS( victim->fighting, ch ) ); else strcat( buf, "someone who left??" ); } if ( victim->riding && victim->riding->in_room == victim->in_room ) { char buf1 [ MAX_STRING_LENGTH ]; sprintf( buf1, ", mounted on %s.", PERS( victim->riding, ch ) ); strcat( buf, buf1 ); } else { // Show the player's race -- Veygoth strcat( buf, ". (" ); strcat( buf, race_table[ victim->race ].colorname ); strcat( buf, ")" ); } strcat( buf, "\n\r" ); buf[0] = UPPER( buf[0] ); send_to_char( buf, ch ); return; } void show_char_to_char_1( CHAR_DATA *victim, CHAR_DATA *ch ) { OBJ_DATA *obj; char buf [ MAX_STRING_LENGTH ]; char buf1 [ MAX_STRING_LENGTH ]; int iWear; int percent; bool found; if ( can_see( victim, ch ) ) { act( "$n&n looks at you.", ch, NULL, victim, TO_VICT ); act( "$n&n looks at $N&n.", ch, NULL, victim, TO_NOTVICT ); } buf[0] = '\0'; if ( victim->riding ) { sprintf( buf1, "Mounted on %s, ", PERS( victim->riding, ch ) ); strcat( buf, buf1 ); } else if ( victim->rider ) { sprintf( buf1, "Ridden by %s, ", PERS( victim->rider, ch ) ); strcat( buf, buf1 ); } sprintf( buf1, "$N&n the %s:\n\r", race_table[ victim->race ].colorname ); strcat( buf, buf1 ); if ( !IS_NPC( victim ) && is_clan( victim ) ) { sprintf( buf1, "%s of %s.\n\r", flag_string( rank_flags, victim->pcdata->rank ), victim->pcdata->clan->name ); buf1[0] = UPPER( buf1[0] ); strcat( buf, buf1 ); } act( buf, ch, NULL, victim, TO_CHAR ); if ( victim->description[0] != '\0' ) { send_to_char( victim->description, ch ); } else { act( "You see nothing special about $M.", ch, NULL, victim, TO_CHAR ); } if ( victim->max_hit > 0 ) percent = ( 100 * victim->hit ) / victim->max_hit; else percent = -1; strcpy( buf, PERS( victim, ch ) ); if ( percent >= 100 ) strcat( buf, " is in &+gperfect health&n.\n\r" ); else if ( percent >= 90 ) strcat( buf, " is &+yslightly scratched&n.\n\r" ); else if ( percent >= 80 ) strcat( buf, " has a &+yfew bruises&n.\n\r" ); else if ( percent >= 70 ) strcat( buf, " has &+Ysome cuts&n.\n\r" ); else if ( percent >= 60 ) strcat( buf, " has &+Mseveral wounds&n.\n\r" ); else if ( percent >= 50 ) strcat( buf, " has &+mmany nasty wounds&n.\n\r" ); else if ( percent >= 40 ) strcat( buf, " is &+Rbleeding freely&n.\n\r" ); else if ( percent >= 30 ) strcat( buf, " is &+Rcovered in blood&n.\n\r" ); else if ( percent >= 20 ) strcat( buf, " is &+rleaking guts&n.\n\r" ); else if ( percent >= 10 ) strcat( buf, " is &+ralmost dead&n.\n\r" ); else strcat( buf, " is &+rDYING&n.\n\r" ); buf[0] = UPPER( buf[0] ); send_to_char( buf, ch ); found = FALSE; for ( iWear = 0; iWear < MAX_WEAR; iWear++ ) { if ( ( obj = get_eq_char( victim, topdown_eq[iWear] ) ) && can_see_obj( ch, obj ) ) { if ( !found ) { send_to_char( "\n\r", ch ); act( "$E is using", ch, NULL, victim, TO_CHAR ); found = TRUE; } send_to_char( where_name[topdown_eq[iWear]], ch ); send_to_char( format_obj_to_char( obj, ch, TRUE ), ch ); send_to_char( "\n\r", ch ); } } // Keep in mind that players can spam looking at someone in order // to increase their skill in peek -- this will need to be fixed // - Veygoth if ( ( victim != ch && !IS_NPC( ch ) && number_percent( ) < ch->pcdata->skl_lrn[gsn_peek] ) || ch->riding == victim || ch->rider == victim ) { send_to_char( "\n\rYou peek at the inventory:\n\r", ch ); skill_practice( ch, gsn_peek ); show_list_to_char( victim->carrying, ch, TRUE, TRUE ); } return; } void show_char_to_char( CHAR_DATA *list, CHAR_DATA *ch ) { CHAR_DATA *rch; if ( !list ) return; for ( rch = list; rch; rch = rch->next_in_room ) { if ( rch->deleted || rch == ch ) continue; if ( !IS_NPC( rch ) && IS_SET( rch->act, PLR_WIZINVIS ) && get_trust( ch ) < get_trust( rch ) ) continue; if ( can_see( ch, rch ) ) { show_char_to_char_0( rch, ch ); } else if ( room_is_dark( ch->in_room ) && ( IS_AFFECTED( rch, AFF_INFRARED ) || IS_SET( race_table[ rch->race ].race_abilities, RACE_INFRAVISION ) ) ) { send_to_char( "You see glowing red eyes watching YOU!\n\r", ch ); } } return; } bool check_blind( CHAR_DATA *ch ) { if ( !IS_NPC( ch ) && IS_SET( ch->act, PLR_HOLYLIGHT ) ) return TRUE; if ( IS_AFFECTED( ch, AFF_BLIND ) ) { send_to_char( "You can't see a thing!\n\r", ch ); return FALSE; } return TRUE; } void do_look( CHAR_DATA *ch, char *argument ) { OBJ_DATA *obj; CHAR_DATA *victim; EXIT_DATA *pexit; char buf [ MAX_STRING_LENGTH ]; char arg1 [ MAX_INPUT_LENGTH ]; char arg2 [ MAX_INPUT_LENGTH ]; char *pdesc; int door; if ( !IS_NPC( ch ) && !ch->desc ) return; if ( ch->position < POS_SLEEPING ) { send_to_char( "You can't see anything but stars! See how pretty!\n\r", ch ); return; } if ( ch->position == POS_SLEEPING ) { send_to_char( "You can't see anything, you're sleeping! Zzz.\n\r", ch ); return; } if ( !check_blind( ch ) ) return; if ( !IS_NPC( ch ) && !IS_SET( ch->act, PLR_HOLYLIGHT ) && room_is_dark( ch->in_room ) && !IS_SET( race_table[ch->race].race_abilities, RACE_ULTRAVISION ) && !IS_AFFECTED( ch, AFF_ULTRAVISION )) { send_to_char( "It is pitch black ... \n\r", ch ); show_char_to_char( ch->in_room->people, ch ); return; } argument = one_argument( argument, arg1 ); one_argument( argument, arg2 ); if ( arg1[0] == '\0' || !str_cmp( arg1, "auto" ) ) { /* 'look' or 'look auto' */ if ( !IS_SET( ch->act, PLR_EDIT_INFO ) ) { sprintf ( buf, "%s&n\n\r ", ch->in_room->name ); send_to_char( buf, ch ); } else show_room_info( ch, ch->in_room ); if ( arg1[0] == '\0' || ( !IS_NPC( ch ) && !IS_SET( ch->act, PLR_BRIEF ) ) ) { sprintf ( buf, "%s&n", ch->in_room->description ); send_to_char( buf, ch ); } if ( IS_SET( ch->in_room->room_flags, ROOM_SILENT ) ) send_to_char( "It seems eerily quiet.\n\r", ch ); if ( !IS_NPC( ch ) && IS_SET( ch->act, PLR_AUTOEXIT ) ) do_exits( ch, "auto" ); show_list_to_char( ch->in_room->contents, ch, FALSE, FALSE ); show_char_to_char( ch->in_room->people, ch ); return; } if ( !str_prefix( arg1, "in" ) ) { /* 'look in' */ if ( arg2[0] == '\0' ) { send_to_char( "Look in what?\n\r", ch ); return; } if ( !( obj = get_obj_here( ch, arg2 ) ) ) { send_to_char( "You do not see that here.\n\r", ch ); return; } switch ( obj->item_type ) { default: send_to_char( "That is not a container.\n\r", ch ); break; case TYPE_DRINK_CON: if ( obj->value[1] <= 0 ) { send_to_char( "It is empty.\n\r", ch ); break; } sprintf( buf, "It's %s full of a %s liquid.\n\r", obj->value[1] < obj->value[0] / 4 ? "less than half" : obj->value[1] < 3 * obj->value[0] / 4 ? "about half" : "more than half", liq_table[obj->value[2]].liq_color ); send_to_char( buf, ch ); break; case TYPE_CONTAINER: case TYPE_CORPSE_NPC: case TYPE_CORPSE_PC: if ( IS_SET( obj->value[1], CONT_CLOSED ) ) { send_to_char( "It is closed.\n\r", ch ); break; } act( "$p contains:", ch, obj, NULL, TO_CHAR ); show_list_to_char( obj->contains, ch, TRUE, TRUE ); break; } return; } if ( ( victim = get_char_room( ch, arg1 ) ) ) { show_char_to_char_1( victim, ch ); return; } for ( obj = ch->carrying; obj; obj = obj->next_content ) { if ( can_see_obj( ch, obj ) ) { pdesc = get_extra_descr( arg1, obj->extra_descr ); if ( pdesc ) { send_to_char( pdesc, ch ); return; } pdesc = get_extra_descr( arg1, obj->pIndexData->extra_descr ); if ( pdesc ) { send_to_char( pdesc, ch ); return; } } if ( is_name( arg1, obj->name ) ) { send_to_char( obj->description, ch ); send_to_char( "\n\r", ch ); return; } } for ( obj = ch->in_room->contents; obj; obj = obj->next_content ) { if ( can_see_obj( ch, obj ) ) { pdesc = get_extra_descr( arg1, obj->extra_descr ); if ( pdesc ) { send_to_char( pdesc, ch ); return; } pdesc = get_extra_descr( arg1, obj->pIndexData->extra_descr ); if ( pdesc ) { send_to_char( pdesc, ch ); return; } } if ( is_name( arg1, obj->name ) ) { send_to_char( obj->description, ch ); send_to_char( "\n\r", ch ); return; } } pdesc = get_extra_descr( arg1, ch->in_room->extra_descr ); if ( pdesc ) { send_to_char( pdesc, ch ); return; } if ( !str_prefix( arg1, "north" ) ) door = 0; else if ( !str_prefix( arg1, "east" ) ) door = 1; else if ( !str_prefix( arg1, "south" ) ) door = 2; else if ( !str_prefix( arg1, "west" ) ) door = 3; else if ( !str_prefix( arg1, "up" ) ) door = 4; else if ( !str_prefix( arg1, "down" ) ) door = 5; else if ( !str_prefix( arg1, "northwest" ) ) door = 6; else if ( !str_prefix( arg1, "southwest" ) ) door = 7; else if ( !str_prefix( arg1, "northeast" ) ) door = 8; else if ( !str_prefix( arg1, "southeast" ) ) door = 9; else { send_to_char( "You do not see that here.\n\r", ch ); return; } /* 'look direction' */ if ( !( pexit = ch->in_room->exit[door] ) ) { send_to_char( "Nothing special there.\n\r", ch ); return; } if ( pexit->description && pexit->description[0] != '\0' ) send_to_char( pexit->description, ch ); else send_to_char( "Nothing special there.\n\r", ch ); if ( pexit->keyword && pexit->keyword[0] != '\0' && pexit->keyword[0] != ' ' ) { if ( IS_SET( pexit->exit_info, EX_BASHED ) ) act( "The $d has been bashed from its hinges.", ch, NULL, pexit->keyword, TO_CHAR ); else if ( IS_SET( pexit->exit_info, EX_CLOSED ) ) act( "The $d is closed.", ch, NULL, pexit->keyword, TO_CHAR ); else if ( IS_SET( pexit->exit_info, EX_ISDOOR ) ) act( "The $d is open.", ch, NULL, pexit->keyword, TO_CHAR ); } return; } void do_examine( CHAR_DATA *ch, char *argument ) { OBJ_DATA *obj; char buf [ MAX_STRING_LENGTH ]; char arg [ MAX_INPUT_LENGTH ]; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Examine what?\n\r", ch ); return; } do_look( ch, arg ); if ( ( obj = get_obj_here( ch, arg ) ) ) { switch ( obj->item_type ) { default: break; case TYPE_DRINK_CON: case TYPE_CONTAINER: case TYPE_CORPSE_NPC: case TYPE_CORPSE_PC: send_to_char( "When you look inside, you see:\n\r", ch ); sprintf( buf, "in %s", arg ); do_look( ch, buf ); } } return; } /* * Thanks to Zrin for auto-exit part. */ void do_exits( CHAR_DATA *ch, char *argument ) { EXIT_DATA *pexit; extern char * const dir_name [ ]; char buf [ MAX_STRING_LENGTH ]; int door; bool found; bool fAuto; buf[0] = '\0'; fAuto = !str_cmp( argument, "auto" ); if ( !check_blind( ch ) ) return; strcpy( buf, fAuto ? "&+c[Exits:" : "Obvious exits:\n\r" ); found = FALSE; // Veygoth - made it show the direction with an asterisk if it // has a closed door, and in exits command it shows up as a // closed <whatever>. It was silly not to show that a room had // doors and such. for ( door = 0; door < MAX_DIR; door++ ) { if ( ( pexit = ch->in_room->exit[door] ) && pexit->to_room ) { found = TRUE; if ( fAuto ) { strcat( buf, " " ); if(IS_SET( pexit->exit_info, EX_CLOSED )) strcat( buf, "&+m*&+c" ); strcat( buf, dir_name[door] ); } else { if(!IS_SET( pexit->exit_info, EX_CLOSED )) { sprintf( buf + strlen( buf ), "%-5s - %s\n\r", capitalize( dir_name[door] ), room_is_dark( pexit->to_room ) ? "Too dark to tell" : pexit->to_room->name ); } else { sprintf( buf + strlen( buf ), "%-5s - closed %s\n\r", capitalize( dir_name[door] ), pexit->keyword ); } } } } if ( !found ) strcat( buf, fAuto ? " none" : "None.\n\r" ); if ( fAuto ) strcat( buf, "]&n\n\r" ); send_to_char( buf, ch ); return; } /* * Enhanced version of do_exits() done by Zen. */ void show_room_info( CHAR_DATA *ch, ROOM_INDEX_DATA *room ) { char buf [ MAX_STRING_LENGTH ]; char buf1 [ MAX_STRING_LENGTH ]; if ( !IS_SET( ch->act, PLR_EDIT_INFO ) ) return; buf[0] = '\0'; strcpy ( buf1, flag_string( room_flags, room->room_flags ) ); sprintf( buf, "[%d] %s ( %s ) [ %s ]\n\r", room->vnum, room->name, flag_string( sector_flags, room->sector_type ), all_capitalize( buf1 ) ); buf1[0] = '\0'; strcat( buf1, buf ); send_to_char( buf1, ch ); return; } void do_score( CHAR_DATA *ch, char *argument ) { AFFECT_DATA *paf; char buf [ MAX_STRING_LENGTH ]; char buf1 [ MAX_STRING_LENGTH ]; buf1[0] = '\0'; sprintf( buf, "&+WName: &+G%s&n%s\n\r", ch->name, IS_NPC( ch ) ? "" : ch->pcdata->title ); strcat( buf1, buf ); sprintf( buf, "&+WRace: &n%-10.10s&n &+WClass: %-15.15s&n &+WSex: %s\n\r", race_table[ ch->race ].colorname, class_table[ch->class]->who_name, capitalize( get_sex( ch ))); strcat( buf1, buf ); sprintf( buf, "&+WLevel: %-5d Played: %d hours\n\r", ch->level, ( ch->played / 3600 ) ); strcat( buf1, buf ); // May want to throw character's age in here somewhere sprintf( buf, "&+WExperience: &+b%s&n\n\r\n\r", get_exp_string( ch ) ); strcat( buf1, buf ); sprintf( buf, "&+WCurrent/Max Health: [&+g%4d&+W / &+g%-4d&+W] Coins: Carried In Bank\n\r", ch->hit, ch->max_hit ); strcat( buf1, buf ); sprintf( buf, "&+WCurrent/Max Moves: [&+g%4d&+W / &+g%-4d&+W] &+WPlatinum %4d %4d\n\r", ch->move, ch->max_move, ch->money.platinum, ch->pcdata->bank.platinum ); strcat( buf1, buf ); sprintf( buf, "Current/Max Mana: [&+g%4d&+W / &+g%-4d&+W] &+YGold %4d %4d\n\r", ch->mana, ch->max_mana, ch->money.gold, ch->pcdata->bank.gold ); strcat( buf1, buf ); sprintf( buf, " &+wSilver %4d %4d\n\r", ch->money.silver, ch->pcdata->bank.silver ); strcat( buf1, buf ); sprintf( buf, "&+WFrags: &+W%-3d&n &+yCopper %4d %4d\n\r\n\r", ch->pcdata->frags, ch->money.copper, ch->pcdata->bank.copper ); strcat( buf1, buf ); if ( ch->affected ) { bool printed = FALSE; for ( paf = ch->affected; paf; paf = paf->next ) { if ( paf->deleted ) continue; if ( !printed ) { strcat( buf1, "&+BActive Spells:&+W\n\r" ); printed = TRUE; } if( paf->skill && paf->spell ) log_string( "Possible bug - affect with both spell and skill type defined" ); if( paf->skill ) { sprintf( buf, "%s", skills_table[paf->skill].name ); strcat( buf1, buf ); } else if( paf->spell ) { sprintf( buf, "%s", spells_table[paf->spell].name ); strcat( buf1, buf ); } else { log_string( "affect without spell or skill associated. possible bug" ); } if ( IS_IMMORTAL( ch ) ) { sprintf( buf, " modifies %s by %d for %d hours.", affect_loc_name( paf->location ), paf->modifier, paf->duration ); strcat( buf1, buf ); } strcat( buf1, "\n\r" ); } } strcat( buf1, "&n" ); send_to_char( buf1, ch ); return; } void do_exp( CHAR_DATA *ch, char *arg ) { char buf[MAX_STRING_LENGTH]; sprintf( buf, "&+b%s&n\n\r", get_exp_string( ch )); send_to_char( buf, ch ); } char * const day_name [] = { "the Moon", "the Bull", "Deception", "Thunder", "Freedom", "the Great Gods", "the Sun" }; char * const month_name [] = { "Winter", "the Winter Wolf", "the Frost Giant", "the Old Forces", "the Grand Struggle", "the Spring", "Nature", "Futility", "the Dragon", "the Sun", "the Heat", "the Battle", "the Dark Shades", "the Shadows", "the Long Shadows", "the Ancient Darkness", "the Great Evil" }; void do_time( CHAR_DATA *ch, char *argument ) { char buf [ MAX_STRING_LENGTH ]; extern char str_boot_time[]; char *suf; int day; day = time_info.day + 1; if ( day > 4 && day < 20 ) suf = "th"; else if ( day % 10 == 1 ) suf = "st"; else if ( day % 10 == 2 ) suf = "nd"; else if ( day % 10 == 3 ) suf = "rd"; else suf = "th"; sprintf( buf, "It is %d o'clock %s, Day of %s, %d%s the Month of %s.\n\rThe year is %d.\n\r", ( time_info.hour % 12 == 0 ) ? 12 : time_info.hour % 12, time_info.hour >= 12 ? "pm" : "am", day_name[day % 7], day, suf, month_name[time_info.month], time_info.year ); send_to_char( buf, ch ); sprintf( buf, "Magma MUD started up %s\rThe system time is %s\r", str_boot_time, (char *) ctime( ¤t_time ) ); send_to_char( buf, ch ); if ( down_time > 0 ) { sprintf( buf, "%s will be at %s\r", Reboot ? "Reboot" : "Shutdown", (char *) ctime( &down_time ) ); send_to_char( buf, ch ); } return; } void do_weather( CHAR_DATA *ch, char *argument ) { char buf [ MAX_STRING_LENGTH ]; char descr [ MAX_STRING_LENGTH ]; int wind; static char * const sky_look[ 8 ] = { "cloudless", "cloudy", "rainy", "lit by flashes of lightning", "slightly overcast", "scattered with a few flakes", "filled with flakes", "a blizzard of white" }; if ( !IS_OUTSIDE( ch ) ) { send_to_char( "You can't see the weather indoors.\n\r", ch ); return; } wind = weather_info.windspeed; descr[0] = '\0'; sprintf( buf, "The sky is %s ", (time_info.month <= 4 || time_info.month >= 15) ? sky_look[weather_info.sky + 4] : sky_look[weather_info.sky] ); strcat( descr, buf ); sprintf( buf, "and a %s %sward %s blows.\n\r", ( weather_info.temperature < 35 ) ? "cold" : ( weather_info.temperature < 60 ) ? "cool" : ( weather_info.temperature < 90 ) ? "warm" : "hot", dir_name[abs( weather_info.winddir ) % 3], wind <= 20 ? "breeze" : wind <= 50 ? "wind" : wind <= 80 ? "gust" : "torrent" ); strcat( descr, buf ); send_to_char( descr, ch ); return; } void do_help( CHAR_DATA *ch, char *argument ) { HELP_DATA *pHelp; bool hfound = FALSE; /* modification to show multiple helps by Robin Goodall from merc mailing list */ if ( argument[0] == '\0' ) argument = "summary"; for ( pHelp = help_first; pHelp; pHelp = pHelp->next ) { if ( pHelp->level > get_trust( ch ) ) continue; if ( is_name( argument, pHelp->keyword ) ) { if ( hfound ) send_to_char( "\n\r----------------------------------------------------------------------------\n\r\n\r", ch ); if ( pHelp->level >= 0 && str_cmp( argument, "imotd" ) ) { send_to_char( pHelp->keyword, ch ); send_to_char( "\n\r", ch ); } /* * Strip leading '.' to allow initial blanks. */ if ( pHelp->text[0] == '.' ) send_to_char( pHelp->text+1, ch ); else send_to_char( pHelp->text , ch ); hfound = TRUE; } } if ( !hfound ) send_to_char( "No help on that word.\n\r", ch ); return; } /* * New 'who' command originally by Alander of Rivers of Mud. * * 'who good' and 'who evil' added by Veygoth */ void do_who( CHAR_DATA *ch, char *argument ) { DESCRIPTOR_DATA *d; char buf [ MAX_STRING_LENGTH*3 ]; int iClass; int iLevelLower; int iLevelUpper; int nNumber; int nMatch; bool rgfClass [ MAX_CLASS ]; bool fClassRestrict; bool fImmortalOnly; bool fGoodOnly; // for racewar wholist bool fEvilOnly; // for racewar wholist WHO_DATA *curr_who = NULL; WHO_DATA *next_who = NULL; WHO_DATA *first_mortal = NULL; WHO_DATA *first_imm = NULL; /* * Set default arguments. */ iLevelLower = 0; iLevelUpper = L_DIR; /*Used to be Max_level */ fClassRestrict = FALSE; fImmortalOnly = FALSE; fGoodOnly = FALSE; fEvilOnly = FALSE; for ( iClass = 0; iClass < MAX_CLASS; iClass++ ) rgfClass[iClass] = FALSE; /* * Parse arguments. */ nNumber = 0; for ( ;; ) { char arg [ MAX_STRING_LENGTH ]; argument = one_argument( argument, arg ); if ( arg[0] == '\0' ) break; if ( is_number( arg ) ) { switch ( ++nNumber ) { case 1: iLevelLower = atoi( arg ); break; case 2: iLevelUpper = atoi( arg ); break; default: send_to_char( "Only two level numbers allowed.\n\r", ch ); return; } } else { int iClass; /* * Look for classes to turn on. */ arg[3] = '\0'; if ( !str_prefix( arg, "imm" ) ) { fImmortalOnly = TRUE; } else if ( !str_prefix( arg, "good" ) ) { fGoodOnly = TRUE; } else if( !str_prefix( arg, "evil" ) ) { fEvilOnly = TRUE; } else { fClassRestrict = TRUE; for ( iClass = 0; iClass < MAX_CLASS; iClass++ ) { if ( !str_prefix( arg, class_table[iClass]->name ) ) { rgfClass[iClass] = TRUE; break; } } if ( iClass == MAX_CLASS ) { send_to_char( "That's not a class.\n\r", ch ); return; } } } } /* * Now show matching chars. */ nMatch = 0; for ( d = descriptor_list; d; d = d->next ) { CHAR_DATA *wch; char const *class; wch = ( d->original ) ? d->original : d->character; /* * Check for match against restrictions. * Don't use trust as that exposes trusted mortals. */ if ( d->connected != CON_PLAYING || !can_see( ch, wch ) ) continue; if ( wch->level < iLevelLower || wch->level > iLevelUpper || ( fImmortalOnly && wch->level < LEVEL_HERO ) || ( fClassRestrict && !rgfClass[wch->class] ) || ( fGoodOnly && race_table[wch->race].racewar_side != RACEWAR_GOOD) || ( fEvilOnly && race_table[wch->race].racewar_side != RACEWAR_EVIL) ) continue; nMatch++; buf[0] = '\0'; /* * Figure out what to print for class. */ class = class_table[wch->class]->who_name; if ( wch->level >= LEVEL_HERO ) switch ( wch->level ) { default: break; case L_DIR: class = "&+r Overlord &n"; break; case L_SEN: class = "&+LImplementor&n"; break; case L_JUN: class = "&+mGreater God&n"; break; case L_APP: class = "&+MLesser God &n"; break; case L_DEM: class = "&+y Demigod &n"; break; case L_IMM: class = "&+c Immortal &n"; break; case L_AVA: class = "&+R Avatar &n"; break; case L_BUI: class = "&+LBu&+wil&+Wder&n"; break; } /* * Format it up. */ if ( wch->level < LEVEL_IMMORTAL ) { char buf1 [ MAX_STRING_LENGTH ]; char buf2 [ MAX_STRING_LENGTH ]; char leftletter; char rightletter; sprintf( buf1, "%s%s%s (%s)", IS_SET( wch->act, PLR_AFK ) ? "[AFK] " : "", wch->name, wch->pcdata->title, race_table[wch->race].colorname ); leftletter = !is_clan( wch ) ? ' ' : ( wch->pcdata->clan->clan_type == CLAN_GUILD ) ? '<' : '('; rightletter = !is_clan( wch ) ? ' ' : ( wch->pcdata->clan->clan_type == CLAN_GUILD ) ? '>' : ')'; sprintf( buf2, " %c%s%c", leftletter, !is_clan( wch ) ? "" : wch->pcdata->clan->who_name, rightletter ); sprintf( buf + strlen( buf ), "&+L[&n%-2d %-12s&+L]&n %s%s\n\r", wch->level, class, buf1, buf2 ); } else { char buf1 [ MAX_STRING_LENGTH ]; char buf2 [ MAX_STRING_LENGTH ]; char leftletter; char rightletter; sprintf( buf1, "%s%s%s%s", IS_SET( wch->act, PLR_WIZINVIS ) ? "(WIZINVIS) " : "", IS_SET( wch->act, PLR_AFK ) ? "[AFK] " : "", wch->name, wch->pcdata->title ); leftletter = !is_clan( wch ) ? ' ' : ( wch->pcdata->clan->clan_type == CLAN_GUILD ) ? '<' : '('; rightletter = !is_clan( wch ) ? ' ' : ( wch->pcdata->clan->clan_type == CLAN_GUILD ) ? '>' : ')'; sprintf( buf2, " %c%s%c", leftletter, !is_clan( wch ) ? "" : wch->pcdata->clan->who_name, rightletter ); sprintf( buf + strlen( buf ), "&+L[&n%-15s&+L]&n %s%s\n\r", class, buf1, buf2 ); } curr_who = alloc_mem( sizeof( WHO_DATA ) ); curr_who->text = str_dup( buf ); if ( wch->level < LEVEL_IMMORTAL ) { curr_who->next = first_mortal; first_mortal = curr_who; } else { curr_who->next = first_imm; first_imm = curr_who; } } // Veygoth - made immortals show up above mortals because immortals // are more important. if ( first_imm ) send_to_char( "&+b-----------------------------------[ &+BIMMORTALS&+b ]------------------------------&n\n\r", ch ); for ( curr_who = first_imm; curr_who; curr_who = next_who ) { send_to_char( curr_who->text, ch ); next_who = curr_who->next; free_string( curr_who->text ); free_mem( curr_who, sizeof( WHO_DATA ) ); } if ( first_mortal ) send_to_char( "&+b------------------------------------[ &+BMORTALS&+b ]-------------------------------&n\n\r", ch ); for ( curr_who = first_mortal; curr_who; curr_who = next_who ) { send_to_char( curr_who->text, ch ); next_who = curr_who->next; free_string( curr_who->text ); free_mem( curr_who, sizeof( WHO_DATA ) ); } send_to_char( "&+b------------------------------------------------------------------------------&n\n\r", ch ); sprintf( buf, "You see %d player%s in the game.\n\r", nMatch, nMatch == 1 ? "" : "s" ); send_to_char( buf, ch ); return; } /* Contributed by Kaneda */ void do_whois( CHAR_DATA *ch, char *argument ) { char *race; DESCRIPTOR_DATA *d; char buf [ MAX_STRING_LENGTH ]; char name [ MAX_INPUT_LENGTH ]; race = "\0"; one_argument( argument, name ); if( name[0] == '\0' ) { send_to_char( "Usage: whois <name>\n\r", ch ); return; } name[0] = UPPER( name[0] ); buf[0] = '\0'; for( d = descriptor_list ; d ; d = d->next ) { CHAR_DATA *wch; char const *class; wch = ( d->original ) ? d->original : d->character; if( d->connected != CON_PLAYING || !can_see( ch, wch ) ) continue; if( str_prefix( name, wch->name ) ) continue; class = class_table[ wch->class ]->who_name; if( wch->level >= LEVEL_IMMORTAL ) switch( wch->level ) { case L_DIR: class = "&+r Overlord&n"; break; case L_SEN: class = "&+LImplementor&n"; break; case L_JUN: class = "&+mGreater God&n"; break; case L_APP: class = "&+MLesser God&n"; break; case L_DEM: class = "&+y Demigod&n"; break; case L_IMM: class = "&+c Immortal&n"; break; case L_AVA: class = "&+R Avatar&n"; break; } /* * Format it up. */ if ( wch->level < LEVEL_IMMORTAL ) { sprintf( buf + strlen( buf ), "%s%s\n\r", wch->name, wch->pcdata->title ); sprintf( buf + strlen( buf ), "%s\n\r", IS_SET( wch->act, PLR_AFK ) ? "[AFK] " : "" ); sprintf( buf + strlen( buf ), "level %d %s %s.\n\r", wch->level, class, race_table[wch->race].colorname ); } else { sprintf( buf + strlen( buf ), "%s%s\n\r", wch->name, wch->pcdata->title ); sprintf( buf + strlen( buf ), "%s%s\n\r", IS_SET( wch->act, PLR_WIZINVIS ) ? "(WIZINVIS) " : "", IS_SET( wch->act, PLR_AFK ) ? "[AFK] " : "" ); sprintf( buf + strlen( buf ), "%s\n\r", class ); } if ( is_clan( wch ) ) { sprintf( buf + strlen( buf ), "%s of %s.\n\r", flag_string( rank_flags, wch->pcdata->rank ), wch->pcdata->clan->name ); } strcat( buf, "-----------------------------------------------------------------------------\n\r" ); } if ( buf[0] == '\0' ) send_to_char( "No one matches the given criteria.\n\r", ch ); else send_to_char( buf, ch ); return; } void do_inventory( CHAR_DATA *ch, char *argument ) { send_to_char( "You are carrying:\n\r", ch ); show_list_to_char( ch->carrying, ch, TRUE, TRUE ); return; } void do_equipment( CHAR_DATA *ch, char *argument ) { OBJ_DATA *obj; int iWear; bool found; send_to_char( "You are using:\n\r", ch ); found = FALSE; for ( iWear = 0; iWear < MAX_WEAR; iWear++ ) { if ( !( obj = get_eq_char( ch, topdown_eq[iWear] ) ) ) continue; send_to_char( where_name[topdown_eq[iWear]], ch ); if ( can_see_obj( ch, obj ) ) { send_to_char( format_obj_to_char( obj, ch, TRUE ), ch ); send_to_char( "\n\r", ch ); } else { send_to_char( "something.\n\r", ch ); } found = TRUE; } if ( !found ) send_to_char( "Nothing.\n\r", ch ); return; } void do_compare( CHAR_DATA *ch, char *argument ) { OBJ_DATA *obj1; OBJ_DATA *obj2; char *msg; char arg1 [ MAX_INPUT_LENGTH ]; char arg2 [ MAX_INPUT_LENGTH ]; int value1; int value2; argument = one_argument( argument, arg1 ); one_argument( argument, arg2 ); if ( arg1[0] == '\0' ) { send_to_char( "Compare what to what?\n\r", ch ); return; } if ( !( obj1 = get_obj_carry( ch, arg1 ) ) ) { send_to_char( "You do not have that item.\n\r", ch ); return; } if ( arg2[0] == '\0' ) { for ( obj2 = ch->carrying; obj2; obj2 = obj2->next_content ) { if ( obj2->wear_loc != WEAR_NONE && can_see_obj( ch, obj2 ) && obj1->item_type == obj2->item_type && ( obj1->wear_flags & obj2->wear_flags & ~ITEM_TAKE) != 0 ) break; } if ( !obj2 ) { send_to_char( "You aren't wearing anything comparable.\n\r", ch ); return; } } else { if ( !( obj2 = get_obj_carry( ch, arg2 ) ) ) { char new_arg2 [ MAX_INPUT_LENGTH ]; int number; /* Strip off number argument, subtract one, paste it together */ number = number_argument( arg2, arg2 ); if ( number > 1 ) number--; sprintf( new_arg2, "%d.%s", number, arg2 ); if ( !( obj2 = get_obj_wear( ch, new_arg2 ) ) ) { send_to_char( "You do not have that item.\n\r", ch ); return; } if ( ( obj1->wear_flags & obj2->wear_flags & ~ITEM_TAKE ) == 0 ) { send_to_char( "They are not comparable items.\n\r", ch ); return; } } } msg = NULL; value1 = 0; 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 TYPE_ARMOR: value1 = obj1->value[0]; value2 = obj2->value[0]; break; case TYPE_CLOTHING: value1 = obj1->value[0]; value2 = obj2->value[0]; break; case TYPE_WEAPON: value1 = obj1->value[1] + obj1->value[2]; value2 = obj2->value[1] + obj2->value[2]; break; } } if ( !msg ) { if ( obj2->wear_loc != WEAR_NONE ) { if ( value1 == value2 ) msg = "$p and $P (equipped) look about the same."; else if ( value1 > value2 ) msg = "$p looks better than $P (equipped)."; else msg = "$p looks worse than $P (equipped)."; } else { 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, ch, obj1, obj2, TO_CHAR ); return; } void do_credits( CHAR_DATA *ch, char *argument ) { do_help( ch, "diku" ); return; } void do_pwhere( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; DESCRIPTOR_DATA *d; char buf [ MAX_STRING_LENGTH ]; char arg [ MAX_INPUT_LENGTH ]; bool found; if ( !check_blind( ch ) ) return; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Players near you:\n\r", ch ); found = FALSE; for ( d = descriptor_list; d; d = d->next ) { if ( d->connected == CON_PLAYING && ( victim = d->character ) && !IS_NPC( victim ) && victim->in_room && victim->in_room->area == ch->in_room->area && can_see( ch, victim ) ) { found = TRUE; sprintf( buf, "%-28s %s\n\r", victim->name, victim->in_room->name ); send_to_char( buf, ch ); } } if ( !found ) send_to_char( "None\n\r", ch ); } else { found = FALSE; for ( victim = char_list; victim; victim = victim->next ) { if ( !victim->in_room || IS_AFFECTED( victim, AFF_HIDE ) || IS_AFFECTED( victim, AFF_SNEAK ) ) continue; if ( victim->in_room->area == ch->in_room->area && can_see( ch, victim ) && is_name( arg, victim->name ) ) { found = TRUE; sprintf( buf, "%-28s %s\n\r", PERS( victim, ch ), victim->in_room->name ); send_to_char( buf, ch ); break; } } if ( !found ) act( "You didn't find any $T.", ch, NULL, arg, TO_CHAR ); } return; } void do_consider( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; char *msg; char arg [ MAX_INPUT_LENGTH ]; int diff; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Consider killing whom?\n\r", ch ); return; } if ( !( victim = get_char_room( ch, arg ) ) ) { send_to_char( "They're not here.\n\r", ch ); return; } // Veygoth - removed code that would not let you consider players. diff = victim->level - ch->level; if ( diff <= -10 ) msg = "You can kill $N&n naked and weaponless."; else if ( diff <= -5 ) msg = "$N&n is no match for you."; else if ( diff <= -2 ) msg = "$N&n looks like an easy kill."; else if ( diff <= 1 ) msg = "The perfect match!"; else if ( diff <= 4 ) msg = "$N&n says 'Do you feel lucky, punk?'."; else if ( diff <= 9 ) msg = "$N&n laughs at you mercilessly."; else msg = "Death will thank you for your gift."; act( msg, ch, NULL, victim, TO_CHAR ); /* Removed health comparison messages - Veygoth */ return; } void do_glance( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; char msg[MAX_STRING_LENGTH]; if ( argument[0] == '\0' ) { send_to_char( "Glance at whom?\n\r", ch ); return; } if ( !( victim = get_char_room( ch, argument ) ) ) { send_to_char( "They're not here.\n\r", ch ); return; } sprintf( msg, "You glance at $N&n.\n\r$N&n is %s.", condition_string( victim ) ); act( msg, ch, NULL, victim, TO_CHAR ); return; } void set_title( CHAR_DATA *ch, char *title ) { char buf [ MAX_STRING_LENGTH ]; if ( IS_NPC( ch ) ) { bug( "Set_title: NPC.", 0 ); return; } buf[0] = '\0'; sprintf( buf, " " ); strcat( buf, title ); strcat( buf, "&n" ); free_string( ch->pcdata->title ); ch->pcdata->title = str_dup( buf ); return; } void do_title( CHAR_DATA *ch, char *argument ) { if ( IS_NPC( ch ) ) return; if ( argument[0] == '\0' ) { send_to_char( "Change your title to what?\n\r", ch ); return; } if ( strlen( argument ) > 60 ) argument[60] = '\0'; smash_tilde( argument ); set_title( ch, argument ); send_to_char( "Ok.\n\r", ch ); } void do_description( CHAR_DATA *ch, char *argument ) { if ( IS_NPC( ch ) ) return; string_append( ch, &ch->description ); return; } void do_report( CHAR_DATA *ch, char *argument ) { char buf [ MAX_INPUT_LENGTH ]; sprintf( buf, "You report: %d/%d hp %d/%d mana %d/%d mv.\n\r", ch->hit, ch->max_hit, ch->mana, ch->max_mana, ch->move, ch->max_move ); send_to_char( buf, ch ); sprintf( buf, "$n&n reports: %d/%d hp %d/%d mana %d/%d mv.", ch->hit, ch->max_hit, ch->mana, ch->max_mana, ch->move, ch->max_move ); act( buf, ch, NULL, NULL, TO_ROOM ); return; } void do_practice( CHAR_DATA *ch, char *argument ) { send_to_char( "This MUD does not use practice. Go use your skills instead!\n\r", ch ); return; } /* * 'Wimpy' originally by Dionysos. */ void do_wimpy( CHAR_DATA *ch, char *argument ) { char buf [ MAX_STRING_LENGTH ]; char arg [ MAX_INPUT_LENGTH ]; int wimpy; one_argument( argument, arg ); if ( arg[0] == '\0' ) wimpy = ch->max_hit / 5; else wimpy = atoi( arg ); if ( wimpy < 0 ) { send_to_char( "Your courage exceeds your wisdom.\n\r", ch ); return; } if ( wimpy > ch->max_hit ) { send_to_char( "Such cowardice ill becomes you.\n\r", ch ); return; } ch->wimpy = wimpy; sprintf( buf, "Wimpy set to %d hit points.\n\r", wimpy ); send_to_char( buf, ch ); return; } void do_password( CHAR_DATA *ch, char *argument ) { extern const char echo_off_str [ ]; if ( IS_NPC( ch ) ) return; write_to_buffer( ch->desc, "Password: ", 0 ); write_to_buffer( ch->desc, echo_off_str, 0 ); ch->desc->connected = CON_PASSWD_GET_OLD; return; } void do_socials( CHAR_DATA *ch, char *argument ) { SOC_INDEX_DATA *social; char buf [ MAX_STRING_LENGTH * 2]; char buf1 [ MAX_STRING_LENGTH * 2 ]; int col; int x; buf1[0] = '\0'; col = 0; for ( x = 0; x < MAX_WORD_HASH; x++ ) { for ( social = soc_index_hash[x]; social; social = social->next ) { if ( !social->name || social->name[0] == '\0' ) continue; sprintf( buf, "%-12s", social->name ); strcat( buf1, buf ); if ( ++col % 6 == 0 ) strcat( buf1, "\n\r" ); } } if ( col % 6 != 0 ) strcat( buf1, "\n\r" ); send_to_char( buf1, ch ); return; } /* * Contributed by Alander. */ void do_commands( CHAR_DATA *ch, char *argument ) { char buf [ MAX_STRING_LENGTH ]; char buf1 [ MAX_STRING_LENGTH ]; int cmd; int col; buf1[0] = '\0'; 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( ch ) && cmd_table[cmd].show ) { sprintf( buf, "%-16s", cmd_table[cmd].name ); strcat( buf1, buf ); if ( ++col % 5 == 0 ) strcat( buf1, "\n\r" ); } } if ( col % 5 != 0 ) strcat( buf1, "\n\r" ); send_to_char( buf1, ch ); return; } void do_channels( CHAR_DATA *ch, char *argument ) { char arg [ MAX_INPUT_LENGTH ]; one_argument( argument, arg ); if ( arg[0] == '\0' ) { if ( !IS_NPC( ch ) && IS_SET( ch->act, PLR_SILENCE ) ) { send_to_char( "You are silenced.\n\r", ch ); return; } send_to_char( "Channels:", ch ); send_to_char( !IS_SET( ch->deaf, CHANNEL_SHOUT ) ? " +SHOUT" : " -shout", ch ); send_to_char( !IS_SET( ch->deaf, CHANNEL_YELL ) ? " +YELL" : " -yell", ch ); if ( is_clan( ch ) ) { send_to_char( !IS_SET( ch->deaf, CHANNEL_CLANTALK ) ? " +CLANTALK" : " -clantalk", ch ); } if ( IS_HERO( ch ) ) { send_to_char( "\n\r", ch ); send_to_char( !IS_SET( ch->deaf, CHANNEL_IMMTALK ) ? " +IMMTALK" : " -immtalk", ch ); } send_to_char( ".\n\r", ch ); } else { int bit; bool fClear; if ( arg[0] == '+' ) fClear = TRUE; else if ( arg[0] == '-' ) fClear = FALSE; else { send_to_char( "Channels -channel or +channel?\n\r", ch ); return; } if ( !str_cmp( arg+1, "immtalk" ) ) bit = CHANNEL_IMMTALK; else if ( !str_cmp( arg+1, "clantalk" ) ) bit = CHANNEL_CLANTALK; else if ( !str_cmp( arg+1, "shout" ) ) bit = CHANNEL_SHOUT; else if ( !str_cmp( arg+1, "yell" ) ) bit = CHANNEL_YELL; else { send_to_char( "Set or clear which channel?\n\r", ch ); return; } if ( fClear ) REMOVE_BIT ( ch->deaf, bit ); else SET_BIT ( ch->deaf, bit ); send_to_char( "Ok.\n\r", ch ); } return; } /* * Contributed by Grodyn. */ void do_config( CHAR_DATA *ch, char *argument ) { char arg [ MAX_INPUT_LENGTH ]; if ( IS_NPC( ch ) ) return; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "[ Keyword ] Option\n\r", ch ); if ( IS_IMMORTAL( ch ) ) send_to_char( IS_SET( ch->act, PLR_EDIT_INFO ) ? "[+EDITINFO ] You see extra info on rooms.\n\r" : "[-editinfo ] You don't see extra info on rooms.\n\r" , ch ); send_to_char( IS_SET( ch->act, PLR_AUTOEXIT ) ? "[+AUTOEXIT ] You automatically see exits.\n\r" : "[-autoexit ] You don't automatically see exits.\n\r" , ch ); send_to_char( IS_SET( ch->act, PLR_BLANK ) ? "[+BLANK ] You have a blank line before your prompt.\n\r" : "[-blank ] You have no blank line before your prompt.\n\r" , ch ); send_to_char( IS_SET( ch->act, PLR_BRIEF ) ? "[+BRIEF ] You see brief descriptions.\n\r" : "[-brief ] You see long descriptions.\n\r" , ch ); send_to_char( IS_SET( ch->act, PLR_CAST_TICK ) ? "[+CASTTICK ] You see your casting ticks.\n\r" : "[-CASTTICK ] For spam's sake, no casting ticks!\n\r" , ch ); send_to_char( IS_SET( ch->act, PLR_COMBINE ) ? "[+COMBINE ] You see object lists in combined format.\n\r" : "[-combine ] You see object lists in single format.\n\r" , ch ); send_to_char( IS_SET( ch->act, PLR_COLOUR ) ? "[+COLOUR ] You see ANSI colours.\n\r" : "[-colour ] You don't see ANSI colours.\n\r" , ch ); send_to_char( IS_SET( ch->act, PLR_PAGER ) ? "[+PAGER ] You have a pager.\n\r" : "[-pager ] You don't have a pager.\n\r" , ch ); send_to_char( IS_SET( ch->act, PLR_PROMPT ) ? "[+PROMPT ] You have a prompt.\n\r" : "[-prompt ] You don't have a prompt.\n\r" , ch ); send_to_char( IS_SET( ch->act, PLR_SHOUT ) ? "[+SHOUT ] You can hear shouts.\n\r" : "[-shout ] You cover your ears when someone is yelling.\n\r" , ch ); send_to_char( IS_SET( ch->act, PLR_TELNET_GA ) ? "[+TELNETGA ] You receive a telnet GA sequence.\n\r" : "[-telnetga ] You don't receive a telnet GA sequence.\n\r" , ch ); send_to_char( IS_SET( ch->act, PLR_SILENCE ) ? "[+SILENCE ] You are silenced.\n\r" : "" , ch ); send_to_char( !IS_SET( ch->act, PLR_NO_EMOTE ) ? "" : "[-emote ] You can't emote.\n\r" , ch ); send_to_char( !IS_SET( ch->act, PLR_NO_TELL ) ? "" : "[-tell ] You can't use 'tell'.\n\r" , ch ); } else { char buf [ MAX_STRING_LENGTH ]; int bit; bool fSet; if ( arg[0] == '+' ) fSet = TRUE; else if ( arg[0] == '-' ) fSet = FALSE; else { send_to_char( "Config -option or +option?\n\r", ch ); return; } if ( !str_cmp( arg+1, "editinfo" ) && IS_IMMORTAL( ch ) ) bit = PLR_EDIT_INFO; else if ( !str_cmp( arg+1, "autoexit" ) ) bit = PLR_AUTOEXIT; else if ( !str_cmp( arg+1, "blank" ) ) bit = PLR_BLANK; else if ( !str_cmp( arg+1, "brief" ) ) bit = PLR_BRIEF; else if ( !str_cmp( arg+1, "casttick" ) ) bit = PLR_CAST_TICK; else if ( !str_cmp( arg+1, "combine" ) ) bit = PLR_COMBINE; else if ( !str_cmp( arg+1, "colour" ) ) bit = PLR_COLOUR; else if ( !str_cmp( arg+1, "pager" ) ) bit = PLR_PAGER; else if ( !str_cmp( arg+1, "shout" ) ) bit = PLR_SHOUT; else if ( !str_cmp( arg+1, "prompt" ) ) bit = PLR_PROMPT; else if ( !str_cmp( arg+1, "telnetga" ) ) bit = PLR_TELNET_GA; else { send_to_char( "Config which option?\n\r", ch ); return; } if ( fSet ) { SET_BIT ( ch->act, bit ); sprintf( buf, "%s is now ON.\n\r", arg+1 ); buf[0] = UPPER( buf[0] ); send_to_char( buf, ch ); } else { REMOVE_BIT ( ch->act, bit ); sprintf( buf, "%s is now OFF.\n\r", arg+1 ); buf[0] = UPPER( buf[0] ); send_to_char( buf, ch ); } } return; } void do_news ( CHAR_DATA *ch, char *argument ) { do_help ( ch, "news" ); return; } void do_wizlist ( CHAR_DATA *ch, char *argument ) { do_help ( ch, "wizlist" ); return; } // reformatted - Veygoth void do_slist ( CHAR_DATA *ch, char *argument ) { char buf [ MAX_STRING_LENGTH ]; char buf1 [ MAX_STRING_LENGTH ]; int sn; int level; bool pSpell; if ( IS_NPC( ch ) ) { send_to_char ( "You do not need any stinking skills!\n\r", ch ); return; } buf1[0] = '\0'; strcat ( buf1, "&+yALL Abilities available for your class.&n\n\r" ); strcat ( buf1, "&+bLv Abilities&n\n\r" ); for ( level = 1; level <= LEVEL_HERO; level++ ) { pSpell = TRUE; for ( sn = 0; sn < MAX_SKILL; sn++ ) { if ( !skills_table[sn].name ) break; if ( skills_table[sn].skill_level[ch->class] != level ) continue; if ( pSpell ) { sprintf ( buf, "&+Y%2d&+y:&n", level ); strcat ( buf1, buf ); pSpell = FALSE; } else strcat( buf1, " " ); /* format fix by Koala */ strcat ( buf1, " " ); sprintf ( buf, "&+c%-18s &+Y%d&n", skills_table[sn].name, ch->pcdata->skl_lrn[sn] ); strcat ( buf1, buf ); strcat ( buf1, "\n\r" ); } } send_to_char( buf1, ch ); return; } void do_spells ( CHAR_DATA *ch, char *argument ) { char buf [ MAX_STRING_LENGTH * 3 ]; char buf1 [ MAX_STRING_LENGTH * 3 ]; int sn; int circle; bool pSpell; if ( IS_NPC( ch ) ) { send_to_char ( "You do not need any stinking spells!\n\r", ch ); return; } buf1[0] = '\0'; strcat ( buf1, "&+yALL spells available for your class.&n\n\r" ); strcat ( buf1, "&+bLv Spell&n\n\r" ); // Don't show 12th circle spells... for ( circle = 1; circle < MAX_CIRCLE; circle++ ) { pSpell = TRUE; for ( sn = 0; sn < MAX_SPELL; sn++ ) { if ( !spells_table[sn].name ) break; if ( spells_table[sn].spell_circle[ch->class] != circle ) continue; if ( pSpell ) { sprintf ( buf, "&+Y%2d&+y:&n", circle ); strcat ( buf1, buf ); pSpell = FALSE; } else strcat( buf1, " " ); /* format fix by Koala */ strcat ( buf1, " " ); sprintf ( buf, "&+c%-18s &+Y%d&n", spells_table[sn].name, ch->pcdata->spl_lrn[sn] ); strcat ( buf1, buf ); strcat ( buf1, "\n\r" ); } } send_to_char( buf1, ch ); return; } /* bypassing the config command - Kahn */ void do_autoexit ( CHAR_DATA *ch, char *argument ) { char buf[ MAX_STRING_LENGTH ]; ( IS_SET ( ch->act, PLR_AUTOEXIT ) ? sprintf( buf, "-autoexit" ) : sprintf( buf, "+autoexit" ) ); do_config( ch, buf ); return; } void do_blank ( CHAR_DATA *ch, char *argument ) { char buf[ MAX_STRING_LENGTH ]; ( IS_SET ( ch->act, PLR_BLANK ) ? sprintf( buf, "-blank" ) : sprintf( buf, "+blank" ) ); do_config( ch, buf ); return; } void do_brief ( CHAR_DATA *ch, char *argument ) { char buf[ MAX_STRING_LENGTH ]; ( IS_SET ( ch->act, PLR_BRIEF ) ? sprintf( buf, "-brief" ) : sprintf( buf, "+brief" ) ) ; do_config( ch, buf ); return; } void do_combine ( CHAR_DATA *ch, char *argument ) { char buf[ MAX_STRING_LENGTH ]; ( IS_SET ( ch->act, PLR_COMBINE ) ? sprintf( buf, "-combine" ) : sprintf( buf, "+combine" ) ); do_config( ch, buf ); return; } void do_pagelen ( CHAR_DATA *ch, char *argument ) { char buf [ MAX_STRING_LENGTH ]; char arg [ MAX_INPUT_LENGTH ]; int lines; if ( IS_NPC( ch ) ) return; one_argument( argument, arg ); if ( arg[0] == '\0' ) lines = 20; else lines = atoi( arg ); if ( lines < 19 ) { send_to_char( "Less than 19 lines of paged text is not allowed", ch ); return; } if ( lines > 60 ) { send_to_char( "I don't know of a screen that is larger than 60 lines!\n\r", ch ); lines = 60; } ch->pcdata->pagelen = lines; sprintf( buf, "Page pause set to %d lines.\n\r", lines ); send_to_char( buf, ch ); return; } /* Do_prompt from Morgenes from Aldara Mud */ void do_prompt( CHAR_DATA *ch, char *argument ) { char buf [ MAX_STRING_LENGTH ]; buf[0] = '\0'; /* Unswitched NPC's get kicked out */ if ( !ch->desc ) return; /* Will always have a pc ch after this */ ch = ( ch->desc->original ? ch->desc->original : ch->desc->character ); if ( argument[0] == '\0' ) { ( IS_SET ( ch->act, PLR_PROMPT ) ? sprintf( buf, "-prompt" ) : sprintf( buf, "+prompt" ) ); do_config( ch, buf ); return; } if( !strcmp( argument, "all" ) ) strcat( buf, "&+g<%hhp %mm %vmv>\n\r<&n%T %E&+g>&n "); else if( !strcmp( argument, "meter" ) ) strcat( buf, "&+g<%hhp %mm %vmv>\n\r<&n%t %e&+g>&n "); else { if ( strlen( argument ) > 50 ) argument[50] = '\0'; smash_tilde( argument ); strcat( buf, argument ); } free_string( ch->pcdata->prompt ); ch->pcdata->prompt = str_dup( buf ); send_to_char( "Ok.\n\r", ch ); return; } void do_auto( CHAR_DATA *ch, char *argument ) { do_config( ch, "" ); return; } void do_afk( CHAR_DATA *ch, char *argument ) { if ( IS_NPC( ch ) ) return; if ( IS_SET( ch->act, PLR_AFK ) ) { REMOVE_BIT( ch->act, PLR_AFK ); send_to_char( "You are back at your keyboard.\n\r", ch ); act( "$n&n has returned to $s keyboard.", ch, NULL, ch, TO_ROOM ); } else { SET_BIT( ch->act, PLR_AFK ); send_to_char( "You are now away from keyboard.\n\r", ch ); act( "$n&n has left $s keyboard.", ch, NULL, ch, TO_ROOM ); } return; } void do_trophy( CHAR_DATA *ch, char *argument ) { int count; char buf[MAX_STRING_LENGTH]; if( IS_NPC( ch )) return; send_to_char( "Trophy data:\n\r", ch ); for( count = 0; count < MAX_LEVEL; count++ ) { if( ch->pcdata->trophy[count].vnum == 0 ) continue; if( ch->pcdata->trophy[count].number == 0 ) continue; sprintf( buf, " &+b(&+y%4.2f&+b)&n %s&n\n\r", (float)(ch->pcdata->trophy[count].number / 100), (get_mob_index( ch->pcdata->trophy[count].vnum ))->short_descr ); send_to_char( buf, ch ); } send_to_char( "\n\r", ch ); return; } // Returns the text string of someone's sex - Veygoth char *get_sex( CHAR_DATA *ch ) { switch( ch->sex ) { case 0: return "neuter"; break; case 1: return "male"; break; case 2: return "female"; break; default: return "mutant"; break; } } // Returns how far a character is from their next level as a text string // -- Veygoth char *get_exp_string( CHAR_DATA *ch ) { int exp; exp = ch->exp - (ch->level * EXP_PER_LEVEL); if( exp < 200 ) return "You have just begun the trek to your next level!"; if( exp < 400 ) return "You are still a very long way from your next level."; if( exp < 600 ) return "Have gained some progress but still have a long way to your next level."; if( exp < 800 ) return "You have gained some progress and are nearing the halfway point."; if( exp < 950 ) return "You are close to the halfway point in the journey to your next level."; if( exp < 1050 ) return "You are at the halfway point."; if( exp < 1200 ) return "You have just passed the halfway point."; if( exp < 1400 ) return "You are well on your way to the next level."; if( exp < 1600 ) return "You are three quarters the way to your next level."; if( exp < 1800 ) return "You are almost ready to attain your next level."; if( exp < 2000 ) return "You should level anytime now!"; return NULL; } void do_fraglist( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; int count; sprintf( buf, "&+YTotal Frags&n\n\r" ); sprintf( buf2, "Total Good Side Frags: %5d Total Evil Side Frags: %5d\n\t", fraglist.total_side_frags[RACEWAR_GOOD], fraglist.total_side_frags[RACEWAR_EVIL] ); strcat( buf, buf2 ); strcat( buf, "\n\rRace Frags:\n\r" ); for( count = 0; count < MAX_PC_RACE; count++ ) { sprintf( buf2, " %-10s: %5d", race_table[count].name, fraglist.total_race_frags[count] ); strcat( buf, buf2 ); if( count % 3 == 2 ) strcat( buf, "\n\r" ); } strcat( buf, "\n\rClass Frags:\n\r" ); // Starting at one because we don't care about class_none frags for( count = 1; count < MAX_CLASS; count++ ) { sprintf( buf2, " %-18s: %5d", class_table[count]->who_name, fraglist.total_class_frags[count] ); strcat( buf, buf2 ); if( count % 3 == 0 ) strcat( buf, "\n\r" ); } strcat( buf, "\n\r" ); send_to_char( buf, ch ); } void do_innate( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; sprintf( buf, "Innate abilities available to your race and class:\n\r" ); if( IS_SET( race_table[ch->race].race_abilities, RACE_BODYSLAM )) strcat( buf, " bodyslam\n\r" ); if( IS_SET( race_table[ch->race].race_abilities, RACE_CHARGE )) strcat( buf, " charge\n\r" ); if( IS_SET( race_table[ch->race].race_abilities, RACE_FLY )) strcat( buf, " fly\n\r" ); if( IS_SET( race_table[ch->race].race_abilities, RACE_PASSDOOR )) strcat( buf, " pass door\n\r" ); if( IS_SET( race_table[ch->race].race_abilities, RACE_SWIM )) strcat( buf, " swim\n\r" ); if( IS_SET( race_table[ch->race].race_abilities, RACE_WATERBREATH )) strcat( buf, " water breathing\n\r" ); if( IS_SET( race_table[ch->race].race_abilities, RACE_INFRAVISION )) strcat( buf, " infravision\n\r" ); if( IS_SET( race_table[ch->race].race_abilities, RACE_ULTRAVISION )) strcat( buf, " ultravision\n\r" ); if( IS_SET( race_table[ch->race].race_abilities, RACE_DETECT_ALIGN )) strcat( buf, " detect align\n\r" ); if( IS_SET( race_table[ch->race].race_abilities, RACE_DETECT_INVIS )) strcat( buf, " detect invis\n\r" ); if( IS_SET( race_table[ch->race].race_abilities, RACE_DETECT_HIDDEN )) strcat( buf, " detect hidden\n\r" ); if( IS_SET( race_table[ch->race].race_abilities, RACE_MUTE )) strcat( buf, " mute\n\r" ); send_to_char( buf, ch ); return; }