roh/conf/area/
roh/game/talk/
roh/help/
roh/monsters/ocean/
roh/objects/ocean/
roh/player/
roh/rooms/area/1/
roh/rooms/misc/
roh/rooms/ocean/
roh/src-2.44b/
/*
 * dmply.cpp
 *	 Staff functions related to players
 *   ____            _
 *  |  _ \ ___  __ _| |_ __ ___  ___
 *  | |_) / _ \/ _` | | '_ ` _ \/ __|
 *  |  _ <  __/ (_| | | | | | | \__ \
 *  |_| \_\___|\__,_|_|_| |_| |_|___/
 *
 *	Copyright (C) 2007-2009 Jason Mitchell, Randi Mitchell
 * 	   Contributions by Tim Callahan, Jonathan Hseu
 *  Based on Mordor (C) Brooke Paul, Brett J. Vickers, John P. Freeman
 *
 */
#include "mud.h"
#include "commands.h"
#include "dm.h"
#include "guilds.h"
#include "login.h"
#include "unique.h"
#include "web.h"
#include "magic.h"
#include <sys/stat.h>


//*********************************************************************
//						dmLastCommand
//*********************************************************************

bstring dmLastCommand(const Player* player) {
	if(player->isPassword(player->getLastCommand()))
		return("**********");
	return(escapeColor(player->getLastCommand()));
}


//*********************************************************************
//						dmForce
//*********************************************************************
// This function allows a DM to force another user to do a command.

int dmForce(Player* player, cmd* cmnd) {
	Player	*target=0;
	int		index=0;
	unsigned int i=0;
	char	str[IBUFSIZE+1];

	if(cmnd->num < 2) {
		player->print("*force whom?\n");
		return(0);
	}

	lowercize(cmnd->str[1], 1);
	target = gServer->findPlayer(cmnd->str[1]);
	if(!target) {
		player->print("%s is not on.\n", cmnd->str[1]);
		return(0);
	}
	if(target == player) {
		player->print("You can't *force yourself!\n");
		return(0);
	}

	if(!target->getSock()->canForce()) {
		player->print("Can not force %s right now.\n", cmnd->str[1]);
		return(0);
	}

	for(i=0; i<strlen(cmnd->fullstr); i++)
		if(cmnd->fullstr[i] == ' ') {
			index = i+1;
			break;
		}
	for(i=index; i<strlen(cmnd->fullstr); i++)
		if(cmnd->fullstr[i] != ' ') {
			index = i+1;
			break;
		}
	for(i=index; i<strlen(cmnd->fullstr); i++)
		if(cmnd->fullstr[i] == ' ') {
			index = i+1;
			break;
		}
	for(i=index; i<strlen(cmnd->fullstr); i++)
		if(cmnd->fullstr[i] != ' ') {
			index = i;
			break;
		}
	strcpy(str, &cmnd->fullstr[index]);
	if(target->getClass() >= player->getClass())
		target->print("%s forces you to \"%s\".\n", player->name, str);

	bstring txt = escapeColor(str);
	log_immort(true, player, "%s forced %s to \"%s\".\n", player->name, target->name, txt.c_str());
	command(target->getSock(), str);

	return(0);
}


//*********************************************************************
//						dmSpy
//*********************************************************************

int dmSpy(Player* player, cmd* cmnd) {
	Player	*target=0;


	if(cmnd->num < 2 && !player->flagIsSet(P_SPYING)) {
		player->print("Spy on whom?\n");
		return(0);
	}

	if(player->flagIsSet(P_SPYING)) {
		player->getSock()->clearSpying();
		player->clearFlag(P_SPYING);
		player->print("Spy mode off.\n");
		if(!player->isDm())
			log_immort(false,player, "%s turned spy mode off.\n", player->name);
		return(0);
	}

	cmnd->str[1][0] = up(cmnd->str[1][0]);
	target = gServer->findPlayer(cmnd->str[1]);
	if(!target || !player->canSee(target)) {
		player->print("Spy on whom?  Use full names.\n");
		return(0);
	}

	if(target->isDm() && !player->isDm()) {
		player->print("You cannot spy on DM's!\n");
		target->printColor("^r%M tried to spy on you.\n", player);
		return(0);
	}

	if(target == player) {
		player->print("You can't spy on yourself.\n");
		return(0);
	}

	if(player->getClass() <= target->getClass())
		target->printColor("^r%s is observing you.\n", player->name);

	player->getSock()->setSpying(target->getSock());

	player->setFlag(P_SPYING);
	player->setFlag(P_DM_INVIS);

	player->print("Spy on. Type *spy to turn it off.\n");
	if(!player->isDm())
		log_immort(false,player, "%s started spying on %s.\n", player->name, target->name);
	return(0);
}


//*********************************************************************
//						dmSilence
//*********************************************************************
// This function sets it so a player can't broadcast for 10 minutes or
// however long specified by [minutes]

int dmSilence(Player* player, cmd* cmnd) {
	Creature* target=0;


	if(cmnd->num < 2) {
		player->print("syntax: *silence <player> [minutes]/[r]\n");
		return(0);
	}

	lowercize(cmnd->str[1], 1);
	target = gServer->findPlayer(cmnd->str[1]);

	if(!target || !player->canSee(target)) {
		player->print("That player is not logged on.\n");
		return(0);
	}

	target->print("You have been silenced by the gods.\n");
	target->lasttime[LT_NO_BROADCAST].ltime = time(0);


	if(cmnd->num > 2 && low(cmnd->str[2][0]) == 'r') {
		if(target->flagIsSet(P_CANT_BROADCAST)) {
			player->print("%s can now broadcast again.\n", target->name);
			target->clearFlag(P_CANT_BROADCAST);
		} else {
			player->print("But %s can already broadcast!\n", target->name);
		}
	} else {
		if(cmnd->val[1]) {
			target->lasttime[LT_NO_BROADCAST].interval = cmnd->val[1] * 60L;
			player->print("%s silenced for %d minute(s).\n", target->name, cmnd->val[1]);
		} else {
			player->print("%s silenced for 10 minutes.\n", target->name);
			target->lasttime[LT_NO_BROADCAST].interval = 600L;
		}
		target->setFlag(P_CANT_BROADCAST);
		log_immort(true, player, "%s removed %s's ability to broadcast.\n", player->name, target->name);
	}
	return(0);
}


//*********************************************************************
//						dmTitle
//*********************************************************************

int dmTitle(Player* player, cmd* cmnd) {
	Player	*target=0;
	bstring title = "";

	if(cmnd->num < 3) {
		player->print("\nSyntax: *title <player> [<title>|-d]\n");
		return(PROMPT);
	}

	lowercize(cmnd->str[1], 1);
	target = gServer->findPlayer(cmnd->str[1]);

	if(!target || !player->canSee(target)) {
		player->print("Player not found.\n");
		return(0);
	}

	if(!player->isDm() && target != player) {
		player->print("You can only set your own title.\n");
		return(0);
	}

	title = getFullstrText(cmnd->fullstr, 2);

	if(title == "-d") {
		target->setTitle("");
		player->print("\nTitle cleared.\n");
	} else {
		title = escapeColor(title);
		target->setTitle(title);
		player->print("\nTitle Set\n");
	}
	return(0);
}

//*********************************************************************
//						dmSurname
//*********************************************************************

int dmSurname(Player* player, cmd* cmnd) {
	Player	*target=0;
	int		i=0;
	char	which=0;

	if(cmnd->num < 3) {
		player->print("\nSyntax: *surname (player) [(surname)|-d]\n");
		return(PROMPT);
	}

	// Parse the flag here
	while(isspace(cmnd->fullstr[i]))
		i++;
	while(!isspace(cmnd->fullstr[i]))
		i++;
	while(isspace(cmnd->fullstr[i]))
		i++;
	while(isalpha(cmnd->fullstr[i]))
		i++;
	while(isspace(cmnd->fullstr[i]))
		i++;

	lowercize(cmnd->str[1], 1);
	target = gServer->findPlayer(cmnd->str[1]);

	if(!target || !player->canSee(target)) {
		player->print("Player not found.\n");
		return(PROMPT);
	}

	if(!player->isDm() && target->isStaff()) {
		player->print("You can only set the surnames of players.\n");
		return(0);
	}



	while(isdigit(cmnd->fullstr[i]))
		i++;
	while(isspace(cmnd->fullstr[i]))
		i++;

	// parse flag
	if(cmnd->fullstr[i] == '-') {
		if(cmnd->fullstr[i + 1] == 'd') {
			which = 1;
			i += 2;
		} else if(cmnd->fullstr[i + 1] == 'l') {
			which = 2;
			i += 2;
		}
		while(isspace(cmnd->fullstr[i]))
			i++;
	}



	switch (which) {
	case 0:
		target->setSurname(&cmnd->fullstr[i]);
		player->print("\nSurname set\n");
		target->setFlag(P_CHOSEN_SURNAME);
		break;
	case 1:
		target->setSurname("");
		player->print("\nSurname cleared.\n");
		target->clearFlag(P_CHOSEN_SURNAME);
		break;
	case 2:
		target->setSurname("");
		player->print("\n%s's surname command is now locked.\n", target->name);
		target->setFlag(P_NO_SURNAME);
		break;
	default:
		player->print("\nNothing Done.\n");
		break;
	}
	return(0);
}


//*********************************************************************
//						dmGroup
//*********************************************************************
// This function allows you to see who is in a group or party of people
// who are following you.

int dmGroup(Player* player, cmd* cmnd) {
	Creature *target=0;
	ctag	*cp=0;
	char	str[2048];


	str[0] = 0;

	if(cmnd->num < 2) {
		player->print("Show who's group?\n");
		return(PROMPT);
	}

	target = player->getRoom()->findCreature(player, cmnd);

	if(!target) {
		lowercize(cmnd->str[1], 1);
		target = gServer->findPlayer(cmnd->str[1]);
	}

	if(!target || !player->canSee(target)) {
		player->print("That player is not logged on.\n");
		return(PROMPT);
	}

	player->print("%M is following: %s\n", target, (target->following) ?
			target->following->name : "no one");

	cp = target->first_fol;
	player->print("%M group: ", target);
	if(!cp) {
		player->print("None.\n");
		return(0);
	}

	while(cp) {
		strcat(str, cp->crt->name);
		strcat(str, ", ");
		cp = cp->next_tag;
	}


	str[strlen(str)-2] = 0;
	player->print("%s.\n", str);

	return(0);
}

//*********************************************************************
//						dmDust
//*********************************************************************
// This function allows staff to delete a player.

int dmDust(Player* player, cmd* cmnd) {
	Player	*target=0;
	char	buf[120];

	if(cmnd->num < 2) {
		player->print("\nDust whom?\n");
		return(PROMPT);
	}

	lowercize(cmnd->str[1], 1);
	target = gServer->findPlayer(cmnd->str[1]);

	if(!target || !player->canSee(target)) {
		player->print("%s is not on.\n", cmnd->str[1]);
		return(0);
	}

	if(target->isCt() && !player->isDm()) {
		target->printColor("^r%s tried to dust you!\n", player->name);
		return(0);
	}

	if(player->getClass() == CARETAKER && target->isStaff()) {
		target->printColor("^r%s tried to dust you!\n", player->name);
		return(0);
	}

	if(isdm(target->name)) {
		target->printColor("^r%s tried to dust you!\n", player->name);
		return(0);
	}

	if(player->getClass() == CARETAKER && target->getLevel() > 10) {
		player->print("You are only able to dust people levels 10 and below.\n");
		return(0);
	}

	logn("log.dust", "%s was dusted by %s.\n", target->name, player->name);

	// TODO: Handle guild creations
	sprintf(buf, "\n%c[35mLightning comes down from on high! You have angered the gods!%c[35m\n", 27, 27);
	target->getSock()->write(buf);

	if(!strcmp(cmnd->str[2], "-n")) {
		broadcast(isCt, "^y### %s has been turned to dust!", target->name);
	} else {
		broadcast("### %s has been turned to dust!", target->name);
		broadcast(target->getSock(), target->getRoom(), "A bolt of lightning strikes %s from on high.", target->name);
		last_dust_output = time(0) + 15L;
	}

	deletePlayer(target);
	return(0);
}

//*********************************************************************
//						dmFlash
//*********************************************************************
//  This function allows a DM to output a string to an individual
//  players screen.

int dmFlash(Player* player, cmd* cmnd) {
	bstring text = "";
	Player	*target=0;


	if(cmnd->num < 2) {
		player->print("DM flash to whom?\n");
		return(0);
	}

	lowercize(cmnd->str[1], 1);
	target = gServer->findPlayer(cmnd->str[1]);

	if(!target) {
		player->print("Send to whom?\n");
		return(0);
	}

	text = getFullstrText(cmnd->fullstr, 2);
	if(text == "") {
		player->print("Send what?\n");
		return(0);
	}

	player->printColor("^cYou flashed: \"%s^c\" to %N.\n", text.c_str(), target);

	target->printColor("%s\n", text.c_str());
	return(0);
}

//*********************************************************************
//						dmAward
//*********************************************************************

int dmAward(Player* player, cmd* cmnd) {
	Player	*target;
	long	i=0, t=0, amount=0, gp=0;
	char	temp[80];

	if(!player->flagIsSet(P_CAN_AWARD) && !player->isDm())
		return(cmdNoAuth(player));

	if(cmnd->num < 2) {
		player->print("*award whom?\n");
		return(PROMPT);
	}

	lowercize(cmnd->str[1], 1);
	target = gServer->findPlayer(cmnd->str[1]);

	if(!target || !player->canSee(target)) {
		player->print("%s is not on.\n", cmnd->str[1]);
		return(0);
	}

	if(target->isStaff()) {
		player->print("Why award a staff member with roleplaying xp?\n");
		return(0);
	}

	sprintf(temp, "%s", target->name);

	if(!target->getSock()->canForce()) {
		player->print("You can't award %s right now.\n", cmnd->str[1]);
		return(0);
	}

	amount = cmnd->val[1];


	if(amount < 2) {
		amount = target->getExperience() / 100;     // 1% of current xp is award.
		amount = MAX(amount, 500);
	}

	gp = MAX(500, MIN(1000000, amount));



	i = LT(target, LT_RP_AWARDED);
	t = time(0);

	if(i > t && !player->isDm()) {
		if(i - t > 3600)
			player->print("%s cannot be awarded for %02d:%02d:%02d more hours.\n", target->name,(i - t) / 3600L, ((i - t) % 3600L) / 60L, (i - t) % 60L);
		else if((i - t > 60) && (i - t < 3600))
			player->print("%s cannot be awarded for %d:%02d more minutes.\n", target->name, (i - t) / 60L, (i - t) % 60L);
		else
			player->pleaseWait(i-t);
		return(0);
	}



	player->print("%d xp awarded to %s for roleplaying.\n", amount, target->name);
	target->printColor("^yYou have been awarded %d xp for good roleplaying!\n", amount);
	target->addExperience(amount);


	target->lasttime[LT_RP_AWARDED].ltime = t;
	target->lasttime[LT_RP_AWARDED].interval = 500L; // 45 minutes.

	if(!strcmp(cmnd->str[2], "-g")) {
		player->print("%ld gold awarded to %s for roleplaying.\n", gp, target->name);
		target->printColor("^yYou have been awarded %ld gold as well!\nIt was put in your bank account!\n", gp);
		target->bank.add(gp, GOLD);
		logn("log.bank", "%s was awarded %ld gold for roleplaying. (Balance=%s)\n",target->name, gp, target->bank.str().c_str());
		banklog(target->name, "ROLEPLAY AWARD: %ld [Balance: %s]\n", gp, target->bank.str().c_str());
	}

	log_immort(true, player, "%s awarded %s %d xp for roleplaying.\n", player->name, temp, amount);

	if(!strcmp(cmnd->str[2], "-g"))
		log_immort(true, player, "%s was awarded %ld gold for roleplaying. (Balance=%s)\n",target->name, gp, target->bank.str().c_str());

	return(0);
}


//*********************************************************************
//						dmBeep
//*********************************************************************
int dmBeep(Player* player, cmd* cmnd) {
	Player	*target=0;

	if(cmnd->num < 2) {
		player->print("\n*Beep whom?\n");
		return(PROMPT);
	}

	lowercize(cmnd->str[1], 1);
	target = gServer->findPlayer(cmnd->str[1]);

	if(!target) {
		player->print("%s is not on.\n", cmnd->str[1]);
		return(0);
	}

	if(!target->getSock()->canForce()) {
		player->print("Can't beep %s right now.\n", cmnd->str[1]);
		return(0);
	}

	target->print("\a\a\a\a\a\a\a\a\a\a");
	return(0);
}


//*********************************************************************
//						dmAdvance
//*********************************************************************

int dmAdvance(Player* player, cmd* cmnd) {
	Player	*target=0;
	int		lev=0, i=0;

	if(cmnd->num < 2) {
		player->print("Advance who at what level?\n");
		return(0);
	}

	lowercize(cmnd->str[1], 1);
	target = gServer->findPlayer(cmnd->str[1]);

	if(!target) {
		player->print("Advance whom?\n");
		return(0);
	}

	if(target->getNegativeLevels()) {
		player->print("Clear %s's negative levels first.\n", target->name);
		return(0);
	}
	if(cmnd->val[1] <= 0 || cmnd->val[1] > MAXALVL) {
		player->print("Only levels between 1 and %d!\n", MAXALVL);
		return(0);
	}
	lev = cmnd->val[1] - target->getLevel();
	if(lev == 0) {
		player->print("But %N is already level %d!\n", target, target->getLevel());
		return(0);
	}
	if(lev > 0) {
		for(i = 0; i < lev; i++)
			target->upLevel();
		player->print("%M has been raised to level %d.\n", target, target->getLevel());
	}
	if(lev < 0) {
		for(i = 0; i > lev; i--)
			target->downLevel();
		player->print("%M has been lowered to level %d.\n", target, target->getLevel());
	}
	if(target->getLevel() > 1)
		target->setExperience(gConfig->expNeeded(target->getLevel()-1)+1);
	else
		target->setExperience(0);
	return(0);
}

//*********************************************************************
//						dmFinger
//*********************************************************************

int dmFinger(Player* player, cmd* cmnd) {
	struct stat     f_stat;
	Player	*target=0;
	char	tmp[80];

	if(cmnd->num < 2) {
		player->print("Dmfinger who?\n");
		return(0);
	}

	cmnd->str[1][0] = up(cmnd->str[1][0]);
	target = gServer->findPlayer(cmnd->str[1]);

	if(!target) {

		if(!loadPlayer(cmnd->str[1], &target)) {
			player->print("Player does not exist.\n");
			return(0);
		}

		player->print("\n");
		target->information(player, false);
		free_crt(target);

	} else {
		player->print("\n");
		target->information(player, true);
	}

	sprintf(tmp, "%s/%s", POSTPATH, cmnd->str[1]);
	if(stat(tmp, &f_stat)) {
		player->print("No mail.\n");
		return(PROMPT);
	}

	if(f_stat.st_atime > f_stat.st_ctime)
		player->print("No unread mail since: %s", ctime(&f_stat.st_atime));
	else
		player->print("New mail since: %s", ctime(&f_stat.st_ctime));
	return(PROMPT);
}

//*********************************************************************
//						dmDisconnect
//*********************************************************************

int dmDisconnect(Player* player, cmd* cmnd) {
	Player	*creature=0;

	if(cmnd->num < 2) {
		player->print("\nDisconnect whom?\n");
		return(PROMPT);
	}

	lowercize(cmnd->str[1], 1);
	creature = gServer->findPlayer(cmnd->str[1]);

	if(!creature || !player->canSee(creature)) {
		player->print("%s is not on.\n", cmnd->str[1]);
		return(0);
	}
	if(creature->isCt() && !player->isDm()) {
		creature->printColor("^r%s tried to disconnect you!\n", player->name);
		return(0);
	}

	log_immort(true, player, "%s disconnected %s.\n", player->name, creature->name);

	creature->getSock()->disconnect();
	return(0);

}

//*********************************************************************
//						dmTake
//*********************************************************************
// This function allows staff to steal items from a player remotely.

int dmTake(Player* player, cmd* cmnd) {
	Player	*target=0;
	Object	*object=0, *container=0;
	bool	online=false;

	if(cmnd->num < 2) {
		player->print("*take what?\n");
		return(0);
	}

	if(cmnd->num < 3) {
		player->print("*take what from whom?\n");
		return(0);
	}


	cmnd->str[2][0]=up(cmnd->str[2][0]);
	target = gServer->findPlayer(cmnd->str[2]);


	if(!target || !player->canSee(target)) {
		if(player->isDm()) {
			if(!loadPlayer(cmnd->str[2], &target)) {
				player->print("Player does not exist.\n");
				return(0);
			}
		} else {
			player->print("That player is not logged on.\n");
			return(0);
		}
	} else
		online = true;



	if(cmnd->num > 3) {

		container = findObject(player, target->first_obj, cmnd, 3);

		if(!container) {
			player->print("%s doesn't have that container.\n", target->upHeShe());
			if(!online)
				free_crt(target);
			return(0);
		}

		if(container->getType() != CONTAINER) {
			player->print("That isn't a container.\n");
			if(!online)
				free_crt(target);
			return(0);
		}

		object = findObject(player, container->first_obj, cmnd);
		if(!object) {
			player->print("That is not in that container.\n");
			if(!online)
				free_crt(target);
			return(0);
		}

		del_obj_obj(object, container);
		Limited::deleteOwner(target, object);
		// dont need to run addUnique on staff
		player->addObj(object);

		player->printColor("You remove a %P from %N's %s.\n", object, target, container->name);

		if(!player->isDm())
			log_immort(true, player, "%s removed %s from %s's %s.\n", player->name, object->name, target->name, container->name);

		target->save(online);
		if(!online)
			free_crt(target);
		return(0);
	}


	object = findObject(player, target->first_obj, cmnd);

	if(!object) {
		player->print("%s doesn't have that.\n", target->upHeShe());

		if(!online)
			free_crt(target);
		return(0);
	}


	player->printColor("You remove %P from %N's inventory.\n", object, target);

	if(!player->isDm())
		log_immort(true, player, "%s removed %s from %s's inventory.\n", player->name, object->name, target->name);

	target->delObj(object, false, true, true, true, true);
	// dont need to run addUnique on staff
	player->addObj(object);

	target->save(online);
	if(!online)
		free_crt(target);
	return(0);
}

//*********************************************************************
//						dmRemove
//*********************************************************************
// This function allows staff to unwield/unwear items from a player remotely.

int dmRemove(Player* player, cmd* cmnd) {
	Player	*target=0;
	Object	*object=0;
	int     i=0, j=0, found=0;

	if(cmnd->num < 2) {
		player->print("*remove what?\n");
		return(0);
	}
	if(cmnd->num < 3) {
		player->print("*remove what from whom?\n");
		return(0);
	}

	cmnd->str[2][0] = up(cmnd->str[2][0]);
	target = gServer->findPlayer(cmnd->str[2]);


	if(!target || !player->canSee(target)) {
		player->print("That player is not logged on.\n");
		return(0);
	}


	for(i=0; i<MAXWEAR; i++)
		if(target->ready[i])
			found = 1;

	if(!found) {
		player->print("%s isn't wearing anything.\n", target->upHeShe());
		return(0);
	}



	for(i=0,j=0; i<MAXWEAR; i++) {
		if(target->ready[i] && keyTxtEqual(target->ready[i], cmnd->str[1])) {
			j++;
			if(j == cmnd->val[1]) {
				object = target->ready[i];
				if(target->inCombat() && object->getType() <=4) {
					player->print("Not while %s is in combat.\n", target->upHeShe());
					return(0);
				}
				// i is wearloc-1, so add 1  -- We might be add it to someone else's
				// inventory, so do nothing afterwards
				target->unequip(i+1, UNEQUIP_NOTHING);
				Limited::deleteOwner(target, object);
				target->computeAttackPower();
				target->computeAC();
				break;
			}
		}
	}



	if(!object) {
		player->print("%s isn't wearing/wielding that.\n", target->upHeShe());
		return(0);
	}


	player->printColor("You remove %P from %N's worn equipment.\n", object, target);

	if(!player->isDm())
		log_immort(true, player, "%s removed %s from %s's worn equipment.\n", player->name, object->name, target->name);

	player->addObj(object);

	target->save(true);
	return(0);
}

//*********************************************************************
//						dmPut
//*********************************************************************
// This function allows a CT or DM to remotely add items to a player.

int dmPut(Player* player, cmd* cmnd) {
	Player	*target=0;
	Object	*object=0, *container=0;

	bool	online=false;

	if(cmnd->num < 2) {
		player->print("*put what?\n");
		return(0);
	}
	if(cmnd->num < 3) {
		player->print("*put what on whom?\n");
		return(0);
	}

	cmnd->str[2][0] = up(cmnd->str[2][0]);
	target = gServer->findPlayer(cmnd->str[2]);


	if(!target || !player->canSee(target)) {
		if(player->isDm()) {
			if(!loadPlayer(cmnd->str[2], &target)) {
				player->print("Player does not exist.\n");
				return(0);
			}
		} else {
			player->print("That player is not logged on.\n");
			return(0);
		}
	} else
		online = true;



	if(cmnd->num > 3) {

		container = findObject(player, target->first_obj, cmnd, 3);

		if(!container) {
			player->print("%s doesn't have that container.\n", target->upHeShe());
			if(!online)
				free_crt(target);
			return(0);
		}

		if(container->getType() != CONTAINER) {
			player->print("That isn't a container.\n");
			if(!online)
				free_crt(target);
			return(0);
		}

		object = findObject(player, player->first_obj, cmnd);
		if(!object) {
			player->print("You do not have that.\n");
			if(!online)
				free_crt(target);
			return(0);
		}


		if((container->getShotscur() + 1) > container->getShotsmax()) {
			player->printColor("You will exceed the maximum allowed items for %P(%d).\n", container->name, container->getShotsmax());
			player->print("Aborted.\n");
			if(!online)
				free_crt(target);
			return(0);
		}

		player->delObj(object, false, false, true, true, true);
		container->incShotscur();
		container->addObj(object);
		Limited::addOwner(target, object);

		player->printColor("You put %P into %N's %s.\n", object, target, container->name);

		target->save(online);
		if(!online)
			free_crt(target);
		return(0);
	}


	object = findObject(player, player->first_obj, cmnd);
	if(!object) {
		player->print("You don't have that.\n");
		if(!online)
			free_crt(target);
		return(0);
	}

	if(object->flagIsSet(O_DARKMETAL) && target->getRoom()->isSunlight()) {
		player->printColor("You cannot give %P to %N now!\nIt would surely be destroyed!\n", object, target);
		return(0);
	}

	player->printColor("You add %P to %N's inventory.\n", object, target);
	player->delObj(object, false, false, true, true, true);
	Limited::addOwner(target, object);
	target->addObj(object);

	target->save(online);
	if(!online)
		free_crt(target);
	return(0);
}


//*********************************************************************
//						dmMove
//*********************************************************************
// this function allows a DM char to put a player into a totally new room
// when logged off. If logged on it will do nothing as teleport handles
// the online function.

int dmMove(Player* player, cmd* cmnd) {
	Player	*creature=0;

	MapMarker mapmarker;
	std::ostringstream log;
	CatRef	cr;

	// normal checks
	if(cmnd->num < 2) {
		player->print("Offline move whom?\n");
		return(0);
	}

	// already logged on?
	cmnd->str[1][0] = up(cmnd->str[1][0]);
	creature = gServer->findPlayer(cmnd->str[1]);
	if(creature) {
		if(player->canSee(creature))
			player->print("%s is already logged on, use *teleport!\n",  cmnd->str[1]);
		else
			player->print("You cannot move that player.\n");
		return(0);
	}

	// now load 'em in
	if(!loadPlayer(cmnd->str[1], &creature)) {
		player->print("player %s does not exist\n", cmnd->str[1]);
		return(0);
	}
	if(creature->isCt() && !player->isDm()) {
		player->print("You cannot move that player.\n");
		free_crt(creature);
		return(0);
	}

	// put them in their new location
	log << player->name << " moved player " << creature->name << " from room ";
	if(creature->area_room)
		log << creature->area_room->fullName();
	else
		log << creature->room.str();

	log << " to room ";

	getDestination(getFullstrText(cmnd->fullstr, 2), &mapmarker, &cr, player);

	if(!cr.id) {
		Area *area = gConfig->getArea(mapmarker.getArea());
		if(!area) {
			player->print("That area does not exist.\n");
			free_crt(creature);
			return(0);
		}
		creature->room.clear();
		if(creature->area_room)
			creature->area_room->mapmarker = mapmarker;
		else {
			AreaRoom *aRoom = area->loadRoom(0, &mapmarker, false);
			creature->area_room = aRoom;
		}
		log << creature->area_room->fullName();
		player->print("Player %s moved to location %s.\n", creature->name, creature->area_room->fullName().c_str());
	} else {
		if(!validRoomId(cr)) {
			player->print("Can only put players in the range of 1-%d.\n", RMAX);
			free_crt(creature);
			return(0);
		}
		if(creature->area_room)
			creature->deleteFromRoom();
		*&creature->room = *&cr;
		log << cr.str();
		player->print("Player %s moved to location %s.\n", creature->name, cr.str().c_str());
	}

	log_immort(true, player, "%s.\n", log.str().c_str());

	creature->save();
	free_crt(creature);
	return(0);
}


//*********************************************************************
//						dmWordAll
//*********************************************************************
// This function is to be used to quickly move ALL players online to
// one place for whatever reason.

int dmWordAll(Player* player, cmd* cmnd) {
	BaseRoom	*room=0;

	std::pair<bstring, Player*> p;
	Player* target=0;

	foreach(p, gServer->players) {
		target = p.second;

		if(!target->isConnected())
			continue;
		if(target->isStaff())
			continue;

		room = target->getRecallRoom().loadRoom(target);

		target->print("An astral vortex just arrived.\n");
		broadcast(target->getSock(), target->getRoom(), "An astral vortex just arrived.");

		target->print("The astral vortex sucks you in!\n");
		broadcast(target->getSock(), target->getRoom(), "The astral vortex sucks %N into it!", target);

		broadcast(target->getSock(), target->getRoom(), "The astral vortex disappears.");

		broadcast("^Y### Strangely, %N was sucked into an astral vortex.", target);

		// Optionally, can knock everyone out for one minute.
		if(!strcmp(cmnd->str[1], "-u"))
			target->knockUnconscious(60);


		if(!target->inJail()) {
			target->deleteFromRoom();
			target->addToRoom(room);
		}

		target->save(true);
	}
	return(0);
}

//*********************************************************************
//						dmRename
//*********************************************************************

int dmRename(Player* player, cmd* cmnd) {
	Player	*target=0;
	int		i=0;
	FILE	*fp;
	char	old_name[25], new_name[25];
	char	file[80];

	if(!player->isStaff() && !player->isWatcher())
		return(cmdNoExist(player, cmnd));
	if(!player->isWatcher())
		return(cmdNoAuth(player));

	if(cmnd->num < 2) {
		player->print("Rename who?\n");
		return(0);
	}
	if(cmnd->num < 3) {
		player->print("Rename to what?\n");
		return(0);
	}

	cmnd->str[1][0] = up(cmnd->str[1][0]);
	target = gServer->findPlayer(cmnd->str[1]);

	if(!target || !player->canSee(target)) {
		player->print("%s is not logged on!\n", cmnd->str[1]);
		return(0);
	}

	if(target->isCt() && !player->isDm()) {
		player->print("You cannot rename that player.\n");
		return(0);
	}

	if(target->getLevel() > 9 && player->isWatcher() && !player->isCt()) {
		player->print("You may only rename players under 10th level.\n");
		return(0);
	}

	strcpy(old_name, target->name);
	strcpy(new_name, cmnd->str[2]);
	new_name[0] = up(new_name[0]);

	if(!strcmp(new_name, old_name)) {
		player->print("Names are the same: hoose a different name.\n");
		return(0);
	}
	if(!strcmp(player->name, old_name)) {
		player->print("You can't rename yourself.\n");
		return(0);
	}
	if(!parse_name(new_name)) {
		player->print("The new name is not allowed, pick another.\n");
		return(0);
	}
	if(strlen(new_name) >= 20) {
		player->print("The name must be less than 20 characters.\n");
		return(0);
	}
	if(strlen(new_name) < 3) {
		player->print("The name must be more than 3 characters.\n");
		return(0);
	}
	for(i=0; i< (int)strlen(new_name); i++)
		if(!isalpha(new_name[i]) && (new_name[i] != '\'')) {
			player->print("Name must be alphabetic, pick another.\n");
			return(0);
		}

	// See if a player with the new name exists
	sprintf(file, "%s/%s.xml", PLAYERPATH, new_name);
	fp = fopen(file, "r");
	if(fp) {
		player->print("A player with that name already exists.\n");
		fclose(fp);
		return(0);
	}

	strcpy(target->name, new_name);

	if(target->getGuild()) {
		Guild* guild = gConfig->getGuild(target->getGuild());
		guild->renameMember(old_name, new_name);
	}
	gConfig->guildCreationsRenameSupporter(old_name, new_name);
	gConfig->saveGuilds();


	gConfig->renamePropertyOwner(old_name, target);
	renamePlayerFiles(old_name, new_name);
	gServer->clearPlayer(old_name);
	gServer->addPlayer(target);

	player->print("%s has been renamed to %s.\n", old_name, target->name);
	target->print("You have been renamed to %s.\n", target->name);
	broadcast(isDm, "^g### %s renamed %s to %s.", player->name, old_name, target->name);
	logn("log.rename", "%s renamed %s to %s.\n", player->name, old_name, target->name);

	// unassociate
	if(target->getForum() != "") {
		//target->printColor("Your forum account ^C%s^x is no longer unassociated with this character.\n", target->getForum().c_str());
		//target->print("Use the \"forum\" command to reassociate this character with your forum account.\n");
		//target->setForum("");
		callWebserver((bstring)"mud.php?type=forum&char=" + old_name + "&rename=" + new_name);
	}

	target->save(true);
	return(0);
}


//*********************************************************************
//						dmPassword
//*********************************************************************

int dmPassword(Player* player, cmd* cmnd) {
	Player	*target=0;

	bool	online=false;
	bstring pass = "";

	if(cmnd->num < 2) {
		player->print("Change who's password?\n");
		return(0);
	}

	pass = getFullstrText(cmnd->fullstr, 2);
	if(pass == "") {
		player->print("Change the password to what?\n");
		return(0);
	}

	cmnd->str[1][0] = up(cmnd->str[1][0]);
	target = gServer->findPlayer(cmnd->str[1]);
	if(!target) {
		if(!loadPlayer(cmnd->str[1], &target)) {
			player->print("Player does not exist.\n");
			return(0);
		}
	} else
		online = true;


	if(target->isPassword(pass)) {
		player->print("Passwords must be different.\n");
		return(0);
	}
	if(pass.getLength() > PASSWORD_MAX_LENGTH) {
		player->print("The password must be %d characters or less.\n", PASSWORD_MAX_LENGTH);
		return(0);
	}
	if(pass.getLength() < PASSWORD_MIN_LENGTH) {
		player->print("Password must be at least %d characters.\n", PASSWORD_MAX_LENGTH);
		return(0);
	}

	target->setPassword(pass);

	player->print("%s's password has been changed to %s.\n", target->name, pass.c_str());
	logn("log.passwd", "### %s changed %s's password to %s.\n", player->name, target->name, pass.c_str());

	target->save(online);
	if(!online)
		free_crt(target);
	return(0);
}


//*********************************************************************
//						dmRestorePlayer
//*********************************************************************

int dmRestorePlayer(Player* player, cmd* cmnd) {
	Player	*target=0;
	int		n=0;
	long	old_xp=0;
	float	exp=0;
	bool	online=false;

	lowercize(cmnd->str[1], 1);
	target = gServer->findPlayer(cmnd->str[1]);

	if(!target) {
		if(!loadPlayer(cmnd->str[1], &target)) {
			player->print("Player does not exist.\n");
			return(0);
		}
	} else
		online = true;

	if(target->getNegativeLevels()) {
		player->print("Clear %s's negative levels first.\n", target->name);
		return(0);
	}

	old_xp = target->getExperience();

	exp = (float)target->getExperience();
	exp /= 0.85;
	target->setExperience((long)exp);

	n = exp_to_lev(target->getExperience());
	while(target->getLevel() < n)
		target->upLevel();


	player->print("%M has been restored.\n", target);

	log_immort(true, player, "%s restored %s from %ld to %ld xp.\n", player->name,
	           target->name, old_xp, target->getExperience());

	target->save(online);
	if(!online)
		free_crt(target);
	else
		target->print("Your experience has been restored.\n");
	return(0);
}

//*********************************************************************
//				dmGeneric
//*********************************************************************
// This is a generic function that handles getting information or doing
// something minor to a player who may be online or offline.
// Authorization is not done here.

#define DM_GEN_BANK		1
#define DM_GEN_INVVAL	2
#define DM_GEN_PROXY	3
#define DM_GEN_WARN		4
#define DM_GEN_BUG		5

int dmGeneric(Player* player, cmd* cmnd, bstring action, int what) {
	Player	*target=0;

	bool	online=false;

	if(cmnd->num < 2) {
		player->print("%s whom?\n", action.c_str());
		return(0);
	}

	cmnd->str[1][0] = up(cmnd->str[1][0]);
	target = gServer->findPlayer(cmnd->str[1]);

	if(!target || !player->canSee(target)) {
		if(player->isCt()) {
			if(!loadPlayer(cmnd->str[1], &target)) {
				player->print("Player does not exist.\n");
				return(DOPROMPT);
			}
		} else {
			player->print("That player is not logged on.\n");
			return(DOPROMPT);
		}
	} else
		online = true;


	// time to actually do what they want us to do
	if(what == DM_GEN_BANK)
		player->print("%s's bank balance is: %ldgp.\n", target->name, target->bank[GOLD]);
	else if(what == DM_GEN_INVVAL)
		player->print("%s's total inventory assets: %ldgp.\n", target->name, target->getInventoryValue());
	else if(what == DM_GEN_PROXY) {

		if(!target->flagIsSet(P_ON_PROXY)) {
			player->print("%s is now allowed to multi-log for proxy purposes.\n", target->name);
			target->setFlag(P_ON_PROXY);
		} else {
			player->print("%s is no longer allowed to multi-log.\n", target->name);
			target->clearFlag(P_ON_PROXY);
		}
		target->save(online);

	} else if(what == DM_GEN_WARN) {

		if(!player->isDm() && target->isDm()) {
			player->print("Don't be silly.\n");
			if(!online == 1)
				free_crt(target);
			return(0);
		}

		if(cmnd->num < 3) {
			player->print("%M has %d total warning%s.\n", target, target->getWarnings(), (target->getWarnings()==1 ? "":"s") );
			if(!online)
				free_crt(target);
			return(0);
		}

		if(!strcmp(cmnd->str[2], "-r")) {
			if(!player->isCt()) {
				player->print("You are unable to remove warnings.\n");
				if(!online)
					free_crt(target);
				return(0);
			}
			if(target->getWarnings() < 1) {
				player->print("%M has no warnings.\n", target);
				if(!online)
					free_crt(target);
				return(0);
			} else {
				target->subWarnings(1);
				if(online)
					target->print("%M removed one of your warnings. You now have %d.\n", player, target->getWarnings());
				player->print("One warning removed. %M now has %d warning%s remaining.\n", target, target->getWarnings(), (target->getWarnings()==1 ? "":"s"));
			}
			log_immort(false,player, "%s removed a warning from %s.\n", player->name, target->name);
			logn("log.warn", "%s removed a warning from %s.\n", player->name, target->name);

			broadcast(isCt, "^y%s removed a warning from %s. New total: %d", player->name, target->name, target->getWarnings());
		} else if(!strcmp(cmnd->str[2], "-a")) {
			if(target->getWarnings() > 2) {
				player->print("%M already has 3 warnings. %s cannot be warned further.\n",
				      target, target->upHeShe());
				if(!online)
					free_crt(target);
				return(0);
			} else {
				target->addWarnings(1);
				if(online)
					target->print("%M has formally warned you. You now have %d warning%s.\n",
					      player, target->getWarnings(), (target->getWarnings()>1 ? "s":""));
				player->print("Warning added. %M now has %d total warning%s.\n", target, target->getWarnings(), (target->getWarnings()>1 ? "s":""));

				logn("log.warn", "%s added a warning to %s.\n", player->name, target->name);
				log_immort(false,player, "%s added a warning to %s.\n", player->name, target->name);

				broadcast(isCt, "^y%s added a warning to %s. New total: %d", player->name, target->name, target->getWarnings());
			}

		} else {
			player->print("Syntax: *warn (player) [-r|-a]\n");
			if(!online)
				free_crt(target);
			return(0);
		}
		target->save(online);

	} else if(what == DM_GEN_BUG) {

		if(!target->flagIsSet(P_BUGGED)) {
			player->print("%s is now bugged for surveillance.\n", target->name);
			target->setFlag(P_BUGGED);
		} else {
			player->print("%s is no longer bugged for surveillance.\n", target->name);
			target->clearFlag(P_BUGGED);
		}
		target->save(online);

	} else
		player->print("Invalid option for dmGetInfo().\n");


	if(!online)
		free_crt(target);
	return(0);
}

//*********************************************************************
//						dmBank
//*********************************************************************
int dmBank(Player* player, cmd* cmnd) {
	return(dmGeneric(player, cmnd, "*bank", DM_GEN_BANK));
}
//*********************************************************************
//						dmInventoryValue
//*********************************************************************
int dmInventoryValue(Player* player, cmd* cmnd) {
	return(dmGeneric(player, cmnd, "*inv", DM_GEN_INVVAL));
}
//*********************************************************************
//						dmProxy
//*********************************************************************
int dmProxy(Player* player, cmd* cmnd) {
	return(dmGeneric(player, cmnd, "*proxy", DM_GEN_PROXY));
}
//*********************************************************************
//						dmWarn
//*********************************************************************
int dmWarn(Player* player, cmd* cmnd) {

	// watchers can use *warn
	if(!player->isStaff() && !player->isWatcher())
		return(cmdNoExist(player, cmnd));
	if(!player->isWatcher())
		return(cmdNoAuth(player));

	return(dmGeneric(player, cmnd, "*warn", DM_GEN_WARN));
}
//*********************************************************************
//						dmBugPlayer
//*********************************************************************
int dmBugPlayer(Player* player, cmd* cmnd) {
	return(dmGeneric(player, cmnd, "*bug", DM_GEN_BUG));
}



// dmKill function decides which of these are player-kill,
// room-kill or all-kill
#define DM_KILL			0
#define DM_COMBUST		1
#define DM_SLIME		2
#define DM_GNATS		3
#define DM_TRIP			4
#define DM_BOMB			5
#define DM_NUCLEAR		6
#define DM_ARMAGEDDON	7
#define DM_IGMOO		8
#define DM_RAPE		    9
#define DM_DRAIN		10
#define DM_CRUSH		11
#define DM_MISSILE		12

//*********************************************************************
//						dmKillAll
//*********************************************************************
// not declared in proto.h, only used below
// this function handles and *kill commands that kill everyone

int dmKillAll(int type, int silent, int unconscious, int uncon_length) {
	BaseRoom *room=0;

	std::pair<bstring, Player*> p;
	Player* target;
	foreach(p, gServer->players) {
		target = p.second;

		if(!target->isConnected())
			continue;
		if(target->isStaff())
			continue;

		room = target->getLimboRoom().loadRoom(target);

		if(!room)
			continue;

		switch(type) {
		case DM_ARMAGEDDON:
			target->print("Meteors begin falling from the sky!\n");
			broadcast(target->getSock(), target->getRoom(), "Meteors begin falling from the sky!\n");

			target->print("A freak meteor strikes you!\n");
			broadcast(target->getSock(), target->getRoom(), "A freak meteors strikes %N!", target);

			target->print("The freak meteor slams into you for %d damage!\n", mrand(5000,10000));
			broadcast(target->getSock(), target->getRoom(), "The freak meteor blasts right through %N!", target);
			target->print("You die as your ashes fall to the ground.\n");
			broadcast(target->getSock(), target->getRoom(), "The freak meteor vaporized %N!", target);

			if(!silent)
				broadcast("### Sadly, %N was killed by a freak meteor shower.", target);

			break;
		case DM_IGMOO:
			target->print("Igmoo the Mad just arrived.\n");

			target->printColor("^GIgmoo the Mad casts a disintegration spell on you.\n");
			target->print("You are engulfed in an eerie green light.\n");
			target->printColor("You've been disintegrated!\n");

			target->print("Igmoo the Mad killed you.\n");

			if(!silent)
				broadcast("### Sadly, %N was disintegrated by Igmoo the Mad.", target);

		default:
			break;
		}


		target->hp.setCur(1);
		target->mp.setCur(1);

		if(unconscious)
			target->knockUnconscious(uncon_length);

		if(!target->inJail()) {
			target->deleteFromRoom();
			target->addToRoom(room);
			target->doPetFollow();
		}

	}
	return(0);
}

//*********************************************************************
//						dmKill
//*********************************************************************
// not declared in proto.h, only used below
// handles player-targeted *kills

int dmKill(Player* player, Player *victim, int type, int silent, int unconscious, int uncon_length) {
	int		kill_room=0, no_limbo=0;
	ctag	*cp=0;
	BaseRoom *newRoom=0;

	// room kill or no limbo?
	switch(type) {
		case DM_BOMB:
		case DM_NUCLEAR:
			kill_room = 1;
			break;
		case DM_RAPE:
		case DM_DRAIN:
			no_limbo = 1;
			break;
		default:
			break;
	}

	if(victim->isDm()) {
		switch(type) {
		case DM_COMBUST:
			player->print("You tried to make %N spontaneously combust!\n", victim);
			victim->printColor("^r%M tried to make you spontaneously combust!\n", player);
			break;
		case DM_SLIME:
			player->print("You tried to make %N dissolve in green slime!\n", victim);
			victim->printColor("^g%M tried to dissolve you in green slime!\n", player);
			break;
		case DM_GNATS:
			player->print("You tried to make a swarm of gnats eat %N!\n", victim);
			victim->printColor("^m%M tried to send a swarm of ravenous gnats after you!\n", player);
			break;
		case DM_TRIP:
			player->print("You tried to make %N trip and break %s neck!\n", victim, victim->hisHer());
			victim->printColor("^y%M tried to make you trip and break your neck!\n", player);
			break;
		case DM_BOMB:
			player->print("You tried to suicide bomb %N!\n", victim);
			victim->printColor("^r%M tried to suicide bomb you!\n", player);
			break;
		case DM_NUCLEAR:
			player->print("You tried to make %N meltdown!\n", victim);
			victim->printColor("^g%M tried to make you meltdown!\n", player);
			break;
		case DM_RAPE:
			player->print("You tried to rape %N!\n", victim);
			victim->printColor("^m%M tried to rape you!\n", player);
			break;
		case DM_DRAIN:
			player->print("You tried to drain %N!\n", victim);
			victim->printColor("^c%M tried to drain you!\n", player);
			break;
		case DM_CRUSH:
			player->print("You tried to crush %N!\n", victim);
			victim->printColor("^c%M tried to crush you!\n", player);
			break;
		case DM_MISSILE:
			player->print("You tried to hit %N with a cruise missile!\n", victim);
			victim->printColor("^r%M tried to hit you with a cruise missile!\n", player);
			break;
		default:
			player->print("You tried to strike down %N!\n", victim);
			victim->printColor("^r%M tried to strike you down with lightning!\n", player);
			break;
		}
		return(0);
	}

	switch(type) {
	case DM_COMBUST:
		victim->printColor("^rYou just spontaneously combusted!\n");
		break;
	case DM_SLIME:
		victim->printColor("^gYou have been dissolved by green slime!\n");
		break;
	case DM_GNATS:
		victim->printColor("^mYou have been eaten by a ravenous demonic gnat swarm!\n");
		break;
	case DM_TRIP:
		victim->printColor("^yYou slip on an oversized banana and break your neck.\nYou're dead!\n");
		break;
	case DM_BOMB:
		victim->printColor("^rYou blow yourself to smithereens!\n");
		break;
	case DM_NUCLEAR:
		victim->printColor("^gYou begin to meltdown!\n");
		break;
	case DM_RAPE:
		victim->printColor("^mYou have been raped by the gods!\n");
		break;
	case DM_DRAIN:
		victim->printColor("^cYour life force drains away!\n");
		break;
	case DM_CRUSH:
		victim->printColor("^cA giant stone slab falls from the sky!\n");
		break;
	case DM_MISSILE:
		victim->printColor("^rYou are struck by a cruise missile!\nYou explode!\n");
		break;
	case DM_KILL:
		victim->printColor("^rA giant lightning bolt strikes you!\n");
		break;
	default:
		break;
	}

	if(victim->getClass() < BUILDER && !silent) {
		switch(type) {
		case DM_COMBUST:
			broadcast(victim->getSock(), victim->getRoom(), "^r%s bursts into flames!", victim->name);
			broadcast("^r### Sadly, %s spontaneously combusted.", victim->name);
			break;
		case DM_SLIME:
			broadcast(victim->getSock(), victim->getRoom(),
				"^gA massive green slime just arrived.\nThe massive green slime attacks %s!", victim->name);
			broadcast("^g### Sadly, %s was dissolved by a massive green slime.", victim->name);
			break;
		case DM_GNATS:
			broadcast(victim->getSock(), victim->getRoom(),
				"^mA demonic gnat swarm just arrived.\nThe demonic gnat swarm attacks %s!", victim->name);
			broadcast("^m### Sadly, %s was eaten by a ravenous demonic gnat swarm!", victim->name);
			break;
		case DM_TRIP:
			broadcast(victim->getSock(), victim->getRoom(), "^m%s slips on an oversized banana peel!", victim->name);
			broadcast("^m### Sadly, %s tripped and broke %s neck.", victim->name, victim->hisHer());
			break;
		case DM_BOMB:
			broadcast(victim->getSock(), victim->getRoom(), "^r%s begins to tick!", victim->name);
			broadcast("^r### Sadly, %s blew %sself up!", victim->name, victim->himHer());
			break;
		case DM_NUCLEAR:
			broadcast(victim->getSock(), victim->getRoom(), "^g%s begins to meltdown!", victim->name);
			broadcast("^g### Sadly, %s was killed in a nuclear explosion.", victim->name);
			break;
		case DM_KILL:
			broadcast(victim->getSock(), victim->getRoom(), "^rA giant lightning bolt strikes %s!", victim->name);
			broadcast("^r### Sadly, %s has been incinerated by lightning from the heavens!", victim->name);
			break;
		case DM_RAPE:
			broadcast(victim->getSock(), victim->getRoom(), "^m%s was raped by the gods!", victim->name);
			broadcast(isStaff, "^m*** %s raped %s.", player->name, victim->name);
			break;
		case DM_DRAIN:
			broadcast(victim->getSock(), victim->getRoom(), "^c%s's life force drains away!", victim->name);
			broadcast(isStaff, "^g*** %s drained %s.", player->name, victim->name);
			break;
		case DM_CRUSH:
			broadcast(victim->getSock(), victim->getRoom(), "^cA giant stone slab falls on %s!", victim->name);
			broadcast("^c### Sadly, %s was crushed under a giant stone slab.", victim->name);
			break;
		case DM_MISSILE:
			broadcast(victim->getSock(), victim->getRoom(),
				"^r%s was struck by a cruise missile!\n%s exploded!", victim->name, victim->name);
			broadcast("^r### Sadly, %s was killed by a precision-strike cruise missile.", victim->name);
			break;
		default:
			break;
		}
	} else {
		switch(type) {
		case DM_COMBUST:
			broadcast(isStaff, "^G### Sadly, %s spontaneously combusted.", victim->name);
			break;
		case DM_SLIME:
			broadcast(isStaff, "^G### Sadly, %s was dissolved by a massive green slime.", victim->name);
			break;
		case DM_GNATS:
			broadcast(isStaff, "^G### Sadly, %s was eaten by a ravenous demonic gnat swarm!", victim->name);
			break;
		case DM_TRIP:
			broadcast(isStaff, "^G### Sadly, %s tripped and broke %s neck.", victim->name, victim->hisHer());
			break;
		case DM_BOMB:
			broadcast(isStaff, "^G### Sadly, %s blew %sself up!!", victim->name, victim->himHer());
			break;
		case DM_NUCLEAR:
			broadcast(isStaff, "^G### Sadly, %s was killed in a nuclear explosion.", victim->name);
			break;
		case DM_KILL:
			broadcast(isStaff, "^G### Sadly, %s has been incinerated by lightning from the heavens!", victim->name);
			break;
		case DM_RAPE:
			broadcast(isStaff, "^g*** %s raped %s.", player->name, victim->name);
			break;
		case DM_DRAIN:
			broadcast(isStaff, "^g*** %s drained %s.", player->name, victim->name);
			break;
		case DM_CRUSH:
			broadcast(isStaff, "^G### Sadly, %s was crushed under a giant stone slab.", victim->name);
			break;
		case DM_MISSILE:
			broadcast(isStaff, "^G### Sadly, %s was killed by a precision-strike cruise missile.", victim->name);
			break;
		default:
			break;
		}
	}


	cp = victim->getRoom()->first_ply;
	while(cp) {

		player = cp->crt->getPlayer();
		cp = cp->next_tag;
		if(!player || (player->isStaff() && player!=victim))
			continue;


		if(player==victim || kill_room) {

			if(kill_room && player!=victim && !silent) {
				switch(type) {
				case DM_NUCLEAR:
					broadcast("^g### Sadly, %s was killed by %s's radiation.", player->name, victim->name);
					break;
				default:
					broadcast("^r### Sadly, %s died in %s's explosion!", player->name, victim->name);
					break;
				}
			}

			player->hp.setCur(1);
			player->mp.setCur(1);

			if(unconscious)
				player->knockUnconscious(uncon_length);

			// do we send them to limbo?
			if(!no_limbo && !player->isStaff()) {
				newRoom = player->getLimboRoom().loadRoom(player);
				if(newRoom) {
					player->deleteFromRoom();
					player->addToRoom(newRoom);
					player->doPetFollow();
				}
			}
		}
	}
	return(0);
}

//*********************************************************************
//						dmKillSwitch
//*********************************************************************
// all *kill commands are routed through this function; dmKillAll
// and dmKill are passed the appropriate arguments

int dmKillSwitch(Player* player, cmd* cmnd) {
	int		i, silent=0, unconscious=0, uncon_length=0, type=DM_KILL;
	Player	*victim;

	// -s and -u can be in any position, so we have to look for them
	for(i=1; i<cmnd->num; i++) {
		if(!strcmp(cmnd->str[i], "-s"))
			silent=1;
		if(!strcmp(cmnd->str[i], "-u")) {
			unconscious=1;
			if(i < cmnd->num)
				uncon_length = atoi(cmnd->str[i+1]);

			uncon_length = MIN(600, MAX(15, uncon_length ) );
		}
	}


	// check for world-killers!
	if(!strcasecmp(cmnd->str[0], "*arma") || !strcasecmp(cmnd->str[0], "*armageddon"))
		type = DM_ARMAGEDDON;
	else if(!strcasecmp(cmnd->str[0], "*igmoo"))
		type = DM_IGMOO;
	else if(cmnd->num < 2) {
		player->print("Kill whom?\n");
		return(0);
	} else {
		if(!strcasecmp(cmnd->str[1], "-arma") || !strcasecmp(cmnd->str[1], "-armageddon"))
			type = DM_ARMAGEDDON;
		else if(!strcasecmp(cmnd->str[1], "-igmoo"))
			type = DM_IGMOO;
	}


	// if it's a world-killer
	if(type != DM_KILL)
		return(dmKillAll(type, silent, unconscious, uncon_length));


	// if it wont kill everyone, who will it kill?
	cmnd->str[1][0]=up(cmnd->str[1][0]);
	victim = gServer->findPlayer(cmnd->str[1]);
	if(!victim) {
		player->print("That person is not logged on.\n");
		return(0);
	}


	if(!strcasecmp(cmnd->str[0], "*kill")) {
		// default
	} else if(!strcasecmp(cmnd->str[0], "*combust"))
		type = DM_COMBUST;
	else if(!strcasecmp(cmnd->str[0], "*slime"))
		type = DM_SLIME;
	else if(!strcasecmp(cmnd->str[0], "*gnat"))
		type = DM_GNATS;
	else if(!strcasecmp(cmnd->str[0], "*trip"))
		type = DM_TRIP;
	else if(!strcasecmp(cmnd->str[0], "*bomb"))
		type = DM_BOMB;
	else if(!strcasecmp(cmnd->str[0], "*nuke"))
		type = DM_NUCLEAR;
	else if(!strcasecmp(cmnd->str[0], "*rape"))
		type = DM_RAPE;
	else if(!strcasecmp(cmnd->str[0], "*drain"))
		type = DM_DRAIN;
	else if(!strcasecmp(cmnd->str[0], "*crush"))
		type = DM_CRUSH;
	else if(!strcasecmp(cmnd->str[0], "*missile"))
		type = DM_MISSILE;

	if(cmnd->num >  2) {
		if(!strcasecmp(cmnd->str[2], "-combust"))
			type = DM_COMBUST;
		else if(!strcasecmp(cmnd->str[2], "-slime"))
			type = DM_SLIME;
		else if(!strcasecmp(cmnd->str[2], "-gnats"))
			type = DM_GNATS;
		else if(!strcasecmp(cmnd->str[2], "-trip"))
			type = DM_TRIP;
		else if(!strcasecmp(cmnd->str[2], "-bomb"))
			type = DM_BOMB;
		else if(!strcasecmp(cmnd->str[2], "-nuclear") || !strcmp(cmnd->str[2], "-nuke"))
			type = DM_NUCLEAR;
		else if(!strcasecmp(cmnd->str[2], "-rape"))
			type = DM_RAPE;
		else if(!strcasecmp(cmnd->str[2], "-drain"))
			type = DM_DRAIN;
		else if(!strcasecmp(cmnd->str[2], "-crush"))
			type = DM_CRUSH;
		else if(!strcasecmp(cmnd->str[2], "-missile"))
			type = DM_MISSILE;
	}

	dmKill(player, victim, type, silent, unconscious, uncon_length);
	return(0);
}

//*********************************************************************
//						dmRepair
//*********************************************************************

int dmRepair(Player* player, cmd* cmnd) {
	Player	*creature=0;
	int		a=0, count=0, check=0;

	if(cmnd->num < 2) {
		player->print("Repair who's armor?\n");
		return(0);
	}

	if(!strcmp(cmnd->str[2], "-c"))
		check=1;

	cmnd->str[1][0] = up(cmnd->str[1][0]);
	creature = gServer->findPlayer(cmnd->str[1]);

	if(!creature) {
		player->print("Player not found online.\n");
		return(0);
	}

	if(check)
		player->print("%s's current armor status:\n", creature->name);

	for(a=0;a<MAXWEAR;a++) {
		if(!creature->ready[a])
			continue;

		if(check) {
			player->print("%s: [%d/%d](%2f)\n", creature->ready[a]->name,
			      creature->ready[a]->getShotscur(), creature->ready[a]->getShotsmax(),
			      ((float)creature->ready[a]->getShotscur()/(float)creature->ready[a]->getShotsmax()));
			continue;
		}
		if(creature->ready[a]->getShotscur() < creature->ready[a]->getShotsmax()) {
			creature->ready[a]->setShotscur(creature->ready[a]->getShotsmax());

			player->print("%s's %s repaired to full shots (%d/%d).\n", creature->name, creature->ready[a]->name,
			      creature->ready[a]->getShotscur(), creature->ready[a]->getShotsmax());
			count++;

		}

	}


	if(count) {
		broadcast(isDm, "^g### %s repaired all of %s's armor.", player->name, creature->name);
		log_immort(true, player, "%s repaired all of %s's armor.", player->name, creature->name);
	}

	if(!count)
		player->print("%s is wearing nothing that needs to be repaired.\n", creature->name);

	return(0);
}

//*********************************************************************
//						dmMax
//*********************************************************************

int dmMax(Player* player, cmd* cmnd) {
	int i=0;

	if(cmnd)
		player->print("Maxing your stats out.\n");

	player->strength.setMax(MAX_STAT_NUM);
	player->dexterity.setMax(MAX_STAT_NUM);
	player->intelligence.setMax(MAX_STAT_NUM);
	player->constitution.setMax(MAX_STAT_NUM);
	player->piety.setMax(MAX_STAT_NUM);

	player->strength.setCur(MAX_STAT_NUM);
	player->dexterity.setCur(MAX_STAT_NUM);
	player->intelligence.setCur(MAX_STAT_NUM);
	player->constitution.setCur(MAX_STAT_NUM);
	player->piety.setCur(MAX_STAT_NUM);

	for(Realm r = MIN_REALM; r<MAX_REALM; r = (Realm)((int)r + 1))
		player->setRealm(10000000, r);
	player->coins.set(100000000, GOLD);

	player->hp.setMax(30000);
	player->hp.setCur(30000);
	player->mp.setMax(30000);
	player->mp.setCur(30000);

	if(!strcmp(player->name, "Bane")) {
		player->setLevel(69);
		player->setExperience(2100000000);
	} else {
		player->setLevel(MAXALVL);
		player->setExperience(900000000);
	}

	for(i=0; i<MAXSPELL; i++)
		player->learnSpell(i);
	for(i=0; i<gConfig->getMaxSong(); i++)
		player->learnSong(i);

	if(player->getClass() == BUILDER) {
		player->forgetSpell(S_PLANE_SHIFT);
		player->forgetSpell(S_JUDGEMENT);
		player->forgetSpell(S_ANIMIATE_DEAD);
	}

	player->setAlignment(0);
	return(0);
}


//*********************************************************************
//						dmBackupPlayer
//*********************************************************************

int dmBackupPlayer(Player* player, cmd* cmnd) {

	char    filename[80], restoredFile[80];
	Player	*target=0;
	bool	online=false;

	if(cmnd->num < 2) {
		player->print("Backup who?\n");
		return(0);
	}


	if(cmnd->num > 2 && !strcmp(cmnd->str[2], "-r")) {
		cmnd->str[1][0] = up(cmnd->str[1][0]);
		sprintf(filename, "%s/%s.bak.xml", BACKUPPATH, cmnd->str[1]);
		sprintf(restoredFile, "%s/%s.xml", PLAYERPATH, cmnd->str[1]);

		if(file_exists(filename)) {

			target = gServer->findPlayer(cmnd->str[1]);
			if(target) {
				player->print("%s is currently online.\n%s must be offline for auto-backup restore.\n", target->name, target->upHeShe());
				return(0);
			}

			if(file_exists(restoredFile))
				unlink(restoredFile);

			link(filename, restoredFile);
			broadcast(isDm, "^g*** %s restored %s from auto-backup.", player->name, cmnd->str[1]);
			player->print("Restoring %s from last auto-backup.\n", cmnd->str[1]);
			log_immort(false,player, "%s restored %s from auto-backup file.\n", player->name, cmnd->str[1]);
		} else {
			player->print("Backup file for that player does not exist.\n");
		}
		return(0);
	}


	cmnd->str[1][0] = up(cmnd->str[1][0]);
	target = gServer->findPlayer(cmnd->str[1]);

	if(!target) {
		if(!loadPlayer(cmnd->str[1], &target)) {
			player->print("Player does not exist.\n");
			return(0);
		}
	} else
		online = true;


	if(cmnd->num > 2 && !strcmp(cmnd->str[2], "-d")) {
		sprintf(filename, "%s/%s.bak.xml", BACKUPPATH, target->name);
		if(file_exists(filename)) {
			unlink(filename);
			broadcast(isDm, "^g*** %s deleted %s's backup file.", player->name, target->name);
			player->print("Deleted %s.bak from disk.\n", target->name);

			log_immort(false,player, "%s deleted backup file for player %s.\n", player->name, target->name);
		} else {
			player->print("Backup file for player %s does not exist.\n", target->name);

		}

		if(!online)
			free_crt(target);
		return(0);
	}


	if(target->save(online, LS_BACKUP) > 0) {
		player->print("Backup failed.\n");
		if(!online)
			free_crt(target);
		return(0);
	}

	broadcast(isDm, "^g*** %s backed up %s to disk.", player->name, target->name);
	player->print("%s has been backed up.\n", target->name);

	log_immort(false,player, "%s backed up player %s to disk.\n", player->name, target->name);

	if(!online)
		free_crt(target);
	return(0);
}


//*********************************************************************
//						dmChangeStats
//*********************************************************************

int dmChangeStats(Player* player, cmd* cmnd) {
	Player	*target=0;


	if(cmnd->num < 2) {
		player->print("Allow whom to change their stats?\n");
		return(0);
	}

	cmnd->str[1][0]=up(cmnd->str[1][0]);
	target = gServer->findPlayer(cmnd->str[1]);
	if(!target) {
		player->print("Player not online.\n");
		return(0);
	}

	if(target->flagIsSet(P_DM_INVIS) && !isDm(player)) {
		player->print("Player not online.\n");
		return(0);
	}

	if(!target->flagIsSet(P_CAN_CHANGE_STATS)) {
		target->setFlag(P_CAN_CHANGE_STATS);
		player->print("%s can now choose new stats.\n", target->name);
	} else {
		target->clearFlag(P_CAN_CHANGE_STATS);
		player->print("%s can no longer choose new stats.\n", target->name);
	}

	log_immort(false, player, "%s set %s to choose new stats\n", player->name, target->name);

	return(0);
}


//*********************************************************************
//						dmJailPlayer
//*********************************************************************

int dmJailPlayer(Player* player, cmd* cmnd) {
	int			tm=0, i=0, iTmp=0, len=0, strLen=0;
	long		t=0;
	Room	*newRoom=0;
	Player	*target=0;
	char		*reason=0;
	bool		online=false;

	if(!player->isStaff() && !player->isWatcher())
		return(cmdNoExist(player, cmnd));
	if(!player->isWatcher())
		return(cmdNoAuth(player));

	if(cmnd->num < 2) {
		player->print("Jail whom?\n");
		player->print("Syntax: *jail (player) (minutes) [-b|-r]\n");
		return(0);
	}

	lowercize(cmnd->str[1], 1);
	target = gServer->findPlayer(cmnd->str[1]);
	if(!target) {
		if(!loadPlayer(cmnd->str[1], &target)) {
			player->print("Player does not exist.\n");
			return(0);
		}
	} else
		online = true;

	if(target->isStaff()) {
		player->print("Don't use *jail on staff members.\n");
		if(!online)
			free_crt(target);
		return(0);
	}
	if(player == target) {
		player->print("Do not jail yourself.\n");
		if(!online)
			free_crt(target);
		return(0);
	}

	if(player->isWatcher() && !isCt(player) && target->isWatcher()) {
		player->print("Do not jail other watchers.\n");
		if(!online)
			free_crt(target);
		return(0);
	}

	strLen = strlen(cmnd->fullstr);

	// This kills all leading whitespace
	while(i<strLen && isspace(cmnd->fullstr[i]))
		i++;

	// This kills the command itself
	while(i<strLen && !isspace(cmnd->fullstr[i]))
		i++;

	// This kills all the white space before the guild
	while(i<strLen && isspace(cmnd->fullstr[i]))
		i++;

	len = strlen(&cmnd->fullstr[i]);

	reason = strstr(&cmnd->fullstr[i], "-r ");
	if(reason) { // There is a reason string then
		iTmp = i;
		while(iTmp < strLen && &cmnd->fullstr[iTmp] != reason)
			iTmp++;
		reason += 3;
		while(isspace(*reason))
			reason++;
		// Kill trailing whitespace
		len = strlen(reason);
		while(isspace(reason[len-1]))
			len--;
		reason[len] = '\0';
	}
	if(iTmp) { // We have a reason, everything else stops at the beginging of the -r
		strLen = iTmp;
		cmnd->fullstr[iTmp] = '\0';
	}
	if(!reason && player->isWatcher()) {
		player->print("You must enter a reason. Use the -r option.\n");
		if(!online)
			free_crt(target);
		return(0);
	}

	if(!reason && !strcmp(player->name, "Bane")) {
		player->print("Use the -r option and enter a reason, assbandit!\n");
		if(!online)
			free_crt(target);
		return(0);
	}

	tm = MAX(1, cmnd->val[1]);

	if(player->isWatcher())
		tm = MIN(60, cmnd->val[1]);

	t = (long)tm*60;

	target->lasttime[LT_JAILED].ltime = time(0);
	target->lasttime[LT_JAILED].interval = t;

	target->setFlag(P_JAILED);


	//log_immort(true, player, "%s jailed %s for %d minutes.\n", player->name, target->name, tm);
	if(!reason) {
		logn("log.jail", "%s jailed %s for %d minutes.%s\n", player->name, target->name, tm);
		broadcast(isCt, "^y*** %s jailed %s for %d minutes.%s", player->name, target->name, tm);
	} else {
		logn("log.jail", "%s jailed %s for %d minutes. Reason: %s\n", player->name, target->name, tm, reason);
		broadcast(isCt, "^y*** %s jailed %s for %d minutes. Reason: %s", player->name, target->name, tm, reason);
	}

	if(player->isWatcher())
		logn("log.wjail", "%s jailed %s(%s) for %d minutes. Reason: %s\n",
			player->name, target->name, target->room.str().c_str(), tm, reason);

	CatRef	cr;
	cr.setArea("jail");
	cr.id = 1;

	if(!online) {

		if(!strcmp(cmnd->str[2], "-b"))
			broadcast("^R### Cackling demons drag %s to the Dungeon of Despair.", target->name);
		target->room = cr;
		player->print("%s is now jailed.\n", target->name);

	} else {

		if(!loadRoom(cr, &newRoom)) {
			player->print("Problem loading room %s.\nAborting.\n", cr.str().c_str());
			return(0);
		} else {
			player->print("%s is now jailed.\n", target->name);
			broadcast(NULL, target->getRoom(),
				"^RA demonic jailer just arrived.\nThe demonic jailer opens a portal to Hell.\nThe demonic jailer drags %s screaming to the Dungeon of Despair.", target->name);

			target->printColor("^RThe demonic jailer grips your soul and drags you to the Dungeon of Despair.\n");
			broadcast(target->getSock(), target->getRoom(), "^RThe portal closes with a puff of smoke.");

			target->deleteFromRoom();
			target->addToRoom(newRoom);
			target->printColor("^RThe demonic jailer says, \"Pathetic mortal!\"\nThe demonic jailer spits on you.\nThe demonic jailer vanishes.\n");
//			target->doPetFollow();
		}

		if(!strcmp(cmnd->str[2], "-b"))
			broadcast("^R### Cackling demons drag %s to the Dungeon of Despair.", target->name);

	}

	target->save();
	if(!online)
		free_crt(target);
	return(0);
}


//*********************************************************************
//						dmLts
//*********************************************************************

int dmLts(Player* player, cmd* cmnd) {
	Player	*target=0;
	int		i=0;
	long	t = time(0);

	if(cmnd-> num < 2) {
		player->print("syntax: *lt <player>\n");
		return(0);
	}
	cmnd->str[1][0] = up(cmnd->str[1][0]);
	target = gServer->findPlayer(cmnd->str[1]);
	if(target == NULL) {
		player->print("%s is not on.\n", cmnd->str[1]);
		return(0);
	}
	player->print("Now: %ld\n", t);
	for(i = 0 ; i < MAX_LT ; i++ ) {
		player->print("LT %d - %ld %ld %ld (%ld)\n", i, target->lasttime[i].interval,
		      target->lasttime[i].ltime, target->lasttime[i].misc, LT(player, i) - t);
	}
	return(0);
}



//*********************************************************************
//						dmLtClear
//*********************************************************************

int dmLtClear(Player* player, cmd* cmnd) {
	Player	*target=0;
//	int		i=0;

	if(cmnd->num < 2) {
		player->print("syntax: *ltclear <player>\n");
		return(0);
	}

	lowercize(cmnd->str[1], 1);
	target = gServer->findPlayer(cmnd->str[1]);

	if(!target) {
		player->print("%s is not on.\n", cmnd->str[1]);
		return(0);
	}
	target->lasttime[LT_INVOKE].interval = 0;
//	for(i=0; i<MAX_LT; i++) {
//		target->lasttime[i].interval = 0;
//	}
//
	player->print("Last times reset!\n");
	return(0);

}

//*********************************************************************
//						dm2x
//*********************************************************************

int dm2x(Player* player, cmd* cmnd) {
	if(cmnd->num == 1) {

		// give them a list
		player->printColor("Syntax: *2x                          - list accounts that may double log.\n");
		player->printColor("Syntax: *2x -add ^e<account> <account>^x - allow accounts to double log.\n");
		player->printColor("Syntax: *2x -del ^e<account> <account>^x - prevent accounts to double log.\n");
		player->print("\n");
		gConfig->listDoubleLog(player);

	} else if(!strcmp(cmnd->str[1], "-add")) {

		// add a new account pair
		if(!cmnd->str[2][0] || !cmnd->str[3][0]) {
			player->print("Account names not provided.\n");
		} else {
			player->printColor("^G*ADD*^X Accounts \"%s\" and \"%s\" may now double log.\n",
				cmnd->str[2], cmnd->str[3]);
			gConfig->addDoubleLog(cmnd->str[2], cmnd->str[3]);
		}

	} else if(!strcmp(cmnd->str[1], "-del") || !strcmp(cmnd->str[1], "-rem")) {

		// remove an account pair
		if(!cmnd->str[2][0] || !cmnd->str[3][0]) {
			player->print("Account names not provided.\n");
		} else {
			player->printColor("^R*DEL*^X Accounts \"%s\" and \"%s\" may no longer double log.\n",
				cmnd->str[2], cmnd->str[3]);
			gConfig->remDoubleLog(cmnd->str[2], cmnd->str[3]);
		}

	} else {
		player->printColor("Command not understood.\n");
		player->printColor("Syntax: *2x                          - list accounts that may double log.\n");
		player->printColor("Syntax: *2x -add ^e<account> <account>^x - allow accounts to double log.\n");
		player->printColor("Syntax: *2x -del ^e<account> <account>^x - prevent accounts to double log.\n");
	}
	return(0);
}