inline
void cGrannyLoader::InsertAnimset(TiXmlElement *set_node)
{
	if (!set_node) return;

	XML::Node value;
	cAnimSet * animset = new cAnimSet;
	value = set_node->FirstChildElement("ID");
	animset->id = value.asInteger();

	if (value = set_node->FirstChildElement("DEFAULTANIM")) 
	{
		animset->defaultanim = mulpath + to_lower(value.asString());

		// animtype 을 anim_typeid 로 변경
		int anim_typeid = TypeData::GetAnimType("default.animation");

		if (anim_typeid != -1) 
			animset->anim_names.insert(make_pair(anim_typeid, animset->defaultanim));
	}


	TiXmlElement *anim_node = set_node->FirstChildElement("ANIMATION");
	while (anim_node) 
	{
		std::string animtype = "", filename = "";
		if (value = anim_node->FirstChildElement("TYPE"))
			animtype = value.asString();
		if ((value = anim_node->FirstChildElement("FILE")))
			filename = mulpath + to_lower(value.asString());

		// animtype 을 anim_typeid 로 변경
		int anim_typeid = TypeData::GetAnimType(animtype);

		if (anim_typeid != -1) 
			animset->anim_names.insert(make_pair(anim_typeid, filename));

		anim_node = anim_node->NextSiblingElement("ANIMATION");
	}

	m_animsets.insert(make_pair(animset->id, animset));
}
bool cGrannyLoader::Load(std::string filename, std::string mulpath)
{
	tick = 0;

	XML::Parser parser;
	XML::Node *granny=NULL, *document=NULL;

	try
	{
		parser.loadData(filename);
		document = parser.parseDocument();

		granny = document->findNode( "GRANNY" );

		if( !granny )
			throw "Couldn't find granny node.";
	}
	catch( ... )
	{
		pDebug.Log ("Couldn't load Granny Definitions");
		return false;
	}

	XML::Node value;

	TiXmlNode *tgranny  = granny->getTinyNode();


	bool ext = false;
	std::string texpath, smdpath;

	if (value = tgranny->FirstChildElement("TEXTUREPATH"))
		texpath = value.asString();

	if (value = tgranny->FirstChildElement("SMDPATH"))
		smdpath = value.asString();

	if (smdpath==".") 
	{
		CString strPath = CFileString::GetModuleDir()+"/";
		strPath.Replace('\\','/');
		mulpath = strPath;
	}
	else if (!smdpath.empty())
	{
		mulpath = smdpath;
	}

	this->mulpath = mulpath;

	if (texpath.find(":/") != std::string::npos || texpath.find(":\\") != std::string::npos)
		tex_basepath = texpath;
	else
		tex_basepath = mulpath + texpath;

	assert(!pGrannyTextureLoader);
	pGrannyTextureLoader = new cGrannyTextureLoader(tex_basepath);

	TiXmlHandle hgranny(granny->getTinyNode());

#if 0
	TiXmlElement *set_node = hgranny.FirstChild("ANIMSET_LIST").FirstChild("ANIMSET").Element();

	while (set_node) 
	{
		InsertAnimset(set_node);

		set_node = set_node->NextSiblingElement(set_node->Value());
	}

	TiXmlElement *char_node = hgranny.FirstChild("CHARACTER_AOS_LIST").FirstChild("CHARACTER_AOS").Element();
	while (char_node) 
	{
		InsertCharacterAOS(char_node);
		
		char_node = char_node->NextSiblingElement(char_node->Value());
	}

	char_node = hgranny.FirstChild("CHARACTER_LIST").FirstChild("CHARACTER").Element();
	while (char_node) 
	{
		InsertCharacter(char_node);
		
		char_node = char_node->NextSiblingElement(char_node->Value());
	}
#else
	TiXmlElement *anim_node = tgranny->FirstChildElement("ANIMSET");
	while (anim_node) 
	{
		InsertAnimset(anim_node);
		anim_node = anim_node->NextSiblingElement("ANIMSET");
	}
	
	TiXmlElement * char_node = tgranny->FirstChildElement();
	while (char_node) 
	{
		if (char_node->ValueStr()=="CHARACTER")
			InsertCharacter(char_node);
		else if (char_node->ValueStr()=="CHARACTER_AOS")
			InsertCharacterAOS(char_node);
		
		char_node = char_node->NextSiblingElement();
	}
#endif
	

	delete document;

	return true;
}
inline
void cGrannyLoader::InsertCharacterAOS(TiXmlElement *char_node)
{
	if (!char_node) return;

	XML::Node value;

	std::string filename, default_anim, desc;
	int animset = -1;

	int left_hand_bone = -1;
	int right_hand_bone = -1;
	int hand = HAND_NONE;

	value = char_node->FirstChildElement("ID");
	Uint32 id = value.asInteger();
	if (value = char_node->FirstChildElement("ANIMSET"))
		animset = value.asInteger();

	if (value = char_node->FirstChildElement ("LEFT_HAND_BONE"))
	{
		left_hand_bone = value.asInteger ();
		hand = HAND_OWNER;
	}
	if (value = char_node->FirstChildElement ("RIGHT_HAND_BONE"))
	{
		right_hand_bone = value.asInteger ();
		hand = HAND_OWNER;
	}

	if (value = char_node->FirstChildElement("DESCRIPTION"))
		desc = value.asString();

	Uint16 assign = 0;
	if (value = char_node->FirstChildElement("ASSIGN"))
		assign = value.asInteger();
	id |= assign << 16;

	map <int, cAnimSet *>::iterator iter;
	map <int, string>::iterator name_iter;


	iter = m_animsets.find(animset);

	if (id && (iter != m_animsets.end())) 
	{
		assert(iter->second);
		cGrannyModelAOS * model = new cGrannyModelAOS (tex_basepath, iter->second->defaultanim);
		model->SetHandBones (left_hand_bone, right_hand_bone);
		model->SetHand (hand);
		model->SetAnimset (animset);
		model->desc = desc;

		// HARKON : bodypart is freed by loader
		model->setFreeBodyParts(false);

		for(int i = 0; AOSBodyInfo[i].id != 0; i++) 
		{
			const AOSBodyData& Data = AOSBodyInfo[i];
			TiXmlElement *submodel = char_node->FirstChildElement(Data.name);
			if (submodel) 
			{
				cGrannyModel *m = model->AddModel(Data.id, mulpath + to_lower(submodel->GetText()));
				UINT id2 = 0xC000 | id << 4 | Data.id;
				models.insert(make_pair(id2, m));
			}
		}

		for (name_iter=iter->second->anim_names.begin(); name_iter!=iter->second->anim_names.end();name_iter++)
		{ 
			model->AddAnimation(name_iter->first, name_iter->second);
		}
		//models.erase(id);
		if (models.find(id)!=models.end()) 
		{
			pDebug.Log("Warning: duplicated model id : %d\n", id);
			delete models.find(id)->second;
			models.erase(id);
		}
		models.insert(make_pair(id, model));

	} 
	else 
	{
		pDebug.Log ("Warning: Invalid Granny AOS Definition");
	}
}
inline
void cGrannyLoader::InsertCharacter(TiXmlElement *char_node)
{
	if (!char_node) return;

	XML::Node value;
	std::string filename = "", default_anim = "", prefix = "", desc;
	int left_hand_bone = -1;
	int right_hand_bone = -1;
	int animset = -1;
	int hand = HAND_NONE;

	value = char_node->FirstChildElement("ID");
	Uint32 id = (value != NULL) ? value.asInteger() : 0;

	if (value = char_node->FirstChildElement("FILE")) 
		filename = mulpath + to_lower(value.asString());

	if (value = char_node->FirstChildElement("ANIMSET"))
		animset = value.asInteger();
	if (value = char_node->FirstChildElement("PREFIX"))
		prefix = to_lower(value.asString());

	if (value = char_node->FirstChildElement("LEFT_HAND_BONE")) 
	{
		left_hand_bone = value.asInteger();
		hand = HAND_OWNER;
	}
	if (value = char_node->FirstChildElement("RIGHT_HAND_BONE")) 
	{
		right_hand_bone = value.asInteger();
		hand = HAND_OWNER;
	}

	if (value = char_node->FirstChildElement("HAND")) 
	{
		if (value.asString () == "left")
			hand = HAND_LEFT;
		if (value.asString () == "right")
			hand = HAND_RIGHT;
	}

	if (value = char_node->FirstChildElement("DESCRIPTION"))
		desc = value.asString();

	Uint16 assign = 0;
	if (value = char_node->FirstChildElement("ASSIGN"))
		assign = value.asInteger();
	id |= assign << 16;

	// humonoid, monster can hold weapons.
	if (assign == 0 && (animset <= 1 || animset == 3)) 
		hand = HAND_OWNER; 

	map <int, cAnimSet *>::iterator iter;
	map <int, string>::iterator name_iter;

	iter = m_animsets.find(animset);

	if (id && (iter != m_animsets.end())) 
	{
		assert(iter->second);
		cGrannyModel * model = new cGrannyModelTD (filename, tex_basepath, iter->second->defaultanim, prefix);
		model->SetHandBones(left_hand_bone, right_hand_bone);
		model->SetHand(hand);
		model->desc = desc;

		model->SetAnimset (animset);

		for (name_iter=iter->second->anim_names.begin(); name_iter!=iter->second->anim_names.end();name_iter++)
		{
			model->AddAnimation(name_iter->first, name_iter->second);
		}

		//models.erase(id);
		if (models.find(id)!=models.end()) 
		{
			pDebug.Log("Warning: duplicated model id : %d", id);
			delete models.find(id)->second;
			models.erase(id);
		}
		models.insert(make_pair(id, model));
	} 
	else 
	{
		pDebug.Log ("Warning: Invalid Granny Definition");
	}
}
Example #5
0
cGrannyLoader::cGrannyLoader( string filename, string mulpath )
{
	this->mulpath = mulpath;
	tick = 0;

	XML::Parser parser;
	XML::Node *granny, *document;

	try
	{
		parser.loadData( filename );
		document = parser.parseDocument();

		granny = document->findNode( "GRANNY" );

		if ( !granny )
		{
			throw "Couldn't find granny node.";
		}
	}
	catch (...)
	{
		Logger::WriteLine( "Couldn't load Granny Definitions" );
		return;
	}

	XML::Node *char_node, *set_node, *value;

	if ( (value = granny->findNode( "TEXTUREPATH" ) ) )
	{
		tex_basepath = mulpath + value->asString();
	}

	assert( !pGrannyTextureLoader );
	pGrannyTextureLoader = new cGrannyTextureLoader( tex_basepath );

	std::map<int, cAnimSet *> animsets;
	std::map<int, cAnimSet *>::iterator iter;
	std::map<int, string>::iterator name_iter;


	int idx = 0;
	while ( (set_node = granny->findNode("ANIMSET", idx)) )
	{
		cAnimSet *animset = new cAnimSet();
		value = set_node->findNode( "ID" );
		animset->id = (value != NULL) ? value->asInteger() : 0;
		if ( ( value = set_node->findNode( "DEFAULTANIM" )) )
		{
			animset->defaultanim = mulpath + to_lower( value->asString() );
		}

		int idx2 = 0;
		XML::Node *anim_node;
		while ( (anim_node = set_node->findNode( "ANIMATION", idx2 )) )
		{
			std::string animtype = "", filename = "";
			if ( (value = anim_node->findNode( "TYPE" )) )
			{
				animtype = value->asString();
			}
			if ( (value = anim_node->findNode ("FILE")) )
			{
				filename = mulpath + to_lower( value->asString() );
			}

			int anim_typeid = -1;
			for ( int i = 0; TypeInfo[i].blockid != -1; i++ )
			{
				const TypeData &Data = TypeInfo[i];
				if ( Data.name == animtype )
				{
					anim_typeid = Data.blockid;
				}
			}

			if ( anim_typeid != -1 )
			{
				animset->anim_names.insert( std::make_pair( anim_typeid, filename ) );
			}

			idx2++;
		}

		//animsets.erase(animset->id);
		animsets.insert( std::make_pair( animset->id, animset ) );

		idx++;
	}

	idx = 0;
	while ((char_node = granny->findNode ("CHARACTER", idx)))
	{
		std::string filename = "", default_anim = "", prefix = "";
		int left_hand_bone = -1;
		int right_hand_bone = -1;
		int animset = -1;
		int hand = HAND_NONE;

		value = char_node->findNode ("ID");
		Uint32 id = (value != NULL) ? value->asInteger () : 0;
		if ((value = char_node->findNode ("FILE")))
			filename = mulpath + to_lower (value->asString ());
		if ((value = char_node->findNode ("ANIMSET")))
			animset = value->asInteger ();
		if ((value = char_node->findNode ("PREFIX")))
			prefix = to_lower (value->asString ());

		if ((value = char_node->findNode ("LEFT_HAND_BONE")))
		{
			left_hand_bone = value->asInteger ();
			hand = HAND_OWNER;
		}
		if ((value = char_node->findNode ("RIGHT_HAND_BONE")))
		{
			right_hand_bone = value->asInteger ();
			hand = HAND_OWNER;
		}

		if ((value = char_node->findNode ("HAND")))
		{
			if (value->asString () == "left")
				hand = HAND_LEFT;
			if (value->asString () == "right")
				hand = HAND_RIGHT;
		}

		Uint16 assign = 0;
		if ((value = char_node->findNode ("ASSIGN")))
			assign = value->asInteger ();

		//SiENcE: if female id-1000, to show female clothes
		// (i dont know why it needs a subtract of 1000!, ids are correct)
		//if (assign == 401) id=id-1000;

		//HARKON: recevied clothes id is equals male/female(runuo 1.0). but weapon isn't equals.
		// examples, ganny_aos.xml male kilt id is 455, female kilt id is 1455. server only sends 455.
		if (assign == 401 && hand == HAND_NONE) id -= 1000;

		id |= assign << 16;      
		iter = animsets.find (animset);

		if (id && (iter != animsets.end ()))
		{
			assert (iter->second);
			cGrannyModel *model = new cGrannyModelTD( filename, tex_basepath, iter->second->defaultanim, prefix );
			model->SetHandBones( left_hand_bone, right_hand_bone );
			model->SetHand( hand );
			model->SetAnimset( animset );
			for ( name_iter=iter->second->anim_names.begin(); name_iter != iter->second->anim_names.end(); name_iter++ )
			{
				model->AddAnimation( name_iter->first, name_iter->second );
			}

			//models.erase(id);
			if ( models.find( id ) != models.end() )
			{
				//Logger::WriteLine("Warning: duplicated model id : %d", id);
				SAFE_DELETE( models.find( id )->second );
				models.erase( id );
			}
			models.insert( make_pair( id, model ) );
		}
		else
		{
			Logger::WriteLine ("Warning: Invalid Granny Definition");
		}

		idx++;
	}

	idx = 0;
	while ((char_node = granny->findNode ("CHARACTER_AOS", idx)))
	{
		std::string filename = "", default_anim = "";
		int animset = -1;

		int left_hand_bone = -1;
		int right_hand_bone = -1;
		int hand = HAND_NONE;

		value = char_node->findNode ("ID");
		Uint32 id = (value != NULL) ? value->asInteger () : 0;
		if ((value = char_node->findNode ("ANIMSET")))
			animset = value->asInteger ();

		if ((value = char_node->findNode ("LEFT_HAND_BONE")))
		{
			left_hand_bone = value->asInteger ();
			hand = HAND_OWNER;
		}
		if ((value = char_node->findNode ("RIGHT_HAND_BONE")))
		{
			right_hand_bone = value->asInteger ();
			hand = HAND_OWNER;
		}

		Uint16 assign = 0;
		if ((value = char_node->findNode ("ASSIGN")))
			assign = value->asInteger ();
		id |= assign << 16;

		iter = animsets.find (animset);

		if ( id && ( iter != animsets.end() ) )
		{
			assert (iter->second);
			cGrannyModelAOS *model = new cGrannyModelAOS (tex_basepath, iter->second->defaultanim);

			model->SetHandBones (left_hand_bone, right_hand_bone);
			model->SetHand (hand);

			model->SetAnimset (animset);
			for (int i = 0; AOSBodyInfo[i].id != 0; i++)
			{
				const AOSBodyData &Data = AOSBodyInfo[i];
				XML::Node *submodel = char_node->findNode (Data.name);
				if ( submodel )
				{
					model->AddModel( i, mulpath + to_lower( submodel->asString() ) );
				}
			}

			for ( name_iter = iter->second->anim_names.begin(); name_iter != iter->second->anim_names.end(); name_iter++ )
			{
				model->AddAnimation( name_iter->first, name_iter->second );
			}

			//models.erase(id);
			if ( models.find( id ) != models.end() )
			{
				//Logger::WriteLine("Warning: duplicated model id : %d\n", id);
				SAFE_DELETE( models.find( id )->second );
				models.erase( id );
			}
			models.insert( std::make_pair( id, model ) );

		}
		else
		{
			Logger::WriteLine ("Warning: Invalid Granny AOS Definition");
		}

		idx++;
	}

	for ( iter = animsets.begin(); iter != animsets.end(); iter++ )
	{
		SAFE_DELETE( iter->second );
	}
	animsets.clear();

	//delete document;
}
Example #6
0
bool Config::Init()
{
	// Default values, if they are not set under config.xml those will be used.
	// Section GFX
	m_vParserInfo.push_back( ParserData( "GFX", IS_SECTION, NULL ) );
	m_vParserInfo.push_back( ParserData( "WIDTH", IS_INTEGER, &m_iWidth ) );
	m_vParserInfo.push_back( ParserData( "HEIGHT", IS_INTEGER, &m_iHeight ) );
	m_vParserInfo.push_back( ParserData( "BPP", IS_INTEGER, &m_iBPP ) );
	m_vParserInfo.push_back( ParserData( "CURSOR", IS_INTEGER, &m_iCursor ) );
	m_vParserInfo.push_back( ParserData( "PERSPECTIVE", IS_INTEGER, &m_iPerspective ) );
	m_vParserInfo.push_back( ParserData( "FULLSCREEN", IS_INTEGER, &m_iStartFullScreen ) );
	m_vParserInfo.push_back( ParserData( "ROOF_FADE_TIME", IS_INTEGER, &m_iRoofFadeTime ) );
	m_vParserInfo.push_back( ParserData( "ROOF_FADE_ALPHA", IS_INTEGER, &m_iRoofFadeAlpha ) );
	m_vParserInfo.push_back( ParserData( "ZBUFFER_SIZE", IS_INTEGER, &m_iDepthBuffer ) );
	m_vParserInfo.push_back( ParserData( "MAXZOOM", IS_INTEGER, &m_iMaxZoom ) );
	m_vParserInfo.push_back( ParserData( "MAXANGLE", IS_INTEGER, &m_iMaxAngle ) );
	m_vParserInfo.push_back( ParserData( "VIEWDISTANCE", IS_INTEGER, &m_iViewDistance ) );
	m_vParserInfo.push_back( ParserData( "BRIGHTNESS", IS_INTEGER, &m_iBrightness ) );

	// Section UO
	m_vParserInfo.push_back( ParserData( "UO", IS_SECTION, NULL ) );
	m_vParserInfo.push_back( ParserData( "STARTX", IS_INTEGER, &m_iStartX ) );
	m_vParserInfo.push_back( ParserData( "STARTY", IS_INTEGER, &m_iStartY ) );
	m_vParserInfo.push_back( ParserData( "STARTZ", IS_INTEGER, &m_iStartZ ) );
	m_vParserInfo.push_back( ParserData( "MULPATH", IS_STRING, &m_sMulPath ) );
	// m_vParserInfo.push_back( ParserData( "COMPRESSED_MAP", IS_STRING, &m_sCompressedMap ) );
	m_vParserInfo.push_back( ParserData( "POPUP_MENU", IS_INTEGER, &m_iPopup ) );
	m_vParserInfo.push_back( ParserData( "AOS", IS_INTEGER, &m_iAOSToolTips ) );
	m_vParserInfo.push_back( ParserData( "CLIENT_IDENTIFICATION", IS_STRING, &m_sClientVersion ) );
	m_vParserInfo.push_back( ParserData( "USE_CLILOCS", IS_INTEGER, &m_iClilocs ) );
	m_vParserInfo.push_back( ParserData( "CLILOC_LANGUAGE", IS_STRING, &m_sClilocLang ) );
	m_vParserInfo.push_back( ParserData( "SPEECH_HUE", IS_INTEGER, &m_iSpeechHue ) );
	m_vParserInfo.push_back( ParserData( "AOSTOOLTIPS", IS_INTEGER, &m_iAOSToolTips ) );
    //Artix added speech.mul config option
    m_vParserInfo.push_back( ParserData( "USE_SPEECH", IS_INTEGER, &m_iSpeech ) );
	// Section NET
	m_vParserInfo.push_back( ParserData( "NET", IS_SECTION, NULL ) );
	m_vParserInfo.push_back( ParserData( "PORT", IS_INTEGER, &m_iServerPort ) );
	m_vParserInfo.push_back( ParserData( "SERVER", IS_STRING, &m_sServer ) );
	m_vParserInfo.push_back( ParserData( "LOGIN", IS_STRING, &m_sLogin ) );
	m_vParserInfo.push_back( ParserData( "PASSWORD", IS_STRING, &m_sPassword ) );
	m_vParserInfo.push_back( ParserData( "IS_SPHERE", IS_INTEGER, &m_iIsSphere ) );
	m_vParserInfo.push_back( ParserData( "IS_SPHERE55R", IS_INTEGER, &m_iIsSphere55R ) );
	m_vParserInfo.push_back( ParserData( "IS_POL", IS_INTEGER, &m_iIsPol ) );
	m_vParserInfo.push_back( ParserData( "IS_RUNUO", IS_INTEGER, &m_iIsRunUO ) );
	m_vParserInfo.push_back( ParserData( "IS_UOX3", IS_INTEGER, &m_iIsUox3 ) );
	m_vParserInfo.push_back( ParserData( "CLIENT_KEY", IS_INTEGER, &m_iClientKey ) );

	// Section Sound
	m_vParserInfo.push_back( ParserData( "SOUND", IS_SECTION, NULL ) );
	m_vParserInfo.push_back( ParserData( "MUSIC", IS_INTEGER, &m_iMusic ) );
	m_vParserInfo.push_back( ParserData( "SOUND", IS_INTEGER, &m_iSound ) );
	m_vParserInfo.push_back( ParserData( "FREQUENCY", IS_INTEGER, &m_iFrequency ) );
	m_vParserInfo.push_back( ParserData( "STEREO", IS_INTEGER, &m_iStereo ) );
	m_vParserInfo.push_back( ParserData( "CHUNKSIZE", IS_INTEGER, &m_iChunkSize ) );
	m_vParserInfo.push_back( ParserData( "MUSICVOLUME", IS_INTEGER, &m_iMusicVolume ) );
	m_vParserInfo.push_back( ParserData( "SOUNDVOLUME", IS_INTEGER, &m_iSoundVolume ) );
	m_vParserInfo.push_back( ParserData( "MP3", IS_INTEGER, &m_iMP3 ) );
	m_vParserInfo.push_back( ParserData( "FOOTSTEPS", IS_INTEGER, &m_iFootSteps ) );

	// Section Iris Client
	m_vParserInfo.push_back( ParserData( "IRIS", IS_SECTION, NULL ) );
	m_vParserInfo.push_back( ParserData( "SCRIPTS_PATH", IS_STRING, &m_sScriptPath ) );
	m_vParserInfo.push_back( ParserData( "MOUSEOVER_TIMER", IS_INTEGER, &m_iMouseMotionTimer ) );
	m_vParserInfo.push_back( ParserData( "", IS_END, NULL ) );


	// After adding to the vector our struct start filling it with actual values
	XML::Parser kParser;

	kParser.loadData( "./xml/config.xml" );
	XML::Node *kDocument = kParser.parseDocument();
	XML::Node *kConfig = kDocument->findNode( "CONFIG" );

	if ( !kConfig )
	{
		THROWEXCEPTION( "Could not find configuration node." );

		return false;
	}

	XML::Node *kValue = NULL, *kSection = NULL;
	// Read all values from config.xml
	for ( int i = 0; m_vParserInfo[i].iType != IS_END; i++ )
	{
		const ParserData &Data = m_vParserInfo[i];

		if ( Data.iType == IS_SECTION )
		{
			kSection = kConfig->findNode( Data.sName );
		}
		else
		{
			// If no section is loaded get from <config>
			kValue = kSection != NULL ? kSection->findNode( Data.sName ) : kConfig->findNode( Data.sName );

			if ( kValue != NULL )
			{
				if ( Data.iType == IS_BOOL )
				{
					*reinterpret_cast<bool *>( Data.pData ) = kValue->asBool();
				}
				else if ( Data.iType == IS_INTEGER )
				{
					*reinterpret_cast<int *>( Data.pData ) = kValue->asInteger();
				}
				else if ( Data.iType == IS_STRING )
				{
					*reinterpret_cast<std::string *>( Data.pData ) = kValue->asString();
				}
			}
		}
	}


	// Read Fonts bit of the file
	XML::Node *kFontSet = kConfig->findNode( "FONTSET" );

	if ( kFontSet )
	{
		int idx = 0;
		XML::Node *kFontNode = NULL;
		FontInfo kFontInfo;

		while ( ( kFontNode = kFontSet->findNode( "FONT", idx++ ) ) )
		{
			if ( !kFontNode->lookupAttribute( "ID", kFontInfo.iId ) )
			{
				continue;
			}

			if ( !kFontNode->lookupAttribute( "FILE", kFontInfo.sFileName ) )
			{
				continue;
			}

			if ( !kFontNode->lookupAttribute( "NAME", kFontInfo.sFontName ) )
			{
				continue;
			}

			if ( !kFontNode->lookupAttribute( "SIZE", kFontInfo.iSize ) )
			{
				continue;
			}

			if ( !kFontNode->lookupAttribute( "HUE",  kFontInfo.iHue ) )
			{
				continue;
			}

			FontManager::GetInstance()->AddTTFFont( kFontInfo.iId, kFontInfo.sFileName, kFontInfo.sFontName, kFontInfo.iSize, kFontInfo.iHue );
		}
	}


	// Depth Buffer
	if ( m_iDepthBuffer <= 0 )
	{
		m_iDepthBuffer = 16;
	}

	// View Distance
	if ( m_iViewDistance < 3 )
	{
		m_iViewDistance = 3;
	}

	// Max Zoom
	if ( m_iMaxZoom <= 0 )
	{
		m_iMaxZoom = 0;
	}

	// Max Angle
	if ( m_iMaxAngle < 10 )
	{
		m_iMaxAngle = 10;
	}

	// Max Angle
	if ( m_iMaxAngle > 90 )
	{
		m_iMaxAngle = 90;
	}

	// Fix Mul path if no / at the end
	if ( m_sMulPath.size() )
	{
		char cLastChar = m_sMulPath[m_sMulPath.length() - 1];

		if ( ( cLastChar != '/' ) && ( cLastChar != '\\' ) )
		{
			m_sMulPath += "/";
		}
	}

	return true;
}