static void CreateServerMark(CLIENTWEAPONFX & theStruct) { AMMO* pAmmo = g_pWeaponMgr->GetAmmo(theStruct.nAmmoId); if (!pAmmo) return; // If this isn't a GameBase object, return... if (!IsGameBase(theStruct.hObj)) return; // See if we should create a mark, or simply move one of the GameBase's // marks. // If the GameBase has the max number of marks or this mark is very close // to a pre-existing mark, just move that mark to the new position. GameBase* pObj = (GameBase*) g_pLTServer->HandleToObject(theStruct.hObj); if (!pObj) return; HOBJECT hMoveObj = LTNULL; HOBJECT hFarObj = LTNULL; ObjectList* pMarkList = pObj->GetMarkList(); if (pMarkList) { uint8 nNumMarks = pMarkList->m_nInList; ObjectLink* pLink = pMarkList->m_pFirstLink; LTFLOAT fClosestMarkDist = REGION_DIAMETER; LTFLOAT fFarthestMarkDist = 0.0f; uint8 nNumInRegion = 0; LTVector vPos; for (int i=0; i < nNumMarks && pLink; i++) { if (pLink->m_hObject) { HATTACHMENT hAttachment; if (LT_OK == g_pLTServer->FindAttachment(theStruct.hObj, pLink->m_hObject, &hAttachment)) { LTransform transform; g_pLTServer->Common()->GetAttachmentTransform(hAttachment, transform, LTTRUE); vPos = transform.m_Pos; } LTFLOAT fDist = VEC_DISTSQR(vPos, theStruct.vPos); if (fDist < REGION_DIAMETER) { if (fDist < fClosestMarkDist) { fClosestMarkDist = fDist; hMoveObj = pLink->m_hObject; } if (++nNumInRegion > MAX_MARKS_IN_REGION) { // Just move this mark to the correct pos... hMoveObj = hMoveObj ? hMoveObj : pLink->m_hObject; break; } } if (fDist > fFarthestMarkDist) { fFarthestMarkDist = fDist; hFarObj = pLink->m_hObject; } } pLink = pLink->m_pNext; } // If we've got the max number of marks on this object, just move // the closest one to the new position... if (nNumMarks >= MAX_MARKS_PER_OBJECT) { hMoveObj = hMoveObj ? hMoveObj : (hFarObj ? hFarObj : pMarkList->m_pFirstLink->m_hObject); } else { hMoveObj = LTNULL; // Need to create one... } } // Re-setup the object to move it... if (hMoveObj && IsKindOf(hMoveObj, "CServerMark")) { CServerMark* pMoveMark = (CServerMark*) g_pLTServer->HandleToObject(hMoveObj); if (!pMoveMark) return; // Since this mark is already attached to pObj, remove the attachment // (since CServerMark::Setup() will re-attach it)... HATTACHMENT hAttachment; if (LT_OK == g_pLTServer->FindAttachment(theStruct.hObj, hMoveObj, &hAttachment)) { g_pLTServer->RemoveAttachment(hAttachment); } pMoveMark->Setup((CLIENTWEAPONFX)theStruct); return; } // Okay, no luck, need to create a new mark... ObjectCreateStruct createStruct; INIT_OBJECTCREATESTRUCT(createStruct); LTFLOAT fScaleAdjust = 1.0f; if (!GetImpactSprite((SurfaceType)theStruct.nSurfaceType, fScaleAdjust, theStruct.nAmmoId, createStruct.m_Filename, ARRAY_LEN(createStruct.m_Filename))) { return; } createStruct.m_ObjectType = OT_SPRITE; createStruct.m_Flags = FLAG_VISIBLE | FLAG_NOLIGHT | FLAG_ROTATEABLESPRITE; createStruct.m_Pos = theStruct.vPos; g_pLTServer->AlignRotation(&(createStruct.m_Rotation), &((LTVector)theStruct.vSurfaceNormal), LTNULL); HCLASS hClass = g_pLTServer->GetClass("CServerMark"); CServerMark* pMark = (CServerMark*) g_pLTServer->CreateObject(hClass, &createStruct); if (!pMark) return; // Add the mark to the object... pObj->AddMark(pMark->m_hObject); // Randomly adjust the mark's scale to add a bit o spice... if (pAmmo->pImpactFX) { LTFLOAT fScale = fScaleAdjust * pAmmo->pImpactFX->fMarkScale; LTVector vScale; VEC_SET(vScale, fScale, fScale, fScale); g_pLTServer->ScaleObject(pMark->m_hObject, &vScale); } pMark->Setup((CLIENTWEAPONFX)theStruct); }
LTBOOL CSearchLightFX::CreateObject(ILTClient* pClientDE) { if (!CSpecialFX::CreateObject(pClientDE) || !m_hServerObject) return LTFALSE; ObjectCreateStruct createStruct; INIT_OBJECTCREATESTRUCT(createStruct); // Create the beam model... m_pClientDE->GetObjectPos(m_hServerObject, &(createStruct.m_Pos)); createStruct.m_ObjectType = OT_MODEL; CString str = g_pClientButeMgr->GetSpecialFXAttributeString("SearchBeam"); if (str.IsEmpty()) return LTFALSE; SAFE_STRCPY(createStruct.m_Filename, (char *)(LPCSTR)str); str = g_pClientButeMgr->GetSpecialFXAttributeString("SearchSkin"); if (!str.IsEmpty()) { SAFE_STRCPY(createStruct.m_SkinName, (char *)(LPCSTR)str); } createStruct.m_Flags = FLAG_VISIBLE | FLAG_NOLIGHT; if (m_cs.bBeamAdditive) { createStruct.m_Flags2 = FLAG2_ADDITIVE; } m_hBeam = m_pClientDE->CreateObject(&createStruct); if (!m_hBeam) return LTFALSE; LTFLOAT r, g, b, a; m_pClientDE->GetObjectColor(m_hBeam, &r, &g, &b, &a); r = g = b = 1.0f; m_pClientDE->SetObjectColor(m_hBeam, r, g, b, m_cs.fBeamAlpha); // Create the dynamic light... if (m_cs.fLightRadius > 1.0f) { createStruct.m_ObjectType = OT_LIGHT; createStruct.m_Flags = FLAG_VISIBLE | FLAG_DONTLIGHTBACKFACING; m_hLight = m_pClientDE->CreateObject(&createStruct); if (!m_hLight) return LTFALSE; m_pClientDE->SetLightColor(m_hLight, m_cs.vLightColor.x, m_cs.vLightColor.y, m_cs.vLightColor.z); m_pClientDE->SetLightRadius(m_hLight, m_cs.fLightRadius); } // Create the lens flare... LENSFLARECREATESTRUCT lens = m_cs.lens; lens.hServerObj = m_hServerObject; lens.bInSkyBox = LTFALSE; lens.bCreateSprite = LTTRUE; lens.bSpriteOnly = LTTRUE; lens.bUseObjectAngle = LTTRUE; if (!m_LensFlare.Init(&lens) || !m_LensFlare.CreateObject(m_pClientDE)) { return LTFALSE; } return LTTRUE; }
bool CSnowFXAirspace::Activate( float detail ) { // update the LOD ASSERT( detail > 0.0f && detail <= 1.0f ); m_LOD = detail; // don't do anything else if already active if( m_Active ) return true; #ifdef SNOWFX_PROFILE_ACTIVATION LARGE_INTEGER pcStart, pcEnd, pcFreq; QueryPerformanceFrequency( &pcFreq ); QueryPerformanceCounter( &pcStart ); #endif if( !m_Parent->m_ParticleMgr.AllocateParticles( m_NumParticles, m_Particles ) ) return false; m_Active = true; // allocate space for the particle minimum elevation array m_MinY = debug_newa( float, m_NumParticles ); // initialize the minimum elevation array for( uint32 i = 0; i < m_NumParticles; i++ ) { m_MinY[i] = m_Pos.y - m_Dims.y; } // adjust minimum elevation array by blockers for( std::vector<uint32>::iterator it = m_Blockers.begin(); it != m_Blockers.end(); it++ ) { float t; LTPlane blockerPlane; uint32 numEdges; LTPlane* edgePlanes; // get the current particle blocker m_Parent->m_pClientDE->GetParticleBlockerEdgesXZ( *it, blockerPlane, numEdges, edgePlanes ); // don't consider nearly vertical blockers if( fabs(blockerPlane.m_Normal.y) < 0.00001 ) continue; // precalculate some stuff for plane intersection calculations float dc = -1.0f / blockerPlane.m_Normal.y; float xc = blockerPlane.m_Normal.x * dc; float zc = blockerPlane.m_Normal.z * dc; dc *= blockerPlane.m_Dist; LTVector curPos; curPos.y = 0.0f; // check all particles against this blocker for( uint32 i = 0; i < m_NumParticles; i++ ) { curPos.x = m_Pos.x + m_Particles[i].pos.x * m_Dims.x; curPos.z = m_Pos.z + m_Particles[i].pos.z * m_Dims.z; // check if the xz of the particle is within the projected xz polygon if( TestParticleBlocker( curPos, numEdges, const_cast<const LTPlane *&>(edgePlanes) ) ) { // find where the particle hits the blocker t = dc + curPos.x * xc + curPos.z * zc; if( t > m_MinY[i] ) m_MinY[i] = t; } } } // create the volume effect (either reusing an old one, or creating a new one) if( !m_Parent->freeEffects.empty() ) { m_Effect = HOBJECT(*m_Parent->freeEffects.begin()); m_Parent->freeEffects.pop_front(); m_Parent->m_pClientDE->SetObjectPos( m_Effect, &m_Pos ); g_pCommonLT->SetObjectFlags( m_Effect, OFT_Flags, FLAG_VISIBLE, FLAG_VISIBLE ); } else { ObjectCreateStruct ocs; INIT_OBJECTCREATESTRUCT( ocs ); ocs.m_ObjectType = OT_VOLUMEEFFECT; ocs.m_Flags = FLAG_VISIBLE; ocs.m_Flags2 = FLAG2_FORCETRANSLUCENT; ocs.m_Pos = m_Pos; ocs.m_Rotation.Init(); m_Effect = m_Parent->m_pClientDE->CreateObject( &ocs ); } VolumeEffectInfo vei; vei.m_EffectType = VolumeEffectInfo::kDynamicParticles; vei.m_Dims = m_Dims; vei.m_DPPrimitive = VolumeEffectInfo::kTrilist; vei.m_DPLighting = m_Parent->m_bUseLighting ? VolumeEffectInfo::kSinglePointNonDirectional : VolumeEffectInfo::kNone; vei.m_DPLightConstant = 0xffffffff; vei.m_DPSaturate = m_Parent->m_bUseSaturate; vei.m_DPTextureName = m_Parent->m_pClientDE->GetStringData( m_Parent->m_hstrTextureName ); vei.m_DPUserData = this; vei.m_DPUpdateFn = &SnowFXFillVertexBuffer; m_Parent->m_pClientDE->SetupVolumeEffect( m_Effect, vei ); m_Parent->activeAirspaces.insert( this ); #ifdef SNOWFX_PROFILE_ACTIVATION QueryPerformanceCounter( &pcEnd ); double pcTime = (double)(pcEnd.QuadPart - pcStart.QuadPart) * (double)1000.0 / (double)pcFreq.QuadPart; g_pLTClient->CPrint( " Snow Activation: %8.6f ms", pcTime ); #endif return true; }
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 SecurityCamera::SetupDisabledState() { if (m_eState == eStateDisabled || m_hDisablerModel) return; g_pCommonLT->SetObjectFlags(m_hObject, OFT_User, 0, USRFLG_GADGET_CAMERA_DISABLER); // Create the camera disabler model, and attach it to the camera... ObjectCreateStruct theStruct; INIT_OBJECTCREATESTRUCT(theStruct); theStruct.m_Pos = m_vPos; char szFile[128] = {0}; g_pServerButeMgr->GetSecurityCameraString( SCS_DISABLER_FILENAME, szFile, ARRAY_LEN( szFile )); if( szFile[0] ) SAFE_STRCPY(theStruct.m_Filename, szFile); szFile[0] = '\0'; g_pServerButeMgr->GetSecurityCameraString( SCS_DISABLER_SKIN, szFile, ARRAY_LEN( szFile )); if( szFile[0] ) SAFE_STRCPY(theStruct.m_SkinName, szFile); theStruct.m_Flags = FLAG_VISIBLE | FLAG_GOTHRUWORLD; theStruct.m_ObjectType = OT_MODEL; HCLASS hClass = g_pLTServer->GetClass("BaseClass"); LPBASECLASS pModel = g_pLTServer->CreateObject(hClass, &theStruct); if (!pModel) return; m_hDisablerModel = pModel->m_hObject; // Don't eat ticks please... ::SetNextUpdate(m_hDisablerModel, UPDATE_NEVER); // Attach the model to the the camera... LTVector vOffset(0, 0, 0); LTRotation rOffset; HATTACHMENT hAttachment; LTRESULT dRes = g_pLTServer->CreateAttachment(m_hObject, m_hDisablerModel, "Disabler", &vOffset, &rOffset, &hAttachment); if (dRes != LT_OK) { g_pLTServer->RemoveObject(m_hDisablerModel); m_hDisablerModel = LTNULL; return; } // Set the Disabler's animation... HMODELANIM hAni = g_pLTServer->GetAnimIndex(m_hDisablerModel, "Activate"); if (hAni) { g_pLTServer->SetModelLooping(m_hDisablerModel, LTFALSE); g_pLTServer->SetModelAnimation(m_hDisablerModel, hAni); } // Play the activate sound... szFile[0] = '\0'; g_pServerButeMgr->GetSecurityCameraString( SCS_DISABLER_SOUND, szFile, ARRAY_LEN( szFile )); LTFLOAT fRadius = g_pServerButeMgr->GetSecurityCameraFloat( SCS_SOUND_RADIUS ); if( szFile ) g_pServerSoundMgr->PlaySoundFromPos(m_vPos, szFile, fRadius, SOUNDPRIORITY_MISC_LOW); // Camera is now disabled... m_bDisabled = LTTRUE; }