Esempio n. 1
0
unsigned int psEffectManager::RenderEffect(const csString & effectName, iSectorList * sectors, const csVector3 & pos, 
                                           iMeshWrapper * attachTarget, const csVector3 & up, 
                                           const unsigned int uniqueIDOverride, const float* scale)
{
#ifndef DONT_DO_EFFECTS
    // check if it's a single effect
    psEffect * currEffect = FindEffect(effectName);
    if (currEffect != 0)
    {
        currEffect = currEffect->Clone();

        if (scale != NULL)
        {
            if (!currEffect->SetFrameParamScalings(scale))
            {
                Error2("Received scale factor for effect %s that don't use param scaling",effectName.GetDataSafe());
            }
        }

        const unsigned int uniqueID = currEffect->Render(sectors, pos, 0, attachTarget, up.Unit(), uniqueIDOverride);
        actualEffects.Put(uniqueID, currEffect);
        return uniqueID;
    }
#endif
    return 0;
   
}
//-----------------------------------------------------------------------------
// Purpose: Stop effects from emitting more particles. If no effect is 
//			specified, all effects attached to this entity are stopped.
//-----------------------------------------------------------------------------
void CParticleProperty::StopEmission( CNewParticleEffect *pEffect, bool bWakeOnStop, bool bDestroyAsleepSystems )
{
	// If we return from dormancy and are then told to stop emitting,
	// we should have died while dormant. Remove ourselves immediately.
	bool bRemoveInstantly = (m_iDormancyChangedAtFrame == gpGlobals->framecount);

	if ( pEffect )
	{
		if ( FindEffect( pEffect ) != -1 )
		{
			pEffect->StopEmission( false, bRemoveInstantly, bWakeOnStop );
		}
	}
	else
	{
		// Stop all effects
		float flNow = g_pParticleSystemMgr->GetLastSimulationTime();
		int nCount = m_ParticleEffects.Count();
		for ( int i = nCount-1; i >= 0; i-- )
		{
			CNewParticleEffect *pTmp = m_ParticleEffects[i].pParticleEffect.GetObject();
			bool bRemoveSystem = bRemoveInstantly || ( bDestroyAsleepSystems && ( flNow >= pTmp->m_flNextSleepTime ) );
			if ( bRemoveSystem )
			{
				m_ParticleEffects.Remove( i );
				pTmp->SetOwner( NULL );
			}
			pTmp->StopEmission( false, bRemoveSystem, !bRemoveSystem && bWakeOnStop );
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: Remove effects immediately, including all current particles. If no
// effect is specified, all effects attached to this entity are removed.
//-----------------------------------------------------------------------------
void CParticleProperty::StopEmissionAndDestroyImmediately( CNewParticleEffect *pEffect )
{
	if ( pEffect )
	{
		int iIndex = FindEffect( pEffect );
		//Assert( iIndex != -1 );
		if ( iIndex != -1 )
		{
			m_ParticleEffects.Remove( iIndex );

			// Clear the owner so it doesn't try to call back to us on deletion
			pEffect->SetOwner( NULL );
			pEffect->StopEmission( false, true );
		}
	}
	else
	{
		// Immediately destroy all effects
		int nCount = m_ParticleEffects.Count();
		for ( int i = nCount-1; i >= 0; i-- )
		{
			CNewParticleEffect *pTmp = m_ParticleEffects[i].pParticleEffect.GetObject();
			m_ParticleEffects.Remove( i );

			// Clear the owner so it doesn't try to call back to us on deletion
			pTmp->SetOwner( NULL );
			pTmp->StopEmission( false, true );
		}
	}
}
Esempio n. 4
0
CNewParticleEffect *CParticleProperty::Create( CParticleSystemDefinition *pDef, ParticleAttachment_t iAttachType, int iAttachmentPoint, Vector vecOriginOffset, matrix3x4_t *matOffset )
{
	int nBatchMode = cl_particle_batch_mode.GetInt();
	bool bRequestedBatch = ( nBatchMode == 2 ) || ( ( nBatchMode == 1 ) && pDef && pDef->ShouldBatch() ); 
	if ( ( iAttachType == PATTACH_CUSTOMORIGIN ) && bRequestedBatch )
	{
		int iIndex = FindEffect( pDef->GetName() );
		if ( iIndex >= 0 )
		{
			CNewParticleEffect *pEffect = m_ParticleEffects[iIndex].pParticleEffect.GetObject();
			pEffect->Restart();
			return pEffect;
		}
	}

	int iIndex = m_ParticleEffects.AddToTail();
	ParticleEffectList_t *newEffect = &m_ParticleEffects[iIndex];
	newEffect->pParticleEffect = CNewParticleEffect::Create( m_pOuter, pDef, pDef->GetName() );

	if ( !newEffect->pParticleEffect->IsValid() )
	{
		// Caused by trying to spawn an unregistered particle effect. Remove it.
		ParticleMgr()->RemoveEffect( newEffect->pParticleEffect.GetObject() );
		return NULL;
	}

	AddControlPoint( iIndex, 0, GetOuter(), iAttachType, iAttachmentPoint, vecOriginOffset, matOffset );

	if ( m_pOuter )
	{
		m_pOuter->OnNewParticleEffect( pDef->GetName(), newEffect->pParticleEffect.GetObject() );
	}

	return newEffect->pParticleEffect.GetObject();
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CParticleProperty::OnParticleSystemDeleted( CNewParticleEffect *pEffect )
{
	int iIndex = FindEffect( pEffect );
	if ( iIndex == -1 )
		return;

	m_ParticleEffects[iIndex].pParticleEffect.MarkDeleted();
	m_ParticleEffects.Remove( iIndex );
}
Esempio n. 6
0
// 이펙트오브젝트를 추가한다
EFFECT_OBJ* XBuffObj::AddEffect( EFFECT *pEffect ) 
{	
	EFFECT_OBJ *pEffObj;
	if(( pEffObj = FindEffect( pEffect ) ))	// 이미 같은 효과가 있다면
		return pEffObj;
	// 없는효과면 새로 생성해서 리턴
	pEffObj = new EFFECT_OBJ( pEffect );
	m_listEffectObjs.push_back( pEffObj );		// 이펙오브젝트 리스트에 추가
	return pEffObj;
}
Esempio n. 7
0
void psEffectManager::ShowEffect(unsigned int id,bool value)
{
    psEffect* eff = FindEffect(id);
    if(!eff)
        return;

    // No change?
    if(value == eff->IsVisible())
        return;

    if(value)
        eff->Show();
    else
        eff->Hide();
}
CNewParticleEffect *CParticleProperty::Create( const char *pszParticleName, ParticleAttachment_t iAttachType, int iAttachmentPoint, Vector vecOriginOffset )
{
	if ( GameRules() )
	{
		pszParticleName = GameRules()->TranslateEffectForVisionFilter( "particles", pszParticleName );
	}

	int nBatchMode = cl_particle_batch_mode.GetInt();
	CParticleSystemDefinition *pDef = g_pParticleSystemMgr->FindParticleSystem( pszParticleName );
	bool bRequestedBatch = ( nBatchMode == 2 ) || ( ( nBatchMode == 1 ) && pDef && pDef->ShouldBatch() ); 
	if ( ( iAttachType == PATTACH_CUSTOMORIGIN ) && bRequestedBatch )
	{
		int iIndex = FindEffect( pszParticleName );
		if ( iIndex >= 0 )
		{
			CNewParticleEffect *pEffect = m_ParticleEffects[iIndex].pParticleEffect.GetObject();
			pEffect->Restart();
			return pEffect;
		}
	}

	if ( !pDef )
	{
		AssertMsg( 0, "Attempting to create unknown particle system" );
		Warning( "Attempting to create unknown particle system '%s' \n", pszParticleName );
		return NULL;
	}

	int iIndex = m_ParticleEffects.AddToTail();
	ParticleEffectList_t *newEffect = &m_ParticleEffects[iIndex];
	newEffect->pParticleEffect = CNewParticleEffect::Create( m_pOuter, pDef );

	if ( !newEffect->pParticleEffect->IsValid() )
	{
		// Caused by trying to spawn an unregistered particle effect. Remove it.
		ParticleMgr()->RemoveEffect( newEffect->pParticleEffect.GetObject() );
		return NULL;
	}

	AddControlPoint( iIndex, 0, GetOuter(), iAttachType, iAttachmentPoint, vecOriginOffset );

	if ( m_pOuter )
	{
		m_pOuter->OnNewParticleEffect( pszParticleName, newEffect->pParticleEffect.GetObject() );
	}
	
	return newEffect->pParticleEffect.GetObject();
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CParticleProperty::OnParticleSystemUpdated( CNewParticleEffect *pEffect, float flTimeDelta )
{
	int iIndex = FindEffect( pEffect );
	Assert( iIndex != -1 );
	if ( iIndex == -1 )
		return;

	UpdateParticleEffect( &m_ParticleEffects[iIndex] );

	/*
	// Display the bounding box of the particle effect
	Vector vecMins, vecMaxs;
	pEffect->GetRenderBounds( vecMins, vecMaxs );
	debugoverlay->AddBoxOverlay( pEffect->GetRenderOrigin(), vecMins, vecMaxs, QAngle( 0, 0, 0 ), 0, 255, 255, 0, 0 );
	*/
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CParticleProperty::OnParticleSystemUpdated( CNewParticleEffect *pEffect, float flTimeDelta )
{
	int iIndex = FindEffect( pEffect );
	Assert( iIndex != -1 );
	if ( iIndex == -1 )
		return;

	// Enable FP exceptions here when FP_EXCEPTIONS_ENABLED is defined,
	// to help track down bad math.
	FPExceptionEnabler enableExceptions;

	UpdateParticleEffect( &m_ParticleEffects[iIndex] );

	/*
	// Display the bounding box of the particle effect
	Vector vecMins, vecMaxs;
	pEffect->GetRenderBounds( vecMins, vecMaxs );
	debugoverlay->AddBoxOverlay( pEffect->GetRenderOrigin(), vecMins, vecMaxs, QAngle( 0, 0, 0 ), 0, 255, 255, 0, 0 );
	*/
}
Esempio n. 11
0
void CFixSummonAI::AI()
{
	if(GetRemainedTime() == 0)
	{
		StepEndAI();
		return;
	}
	else
	{
		if(FindEffect(m_vecSummonEffect[0]) == NULL)
		{
			CClientRegion *pRegion = GetGame()->GetRegion();
			float x = GetPosX();
			float y = GetPosY();
			float h = pRegion->GetCellHeight(x, y);
			AddEffect(m_vecSummonEffect[0], x, y, h, true);

			char strFile[MAX_PATH];
			sprintf(strFile, "sounds/skills/%d.wav", m_vecSummonSound[0]);
			GetGame()->GetAudioList()->Play(strFile, x, y, h);
		}
	}
}
Esempio n. 12
0
void LoadReplacementBitmaps (const char *pszLevelName)
{
	char		szFilename [SHORT_FILENAME_LEN];
	CFile		cf;
	int		i, j;
	CBitmap	bm;

//first, free up data allocated for old bitmaps
PrintLog ("   loading replacement textures\n");
CFile::ChangeFilenameExtension (szFilename, pszLevelName, ".pog");
if (cf.Open (szFilename, gameFolders.szDataDir, "rb", 0)) {
	int					id, version, nBitmapNum, bTGA;
	int					bmDataSize, bmDataOffset, bmOffset;
	ushort				*indices;
	tPIGBitmapHeader	*bmh;

	id = cf.ReadInt ();
	version = cf.ReadInt ();
	if (id != MAKE_SIG ('G','O','P','D') || version != 1) {
		cf.Close ();
		return;
		}
	nBitmapNum = cf.ReadInt ();
	indices = new ushort [nBitmapNum];
	bmh = new tPIGBitmapHeader [nBitmapNum];
#if 0
	cf.Read (indices, nBitmapNum * sizeof (ushort), 1);
	cf.Read (bmh, nBitmapNum * sizeof (tPIGBitmapHeader), 1);
#else
	for (i = 0; i < nBitmapNum; i++)
		indices [i] = cf.ReadShort ();
	for (i = 0; i < nBitmapNum; i++)
		PIGBitmapHeaderRead (bmh + i, cf);
#endif
	bmDataOffset = cf.Tell ();
	bmDataSize = cf.Length () - bmDataOffset;

	for (i = 0; i < nBitmapNum; i++) {
		bmOffset = bmh [i].offset;
		memset (&bm, 0, sizeof (CBitmap));
		bm.AddFlags (bmh [i].flags & (BM_FLAGS_TO_COPY | BM_FLAG_TGA));
		bm.SetWidth (bmh [i].width + ((short) (bmh [i].wh_extra & 0x0f) << 8));
		bm.SetRowSize (bm.Width ());
		if ((bTGA = (bm.Flags () & BM_FLAG_TGA)) && (bm.Width () > 256))
			bm.SetHeight (bm.Width () * bmh [i].height);
		else
			bm.SetHeight (bmh [i].height + ((short) (bmh [i].wh_extra & 0xf0) << 4));
		bm.SetBPP (bTGA ? 4 : 1);
		if (!(bm.Width () * bm.Width ()))
			continue;
		bm.SetAvgColorIndex (bmh [i].avgColor);
		bm.SetType (BM_TYPE_ALT);
		if (!bm.CreateBuffer ())
			break;
		cf.Seek (bmDataOffset + bmOffset, SEEK_SET);
#if DBG
		if (indices [i] == nDbgTexture)
			nDbgTexture = nDbgTexture;
#endif
		if (bTGA) {
			int			nFrames = bm.Height () / bm.Width ();
			tTgaHeader	h;

			h.width = bm.Width ();
			h.height = bm.Width ();
			h.bits = 32;
			if (!ReadTGAImage (cf, &h, &bm, -1, 1.0, 0, 1)) {
				bm.DestroyBuffer ();
				break;
				}
			bm.SetFrameCount ((ubyte) nFrames);
			if (nFrames > 1) {
				tEffectClip	*ecP = NULL;
				tWallClip *wcP;
				tVideoClip *vcP;
				while ((ecP = FindEffect (ecP, indices [i]))) {
					//e->vc.nFrameCount = nFrames;
					ecP->flags |= EF_ALTFMT | EF_FROMPOG;
					}
				if (!ecP) {
					if ((wcP = FindWallAnim (indices [i]))) {
						//w->nFrameCount = nFrames;
						wcP->flags |= WCF_ALTFMT | WCF_FROMPOG;
						}
					else if ((vcP = FindVClip (i))) {
						//v->nFrameCount = nFrames;
						vcP->flags |= WCF_ALTFMT | WCF_FROMPOG;
						}
					}
				}
			j = indices [i];
			bm.SetId (j);
			}
		else {
#if DBG
			if (j == nDbgTexture)
				nDbgTexture = nDbgTexture;
#endif
			ReadBitmap (&bm, int (bm.Width ()) * int (bm.Height ()), &cf, true, false);
			j = indices [i];
			bm.SetId (j);
			bm.RLEExpand (NULL, 0);
			*bm.Props () = *gameData.pig.tex.bitmapP [j].Props ();
			bm.Remap (paletteManager.Game (), TRANSPARENCY_COLOR, SUPER_TRANSP_COLOR);
			}
#if DBG
		if (j == nDbgTexture)
			nDbgTexture = nDbgTexture;
#endif
		gameData.pig.tex.bitmapP [j].Unload (j, 0);
		bm.SetFromPog (1);
		char szName [20];
		if (*gameData.pig.tex.bitmapP [j].Name ())
			sprintf (szName, "[%s]", gameData.pig.tex.bitmapP [j].Name ());
		else
			sprintf (szName, "POG#%04d", j);
		bm.SetName (szName);
		gameData.pig.tex.altBitmapP [j] = bm;
		gameData.pig.tex.altBitmapP [j].SetBuffer (bm.Buffer (), 0, bm.Length ());
		bm.SetBuffer (NULL);
		gameData.pig.tex.bitmapP [j].SetOverride (gameData.pig.tex.altBitmapP + j);
		CBitmap* bmP = gameData.pig.tex.altBitmapP + j;
		tRgbColorf color;
		if (0 <= bmP->AvgColor (&color))
			bmP->SetAvgColorIndex (bmP->Palette ()->ClosestColor (&color));
		UseBitmapCache (gameData.pig.tex.altBitmapP + j, (int) bm.Width () * (int) bm.RowSize ());
		}
	delete[] indices;
	delete[] bmh;
	cf.Close ();
	paletteManager.SetLastPig ("");
	TexMergeFlush ();       //for re-merging with new textures
	}
}
Esempio n. 13
0
int PageInBitmap (CBitmap *bmP, const char *bmName, int nIndex, int bD1, bool bHires)
{
	CBitmap			*altBmP = NULL;
	int				nFile, nSize, nOffset, nFrames, nShrinkFactor, nBestShrinkFactor,
						bRedone = 0, bTGA;
	sbyte				nFlags;
	bool				bDefault = false;
	CFile				cf, *cfP = &cf;
	char				fn [6][FILENAME_LEN];

#if DBG
if (!bmName)
	return 0;
if ((nDbgTexture > 0) && (nIndex == nDbgTexture))
	nDbgTexture = nDbgTexture;
#endif
if (bmP->Buffer ())
	return 1;

StopTime ();
nShrinkFactor = 8 >> min (gameOpts->render.textures.nQuality, gameStates.render.nMaxTextureQuality);
if (nShrinkFactor < 4) {
	if (nShrinkFactor == 1)
		nShrinkFactor = 2;	// cap texture quality at 256x256 (x frame#)
	else if (IsPowerup (bmName) || IsWeapon (bmName))	// force downscaling of powerup hires textures
		nShrinkFactor <<= 1;
	}
nSize = (int) bmP->FrameSize ();
if (nIndex >= 0)
	GetFlagData (bmName, nIndex);
#if DBG
if (strstr (bmName, "metl139"))
	bmName = bmName;
#endif
if (gameStates.app.bNostalgia)
	gameOpts->render.textures.bUseHires [0] = 0;

bTGA = 0;
nFlags = (nIndex < 0) ? 0 : gameData.pig.tex.bitmapFlags [bD1][nIndex];
if (bmP->Texture ())
	bmP->Texture ()->Release ();
bmP->SetBPP (1);

if ((*bmName && /*!gameStates.app.bDemoData &&*/ ((nIndex < 0) || IsCockpit (bmName) || bHires || gameOpts->render.textures.bUseHires [0])) &&
	 !(gameOpts->render.powerups.b3D && IsWeapon (bmName) && !gameStates.app.bHaveMod)) {
#if 0
	if ((nIndex >= 0) && ReadS3TC (gameData.pig.tex.altBitmaps [bD1] + nIndex, gameFolders.szTextureCacheDir [bD1], bmName)) {
		altBmP = gameData.pig.tex.altBitmaps [bD1] + nIndex;
		altBmP->nType = BM_TYPE_ALT;
		bmP->SetOverride (altBmP);
		BM_FRAMECOUNT (altBmP) = 1;
		nFlags &= ~BM_FLAG_RLE;
		nFlags |= BM_FLAG_TGA;
		bmP = altBmP;
		altBmP = NULL;
		}
	else
#endif
	if (*gameFolders.szTextureDir [2]) {
		char szLevelFolder [FILENAME_LEN];
		if (gameData.missions.nCurrentLevel < 0)
			sprintf (szLevelFolder, "slevel%02d", -gameData.missions.nCurrentLevel);
		else
			sprintf (szLevelFolder, "level%02d", gameData.missions.nCurrentLevel);
		sprintf (gameFolders.szTextureDir [3], "%s/%s", gameFolders.szTextureDir [2], szLevelFolder);
		sprintf (gameFolders.szTextureCacheDir [3], "%s/%s", gameFolders.szTextureCacheDir [2], szLevelFolder);
		}
	else
		*gameFolders.szTextureDir [3] =
		*gameFolders.szTextureCacheDir [3] = '\0';
	MakeBitmapFilenames (bmName, gameFolders.szTextureDir [3], gameFolders.szTextureCacheDir [3], fn [1], fn [0], nShrinkFactor);
	MakeBitmapFilenames (bmName, gameFolders.szTextureDir [2], gameFolders.szTextureCacheDir [2], fn [3], fn [2], nShrinkFactor);
	MakeBitmapFilenames (bmName, gameFolders.szTextureDir [bD1], gameFolders.szTextureCacheDir [bD1], fn [5], fn [4], nShrinkFactor);

	if (0 <= (nFile = OpenBitmapFile (fn, cfP))) {
		cfP->Close ();
		PrintLog ("loading hires texture '%s' (quality: %d)\n", fn [nFile], min (gameOpts->render.textures.nQuality, gameStates.render.nMaxTextureQuality));
		if (nFile < 2)	//was level specific mod folder
			MakeTexSubFolders (gameFolders.szTextureCacheDir [3]);
		if (nIndex < 0)
			altBmP = &gameData.pig.tex.addonBitmaps [-nIndex - 1];
		else
			altBmP = &gameData.pig.tex.altBitmaps [bD1][nIndex];
		if (!ReadTGA (fn [nFile], "", altBmP)) {
			altBmP = NULL;
			if (!bDefault)
				cfP->Close ();
			throw (EX_OUT_OF_MEMORY);
			}
		else {
			bTGA = 1;
			if (strstr (fn [nFile], "omegblob#") && strstr (fn [nFile], "/mods/"))
				gameStates.render.bOmegaModded = 1;
			altBmP->SetType (BM_TYPE_ALT);
			bmP->SetOverride (altBmP);
			bmP = altBmP;
			bmP->DelFlags (BM_FLAG_RLE);
			nSize = bmP->Size ();
			nFrames = (bmP->Height () % bmP->Width ()) ? 1 : bmP->Height () / bmP->Width ();
			bmP->SetFrameCount (ubyte (nFrames));
			nOffset = -1;
			if (nIndex >= 0) {
				nFlags = bmP->Flags ();
				if (bmP->Height () > bmP->Width ()) {
					tEffectClip	*ecP = NULL;
					tWallClip *wcP;
					tVideoClip *vcP;
					while ((ecP = FindEffect (ecP, nIndex))) {
						//e->vc.nFrameCount = nFrames;
						ecP->flags |= EF_ALTFMT;
						//ecP->vClipInfo.flags |= WCF_ALTFMT;
						}
					if (!ecP) {
						if ((wcP = FindWallAnim (nIndex))) {
						//w->nFrameCount = nFrames;
							wcP->flags |= WCF_ALTFMT;
							}
						else if ((vcP = FindVClip (nIndex))) {
							//v->nFrameCount = nFrames;
							vcP->flags |= WCF_ALTFMT;
							}
						else {
							PrintLog ("   couldn't find animation for '%s'\n", bmName);
							}
						}
					}
				}
			}
		}
	}

if (!altBmP) {
	if (nIndex < 0) {
		StartTime (0);
		return 0;
		}
	cfP = cfPiggy + bD1;
	if (!cfP->File ())
		PiggyInitPigFile (NULL);
	nOffset = bitmapOffsets [bD1][nIndex];
	bDefault = true;
	}

bRedone = 1;
if ((nOffset >= 0) && cfP->Seek (nOffset, SEEK_SET)) {
	if (!bDefault)
		cfP->Close ();
	throw (EX_IO_ERROR);
	}
#if 1//DBG
bmP->SetName (bmName);
#endif
#if TEXTURE_COMPRESSION
if (bmP->Compressed ())
	UseBitmapCache (bmP, bmP->CompressedSize ());
else
#endif
	{
	if (bTGA || bmP->CreateBuffer ())
		UseBitmapCache (bmP, nSize);
	}
if (!bmP->Buffer () || (bitmapCacheUsed > bitmapCacheSize)) {
	if (!bDefault)
		cfP->Close ();
	throw (EX_OUT_OF_MEMORY);
	}
if (!bTGA && (nIndex >= 0))
	bmP->SetFlags (nFlags);
bmP->SetId (nIndex);
#if DBG
if (nIndex == nDbgTexture)
	nDbgTexture = nDbgTexture;
#endif
int i = ReadBitmap (bmP, nSize, cfP, bDefault, bD1 != 0, bHires);
if (i) {
	if (i < 0) {
		if (!bDefault)
			cfP->Close ();
		throw (EX_IO_ERROR);
		}
	}
else
#if TEXTURE_COMPRESSION
if (!bmP->Compressed ())
#endif
	{
	bmP->SetType (BM_TYPE_ALT);
	bmP->SetTranspType (-1);
	if (IsOpaqueDoor (nIndex)) {
		bmP->DelFlags (BM_FLAG_TRANSPARENT);
		bmP->TransparentFrames () [0] &= ~1;
		}
#if TEXTURE_COMPRESSION
	if (CompressTGA (bmP))
		bmP->SaveS3TC (gameFolders.szTextureCacheDir [(nFile < 2) ? 3 : (nFile < 4) ? 2 : bD1], bmName);
	else {
#endif
		nBestShrinkFactor = BestShrinkFactor (bmP, nShrinkFactor);
		if ((nBestShrinkFactor > 1) && ShrinkTGA (bmP, nBestShrinkFactor, nBestShrinkFactor, 1)) {
			nSize /= (nBestShrinkFactor * nBestShrinkFactor);
			if (gameStates.app.bCacheTextures) {
				tTgaHeader	h;

				memset (&h, 0, sizeof (h));
				h.bits = bmP->BPP () * 8;
				h.width = bmP->Width ();
				h.height = bmP->Height ();
				h.imageType = 2;
				// nFile < 2: mod level texture folder
				// nFile < 4: mod texture folder
				// otherwise standard D1 or D2 texture folder
				SaveTGA (bmName, gameFolders.szTextureCacheDir [(nFile < 2) ? 3 : (nFile < 4) ? 2 : bD1], &h, bmP);
				}
			}
		}
#if TEXTURE_COMPRESSION
	}
#endif

#if DBG
nPrevIndex = nIndex;
strcpy (szPrevBm, bmName);
#endif
tRgbColorf color;
if (0 <= (bmP->AvgColor (&color)))
	bmP->SetAvgColorIndex (ubyte (bmP->Palette ()->ClosestColor (&color)));
StartTime (0);
if (!bDefault)
	cfP->Close ();
return 1;
}