LTBOOL ScaleSprite::Update() { if (m_bStartOn) { g_pCommonLT->SetObjectFlags(m_hObject, OFT_User, USRFLG_VISIBLE, USRFLG_VISIBLE); g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, FLAG_VISIBLE, FLAG_VISIBLE); } SetNextUpdate(UPDATE_NEVER); // BUG - This isn't quite right. Sometimes this works (flipping the sprite) // other times the sprite shouldn't be flipped...Not sure what the bug is. // For some reason the sprites are sometimes backwards...Get the rotation // so we can flip it... LTRotation rRot; LTVector vPos, vDir, vU, vR, vF; g_pLTServer->GetObjectPos(m_hObject, &vPos); g_pLTServer->GetObjectRotation(m_hObject, &rRot); vU = rRot.Up(); vR = rRot.Right(); vF = rRot.Forward(); if (m_bFlushWithWorld) { // Align the sprite to the surface directly behind the sprite // (i.e., opposite the forward vector)... VEC_NORM(vF); VEC_MULSCALAR(vDir, vF, -1.0f); // Determine where on the surface to place the sprite... IntersectInfo iInfo; IntersectQuery qInfo; VEC_COPY(qInfo.m_From, vPos); VEC_COPY(qInfo.m_Direction, vDir); qInfo.m_Flags = IGNORE_NONSOLID | INTERSECT_OBJECTS | INTERSECT_HPOLY; qInfo.m_FilterFn = LTNULL; if (g_pLTServer->CastRay(&qInfo, &iInfo)) { LTVector vTemp; VEC_COPY(vPos, iInfo.m_Point); VEC_COPY(vDir, iInfo.m_Plane.m_Normal); // Place the sprite just above the surface... VEC_MULSCALAR(vTemp, vDir, 1.0f); VEC_ADD(vPos, vPos, vTemp); g_pLTServer->SetObjectPos(m_hObject, &vPos); } } return LTTRUE; }
bool CFallingStuffFX::Init(ILTClient *pClientDE, FX_BASEDATA *pBaseData, const CBaseFXProps *pProps) { // Perform base class initialisation if (!CBaseFX::Init(pClientDE, pBaseData, pProps)) return false; // Store the first position as the last position m_vLastPos = pBaseData->m_vPos; // If we have a parent object, get it and apply it's rotation // to the plane direction m_vPlaneDir = GetProps()->m_vPlaneDir; if (m_hParent) { LTRotation orient; m_pLTClient->GetObjectRotation(m_hParent, &orient); LTMatrix mRot; Mat_SetBasisVectors(&mRot, &orient.Right(), &orient.Up(), &orient.Forward()); LTVector vTmp = m_vPlaneDir; MatVMul(&m_vPlaneDir, &mRot, &vTmp); } LTVector vUp; vUp.x = 0.0f; vUp.y = 1.0f; vUp.z = 0.0f; LTVector vTest = m_vPlaneDir; vTest.x = (float)fabs(vTest.x); vTest.y = (float)fabs(vTest.y); vTest.z = (float)fabs(vTest.z); if (vTest == vUp) { // Gotsta use another axis vUp.x = -1.0f; vUp.y = 0.0f; vUp.z = 0.0f; } m_vRight = m_vPlaneDir.Cross(vUp); m_vUp = m_vPlaneDir.Cross(m_vRight); // Create the base object CreateDummyObject(); // Success !! return true; }
LTBOOL CLaserTriggerFX::CalcBeamCoords() { if (!m_hServerObject) return LTFALSE; // The beam is relative to the server object's dims... LTVector vPos; g_pLTClient->GetObjectPos(m_hServerObject, &vPos); LTRotation rRot; g_pLTClient->GetObjectRotation(m_hServerObject, &rRot); LTVector vU, vR, vF; vU = rRot.Up(); vR = rRot.Right(); vF = rRot.Forward(); // Okay, the beam is always along the object's longest dim... LTVector vDir = vF; LTFLOAT fLongestDim = m_cs.vDims.z; // Assume forward first... m_pls.fMaxWidth = (m_cs.vDims.x + m_cs.vDims.y); // Assume x/y are same... if (m_cs.vDims.y > fLongestDim) { vDir = vU; fLongestDim = m_cs.vDims.y; m_pls.fMaxWidth = (m_cs.vDims.x + m_cs.vDims.z); } if (m_cs.vDims.x > fLongestDim) { vDir = vR; fLongestDim = m_cs.vDims.x; m_pls.fMaxWidth = (m_cs.vDims.y + m_cs.vDims.z); } m_pls.vStartPos = vPos + (vDir * fLongestDim); m_pls.vEndPos = vPos - (vDir * fLongestDim); return LTTRUE; }
bool ConstraintWheel::SetupBodySpaceData(const LTRigidTransform& tInvBody1, const LTRigidTransform& tInvBody2) { //get the position of our object which will serve as the constraint point LTVector vConstraintPos; if(g_pLTServer->GetObjectPos(m_hObject, &vConstraintPos) != LT_OK) return false; LTRotation rConstraintOr; if(g_pLTServer->GetObjectRotation(m_hObject, &rConstraintOr) != LT_OK) return false; m_vPivotPt1 = tInvBody1 * vConstraintPos; m_vPivotPt2 = tInvBody2 * vConstraintPos; m_vRotation1 = tInvBody1.m_rRot.RotateVector(rConstraintOr.Forward()); m_vRotation2 = tInvBody2.m_rRot.RotateVector(rConstraintOr.Forward()); m_vSuspension2 = tInvBody2.m_rRot.RotateVector(rConstraintOr.Up()); return true; }
void CFlashLight3rdPerson::GetLightPositions(LTVector& vStartPos, LTVector& vEndPos, LTVector& vUOffset, LTVector& vROffset) { if ( !m_hObj ) return; HMODELSOCKET hSocket; if ( LT_OK == g_pModelLT->GetSocket(m_hObj, "LeftHand", hSocket) ) { LTransform tf; if ( LT_OK == g_pModelLT->GetSocketTransform(m_hObj, hSocket, tf, LTTRUE) ) { LTVector vPos = tf.m_Pos; LTRotation rRot = tf.m_Rot; LTVector vRight, vUp, vForward; vRight = rRot.Right(); vUp = rRot.Up(); vForward = rRot.Forward(); //vStartPos = vPos - vUp*4.0f + vForward*8.0f; //vEndPos = vPos + vForward*200.0f; //vUOffset = vUp; //vROffset = vRight; vStartPos = vPos; vEndPos = vPos + (vForward * g_cvarFLLightOffsetForward.GetFloat()); vROffset = (vRight * g_cvarFLLightOffsetRight.GetFloat()); vUOffset = (vUp * g_cvarFLLightOffsetUp.GetFloat()); // Update the Start/End position to addjust for any offset... vEndPos += vROffset; vEndPos += vUOffset; vStartPos += vROffset; vStartPos += vUOffset; } } }
LTBOOL CPickupItemFX::Update() { if (!m_pClientDE || m_bWantRemove || !m_hServerObject) return LTFALSE; LTFLOAT fDeltaTime = g_pGameClientShell->GetFrameTime(); if (m_bRotate) { LTRotation rRot; g_pLTClient->GetObjectRotation(m_hServerObject, &rRot); rRot.Rotate(rRot.Up(), PICKUPITEM_ROTVEL * fDeltaTime); g_pLTClient->SetObjectRotation(m_hServerObject, &rRot); } if (m_bBounce) { } // If we have a ClientFX that is playing hide or show it based on the serverobject... if( m_linkClientFX.IsValid() ) { uint32 dwFlags; g_pCommonLT->GetObjectFlags( m_hServerObject, OFT_Flags, dwFlags ); if( dwFlags & FLAG_VISIBLE ) { m_linkClientFX.GetInstance()->Show(); } else { m_linkClientFX.GetInstance()->Hide(); } } return LTTRUE; }
void CFlashLightPlayer::GetLightPositions(LTVector& vStartPos, LTVector& vEndPos, LTVector& vUOffset, LTVector& vROffset) { vStartPos.Init(); vEndPos.Init(); vUOffset.Init(); vROffset.Init(); CMoveMgr* pMoveMgr = g_pPlayerMgr->GetMoveMgr(); if (!pMoveMgr) return; LTRotation rRot; if (pMoveMgr->GetVehicleMgr()->IsVehiclePhysics()) { if (g_pPlayerMgr->IsFirstPerson()) { pMoveMgr->GetVehicleMgr()->GetVehicleLightPosRot(vStartPos, rRot); } else // 3rd person vehicle { // Get light pos on 3rd-person vehicle... HLOCALOBJ hPlayerObj = g_pLTClient->GetClientObject(); if (hPlayerObj) { g_pLTClient->GetObjectRotation(hPlayerObj, &rRot); g_pLTClient->GetObjectPos(hPlayerObj, &vStartPos); } } } else if (g_pPlayerMgr->IsFirstPerson()) { HOBJECT hCamera = g_pPlayerMgr->GetCamera(); if (!hCamera) return; g_pLTClient->GetObjectRotation(hCamera, &rRot); g_pLTClient->GetObjectPos(hCamera, &vStartPos); } else // 3rd person { // Get light pos from 3rd-person model... HLOCALOBJ hPlayerObj = g_pLTClient->GetClientObject(); if (hPlayerObj) { // g_pLTClient->GetObjectRotation(hPlayerObj, &rRot); // g_pLTClient->GetObjectPos(hPlayerObj, &vStartPos); HMODELSOCKET hSocket; if ( LT_OK == g_pModelLT->GetSocket(hPlayerObj, "LeftHand", hSocket) ) { LTransform tf; if ( LT_OK == g_pModelLT->GetSocketTransform(hPlayerObj, hSocket, tf, LTTRUE) ) { vStartPos = tf.m_Pos; rRot = tf.m_Rot; } } } } vEndPos = vStartPos + (rRot.Forward() * g_cvarFLLightOffsetForward.GetFloat()); if (g_pPlayerMgr->IsFirstPerson()) { vROffset = (rRot.Right() * g_cvarFLLightOffsetRight.GetFloat()); vUOffset = (rRot.Up() * g_cvarFLLightOffsetUp.GetFloat()); // Update the Start/End position to addjust for any offset... vEndPos += vROffset; vEndPos += vUOffset; vStartPos += vROffset; vStartPos += vUOffset; } }
void DebugLineSystem::AddOrientation( const LTVector& vCenter, const LTRotation& rRot, float fLength, uint8 nAlpha) { AddArrow(vCenter, vCenter + rRot.Right() * fLength, Color::Red, nAlpha); AddArrow(vCenter, vCenter + rRot.Up() * fLength, Color::Green, nAlpha); AddArrow(vCenter, vCenter + rRot.Forward() * fLength, Color::Blue, nAlpha); }
//function that handles the custom rendering void CParticleSystemGroup::RenderParticleSystem(ILTCustomRenderCallback* pInterface, const LTRigidTransform& tCamera) { //track our performance CTimedSystemBlock TimingBlock(g_tsClientFXParticles); //setup our vertex declaration if(pInterface->SetVertexDeclaration(g_ClientFXVertexDecl.GetTexTangentSpaceDecl()) != LT_OK) return; //bind a quad index stream if(pInterface->BindQuadIndexStream() != LT_OK) return; //set the fact that we were visible *m_pVisibleFlag = true; //now determine the largest number of particles that we can render at any time uint32 nMaxParticlesPerBatch = QUAD_RENDER_INDEX_STREAM_SIZE / 6; nMaxParticlesPerBatch = LTMIN(nMaxParticlesPerBatch, DYNAMIC_RENDER_VERTEX_STREAM_SIZE / (sizeof(STexTangentSpaceVert) * 4)); //determine the screen orientation LTRotation rCamera = tCamera.m_rRot; if (m_pProps->m_bObjectSpace) { LTRotation rObjectRotation; g_pLTClient->GetObjectRotation(m_hCustomRender, &rObjectRotation); rCamera = rObjectRotation.Conjugate() * rCamera; } LTVector vUp = rCamera.Up(); LTVector vRight = rCamera.Right(); //create some vectors to offset to each corner (avoids adding for displacement in the inner loop) //Each one can just be scaled by the size of the particle to get the final offset static const float kfHalfRoot2 = 0.5f * MATH_SQRT2; //premultiplied versions of up and right scaled by half the square root of two LTVector vUpHalfRoot2 = vUp * kfHalfRoot2; LTVector vRightHalfRoot2 = vRight * kfHalfRoot2; //precalculate the diagonals for non-rotating particles since these are constant LTVector vDiagonals[4]; vDiagonals[0] = vUpHalfRoot2 - vRightHalfRoot2; vDiagonals[1] = vUpHalfRoot2 + vRightHalfRoot2; vDiagonals[2] = -vUpHalfRoot2 + vRightHalfRoot2; vDiagonals[3] = -vUpHalfRoot2 - vRightHalfRoot2; uint32 nNumParticlesLeft = m_Particles.GetNumParticles(); //precalculate some data for the basis space of the particles LTVector vNormal = -rCamera.Forward(); LTVector vTangent = vRight; LTVector vBinormal = -vUp; //the U scale for particle images float fUImageWidth = 1.0f / (float)m_pProps->m_nNumImages; //variables used within the inner loop float fSize; uint32 nColor; //now run through all the particles and render CParticleIterator itParticles = m_Particles.GetIterator(); while(nNumParticlesLeft > 0) { //determine our batch size uint32 nBatchSize = LTMIN(nNumParticlesLeft, nMaxParticlesPerBatch); //lock down our buffer for rendering SDynamicVertexBufferLockRequest LockRequest; if(pInterface->LockDynamicVertexBuffer(nBatchSize * 4, LockRequest) != LT_OK) return; //fill in a batch of particles STexTangentSpaceVert* pCurrOut = (STexTangentSpaceVert*)LockRequest.m_pData; if(m_pProps->m_bRotate) { //we need to render the particles rotated for(uint32 nBatchParticle = 0; nBatchParticle < nBatchSize; nBatchParticle++) { //sanity check LTASSERT(!itParticles.IsDone(), "Error: Particle count and iterator mismatch"); //get the particle from the iterator SParticle* pParticle = (SParticle*)itParticles.GetParticle(); GetParticleSizeAndColor(pParticle, nColor, fSize); //determine the sin and cosine of this particle angle float fAngle = pParticle->m_fAngle; float fSinAngle = LTSin(fAngle); float fCosAngle = LTCos(fAngle); LTVector vRotRight = (vRightHalfRoot2 * fCosAngle + vUpHalfRoot2 * fSinAngle) * fSize; LTVector vRotUp = vNormal.Cross(vRotRight); LTVector vRotTangent = vTangent * fCosAngle + vBinormal * fSinAngle; LTVector vRotBinormal = vTangent * fSinAngle + vBinormal * fCosAngle; SetupParticle( pCurrOut, pParticle->m_Pos + vRotUp - vRotRight, pParticle->m_Pos + vRotUp + vRotRight, pParticle->m_Pos - vRotUp + vRotRight, pParticle->m_Pos - vRotUp - vRotRight, nColor, vNormal, vRotTangent, vRotBinormal, pParticle->m_nUserData & PARTICLE_IMAGE_MASK, fUImageWidth); //move onto the next set of particles pCurrOut += 4; //move onto the next particle for processing itParticles.Next(); } } else if (m_pProps->m_bStreak) { //the particles are non-rotated but streaked along their velocity for(uint32 nBatchParticle = 0; nBatchParticle < nBatchSize; nBatchParticle++) { //sanity check LTASSERT(!itParticles.IsDone(), "Error: Particle count and iterator mismatch"); //get the particle from the iterator SParticle* pParticle = (SParticle*)itParticles.GetParticle(); GetParticleSizeAndColor(pParticle, nColor, fSize); //in order to render the streak, we determine a line that passes through //the particle and runs in the direction of the velocity of the particle //we need to project the velocity onto the screen LTVector2 vScreen; vScreen.x = -(pParticle->m_Velocity.Dot(vRight)); vScreen.y = -(pParticle->m_Velocity.Dot(vUp)); //we know that the up and right vectors are normalized, so we can save some work by //just doing a 2d normalization float fMag = vScreen.Mag(); if(fMag == 0.0f) vScreen.Init(fSize, 0.0f); else vScreen *= fSize / fMag; //determine our actual screen space velocity LTVector vScreenRight = vUp * vScreen.y + vRight * vScreen.x; LTVector vScreenUp = vUp * -vScreen.x + vRight * vScreen.y; //and now compute the endpoint of the streak LTVector vEndPos = pParticle->m_Pos - pParticle->m_Velocity * m_pProps->m_fStreakScale; SetupParticle( pCurrOut, pParticle->m_Pos - vScreenRight - vScreenUp, vEndPos + vScreenRight - vScreenUp, vEndPos + vScreenRight + vScreenUp, pParticle->m_Pos - vScreenRight + vScreenUp, nColor, vNormal, vScreenRight, vScreenUp, pParticle->m_nUserData & PARTICLE_IMAGE_MASK, fUImageWidth); //move onto the next set of particles pCurrOut += 4; //move onto the next particle for processing itParticles.Next(); } } else { //the particles are non-rotated for(uint32 nBatchParticle = 0; nBatchParticle < nBatchSize; nBatchParticle++) { //sanity check LTASSERT(!itParticles.IsDone(), "Error: Particle count and iterator mismatch"); //get the particle from the iterator SParticle* pParticle = (SParticle*)itParticles.GetParticle(); GetParticleSizeAndColor(pParticle, nColor, fSize); SetupParticle( pCurrOut, pParticle->m_Pos + vDiagonals[0] * fSize, pParticle->m_Pos + vDiagonals[1] * fSize, pParticle->m_Pos + vDiagonals[2] * fSize, pParticle->m_Pos + vDiagonals[3] * fSize, nColor, vNormal, vTangent, vBinormal, pParticle->m_nUserData & PARTICLE_IMAGE_MASK, fUImageWidth); //move onto the next set of particles pCurrOut += 4; //move onto the next particle for processing itParticles.Next(); } } //unlock and render the batch pInterface->UnlockAndBindDynamicVertexBuffer(LockRequest); pInterface->RenderIndexed( eCustomRenderPrimType_TriangleList, 0, nBatchSize * 6, LockRequest.m_nStartIndex, 0, nBatchSize * 4); nNumParticlesLeft -= nBatchSize; } }
LTBOOL CShellCasingFX::Update() { if (!m_hObject || !m_pClientDE) return LTFALSE; if (g_pGameClientShell->IsServerPaused()) { return LTTRUE; } m_fElapsedTime += g_pGameClientShell->GetFrameTime(); m_fDieTime -= g_pGameClientShell->GetFrameTime(); if (m_fDieTime <= 0.0f) return LTFALSE; // Update object scale if necessary... LTVector vScale; m_pClientDE->GetObjectScale(m_hObject, &vScale); if (vScale != m_vFinalScale) { if (m_fElapsedTime <= g_vtShellScaleTime.GetFloat()) { LTVector vScaleRange = (m_vFinalScale - m_vInitialScale); vScale = m_vInitialScale + (vScaleRange * (m_fElapsedTime/g_vtShellScaleTime.GetFloat())); if (vScale > m_vFinalScale) { vScale = m_vFinalScale; } m_pClientDE->SetObjectScale(m_hObject, &vScale); } else { m_pClientDE->SetObjectScale(m_hObject, &m_vFinalScale); } } if (m_bResting) return LTTRUE; LTRotation rRot; g_pLTClient->GetObjectRotation(m_hObject, &rRot); // If velocity slows enough, and we're on the ground, just stop bouncing and just wait to expire. if (m_movingObj.m_dwPhysicsFlags & MO_RESTING) { m_bResting = LTTRUE; // Stop the spinning... rRot.Rotate(rRot.Up(), m_fYaw); g_pLTClient->SetObjectRotation(m_hObject, &rRot); // Shell is at rest, we can add a check here to see if we really want // to keep it around depending on detail settings... //HLOCALOBJ hObjs[1]; //uint32 nNumFound, nBogus; //m_pClientDE->FindObjectsInSphere(&m_movingObj.m_vPos, 64.0f, hObjs, 1, &nBogus, &nNumFound); // Remove thyself... //if (nNumFound > 15) return LTFALSE; } else { if (m_fPitchVel != 0 || m_fYawVel != 0) { LTFLOAT fDeltaTime = g_pGameClientShell->GetFrameTime(); m_fPitch += m_fPitchVel * fDeltaTime; m_fYaw += m_fYawVel * fDeltaTime; rRot.Rotate(rRot.Up(), m_fYaw); rRot.Rotate(rRot.Right(), m_fPitch); g_pLTClient->SetObjectRotation(m_hObject, &rRot); } } LTVector vNewPos; if (UpdateMovingObject(LTNULL, &m_movingObj, vNewPos)) { ClientIntersectInfo info; LTBOOL bBouncedOnGround = LTFALSE; if (BounceMovingObject(LTNULL, &m_movingObj, vNewPos, &info, INTERSECT_HPOLY, true, bBouncedOnGround)) { // If we hit the sky/invisible surface we're done... SurfaceType eType = GetSurfaceType(info); if (eType == ST_SKY || eType == ST_INVISIBLE) { return LTFALSE; } if (m_nBounceCount >= MAX_BOUNCE_COUNT) { if (!(m_movingObj.m_dwPhysicsFlags & MO_LIQUID)) { SURFACE* pSurf = g_pSurfaceMgr->GetSurface(eType); if (pSurf) { // Play appropriate sound... if (pSurf->szShellImpactSnds[0]) { g_pClientSoundMgr->PlaySoundFromPos(vNewPos, pSurf->szShellImpactSnds[0], pSurf->fShellSndRadius, SOUNDPRIORITY_MISC_LOW); } } } } // Adjust the bouncing.. m_fPitchVel *= 0.75f; m_fYawVel *= -0.75f; m_nBounceCount--; if (m_nBounceCount <= 0) { m_movingObj.m_dwPhysicsFlags |= MO_RESTING; } } m_movingObj.m_vPos = vNewPos; if (g_pCommonLT->GetPointStatus(&vNewPos) == LT_OUTSIDE) { return LTFALSE; } g_pLTClient->SetObjectPos(m_hObject, &vNewPos); } return LTTRUE; }
void SecurityCamera::UpdateRotation() { LTFLOAT fTimeDelta = g_pLTServer->GetFrameTime(); if ( m_eState == eStateDetected || m_eState == eStateDestroyed || m_eState == eStateFocusing) { return; } if ( m_eState == eStateTurningTo1 || m_eState == eStateTurningTo2 ) { LTFLOAT fYaw = g_pLTServer->GetFrameTime()*m_fYawSpeed; if ( m_eState == eStateTurningTo1 ) { fYaw = -fYaw; m_fYaw += fYaw; if ( m_fYaw < m_fYaw1 ) { if ( m_fYaw1PauseTime ) { SetState(eStatePausingAt1); } else { SetState(eStateTurningTo2); } } } else { m_fYaw += fYaw; if ( m_fYaw > m_fYaw2 ) { if ( m_fYaw2PauseTime ) { SetState(eStatePausingAt2); } else { SetState(eStateTurningTo1); } } } LTRotation rRot; g_pLTServer->GetObjectRotation(m_hObject, &rRot); rRot.Rotate(rRot.Up(), fYaw); g_pLTServer->SetObjectRotation(m_hObject, &rRot); } if ( m_eState == eStatePausingAt1 ) { m_fYawPauseTimer += fTimeDelta; if ( m_fYawPauseTimer > m_fYaw1PauseTime ) { m_fYawPauseTimer = 0.0f; SetState(eStateTurningTo2); } } if ( m_eState == eStatePausingAt2 ) { m_fYawPauseTimer += fTimeDelta; if ( m_fYawPauseTimer > m_fYaw2PauseTime ) { m_fYawPauseTimer = 0.0f; SetState(eStateTurningTo1); } } }
bool CPolyTubeFX::Update(float tmFrameTime) { // Base class update first if (!CBaseFX::Update(tmFrameTime)) return false; if ((!m_hTexture) && (!m_bLoadFailed)) { m_pLTClient->GetTexInterface()->CreateTextureFromName(m_hTexture, GetProps()->m_sPath); if (m_hTexture) { // Retrieve texture dims uint32 nHeight; m_pLTClient->GetTexInterface()->GetTextureDims(m_hTexture, m_dwWidth, nHeight); } else { m_bLoadFailed = true; } } if ((m_collPathPts.GetSize() < 2) && IsShuttingDown()) { m_collPathPts.RemoveAll(); return true; } float tmAddPtInterval = GetProps()->m_tmAddPtInterval * 2.0f; LTRotation rRot; m_pLTClient->GetObjectRotation( m_hObject, &rRot ); //increase the emission time elapse m_tmElapsedEmission += tmFrameTime; if (!IsShuttingDown() && (m_collPathPts.GetSize() < GetProps()->m_nMaxTrailLength) && ((m_tmElapsedEmission > GetProps()->m_tmAddPtInterval) || (m_collPathPts.GetSize() == 1))) { LTVector vNew = m_vPos; // Only add the new point if it's not the same as the last one.... // Add a new trail section PT_TRAIL_SECTION ts; ts.m_vPos = vNew; ts.m_tmElapsed = 0.0f; switch( GetProps()->m_eAllignment ) { case ePTA_Up: ts.m_vBisector = rRot.Up(); break; case ePTA_Right: ts.m_vBisector = rRot.Right(); break; case ePTA_Forward: ts.m_vBisector = rRot.Forward(); break; case ePTA_Camera: default: ts.m_vBisector.Init(); break; } // Compute u coordinate if (m_collPathPts.GetSize()) { LTVector vPrev = m_collPathPts.GetTail()->m_Data.m_vPos; float fUPrev = m_collPathPts.GetTail()->m_Data.m_uVal; float fWidth = (float)m_dwWidth; float fScalar = fWidth / GetProps()->m_fTrailWidth; ts.m_uVal = fUPrev + ((((vNew - vPrev).Mag()) / fWidth) * fScalar); } else { ts.m_uVal = 0.0f; } m_collPathPts.AddTail(ts); m_tmElapsedEmission = 0.0f; } // Render the tube.... if (m_collPathPts.GetSize() < 2) return true; CLinkListNode<PT_TRAIL_SECTION> *pNode = m_collPathPts.GetHead(); // Fudge the last point to be the current one... if( !IsShuttingDown() ) m_collPathPts.GetTail()->m_Data.m_vPos = m_vPos; // Transform the path LTMatrix mCam; if( m_bReallyClose || (GetProps()->m_eAllignment != ePTA_Camera)) { mCam.Identity(); } else { mCam = GetCamTransform(m_pLTClient, m_hCamera); } while (pNode) { MatVMul(&pNode->m_Data.m_vTran, &mCam, &pNode->m_Data.m_vPos); pNode = pNode->m_pNext; } // Do some precalculations pNode = m_collPathPts.GetHead(); float fCurU = 0.0f; while (pNode) { pNode->m_Data.m_tmElapsed += tmFrameTime; if( GetProps()->m_eAllignment == ePTA_Camera ) { LTVector vBisector; vBisector.z = 0.0f; // Compute the midpoint vectors if (pNode == m_collPathPts.GetHead()) { LTVector vStart = pNode->m_Data.m_vTran; LTVector vEnd = pNode->m_pNext->m_Data.m_vTran; vBisector.x = vEnd.y - vStart.y; vBisector.y = -(vEnd.x - vStart.x); } else if (pNode == m_collPathPts.GetTail()) { LTVector vEnd = pNode->m_Data.m_vTran; LTVector vStart = pNode->m_pPrev->m_Data.m_vTran; vBisector.x = vEnd.y - vStart.y; vBisector.y = -(vEnd.x - vStart.x); } else { LTVector vPrev = pNode->m_pPrev->m_Data.m_vTran; LTVector vStart = pNode->m_Data.m_vTran; LTVector vEnd = pNode->m_pNext->m_Data.m_vTran; float x1 = vEnd.y - vStart.y; float y1 = -(vEnd.x - vStart.x); float z1 = vStart.z - vEnd.z; float x2 = vStart.y - vPrev.y; float y2 = -(vStart.x - vPrev.x); float z2 = vPrev.z - vEnd.z; vBisector.x = (x1 + x2) / 2.0f; vBisector.y = (y1 + y2) / 2.0f; } pNode->m_Data.m_vBisector = vBisector; } LTFLOAT fWidth = CalcCurWidth(); pNode->m_Data.m_vBisector.Norm( fWidth ); // Setup the colour float r, g, b, a; CalcColour(pNode->m_Data.m_tmElapsed, GetProps()->m_tmSectionLifespan, &r, &g, &b, &a); int ir = (int)(r * 255.0f); int ig = (int)(g * 255.0f); int ib = (int)(b * 255.0f); int ia = (int)(a * 255.0f); pNode->m_Data.m_red = Clamp( ir, 0, 255 ); pNode->m_Data.m_green = Clamp( ig, 0, 255 ); pNode->m_Data.m_blue = Clamp( ib, 0, 255 ); pNode->m_Data.m_alpha = Clamp( ia, 0, 255 ); pNode = pNode->m_pNext; } pNode = m_collPathPts.GetHead(); pNode = m_collPathPts.GetHead(); // Delete any dead nodes while (pNode->m_pNext) { CLinkListNode<PT_TRAIL_SECTION> *pDelNode= NULL; if (pNode->m_Data.m_tmElapsed >= GetProps()->m_tmSectionLifespan) { pDelNode = pNode; } pNode = pNode->m_pNext; if (pDelNode) m_collPathPts.Remove(pDelNode); } // Increment the offset m_uOffset += tmFrameTime * GetProps()->m_uAdd; // Success !! return true; }
LTBOOL CParticleSystemFX::Update() { if (!m_hObject || !m_pClientDE || m_bWantRemove) return LTFALSE; LTFLOAT fTime = m_pClientDE->GetTime(); // Hide/show the particle system if necessary... if (m_hServerObject) { uint32 dwUserFlags; g_pCommonLT->GetObjectFlags(m_hServerObject, OFT_User, dwUserFlags); if (!(dwUserFlags & USRFLG_VISIBLE)) { uint32 dwFlags; g_pCommonLT->GetObjectFlags(m_hObject, OFT_Flags, dwFlags); // Once last puff as disappeared, hide the system (no new puffs // will be added...) if (dwFlags & FLAG_VISIBLE) { if (fTime > m_fLastTime + m_cs.fParticleLifetime) { g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, 0, FLAG_VISIBLE); } } else { m_fLastTime = fTime; } return LTTRUE; } else { g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, FLAG_VISIBLE, FLAG_VISIBLE); } } // Debugging aid... if (s_cvarTweak.GetFloat() > 0) { TweakSystem(); } if (m_bFirstUpdate) { m_fLastTime = fTime; m_bFirstUpdate = LTFALSE; } // Make sure it is time to update... if (fTime < m_fLastTime + m_fNextUpdate) { return LTTRUE; } // Ok, how many to add this frame....(make sure time delta is no more than // 15 frames/sec... float fTimeDelta = fTime - m_fLastTime; fTimeDelta = fTimeDelta > 0.0666f ? 0.0666f : fTimeDelta; int nToAdd = (int) floor(m_cs.fParticlesPerSecond * fTimeDelta); nToAdd = LTMIN(nToAdd, (int)(MAX_PARTICLES_PER_SECOND * fTimeDelta)); nToAdd = GetNumParticles(nToAdd); m_pClientDE->AddParticles(m_hObject, nToAdd, &m_vMinOffset, &m_vMaxOffset, // Position offset &(m_cs.vMinVel), &(m_cs.vMaxVel), // Velocity &(m_cs.vColor1), &(m_cs.vColor2), // Color m_cs.fParticleLifetime, m_cs.fParticleLifetime); // Determine when next update should occur... if (m_cs.fBurstWait > 0.001f) { m_fNextUpdate = m_cs.fBurstWait * GetRandom(m_cs.fBurstWaitMin, m_cs.fBurstWaitMax); } else { m_fNextUpdate = 0.001f; } // Rotate the particle system... if (m_cs.fRotationVelocity != 0.0f) { LTRotation rRot; g_pLTClient->GetObjectRotation(m_hObject, &rRot); rRot.Rotate(rRot.Up(), g_pGameClientShell->GetFrameTime() * m_cs.fRotationVelocity); g_pLTClient->SetObjectRotation(m_hObject, &rRot); } m_fLastTime = fTime; return LTTRUE; }
bool CFallingStuffFX::Update(float tmFrameTime) { // Base class update first m_vLastPos = m_vPos; if (!CBaseFX::Update(tmFrameTime)) return false; //increment our emission time by the elapsed frame time m_tmElapsedEmission += tmFrameTime; if (!IsShuttingDown() && !IsSuspended() && (m_tmElapsedEmission > GetProps()->m_tmFallingStuffFXEmission)) { ObjectCreateStruct ocs; INIT_OBJECTCREATESTRUCT(ocs); LTVector vScale; vScale.Init(m_scale, m_scale, m_scale); LTVector vInterp; LTVector vInterpCur = m_vPos; // Calculate interpolant for particle system if (GetProps()->m_nFallingStuffFXEmission) { vInterp = m_vPos - m_vLastPos; vInterp /= (float)GetProps()->m_nFallingStuffFXEmission; } for (uint32 i = 0; i < GetProps()->m_nFallingStuffFXEmission; i ++) { ocs.m_ObjectType = OT_SPRITE; ocs.m_Flags = FLAG_VISIBLE | FLAG_NOLIGHT | FLAG_ROTATABLESPRITE; // Compute the initial position float xRand = GetProps()->m_fRadius * ((-10000.0f + (rand() % 20000)) / 10000.0f); float zRand = GetProps()->m_fRadius * ((-10000.0f + (rand() % 20000)) / 10000.0f); ocs.m_Pos = m_vPos + (m_vRight * xRand) + (m_vUp * zRand); ocs.m_Scale = vScale; strcpy(ocs.m_Filename, GetProps()->m_sSpriteName); // Move the start point vInterpCur += vInterp; HLOCALOBJ hNewSprite = m_pLTClient->CreateObject(&ocs); if (hNewSprite) { // Create a new sprite FALLING_THING *pNewSprite = debug_new( FALLING_THING ); if (GetProps()->m_nImpactCreate) { if (g_dwSplash > (uint32)GetProps()->m_nImpactCreate) { pNewSprite->m_bSplash = true; g_dwSplash = 0; } else { pNewSprite->m_bSplash = false; } } else { pNewSprite->m_bSplash = false; } g_dwSplash ++; if (pNewSprite) { LTVector v; // Compute the initial velocity v = m_vPlaneDir * GetProps()->m_fVel; pNewSprite->m_hObject = hNewSprite; pNewSprite->m_vVel = v; pNewSprite->m_tmElapsed = 0.0f; pNewSprite->m_vPos = ocs.m_Pos; pNewSprite->m_vLastPos = ocs.m_Pos; m_collSprites.AddTail(pNewSprite); } } } m_tmElapsedEmission = 0.0f; // And store the last position m_vLastPos = m_vPos; } LTMatrix mSpin; if (GetProps()->m_bUseSpin) { // Setup rotation LTMatrix vRight; LTMatrix vUp; LTMatrix vForward; LTMatrix vTmp; Mat_SetupRot(&vRight, &m_vRight, m_xRot); Mat_SetupRot(&vUp, &m_vUp, m_yRot); Mat_SetupRot(&vForward, &m_vPlaneDir, m_zRot); MatMul(&vTmp, &vRight, &vUp); MatMul(&mSpin, &vTmp, &vForward); m_xRot += GetProps()->m_vRotAdd.x * tmFrameTime; m_yRot += GetProps()->m_vRotAdd.y * tmFrameTime; m_zRot += GetProps()->m_vRotAdd.z * tmFrameTime; } // Get the camera rotation LTRotation orient; m_pLTClient->GetObjectRotation(m_hCamera, &orient); LTRotation dRot(orient); LTVector vF = orient.Forward(); float rot = (float)atan2(vF.x, vF.z); // Update the sprites.... CLinkListNode<FALLING_THING *> *pNode = m_collSprites.GetHead(); CLinkListNode<FALLING_THING *> *pDelNode; while (pNode) { pDelNode = NULL; FALLING_THING *pSprite = pNode->m_Data; //adjust our elapsed time pSprite->m_tmElapsed += tmFrameTime; // Check for expiration if (pSprite->m_tmElapsed > GetProps()->m_tmSpriteLifespan) { // Destroy this object m_pLTClient->RemoveObject(pSprite->m_hObject); pDelNode = pNode; } else { // Update !! pSprite->m_vLastPos = pSprite->m_vPos; pSprite->m_vPos += (pSprite->m_vVel * tmFrameTime); // Rotate if neccessary TVector3<float> vPos = pSprite->m_vPos; if (GetProps()->m_bUseSpin) { MatVMul_InPlace(&mSpin, &vPos); } // Add in wind vPos += (GetProps()->m_vWind * GetProps()->m_fWindAmount) * tmFrameTime; // Setup the new sprite position LTVector vPos2 = vPos; m_pLTClient->SetObjectPos(pSprite->m_hObject, &vPos2); // Setup the colour float r, g, b, a; m_pLTClient->GetObjectColor(pSprite->m_hObject, &r, &g, &b, &a); CalcColour(pSprite->m_tmElapsed, GetProps()->m_tmSpriteLifespan, &r, &g, &b, &a); m_pLTClient->SetObjectColor(pSprite->m_hObject, r, g, b, a); // Setup the scale float scale = 0.1f; CalcScale(pSprite->m_tmElapsed, GetProps()->m_tmSpriteLifespan, &scale); LTVector vScale; vScale.Init(scale, scale * GetProps()->m_fStretchMul, scale); m_pLTClient->SetObjectScale(pSprite->m_hObject, &vScale); // Setup the rotation dRot = LTRotation(0, 0, 0, 1); LTRotation orient(dRot); orient.Rotate( orient.Up(), rot ); m_pLTClient->SetObjectRotation(pSprite->m_hObject, &orient); // Check to see if we need to start a splash sprite if (pSprite->m_bSplash) { ClientIntersectQuery ciq; ClientIntersectInfo cii; ciq.m_From = pSprite->m_vLastPos; ciq.m_To = pSprite->m_vPos; if ((GetProps()->m_sImpactSpriteName[0]) && (m_pLTClient->IntersectSegment(&ciq, &cii))) { // Create a splash sprite SPLASH *pSplash = debug_new( SPLASH ); ObjectCreateStruct ocs; INIT_OBJECTCREATESTRUCT(ocs); LTVector vScale; vScale.Init(0.0f, 0.0f, 0.0f); ocs.m_ObjectType = OT_SPRITE; ocs.m_Flags = FLAG_VISIBLE | FLAG_ROTATABLESPRITE | FLAG_NOLIGHT; ocs.m_Pos = cii.m_Point + (cii.m_Plane.m_Normal * 2.0f); ocs.m_Scale = vScale; LTRotation dOrient( cii.m_Plane.m_Normal, LTVector(0.0f, 1.0f, 0.0f) ); strcpy(ocs.m_Filename, GetProps()->m_sImpactSpriteName); pSplash->m_hObject = m_pLTClient->CreateObject(&ocs); pSplash->m_scale = 0.0f; LTRotation orient(dRot); m_pLTClient->SetObjectRotation(pSplash->m_hObject, &orient); pSplash->m_tmElapsed = 0.0f; m_collSplashes.AddTail(pSplash); // Destroy this object m_pLTClient->RemoveObject(pSprite->m_hObject); // Delete the sprite pDelNode = pNode; } } } pNode = pNode->m_pNext; if (pDelNode) m_collSprites.Remove(pDelNode); } // Update our splashes CLinkListNode<SPLASH *> *pSplashNode = m_collSplashes.GetHead(); while (pSplashNode) { CLinkListNode<SPLASH *> *pDelNode = NULL; SPLASH *pSplash = pSplashNode->m_Data; //update the elapsed time on the splash pSplash->m_tmElapsed += tmFrameTime; // Calculate the new scale float scale = GetProps()->m_fImpactScale1 + ((GetProps()->m_fImpactScale2 - GetProps()->m_fImpactScale1) * (pSplash->m_tmElapsed / GetProps()->m_tmImpactLifespan)); LTVector vScale(scale, scale, scale); m_pLTClient->SetObjectScale(pSplash->m_hObject, &vScale); float r, g, b, a; m_pLTClient->GetObjectColor(pSplash->m_hObject, &r, &g, &b, &a); a = (float)(int)(pSplash->m_tmElapsed / GetProps()->m_tmImpactLifespan); if (a < 0.0f) a = 0.0f; if (a > 1.0f) a = 1.0f; m_pLTClient->SetObjectColor(pSplash->m_hObject, r, g, b, a); if (pSplash->m_tmElapsed > GetProps()->m_tmImpactLifespan) { m_pLTClient->RemoveObject(pSplash->m_hObject); pDelNode = pSplashNode; } pSplashNode = pSplashNode->m_pNext; if (pDelNode) m_collSplashes.Remove(pDelNode); } // Success !! return true; }
void CLightningFX::EmitBolts( float tmFrameTime ) { // Make sure enough time between emissions has passed... m_tmElapsedEmission += tmFrameTime; if( m_fDelay < m_tmElapsedEmission ) { LTransform lTrans; LTVector vAttractorPos; ILTModel *pModelLT = m_pLTClient->GetModelLT(); uint32 nActiveBolts = GetRandom( (int)GetProps()->m_nMinNumBolts, (int)GetProps()->m_nMaxNumBolts ); uint32 nBolt; bool bCanUseAttractors = (m_lstAttractors.size() > 0); bool bCanUseRadius = (GetProps()->m_fOmniDirectionalRadius >= 1.0f); CLightningBolt *pBolt = LTNULL; LightningBolts::iterator iter; for( nBolt = 0, iter = m_lstBolts.begin(); iter != m_lstBolts.end(), nBolt < nActiveBolts; ++iter, ++nBolt ) { pBolt = *iter; pBolt->m_fWidth = GetRandom( GetProps()->m_fMinBoltWidth, GetProps()->m_fMaxBoltWidth ); pBolt->m_fLifetime = GetRandom( GetProps()->m_fMinLifetime, GetProps()->m_fMaxLifetime ); pBolt->m_tmElapsed = 0.0f; pBolt->m_bActive = true; // Grab the position of the object to compensate for offset if( m_hTarget ) { m_pLTClient->GetObjectPos( m_hTarget, &vAttractorPos ); } else { vAttractorPos = m_vTargetPos; } // Decide if we should use an attractor or radius for the end pos... if( bCanUseAttractors && (!bCanUseRadius || GetRandom(0,1)) ) { uint8 nIndex = GetRandom( 0, (int)(m_lstAttractors.size()) - 1 ); CAttractor cAttractor = m_lstAttractors[nIndex]; if( cAttractor.GetTransform( lTrans, true ) == LT_OK ) { vAttractorPos = lTrans.m_Pos; } } else if( bCanUseRadius ) { LTVector vRandomPos; vRandomPos.x = GetRandom( -1.0f, 1.0f ); vRandomPos.y = GetRandom( -1.0f, 1.0f ); vRandomPos.z = GetRandom( -1.0f, 1.0f ); vRandomPos.Normalize(); vRandomPos *= GetRandom( -GetProps()->m_fOmniDirectionalRadius, GetProps()->m_fOmniDirectionalRadius ); vAttractorPos = m_vPos + vRandomPos; IntersectQuery iQuery; IntersectInfo iInfo; iQuery.m_From = m_vPos; iQuery.m_To = vAttractorPos; if( m_pLTClient->IntersectSegment( &iQuery, &iInfo )) { vAttractorPos = iInfo.m_Point; } } LTVector vNew = m_vPos; LTVector vDir = vAttractorPos - vNew; float fStep = vDir.Length() / (float)pBolt->m_nNumSegments; float fPerturb = GetRandom( GetProps()->m_fMinPerturb, GetProps()->m_fMaxPerturb ); vDir.Normalize(); LTRotation rRot = LTRotation( vDir, LTVector( 0.0f, 1.0f, 0.0f )); CLinkListNode<PT_TRAIL_SECTION> *pNode = pBolt->m_collPathPts.GetHead(); while( pNode ) { pNode->m_Data.m_vPos = vNew; pNode->m_Data.m_tmElapsed = 0.0f; pNode->m_Data.m_vBisector.Init(); // Add in some perturb going in the direction of the attractor pos for the next section... vNew += (rRot.Forward() * fStep ); vNew += (rRot.Up() * GetRandom( -fPerturb, fPerturb )); vNew += (rRot.Right() * GetRandom( -fPerturb, fPerturb )); // Make sure the last section goes to the end pos... if( !pNode->m_pNext ) pNode->m_Data.m_vPos = vAttractorPos; pNode = pNode->m_pNext; } } // Decide when the next emission will be... m_tmElapsedEmission = 0.0f; m_fDelay = GetRandom( GetProps()->m_fMinDelay, GetProps()->m_fMaxDelay ); } }
void CLaserBeam::Update(LTVector &vBeamStartPos, const LTRotation* pRDirRot, LTBOOL b3rdPerson, LTBOOL bDetect) { if (!m_bOn) return; // Calculate beam position... HOBJECT hCamera = g_pPlayerMgr->GetCamera(); if (!hCamera) return; HLOCALOBJ hPlayerObj = g_pLTClient->GetClientObject(); if (!hPlayerObj) return; HOBJECT hFilterList[] = {hPlayerObj, g_pPlayerMgr->GetMoveMgr()->GetObject(), LTNULL}; IntersectQuery qInfo; IntersectInfo iInfo; LTVector vPos(0, 0, 0); LTRotation rRot; LTVector vU, vR, vF; if (pRDirRot && b3rdPerson) { vPos = vBeamStartPos; vU = pRDirRot->Up(); vR = pRDirRot->Right(); vF = pRDirRot->Forward(); } else { g_pLTClient->GetObjectRotation(hCamera, &rRot); g_pLTClient->GetObjectPos(hCamera, &vPos); vU = rRot.Up(); vR = rRot.Right(); vF = rRot.Forward(); if (g_cvarLaserBeamDebug.GetFloat() == 0.0f) { vBeamStartPos += vPos; } else if (g_cvarLaserBeamDebug.GetFloat() == 1.0f) { vBeamStartPos = vPos; } else if (pRDirRot) { vU = pRDirRot->Up(); vR = pRDirRot->Right(); vF = pRDirRot->Forward(); vBeamStartPos = vBeamStartPos; } } LTVector vEndPos = vPos + (vF * 10000.0f); qInfo.m_From = vPos; qInfo.m_To = vEndPos; qInfo.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID; qInfo.m_FilterFn = ObjListFilterFn; qInfo.m_pUserData = hFilterList; if (g_pLTClient->IntersectSegment(&qInfo, &iInfo)) { vEndPos = iInfo.m_Point; } // Show the light beam... LTVector vColor = LTVector(GetRandom(235.0f, 255.0f), GetRandom(35.0f, 55.0f), GetRandom(35.0f, 55.0f));; LTFLOAT fAlpha = g_cvarLaserBeamAlpha.GetFloat(); if (iInfo.m_hObject && bDetect) { uint32 dwUsrFlgs = 0; g_pCommonLT->GetObjectFlags(iInfo.m_hObject, OFT_User, dwUsrFlgs); if (dwUsrFlgs & USRFLG_CHARACTER) { fAlpha = 0.95f; vColor.Init(GetRandom(35.0f, 55.0f), GetRandom(235.0f, 255.0f), GetRandom(35.0f, 55.0f));; } } LTFLOAT fWidth = g_cvarLaserBeamThickness.GetFloat(); fWidth = b3rdPerson ? fWidth*2.0f : fWidth; vBeamStartPos += (vF * g_cvarLaserBeamFOffset.GetFloat()); vBeamStartPos += (vR * g_cvarLaserBeamROffset.GetFloat()); vBeamStartPos += (vU * g_cvarLaserBeamUOffset.GetFloat()); PLFXCREATESTRUCT pls; if (g_cvarLaserBeamDebug.GetFloat() >= 0.0f) { // g_pLTClient->CPrint("StartPos = %.2f, %.2f, %.2f", VEC_EXPAND(vBeamStartPos)); // g_pLTClient->CPrint("EndPos = %.2f, %.2f, %.2f", VEC_EXPAND(vEndPos)); } pls.vStartPos = vBeamStartPos; pls.vEndPos = vEndPos; pls.vInnerColorStart = vColor; pls.vInnerColorEnd = pls.vInnerColorStart; pls.vOuterColorStart = LTVector(0, 0, 0); pls.vOuterColorEnd = LTVector(0, 0, 0); pls.fAlphaStart = fAlpha; pls.fAlphaEnd = fAlpha; pls.fMinWidth = 0; pls.fMaxWidth = fWidth; pls.fMinDistMult = 1.0f; pls.fMaxDistMult = 1.0f; pls.fLifeTime = 1.0f; pls.fAlphaLifeTime = 1.0f; pls.fPerturb = 0.0f; pls.bAdditive = LTTRUE; pls.bAlignFlat = b3rdPerson ? LTFALSE : LTTRUE; pls.nWidthStyle = PLWS_CONSTANT; pls.nNumSegments = (int)g_cvarLaserBeamNumSegments.GetFloat(); if (m_LightBeam.HasBeenDrawn()) { // Keep the light beam in the vis list... m_LightBeam.SetPos(vBeamStartPos); // Hide the beam in portals if 1st person...Also set flag really // close to true... uint32 dwFlags2, dwFlags; dwFlags = m_LightBeam.GetFlags(); dwFlags2 = m_LightBeam.GetFlags2(); if (b3rdPerson) { dwFlags &= ~FLAG_REALLYCLOSE; } else { if (g_cvarLaserBeamDebug.GetFloat() > 1.0f) { dwFlags |= FLAG_REALLYCLOSE; pls.bUseObjectRotation = LTTRUE; } } m_LightBeam.SetFlags(dwFlags); m_LightBeam.SetFlags2(dwFlags2); m_LightBeam.ReInit(&pls); } else { m_LightBeam.Init(&pls); m_LightBeam.CreateObject(g_pLTClient); } m_LightBeam.Update(); }
LTBOOL CParticleExplosionFX::Update() { if (!m_hObject || !m_pClientDE) return LTFALSE; if (!CBaseParticleSystemFX::Update()) return LTFALSE; LTFLOAT fTime = m_pClientDE->GetTime(); if (m_bFirstUpdate) { m_bFirstUpdate = LTFALSE; m_fStartTime = fTime; m_fLastTime = fTime; } // Check to see if we should start fading the system... if (fTime > m_fStartTime + m_fFadeTime) { LTFLOAT fEndTime = m_fStartTime + m_fLifeTime; if (fTime > fEndTime) { return LTFALSE; } LTFLOAT fScale = (fEndTime - fTime) / (m_fLifeTime - m_fFadeTime); LTFLOAT r, g, b, a; m_pClientDE->GetObjectColor(m_hObject, &r, &g, &b, &a); m_pClientDE->SetObjectColor(m_hObject, r, g, b, fScale); } // See if it is time to create a new Particle puff... if (fTime >= m_fLastTime + m_fOffsetTime) { // Loop over our list of Emitters, creating new particles... for (int i=0; i < m_nNumEmitters; i++) { if (m_ActiveEmitters[i]) { AddParticles(&m_Emitters[i]); } } m_fLastTime = fTime; } // Loop over our list of Emitters, updating the position of each for (int i=0; i < m_nNumEmitters; i++) { if (m_ActiveEmitters[i]) { LTBOOL bBounced = LTFALSE; if (bBounced = UpdateEmitter(&m_Emitters[i])) { if (!(m_Emitters[i].m_dwPhysicsFlags & MO_LIQUID) && (m_hDebris[i])) { /* char* pSound = GetDebrisBounceSound(DBT_STONE_BIG); // Play appropriate sound... g_pClientSoundMgr->PlaySoundFromPos(m_Emitters[i].m_Pos, pSound, 300.0f, SOUNDPRIORITY_MISC_LOW); */ } m_BounceCount[i]--; if (m_BounceCount[i] <= 0) { m_Emitters[i].m_dwPhysicsFlags |= MO_RESTING; } } if (m_Emitters[i].m_dwPhysicsFlags & MO_RESTING) { m_ActiveEmitters[i] = LTFALSE; if (m_hDebris[i]) { m_pClientDE->RemoveObject(m_hDebris[i]); m_hDebris[i] = LTNULL; } } else if (m_hDebris[i]) { g_pLTClient->SetObjectPos(m_hDebris[i], &(m_Emitters[i].m_vPos)); if (m_bRotateDebris) { if (bBounced) { // Adjust due to the bounce... m_fPitchVel = GetRandom(-MATH_CIRCLE, MATH_CIRCLE); m_fYawVel = GetRandom(-MATH_CIRCLE, MATH_CIRCLE); } if (m_fPitchVel != 0 || m_fYawVel != 0) { LTFLOAT fDeltaTime = g_pGameClientShell->GetFrameTime(); m_fPitch += m_fPitchVel * fDeltaTime; m_fYaw += m_fYawVel * fDeltaTime; LTRotation rRot; rRot.Rotate(rRot.Up(), m_fYaw); rRot.Rotate(rRot.Right(), m_fPitch); g_pLTClient->SetObjectRotation(m_hDebris[i], &rRot); } } } } } return LTTRUE; }