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(); } }
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++; }