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/
/*
 * dmcrt.cpp
 *	 Staff functions related to creatures
 *   ____            _
 *  |  _ \ ___  __ _| |_ __ ___  ___
 *  | |_) / _ \/ _` | | '_ ` _ \/ __|
 *  |  _ <  __/ (_| | | | | | | \__ \
 *  |_| \_\___|\__,_|_|_| |_| |_|___/
 *
 *	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 "move.h"
#include "factions.h"
#include "effects.h"
#include "clans.h"
#include "calendar.h"
#include "unique.h"
#include "magic.h"

#include <sstream>
#include <iomanip>
#include <locale>


//*********************************************************************
//						dmCreateMob
//*********************************************************************
// This function allows a staff member to create a creature that will appear
// in the room they are located in.

int dmCreateMob(Player* player, cmd* cmnd) {
	Monster	*monster=0;
	BaseRoom* room = player->getRoom();
	int		l=0, total=1;
	bstring	noMonsters = "^mNo monsters were summoned.\n";

	CatRef  cr;
    getCatRef(getFullstrText(cmnd->fullstr, 1), &cr, player);


	if(cr.id && !player->checkBuilder(cr)) {
		player->print("Error: monster index not in any of your alotted ranges.\n");
		return(0);
	}
	if(!player->checkBuilder(player->parent_rom)) {
		player->print("Error: room number not in any of your alotted ranges.\n");
		return(0);
	}
	if(!player->builderCanEditRoom("create monsters"))
		return(0);

	WanderInfo* wander = player->getRoom()->getWanderInfo();

	if(cr.id < 1) {
		if(!wander) {
			player->printColor(noMonsters.c_str());
			return(0);
		}
		cr = wander->getRandom();
		if(!cr.id) {
			player->printColor(noMonsters.c_str());
			return(0);
		}
	}

	if(getFullstrText(cmnd->fullstr, 2).left(1) == "n")
		total = MIN(atoi(getFullstrText(cmnd->fullstr, 3).c_str()), MAX_MOBS_IN_ROOM);
	/*
	 * nobody uses this
	 *
	else if(getFullstrText(cmnd->fullstr, 2).left(1) == "g") {
		total = mrand(1, room->countVisPly());
		if(cmnd->val[1] == 1) {
			cr = wander->getRandom();
			if(!cr.id) {
				player->printColor(noMonsters.c_str());
				return(0);
			}
		}
	}
	*/

	total = MIN(total, MAX_MOBS_IN_ROOM - room->countCrt());

	if(total < 1) {
		player->printColor(noMonsters.c_str());
		return(0);
	}

	if(!loadMonster(cr, &monster)) {
		player->print("Error (%s)\n", cr.str().c_str());
		return(0);
	}

	if(!monster->flagIsSet(M_CUSTOM))
		monster->validateAc();

	if(!monster->name[0] || monster->name[0] == ' ') {
		free_crt(monster);
		player->print("Error (%s)\n", cr.str().c_str());
		return(0);
	}


	for(l=0; l<total;) {

		monster->initMonster(cmnd->str[1][0]=='r' ? false : true, cmnd->str[1][0]=='p' ? true : false);

		if(!l)
			monster->addToRoom(room, total);
		else
			monster->addToRoom(room, 0);

		gServer->addActive(monster);
		l++;
		if(l < total)
			loadMonster(cr, &monster);
	}

	if(!player->isDm())
		log_immort(false,player, "%s created %d %s's in room %s.\n", player->name, total, monster->name,
			player->getRoom()->fullName().c_str());

	return(0);
}

//*********************************************************************
//						stat_crt
//*********************************************************************
//  Display information on creature given to player given.

bstring Creature::statCrt(int statFlags) {
	const Player *pTarget = getConstPlayer();
	const Monster *mTarget = getConstMonster();
	std::ostringstream crtStr;
	bstring str = "";
	int		i=0, n=0;
	long	t = time(0);
	char	tmp[10], spl[128][20];
	bstring	txt = "";

	// set left aligned
	crtStr.setf(std::ios::left, std::ios::adjustfield);
	crtStr.imbue(std::locale(""));

	if(pTarget && pTarget->getSock()) {
		Socket* sock = pTarget->getSock();
		crtStr << "\n" << pTarget->fullName() << " the " << pTarget->getTitle() << ": ";
		//crtStr.setfill('0');
		crtStr.setf(std::ios::right, std::ios::adjustfield);
		crtStr << "Idle: " << std::setfill('0') << std::setw(2) << ((t - sock->ltime) / 60L) << ":"
		       << std::setfill('0') << std::setw(2) << ((t - sock->ltime) % 60L) << std::setfill(' ') << "\n\n";
		crtStr.setf(std::ios::left, std::ios::adjustfield);
		//crtStr.setFill(' ');
		crtStr << "Term(" << sock->getTermType() << ")";
		if(sock->getMxp())
			crtStr << "MXP Enabled";
		crtStr << " size: " << sock->getTermCols() << " x " << sock->getTermRows() << "\n";
		crtStr << "Host: " << sock->getHostname() << " Ip: " << sock->getIp() << "\n";

		if(statFlags & ISDM) {
			crtStr << "Password: " << pTarget->getPassword();
			if(pTarget->getLastPassword() != "")
				crtStr << " Previous password: " << pTarget->getLastPassword();
			crtStr << "\n";
		}

		if(pTarget->getForum() != "")
			crtStr << "^gForum Account:^x " << pTarget->getForum() << "\n";

		crtStr << "Room: " << pTarget->getRoom()->fullName() << "\n";
		crtStr << "Cmd : ";
		if(!pTarget->isDm() || statFlags & ISDM)
			crtStr << dmLastCommand(pTarget);
		else
			crtStr << "l"; // Make it look like they just 'looked'
		crtStr << "\n\n";

	} else {
		crtStr << "Name: " << mTarget->name;

		if(!mTarget->flagIsSet(M_CUSTOM))
			crtStr << " (" << monType::getName(mTarget->type) << ":"
				   << monType::getHitdice(mTarget->type) << "HD)\n";
		else
			crtStr << " (CUSTOM:" << monType::getHitdice(mTarget->type) << "HD)\n";

		// Stop the comma for index
		crtStr.imbue(std::locale("C"));
		crtStr << "\nIndex: " << mTarget->info.str("", 'y') << "                "
			   << "Toughness: " << Statistics::calcToughness(mTarget) << "\n";
		crtStr.imbue(std::locale(""));

		if(mTarget->getPrimeFaction() != "")
			crtStr << "\n^yPrime Faction:^x " << mTarget->getPrimeFaction() << "\n";

		crtStr << "Desc: " << mTarget->getDescription() << "\n";
		crtStr << "Talk: " << mTarget->getTalk() << "\n";
		crtStr << "Keys: [" << mTarget->key[0] << "] [" << mTarget->key[1]
		                    << "] [" << mTarget->key[2] << "]\n";

		for(i=0; i<3; i++) {
			if(mTarget->attack[i][0])
				crtStr << "Attack type " << (n+1) << ": " << mTarget->attack[i] << "\n";
		}

		for(i=0; i<3; i++) {
			if(mTarget->movetype[i][0])
				crtStr << "Movement type " << (n+1) << ": " << mTarget->movetype[i] << "\n";
		}

		if(mTarget->ttalk[0])
			crtStr << "After trade talk: " << mTarget->ttalk << "\n";

		// stop the comma
		crtStr.imbue(std::locale("C"));
		crtStr << "\nJail Room: " <<  mTarget->jail.str() << "\n";
		crtStr.imbue(std::locale(""));
		crtStr << "Aggro String: " << mTarget->aggroString << "\n";
		if(mTarget->flagIsSet(M_LEVEL_RESTRICTED))
			crtStr << "Max Lvl: " << mTarget->getMaxLevel() << "\n";
	}

	crtStr << "Level: " << level;
	if(pTarget) {
		if(pTarget->getActualLevel() && pTarget->getLevel() != pTarget->getActualLevel())
			crtStr << "(" << pTarget->getActualLevel() << ")";
		if(pTarget->getNegativeLevels())
			crtStr << "   Neg lvls: " << pTarget->getNegativeLevels();
	}
	crtStr << "   Race: ";
	if(race)
		crtStr << gConfig->getRace(race)->getName();
	crtStr << "(" << race << ")\n";

	crtStr << "Class: " << std::setw(20) << get_class_string(cClass);
	crtStr << "  Alignment: ";
	if(pTarget) {
		if(pTarget->flagIsSet(P_CHAOTIC))
			crtStr << "Chaotic ";
		else
			crtStr <<  "Lawful ";
	}
	crtStr << alignment << "\n";

	if(pTarget && pTarget->getSecondClass())
		crtStr << "Second Class: " << get_class_string(pTarget->getSecondClass()) << "\n";
	if(deity)
		crtStr << "Deity: " << gConfig->getDeity(deity)->getName() << "(" << deity << ")\n";

	if(size)
		crtStr << "Size: ^Y" << getSizeName(size) << "^x\n";

	if(clan)
		crtStr << "Clan: " << gConfig->getClan(clan)->getName() << "(" << clan << ")\n";
	if(pTarget && pTarget->getGuild())
		crtStr << "^mGuild:^x " << getGuildName(pTarget->getGuild()) << "(" << pTarget->getGuild() << ")"
			   << "Rank: " << pTarget->getGuildRank();

	if(mTarget && mTarget->getNumWander() > 1)
		crtStr << "Numwander: " << mTarget->getNumWander() << "\n";

	crtStr << "\n";

	crtStr << "Exp: " << experience << "  Gold: " << coins[GOLD];
	if(pTarget)
		crtStr << "  Bank: " << pTarget->bank[GOLD];
	crtStr << "\n";

	if(statFlags & ISCT && mTarget)
		crtStr << "Last modified by: " << mTarget->last_mod << "\n";
	if(pTarget) {
		crtStr << "Lost Experience: " << pTarget->getLostExperience() << "\n";
		cDay* b = pTarget->getBirthday();
		if(b)
			crtStr << "Birthday:  Day:" << b->getDay() <<
					  "  Month:" << b->getMonth() <<
					  "  Year:" << b->getYear() << "\n";

		crtStr << "Character born: " << pTarget->getCreatedStr() << "\n";
		crtStr << "Initial stats: Str[" << pTarget->strength.getInitial() <<
		                       "] Dex[" << pTarget->dexterity.getInitial() <<
		                       "] Con[" << pTarget->constitution.getInitial() <<
		                       "] Int[" << pTarget->intelligence.getInitial() <<
		                       "] Pty[" << pTarget->piety.getInitial() << "]\n";
	}

	str = "";
	for(i=0; i<LANGUAGE_COUNT; i++) {
		if(languageIsKnown(LUNKNOWN + i)) {
			str += get_language_adj(i);
			str += ", ";
		}
	}

	if(str == "")
		str = "None";
	else
		str = str.substr(0, str.length() - 2);

	crtStr << "Languages known: " << str << ".\n"
		<< "Currently speaking: " << get_language_adj(current_language) << "\n\n";


	if(mTarget && mTarget->getMobTrade()) {
		crtStr << "NPC Trade: " << get_trade_string(mTarget->getMobTrade()) << "(" << mTarget->getMobTrade() << ")";
		crtStr << "   Skill: " << get_skill_string(mTarget->getSkillLevel()/10) << "(" << mTarget->getSkillLevel() << ")\n";
	}

	if(pTarget) {
		// Stop the comma again
		crtStr.imbue(std::locale("C"));

		crtStr << "Bound Room: " << pTarget->bound.str() << "      "
			   << "Previous Room: " << pTarget->previousRoom.str() << "      ";
		crtStr.imbue(std::locale(""));
		crtStr << "Wimpy: " << pTarget->getWimpy() << "\n";
	} else {
		if(mTarget->getLoadAggro())
			crtStr << "  Aggro on load: " << mTarget->getLoadAggro() << "%\n";
		if(mTarget->flagIsSet(M_WILL_BE_AGGRESSIVE))
			crtStr << "  Will aggro: " << mTarget->getUpdateAggro() << "% chance (each update cycle).\n";
	}

	crtStr << "HP: " << hp.getCur() << "/" << hp.getMax();
	crtStr << "   MP: " << mp.getCur() << "/" << mp.getMax() << "\n";

	crtStr << "Armor: " << armor;
	if(mTarget) {
		crtStr << " Defense: " << mTarget->getDefenseSkill();
		crtStr << " WeaponSkill: " << mTarget->getWeaponSkill();
	}
	crtStr << " AttackPower: " << attackPower << "\n";
	//crtStr << "   THAC0: " << thaco << "\n";

	crtStr << "Hit: " << damage.str() << " ";
	crtStr << "Damage: low " << damage.low() << ", high " << damage.high() <<
			  "  Average: " << damage.average() << "\n";

	crtStr << "Str[" << strength.getCur() <<
	          "]  Dex[" << dexterity.getCur() <<
	          "]  Con[" << constitution.getCur() <<
	          "]  Int[" << intelligence.getCur() <<
	          "]  Pty[" << piety.getCur() << "]";

	if(pTarget)
		crtStr <<  "  Lck[" <<  pTarget->getLuck() << "]";
	crtStr << "\n\n";

	crtStr.setf(std::ios::right, std::ios::adjustfield);

	crtStr << "Ea: "<< getRealm(EARTH) <<
	        "  Ai: "<< getRealm(WIND) <<
	        "  Fi: "<< getRealm(FIRE) <<
	        "  Wa: "<< getRealm(WATER) <<
	        "  El: "<< getRealm(ELEC) <<
	        "  Co: "<< getRealm(COLD) << "\n";

	crtStr << "Ea: " << std::setw(2) << mprofic(this, EARTH) << "%" <<
	       "   Ai: " << std::setw(2) << mprofic(this, WIND) << "%" <<
	       "   Fi: " << std::setw(2) << mprofic(this, FIRE) << "%" <<
	       "   Wa: " << std::setw(2) << mprofic(this, WATER) << "%" <<
	       "   El: " << std::setw(2) << mprofic(this, ELEC) << "%" <<
	       "   Co: " << std::setw(2) << mprofic(this, COLD) << "%" << "\n\n";

	i = (saves[POI].chance + saves[DEA].chance + saves[BRE].chance +
	       saves[MEN].chance + saves[SPL].chance)/5;
	crtStr << "Poi:" << std::setw(2) << saves[POI].chance << "%" <<
	       "   Dea:" << std::setw(2) << saves[DEA].chance << "%" <<
	       "   Bre:" << std::setw(2) << saves[BRE].chance << "%" <<
	       "   Men:" << std::setw(2) << saves[MEN].chance << "%" <<
	       "   Spl:" << std::setw(2) << saves[SPL].chance << "%" <<
	       "   Lck:" << std::setw(2) << i << "%" << "\n";

	if(poison_dur || poison_dmg) {
		crtStr << "^y";

		if(poison_dur)
			crtStr << "Poison duration: " << poison_dur << " sec\n";

		if(poison_dmg)
			crtStr << "Poison damage: " << poison_dmg << "/tic\n";

		crtStr << "^x";
	}

	if(mTarget) {

		if(mTarget->flagIsSet(M_CAN_CAST) && (!mTarget->flagIsSet(M_CAST_PRECENT)))
			crtStr << "^rCast Percent: You need to set mflag " << (M_CAST_PRECENT+1) << " (cast percent).^x\n";

		if(	mTarget->flagIsSet(M_CAN_CAST) &&
			mTarget->flagIsSet(M_CAST_PRECENT)
		) {
			if(!mTarget->getCastChance())
				crtStr << "^rCast Percent: (cast needs to be set to 1-100%)^x\n";
			else
				crtStr << "Cast Percent: " << mTarget->getCastChance() << "%\n";
		}

		crtStr.imbue(std::locale("C"));

		crtStr << "Carried Items:\n";
		for(i=0; i<10; i++)
			crtStr << "[" << std::setw(4) << mTarget->carry[i].str() << "]";
		crtStr << "\n";

		if(mTarget->getMagicResistance())
			crtStr << "^MMagic Resistance: " << mTarget->getMagicResistance() << "% ^x\n";

		if(mTarget->flagIsSet(M_WILL_YELL_FOR_HELP) || mTarget->flagIsSet(M_YELLED_FOR_HELP)) {
			crtStr << "Rescue mobs:   ";

			n = 0;
			for(i=0; i<NUM_RESCUE; i++) {
				crtStr << "[" << (i+1) << "] ";
				if(!validMobId(mTarget->rescue[i]))
					crtStr << "None";
				else {
					n++;
					crtStr << mTarget->rescue[i].str();
				}
				crtStr << "   ";
			}
			if(!n)
				crtStr << "^r*set c [mob] re[scue]{1-" << NUM_RESCUE << "} {misc.id}^x";
			crtStr << "\n";
		}

		for(i=0; i<NUM_ENEMY_MOB; i++) {
			if(mTarget->enemy_mob[i].id) {
				crtStr << "Enemy Creatures: ";
				for(i=0; i<NUM_ENEMY_MOB; i++)
					crtStr << "[" << std::setw(4) << mTarget->enemy_mob[i].str() << "]";
				crtStr << "\n";
				break;
			}
		}

		for(i=0; i<NUM_ASSIST_MOB; i++) {
			if(mTarget->assist_mob[i].id) {
				crtStr << "Will Assist: ";
				for(i=0; i<NUM_ASSIST_MOB; i++)
					crtStr << "[" << std::setw(4) << mTarget->assist_mob[i].str() << "]";
				crtStr << "\n";
				break;
			}
		}
	} else {
		if(pTarget->getPoisonedBy() != "")
			crtStr << "^r*Poisoned* by " <<  pTarget->getPoisonedBy() << ".^x";

		if(	pTarget->parent_rom &&
			pTarget->parent_rom->flagIsSet(R_MOB_JAIL)
		) {
			crtStr << "^bIn Jailhouse. ";
			crtStr << "Time remaining: " <<
					timestr( MAX(0,pTarget->lasttime[LT_MOB_JAILED].ltime+pTarget->lasttime[LT_MOB_JAILED].interval-t) );
			crtStr << ".^x\n";
		}

		if(pTarget->flagIsSet(P_JAILED)) {
			crtStr << "^RIn Dungeon of Despair. ";
			crtStr << "Time remaining: " <<
					timestr( MAX(0,pTarget->lasttime[LT_JAILED].ltime+pTarget->lasttime[LT_JAILED].interval-t) );
			crtStr << ".^x\n";
		}
	}


	str = "";
	for(i=0; i<(pTarget ? MAX_PLAYER_FLAGS : MAX_MONSTER_FLAGS); i++) {
		if(pTarget && !(statFlags & ISDM) && i == P_BUGGED)
			continue;
		if(flagIsSet(i)) {
			str += (!pTarget ? get_mflag(i) : get_pflag(i));
			sprintf(tmp, "(%d), ", i+1);
			str += tmp;
		}
	}

	if(str == "")
		str = "None";
	else
		str = str.substr(0, str.length() - 2);
	crtStr << "Flags set: " << str << "\n";

	crtStr << effects.getEffectsList();
	crtStr << getSpecialsList();

	str = "";
	if(mTarget) {
		for(i=1; i<STAFF; i++) {
			if(mTarget->isClassAggro(i, false)) {
				str += getClassAbbrev(i);
				sprintf(tmp, "(%d), ", i);
				str += tmp;
			}
		}

		for(i=1; i<RACE_COUNT; i++) {
			if(mTarget->isRaceAggro(i, false)) {
				str += gConfig->getRace(i)->getName();
				sprintf(tmp, "(%d), ", i);
				str += tmp;
			}
		}

		for(i=1; i<DEITY_COUNT; i++) {
			if(mTarget->isDeityAggro(i, false)) {
				str += gConfig->getDeity(i)->getName();
				sprintf(tmp, "(%d), ", i);
				str += tmp;
			}
		}


		if(str != "") {
			str = str.substr(0, str.length() - 2);
			crtStr << "Will aggro: " << str << ".\n";
		}


		str = "";

		if(mTarget->flagIsSet(M_TRADES)) {
			crtStr << "Trade items:\n";
			for(i=0; i<10; i++) {
				if(i == 5)
					crtStr << "\n";
				crtStr << std::setw(15) << mTarget->carry[i].str();
			}
			crtStr << str << "\n";
		}

		for(i=0, n=0; i<get_spell_list_size(); i++)
			if(mTarget->spellIsKnown(i))
				strcpy(spl[n++], get_spell_name(i));

		if(!n)
			str = "None";
		else {
			qsort((void *) spl, n, 20, (PFNCOMPARE) strcmp);
			for(i=0; i<n; i++) {
				if(i)
					str += ", ";
				str += spl[i];
			}
		}

		crtStr << "Spells Known: " << str << ".\n";

	} else {

		for(i=1, n=0; i<65; i++) {
			if(pTarget->questIsSet(i)) {
				sprintf(tmp, "(%d) - (", i+1);
				str += tmp;
				str += get_quest_name(i);
				str += "), ";
			}
		}

		if(str == "")
			str = "None";
		else
			str = str.substr(0, str.length() - 2);
		crtStr << "Quests Completed: " << str << ".\n";


//		str = "";
//		for(i=0; i<2; i++) {
//			if(pTarget->lastDeath[i]) {
//				crtStr << "  Death #" << i+1 << ": " << pTarget->killedBy[i]
//				       << " on " << ctime(&pTarget->lastDeath[i]);
//			}
//		}

		crtStr << "Lore: ";
		i=0;
		if(!pTarget->lore.empty()) {
			std::list<CatRef>::const_iterator it;
			for(it = pTarget->lore.begin() ; it != pTarget->lore.end() ; it++) {
				if(i)
					crtStr << ", ";
				crtStr << "^y" << (*it).str() << "^x";
				i++;
			}
		}
		crtStr << "\n";
	}

	crtStr << "\n";

	return(crtStr.str());
}

//*********************************************************************
//						dmSetCrt
//*********************************************************************
// This function allows a DM to set a defining characteristic of
// a creature or player

/*			Web Editor
 * 			 _   _  ____ _______ ______
 *			| \ | |/ __ \__   __|  ____|
 *			|  \| | |  | | | |  | |__
 *			| . ` | |  | | | |  |  __|
 *			| |\  | |__| | | |  | |____
 *			|_| \_|\____/  |_|  |______|
 *
 * 		If you change anything here, make sure the changes are reflected in the web
 * 		editor! Either edit the PHP yourself or tell Dominus to make the changes.
 */

int dmSetCrt(Player* player, cmd* cmnd) {
	Creature* target=0;
	Player	*pTarget=0;
	Monster	*mTarget=0;
	int		i=0, num=0, test=0, a=0, sp=0,  rnum=0, f=0;
	Object	*object=0;
	bool	ctModBuilder=false;

	if(player->getClass() == BUILDER) {
		if(!player->canBuildMonsters())
			return(cmdNoAuth(player));
		if(!player->checkBuilder(player->parent_rom)) {
			player->print("Error: Room number not inside any of your alotted ranges.\n");
			return(0);
		}
	}

	if(cmnd->num < 4) {
		player->print("Syntax: *set c <name> <a|con|c|dex|e|f|g|hm|h|int|inv|l|mm|m|\npie|p#|r#|sp|str> [<value>]\n");
		return(0);
	}



	cmnd->str[2][0] = up(cmnd->str[2][0]);
	target = gServer->findPlayer(cmnd->str[2]);
	cmnd->str[2][0] = low(cmnd->str[2][0]);
	if(!target || (!player->isCt() && target->flagIsSet(P_DM_INVIS)))
		target = player->getRoom()->findCreature(player, cmnd, 2);

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

	pTarget = target->getPlayer();
	mTarget = target->getMonster();

	// trying to modify a player?
	if(pTarget && !player->isDm()) {
		if(player->getClass() <= BUILDER) {
			player->print("You are not allowed to do that.\n");
			return(0);
		}
		if(player != pTarget) {
			if(!pTarget->isStaff()) {
				player->print("You may only modify builder characters.\n");
				return(0);
			}
			ctModBuilder = true;
		}
	}

	if(mTarget) {
		if(mTarget->info.id && !player->checkBuilder(mTarget->info)) {
			player->print("Error: Monster not inside any of your alotted ranges.\n");
			return(0);
		}
		// Don't touch
		mTarget->setFlag(M_WILL_BE_LOGGED);
	}


	switch (low(cmnd->str[3][0])) {
	case 'a':

		if(	!strcmp(cmnd->str[3], "ac") ||
			(strlen(cmnd->str[3]) > 1 && !strncmp(cmnd->str[3], "armor", strlen(cmnd->str[3])))
		) {

			target->setArmor(cmnd->val[3]);

			player->print("Armor Class set.\n");
			log_immort(true, player, "%s set %s %s's armor class to %ld.\n",
				player->name, PLYCRT(target), target->name, cmnd->val[3]);
			break;

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

			if(!mTarget) {
				player->print("Error: aggro percent chance cannot be set on players.\n");
				return(PROMPT);
			}

			mTarget->setLoadAggro((short)cmnd->val[3]);
			log_immort(true, player, "%s set %s %s's aggro chance to %ld.\n",
				player->name, PLYCRT(mTarget), mTarget->name, mTarget->getLoadAggro());

			player->print("Aggro percent chance set.\n");
			break;

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

			if(!pTarget) {
				player->print("Error: age cannot be set on mobs.\n");
				return(PROMPT);
			}

			pTarget->lasttime[LT_AGE].ltime = time(0);
			pTarget->lasttime[LT_AGE].interval = (long)cmnd->val[3];

			player->print("Player age set.\n");
			break;

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

			if(!mTarget) {
				player->print("Error: aggro update chance cannot be set on players.\n");
				return(PROMPT);
			}

			mTarget->setUpdateAggro((short)cmnd->val[3]);
			player->print("Aggro update chance set.\n");
			player->print("%M has a %d%% chance to go aggressive each update cycle.\n", mTarget, mTarget->getUpdateAggro());
			log_immort(true, player, "%s set %s %s's chance to go aggro each update cycle to %d.\n",
			        player->name, PLYCRT(mTarget), mTarget->name, mTarget->getUpdateAggro());
			break;

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

			if(!pTarget) {
				player->print("Error: actual level cannot be set on mobs.\n");
				return(PROMPT);
			}

			pTarget->setActualLevel((short)cmnd->val[3]);
			player->print("Actual Level set.\n");
			log_immort(true, player, "%s set %s %s's actual level to %d.\n",
			        player->name, PLYCRT(pTarget), pTarget->name, pTarget->getActualLevel());
			break;

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

			target->setAlignment((short)cmnd->val[3]);

			player->print("Alignment set.\n");
			log_immort(true, player, "%s set %s %s's alignment to %d.\n",
				player->name, PLYCRT(target), target->name, target->getAlignment());
			break;

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

			target->setAttackPower((int)cmnd->val[3]);
			player->print("Attack power set to %d\n", target->getAttackPower());
			break;

		}

		if(cmnd->num >= 4 && cmnd->str[4][0] == 'd') {
			for(i=0; i<NUM_ASSIST_MOB; i++)
				mTarget->assist_mob[i].clear();
			player->print("%M's assist mobs deleted.\n", mTarget);
			return(PROMPT);
		}

		num = atoi(&cmnd->str[3][1]);
		if(num < 1 || num > NUM_ASSIST_MOB) {
			player->print("Error: %d is out of range for assist mobs (1-%d).\n", num, NUM_ASSIST_MOB);
			return(PROMPT);
		}

		if(!mTarget) {
			player->print("Error: assist mobs cannot be set on players.\n");
			return(PROMPT);
		}

		getCatRef(getFullstrText(cmnd->fullstr, 4), &mTarget->assist_mob[num-1], mTarget);
		player->print("%M's assist mob #%d set to creature %s.\n", mTarget, num, mTarget->assist_mob[num-1].str().c_str());

		log_immort(true, player, "%s set %s %s's AssistMob#%d to %s.\n",
			player->name, PLYCRT(mTarget), mTarget->name, num, mTarget->assist_mob[num-1].str().c_str());
		break;

	case 'b':
		if(!strcmp(cmnd->str[3], "bank")) {
			if(!pTarget) {
				player->print("Error: bank gold cannot be set on mobs.\n");
				return(PROMPT);
			}

			pTarget->bank.set(cmnd->val[3], GOLD);

			player->print("%M bank gold is now set at %ld.\n", pTarget, pTarget->bank[GOLD]);
			log_immort(true, player, "%s set %s %s's Bank gold to %d.\n",
				player->name, PLYCRT(pTarget), pTarget->name, pTarget->bank[GOLD]);

		}


		if(!strcmp(cmnd->str[3], "bound")) {
			if(!pTarget) {
				player->print("Error: bound room cannot be set on mobs.\n");
				return(0);
			}
			if(ctModBuilder) {
				player->print("Error: you cannot modify bound room on builders.\n");
				return(0);
			}

			getDestination(getFullstrText(cmnd->fullstr, 4), &pTarget->bound, player);
			player->print("Bound room set to %s.\n", pTarget->bound.str().c_str());

			log_immort(true, player, "%s set %s %s's bound room to %s.\n",
				player->name, PLYCRT(pTarget), pTarget->name, pTarget->bound.str().c_str());
		}

		break;
	case 'c':
		if(!strcmp(cmnd->str[3], "cag")) {
			if(!mTarget) {
				player->print("Error: class aggro cannot be set on players.\n");
				return(PROMPT);
			}
			num = cmnd->val[3];

			if(!strcmp(cmnd->str[4], "del")) {
				for(a=1; a<STAFF; a++)
					mTarget->clearClassAggro(a);
				player->print("All %s's class aggros now cleared.\n");
				return(0);
			}

			if(num < 1 || num >= STAFF) {
				player->print("Error: class aggro out of range.\n");
				return(0);
			}

			if(mTarget->isClassAggro(num, false)) {
				player->print("%M will no longer attack %s's.\n", mTarget, getClassAbbrev(num));
				mTarget->clearClassAggro(num);
				log_immort(true, player, "%s set %s %s's to NOT aggro %ss(%d).\n",
			        player->name, PLYCRT(mTarget), mTarget->name, getClassAbbrev(num), num);
			} else {
				mTarget->setClassAggro(num);
				player->print("%M will now attack %s's.\n", mTarget, getClassAbbrev(num));
				log_immort(true, player, "%s set %s %s's to aggro %ss(%d).\n",
			        player->name, PLYCRT(mTarget), mTarget->name, getClassAbbrev(num), num);
			}

			break;
		}


		if(!strcmp(cmnd->str[3], "con")) {
			target->constitution.setCur(MAX(1, MIN(cmnd->val[3], MAX_STAT_NUM)));
			player->print("Constitution set.\n");

			log_immort(true, player, "%s set %s %s's constitution to %d.\n",
				player->name, PLYCRT(target), target->name, target->constitution.getCur());
			break;
		}

		if(!strcmp(cmnd->str[3], "cast")) {
			if(!mTarget) {
				player->print("Error: cast chance cannot be set on players.\n");
				return(PROMPT);
			}

			mTarget->setCastChance((short)cmnd->val[3]);
			player->print("Casting %% chance set.\n");
			log_immort(true, player, "%s set %s %s's Cast %% chance to %d.\n",
				player->name, PLYCRT(mTarget), mTarget->name, mTarget->getCastChance());

			break;
		}

		if(!strcmp(cmnd->str[3], "c2")) {
			if(!pTarget) {
				player->print("Error: second class cannot be set on monsters.\n");
				return(0);
			}
			if(ctModBuilder) {
				player->print("Error: you cannot modify second class on builders.\n");
				return(0);
			}

			pTarget->setSecondClass((int)cmnd->val[3]);
			player->print("Player's 2nd class set.\n");
			log_immort(true, player, "%s set %s %s's 2nd class to %d.\n",
			        player->name, PLYCRT(pTarget), pTarget->name, pTarget->getSecondClass());
			break;
		}

		if(!strcmp(cmnd->str[3], "clan") || !strcmp(cmnd->str[3], "cl")) {
			target->setClan((short)cmnd->val[3]);
			if(pTarget) {
				if(pTarget->getClan() == 0)
					pTarget->clearFlag(P_PLEDGED);
				else
					pTarget->setFlag(P_PLEDGED);
			} else
				player->print("Dont forget to %s flag 33 or 34 (Pledge/Rescind).\n", mTarget->getClan() ? "set" : "clear");
			if(target->getClan()) {
				player->print("Clan set to %d(%s).\n", target->getClan(), gConfig->getClan(target->getClan())->getName().c_str());
				log_immort(true, player, "%s set %s %s's clan to %d(%s).\n",
					player->name, PLYCRT(target), target->name, target->getClan(), gConfig->getClan(target->getClan())->getName().c_str());
			} else {
				player->print("Clan cleared.\n");
				log_immort(true, player, "%s cleared %s %s's clan.\n",
					player->name, PLYCRT(target), target->name);
				}
			break;
		}
		if(ctModBuilder) {
			player->print("Error: you cannot modify class on builders.\n");
			return(0);
		}
		if(!player->isDm() && pTarget)
			return(PROMPT);
		{
		unsigned short cClass = target->getClass();
		target->setClass((short)cmnd->val[3]);


		if(cClass == VAMPIRE && target->getClass() != VAMPIRE)
			player->printColor("Auto-removing ^rVampirism.\n");
		else if(cClass == WEREWOLF && target->getClass() != WEREWOLF)
			player->printColor("Auto-removing ^oLycanthropy.\n");

		if(cClass != VAMPIRE && target->getClass() == VAMPIRE)
			player->printColor("Auto-adding ^rVampirism.\n");
		else if(cClass != WEREWOLF && target->getClass() == WEREWOLF)
			player->printColor("Auto-adding ^oLycanthropy.\n");



		//if(target->isPlayer() && cmnd->val[3] == DUNGEONMASTER)
		//	if(!isdm(target->name))
		//		target->getClass() = CARETAKER;
		player->print("Class set.\n");
		log_immort(true, player, "%s set %s %s's class to %d.\n",
			player->name, PLYCRT(target), target->name, target->getClass());

		if(pTarget)
			pTarget->update();
		}
		break;
	case 'd':
		if(!strcmp(cmnd->str[3], "dag")) {
			if(!mTarget) {
				player->print("Error: deity aggro cannot be set on players.\n");
				return(PROMPT);
			}
			num = cmnd->val[3];

			if(!strcmp(cmnd->str[4], "del")) {
				for(a=1; a<DEITY_COUNT; a++)
					mTarget->clearDeityAggro(a);
				player->print("All %s's class aggros now cleared.\n");
				return(0);
			}

			if(num < 1 || num >= DEITY_COUNT) {
				player->print("Error: deity aggro out of range.\n");
				return(0);
			}

			if(mTarget->isDeityAggro(num, false)) {
				player->print("%M will no longer attack %s's.\n", mTarget, gConfig->getDeity(num)->getName().c_str());
				mTarget->clearDeityAggro(num);
				log_immort(true, player, "%s set %s %s's to NOT aggro %ss(%d).\n",
			        player->name, PLYCRT(mTarget), mTarget->name, gConfig->getDeity(num)->getName().c_str(), num);
			} else {
				mTarget->setDeityAggro(num);
				player->print("%M will now attack %s's.\n", mTarget, gConfig->getDeity(num)->getName().c_str());
				log_immort(true, player, "%s set %s %s's to aggro %ss(%d).\n",
			        player->name, PLYCRT(mTarget), mTarget->name, gConfig->getDeity(num)->getName().c_str(), num);
			}

			break;
		}

		if(!strcmp(cmnd->str[3], "deity")) {
			target->setDeity((short)cmnd->val[3]);
			player->print("Deity set.\n");
			log_immort(true, player, "%s set %s %s's deity to %d(%s).\n",
				player->name, PLYCRT(target), target->name, target->getDeity(),
				gConfig->getDeity(target->getDeity())->getName().c_str());
			break;
		}


		if(!strcmp(cmnd->str[3], "dex")) {
			target->dexterity.setCur(MAX(1, MIN(cmnd->val[3], MAX_STAT_NUM)));
			player->print("Dexterity set.\n");
			log_immort(true, player, "%s set %s %s's dexterity to %d.\n",
				player->name, PLYCRT(target), target->name, target->dexterity.getCur());
			break;
		} else if(!strcmp(cmnd->str[3], "dn") && mTarget) {

			mTarget->damage.setNumber(cmnd->val[3]);
			player->print("Number of dice set.\n");
			log_immort(true, player, "%s set %s %s's Number of Dice to %d.\n",
				player->name, PLYCRT(mTarget), mTarget->name, mTarget->damage.getNumber());
			break;
		} else if(!strcmp(cmnd->str[3], "ds") && mTarget) {

			mTarget->damage.setSides(cmnd->val[3]);
			player->print("Sides of dice set.\n");
			log_immort(true, player, "%s set %s %s's Sides of dice to %d.\n",
				player->name, PLYCRT(mTarget), mTarget->name, mTarget->damage.getSides());
			break;
		} else if(!strcmp(cmnd->str[3], "dp") && mTarget) {

			mTarget->damage.setPlus(cmnd->val[3]);
			player->print("Plus on dice set.\n");
			log_immort(true, player, "%s set %s %s's plus on dice to %d.\n",
				player->name, PLYCRT(mTarget), mTarget->name, mTarget->damage.getPlus());
			break;
		} else if(!strcmp(cmnd->str[3], "def") && mTarget) {
			num = (int)cmnd->val[3];
			num = MAX(0, MIN(num, MAXALVL*10));
			mTarget->setDefenseSkill(num);
			player->print("Target defense set to %d.\n", num);
			break;
		}
		break;
	case 'e':
		if(cmnd->str[3][1] == 'f') {
			if(cmnd->num < 5) {
				player->print("Set what effect to what?\n");
				return(0);
			}

			long duration = -1;
			int strength = 1;

			bstring txt = getFullstrText(cmnd->fullstr, 5);
			if(txt != "")
				duration = atoi(txt.c_str());
			txt = getFullstrText(cmnd->fullstr, 6);
			if(txt != "")
				strength = atoi(txt.c_str());

			if(duration > EFFECT_MAX_DURATION || duration < -1) {
				player->print("Duration must be between -1 and %d.\n", EFFECT_MAX_DURATION);
				return(0);
			}

			if(strength < 0 || strength > EFFECT_MAX_STRENGTH) {
				player->print("Strength must be between 0 and %d.\n", EFFECT_MAX_STRENGTH);
				return(0);
			}

			bstring effectStr = cmnd->str[4];
			EffectInfo* toSet = 0;
			if(toSet = target->getEffect(effectStr)) {
				// We have an existing effect we're modifying
				if(duration == 0) {
					// Duration is 0, so remove it
					target->removeEffect(toSet, true);
					player->print("Effect '%s' (creature) removed.\n", effectStr.c_str());
				} else {
					// Otherwise modify as appropriate
					toSet->setDuration(duration);
					if(strength != -1)
						toSet->setStrength(strength);
					player->print("Effect '%s' (creature) set to duration %d and strength %d.\n", effectStr.c_str(), toSet->getDuration(), toSet->getStrength());
				}
				break;
			} else {
				// No existing effect, add a new one
				if(strength == -1)
					strength = 1;
				if(target->addEffect(effectStr, duration, strength, true) == true) {
					player->print("Effect '%s' (creature) added with duration %d and strength %d.\n", effectStr.c_str(), duration, strength);
				} else {
					player->print("Unable to add effect '%s' (creature)\n", effectStr.c_str());
				}
				break;
			}

		} else if(cmnd->str[3][1] == 'x') {

			target->setExperience(cmnd->val[3]);
			if(target->isMonster() && !player->isDm()) {
				if(target->getExperience() > 10000)
					target->setExperience(10000);
			}
			player->print("%M has %ld experience.\n", target, target->getExperience());
			log_immort(true, player, "%s set %s %s's experience to %ld.\n",
				player->name, PLYCRT(target), target->name, target->getExperience());
			break;
		}

		if(cmnd->str[4][0] == 'd') {
			for(i=0; i<NUM_ENEMY_MOB; i++)
				mTarget->enemy_mob[i].clear();
			player->print("%M's enemy mobs deleted.\n", mTarget);
			break;
		}

		num = atoi(&cmnd->str[3][1]);
		if(num < 1 || num > NUM_ENEMY_MOB) {
			player->print("Error: %d is out of range for enemy mobs (1-%d).\n", num, NUM_ENEMY_MOB);
			return(0);
		}

		if(!mTarget) {
			player->print("Error: enemy mobs cannot be set on players.\n");
			return(0);
		}

		getCatRef(getFullstrText(cmnd->fullstr, 4), &mTarget->enemy_mob[num-1], mTarget);
		player->print("%M's enemy mob #%d set to creature %s.\n", mTarget, num, mTarget->enemy_mob[num-1].str().c_str());
		log_immort(true, player, "%s set %s %s's EnemyMob#%d to %s.\n",
			player->name, PLYCRT(mTarget), mTarget->name, num, mTarget->enemy_mob[num-1].str().c_str());
		break;


	case 'f':
		switch(cmnd->str[3][1]) {
		case 'a':
		{
			if(cmnd->num < 5) {
				player->print("Set what faction to what?\n");
				return(0);
			}

			const Faction *faction = gConfig->getFaction(cmnd->str[4]);
			if(!faction) {
				player->print("'%s' is an invalid faction.\n", cmnd->str[4]);
				return(0);
			}

			if(pTarget) {
				if(cmnd->val[4] > faction->getUpperLimit(pTarget) || cmnd->val[4] < faction->getLowerLimit(pTarget)) {
					player->print("Faction rating must be between %d and %d for this player.\n",
						faction->getUpperLimit(pTarget), faction->getLowerLimit(pTarget));
					return(0);
				}
			} else {
				if(cmnd->val[4] > Faction::MAX || cmnd->val[4] < Faction::MIN) {
					player->print("Faction rating must be between %d and %d.\n", Faction::MIN, Faction::MAX);
					return(0);
				}
			}

			target->factions[faction->getName()] = cmnd->val[4];
			//target->faction[num] = (int)cmnd->val[3];
			player->print("%s's faction %s(%s) set to %d.\n", target->name, faction->getName().c_str(), faction->getDisplayName().c_str(), cmnd->val[4]);
			log_immort(true, player, "%s set %s %s's faction %s(%s) to %d.\n",
				player->name, PLYCRT(target), target->name, faction->getName().c_str(), faction->getDisplayName().c_str(), cmnd->val[4]);
			return(0);
		}
		case 'c':
			if(pTarget) {
				pTarget->focus.setCur(MAX(1,MIN(30000,(int)cmnd->val[3])));
				player->print("Current Focus points set.\n");
				log_immort(true, player, "%s set %s %s's Current Focus Points to %d.\n",
					player->name, PLYCRT(pTarget), pTarget->name, pTarget->focus.getCur());
				return(0);
			}
		case 'm':
			if(pTarget) {
				pTarget->focus.setMax(MAX(1,MIN(30000,(int)cmnd->val[3])));
				player->print("Max Focus Points set.\n");
				log_immort(true, player, "%s set %s %s's Max Focus Points to %d.\n",
					player->name, PLYCRT(pTarget), pTarget->name, pTarget->focus.getMax());
				return(0);
			}
		}




		if(cmnd->num >= 5 && cmnd->str[4][0] == 'd' && mTarget) {
			for(f=0; f < MAX_MONSTER_FLAGS; f++) {
				mTarget->clearFlag(f);
			}
			player->print("All of %s's flags deleted.\n", target->name);
			break;
		}

		num = cmnd->val[3];
		if(num < 1 || num > (target->isPlayer() ? MAX_PLAYER_FLAGS : MAX_MONSTER_FLAGS)) {
			player->print("Error: flag out of range.\n");
			return(0);
		}

		if((mTarget && num == M_DM_FOLLOW+1 ) ||
		   ( pTarget && !player->isDm() &&
		      ( num == P_CAN_OUTLAW+1 || num == P_CAN_AWARD+1 || num == P_CT_CAN_DM_BROAD+1 || num == P_BUGGED+1 ||
		        num == P_CT_CAN_DM_LIST+1 || num == P_NO_COMPUTE+1 )  ) )
		{
		   player->print("You cannot set that flag.\n");
		   return(0);
		}

		if(ctModBuilder && num == P_INCOGNITO+1 && pTarget && pTarget->flagIsSet(P_INCOGNITO)) {
			player->print("Error: you cannot unset incognito flag on builders.\n");
			return(0);
		}
		if(num == M_WILL_BE_LOGGED+1 && mTarget) {
			player->print("Error: you cannot set/clear this flag.\n");
			return(PROMPT);
		}



		if(target->flagIsSet(num - 1)) {
			target->clearFlag(num - 1);
			player->print("%M's flag #%d(%s) off.\n", target, num, (mTarget ? get_mflag(num-1):get_pflag(num-1)));
			i=0;
		} else {
			target->setFlag(num - 1);
			player->print("%M's flag #%d(%s) on.\n", target, num, (mTarget ? get_mflag(num-1):get_pflag(num-1)));
			i=1;

			if(pTarget && num == P_MXP_ENABLED+1)
				pTarget->defineMXP();
		}

		if(pTarget && (num == P_BUILDER_MOBS+1 || num == P_BUILDER_OBJS+1))
			pTarget->save(true);

		log_immort(true, player, "%s set %s %s's flag %d(%s) %s.\n",
			player->name, PLYCRT(target), target->name, num,
			(mTarget ? get_mflag(num-1):get_pflag(num-1)), (i ? "On" : "Off"));
		break;
	case 'g':
		if(!strcmp(cmnd->str[3], "guild") || !strcmp(cmnd->str[3], "gu")) {
			if(!player->isDm()) {
				player->print("Error: you cannot set guilds.\n");
				return(0);
			}
			if(!pTarget) {
				player->print("Error: guilds cannot be set on mobs.\n");
				return(0);
			}
			pTarget->setGuild((int)cmnd->val[3]);
			player->print("Guild set.\n");
			log_immort(true, player, "%s set %s %s's guild to %d.\n",
			        player->name, PLYCRT(pTarget), pTarget->name, pTarget->getGuild());
			break;
		}

		if(!strcmp(cmnd->str[3], "guildrank") || !strcmp(cmnd->str[3], "gr")) {
			if(!player->isDm()) {
				player->print("Error: you cannot set guild rank.\n");
				return(0);
			}
			if(!pTarget) {
				player->print("Error: guild rank cannot be set on mobs.\n");
				return(0);
			}
			pTarget->setGuildRank((int)cmnd->val[3]);
			player->print("Guild Rank set.\n");
			log_immort(true, player, "%s set %s %s's guild rank to %d.\n",
				player->name, PLYCRT(pTarget), pTarget->name, pTarget->getGuildRank());
			break;
		}

		target->coins.set(cmnd->val[3], GOLD);

		player->print("%M has %ld gold.\n", target, target->coins[GOLD]);
		log_immort(true, player, "%s set %s %s's gold to %ld.\n",
			player->name, PLYCRT(target), target->name, target->coins[GOLD]);
		break;
	case 'h':
		if(cmnd->str[3][1] == 'm') {

			target->hp.setMax( MAX(1,MIN(30000,(int)cmnd->val[3])));
			player->print("Max Hit Points set.\n");
			log_immort(true, player, "%s set %s %s's Max Hit Points to %d.\n",
				player->name, PLYCRT(target), target->name, target->hp.getMax());
		} else {

			target->hp.setCur((int)cmnd->val[3]);
			player->print("Current Hitpoints set.\n");
			log_immort(true, player, "%s set %s %s's Current Hit Points to %d.\n",
				player->name, PLYCRT(target), target->name, target->hp.getCur());
		}
		break;
	case 'i':
		if(!strcmp(cmnd->str[3], "int")) {
			target->intelligence.setCur(MAX(1, MIN(cmnd->val[3], MAX_STAT_NUM)));
			player->print("Intelligence set.\n");
			log_immort(true, player, "%s set %s %s's Intelligence to %d.\n",
				player->name, PLYCRT(target), target->name, target->intelligence.getCur());
			break;
		}

		if(!strcmp(cmnd->str[3], "inum") && mTarget) {
			int inv = atoi(getFullstrText(cmnd->fullstr, 4).c_str());
			int numTrade = atoi(getFullstrText(cmnd->fullstr, 5).c_str());

			if(inv > 10 || inv < 1) {
				player->print("Carry slot number invalid.\n");
				player->print("Must be from 1 to 10.\n");
				return(0);
			}

			if(numTrade < 0)
				numTrade = 0;

			mTarget->carry[inv-1].numTrade = numTrade;
			if(numTrade) {
				player->print("Carry slot %d numTrade set to %d.\n", inv, numTrade);
				log_immort(true, player, "%s set %s %s's carry slot %d numTrade to %d.\n",
					player->name, PLYCRT(mTarget), mTarget->name, inv, numTrade);
			} else {
				player->print("Carry slot %d numTrade cleared.\n", inv);
				log_immort(true, player, "%s cleared %s %s's carry slot %d numTrade.\n",
					player->name, PLYCRT(mTarget), mTarget->name, inv);
			}
			break;
		}

		if(!strcmp(cmnd->str[3], "inv") && mTarget) {

			// the parser does a terrible job here, so we have to manually figure it out
			bstring txt = getFullstrText(cmnd->fullstr, 4);
			int inv=0;
			char action=0;

			if(txt != "") {
				inv = atoi(txt.c_str());
				if(!inv) {
					action = txt.getAt(0);
				} else {
					txt = getFullstrText(cmnd->fullstr, 5);
					if(txt != "")
						action = txt.getAt(0);
				}
			}

			// both mean delete
			if(action == '0')
				action = 'd';

			if((inv > 10 || inv < 0) && action != 'd') {
				player->print("Carry slot number invalid.\n");
				player->print("Must be from 1 to 10.\n");
				return(0);
			}
			if(inv && action == 'd') {
				mTarget->carry[inv-1].info.id = 0;
				mTarget->carry[inv-1].numTrade = 0;

				player->print("Carry slot %d cleared.\n", cmnd->val[3]);

				log_immort(true, player, "%s cleared %s's carry slot %ld.\n",
					player->name, mTarget->name, cmnd->val[3]);
				break;
			}

			if(action == 'd') {
				for(i=0; i<10; i++) {
					mTarget->carry[i].info.id = 0;
					mTarget->carry[i].numTrade = 0;
				}
				mTarget->clearMobInventory();

				player->print("Inventory cleared.\n");
				log_immort(true, player, "%s cleared %s's inventory.\n",
					player->name, mTarget->name);
				break;
			}
			object = findObject(player, player->first_obj, cmnd->str[4], 1);
			if(!object) {
				player->print("You are not carrying that.\n");
				return(0);
			}

			mTarget->carry[inv-1].info = object->info;
			player->print("Carry slot %d set to object %s.\n", inv, object->info.str().c_str());
			log_immort(true, player, "%s set %s %s's carry slot %ld to %s.\n",
				player->name, PLYCRT(mTarget), mTarget->name, inv, object->info.str().c_str());
			break;
		}
	case 'j':
		if(!mTarget) {
			player->print("Error: jail room cannot be set on players.\n");
			return(0);
		}

		getCatRef(getFullstrText(cmnd->fullstr, 4), &mTarget->jail, player);

		player->print("Jail room set to %s.\n", mTarget->jail.str().c_str());
		log_immort(true, player, "%s set %s %s's jail room to %s.\n",
			player->name, PLYCRT(mTarget), mTarget->name, mTarget->jail.str().c_str());
		break;
	case 'l':
		//target->getLevel() = MAX(1, MIN(cmnd->val[3], 30));
		num = cmnd->val[3];

		if(!strcmp(cmnd->str[3], "lc")) {
			if(num < 1 || num > LANGUAGE_COUNT) {
				player->print("Error: current language out of range.\n");
				return(0);
			}
			player->print("Current language set.\n");
			target->current_language = num-1;
			log_immort(true, player, "%s set %s %s's current language to %d(%s).\n",
				player->name, PLYCRT(target), target->name, target->current_language+1,
				get_language_adj(target->current_language));

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

			if(num < 1 || num > LANGUAGE_COUNT) {
				player->print("Error: language out of range.\n");
				return(0);
			}
			player->print("Language set.\n");

			log_immort(true, player, "%s turned %s %s's language #%d(%s).\n",
				player->name, (target->languageIsKnown(LUNKNOWN+(num-1)) ? "off":"on"),
				target->name, num, get_language_adj(num-1));

			if(target->languageIsKnown(LUNKNOWN+(num-1)))
				target->forgetLanguage(LUNKNOWN+num-1);
			else
				target->learnLanguage(LUNKNOWN+num-1);

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

			if(!pTarget) {
				player->print("Lore may only be reset on players.\n");
				return(0);
			}
			if(ctModBuilder) {
				player->print("Error: you cannot reset lore on builders.\n");
				return(0);
			}

			player->printColor("Before: ^c%d  ", pTarget->lore.size());
			Lore::reset(pTarget);
			player->printColor("After: ^c%d\n", pTarget->lore.size());
			player->print("%s's lore count has been reset.\n", pTarget->name);

		} else {

			target->setLevel(num, player->isDm());
			player->print("Level set.\n");
			log_immort(true, player, "%s set %s %s's %s to %d.\n",
				player->name, PLYCRT(target), target->name,
				"Level", target->getLevel());

		}

		break;
	case 'm':
		if(cmnd->str[3][1] == 'm') {

			target->mp.setMax(MAX(0,MIN(30000,(int)cmnd->val[3])), true);
			player->print("Max Magic Points set.\n");
			log_immort(true, player, "%s set %s %s's %s to %d.\n",
				player->name, PLYCRT(target), target->name,
				"Magic Points", target->mp.getMax());

		} else if(cmnd->str[3][1] == 'l' && mTarget) {
			mTarget->setMaxLevel((int)cmnd->val[3]);
			if(!mTarget->getMaxLevel())
				mTarget->clearFlag(M_LEVEL_RESTRICTED);
			else
				mTarget->setFlag(M_LEVEL_RESTRICTED);
			player->print("Max Killable Level set.\n");
			log_immort(true, player, "%s set %s %s's %s to %ld.\n",
				player->name, PLYCRT(mTarget), mTarget->name, "Max Killable Level",
				mTarget->getMaxLevel());

		} else if(cmnd->str[3][1] == 'r') {
			if(!mTarget) {
				player->print("Error: magic resistance cannot be set on player.\n");
				return(0);
			}

			mTarget->setMagicResistance((int)cmnd->val[3]);

			player->print("Magic resistance set.\n");
			log_immort(true, player, "%s set %s %s's %s to %d.\n",
				player->name, PLYCRT(mTarget), mTarget->name,
				"magic resistance", mTarget->getMagicResistance());
		} else {

			target->mp.setCur(MAX(0,MIN(30000,(int)cmnd->val[3])));
			player->print("Current Magic Points set.\n");
			log_immort(true, player, "%s set %s %s's %s to %d.\n",
				player->name, PLYCRT(target), target->name,
				"Current Magic Points", target->mp.getCur());
		}
		break;
	case 'n':
		if(!strcmp(cmnd->str[3], "nl")) {
			if(!pTarget) {
				player->print("Error: negative levels cannot be set on mobs.\n");
				return(0);
			}


			pTarget->setNegativeLevels((short)cmnd->val[3]);
			player->print("%s's negative levels set to %d.\n", pTarget->name, pTarget->getNegativeLevels());
			log_immort(true, player, "%s set %s %s's %s to #%d.\n",
				player->name, "Player", pTarget->name, "Negative Levels",
				pTarget->getNegativeLevels());
			break;
		}

		if(mTarget) {
			mTarget->setNumWander((short)cmnd->val[3]);
			player->print("Num wander set.\n");
			log_immort(true, player, "%s set %s %s's %s to %d.\n",
				player->name, PLYCRT(mTarget), mTarget->name,
				"Num Wander", mTarget->getNumWander());
		}
		break;
	case 'p':
		num = strlen(cmnd->str[3]);
		if(!strcmp(cmnd->str[3], "pf") || (num >= 3 && !strncmp(cmnd->str[3], "primefaction", num))) {
			if(!mTarget) {
				player->print("Error: prime faction cannot be set on players.\n");
				return(0);
			}
			if(cmnd->num < 4) {
				player->print("Set faction to what?\n");
				return(0);
			} else if(cmnd->num == 4) {
				mTarget->setPrimeFaction("");
				player->print("%s's prime faction is cleared.\n", target->name);
				log_immort(true, player, "%s cleared %s %s's %s.\n",
					player->name, "Monster", mTarget->name, "Primary Faction");
				return(0);
			}
			const Faction* faction = gConfig->getFaction(cmnd->str[4]);
			if(!faction) {
				player->print("'%s' is an invalid faction.\n", cmnd->str[4]);
				return(0);
			}
			mTarget->setPrimeFaction(faction->getName());
			player->print("%s is now set to prime faction %s(%s).\n", target->name, faction->getName().c_str(), faction->getDisplayName().c_str());
			log_immort(true, player, "%s set %s %s's %s to %s(%s).\n",
				player->name, "Monster", mTarget->name,
				"Primary Faction", faction->getName().c_str(), faction->getDisplayName().c_str());
			break;
		}

		if(!strcmp(cmnd->str[3], "pdur")) {

			if(!mTarget) {
				player->print("Error: Poison duration cannot be set on players.\n");
				return(0);
			}
			mTarget->setPoisonDamage(MAX(1, MIN(cmnd->val[3], 1200)));
			player->print("Poison duration set to %d seconds.\n", mTarget->getPoisonDuration());
			log_immort(true, player, "%s set %s %s's %s to %d.\n",
			        player->name, PLYCRT(target), target->name,
			        "Poison duration", mTarget->getPoisonDuration());
			break;
		}
		if(!strcmp(cmnd->str[3], "pdmg")) {

			if(!mTarget) {
				player->print("Error: Poison damage/tick cannot be set on players.\n");
				return(0);
			}
			mTarget->setPoisonDamage(MAX(1, MIN(cmnd->val[3], 500)));
			player->print("Poison damage set to %d per tick.\n", mTarget->getPoisonDamage());
			log_immort(true, player, "%s set %s %s's %s to %d.\n",
			        player->name, PLYCRT(target), mTarget->name,
			        "Poison damage/tick", mTarget->getPoisonDamage());
			break;
		}
		//if(!strcmp(cmnd->str[3], "pie")) {

		target->piety.setCur(MAX(1, MIN(cmnd->val[3], MAX_STAT_NUM)));
		player->print("Piety set.\n");
		log_immort(true, player, "%s set %s %s's %s to %d.\n",
			player->name, PLYCRT(target), target->name,
			"Peity", target->piety.getCur());
		break;

		//}
		/*
		if(!strcmp(cmnd->str[3], "pkin") && player->isDm()) {
			if(!pTarget) {
				player->print("Error: PKIN cannot be set on mobs.\n");
				return(0);
			}

			player->print("Pkills In set.\n");
			pTarget->setPkin((short)cmnd->val[3]);

			break;
		}
		if(!strcmp(cmnd->str[3], "pkwon") && player->isDm()) {
			if(!pTarget) {
				player->print("Error: PKWON cannot be set on mobs.\n");
				return(0);
			}

			player->print("Pkills Won set.\n");
			pTarget->setPkwon((short)cmnd->val[3]);
			break;
		}

		num = atoi(&cmnd->str[3][1]);
		if(num < 0 || num > 5) {
			player->print("Error: proficiency out of range.\n");
			return(0);
		}


		target->proficiency[num] = MAX(0, MIN(cmnd->val[3], 10000000));
		player->print("%M given %d shots in prof#%d.\n", target,
			target->proficiency[num], num);
		log_immort(true, player, "%s set %s %s's %s%d to %ld.\n",
			player->name, PLYCRT(target), target->name,
			"Prof#", num, target->proficiency[num]);

		break;
		 */
	case 'q':
		if(!pTarget) {
			player->print("Error: quests cannot be set on mobs.\n");
			return(0);
		}

		num = cmnd->val[3];
		if(num < 1 || num > MAX_QUEST) {
			player->print("Error: quest out of range.\n");
			return(0);
		}
		if(pTarget->questIsSet(num - 1)) {
			pTarget->clearQuest(num - 1);
			player->print("%M's quest #%d - (%s) off.\n", pTarget, num, get_quest_name(num-1));
			i=0;
		} else {
			pTarget->setQuest(num - 1);
			player->print("%M's quest #%d - (%s) on.\n", pTarget, num, get_quest_name(num-1));
			i=1;
		}
		log_immort(true, player, "%s turned %s %s's %s %d - (%s) %s.\n",
			player->name, PLYCRT(pTarget), pTarget->name, "Quest",
			num, get_quest_name(num-1), i ? "On" : "Off");

		break;
	case 'r':
		if(!strcmp(cmnd->str[3], "rag")) {
			if(!mTarget) {
				player->print("Error: race aggro cannot be set on players.\n");
				return(0);
			}
			num = cmnd->val[3];

			if(!strcmp(cmnd->str[4], "del")) {
				for(a=1; a<RACE_COUNT-1; a++)
					mTarget->clearRaceAggro(a);
				player->print("All %s's race aggros now cleared.\n");
				return(0);
			}

			if(num < 1 || num >= RACE_COUNT) {
				player->print("Error: race aggro out of range.\n");
				return(0);
			}

			if(mTarget->isRaceAggro(num, false)) {
				player->print("%M will no longer attack %s's.\n", mTarget, gConfig->getRace(num)->getName().c_str());
				mTarget->clearRaceAggro(num);
				log_immort(true, player, "%s set creature %s to NOT aggro %ss(%d).\n",
					player->name, mTarget->name, gConfig->getRace(num)->getName().c_str(), num);
			} else {
				mTarget->setRaceAggro(num);
				player->print("%M will now attack %s's.\n", mTarget, gConfig->getRace(num)->getName().c_str());
				log_immort(true, player, "%s set creature %s to aggro %ss(%d).\n",
					player->name, mTarget->name, gConfig->getRace(num)->getName().c_str(), num);
			}
			break;
		}
		switch(cmnd->str[3][1]) {
		case 'a':

			if(isdigit(cmnd->str[3][2])) {

				if(!pTarget) {
					player->print("Error: room boundaries cannot be set on mobs.\n");
					return(0);
				}
				if(!pTarget->isStaff()) {
					player->print("Error: room boundaries can only be set on staff.\n");
					return(0);
				}

				rnum = MAX(0, MIN(atoi(&cmnd->str[3][2]), MAX_BUILDER_RANGE));
				pTarget->bRange[rnum-1].low.setArea(cmnd->str[4]);

				player->print("%s's range #%d area set to %s.\n", pTarget->name, rnum,
					pTarget->bRange[rnum-1].low.area.c_str());
				log_immort(true, player, "%s set %s's range #%d area to %s.\n",
					player->name, pTarget->name, rnum, pTarget->bRange[rnum-1].low.area.c_str());

			} else {

				target->setRace((short)cmnd->val[3]);
				player->print("Race set to %s(%d).\n", target->getRace() ? gConfig->getRace(target->getRace())->getName().c_str() : "", target->getRace());
				if(target->getRace()) {
					target->setSize(gConfig->getRace(target->getRace())->getSize());
					player->print("Size automatically set to %s.\n", getSizeName(target->getSize()).c_str());
				}
				log_immort(true, player, "%s set %s %s's %s to %s(%d).\n",
					player->name, PLYCRT(target), target->name,
					"Race", target->getRace() ? gConfig->getRace(target->getRace())->getName().c_str() : "", target->getRace());
			}
			break;

		case 'e':
			if(!mTarget) {
				player->print("Error: rescue monsters cannot be set on players.\n");
				return(0);
			}

			rnum = MAX(1, MIN(atoi(&cmnd->str[3][strlen(cmnd->str[3])-1]), NUM_RESCUE))-1;
			getCatRef(getFullstrText(cmnd->fullstr, 4), &mTarget->rescue[rnum], mTarget);

			player->print("%s's rescue mob #%d set to %s.\n", mTarget->name, rnum+1,
				mTarget->rescue[rnum].str().c_str());
			log_immort(true, player, "%s set %s's rescue mob #%d to %s.\n",
				player->name, mTarget->name, rnum+1, mTarget->rescue[rnum].str().c_str());

			break;
			/*
		case 'e':
			if(!strcmp(cmnd->str[3], "reg") && target->isMonster())
			{

				if(!target->flagIsSet(M_REGENERATES)) {
					player->print("You must set mflag#%d(regenerates) first.\n", M_REGENERATES+1);
					return(0);
				}
				target->regenRate = MAX(1,MIN(cmnd->val[3], 30));
				player->print("Regeneration rate set.\n");
				log_immort(true, player, "%s set %s regeneration rate to %d seconds.\n", player->name, target->name, target->regenRate);
			}
			break;
			*/
		case 'l':

			if(!pTarget) {
				player->print("Error: room boundaries cannot be set on mobs.\n");
				return(0);
			}
			if(!pTarget->isStaff()) {
				player->print("Error: room boundaries can only be set on staff.\n");
				return(0);
			}

			rnum = MAX(0, MIN(atoi(&cmnd->str[3][2]), MAX_BUILDER_RANGE));
			pTarget->bRange[rnum-1].low.id = MAX(-1, MIN(RMAX, cmnd->val[3]));

			player->print("%s's low range #%d set to %d.\n", pTarget->name, rnum,
				pTarget->bRange[rnum-1].low.id);
			log_immort(true, player, "%s set %s's low range #%d to %d.\n",
				player->name, pTarget->name, rnum, pTarget->bRange[rnum-1].low.id);
			break;
		case 'h':

			if(!pTarget) {
				player->print("Error: room boundaries cannot be set on mobs.\n");
				return(0);
			}
			if(!pTarget->isStaff()) {
				player->print("Error: room boundaries can only be set on staff.\n");
				return(0);
			}

			rnum = MIN(MAX_BUILDER_RANGE, MAX(atoi(&cmnd->str[3][2]),0));
			pTarget->bRange[rnum-1].high = MAX(-1, MIN(RMAX, cmnd->val[3]));

			player->print("%s's high range #%d set to %d.\n", pTarget->name, rnum,
				pTarget->bRange[rnum-1].high);
			log_immort(true, player, "%s set %s's high range #%d to %d.\n",
				player->name, pTarget->name, rnum, pTarget->bRange[rnum-1].high);
			break;
		default:

			Realm r = (Realm)MAX(MIN_REALM, MIN(MAX_REALM-1, atoi(&cmnd->str[3][1])));
			target->setRealm(cmnd->val[3], r);
			player->print("%M given %d shots in realm#%d.\n", target, target->getRealm(r), num);
			log_immort(true, player, "%s set %s %s's %s%d to %ld.\n",
				player->name, PLYCRT(target), target->name, "Realm#",
				num, target->getRealm(r));
			break;
		}
		break;
	case 's':
		switch(cmnd->str[3][1]) {
		case 'i':
			target->setSize(getSize(cmnd->str[4]));
			player->print("%s's %s set to %s.\n", target->name, "Size", getSizeName(target->getSize()).c_str());
			log_immort(true, player, "%s set %s %s's %s to %s.\n",
				player->name, PLYCRT(target), target->name, "Size", getSizeName(target->getSize()).c_str());
			return(0);

			break;
		case 'k':
		{
			if(cmnd->num < 5) {
				player->print("Set what skill to what?\n");
				return(0);
			}
			if((int)cmnd->val[4] > MAXALVL*10 || (int)cmnd->val[4] < -1) {
				player->print("Skill range is 0 - %d, -1 to delete.\n", MAXALVL*10);
				return(0);
			}
			//bstring skillStr = cmnd->str[4];
			if(cmnd->val[4] == -1) {
				if(!target->knowsSkill(cmnd->str[4])) {
					player->print("%s doesn't know that skill.\n", target->name);
					return(0);
				}

				target->remSkill(cmnd->str[4]);

				player->print("%s's skill %s has been removed.\n", target->name, cmnd->str[4]);
				log_immort(true, player, "%s removed %s %s's skill %s.\n",
						player->name, PLYCRT(target), target->name, cmnd->str[4]);

			} else if(!target->setSkill(cmnd->str[4], cmnd->val[4])) {
				player->print("'%s' is not a valid skill.\n", cmnd->str[4]);
				return(0);
			} else {

				player->print("%s's skill %s set to %d.\n", target->name, cmnd->str[4], cmnd->val[4]);
				log_immort(true, player, "%s set %s %s's skill %s to %d.\n",
						player->name, PLYCRT(target), target->name, cmnd->str[4], (short)cmnd->val[4]);

			}
			break;
		}
		case 'l':
			if(!mTarget) {
				player->print("Error: skillLevel cannot be set on players.\n");
				return(0);
			}
			mTarget->setSkillLevel((int)cmnd->val[3]);
			player->print("Monster trade skill level set.\n");
			log_immort(true, player, "%s set %s %s's %s to %d(%s).\n",
				player->name, PLYCRT(mTarget), mTarget->name, "trade skill level",
				mTarget->getSkillLevel(), get_skill_string((int)mTarget->getSkillLevel()/10));
			break;
		case 'o':
			if(!pTarget) {
				player->print("Error: songs cannot be set on mobs.\n");
				return(0);
			}

			num = cmnd->val[3];
			if(num < 1 || num > gConfig->getMaxSong()) {
				player->print("Error: song out of range.\n");
				return(0);
			}

			if(!pTarget->songIsKnown(num - 1)) {
				pTarget->learnSong(num - 1);
				player->print("Song #%d - (Song of %s) on.\n", num, get_song_name(num-1));
				test=1;
			} else {
				pTarget->forgetSong(num - 1);
				player->print("Song #%d - (Song of %s) off.\n", num, get_song_name(num-1));
				test=0;
			}
			log_immort(true, player, "%s turned %s %s's %s %d - (Song of %s) %s.\n",
				player->name, PLYCRT(pTarget), pTarget->name, "Song",
				num, get_song_name(num-1), test == 1 ? "On" : "Off");
			break;
		case 'p':
			if(cmnd->str[4][0] == 'd') {
				for(sp=0; sp < MAXSPELL; sp++) {
					target->forgetSpell(sp);
				}
				player->print("%M's spells deleted.\n", target);
				break;
			}

			if(cmnd->str[4][0] == 'a') {
				for(sp=0; sp < MAXSPELL; sp++) {
					target->learnSpell(sp);
				}
				player->print("%M's spells all set.\n", target);
				break;
			}

			num = cmnd->val[3];
			if(num < 1 || num > MAXSPELL) {
				player->print("Error: spell out of range.\n");
				return(0);
			}

			if(!target->spellIsKnown(cmnd->val[3] - 1)) {
				target->learnSpell(cmnd->val[3] - 1);
				player->print("Spell #%d - (%s) on.\n", num, get_spell_name(num-1));
				test=1;
			} else {
				target->forgetSpell(cmnd->val[3] - 1);
				player->print("Spell #%d - (%s) off.\n", num, get_spell_name(num-1));
				test=0;
			}
			log_immort(true, player, "%s turned %s %s's %s %d - (%s) %s.\n",
				player->name, PLYCRT(target), target->name, "Spell",
				num, get_spell_name(num-1), test == 1 ? "On" : "Off");


			break;

		case 't':
			target->strength.setCur(MAX(1, MIN(cmnd->val[3], MAX_STAT_NUM)));
			player->print("Strength set.\n");
			log_immort(true, player, "%s set %s %s's %s to %d.\n",
				player->name, PLYCRT(target), target->name,
				"Strength", target->strength.getCur());
			break;
		default:
			if(!strcmp(cmnd->str[4], "d")) {
				target->saves[POI].chance = 0;
				target->saves[POI].gained = 0;
				target->saves[DEA].chance = 0;
				target->saves[DEA].gained = 0;
				target->saves[BRE].chance = 0;
				target->saves[BRE].gained = 0;
				target->saves[MEN].chance = 0;
				target->saves[MEN].gained = 0;
				target->saves[SPL].chance = 0;
				target->saves[SPL].gained = 0;
				player->print("%s's saves reset to 0.\n", target->name);

				break;
			} else {

				num = atoi(&cmnd->str[3][1]);
				if(num < 0 || num > 5) {
					player->print("Error: save out of range.\n");
					return(0);
				}

				target->saves[num].chance = MAX(1, MIN(cmnd->val[3], 99));
				player->print("%M now has %d%% chance for save #%d.\n", target,
					target->saves[num].chance, num);
				log_immort(true, player, "%s set %s %s's %s%d to %d.\n",
					player->name, PLYCRT(target), target->name,
					"Save#", num, target->saves[num].chance);

			}
		}
		break;
	case 't':
		switch(low(cmnd->str[3][1])) {
		case 'r':
			if(!mTarget) {
				player->print("Error: trade cannot be set on players.\n");
				return(0);
			}

			mTarget->setMobTrade((int)cmnd->val[3]);
			player->print("Trade set to %s.\n", get_trade_string((int)mTarget->getMobTrade()));
			log_immort(true, player, "%s set %s %s's %s to %d(%s).\n",
				player->name, PLYCRT(target), target->name,
				"NPC trade", mTarget->getMobTrade(), get_trade_string((int)mTarget->getMobTrade()));


			break;
			/*case 't':
				if(target->isPlayer())
					return(PROMPT);
				target->ttype = MAX(0,MIN(MAX_TTYPE,(int)cmnd->val[3]));
				player->print("Treasure type set.\n");
				log_immort(true, player, "%s set %s %s's %s to %d.\n",
					player->name,
					PLYCRT(target),
					target->name,
					"Treasure type",
					target->thaco);


			break; */
		case 'y':
			if(!mTarget) {
				player->print("Error: mob type cannot be set on players.\n");
				return(0);
			}

			mTarget->setType((int)cmnd->val[3]);

			if(mTarget->flagIsSet(M_CUSTOM)) {
				player->print("CUSTOM mob flag cleared.\n");
				mTarget->clearFlag(M_CUSTOM);
			}

			player->print("Monster set to type %s.\n", monType::getName(mTarget->getType()));
			log_immort(true, player, "%s set %s %s's %s to %s.\n",
				player->name, PLYCRT(mTarget), mTarget->name,
				"type", monType::getName(mTarget->getType()));

			if(mTarget->getSize() == NO_SIZE) {
				mTarget->setSize(monType::size(mTarget->getType()));
				if(mTarget->getSize() == NO_SIZE)
					player->print("Size automatically set to %s.\n", getSizeName(mTarget->getSize()).c_str());
			}

			if(!mTarget->flagIsSet(M_CUSTOM))
				mTarget->adjust(0);
			player->print("%s adjusted to standard \"%s\" stats.\n", mTarget->name, monType::getName(mTarget->getType()));
			break;
		}
		break;
	case 'w':
		if(mTarget) {
			num = (int)cmnd->val[3];
			num = MAX(0, MIN(MAXALVL*10, num));

			mTarget->setWeaponSkill(num);
			player->print("Weapon Skill set to %d.\n", mTarget->getWeaponSkill());
			break;
		}
		default:
			player->print("Invalid option.\n");
			return(0);
	}


	// Clear index when updating a monster
	// Set logged flags and save full flags
	if(mTarget) {
		mTarget->info.id = 0;
		mTarget->setFlag(M_WILL_BE_LOGGED);
		mTarget->setFlag(M_SAVE_FULL);

		strcpy(mTarget->last_mod, player->name);
		mTarget->escapeText();
	}

	return(0);
}


//*********************************************************************
//						dmCrtName
//*********************************************************************
// the dmObjName command allows a dm/ caretaker to modify an already
// existing object's name, description, wield description, and key
// words. This command does not save the changes to the object to the
// object data base.  This command is intended for adding personalize
// weapons and objects to the game

int dmCrtName(Player* player, cmd* cmnd) {
	Monster *target=0;
	int		i=0, num=0;
	char	modstr[32];
	char	which=0;
	bstring	text = "";

	strcpy(modstr, "");

	if(cmnd->num < 2) {
		player->print("\nRename what creature to what?\n");
		player->print("*cname <creature> [#] [-Aadtmk] <name>\n");
		return(PROMPT);
	}

	// parse the full command string for the start of the description
	// (pass  command, object, obj #, and possible flag).   The object
	// number has to be interpreted separately, ad with the normal
	// command parse (cmnd->val), due to problems caused having
	// the object number followed by a "-"

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

	cmnd->val[1]= 1;
	if(isdigit(cmnd->fullstr[i]))
		cmnd->val[1] = atoi(&cmnd->fullstr[i]);

	target = player->getRoom()->findMonster(player, cmnd);
	if(!target) {
		player->print("Monster not found in the room.\n");
		return(PROMPT);
	}

	if(target->info.id && !player->checkBuilder(target->info))
		return(0);
	if(!player->builderCanEditRoom("use *cname"))
		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] == 't' && cmnd->fullstr[i+2] == 't') {
			which = 7;
			i += 3;
		} else if(cmnd->fullstr[i+1] == 't') {
			which = 2;
			i += 2;
		} else if(cmnd->fullstr[i+1] == 'A') {
			which = 4;
			i += 2;
		} else if(cmnd->fullstr[i+1] == 'a') {
			i += 2;
			which = 5;
			num = atoi(&cmnd->fullstr[i]);
			if(num <1 || num > 3)
				num = 0;
			while(isdigit(cmnd->fullstr[i]))
				i++;
		} else if(cmnd->fullstr[i+1] == 'k') {
			i += 2;
			which = 3;
			num = atoi(&cmnd->fullstr[i]);
			if(num <1 || num > 3)
				num = 0;
			while(isdigit(cmnd->fullstr[i]))
				i++;
		} else if(cmnd->fullstr[i+1] == 'm') {
			i += 2;
			which = 6;
			num = atoi(&cmnd->fullstr[i]);
			if(num <1 || num > 3)
				num = 0;
			while(isdigit(cmnd->fullstr[i]))
				i++;
		}
		while(isspace(cmnd->fullstr[i]))
			i++;
	}

	// no description given
	if(cmnd->fullstr[i] == 0)
		return(PROMPT);

	text = &cmnd->fullstr[i];
	// handle object modification

	switch (which) {
	case 0:
		if(text.getLength() > 79)
			text = text.left(79);
		if(Pueblo::is(text)) {
			player->print("That monster name is not allowed.\n");
			return(0);
		}
		strcpy(target->name, text.c_str());
		player->print("\nName ");
		strcpy(modstr, "name");
		break;
	case 1:
		strcpy(modstr, "description");
		if(text == "0" && target->getDescription() == "") {
			target->setDescription("");
			player->print("Description cleared.\n");
			return(0);
		} else {
			target->setDescription(text);
			player->print("\nDescription ");
		}
		break;
	case 2:
		strcpy(modstr, "talk string");
		if(text == "0" && target->getTalk() != "") {
			target->setTalk("");
			player->print("Talk string cleared.\n");
			return(0);
		} else {
			target->setTalk(text);
			player->print("\nTalk String ");
		}
		break;
	case 3:
		if(num) {
			if(text == "0" && target->key[num-1][0]) {
				zero(target->key[num-1], sizeof(target->key[num-1]));
				player->print("Key #%d string cleared.\n", num);
				return(0);
			} else {
				if(text.getLength() > 19)
					text = text.left(19);
				for(i=0; i < text.getLength(); i++)
					text.setAt(i, keyTxtConvert(text.getAt(i)));
				strcpy(target->key[num-1], text.c_str());
				player->print("\nKey ");
				strcpy(modstr, "desc key");
			}
		}
		break;
	case 4:
		strcpy(modstr, "aggro string");
		if(text == "0" && target->aggroString[0]) {
			zero(target->aggroString, sizeof(target->aggroString));
			player->print("Aggro string cleared.\n");
			return(0);
		} else {
			if(text.getLength() > 79)
				text = text.left(79);
			strcpy(target->aggroString, text.c_str());
			player->print("\nAggro talk string ");
		}
		break;
	case 5:
		if(num) {
			strcpy(modstr, "attack strings");
			if(text == "0" && target->attack[num-1][0]) {
				zero(target->attack[num-1], sizeof(target->attack[num-1]));
				player->print("Attack string %d cleared.\n", num);
				return(0);
			} else {
				if(text.getLength() > 29)
					text = text.left(29);
				strcpy(target->attack[num-1], text.c_str());
				player->print("Attack type %d ", num);
			}
		}
		break;
	case 6:
		if(num) {
			strcpy(modstr, "movement strings");
			if(text == "0" && target->movetype[num-1][0]) {
				zero(target->movetype[num-1], sizeof(target->movetype[num-1]));
				player->print("Movement string %d cleared.\n", num);
				return(0);
			} else {
				if(text.getLength() > CRT_MOVETYPE_LENGTH-1)
					text = text.left(CRT_MOVETYPE_LENGTH-1);
				strcpy(target->movetype[num-1], text.c_str());
				player->print("Movement string %d ", num);
			}
		}
		break;
	case 7:
		strcpy(modstr, "trade talk string");
		if(text == "0" && target->ttalk[0]) {
			zero(target->ttalk, sizeof(target->ttalk));
			player->print("After trade talk string cleared.\n");
			return(0);
		} else {
			if(text.getLength() > 79)
				text = text.left(79);
			strcpy(target->ttalk, text.c_str());
			player->print("\nAfter trade talk string ");
		}
		break;
	default:
		player->print("\nNothing ");
	}
	player->print("done.\n");

	log_immort(true, player, "%s modified %s of creature %s(%s).\n",
		player->name, modstr, target->name, target->info.str().c_str());

	target->escapeText();
	strcpy(target->last_mod, player->name);
	return(0);
}

//*********************************************************************
//						dmAlias
//*********************************************************************
//  This function allows staff to become a monster.

int dmAlias(Player* player, cmd* cmnd) {
	Monster* monster = 0;

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

	monster = player->getRoom()->findMonster(player, cmnd);
	if(!monster) {
		player->print("Can't seem to locate that monster here.\n");
		return(0);
	}

	if(monster->isPlayer()) {
		player->print("Their soul refuses to be displaced.\n");
		return(0);
	}

	if(monster->flagIsSet(M_PERMENANT_MONSTER) || monster->isPet()) {
		player->print("Their soul refuses to be displaced.\n");
		return(0);
	}
	if(player->flagIsSet(P_ALIASING) && monster != player->getAlias()) {
		player->print("You may only possess one monster at a time.\n");
		return(0);
	}
	if(monster->flagIsSet(M_DM_FOLLOW)) {
		if(monster != player->getAlias()) {
			player->print("Their soul belongs to another.\n");
			return(0);
		}
		monster->clearFlag(M_DM_FOLLOW);
		player->clearFlag(P_ALIASING);
		player->print("You release %1N's body.\n", monster);

		log_immort(false,player, "%s no longer possesses %s.\n", player->name, monster->name);

		doStopFollowing(monster, FALSE);
		player->setAlias(0);
		return(0);
	}

	addFollower(player, monster, FALSE);
	player->setAlias(monster);
	player->setFlag(P_ALIASING);
	monster->setFlag(M_DM_FOLLOW);
	//  monster->setFlag(M_UNKILLABLE);

	//  player->strength.getCur() = monster->strength.getCur();
	//  player->dexterity.getCur() = monster->dexterity.getCur();
	//  player->constitution.getCur() = monster->constitution.getCur();
	//  player->intelligence.getCur() = monster->intelligence.getCur();
	//  player->piety.getCur() = monster->piety.getCur();
	//  player->getLevel() = monster->getLevel();
	//  player->ndice = monster->ndice;
	//  player->sdice = monster->sdice;
	//  player->pdice = monster->pdice;

	player->print("You possess %1N.\n", monster);

	// make sure we are invis at this point
	if(!player->flagIsSet(P_DM_INVIS)) {
		// dmInvis does not use the second param
		dmInvis(player, NULL);
	}

	log_immort(false,player, "%s possesses %s in room %s.\n", player->name, monster->name,
		player->getRoom()->fullName().c_str());

	return(0);
}

//*********************************************************************
//						dmFollow
//*********************************************************************
// This function allows staff to force a monster to follow
// them, and has been made to allow for the movement of
// custom monsters (made with the dmCrtName function).

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

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

	creature = player->getRoom()->findMonster(player, cmnd);
	if(!creature) {
		player->print("Can't seem to locate that creature here.\n");
		return(0);
	}

	if(creature->flagIsSet(M_PERMENANT_MONSTER)) {
		player->print("Perms can't follow.\n");
		return(0);
	}
	if(creature->following == player) {
		player->print("%s stops following you.\n", creature->name);
		doStopFollowing(creature, FALSE);
		return(0);
	}

	addFollower(player, creature, FALSE);
	player->print("%s starts following you.\n", creature->name);
	return(0);
}

//*********************************************************************
//						dmAttack
//*********************************************************************
//  This function allows staff to make a monster attack a given player.

int dmAttack(Player* player, cmd* cmnd) {
	Monster* attacker=0;
	Creature* victim=0;
	int	inroom=1;

	if(!player->checkBuilder(player->parent_rom)) {
		player->print("Error: Room number not inside any of your alotted ranges.\n");
		return(0);
	}
	if(!player->builderCanEditRoom("use *attack"))
		return(0);

	if(cmnd->num < 3) {
		player->print("syntax: *attack <monster> <defender>\n");
		return(0);
	}

	attacker = player->getRoom()->findMonster(player, cmnd);

	if(!attacker || !player->canSee(attacker)) {
		player->print("Can't seem to locate that attacker here.\n");
		return(0);
	}

	if(attacker->flagIsSet(M_PERMENANT_MONSTER)) {
		player->print("Perms can't do that.\n");
		return(0);
	}


	victim = player->getRoom()->findMonster(player, cmnd, 2);

	if(!victim) {
		lowercize(cmnd->str[2], 1);
		victim = gServer->findPlayer(cmnd->str[2]);
		inroom=0;
	}
	if(!victim || !player->canSee(victim)) {
		player->print("Can't seem to locate that victim here.\nPlease use full names.\n");
		return(0);
	}

	if(victim->flagIsSet(M_PERMENANT_MONSTER) && victim->isMonster()) {
		player->print("Perms can't do that.\n");
		return(0);
	}
	player->print("Adding %N to attack list of %N.\n", victim, attacker);


	if(!player->isDm())
		log_immort(true, player, "%s forces %s to attack %s.\n", player->name, attacker->name, victim->name);

	attacker->addEnmCrt(victim);

	if(inroom) {
		broadcast(victim->getSock(), victim->getRoom(), "%M attacks %N.", attacker, victim);
		victim->print("%M attacked you!\n", attacker);
	}
	return(0);
}

//*********************************************************************
//						dmListEnemy
//*********************************************************************
//  This function lists the enemy list of a given monster.

int dmListEnemy(Player* player, cmd* cmnd) {
	Creature* target=0;
	etag	*ep=0;

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

	if(!target) {
		player->print("Not here.\n");
		return(0);
	}

	player->print("Enemy list for %s:\n", target->name);
	ep = target->first_enm;

	if(!ep)
		player->print("None.\n");
	while(ep) {
		player->print("  %s.\n", ep->enemy);
		ep = ep->next_tag;
	}
	return(0);
}

//*********************************************************************
//						dmListCharm
//*********************************************************************
// This function allows staff to see a given players charm list

int dmListCharm(Player* player, cmd* cmnd) {
	Player* target=0;
	etag	*cp=0;

	if(cmnd->num < 2) {
		player->print("See whose charm list?\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);
	}

	cp = target->first_charm;
	player->print("Charm list for %s:\n", target->name);

	if(!cp)
		player->print("Nobody.\n");
	while(cp) {
		player->print("  %s\n", cp->enemy);
		cp = cp->next_tag;
	}

	player->print("Afflicted By: %s\n", target->getAfflictedBy().c_str());
	if(!target->minions.empty()) {
		player->print("Minions:\n");
		std::list<bstring>::iterator mIt;
		for(mIt = target->minions.begin() ; mIt != target->minions.end() ; mIt++) {
			player->print("  %s\n", (*mIt).c_str());
		}
	}
	return(0);
}

//*********************************************************************
//						dmSaveMob
//*********************************************************************

void dmSaveMob(Player* player, cmd* cmnd, CatRef cr) {
	Monster *target=0;
	ttag	*tp=0, *tempt=0;
	char	file[80];
	int		i=0, x=0;
	otag	*op=0;
	ctag	*fol=0;

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

	if(cmnd->num < 3) {
		player->print("Syntax: *save c [name] [number]\n");
		return;
	}

	target = player->getRoom()->findMonster(player, cmnd->str[2], 1);

	if(!target) {
		player->print("Monster not found.\n");
		return;
	}

	if(!validMobId(cr)) {
		player->print("Index error: monster number invalid.\n");
		return;
	}
	if(!player->checkBuilder(cr, false)) {
		player->print("Error: %s out of your allowed range.\n", cr.str().c_str());
		return;
	}

	log_immort(true, player, "%s saved %s to %s.\n",
		player->name, target->name, cr.str().c_str());

	target->clearMobInventory();
	player->print("Monster inventory cleaned before saving.\n");

	// No longer need to log this monster because he's been saved
	target->clearFlag(M_WILL_BE_LOGGED);
	// Also no longer need to do a full save to the player's inv
	// because he's been updated on disk
	target->clearFlag(M_SAVE_FULL);

	tp = target->first_tlk;
	while(tp) {
		tempt = tp->next_tag;
		if(tp->key)
			delete tp->key;
		if(tp->response)
			delete[] tp->response;
		if(tp->action)
			delete tp->action;
		if(tp->target)
			delete tp->target;
		delete tp;
		tp = tempt;
	}
	target->first_tlk = 0;

	op = target->first_obj;
	if(!target->flagIsSet(M_TRADES)) {
		while(op) {
			x = op->obj->info.id;
			if(!x) {
				player->print("Unique object in inventory not saved.\n");
				op = op->next_tag;
				continue;
			}
			target->carry[i].info.id = x;
			i++;
			if(i>9) {
				player->print("Only first 10 objects in inventory saved.\n");
				break;
			}
			op = op->next_tag;
		}
	}

	// clean up possesed before save
	if(target->flagIsSet(M_DM_FOLLOW)) { // clear relevant follow lists
		if(target->following) {
			target->following->clearFlag(P_ALIASING);
			Player* master = target->following->getPlayer();
			master->setAlias(0);
			master->print("%1M's soul was saved.\n", target);
			fol = master->first_fol;
			if(fol->crt == target) {
				master->first_fol = fol->next_tag;
				delete fol;
			}
		}
		target->clearFlag(M_DM_FOLLOW);

	}

	target->info = cr;

	sprintf(file, monsterPath(target->info));
	if(file_exists(file))
		player->print( "Monster %s might already exist.\n", cr.str().c_str());

	if(target->saveToFile()!= 0) {
		loge("Error saving monster in dmSaveMob()");
		player->print("Error: monster was not saved\n" );
	} else
		player->print("Monster %s updated.\n", cr.str().c_str());

	if(player->flagIsSet(P_NO_FLUSHCRTOBJ))
		gConfig->replaceMonsterInQueue(target->info, target);
}

//*********************************************************************
//						dmAddMob
//*********************************************************************
// This function creates a generic creature for staff to work on.

int dmAddMob(Player* player, cmd* cmnd) {
	Monster	*new_mob=0;
	int		n;
	long	t = time(0);

	if(!player->canBuildMonsters())
		return(cmdNoAuth(player));
	if(!player->checkBuilder(player->parent_rom)) {
		player->print("Error: this room is out of your range; you cannot create a mob here.\n");
		return(0);
	}
	if(!player->builderCanEditRoom("add monsters"))
		return(0);

	new_mob = new Monster;
	if(!new_mob) {
		player->print("Cannot allocate memory for monster.\n");
		merror("dmAddMob", NONFATAL);
		return(0);
	}
	log_immort(true, player, "%s made a new mob!\n", player->name);

	//zero(new_mob, sizeof(Monster));

	strcpy(new_mob->name, "clay form");
	strcpy(new_mob->key[0], "form");
	new_mob->setLevel(1);
	new_mob->setType(MONSTER);
	new_mob->strength.setCur(100);
	new_mob->dexterity.setCur(100);
	new_mob->constitution.setCur(100);
	new_mob->intelligence.setCur(100);
	new_mob->piety.setCur(100);
	new_mob->hp.setMax(12);
	new_mob->hp.restore();
	new_mob->setArmor(25);
	new_mob->setDefenseSkill(5);
	new_mob->setWeaponSkill(5);
	new_mob->setExperience(10);
	new_mob->damage.setNumber(1);
	new_mob->damage.setSides(4);
	new_mob->damage.setPlus(1);
	new_mob->first_obj = 0;
	new_mob->first_fol = 0;
	new_mob->first_enm = 0;
	new_mob->first_tlk = 0;
	new_mob->parent_rom = 0;
	new_mob->area_room = 0;
	new_mob->following = 0;
	for(n=0; n<20; n++)
		new_mob->ready[n] = 0;
	new_mob->setFlag(M_SAVE_FULL);
	new_mob->lasttime[LT_MON_SCAVANGE].ltime =
	new_mob->lasttime[LT_MON_WANDER].ltime =
	new_mob->lasttime[LT_MOB_THIEF].ltime =
	new_mob->lasttime[LT_TICK].ltime =
	new_mob->lasttime[LT_TICK_SECONDARY].ltime =
	new_mob->lasttime[LT_TICK_HARMFUL].ltime = t;
	new_mob->addToRoom(player->getRoom());


	player->print("Monster created.\n");
	return(0);
}



//*********************************************************************
//						dmForceWander
//*********************************************************************

int	dmForceWander(Player* player, cmd* cmnd) {
	Monster* monster=0;
	char	name[80];

	strcpy(name,"");

	if(!player->checkBuilder(player->parent_rom)) {
		player->print("Error: Room number not inside any of your alotted ranges.\n");
		return(0);
	}
	if(!player->builderCanEditRoom("use *wander"))
		return(0);

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


	monster = player->getRoom()->findMonster(player, cmnd);

	if(!monster) {
		player->print("That is not here.\n");
		return(0);
	}

	if(monster->isPlayer()) {
		player->print("That is not here.\n");
		return(0);
	}
	if(monster->isPet() || monster->flagIsSet(M_DM_FOLLOW)) {
		player->print("You can't make them wander away.\n");
		return(0);
	}

	if(monster->flagIsSet(M_PERMENANT_MONSTER)) {
		player->print("Do not make perms wander away.\n");
		return(0);
	}

	strcpy(name, monster->name);
	broadcast(NULL, player->getRoom(), "%1M just %s away.", monster, Move::getString(monster).c_str());

	monster->deleteFromRoom();
	free_crt(monster);

	log_immort(false,player,"%s forced %s to wander away in room %s.\n",
		player->name, name, player->getRoom()->fullName().c_str());


	return(0);
}


//*********************************************************************
//						dmBalance
//*********************************************************************

int dmBalance(Player* player, cmd* cmnd) {
	Monster	*target=0;
	int		lvl=0;

	if(cmnd->num < 2) {
		player->print("*balance what and to what level?\n");
		player->print("Syntax: *balance <creature> <level#>\n");
		return(0);
	}

	target = player->getRoom()->findMonster(player, cmnd->str[1], 1);

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


	if(target->info.id && !player->checkBuilder(target->info)) {
		player->print("Creature not in any of your alotted ranges.\n");
		return(0);
	}
	if(!player->builderCanEditRoom("use *balance"))
		return(0);


	if(target->getType() == MONSTER) {
		player->print("Set creature type first. *dmh mtypes.\n");
		player->print(":*set c mob ty #\n");
		return(0);
	}

	target->setLevel((short)cmnd->val[1]);

	// Adjusts mob to normal stats.
	target->adjust(0);

	if(lvl >= 7)
		target->setFlag(M_BLOCK_EXIT);

	player->print("%M is now balanced at level %d.\n", target, target->getLevel());

	player->print("%M was balanced with average %s stats.\n", target, monType::getName(target->getType()));
	log_immort(true, player, "%s balanced %s (%s) to level %d.\n", player->name, target->name, monType::getName(target->getType()), target->getLevel());

	return(0);
}