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::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(); }
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(); }
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; }
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; }
void CSFXMgr::OnObjectRotate( HOBJECT hObj, bool bTeleport, LTRotation *pNewRot ) { if( !hObj || ! pNewRot ) return; // If it's a CharacterFX we might want to modify the rotation... CSpecialFX *pFX = FindSpecialFX( SFX_CHARACTER_ID, hObj ); if( pFX ) { pFX->OnObjectRotate( pNewRot ); } }
void CSFXMgr::OnTouchNotify(HOBJECT hMain, CollisionInfo *pInfo, float forceMag) { if (!hMain) return; // See if this is the move-mgr's object... if (hMain == g_pPlayerMgr->GetMoveMgr()->GetObject()) { g_pPlayerMgr->GetMoveMgr()->OnTouchNotify(pInfo, forceMag); } else { // Okay see if this is a special fx... CSpecialFX* pFX = FindSpecialFX(SFX_PROJECTILE_ID, hMain); if (pFX) { pFX->HandleTouch(pInfo); } } }
void CSFXMgr::UpdateDynamicSpecialFX() { //track our performance CTimedSystemBlock TimingBlock(g_tsClientSFXUpdate); for (int j=0; j < DYN_ARRAY_SIZE; j++) { int nNumSFX = m_dynSFXLists[j].GetSize(); for (int i=0; i < nNumSFX; i++) { CSpecialFX* pSFX = m_dynSFXLists[j][i]; if( pSFX ) { if (!pSFX->Update()) { m_dynSFXLists[j].Remove(pSFX); } } } } }
CSpecialFX* CGibFX::CreateGibTrail(HLOCALOBJ hObj) { if (!hObj || !m_pClientDE) return LTNULL; CGameSettings* pSettings = g_pInterfaceMgr->GetSettings(); if (!pSettings) return LTNULL; uint8 nDetailLevel = pSettings->SpecialFXSetting(); if (nDetailLevel == RS_LOW) return LTNULL; PTCREATESTRUCT pt; pt.hServerObj = hObj; pt.nType = (uint8) (m_eModelType == eModelTypeHuman ? PT_BLOOD : PT_GIBSMOKE); CSpecialFX* pSFX = debug_new(CParticleTrailFX); if (!pSFX) return LTNULL; pSFX->Init(&pt); pSFX->CreateObject(m_pClientDE); return pSFX; }
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; }
void CWeaponFX::CreateLightBeamFX(SURFACE* pSurf) { if (!pSurf) return; LTVector vEnterColor, vExitColor; if (g_pLTClient->GetPointShade(&m_vExitPos, &vExitColor) == LT_OK) { // Get the EnterColor value... LTVector vEnterPos = m_vExitPos - (m_vExitNormal * float(pSurf->nMaxShootThroughThickness + 1)); if (g_pLTClient->GetPointShade(&vEnterPos, &vEnterColor) == LT_OK) { // Calculate the difference in light value... LTFLOAT fMaxEnter = Max(vEnterColor.x, vEnterColor.y); fMaxEnter = Max(fMaxEnter, vEnterColor.z); LTFLOAT fMaxExit = Max(vExitColor.x, vExitColor.y); fMaxExit = Max(fMaxExit, vExitColor.z); if (fabs((double)(fMaxExit - fMaxEnter)) >= g_cvarLightBeamColorDelta.GetFloat()) { LTVector vStartPoint, vDir; if (fMaxEnter > fMaxExit) { vStartPoint = m_vExitPos; vDir = m_vDir; } else { vStartPoint = vEnterPos; vDir = -m_vDir; } PLFXCREATESTRUCT pls; pls.vStartPos = vStartPoint; pls.vEndPos = vStartPoint + (vDir * GetRandom(100.0, 150.0f)); pls.vInnerColorStart = LTVector(230, 230, 230); pls.vInnerColorEnd = pls.vInnerColorStart; pls.vOuterColorStart = LTVector(0, 0, 0); pls.vOuterColorEnd = LTVector(0, 0, 0); pls.fAlphaStart = 0.5f; pls.fAlphaEnd = 0.0f; pls.fMinWidth = 0; pls.fMaxWidth = 10; pls.fMinDistMult = 1.0f; pls.fMaxDistMult = 1.0f; pls.fLifeTime = 10.0f; pls.fAlphaLifeTime = 10.0f; pls.fPerturb = 0.0f; pls.bAdditive = LTFALSE; pls.nWidthStyle = PLWS_CONSTANT; pls.nNumSegments = 1; CSpecialFX* pFX = g_pGameClientShell->GetSFXMgr()->CreateSFX(SFX_POLYLINE_ID, &pls); if (pFX) pFX->Update(); } } } }
LTBOOL CWeaponFX::CreateObject(ILTClient* pClientDE) { if (!CSpecialFX::CreateObject(pClientDE) || !g_pWeaponMgr) return LTFALSE; CGameSettings* pSettings = g_pInterfaceMgr->GetSettings(); if (!pSettings) return LTFALSE; // Set up our data members... // Set the local client id... uint32 dwId; g_pLTClient->GetLocalClientID(&dwId); m_nLocalId = (uint8)dwId; m_nDetailLevel = pSettings->SpecialFXSetting(); // Fire pos may get tweaked a little... m_vFirePos = CalcFirePos(m_vFirePos); m_vDir = m_vPos - m_vFirePos; m_fFireDistance = m_vDir.Mag(); m_vDir.Norm(); g_pLTClient->AlignRotation(&m_rSurfaceRot, &m_vSurfaceNormal, LTNULL); g_pLTClient->AlignRotation(&m_rDirRot, &m_vDir, LTNULL); SetupExitInfo(); // Calculate if the camera can see the fire position and the impact // position... g_bCanSeeImpactPos = LTTRUE; g_bCanSeeFirePos = LTTRUE; g_bDistantImpactPos = LTFALSE; g_bDistantFirePos = LTFALSE; if (g_vtWeaponFXUseFOVPerformance.GetFloat()) { HOBJECT hCamera = g_pGameClientShell->GetCamera(); LTVector vCameraPos, vU, vR, vF, vDir; LTRotation rCameraRot; g_pLTClient->GetObjectPos(hCamera, &vCameraPos); g_pLTClient->GetObjectRotation(hCamera, &rCameraRot); g_pLTClient->GetRotationVectors(&rCameraRot, &vU, &vR, &vF); vDir = m_vPos - vCameraPos; LTFLOAT fImpactDist = vDir.Mag(); if (fImpactDist > g_vtWeaponFXMaxImpactDist.GetFloat()) { g_bDistantImpactPos = LTTRUE; } vDir.Norm(); LTFLOAT fMul = VEC_DOT(vDir, vF); g_bCanSeeImpactPos = (fMul < g_vtWeaponFXMinImpactDot.GetFloat() ? LTFALSE : LTTRUE); // In multiplayer we need to account for impacts that occur around // our camera that we didn't cause (this is also an issue in single // player, but due to the singler player gameplay dynamics it isn't // as noticeable)... if (!g_bCanSeeImpactPos && IsMultiplayerGame()) { // Somebody else shot this...if the impact is close enough, we // "saw" it... if (m_nLocalId != m_nShooterId && fImpactDist <= g_vtWeaponFXMaxMultiImpactDist.GetFloat()) { g_bCanSeeImpactPos = LTTRUE; } } vDir = m_vFirePos - vCameraPos; if (vDir.Mag() > g_vtWeaponFXMaxFireDist.GetFloat()) { g_bDistantFirePos = LTTRUE; } vDir.Norm(); fMul = VEC_DOT(vDir, vF); g_bCanSeeFirePos = (fMul < g_vtWeaponFXMinFireDot.GetFloat() ? LTFALSE : LTTRUE); } // Determine what container the sfx is in... HLOCALOBJ objList[1]; LTVector vTestPos = m_vPos + m_vSurfaceNormal; // Test a little closer... uint32 dwNum = g_pLTClient->GetPointContainers(&vTestPos, objList, 1); if (dwNum > 0 && objList[0]) { uint32 dwUserFlags; g_pLTClient->GetObjectUserFlags(objList[0], &dwUserFlags); if (dwUserFlags & USRFLG_VISIBLE) { uint16 dwCode; if (g_pLTClient->GetContainerCode(objList[0], &dwCode)) { m_eCode = (ContainerCode)dwCode; } } } // Determine if the fire point is in liquid vTestPos = m_vFirePos + m_vDir; // Test a little further in... dwNum = g_pLTClient->GetPointContainers(&vTestPos, objList, 1); if (dwNum > 0 && objList[0]) { uint32 dwUserFlags; g_pLTClient->GetObjectUserFlags(objList[0], &dwUserFlags); if (dwUserFlags & USRFLG_VISIBLE) { uint16 dwCode; if (g_pLTClient->GetContainerCode(objList[0], &dwCode)) { m_eFirePosCode = (ContainerCode)dwCode; } } } if (IsLiquid(m_eCode)) { m_wImpactFX = m_pAmmo->pUWImpactFX ? m_pAmmo->pUWImpactFX->nFlags : 0; } else { m_wImpactFX = m_pAmmo->pImpactFX ? m_pAmmo->pImpactFX->nFlags : 0; } m_wFireFX = m_pAmmo->pFireFX ? m_pAmmo->pFireFX->nFlags : 0; // Assume alt-fire, silenced, and tracer...these will be cleared by // IgnoreFX if not used... m_wFireFX |= WFX_ALTFIRESND | WFX_SILENCED | WFX_TRACER; // Assume impact ding, it will be cleared if not used... m_wImpactFX |= WFX_IMPACTDING; // Clear all the fire fx we want to ignore... m_wFireFX &= ~m_wIgnoreFX; m_wImpactFX &= ~m_wIgnoreFX; // See if this is a redundant weapon fx (i.e., this client shot the // weapon so they've already seen this fx)... if (g_pGameClientShell->IsMultiplayerGame()) { if (m_pAmmo->eType != PROJECTILE) { if (!m_bLocal && m_nLocalId >= 0 && m_nLocalId == m_nShooterId) { if (m_wImpactFX & WFX_IMPACTDING) { if (g_vtMultiDing.GetFloat()) { PlayImpactDing(); } } return LTFALSE; } } } // Show the fire path...(debugging...) if (g_cvarShowFirePath.GetFloat() > 0) { PLFXCREATESTRUCT pls; pls.vStartPos = m_vFirePos; pls.vEndPos = m_vPos; pls.vInnerColorStart = LTVector(GetRandom(127.0f, 255.0f), GetRandom(127.0f, 255.0f), GetRandom(127.0f, 255.0f)); pls.vInnerColorEnd = pls.vInnerColorStart; pls.vOuterColorStart = LTVector(0, 0, 0); pls.vOuterColorEnd = LTVector(0, 0, 0); pls.fAlphaStart = 1.0f; pls.fAlphaEnd = 1.0f; pls.fMinWidth = 0; pls.fMaxWidth = 10; pls.fMinDistMult = 1.0f; pls.fMaxDistMult = 1.0f; pls.fLifeTime = 10.0f; pls.fAlphaLifeTime = 10.0f; pls.fPerturb = 0.0f; pls.bAdditive = LTFALSE; pls.nWidthStyle = PLWS_CONSTANT; pls.nNumSegments = 2; CSpecialFX* pFX = g_pGameClientShell->GetSFXMgr()->CreateSFX(SFX_POLYLINE_ID, &pls); if (pFX) pFX->Update(); } // If the surface is the sky, don't create any impact related fx... if (m_eSurfaceType != ST_SKY || (m_wImpactFX & WFX_IMPACTONSKY)) { CreateWeaponSpecificFX(); if (g_bCanSeeImpactPos) { if ((m_wImpactFX & WFX_MARK) && ShowsMark(m_eSurfaceType) && (LTBOOL)GetConsoleInt("MarkShow", 1)) { LTBOOL bCreateMark = LTTRUE; if (g_bDistantImpactPos && m_nLocalId == m_nShooterId) { // Assume we'll see the mark if we're zoomed in ;) bCreateMark = g_pGameClientShell->IsZoomed(); } if (bCreateMark) { CreateMark(m_vPos, m_vSurfaceNormal, m_rSurfaceRot, m_eSurfaceType); } } CreateSurfaceSpecificFX(); } PlayImpactSound(); } if (IsBulletTrailWeapon()) { if (IsLiquid(m_eFirePosCode)) { if (m_nDetailLevel != RS_LOW) { CreateBulletTrail(&m_vFirePos); } } } // No tracers under water... if ((LTBOOL)GetConsoleInt("Tracers", 1) && (m_wFireFX & WFX_TRACER) && !IsLiquid(m_eCode)) { CreateTracer(); } if (g_bCanSeeFirePos) { // Only do muzzle fx for the client (not for AIs)... if ((m_wFireFX & WFX_MUZZLE) && (m_nLocalId == m_nShooterId)) { CreateMuzzleFX(); } if (!g_bDistantFirePos && (LTBOOL)GetConsoleInt("ShellCasings", 1) && (m_wFireFX & WFX_SHELL)) { CreateShell(); } if ((m_wFireFX & WFX_LIGHT)) { CreateMuzzleLight(); } } if ((m_wFireFX & WFX_FIRESOUND) || (m_wFireFX & WFX_ALTFIRESND) || (m_wFireFX & WFX_SILENCED)) { PlayFireSound(); } // Only do fly-by sounds for weapons that leave bullet trails... if (IsBulletTrailWeapon()) { PlayBulletFlyBySound(); } return LTFALSE; // Just delete me, I'm done :) }
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; } } }
CSpecialFX* CSFXMgr::CreateSFX(uint8 nId, SFXCREATESTRUCT *psfxCreateStruct, ILTMessage_Read *pMsg, HOBJECT hServerObj) { CSpecialFX* pSFX = NULL; switch (nId) { case SFX_WEAPON_ID : { pSFX = &s_WeaponFX; } break; case SFX_PLAYERLURE_ID : { pSFX = debug_new( PlayerLureFX ); } break; case SFX_PLAYERSOUND_ID : { pSFX = g_SFXBank_PlayerSound.New(); } break; case SFX_PROJECTILE_ID : { pSFX = g_SFXBank_Projectile.New(); } break; case SFX_SEARCHLIGHT_ID : { pSFX = g_SFXBank_SearchLight.New(); } break; case SFX_MARK_ID : { pSFX = g_SFXBank_Mark.New(); } break; case SFX_SHELLCASING_ID : { pSFX = g_SFXBank_ShellCasing.New(); } break; case SFX_CAMERA_ID : { pSFX = g_SFXBank_Camera.New(); if (pSFX) { if (pSFX->Init(psfxCreateStruct)) { if (g_pLTClient->IsConnected()) { if (pSFX->CreateObject(g_pLTClient)) { m_cameraSFXList.Add(pSFX); } else { DeleteSFX(pSFX); pSFX = NULL; } } else { DeleteSFX(pSFX); pSFX = NULL; } } } return pSFX; } break; case SFX_POLYGRID_ID : { pSFX = g_SFXBank_PolyGrid.New(); } break; case SFX_RENDERTARGET_ID : { pSFX = g_SFXBank_RenderTarget.New(); } break; case SFX_RENDERTARGETGROUP_ID : { pSFX = g_SFXBank_RenderTargetGroup.New(); } break; case SFX_EXPLOSION_ID : { pSFX = g_SFXBank_Explosion.New(); } break; case SFX_VOLUMEBRUSH_ID : { pSFX = g_SFXBank_VolumeBrush.New(); } break; case SFX_PICKUPITEM_ID : { pSFX = g_SFXBank_PickupItem.New(); } break; case SFX_AIMMAGNET_ID : { pSFX = g_SFXBank_AimMagnet.New(); } break; case SFX_NAVMARKER_ID : { pSFX = g_SFXBank_NavMarker.New(); } break; case SFX_LADDER_ID : { pSFX = g_SFXBank_Ladder.New(); } break; case SFX_SPECIALMOVE_ID : { pSFX = g_SFXBank_SpecialMove.New(); } break; case SFX_FINISHINGMOVE_ID : { pSFX = g_SFXBank_FinishingMove.New(); } break; case SFX_CHARACTER_ID : { pSFX = g_SFXBank_Character.New(); } break; case SFX_DEBUGLINE_ID: { pSFX = g_SFXBank_DebugLine.New(); } break; case SFX_SNOW_ID: { pSFX = g_SFXBank_Snow.New(); } break; case SFX_JUMPVOLUME_ID: { pSFX = g_SFXBank_JumpVolume.New(); } break; case SFX_DYNAMIC_SECTOR_ID: { pSFX = g_SFXBank_DynamicSectorVolume.New(); } break; case SFX_SCATTER_ID: { pSFX = g_SFXBank_Scatter.New(); } break; case SFX_TRIGGER_ID: { pSFX = g_SFXBank_Trigger.New(); } break; case SFX_FORENSICOBJECT_ID : { pSFX = g_SFXBank_ForensicObject.New(); } break; case SFX_TURRET_ID: { pSFX = g_SFXBank_Turret.New( ); } break; case SFX_TEAMCLIENTFX_ID: { pSFX = g_SFXBank_TeamClientFx.New( ); } break; case SFX_CTFFLAGBASE_ID: { LT_MEM_TRACK_ALLOC(pSFX = new CTFFlagBaseSFX, LT_MEM_TYPE_GAMECODE); } break; case SFX_CTFFLAG_ID: { LT_MEM_TRACK_ALLOC(pSFX = new CTFFlagSFX, LT_MEM_TYPE_GAMECODE); } break; case SFX_CONTROLPOINT_ID: { LT_MEM_TRACK_ALLOC(pSFX = new ControlPointSFX, LT_MEM_TYPE_GAMECODE); } break; case SFX_SOUND_NONPOINT_ID : { pSFX = g_SFXBank_SoundNonPoint.New(); } break; case SFX_VOLUMETRICLIGHT_ID : { pSFX = g_SFXBank_VolumetricLight.New(); } break; case SFX_ENTRYTOOLLOCK_ID : { pSFX = g_SFXBank_EntryToolLock.New(); } break; case SFX_SCREENEFFECT_ID : { pSFX = g_SFXBank_ScreenEffect.New(); } break; case SFX_ACTIVATEOBJECT_ID: { pSFX = g_SFXBank_ActivateObject.New(); } break; case SFX_PHYSICS_CONSTRAINT_ID: { pSFX = g_SFXBank_PhysicsConstraintFX.New( ); } break; case SFX_PHYSICS_COLLISION_SYSTEM_ID: { pSFX = g_SFXBank_PhysicsCollisionSystemFX.New( ); } break; default : return NULL; break; } // Initialize the sfx, and add it to the appropriate array... if (!pSFX) return NULL; // First initialize with the create struct... if (psfxCreateStruct) { if (!pSFX->Init(psfxCreateStruct)) { DeleteSFX(pSFX); return NULL; } } else if (pMsg) // Initialize using the hMessage { if (!pSFX->Init(hServerObj, pMsg)) { DeleteSFX(pSFX); return NULL; } } else { DeleteSFX(pSFX); return NULL; } if (!pSFX->CreateObject(g_pLTClient)) { DeleteSFX(pSFX); return NULL; } if( !AddDynamicSpecialFX(pSFX, nId)) { DeleteSFX( pSFX ); return NULL; } return pSFX; }
void CSFXMgr::OnSFXMessage(ILTMessage_Read *pMsg) { if (!pMsg) return; uint32 nInitialMsgPos = pMsg->Tell( ); uint8 nFXType = pMsg->Readuint8(); HOBJECT hObj = pMsg->ReadObject(); switch( nFXType ) { // Special case for the camera case SFX_CAMERA_ID: { // Find the camera sfx... int nNumSFX = m_cameraSFXList.GetSize(); for( int i = 0; i < nNumSFX; ++i ) { if( m_cameraSFXList[i] && m_cameraSFXList[i]->GetServerObj() == hObj ) { m_cameraSFXList[i]->OnServerMessage( pMsg ); } } return; } break; // Special case for the texture FX case SFX_DISPLAYTIMER_ID: { g_pInterfaceMgr->HandleDisplayTimerMsg( *pMsg ); return; } break; } if (0 <= nFXType && nFXType < DYN_ARRAY_SIZE && hObj) { CSpecialFX* pFX = FindSpecialFX(nFXType, hObj); if (pFX) { pFX->OnServerMessage(pMsg); } // If the object is waiting to be created, then append the message. else { // Need to save the message from the beginning. uint32 nCurPos = pMsg->Tell( ); pMsg->SeekTo( nInitialMsgPos ); SpecialFXNotifyMessageHandler::Instance().AppendMessage( *pMsg, hObj ); pMsg->SeekTo( nCurPos ); } } }
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(); } }