/////////////////////////////////////////////////////////////////////////////
//Stun
/////////////////////////////////////////////////////////////////////////////
StatusStun::StatusStun(const Id & owner, double delay)
: CreatureStatus(CRESTATUS_STUN, owner), m_parFX(0)
{
	TimeInit(&m_stunDelay, delay);

	string fxTxtFile = GAMEFOLDER;
	fxTxtFile += "\\";
	fxTxtFile += "Textures\\Particles\\star.tga";

	Creature *pCre = (Creature *)IDPageQuery(m_owner);

	if(pCre)
	{
		fxGlow_init fx;

		fx.glowTxt = TextureCreate(0, fxTxtFile.c_str(), false, 0);

		if(fx.glowTxt)
		{
			fx.r = fx.g = fx.b = 255;

			fx.scaleStart = 0; fx.scaleEnd = pCre->BoundGetRadius()*2;

			fx.delay = delay*0.125;

			fx.bRepeat = true;

			m_parFX = PARFXCreate(ePARFX_GLOW, &fx, -1, pCre->GetOBJ(), -1, 0);
		}
	}
}
AnimatedSprite* AnimatedSpriteCreate(SDL_Renderer* renderer, String* str, unsigned int numberx, unsigned int numbery, unsigned int animMode, unsigned int duration, int alpha)
{
	AnimatedSprite* spr;

	if(numberx == 0)
		numberx = 1;

	if(numbery == 0)
		numbery = 1;

	spr = (AnimatedSprite*) malloc(sizeof(AnimatedSprite));
	if(spr == NULL)
		printf( "Erreur (Fonction AnimatedSpriteCreate) : impossible d'allouer la memoire pour l'image animee \"%s\".\n", str->data);

	spr->texture = TextureCreate(renderer, str, T_RED, T_GREEN, T_BLUE, alpha);
	spr->currentPos = 0;
	spr->rectAnimation.x = 0;
	spr->rectAnimation.y = 0;
	spr->rectAnimation.w = spr->texture->w/numberx;
	spr->rectAnimation.h = spr->texture->h/numbery;
	spr->animMode = animMode;
	spr->autom = duration > 0 ? 1:0;
	spr->duration = duration;
	spr->direction = 1;

	if(numbery == 1 && numberx == 1)
		spr->autom = 0;
	spr->t0 = SDL_GetTicks();

	return spr;
}
/////////////////////////////////////
// Name:	StageSelectInit
// Purpose:	initialize the stage and
//			level lists, call this after
//			loading a profile
// Output:	stages initialized
// Return:	success if success
/////////////////////////////////////
PUBLIC RETCODE StageSelectInit(const char *levelFile, hCFG playerProfile)
{
	TataDisplayLoadText("Destroying Previous Stages...");
	StageSelectDestroy();

	hCFG stageCfg = CfgFileLoad(levelFile);

	int stage = 0;
	char stageStr[MAXCHARBUFF]={0}, mapImgPath[MAXCHARBUFF]={0};

	string txtFile;

	if(stageCfg)
	{
		//go find all the stages
		while(1)
		{
			sprintf(stageStr, "stage_%d", stage);

			if(CfgSectionExist(stageCfg, stageStr))
			{
				TataDisplayLoadText("Parsing Stage %d", stage);

				SelectStage newStage;

				//get map image file
				if(CfgGetItemStr(stageCfg, stageStr, "mapImage", mapImgPath))
				{
					txtFile = GAMEFOLDER;
					txtFile += "\\";
					txtFile += mapImgPath;

					newStage.mapImg = TextureCreate(0, txtFile.c_str(), false, 0);
				}
				else
					newStage.mapImg = 0;

				//determine if locked or unlocked
				if(playerProfile && CfgSectionExist(playerProfile, stageStr))
					newStage.type = ST_UNLOCK;
				else
					newStage.type = ST_LOCK;

				//load the items
				_StageSelectLoadItems(stageCfg, playerProfile, stageStr, &newStage);

				//add to global stages
				g_stages.push_back(newStage);

				stage++;
			}
			else
				break;
		}

		CfgFileDestroy(&stageCfg);
	}

	return RETCODE_SUCCESS;
}
Exemple #4
0
bool PicTryMakeTex(Pic *p)
{
	SDL_DestroyTexture(p->Tex);
	p->Tex = TextureCreate(
		gGraphicsDevice.gameWindow.renderer, SDL_TEXTUREACCESS_STATIC,
		p->size, SDL_BLENDMODE_NONE, 255);
	if (p->Tex == NULL)
	{
		LOG(LM_GFX, LL_ERROR, "cannot create texture: %s", SDL_GetError());
		return false;
	}
	if (SDL_UpdateTexture(
		p->Tex, NULL, p->Data, p->size.x * sizeof(Uint32)) != 0)
	{
		LOG(LM_GFX, LL_ERROR, "cannot update texture: %s", SDL_GetError());
		return false;
	}
	// Check for alpha pixels - if none we can get away with no blending
	bool hasAlpha = false;
	for (int i = 0; i < p->size.x * p->size.y; i++)
	{
		const Uint32 pixel = p->Data[i];
		color_t c;
		SDL_GetRGBA(pixel, gGraphicsDevice.Format, &c.r, &c.g, &c.b, &c.a);
		hasAlpha = hasAlpha || c.a < 255;
	}
	if (hasAlpha && SDL_SetTextureBlendMode(p->Tex, SDL_BLENDMODE_BLEND) != 0)
	{
		LOG(LM_GFX, LL_ERROR, "cannot set texture blend mode: %s",
			SDL_GetError());
		return false;
	}
	return true;
}
Exemple #5
0
TRenderEntity *RenderEntityCreate2D(const uint32 pWidth, const uint32 pHeight, const char *pFileName)
{
    TTexture *lTexture = TextureCreate(pFileName, false);
    if(lTexture==NULL)
        return NULL;
        
    TMaterial *lMaterial = MaterialCreate();
    MaterialAddTexture(lMaterial, lTexture);
        
    TGeom *lQuad = GeomCreateQuad(pWidth, pHeight);
    GeomSetMaterial(lQuad, lMaterial);
        
    TRenderEntity *this = RenderEntityCreate();
    RenderEntitySetGeometry(this, lQuad);
    RenderEntityMove2D(this, pWidth/2.0f, pHeight/2.0f);
    
    this->mWidth = pWidth;
    this->mHeight= pHeight;
        
    TextureDestroy(lTexture);
    MaterialDestroy(lMaterial);
    GeomDestroy(lQuad);
    
    CLASS_INSTANCE();
}
Exemple #6
0
TRenderEntity *RenderEntityCreateQuadTextured(const uint32 pSizeX, const uint32 pSizeY, const char *pFileName)
{
    TTexture *lTexture = TextureCreate(pFileName, false);
    if(lTexture==NULL)
        return NULL;
        
    TMaterial *lMaterial = MaterialCreate();
    MaterialAddTexture(lMaterial, lTexture);
        
    TGeom *lQuad = GeomCreateQuad(pSizeX, pSizeY);
    GeomSetMaterial(lQuad, lMaterial);
    
    GeomSetTexCoord(lQuad, 0, 0.0f, 0.0f);
	GeomSetTexCoord(lQuad, 1, 1.0f, 0.0f);
	GeomSetTexCoord(lQuad, 2, 1.0f, 1.0f);
	GeomSetTexCoord(lQuad, 3, 0.0f, 1.0f);
        
    TRenderEntity *this = RenderEntityCreate();
    RenderEntitySetGeometry(this, lQuad);
    
    TextureDestroy(lTexture);
    MaterialDestroy(lMaterial);
    GeomDestroy(lQuad);
    
    CLASS_INSTANCE();
}
RETCODE World::EntityLoad_Sign(hQBSP qbsp, const EntityParse & entityDat)
{
	hTXT txt;
	int r,g,b,a;

	//create new sign
	Sign *newObj = new Sign; assert(newObj);

	///////////////////////////////////////////////////////
	//load up the common stuff
	EntityLoad_CommonObject(qbsp, entityDat, dynamic_cast<Object *>(newObj));

	const char *pStr;

	///////////////////////////////////////////////////////
	//load image
	pStr = entityDat.GetVal("image");

	if(pStr)
	{
		string imgPath = GAMEFOLDER;
		imgPath += "\\";
		imgPath += pStr;

		txt = TextureCreate(0, imgPath.c_str(), false, 0);
	}

	///////////////////////////////////////////////////////
	//get color
	pStr = entityDat.GetVal("color");

	if(pStr)
	{
		sscanf(pStr, "%d %d %d %d", &r,&g,&b,&a);
	}

	if(txt)
	{
		float sX = (SCRN_W/2) - (TextureGetWidth(txt)/2);
		float sY = (SCRN_H/2) - (TextureGetHeight(txt)/2);
		float eX = sX + TextureGetWidth(txt);
		float eY = sY + TextureGetHeight(txt);

		sX /= SCRN_W; sY /= SCRN_H;
		eX /= SCRN_W; eY /= SCRN_H;

		newObj->SetImageDisplay(ImageDisplayAdd(txt, sX,sY,eX,eY, r,g,b,a));
		TextureDestroy(&txt);
	}

	return RETCODE_SUCCESS;
}
Exemple #8
0
TRenderEntity *RenderEntityCreateCubeTextured(const uint32 pSizeX, const uint32 pSizeY, const uint32 pSizeZ, const char *pFileName)
{
    TTexture *lTexture = TextureCreate(pFileName, false);
    if(lTexture==NULL)
        return NULL;
        
    TMaterial *lMaterial = MaterialCreate();
    MaterialAddTexture(lMaterial, lTexture);
        
    TGeom *lCube = GeomCreateCube(pSizeX, pSizeY, pSizeZ);
    GeomSetMaterial(lCube, lMaterial);
        
    TRenderEntity *this = RenderEntityCreate();
    RenderEntitySetGeometry(this, lCube);
    
    TextureDestroy(lTexture);
    MaterialDestroy(lMaterial);
    GeomDestroy(lCube);
    
    CLASS_INSTANCE();
}
/////////////////////////////////////
// Name:	TextureSearch
// Purpose:	load image/texture via 
//			list file with ID
//			NOTE: This will first find
//			the ID from the texture
//			list.
// Output:	add texture to list if not
//			yet done
// Return:	the texture
/////////////////////////////////////
PUBLIC hTXT TextureSearch(unsigned int ID)
{
	//first, check to see if image already exist
	hTXT texture=_TextureSearchList(ID);

	if(!texture) //search through the file
	{
		char txtFName[MAXCHARBUFF];
		unsigned int txtID, clrKey, r=0, g=0, b=0;

		//load up file
		FILE *fp = fopen(g_TXTLISTFILE, "rt");

		if(!fp)
			return 0;

		while(!feof(fp))
		{
			fscanf(fp, "%d %s %d", &txtID, txtFName, &clrKey);

			if(clrKey == 1)
				fscanf(fp, "%d,%d,%d", &r, &g, &b);
			else
				fscanf(fp, "\n");

			if(txtID == ID) //does it match???
			{
				//load this puppy up!
				texture = TextureCreate(ID, txtFName, clrKey == 1 ? true : false, D3DCOLOR_XRGB(r,g,b));
				break;
			}
		}

		fclose(fp);
	}
	else
		TextureAddRef(texture);

	return texture;
}
int ShroomShooter::Callback(unsigned int msg, unsigned int wParam, int lParam)
{
	switch(msg)
	{
	case ENTITYMSG_CFGLOAD:
		{
			char buff[MAXCHARBUFF]={0};
			hCFG cfg = (hCFG)wParam;

			//Load the model for spit
			if(CfgGetItemStr(cfg, "special", "attackModel", buff))
			{
				string mdlPath = GAMEFOLDER;
				mdlPath += "\\";
				mdlPath += buff;

				m_spitMdl = MDLCreate(0, mdlPath.c_str());
			}

			//Load the texture for spit trails
			if(CfgGetItemStr(cfg, "special", "attackTrail", buff))
			{
				string txtPath = GAMEFOLDER;
				txtPath += "\\";
				txtPath += buff;

				m_spitFXTxt = TextureCreate(0, txtPath.c_str(), false, 0);
			}

			//load color
			if(CfgGetItemStr(cfg, "special", "attackClr", buff))
			{
				int r,g,b;
				sscanf(buff, "%d,%d,%d", &r,&g,&b);
				m_r=r; m_g=g; m_b=b;
			}

			//load attack stuff
			m_attackSpd = CfgGetItemFloat(cfg, "special", "attackSpd");

			double atkDelay = CfgGetItemFloat(cfg, "special", "attackDelay");

			TimeInit(&m_attackDelay, atkDelay);
		}
		break;

	case ENTITYMSG_UPDATE:
		{
			int state = OBJGetCurState(GetOBJ());

			if(state != SHROOMSHOOTER_ANIM_SHOOT
				&& state != SHROOMSHOOTER_ANIM_OUCH)
			{
				if(TimeElapse(&m_attackDelay))
				{
					//set to attack state
					OBJSetState(GetOBJ(), SHROOMSHOOTER_ANIM_SHOOT);

					//spit sound
					//CREPlaySound(19);
				}
			}

			if(OBJIsStateEnd(GetOBJ()))
			{
				if(state == SHROOMSHOOTER_ANIM_SHOOT)
				{
					//create spit projectile
					if(m_spitMdl)
					{
						D3DXVECTOR3 spitLoc;
						OBJJointGetWorldLoc(GetOBJ(), OBJJointGetIndex(GetOBJ(), "mouth"), (float*)spitLoc);
						new Spit(GetID(), spitLoc, m_attackSpd, m_spitMdl, 
							m_spitFXTxt, m_r, m_g, m_b);
					}
				}

				//random idle
				int newIdleState = Random(SHROOMSHOOTER_ANIM_IDLE1, 
					SHROOMSHOOTER_ANIM_IDLE_MAX);

				OBJSetState(GetOBJ(), newIdleState);
			}
		}
		break;

	case ENTITYMSG_ENTITYCOLLIDE:
		break;

	case ENTITYMSG_REQUESTSOUND:
		switch(wParam)
		{
		case SND_REQ_PROJ_HIT_CRE:
			*((int*)lParam) = 20;
			break;
		}
		break;
	}

	return RETCODE_SUCCESS;
}
//Direct X-files!  Those bastards made it too easy...
PROTECTED RETCODE _ModelLoadDataFromFileX(hMDL model, const char *filename)
{
	assert(model);

	RETCODE ret = RETCODE_SUCCESS;
	
	char path[DMAXCHARBUFF];

	LPD3DXBUFFER pD3DXMtrlBuffer = 0; //material buffer to be copied later

	//DXUtil_FindMediaFile(path, filename);
	strcpy(path, filename);

	unsigned long numMat;

	if(_GFXCheckError(
		D3DXLoadMeshFromX( path, D3DXMESH_MANAGED, g_p3DDevice, 
                            &model->adjacencyBuffer, &pD3DXMtrlBuffer, 
                            &numMat, &model->mesh),
							true, "Error in ModelLoadDataFromFileASE"))
	{ ret=RETCODE_FAILURE; return ret; }

	model->numMaterial = numMat;

	//allocate both textures and materials
	if(MemAlloc((void**)&model->textures, sizeof(hTXT)*model->numMaterial, M_ZERO) != RETCODE_SUCCESS)
	{ ret=RETCODE_FAILURE; return ret; }

	if(MemAlloc((void**)&model->materials, sizeof(GFXMATERIAL)*model->numMaterial, M_ZERO) != RETCODE_SUCCESS)
	{ ret=RETCODE_FAILURE; return ret; }

	D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();

	//load up texture and copy material data
	for(int i = 0; i < model->numMaterial; i++ )
    {
        model->materials[i] = d3dxMaterials[i].MatD3D;
        model->materials[i].Ambient = model->materials[i].Diffuse;

        // Get a path to the texture
		if(d3dxMaterials[i].pTextureFilename)
		{
			//DXUtil_FindMediaFile(path, d3dxMaterials[i].pTextureFilename);

			// Load the texture
			model->textures[i] = TextureCreate(MDLTXTID, d3dxMaterials[i].pTextureFilename, false, 0);
			TextureAddRef(model->textures[i]);

			if(!model->textures[i])
			{ ret=RETCODE_FAILURE; return ret; }
		}
    }

	pD3DXMtrlBuffer->Release();

	//compute normals if specified
	if(model->mesh->GetFVF() & D3DFVF_NORMAL)
		D3DXComputeNormals(model->mesh);

	model->indCount = model->mesh->GetNumFaces()*NUMPTFACE;

	return ret;
}
//3ds ascii file textured
PROTECTED RETCODE _ModelLoadDataFromFileASE(hMDL model, const char *filename)
{
	assert(model);

	RETCODE ret = RETCODE_SUCCESS;

	//data structures
	gfxVtx *vtxBuff=0; //it's gonna be biG!, bIG!!, BIG!!!
	txc *txcList=0;		//allocated later (numTxc)
	unsigned short *indList=0;		//allocated later (indNum inside model)
	int numTxc;
	int vtxInd[NUMPTFACE], txtInd[NUMPTFACE];

	int vtxCount, faceCount;

	//ready the file
	FILE *theFile;
	char buff[MAXCHARBUFF];

	theFile = fopen(filename, "rt"); //FileOpenFile(filename, FILEREAD | FILETEXT);
	if(!theFile)
	{ ASSERT_MSG(0,"Unable to open file", "Error in _ModelLoadDataFromFileASE"); return RETCODE_FAILURE; }

	//now let's parse this baby!
	if(ParserSkipString(theFile, '*', ' ', "BITMAP"))
	{
		//let's get the filename
		if(ParserReadStringFile(theFile, buff, MAXCHARBUFF, '"', '"') == RETCODE_FAILURE) //we have reached end of file
		{ ASSERT_MSG(0,"Error reading ASE model file, cannot get BITMAP file!", "Error in _ModelLoadDataFromFileASE"); ret = RETCODE_FAILURE; goto BADMOJO2; }

		//we will only have one texture for now...
		model->numMaterial = 1;

		//allocate texture array
		if(MemAlloc((void**)&model->textures, sizeof(hTXT)*model->numMaterial, M_ZERO) != RETCODE_SUCCESS)
		{ ASSERT_MSG(0,"Unable to allocate textures", "error in _ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }
		MemSetPattern(model->textures, "MDLTXTS");

		model->textures[0] = TextureCreate(MDLTXTID, buff, false, 0);
		TextureAddRef(model->textures[0]);
		//D3DXCreateTextureFromFile(g_p3DDevice, buff, &model->texture);
		
		if(!model->textures[0])
		{ ASSERT_MSG(0,"Unable to load texture", "error in _ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }
	}
	else
	{ ASSERT_MSG(0,"Error reading ASE model file", "Error in _ModelLoadDataFromFileASE"); ret = RETCODE_FAILURE; goto BADMOJO2; }

	//now let's find the num vertices
	if(ParserSkipString(theFile, '*', ' ', "MESH_NUMVERTEX"))
	{
		//get the number
		fscanf(theFile, "%d", &vtxCount);

		//create the array
		if(MemAlloc((void**)&vtxBuff, sizeof(gfxVtx)*vtxCount, M_ZERO) != RETCODE_SUCCESS)
		{ ASSERT_MSG(0,"Unable to allocate vertex buffer", "error in _ModelLoadDataFromFileASE"); ret = RETCODE_FAILURE; goto BADMOJO2; }

		MemSetPattern(vtxBuff, "GFXVTXB");
	}
	else
	{ ASSERT_MSG(0,"Error reading ASE model file", "Error in _ModelLoadDataFromFileASE"); ret = RETCODE_FAILURE; goto BADMOJO2; }

	//now get the num faces
	if(ParserSkipString(theFile, '*', ' ', "MESH_NUMFACES"))
	{
		//get the number
		fscanf(theFile, "%d", &faceCount);

		//create the BIG @$$ array
		model->indCount = faceCount*NUMPTFACE;
		if(MemAlloc((void**)&indList, sizeof(unsigned short)*model->indCount, M_ZERO) != RETCODE_SUCCESS)
		{ ASSERT_MSG(0,"Unable to allocate vertex buffer, It's not HUGE!!!", "error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

		MemSetPattern(indList, "GFXINDB");
	}
	else
	{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

	int i, j, dummy;

	//load up the vertex list
	for(i = 0; i < vtxCount; i++)
	{
		//skip "*MESH_VERTEX "
		if(ParserSkipString(theFile, '*', ' ', "MESH_VERTEX"))
		{
			//skip index number
			if(ParserReadDataFile(theFile, &dummy, dataINT, 9) == RETCODE_FAILURE) //we have reached end of file
			{ ASSERT_MSG(0,"Error reading ASE model file 'dummy'", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

			//now let's get those that we need
			if(ParserReadDataFile(theFile, &vtxBuff[i].x, dataFLOAT, 9) == RETCODE_FAILURE)
			{ ASSERT_MSG(0,"Error reading ASE model file 'vtx X'", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

			if(ParserReadDataFile(theFile, &vtxBuff[i].y, dataFLOAT, 9) == RETCODE_FAILURE)
			{ ASSERT_MSG(0,"Error reading ASE model file 'vtx Y'", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

			if(ParserReadDataFile(theFile, &vtxBuff[i].z, dataFLOAT, 9) == RETCODE_FAILURE)
			{ ASSERT_MSG(0,"Error reading ASE model file 'vtx Z'", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }
			
			vtxBuff[i].color = 0xFFFFFFFF;

			//get the normalized vector and put it as the normal for lighting
			D3DXVECTOR3 vect(vtxBuff[i].x, vtxBuff[i].y, vtxBuff[i].z);
			D3DXVec3Normalize(&vect,&vect);
			float *nV = (float*)vect;
			vtxBuff[i].nX = -nV[eX]; vtxBuff[i].nY = -nV[eY]; vtxBuff[i].nZ = -nV[eZ];
		}
		else
		{ ASSERT_MSG(0,"Error reading ASE model file '*MESH_VERTEX '", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }
	}

	//now to fill in the face index
	for(i = 0, j = 0; i < faceCount; i++, j+=NUMPTFACE)
	{
		//skip "*MESH_FACE "
		if(ParserSkipString(theFile, '*', ' ', "MESH_FACE"))
		{
			//skip index number
			if(ParserReadDataFile(theFile, &dummy, dataINT, ':') == RETCODE_FAILURE) //we have reached end of file
			{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

			//now let's get those that we need

			//skip this junk A:
			if(ParserReadWordFile(theFile, buff, MAXCHARBUFF, ':') == RETCODE_FAILURE)
			{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

			if(ParserReadDataFile(theFile, &vtxInd[0], dataINT, ' ') == RETCODE_FAILURE)
			{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

			//skip this junk B:
			if(ParserReadWordFile(theFile, buff, MAXCHARBUFF, ':') == RETCODE_FAILURE)
			{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

			if(ParserReadDataFile(theFile, &vtxInd[1], dataINT, ' ') == RETCODE_FAILURE)
			{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

			//skip this junk C:
			if(ParserReadWordFile(theFile, buff, MAXCHARBUFF, ':') == RETCODE_FAILURE)
			{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

			if(ParserReadDataFile(theFile, &vtxInd[2], dataINT, ' ') == RETCODE_FAILURE)
			{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

			indList[j] = vtxInd[0];
			indList[j+1] = vtxInd[1];
			indList[j+2] = vtxInd[2];
		}
		else
		{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }
	}

	//now let's get the number of texture vertices
	if(ParserSkipString(theFile, '*', ' ', "MESH_NUMTVERTEX"))
	{
		//get the number
		fscanf(theFile, "%d", &numTxc);

		//create the array
		if(MemAlloc((void**)&txcList, sizeof(txc)*numTxc, M_ZERO) != RETCODE_SUCCESS)
		{ ASSERT_MSG(0,"Unable to create texture location list", "error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

		MemSetPattern(txcList, "GFXTXTL");
	}
	else
	{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

	float junk; //we don't need the depth in texture for now...

	//let's fill 'er up
	for(i = 0; i < numTxc; i++)
	{
		//skip "*MESH_TVERT "
		if(ParserSkipString(theFile, '*', ' ', "MESH_TVERT"))
		{
			//skip index number
			if(ParserReadDataFile(theFile, &dummy, dataINT, 9) == RETCODE_FAILURE) //we have reached end of file
			{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

			//now let's get those that we need
			if(ParserReadDataFile(theFile, &txcList[i].s, dataFLOAT, 9) == RETCODE_FAILURE)
			{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

			if(ParserReadDataFile(theFile, &txcList[i].t, dataFLOAT, 9) == RETCODE_FAILURE)
			{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

			if(ParserReadDataFile(theFile, &junk, dataFLOAT, 9) == RETCODE_FAILURE)
			{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }
			
		}
		else
		{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }
	}

	//let's fill in the face index
	//number of face to have texture will be the number of faces created...for now...
	for(i = 0, j = 0; i < faceCount; i++, j+=NUMPTFACE)
	{
		//skip "*MESH_TFACE "
		if(ParserSkipString(theFile, '*', ' ', "MESH_TFACE"))
		{
			//skip index number
			if(ParserReadDataFile(theFile, &dummy, dataINT, 9) == RETCODE_FAILURE) //we have reached end of file
			{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

			//now let's get those that we need
			if(ParserReadDataFile(theFile, &txtInd[0], dataINT, 9) == RETCODE_FAILURE)
			{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

			if(ParserReadDataFile(theFile, &txtInd[1], dataINT, 9) == RETCODE_FAILURE)
			{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

			if(ParserReadDataFile(theFile, &txtInd[2], dataINT, 9) == RETCODE_FAILURE)
			{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); ret=RETCODE_FAILURE; goto BADMOJO2; }

			vtxBuff[indList[j]].s = txcList[txtInd[0]].s;
			vtxBuff[indList[j]].t = txcList[txtInd[0]].t;

			vtxBuff[indList[j+1]].s = txcList[txtInd[0]].s;
			vtxBuff[indList[j+1]].t = txcList[txtInd[0]].t;

			vtxBuff[indList[j+2]].s = txcList[txtInd[2]].s;
			vtxBuff[indList[j+2]].t = txcList[txtInd[2]].t;
		}
		else
		{ ASSERT_MSG(0,"Error reading ASE model file", "Error in ModelLoadDataFromFileASE"); fclose(theFile); return RETCODE_FAILURE; }
	}

	//////////////////////////////////////////////////////////////
	//now time to stuff it all in the D3D vertex buffer
	//create the mesh
	_GFXCheckError(D3DXCreateMeshFVF(
		faceCount,
		vtxCount,
		D3DXMESH_MANAGED,
		GFXVERTEXFLAG,
		g_p3DDevice,
		&model->mesh),
	true, "Error in ModelLoadDataFromFileASE");
	//////////////////////////////////////////////////////////////

	/////////////////
	//now fill 'er up
	BYTE *ptrVtx;

	if(_GFXCheckError(
		model->mesh->LockVertexBuffer(0, //Flags, nothing special
					   &ptrVtx			 //If successful, this will point to the data in the VB
					   ), 
					   true,
			"Error in ModelLoadDataFromFileASE"))
	{ ret=RETCODE_FAILURE; goto BADMOJO2; }

	memcpy(ptrVtx, vtxBuff, sizeof(gfxVtx)*vtxCount);

	model->mesh->UnlockVertexBuffer();
	/////////////////

	/////////////////
	//now fill the index buffer up
	BYTE *ptrInd;

	if(_GFXCheckError(
			model->mesh->LockIndexBuffer(0, //Flags, nothing special
					   &ptrInd     //If successful, this will point to the data in the IB
					   ),          
			true,
			"Error in ModelLoadDataFromFileASE"))
	{ ret=RETCODE_FAILURE; goto BADMOJO2; }

	memcpy(ptrInd, indList, sizeof(unsigned short)*model->indCount);

	model->mesh->UnlockIndexBuffer();
	/////////////////

	/////////////////////////////
	//create the adjacency buffer
	//and do some funky stuff
	D3DXCreateBuffer(sizeof(DWORD)*model->indCount, &model->adjacencyBuffer);

	model->mesh->GenerateAdjacency(0.0f, (DWORD*)model->adjacencyBuffer->GetBufferPointer());

	D3DXValidMesh(model->mesh, (DWORD*)model->adjacencyBuffer->GetBufferPointer());
	//////////////////////////////

	//This outta make lighting easy
	D3DXComputeNormals(model->mesh);

BADMOJO2:

	if(theFile) fclose(theFile);
	if(indList) MemFree((void**)&indList);
	if(vtxBuff) MemFree((void**)&vtxBuff);
	if(txcList) MemFree((void**)&txcList);

	return ret;
}
//my own model file!
PROTECTED RETCODE _ModelLoadDataFromFile(hMDL model, const char *filename)
{
	assert(model);

	RETCODE ret = RETCODE_SUCCESS;

	//data structures
	gfxVtx *vtxBuff=0; //it's gonna be biG!, bIG!!, BIG!!!
	
	txc *txcList=0;		//allocated later (numTxc)
	unsigned short *indList=0;		//allocated later (indNum inside model)
	int numTxc;
	int vtxInd[NUMPTFACE], txtInd[NUMPTFACE];

	int vtxCount, faceCount;

	//ready the file
	FILE *theFile;
	char buff[MAXCHARBUFF];
	bool bLoading = false;

	theFile = fopen(filename, "rt");
	if(!theFile)
	{ ASSERT_MSG(0, "Unable to open file", "Error in _ModelLoadDataFromFile"); return RETCODE_FAILURE; }

	do
	{
		fscanf(theFile, "%s\n", buff);

		if(strcmp(buff, "START") == 0) //start loading stuff if we found the START
			bLoading = true;
		else if(bLoading)
		{
			if(strcmp("[VERTEX]", buff) == 0)
			{
				fscanf(theFile, "numvertex=%d\n", &vtxCount);

				//create the array
				if(MemAlloc((void**)&vtxBuff, sizeof(gfxVtx)*vtxCount, M_ZERO) != RETCODE_SUCCESS)
				{ ASSERT_MSG(0,"Unable to allocate vertex buffer", "error in _ModelLoadDataFromFile"); ret=RETCODE_FAILURE; goto BADMOJO; }

				//fill 'em up!
				int r,g,b,a;

				for(int i = 0; i < vtxCount; i++)
				{
					fscanf(theFile, "vertex=%f,%f,%f color=%d,%d,%d,%d\n", 
						&vtxBuff[i].x,&vtxBuff[i].y,&vtxBuff[i].z,
						&r,&g,&b,&a);
					vtxBuff[i].color = D3DCOLOR_RGBA(r,g,b,a);

					//get the normalized vector and put it as the normal for lighting
					//D3DXVECTOR3 vect(vtxBuff[i].x, vtxBuff[i].y, vtxBuff[i].z);
					//D3DXVec3Normalize(&vect,&vect);
					//float *nV = (float*)vect;
					//vtxBuff[i].nX = -nV[eX]; vtxBuff[i].nY = -nV[eY]; vtxBuff[i].nZ = -nV[eZ];
				}
			}
			else if(strcmp("[TEXTURE]", buff) == 0)
			{
				fscanf(theFile, "image=%s\n", buff);

				int filtermode;

				fscanf(theFile, "filtermode=%d\n", &filtermode);

				//we will only have one texture for now...
				model->numMaterial = 1;

				//allocate texture array
				if(MemAlloc((void**)&model->textures, sizeof(hTXT)*model->numMaterial, M_ZERO) != RETCODE_SUCCESS)
				{ ASSERT_MSG(0,"Unable to allocate textures", "error in _ModelLoadDataFromFile"); ret=RETCODE_FAILURE; goto BADMOJO; }
				MemSetPattern(model->textures, "MDLTXTS");

				model->textures[0] = TextureCreate(MDLTXTID, buff, false, 0);
				TextureAddRef(model->textures[0]);
				//D3DXCreateTextureFromFile(g_p3DDevice, buff, &model->texture);
				
				if(!model->textures[0])
				{ ASSERT_MSG(0,"Unable to load texture", "error in _ModelLoadDataFromFile"); ret=RETCODE_FAILURE; goto BADMOJO; }

				//now get the texture locations
				fscanf(theFile, "numtextureloc=%d\n", &numTxc);

				//create the array
				if(MemAlloc((void**)&txcList, sizeof(txc)*numTxc, M_ZERO) != RETCODE_SUCCESS)
				{ ASSERT_MSG(0,"Unable to create texture location list", "error in _ModelLoadDataFromFile"); ret=RETCODE_FAILURE; goto BADMOJO; }

				MemSetPattern(txcList, "GFXTXTL");

				//fill 'er up
				for(int i = 0; i < numTxc; i++)
				{
					fscanf(theFile, "texloc=%f,%f\n", &txcList[i].s, &txcList[i].t);
				}
			}
			else if(strcmp("[FACE]", buff) == 0)
			{
				fscanf(theFile, "numface=%d\n", &faceCount);

				//create the BIG @$$ array
				model->indCount = faceCount*NUMPTFACE;
				if(MemAlloc((void**)&indList, sizeof(unsigned short)*model->indCount, M_ZERO) != RETCODE_SUCCESS)
				{ ASSERT_MSG(0,"Unable to allocate index buffer, It's not so HUGE!!!", "error in _ModelLoadDataFromFile"); ret=RETCODE_FAILURE; goto BADMOJO; }

				MemSetPattern(vtxBuff, "GFXINDB");

				//fill 'em up
				for(int i = 0, j = 0; i < faceCount; i++, j+=NUMPTFACE)
				{
					fscanf(theFile, "vertexIndex=%d,%d,%d textureIndex=%d,%d,%d\n", 
						&vtxInd[0], &vtxInd[1], &vtxInd[2],
						&txtInd[0], &txtInd[1], &txtInd[2]);

					indList[j] = vtxInd[0];
					indList[j+1] = vtxInd[1];
					indList[j+2] = vtxInd[2];

					//do some messed up texture assign
					vtxBuff[vtxInd[0]].s = txcList[txtInd[0]].s;
					vtxBuff[vtxInd[0]].t = txcList[txtInd[0]].t;
					vtxBuff[vtxInd[1]].s = txcList[txtInd[1]].s;
					vtxBuff[vtxInd[1]].t = txcList[txtInd[1]].t;
					vtxBuff[vtxInd[2]].s = txcList[txtInd[2]].s;
					vtxBuff[vtxInd[2]].t = txcList[txtInd[2]].t;
				}
			}
			else if(strcmp("END", buff) == 0)
				bLoading = false;
		}
	}while(bLoading);

	//////////////////////////////////////////////////////////////
	//now time to stuff it all in the D3D vertex buffer
	//create the mesh
	_GFXCheckError(D3DXCreateMeshFVF(
		faceCount,
		vtxCount,
		D3DXMESH_MANAGED,
		GFXVERTEXFLAG,
		g_p3DDevice,
		&model->mesh),
	true, "Error in _ModelLoadDataFromFile");
	//////////////////////////////////////////////////////////////

	/////////////////
	//now fill 'er up
	BYTE *ptrVtx;

	if(_GFXCheckError(
		model->mesh->LockVertexBuffer(0, //Flags, nothing special
					   &ptrVtx			 //If successful, this will point to the data in the VB
					   ), 
					   true,
			"Error in _ModelLoadDataFromFile"))
	{ ret=RETCODE_FAILURE; goto BADMOJO; }

	memcpy(ptrVtx, vtxBuff, sizeof(gfxVtx)*vtxCount);

	model->mesh->UnlockVertexBuffer();
	/////////////////

	/////////////////
	//now fill the index buffer up
	BYTE *ptrInd;

	if(_GFXCheckError(
			model->mesh->LockIndexBuffer(0, //Flags, nothing special
					   &ptrInd     //If successful, this will point to the data in the IB
					   ),          
			true,
			"Error in _ModelLoadDataFromFile"))
	{ ret=RETCODE_FAILURE; goto BADMOJO; }

	memcpy(ptrInd, indList, sizeof(unsigned short)*model->indCount);

	model->mesh->UnlockIndexBuffer();
	/////////////////

	/////////////////////////////
	//create the adjacency buffer
	//and do some funky stuff
	D3DXCreateBuffer(sizeof(DWORD)*model->indCount, &model->adjacencyBuffer);

	model->mesh->GenerateAdjacency(0.0f, (DWORD*)model->adjacencyBuffer->GetBufferPointer());

	D3DXValidMesh(model->mesh, (DWORD*)model->adjacencyBuffer->GetBufferPointer());
	//////////////////////////////

	//This outta make lighting easy
	D3DXComputeNormals(model->mesh);

BADMOJO:

	if(theFile) fclose(theFile);
	if(indList) MemFree((void**)&indList);
	if(vtxBuff) MemFree((void**)&vtxBuff);
	if(txcList) MemFree((void**)&txcList);

	return ret;
}
RETCODE World::EntityLoad_Start(hQBSP qbsp, const EntityParse & entityDat)
{
	///////////////////////////////////////////////////////////////////////
	// Load Scene
	//not much to do...
	const char *pStr;
	const char * pFilename = entityDat.GetVal("sceneFile");

	pStr = entityDat.GetVal("sceneScript");

	if(pStr)
	{
		//get script file
		char scriptPath[MAXCHARBUFF];

		strcpy(scriptPath, m_filePath.c_str());
		strcpy(GetExtension(scriptPath), SCENE_EXT);

		//if pFilename exists, then use that
		CutsceneSet(pFilename ? pFilename : scriptPath, pStr);
	}

	//ending scene

	pFilename = entityDat.GetVal("endSceneFile");

	pStr = entityDat.GetVal("endSceneScript");

	if(pStr)
	{
		//get script file
		char scriptPath[MAXCHARBUFF];

		strcpy(scriptPath, m_filePath.c_str());
		strcpy(GetExtension(scriptPath), SCENE_EXT);

		//if pFilename exists, then use that
		CutsceneSetEnding(pFilename ? pFilename : scriptPath, pStr);
	}

	///////////////////////////////////////////////////////////////////////
	// Load Skybox
	if(entityDat.GetVal("skyTop")
		&& entityDat.GetVal("skyBottom")
		&& entityDat.GetVal("skyFront")
		&& entityDat.GetVal("skyBack")
		&& entityDat.GetVal("skyLeft")
		&& entityDat.GetVal("skyRight"))
	{
		char topStr[MAXCHARBUFF] = GAMEFOLDER,
			 bottomStr[MAXCHARBUFF] = GAMEFOLDER,
			 frontStr[MAXCHARBUFF] = GAMEFOLDER,
			 backStr[MAXCHARBUFF] = GAMEFOLDER,
			 leftStr[MAXCHARBUFF] = GAMEFOLDER,
			 rightStr[MAXCHARBUFF] = GAMEFOLDER;

		strcat(topStr, "\\"); strcat(topStr, entityDat.GetVal("skyTop"));
		strcat(bottomStr, "\\"); strcat(bottomStr, entityDat.GetVal("skyBottom"));
		strcat(frontStr, "\\"); strcat(frontStr, entityDat.GetVal("skyFront"));
		strcat(backStr, "\\"); strcat(backStr, entityDat.GetVal("skyBack"));
		strcat(leftStr, "\\"); strcat(leftStr, entityDat.GetVal("skyLeft"));
		strcat(rightStr, "\\"); strcat(rightStr, entityDat.GetVal("skyRight"));

		SkyBoxInit(500,
			TextureCreate(0, topStr, false, 0),
			TextureCreate(0, bottomStr, false, 0),
			TextureCreate(0, frontStr, false, 0),
			TextureCreate(0, backStr, false, 0),
			TextureCreate(0, leftStr, false, 0),
			TextureCreate(0, rightStr, false, 0));
	}

	///////////////////////////////////////////////////////////////////////
	// Get Goal Stuff
	pStr = entityDat.GetVal("goalImg");

	if(pStr)
	{
		string imgPath = GAMEFOLDER;
		imgPath += "\\";
		imgPath += pStr;

		HUDSetGoalTxt(TextureCreate(0, imgPath.c_str(), false, 0));
	}

	///////////////////////////////////////////////////////////////////////
	// Set Up Goal
	pStr = entityDat.GetVal("goalMax");

	if(pStr)
	{
		int gMax; sscanf(pStr, "%d", &gMax);
		HUDSetGoalMax(gMax);
	}

	///////////////////////////////////////////////////////////////////////
	// Get the level desc
	pStr = entityDat.GetVal("descFile");

	if(pStr)
	{
		string path = GAMEFOLDER;
		path += "\\";
		path += pStr;

		char *strBuff = GrabAllText((char*)path.c_str());

		if(strBuff)
		{
			m_desc = strBuff;

			free(strBuff);
		}
	}

	///////////////////////////////////////////////////////////////////////
	// Get the music
	pStr = entityDat.GetVal("musicFile");

	if(pStr)
	{
		string musPath = GAMEFOLDER;
		musPath += "\\";
		musPath += pStr;

		MusicSet(musPath.c_str());
	}

	return RETCODE_SUCCESS;
}
//Dialog (string imgfile, float sx, float sy, float ex, float ey)
//a dialog, must set font before use
//make sure to open it to display
PROTECTED long S_DialogCallback(void *owner, void *handle, int msg, WPARAM wparam, LPARAM lparam)
{
	hVAR var = (hVAR)handle; assert(var);

	Id *pID = (Id *)ScriptVarGetData(var);

	switch(msg)
	{
	case VAR_CREATE:
		pID = new Id; assert(pID);

		pID->ID = 0;
		pID->counter = -1;

		ScriptVarSetData(var, pID);
		break;

	case VAR_SET:
		{
			GameDialog *pDlg = (GameDialog*)IDPageQuery(*pID);

			if(pDlg)
				delete pDlg;

			pID->counter = -1;

			if(g_world)
			{
				hPARAM param = (hPARAM)wparam;

				char *imgFilePath;
				float sx,sy,ex,ey;

				if(ScriptParamGetType(param, 0) == eVarPtr)
					imgFilePath = (char *)((string *)ScriptParamGetVar(param, 0))->c_str();
				else
					imgFilePath = (char *)ScriptParamGetVar(param, 0);

				sx = *(float*)ScriptParamGetVar(param, 1);
				sy = *(float*)ScriptParamGetVar(param, 2);
				ex = *(float*)ScriptParamGetVar(param, 3);
				ey = *(float*)ScriptParamGetVar(param, 4);

				if(imgFilePath[0] != 0)
				{
					string imgPath = GAMEFOLDER;
					imgPath += "\\";
					imgPath += imgFilePath;

					hTXT txt = TextureCreate(0, imgPath.c_str(), false, 0);

					*pID = g_world->DialogAdd(txt, sx,sy,ex,ey);
				}
			}
		}
		break;

	case VAR_GETBASEVAR:
		{
			Param *pOut = (Param *)wparam;

			pOut->paramVarType = eVarInt;

			pOut->dat._int = GAME_IDVALID(*pID);
		}
		break;

	case VAR_DESTROY:
		{
			GameDialog *pDlg = (GameDialog*)IDPageQuery(*pID);

			if(pDlg)
				delete pDlg;

			delete pID;
		}
		break;
	}

	return RETCODE_SUCCESS;
}
//Level Start
RETCODE MCB_LevelStart(hMENU hMenu, DWORD msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
	case MENU_MSG_LOAD:
		{
			SIZE scrnSize = GFXGetScrnSize();

			hCFG cfg = (hCFG)wParam;

			if(cfg)
			{
				char buff[MAXCHARBUFF]={0};
				int r,g,b,a;
				float fntSize;

				///////////////////////////////////////
				// Get Font Title
				fntSize = CfgGetItemFloat(cfg, LEVEL_START_SECTION, "titleFntSize");
				fntSize *= scrnSize.cx;

				if(CfgGetItemStr(cfg, LEVEL_START_SECTION, "titleFnt", buff))
					g_titleFnt = FontCreate(buff, fntSize, 0);

				if(CfgGetItemStr(cfg, LEVEL_START_SECTION, "titleFntClr", buff))
				{
					sscanf(buff, "%d,%d,%d,%d", &r,&g,&b,&a);
					g_titleClr = D3DCOLOR_RGBA(r,g,b,a);
				}

				///////////////////////////////////////
				// Get Font Desc.
				fntSize = CfgGetItemFloat(cfg, LEVEL_START_SECTION, "descFntSize");
				fntSize *= scrnSize.cx;

				if(CfgGetItemStr(cfg, LEVEL_START_SECTION, "descFnt", buff))
					g_descFnt = FontCreate(buff, fntSize, 0);

				if(CfgGetItemStr(cfg, LEVEL_START_SECTION, "descFntClr", buff))
				{
					sscanf(buff, "%d,%d,%d,%d", &r,&g,&b,&a);
					g_descClr = D3DCOLOR_RGBA(r,g,b,a);
				}

				///////////////////////////////////////
				// Get Background img
				if(CfgGetItemStr(cfg, LEVEL_START_SECTION, "bkImg", buff))
				{
					string imgPath = GAMEFOLDER;
					imgPath += "\\";
					imgPath += buff;

					g_bkImg = TextureCreate(0, imgPath.c_str(), false, 0);
				}

				///////////////////////////////////////
				// Load other components
				g_bkOfs = CfgGetItemFloat(cfg, LEVEL_START_SECTION, "bkOfs");
				g_bkOfs *= scrnSize.cx;

				g_titleSY = CfgGetItemFloat(cfg, LEVEL_START_SECTION, "titleY");
				g_titleSY *= scrnSize.cy;

				if(CfgGetItemStr(cfg, LEVEL_START_SECTION, "descSLoc", buff))
				{
					sscanf(buff, "%f,%f", &g_descLoc.x, &g_descLoc.y);

					g_descLoc.x *= scrnSize.cx;
					g_descLoc.y *= scrnSize.cy;
				}

				if(CfgGetItemStr(cfg, LEVEL_START_SECTION, "descELoc", buff))
				{
					D3DXVECTOR2 eLoc;
					sscanf(buff, "%f,%f", &eLoc.x, &eLoc.y);

					g_descSize.x = (eLoc.x*scrnSize.cx) - g_descLoc.x;
					g_descSize.y = (eLoc.y*scrnSize.cy) - g_descLoc.y;
				}
			}

			g_world->SetFlag(WORLD_FLAG_INPUT_DISABLE, true);
		}
		break;

	case MENU_MSG_BTN:
		if(lParam == INP_STATE_RELEASED)
		{
			switch(wParam)
			{
			case INP_A:
			case INP_B:
			case INP_C:
			case INP_D:
			case INP_START:
				g_world->SetFlag(WORLD_FLAG_INPUT_DISABLE, false);
				MenuExitCurrent();
				g_world->CutsceneRemove();
				InputClear();
				break;
			}
		}
		break;

	case MENU_MSG_ITEM:
		g_world->SetFlag(WORLD_FLAG_INPUT_DISABLE, false);
		MenuExitCurrent();
		g_world->CutsceneRemove();
		InputClear();
		break;

	case MENU_MSG_UPDATE:
		switch(wParam)
		{
		case MENU_UPDATE_NORMAL:
			if(INPXKbIsReleased(DIK_ESCAPE) || INPXKbIsReleased(DIK_RETURN))
			{
				g_world->SetFlag(WORLD_FLAG_INPUT_DISABLE, false);
				MenuExitCurrent();
				g_world->CutsceneRemove();
			}
			break;

		case MENU_UPDATE_ENTERING:
		case MENU_UPDATE_EXITING:
			return RETCODE_BREAK;
		}
		break;

	case MENU_MSG_DRAW:
		if(g_world)
		{
			SIZE scrnSize = GFXGetScrnSize();

			SIZE fntSize;

			float fntX, fntY;
			float bkX, bkY, bkW, bkH;

			///////////////////////////////////////////
			//Display Title
			const char *titleStr = g_world->GetName();
			FontGetStrSize(g_titleFnt, (char*)titleStr, &fntSize);

			fntX = (scrnSize.cx/2)-(fntSize.cx/2);
			fntY = g_titleSY;

			bkX = fntX - g_bkOfs;
			bkY = fntY - g_bkOfs;

			bkW = fntSize.cx+(g_bkOfs*2);
			bkH = fntSize.cy+(g_bkOfs*2);

			GFXBltModeEnable(0);
			TextureStretchBlt(g_bkImg, bkX,bkY,bkW,bkH, 0, 0, 0);
			GFXBltModeDisable();

			FontPrintf2D(g_titleFnt, fntX, fntY, g_titleClr, titleStr);

			///////////////////////////////////////////
			//Display Description
			bkX = g_descLoc.x - g_bkOfs;
			bkY = g_descLoc.y - g_bkOfs;

			bkW = g_descSize.x+(g_bkOfs*2);
			bkH = g_descSize.y+(g_bkOfs*2);

			GFXBltModeEnable(0);
			TextureStretchBlt(g_bkImg, bkX,bkY,bkW,bkH, 0, 0, 0);
			GFXBltModeDisable();

			FontTextBox(g_descFnt, g_descLoc.x,g_descLoc.y, 
				g_descLoc.x+g_descSize.x, g_descLoc.y+g_descSize.y, g_descClr, g_world->MapGetDesc());

			///////////////////////////////////////////
			//Press Any Button To Start
			FontGetStrSize(g_descFnt, "Press Any Button To Start", &fntSize);

			fntX = (scrnSize.cx/2)-(fntSize.cx/2);
			fntY = scrnSize.cy - fntSize.cy;

			FontPrintf2D(g_descFnt, fntX, fntY, 0xffffffff, "Press Any Button To Start");
		}
		break;

	case MENU_MSG_DESTROY:
		if(g_titleFnt)
		{ FontDestroy(&g_titleFnt); g_titleFnt = 0; }

		if(g_descFnt)
		{ FontDestroy(&g_descFnt); g_descFnt = 0; }

		if(g_bkImg)
		{ TextureDestroy(&g_bkImg); g_bkImg = 0; }
		break;
	}

	return RETCODE_SUCCESS;
}