/
rogue24b3/
rogue24b3/data/
/***************************************************************************
*	ROM 2.4 is copyright 1993-1998 Russ Taylor			   *
*	ROM has been brought to you by the ROM consortium		   *
*	    Russ Taylor (rtaylor@hypercube.org)				   *
*	    Gabrielle Taylor (gtaylor@hypercube.org)			   *
*	    Brian Moore (zump@rom.org)					   *
*	By using this code, you have agreed to follow the terms of the	   *
*	ROM license, in the file Rom24/doc/rom.license			   *
***************************************************************************/

#include <unistd.h>
#include "merc.h"
#include "interp.h"
#include "recycle.h"
#include "tables.h"
#include "lookup.h"
#include "olc.h"
#include "staffcmds.h"

/*
 * Local functions.
 */
ROOM_INDEX_DATA *	find_location	args( ( CHAR_DATA *ch, char *arg ) );
bool write_to_descriptor( int desc, char *txt, int length );

// External functions.
extern char *staff_bits[];

const struct {
    sh_int	state;
    char *	desc;
} socket_table[] = {
 { CON_PLAYING,			"Playing       "},
 { CON_GET_NAME,		"Get Name      "},
 { CON_GET_OLD_PASSWORD,	"Get Old Passwd"},
 { CON_CONFIRM_NEW_NAME,	"Confirm Name  "},
 { CON_GET_NEW_PASSWORD,	"Get New Passwd"},
 { CON_CONFIRM_NEW_PASSWORD,	"Confirm Passwd"},
 { CON_GET_LAST_NAME,		"Get Last Name "},
 { CON_GET_NEW_RACE,		"Get Race      "},
 { CON_GET_NEW_SEX,		"Get Sex       "},
 { CON_GET_NEW_CLASS,		"Get Class     "},
 { CON_GET_ALIGNMENT,		"Get Align     "},
 { CON_CHOOSE_TERM,		"Choose Term   "},
 { CON_DEFAULT_CHOICE,		"Choose Cust   "},
 { CON_GEN_GROUPS,		"Customization "},
 { CON_PICK_WEAPON,		"Choose Weap   "},
 { CON_READ_MOTD,		"Reading MOTD  "},
 { CON_BREAK_CONNECT,		"LinkDead      "},
 { CON_COPYOVER_RECOVER,	"Copyover Recov"},
 { CON_NOTE_TO,			"Note To       "},
 { CON_NOTE_SUBJECT,		"Note Subject  "},
 { CON_NOTE_EXPIRE,		"Note Expire   "},
 { CON_NOTE_TEXT,		"Note Writing  "},
 { CON_NOTE_FINISH,		"Note Finish   "},
 { CON_DISCONNECT,		"Disconnect    "},
 { CON_MENU,			"Main Menu     "},
 { CON_CHPWD_GETOLD,		"ChPwd Get Old "},
 { CON_CHPWD_GETNEW,		"ChPwd Get New "},
 { CON_CHPWD_VERIFY,		"ChPwd Verify  "},
 { CON_DELETE_CONF1,		"Self-Delete 1 "},
 { CON_DELETE_CONF2,		"Self-Delete 2 "},
 { CON_EXDESC,			"Get Descript. "},
 { CON_CLOSE,			"Closing       "},
 { CON_CHANGE_LNAME,		"Get Last Name "},
 { -1,				"\n"		}
};

char *socket_state(int state) {
    sh_int i=0;

    for (i=0; *socket_table[i].desc != '\n'; i++)
        if (socket_table[i].state == state)
            return socket_table[i].desc;
    return "(UNKNOWN)     ";
}

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;
}

struct cat_type cat_table[] ={
 { "none",	CAT_NONE,	"           ", "None"},
 { "coder",	CAT_CODER,	"   Coder   ", "Coder"},
 { "admin",	CAT_ADMIN,	"   Admin   ", "Admin"},
 { "stfadmin",	CAT_STFAD,	"Staff Admin", "Staff Admin"},
 { "secpr",	CAT_SECPR,	"Security/PR", "Security/PR"},
 { "terraform",	CAT_TERRA,	"Terraformer", "Terraformer"},
 { "trainee",	CAT_TRAIN,	"  Trainee  ", "Trainee"},
 { "associate",	CAT_ASSOC,	" Associate ", "Associate"},
 { "quality",	CAT_QUALT,	"  Quality  ", "Quality"},
 { "mission",	CAT_MISSI,	"Mission Ops", "Mission Operator"},
 { "housing",	CAT_HOUSE,	"Housing Dev", "Housing Developer"},
 { "clans",	CAT_CLANS,	" Guild Dev ", "Clan Developer"},
 { "meqref",	CAT_MEQRE,	"MEQ Refiner", "MEQ Refiner"},
 { "relation",	CAT_RELAT,	" Relations ", "Relations"},
 { "olctrain",	CAT_OLCTR,	"OLC Trainee", "OLC Trainee"},
 { "sectrain",	CAT_SECTR,	"Sec Trainee", "Sec Trainee"},
 { "helper",	CAT_HELPE,	"Newbie Help", "Newbie Helper"},
 // Add more above this line.
 { "\n",	-1,             "\n", "\n"},
};

char *get_sh_cat(int cat) {
	int i;

	for (i=0; *cat_table[i].desc != '\n'; i++)
		if (cat_table[i].stflev == cat)
			return cat_table[i].sh_desc;
	return "(UNKNOWN)";
}

char *get_cat(int cat) {
	int i;

	for (i=0; *cat_table[i].desc != '\n'; i++)
		if (cat_table[i].stflev == cat)
			return cat_table[i].desc;
	return " (UNKNOWN) ";
}

ACMD(do_category) {
	char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH];
	SInt32 i=0, c=0;
	CHAR_DATA *vict=NULL;

	if (IS_NPC(ch)) return;
	argument = one_argument(argument, arg1);
	argument = one_argument(argument, arg2);

	if (arg1[0] == '\0' || arg2[0] == '\0' || !STF_FLAGGED(ch, STAFF_ADMIN)) {
		send_to_char("Usage: category <name> <category>\n\r"
			 "Categories available:\n\r",ch);
		for(i=0; *cat_table[i].field != '\n'; i++) {
			c++;
			ch->Send("%-9.9s%s", cat_table[i].field,
			!(c % 6) ? "\n\r" : " ");
		}
		if ((c % 6)) send_to_char("\n\r", ch);
	} else if (!(vict = get_char_world(ch, arg1))) {
		send_to_char("Player not found.\n\r", ch);
	} else if (IS_NPC(vict)) {
		send_to_char("Not on NPCs.\n\r", ch);
	} else if (!IS_STAFF(vict)) {
		send_to_char("Only on staff members.\n\r", ch);
	} else {
		for (i = 0; *cat_table[i].field != '\n'; i++)
			if (is_name(arg2, cat_table[i].field))
				break;
		if (*cat_table[i].field == '\n')
			send_to_char("Invalid choice.\n\r", ch);
		else {
		mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s makes %s %s %s.",
			ch->name, vict->name, AN(cat_table[i].field), cat_table[i].sh_desc);
		GET_CATEGORY(vict) = cat_table[i].stflev;
		ch->Send("You make %s %s %s.\n\r", vict->name, 
		AN(cat_table[i].field), cat_table[i].sh_desc);
		vict->Send("%s makes you %s %s.\n\r", ch->name,
		AN(cat_table[i].field), cat_table[i].sh_desc);
		}
	}
	return;
}

ACMD(do_cname) {
    char	buf[MIL], arg[MIL];

    smash_tilde(argument);
    strcpy(arg, argument);
    strcpy(buf, strip_color(argument));

    if (arg[0] == '\0')
    {
	send_to_char("Sytax: cname <color name>\n\r", ch);
	return;
    }

    if (!str_cmp(arg, "none"))
    {
	free_string(ch->cname);
	ch->cname = str_dup("");
	send_to_char("Color name has been cleared.\n\r",ch);
	return;
    }

    if (str_cmp(ch->name,buf))
    {
	ch->Send("%s is not a valid name.\n\r", buf);
	return;
    }

    check_color_string(argument); // Make sure no ending color codes.
    free_string( ch->cname );
    ch->cname = str_dup(argument);
    ch->Send("Color name set to '%s`n'\n\r", ch->cname);
    return;
}

ACMD(do_immtitle) {
    char buf[MAX_STRING_LENGTH];
    int realsize = 0;

    if (!IS_NPC(ch))
    {
	smash_tilde(argument);

	if (argument[0] == '\0')
	{
	  sprintf(buf,"Your immtitle is: %s\n\r",ch->pcdata->immtitle);
	  send_to_char(buf,ch);
	  send_to_char("To remove your immtitle type: immtitle none\n\r",ch);
	  return;
	}

	if (!str_cmp(argument, "none"))
	{
		free_string(ch->pcdata->immtitle);
		ch->pcdata->immtitle = str_dup("");
		send_to_char("Immtitle removed.\n\r",ch);
		return;
	}

    check_color_string(argument);
    realsize = rstrlen(argument);

    if ((realsize > 11) || (realsize < 11))
    {
	send_to_char("Your title must be 11 characters long.\n\r",ch);
	return;
    }
	free_string(ch->pcdata->immtitle);
	ch->pcdata->immtitle = str_dup(argument);
	sprintf(buf, "Your immtitle is now: %s\n\r",ch->pcdata->immtitle);
	send_to_char(buf,ch);
	}
    return;
}

ACMD(do_immcurse) {
	CHAR_DATA *vict;

	if ((vict = get_char_room(ch, argument)) == NULL)
		send_to_char("Player not found.\n\r",ch);
	else {
		(*skill_table[find_spell(ch,"poison")].spell_fun) ( find_spell(ch,"poison"), ch->level*2, ch, vict,TAR_IGNORE);
		(*skill_table[find_spell(ch,"curse")].spell_fun) ( find_spell(ch,"curse"),ch->level*2, ch, vict,TAR_IGNORE);
		(*skill_table[find_spell(ch,"blind")].spell_fun) ( find_spell(ch,"blind"),ch->level*2, ch, vict,TAR_IGNORE);
		(*skill_table[find_spell(ch,"slow")].spell_fun) ( find_spell(ch,"slow"),ch->level*2, ch, vict,TAR_IGNORE);
		(*skill_table[find_spell(ch,"weaken")].spell_fun) (find_spell(ch,"weaken"), ch->level*2, ch, vict,TAR_IGNORE);
		(*skill_table[find_spell(ch,"plague")].spell_fun) (find_spell(ch,"plague"), ch->level*2, ch, vict,TAR_IGNORE);
		(*skill_table[find_spell(ch,"change")].spell_fun) (find_spell(ch,"change"), ch->level*2, ch, vict,TAR_IGNORE);
		(*skill_table[find_spell(ch,"charm")].spell_fun) ( find_spell(ch,"charm"),ch->level*2, ch, vict,TAR_IGNORE);
	}
	return;
}

char *FOR_USAGE =
	"Usage: for [all/imm/mobs/player/everywhere] [argument]\n\r";

ACMD(do_for) {
    int i;
    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;

    argument = one_argument(argument, range);

    if (!range[0] || !argument[0]) {
	send_to_char(FOR_USAGE, ch);
	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, "imm"))
	fGods = TRUE;
    else if (!str_cmp (range, "player"))
	fMortals = TRUE;
    else if (!str_cmp (range, "mob"))
	fMobs = TRUE;
    else if (!str_cmp (range, "everywhere"))
	fEverywhere = TRUE;
    else
	send_to_char(FOR_USAGE, ch);

    if (fEverywhere && strchr (argument, '#')) {
	send_to_char("Cannot use FOR EVERYWHERE with the # thingie.\n\r",ch);
	return;
    }

    if (strchr (argument, '#')) { 
	for (p = char_list; p != NULL; p = p_next) {
		p_next = p->next;
		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;

		if (found) {
			char *pSource = argument;
			char *pDest = buf;

			while (*pSource) {
				if (*pSource == '#') {
					const char *namebuf = name_expand (p);

					if (namebuf)
						while (*namebuf)
							*(pDest++) = *(namebuf++);

					pSource++;
				} else
					*(pDest++) = *(pSource++);
			}
			*pDest = '\0';

			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);
		}
	}
    } else {
	for (i = 0; i < MAX_KEY_HASH; i++)
		for (room = room_index_hash[i] ; room ; room = room->next) {
			found = FALSE;

			if (fEverywhere)
				found = TRUE;
			else if (!room->people)
				continue;
			for (p = room->people; p != NULL; p = p_next) {
				p_next = p->next_in_room;

				if (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;
			}

			if (found) {
				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);
			}
		}
    }
}

bool check_parse_name(char *name);

ACMD(do_rename) {
    FILE *file;
    CHAR_DATA *victim;
    char old_name[MAX_INPUT_LENGTH], 
	 new_name[MAX_INPUT_LENGTH],
	 strsave [MAX_INPUT_LENGTH];

    argument = one_argument(argument, old_name);
    one_argument(argument, new_name);

    if (!old_name[0]) {
	send_to_char("Rename who?\n\r",ch);
	return;
    }
    if ((victim = get_pc_world(ch, old_name)) == NULL) {
	send_to_char("There is no such a person online.\n\r",ch);
	return;
    }
    if ((victim != ch) && (get_trust(victim) >= get_trust(ch))) {
	send_to_char("You failed.\n\r",ch);
	return;
    }
    if (!victim->desc || (STATE(victim->desc) != CON_PLAYING)) {
	act("$N has lost $S playing status. Please wait.", ch, 0, victim, TO_CHAR);
	return;
    }
    if (!new_name[0]) {
	send_to_char("Rename to what new name?\n\r",ch);
	return;
    }
    if (!check_parse_name(new_name)) {
	send_to_char("The new name is illegal.\n\r",ch);
	return;
    }

    sprintf(strsave, "%s%s", PLAYER_DIR, capitalize(new_name));
    fclose(fpReserve);
    file = fopen(strsave, "r");
    if (file) {
	send_to_char("A player with that name already exists!\n\r",ch);
	fclose(file);
	fpReserve = fopen(NULL_FILE, "r");
	return;
    }
    fpReserve = fopen(NULL_FILE, "r");

    sprintf(strsave, "%s%s.gz", PLAYER_DIR, capitalize(new_name));
    fclose(fpReserve);
    file = fopen(strsave, "r");
    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");

    if (get_char_world(ch,new_name)) {
	send_to_char("A player with the name you specified already exists!\n\r",ch);
	return;
    }

    sprintf(strsave, "%s%s", PLAYER_DIR, capitalize(victim->name));
    free_string(victim->name);
    victim->name = str_dup(capitalize(new_name));

    save_char_obj(victim);
    unlink(strsave);
    victim->position = POS_STANDING;
    send_to_char("Character renamed.\n\r",ch);
    act("$n has renamed you to $N!",ch,NULL,victim,TO_VICT);
}

ACMD(do_vape) {
    CHAR_DATA *victim;
    DESCRIPTOR_DATA *d;
    char strsave[MAX_INPUT_LENGTH], arg[MAX_INPUT_LENGTH];
    static char * const his_her [] = { "its", "his", "her" };
    one_argument(argument, arg);

    if (arg[0] == '\0') {
	send_to_char("Syntax: vape <name> \n\r", ch);
	return;
    }

    if ((victim = get_pc_world(ch, arg)) == NULL) {
	send_to_char("They aren't here.\n\r", ch);
	return;
    }

    if (get_trust(victim) >= get_trust(ch)) {
	send_to_char("You cannot vaporize that person.\n\r",ch);
	return;
    }

    if (is_exact_name(victim->name, IMP_NAME))
	return;

    if (victim->level >= LEVEL_IMMORTAL)
	update_wizlist(victim, 1);

    sprintf(strsave, "%s%s", PLAYER_DIR, capitalize(victim->name));

    info(NULL, 0, 
	"`y[`bINFO`y] %s ceases %s's existance with a wave of %s hand.`n\n\r",
	ch->name, victim->name, his_her[ch->sex]);

    mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s vaporizes %s.", RealName(ch), RealName(victim));

    d = victim->desc;
    extract_char(victim);
    if (d != NULL)
	close_socket(d);
    unlink(strsave); // delete pfile
    return;
}

ACMD(do_pload) {
    DESCRIPTOR_DATA d;
    char name[MAX_INPUT_LENGTH];

    if (argument[0] == '\0') {
	send_to_char("Load who?\n\r", ch);
	return;
    }

    argument[0] = UPPER(argument[0]);
    argument = one_argument(argument, name);

    if (get_pc_world( ch, name ) != NULL) {
	send_to_char( "That person is allready connected!\n\r", ch );
	return;
    }
    if (!load_char_obj(&d, name, FALSE)) {
	send_to_char("Load Who? Are you sure? I cant seem to find them.\n\r",ch);
	return;
    }

    d.character->desc     = NULL;
    d.character->next     = char_list;
    char_list             = d.character;
    d.connected           = CON_PLAYING;
    reset_char(d.character);

    if (d.character->in_room != NULL) {
	char_to_room( d.character, ch->in_room);
    }
    act("You extract $N from the pattern!",ch, NULL, d.character, TO_CHAR);
    act( "$n has pulled $N from the pattern!", ch, NULL, d.character, TO_ROOM);
    mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s loaded player %s.", RealName(ch), RealName(d.character));

    if (d.character->pet != NULL) {
	char_to_room(d.character->pet,d.character->in_room);
	act("$n has entered the game.",d.character->pet,NULL,NULL,TO_ROOM);
    }
}

ACMD(do_punload) {
    CHAR_DATA *victim;
    char who[MAX_INPUT_LENGTH];

    argument = one_argument(argument, who);

    if ((victim = get_pc_world(ch, who)) == NULL) {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if (victim->desc != NULL) {
	send_to_char("I dont think that would be a good idea...\n\r", ch);
	return;
    }

    if (victim->was_in_room != NULL) {
	char_to_room(victim, victim->was_in_room);
	if (victim->pet != NULL)
		char_to_room(victim->pet, victim->was_in_room);
    }

    save_char_obj(victim);
    extract_char(victim);

    act("You release $N back into the pattern!",ch, NULL, victim,TO_CHAR);
    act("$n has released $N back to the Pattern.", ch, NULL, victim, TO_ROOM);
    mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s has unloaded player %s", RealName(ch), RealName(victim));
}

/*
 * Library List - Mendanbar
 * Lists up to 300 items with vnums and descriptions
 */
ACMD(do_liblist) {
    BUFFER		*output;
    char buf1[MAX_STRING_LENGTH];
    char buf2[MAX_STRING_LENGTH];
    int first, last, vnum, found=0;

    argument = one_argument(argument, buf1);
    argument = one_argument(argument, buf2);

    if (!*buf1 || !*buf2) {
	switch(subcmd) {
		case SCMD_RLIST:
			send_to_char("Usage: rlist <begining number> <ending number>\n\r", ch);
			break;
		case SCMD_OLIST:
			send_to_char("Usage: olist <begining number> <ending number>\n\r", ch);
			break;
		case SCMD_MLIST:
			send_to_char("Usage: mlist <begining number> <ending number>\n\r", ch);
			break;
		case SCMD_TLIST:
			send_to_char("Usage: tlist <begining number> <ending number>\n\r", ch);
			break;
		default:
			mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: invalid SCMD passed to do_liblist! (SCMD = %d)", subcmd);
			break;
	}
	return;
    }

    first = atoi(buf1);
    last  = atoi(buf2);

    if ((first < 0) || (first > 99999) || (last < 0) || (last > 99999)) {
	send_to_char("Values must be between 0 and 99999.\n\r", ch);
	return;
    }
    if (first >= last) {
	send_to_char("Second value must be greater than first.\n\r", ch);
	return;
    }
    if ((first+300) <= last) {
	send_to_char("May not exceed 300 items, try using a smaller end number!\n\r" ,ch);
	return;
    }

    output = new_buf();

    switch(subcmd) {
	case SCMD_RLIST: {
		ROOM_INDEX_DATA *nr;
		sprintf(buf1, "Room List From Vnum %d to %d\n\r", first, last);
		add_buf(output, buf1);
		for (vnum = first; vnum <= last; vnum++) {
			if ((nr = get_room_index(vnum))) {
				sprintf(buf1, "%3d. [%5d] (%3d) %s\n\r",
					++found, nr->vnum, nr->area->vnum,
					nr->name ? nr->name : "<ERROR>");
				add_buf(output, buf1);
			}
		}
		break;
	}
	case SCMD_OLIST: {
		OBJ_INDEX_DATA *nr;
		sprintf(buf1, "Object List From Vnum %d to %d\n\r", first, last);
		add_buf(output, buf1);
		for (vnum = first; vnum <= last; vnum++) {
			if ((nr = get_obj_index(vnum))) {
				sprintf(buf1, "%3d. [%5d] %s\n\r",
					++found, nr->vnum, nr->short_descr);
				add_buf(output, buf1);
			}
		}
		break;
	}
	case SCMD_MLIST: {
		MOB_INDEX_DATA *nr;
		sprintf(buf1, "Mobile List From Vnum %d to %d\n\r", first, last);
		add_buf(output, buf1);
		for (vnum = first; vnum <= last; vnum++) {
			if ((nr = get_mob_index(vnum))) {
				sprintf(buf1, "%3d. [%5d] %s\n\r",
					++found, nr->vnum, nr->short_descr);
				add_buf(output, buf1);
			}
		}
		break;
	}
	case SCMD_TLIST: {
		MPROG_CODE *nr;
		sprintf(buf1, "Trigger List From Vnum %d to %d\n\r", first, last);
		add_buf(output, buf1);
		for (vnum = first; vnum <= last; vnum++) {
			if ((nr = get_mprog_index(vnum))) {
				sprintf(buf1, "%3d. [%5d] %s\n\r",
					++found, nr->vnum, nr->name);
				add_buf(output, buf1);
			}
		}
		break;
	}
    }

    if (!found) {
	switch(subcmd) {
	    case SCMD_RLIST:
		send_to_char("No rooms found within those parameters.\n\r", ch);
		break;
	    case SCMD_OLIST:
		send_to_char("No objects found within those parameters.\n\r", ch);
		break;
	    case SCMD_MLIST:
		send_to_char("No mobiles found within those parameters.\n\r", ch);
		break;
	    case SCMD_TLIST:
		send_to_char("No triggers found within those parameters.\n\r", ch);
		break;
	    default:
		mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: invalid SCMD passed to do_liblist! (SCMD = %d)", subcmd);
		break;
	}
    } else
	page_to_char(buf_string(output), ch);
    free_buf(output);
    return;
}

ACMD(do_outfit) {
    OBJ_DATA *obj;
    int i,sn,vnum;

    if (ch->level > 5 || IS_NPC(ch))
    {
	send_to_char("Find it yourself!\n\r",ch);
	return;
    }

   if (ch->carry_number+4 > can_carry_n(ch))   {
        send_to_char("You are carrying too much, try dropping some items.\n\r",ch);
        return;
   }
    if ( ( obj = get_eq_char( ch, WEAR_LIGHT ) ) == NULL )
    {
        obj = create_object( get_obj_index(OBJ_VNUM_SCHOOL_BANNER), 0 );
	obj->cost = 0;
        obj_to_char( obj, ch );
        equip_char( ch, obj, WEAR_LIGHT );
    }
 
    if ( ( obj = get_eq_char( ch, WEAR_BODY ) ) == NULL )
    {
	obj = create_object( get_obj_index(OBJ_VNUM_SCHOOL_VEST), 0 );
	obj->cost = 0;
        obj_to_char( obj, ch );
        equip_char( ch, obj, WEAR_BODY );
    }

    /* do the weapon thing */
    if ((obj = get_eq_char(ch,WEAR_WIELD)) == NULL)
    {
    	sn = 0; 
    	vnum = OBJ_VNUM_SCHOOL_SWORD; /* just in case! */

    	for (i = 0; weapon_table[i].name != NULL; i++)
    	{
	    if (ch->pcdata->learned[sn] < 
		ch->pcdata->learned[*weapon_table[i].gsn])
	    {
	    	sn = *weapon_table[i].gsn;
	    	vnum = weapon_table[i].vnum;
	    }
    	}

    	obj = create_object(get_obj_index(vnum),0);
     	obj_to_char(obj,ch);
    	equip_char(ch,obj,WEAR_WIELD);
    }

    if (((obj = get_eq_char(ch,WEAR_WIELD)) == NULL 
    ||   !IS_WEAPON_STAT(obj,WEAPON_TWO_HANDS)) 
    &&  (obj = get_eq_char( ch, WEAR_SHIELD ) ) == NULL )
    {
        obj = create_object( get_obj_index(OBJ_VNUM_SCHOOL_SHIELD), 0 );
	obj->cost = 0;
        obj_to_char( obj, ch );
        equip_char( ch, obj, WEAR_SHIELD );
    }

    send_to_char("You have been equipped.\n\r",ch);
}

static char *logtypes[] = {"off", "brief", "normal", "complete", "\n"};

ACMD(do_syslog) {
    int tp;
    char arg[MAX_INPUT_LENGTH];

    one_argument(argument, arg);

    if (!*arg) {
	tp = ((PLR_FLAGGED(ch, PLR_LOG1) ? 1 : 0) +
		(PLR_FLAGGED(ch, PLR_LOG2) ? 2 : 0));
	ch->Send("Your syslog is currently %s.\n\r", logtypes[tp]);
    } else if (((tp = search_block(arg, logtypes, FALSE)) == -1))
	send_to_char("Usage: syslog { Off | Brief | Normal | Complete }\n\r", ch);
    else {
	REMOVE_BIT(PLR_FLAGS(ch), PLR_LOG1 | PLR_LOG2);
	SET_BIT(PLR_FLAGS(ch), (PLR_LOG1 * (tp & 1)) | (PLR_LOG2 * (tp & 2) >> 1));
	ch->Send("Your syslog is now %s.\n\r", logtypes[tp]);
    }
}

ACMD(do_smote) {
    CHAR_DATA *vch;
    char *letter,*name;
    char last[MAX_INPUT_LENGTH], temp[MAX_STRING_LENGTH];
    int matches = 0;
 
    if ( !IS_NPC(ch) && IS_SET(ch->comm, COMM_MUTED) )
    {
        send_to_char( "You can't show your emotions.\n\r", ch );
        return;
    }
 
    if ( argument[0] == '\0' )
    {
        send_to_char( "Emote what?\n\r", ch );
        return;
    }
    
    if (strstr(argument,ch->name) == NULL)
    {
	send_to_char("You must include your name in an smote.\n\r",ch);
	return;
    }
   
    send_to_char(argument,ch);
    send_to_char("\n\r",ch);
 
    for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room)
    {
        if (vch->desc == NULL || vch == ch)
            continue;
 
        if ((letter = strstr(argument,vch->name)) == NULL)
        {
	    send_to_char(argument,vch);
	    send_to_char("\n\r",vch);
            continue;
        }
 
        strcpy(temp,argument);
        temp[strlen(argument) - strlen(letter)] = '\0';
        last[0] = '\0';
        name = vch->name;
 
        for (; *letter != '\0'; letter++)
        {
            if (*letter == '\'' && matches == strlen(vch->name))
            {
                strcat(temp,"r");
                continue;
            }
 
            if (*letter == 's' && matches == strlen(vch->name))
            {
                matches = 0;
                continue;
            }
 
            if (matches == strlen(vch->name))
            {
                matches = 0;
            }
 
            if (*letter == *name)
            {
                matches++;
                name++;
                if (matches == strlen(vch->name))
                {
                    strcat(temp,"you");
                    last[0] = '\0';
                    name = vch->name;
                    continue;
                }
                strncat(last,letter,1);
                continue;
            }
 
            matches = 0;
            strcat(temp,last);
            strncat(temp,letter,1);
            last[0] = '\0';
            name = vch->name;
        }
 
	send_to_char(temp,vch);
	send_to_char("\n\r",vch);
    }
 
    return;
}

ACMD(do_rmsg) {
    char buf[MSL];

    if (!IS_NPC(ch))
    {
	smash_tilde(argument);

	if (argument[0] == '\0')
	{
	  sprintf(buf,"Your rmessage is: %s\n\r",ch->pcdata->r_msg);
	  send_to_char(buf,ch);
	  return;
	}
	if (!str_cmp(argument,"none"))
	{
		free_string(ch->pcdata->r_msg);
		ch->pcdata->r_msg = str_dup("");
		send_to_char("Restore message cleared.\n\r",ch);
		return;
	}
	if (strstr(argument,ch->name) == NULL)
	{
	  send_to_char("You must include your name.\n\r",ch);
	  return;
	}
	free_string(ch->pcdata->r_msg);
	ch->pcdata->r_msg = str_dup(argument);
	sprintf(buf, "Your rmessage is now: %s\n\r",ch->pcdata->r_msg);
	send_to_char(buf,ch);
	}
	  return;
}

ACMD(do_bamfin) {
    char buf[MAX_STRING_LENGTH];

    if ( !IS_NPC(ch) )
    {
	smash_tilde( argument );

	if (argument[0] == '\0')
	{
	    sprintf(buf,"Your poofin is %s\n\r",ch->pcdata->bamfin);
	    send_to_char(buf,ch);
	    return;
	}

	if ( strstr(argument,ch->name) == NULL)
	{
	    send_to_char("You must include your name.\n\r",ch);
	    return;
	}
	     
	free_string( ch->pcdata->bamfin );
	ch->pcdata->bamfin = str_dup( argument );

        sprintf(buf,"Your poofin is now %s\n\r",ch->pcdata->bamfin);
        send_to_char(buf,ch);
    }
    return;
}

ACMD(do_bamfout) {
    char buf[MAX_STRING_LENGTH];
 
    if ( !IS_NPC(ch) )
    {
        smash_tilde( argument );
 
        if (argument[0] == '\0')
        {
            sprintf(buf,"Your poofout is %s\n\r",ch->pcdata->bamfout);
            send_to_char(buf,ch);
            return;
        }
 
        if ( strstr(argument,ch->name) == NULL)
        {
            send_to_char("You must include your name.\n\r",ch);
            return;
        }
 
        free_string( ch->pcdata->bamfout );
        ch->pcdata->bamfout = str_dup( argument );
 
        sprintf(buf,"Your poofout is now %s\n\r",ch->pcdata->bamfout);
        send_to_char(buf,ch);
    }
    return;
}



ACMD(do_disconnect) {
    char arg[MAX_INPUT_LENGTH];
    DESCRIPTOR_DATA *d;
    CHAR_DATA *victim;

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
    {
	send_to_char( "Disconnect whom?\n\r", ch );
	return;
    }

    if (is_number(arg))
    {
	int desc;

	desc = atoi(arg);
    	for ( d = descriptor_list; d != NULL; d = d->next )
    	{
            if ( d->descriptor == desc )
            {
            	close_socket( d );
            	send_to_char( "Okay.\n\r", ch );
            	return;
            }
	}
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( victim->desc == NULL )
    {
	act( "$N doesn't have a descriptor.", ch, NULL, victim, TO_CHAR );
	return;
    }

    for ( d = descriptor_list; d != NULL; d = d->next )
    {
	if ( d == victim->desc )
	{
	    close_socket( d );
	    send_to_char( "Okay.\n\r", ch );
	    return;
	}
    }

    mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: do_disconnect: descriptor not found.");
    send_to_char( "Descriptor not found!\n\r", ch );
    return;
}



ACMD(do_pardon) {
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' || arg2[0] == '\0' )
    {
	send_to_char( "Syntax: pardon <character> <killer|thief>.\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
    {
	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) )
	{
	    REMOVE_BIT( victim->act, PLR_KILLER );
	    send_to_char( "Killer flag removed.\n\r", ch );
	    send_to_char( "You are no longer a KILLER.\n\r", victim );
	}
	return;
    }

    if ( !str_cmp( arg2, "thief" ) )
    {
	if ( IS_SET(victim->act, PLR_THIEF) )
	{
	    REMOVE_BIT( victim->act, PLR_THIEF );
	    send_to_char( "Thief flag removed.\n\r", ch );
	    send_to_char( "You are no longer a THIEF.\n\r", victim );
	}
	return;
    }

    send_to_char( "Syntax: pardon <character> <killer|thief>.\n\r", ch );
    return;
}


ACMD(do_echo) {
    DESCRIPTOR_DATA *d;
    
    if ( argument[0] == '\0' )
    {
	send_to_char( "Global echo what?\n\r", ch );
	return;
    }
    
    for ( d = descriptor_list; d; d = d->next )
    {
	if ( d->connected == CON_PLAYING )
	{
	    if (get_trust(d->character) >= get_trust(ch))
		send_to_char( "global> ",d->character);
	    send_to_char( argument, d->character );
	    send_to_char( "\n\r",   d->character );
	}
    }

    return;
}



ACMD(do_recho) {
    DESCRIPTOR_DATA *d;
    
    if ( argument[0] == '\0' )
    {
	send_to_char( "Local echo what?\n\r", ch );

	return;
    }

    for ( d = descriptor_list; d; d = d->next )
    {
	if ( d->connected == CON_PLAYING
	&&   d->character->in_room == ch->in_room )
	{
            if (get_trust(d->character) >= get_trust(ch))
                send_to_char( "local> ",d->character);
	    send_to_char( argument, d->character );
	    send_to_char( "\n\r",   d->character );
	}
    }

    return;
}

ACMD(do_zecho) {
    DESCRIPTOR_DATA *d;

    if (argument[0] == '\0')
    {
	send_to_char("Zone echo what?\n\r",ch);
	return;
    }

    for (d = descriptor_list; d; d = d->next)
    {
	if (d->connected == CON_PLAYING
	&&  d->character->in_room != NULL && ch->in_room != NULL
	&&  d->character->in_room->area == ch->in_room->area)
	{
	    if (get_trust(d->character) >= get_trust(ch))
		send_to_char("zone> ",d->character);
	    send_to_char(argument,d->character);
	    send_to_char("\n\r",d->character);
	}
    }
}

ACMD(do_pecho) {
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    argument = one_argument(argument, arg);
 
    if ( argument[0] == '\0' || arg[0] == '\0' )
    {
	send_to_char("Personal echo what?\n\r", ch); 
	return;
    }
   
    if  ( (victim = get_char_world(ch, arg) ) == NULL )
    {
	send_to_char("Target not found.\n\r",ch);
	return;
    }

    if (get_trust(victim) >= get_trust(ch) && get_trust(ch) != MAX_LEVEL)
        send_to_char( "personal> ",victim);

    send_to_char(argument,victim);
    send_to_char("\n\r",victim);
    send_to_char( "personal> ",ch);
    send_to_char(argument,ch);
    send_to_char("\n\r",ch);
}


ROOM_INDEX_DATA *find_location( CHAR_DATA *ch, char *arg )
{
    CHAR_DATA *victim;
    OBJ_DATA *obj;

    if ( is_number(arg) )
	return get_room_index( atoi( arg ) );

    if ( ( victim = get_char_world( ch, arg ) ) != NULL )
	return victim->in_room;

    if ( ( obj = get_obj_world( ch, arg ) ) != NULL )
	return obj->in_room;

    return NULL;
}

ACMD(do_transfer) {
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    ROOM_INDEX_DATA *location;
    DESCRIPTOR_DATA *d;
    CHAR_DATA *victim;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' )
    {
	send_to_char( "Transfer whom (and where)?\n\r", ch );
	return;
    }

    if ( !str_cmp( arg1, "all" ) )
    {
	for ( d = descriptor_list; d != NULL; d = d->next )
	{
	    if ( d->connected == CON_PLAYING
	    &&   d->character != ch
	    &&   d->character->in_room != NULL
	    &&   can_see( ch, d->character ) )
	    {
		char buf[MAX_STRING_LENGTH];
		sprintf( buf, "%s %s", d->character->name, arg2 );
		do_function(ch, &do_transfer, buf, 0);
	    }
	}
	return;
    }

    /*
     * Thanks to Grodyn for the optional location parameter.
     */
    if ( arg2[0] == '\0' )
    {
	location = ch->in_room;
    }
    else
    {
	if ( ( location = find_location( ch, arg2 ) ) == NULL )
	{
	    send_to_char( "No such location.\n\r", ch );
	    return;
	}

	if ( !is_room_owner(ch,location) && room_is_private( location ) 
	&&  get_trust(ch) < MAX_LEVEL)
	{
	    send_to_char( "That room is private right now.\n\r", ch );
	    return;
	}
    }

    if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( victim->in_room == NULL )
    {
	send_to_char( "They are in limbo.\n\r", ch );
	return;
    }

    if (get_trust(ch) <= get_trust(victim))
    {
	act("I don't think $E would like that.", ch, NULL, victim, TO_CHAR);
	return;
    }

    if ( victim->fighting != NULL )
	stop_fighting( victim, TRUE );
    act( "$n disappears in a mushroom cloud.", victim, NULL, NULL, TO_ROOM );
    char_from_room( victim );
    char_to_room( victim, location );
    act( "$n arrives from a puff of smoke.", victim, NULL, NULL, TO_ROOM );
    if ( ch != victim )
	act( "$n has transferred you.", ch, NULL, victim, TO_VICT );
    look_at_room(victim, 0);
    send_to_char( "Okay.\n\r", ch );
}

struct {
	char *  field;
	Flags   permission;
} StaffPermissions[] = {
	{ "admin",	STAFF_ADMIN	},
	{ "secadmin",	STAFF_SECADMIN	},
	{ "characters", STAFF_CHAR	},
	{ "clans",	STAFF_CLANS	},
	{ "game",	STAFF_GAME	},
	{ "general",	STAFF_GEN	},
	{ "help",	STAFF_HELP	},
	{ "olc",	STAFF_OLC	},
	{ "olcadmin",	STAFF_OLCADMIN	},
	{ "script",	STAFF_SCRIPT	},
	{ "security",	STAFF_SECURITY	},
	{ "socials",	STAFF_SOCIALS	},
	{ "coder",	STAFF_CODER	},
	{ "associate",	STAFF_ASSOCIATE	},
	{ "trainee",	STAFF_TRAINEE	},
	{ "\n", 0 }
};

ACMD(do_allow) {
	BUFFER *output;
	CHAR_DATA *vict;
	SInt32	i=0, l=0, tempCmd=0, cmd=0;
	char arg[MIL];

	if (IS_NPC(ch)) return;
	argument = one_argument(argument, arg);

	if (arg[0] == '\0' || argument[0] == '\0'
	|| !STF_FLAGGED(ch, STAFF_ADMIN)) {
		output = new_buf();
		sprintf(arg, "Usage: %s <name> <permission>\n\r"
				"Permissions available:\n\r",
				subcmd == SCMD_ALLOW ? "allow" : "deny");
		add_buf(output, arg);
		for (l=0; *StaffPermissions[l].field != '\n'; l++) {
			i = 1;
			sprintf(arg, "%-9.9s: ",StaffPermissions[l].field);
			add_buf(output, arg);
			for(cmd=0; cmd_table[cmd].name[0] != '\0'; cmd++) {
				tempCmd = cmd;
				if (IS_SET(cmd_table[tempCmd].staffcmd, StaffPermissions[l].permission)
				&& cmd_table[tempCmd].show) {
				if (((i % 6) == 1) && (i != 1))
					add_buf(output, "           ");
				sprintf(arg, "%-11.11s%s", cmd_table[tempCmd].name,
					!(i % 6) ? "\n\r" : "");
				add_buf(output, arg);
				i++;
				}
			}
			if (--i % 6)	add_buf(output, "\n\r");
			if (i == 0)	add_buf(output, "None.\n\r");
		}
		page_to_char(buf_string(output), ch);
		free_buf(output);
		return;
	} else if ((vict = get_char_world(ch, arg)) == NULL)
		send_to_char("Player not found.\n\r",ch);
	else {
		for (i = 0; *StaffPermissions[i].field != '\n'; i++)
			if (is_name(argument, StaffPermissions[i].field))
			break;
		if (*StaffPermissions[i].field == '\n')
			send_to_char("Invalid choice.\n\r",ch);
		else {
			if (subcmd == SCMD_ALLOW)
				SET_BIT(STF_FLAGS(vict),StaffPermissions[i].permission);
			else
				REMOVE_BIT(STF_FLAGS(vict),StaffPermissions[i].permission);

			ch->Send("You %s %s access to %s commands.\n\r", 
				subcmd == SCMD_ALLOW ? "allow" : "deny",vict->name, StaffPermissions[i].field);
			vict->Send("%s %s you access to %s commands.\n\r", 
				ch->name, subcmd == SCMD_ALLOW ? "allowed" : "denied", StaffPermissions[i].field);
			mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s %s %s access to %s commands.",
				ch->name, subcmd == SCMD_ALLOW ? "allowed" : "denied",vict->name, StaffPermissions[i].field);
		}
	}
}

ACMD(do_at) {
    char arg[MAX_INPUT_LENGTH];
    ROOM_INDEX_DATA *location;
    ROOM_INDEX_DATA *original;
    OBJ_DATA *on;
    CHAR_DATA *wch;
    
    argument = one_argument( argument, arg );

    if ( arg[0] == '\0' || argument[0] == '\0' )
    {
	send_to_char( "At where what?\n\r", ch );
	return;
    }

    if ( ( location = find_location( ch, arg ) ) == NULL )
    {
	send_to_char( "No such location.\n\r", ch );
	return;
    }

    if (!is_room_owner(ch,location) && room_is_private( location ) 
    &&  get_trust(ch) < MAX_LEVEL)
    {
	send_to_char( "That room is private right now.\n\r", ch );
	return;
    }

    original = ch->in_room;
    on = ch->on;
    char_from_room( ch );
    char_to_room( ch, location );
    interpret( ch, argument );

     /*      * See if 'ch' still exists before continuing!
      * Handles 'at XXXX quit' case.      */
     for ( wch = char_list; wch != NULL; wch = wch->next )     {
	if ( wch == ch )	{	    OBJ_DATA *obj;
	    char_from_room( ch );
	    char_to_room( ch, original );
	    /* See if on still exists before setting ch->on back to it. */
	    for ( obj = original->contents; obj; obj = obj->next_content )
		{
		if ( obj == on )
		{
		    ch->on = on;
		    break;
		}
	    }
	    break;
	}
    }
    /*
     * See if 'ch' still exists before continuing!
     * Handles 'at XXXX quit' case.
     */
    for ( wch = char_list; wch != NULL; wch = wch->next )
    {
	if ( wch == ch )
	{
	    char_from_room( ch );
	    char_to_room( ch, original );
	    ch->on = on;
	    break;
	}
    }
     /*
      * See if 'ch' still exists before continuing!
      * Handles 'at XXXX quit' case.
      */
     for ( wch = char_list; wch != NULL; wch = wch->next )
     {
	if ( wch == ch )
	{
	    OBJ_DATA *obj;
	    char_from_room( ch );
	    char_to_room( ch, original );
	    /* See if on still exists before setting ch->on back to it. */
	    for ( obj = original->contents; obj; obj = obj->next_content )
	    {
		if ( obj == on )
		{
		    ch->on = on;
		    break;
		}
	    }
	    break;
	}
     }
    return;
}



ACMD(do_goto) {
    int count = 0;
    CHAR_DATA *rch;
    ROOM_INDEX_DATA *location;

    if (argument[0] == '\0') {
	send_to_char("Goto where?\n\r", ch);
	return;
    }

    if ((location = find_location(ch, argument)) == NULL) {
	send_to_char("No such location.\n\r", ch);
	return;
    }

    count = 0;
    for (rch = location->people; rch != NULL; rch = rch->next_in_room)
        count++;

    if (!is_room_owner(ch,location) && room_is_private(location) 
    &&  (count > 1 || get_trust(ch) < MAX_LEVEL)) {
	send_to_char("That room is private right now.\n\r", ch);
	return;
    }

    if (ch->fighting != NULL)
	stop_fighting(ch, TRUE);

    for (rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room)
    {
	if (get_trust(rch) >= ch->invis_level && ch != rch)
	{
	    if (ch->pcdata != NULL && ch->pcdata->bamfout[0] != '\0')
		act("$t",ch,ch->pcdata->bamfout,rch,TO_VICT);
	    else
		act("$n leaves in a swirling mist.",ch,NULL,rch,TO_VICT);
	}
    }

    char_from_room(ch);
    char_to_room(ch, location);


    for (rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room)
    {
        if (get_trust(rch) >= ch->invis_level && ch != rch)
        {
            if (ch->pcdata != NULL && ch->pcdata->bamfin[0] != '\0')
                act("$t",ch,ch->pcdata->bamfin,rch,TO_VICT);
            else
                act("$n appears in a swirling mist.",ch,NULL,rch,TO_VICT);
        }
    }

    look_at_room(ch, 0);
    return;
}

ACMD(do_violate) {
    ROOM_INDEX_DATA *location;
    CHAR_DATA *rch;
 
    if ( argument[0] == '\0' )
    {
        send_to_char( "Goto where?\n\r", ch );
        return;
    }
 
    if ( ( location = find_location( ch, argument ) ) == NULL )
    {
        send_to_char( "No such location.\n\r", ch );
        return;
    }

    if (!room_is_private( location ))
    {
        send_to_char( "That room isn't private, use goto.\n\r", ch );
        return;
    }
 
    if ( ch->fighting != NULL )
        stop_fighting( ch, TRUE );
 
    for (rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room)
    {
        if (get_trust(rch) >= ch->invis_level)
        {
            if (ch->pcdata != NULL && ch->pcdata->bamfout[0] != '\0')
                act("$t",ch,ch->pcdata->bamfout,rch,TO_VICT);
            else
                act("$n leaves in a swirling mist.",ch,NULL,rch,TO_VICT);
        }
    }
 
    char_from_room( ch );
    char_to_room( ch, location );
 
 
    for (rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room)
    {
        if (get_trust(rch) >= ch->invis_level)
        {
            if (ch->pcdata != NULL && ch->pcdata->bamfin[0] != '\0')
                act("$t",ch,ch->pcdata->bamfin,rch,TO_VICT);
            else
                act("$n appears in a swirling mist.",ch,NULL,rch,TO_VICT);
        }
    }

    look_at_room(ch, 0);
    return;
}

ACMD(do_stat) {
   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);
	return;
   }

   if (!str_cmp(arg,"room"))
   {
	do_function(ch, &do_rstat, string, 0);
	return;
   }
  
   if (!str_cmp(arg,"obj"))
   {
	do_function(ch, &do_ostat, string, 0);
	return;
   }

   if(!str_cmp(arg,"char")  || !str_cmp(arg,"mob"))
   {
	do_function(ch, &do_mstat, string, 0);
	return;
   }
   
   /* do it the old way */

   obj = get_obj_world(ch,argument);
   if (obj != NULL)
   {
     do_function(ch, &do_ostat, argument, 0);
     return;
   }

  victim = get_char_world(ch,argument);
  if (victim != NULL)
  {
    do_function(ch, &do_mstat, argument, 0);
    return;
  }

  location = find_location(ch,argument);
  if (location != NULL)
  {
    do_function(ch, &do_rstat, argument, 0);
    return;
  }

  send_to_char("Nothing by that name found anywhere.\n\r",ch);
}

ACMD(do_rstat) {
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    ROOM_INDEX_DATA *location;
    OBJ_DATA *obj;
    CHAR_DATA *rch;
    int door;

    one_argument( argument, arg );
    location = ( arg[0] == '\0' ) ? ch->in_room : find_location( ch, arg );
    if ( location == NULL )
    {
	send_to_char( "No such location.\n\r", ch );
	return;
    }

    if (!is_room_owner(ch,location) && ch->in_room != location 
    &&  room_is_private( location ) && !IS_TRUSTED(ch,IMPLEMENTOR))
    {
	send_to_char( "That room is private right now.\n\r", ch );
	return;
    }

    sprintf( buf, "Name: '%s'\n\rArea: '%s'\n\r",
	location->name,
	location->area->name );
    send_to_char( buf, ch );

    sprintf( buf,
	"Vnum: %d  Sector: %d  Light: %d  Healing: %d  Mana: %d\n\r",
	location->vnum,
	location->sector_type,
	location->light,
	location->heal_rate,
	location->mana_rate );
    send_to_char( buf, ch );

    sprintf( buf,
	"Room flags: %d.\n\rDescription:\n\r%s",
	location->room_flags,
	location->description );
    send_to_char( buf, ch );

    if ( location->extra_descr != NULL )
    {
	EXTRA_DESCR_DATA *ed;

	send_to_char( "Extra description keywords: '", ch );
	for ( ed = location->extra_descr; ed; ed = ed->next )
	{
	    send_to_char( ed->keyword, ch );
	    if ( ed->next != NULL )
		send_to_char( " ", ch );
	}
	send_to_char( "'.\n\r", ch );
    }

    send_to_char( "Characters:", ch );
    for ( rch = location->people; rch; rch = rch->next_in_room )
    {
	if (can_see(ch,rch))
        {
	    send_to_char( " ", ch );
	    one_argument( rch->name, buf );
	    send_to_char( buf, ch );
	}
    }

    send_to_char( ".\n\rObjects:   ", ch );
    for ( obj = location->contents; obj; obj = obj->next_content )
    {
	send_to_char( " ", ch );
	one_argument( obj->name, buf );
	send_to_char( buf, ch );
    }
    send_to_char( ".\n\r", ch );

    for ( door = 0; door <= 5; door++ )
    {
	EXIT_DATA *pexit;

	if ( ( pexit = location->exit[door] ) != NULL )
	{
	    sprintf( buf,
		"Door: %d.  To: %d.  Key: %d.  Exit flags: %d.\n\rKeyword: '%s'.  Description: %s",

		door,
		(pexit->u1.to_room == NULL ? -1 : pexit->u1.to_room->vnum),
	    	pexit->key,
	    	pexit->exit_info,
	    	pexit->keyword,
	    	pexit->description[0] != '\0'
		    ? pexit->description : "(none).\n\r" );
	    send_to_char( buf, ch );
	}
    }

    return;
}



ACMD(do_ostat) {
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    AFFECT_DATA *paf;
    OBJ_DATA *obj;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Stat what?\n\r", ch );
	return;
    }

    if ( ( obj = get_obj_world( ch, argument ) ) == NULL )
    {
	send_to_char( "Nothing like that in hell, earth, or heaven.\n\r", ch );
	return;
    }

    sprintf( buf, "Name(s): %s\n\r",
	obj->name );
    send_to_char( buf, ch );

    sprintf( buf, "Vnum: %d  Format: %s  Type: %s  Resets: %d\n\r",
	obj->pIndexData->vnum, obj->pIndexData->new_format ? "new" : "old",
	item_name(obj->item_type), obj->pIndexData->reset_num );
    send_to_char( buf, ch );

    sprintf( buf, "Short description: %s\n\rLong description: %s\n\r",
	obj->short_descr, obj->description );
    send_to_char( buf, ch );

    sprintf( buf, "Wear bits: %s\n\rExtra bits: %s\n\r",
	wear_bit_name(obj->wear_flags), extra_bit_name( obj->extra_flags ) );
    send_to_char( buf, ch );

    sprintf( buf, "Number: %d/%d  Weight: %d/%d/%d (10th pounds)\n\r",
	1,           get_obj_number( obj ),
	obj->weight, get_obj_weight( obj ),get_true_weight(obj) );
    send_to_char( buf, ch );

    sprintf( buf, "Level: %d  Cost: %d  Condition: %d  Timer: %d\n\r",
	obj->level, obj->cost, obj->condition, obj->timer );
    send_to_char( buf, ch );

    sprintf( buf,
	"In room: %d  In object: %s  Carried by: %s  Wear_loc: %d\n\r",
	obj->in_room    == NULL    ?        0 : obj->in_room->vnum,
	obj->in_obj     == NULL    ? "(none)" : obj->in_obj->short_descr,
	obj->carried_by == NULL    ? "(none)" : 
	    can_see(ch,obj->carried_by) ? obj->carried_by->name
				 	: "someone",
	obj->wear_loc );
    send_to_char( buf, ch );
    
    sprintf( buf, "Values: %d %d %d %d %d\n\r",
	obj->value[0], obj->value[1], obj->value[2], obj->value[3],
	obj->value[4] );
    send_to_char( buf, ch );
    
    /* now give out vital statistics as per identify */
    
    switch ( obj->item_type )
    {
    	case ITEM_SCROLL: 
    	case ITEM_POTION:
    	case ITEM_PILL:
	    sprintf( buf, "Level %d spells of:", obj->value[0] );
	    send_to_char( buf, ch );

	    if ( obj->value[1] >= 0 && obj->value[1] < MAX_SKILL )
	    {
	    	send_to_char( " '", ch );
	    	send_to_char( skill_table[obj->value[1]].name, ch );
	    	send_to_char( "'", ch );
	    }

	    if ( obj->value[2] >= 0 && obj->value[2] < MAX_SKILL )
	    {
	    	send_to_char( " '", ch );
	    	send_to_char( skill_table[obj->value[2]].name, ch );
	    	send_to_char( "'", ch );
	    }

	    if ( obj->value[3] >= 0 && obj->value[3] < MAX_SKILL )
	    {
	    	send_to_char( " '", ch );
	    	send_to_char( skill_table[obj->value[3]].name, ch );
	    	send_to_char( "'", ch );
	    }

	    if (obj->value[4] >= 0 && obj->value[4] < MAX_SKILL)
	    {
		send_to_char(" '",ch);
		send_to_char(skill_table[obj->value[4]].name,ch);
		send_to_char("'",ch);
	    }

	    send_to_char( ".\n\r", ch );
	break;

    	case ITEM_WAND: 
    	case ITEM_STAFF: 
	    sprintf( buf, "Has %d(%d) charges of level %d",
	    	obj->value[1], obj->value[2], obj->value[0] );
	    send_to_char( buf, ch );
      
	    if ( obj->value[3] >= 0 && obj->value[3] < MAX_SKILL )
	    {
	    	send_to_char( " '", ch );
	    	send_to_char( skill_table[obj->value[3]].name, ch );
	    	send_to_char( "'", ch );
	    }

	    send_to_char( ".\n\r", ch );
	break;

	case ITEM_DRINK_CON:
	    sprintf(buf,"It holds %s-colored %s.\n\r",
		liq_table[obj->value[2]].liq_color,
		liq_table[obj->value[2]].liq_name);
	    send_to_char(buf,ch);
	    break;
		
      
    	case ITEM_WEAPON:
 	    send_to_char("Weapon type is ",ch);
	    switch (obj->value[0])
	    {
	    	case(WEAPON_EXOTIC): 
		    send_to_char("exotic\n\r",ch);
		    break;
	    	case(WEAPON_SWORD): 
		    send_to_char("sword\n\r",ch);
		    break;	
	    	case(WEAPON_DAGGER): 
		    send_to_char("dagger\n\r",ch);
		    break;
	    	case(WEAPON_SPEAR):
		    send_to_char("spear/staff\n\r",ch);
		    break;
	    	case(WEAPON_MACE): 
		    send_to_char("mace/club\n\r",ch);	
		    break;
	   	case(WEAPON_AXE): 
		    send_to_char("axe\n\r",ch);	
		    break;
	    	case(WEAPON_FLAIL): 
		    send_to_char("flail\n\r",ch);
		    break;
	    	case(WEAPON_WHIP): 
		    send_to_char("whip\n\r",ch);
		    break;
	    	case(WEAPON_POLEARM): 
		    send_to_char("polearm\n\r",ch);
		    break;
		case(WEAPON_QUARTERSTAFF):
		    send_to_char("quarterstaff\n\r",ch);
	    	default: 
		    send_to_char("unknown\n\r",ch);
		    break;
 	    }
	    if (obj->pIndexData->new_format)
	    	sprintf(buf,"Damage is %dd%d (average %d)\n\r",
		    obj->value[1],obj->value[2],
		    (1 + obj->value[2]) * obj->value[1] / 2);
	    else
	    	sprintf( buf, "Damage is %d to %d (average %d)\n\r",
	    	    obj->value[1], obj->value[2],
	    	    ( obj->value[1] + obj->value[2] ) / 2 );
	    send_to_char( buf, ch );

	    sprintf(buf,"Damage noun is %s.\n\r",
		(obj->value[3] > 0 && obj->value[3] < MAX_DAMAGE_MESSAGE) ?
		    attack_table[obj->value[3]].noun : "undefined");
	    send_to_char(buf,ch);
	    
	    if (obj->value[4])  /* weapon flags */
	    {
	        sprintf(buf,"Weapons flags: %s\n\r",
		    weapon_bit_name(obj->value[4]));
	        send_to_char(buf,ch);
            }
	break;

    	case ITEM_ARMOR:
	    sprintf( buf, 
	    "Armor class is %d pierce, %d bash, %d slash, and %d vs. magic\n\r",
	        obj->value[0], obj->value[1], obj->value[2], obj->value[3] );
	    send_to_char( buf, ch );
	break;

        case ITEM_CONTAINER:
            sprintf(buf,"Capacity: %d#  Maximum weight: %d#  flags: %s\n\r",
                obj->value[0], obj->value[3], cont_bit_name(obj->value[1]));
            send_to_char(buf,ch);
            if (obj->value[4] != 100)
            {
                sprintf(buf,"Weight multiplier: %d%%\n\r",
		    obj->value[4]);
                send_to_char(buf,ch);
            }
        break;
    }


    if ( obj->extra_descr != NULL || obj->pIndexData->extra_descr != NULL )
    {
	EXTRA_DESCR_DATA *ed;

	send_to_char( "Extra description keywords: '", ch );

	for ( ed = obj->extra_descr; ed != NULL; ed = ed->next )
	{
	    send_to_char( ed->keyword, ch );
	    if ( ed->next != NULL )
	    	send_to_char( " ", ch );
	}

	for ( ed = obj->pIndexData->extra_descr; ed != NULL; ed = ed->next )
	{
	    send_to_char( ed->keyword, ch );
	    if ( ed->next != NULL )
		send_to_char( " ", ch );
	}

	send_to_char( "'\n\r", ch );
    }

    for ( paf = obj->affected; paf != NULL; paf = paf->next )
    {
	sprintf( buf, "Affects %s by %d, level %d",
	    affect_loc_name( paf->location ), paf->modifier,paf->level );
	send_to_char(buf,ch);
	if ( paf->duration > -1)
	    sprintf(buf,", %d hours.\n\r",paf->duration);
	else
	    sprintf(buf,".\n\r");
	send_to_char( buf, ch );
	if (paf->bitvector)
	{
	    switch(paf->where)
	    {
		case TO_AFFECTS:
		    sprintf(buf,"Adds %s affect.\n",
			affect_bit_name(paf->bitvector));
		    break;
                case TO_WEAPON:
                    sprintf(buf,"Adds %s weapon flags.\n",
                        weapon_bit_name(paf->bitvector));
		    break;
		case TO_OBJECT:
		    sprintf(buf,"Adds %s object flag.\n",
			extra_bit_name(paf->bitvector));
		    break;
		case TO_IMMUNE:
		    sprintf(buf,"Adds immunity to %s.\n",
			imm_bit_name(paf->bitvector));
		    break;
		case TO_RESIST:
		    sprintf(buf,"Adds resistance to %s.\n\r",
			imm_bit_name(paf->bitvector));
		    break;
		case TO_VULN:
		    sprintf(buf,"Adds vulnerability to %s.\n\r",
			imm_bit_name(paf->bitvector));
		    break;
		default:
		    sprintf(buf,"Unknown bit %d: %d\n\r",
			paf->where,paf->bitvector);
		    break;
	    }
	    send_to_char(buf,ch);
	}
    }

    if (!obj->enchanted)
    for ( paf = obj->pIndexData->affected; paf != NULL; paf = paf->next )
    {
	sprintf( buf, "Affects %s by %d, level %d.\n\r",
	    affect_loc_name( paf->location ), paf->modifier,paf->level );
	send_to_char( buf, ch );
        if (paf->bitvector)
        {
            switch(paf->where)
            {
                case TO_AFFECTS:
                    sprintf(buf,"Adds %s affect.\n",
                        affect_bit_name(paf->bitvector));
                    break;
                case TO_OBJECT:
                    sprintf(buf,"Adds %s object flag.\n",
                        extra_bit_name(paf->bitvector));
                    break;
                case TO_IMMUNE:
                    sprintf(buf,"Adds immunity to %s.\n",
                        imm_bit_name(paf->bitvector));
                    break;
                case TO_RESIST:
                    sprintf(buf,"Adds resistance to %s.\n\r",
                        imm_bit_name(paf->bitvector));
                    break;
                case TO_VULN:
                    sprintf(buf,"Adds vulnerability to %s.\n\r",
                        imm_bit_name(paf->bitvector));
                    break;
                default:
                    sprintf(buf,"Unknown bit %d: %d\n\r",
                        paf->where,paf->bitvector);
                    break;
            }
            send_to_char(buf,ch);
        }
    }

    return;
}



ACMD(do_mstat) {
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    AFFECT_DATA *paf;
    CHAR_DATA *victim;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Stat whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, argument ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    sprintf( buf, "Name: %s\n\r",
	victim->name);
    send_to_char( buf, ch );

    sprintf( buf, 
	"Vnum: %d  Format: %s  Race: %s  Group: %d  Sex: %s  Room: %d\n\r",
	IS_NPC(victim) ? victim->pIndexData->vnum : 0,
	IS_NPC(victim) ? victim->pIndexData->new_format ? "new" : "old" : "pc",
	race_table[victim->race].name,
	IS_NPC(victim) ? victim->group : 0, sex_table[victim->sex].name,
	victim->in_room == NULL    ?        0 : victim->in_room->vnum
	);
    send_to_char( buf, ch );

    if (IS_NPC(victim))
    {
	sprintf(buf,"Count: %d  Killed: %d\n\r",
	    victim->pIndexData->count,victim->pIndexData->killed);
	send_to_char(buf,ch);
    }

    sprintf( buf, 
   	"Str: %d(%d)  Int: %d(%d)  Wis: %d(%d)  Dex: %d(%d)  Con: %d(%d)  Cha: %d(%d)\n\r",
	victim->perm_stat[STAT_STR],
	get_curr_stat(victim,STAT_STR),
	victim->perm_stat[STAT_INT],
	get_curr_stat(victim,STAT_INT),
	victim->perm_stat[STAT_WIS],
	get_curr_stat(victim,STAT_WIS),
	victim->perm_stat[STAT_DEX],
	get_curr_stat(victim,STAT_DEX),
	victim->perm_stat[STAT_CON],
	get_curr_stat(victim,STAT_CON),
	victim->perm_stat[STAT_CHA],
	get_curr_stat(victim, STAT_CHA) );
    send_to_char( buf, ch );

    sprintf( buf, "Hp: %d/%d  Mana: %d/%d  Move: %d/%d  Practices: %d\n\r",
	victim->hit,         victim->max_hit,
	victim->mana,        victim->max_mana,
	victim->move,        victim->max_move,
	IS_NPC(victim) ? 0 : victim->practice );
    send_to_char( buf, ch );
	
    sprintf( buf,
	"Lv: %d  Class: %s  Align: %d  Gold: %ld  Silver: %ld  Exp: %d\n\r",
	victim->level,       
	IS_NPC(victim) ? "mobile" : class_table[victim->Class].name,            
	victim->alignment,
	victim->gold, victim->silver, victim->exp );
    send_to_char( buf, ch );

    sprintf(buf,"Armor: pierce: %d  bash: %d  slash: %d  magic: %d\n\r",
	    GET_AC(victim,AC_PIERCE), GET_AC(victim,AC_BASH),
	    GET_AC(victim,AC_SLASH),  GET_AC(victim,AC_EXOTIC));
    send_to_char(buf,ch);

    sprintf( buf, 
	"Hit: %d  Dam: %d  Saves: %d  Size: %s  Position: %s  Wimpy: %d\n\r",
	GET_HITROLL(victim), GET_DAMROLL(victim), victim->saving_throw,
	size_table[victim->size].name, position_table[victim->position].name,
	victim->wimpy );
    send_to_char( buf, ch );

    if (IS_NPC(victim) && victim->pIndexData->new_format)
    {
	sprintf(buf, "Damage: %dd%d  Message:  %s\n\r",
	    victim->damage[DICE_NUMBER],victim->damage[DICE_TYPE],
	    attack_table[victim->dam_type].noun);
	send_to_char(buf,ch);
    }
    sprintf( buf, "Fighting: %s\n\r",
	victim->fighting ? victim->fighting->name : "(none)" );
    send_to_char( buf, ch );

    sprintf( buf,
	"Thirst: %d  Hunger: %d  Full: %d  Drunk: %d  Hangover: %d\n\r",
	GET_COND(victim, COND_THIRST),
	GET_COND(victim, COND_HUNGER),
	GET_COND(victim, COND_FULL),
	GET_COND(victim, COND_DRUNK),
	GET_COND(victim, COND_HANGOVER));
    send_to_char( buf, ch );

    sprintf( buf, "Carry number: %d  Carry weight: %ld\n\r",
	victim->carry_number, get_carry_weight(victim) / 10 );
    send_to_char( buf, ch );


    if (!IS_NPC(victim))
    {
    	sprintf( buf, 
	    "Age: %d  Played: %d  Last Level: %d  Timer: %d\n\r",
	    get_age(victim), 
	    (int) (victim->played + current_time - victim->logon) / 3600, 
	    victim->pcdata->last_level, 
	    victim->timer );
    	send_to_char( buf, ch );
    }

    sprintf(buf, "Act: %s\n\r",act_bit_name(victim->act));
    send_to_char(buf,ch);
    
    if (victim->comm)
    {
    	sprintf(buf,"Comm: %s\n\r",comm_bit_name(victim->comm));
    	send_to_char(buf,ch);
    }
    if (victim->staff)
	{
	sprintf(buf,"Staff: %s\n\r",staff_bit_name(victim->staff));
	send_to_char(buf,ch);
	}

    if (IS_NPC(victim) && victim->off_flags)
    {
    	sprintf(buf, "Offense: %s\n\r",off_bit_name(victim->off_flags));
	send_to_char(buf,ch);
    }

    if (victim->imm_flags)
    {
	sprintf(buf, "Immune: %s\n\r",imm_bit_name(victim->imm_flags));
	send_to_char(buf,ch);
    }
 
    if (victim->res_flags)
    {
	sprintf(buf, "Resist: %s\n\r", imm_bit_name(victim->res_flags));
	send_to_char(buf,ch);
    }

    if (victim->vuln_flags)
    {
	sprintf(buf, "Vulnerable: %s\n\r", imm_bit_name(victim->vuln_flags));
	send_to_char(buf,ch);
    }

    sprintf(buf, "Form: %s\n\rParts: %s\n\r", 
	form_bit_name(victim->form), part_bit_name(victim->parts));
    send_to_char(buf,ch);

    if (victim->affected_by)
    {
	sprintf(buf, "Affected by %s\n\r", 
	    affect_bit_name(victim->affected_by));
	send_to_char(buf,ch);
    }
    if (victim->affected2_by)
    {
	sprintf(buf, "Affected by %s\n\r",
	    affect2_bit_name(victim->affected2_by));
	send_to_char(buf,ch);
    }

    sprintf( buf, "Master: %s  Leader: %s  Pet: %s\n\r",
	victim->master      ? victim->master->name   : "(none)",
	victim->leader      ? victim->leader->name   : "(none)",
	victim->pet 	    ? victim->pet->name	     : "(none)");
    send_to_char( buf, ch );

    if (!IS_NPC(victim))
    {
	sprintf( buf, "Security: %d.\n\r", victim->pcdata->security );	/* OLC */
	send_to_char( buf, ch );					/* OLC */
    }
if (IS_NPC(victim)) {
    sprintf( buf, "Short description: %s\n\rLong  description: %s",
	victim->short_descr,
	victim->long_descr[0] != '\0' ? victim->long_descr : "(none)\n\r" );
    send_to_char( buf, ch );
}
    if ( IS_NPC(victim) && victim->spec_fun != 0 )
    {
	sprintf(buf,"Mobile has special procedure %s.\n\r",
		spec_name(victim->spec_fun));
	send_to_char(buf,ch);
    }

    for ( paf = victim->affected; paf != NULL; paf = paf->next )
    {
	sprintf( buf,
	    "Spell: '%s' modifies %s by %d for %d hours with bits %s, level %d.\n\r",
	    skill_table[(int) paf->type].name,
	    affect_loc_name( paf->location ),
	    paf->modifier,
	    paf->duration,
	    (paf->where == TO_AFFECTS ? affect_bit_name( paf->bitvector ) :
	    affect2_bit_name( paf->bitvector )),
	    paf->level
	    );
	send_to_char( buf, ch );
    }

    return;
}

/* ofind and mfind replaced with vnum, vnum skill also added */
ACMD(do_vnum) {
    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_prefix(arg,"obj"))
    {
	do_function(ch, &do_ofind, string, 0);
 	return;
    }

    if (!str_prefix(arg,"mob") || !str_prefix(arg,"char"))
    { 
	do_function(ch, &do_mfind, string, 0);
	return;
    }

    if (!str_cmp(arg,"skill") || !str_cmp(arg,"spell"))
    {
	do_function (ch, &do_slookup, string, 0);
	return;
    }
    /* do both */
    do_function(ch, &do_mfind, argument, 0);
    do_function(ch, &do_ofind, argument, 0);
}


ACMD(do_mfind) {
    extern int top_mob_index;
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    MOB_INDEX_DATA *pMobIndex;
    int vnum;
    int nMatch;
    bool fAll;
    bool found;

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
    {
	send_to_char( "Find whom?\n\r", ch );
	return;
    }

    fAll	= FALSE; /* !str_cmp( arg, "all" ); */
    found	= FALSE;
    nMatch	= 0;

    /*
     * Yeah, so iterating over all vnum's takes 10,000 loops.
     * Get_mob_index is fast, and I don't feel like threading another link.
     * Do you?
     * -- Furey
     */
    for ( vnum = 0; nMatch < top_mob_index; vnum++ )
    {
	if ( ( pMobIndex = get_mob_index( vnum ) ) != NULL )
	{
	    nMatch++;
	    if ( fAll || is_name( argument, pMobIndex->player_name ) )
	    {
		found = TRUE;
		sprintf( buf, "[%5d] %s\n\r",
		    pMobIndex->vnum, pMobIndex->short_descr );
		send_to_char( buf, ch );
	    }
	}
    }

    if ( !found )
	send_to_char( "No mobiles by that name.\n\r", ch );

    return;
}



ACMD(do_ofind) {
    extern int top_obj_index;
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    OBJ_INDEX_DATA *pObjIndex;
    int vnum;
    int nMatch;
    bool fAll;
    bool found;

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
    {
	send_to_char( "Find what?\n\r", ch );
	return;
    }

    fAll	= FALSE; /* !str_cmp( arg, "all" ); */
    found	= FALSE;
    nMatch	= 0;

    /*
     * Yeah, so iterating over all vnum's takes 10,000 loops.
     * Get_obj_index is fast, and I don't feel like threading another link.
     * Do you?
     * -- Furey
     */
    for ( vnum = 0; nMatch < top_obj_index; vnum++ )
    {
	if ( ( pObjIndex = get_obj_index( vnum ) ) != NULL )
	{
	    nMatch++;
	    if ( fAll || is_name( argument, pObjIndex->name ) )
	    {
		found = TRUE;
		sprintf( buf, "[%5d] %s\n\r",
		    pObjIndex->vnum, pObjIndex->short_descr );
		send_to_char( buf, ch );
	    }
	}
    }

    if ( !found )
	send_to_char( "No objects by that name.\n\r", ch );

    return;
}


ACMD(do_owhere) {
    char buf[MAX_INPUT_LENGTH];
    BUFFER *buffer;
    OBJ_DATA *obj;
    OBJ_DATA *in_obj;
    bool found;
    int number = 0, max_found;

    found = FALSE;
    number = 0;
    max_found = 200;

    buffer = new_buf();

    if (argument[0] == '\0')
    {
	send_to_char("Find what?\n\r",ch);
	return;
    }
 
    for ( obj = object_list; obj != NULL; obj = obj->next )
    {
        if ( !can_see_obj( ch, obj ) || !is_name( argument, obj->name )
        ||   ch->level < obj->level)
            continue;
 
        found = TRUE;
        number++;
 
        for ( in_obj = obj; in_obj->in_obj != NULL; in_obj = in_obj->in_obj )
            ;
 
        if ( in_obj->carried_by != NULL && can_see(ch,in_obj->carried_by)
	&&   in_obj->carried_by->in_room != NULL)
            sprintf( buf, "%3d) %s is carried by %s [Room %d]\n\r",
                number, obj->short_descr,PERS(in_obj->carried_by, ch),
		in_obj->carried_by->in_room->vnum );
        else if (in_obj->in_room != NULL && can_see_room(ch,in_obj->in_room))
            sprintf( buf, "%3d) %s is in %s [Room %d]\n\r",
                number, obj->short_descr,in_obj->in_room->name, 
	   	in_obj->in_room->vnum);
	else
            sprintf( buf, "%3d) %s is somewhere\n\r",number, obj->short_descr);
 
        buf[0] = UPPER(buf[0]);
        add_buf(buffer,buf);
 
        if (number >= max_found)
            break;
    }
 
    if ( !found )
        send_to_char( "Nothing like that in heaven or earth.\n\r", ch );
    else
        page_to_char(buf_string(buffer),ch);

    free_buf(buffer);
}


ACMD(do_mwhere) {
    char buf[MAX_STRING_LENGTH];
    BUFFER *buffer;
    CHAR_DATA *victim;
    bool found;
    int count = 0;

    if ( argument[0] == '\0' )
    {
	DESCRIPTOR_DATA *d;

	/* show characters logged */

	buffer = new_buf();
	for (d = descriptor_list; d != NULL; d = d->next)
	{
	    if (d->character != NULL && d->connected == CON_PLAYING
	    &&  d->character->in_room != NULL && can_see(ch,d->character)
	    &&  can_see_room(ch,d->character->in_room))
	    {
		victim = d->character;
		count++;
		if (d->original != NULL)
		    sprintf(buf,"%3d) %s (in the body of %s) is in %s [%d]\n\r",
			count, d->original->name,victim->short_descr,
			victim->in_room->name,victim->in_room->vnum);
		else
		    sprintf(buf,"%3d) %s is in %s [%d]\n\r",
			count, victim->name,victim->in_room->name,
			victim->in_room->vnum);
		add_buf(buffer,buf);
	    }
	}

        page_to_char(buf_string(buffer),ch);
	free_buf(buffer);
	return;
    }

    found = FALSE;
    buffer = new_buf();
    for ( victim = char_list; victim != NULL; victim = victim->next )
    {
	if ( victim->in_room != NULL
	&&   is_name( argument, victim->name ) )
	{
	    found = TRUE;
	    count++;
	    sprintf( buf, "%3d) [%5d] %-28s [%5d] %s\n\r", count,
		IS_NPC(victim) ? victim->pIndexData->vnum : 0,
		IS_NPC(victim) ? victim->short_descr : victim->name,
		victim->in_room->vnum,
		victim->in_room->name );
	    add_buf(buffer,buf);
	}
    }

    if ( !found )
	act( "You didn't find any $T.", ch, NULL, argument, TO_CHAR );
    else
    	page_to_char(buf_string(buffer),ch);

    free_buf(buffer);

    return;
}



ACMD(do_reboot) {
    extern bool merc_down;
    DESCRIPTOR_DATA *d,*d_next;
    CHAR_DATA *vch;

    send_to_all("Rebooting.. come back in a minute or two.\n\r");
    merc_down = TRUE;
    for ( d = descriptor_list; d != NULL; d = d_next )
    {
	d_next = d->next;
	vch = Original(d);
	if (vch != NULL)
	    save_char_obj(vch);
    	close_socket(d);
    }
    
    return;
}

ACMD(do_shutdown) {
    extern bool merc_down;
    DESCRIPTOR_DATA *d,*d_next;
    CHAR_DATA *vch;

    send_to_all("Shutting down for maintenance.\n\r");
    touch(SHUTDOWN_FILE);
    merc_down = TRUE;
    for ( d = descriptor_list; d != NULL; d = d_next)
    {
	d_next = d->next;
	vch = Original(d);
	if (vch != NULL)
	    save_char_obj(vch);
	close_socket(d);
    }
    return;
}

ACMD(do_protect) {
    CHAR_DATA *victim;

    if (argument[0] == '\0')
    {
	send_to_char("Protect whom from snooping?\n\r",ch);
	return;
    }

    if ((victim = get_char_world(ch,argument)) == NULL)
    {
	send_to_char("You can't find them.\n\r",ch);
	return;
    }

    if (IS_SET(victim->comm,COMM_SNOOP_PROOF))
    {
	act_new("$N is no longer snoop-proof.",ch,NULL,victim,TO_CHAR,POS_DEAD, TRUE, FALSE);
	send_to_char("Your snoop-proofing was just removed.\n\r",victim);
	REMOVE_BIT(victim->comm,COMM_SNOOP_PROOF);
    }
    else
    {
	act_new("$N is now snoop-proof.",ch,NULL,victim,TO_CHAR,POS_DEAD, TRUE, FALSE);
	send_to_char("You are now immune to snooping.\n\r",victim);
	SET_BIT(victim->comm,COMM_SNOOP_PROOF);
    }
}
  


ACMD(do_snoop) {
    char arg[MAX_INPUT_LENGTH];
    DESCRIPTOR_DATA *d;
    CHAR_DATA *victim;

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char( "Snoop whom?\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( victim->desc == NULL )
    {
	send_to_char( "No descriptor to snoop.\n\r", ch );
	return;
    }

    if ( victim == ch )
    {
	send_to_char( "Cancelling all snoops.\n\r", ch );
	for ( d = descriptor_list; d != NULL; d = d->next )
	{
	    if ( d->snoop_by == ch->desc )
		d->snoop_by = NULL;
	}
	return;
    }

    if ( victim->desc->snoop_by != NULL )
    {
	send_to_char( "Busy already.\n\r", ch );
	return;
    }

    if (!is_room_owner(ch,victim->in_room) && ch->in_room != victim->in_room 
    &&  room_is_private(victim->in_room) && !IS_TRUSTED(ch,IMPLEMENTOR))
    {
        send_to_char("That character is in a private room.\n\r",ch);
        return;
    }

    if (STATE(victim->desc) >= CON_MENU && STATE(victim->desc) <= CON_EXDESC) {
	ch->Send("%s is in private mode, snoop someone else.\n\r", RealName(victim));
	return;
    }

    if ( get_trust( victim ) >= get_trust( ch ) 
    ||   IS_SET(victim->comm,COMM_SNOOP_PROOF))
    {
	send_to_char( "You failed.\n\r", ch );
	return;
    }

    if ( ch->desc != NULL )
    {
	for ( d = ch->desc->snoop_by; d != NULL; d = d->snoop_by )
	{
	    if ( d->character == victim || d->original == victim )
	    {
		send_to_char( "No snoop loops.\n\r", ch );
		return;
	    }
	}
    }

    victim->desc->snoop_by = ch->desc;
    mudlogf(NRM, get_trust(ch), TRUE, "%s starts snooping %s",
	RealName(ch), RealName(victim));
    send_to_char( "Okay.\n\r", ch );
    return;
}



ACMD(do_switch) {
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    one_argument( argument, arg );
    
    if ( arg[0] == '\0' )
    {
	send_to_char( "Switch into whom?\n\r", ch );
	return;
    }

    if ( ch->desc == NULL )
	return;
    
    if ( ch->desc->original != NULL )
    {
	send_to_char( "You are already switched.\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    if ( victim == ch )
    {
	send_to_char( "Okay.\n\r", ch );
	return;
    }

    if (!IS_NPC(victim))
    {
	send_to_char("You can only switch into mobiles.\n\r",ch);
	return;
    }

    if (!is_room_owner(ch,victim->in_room) && ch->in_room != victim->in_room 
    &&  room_is_private(victim->in_room) && !IS_TRUSTED(ch,IMPLEMENTOR))
    {
	send_to_char("That character is in a private room.\n\r",ch);
	return;
    }

    if ( victim->desc != NULL )
    {
	send_to_char( "Character in use.\n\r", ch );
	return;
    }

    mudlogf(NRM, get_trust(ch), TRUE, "(GC) %s switches into %s",
	RealName(ch), RealName(victim));

    ch->desc->character = victim;
    ch->desc->original  = ch;
    victim->desc        = ch->desc;
    ch->desc            = NULL;
    /* change communications to match */
    if (ch->prompt != NULL)
        victim->prompt = str_dup(ch->prompt);
    victim->comm = ch->comm;
    victim->lines = ch->lines;
    send_to_char( "Okay.\n\r", victim );
    return;
}



ACMD(do_return) {

    if ( ch->desc == NULL )
	return;

    if ( ch->desc->original == NULL )
    {
	send_to_char( "You aren't switched.\n\r", ch );
	return;
    }

    send_to_char( 
    "You return to your original body. Type replay to see any missed tells.\n\r", ch);
    if (ch->prompt != NULL)
    {
	free_string(ch->prompt);
	ch->prompt = NULL;
    }

    mudlogf(NRM, get_trust(ch->desc->original), FALSE, "(GC) %s returns from %s",
	RealName(ch->desc->original), RealName(ch));

    ch->desc->character       = ch->desc->original;
    ch->desc->original        = NULL;
    ch->desc->character->desc = ch->desc; 
    ch->desc                  = NULL;
    return;
}

/* trust levels for load and clone */
bool obj_check (CHAR_DATA *ch, OBJ_DATA *obj)
{
    if (IS_TRUSTED(ch,GOD)
	|| (IS_TRUSTED(ch,IMMORTAL) && obj->level <= 20 && obj->cost <= 1000)
	|| (IS_TRUSTED(ch,DEMI)	    && obj->level <= 10 && obj->cost <= 500)
	|| (IS_TRUSTED(ch,ANGEL)    && obj->level <=  5 && obj->cost <= 250)
	|| (IS_TRUSTED(ch,AVATAR)   && obj->level ==  0 && obj->cost <= 100))
	return TRUE;
    else
	return FALSE;
}

/* for clone, to insure that cloning goes many levels deep */
void recursive_clone(CHAR_DATA *ch, OBJ_DATA *obj, OBJ_DATA *clone)
{
    OBJ_DATA *c_obj, *t_obj;


    for (c_obj = obj->contains; c_obj != NULL; c_obj = c_obj->next_content)
    {
	if (obj_check(ch,c_obj))
	{
	    t_obj = create_object(c_obj->pIndexData,0);
	    clone_object(c_obj,t_obj);
	    obj_to_obj(t_obj,clone);
	    recursive_clone(ch,c_obj,t_obj);
	}
    }
}

/* command that is similar to load */
ACMD(do_clone) {
    char arg[MAX_INPUT_LENGTH];
    char *rest;
    CHAR_DATA *mob;
    OBJ_DATA  *obj;

    rest = one_argument(argument,arg);

    if (arg[0] == '\0')
    {
	send_to_char("Clone what?\n\r",ch);
	return;
    }

    if (!str_prefix(arg,"object"))
    {
	mob = NULL;
	obj = get_obj_here(ch,rest);
	if (obj == NULL)
	{
	    send_to_char("You don't see that here.\n\r",ch);
	    return;
	}
    }
    else if (!str_prefix(arg,"mobile") || !str_prefix(arg,"character"))
    {
	obj = NULL;
	mob = get_char_room(ch,rest);
	if (mob == NULL)
	{
	    send_to_char("You don't see that here.\n\r",ch);
	    return;
	}
    }
    else /* find both */
    {
	mob = get_char_room(ch,argument);
	obj = get_obj_here(ch,argument);
	if (mob == NULL && obj == NULL)
	{
	    send_to_char("You don't see that here.\n\r",ch);
	    return;
	}
    }

    /* clone an object */
    if (obj != NULL)
    {
	OBJ_DATA *clone;

	if (!obj_check(ch,obj))
	{
	    send_to_char(
		"Your powers are not great enough for such a task.\n\r",ch);
	    return;
	}

	clone = create_object(obj->pIndexData,0); 
	clone_object(obj,clone);
	if (obj->carried_by != NULL)
	    obj_to_char(clone,ch);
	else
	    obj_to_room(clone,ch->in_room);
 	recursive_clone(ch,obj,clone);

	act("$n has created $p.",ch,clone,NULL,TO_ROOM);
	act("You clone $p.",ch,clone,NULL,TO_CHAR);
	mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s clones obj %d",
		RealName(ch), clone->pIndexData->vnum);
	return;
    }
    else if (mob != NULL)
    {
	CHAR_DATA *clone;
	OBJ_DATA *new_obj;

	if (!IS_NPC(mob))
	{
	    send_to_char("You can only clone mobiles.\n\r",ch);
	    return;
	}

	if ((mob->level > 20 && !IS_TRUSTED(ch,GOD))
	||  (mob->level > 10 && !IS_TRUSTED(ch,IMMORTAL))
	||  (mob->level >  5 && !IS_TRUSTED(ch,DEMI))
	||  (mob->level >  0 && !IS_TRUSTED(ch,ANGEL))
	||  !IS_TRUSTED(ch,AVATAR))
	{
	    send_to_char(
		"Your powers are not great enough for such a task.\n\r",ch);
	    return;
	}

	clone = create_mobile(mob->pIndexData);
	clone_mobile(mob,clone); 
	
	for (obj = mob->carrying; obj != NULL; obj = obj->next_content)
	{
	    if (obj_check(ch,obj))
	    {
		new_obj = create_object(obj->pIndexData,0);
		clone_object(obj,new_obj);
		recursive_clone(ch,obj,new_obj);
		obj_to_char(new_obj,clone);
		new_obj->wear_loc = obj->wear_loc;
	    }
	}
	char_to_room(clone,ch->in_room);
        act("$n has created $N.",ch,NULL,clone,TO_ROOM);
        act("You clone $N.",ch,NULL,clone,TO_CHAR);
	mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s clones mob %d",
		RealName(ch), clone->pIndexData->vnum);
        return;
    }
}

/* RT to replace the two load commands */
ACMD(do_load) {
    int  number;
    char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH];

    argument = one_argument(argument, arg1);
    argument = one_argument(argument, arg2);

    if (!*arg1 || !*arg2 || !isdigit(*arg2))
	send_to_char("Usage: load { obj | mob } <number>\n\r", ch);
    else if ((number = atoi(arg2)) < 0)
	send_to_char("A negative number? Think POSITIVE!\n\r", ch);
    else if (!str_prefix(arg1, "mob")) {
	CHAR_DATA *mob;
	MOB_INDEX_DATA *pMob;
	if ((pMob = get_mob_index(number)) == NULL)
		send_to_char("There is no monster with that number.\n\r", ch);
	else {
		mob = create_mobile(pMob);
		char_to_room(mob, IN_ROOM(ch));
		act("$n has created $N!", ch, NULL, mob, TO_ROOM);
		act("You create $N.", ch, NULL, mob, TO_CHAR);
		mudlogf(NRM, LVL_STAFF, TRUE,"(GC) %s has loaded mob #%d.",
			RealName(ch), pMob->vnum);
	}
    } else if (!str_prefix(arg1, "obj")) {
	OBJ_DATA *obj;
	OBJ_INDEX_DATA *pObj;
	if ((pObj = get_obj_index(number)) == NULL)
		send_to_char("There is no object with that number.\n\r", ch);
	else {
		obj = create_object(pObj, get_trust(ch));
		if (CAN_WEAR(obj, ITEM_TAKE))
			obj_to_char(obj, ch);
		else
			obj_to_room(obj, IN_ROOM(ch));
		act("$n has created $p!", ch, obj, NULL, TO_ROOM);
		act("You create $p.", ch, obj, NULL, TO_CHAR);
		mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s has loaded obj #%d.",
			RealName(ch), pObj->vnum);
	}
    } else
	send_to_char("That'll have to be either 'obj' or 'mob'.\n\r", ch);
    return;
}

/*
 * New Purge: Allows room, NPC/PC, and objects. -Mendanbar
 */
ACMD(do_purge) {
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA		*obj;
    CHAR_DATA		*vict;
    DESCRIPTOR_DATA	*d;
    bool ok_purge = STF_FLAGGED(ch, STAFF_ADMIN);

    one_argument(argument, arg);

    if (arg[0] != '\0') {
	if ((vict = get_char_world(ch, arg))) {
	    if (!IS_NPC(vict)) {
		if (ch == vict) {
		    send_to_char("Ho ho ho!\n\r", ch);
		    return;
		}
		if (get_trust(ch) <= get_trust(vict)) {
		    send_to_char("Maybe that wasn't a good idea.\n\r",ch);
		    act("$n tried to purge you!", ch, 0, vict, TO_VICT);
		    return;
		}
		act("$n disintegrates $N.",ch, NULL,vict,TO_NOTVICT);
		mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s has purged %s.", RealName(ch), RealName(vict));
		if (vict->level > 1)
			save_char_obj(vict);
		if (!IS_NPC(vict)) {
		    if (vict->desc) {
			STATE(vict->desc) = CON_DISCONNECT;
			vict->desc->character = NULL;
			vict->desc = NULL;
		    }
		}
		extract_char(vict);
	    } else {
		if (MOB_FLAGGED(vict, ACT_NOPURGE) && !ok_purge) {
			act("Woops! $E is immune to being purged.", ch, NULL, vict, TO_CHAR);
			return;
		}
		act("$n disintegrates $N.", ch, NULL, vict, TO_NOTVICT);
		extract_char( vict );
	    }
	} else if ((obj = get_obj_here(ch, arg))) {
	    if (OBJ_FLAGGED(obj, ITEM_NOPURGE) && !ok_purge) {
		act("$p cannot be destroyed!", ch, obj, NULL, TO_CHAR);
		return;
	    }
	    act("$n destroys $p.", ch, obj, NULL, TO_ROOM);
	    extract_obj(obj);
	} else {
	    send_to_char("Nothing here by that name.\n\r", ch);
	    return;
	}
	send_to_char("Okay.\n\r", ch);
    } else {
	OBJ_DATA	*obj_next;
	CHAR_DATA	*vnext;
	act("$n gestures... You are surrounded by scorching flames!",
		ch, NULL, NULL, TO_ROOM);

	IN_ROOM(ch)->Send("The world seems a little cleaner.\n\r");

	// mobs and objects that are nopurge do not purge automatically
	// you have to purge them one by one, just a safty feature. -M
	for (vict = IN_ROOM(ch)->people; vict != NULL; vict = vnext) {
	    vnext = vict->next_in_room;
	    if (IS_NPC(vict) && !MOB_FLAGGED(vict, ACT_NOPURGE) && (vict != ch))
		extract_char( vict );
	}
	for (obj = IN_ROOM(ch)->contents; obj != NULL; obj = obj_next) {
	    obj_next = obj->next_content;
	    if (!OBJ_FLAGGED(obj, ITEM_NOPURGE))
		extract_obj( obj );
	}
    }
    return;
}

ACMD(do_advance) {
    char buf[MAX_STRING_LENGTH];
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    int level, oldlevel, iLevel;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' || arg2[0] == '\0' || !is_number( arg2 ) )
    {
	send_to_char( "Syntax: advance <char> <level>.\n\r", ch );
	return;
    }

    if ( ( victim = get_pc_world( ch, arg1 ) ) == NULL )
    {
	send_to_char( "That player is not here.\n\r", ch);
	return;
    }

    if ( ( level = atoi( arg2 ) ) < 1 || level > MAX_LEVEL )
    {
	sprintf(buf,"Level must be 1 to %d.\n\r", MAX_LEVEL);
	send_to_char(buf, ch);
	return;
    }

    if ( level > get_trust( ch ) )
    {
	send_to_char( "Limited to your trust level.\n\r", ch );
	return;
    }

    /*
     * Lower level:
     *   Reset to level 1.
     *   Then raise again.
     *   Currently, an imp can lower another imp.
     *   -- Swiftest
     */
    if ( level <= victim->level )
    {
        int temp_prac;

	send_to_char( "Lowering a player's level!\n\r", ch );
	send_to_char( "**** OOOOHHHHHHHHHH  NNNNOOOO ****\n\r", victim );
	if (victim->level >= LEVEL_IMMORTAL || level >= LEVEL_IMMORTAL)
		update_wizlist(victim, level);
	temp_prac = victim->practice;
	oldlevel	= victim->level;
	victim->level	= 1;
	victim->hero_level = 0;
	victim->exp      = exp_per_level(victim,victim->pcdata->points);
	victim->max_hit  = 10;
	victim->max_mana = 100;
	victim->max_move = 100;
	victim->practice = 0;
	victim->hit      = victim->max_hit;
	victim->mana     = victim->max_mana;
	victim->move     = victim->max_move;
	advance_level( victim, TRUE );
	victim->practice = temp_prac;
    }
    else
    {
	send_to_char( "Raising a player's level!\n\r", ch );
	send_to_char( "**** OOOOHHHHHHHHHH  YYYYEEEESSS ****\n\r", victim );
	if (victim->level >= LEVEL_IMMORTAL || level >= LEVEL_IMMORTAL)
		update_wizlist(victim, level);
	oldlevel = victim->level;
    }

    for (iLevel = victim->level ; iLevel < level; iLevel++)
    {
	victim->level += 1;
	advance_level( victim,TRUE);
    }
    victim->Send("You are now level %d.\n\r", victim->level);
    victim->exp   = exp_per_level(victim,victim->pcdata->points) 
		  * UMAX( 1, victim->level );
    victim->trust = 0;
    mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s has advanced %s to level %d (from %d)",
	RealName(ch), RealName(victim), victim->level, oldlevel);
    save_char_obj(victim);
    return;
}


ACMD(do_trust) {
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *victim;
    int level;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if (arg1[0] == '\0' || arg2[0] == '\0' || !is_number(arg2))
    {
	send_to_char("Syntax: trust <char> <level>.\n\r", ch);
	return;
    }

    if ((victim = get_char_world(ch, arg1)) == NULL)
    {
	send_to_char("That player is not here.\n\r", ch);
	return;
    }

    if ((level = atoi(arg2)) < 0 || level > MAX_LEVEL)
    {
	sprintf(buf, "Level must be 0 (reset) or 1 to %d.\n\r",MAX_LEVEL);
	send_to_char(buf, ch);
	return;
    }

    if (level > get_trust(ch))
    {
	send_to_char("Limited to your trust.\n\r", ch);
	return;
    }

    victim->trust = level;
    mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s trusted %s at level %s.",
	RealName(ch), RealName(victim), victim->trust);
    return;
}


ACMD(do_restore) {
    CHAR_DATA *victim;
    CHAR_DATA *vch;
    DESCRIPTOR_DATA *d;
    char arg[MAX_INPUT_LENGTH];

    if (IS_NPC(ch)) return;
    one_argument(argument, arg);
    if (arg[0] == '\0' || !str_cmp(arg,"room"))
    {
        for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room)
        {
            affect_strip(vch,gsn_plague);
            affect_strip(vch,gsn_poison);
            affect_strip(vch,gsn_blindness);
            affect_strip(vch,gsn_sleep);
            affect_strip(vch,gsn_curse);
	    affect_strip(vch,gsn_intoxication);
            
            vch->hit 	= vch->max_hit;
            vch->mana	= vch->max_mana;
            vch->move	= vch->max_move;
            update_pos(vch);
                if (ch->pcdata->r_msg[0] != '\0')
                    act(ch->pcdata->r_msg,ch,NULL,vch,TO_VICT);
                else
            act("$n has restored you.",ch,NULL,vch,TO_VICT);
        }

	mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s restores room #%d.",
		RealName(ch), IN_ROOM(ch)->vnum);
        send_to_char("Room restored.\n\r",ch);
        return;
    }
    
    if (get_trust(ch) >=  MAX_LEVEL - 1 && !str_cmp(arg,"all"))
    {
        for (d = descriptor_list; d != NULL; d = d->next)
        {
	    victim = d->character;

	    if (victim == NULL || IS_NPC(victim))
		continue;
                
            affect_strip(victim, gsn_plague);
            affect_strip(victim, gsn_poison);
            affect_strip(victim, gsn_blindness);
            affect_strip(victim, gsn_sleep);
            affect_strip(victim, gsn_curse);
	    affect_strip(victim, gsn_intoxication);

            victim->hit 	= victim->max_hit;
            victim->mana	= victim->max_mana;
            victim->move	= victim->max_move;
            update_pos(victim);
	    if (victim->in_room != NULL) {
		if (ch->pcdata->r_msg[0] != '\0')
		    act(ch->pcdata->r_msg,ch,NULL,victim,TO_VICT);
		else
                    act("$n has restored you.",ch,NULL,victim,TO_VICT);
            	}
	}
	mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s restores all players.", RealName(ch));
	send_to_char("All active players restored.\n\r",ch);
	return;
    }

    if ((victim = get_char_world(ch, arg)) == NULL)
    {
	send_to_char("They aren't here.\n\r", ch);
	return;
    }

    affect_strip(victim, gsn_plague);
    affect_strip(victim, gsn_poison);
    affect_strip(victim, gsn_blindness);
    affect_strip(victim, gsn_sleep);
    affect_strip(victim, gsn_curse);
    affect_strip(victim, gsn_intoxication);
    victim->hit  = victim->max_hit;
    victim->mana = victim->max_mana;
    victim->move = victim->max_move;
    update_pos( victim );
    if (ch->pcdata->r_msg[0] != '\0')
	act(ch->pcdata->r_msg, ch, NULL, victim, TO_VICT);
    else
	act( "$n has restored you.", ch, NULL, victim, TO_VICT );
    mudlogf(NRM, LVL_STAFF, TRUE, "%s restores %s.", RealName(ch), RealName(victim));
    send_to_char("Okay.\n\r", ch);
    return;
}

 	
ACMD(do_freeze) {
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    one_argument(argument, arg);

    if (arg[0] == '\0')
    {
	send_to_char("Freeze whom?\n\r", ch);
	return;
    }

    if ((victim = get_char_world(ch, arg)) == NULL)
    {
	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(victim) >= get_trust(ch))
    {
	send_to_char("You failed.\n\r", ch);
	return;
    }

    if (IS_SET(victim->act, PLR_FREEZE))
    {
	REMOVE_BIT(victim->act, PLR_FREEZE);
	send_to_char("You can play again.\n\r", victim);
	send_to_char("FREEZE removed.\n\r", ch);
	mudlogf(NRM, LVL_SRSTAFF, TRUE, "%s unfreezes %s", RealName(ch), RealName(victim));
    }
    else
    {
	SET_BIT(victim->act, PLR_FREEZE);
	send_to_char("You can't do ANYthing!\n\r", victim);
	send_to_char("FREEZE set.\n\r", ch);
	mudlogf(NRM, LVL_STAFF, TRUE, "%s freezes %s", RealName(ch), RealName(victim));
    }

    save_char_obj(victim);
    return;
}


ACMD(do_log) {
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    one_argument(argument, arg);

    if (arg[0] == '\0')
    {
	send_to_char("Log whom?\n\r", ch);
	return;
    }

    if (!str_cmp(arg, "all"))
    {
	if (fLogAll)
	{
	    fLogAll = FALSE;
	    send_to_char("Log ALL off.\n\r", ch);
	    mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s sets log ALL off.", RealName(ch));
	}
	else
	{
	    fLogAll = TRUE;
	    send_to_char("Log ALL on.\n\r", ch);
	    mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s sets log ALL on.", RealName(ch));
	}
	return;
    }

    if ((victim = get_pc_world(ch, arg)) == NULL)
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    /*
     * No level check, gods can log anyone.
     */
    if (IS_SET(victim->act, PLR_LOG))
    {
	REMOVE_BIT(victim->act, PLR_LOG);
	send_to_char("LOG removed.\n\r", ch);
	mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s removes log on %s.", RealName(ch), RealName(victim));
    }
    else
    {
	SET_BIT(victim->act, PLR_LOG);
	send_to_char("LOG set.\n\r", ch);
	mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s sets log on %s.", RealName(ch), RealName(victim));
    }
    return;
}

ACMD(do_mute) {
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;

    one_argument(argument, arg);

    if (!*arg) {
	send_to_char("Mute whom?\n\r", ch);
	return;
    }

    if ((victim = get_pc_world(ch, arg)) == NULL) {
	send_to_char("They aren't here.\n\r", ch);
	return;
    }

    if (get_trust(victim) >= get_trust(ch)) {
	send_to_char("You failed.\n\r", ch);
	return;
    }

    if (COMM_FLAGGED(victim, COMM_MUTED)) {
	REMOVE_BIT(CHN_FLAGS(victim), COMM_MUTED);
	send_to_char("You can talk again.\n\r", victim);
	ch->Send("%s unmuted.\n\r", victim->name);
	mudlogf(NRM, LVL_SRSTAFF, TRUE, "(GC) Squelch off for %s by %s.",
		RealName(ch), RealName(victim));
    } else {
	SET_BIT(CHN_FLAGS(victim), COMM_MUTED);
	send_to_char("You can't talk!\n\r", victim);
	ch->Send("%s muted.\n\r", victim->name);
	mudlogf(NRM, LVL_SRSTAFF, TRUE, "(GC) Squelch on for %s by %s.",
		RealName(ch), RealName(victim));
    }
    return;
}

ACMD(do_peace) {
    CHAR_DATA *vch;
    char arg[MAX_INPUT_LENGTH];

    argument = one_argument(argument, arg);

    if (*arg && !str_prefix(arg, "all")) {
	for (vch = char_list; vch != NULL; vch = vch->next) {
	    if ((vch != ch) && (IN_ROOM(vch) != NULL)
	    && get_trust(ch) > get_trust(vch) && can_see(ch, vch))
	    {
		if (vch->fighting != NULL) {
		    stop_fighting(vch, TRUE);
		    if (MOB_FLAGGED(vch, ACT_AGGRESSIVE))
			REMOVE_BIT(MOB_FLAGS(vch), ACT_AGGRESSIVE);
		}
		act("A wave of calm passes over you.", vch, 0, 0, TO_CHAR);
	    }
	}
    mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s has pacified the world.", RealName(ch));
    ch->Send("The world has been pacified.\n\r");
    } else {
	for (vch = IN_ROOM(ch)->people; vch != NULL; vch = vch->next_in_room) {
	    if (vch->fighting != NULL)
		stop_fighting(vch, TRUE);
	    if (IS_NPC(vch) && IS_SET(vch->act,ACT_AGGRESSIVE))
		REMOVE_BIT(vch->act,ACT_AGGRESSIVE);
	}
	IN_ROOM(ch)->Send("A wave of calm passes over you.\n\r");
    }
    return;
}

ACMD(do_wizlock) {
    extern bool wizlock;
    wizlock = !wizlock;

    if ( wizlock )
    {
	mudlogf(NRM, LVL_STAFF, TRUE, "%s has wizlocked the game.", RealName(ch));
	send_to_char( "Game wizlocked.\n\r", ch );
    }
    else
    {
	mudlogf(NRM, LVL_STAFF, TRUE, "%s removes wizlock on the game.", RealName(ch));
	send_to_char( "Game un-wizlocked.\n\r", ch );
    }

    return;
}

/* RT anti-newbie code */
ACMD(do_newlock) {
    extern bool newlock;
    newlock = !newlock;
 
    if ( newlock )
    {
	mudlogf(NRM, LVL_STAFF, TRUE, "%s locks out new characters.", RealName(ch));
        send_to_char( "New characters have been locked out.\n\r", ch );
    }
    else
    {
	mudlogf(NRM, LVL_STAFF, TRUE, "%s removes the newlock.", RealName(ch));
        send_to_char( "Newlock removed.\n\r", ch );
    }
 
    return;
}


ACMD(do_slookup) {
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    int sn;

    one_argument( argument, arg );
    if ( arg[0] == '\0' )
    {
	send_to_char( "Lookup which skill or spell?\n\r", ch );
	return;
    }

    if ( !str_cmp( arg, "all" ) )
    {
	for ( sn = 0; sn < MAX_SKILL; sn++ )
	{
	    if ( skill_table[sn].name == NULL )
		break;
	    sprintf( buf, "Sn: %3d  Slot: %3d  Skill/spell: '%s'\n\r",
		sn, skill_table[sn].slot, skill_table[sn].name );
	    send_to_char( buf, ch );
	}
    }
    else
    {
	if ( ( sn = skill_lookup( arg ) ) < 0 )
	{
	    send_to_char( "No such skill or spell.\n\r", ch );
	    return;
	}

	sprintf( buf, "Sn: %3d  Slot: %3d  Skill/spell: '%s'\n\r",
	    sn, skill_table[sn].slot, skill_table[sn].name );
	send_to_char( buf, ch );
    }

    return;
}

#define PC   1
#define NPC  2
#define BOTH 3

#define MISC    0
#define BINARY  1
#define NUMBER  2

#define SET_OR_REMOVE(flagset, flags) { \
	if (on) SET_BIT(flagset, flags); \
	else if (off) REMOVE_BIT(flagset, flags); }

#define RANGE(low, high) (value = UMAX((low), UMIN((high), (value))))
#define CAP(st)  (*(st) = UPPER(*(st)), st)

struct set_struct {
	char *cmd;
	char level;
	char pcnpc;
	char type;
} set_fields[] = {
	{ "str",	LVL_SRSTAFF,	BOTH,	NUMBER	},
	{ "int",	LVL_SRSTAFF,	BOTH,	NUMBER	},
	{ "wis",	LVL_SRSTAFF,	BOTH,	NUMBER	},
	{ "dex",	LVL_SRSTAFF,	BOTH,	NUMBER	},
	{ "con",	LVL_SRSTAFF,	BOTH,	NUMBER	},
	{ "cha",	LVL_SRSTAFF,	BOTH,	NUMBER	},
	{ "class",	LVL_SRSTAFF,	PC,	MISC	},
	{ "level",	LVL_ADMIN,	BOTH,	NUMBER	},
	{ "race",	LVL_SRSTAFF,	BOTH,	MISC	},
	{ "gold",	LVL_SRSTAFF,	BOTH,	NUMBER	},
	{ "silver",	LVL_SRSTAFF,	BOTH,	NUMBER	},
	{ "hit",	LVL_SRSTAFF,	BOTH,	NUMBER	},
	{ "maxhit",	LVL_SRSTAFF,	BOTH,	NUMBER	},
	{ "mana",	LVL_SRSTAFF,	BOTH,	NUMBER	},
	{ "maxmana",	LVL_SRSTAFF,	BOTH,	NUMBER	},
	{ "move",	LVL_SRSTAFF,	BOTH,	NUMBER	},
	{ "maxmove",	LVL_SRSTAFF,	BOTH,	NUMBER	},
	{ "practice",	LVL_SRSTAFF,	PC,	NUMBER	},
	{ "train",	LVL_SRSTAFF,	PC,	NUMBER	},
	{ "align",	LVL_STAFF,	BOTH,	NUMBER	},
	{ "thirst",	LVL_STAFF,	PC,	NUMBER	},
	{ "full",	LVL_STAFF,	PC,	NUMBER	},
	{ "hunger",	LVL_STAFF,	PC,	NUMBER	},
	{ "drunk",	LVL_STAFF,	PC,	NUMBER	},
	{ "hangover",	LVL_STAFF,	PC,	NUMBER	},
	{ "security",	LVL_SRSTAFF,	PC,	NUMBER	},
	{ "loadroom",	LVL_SRSTAFF,	PC,	NUMBER	},
	{ "room",	LVL_STAFF,	BOTH,	NUMBER	},
	{ "hitroll",	LVL_SRSTAFF,	BOTH,	NUMBER	},
	{ "damroll",	LVL_SRSTAFF,	BOTH,	NUMBER	},
	{ "killer",	LVL_SRSTAFF,	PC,	BINARY	},
	{ "thief",	LVL_SRSTAFF,	PC,	BINARY	},
	{ "nohassle",	LVL_ADMIN,	PC,	BINARY	},
	{ "invis",	LVL_SRSTAFF,	PC,	NUMBER	},
	{ "incog",	LVL_SRSTAFF,	PC,	NUMBER	},
	{ "passwd",	LVL_ADMIN,	PC,	MISC	},
	{ "frozen",	LVL_SRSTAFF,	PC,	BINARY	},
	{ "color",	LVL_STAFF,	PC,	BINARY	},
	{ "sex",	LVL_STAFF,	BOTH,	MISC	},
	{ "title",	LVL_STAFF,	PC,	MISC	},
	{ "siteok",	LVL_SRSTAFF,	PC,	BINARY	},
	{ "pueblo",	LVL_STAFF,	PC,	BINARY	},
	{ "msp",	LVL_STAFF,	PC,	BINARY	},
	{ "cname",	LVL_STAFF,	PC,	MISC	},
	{ "lname",	LVL_STAFF,	PC,	MISC	},
	{ "hlevel",	LVL_ADMIN,	PC,	NUMBER	},
	// Add new commands above this.
	{ "\n",		0,		BOTH,	MISC	}
};

bool perform_set(CHAR_DATA *ch, CHAR_DATA *vict, SInt32 mode, char *val_arg) {
	SInt32	i, value = 0;
	bool	on = FALSE, off = FALSE;
	char	output[MAX_STRING_LENGTH], buf[MAX_STRING_LENGTH];

	if (!vict) {
		send_to_char("Oops, no victim.\n\r", ch);
		return 0;
	}
	if (((IS_STAFF(vict) && !STF_FLAGGED(ch, STAFF_ADMIN)) || STF_FLAGGED(vict, STAFF_CODER)) && (vict != ch)) {
		send_to_char("Maybe that's not such a great idea...\n\r",ch);
		return 0;
	}
	if (get_trust(ch) <= get_trust(vict) && vict != ch) {
		// old trust range also included...
		send_to_char("Maybe that's not such a great idea...\n\r", ch);
		return 0;
	}
	if (get_trust(ch) < set_fields[mode].level) {
		send_to_char("You do not have authority to do that.\n\r",ch);
		return 0;
	}
	if (IS_NPC(vict) && !(set_fields[mode].pcnpc & NPC)) {
		send_to_char("You can't do that to a mob!\n\r", ch);
		return 0;
	} else if (!IS_NPC(vict) && !(set_fields[mode].pcnpc & PC)) {
		send_to_char("You can only do that to a mob!\n\r", ch);
		return 0;
	}
	output[0] = '\0';

	if (set_fields[mode].type == BINARY) {
		if (!strcmp(val_arg, "on") || !strcmp(val_arg, "yes"))
			on = TRUE;
		else if (!strcmp(val_arg, "off") || !strcmp(val_arg, "no"))
			off = TRUE;
		if (!(on || off)) {
			send_to_char("Value must be 'on' or 'off'.\n\r", ch);
			return 0;
		}
		sprintf(output, "%s %s for %s.", set_fields[mode].cmd, ONOFF(on), RealName(vict));
	} else if (set_fields[mode].type == NUMBER) {
		value = atoi(val_arg);
		sprintf(output, "%s's %s set to %d.", RealName(vict),set_fields[mode].cmd, value);
	} else {
		strcpy(output, "Okay.");
	}

	switch (mode) {
		case 0:
			RANGE(3, 25);
			vict->perm_stat[STAT_STR] = value;
			break;
		case 1:
			RANGE(3, 25);
			vict->perm_stat[STAT_INT] = value;
			break;
		case 2:
			RANGE(3, 25);
			vict->perm_stat[STAT_WIS] = value;
			break;
		case 3:
			RANGE(3, 25);
			vict->perm_stat[STAT_DEX] = value;
			break;
		case 4:
			RANGE(3, 25);
			vict->perm_stat[STAT_CON] = value;
			break;
		case 5:
			RANGE(3, 25);
			vict->perm_stat[STAT_CHA] = value;
			break;
		case 6:
			if (!(i = class_lookup(val_arg))) {
				send_to_char("That is not a class.\n\r",ch);
				return FALSE;
			}
			vict->Class = i;
			break;
		case 7:
			if (value > ch->level) {
				send_to_char("You can't do that.\n\r",ch);
				return FALSE;
			}
			RANGE(0, LVL_CODER);
			vict->level = value;
			break;
		case 8:
			if (!(i = race_lookup(val_arg))) {
				send_to_char("That is not a race.\n\r",ch);
				return FALSE;
			}
			if (!IS_NPC(vict) && !race_table[i].pc_race) {
				send_to_char("That is not a PC race.\n\r",ch);
				return FALSE;
			}
			vict->race = i;
			break;
		case 9:
			vict->gold = RANGE(0, 100000);
			break;
		case 10:
			vict->silver = RANGE(0, 100000);
			break;
		case 11:
			vict->hit = RANGE(-10, vict->max_hit);
			break;
		case 12:
			vict->max_hit = RANGE(0, 30000);
			if (!IS_NPC(vict))
				vict->pcdata->perm_hit = value;
			break;
		case 13:
			vict->mana = RANGE(0, vict->max_mana);
			break;
		case 14:
			vict->max_mana = RANGE(0, 30000);
			if (!IS_NPC(vict))
				vict->pcdata->perm_mana = value;
			break;
		case 15:
			vict->move = RANGE(0, vict->max_move);
			break;
		case 16:
			vict->max_move = RANGE(0, 30000);
			if (!IS_NPC(vict))
				vict->pcdata->perm_move = value;
			break;
		case 17:
			vict->practice = RANGE(0, 1000);
			break;
		case 18:
			vict->train = RANGE(0, 1000);
			break;
		case 19:
			vict->alignment = RANGE(-1000, 1000);
			break;
		case 20:
			RANGE(-1,100);
			vict->pcdata->condition[COND_THIRST] = value;
			break;
		case 21:
			RANGE(-1,100);
			vict->pcdata->condition[COND_FULL] = value;
			break;
		case 22:
			RANGE(-1,100);
			vict->pcdata->condition[COND_HUNGER] = value;
			break;
		case 23:
			RANGE(-1,100);
			vict->pcdata->condition[COND_DRUNK] = value;
			break;
		case 24:
			RANGE(-1,100);
			vict->pcdata->condition[COND_HANGOVER] = value;
			break;
		case 25:
			RANGE(0, vict->pcdata->security);
			vict->pcdata->security = value;
			break;
		case 26:
			if (!str_cmp(val_arg, "off"))
				REMOVE_BIT(PLR_FLAGS(vict), PLR_LOADROOM);
			else if (is_number(val_arg)) {
				value = atoi(val_arg);
				if (!get_room_index(value)) {
					send_to_char("That room does not exist!\n\r", ch);
					return FALSE;
				}
				SET_BIT(PLR_FLAGS(vict), PLR_LOADROOM);
				GET_LOADROOM(vict) = value;
				sprintf(output, "%s will enter at room #%d.", RealName(vict), value);
			} else {
				send_to_char("Must be 'off' or a room's virtual number.\n\r", ch);
				return FALSE;
			}
			break;
		case 27:
			ROOM_INDEX_DATA *room;
			if (!(room = get_room_index(value))) {
				send_to_char("No room exists with that number.\n\r", ch);
				return FALSE;
			}
			if (IN_ROOM(vict) != NULL)
				char_from_room(vict);
			char_to_room(vict, room);
			break;
		case 28:
			vict->hitroll = RANGE(-20, 20);
			break;
		case 29:
			vict->damroll = RANGE(-20, 20);
			break;
		case 30:
			SET_OR_REMOVE(PLR_FLAGS(vict), PLR_KILLER);
			break;
		case 31:
			SET_OR_REMOVE(PLR_FLAGS(vict), PLR_THIEF);
			break;
		case 32:
			SET_OR_REMOVE(PLR_FLAGS(vict), PLR_NOHASSLE);
			break;
		case 33:
			vict->invis_level = RANGE(0, get_trust(vict));
			break;
		case 34:
			vict->incog_level = RANGE(0, get_trust(vict));
			break;
		case 35:
			if (vict->level >= ch->level) {
				send_to_char("You cannot change that.\n\r",ch);
				return FALSE;
			} else {
				char *pwdnew;
				smash_tilde(val_arg);
				pwdnew = crypt(val_arg, vict->name);
				free_string(vict->pcdata->pwd);
				vict->pcdata->pwd = str_dup(pwdnew);
				sprintf(output, "Password changed to '%s'.", val_arg);
			}
			break;
		case 36:
			SET_OR_REMOVE(PLR_FLAGS(vict), PLR_FREEZE);
			break;
		case 37:
			SET_OR_REMOVE(PLR_FLAGS(vict), PLR_COLOUR);
			break;
		case 38:
			if (!str_cmp(val_arg, "male")) {
				vict->sex = 1;
				if (!IS_NPC(vict))
					vict->pcdata->true_sex = 1;
			} else if (!str_cmp(val_arg, "female")) {
				vict->sex = 2;
				if (!IS_NPC(vict))
					vict->pcdata->true_sex = 2;
			} else if (!str_cmp(val_arg, "neutral")) {
				vict->sex = 0;
				if (!IS_NPC(vict))
					vict->pcdata->true_sex = 0;
			} else {
				send_to_char("Must be 'male', 'female', or 'neutral'.\n\r", ch);
				return FALSE;
			}
			break;
		case 39:
			set_title(vict, val_arg);
			sprintf(output, "%s's title is now: %s", RealName(vict), val_arg);
			break;
		case 40:
			SET_OR_REMOVE(PLR_FLAGS(vict), PLR_PERMIT);
			break;
		case 41:
			SET_OR_REMOVE(PLR_FLAGS(vict), PLR_PUEBLO);
			break;
		case 42:
			SET_OR_REMOVE(PLR_FLAGS(vict), PLR_MSP);
			break;
		case 43:
			if (!str_cmp(val_arg, "none")) {
				free_string(vict->cname);
				vict->cname = str_dup("");
				sprintf(output, "%s's color name has been cleared.", RealName(vict));
				break;
			}
			if (str_cmp(vict->name, strip_color(val_arg))) {
				send_to_char("That is not a valid name.\n\r", ch);
				return FALSE;
			}
			check_color_string(val_arg);
			free_string(vict->cname);
			vict->cname = str_dup(val_arg);
			sprintf(output, "%s's color name is now: %s", RealName(vict), vict->cname);
			break;
		case 44:
			if (!str_cmp(val_arg, "none")) {
				free_string(vict->lname);
				vict->lname = str_dup("");
				sprintf(output, "%s's last name has been cleared.", RealName(vict));
				break;
			}
			sprintf(buf, " %s", strip_color(val_arg));
			free_string(vict->lname);
			vict->lname = str_dup(buf);
			sprintf(output, "%s's last name is now:%s", RealName(vict), vict->lname);
			break;
		case 45:
			RANGE(1, MAX_HERO_LEVEL);
			vict->hero_level = value;
			break;
		default:
			send_to_char("Can't set that!\n\r", ch);
			return FALSE;
	}
	ch->Send("%s\n\r", CAP(output));
	return TRUE;
}

ACMD(do_set) {
	DESCRIPTOR_DATA *d;
	CHAR_DATA *vict = NULL, *cbuf = NULL;
	char	field[MIL], name[MIL], buf[MIL];
	SInt32	mode = -1, len = 0, i = 0;
	bool	is_file = FALSE, is_mob = FALSE,
		is_player = FALSE, is_list = FALSE, retval;

	argument = one_argument(argument, name);
	if (!str_cmp(name, "@list")) {
		is_list = TRUE;
	} else if (!str_cmp(name, "obj")) {
		do_function(ch, &do_oset, argument, 0);
		return; // heh hieeya! *karate chop*
	} else if (!str_cmp(name, "file")) {
		is_file = TRUE;
		argument = one_argument(argument, name);
	} else if (!str_cmp(name, "player")) {
		is_player = TRUE;
		argument = one_argument(argument, name);
	} else if (!str_cmp(name, "mob")) {
		is_mob = TRUE;
		argument = one_argument(argument, name);
	}
	argument = one_argument(argument, field);
	strcpy(buf, argument);

	if (IS_NULLSTR(name) || (IS_NULLSTR(field) && !is_list)) {
		send_to_char(	"Usage: set <victim> <field> <value>\n\r"
				"       set @list\n\r",ch);
		return;
	}

    if (is_list) {
	send_to_char("Set commands available:\n\r", ch);
	for (i=LVL_STAFF; i <= get_trust(ch); i++) {
		len = 0;
		/* Forgive the hackish stuff below but if the level
		 * doesn't have a command why display it?
		 * - Mendanbar
		 */
		for (mode=0; *set_fields[mode].cmd != '\n'; mode++)
			if (set_fields[mode].level == i) len++;
		if (!len)
			continue;

		len = 1;
		ch->Send("%-3d: ", i);
		for (mode=0; *set_fields[mode].cmd != '\n'; mode++) {
			if (set_fields[mode].level == i) {
				if (((len % 6) == 1) && (len != 1))
					send_to_char("     ", ch);
				ch->Send("%-11.11s%s",
				set_fields[mode].cmd, !(len % 6) ? "\n\r" : "");
				len++;
			}
		}
		if (--len % 6)	send_to_char("\n\r",ch);
		if (len == 0)	send_to_char("None.\n\r",ch);
	}
	return;
    }
	if (!is_file) {
		if (is_player) {
			if (!(vict = get_pc_world(ch, name))) {
				send_to_char("No such player.\n\r", ch);
				return;
			}
		} else {
			if (!(vict = get_char_world(ch, name))) {
				send_to_char("No such creature.\n\r", ch);
				return;
			}
		}
	} else {
		d = new_descriptor();
		if (load_char_obj(d, name, FALSE)) {
			cbuf = Original(d);
			if ((IS_STAFF(cbuf) && !STF_FLAGGED(ch,STAFF_ADMIN)) || STF_FLAGGED(cbuf, STAFF_CODER)) {
				send_to_char("Sorry, you can't do that.\n\r",ch);
				extract_char(cbuf);
				return;
			}
			vict = cbuf;
		} else {
			send_to_char("There is no such player.\n\r", ch);
			free_descriptor(d);
			return;
		}
	}

	len = strlen(field);
	for (mode = 0; *(set_fields[mode].cmd) != '\n'; mode++)
		if (!strncmp(field, set_fields[mode].cmd, len))
			break;

	retval = perform_set(ch, vict, mode, buf);

	if (retval) {
		if (!IS_NPC(vict)) {
			save_char_obj(vict);
			if (is_file)
				send_to_char("Saved in file.\n\r",ch);
		}
	}

	if (is_file)
		extract_char(cbuf);
	return;
}

ACMD(do_sset) {
    char arg1 [MAX_INPUT_LENGTH];
    char arg2 [MAX_INPUT_LENGTH];
    char arg3 [MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    int value, sn;
    bool fAll;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
    argument = one_argument( argument, arg3 );

    if ( arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0' )
    {
	send_to_char( "Syntax:\n\r",ch);
	send_to_char( "  setskill <name> <spell or skill> <value>\n\r",ch);
	send_to_char( "  setskill <name> all <value>\n\r",ch);  
	return;
    }

    if ( ( victim = get_pc_world( ch, arg1 ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    fAll = !str_cmp( arg2, "all" );
    sn   = 0;
    if ( !fAll && ( sn = skill_lookup( arg2 ) ) < 0 )
    {
	send_to_char( "No such skill or spell.\n\r", ch );
	return;
    }

    /*
     * Snarf the value.
     */
    if ( !is_number( arg3 ) )
    {
	send_to_char( "Value must be numeric.\n\r", ch );
	return;
    }

    value = atoi( arg3 );
    if ( value < 0 || value > 100 )
    {
	send_to_char( "Value range is 0 to 100.\n\r", ch );
	return;
    }

    if ( fAll )
    {
	for ( sn = 0; sn < MAX_SKILL; sn++ )
	{
	    if ( skill_table[sn].name != NULL )
		victim->pcdata->learned[sn]	= value;
	}
    }
    else
	victim->pcdata->learned[sn] = value;
    send_to_char("Okay.\n\r", ch);
    return;
}

ACMD(do_string) {
    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;

    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\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;
    	}

	/* clear zone for mobs */
	victim->zone = NULL;

	/* 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;
    	}

    	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(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");

	    ed = new_extra_descr();

	    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_function(ch, &do_string, "", 0);
}

ACMD(do_oset) {
    char arg1 [MAX_INPUT_LENGTH];
    char arg2 [MAX_INPUT_LENGTH];
    char arg3 [MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    int value;

    smash_tilde( argument );
    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
    strcpy( arg3, argument );

    if ( arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0' )
    {
	send_to_char("Syntax:\n\r",ch);
	send_to_char("  set obj <object> <field> <value>\n\r",ch);
	send_to_char("  Field being one of:\n\r",				ch );
	send_to_char("    value0 value1 value2 value3 value4 (v1-v4)\n\r",	ch );
	send_to_char("    extra wear level weight cost timer\n\r",		ch );
	return;
    }

    if ( ( obj = get_obj_world( ch, arg1 ) ) == NULL )
    {
	send_to_char( "Nothing like that in heaven or earth.\n\r", ch );
	return;
    }

    /*
     * Snarf the value (which need not be numeric).
     */
    value = atoi( arg3 );

    /*
     * Set something.
     */
    if ( !str_cmp( arg2, "value0" ) || !str_cmp( arg2, "v0" ) )
    {
	obj->value[0] = UMIN(50,value);
	return;
    }

    if ( !str_cmp( arg2, "value1" ) || !str_cmp( arg2, "v1" ) )
    {
	obj->value[1] = value;
	return;
    }

    if ( !str_cmp( arg2, "value2" ) || !str_cmp( arg2, "v2" ) )
    {
	obj->value[2] = value;
	return;
    }

    if ( !str_cmp( arg2, "value3" ) || !str_cmp( arg2, "v3" ) )
    {
	obj->value[3] = value;
	return;
    }

    if ( !str_cmp( arg2, "value4" ) || !str_cmp( arg2, "v4" ) )
    {
	obj->value[4] = value;
	return;
    }

    if ( !str_prefix( arg2, "extra" ) )
    {
     	if ( ( value = flag_value( extra_flags, arg3 ) ) != NO_FLAG)     
	{
        	TOGGLE_BIT(obj->extra_flags, value);     
	}
     	return;
    }

    if ( !str_prefix( arg2, "wear" ) )
    {
	obj->wear_flags = value;
	return;
    }

    if ( !str_prefix( arg2, "level" ) )
    {
	obj->level = value;
	return;
    }
	
    if ( !str_prefix( arg2, "weight" ) )
    {
	obj->weight = value;
	return;
    }

    if ( !str_prefix( arg2, "cost" ) )
    {
	obj->cost = value;
	return;
    }

    if ( !str_prefix( arg2, "timer" ) )
    {
	obj->timer = value;
	return;
    }
	
    /*
     * Generate usage message.
     */
    do_function(ch, &do_oset, "", 0);
    return;
}

#define USERS_FORMAT \
"format: users [-l minlevel[-maxlevel]] [-n name] [-h host] [-p] [-c] [-m] [-d]\n\r"

ACMD(do_users) {
    CHAR_DATA	*tch;
    DESCRIPTOR_DATA *d, *match;
    SInt32	low = 0, high = MAX_LEVEL, num_can_see = 0;
    bool	playing = FALSE, matching = FALSE, complete = FALSE;
    char	buf[MSL], arg[MIL], name_search[MIL], host_search[MIL];
    char	idletime[10], *timeptr = NULL, mode;
    const char	*state;

    name_search[0] = '\0';
    host_search[0] = '\0';

    while (*argument) {
	argument = one_argument(argument, arg);
	if (*arg == '-') {
		mode = *(arg+1);
		switch (mode) {
			case 'm':	matching = TRUE;	break;
			case 'c':	complete = TRUE;	break;
			case 'p':	playing  = TRUE;	break;
			case 'l':
				playing = TRUE;
				argument = one_argument(argument, arg);
				sscanf(arg, "%d-%d", &low, &high);
				break;
			case 'n':
				playing = TRUE;
				argument = one_argument(argument, name_search);
				break;
			case 'h':
				playing = TRUE;
				argument = one_argument(argument, host_search);
				break;
			case 'd':
			default:
				send_to_char(USERS_FORMAT, ch);
				return;
		}
	} else {
		send_to_char(USERS_FORMAT, ch);
		return;
	}
    }
    strcpy(buf, "Num Race      Name         State          Idl Login@   Site\n\r");
    strcat(buf, "--- --------- ------------ -------------- --- -------- ------------------------\n\r");

    one_argument(argument, arg);

    for (d = descriptor_list; d; d = d->next) {
	tch = Original(d);
	if ((STATE(d) == CON_PLAYING)) {
	    if (!tch)						continue;
	    if (*host_search && !strstr(d->host, host_search))	continue;
	    if (*name_search && str_cmp(RealName(tch), name_search))	continue;
	    if (!can_see(ch, tch))				continue;
	    if ((tch->level < low) || (tch->level > high))	continue;
	} else {
	    if (playing)					continue;
	    if (tch && !can_see(ch, tch))			continue;
	}
	if (matching) {
	    if (!d->host)
		continue;

	    for (match = descriptor_list; match; match = match->next) {
		CHAR_DATA *mch = Original(match);
		if (!match->host || (match == d))
			continue;
		if ((tch && !can_see(ch, tch)) || (mch && !can_see(ch, mch)))
			continue;
		if (!str_cmp(match->host, d->host))
			break;
	    }
	    if (!match)
		continue;
	}
	if (tch) {
		timeptr = asctime(localtime(&tch->logon));
		timeptr += 11;
		*(timeptr + 8) = '\0';
	}

	state = ((STATE(d) == CON_PLAYING) && d->original) ? "Switched" :
		socket_state(STATE(d));

	if ((STATE(d) == CON_PLAYING) && d->character && !IS_STAFF(d->character))
		sprintf(idletime, "%3d", tch->timer);
	else
		sprintf(idletime, "   ");

	strcat(buf, STATE(d) == CON_PLAYING ? "`n" : "`G");

	if (tch && tch->name)
		sprintf(buf + strlen(buf), "%3d [%3d %3s] %-12s %-14.14s %-3s %-8s ",
		d->descriptor, tch->level,
		pc_race_table[tch->race].who_name,
		tch->name, state, idletime, timeptr);
	else
		sprintf(buf + strlen(buf), "%3d     -     %-12s %-14.14s %-3s %-8s ",
		d->descriptor, "UNDEFINED", state, idletime, "00:00:00");
	sprintf(buf + strlen(buf), complete ? "[%-22s]\n\r" : "[%-22.22s]\n\r",
	(d->host && *d->host) ? d->host : "Hostname unknown");
	num_can_see++;
    }
    sprintf(buf + strlen(buf), "\n\r`n%d visible socket%s connected.\n\r",
	num_can_see, num_can_see == 1 ? "" : "s");
    page_to_char(buf, ch);
    return;
}

/*
 * Thanks to Grodyn for pointing out bugs in this function.
 */
ACMD(do_force) {
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];

    argument = one_argument( argument, arg );

    if ( arg[0] == '\0' || argument[0] == '\0' )
    {
	send_to_char( "Force whom to do what?\n\r", ch );
	return;
    }

    one_argument(argument,arg2);
  
    if (!str_cmp(arg2,"delete") || !str_prefix(arg2,"mob"))
    {
	send_to_char("That will NOT be done.\n\r",ch);
	return;
    }

    sprintf( buf, "$n forces you to '%s'.", argument );

    if ( !str_cmp( arg, "all" ) )
    {
	CHAR_DATA *vch;
	CHAR_DATA *vch_next;

	if (get_trust(ch) < MAX_LEVEL - 3)
	{
	    send_to_char("Not at your level!\n\r",ch);
	    return;
	}
	mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s forced all to %s", RealName(ch), argument);
	for ( vch = char_list; vch != NULL; vch = vch_next )
	{
	    vch_next = vch->next;

	    if ( !IS_NPC(vch) && get_trust( vch ) < get_trust( ch ) )
	    {
		act( buf, ch, NULL, vch, TO_VICT );
		interpret( vch, argument );
	    }
	}
    }
    else if (!str_cmp(arg,"players"))
    {
        CHAR_DATA *vch;
        CHAR_DATA *vch_next;
 
        if (get_trust(ch) < MAX_LEVEL - 2)
        {
            send_to_char("Not at your level!\n\r",ch);
            return;
        }

	mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s forced all players to %s", RealName(ch), argument);

        for ( vch = char_list; vch != NULL; vch = vch_next )
        {
            vch_next = vch->next;
 
            if ( !IS_NPC(vch) && get_trust( vch ) < get_trust( ch ) 
	    &&	 vch->level <= LEVEL_HERO)
            {
                act( buf, ch, NULL, vch, TO_VICT );
                interpret( vch, argument );
            }
        }
    }
    else if (!str_cmp(arg,"gods"))
    {
        CHAR_DATA *vch;
        CHAR_DATA *vch_next;
 
        if (get_trust(ch) < MAX_LEVEL - 2)
        {
            send_to_char("Not at your level!\n\r",ch);
            return;
        }
	mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s forced all gods to %s", RealName(ch), argument);
        for ( vch = char_list; vch != NULL; vch = vch_next )
        {
            vch_next = vch->next;
 
            if ( !IS_NPC(vch) && get_trust( vch ) < get_trust( ch )
            &&   vch->level >= LEVEL_HERO)
            {
                act( buf, ch, NULL, vch, TO_VICT );
                interpret( vch, argument );
            }
        }
    }
    else if (!str_prefix(arg, "room")) {
	CHAR_DATA *rch, *rch_next;

	if (get_trust(ch) < MAX_LEVEL - 3) {
		send_to_char("Not at your level buddy!\n\r",ch);
		return;
	}
	mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s forced room %d to %s",
		RealName(ch), IN_ROOM(ch)->vnum, argument);
	for (rch = IN_ROOM(ch)->people; rch != NULL; rch = rch_next) {
		rch_next = rch->next_in_room;
		if (get_trust(rch) < get_trust(ch)) {
			act(buf, ch, NULL, rch, TO_VICT);
			interpret(rch, argument);
		}
	}
    } else {
	CHAR_DATA *victim;

	if ( ( victim = get_char_world( ch, arg ) ) == NULL )
	{
	    send_to_char( "They aren't here.\n\r", ch );
	    return;
	}

	if ( victim == ch )
	{
	    send_to_char( "Aye aye, right away!\n\r", ch );
	    return;
	}

    	if (!is_room_owner(ch,victim->in_room) 
	&&  ch->in_room != victim->in_room 
        &&  room_is_private(victim->in_room) && !IS_TRUSTED(ch,IMPLEMENTOR))
    	{
            send_to_char("That character is in a private room.\n\r",ch);
            return;
        }

	if ( get_trust( victim ) >= get_trust( ch ) )
	{
	    send_to_char( "Do it yourself!\n\r", ch );
	    return;
	}

	if (!IS_NPC(victim) && get_trust(ch) < MAX_LEVEL -3)
	{
	    send_to_char("Not at your level!\n\r",ch);
	    return;
	}

	mudlogf(NRM, LVL_STAFF, TRUE, "(GC) %s forced %s to %s",
		RealName(ch), RealName(victim), argument);
	act( buf, ch, NULL, victim, TO_VICT );
	interpret( victim, argument );
    }
    send_to_char( "Okay.\n\r", ch );
    return;
}



/*
 * New routines by Dionysos.
 */
ACMD(do_invis) {
    int level;
    char arg[MAX_STRING_LENGTH];

    /* RT code for taking a level argument */
    one_argument( argument, arg );

    if ( arg[0] == '\0' ) 
    /* take the default path */

      if ( ch->invis_level)
      {
	  ch->invis_level = 0;
	  act( "$n slowly fades into existence.", ch, NULL, NULL, TO_ROOM );
	  send_to_char( "You slowly fade back into existence.\n\r", ch );
      }
      else
      {
	  ch->invis_level = get_trust(ch);
	  act( "$n slowly fades into thin air.", ch, NULL, NULL, TO_ROOM );
	  send_to_char( "You slowly vanish into thin air.\n\r", ch );
      }
    else
    /* do the level thing */
    {
      level = atoi(arg);
      if (level < 2 || level > get_trust(ch))
      {
	send_to_char("Invis level must be between 2 and your level.\n\r",ch);
        return;
      }
      else
      {
	  ch->reply = NULL;
          ch->invis_level = level;
          act( "$n slowly fades into thin air.", ch, NULL, NULL, TO_ROOM );
          send_to_char( "You slowly vanish into thin air.\n\r", ch );
      }
    }

    return;
}


ACMD(do_incognito) {
    int level;
    char arg[MAX_STRING_LENGTH];
 
    /* RT code for taking a level argument */
    one_argument( argument, arg );
 
    if ( arg[0] == '\0' )
    /* take the default path */
 
      if ( ch->incog_level)
      {
          ch->incog_level = 0;
          act( "$n is no longer cloaked.", ch, NULL, NULL, TO_ROOM );
          send_to_char( "You are no longer cloaked.\n\r", ch );
      }
      else
      {
          ch->incog_level = get_trust(ch);
          act( "$n cloaks $s presence.", ch, NULL, NULL, TO_ROOM );
          send_to_char( "You cloak your presence.\n\r", ch );
      }
    else
    /* do the level thing */
    {
      level = atoi(arg);
      if (level < 2 || level > get_trust(ch))
      {
        send_to_char("Incog level must be between 2 and your level.\n\r",ch);
        return;
      }
      else
      {
          ch->reply = NULL;
          ch->incog_level = level;
          act( "$n cloaks $s presence.", ch, NULL, NULL, TO_ROOM );
          send_to_char( "You cloak your presence.\n\r", ch );
      }
    }
 
    return;
}

/* prefix command: it will put the string typed on each line typed */
ACMD(do_prefix) {
    char buf[MAX_INPUT_LENGTH];

    if (argument[0] == '\0')
    {
	if (ch->prefix[0] == '\0')
	{
	    send_to_char("You have no prefix to clear.\n\r",ch);
	    return;
	}

	send_to_char("Prefix removed.\n\r",ch);
	free_string(ch->prefix);
	ch->prefix = str_dup("");
	return;
    }

    if (ch->prefix[0] != '\0')
    {
	sprintf(buf,"Prefix changed to %s.\n\r",argument);
	free_string(ch->prefix);
    }
    else
    {
	sprintf(buf,"Prefix set to %s.\n\r",argument);
    }

    ch->prefix = str_dup(argument);
}

#define CH(descriptor)  ((descriptor)->original ? (descriptor)->original : (descriptor)->character)

/* This file holds the copyover data */
#define COPYOVER_FILE "copyover.data"

/* This is the executable file */
#define EXE_FILE	  "../src/rogue"


/*  Copyover - Original idea: Fusion of MUD++
 *  Adapted to Diku by Erwin S. Andreasen, <erwin@pip.dknet.dk>
 *  http://pip.dknet.dk/~pip1773
 *  Changed into a ROM patch after seeing the 100th request for it :)
 */
ACMD(do_copyover) {
	FILE *fp;
	DESCRIPTOR_DATA *d, *d_next;
	char buf [100], buf2[100];
	extern int port,control; /* db.c */
	
	fp = fopen (COPYOVER_FILE, "w");
	
	if (!fp)
	{
		send_to_char("Copyover file not writeable, aborted.\n\r",ch);
		mudlogf(BRF, LVL_STAFF, TRUE, "Could not write to copyover file: %s", COPYOVER_FILE);
		perror ("do_copyover:fopen");
		return;
	}
	
	sprintf (buf, "\n\r*** COPYOVER by %s - please remain seated!\n\r", ch->name);
	
	/* For each playing descriptor, save its state */
	for (d = descriptor_list; d ; d = d_next)
	{
		CHAR_DATA * och = CH (d);
		d_next = d->next; /* We delete from the list , so need to save this */
		
		if (!d->character || d->connected > CON_PLAYING) /* drop those logging on */
		{
			write_to_descriptor(d->descriptor, "\n\rSorry, we are rebooting. Come back in a few minutes.\n\r", 0);
			close_socket (d); /* throw'em out */
		}
		else
		{
			fprintf (fp, "%d %s %s\n", d->descriptor, och->name, d->host);
			save_char_obj (och);
			
			write_to_descriptor (d->descriptor, buf, 0);
		}
	}
	
	fprintf (fp, "-1\n");
	fclose (fp);
	
	/* Close reserve and other always-open files and release other resources */
	
	fclose (fpReserve);
	
	/* exec - descriptors are inherited */
	
	sprintf (buf, "%d", port);
	sprintf (buf2, "%d", control);
	execl(EXE_FILE, "rogue", buf, "hboot", buf2, (char *) NULL);

	/* Failed - sucessful exec will not return */
	
	perror ("do_copyover: execl");
	send_to_char("Copyover FAILED!\n\r",ch);
	
	/* Here you might want to reopen fpReserve */
	fpReserve = fopen (NULL_FILE, "r");
}

/* Recover from a copyover - load players */
void copyover_recover ()
{
	DESCRIPTOR_DATA *d;
	FILE *fp;
	char name [100];
	char host[MSL];
	int desc;
	bool fOld;
	
	log_string("Copyover recovery initiated");

	fp = fopen (COPYOVER_FILE, "r");
	
	if (!fp) /* there are some descriptors open which will hang forever then ? */
	{
		perror ("copyover_recover:fopen");
		log_string("Copyover file not found. Exitting.\n\r");
		exit (1);
	}

	unlink (COPYOVER_FILE); /* In case something crashes - doesn't prevent reading	*/
	
	for (;;)
	{
		fscanf (fp, "%d %s %s\n", &desc, name, host);
		if (desc == -1)
			break;

		/* Write something, and check if it goes error-free */		
		if (!write_to_descriptor (desc, "\n\rRestoring from copyover...\n\r",0))
		{
			close (desc); /* nope */
			continue;
		}
		
		d = new_descriptor();
		d->descriptor = desc;
		
		d->host = str_dup (host);
		d->next = descriptor_list;
		descriptor_list = d;
		d->connected = CON_COPYOVER_RECOVER; /* -15, so close_socket frees the char */
		
	
		/* Now, find the pfile */
		fOld = load_char_obj(d, name, FALSE);

		if (!fOld) /* Player file not found?! */
		{
			write_to_descriptor (desc, "\n\rSomehow, your character was lost in the copyover. Sorry.\n\r", 0);
			close_socket (d);			
		}
		else /* ok! */
		{
			write_to_descriptor (desc, "\n\rCopyover recovery complete.",0);

			/* Just In Case */
			if (!d->character->in_room)
				d->character->in_room = get_room_index (ROOM_VNUM_TEMPLE);

			/* Insert in the char_list */
			d->character->next = char_list;
			char_list = d->character;

			char_to_room(d->character, d->character->in_room);
			look_at_room(d->character, 0);
			act ("$n materializes!", d->character, NULL, NULL, TO_ROOM);
			d->connected = CON_PLAYING;

			if (d->character->pet != NULL)
			{
			    char_to_room(d->character->pet,d->character->in_room);
			    act("$n materializes!.",d->character->pet,NULL,NULL,TO_ROOM);
			}
		}
		
	}
   fclose (fp);	
}