void CGibFX::CreateBloodSpray()
{
	CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr();
	if (!psfxMgr) return;

	BSCREATESTRUCT sc;

	VEC_COPY(sc.vPos, m_vPos);
	sc.vPos.y += 30.0f;
	VEC_SET(sc.vVel, 0.0f, -20.0f, 0.0f);
	VEC_SET(sc.vInitialScale, GetRandom(2.0f, 4.0f), GetRandom(2.0f, 4.0f), 1.0f);
	VEC_SET(sc.vFinalScale, GetRandom(0.5f, 0.8f), GetRandom(0.5f, 0.8f), 1.0f);

	sc.dwFlags			= FLAG_VISIBLE | FLAG_SPRITEBIAS | FLAG_NOLIGHT;
	sc.fLifeTime		= 0.5f;
	sc.fInitialAlpha	= 1.0f;
	sc.fFinalAlpha		= 0.0f;
	sc.nType			= OT_SPRITE;

	char* pBloodFiles[] =
	{
		"Sprites\\BloodSplat1.spr",
		"Sprites\\BloodSplat2.spr",
		"Sprites\\BloodSplat3.spr",
		"Sprites\\BloodSplat4.spr"
	};

	sc.pFilename = pBloodFiles[GetRandom(0,3)];


	CSpecialFX* pFX = psfxMgr->CreateSFX(SFX_SCALE_ID, &sc);
	if (pFX) pFX->Update();
}
Пример #2
0
void CWeaponFX::CreateMark(LTVector vPos, LTVector vNorm, LTRotation rRot,
						   SurfaceType eType)
{
	IMPACTFX* pImpactFX = m_pAmmo->pImpactFX;

	if (IsLiquid(m_eCode))
	{
		pImpactFX = m_pAmmo->pUWImpactFX;
	}

	if (!pImpactFX) return;

	CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr();
	if (!psfxMgr) return;

	MARKCREATESTRUCT mark;

	mark.m_vPos = vPos;
	mark.m_Rotation = rRot;

	// Randomly rotate the bullet hole...

    g_pLTClient->RotateAroundAxis(&mark.m_Rotation, &vNorm, GetRandom(0.0f, MATH_CIRCLE));

	mark.m_fScale		= pImpactFX->fMarkScale;
	mark.nAmmoId		= m_nAmmoId;
	mark.nSurfaceType   = eType;

	psfxMgr->CreateSFX(SFX_MARK_ID, &mark);
}
Пример #3
0
// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CAutoTargetMgr::AddMagnets()
//
//	PURPOSE:	Add any aim magnets in our cone to the array
//
// ----------------------------------------------------------------------- //
void CAutoTargetMgr::AddMagnets()
{
	CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr();

	//step through the chars
	CSpecialFXList* const pMagnetList = psfxMgr->GetFXList(SFX_AIMMAGNET_ID);	
	int nNumSFX  = pMagnetList->GetSize();
	
	for (int nMag=0; nMag < nNumSFX; nMag++)
	{
		CAimMagnetFX* pMag = (CAimMagnetFX*)(*pMagnetList)[nMag];
		if (pMag)
		{
			uint32 dwFlags;
			g_pCommonLT->GetObjectFlags(pMag->GetServerObj(), OFT_Flags, dwFlags);

			if (!(dwFlags & FLAG_VISIBLE))
				continue;

			//filter out anyone outside the cone
			LTVector vTargetPos;
			g_pLTClient->GetObjectPos(pMag->GetTarget(), &vTargetPos);

			if (IsPointInCone( vTargetPos ) && m_nNodeCount < MAX_AUTOTARGET_NODES)
			{
				m_NodeArray[m_nNodeCount].vPos = vTargetPos;
				m_NodeArray[m_nNodeCount].hChar = pMag->GetTarget();
				m_nNodeCount++;
			}
		}
	}

}
Пример #4
0
void CWeaponFX::CreateBulletTrail(LTVector *pvStartPos)
{
	CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr();
	if (!psfxMgr || !pvStartPos) return;

    LTVector vColor1, vColor2;
	vColor1.Init(200.0f, 200.0f, 200.0f);
	vColor2.Init(255.0f, 255.0f, 255.0f);

	BTCREATESTRUCT bt;

	bt.vStartPos		= *pvStartPos;
	bt.vDir				= m_vDir;
	bt.vColor1			= vColor1;
	bt.vColor2			= vColor2;
	bt.fLifeTime		= 0.5f;
	bt.fFadeTime		= 0.3f;
	bt.fRadius			= 400.0f;
	bt.fGravity			= 0.0f;
	bt.fNumParticles	= (m_nDetailLevel == RS_MED) ? 15.0f : 30.0f;

	CSpecialFX* pFX = psfxMgr->CreateSFX(SFX_BULLETTRAIL_ID, &bt);

	// Let each bullet trail do its initial update...

	if (pFX) pFX->Update();
}
Пример #5
0
void CDeathFX::CreateVehicleDeathFX()
{
	CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr();
	if (!psfxMgr) return;

	GIBCREATESTRUCT gib;

    m_pClientDE->AlignRotation(&(gib.rRot), &m_vDir, LTNULL);

    LTFLOAT fDamage = VEC_MAG(m_vDir);

	VEC_COPY(gib.vPos, m_vPos);
	VEC_SET(gib.vMinVel, 50.0f, 100.0f, 50.0f);
	VEC_MULSCALAR(gib.vMinVel, gib.vMinVel, fDamage);
	VEC_SET(gib.vMaxVel, 100.0f, 200.0f, 100.0f);
	VEC_MULSCALAR(gib.vMaxVel, gib.vMaxVel, fDamage);
	gib.fLifeTime		= 20.0f;
	gib.fFadeTime		= 7.0f;
	gib.nGibFlags		= 0;
    gib.bRotate         = LTTRUE;
	gib.eModelId		= m_eModelId;
	gib.eModelStyle		= m_eModelStyle;
	gib.nCode			= m_eCode;
    gib.bSubGibs        = LTTRUE;

	SetupGibTypes(gib);

	psfxMgr->CreateSFX(SFX_GIB_ID, &gib);
}
Пример #6
0
void CWeaponFX::CreateTracer()
{
	if (!m_pAmmo || !m_pAmmo->pTracerFX) return;

	CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr();
	if (!psfxMgr) return;

	if (m_nDetailLevel != RS_HIGH && GetRandom(1, 2) == 1) return;

	// Create tracer...

	if (m_fFireDistance > 100.0f)
	{
		TRCREATESTRUCT tracer;

		// Make tracer start in front of gun a little ways...

		tracer.vStartPos	= m_vFirePos; // + (m_vDir * 25.0f);
		tracer.vEndPos		= m_vPos;
		tracer.pTracerFX	= m_pAmmo->pTracerFX;

		CSpecialFX* pFX = psfxMgr->CreateSFX(SFX_TRACER_ID, &tracer);
		if (pFX) pFX->Update();
	}
}
void CGibFX::CreateLingeringSmoke(int nIndex)
{
	CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr();
	if (!psfxMgr) return;

	CGameSettings* pSettings = g_pInterfaceMgr->GetSettings();
	if (!pSettings) return;

    uint8 nDetailLevel = pSettings->SpecialFXSetting();
	if (nDetailLevel == RS_LOW) return;

	SMCREATESTRUCT sm;

	char* pTexture = "Sprites\\SmokeTest.spr";

	VEC_SET(sm.vColor1, 100.0f, 100.0f, 100.0f);
	VEC_SET(sm.vColor2, 125.0f, 125.0f, 125.0f);
	VEC_SET(sm.vMinDriftVel, -10.0f, 25.0f, -10.0f);
	VEC_SET(sm.vMaxDriftVel, 10.0f, 50.0f, 10.0f);

    LTFLOAT fVolumeRadius        = 10.0f;
    LTFLOAT fLifeTime            = GetRandom(m_fLifeTime * 0.75f, m_fLifeTime);
    LTFLOAT fRadius              = 1500;
    LTFLOAT fParticleCreateDelta = 0.1f;
    LTFLOAT fMinParticleLife     = 1.0f;
    LTFLOAT fMaxParticleLife     = 5.0f;
    uint8  nNumParticles        = 3;
    LTBOOL  bIgnoreWind          = LTFALSE;

	if (IsLiquid(m_eCode))
	{
		GetLiquidColorRange(m_eCode, &sm.vColor1, &sm.vColor2);
		pTexture			= DEFAULT_BUBBLE_TEXTURE;
		fRadius				= 750.0f;
        bIgnoreWind         = LTTRUE;
		fMinParticleLife	= 1.0f;
		fMaxParticleLife	= 1.5f;
	}

	sm.vPos					= m_Emitters[nIndex].m_vPos;
	sm.hServerObj 		    = m_hGib[nIndex];
	sm.fVolumeRadius		= fVolumeRadius;
	sm.fLifeTime			= fLifeTime;
	sm.fRadius				= fRadius;
	sm.fParticleCreateDelta	= fParticleCreateDelta;
	sm.fMinParticleLife		= fMinParticleLife;
	sm.fMaxParticleLife		= fMaxParticleLife;
	sm.nNumParticles		= nNumParticles;
	sm.bIgnoreWind			= bIgnoreWind;
	sm.hstrTexture			= m_pClientDE->CreateString(pTexture);

	psfxMgr->CreateSFX(SFX_SMOKE_ID, &sm);

	m_pClientDE->FreeString(sm.hstrTexture);
}
Пример #8
0
LTBOOL CParticleTrailFX::Update()
{
	CSFXMgr* psfxMgr = g_pRiotClientShell->GetSFXMgr();
	if (!psfxMgr || !m_pClientDE || !m_hServerObject) return LTFALSE;

	LTFLOAT fTime = m_pClientDE->GetTime();

	// Check to see if we should go away...

	if (m_bWantRemove)
	{
		return LTFALSE;
	}


	// See if it is time to create a new trail segment...

	if ((m_fStartTime < 0) || (fTime > m_fStartTime + m_fSegmentTime))
	{
		PTSCREATESTRUCT pts;

		pts.hServerObj = m_hServerObject;
		VEC_COPY(pts.vColor1, m_vColor1);
		VEC_COPY(pts.vColor2, m_vColor2);
		VEC_COPY(pts.vDriftOffset, m_vDriftOffset);
		pts.nType			= m_nType;
		pts.bSmall			= m_bSmall;
		pts.fLifeTime		= m_fLifeTime;
		pts.fFadeTime		= m_fFadeTime;
		pts.fOffsetTime		= m_fOffsetTime;
		pts.fRadius			= 2000.0f;
		pts.fGravity		= 0.0f;
		pts.nNumPerPuff		= m_nNumPerPuff;

		if (m_nType & PT_BLOOD)
		{
			pts.fRadius	 = 600.0f;
		}
		else if (m_nType & PT_GIBSMOKE)
		{
			pts.fRadius	 = 1250.0f;
		}

		CSpecialFX* pFX = psfxMgr->CreateSFX(SFX_PARTICLETRAILSEG_ID, &pts);

		// Let each Particle segment do its initial update...

		if (pFX) pFX->Update();

		m_fStartTime = fTime;
	}

	return LTTRUE;
}
Пример #9
0
DBOOL CSmokeTrailFX::Update()
{
	CBloodClientShell *pShell = (CBloodClientShell*)g_pClientDE->GetClientShell();
	CSFXMgr* psfxMgr = pShell->GetSFXMgr();
	if (!psfxMgr || !m_pClientDE || !m_hServerObject) return DFALSE;

	DFLOAT fTime = m_pClientDE->GetTime();

	// Check to see if we should go away...

	if (m_bWantRemove)
	{
		return DFALSE;
	}


	// See if it is time to create a new trail segment...
	if ((m_fStartTime < 0) || (fTime > m_fStartTime + m_fSegmentTime))
	{
		STSCREATESTRUCT sts;

		sts.hServerObj = m_hServerObject;
		VEC_COPY(sts.vVel, m_vVel);
		VEC_COPY(sts.vColor1, m_vColor1);
		VEC_COPY(sts.vColor2, m_vColor2);
		sts.bSmall			= m_bSmall;
		sts.fLifeTime		= m_fLifeTime;
		sts.fFadeTime		= m_fFadeTime;
		sts.fOffsetTime		= m_fOffsetTime;
		sts.fRadius			= 1000.0f;
		sts.fGravity		= 15.0f;
		sts.nNumPerPuff		= m_nNumPerPuff;

		if(VEC_MAG(sts.vVel) < 1.0f)
		{
			sts.fGravity = 25.0f;
			sts.fOffsetTime = 0.1f;
			sts.fRadius = 500.0f;
			sts.nNumPerPuff = 1;
			sts.fLifeTime = 1.0f;
		}

 		CSpecialFX* pFX = psfxMgr->CreateSFX(SFX_SMOKETRAILSEG_ID, &sts, DFALSE, this);

		// Let each smoke segment do its initial update...
		if (pFX) pFX->Update();

		m_fStartTime = fTime;
	}

	return DTRUE;
}
Пример #10
0
void CWeaponFX::CreateShell()
{
	CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr();
	if (!psfxMgr) return;

	SHELLCREATESTRUCT sc;
	sc.rRot		 = m_rDirRot;
	sc.vStartPos = m_vFirePos;
	sc.nWeaponId = m_nWeaponId;
	sc.nAmmoId	 = m_nAmmoId;

    sc.b3rdPerson = LTFALSE;

	// See if this is our local client who fired, and if so are we in 3rd person...

	if (m_nLocalId == m_nShooterId)
	{
		sc.b3rdPerson = !g_pGameClientShell->IsFirstPerson();
	}
	else
	{
        sc.b3rdPerson = LTTRUE;
	}


	// Adjust the shell position based on the hand-held breach offset...

	if (sc.b3rdPerson)
	{
		sc.vStartPos += (m_vDir * m_pWeapon->fHHBreachOffset);
	}
	else  // Get the shell eject pos...
	{
		sc.vStartPos = g_pGameClientShell->GetWeaponModel()->GetShellEjectPos(sc.vStartPos);

		// Add on the player's velocity...

		HOBJECT hObj = g_pGameClientShell->GetMoveMgr()->GetObject();
		if (hObj)
		{
            g_pLTClient->Physics()->GetVelocity(hObj, &sc.vStartVel);
		}
		//sc.dwFlags = FLAG_REALLYCLOSE;
	}


	// Only create every other shell if medium detail set...
	// if (m_nDetailLevel == RS_MED && (++s_nNumShells % 2 == 0)) return;

	psfxMgr->CreateSFX(SFX_SHELLCASING_ID, &sc);
}
Пример #11
0
void CGibFX::CreateMiniBloodExplosion(int nIndex)
{
	// Add a mini blood explosion...

	CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr();
	if (!psfxMgr) return;

	CGameSettings* pSettings = g_pInterfaceMgr->GetSettings();
	if (!pSettings) return;

    uint8 nDetailLevel = pSettings->SpecialFXSetting();
	if (nDetailLevel == RS_LOW) return;

	char* szBlood[2] = { "SpecialFX\\ParticleTextures\\Blood_1.dtx",
					     "SpecialFX\\ParticleTextures\\Blood_2.dtx" };

	PARTICLESHOWERCREATESTRUCT ps;

	ps.vPos = m_Emitters[nIndex].m_vPos;
	ps.vPos.y += 30.0f;

	ps.vDir.Init(0, 100, 0);
	VEC_SET(ps.vColor1, 200.0f, 200.0f, 200.0f);
	VEC_SET(ps.vColor2, 255.0f, 255.0f, 255.0f);
	ps.pTexture			= szBlood[GetRandom(0,1)];;
	ps.nParticles		= 50;
	ps.fDuration		= 1.0f;
	ps.fEmissionRadius	= 0.3f;
	ps.fRadius			= 800.0f;
	ps.fGravity			= PSFX_DEFAULT_GRAVITY;

	if (IsLiquid(m_eCode))
	{
		ps.vDir	*= 3.0f;
		ps.fEmissionRadius	= 0.2f;
		ps.fRadius			= 700.0f;
	}

	psfxMgr->CreateSFX(SFX_PARTICLESHOWER_ID, &ps);

	// Play appropriate sound...

	char* pSound = GetGibDieSound();

	if (pSound)
	{
		g_pClientSoundMgr->PlaySoundFromPos(ps.vPos, pSound, 300.0f,
			SOUNDPRIORITY_MISC_LOW);
	}
}
Пример #12
0
void CWeaponFX::CreateMuzzleLight()
{
	// Check to see if we have the silencer...

	if (m_wFireFX & WFX_SILENCED) return;

	if (m_nLocalId != m_nShooterId || !g_pGameClientShell->IsFirstPerson())
	{
		MUZZLEFLASHCREATESTRUCT mf;

		mf.pWeapon	= m_pWeapon;
		mf.hParent	= m_hFiredFrom;
		mf.vPos		= m_vFirePos;
		mf.rRot		= m_rDirRot;

		CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr();
		if (!psfxMgr) return;

		psfxMgr->CreateSFX(SFX_MUZZLEFLASH_ID, &mf);
	}
}
Пример #13
0
void CWeaponFX::CreateMuzzleFX()
{
	CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr();
	if (!psfxMgr) return;


	char* pTexture = "SFX\\Impact\\Spr\\Smoke.spr";

	if (IsLiquid(m_eFirePosCode))
	{
		pTexture = DEFAULT_BUBBLE_TEXTURE;
	}

	PARTICLESHOWERCREATESTRUCT sp;

	sp.vPos				= m_vFirePos;
	sp.vDir				= m_vSurfaceNormal * 10.0f;
	sp.pTexture			= pTexture;
	sp.nParticles		= 1;
	sp.fRadius			= 400.0f;
	sp.fDuration		= 1.0f;
	sp.fEmissionRadius	= 0.05f;
	sp.fRadius			= 800.0f;
	sp.fGravity			= 0.0f;

	sp.vColor1.Init(100.0f, 100.0f, 100.0f);
	sp.vColor2.Init(125.0f, 125.0f, 125.0f);

	if (IsLiquid(m_eFirePosCode))
	{
		GetLiquidColorRange(m_eFirePosCode, &sp.vColor1, &sp.vColor2);
		sp.fRadius		= 600.0f;
		sp.fGravity		= 50.0f;
	}

	psfxMgr->CreateSFX(SFX_PARTICLESHOWER_ID, &sp);
}
Пример #14
0
DBOOL CBloodTrailFX::Update()
{
	CBloodClientShell *pShell = (CBloodClientShell*)g_pClientDE->GetClientShell();
	CSFXMgr* psfxMgr = pShell->GetSFXMgr();
	if (!psfxMgr || !m_pClientDE || !m_hServerObject) return DFALSE;

	DFLOAT fTime = m_pClientDE->GetTime();

	// Check to see if we should go away...

	if (m_bWantRemove || (m_hServerObject == DNULL))
	{
		return DFALSE;
	}


	// See if it is time to create a new trail segment...

	if ((m_fStartTime < 0) || (fTime > m_fStartTime + m_fSegmentTime))
	{
		BTSCREATESTRUCT bts;

		bts.hServerObj = m_hObject;
		VEC_COPY(bts.vColor1, m_vColor);
		bts.fLifeTime		= m_fLifeTime;
		bts.fOffsetTime		= m_fOffsetTime;
		bts.fRadius			= 200.0f;
		bts.nNumPerPuff		= m_nNumPerPuff;

 		CSpecialFX* pFX = psfxMgr->CreateSFX(SFX_BLOODTRAILSEG_ID, &bts, DFALSE, this);
		if (pFX) pFX->Update();
 
		m_fStartTime = fTime;
	}

	return DTRUE;
}
Пример #15
0
// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CAutoTargetMgr::GenerateCharArray()
//
//	PURPOSE:	Fill array with list of chars sorted by distance
//
// ----------------------------------------------------------------------- //
void CAutoTargetMgr::GenerateCharArray()
{
	//clear our target array
	m_Targets.resize(0);

	CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr();

	//step through the chars
	CSpecialFXList* const pCharList = psfxMgr->GetFXList(SFX_CHARACTER_ID);	
	int nNumSFX  = pCharList->GetSize();
	
	for (int nChar=0; nChar < nNumSFX; nChar++)
	{
		CCharacterFX* pChar = (CCharacterFX*)(*pCharList)[nChar];
		if (pChar)
		{
			if (pChar->m_cs.bIsPlayer)
			{
				//filter out local player
			    HLOCALOBJ hPlayerObj = g_pLTClient->GetClientObject();
			    if (hPlayerObj == pChar->GetServerObj())
					continue;
				if(pChar->IsPlayerDead())
					continue;

				//if this is a team game filter out our teammates
				if (GameModeMgr::Instance( ).m_grbUseTeams )
				{
					// Get the client information of the body and us.
					uint32 nId = pChar->m_cs.nClientID;
					CClientInfoMgr* pCIMgr = g_pInterfaceMgr->GetClientInfoMgr();
					CLIENT_INFO* pCI = pCIMgr->GetClientByID(nId);
					CLIENT_INFO *pLocalCI = g_pInterfaceMgr->GetClientInfoMgr()->GetLocalClient();

					// Only allow us to auto-target people on the other team.
					if( pCI && pLocalCI )
					{
						if (pCI->nTeamID == pLocalCI->nTeamID)
							continue;
					}

				}
			}
			else
			{
				// Check alignment of non-players
				if(pChar->m_cs.eCrosshairPlayerStance != kCharStance_Hate)
					continue;
			}

			//filter out anyone outside the cone
			LTVector vTargetPos;
			g_pLTClient->GetObjectPos(pChar->GetServerObj(), &vTargetPos);
			LTVector vOffset(0.0f,32.0f,0.0f);

			// we check both upper and lower parts of the body and if either is in the cone, we're good
			if (IsPointInCone( vTargetPos - vOffset) || IsPointInCone( vTargetPos + vOffset) )
			{
				// we only care about the n closest characters, so...
				// if the new one farther away than the n-th one, drop it, 
				//	otherwise drop the n-th one and insert the new one
			
				//step through the chars we already know about...
				CharFXArray::iterator iter = m_Targets.begin();
				bool bInserted = false;
				while (iter != m_Targets.end() && !bInserted)
				{
					//figure out how far away this one is
					CCharacterFX* pTestChar = (CCharacterFX*)(*iter);
					LTVector vTestPos;
					g_pLTClient->GetObjectPos(pTestChar->GetServerObj(), &vTestPos);
					float fTestDistSqr = m_vFirePos.DistSqr(vTestPos);

					//if this char is farther away than the one we're inserting
					if (fTestDistSqr > m_fRangeSqr)
					{
						//if our list is full, pop off the last one...
						if (m_Targets.size() >= MAX_AUTOTARGET_CHARACTERS)
							m_Targets.pop_back();

						m_Targets.insert(iter,pChar);
						bInserted = true;
					}

					iter++;
				}

				//if we haven't inseted it yet, and we have room, add it to the back
				if (!bInserted && m_Targets.size() < MAX_AUTOTARGET_CHARACTERS)
					m_Targets.push_back(pChar);
			}
		}

	}

}
LTBOOL CFireFX::Update()
{
	CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr();
    if (!psfxMgr || !m_pClientDE || !m_hServerObject) return LTFALSE;

    LTFLOAT fTime = m_pClientDE->GetTime();

	// Check to see if we should go away...

	if (m_bWantRemove)
	{
        return LTFALSE;
	}


	// Update FX...

	if (m_cs.bCreateSmoke)
	{
		m_Smoke1.Update();
	}

	if (m_cs.bCreateLight)
	{
		m_Light.Update();
	}

	m_Fire1.Update();
	m_Fire2.Update();


	// Hide/show the fire if necessary...

	if (m_hServerObject)
	{
        uint32 dwUserFlags;
		m_pClientDE->GetObjectUserFlags(m_hServerObject, &dwUserFlags);

		if (!(dwUserFlags & USRFLG_VISIBLE))
		{
			if (m_hSound)
			{
                g_pLTClient->KillSound(m_hSound);
                m_hSound = LTNULL;
			}

            return LTTRUE;
		}
		else
		{
			if (m_cs.bCreateSound && !m_hSound)
			{
				CString str = g_pClientButeMgr->GetSpecialFXAttributeString("FireSnd");

				m_hSound = g_pClientSoundMgr->PlaySoundFromPos(m_cs.vPos, (char*)(LPCSTR)str,
					m_cs.fSoundRadius, SOUNDPRIORITY_MISC_MEDIUM, PLAYSOUND_GETHANDLE | PLAYSOUND_LOOP);
			}
		}
	}

	// Create the random spark particles...

	if (m_cs.bCreateSparks && GetRandom(1, 10) == 1)
	{
		CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr();
        if (!psfxMgr) return LTFALSE;

		RANDOMSPARKSCREATESTRUCT sparks;
		sparks.hServerObj = m_hServerObject;

        LTFLOAT fVel = m_fSizeAdjust * GetRandom(50.0f, 70.0f);
		fVel = (fVel < 30.0f ? 30.0f : (fVel > 100.0f ? 100.0f : fVel));

        LTVector vDir(0.0, 1.0, 0.0);
		sparks.vMinVelAdjust.Init(1, 3, 1);
		sparks.vMaxVelAdjust.Init(1, 6, 1);
		sparks.vDir	= vDir * fVel;
		sparks.nSparks = GetRandom(1, 5);
		sparks.fDuration = m_fSizeAdjust * GetRandom(1.0f, 2.0f);
        sparks.bRelToCameraPos = LTTRUE;
		sparks.fInnerCamRadius = FFX_INNER_CAM_RADIUS;
		sparks.fOuterCamRadius = FFX_INNER_CAM_RADIUS + (FFX_CAM_FALLOFF_RANGE * m_fSizeAdjust);
		sparks.fRadius = 300.0f * m_fSizeAdjust;
		sparks.fRadius = sparks.fRadius < 100.0f ? 100.0f : (sparks.fRadius > 500.0f ? 500.0f : sparks.fRadius);

		psfxMgr->CreateSFX(SFX_RANDOMSPARKS_ID, &sparks);
	}

    return LTTRUE;
}
Пример #17
0
void CGibFX::HandleBounce(int nIndex)
{
	if (nIndex < 0 || nIndex >= m_nNumGibs) return;

	// Play a bounce sound if the gib isn't in liquid...

	if (!(m_Emitters[nIndex].m_dwPhysicsFlags & MO_LIQUID) && (m_hGib[nIndex]))
	{
		if (m_bPlayBounceSound && GetRandom(1, 4) != 1)
		{
			char* pSound = GetBounceSound();

			// Play appropriate sound...

			if (pSound)
			{
				g_pClientSoundMgr->PlaySoundFromPos(m_Emitters[nIndex].m_vPos,
					pSound, 1000.0f, SOUNDPRIORITY_MISC_LOW);
			}
		}
	}


	// See if we're resting...

	m_BounceCount[nIndex]--;
	if (m_BounceCount[nIndex] <= 0)
	{
		m_Emitters[nIndex].m_dwPhysicsFlags |= MO_RESTING;
		if (m_bSubGibs) HandleDoneBouncing(nIndex);
	}


	// Add a blood splat...

	if (m_bBloodSplats)
	{
		// Don't add blood splats on the sky...

        uint32 dwTextureFlags;
		m_pClientDE->GetPolyTextureFlags(m_info.m_hPoly, &dwTextureFlags);
		SurfaceType eType = (SurfaceType)dwTextureFlags;
		if (eType == ST_SKY) return;


		CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr();
		if (!psfxMgr) return;

		BSCREATESTRUCT sc;

        m_pClientDE->AlignRotation(&(sc.rRot), &(m_info.m_Plane.m_Normal), LTNULL    );

        LTVector vTemp;
		VEC_MULSCALAR(vTemp, m_info.m_Plane.m_Normal, 2.0f);
		VEC_ADD(sc.vPos, m_info.m_Point, vTemp);  // Off the wall/floor a bit
		VEC_SET(sc.vVel, 0.0f, 0.0f, 0.0f);
		VEC_SET(sc.vInitialScale, GetRandom(0.3f, 0.5f), GetRandom(0.3f, 0.5f), 1.0f);
		VEC_SET(sc.vFinalScale, GetRandom(0.8f, 1.0f), GetRandom(0.8f, 1.0f), 1.0f);

		sc.dwFlags			= FLAG_VISIBLE | FLAG_ROTATEABLESPRITE | FLAG_NOLIGHT;
		sc.fLifeTime		= m_fLifeTime + 10.0f;
		sc.fInitialAlpha	= 1.0f;
		sc.fFinalAlpha		= 0.0f;
		sc.nType			= OT_SPRITE;

		char* pBloodFiles[] =
		{
			"Sprites\\BloodSplat1.spr",
			"Sprites\\BloodSplat2.spr",
			"Sprites\\BloodSplat3.spr",
			"Sprites\\BloodSplat4.spr"
		};

		sc.pFilename = pBloodFiles[GetRandom(0,3)];


		CSpecialFX* pFX = psfxMgr->CreateSFX(SFX_SCALE_ID, &sc);
		if (pFX) pFX->Update();
	}
}
Пример #18
0
void CWeaponFX::CreateBloodSplatFX()
{
	CGameSettings* pSettings = g_pInterfaceMgr->GetSettings();
	if (!pSettings || !pSettings->Gore()) return;

	CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr();
	if (!psfxMgr) return;

	CSpecialFX* pFX = LTNULL;

	LTFLOAT fRange = g_vtBloodSplatsRange.GetFloat();

	// See if we should make some blood splats...

	ClientIntersectQuery iQuery;
	IntersectInfo iInfo;

	iQuery.m_From = m_vPos;

	LTVector vDir = m_vDir;

	// Create some blood splats...

	int nNumSplats = GetRandom((int)g_vtBloodSplatsMinNum.GetFloat(), (int)g_vtBloodSplatsMaxNum.GetFloat());

	LTVector vU, vR, vF;
    g_pLTClient->GetRotationVectors(&m_rDirRot, &vU, &vR, &vF);

	for (int i=0; i < nNumSplats; i++)
	{
		LTVector vDir = m_vDir;

		// Perturb direction after first splat...

		if (i > 0)
		{
			float fPerturb = g_vtBloodSplatsPerturb.GetFloat();

			float fRPerturb = (GetRandom(-fPerturb, fPerturb))/1000.0f;
			float fUPerturb = (GetRandom(-fPerturb, fPerturb))/1000.0f;

			vDir += (vR * fRPerturb);
			vDir += (vU * fUPerturb);
		}

		iQuery.m_To = vDir * fRange;
		iQuery.m_To += m_vPos;
		iQuery.m_Flags = IGNORE_NONSOLID | INTERSECT_HPOLY;

		if (g_pLTClient->IntersectSegment(&iQuery, &iInfo) && IsMainWorld(iInfo.m_hObject))
		{
			SurfaceType eType = GetSurfaceType(iInfo);
			if (eType == ST_SKY || eType == ST_INVISIBLE)
			{
				return; // Don't leave blood on the sky
			}


			LTBOOL bBigBlood = (LTBOOL)GetConsoleInt("BigBlood", 0);

			// Create a blood splat...

			BSCREATESTRUCT sc;

			g_pLTClient->AlignRotation(&(sc.rRot), &(iInfo.m_Plane.m_Normal), LTNULL);

			// Randomly rotate the blood splat

			g_pLTClient->RotateAroundAxis(&(sc.rRot), &(iInfo.m_Plane.m_Normal), GetRandom(0.0f, MATH_CIRCLE));

			LTVector vTemp = vDir * -2.0f;
			sc.vPos = iInfo.m_Point + vTemp;  // Off the wall a bit
			sc.vVel.Init(0.0f, 0.0f, 0.0f);

			sc.vInitialScale.Init(1.0f, 1.0f, 1.0f);
			sc.vInitialScale.x	= GetRandom(g_vtBloodSplatsMinScale.GetFloat(), g_vtBloodSplatsMaxScale.GetFloat());

			if (bBigBlood) sc.vInitialScale.x *= g_vtBigBloodSizeScale.GetFloat();

			sc.vInitialScale.y	= sc.vInitialScale.x;
			sc.vFinalScale		= sc.vInitialScale;

			sc.dwFlags			= FLAG_VISIBLE | FLAG_ROTATEABLESPRITE | FLAG_NOLIGHT;
			sc.fLifeTime		= GetRandom(g_vtBloodSplatsMinLifetime.GetFloat(), g_vtBloodSplatsMaxLifetime.GetFloat());

			if (bBigBlood) sc.fLifeTime *= g_vtBigBloodLifeScale.GetFloat();

			sc.fInitialAlpha	= 1.0f;
			sc.fFinalAlpha		= 0.0f;
			sc.nType			= OT_SPRITE;
			sc.bMultiply		= LTTRUE;

			char* pBloodFiles[] =
			{
				"Sfx\\Test\\Spr\\BloodL1.spr",
				"Sfx\\Test\\Spr\\BloodL2.spr",
				"Sfx\\Test\\Spr\\BloodL3.spr",
				"Sfx\\Test\\Spr\\BloodL4.spr"
			};

			sc.pFilename = pBloodFiles[GetRandom(0,3)];

			pFX = psfxMgr->CreateSFX(SFX_SCALE_ID, &sc);
			if (pFX) pFX->Update();
		}
		else if (i==0)
		{
			// Didn't hit anything straight back, do don't bother to
			// do anymore...

			return;
		}
	}
}
Пример #19
0
void CNodeController::HandleNodeConrolLipSync(HSTRING hSound, LTFLOAT fRadius)
{
 	ModelNode eModelNode = g_pModelButeMgr->GetSkeletonNode(m_pCharacterFX->GetModelSkeleton(), "LowerJaw");

	// See if we are already controlling the jaw node
	int iCtrl = FindNodeControl(eModelNode, eControlLipSync);

	char szSound[128];
    strcpy(szSound, g_pLTClient->GetStringData(hSound));
    g_pLTClient->FreeString(hSound);

	// Check to make sure all the info is ok...
	if((eModelNode == eModelNodeInvalid) || fRadius <= 0.0f)
	{
		if(iCtrl > -1)
		{
			if(m_aNodeControls[iCtrl].hLipSyncSound)
			{
                g_pLTClient->KillSound(m_aNodeControls[iCtrl].hLipSyncSound);
                m_aNodeControls[iCtrl].hLipSyncSound = LTNULL;

				if (m_aNodeControls[iCtrl].bShowingSubtitles)
				{
					g_pInterfaceMgr->ClearSubtitle();
				}
			}

            m_aNodeControls[iCtrl].bValid = LTFALSE;
		}

		return;
	}

	// Add the node control structure...
	int iNodeControl = (iCtrl > -1) ? iCtrl : AddNodeControl();

	_ASSERT(iNodeControl >= 0);
	if ( iNodeControl < 0 )
		return;

	if(m_aNodeControls[iNodeControl].hLipSyncSound)
	{
        g_pLTClient->KillSound(m_aNodeControls[iNodeControl].hLipSyncSound);
        m_aNodeControls[iNodeControl].hLipSyncSound = LTNULL;

		if (m_aNodeControls[iNodeControl].bShowingSubtitles)
		{
			g_pInterfaceMgr->ClearSubtitle();
		}
	}

    m_aNodeControls[iNodeControl].bValid = LTTRUE;
	m_aNodeControls[iNodeControl].eControl = eControlLipSync;
	m_aNodeControls[iNodeControl].eModelNode = eModelNode;
    m_aNodeControls[iNodeControl].pSixteenBitBuffer = LTNULL;
    m_aNodeControls[iNodeControl].pEightBitBuffer = LTNULL;

	LTBOOL bSubtitles = LTFALSE;
	m_aNodeControls[iNodeControl].hLipSyncSound = m_pCharacterFX->PlayLipSyncSound(szSound, fRadius, bSubtitles);
	m_aNodeControls[iNodeControl].bShowingSubtitles = bSubtitles;

	// Increment the number of controllers for this node...
	m_aNodes[eModelNode].cControllers++;

	// PLH DEBUG
	// Show graph over character.
#ifdef GRAPH_LIPSYNC_SOUND
	GCREATESTRUCT graph_init;
	graph_init.hServerObj = m_pCharacterFX->GetServerObj();
    graph_init.m_vOffsetPos = LTVector(0.0f,70.0f,0.0f);
	graph_init.m_fWidth = 60.0f;
	graph_init.m_fHeight = 60.0f;
    graph_init.m_bIgnoreX = LTTRUE;
	graph_init.m_UpdateGraphCallback
        = make_callback2<LTBOOL,GraphFXPoint * *, uint32 *>(g_GraphPoints,GraphPoints::GetData);

	CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr();
	if (!psfxMgr) return;

	psfxMgr->CreateSFX(SFX_GRAPH_ID, &graph_init);
#endif

}
Пример #20
0
DBOOL CMarkSFX::CreateObject(CClientDE *pClientDE)
{
	if (!CSpecialFX::CreateObject(pClientDE)) return DFALSE;

	CSFXMgr* psfxMgr = g_pBloodClientShell->GetSFXMgr();
	if (!psfxMgr) return DFALSE;


	// Before we create a new buillet hole see if there is already another
	// bullet hole close by that we could use instead...

	CSpecialFXList* pList = psfxMgr->GetBulletHoleFXList();
	if (!pList) return DFALSE;

	int nNumBulletHoles = pList->GetSize();

	HOBJECT hMoveObj		 = DNULL;
	HOBJECT hObj			 = DNULL;
	DFLOAT	fClosestMarkDist = REGION_DIAMETER;
	DBYTE	nNumInRegion	 = 0;
	DVector vPos;

	for (int i=0; i < nNumBulletHoles; i++)
	{
		if ((*pList)[i])
		{
			hObj = (*pList)[i]->GetObject();
			if (hObj)
			{
				pClientDE->GetObjectPos(hObj, &vPos);
				
				DFLOAT fDist = VEC_DISTSQR(vPos, m_Pos);
				if (fDist < REGION_DIAMETER)
				{
					if (fDist < fClosestMarkDist)
					{
						fClosestMarkDist = fDist;
						hMoveObj = hObj;
					}

					if (++nNumInRegion > MAX_MARKS_IN_REGION)
					{
						// Just move this bullet-hole to the correct pos, and
						// remove thyself...

						pClientDE->SetObjectPos(hMoveObj, &m_Pos);
						return DFALSE;
					}
				}
			}
		}
	}


	// Setup the mark...
	ObjectCreateStruct createStruct;
	INIT_OBJECTCREATESTRUCT(createStruct);

	createStruct.m_ObjectType = OT_SPRITE;
	_mbscpy((unsigned char*)createStruct.m_Filename, (const unsigned char*)m_pClientDE->GetStringData( m_hstrSprite ));
	createStruct.m_Flags	  = FLAG_VISIBLE | FLAG_ROTATEABLESPRITE;
	VEC_COPY(createStruct.m_Pos, m_Pos);
	ROT_COPY( createStruct.m_Rotation, m_Rotation );

	m_hObject = pClientDE->CreateObject(&createStruct);

	m_pClientDE->SetObjectScale(m_hObject, &m_vScale);


	// See what it hit
	DVector vU, vR;
	pClientDE->GetRotationVectors(&m_Rotation, &vU, &vR, &m_vForward);

	ClientIntersectQuery iq;
	ClientIntersectInfo  ii;

	iq.m_Flags = INTERSECT_OBJECTS | INTERSECT_HPOLY;

	VEC_COPY(iq.m_From, vPos);			// Get start point at the last known position.
	VEC_MULSCALAR(iq.m_To, m_vForward, -1.0f);
	VEC_ADD(iq.m_To, iq.m_To, iq.m_From);	// Get destination point slightly past where we should be

	// Hit something!  try to clip against it. (since this is only being used for bullet marks,
	if (pClientDE->IntersectSegment(&iq, &ii))
	{
		HPOLY hPoly = ii.m_hPoly;
		pClientDE->ClipSprite(m_hObject, hPoly);
	}
	m_pClientDE->SetObjectColor(m_hObject, 0.1f, 0.1f, 0.1f, 1.0f);
	
	return DTRUE;
}