/*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvements 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. * * * * 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 <unistd.h> #include <assert.h> #include "merc.h" /* opposite directions */ const int opposite_dir [6] = { DIR_SOUTH, DIR_WEST, DIR_NORTH, DIR_EAST, DIR_DOWN, DIR_UP }; /* command procedures needed */ void do_sstat( CHAR_DATA *ch, char *argument ) /* sstat by Garion */ { CHAR_DATA *victim; char arg[MAX_INPUT_LENGTH]; char buf1[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; int sn; int col; if ( !authorized( ch, "sstat" ) ) return; one_argument( argument, arg ); col = 0; if ( arg[0] == '\0' ) { send_to_char("Sstat whom\n\r?", ch); return; } if ( ( victim = get_char_world( ch, arg ) ) == NULL ) { send_to_char("That person isn't logged on.\n\r", ch); return; } if ( IS_NPC( victim ) ) { send_to_char("Not on NPC's.\n\r", ch); return; } buf2[0] = '\0'; for ( sn = 0; sn < MAX_SKILL ; sn++ ) { if ( skill_table[sn].name == NULL ) break; if ( victim->level < skill_table[sn].skill_level[victim->class] ) continue; sprintf( buf1, "%18s %3d %% ", skill_table[sn].name, victim->pcdata->learned[sn] ); strcat( buf2, buf1 ); if ( ++col %3 == 0 ) strcat( buf2, "\n\r" ); } if ( col % 3 != 0 ) strcat( buf2, "\n\r" ); sprintf( buf1, "%s has %d practice sessions left.\n\r", victim->name, victim->practice ); strcat( buf2, buf1 ); send_to_char( buf2, ch ); return; } void do_update( CHAR_DATA *ch, char *argument ) /* by Maniac */ { char arg[MAX_INPUT_LENGTH]; int value; if ( !authorized( ch, "update" ) ) return; if ( argument[0] == '\0' ) /* No options ??? */ { send_to_char( "Update, call some game functions\n\r\n\r", ch ); send_to_char( "bank [value]: Update the share_value.\n\r", ch ); send_to_char( "time <value>: Set time hour to <value>.\n\r", ch); return; } argument = one_argument(argument, arg); if (!str_prefix(arg, "bank" ) ) { one_argument(argument, arg); value = 0; if (arg) { value = atoi(arg); if (value) share_value = value; } else bank_update ( ); sprintf(arg, "Ok...bank updated, share_value is now: %d\n\r", share_value ); send_to_char( arg, ch); return; } if (!str_prefix(arg, "time" ) ) { one_argument(argument, arg); if (arg) value = atoi(arg); else { sprintf (arg, "Current hour is %d.\n\r", time_info.hour); send_to_char(arg, ch); return; } if (!value) return; if ((value >= 0) && (value < 24)) time_info.hour = value; return; } return; } /* Display some simple Immortal-only information to an Immortal. */ void do_iscore( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; char buf[MAX_STRING_LENGTH]; char buf1[MAX_STRING_LENGTH]; extern bool wizlock; extern int numlock; char arg1[MAX_INPUT_LENGTH]; int col = 0; int cmd; if ( !authorized( ch, "iscore" ) ) return; argument = one_argument( argument, arg1 ); if ( arg1[0] == '\0' ) victim = ch; else { if ( !( victim = get_char_world( ch, arg1) ) ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( IS_NPC( victim ) ) { send_to_char( "Not on NPC's.\n\r", ch ); return; } } sprintf( buf, "Bamfin: %s\n\r", (victim->pcdata != NULL && victim->pcdata->bamfin[0] != '\0') ? victim->pcdata->bamfin : "Not changed/Switched." ); send_to_char( buf, ch ); sprintf( buf, "Bamfout: %s\n\r", (victim->pcdata != NULL && victim->pcdata->bamfout[0] != '\0' ) ? victim->pcdata->bamfout : "Not changed/Switched." ); send_to_char( buf, ch ); /* * imortall skills listing added by Canth (phule@xs4all.nl) */ sprintf( buf, "Imortal skills set for %s:\n\r", victim->name ); send_to_char( buf, ch ); buf1[0] = '\0'; for ( cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++ ) { if( cmd_table[cmd].level < LEVEL_HERO || str_infix( cmd_table[cmd].name, victim->pcdata->immskll ) ) continue; sprintf( buf, "%-10s", cmd_table[cmd].name ); strcat( buf1, buf ); if( ++col % 8 == 0 ) strcat( buf1, "\n\r" ); } if( col % 8 != 0 ) strcat( buf1, "\n\r" ); send_to_char( buf1, ch ); if ( wizlock ) send_to_char( "The Mud is currently Wizlocked.\n\r", ch ); /* * Numlock check added by Canth (phule@xs4all.nl) */ if ( numlock ) { sprintf( buf, "The Mud is currently Numlocked at level %d.\n\r", numlock ); send_to_char( buf, ch ); } return; } void do_smite( CHAR_DATA *ch, char *argument ) /* by Garion */ { OBJ_DATA *obj; CHAR_DATA *victim; char arg[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; if ( !authorized( ch, "smite" ) ) return; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char("Smite whom?\n\r", ch ); return; } if ( ( victim = get_char_room( ch, arg ) ) == NULL ) { send_to_char("That person is not here.\n\r", ch); return; } if ( victim == ch ) { send_to_char("Take it somewhere else, Jack.\n\r", ch ); return; } if ( !IS_NPC( victim ) && get_trust(victim) > get_trust(ch) ) { send_to_char("You failed.\n\r", ch); act("$n tried to smite you.", ch, NULL, victim, TO_VICT ); return; } if ( victim->fighting != NULL ) stop_fighting( victim, TRUE ); sprintf(buf," * W W H H AA M M !! * \n\r"); strcat(buf, " ***** W W W HHHH AAAA M M M !! ***** \n\r"); strcat(buf, " * W W H H A A M M !! * \n\r"); strcat( buf, "\n\r" ); send_to_char( buf, victim ); act("$n raises $s hand and smites you!", ch, NULL, victim, TO_VICT ); act("$n raises $s hand and smites $N!", ch, NULL, victim, TO_NOTVICT ); act("You raise your hand and smite $N!", ch, NULL, victim, TO_CHAR ); if ( victim->hit >= 2 ) victim->hit /= 2; if ( ( obj = get_eq_char( victim, WEAR_FEET ) ) != NULL ) { obj_from_char( obj ); send_to_char("You are blown out of your shoes and right onto your ass!\n\r", victim ); act("$N is blown out of $s shoes and right onto $s ass!", ch, NULL, victim, TO_NOTVICT ); act("$N is blown out of $s shoes and right onto $s ass!", ch, NULL, victim, TO_CHAR ); obj_to_room( obj, victim->in_room ); } else { send_to_char("You are knocked on your ass!\n\r", victim ); act("$N is knocked on his ass!", ch, NULL, victim, TO_NOTVICT ); act("$N is knocked on his ass!", ch, NULL, victim, TO_CHAR ); } victim->position = POS_RESTING; return; } void do_dog( CHAR_DATA *ch, char *argument ) { /* A real silly command which switches the (mortal) victim into * a mob. As the victim is mortal, they won't be able to use * return ;P So will have to be released by someone... * -S- */ ROOM_INDEX_DATA *location; MOB_INDEX_DATA *pMobIndex; CHAR_DATA *mob; CHAR_DATA *victim; if ( !authorized( ch, "dog" ) ) return; if ( argument[0] == '\0' ) { send_to_char( "Turn WHO into a little doggy?\n\r", ch ); return; } if ( ( victim = get_char_world( ch, argument ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( IS_NPC(victim) ) { send_to_char( "Cannot do this to mobs, only pcs.\n\r",ch); return; } if ( ( pMobIndex = get_mob_index( MOB_VNUM_DOGGY ) ) == NULL ) { send_to_char( "Couldn't find the doggy's vnum!!\n\r", ch ); return; } if ( victim->desc == NULL ) { send_to_char( "Already switched, like.\n\r", ch ); return; } if ( get_trust(victim) >= get_trust(ch) ) { send_to_char( "You cannot dog your peer nor your superior.\n\r", ch ); return; } mob = create_mobile( pMobIndex ); location = victim->in_room; /* Remember where to load doggy! */ char_from_room( victim ); char_to_room( victim, get_room_index( ROOM_VNUM_LIMBO ) ); char_to_room( mob, location ); /* Instead of calling do switch, just do the relevant bit here */ victim->desc->character = mob; victim->desc->original = victim; mob->desc = victim->desc; victim->desc = NULL; act( "$n is suddenly turned into a small doggy!!", victim, NULL, NULL, TO_ROOM ); send_to_char( "You suddenly turn into a small doggy!", victim ); send_to_char( "Ok.\n\r", ch ); return; } /* Idea from Talen of Vego's do_where command */ void do_owhere( CHAR_DATA *ch, char *argument ) { OBJ_DATA *obj; OBJ_DATA *in_obj; CHAR_DATA *rch; char buf [ MAX_STRING_LENGTH ]; char buf1 [ MAX_STRING_LENGTH*6 ]; char arg [ MAX_INPUT_LENGTH ]; int obj_counter = 1; bool found = FALSE; rch = get_char( ch ); if ( !authorized( rch, "owhere" ) ) return; one_argument( argument, arg ); if( arg[0] == '\0' ) { send_to_char( "Syntax: owhere <object>.\n\r", ch ); return; } else { buf1[0] = '\0'; for ( obj = object_list; obj; obj = obj->next ) { if ( !can_see_obj( ch, obj ) || !is_name( arg, obj->name ) ) continue; found = TRUE; for ( in_obj = obj; in_obj->in_obj; in_obj = in_obj->in_obj ) ; if ( in_obj->carried_by ) { if ( !can_see( ch, in_obj->carried_by ) ) continue; sprintf( buf, "[%2d] %s carried by %s at [%4d].\n\r", obj_counter, obj->short_descr, PERS( in_obj->carried_by, ch ), in_obj->carried_by->in_room->vnum ); } else { sprintf( buf, "[%2d] %s in %s at [%4d].\n\r", obj_counter, obj->short_descr, ( !in_obj->in_room ) ? "somewhere" : in_obj->in_room->name, ( !in_obj->in_room ) ? 0 : in_obj->in_room->vnum ); } obj_counter++; buf[0] = UPPER( buf[0] ); strcat( buf1, buf ); /* Only see the first 101 */ if ( obj_counter > 100 ) break; } send_to_char( buf1, ch ); } if ( !found ) send_to_char( "Nothing like that in hell, earth, or heaven.\n\r" , ch ); return; } void do_numlock( CHAR_DATA *ch, char *argument ) /*By Globi*/ { CHAR_DATA *rch; char buf [ MAX_STRING_LENGTH ]; char arg1 [ MAX_INPUT_LENGTH ]; extern int numlock; int temp; rch = get_char( ch ); if ( !authorized( rch, "numlock" ) ) return; one_argument( argument, arg1 ); temp = atoi( arg1 ); if ( arg1[0] == '\0' ) /* Prints out the current value */ { sprintf( buf, "Current numlock setting is: %d.\n\r", numlock ); send_to_char( buf, ch ); return; } if ( ( temp < 0 ) || ( temp > LEVEL_HERO ) ) { sprintf( buf, "Level must be between 0 and %d.\n\r", LEVEL_HERO ); send_to_char( buf, ch ); return; } numlock = temp; /* Only set numlock if arg supplied and within range */ if ( numlock != 0 ) { sprintf( buf, "Game numlocked to levels %d and below.\n\r", numlock ); send_to_char( buf, ch ); } else send_to_char( "Game now open to all levels.\n\r", ch ); return; } void do_newlock( CHAR_DATA *ch, char *argument ) { CHAR_DATA *rch; extern int numlock; char buf [ MAX_STRING_LENGTH ]; rch = get_char( ch ); if ( !authorized( rch, "newlock" ) ) return; if ( numlock != 0 && get_trust( ch ) < L_SEN ) { send_to_char( "You may not change the current numlock setting\n\r", ch ); sprintf( buf, "Game numlocked to levels %d and below.\n\r", numlock ); send_to_char( buf, ch ); return; } if ( numlock != 0 ) { sprintf( buf, "Game numlocked to levels %d and below.\n\r", numlock ); send_to_char( buf, ch ); send_to_char( "Changing to: ", ch ); } numlock = 1; send_to_char( "Game locked to new characters.\n\r", ch ); return; } void do_sstime( CHAR_DATA *ch, char *argument ) { CHAR_DATA *rch; extern time_t down_time; extern time_t warning1; extern time_t warning2; extern bool Reboot; char buf [ MAX_STRING_LENGTH ]; char arg1 [ MAX_INPUT_LENGTH ]; int number; rch = get_char( ch ); if ( !authorized( rch, "sstime" ) ) return; smash_tilde( argument ); argument = one_argument( argument, arg1 ); if ( !str_cmp( arg1, "reboot" ) ) { Reboot = !Reboot; sprintf( buf, "Reboot is %s.\n\r", Reboot ? "on" : "off" ); send_to_char( buf, ch ); return; } number = atoi( arg1 ); if ( arg1[0] == '\0' || !is_number( arg1 ) || number < 0 ) { send_to_char( "Syntax: sstime <value>/reboot\n\r", ch ); send_to_char( "\n\r", ch ); send_to_char( "Value is number of minutes till reboot/shutdown.", ch ); send_to_char( " Or 0 to turn off.\n\r", ch ); send_to_char( "Reboot will toggle reboot on or off.\n\r", ch ); send_to_char( "\n\r", ch ); if ( down_time > 0 ) { sprintf( buf, "1st warning: %d minutes (%d seconds).\n\r", UMAX( ( (int) warning1 - (int) current_time ) / 60, 0 ), UMAX( ( (int) warning1 - (int) current_time ), 0 ) ); send_to_char( buf, ch ); sprintf( buf, "2nd warning: %d minutes (%d seconds).\n\r", UMAX( ( (int) warning2 - (int) current_time ) / 60, 0 ), UMAX( ( (int) warning2 - (int) current_time ), 0 ) ); send_to_char( buf, ch ); sprintf( buf, "%s%d minutes (%d seconds).\n\r", Reboot ? "Reboot: " : "Shutdown: ", UMAX( ( (int) down_time - (int) current_time ) / 60, 0 ), UMAX( ( (int) down_time - (int) current_time ), 0 ) ); send_to_char( buf, ch ); } else send_to_char( "Automatic reboot/shutdown: off.\n\r", ch ); return; } /* Set something */ if ( number > 0 ) { down_time = current_time + ( number * 60 ); if ( number < 6 ) { warning2 = down_time - 150; warning1 = warning2 - 75; } else { warning2 = down_time - 150; warning1 = warning2 - 150; } sprintf( buf, "%s will be in %d minutes (%d seconds).\n\r", Reboot ? "Reboot" : "Shutdown", ( (int) down_time - (int) current_time ) / 60, ( (int) down_time - (int) current_time ) ); send_to_char( buf, ch ); sprintf( buf, "1st Warning will be in %d minutes (%d seconds).\n\r", ( (int) warning1 - (int) current_time ) / 60, ( (int) warning1 - (int) current_time ) ); send_to_char( buf, ch ); sprintf( buf, "2nd Warning will be in %d minutes (%d seconds).\n\r", ( (int) warning2 - (int) current_time ) / 60, ( (int) warning2 - (int) current_time ) ); send_to_char( buf, ch ); } else { down_time = 0; sprintf( buf, "Auto%s is now off.\n\r", Reboot ? "reboot" : "shutdown" ); send_to_char( buf, ch ); } return; } /* * Modifications to old imtlset by: * Canth (phule@xs4all.nl) * Vego (v942429@si.hhs.nl) */ void do_imtlset( CHAR_DATA *ch, char *argument ) { CHAR_DATA *rch; CHAR_DATA *victim; char arg1 [ MAX_INPUT_LENGTH ]; char buf [ MAX_STRING_LENGTH ]; char buf1 [ MAX_STRING_LENGTH ]; char *buf2; char *buf3 = NULL; char *skill; int cmd; int col = 0; int i = 0; rch = get_char( ch ); if ( !authorized( rch, "imtlset" ) ) return; argument = one_argument( argument, arg1 ); if ( arg1[0] == '\0' ) { send_to_char( "Syntax: imtlset <victim> +|- <immortal skill>\n\r", ch ); send_to_char( "or: imtlset <victim> +|- all\n\r", ch ); send_to_char( "or: imtlset <victim>\n\r", ch ); return; } if ( !( victim = get_char_world( rch, arg1 ) ) ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( IS_NPC( victim ) ) { send_to_char( "Not on NPC's.\n\r", ch ); return; } if ( get_trust(rch) <= get_trust(victim) && rch != victim ) { send_to_char( "You may not imtlset your peer nor your superior.\n\r", ch ); return; } if (( rch == victim ) && (rch->level != L_DIR) ) { send_to_char( "You may not set your own immortal skills.\n\r", ch ); return; } if ( argument[0] == '+' || argument[0] == '-' ) { buf[0] = '\0'; smash_tilde( argument ); if ( argument[0] == '+' ) { argument++; if ( !str_cmp( "all", argument ) ) /* * Imtlset <victim> + all by: * Canth (phule@xs4all.nl) */ { for ( cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++ ) { if ( cmd_table[cmd].level > get_trust( rch ) ) continue; if ( cmd_table[cmd].level <= victim->level && cmd_table[cmd].level >= LEVEL_HERO ) { strcat(buf, cmd_table[cmd].name); strcat(buf, " "); } } } else { if ( victim->pcdata->immskll ) strcat( buf, victim->pcdata->immskll ); while ( isspace( *argument ) ) argument++; for ( cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++ ) { if ( cmd_table[cmd].level > get_trust( rch ) ) continue; if ( !str_cmp( argument, cmd_table[cmd].name ) ) break; } if ( cmd_table[cmd].name[0] == '\0' ) { send_to_char("That is not an immskill.\n\r",ch); return; } if ( !str_infix( argument, victim->pcdata->immskll ) ) { send_to_char("That skill has already been set.\n\r",ch); return; } strcat( buf, argument ); strcat( buf, " " ); } } if ( argument[0] == '-' ) { argument++; one_argument( argument, arg1 ); if ( !str_cmp( "all", arg1 ) ) { free_string( victim->pcdata->immskll ); victim->pcdata->immskll = str_dup( "" ); send_to_char( "All immskills have been deleted.\n\r", ch ); return; } else if ( arg1 ) { /* * Cool great imtlset <victim> - <skill> code... * Idea from Canth (phule@xs4all.nl) * Code by Vego (v942429@si.hhs.nl) * Still needs memory improvements.... (I think) */ buf2 = str_dup( victim->pcdata->immskll ); buf3 = buf2; if ( (skill = strstr( buf2, arg1 ) ) == NULL ) { send_to_char( "That person doesn't have that immskill", ch); return; } else { while ( buf2 != skill ) buf[i++] = *(buf2++); while ( !isspace ( *(buf2++) ) ); buf[i] = '\0'; strcat ( buf, buf2 ); } } else { send_to_char ( "That's not an immskill\n\r", ch ); return; } } free_string( buf3 ); skill = buf2 = buf3 = NULL; free_string( victim->pcdata->immskll ); victim->pcdata->immskll = str_dup( buf ); } sprintf( buf, "Immortal skills set for %s:\n\r", victim->name ); send_to_char( buf, ch ); buf1[0] = '\0'; for ( cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++ ) { if ( cmd_table[cmd].level < LEVEL_HERO || str_infix( cmd_table[cmd].name, victim->pcdata->immskll ) ) continue; sprintf( buf, "%-10s", cmd_table[cmd].name ); strcat( buf1, buf ); if ( ++col % 8 == 0 ) strcat( buf1, "\n\r" ); } if ( col % 8 != 0 ) strcat( buf1, "\n\r" ); send_to_char( buf1, ch ); return; } /* ======================================================================== */ /* Show all connected user sockets */ /* buf set to 256*80 (256 is max connections, 80 chars per line) */ /* ======================================================================== */ void do_users( CHAR_DATA *ch, char *arg ) { DESCRIPTOR_DATA *d; CHAR_DATA *wch; char buf[21000]; int count= 0; if ( !authorized( ch, "users" ) ) return; buf[0] = '\0'; /* Show all descriptors, even if character not assigned yet. */ /* --------------------------------------------------------- */ for ( d= descriptor_list; d; d= d->next ) { wch = d->original ? d->original : d->character; if ( ( arg[0] == '\0' && ( wch == NULL || can_see( ch, wch ) ) ) || ( arg[0] != '\0' && wch && is_name( arg, wch->name ) ) ) { count++; sprintf( buf + strlen(buf), "[%3d %2d] %s@%s\n\r", d->descriptor, d->connected, wch ? wch->name : "(none)", d->host ); } } /* Status messages */ /* --------------- */ if ( count == 0 ) { sprintf( buf, "You didn't find any user with the name %s.\n\r", arg ); send_to_char( buf, ch); } else { sprintf( buf + strlen(buf), "%d connections.\n\r", count ); send_to_char( buf, ch ); } } void do_notestat( CHAR_DATA *ch, char *argument ) /* notestat by Garion */ { char buf1[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; NOTE_DATA *note; int vnum; if ( !authorized( ch, "notestat" ) ) return; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char("Notestat whom?\n\r", ch); return; } if ( ( victim = get_char_world( ch, arg ) ) == NULL ) { send_to_char("There's no such person Jack.\n\r", ch); return; } if ( get_trust(victim) >= get_trust(ch) ) { send_to_char("You may not notestat your peer nor your superior.\n\r", ch ); return; } buf1[0] = '\0'; buf2[0] = '\0'; vnum = 0; for ( note = note_list; note != NULL; note = note->next ) { if ( is_note_to( victim, note ) ) { sprintf( buf1, "[%3d%s] %s: %s\n\r", vnum, ( note->date_stamp > victim->last_note && str_cmp( note->sender, victim->name ) ) ? "N" : " ", note->sender, note->subject ); strcat(buf2, buf1 ); vnum++; } } send_to_char( buf2, ch ); return; } void do_wizpwd( CHAR_DATA *ch, char *argument ) { char *pArg; char *pwdnew; char *p; CHAR_DATA *victim; char arg1 [ MAX_INPUT_LENGTH ]; char arg2 [ MAX_INPUT_LENGTH ]; char cEnd; if ( IS_NPC( ch ) ) return; if ( !authorized( ch, "wizpwd" ) ) return; one_argument(argument, arg1); if ( arg1[0] == '\0' ) { send_to_char("Wizpwd whom ??\n\r", ch); return; } if ( ( victim = get_char_world( ch, arg1 ) ) == NULL ) { send_to_char("That person isn't logged on.\n\r", ch); return; } if ( IS_NPC( victim ) ) { send_to_char("Not on NPC's.\n\r", ch); return; } /* * Level check added by Canth (phule@xs4all.nl) */ if ( get_trust(victim) >= get_trust(ch) ) { send_to_char("You may not wizpwd your peer nor your superior.\n\r",ch); return; } /* * Can't use one_argument here because it smashes case. * So we just steal all its code. Bleagh. */ pArg = arg1; while ( isspace( *argument ) ) argument++; cEnd = ' '; if ( *argument == '\'' || *argument == '"' ) cEnd = *argument++; while ( *argument != '\0' ) { if ( *argument == cEnd ) { argument++; break; } *pArg++ = *argument++; } *pArg = '\0'; pArg = arg2; while ( isspace( *argument ) ) argument++; cEnd = ' '; if ( *argument == '\'' || *argument == '"' ) cEnd = *argument++; while ( *argument != '\0' ) { if ( *argument == cEnd ) { argument++; break; } *pArg++ = *argument++; } *pArg = '\0'; *argument = '\0'; if ( arg1[0] == '\0' || arg2[0] == '\0' ) { send_to_char( "Syntax: wizpwd player newpassword.\n\r", ch ); return; } /* * No tilde allowed because of player file format. */ pwdnew = crypt( arg2, victim->name ); for ( p = pwdnew; *p != '\0'; p++ ) { if ( *p == '~' ) { send_to_char( "New password not acceptable, try again.\n\r", ch ); return; } } free_string( victim->pcdata->pwd ); victim->pcdata->pwd = str_dup( pwdnew ); /* * save_char_obj changed from ch to victim by Canth (phule@xs4all.nl) */ save_char_obj( victim ); send_to_char( "Ok.\n\r", ch ); return; } /* RT set replaces sset, mset, oset, rset and lset */ void do_set( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; argument = one_argument(argument,arg); if (arg[0] == '\0') { send_to_char("Syntax:\n\r",ch); send_to_char(" set mob <name> <field> <value>\n\r",ch); send_to_char(" set obj <name> <field> <value>\n\r",ch); send_to_char(" set room <room> <field> <value>\n\r",ch); send_to_char(" set skill <name> <spell or skill> <value>\n\r",ch); send_to_char(" set lang <name> <language> <value>\n\r",ch); return; } if (!str_prefix(arg,"mobile") || !str_prefix(arg,"character")) { do_mset(ch,argument); return; } if (!str_prefix(arg,"skill") || !str_prefix(arg,"spell")) { do_sset(ch,argument); return; } if (!str_prefix(arg,"language")) { do_lset(ch,argument); return; } if (!str_prefix(arg,"object")) { do_oset(ch,argument); return; } if (!str_prefix(arg,"room")) { do_rset(ch,argument); return; } /* echo syntax */ do_set(ch,""); } /* RT to replace the 3 stat commands */ /* Maniac added lstat */ void do_stat ( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; char *string; OBJ_DATA *obj; ROOM_INDEX_DATA *location; CHAR_DATA *victim; string = one_argument(argument, arg); if ( arg[0] == '\0') { send_to_char("Syntax:\n\r",ch); send_to_char(" stat <name>\n\r",ch); send_to_char(" stat obj <name>\n\r",ch); send_to_char(" stat mob <name>\n\r",ch); send_to_char(" stat room <number>\n\r",ch); send_to_char(" stat lang <name>\n\r",ch); return; } if (!str_cmp(arg,"room")) { do_rstat(ch,string); return; } if (!str_cmp(arg,"obj")) { do_ostat(ch,string); return; } if (!str_cmp(arg, "lang") || !str_cmp(arg, "language")) { do_lstat(ch, string); return; } if(!str_cmp(arg,"char") || !str_cmp(arg,"mob")) { do_mstat(ch,string); return; } /* do it the old way */ obj = get_obj_world(ch,argument); if (obj != NULL) { do_ostat(ch,argument); return; } victim = get_char_world(ch,argument); if (victim != NULL) { do_mstat(ch,argument); return; } location = find_location(ch,argument); if (location != NULL) { do_rstat(ch,argument); return; } send_to_char("Nothing by that name found anywhere.\n\r",ch); } /* ofind and mfind replaced with vnum, vnum skill also added */ void do_vnum(CHAR_DATA *ch, char *argument) { char arg[MAX_INPUT_LENGTH]; char *string; string = one_argument(argument,arg); if (arg[0] == '\0') { send_to_char("Syntax:\n\r",ch); send_to_char(" vnum obj <name>\n\r",ch); send_to_char(" vnum mob <name>\n\r",ch); send_to_char(" vnum skill <skill or spell>\n\r",ch); return; } if (!str_cmp(arg,"obj")) { do_ofind(ch,string); return; } if (!str_cmp(arg,"mob") || !str_cmp(arg,"char")) { do_mfind(ch,string); return; } if (!str_cmp(arg,"skill") || !str_cmp(arg,"spell")) { do_slookup(ch,string); return; } /* do both */ do_mfind(ch,argument); do_ofind(ch,argument); } void do_string( CHAR_DATA *ch, char *argument ) { char type [MAX_INPUT_LENGTH]; char arg1 [MAX_INPUT_LENGTH]; char arg2 [MAX_INPUT_LENGTH]; char arg3 [MAX_INPUT_LENGTH]; CHAR_DATA *victim; OBJ_DATA *obj; if ( !authorized( ch, "string" ) ) return; smash_tilde( argument ); argument = one_argument( argument, type ); argument = one_argument( argument, arg1 ); argument = one_argument( argument, arg2 ); strcpy( arg3, argument ); if (type[0]=='\0' || arg1[0]=='\0' || arg2[0]=='\0' || arg3[0]=='\0') { send_to_char("Syntax:\n\r",ch); send_to_char(" string char <name> <field> <string>\n\r",ch); send_to_char(" fields: name short long desc title spec game\n\r",ch); send_to_char(" string obj <name> <field> <string>\n\r",ch); send_to_char(" fields: name short long extended\n\r",ch); return; } if (!str_prefix(type,"character") || !str_prefix(type,"mobile")) { if ( ( victim = get_char_world( ch, arg1 ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } /* string something */ if ( !str_prefix( arg2, "name" ) ) { if ( !IS_NPC(victim) ) { send_to_char( "Not on PC's.\n\r", ch ); return; } free_string( victim->name ); victim->name = str_dup( arg3 ); return; } if ( !str_prefix( arg2, "description" ) ) { free_string(victim->description); victim->description = str_dup(arg3); return; return; } if ( !str_prefix( arg2, "short" ) ) { free_string( victim->short_descr ); victim->short_descr = str_dup( arg3 ); return; } if ( !str_prefix( arg2, "long" ) ) { free_string( victim->long_descr ); strcat(arg3,"\n\r"); victim->long_descr = str_dup( arg3 ); return; } if ( !str_prefix( arg2, "title" ) ) { if ( IS_NPC(victim) ) { send_to_char( "Not on NPC's.\n\r", ch ); return; } set_title( victim, arg3 ); return; } if ( !str_prefix( arg2, "spec" ) ) { if ( !IS_NPC(victim) ) { send_to_char( "Not on PC's.\n\r", ch ); return; } if ( ( victim->spec_fun = spec_lookup( arg3 ) ) == 0 ) { send_to_char( "No such spec fun.\n\r", ch ); return; } return; } if ( !str_prefix( arg2, "game" ) ) { if ( !IS_NPC(victim) ) { send_to_char( "Not on PC's.\n\r", ch ); return; } if ( ( victim->game_fun = game_lookup( arg3 ) ) == 0 ) { send_to_char( "No such game fun.\n\r", ch ); return; } return; } } if (!str_prefix(type,"object")) { /* string an obj */ if ( ( obj = get_obj_world( ch, arg1 ) ) == NULL ) { send_to_char( "Nothing like that in heaven or earth.\n\r", ch ); return; } if ( !str_prefix( arg2, "name" ) ) { free_string( obj->name ); obj->name = str_dup( arg3 ); return; } if ( !str_prefix( arg2, "short" ) ) { free_string( obj->short_descr ); obj->short_descr = str_dup( arg3 ); return; } if ( !str_prefix( arg2, "long" ) ) { free_string( obj->description ); obj->description = str_dup( arg3 ); return; } if ( !str_prefix( arg2, "ed" ) || !str_prefix( arg2, "extended")) { EXTRA_DESCR_DATA *ed; argument = one_argument( argument, arg3 ); if ( argument == NULL ) { send_to_char( "Syntax: oset <object> ed <keyword> <string>\n\r", ch ); return; } strcat(argument,"\n\r"); if ( extra_descr_free == NULL ) { ed = alloc_perm( sizeof(*ed) ); } else { ed = extra_descr_free; extra_descr_free = ed->next; } ed->keyword = str_dup( arg3 ); ed->description = str_dup( argument ); ed->next = obj->extra_descr; obj->extra_descr = ed; return; } } /* echo bad use message */ do_string(ch,""); } void do_setkill( CHAR_DATA *ch, char *argument ) { CHAR_DATA *rch; CHAR_DATA *victim; char arg1 [ MAX_INPUT_LENGTH ]; char arg2 [ MAX_INPUT_LENGTH ]; rch = get_char( ch ); if ( !authorized( rch, "setkill" ) ) return; argument = one_argument( argument, arg1 ); argument = one_argument( argument, arg2 ); if ( arg1[0] == '\0' || arg2[0] == '\0' ) { send_to_char( "Syntax: setkill <character> <killer|thief>.\n\r", ch ); return; } if ( !( victim = get_char_world( ch, arg1 ) ) ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( IS_NPC( victim ) ) { send_to_char( "Not on NPC's.\n\r", ch ); return; } if ( !str_cmp( arg2, "killer" ) ) { if (!IS_SET( victim->act, PLR_KILLER ) ) { SET_BIT( victim->act, PLR_KILLER ); send_to_char( "Killer flag set.\n\r", ch ); send_to_char( "You are a KILLER.\n\r", victim ); } return; } if ( !str_cmp( arg2, "thief" ) ) { if (!IS_SET( victim->act, PLR_THIEF ) ) { SET_BIT( victim->act, PLR_THIEF ); send_to_char( "Thief flag set.\n\r", ch ); send_to_char( "You are a THIEF.\n\r", victim ); } return; } send_to_char( "Syntax: setkill <character> <killer|thief>.\n\r", ch ); return; } void do_pwhere( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; DESCRIPTOR_DATA *d; char buf [ MAX_STRING_LENGTH ]; if ( !authorized( ch, "pwhere" ) ) return; send_to_char( "Player locations:\n\r", ch ); for ( d = descriptor_list; d; d = d->next ) { if ( d->connected == CON_PLAYING && ( victim = d->character ) && !IS_NPC( victim ) && victim->in_room ) { sprintf( buf, "%-28s %d %s\n\r", victim->name, victim->in_room->vnum, victim->in_room->name ); send_to_char( buf, ch ); } } } /* Expand the name of a character into a string that identifies THAT character within a room. E.g. the second 'guard' -> 2. guard */ const char * name_expand (CHAR_DATA *ch) { int count = 1; CHAR_DATA *rch; char name[MAX_INPUT_LENGTH]; /* HOPEFULLY no mob has a name longer than THAT */ static char outbuf[MAX_INPUT_LENGTH]; if (!IS_NPC(ch)) return ch->name; one_argument (ch->name, name); /* copy the first word into name */ if (!name[0]) /* weird mob .. no keywords */ { strcpy (outbuf, ""); /* Do not return NULL, just an empty buffer */ return outbuf; } for (rch = ch->in_room->people; rch && (rch != ch);rch = rch->next_in_room) if (is_name (name, rch->name)) count++; sprintf (outbuf, "%d.%s", count, name); return outbuf; } /* * For by Erwin S. Andreasen (4u2@aabc.dk) */ void do_for (CHAR_DATA *ch, char *argument) { char range[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; bool fGods = FALSE, fMortals = FALSE, fMobs = FALSE, fEverywhere = FALSE, found; ROOM_INDEX_DATA *room, *old_room; CHAR_DATA *p, *p_next; int i; if ( !authorized( ch, "for" ) ) return; argument = one_argument (argument, range); if (!range[0] || !argument[0]) /* invalid usage? */ { do_help (ch, "for"); return; } if (!str_prefix("quit", argument)) { send_to_char ("Are you trying to crash the MUD or something?\n\r",ch); return; } if (!str_cmp (range, "all")) { fMortals = TRUE; fGods = TRUE; } else if (!str_cmp (range, "gods")) fGods = TRUE; else if (!str_cmp (range, "mortals")) fMortals = TRUE; else if (!str_cmp (range, "mobs")) fMobs = TRUE; else if (!str_cmp (range, "everywhere")) fEverywhere = TRUE; else do_help (ch, "for"); /* show syntax */ /* do not allow # to make it easier */ if (fEverywhere && strchr (argument, '#')) { send_to_char ("Cannot use FOR EVERYWHERE with the # thingie.\n\r",ch); return; } if (strchr (argument, '#')) /* replace # ? */ { for (p = char_list; p ; p = p_next) { p_next = p->next; /* In case someone DOES try to AT MOBS SLAY # */ found = FALSE; if (!(p->in_room) || room_is_private(p->in_room) || (p == ch)) continue; if (IS_NPC(p) && fMobs) found = TRUE; else if (!IS_NPC(p) && p->level >= LEVEL_IMMORTAL && fGods) found = TRUE; else if (!IS_NPC(p) && p->level < LEVEL_IMMORTAL && fMortals) found = TRUE; /* It looks ugly to me.. but it works :) */ if (found) /* p is 'appropriate' */ { char *pSource = argument; /* head of buffer to be parsed */ char *pDest = buf; /* parse into this */ while (*pSource) { if (*pSource == '#') /* Replace # with name of target */ { const char *namebuf = name_expand (p); if (namebuf) /* in case there is no mob name ?? */ while (*namebuf) /* copy name over */ *(pDest++) = *(namebuf++); pSource++; } else *(pDest++) = *(pSource++); } /* while */ *pDest = '\0'; /* Terminate */ /* Execute */ old_room = ch->in_room; char_from_room (ch); char_to_room (ch,p->in_room); interpret (ch, buf); char_from_room (ch); char_to_room (ch,old_room); } /* if found */ } /* for every char */ } else /* just for every room with the appropriate people in it */ { for (i = 0; i < MAX_KEY_HASH; i++) /* run through all the buckets */ for (room = room_index_hash[i] ; room ; room = room->next) { found = FALSE; /* Anyone in here at all? */ if (fEverywhere) /* Everywhere executes always */ found = TRUE; else if (!room->people) /* Skip it if room is empty */ continue; /* Check if there is anyone here of the requried type */ /* Stop as soon as a match is found or there are no more ppl in room */ for (p = room->people; p && !found; p = p->next_in_room) { if (p == ch) /* do not execute on oneself */ continue; if (IS_NPC(p) && fMobs) found = TRUE; else if (!IS_NPC(p) && (p->level >= LEVEL_IMMORTAL) && fGods) found = TRUE; else if (!IS_NPC(p) && (p->level <= LEVEL_IMMORTAL) && fMortals) found = TRUE; } /* for everyone inside the room */ if (found && !room_is_private(room)) /* Any of the required type here AND room not private? */ { /* This may be ineffective. Consider moving character out of old_room once at beginning of command then moving back at the end. This however, is more safe? */ old_room = ch->in_room; char_from_room (ch); char_to_room (ch, room); interpret (ch, argument); char_from_room (ch); char_to_room (ch, old_room); } /* if found */ } /* for every room in a bucket */ } /* if strchr */ } /* do_for */ /* * Rename by Erwin S Andreasen (4u2@aabc.dk) */ /* * do_rename renames a player to another name. * PCs only. Previous file is deleted, if it exists. * Char is then saved to new file. * New name is checked against std. checks, existing offline players and * online players. * .gz files are checked for too, just in case. */ bool check_parse_name (char* name); /* comm.c */ char *initial( const char *str ); /* comm.c */ void do_rename (CHAR_DATA* ch, char* argument) { char old_name[MAX_INPUT_LENGTH], new_name[MAX_INPUT_LENGTH], strsave [MAX_INPUT_LENGTH]; CHAR_DATA* victim; FILE* file; if ( !authorized( ch, "rename" ) ) return; argument = one_argument(argument, old_name); /* find new/old name */ one_argument (argument, new_name); /* Trivial checks */ if (!old_name[0]) { send_to_char ("Rename who?\n\r",ch); return; } victim = get_char_world (ch, old_name); if (!victim) { send_to_char ("There is no such a person online.\n\r",ch); return; } if (IS_NPC(victim)) { send_to_char ("You cannot use Rename on NPCs.\n\r",ch); return; } /* allow rename self new_name,but otherwise only lower level */ if ( (victim != ch) && (get_trust (victim) >= get_trust (ch)) ) { send_to_char ("You failed.\n\r",ch); return; } if (!victim->desc || (victim->desc->connected != CON_PLAYING) ) { send_to_char ("This player has lost his link or is inside a pager or the like.\n\r",ch); return; } if (!new_name[0]) { send_to_char ("Rename to what new name?\n\r",ch); return; } /* Insert check for clan here!! */ /* if (victim->clan) { send_to_char ("This player is member of a clan, remove him from there first.\n\r",ch); return; } */ if (!check_parse_name(new_name)) { send_to_char ("The new name is illegal.\n\r",ch); return; } /* First, check if there is a player named that off-line */ #if !defined(machintosh) && !defined(MSDOS) sprintf( strsave, "%s%s%s%s", PLAYER_DIR, initial( new_name ), "/", capitalize( new_name ) ); #else sprintf( strsave, "%s%s", PLAYER_DIR, capitalize( new_name ) ); #endif fclose (fpReserve); /* close the reserve file */ file = fopen (strsave, "r"); /* attempt to to open pfile */ if (file) { send_to_char ("A player with that name already exists!\n\r",ch); fclose (file); fpReserve = fopen( NULL_FILE, "r" ); /* is this really necessary these days? */ return; } fpReserve = fopen( NULL_FILE, "r" ); /* reopen the extra file */ /* Check .gz file ! */ #if !defined(machintosh) && !defined(MSDOS) sprintf( strsave, "%s%s%s%s.gz", PLAYER_DIR, initial( new_name ), "/", capitalize( new_name ) ); #else sprintf( strsave, "%s%s.gz", PLAYER_DIR, capitalize( new_name ) ); #endif fclose (fpReserve); /* close the reserve file */ file = fopen (strsave, "r"); /* attempt to to open pfile */ if (file) { send_to_char ("A player with that name already exists in a compressed file!\n\r",ch); fclose (file); fpReserve = fopen( NULL_FILE, "r" ); return; } fpReserve = fopen( NULL_FILE, "r" ); /* reopen the extra file */ if (get_char_world(ch,new_name)) /* check for playing level-1 non-saved */ { send_to_char ("A player with the name you specified already exists!\n\r",ch); return; } /* Save the filename of the old name */ #if !defined(machintosh) && !defined(MSDOS) sprintf( strsave, "%s%s%s%s", PLAYER_DIR, initial( victim->name ), "/", capitalize( victim->name ) ); #else sprintf( strsave, "%s%s", PLAYER_DIR, capitalize( victim->name ) ); #endif /* Rename the character and save him to a new file */ /* NOTE: Players who are level 1 do NOT get saved under a new name */ free_string (victim->name); victim->name = str_dup (capitalize(new_name)); save_char_obj (victim); /* unlink the old file */ unlink (strsave); /* unlink does return a value.. but we do not care */ /* That's it! */ send_to_char ("Character renamed.\n\r",ch); victim->position = POS_STANDING; /* I am laaazy */ act ("$n has renamed you to $N!",ch,NULL,victim,TO_VICT); } /* get the 'short' name of an area (e.g. MIDGAARD, MIRROR etc. */ /* assumes that the filename saved in the AREA_DATA struct is something like midgaard.are */ char * area_name (AREA_DATA *pArea) { static char buffer[64]; /* short filename */ char *period; assert (pArea != NULL); strncpy (buffer, pArea->filename, 64); /* copy the filename */ period = strchr (buffer, '.'); /* find the period (midgaard.are) */ if (period) /* if there was one */ *period = '\0'; /* terminate the string there (midgaard) */ return buffer; } typedef enum {exit_from, exit_to, exit_both} exit_status; /* depending on status print > or < or <> between the 2 rooms */ void room_pair (ROOM_INDEX_DATA* left, ROOM_INDEX_DATA* right, exit_status ex, char *buffer) { char *sExit; switch (ex) { default: sExit = "??"; break; /* invalid usage */ case exit_from: sExit = "< "; break; case exit_to: sExit = " >"; break; case exit_both: sExit = "<>"; break; } sprintf (buffer, "%5d %-26.26s %s%5d %-26.26s(%-8.8s)\n\r", left->vnum, left->name, sExit, right->vnum, right->name, area_name(right->area) ); } /* for every exit in 'room' which leads to or from pArea but NOT both, print it */ void checkexits (ROOM_INDEX_DATA *room, AREA_DATA *pArea, char* buffer) { char buf[MAX_STRING_LENGTH]; int i; EXIT_DATA *exit; ROOM_INDEX_DATA *to_room; strcpy (buffer, ""); for (i = 0; i < 6; i++) { exit = room->exit[i]; if (!exit) continue; else to_room = exit->to_room; if (to_room) /* there is something on the other side */ if ( (room->area == pArea) && (to_room->area != pArea) ) { /* an exit from our area to another area */ /* check first if it is a two-way exit */ if ( to_room->exit[opposite_dir[i]] && to_room->exit[opposite_dir[i]]->to_room == room ) room_pair (room,to_room,exit_both,buf); /* <> */ else room_pair (room,to_room,exit_to,buf); /* > */ strcat (buffer, buf); } else if ( (room->area != pArea) && (exit->to_room->area == pArea) ) { /* an exit from another area to our area */ if (! (to_room->exit[opposite_dir[i]] && to_room->exit[opposite_dir[i]]->to_room == room ) ) /* two-way exits are handled in the other if */ { room_pair (to_room,room,exit_from,buf); strcat (buffer, buf); } } /* if room->area */ } /* for */ } /* for now, no arguments, just list the current area */ void do_exlist (CHAR_DATA *ch, char * argument) { AREA_DATA* pArea; ROOM_INDEX_DATA* room; int i; char buffer[MAX_STRING_LENGTH]; pArea = ch->in_room->area; /* this is the area we want info on */ for (i = 0; i < MAX_KEY_HASH; i++) /* room index hash table */ for (room = room_index_hash[i]; room != NULL; room = room->next) /* run through all the rooms on the MUD */ { checkexits (room, pArea, buffer); send_to_char (buffer, ch); } }