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();
	}
}
Beispiel #2
0
void CGrenade::HandleImpact(HOBJECT hObj)
{
	if (!g_vtGrenadeDampenPercent.IsInitted())
	{
        g_vtGrenadeDampenPercent.Init(g_pLTServer, "GrenadeDampenPercent", LTNULL, DEFAULT_GRENADE_DAMPEN_PERCENT);
	}

	if (!g_vtGrenadeMinVelMag.IsInitted())
	{
        g_vtGrenadeMinVelMag.Init(g_pLTServer, "GrenadeMinVelMag", LTNULL, DEFAULT_GRENADE_MIN_VELOCITY);
	}


    LTVector vVel;
    g_pLTServer->GetVelocity(m_hObject, &vVel);


	// See if we are impacting on liquid...

    LTBOOL bEnteringLiquid = LTFALSE;
    uint16 code;
    if (g_pLTServer->GetContainerCode(hObj, &code))
	{
		if (IsLiquid((ContainerCode)code))
		{
            bEnteringLiquid = LTTRUE;
		}
	}


	CollisionInfo info;
    g_pLTServer->GetLastCollision(&info);


	// Do the bounce, if the object we hit isn't liquid...

	if (!bEnteringLiquid)
	{
		vVel += (info.m_vStopVel * 2.0f);
	}


	// Dampen the grenade's new velocity based on the surface type...

    LTFLOAT fDampenPercent = g_vtGrenadeDampenPercent.GetFloat();

	m_eLastHitSurface = GetSurfaceType(info);
	SURFACE* pSurf = g_pSurfaceMgr->GetSurface(m_eLastHitSurface);
	if (pSurf)
	{
		// Play a bounce sound (based on the surface type) if one isn't
		// already playing...

		if ( ShouldPlayBounceSound(pSurf) )
		{
			// Only play one sound at a time...

			if (m_hBounceSnd)
			{
                g_pLTServer->KillSound(m_hBounceSnd);
                m_hBounceSnd = LTNULL;
			}

            uint32 dwFlags = PLAYSOUND_GETHANDLE | PLAYSOUND_TIME;

			int nVolume	= IsLiquid(m_eContainerCode) ? 50 : 100;

            LTVector vPos;
            g_pLTServer->GetObjectPos(m_hObject, &vPos);

			m_hBounceSnd = g_pServerSoundMgr->PlaySoundFromPos(vPos, (char*)GetBounceSound(pSurf),
				pSurf->fGrenadeSndRadius, SOUNDPRIORITY_MISC_MEDIUM, dwFlags, nVolume);
		}

		fDampenPercent = (1.0f - pSurf->fHardness);
	}

	fDampenPercent = fDampenPercent > 1.0f ? 1.0f : (fDampenPercent < 0.0f ? 0.0f : fDampenPercent);

	vVel *= (1.0f - fDampenPercent);


	// See if we should come to a rest...

    LTVector vTest = vVel;
	vTest.y = 0.0f;

	if (vTest.Mag() < g_vtGrenadeMinVelMag.GetFloat())
	{
		// If we're on the ground (or an object), stop movement...

		CollisionInfo standingInfo;
        g_pLTServer->GetStandingOn(m_hObject, &standingInfo);

		CollisionInfo* pInfo = standingInfo.m_hObject ? &standingInfo : &info;

		if (pInfo->m_hObject)
		{
			// Don't stop on walls...

			if (pInfo->m_Plane.m_Normal.y > 0.75f)
			{
				vVel.Init();

				// Turn off gravity, solid, and touch notify....

                uint32 dwFlags = g_pLTServer->GetObjectFlags(m_hObject);
				dwFlags &= ~(FLAG_GRAVITY | FLAG_TOUCH_NOTIFY | FLAG_SOLID);

                g_pLTServer->SetObjectFlags(m_hObject, dwFlags);

				// Rotate to rest...

				RotateToRest();
			}
		}
	}


	// Reset rotation velocities due to the bounce...

	ResetRotationVel(&vVel, pSurf);


	// We need to subtact this out because the engine will add it back in,
	// kind of a kludge but necessary...

	vVel -= info.m_vStopVel;


    g_pLTServer->SetVelocity(m_hObject, &vVel);

	m_cBounces++;
}