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/
/*
 * convert.cpp
 *	 This program is a utility that will convert all old monsters/objects/rooms/players
 *		to the newest file version.  Being used initially for the new combat system.
 *   ____            _               
 *  |  _ \ ___  __ _| |_ __ ___  ___ 
 *  | |_) / _ \/ _` | | '_ ` _ \/ __|
 *  |  _ <  __/ (_| | | | | | | \__ \
 *  |_| \_\___|\__,_|_|_| |_| |_|___/
 *
 * This software is distributed in accordance with the
 *  Creative Commons - Attribution - Non Commercial - Share Alike 3.0 License
 *    http://creativecommons.org/licenses/by-nc-sa/3.0/
 *  
 * 	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 <sstream>
#include <iostream>

#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include "mud.h"
#include "property.h"
#include "commands.h"

#ifdef __CYGWIN__
/* borrowed these definitions from Apache */
#define ap_tolower(c) (tolower(((unsigned char)(c))))
#define ap_toupper(c) (toupper(((unsigned char)(c))))

static inline
const char *strcasestr( const char *h, const char *n )
{ /* h="haystack", n="needle" */
	const char *a=h, *e=n;
	
	if( !h || !*h || !n || !*n ) { return 0; }
	while( *a && *e ) {
		if( ap_toupper(*a)!=ap_toupper(*e) ) {
			++h; a=h; e=n;
		}
		else {
			++a; ++e;
		}
	}
	return *e ? 0 : h;
}
#endif

int rLow = 15000;
int rHigh = 17058;

#define SHARP           0
#define THRUST          1
#define BLUNT           2
#define POLE            3
#define MISSILE         4
#define CLEAVE          5

void convertObj();
void convertCrt();
void convertRoom();
void convertPly();

int main(int argc, char *argv[]) {
	// We need the config loaded for skills
	gConfig = Config::getInstance();
	gConfig->load();
	gConfig->clearProperties();
//	convertObj();
//	convertCrt();
	convertRoom();
//	convertPly();
}
void convertObject(Object* toConvert);
void convertMonster(Creature* toConvert);
void convertRoom(Room* toConvert);

void convertPly() {
	struct		dirent *dirp=0;
	DIR			*dir=0;

	if((dir = opendir(PLAYERPATH)) == NULL) {
		printf("Directory could not be opened.\n");
		return;
	}
	bstring pName;
	Player* toConvert;
	while((dirp = readdir(dir)) != NULL){
		// is this a player file?
		if(dirp->d_name[0] == '.')
			continue; 
		if(!isupper(dirp->d_name[0]))
			continue;
		pName = dirp->d_name;
		pName.Replace(".xml", "");
		printf("Looking to convert %s\n", pName.c_str());
		if(!loadPlayer(pName.c_str(), &toConvert))
			continue;
		
		if(!toConvert)
			continue;

		printf("Converting %s\n", toConvert->name);
		convertMonster(toConvert);
		toConvert->saveToFile();
		free_crt(toConvert);
		
		
	}
	
}

void convertObj() {
	char		filename[256];
	int			curNum, curFile;
	xmlDocPtr	xmlDoc;
	xmlNodePtr	rootNode;
	xmlNodePtr	curNode;	
	int			num;
	Object*     curObject = 0;
	
	// Current mob we're looking at, start at rangeLow
	curNum = rLow;
	// Current file we're looking at
	curFile = curNum/OFILESIZE;
	
	while(curNum <= rHigh) {
		sprintf(filename, "/home/realms/realms/objmon/o%02d.xml", curFile);
		if((xmlDoc = xml::loadFile(filename, "Objects")) == NULL) {
			// Ok so we can't load this file, means none of them in this range are going to be found
			// so jump to the next file and increase the curNum as appropriate
			curFile++;
			curNum = curFile * OFILESIZE;
			continue;
		}
		rootNode = xmlDocGetRootElement(xmlDoc);
		
		curNode = rootNode->children;
		while(curNode != NULL) {
			if(NODE_NAME(curNode, "Object")) {
				num = xml::getIntProp(curNode, "Num");
				// Passed the highest mob we want to see, so quit
				if(num > rHigh)
					break;
				
				// Lower mob than we want to see, go to the next one
				if(num < rLow) {
					curNode = curNode->next;
					continue;
				}

				
				// If we got here, we probly want to see it so lets print it out and set the curNum to what we're at
				curNum = num;
				curObject = new Object;
				if(!curObject) abort();
				curObject->info.id = num;
				curObject->readFromXml(curNode);
					
				// Invert the logic here, test for cases to ignore
				if(!strcmp(curObject->name, "...") ||
				     !strcmp(curObject->name, "none")) 
				{
					// Do nothing
				} else {
					if(curObject->info.id >= 17000 && curObject->info.id < 17999) {
						curObject->info.setArea("tut");
						curObject->info.id -= 16999;
					}
					convertObject(curObject);
					curObject->saveToFile();
				}
				delete curObject;
			}
				curNode = curNode->next;
		}
		xmlFreeDoc(xmlDoc);
		xmlCleanupParser();
		// Move on to the next file
		curFile++;
		curNum = curFile * OFILESIZE;
	}
	
}
void convertCrt() {
	char		filename[256];
	int			curNum, curFile;
	xmlDocPtr	xmlDoc;
	xmlNodePtr	rootNode;
	xmlNodePtr	curNode;	
	int			num;
	Monster*    curMonster = 0;

	// Current mob we're looking at, start at rangeLow
	curNum = rLow;
	// Current file we're looking at
	curFile = curNum/MFILESIZE;

	while(curNum <= rHigh) {
		sprintf(filename, "/home/realms/realms/objmon/m%02d.xml", curFile);
		if((xmlDoc = xml::loadFile(filename, "Creatures")) == NULL) {
			// Ok so we can't load this file, means none of them in this range are going to be found
			// so jump to the next file and increase the curNum as appropriate
			curFile++;
			curNum = curFile * MFILESIZE;
			continue;
		}
		rootNode = xmlDocGetRootElement(xmlDoc);

		curNode = rootNode->children;
		while(curNode != NULL) {
			if(NODE_NAME(curNode, "Creature")) {
				num = xml::getIntProp(curNode, "Num");
				// Passed the highest mob we want to see, so quit
				if(num > rHigh)
					break;
				// Lower mob than we want to see, go to the next one
				if(num < rLow) {
					curNode = curNode->next;
					continue;
				}
				// If we got here, we probly want to see it so lets print it out and set the curNum to what we're at
				curNum = num;
				curMonster = new Monster;
				if(!curMonster) abort();
				curMonster->info.id = num;
				xml::copyPropToBString(curMonster->version, curNode, "Version");
				curMonster->readFromXml(curNode);

				if(!strcmp(curMonster->name, "...") ||
				   !strcmp(curMonster->name, "none") ||
				   !strcmp(curMonster->name, "clay form")) 
				{
					// Do nothing
				} else {
					if(curMonster->info.id >= 17000 && curMonster->info.id < 17999) {
						curMonster->info.setArea("tut");
						curMonster->info.id -= 16999;
					}
					convertMonster(curMonster);
					curMonster->saveToFile();
				}
				free_crt(curMonster);
			}
			curNode = curNode->next;
		}
		xmlFreeDoc(xmlDoc);
		xmlCleanupParser();
		// Move on to the next file
		curFile++;
		curNum = curFile * MFILESIZE;
	}
}


void doConvertRoom(Room *curRoom, bool force) {
	Property	*p=0;
	bstring name = "";
	bool		skipThisRoom = false, isShopStorage=false;

//		if(!curRoom->readFromXml(rootNode) != 0) {
//			delete curRoom;
//			curNum++;
//			continue;
//		};
	
	if(!curRoom->first_mon && !curRoom->first_obj)
		skipThisRoom = true;
	std::cout << "Room:" << curRoom->info.id << "\n";
	// convert all storage rooms
	if(curRoom->info.id > 15000 && curRoom->info.id < 15999) {
		curRoom->info.setArea("stor");
		curRoom->info.id -= 15000;

		name = curRoom->name;
		name = name.left(name.Find("'"));

		p = new Property;
		p->setOwner(name);
		p->setName(curRoom->name);
		p->setDateFounded();
		p->setLocation("any realty office");
		p->addRange(curRoom->info);
		p->setType(PROP_STORAGE);
		gConfig->addProperty(p);

		isShopStorage = true;
		skipThisRoom = false;
	}
	// convert all storage rooms
	if(curRoom->info.id > 16000 && curRoom->info.id < 16999) {
		curRoom->info.setArea("shop");
		curRoom->info.id -= 16000;

		// only create a property for the odd numbered ones
		if(curRoom->info.id % 2) {

			Room* outside=0;
			name = curRoom->name;
			name = name.left(name.Find("'"));

			p = new Property;
			p->setOwner(name);
			p->setName(curRoom->name);
			p->setDateFounded();
			p->addRange(curRoom->info.area, curRoom->info.id, curRoom->info.id+1);
			p->setType(PROP_SHOP);
			
			
			if(loadRoom(curRoom->first_ext->ext->room, &outside)) {

				p->setLocation(outside->name);
				
				// exits need updating as well
				outside->first_obj=0;
				xtag	*xp = outside->first_ext;
				while(xp) {
					if(xp->ext->room.id > 16000 && xp->ext->room.id < 16999) {
						xp->ext->room.setArea("shop");
						xp->ext->room.id -= 16000;
					}
					xp = xp->next_tag;
				}
				outside->saveToFile(1);
			}

			gConfig->addProperty(p);

		} else {
			// update exits leading out of the shop storage room
			xtag	*xp = curRoom->first_ext;
			while(xp) {
				if(xp->ext->room.id > 16000 && xp->ext->room.id < 16999) {
					xp->ext->room.setArea("shop");
					xp->ext->room.id -= 16000;
				}
				xp = xp->next_tag;
			}
		}

		isShopStorage = true;
		skipThisRoom = false;
	}

	if(curRoom->info.id >= 17000 && curRoom->info.id < 17999) {
		curRoom->info.setArea("tut");
		curRoom->info.id -= 16999;

		// update exits
		xtag	*xp = curRoom->first_ext;
		while(xp) {
			if(xp->ext->room.id >= 17000 && xp->ext->room.id < 17999) {
				xp->ext->room.setArea("tut");
				xp->ext->room.id -= 16999;
			}
			xp = xp->next_tag;
		}

		for(int i=0; i<10; i++) {

			//if(curRoom->perm_mon[i].cr.id >= 17000 && curRoom->perm_mon[i].cr.id < 17999) {
			//	curRoom->perm_mon[i].cr.setArea("tut");
			//	curRoom->perm_mon[i].cr.id -= 16999;
			//}
			//if(curRoom->perm_obj[i].cr.id >= 17000 && curRoom->perm_obj[i].cr.id < 17999) {
			//	curRoom->perm_obj[i].cr.setArea("tut");
			//	curRoom->perm_obj[i].cr.id -= 16999;
			//}
			//if(curRoom->wander.random[i].id >= 17000 && curRoom->wander.random[i].id < 17999) {
			//	curRoom->wander.random[i].setArea("tut");
			//	curRoom->wander.random[i].id -= 16999;
			//}

		}

		skipThisRoom = false;
	}


	// don't bother updating any other objects
	if(!isShopStorage)
		curRoom->first_obj = 0;
	curRoom->first_mon = 0;

	if(!skipThisRoom)
		convertRoom(curRoom);
	
	curRoom->saveToFile(1);

}


void convertRoom() {
	char		filename[256];
	int			curNum;
	xmlDocPtr	xmlDoc;
	xmlNodePtr	rootNode;
//	xmlNodePtr	curNode;	
	int			j;
	Room*       curRoom = 0;

	//printRoomHeader();
	
	curNum = rLow;
	
	while(curNum <= rHigh) {
		sprintf(filename, "%s/r%05d.xml", ROOMPATH, curNum);

		if(!file_exists(filename)) {
			curNum++;
			continue;
		}

		if((xmlDoc = xml::loadFile(filename, "Room")) == NULL) {
			curNum++;
			continue;
		}
		rootNode = xmlDocGetRootElement(xmlDoc);
		j = xml::getIntProp(rootNode, "Num");
		if(j != curNum) {
			std::cout << "ERROR: Room " << j << " when expecting " << curNum << ".\n";
			curNum++;
			continue;
		}


		
		curRoom = new Room;
		curRoom->readFromXml(rootNode);
		doConvertRoom(curRoom, false);
		delete curRoom;
		
		
		
		xmlFreeDoc(xmlDoc);
		xmlCleanupParser();
		// Move on to the next file
		curNum++;
	}
	gConfig->saveProperties();
}

const char* oldWeaponType(int type) {
	switch(type) {
	case SHARP:
		return("sharp");
	case THRUST:
		return("thrust");
	case BLUNT:
		return("blunt");
	case MISSILE:
		return("missile");
	case POLE:
		return("pole");
	case CLEAVE:
		return("cleave");
	default:
		return("ERROR!");
	}
}
void convertObject(Object* toConvert) {
	bstring newType = "";
	// Convert old weapons
	if(toConvert->type >= SHARP && toConvert->type <= CLEAVE) {
		int oldType = toConvert->type;
		

		if(	strcasestr(toConvert->name, "dagger")
				|| strcasestr(toConvert->name, "dirk")
				|| strcasestr(toConvert->name, "bone")
				|| strcasestr(toConvert->name, "stinger")
				|| strcasestr(toConvert->name, "fang")
				|| strcasestr(toConvert->name, "bodkin")
				|| strcasestr(toConvert->name, "stiletto")
				|| strcasestr(toConvert->name, "shank")
				|| strcasestr(toConvert->name, "teeth")
				|| strcasestr(toConvert->name, "tooth")
				|| strcasestr(toConvert->name, "athame")
				|| strcasestr(toConvert->name, "knife")
				|| strcasestr(toConvert->name, "bilbo")
				|| strcasestr(toConvert->name, "scalpel")) 
		{
			newType = "dagger";
		} 
		else if(strcasestr(toConvert->name, "rapier")
				|| strcasestr(toConvert->name, "sabre")) 
		{
			newType = "rapier";
		}
		else if(strcasestr(toConvert->name, "blade")
				|| strcasestr(toConvert->description.c_str(), "blade")
				|| strcasestr(toConvert->name, "sword")
				|| strcasestr(toConvert->name, "claymore")
				|| strcasestr(toConvert->name, "falchion")
				|| strcasestr(toConvert->name, "katana")
				|| strcasestr(toConvert->name, "scimitar")
				|| strcasestr(toConvert->name, "cutlass")
				|| strcasestr(toConvert->name, "machete")) 
		{
			if(toConvert->flagIsSet(O_TWO_HANDED)) {
				newType = "great-sword";
			} else {
				newType = "sword";
			}
		} else if(strcasestr(toConvert->name, "axe")
				|| strcasestr(toConvert->name, "hatchet")
				|| strcasestr(toConvert->name, "cleaver")
				|| strcasestr(toConvert->name, "skullsplitter")) 
		{
			if(toConvert->flagIsSet(O_TWO_HANDED)) {
				newType = "great-axe";
			} else {
				newType = "axe";
			}
		}
		else if(strcasestr(toConvert->name, "whip")) {
			newType = "whip";
		}
		else if(strcasestr(toConvert->name, "hammer")
				|| strcasestr(toConvert->name, "mallet"))
		{
			if(toConvert->flagIsSet(O_TWO_HANDED)) {
				newType = "great-hammer";
			} else {
				newType = "hammer";
			}
		}
		else if(strcasestr(toConvert->name, "flail")
				|| strcasestr(toConvert->name, "mace")
				|| strcasestr(toConvert->name, "morning star")) 
		{
			if(toConvert->flagIsSet(O_TWO_HANDED)) {
				newType = "great-mace";
			} else {
				newType = "mace";
			}
		}
		else if(strcasestr(toConvert->name, "club")
				|| strcasestr(toConvert->name, "cudgel")) 
		{
			newType = "club";
		}
		else if(strcasestr(toConvert->name, "staff")
				|| strcasestr(toConvert->name, "stave"))
		{
			newType = "staff";
		}
		else if(strcasestr(toConvert->name, "lance")
				|| strcasestr(toConvert->name, "halberd")
				|| strcasestr(toConvert->name, "scythe")
				|| strcasestr(toConvert->name, "voulge")
				|| strcasestr(toConvert->name, "javelin")
				|| strcasestr(toConvert->name, "pole")
				|| strcasestr(toConvert->name, "glaive")
				|| strcasestr(toConvert->name, "guisarme")
				|| strcasestr(toConvert->name, "bardiche")
				|| strcasestr(toConvert->name, "naginata")
				|| strcasestr(toConvert->name, "spetum"))
		{
			newType = "polearm";
		}
		else if(strcasestr(toConvert->name, "trident")
				|| strcasestr(toConvert->name, "spear")
				|| strcasestr(toConvert->name, "harpoon"))
		{
			newType = "spear";
		}
		else if(strcasestr(toConvert->name, "crossbow"))
		{
			newType = "crossbow";
		}
		else if(strcasestr(toConvert->name, "bow"))
		{
			newType = "bow";
		}
		else if(strcasestr(toConvert->name, "sling")
				|| strcasestr(toConvert->name, "launcher")
				|| strcasestr(toConvert->name, "dart")
				|| strcasestr(toConvert->name, "throwing"))
		{
			newType = "thrown";
		} 
		else if(toConvert->type == MISSILE) {
			newType = "bow";
		} 
		else if(toConvert->type == THRUST) {
			newType = "dagger";
		}
		else if(toConvert->type == BLUNT) {
			newType = "club";
		}
		else if(toConvert->type == CLEAVE) {
			if(toConvert->flagIsSet(O_TWO_HANDED)) {
				newType = "great-axe";
			} else {
				newType = "axe";
			}
		}
		else if(toConvert->type == POLE) {
			newType = "polearm";
		} 
		else if(strcasestr(toConvert->name, "claw")) {
			newType = "claw";
		}
		toConvert->delay *= 10;
		
		if(toConvert->flagIsSet(OLD_O_PROF_20)) {
			toConvert->clearFlag(OLD_O_PROF_20);
			toConvert->requiredSkill = 30;
		}
		if(toConvert->flagIsSet(OLD_O_PROF_40)) {
			toConvert->clearFlag(OLD_O_PROF_40);
			toConvert->requiredSkill = 70;
		}
		if(toConvert->flagIsSet(OLD_O_PROF_60)) {
			toConvert->clearFlag(OLD_O_PROF_60);
			toConvert->requiredSkill = 100;
		}
		if(toConvert->flagIsSet(OLD_O_PROF_80)) {
			toConvert->clearFlag(OLD_O_PROF_80);
			toConvert->requiredSkill = 140;
		}

		// Dunno: meat cleaver
		if(newType != "" ) {
			toConvert->type = WEAPON;
			toConvert->setWeaponType(newType);
			printf("Converted Weapon %s:%s from (%s) to (%s).\n", toConvert->info.str(), toConvert->name, oldWeaponType(oldType), newType.c_str());
		} else {
			toConvert->type = WEAPON;
			printf("Set to weapon type but did not set subtype for %s:%s\n", toConvert->info.str(), toConvert->name);
		}
				
	} else if(toConvert->type == ARMOR) {
		// Convert old armor
		
		// Rings
		if(strcasestr(toConvert->name, "ring") || toConvert->wearflag == FINGER) {
			newType = "ring";
		}
		// Shields
		else if(strcasestr(toConvert->name, "shield") || strcasestr(toConvert->name, "buckler ") || toConvert->wearflag == SHIELD) {
			newType = "shield";
		}
		else if(strcasestr(toConvert->name, "plate") && !toConvert->flagIsSet(O_LIGHT_ARMOR)) {
			newType = "plate";
		}
		// If it's light armor, it's leather
		else if(toConvert->flagIsSet(O_LIGHT_ARMOR)
			|| ((toConvert->flagIsSet(O_SEL_ASSASSIN) || toConvert->flagIsSet(O_SEL_THIEF) || toConvert->flagIsSet(O_SEL_ROGUE)
			|| toConvert->flagIsSet(O_SEL_VAMPIRE) || toConvert->flagIsSet(O_SEL_DRUID) 
			|| toConvert->flagIsSet(O_SEL_CLERIC)) &&  !toConvert->flagIsSet(O_CSEL_INVERT)) ) {
			newType = "leather";
		} 
		// If a mage/lich can use it, it's cloth
		else if((!toConvert->flagIsSet(O_NO_MAGE) && !toConvert->flagIsSet(O_LIGHT_ARMOR)) ||				
				((toConvert->flagIsSet(O_SEL_MAGE) || toConvert->flagIsSet(O_SEL_LICH)) && !toConvert->flagIsSet(O_CSEL_INVERT))) {
			newType = "cloth";
		} 
		// Otherwise if it has 'chain' or 'scale' in it's name..it's chain
		else if(strcasestr(toConvert->name, "chain") || strcasestr(toConvert->name, "scale")){
			newType = "chain";
		} 
		// Last case, plate
		else {
			newType = "plate";
		}
		toConvert->clearFlag(O_LIGHT_ARMOR);
		toConvert->setArmorType(newType);
		toConvert->getArmor() = (int)((float)toConvert->getArmor() * 4.4);
		printf("Converted Armor %s:%s to (%s) New Amror: %d.\n", toConvert->info.str(), toConvert->name, newType.c_str(), toConvert->getArmor());
		
		
		
	}
	
	// Handle objects inside
	otag *ot;
	ot = toConvert->first_obj;
	Object *obj;
	while(ot) {
		obj = ot->obj;
		convertObject(obj);
		ot = ot->next_tag;
	}
}

void convertMonster(Creature* toConvert) {
	Monster* mTarget = toConvert->getMonster();
	Player* pTarget = toConvert->getPlayer();
	
	if(pTarget) {
		pTarget->addSkill("defense", (pTarget->getLevel() - 1) * 10);
		// Give out parry & block
		switch(pTarget->getClass()) {
		// These classes get block + parry
			case ASSASSIN:
			case BARD:
			case FIGHTER:
			case RANGER:
			case ROGUE:
			case PALADIN:
			case DEATHKNIGHT:
				pTarget->addSkill("block", (pTarget->getLevel()-1)*10);
				// fall through for parry
			case THIEF:
				pTarget->addSkill("parry", (pTarget->getLevel()-1)*10);
				break;
			case BERSERKER:
				pTarget->addSkill("block", (pTarget->getLevel()-1)*10);
				// Zerkers are more brute force than finnese...no parry
				break;
			default:
				break;
		}
		// Give out armor skills here
		switch(pTarget->getClass()) {
			case BARD:
			case BERSERKER:
			case FIGHTER:
			case PALADIN:
			case DEATHKNIGHT:
			case RANGER:
				pTarget->addSkill("plate", (pTarget->getLevel()-1)*10);
				pTarget->addSkill("chain", (pTarget->getLevel()-1)*10);
			case ASSASSIN:
			case THIEF:
			case ROGUE:
			case VAMPIRE:
			case DRUID:
			case CLERIC:
				pTarget->addSkill("leather", (pTarget->getLevel()-1)*10);
			case MAGE:
			case MONK:
			case LICH:
			case WEREWOLF:
			default:
				pTarget->addSkill("cloth", (pTarget->getLevel()-1)*10);
				break;
		}
		// A few clerics get plate
		if(pTarget->getClass() == CLERIC && !pTarget->getSecondClass() &&
		  (pTarget->getDeity() == ENOCH || pTarget->getDeity() == ARES || pTarget->getDeity() == GRADIUS)) {
			pTarget->addSkill("plate", (pTarget->getLevel()-1)*10);
			pTarget->addSkill("chain", (pTarget->getLevel()-1)*10);
		}
			
		
		
		
		// Now do weapon skills
		// Monks only get bare-hand, wolves only get claw
		if(pTarget->getClass() == MONK) {
			// Monks will get a quest to learn staffs
			pTarget->addSkill("bare-hand", (pTarget->getLevel()-1)*10);
		} else if(pTarget->getClass() == WEREWOLF) {
			pTarget->addSkill("claw", (pTarget->getLevel()-1)*10);
		} else {
			int numWeapons = 0;
			// Everyone gets bare-handed, but at a low level
			pTarget->addSkill("bare-hand", ((pTarget->getLevel()-1)*10)/2);
			// Everyone gets a new weapon skill every title
			numWeapons = (int)((pTarget->getLevel()+2)/3);
			switch(pTarget->getClass()) {
				case FIGHTER:
					if(!pTarget->getSecondClass()) {
						numWeapons += 1 + (int)(pTarget->getLevel()/4);
					} else {
						// Mutli fighters get weapon skills like other fighting classes
						numWeapons += (int)(pTarget->getLevel()/8);
					}
					break;
				case BERSERKER:
					numWeapons += (int)(pTarget->getLevel()/6);
					break;
				case THIEF:
				case RANGER:
				case ROGUE:
				case BARD:
				case PALADIN:
				case DEATHKNIGHT:
				case ASSASSIN:
					numWeapons += (int)(pTarget->getLevel()/8);
					break;
				case CLERIC:
				case DRUID:
				case VAMPIRE:
					if(pTarget->getSecondClass()) {
						// Cle/Ass
						numWeapons += (int)(pTarget->getLevel()/8);
					} else {
						numWeapons += (int)(pTarget->getLevel()/12);
					}
					break;
				case MAGE:
					if(pTarget->getSecondClass()) {
						numWeapons += (int)(pTarget->getLevel()/12);
					}
					break;
				case DUNGEONMASTER:
				case CARETAKER:
					numWeapons = 0;
					break;
				case LICH:
				default:
					break;
				
			}
			
			pTarget->getWeaponTrains() = numWeapons;
		}
	} else {
		mTarget->setDefenseSkill(((mTarget->getLevel()-1) * 10) + 5);
		mTarget->setWeaponSkill(((mTarget->getLevel()-1) * 10) + 5);
		mTarget->clearFlag(OLD_M_HIRE_FLAG);
		mTarget->clearFlag(OLD_M_CAN_HIRE);
		mTarget->clearFlag(OLD_M_EXPIRES);
		
		
		switch(mtarget->getClass()) {
			case FIGHTER:
			case DUNGEONMASTER:
				mTarget->setAttackPowermTarget->strength.getCur() * 2) + (mTarget->getLevel() * 6);
				break;
			case BERSERKER:
				mTarget->setAttackPower(mTarget->strength.getCur() * 2) + (mTarget->getLevel() * 6);
				break;
			case PALADIN:
			case DEATHKNIGHT:
			case BARD:
			case WEREWOLF:
			case VAMPIRE:
				mTarget->setAttackPower(mTarget->strength.getCur() * 2) + (mTarget->getLevel() * 4);
				break;
			case RANGER:
			case THIEF:
			case ASSASSIN:
			case ROGUE:
			case MONK:
				mTarget->setAttackPower(mTarget->strength.getCur() + mTarget->dexterity.getCur() + (mTarget->getLevel() * 4));
				break;
			case CLERIC:
				mTarget->setAttackPower(mTarget->strength.getCur() + (mTarget->getLevel() * 2));
				break;
			case LICH:
			case MAGE:
			default:
				mTarget->setAttackPower(mTarget->strength.getCur());
				break;
		}

	}
	
	otag *ot;
	ot = toConvert->first_obj;
	Object *obj;
	// Inventory
	while(ot) {
		obj = ot->obj;
		convertObject(obj);
		ot = ot->next_tag;
	}
	
}

void convertRoom(Room* toConvert) {
	// Rather than worrying about the old versions of monsters, just clear out the room
	// and let perms respawn
	
	// NOTE: Yes...I know this will leak memory, but I simply don't care on a one
	// time run program...it shouldn't be too much as to crash us.

	otag *ot;
	ot = toConvert->first_obj;
	Object *obj;
	while(ot) {
		obj = ot->obj;
		convertObject(obj);
		ot = ot->next_tag;
	}
	
}