roh/conf.old/area/
roh/config/code/python/
roh/config/game/area/
roh/config/game/signs/
roh/help/dmhelp/
roh/help/help/
roh/log/
roh/log/staff/
roh/monsters/ocean/
roh/objects/misc/
roh/objects/ocean/
roh/player/
roh/rooms/area/1/
roh/rooms/misc/
roh/rooms/ocean/
roh/src-2.47e/
/*
 * dm.cpp
 *	 Standard staff functions
 *   ____            _
 *  |  _ \ ___  __ _| |_ __ ___  ___
 *  | |_) / _ \/ _` | | '_ ` _ \/ __|
 *  |  _ <  __/ (_| | | | | | | \__ \
 *  |_| \_\___|\__,_|_|_| |_| |_|___/
 *
 *	Copyright (C) 2007-2012 Jason Mitchell, Randi Mitchell
 * 	   Contributions by Tim Callahan, Jonathan Hseu
 *  Based on Mordor (C) Brooke Paul, Brett J. Vickers, John P. Freeman
 *
 */


// Mud Includes
#include "mud.h"
#include "commands.h"
#include "dm.h"
//#include "socket.h"
#include "effects.h"
#include "quests.h"

// C++ includes
#include <sstream>
#include <iomanip>
#include <locale>

extern int	controlSock;
long		last_dust_output;
extern long	last_weather_update;



//*********************************************************************
//						dmReboot
//*********************************************************************

int dmReboot(Player* player, cmd* cmnd) {
	bool    resetShips=false;


	if(	!player->isDm() &&
		!(player->flagIsSet(P_CAN_REBOOT) &&
		player->getClass() == CARETAKER)
	)
		return(cmdNoAuth(player));

	if(cmnd->num==2 && !strcmp(cmnd->str[1], "-ships"))
		resetShips = true;

	player->print("Rebooting now!\n");
	gConfig->swapAbort();
	logn("log.bane", "Reboot by %s.\n", player->getCName());
	broadcast("### Going for a reboot, hang onto your seats!");
	if(resetShips)
		player->print("Resetting game time to midnight, updating ships...\n");
	gServer->processOutput();
	loge("--- Attempting game reboot ---\n");
	gConfig->resaveAllRooms(0);

	gServer->startReboot(resetShips);

	merror("dmReboot failed!!!", FATAL);
	return(0);

}

//*********************************************************************
//						dmMobInventory
//*********************************************************************

int dmMobInventory(Player* player, cmd* cmnd) {
	Monster	*monster=0;
	Object	*object;
	//char	str[2048];
	int		i=0;

	if(!player->canBuildMonsters())
		return(cmdNoAuth(player));


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

	monster = player->getParent()->findMonster(player, cmnd);
	if(!monster) {
		player->print("That's not here.\n");
		return(0);
	}



	if(!strcmp(cmnd->str[2], "-l") || player->getClass() == BUILDER) {
		player->print("Items %s will possibly drop:\n", monster->getCName());
		for(i=0;i<10;i++) {
			if(!monster->carry[i].info.id) {
				player->print("Carry slot %d: %sNothing.\n", i+1, i < 9 ? " " : "");
				continue;
			}

			if(!loadObject(monster->carry[i].info, &object))
				continue;
			if(!object)
				continue;

			if(player->getClass() == BUILDER && player->checkRangeRestrict(object->info))
				player->print("Carry slot %d: %sout of range(%s).\n", i+1, i < 9 ? " " : "", object->info.str().c_str());
			else
				player->printColor("Carry slot %d: %s%s(%s).\n", i+1, i < 9 ? " " : "", object->getCName(), object->info.str().c_str());

			delete object;
		}

		return(0);
	}
	bstring str = monster->listObjects(player, true);
	bstring prefix =bstring(monster->flagIsSet(M_NO_PREFIX) ? "":"The ") + monster->getName() + " is carrying: ";
	if(str != "") {
		str =  prefix + str + ".";
	} else {
		str = prefix + "Nothing.";
	}

	*player << ColorOn << str << "\n" << ColorOff;

	return(0);
}

//*********************************************************************
//						dmSockets
//*********************************************************************

int dmSockets(Player* player, cmd* cmnd) {
	int num=0;

	player->print("Connected Sockets:\n");

	for(Socket* sock : gServer->sockets) {
		num += 1;
		player->print("Fd: %-2d   %s (%ld)\n", sock->getFd(), sock->getHostname().c_str(), sock->getIdle());
	}
	player->print("%d total connection%s.\n", num, num != 1 ? "s" : "");
	return(PROMPT);
}




//*********************************************************************
//						dmLoadSave
//*********************************************************************
// handles loading and saving of a bunch of config files

int dmLoadSave(Player* player, cmd* cmnd, bool load) {
	if(cmnd->num < 2) {
		std::list<bstring> loadList;
		std::list<bstring> saveList;
		std::list<bstring>::const_iterator it;

		// create a list of possible effects
		loadList.push_back("areas");
		loadList.push_back("bans");
		loadList.push_back("calendar");
		loadList.push_back("catrefinfo");
		loadList.push_back("config");
		loadList.push_back("classes");
		loadList.push_back("clans");
		loadList.push_back("deities");
		loadList.push_back("faction");
		loadList.push_back("fishing");
		loadList.push_back("flags");
		loadList.push_back("guilds");
		loadList.push_back("limited");
		loadList.push_back("msdp");
		loadList.push_back("properties");
		loadList.push_back("proxies");
		loadList.push_back("quests");
		loadList.push_back("races");
		loadList.push_back("recipes");
		loadList.push_back("ships");
		loadList.push_back("skills");
		loadList.push_back("socials");
		loadList.push_back("spells");
		loadList.push_back("spl [spell id]");
		loadList.push_back("startlocs");

		saveList.push_back("bans");
		saveList.push_back("config");
		saveList.push_back("guilds");
		saveList.push_back("limited");
		saveList.push_back("properties");
		saveList.push_back("proxies");
		saveList.push_back("recipes");
        saveList.push_back("socials");
		saveList.push_back("spells");

		// run through the lists and display them
		player->print("*dmload / *dmsave supports the following options:\n");
		
		player->printColor("^yLOAD:\n");
		bool leftColumn = true;
		for(it = loadList.begin() ; it != loadList.end() ; it++) {
			player->printColor("   %-15s", (*it).c_str());
			if(!leftColumn)
				player->print("\n");
			leftColumn = !leftColumn;
		}
		if(leftColumn)
			player->print("\n");
		player->print("   \n");


		// now print the save list
		player->printColor("^ySAVE:\n");
		leftColumn = true;
		for(it = saveList.begin() ; it != saveList.end() ; it++) {
			player->printColor("   %-15s", (*it).c_str());
			if(!leftColumn)
				player->print("\n");
			leftColumn = !leftColumn;
		}
		if(leftColumn)
			player->print("\n");
		player->print("\n");
		return(0);
	}

	if(!strcmp(cmnd->str[1], "bans")) {
		if(load) {
			gConfig->loadBans();
			player->print("Bans reloaded.\n");
			dmListbans(player, NULL);
		} else {
			gConfig->saveBans();
			player->print("Bans saved.\n");
		}
	} else if(!strcmp(cmnd->str[1], "config")) {
		if(load) {
			player->print("Reloading configuration file.\n");
			bool result = gConfig->loadConfig(true);
			if(result)
				player->print("Success!\n");
			else
				player->print("Failed!\n");
		} else {
			player->print("Saving configuration file.\n");
			gConfig->saveConfig();
		}
	} else if(!strcmp(cmnd->str[1], "guilds")) {
		if(load) {
			player->print("Reloading guilds.\n");
			gConfig->loadGuilds();
		} else {
			player->print("Saving guilds.\n");
			gConfig->saveGuilds();
		}
	}
	else if(!strcmp(cmnd->str[1], "socials")) {
	    if(load) {
	        gConfig->clearSocials();
	        gConfig->loadSocials();
	        gConfig->writeSocialFile();

	        *player << "Socials reloaded.\n";
	    } else {
	        gConfig->saveSocials();
	        *player << "Socials saved\n";
	    }
	}
	else if(!strcmp(cmnd->str[1], "recipes")) {
		if(load) {
			gConfig->loadRecipes();
			player->print("Recipes reloaded.\n");
		} else {
			gConfig->saveRecipes();
			player->print("Recipes saved.\n");
		}
	} else if(!strcmp(cmnd->str[1], "properties")) {
		if(load) {
			gConfig->loadProperties();
			player->print("Properties reloaded.\n");
		} else {
			gConfig->saveProperties();
			player->print("Properties saved.\n");
		}
	} else if(!strcmp(cmnd->str[1], "proxies")) {
		if(load) {
			gConfig->loadProxyAccess();
			player->print("Proxies reloaded.\n");
		} else {
			gConfig->saveProxyAccess();
			player->print("Proxies saved.\n");
		}
	} else if(!strcmp(cmnd->str[1], "limited")) {
		if(load) {
			gConfig->loadLimited();
			player->print("Limited items reloaded.\n");
		} else {
			gConfig->saveLimited();
			player->print("Limited items saved.\n");
		}
	} else if(!strcmp(cmnd->str[1], "spells")) {
		if(load) {
			gConfig->loadSpells();
			player->print("Spell list reloaded.\n");
		} else {
			gConfig->saveSpells();
            gConfig->writeSpellFiles();
			player->print("Spell list saved.\n");
		}
	} else if(!strcmp(cmnd->str[1], "areas") && load) {
		if(!strcmp(cmnd->str[2], "confirm")) {

			std::list<Area*>::iterator at;
			std::map<bstring, AreaRoom*>::iterator it;
			AreaRoom* aRoom = 0;

			for(at = gConfig->areas.begin() ; at != gConfig->areas.end() ; at++) {
				for(it = (*at)->rooms.begin() ; it != (*at)->rooms.end() ; it++) {
					aRoom = (*it).second;
					aRoom->setStayInMemory(true);
					aRoom->expelPlayers(false, true, true);
				}
			}

			gConfig->loadAreas();
			player->print("Area reloaded.\n");
		} else {
			player->print("This will expel all current players in the overland to their recall rooms.\n");
			player->printColor("Type ^y*dmload areas confirm^x to continue.\n");
		}
	} else if(!strcmp(cmnd->str[1], "quests") && load) {
		gConfig->loadQuestTable();
		gConfig->loadQuests();
		gConfig->resetParentQuests();
		player->print("Quests reloaded.\n");
	}
	else if(!strcmp(cmnd->str[1], "clans") && load) {
		gConfig->loadClans();
		player->print("Clans reloaded.\n");
	} else if(!strcmp(cmnd->str[1], "msdp") && load) {
		gConfig->loadMsdpVariables();
		player->print("MSDP Variables reloaded.\n");
		// We've now cleared all reportable variables, have clients re-send what they want now
		for(Socket* sock : gServer->sockets) {
			if (sock->getMsdp()) {
				sock->bprint(telnet::will_msdp);
			} else if (sock->getAtcp()) {
				sock->bprint(telnet::do_atcp);
			}
		}
	} else if(!strcmp(cmnd->str[1], "classes") && load) {
		gConfig->loadClasses();
		player->print("Classes reloaded.\n");
	} else if(!strcmp(cmnd->str[1], "races") && load) {
		gConfig->loadRaces();
		player->print("Races reloaded.\n");
	} else if(!strcmp(cmnd->str[1], "deities") && load) {
		gConfig->loadDeities();
		player->print("Deities reloaded.\n");
	} else if(!strcmp(cmnd->str[1], "skills") && load) {
		gConfig->loadSkills();
		player->print("Skills reloaded.\n");
	} else if(!strcmp(cmnd->str[1], "startlocs") && load) {
		gConfig->loadStartLoc();
		player->print("StartLocs reloaded.\n");
	} else if(!strcmp(cmnd->str[1], "catrefinfo") && load) {
		gConfig->loadCatRefInfo();
		player->print("CatRefInfo reloaded.\n");
	} else if(!strcmp(cmnd->str[1], "flags") && load) {
		gConfig->loadFlags();
		player->print("Flags reloaded.\n");
	} else if(!strcmp(cmnd->str[1], "faction") && load) {
		gConfig->loadFactions();
		player->print("Factions reloaded.\n");
	} else if(!strcmp(cmnd->str[1], "fishing") && load) {
		gConfig->loadFishing();
		player->print("Fishing reloaded.\n");
	} else if(!strcmp(cmnd->str[1], "calendar") && load) {
		reloadCalendar(player);
	} else {
		player->print("Invalid request!\n");
		cmnd->num = 1;
		dmLoadSave(player, cmnd, load);
	}

	return(0);
}

//*********************************************************************
//						dmLoad
//*********************************************************************
// a wrapper

int dmLoad(Player* player, cmd* cmnd) {
	dmLoadSave(player, cmnd, true);
	return(0);
}

//*********************************************************************
//						dmSave
//*********************************************************************
// a wrapper

int dmSave(Player* player, cmd* cmnd) {
	dmLoadSave(player, cmnd, false);
	return(0);
}

//*********************************************************************
//						dmTeleport
//*********************************************************************
// This function allows staff to teleport to a given room number, or to
// a player's location.  It will also teleport a player to the DM or
// one player to another.

void Player::dmPoof(BaseRoom* room, BaseRoom *newRoom) {
	if(flagIsSet(P_ALIASING)) {
		alias_crt->deleteFromRoom();
		broadcast(getSock(), room, "%M just wandered away.", alias_crt);
		if(newRoom)
			alias_crt->addToRoom(newRoom);
	}

	if(flagIsSet(P_DM_INVIS)) {
		if(isDm())
			broadcast(::isDm, getSock(), room, "*DM* %s disappears in a puff of smoke.", getCName());
		if(cClass == CARETAKER)
			broadcast(::isCt, getSock(), room, "*DM* %s disappears in a puff of smoke.", getCName());
		if(!isCt())
			broadcast(::isStaff, getSock(), room, "*DM* %s disappears in a puff of smoke.", getCName());
	} else {
		broadcast(getSock(), room, "%M disappears in a puff of smoke.", this);
	}
}

int dmTeleport(Player* player, cmd* cmnd) {
	BaseRoom	*room=0, *old_room=0;
	UniqueRoom		*uRoom=0;
	Creature	*creature=0;
	Player		*target=0, *target2=0;

	Location	l;


	// *t 1 and *t 1.-10.7 will trigger num < 2,
	// *t misc.100 will not, so we need to make an exception
	bstring str = getFullstrText(cmnd->fullstr, 1);
	bstring txt = getFullstrText(str, 1, '.');

	// set default *t room
	if(str == "") {
		l = player->getRecallRoom();

		if(player->inAreaRoom() && l.mapmarker == player->currentLocation.mapmarker) {
			player->print("You are already there!\n");
			return(0);
		}

		room = 	l.loadRoom();
	} else if(cmnd->num < 2 || (txt != "" && txt.getAt(0))) {
		Area		*area=0;

		getDestination(str, &l, player);

		if(player->getClass() != BUILDER && l.mapmarker.getArea()) {
			if(player->inAreaRoom() && l.mapmarker == player->currentLocation.mapmarker) {
				player->print("You are already there!\n");
				return(0);
			}

			area = gConfig->getArea(l.mapmarker.getArea());
			if(!area) {
				player->print("Area does not exist.\n");
				return(0);
			}

			// pointer to old room
			player->dmPoof(player->getRoomParent(), 0);
			area->move(player, &l.mapmarker);
			// manual
			if(player->flagIsSet(P_ALIASING))
				player->getAlias()->addToRoom(player->getRoomParent());
			return(0);
		}


		if(!validRoomId(l.room)) {
			player->print("Error: out of range.\n");
			return(0);
		}
		if(!loadRoom(l.room, &uRoom)) {
			player->print("Error (%s)\n", l.str().c_str());
			return(0);
		}

		if(!player->checkBuilder(l.room))
			return(0);

		room = uRoom;

	} else if(cmnd->num < 3) {

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

		if(player->getClass() == BUILDER && creature->getClass() != BUILDER) {
			player->print("You are only allowed to teleport to other builder.\n");
			return(0);
		}


		old_room = player->getRoomParent();
		room = creature->getRoomParent();

		player->dmPoof(old_room, room);

		player->deleteFromRoom();
		player->addToSameRoom(creature);
		player->doFollow(old_room);
		return(0);

	} else {
		if(!player->isCt()) {
			player->print("You are not allowed to teleport others to you.\n");
			return(0);
		}

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


		old_room = target->getRoomParent();
		room = target2->getRoomParent();

		target->dmPoof(old_room, room);

		target->deleteFromRoom();
		target->addToSameRoom(target2);
		target->doPetFollow();
		return(0);
	}

	old_room = player->getRoomParent();

	player->dmPoof(old_room, room);

	player->deleteFromRoom();
	player->addToRoom(room);
	player->doFollow(old_room);

	return(0);
}


//*********************************************************************
//						dmUsers
//*********************************************************************
// This function allows staff to list all users online, displaying
// level, name, current room # and name, and address.

int dmUsers(Player* player, cmd* cmnd) {
	long	t = time(0);
	bool	full=false;
	bstring tmp="", host="";
	Player* user=0;
	//Socket* sock=0;

	std::ostringstream oStr;
	char	str[100];
	oStr.setf(std::ios::left, std::ios::adjustfield);
	oStr.imbue(std::locale(""));

	bstring cr = gConfig->defaultArea;
	if(player->inUniqueRoom())
		cr = player->getUniqueRoomParent()->info.area;

	if(cmnd->num > 1 && cmnd->str[1][0] == 'f')
		full = true;

	oStr << "^bLev  Clas  Player     ";
	if(full)
		oStr << "Address                                                    Idle";
	else
		oStr << "Room                 Address             Last Command      Idle";
	oStr << "\n---------------------------------------------------------------------------------------\n";

	//std::pair<bstring, Player*> p;
	for(Socket* sock : gServer->sockets) {
		//user = p.second;
		//sock = user->getSock();
		user = sock->getPlayer();

		if(!user || !player->canSee(user))
			continue;

		host = sock->getHostname();
		if(user->isDm() && !player->isDm())
			host = "mud.rohonline.net";

		oStr.setf(std::ios::right, std::ios::adjustfield);
		oStr << "^x[" << std::setw(2) << user->getLevel() << "] ";
		oStr.setf(std::ios::left, std::ios::adjustfield);

		if(user->isStaff())
			oStr << "^g";
		oStr << std::setw(4) << bstring(getShortClassName(user)).left(4) << "^w ";

		if(!user->flagIsSet(P_SECURITY_CHECK_OK))
			oStr << "^r";
		else
			oStr << "^y";

		if(user->flagIsSet(P_DM_INVIS))
			oStr << "+";
		else if(user->isEffected("incognito"))
			oStr << "g";
		else if(user->isInvisible())
			oStr << "*";
		else
			oStr << " ";

		if(user->flagIsSet(P_OUTLAW))
			oStr << "^R";
		else if(user->flagIsSet(P_LINKDEAD))
			oStr << "^G";
		else if(user->flagIsSet(P_WATCHER))
			oStr << "^w";
		else if(user->flagIsSet(P_GLOBAL_GAG))
			oStr << "^m";

		if(user->getProxyName().empty())
			oStr << std::setw(10) << user->getName().left(10) << "^w ";
		else
			oStr << std::setw(10) << bstring(user->getName() + "(" + user->getProxyName() + ")").left(10) << "^w ";

		if(!sock->isConnected()) {
			sprintf(str, "connecting (Fd: %d)", sock->getFd());
			oStr << "^Y" << std::setw(20) << str << " ^c" << std::setw(37) << host.left(37);
		} else if(full) {
			oStr << "^m" << std::setw(58) << host.left(58);
		} else {
			if(user->inUniqueRoom()) {
				sprintf(str, "%s: ^b%s", user->getUniqueRoomParent()->info.str(cr, 'b').c_str(), stripColor(user->getUniqueRoomParent()->getCName()).c_str());
				oStr << std::setw(22 + (str[0] == '^' ? 4 : 0)) << bstring(str).left(22 + (str[0] == '^' ? 4 : 0));
			} else if(user->inAreaRoom()){
				//sprintf(str, "%s", user->area_room->mapmarker.str(true).c_str());
				//oStr << std::setw(26) << bstring(str).left(26);
				// TODO: Strip Color
				oStr << std::setw(38) << user->getAreaRoomParent()->mapmarker.str(true).left(38);
			} else {
				oStr << std::setw(38) << "(Unknown)";
			}


			oStr << " ^c" << std::setw(19) << host.left(19)
				 << " ^g";
			if(!user->isDm() || player->isDm())
				oStr << std::setw(17) << dmLastCommand(user).left(17);
			else
				oStr << std::setw(17) << "l";
		}

		sprintf(str, "%02ld:%02ld", (t-sock->ltime)/60L, (t-sock->ltime)%60L);
		oStr << " ^w" << str << "\n";
	}

	player->printColor("%s", oStr.str().c_str());
	player->hasNewMudmail();
	player->print("\n");

	return(0);
}

//*********************************************************************
//						dmFlushSave
//*********************************************************************
// This function allows staff to save all the rooms in memory back to
// disk in one fell swoop.

int dmFlushSave(Player* player, cmd* cmnd) {
	if(cmnd->num < 2) {
		player->print("All rooms and contents flushed to disk.\n");
		gConfig->resaveAllRooms(0);
	} else {
		player->print("All rooms and PERM contents flushed to disk.\n");
		gConfig->resaveAllRooms(PERMONLY);
	}
	return(0);
}

//*********************************************************************
//						dmShutdown
//*********************************************************************
// This function allows staff to shut down the game in a given number of
// minutes.

int dmShutdown(Player* player, cmd* cmnd) {
	player->print("Ok.\n");

	log_immort(true, player, "*** Shutdown by %s.\n", player->getCName());

	Shutdown.ltime = time(0);
	Shutdown.interval = cmnd->val[0] * 60 + 1;

	return(0);
}

//*********************************************************************
//						dmFlushCrtObj
//*********************************************************************
// This function allows staff to flush the object and creature data so
//  that updated data can be loaded into memory instead.

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

	if(!player->canBuildObjects() && !player->canBuildMonsters())
		return(cmdNoAuth(player));

	if(player->canBuildObjects())
		gConfig->flushObject();
	if(player->canBuildMonsters())
		gConfig->flushMonster();

	player->print("Basic object and monster data flushed from memory.\n");
	return(0);
}



//*********************************************************************
//						dmResave
//*********************************************************************
// This function allows staff to save a room back to disk.

int dmResave(Player* player, cmd* cmnd) {
	int		s=0;

	if(!player->builderCanEditRoom("use *save"))
		return(0);

	if(	cmnd->num > 1 &&
		(!strcmp(cmnd->str[1], "c") || !strcmp(cmnd->str[1], "o"))
	) {
		bstring str = getFullstrText(cmnd->fullstr, 3);
		if(str == "") {
			player->print("Syntax: *save %c [name] [number]\n", cmnd->str[1]);
			return(0);
		}

		CatRef	cr;
		getCatRef(str, &cr, player);

		if(!strcmp(cmnd->str[1], "c"))
			dmSaveMob(player, cmnd, cr);
		else if(!strcmp(cmnd->str[1], "o"))
			dmSaveObj(player, cmnd, cr);
		return(0);
	}


	if(!player->checkBuilder(player->getUniqueRoomParent())) {
		player->print("Error: this room is out of your range; you cannot save this room.\n");
		return(0);
	}


	if(player->inUniqueRoom()) {

		s = gConfig->resaveRoom(player->getUniqueRoomParent()->info);
		if(s < 0)
			player->print("Resave failed. Tell this number to Bane: (%d)\n",s);
		else
			player->print("Room saved.\n");

	} else if(player->inAreaRoom()) {

		player->getAreaRoomParent()->save(player);

	} else
		player->print("Nothing to save!\n");

	return(0);
}

//*********************************************************************
//						dmPerm
//*********************************************************************
// This function allows staff to make a given object sitting on the
// floor into a permanent object.

int dmPerm(Player* player, cmd* cmnd) {
	std::map<int, crlasttime>::iterator it;
	Monster* target=0;
	Object	*object=0;
	int		x=0;

	if(!player->canBuildMonsters() && !player->canBuildObjects())
		return(cmdNoAuth(player));

	if(!player->checkBuilder(player->getUniqueRoomParent())) {
		player->print("Room number not in any of your alotted ranges.\n");
		return(0);
	}
	if(!player->builderCanEditRoom("use *perm"))
		return(0);

	if(!needUniqueRoom(player))
		return(0);

	if(cmnd->num < 2) {
		player->print("Syntax: *perm [o|c|t] [name|d|exit] [timeout|slot]\n");
		return(0);
	}

	switch(low(cmnd->str[1][0])) {
	case 'o':

		if(!player->canBuildObjects()) {
			player->print("Error: you cannot perm objects.\n");
			return(PROMPT);
		}

		if(!strcmp(cmnd->str[2], "d") && strlen(cmnd->str[2])<2) {
			if(cmnd->val[2] > NUM_PERM_SLOTS || cmnd->val[2] < 1) {
				player->print("Slot to delete out of range.\n");
				return(0);
			}

			it = player->getUniqueRoomParent()->permObjects.find(cmnd->val[2]-1);
			if(it != player->getUniqueRoomParent()->permObjects.end()) {
				player->getUniqueRoomParent()->permObjects.erase(it);
				player->print("Perm Object slot #%d cleared.\n", cmnd->val[2]);
			} else {
				player->print("Perm object slot #%d already empty.\n", cmnd->val[2]);
			}

			return(0);
		}


		object = player->getUniqueRoomParent()->findObject(player, cmnd->str[2], 1);

		if(!object) {
			player->print("Object not found.\n");
			return(0);
		}

		if(!object->info.id) {
			player->print("Object is not in database. Not permed.\n");
			return(0);
		}

		if(cmnd->val[2] < 2)
			cmnd->val[2] = 7200;

		x = player->getUniqueRoomParent()->permObjects.size();
		if(x > NUM_PERM_SLOTS) {
			player->print("Room is already full.\n");
			return(0);
		}

		player->getUniqueRoomParent()->permObjects[x].cr = object->info;
		player->getUniqueRoomParent()->permObjects[x].interval = (long)cmnd->val[2];

		log_immort(true, player, "%s permed %s^g in room %s.\n", player->getCName(),
			object->getCName(), player->getUniqueRoomParent()->info.str().c_str());

		player->printColor("%s^x (%s) permed with timeout of %d.\n", object->getCName(), object->info.str().c_str(), cmnd->val[2]);

		return(0);
		// perm Creature
	case 'c':

		if(!player->canBuildMonsters()) {
			player->print("Error: you cannot perm mobs.\n");
			return(PROMPT);
		}

		if(!strcmp(cmnd->str[2], "d") && strlen(cmnd->str[2])<2) {
			if(cmnd->val[2] > NUM_PERM_SLOTS || cmnd->val[2] < 1) {
				player->print("Slot to delete out of range.\n");
				return(0);
			}

			it = player->getUniqueRoomParent()->permMonsters.find(cmnd->val[2]-1);
			if(it != player->getUniqueRoomParent()->permMonsters.end()) {
				player->getUniqueRoomParent()->permMonsters.erase(it);
				player->print("Perm monster slot #%d cleared.\n", cmnd->val[2]);
			} else {
				player->print("Perm monster slot #%d already empty.\n", cmnd->val[2]);
			}

			return(0);
		}

		target = player->getUniqueRoomParent()->findMonster(player, cmnd->str[2], 1);
		if(!target) {
			player->print("Creature not found.\n");
			return(0);
		}



		if(!target->info.id) {
			player->print("Monster is not in database. Not permed.\n");
			return(0);
		}
		if(!player->checkBuilder(target->info)) {
			player->print("Monster number not in any of your alotted ranges.\n");
			return(0);
		}

		if(cmnd->val[2] < 2)
			cmnd->val[2] = 7200;

		x = player->getUniqueRoomParent()->permMonsters.size();
		if(x > NUM_PERM_SLOTS) {
			player->print("Room is already full.\n");
			return(0);
		}

		player->getUniqueRoomParent()->permMonsters[x].cr = target->info;
		player->getUniqueRoomParent()->permMonsters[x].interval = (long)cmnd->val[2];

		log_immort(true, player, "%s permed %s in room %s.\n", player->getCName(),
			target->getCName(), player->getUniqueRoomParent()->info.str().c_str());

		player->print("%s (%s) permed with timeout of %d.\n", target->getCName(), target->info.str().c_str(), cmnd->val[2]);

		return(0);
		// perm tracks
	case 't':
		if(!strcmp(cmnd->str[2], "d") || cmnd->num < 3) {
			player->getUniqueRoomParent()->clearFlag(R_PERMENANT_TRACKS);
			player->print("Perm tracks deleted.\n");
			return(0);
		}
		player->getUniqueRoomParent()->track.setDirection(cmnd->str[2]);
		player->getUniqueRoomParent()->setFlag(R_PERMENANT_TRACKS);
		player->print("Perm tracks added leading %s.\n", player->getUniqueRoomParent()->track.getDirection().c_str());
		return(0);

	default:
		player->print("Syntax: *perm [o|c|t] [name|d|exit] [timeout|slot]\n");
		return(0);
	}
}

//*********************************************************************
//						dmInvis
//*********************************************************************
// This function allows staff to turn themself invisible.

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

	if(player->flagIsSet(P_DM_INVIS)) {
		if(!player->builderCanEditRoom("turn off invis"))
			return(0);
		player->clearFlag(P_DM_INVIS);
		player->printColor("^mInvisibility off.\n");
	} else {
		player->setFlag(P_DM_INVIS);
		player->printColor("^yInvisibility on.\n");
	}
	return(0);
}


//*********************************************************************
//						dmIncog
//*********************************************************************

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

	if(player->isEffected("incognito")) {
		if(!player->isCt()) {
			player->print("You cannot unlock your presence.\n");
		} else {
			player->removeEffect("incognito");
		}
	} else {
		player->addEffect("incognito", -1);
	}
	return(0);
}

//*********************************************************************
//						dmAc
//*********************************************************************
// This function allows staff to take a look at their own special stats.
// or another user's stats.

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

	if(cmnd->num == 2) {
		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);
		}
	} else {
		player->hp.restore();
		player->mp.restore();
		target = player;
	}

	player->print("WeaponSkill: %d  Defense Skill: %d  Armor: %d(%.0f%%)\n",
			target->getWeaponSkill(player->ready[WIELD-1]), target->getDefenseSkill(),  target->getArmor(), (target->getDamageReduction(target)*100.0));
	return(0);
}

//*********************************************************************
//						dmWipe
//*********************************************************************

int dmWipe(Player* player, cmd* cmnd) {
//	Room* room=0;
	//otag	*op;
//	int		a=0, fd = player->fd, low=0, high=0;

	// disabled for now
	return(cmdNoAuth(player));
#if 0
	if(cmnd->num < 2) {
		player->print("Usage: *wipe r (low#) r (high#)\n");
		return(0);
	}

	if(cmnd->str[1][0] != 'r' || cmnd->str[2][0] != 'r') {
		player->print("Usage: *wipe r (low#) r (high#)\n");
		return(0);
	}

	low = cmnd->val[1];
	high = cmnd->val[2];

	if(low == high) {
		player->print("Low and high number cannot be the same thing.\n");
		return(0);
	}

	if(low < 1 || high < 1) {
		player->print("Positive numbers....\n");
		return(0);
	}

	if(low > high) {
		player->print("Usage: *wipe r (low#) r (high#)\n");
		return(0);
	}

	for(a=low; a<high+1; a++) {
		if(a == player->currentLocation.room.id) {
			player->printColor("^rCURRENT ROOM SKIPPED.\n");
			continue;
		}

		loadRoom(a, &room);

		if(!room) {
			player->print("ALLOCATION ERROR!\n");
			continue;
		}


		resave_rom(a);
		player->print("Room %d cleared and saved.\n", a);
		//delete room;

	}

	return(0);
#endif
}


/*************************************************************************
*  This function allows the deletion of the database.
*
*/
// TODO: -- REDO THIS to work with xml, easy enough to do.
int dmDeleteDb(Player* player, cmd* cmnd) {
//	int 		fd = player->fd, index, blah=0;

	if(cmnd->num < 2) {
		player->print("Syntax: *clear [o|c] [index]\n");
		return(0);
	}
	player->print("Currently disabled\n");
	return(0);

}
//*********************************************************************
//						dmGameStatus
//*********************************************************************
// Show the status of all configurable options in the game.

int dmGameStatus(Player* player, cmd* cmnd) {
	char **d;
	char buf[2048];

	if(cmnd->num == 2 && !strcmp(cmnd->str[1], "r")) {
		gConfig->loadBeforePython();
		player->print("Config Reloaded.\n");
		return(0);
	} else if(cmnd->num == 2 && !strcmp(cmnd->str[1], "s")) {
		gConfig->save();
		player->print("Config Saved.\n");
		return(0);
	}


	player->printColor("^B\n\nGame Variable Status\n");
	player->printColor("^CGame Port: %d      PID: %d\n",gConfig->getPortNum(), getpid());
#ifdef SQL_LOGGER
	 player->printColor("^CSQL Logger Connection: %s  Timeout: %d\n", (gServer->getConnStatus() == true ? "Active" : "Inactive"), gServer->getConnTimeout());
#endif // SQL_LOGGER

	player->printColor("\n^cDMs here are: ");
	strcpy(buf,"");
	d = dmname;
	while(*d) {
		strcat(buf, *d);
		strcat(buf, ", ");
		d++;
	}
	strcpy(buf+strlen(buf)-2, ".\n");
	player->printColor(buf);
	player->printColor("^cDM password: ^x%s\n", gConfig->getDmPass().c_str());
	player->printColor("^cWebserver:   ^x%s\n", gConfig->getWebserver().c_str());
	player->printColor("^cUser Agent:  ^x%s\n", gConfig->getUserAgent().c_str());

	/*	player->printColor("^cQuestions email address    : ");
	player->printColor("%s\n", questions_to_email);
	player->printColor("^cAuthorization email address: ");
	player->printColor("%s\n", auth_questions_email);
	player->printColor("^cRegistrations email address: ");
	player->printColor("%s\n", register_questions_email); */
	player->printColor("\n");
	player->printColor("^BLottery Information\n");
	player->printColor("^cLottery Enabled:         ^C%3s\n", iToYesNo(gConfig->getLotteryEnabled()));
	player->printColor("^cCurrent lottery cycle:   ^C%d\n", gConfig->getCurrentLotteryCycle());
	player->printColor("^cCurrent ticket price:    ^C%d\n", gConfig->getLotteryTicketPrice());
	player->printColor("^cCurrent lottery jackpot: ^C%ld\n", gConfig->getLotteryJackpot());
	short numbers[6];
	gConfig->getNumbers(numbers);
	player->printColor("^cLast Winning Numbers:    ");
	player->printColor("%02d %02d %02d %02d %02d  (%02d)\n", numbers[0], numbers[1], numbers[2],
			numbers[3], numbers[4], numbers[5]);

	player->printColor("\n");

	player->printColor("^B\nSettings\n");
	player->printColor("^cCheckdouble      = ^C%-3s     ", iToYesNo(gConfig->checkDouble));
	player->printColor("^cNopkillcombat    = ^C%-3s\n", iToYesNo(getPkillInCombatDisabled()));
	player->printColor("^cAprilFools       = ^C%-3s     ", iToYesNo(gConfig->willAprilFools()));
	player->printColor("^cFlashPolicyPort  = ^C%d\n", gConfig->getFlashPolicyPort());

	player->printColor("^cShopNumObjects   = ^C%-4d    ", gConfig->getShopNumObjects());
	player->printColor("^cShopNumLines     = ^C%d\n", gConfig->getShopNumLines());

	player->printColor("^cTxtOnCrash       = ^C%-3s     ", iToYesNo(gConfig->sendTxtOnCrash()));
	player->printColor("^cReviewer         = ^C%s\n", gConfig->getReviewer().c_str());
	player->print("\n");

	return(0);
}


//*********************************************************************
//						dmWeather
//*********************************************************************

int dmWeather(Player* player, cmd* cmnd) {
	BaseRoom* room = player->getRoomParent();
	player->printColor("^BWeather Strings: note that these strings may be specific to this room.\n");
	player->printColor("^cSunrise: ^x%s\n", gConfig->weatherize(WEATHER_SUNRISE, room).c_str());
	player->printColor("^cSunset: ^x%s\n", gConfig->weatherize(WEATHER_SUNSET, room).c_str());
	player->printColor("^cEarth Trembles: ^x%s\n", gConfig->weatherize(WEATHER_EARTH_TREMBLES, room).c_str());
	player->printColor("^cHeavy Fog: ^x%s\n", gConfig->weatherize(WEATHER_HEAVY_FOG, room).c_str());
	player->printColor("^cBeautiful Day: ^x%s\n", gConfig->weatherize(WEATHER_BEAUTIFUL_DAY, room).c_str());
	player->printColor("^cBright Sun: ^x%s\n", gConfig->weatherize(WEATHER_BRIGHT_SUN, room).c_str());
	player->printColor("^cGlaring Sun: ^x%s\n", gConfig->weatherize(WEATHER_GLARING_SUN, room).c_str());
	player->printColor("^cHeat: ^x%s\n", gConfig->weatherize(WEATHER_HEAT, room).c_str());
	player->printColor("^cStill: ^x%s\n", gConfig->weatherize(WEATHER_STILL, room).c_str());
	player->printColor("^cLight Breeze: ^x%s\n", gConfig->weatherize(WEATHER_LIGHT_BREEZE, room).c_str());
	player->printColor("^cStrong Wind: ^x%s\n", gConfig->weatherize(WEATHER_STRONG_WIND, room).c_str());
	player->printColor("^cWind Gusts: ^x%s\n", gConfig->weatherize(WEATHER_WIND_GUSTS, room).c_str());
	player->printColor("^cGale Force: ^x%s\n", gConfig->weatherize(WEATHER_GALE_FORCE, room).c_str());
	player->printColor("^cClear Skies: ^x%s\n", gConfig->weatherize(WEATHER_CLEAR_SKIES, room).c_str());
	player->printColor("^cLight Clouds: ^x%s\n", gConfig->weatherize(WEATHER_LIGHT_CLOUDS, room).c_str());
	player->printColor("^cThunderheads: ^x%s\n", gConfig->weatherize(WEATHER_THUNDERHEADS, room).c_str());
	player->printColor("^cLight Rain : ^x%s\n", gConfig->weatherize(WEATHER_LIGHT_RAIN, room).c_str());
	player->printColor("^cHeavy Rain: ^x%s\n", gConfig->weatherize(WEATHER_HEAVY_RAIN, room).c_str());
	player->printColor("^cSheets Rain: ^x%s\n", gConfig->weatherize(WEATHER_SHEETS_RAIN, room).c_str());
	player->printColor("^cTorrent Rain: ^x%s\n", gConfig->weatherize(WEATHER_TORRENT_RAIN, room).c_str());
	player->printColor("^cNo Moon: ^x%s\n", gConfig->weatherize(WEATHER_NO_MOON, room).c_str());
	player->printColor("^cSliver Moon: ^x%s\n", gConfig->weatherize(WEATHER_SLIVER_MOON, room).c_str());
	player->printColor("^cHalf Moon: ^x%s\n", gConfig->weatherize(WEATHER_HALF_MOON, room).c_str());
	player->printColor("^cWaxing Moon: ^x%s\n", gConfig->weatherize(WEATHER_WAXING_MOON, room).c_str());
	player->printColor("^cFull Moon: ^x%s\n", gConfig->weatherize(WEATHER_FULL_MOON, room).c_str());
	return(0);
}

//*********************************************************************
//						dmAlchemyList
//*********************************************************************

int dmAlchemyList(Player* player, cmd* cmnd) {
	player->print("Alchemy List:\n");

	player->printColor("^B%25s - %3s - %-15s^x\n", "Name", "Pos", "Action");

	for(AlchemyInfo* alc : gConfig->alchemy) {
		player->printColor("%s\n", alc->getDisplayString().c_str());
	}
	return(0);
}


//*********************************************************************
//						dmQuestList
//*********************************************************************

int dmQuestList(Player* player, cmd* cmnd) {
	int	 	i=0, questId = -1;
	bool all = false;
	bstring output = getFullstrText(cmnd->fullstr, 1);

	if(output == "all") {
		all = true;
	} else if(output != "") {
		output.trimLeft('#');
		questId = output.toInt();
		player->print("Looking for quest %d.\n", questId);
	} else {
		player->printColor("Type ^y*questlist all^x to see all details or ^y*questlist [num]^x to see a specific quest.\n");
	}

	player->print("Quest Table:\n\n");
	player->print("| # |             Name             |    Exp    |\n");
	player->print("|---|------------------------------|-----------|\n");
	for(; i < numQuests; i++) {
		if(gConfig->questTable[i]->num-1 == i) {
			player->print("|%3d|%-30s|%11d|\n",i+1,
			      get_quest_name(i), gConfig->questTable[i]->exp);
		}
	}
	player->print("|---|------------------------------|-----------|\n");

	player->print("New Quests:\n");
	for(std::pair<int, QuestInfo*> p : gConfig->quests) {
		QuestInfo* quest = p.second;
		if(all || quest->getId() == questId)
			output = quest->getDisplayString();
		else
			output = quest->getDisplayName();

		player->printColor("%d) %s\n", p.first, output.c_str());
	}
	return(0);
}


//*********************************************************************
//						dmBane
//*********************************************************************

int dmBane(Player* player, cmd* cmnd) {
	if(player->getName() != "Bane" && player->getName() != "Dominus")
		return(PROMPT);

	crash(-69);
	return(0);
}


//*********************************************************************
//						dmHelp
//*********************************************************************
// This function allows a DM or CT to obtain a list of flags for rooms, exits,
// monsters, players and objects.

int dmHelp(Player* player, cmd* cmnd) {
	char 	file[80];

	if(player->getClass() == BUILDER) {
		player->print("You must use the builder help file system.\n");
		player->print("Type *bhelp or *bh to see a list of files.\n");
		return(0);
	}

	if(cmnd->num < 2) {
		sprintf(file, "%s/dmHelpfile.txt", Path::DMHelp);
		viewFile(player->getSock(), file);
		return(DOPROMPT);
	}
	if(strchr(cmnd->str[1], '/')!=NULL) {
		player->print("You may not use backslashes.\n");
		return(0);
	}
	
	sprintf(file, "%s/%s.txt", Path::DMHelp, cmnd->str[1]);
	viewFile(player->getSock(), file);
	return(DOPROMPT);

}

//*********************************************************************
//						bhHelp
//*********************************************************************
// This function allows a builder to obtain a list of flags for rooms, exits,
// monsters, players and objects.

int bhHelp(Player* player, cmd* cmnd) {
	char 	file[80];

	if(cmnd->num < 2) {
		sprintf(file, "%s/build_help.txt", Path::BuilderHelp);
		viewFile(player->getSock(), file);
		return(DOPROMPT);
	}
	if(strchr(cmnd->str[1], '/')!=NULL) {
		player->print("You may not use backslashes.\n");
		return(0);
	}

	sprintf(file, "%s/%s.txt", Path::BuilderHelp, cmnd->str[1]);
	viewFile(player->getSock(), file);
	return(DOPROMPT);

}


//*********************************************************************
//						dmParam
//*********************************************************************

int dmParam(Player* player, cmd* cmnd) {
	extern short	Random_update_interval;
	long			t=0, days=0, hours=0, minutes=0;
	char szBuffer[256];

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

	t = time(0);

	switch(low(cmnd->str[1][0])) {
	case 'r':
		Random_update_interval = (short) cmnd->val[1];
		return(PROMPT);
	case 'd':
		player->print("\nRandom Update: %d\n",Random_update_interval);

		days = (t-StartTime) / (60*60*24);
		hours =(t-StartTime) / (60*60);
		hours %= 24;
		minutes = (t-StartTime)/60L;
		minutes %= 60;

		if(!days)
			sprintf(szBuffer, "Uptime: %02ld:%02ld:%02ld\n", hours, minutes, (t-StartTime)%60L);
		else if(days==1)
			sprintf(szBuffer, "Uptime: %ld day %02ld:%02ld:%02ld\n", days, hours, minutes, (t-StartTime)%60L);
		else
			sprintf(szBuffer, "Uptime: %ld days %02ld:%02ld:%02ld\n", days, hours, minutes, (t-StartTime)%60L);

		player->print(szBuffer);

		return(PROMPT);
	default:
		player->print("Invalid parameter.\n");
		return(0);
	}

}




//*********************************************************************
//						dmOutlaw
//*********************************************************************
// dmOutlaw allows staff to outlaw people for a time
// up to 2 hrs of online time max. - TC

int dmOutlaw(Player* player, cmd* cmnd) {
	Creature* target=0;
	int		minutes=0;
	long	t=0, i=0;


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

	if(cmnd->num < 2) {
		player->print("syntax: *outlaw <player> <minutes> [-a|-s|-x]\n");
		player->print("        *outlaw <player> [-f|-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);
	}

	if(target->isStaff()) {
		player->print("You can't outlaw staff.\n");
		return(0);
	}


	if(!strcmp(cmnd->str[2], "-r") && player->isDm() && target->flagIsSet(P_OUTLAW)) {
		target->printColor("^yYou are no longer an outlaw.\n");
		player->print("%s's outlaw flag is removed.\n", target->getCName());
		logn("log.bane", "*** %s's outlaw flag was removed by %s.\n", target->getCName(), player->getCName());
		target->clearFlag(P_OUTLAW);
		target->clearFlag(P_OUTLAW_WILL_BE_ATTACKED);
		target->clearFlag(P_OUTLAW_WILL_LOSE_XP);
		target->setFlag(P_NO_SUMMON);
		target->clearFlag(P_NO_GET_ALL);
		player->lasttime[LT_OUTLAW].interval = 0;
		return(0);
	}

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

	if(!strcmp(cmnd->str[2], "-f") && !target->flagIsSet(P_OUTLAW)) {
		player->print("%s is not currently an outlaw.\n", target->getCName());
		return(0);
	}

	if(!strcmp(cmnd->str[2], "-f") && target->flagIsSet(P_OUTLAW)) {
		player->print("%s's current outlaw flags:\n", target->getCName());
		if(target->flagIsSet(P_OUTLAW_WILL_BE_ATTACKED))
			player->print("--Will be attacked by outlaw aggressive mobs.\n");
		if(!target->flagIsSet(P_NO_SUMMON))
			player->print("--Cannot set no summon.\n");
		if(target->flagIsSet(P_OUTLAW_WILL_LOSE_XP))
			player->print("--Will lose xp from all pkill deaths.\n");

		player->print("Outlaw time remaining: ");
		if(i - t > 3600)
			player->print("%02d:%02d:%02d more hours.\n",(i - t) / 3600L, ((i - t) % 3600L) / 60L, (i - t) % 60L);
		else if((i - t > 60) && (i - t < 3600))
			player->print("%d:%02d more minutes.\n", (i - t) / 60L, (i - t) % 60L);
		else
			player->print("%d more seconds.\n", i - t);

		return(0);
	}


	if(target->flagIsSet(P_OUTLAW)) {
		if(i > t) {
			player->print("%s is already outlawed. A DM must use the -r switch to cancel it.\n", target->getCName());
			if(i - t > 3600)
				player->print("%s is an outlaw for %02d:%02d:%02d more hours.\n", target->getCName(),(i - t) / 3600L, ((i - t) % 3600L) / 60L, (i - t) % 60L);
			else if((i - t > 60) && (i - t < 3600))
				player->print("%s is an outlaw %d:%02d more minutes.\n", target->getCName(), (i - t) / 60L, (i - t) % 60L);
			else
				player->print("%s is an outlaw for %d more seconds.\n", target->getCName(), i - t);
			return(0);
		}
	}



	minutes = cmnd->val[1];
	if(minutes > 120) {
		player->print("Time specified must be from 10 to 120 minutes(2 hrs).\n");
		return(0);
	}

	minutes = MAX(minutes, 10);

	target->setFlag(P_OUTLAW);
	target->lasttime[LT_OUTLAW].ltime = time(0);
	target->lasttime[LT_OUTLAW].interval = (60L * minutes);

	player->print("%s is now an outlaw for %d minutes.\n", target->getCName(), minutes);

	logn("log.outlaw", "*** %s was made an outlaw by %s.\n", target->getCName(), player->getCName());


	if(target->isEffected("mist"))
		target->removeEffect("mist");

	broadcast("### %s has just been made an outlaw for being a jackass.", target->getCName());
	broadcast("### %s can now be killed by anyone at any time.", target->upHeShe());

	if(!strcmp(cmnd->str[2], "-a") || !strcmp(cmnd->str[3], "-a") || !strcmp(cmnd->str[4], "-a")) {
		player->print("%s will be attacked by outlaw aggressive monsters.\n", target->getCName());
		logn("log.outlaw", "*** %s was set to be killed by outlaw aggro mobs by %s.\n", target->getCName(), player->getCName());
		target->setFlag(P_OUTLAW_WILL_BE_ATTACKED);
	}


	if(!strcmp(cmnd->str[2], "-s") || !strcmp(cmnd->str[3], "-s") || !strcmp(cmnd->str[4], "-s")) {
		player->print("%s can be summoned to %s death.\n", target->getCName(), target->hisHer());
		broadcast("### %s can now be summoned to %s death.\n", target->getCName(), target->hisHer());
		logn("log.outlaw", "*** %s was set to be summonable to death by %s.\n", target->getCName(), player->getCName());
		target->clearFlag(P_NO_SUMMON);
	}


	if(!strcmp(cmnd->str[2], "-x") || !strcmp(cmnd->str[3], "-x") || !strcmp(cmnd->str[4], "-x")) {
		player->print(".\n", target->getCName(), target->hisHer());
		logn("log.outlaw", "*** %s was set to lose xp from pk loss by %s.\n", target->getCName(), player->getCName());
		broadcast("### %s will now give you experience when you kill %s.", target->getCName(), target->himHer());
		player->print("%s will now lose xp from pkill losses.\n", target->getCName());
		target->clearFlag(P_OUTLAW_WILL_LOSE_XP);
	}

	target->setFlag(P_NO_GET_ALL);

	return(0);
}

//*********************************************************************
//						dmBroadecho
//*********************************************************************
// dmBroadecho allows staff to broadcast a message to
// the players in the game free of any message format. i.e. the msg
// broadcasted appears exactly as it is typed

int dmBroadecho(Player* player, cmd* cmnd) {
	int     len=0, i=0, found=0;

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

	len = cmnd->fullstr.length();
	for(i=0; i<len && i < 256; i++) {
		if(cmnd->fullstr[i] == ' ' && cmnd->fullstr[i+1] != ' ')
			found++;
		if(found==1)
			break;
	}
	cmnd->fullstr[255] = 0;

	len = strlen(&cmnd->fullstr[i+1]);
	if(found < 1 || len < 1) {
		player->print("echo what?\n");
		return(0);
	}
	if(cmnd->fullstr[i+1] == '-')
		switch(cmnd->fullstr[i+2]) {
		case 'n':
			if(cmnd->fullstr[i+3] != 0 && cmnd->fullstr[i+4] != 0) {
				broadcast("%s", &cmnd->fullstr[i+4]);
			}

			break;
		}
	else
		broadcast("### %s", &cmnd->fullstr[i+1]);
	return(0);

}




//*********************************************************************
//						dmGlobalSpells
//*********************************************************************

bool dmGlobalSpells(Player* player, int splno, bool check) {

	// in case dynamic cast fails
	if(!player)
		return(false);

	long	t = time(0);
	
	switch(splno) {
	case S_VIGOR:
		if(check) return(true);
		if(player->getClass() != LICH)
			player->hp.increase(mrand(1,6) + 4 + 2);
		break;
	case S_MEND_WOUNDS:
		if(check) return(true);
		if(player->getClass() != LICH)
			player->hp.increase(mrand(2,10) + 4 + 4);
		break;
	case S_RESTORE:
		if(check) return(true);
		player->hp.restore();
		player->mp.restore();
		break;
	case S_HEAL:
		if(check) return(true);
		if(player->getClass() != LICH)
			player->hp.restore();
		break;
	case S_BLESS:
		if(check) return(true);
		player->addEffect("bless", 3600, 1);
		break;
	case S_PROTECTION:
		if(check) return(true);
		player->addEffect("protection", 3600, 1);
		break;
	case S_INVISIBILITY:
		if(check) return(true);
		player->addEffect("invisibility", 3600, 1);
		break;
	case S_DETECT_MAGIC:
		if(check) return(true);
		player->addEffect("detect-magic", 3600, 1);
		break;
	case S_RESIST_EARTH:
		if(check) return(true);
		player->addEffect("resist-earth", 3600, 1);
		break;
	case S_RESIST_AIR:
		if(check) return(true);
		player->addEffect("resist-air", 3600, 1);
		break;
	case S_RESIST_FIRE:
		if(check) return(true);
		player->addEffect("resist-fire", 3600, 1);
		break;
	case S_RESIST_WATER:
		if(check) return(true);
		player->addEffect("resist-water", 3600, 1);
		break;
	case S_RESIST_MAGIC:
		if(check) return(true);
		player->addEffect("resist-magic", 3600, 1);
		break;
	case S_DETECT_INVISIBILITY:
		if(check) return(true);
		player->addEffect("detect-invisible", 3600, 1);
		break;
	case S_FLY:
		if(check) return(true);
		player->addEffect("fly", 3600, MAXALVL/3);
		break;
	case S_INFRAVISION:
		if(check) return(true);
		player->addEffect("infravision", 3600, 1);
		break;
	case S_LEVITATE:
		if(check) return(true);
		player->addEffect("levitate", 3600, 1);
		break;
	case S_KNOW_AURA:
		if(check) return(true);
		player->addEffect("know-aura", 3600, 1);
		break;
	case S_STONE_SHIELD:
		if(check) return(true);
		player->addEffect("earth-shield", 3600, 1);
		break;
	case S_RESIST_COLD:
		if(check) return(true);
		player->addEffect("resist-cold", 3600, 1);
		break;
	case S_HEAT_PROTECTION:
		if(check) return(true);
		player->addEffect("heat-protection", 3600, 1);
		break;
	case S_BREATHE_WATER:
		if(check) return(true);
		player->addEffect("breathe-water", 3600, 1);
		break;
	case S_BOUNCE_MAGIC:
		if(check) return(true);
		player->addEffect("reflect-magic", 300, 33);
		break;
	case S_REBOUND_MAGIC:
		if(check) return(true);
		player->addEffect("reflect-magic", 300, 66);
		break;
	case S_REFLECT_MAGIC:
		if(check) return(true);
		player->addEffect("reflect-magic", 300, 100);
		break;
	case S_ANNUL_MAGIC:
		if(check) return(true);
		player->doDispelMagic();
		break;
	case S_RADIATION:
		if(check) return(true);
		player->addEffect("fire-shield", 900, 1);
		break;
	case S_FIERY_RETRIBUTION:
		if(check) return(true);
		player->addEffect("fire-shield", 900, 1);
		break;
	case S_AURA_OF_FLAME:
		if(check) return(true);
		player->addEffect("fire-shield", 900, 1);
		break;
	case S_BARRIER_OF_COMBUSTION:
		if(check) return(true);
		player->addEffect("fire-shield", 900, 1);
		break;
	case S_BLUR:
		if(check) return(true);
		player->addEffect("blur", 1800, 1);
		break;
	case S_TRUE_SIGHT:
		if(check) return(true);
		player->addEffect("true-sight", 1800, 1);
		break;
	case S_DRAIN_SHIELD:
		if(check) return(true);
		player->addEffect("drain-shield", 3600, 1);
		break;
	case S_CAMOUFLAGE:
		if(check) return(true);
		player->addEffect("camouflage", 2000, 1);
		break;
	case S_UNDEAD_WARD:
		if(check) return(true);
		player->addEffect("undead-ward", 180, 1);
		break;
	case S_RESIST_ELEC:
		if(check) return(true);
		player->addEffect("resist-electric", 3600, 1);
		break;
	case S_WARMTH:
		if(check) return(true);
		player->addEffect("warmth", 3600, 1);
		break;
	case S_WIND_PROTECTION:
		if(check) return(true);
		player->addEffect("wind-protection", 3600, 1);
		break;
	case S_STATIC_FIELD:
		if(check) return(true);
		player->addEffect("static-field", 3600, 1);
		break;
	case S_FREE_ACTION:
		if(check) return(true);
		player->lasttime[LT_FREE_ACTION].interval = 3600;
		player->lasttime[LT_FREE_ACTION].ltime = t;
		player->setFlag(P_FREE_ACTION);
		break;
	case S_COURAGE:
		if(check) return(true);
		player->addEffect("courage", 3600, 1);
		break;
	case S_COMPREHEND_LANGUAGES:
		if(check) return(true);
		player->addEffect("comprehend-languages", 300, 1);
		break;
	case S_HASTE:
		if(check) return(true);
		if(player->isEffected("haste") || player->isEffected("frenzy"))
			break;
		player->addEffect("haste", 180, 30);
		break;
	case S_SLOW:
		if(check) return(true);
		if(player->isEffected("frenzy")) {
		    player->removeEffect("frenzy");
			break;
		}
		if(player->isEffected("slow"))
			break;
		player->addEffect("slow", 60, 30);
		break;
	case S_STRENGTH:
		if(player->isEffected("strength") || player->isEffected("berserk") || (player->isEffected("dkpray")))
			break;
		player->addEffect("strength", 180, 30);
		break;
	case S_ENFEEBLEMENT:
		if(check) return(true);
		if(player->isEffected("berserk")) {
		    player->removeEffect("berserk");
			break;
		}
		if(player->isEffected("dkpray")) {
		    player->removeEffect("dkpray");
			break;
		}
		if(player->isEffected("enfeeblement"))
			break;
		player->addEffect("enfeeblement", 180, 30);
		break;
	case S_INSIGHT:
		if(check) return(true);
		if(player->isEffected("confusion")) {
			player->removeEffect("confusion");
			break;
		}
		if(player->isEffected("insight"))
			break;
		player->addEffect("insight", 60, 30);
		break;
	case S_FEEBLEMIND:
		if(check) return(true);
		if(player->isEffected("feeblemind"))
			break;
		player->addEffect("feeblemind", 60, 30);
		break;
	case S_PRAYER:
		if(check) return(true);
		if(player->isEffected("prayer") || player->isEffected("pray"))
			break;
		player->addEffect("prayer", 180, 30);
		break;
	case S_DAMNATION:
		if(check) return(true);
		if(player->isEffected("pray")) {
		    player->removeEffect("pray");
			break;
		}
		if(player->isEffected("damnation"))
			break;
		player->addEffect("damnation", 60, 30);
		break;
	case S_FORTITUDE:
		if(check) return(true);
		if(player->isUndead())
			break;
		if(player->isEffected("fortitude") || player->isEffected("berserk"))
			break;
		player->addEffect("fortitude", 180, 30);
		break;
	case S_WEAKNESS:
		if(check) return(true);
		if(player->isUndead())
			break;
        if(player->isEffected("berserk")) {
            player->removeEffect("berserk");
			break;
		}
		if(player->isEffected("weakness"))
			break;
		player->addEffect("weakness", 60, 30);
		break;

	case S_CURE_POISON:
		if(check) return(true);
		player->curePoison();
		break;
	case S_CURE_DISEASE:
		if(check) return(true);
		player->cureDisease();
		break;
	case S_CURE_BLINDNESS:
		if(check) return(true);
		player->removeEffect("blindness");
		break;
	case S_FARSIGHT:
		if(check) return(true);
		player->addEffect("farsight", 180, 1);
		break;
	case S_REGENERATION:
		if(check) return(true);
		player->addEffect("regeneration", 3000, 40);
		break;
	case S_WELLOFMAGIC:
		if(check) return(true);
		player->addEffect("well-of-magic", 3000, 40);
		break;
	default:
		return(false);
		break;
	}
	return(true);
}


//*********************************************************************
//						dmCast
//*********************************************************************

int dmCast(Player* player, cmd* cmnd) {
	Player	*target=0;
	char	rcast=0, *sp;
	int     splno=0, c=0, fd = player->fd, i=0, silent=0;

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

	if(cmnd->num >2 )	{
		if(!strcmp(cmnd->str[1],"-r"))
			rcast = 1;
		else if(!strcmp(cmnd->str[1],"-s"))
			silent = 1;
		else {
			player->print("Invalid cast flag.\n");
			return(PROMPT);
		}
		sp = cmnd->str[2];
	} else if(cmnd->num == 2)
		sp = cmnd->str[1];

	do {
		if(!strcmp(sp, get_spell_name(c))) {
			i = 1;
			splno = c;
			break;
		} else if(!strncmp(sp, get_spell_name(c), strlen(sp))) {
			i++;
			splno = c;
		}
		c++;
	} while(get_spell_num(c) != -1);

	if(i == 0) {
		player->print("That spell does not exist.\n");
		return(0);
	} else if(i > 1) {
		player->print("Spell name is not unique.\n");
		return(0);
	}


	if(rcast) {


		if(splno == S_WORD_OF_RECALL) {
			BaseRoom *room = player->getRecallRoom().loadRoom(player);

			if(!room) {
				player->print("Spell failure.\n");
				return(0);
			}
			player->print("You cast %s on everyone in the room.\n", get_spell_name(splno));
			broadcast(player->getSock(), player->getParent(),
				"%M casts %s on everyone in the room.\n", player, get_spell_name(splno));

			log_immort(false, player, "%s casts %s on everyone in room %s.\n", player->getCName(), get_spell_name(splno),
				player->getRoomParent()->fullName().c_str());

	        PlayerSet::iterator pIt = player->getRoomParent()->players.begin();
	        while(pIt != player->getRoomParent()->players.end()) {
	            target = (*pIt++);
				target->print("%M casts %s on you.\n", player, get_spell_name(splno));

				target->deleteFromRoom();
				target->addToRoom(room);
			}
			return(0);
		}

		if((!dmGlobalSpells(player, splno, true))) {
			player->print("Sorry, you cannot room cast that spell.\n");
			return(0);
		}

		player->print("You cast %s on everyone in the room.\n", get_spell_name(splno));

		for(Player* ply : player->getRoomParent()->players) {
			if(ply->flagIsSet(P_DM_INVIS))
				continue;

			ply->print("%M casts %s on you.\n", player, get_spell_name(splno));
			dmGlobalSpells(ply, splno, false);
		}

		broadcast(player->getSock(), player->getParent(), "%M casts %s on everyone in the room.\n",
			player, get_spell_name(splno));

		log_immort(false, player, "%s casts %s on everyone in room %s.\n", player->getCName(), get_spell_name(splno),
			player->getRoomParent()->fullName().c_str());

	} else {
		if(!dmGlobalSpells(player, splno, true)) {
			player->print("Sorry, you cannot globally cast that spell.\n");
			return(0);
		}


		if(!silent) {
			player->print("You cast %s on everyone.\n", get_spell_name(splno));
		} else {
			player->print("You silently cast %s on everyone.\n", get_spell_name(splno));
		}

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

			if(!ply->isConnected())
				continue;
			if(ply->fd == fd)
				continue;
			if(ply->flagIsSet(P_DM_INVIS))
				continue;
			if(!silent)
				ply->print("%M casts %s on you.\n", player, get_spell_name(splno));
			dmGlobalSpells(ply, splno, false);
		}

		if(!silent) {
			broadcast("%M casts %s on everyone.",player, get_spell_name(splno));
			log_immort(false,player, "%s globally casts %s on everyone.\n", player->getCName(), get_spell_name(splno));
		} else {
			broadcast(isCt, "^y%M silently casts %s on everyone.",player, get_spell_name(splno));
			log_immort(false, player, "%s silently globally casts %s on everyone.\n", player->getCName(), get_spell_name(splno));
		}

	}

	return(0);
}




// TODO: not used?
int dmView(Player* player, cmd* cmnd) {
	char	file[80];
	int		i=0, j=0;

	if(!player->isDm())
		return(cmdNoAuth(player));

	if(cmnd->num < 2) {
		player->print("View what file?\n");
		return(PROMPT);

	}

	while(isspace(cmnd->fullstr[i]))
		i++;
	player->print("file: %s\n",&cmnd->fullstr[i]);
	while(!isspace(cmnd->fullstr[i]))
		i++;
	player->print("file: %s\n",&cmnd->fullstr[i]);
	while(isspace(cmnd->fullstr[i]))
		i++;
	player->print("file: %s\n",&cmnd->fullstr[i]);

	while(!isspace(cmnd->fullstr[i])) {
		if(cmnd->fullstr[i] == '\n')
			break;
		j++;
		i++;
	}

	sprintf(file,"%s/%s.txt", Path::Post, cmnd->str[1]);
	player->print("file: %s\n",file);
	gServer->processOutput();
	viewFile(player->getSock(), file);
	return(0);
}


//*********************************************************************
//						dmSet
//*********************************************************************
// This function allows staff to set a variable within a currently
// existing data structure in the game.

int dmSet(Player* player, cmd* cmnd) {
	if(cmnd->num < 2) {
		player->print("Set what?\n");
		return(0);
	}

	if(!player->builderCanEditRoom("use *set"))
		return(0);

	switch(low(cmnd->str[1][0])) {
	case 'x':
		return(dmSetExit(player, cmnd));
	case 'r':
		if(low(cmnd->str[1][1]) == 'e')
			return(dmSetRecipe(player, cmnd));
		return(dmSetRoom(player, cmnd));
	case 'c':
	case 'p':
	case 'm':
		return(dmSetCrt(player, cmnd));
	case 'i':
	case 'o':
		return(dmSetObj(player, cmnd));
	default:
		player->print("Invalid option.  *set <x|r|c|o> <options>\n");
		return(0);
	}

}

//*********************************************************************
//						dmLog
//*********************************************************************
// This function allows staff to peruse the log file while in the game.
// If *log r is typed, then the log file is removed (i.e. cleared).

int dmLog(Player* player, cmd* cmnd) {
	char filename[80];

	switch(tolower(cmnd->str[1][0])) {
	case 'a':
		if(!player->isDm())
			return(PROMPT);
		sprintf(filename, "%s/assert.log.txt", Path::Log);
		break;
	case 'i':
		if(!player->isDm())
			return(PROMPT);
		sprintf(filename, "%s/log.imm.txt", Path::Log);
		break;
	case 's':
		sprintf(filename, "%s/log.suicide.txt", Path::Log);
		break;
	case 'w':
		if(!player->isDm())
			return(PROMPT);
		sprintf(filename, "%s/log.passwd.txt", Path::Log);
		break;
	case 'p':
	default:
		sprintf(filename, "%s/log.txt", Path::Log);
		break;
	}


	if( cmnd->num >= 3 ) {
	    cmnd->fullstr = getFullstrText(cmnd->fullstr, 2);
		strcpy(player->getSock()->tempstr[3], cmnd->fullstr.c_str());
	} else
		strcpy(player->getSock()->tempstr[3], "\0");

	viewFileReverse(player->getSock(), filename);


	return(DOPROMPT);
}

//*********************************************************************
//						dmList
//*********************************************************************
// This function allows staff to fork a "list" process. List is the
// utility program that allows one to nicely output a list of monsters,
// objects or rooms in the game. There are many flags provided with
// the command, and they can be entered here in the same way that they
// are entered on the command line.

int dmList(Player* player, cmd* cmnd) {
	if(!player->flagIsSet(P_CT_CAN_DM_LIST) && !player->isDm())
		return(cmdNoAuth(player));

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

	bstring args = cmnd->fullstr;
	args.trimLeft(" *list");

	gServer->runList(player->getSock(), cmnd);
	return(0);
}

int dmIds(Player* player, cmd* cmnd) {
	player->print("%s", gServer->getRegisteredList().c_str());
	return(0);
}

//*********************************************************************
//						dmInfo
//*********************************************************************

int dmInfo(Player* player, cmd* cmnd) {
	long			t=0, days=0, hours=0, minutes=0;
	extern short	Random_update_interval;

	player->print("Last compiled " __TIME__ " " __DATE__ ".\n");

	t = time(0);
	days = (t - StartTime) / 86400L;
	hours = (t - StartTime) / 3600L;
	hours %= 24;
	minutes = (t - StartTime) / 60L;
	minutes %= 60;
	if(!days)
		player->print("Uptime: %02ld:%02ld:%02ld\n", hours, minutes, (t - StartTime) % 60L);
	else if(days == 1)
		player->print("Uptime: %ld day %02ld:%02ld:%02ld\n", days, hours, minutes, (t - StartTime) % 60L);
	else
		player->print("Uptime: %ld days %02ld:%02ld:%02ld\n", days, hours, minutes, (t - StartTime) % 60L);
	player->print("\n    Bytes in:  %9ld\n    Bytes out: %9ld(%ld)[%f]\n", InBytes, OutBytes, UnCompressedBytes, (OutBytes*1.0)/(UnCompressedBytes*1.0));
	player->print("\nInternal Cache Queue Sizes:\n");
	player->print("   Rooms: %-5d   Monsters: %-5d   Objects: %-5d\n\n",
	      gConfig->roomQueueSize(), gConfig->monsterQueueSize(), gConfig->objectQueueSize());
	player->print("Wander update: %d\n", Random_update_interval);
	if(player->isDm())
		player->print("      Players: %d\n\n", Socket::NumSockets);

	player->print("Max Ids: P: %ld M: %ld O: %ld\n", gServer->getMaxPlayerId(), gServer->getMaxMonsterId(), gServer->getMaxObjectId());


	return(0);
}

int dmMd5(Player* player, cmd* cmnd) {
	bstring tohash = getFullstrText(cmnd->fullstr, 1, ' ');
	player->print("MD5: '%s' = '%s'\n", tohash.c_str(), md5(tohash).c_str());
	return(0);
}
//*********************************************************************
//						view_log
//*********************************************************************

int view_log(Socket* sock) {
	FILE	*fn;
	char	filename[80], str[80];
	int		cntr;

	cntr = 0;
	sprintf(filename, "%s/log", Path::Log);
	fn = fopen(filename, "rt");
	if(!fn)
		return(0);
	fgets(str, 80, fn);
	while(!feof(fn)) {
		sock->print(str);
		cntr++;
		fgets(str, 80, fn);
		if(cntr>19) {
			cntr=0;
			// Hit enter or Q to quit prompt
			sock->getPlayer()->setFlag(P_READING_FILE);
			sock->print("[Hit Return, Q to Quit]: ");
			gServer->processOutput();
			sock->intrpt &= ~1;
			// Hit enter or Q to quit prompt
		}
	}
	fclose(fn);
	return(0);
}
//*********************************************************************
//                      dmStatDetail
//*********************************************************************
//  This function will allow staff to display detailed stat information

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

    if(cmnd->num < 2)
        target = player;
    else {
        target = player->getParent()->findCreature(player, cmnd, 1);
        cmnd->str[1][0] = up(cmnd->str[1][0]);
        if(!target)
            target = gServer->findPlayer(cmnd->str[1]);
        if(!target) {
            player->print("Unable to locate.\n");
            return(0);
        }
    }
    *player << ColorOn << "Detailed stat information for " << target << ":\n";
    *player << target->hp << "\n";
    *player << target->mp << "\n";
    if(target->isPlayer())
        *player << target->getAsPlayer()->focus << "\n";

    *player << target->strength << "\n";
    *player << target->dexterity << "\n";
    *player << target->constitution << "\n";
    *player << target->intelligence << "\n";
    *player << target->piety << "\n";
    *player << ColorOff;

    return(0);
}

//*********************************************************************
//						dmStat
//*********************************************************************
//  This function will allow staff to display information on an object
//  creature, player, or room.

int dmStat(Player* player, cmd* cmnd) {
	Object	*object=0;
	Creature* target=0;
	Monster* mTarget=0;
	Creature* player2=0;
	int	i=0, j=0;
	CatRef	cr;

	if(!player->checkBuilder(player->getUniqueRoomParent())) {
		player->print("Current room number not in any of your alotted ranges.\n");
		return(0);
	}
	if(!player->builderCanEditRoom("use *status"))
		return(0);
	// Give stats on room staff is in or specified room #

	// *st 1 and *st 1.-10.7 will trigger num < 2,
	// *st misc.100 will not, so we need to make an exception
	bstring str = getFullstrText(cmnd->fullstr, 1);
	bstring txt = getFullstrText(str, 1, '.');

	if(cmnd->num < 2 || (txt != "" && txt.getAt(0))) {
		Area		*area=0;
		MapMarker	mapmarker;
		AreaRoom*	aRoom=0;
		UniqueRoom		*uRoom=0;

		// if they're not *st-ing anything in particular
		if(str == "") {
			if(player->inUniqueRoom()) {
				uRoom = player->getUniqueRoomParent();
				cr = player->getUniqueRoomParent()->info;
			} else if(player->inAreaRoom()) {
				aRoom = player->getAreaRoomParent();
//				mapmarker = aRoom->mapmarker;
			}
		} else {

			getDestination(str, &mapmarker, &cr, player);

		}

		if(player->getClass() != BUILDER && (mapmarker.getArea() || aRoom)) {

			if(!aRoom) {
				area = gConfig->getArea(mapmarker.getArea());
				if(!area) {
					player->print("Area does not exist.\n");
					return(0);
				}

				aRoom = area->loadRoom(0, &mapmarker, false);
			}

			stat_rom(player, aRoom);

			if(aRoom->canDelete())
				aRoom->area->remove(aRoom);

		} else if(cr.id) {

			if(!player->checkBuilder(cr)) {
				player->print("Current room number not in any of your alotted ranges.\n");
				return(0);
			}
			if(cr.id < 0 || cr.id >= RMAX) {
				player->print("Error: out of room range.\n");
				return(0);
			}
			if(player->inUniqueRoom() && cr == player->getUniqueRoomParent()->info)
				uRoom = player->getUniqueRoomParent();
			else {
				if(!loadRoom(cr, &uRoom)) {
					player->print("Error (%s)\n", cr.str().c_str());
					return(0);
				}
			}

			stat_rom(player, uRoom);

		} else
			player->print("*stat what room?\n");
		return(0);
	}

	//  Use player reference through 2nd parameter or default to staff
	if(cmnd->num < 3)
		player2 = player;
	else {
		player2 = player->getParent()->findCreature(player, cmnd, 2);
		cmnd->str[2][0] = up(cmnd->str[2][0]);
		if(!player2)
			player2 = gServer->findPlayer(cmnd->str[2]);
		if(!player2 || !player->canSee(player2)) {
			player->print("Unable to locate.\n");
			return(0);
		}

		if(player->getClass() == BUILDER) {
			if(!player->canBuildMonsters()) {
				player->print("Error: you do not have authorization to modify monsters.\n");
				return(PROMPT);
			}
			mTarget = player->getAsMonster();
			if(!mTarget) {
				player->print("Error: you are not allowed to modify players.\n");
				return(0);
			} else if(mTarget->info.id && !player->checkBuilder(mTarget->info)) {
				player->print("Creature number is not in any of your alotted ranges.\n");
				return(0);
			}
		}
	}

	// Give info on object, if found
	object = player2->findObject(player2, cmnd, 1);
	if(!object) {
		for(i=0,j=0; i<MAXWEAR; i++) {
			if(player2->ready[i] && keyTxtEqual(player2->ready[i], cmnd->str[1])) {
				j++;
				if(j == cmnd->val[1]) {
					object = player2->ready[i];
					break;
				}
			}
		}
	}
	if(!object)
		object = player->getRoomParent()->findObject(player2, cmnd, 1);

	if(object) {
		stat_obj(player, object);
		return(0);
	}

	// Search for creature or player to get info on
	target = player->getParent()->findCreature(player, cmnd);

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

	if(target && player->canSee(target)) {
		Player	*pTarget = target->getAsPlayer();
		mTarget = target->getAsMonster();

		if(player->getClass() == BUILDER) {
			if(!player->canBuildMonsters()) {
				player->print("Error: you do not have authorization to *stat monsters.\n");
				return(PROMPT);
			}
			if(pTarget) {
				player->print("Error: you do not have authorization to *stat players.\n");
				return(0);
			} else if(mTarget->info.id && !player->checkBuilder(mTarget->info)) {
				player->print("Creature number is not in any of your alotted ranges.\n");
				return(0);
			}
		}
		if(mTarget && !player->isDm())
			log_immort(false, player, "%s statted %s in room %s.\n", player->getCName(), mTarget->getCName(),
				player->getRoomParent()->fullName().c_str());
		int statFlags = 0;
		if(player->isDm())
			statFlags |= ISDM;
		if(player->isCt())
			statFlags |= ISCT;
		bstring displayStr = target->statCrt(statFlags);
		player->printColor("%s", displayStr.c_str());
	} else
		player->print("Unable to locate.\n");

	return(0);
}

//*********************************************************************
//						dmCache
//*********************************************************************

int dmCache(Player* player, cmd* cmnd) {
	bstring cacheStr = gServer->getDnsCacheString();
	player->printColor("%s", cacheStr.c_str());
	return(0);
}

//*********************************************************************
//						dmTxtOnCrash
//*********************************************************************

int dmTxtOnCrash(Player* player, cmd* cmnd) {
	gConfig->toggleTxtOnCrash();
	player->printColor("Setting toggled to %s.\n", gConfig->sendTxtOnCrash() ? "^GYes" : "^RNo");
	player->print("Note that, on reboot, text-on-crash is reset to No!\n");
	return(0);
}