void CDeathFX::CreateVehicleDeathFX() { CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr(); if (!psfxMgr) return; GIBCREATESTRUCT gib; m_pClientDE->AlignRotation(&(gib.rRot), &m_vDir, LTNULL); LTFLOAT fDamage = VEC_MAG(m_vDir); VEC_COPY(gib.vPos, m_vPos); VEC_SET(gib.vMinVel, 50.0f, 100.0f, 50.0f); VEC_MULSCALAR(gib.vMinVel, gib.vMinVel, fDamage); VEC_SET(gib.vMaxVel, 100.0f, 200.0f, 100.0f); VEC_MULSCALAR(gib.vMaxVel, gib.vMaxVel, fDamage); gib.fLifeTime = 20.0f; gib.fFadeTime = 7.0f; gib.nGibFlags = 0; gib.bRotate = LTTRUE; gib.eModelId = m_eModelId; gib.eModelStyle = m_eModelStyle; gib.nCode = m_eCode; gib.bSubGibs = LTTRUE; SetupGibTypes(gib); psfxMgr->CreateSFX(SFX_GIB_ID, &gib); }
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; }
DBOOL CShellCasingFX::CreateObject(CClientDE *pClientDE) { if (!CSpecialFX::CreateObject(pClientDE)) return DFALSE; char* pModelName = DNULL; char* pSkinName = DNULL; if (!GetFileNames(&pModelName, &pSkinName)) return DFALSE; if (!pModelName || !pSkinName) return DFALSE; // Setup the shell... ObjectCreateStruct createStruct; INIT_OBJECTCREATESTRUCT(createStruct); createStruct.m_ObjectType = OT_MODEL; createStruct.m_Flags = 0; _mbscpy((unsigned char*)createStruct.m_Filename, (const unsigned char*)pModelName); _mbscpy((unsigned char*)createStruct.m_SkinName, (const unsigned char*)pSkinName); VEC_COPY(createStruct.m_Pos, m_vStartPos); ROT_COPY(createStruct.m_Rotation, m_rRot); m_hObject = pClientDE->CreateObject(&createStruct); if (!m_hObject) return DFALSE; m_pClientDE->SetObjectScale(m_hObject, &m_vScale); DVector vU, vR, vF; pClientDE->GetRotationVectors(&m_rRot, &vU, &vR, &vF); DVector vVel; if(m_bLeftHanded) VEC_NEGATE(vR, vR); DFLOAT fUpVel = GetRandom(60.0f, 90.0f); VEC_MULSCALAR(vU, vU, fUpVel); DFLOAT fRightVel = GetRandom(50.0f, 70.0f); VEC_MULSCALAR(vR, vR, fRightVel); DFLOAT fForwardVel = GetRandom(10.0f, 25.0f); VEC_MULSCALAR(vF, vF, fForwardVel); VEC_ADD(vVel, vU, vR); VEC_ADD(vVel, vVel, vF); InitMovingObject(&m_movingObj, &m_vStartPos, &vVel);; m_movingObj.m_PhysicsFlags |= MO_HALFGRAVITY; m_fExpireTime = 20.0f + m_pClientDE->GetTime(); // Set the pitch velocity m_fPitchVel = GetRandom(-MATH_CIRCLE * 2, MATH_CIRCLE * 2); m_fYawVel = GetRandom(-MATH_CIRCLE * 2, MATH_CIRCLE * 2); m_fPitch = m_fYaw = 0.0f; return DTRUE; }
void DeathShroud::MC_Dead() { DVector vColor; DFLOAT fAlpha = 0.0f; m_pServerDE->GetObjectColor(m_hObject,&vColor.x, &vColor.y, &vColor.z, &fAlpha); if (m_bAnimating == DFALSE || m_nCurMetacmd != MC_DEAD) { if(m_hLoopSound) { m_pServerDE->KillSound(m_hLoopSound); m_hLoopSound = DNULL; } m_pServerDE->SetObjectColor(m_hObject,vColor.x,vColor.y,vColor.z, 1.0f); int nSideHit = m_damage.GetSideHit(); switch(m_damage.GetNodeHit()) { case NODE_NECK: m_nCorpseType = m_pAnim_Sound->m_nAnim_DEATH[0 + nSideHit]; break; case NODE_TORSO: m_nCorpseType = m_pAnim_Sound->m_nAnim_DEATH[1 + nSideHit]; break; case NODE_RARM: m_nCorpseType = m_pAnim_Sound->m_nAnim_DEATH[2 + nSideHit]; break; case NODE_LARM: m_nCorpseType = m_pAnim_Sound->m_nAnim_DEATH[3 + nSideHit]; break; case NODE_LLEG: m_nCorpseType = m_pAnim_Sound->m_nAnim_DEATH[4 + nSideHit]; break; case NODE_RLEG: m_nCorpseType = m_pAnim_Sound->m_nAnim_DEATH[5 + nSideHit]; break; } m_pServerDE->SetModelLooping(m_hObject, DFALSE); m_bAnimating = DTRUE; m_nCurMetacmd = MC_DEAD; } else { VEC_MULSCALAR(m_vScale, m_vScale, 0.9f); VEC_MULSCALAR(m_vDims, m_vDims, 0.9f); m_pServerDE->ScaleObject(m_hObject, &m_vScale); m_pServerDE->SetObjectDims2(m_hObject, &m_vDims); fAlpha -= 0.05f; if(fAlpha <= 0.0f) fAlpha = 0.0f; m_pServerDE->SetObjectColor(m_hObject,vColor.x,vColor.y,vColor.z, fAlpha); if(m_pServerDE->GetModelPlaybackState(m_hObject) & MS_PLAYDONE) { m_bAnimating = DFALSE; Metacmd++; m_bRemoveMe = DTRUE; } } return; }
DBOOL UpdateMovingObject(PhysicsState *pUserState, MovingObject *pObject, DVector *pNewPos) { if (!pObject || !pNewPos) return DFALSE; PhysicsState* pState = pUserState ? pUserState : GetCurPhysicsState(pObject); if (!pState) return DFALSE; DVector vTemp, velocityDelta, posDelta; if(pObject->m_PhysicsFlags & MO_RESTING) return DFALSE; // Prevent tiny movements. if(VEC_MAGSQR(pObject->m_Acceleration) < 0.01f) { VEC_INIT(pObject->m_Acceleration); } if(VEC_MAGSQR(pObject->m_Velocity) < 0.01f) { VEC_INIT(pObject->m_Velocity); } // velocityDelta = ( acceleration + accelDelta * 0.5 ) * dt; VEC_INIT(vTemp); if (!(pObject->m_PhysicsFlags & MO_NOGRAVITY)) { DFLOAT fScale = 0.5f; if (pObject->m_PhysicsFlags & MO_HALFGRAVITY) { fScale = 0.20f; } VEC_MULSCALAR(vTemp, pState->m_GravityAccel, fScale); } VEC_ADD(vTemp, vTemp, pObject->m_Acceleration); VEC_MULSCALAR(velocityDelta, vTemp, pState->m_TimeStep); // Apply the velocity to the position (p = p + vt + 0.5a(t^2)). VEC_MULSCALAR(posDelta, pObject->m_Acceleration, pState->m_TimeStepIntegral); VEC_ADDSCALED(posDelta, posDelta, pObject->m_Velocity, pState->m_TimeStep); // Add the final velocity to the new velocity. VEC_ADD(pObject->m_Velocity, pObject->m_Velocity, velocityDelta); if(!pNewPos) pNewPos = &pObject->m_Pos; VEC_ADD(*pNewPos, pObject->m_Pos, posDelta); // Zero out the acceleration. VEC_INIT(pObject->m_Acceleration); return DTRUE; }
HLOCALOBJ CParticleExplosionFX::CreateDebris() { LTVector vScale; VEC_SET(vScale, 1.0f, 1.0f, 1.0f); VEC_MULSCALAR(vScale, vScale, GetRandom(1.0f, 5.0f)); char* pFilename = GetDebrisModel(DBT_STONE_BIG, vScale); char* pSkin = GetDebrisSkin(DBT_STONE_BIG); if (!pFilename) return LTNULL; ObjectCreateStruct createStruct; INIT_OBJECTCREATESTRUCT(createStruct); createStruct.m_ObjectType = OT_MODEL; SAFE_STRCPY(createStruct.m_Filename, pFilename); SAFE_STRCPY(createStruct.m_SkinName, pSkin); createStruct.m_Flags = FLAG_VISIBLE | FLAG_NOLIGHT; VEC_COPY(createStruct.m_Pos, m_vPos); HLOCALOBJ hObj = m_pClientDE->CreateObject(&createStruct); m_pClientDE->SetObjectScale(hObj, &vScale); return hObj; }
LTBOOL CFolderIntel::UpdateSelection() { LTBOOL bChanged = CBaseSelectionFolder::UpdateSelection(); if (bChanged) { CLTGUICtrl *pCtrl = GetControl(m_nLastListItem); if (!pCtrl) return LTFALSE; int nIndex = pCtrl->GetParam1(); if (!nIndex) return LTFALSE; IntelItem *pItem = m_intelArray[nIndex-1]; HSTRING hStr = g_pLTClient->FormatString(pItem->nID); m_pDescription->SetString(hStr); g_pLTClient->FreeString(hStr); CScaleFX* pScaleFX = g_pFXButeMgr->GetScaleFX(pItem->nType); SAFE_STRCPY(m_szModel, pScaleFX->szFile); SAFE_STRCPY(m_szSkin, pScaleFX->szSkin); m_vScale = pScaleFX->vInitialScale; m_bChromakey = pScaleFX->bChromakey; if (pScaleFX->fDirOffset > 0.0f) { LTFLOAT fScaleMult = (100.0f/pScaleFX->fDirOffset); VEC_MULSCALAR(m_vScale, m_vScale, fScaleMult); } CreateModelSFX(); } return bChanged; }
DBOOL CBaseParticleSystemFX::Update() { if(!m_hObject || !m_pClientDE) return DFALSE; // See if we should rotate this bad-boy... if (m_vRotVel.x != 0.0f || m_vRotVel.y != 0.0f || m_vRotVel.z != 0.0f) { DFLOAT fDelta = m_pClientDE->GetFrameTime(); DRotation rRot; m_pClientDE->GetObjectRotation(m_hObject, &rRot); DVector vTemp; VEC_MULSCALAR(vTemp, m_vRotVel, fDelta); VEC_ADD(m_vRotAmount, m_vRotAmount, vTemp); if (m_vRotVel.x != 0.0f) m_pClientDE->EulerRotateX(&rRot, m_vRotAmount.x); if (m_vRotVel.y != 0.0f) m_pClientDE->EulerRotateY(&rRot, m_vRotAmount.y); if (m_vRotVel.z != 0.0f) m_pClientDE->EulerRotateZ(&rRot, m_vRotAmount.z); m_pClientDE->SetObjectRotation(m_hObject, &rRot); } return DTRUE; }
void CProjectile::Setup(DVector *vDir, DBYTE nType, DFLOAT fDamage, DFLOAT fVelocity, int nRadius, HOBJECT hFiredFrom) { CServerDE* pServerDE = BaseClass::GetServerDE(); if (!pServerDE) return; VEC_COPY(m_vDir, *vDir); m_fDamage = fDamage; m_fVelocity = fVelocity; m_nRadius = nRadius; m_hFiredFrom = hFiredFrom; pServerDE->CreateInterObjectLink( m_hObject, m_hFiredFrom ); m_nWeaponType = nType; DVector vVel; VEC_MULSCALAR(vVel, m_vDir, m_fVelocity); // Set the rotation of the projectile... DRotation rRot; pServerDE->AlignRotation(&rRot, &m_vDir, DNULL); pServerDE->SetObjectRotation(m_hObject, &rRot); // And away we go... pServerDE->SetVelocity(m_hObject, &vVel); pServerDE->SetObjectFlags(m_hObject, m_dwFlags); // Add smoke trail if (m_bSmokeTrail) AddSmokeTrail(vVel); }
void CBodyFX::CreateMarker(LTVector & vPos, LTBOOL bSame) { if (!m_pClientDE || !g_pGameClientShell || !m_hServerObject) return; if (!bSame) return; ObjectCreateStruct createStruct; INIT_OBJECTCREATESTRUCT(createStruct); CString str = g_pClientButeMgr->GetSpecialFXAttributeString("TeamSprite"); LTFLOAT fScaleMult = g_pClientButeMgr->GetSpecialFXAttributeFloat("TeamScale"); LTFLOAT fAlpha = g_pClientButeMgr->GetSpecialFXAttributeFloat("TeamAlpha"); LTVector vScale(1.0f,1.0f,1.0f); VEC_MULSCALAR(vScale, vScale, fScaleMult); SAFE_STRCPY(createStruct.m_Filename, (char *)(LPCSTR)str); createStruct.m_ObjectType = OT_SPRITE; createStruct.m_Flags = FLAG_VISIBLE | FLAG_FOGDISABLE | FLAG_NOLIGHT; createStruct.m_Pos = vPos; m_hMarker = m_pClientDE->CreateObject(&createStruct); if (!m_hMarker) return; m_pClientDE->SetObjectScale(m_hMarker, &vScale); LTFLOAT r, g, b, a; m_pClientDE->GetObjectColor(m_hServerObject, &r, &g, &b, &a); m_pClientDE->SetObjectColor(m_hObject, r, g, b, (fAlpha * a)); }
DVector CPlayerCamera::FindFirstPersonCameraPosition(DVector vPos, DVector vF) { DVector vTemp; VEC_MULSCALAR(vTemp, vF, m_TargetFirstPersonOffset.x); VEC_ADD(vPos, vPos, vTemp); vPos.y += m_TargetFirstPersonOffset.y; return vPos; }
void BugAI::MC_Run() { if (m_bAnimating == DFALSE || m_nCurMetacmd != MC_RUN) { DBOOL bRet = DFALSE; m_fTimeStart = m_pServerDE->GetTime(); Move(m_MoveObj.GetForwardVector(),m_fRunSpeed); m_bAnimating = DTRUE; m_nCurMetacmd = MC_RUN; } else { //Check for obstruction; otherwise continue on if(CheckObstructed(m_MoveObj.GetForwardVector(), m_fRunSpeed)) { IntersectQuery IQuery; IntersectInfo ii; IQuery.m_Flags = INTERSECT_OBJECTS; IQuery.m_FilterFn = DNULL; DVector vTemp; VEC_MULSCALAR(vTemp,m_MoveObj.GetForwardVector(),m_fRunSpeed); VEC_COPY(IQuery.m_From,m_MoveObj.GetPos()); VEC_ADD(IQuery.m_To,IQuery.m_From,vTemp); if(m_pServerDE->IntersectSegment(&IQuery, &ii)) { //climb the object DRotation rRot; m_pServerDE->AlignRotation(&rRot,&m_MoveObj.GetUpVector(),&ii.m_Plane.m_Normal); m_pServerDE->SetObjectRotation(m_hObject,&rRot); m_bAnimating = DFALSE; Metacmd++; return; } } Move(m_MoveObj.GetForwardVector(),m_fRunSpeed); //Are we done running? if(m_pServerDE->GetModelPlaybackState(m_hObject) & MS_PLAYDONE) { m_bAnimating = DFALSE; Metacmd++; } } return; }
DBOOL BounceMovingObject(PhysicsState *pUserState, MovingObject *pObject, DVector *pNewPos, ClientIntersectInfo* pInfo, SurfaceType *eType) { if (!pObject || !pNewPos || !pInfo) return DFALSE; PhysicsState* pState = pUserState ? pUserState : GetCurPhysicsState(pObject); if (!pState) return DFALSE; ClientIntersectQuery query; float dot; // Only do an intersection test if the line is long enough (sometimes the // intersection test will fail on really short lines). memset(&query, 0, sizeof(query)); VEC_COPY(query.m_From, pObject->m_Pos); VEC_COPY(query.m_To, *pNewPos); if (eType) query.m_Flags = INTERSECT_HPOLY; if (pState->m_pClientDE->IntersectSegment(&query, pInfo)) { // get the surface type if (eType) *eType = GetSurfaceType(pInfo->m_hObject, pInfo->m_hPoly); // Reflect the velocity. dot = VEC_DOT(pObject->m_Velocity, pInfo->m_Plane.m_Normal); dot *= -2.0f; VEC_ADDSCALED(pObject->m_Velocity, pObject->m_Velocity, pInfo->m_Plane.m_Normal, dot); // If the plane hit is in the opposite direction of travel, then move back a little... if( dot > 0.0f ) { // Move the dest point a little in front of the plane. VEC_ADDSCALED(*pNewPos, pInfo->m_Point, pInfo->m_Plane.m_Normal, 0.3f); } // Dampen it. VEC_MULSCALAR(pObject->m_Velocity, pObject->m_Velocity, pState->m_VelocityDampen); // (250 is the max squared magnitude). if(pInfo->m_Plane.m_Normal.y > 0.6f && (VEC_MAGSQR(pObject->m_Velocity) < (250.0f))) { pObject->m_PhysicsFlags |= MO_RESTING; } return DTRUE; } return DFALSE; }
DVector CMovement::FindTurn(DVector vStart, DVector vTestDir, DVector vMoveDir, DFLOAT fMoveLen, DFLOAT fTestLen) { DVector vFinal,vCurPos; DBOOL bStop = DTRUE; DFLOAT fMaxDist = 0.0f; VEC_INIT(vFinal); VEC_COPY(vCurPos, vStart); CServerDE* pServerDE = BaseClass::GetServerDE(); if (!pServerDE) return vFinal; IntersectQuery IQuery; IntersectInfo IInfo; IQuery.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID; IQuery.m_FilterFn = DNULL; VEC_COPY(IQuery.m_From,vStart); VEC_COPY(IQuery.m_Direction,vMoveDir); //find maximum searchable distance in vMoveDir if(pServerDE->CastRay(&IQuery,&IInfo)) { fMaxDist = VEC_DIST(vStart,IInfo.m_Point); } //loop til we find a spot to turn for(float fDist = 0.0f; !((fDist + fMoveLen) >= fMaxDist); fDist += fMoveLen) { VEC_ADDSCALED(vCurPos, vCurPos, vMoveDir, fMoveLen); VEC_COPY(IQuery.m_From,vCurPos); VEC_ADDSCALED(IQuery.m_To,vCurPos, vTestDir, fTestLen); if(!pServerDE->IntersectSegment(&IQuery, &IInfo)) { VEC_ADDSCALED(vFinal, vCurPos, vMoveDir, fMoveLen); return vFinal; } } if(m_nNumPoints >= 10 || (VEC_DIST(vCurPos,vStart) <= 0.0)) return vCurPos; //we can't turn here so we add to list and keep searching in new direction AddPosToPathList(vCurPos); DVector vNewMoveDir; VEC_MULSCALAR(vNewMoveDir, vTestDir, -1.0f); return FindTurn(vCurPos, vMoveDir, vNewMoveDir, fMoveLen, (fMaxDist - fDist) + 1.0f); }
void CHandWeaponModel::Drop() { CServerDE* pServerDE = GetServerDE(); if (!pServerDE) return; m_bDropped = DTRUE; DVector vF, vR, vU; DRotation rRot; // Set some minimum dims, and make sure x and z are the same. DVector vDims; pServerDE->GetModelAnimUserDims(m_hObject, &vDims, pServerDE->GetModelAnimation(m_hObject)); if (vDims.x < 10.0f) vDims.x = 10.0f; if (vDims.x > vDims.z) vDims.z = vDims.x; else vDims.x = vDims.z; // g_pServerDE->BPrint("Setting PU dims %f,%f,%f", VEC_EXPAND(vDims)); if (pServerDE->SetObjectDims2(m_hObject, &vDims) == DE_ERROR) // Get vectors to set a velocity pServerDE->GetObjectRotation(m_hObject, &rRot); pServerDE->GetRotationVectors(&rRot, &vU, &vR, &vF); // Set some forward and upward velocity VEC_ADD(vF, vF, vU); VEC_MULSCALAR(vF, vF, 150.0f); pServerDE->SetVelocity(m_hObject, &vF); // Make it visible DDWORD dwFlags = pServerDE->GetObjectFlags(m_hObject); pServerDE->SetObjectFlags(m_hObject, dwFlags | FLAG_NOSLIDING | FLAG_VISIBLE | FLAG_GRAVITY | FLAG_REMOVEIFOUTSIDE); // Show the model on the client now /* if(m_dwClientID) { HMESSAGEWRITE hMsg = pServerDE->StartSpecialEffectMessage(this); pServerDE->WriteToMessageByte(hMsg, SFX_WEAPONHANDMODEL_ID); pServerDE->WriteToMessageDWord(hMsg, m_dwClientID); pServerDE->WriteToMessageByte(hMsg, (m_bLeftHand << 1) | DTRUE); pServerDE->EndMessage2(hMsg, MESSAGE_GUARANTEED); } */ // Set next update for 1 second to spawn a powerup pServerDE->SetNextUpdate( m_hObject, 1.0f); }
void CClientExplosionSFX::Setup(DVector *vPos, DVector *vNormal, DFLOAT fOffset) { VEC_COPY(m_vPos, *vPos); VEC_COPY(m_vNormal, *vNormal); m_fOffset = fOffset; if(m_fOffset) { DVector temp; VEC_NORM(m_vNormal); VEC_MULSCALAR(temp, m_vNormal, m_fOffset); VEC_ADD(m_vPos, m_vPos, temp); } }
void UndeadGideon::MC_Dodge_Left() { if (m_bAnimating == DFALSE || m_nCurMetacmd != MC_DODGE_LEFT) { SetAnimation(m_pAnim_Sound->m_nAnim_JUMP[TYPE_MELEE]); m_pServerDE->SetModelLooping(m_hObject, DFALSE); DVector vVel, vLeft; VEC_MULSCALAR(vLeft, m_MoveObj.GetRightVector(), -1.0f); vVel.y = m_MoveObj.GetUpVector().y * m_fJumpSpeed; vVel.x = vLeft.x * m_fRunSpeed; vVel.z = vLeft.z * m_fRunSpeed; Move(vVel, MATH_EPSILON); m_nCurMetacmd = MC_DODGE_LEFT; m_bAnimating = DTRUE; } else { CollisionInfo collisionInfo; DVector vVel; m_pServerDE->GetVelocity(m_hObject,&vVel); m_pServerDE->GetStandingOn(m_hObject, &collisionInfo); if ((collisionInfo.m_hObject == m_pServerDE->GetWorldObject()) && (vVel.y <= 0.0f)) { DVector vVel; VEC_INIT(vVel); Move(vVel, MATH_EPSILON); m_bAnimating = DFALSE; Metacmd++; } } return; }
void GremlinAI::MC_Dodge_Left() { if (m_bAnimating == DFALSE || m_nCurMetacmd != MC_DODGE_LEFT) { SetAnimation(m_pAnim_Sound->m_nAnim_DODGE_RIGHT); m_pServerDE->SetModelLooping(m_hObject, DFALSE); DVector vVel, vLeft; VEC_MULSCALAR(vLeft, m_MoveObj.GetRightVector(), -1.0f); vVel.y = m_MoveObj.GetUpVector().y * m_fJumpSpeed; vVel.x = vLeft.x * m_fRunSpeed; vVel.z = vLeft.z * m_fRunSpeed; Move(vVel, MATH_EPSILON); m_nCurMetacmd = MC_DODGE_LEFT; m_bAnimating = DTRUE; } else { CollisionInfo collisionInfo; m_pServerDE->GetStandingOn(m_hObject, &collisionInfo); if (collisionInfo.m_hObject) { DVector vVel; VEC_INIT(vVel); Move(vVel, MATH_EPSILON); m_bAnimating = DFALSE; Metacmd++; } } return; }
void CDestructable::ApplyDamagePhysics(DFLOAT fDamage, DVector *pvDir) { CServerDE* pServerDE = BaseClass::GetServerDE(); if (!pServerDE || !m_hObject || !pvDir) return; // Don't apply damage physics if the object is a trapped character (Andy 2/22/99) if(IsBaseCharacter(m_hObject)) { CBaseCharacter *pObj = (CBaseCharacter*)pServerDE->HandleToObject(m_hObject); if(pObj->IsTrapped()) return; } if (VEC_MAGSQR(*pvDir) < 0.01) return; DVector vTemp, vVel; pServerDE->GetVelocity(m_hObject, &vVel); VEC_COPY(vTemp, *pvDir); VEC_NORM(vTemp); if (m_fMass <= 0) m_fMass = 1; DFLOAT fMultiplier = (fDamage * PA_DAMAGE_VEL_MUTLIPLIER) / m_fMass; VEC_MULSCALAR(vTemp, vTemp, fMultiplier); VEC_ADD(vVel, vTemp, vVel); // Accumulate damage velocity for player objects to send to the client.. if (IsPlayer(m_hObject)) { VEC_ADD(m_vAddVelocity, m_vAddVelocity, vTemp); m_bAddVelocity = DTRUE; } pServerDE->SetVelocity(m_hObject, &vVel); }
void CPlayerCamera::CircleAroundTarget() { if (!m_pClientDE || !m_hTarget) return; DVector vTargetPos; DRotation rRot; DVector vU, vR, vF; DFLOAT fTimeDelta = m_pClientDE->GetTime() - m_CircleStartTime; DFLOAT fAngle = fTimeDelta * DEFAULT_ROTATE_SPEED; // * MATH_PI * 2; fAngle = (DFLOAT)fmod(fAngle, MATH_PI*2); m_pClientDE->GetObjectRotation(m_hTarget, &rRot); m_pClientDE->EulerRotateY(&rRot, fAngle); m_pClientDE->GetRotationVectors(&rRot, &vU, &vR, &vF); m_pClientDE->GetObjectPos(m_hTarget, &vTargetPos); VEC_MULSCALAR(vF, vF, -m_CameraDistBack*1.2f) // VEC_ADD(vTargetPos, vTargetPos, vF); m_DeathOptX = vF.x; m_DeathOptZ = vF.z; }
LTBOOL CParticleExplosionFX::CreateObject(ILTClient *pClientDE) { LTBOOL bRet = CBaseParticleSystemFX::CreateObject(pClientDE); if (!bRet) return bRet; // Initialize the emmitters velocity ranges based on our rotation... LTVector vVelMin, vVelMax, vTemp, vU, vR, vF; VEC_SET(vVelMin, 1.0f, 1.0f, 1.0f); VEC_SET(vVelMax, 1.0f, 1.0f, 1.0f); m_pClientDE->Common()->GetRotationVectors(m_rSurfaceRot, vU, vR, vF); if (vF.y <= -0.95f || vF.y >= 0.95f) { vF.y = vF.y > 0.0f ? 1.0f : -1.0f; VEC_SET(vR, 1.0f, 0.0f, 0.0f); VEC_SET(vU, 0.0f, 0.0f, 1.0f); } else if (vF.x <= -0.95f || vF.x >= 0.95f) { vF.x = vF.x > 0.0f ? 1.0f : -1.0f; VEC_SET(vR, 0.0f, 1.0f, 0.0f); VEC_SET(vU, 0.0f, 0.0f, 1.0f); } else if (vF.z <= -0.95f || vF.z >= 0.95f) { vF.z = vF.z > 0.0f ? 1.0f : -1.0f; VEC_SET(vR, 1.0f, 0.0f, 0.0f); VEC_SET(vU, 0.0f, 1.0f, 0.0f); } VEC_MULSCALAR(vVelMin, vF, m_vMinVel.y); VEC_MULSCALAR(vVelMax, vF, m_vMaxVel.y); VEC_MULSCALAR(vTemp, vR, m_vMinVel.x); VEC_ADD(vVelMin, vVelMin, vTemp); VEC_MULSCALAR(vTemp, vR, m_vMaxVel.x); VEC_ADD(vVelMax, vVelMax, vTemp); VEC_MULSCALAR(vTemp, vU, m_vMinVel.z); VEC_ADD(vVelMin, vVelMin, vTemp); VEC_MULSCALAR(vTemp, vU, m_vMaxVel.z); VEC_ADD(vVelMax, vVelMax, vTemp); // Initialize our emmitters... LTVector vStartVel; for (int i=0; i < m_nNumEmmitters; i++) { if (m_bCreateDebris) { m_hDebris[i] = CreateDebris(); } m_ActiveEmmitters[i] = LTTRUE; m_BounceCount[i] = 2; VEC_SET(vStartVel, GetRandom(vVelMin.x, vVelMax.x), GetRandom(vVelMin.y, vVelMax.y), GetRandom(vVelMin.z, vVelMax.z)); InitMovingObject(&(m_Emmitters[i]), &m_vPos, &vStartVel); m_Emmitters[i].m_PhysicsFlags |= m_nEmmitterFlags; } return bRet; }
void CProjectileFX::Detonate(CollisionInfo* pInfo) { if (!m_pClientDE || m_bDetonated) return; m_bDetonated = LTTRUE; SurfaceType eType = ST_UNKNOWN; LTVector vPos; g_pLTClient->GetObjectPos(m_hServerObject, &vPos); // Determine the normal of the surface we are impacting on... LTVector vNormal; VEC_SET(vNormal, 0.0f, 1.0f, 0.0f); if (pInfo) { if (pInfo->m_hObject) { eType = GetSurfaceType(pInfo->m_hObject); } else if (pInfo->m_hPoly != INVALID_HPOLY) { eType = GetSurfaceType(pInfo->m_hPoly); VEC_COPY(vNormal, pInfo->m_Plane.m_Normal); LTRotation rRot(vNormal, LTVector(0.0f, 1.0f, 0.0f)); m_pClientDE->SetObjectRotation(m_hServerObject, &rRot); // Calculate where we really hit the plane... LTVector vVel, vP0, vP1; g_pPhysicsLT->GetVelocity(m_hServerObject, &vVel); VEC_COPY(vP1, vPos); VEC_MULSCALAR(vVel, vVel, g_pGameClientShell->GetFrameTime()); VEC_SUB(vP0, vP1, vVel); LTFLOAT fDot1 = VEC_DOT(pInfo->m_Plane.m_Normal, vP0) - pInfo->m_Plane.m_Dist; LTFLOAT fDot2 = VEC_DOT(pInfo->m_Plane.m_Normal, vP1) - pInfo->m_Plane.m_Dist; if (fDot1 < 0.0f && fDot2 < 0.0f || fDot1 > 0.0f && fDot2 > 0.0f) { VEC_COPY(vPos, vP1); } else { LTFLOAT fPercent = -fDot1 / (fDot2 - fDot1); VEC_LERP(vPos, vP0, vP1, fPercent); } } } else { // Since pInfo was null, this means the projectile's lifetime was up, // so we just blow-up in the air. eType = ST_AIR; } HOBJECT hObj = !!pInfo ? pInfo->m_hObject : LTNULL; ::AddLocalImpactFX(hObj, m_vFirePos, vPos, vNormal, eType, m_vPath, m_nWeaponId, m_nAmmoId, 0); m_bWantRemove = LTTRUE; }
void Body::Init(const BODYINITSTRUCT& bi) { if (!bi.pCharacter || !bi.pCharacter->m_hObject) return; // Get the death type etc m_eDeathType = bi.pCharacter->GetDeathType(); m_eModelId = bi.pCharacter->GetModelId(); m_eModelSkeleton = bi.pCharacter->GetModelSkeleton(); m_eModelStyle = bi.pCharacter->GetModelStyle(); // Get the body lifetime m_fLifetime = bi.fLifetime; // Create the SFX BODYCREATESTRUCT bcs; bcs.eBodyState = bi.eBodyState; if (IsPlayer(bi.pCharacter->m_hObject)) { CPlayerObj* pPlayer = (CPlayerObj*) bi.pCharacter; bcs.nClientId = (uint8) g_pLTServer->GetClientID(pPlayer->GetClient()); } HMESSAGEWRITE hMessage = g_pLTServer->StartSpecialEffectMessage(this); g_pLTServer->WriteToMessageByte(hMessage, SFX_BODY_ID); bcs.Write(g_pLTServer, hMessage); g_pLTServer->EndMessage(hMessage); // Create the death scene CreateDeathScene(bi.pCharacter); // We'll handle creating the necessary debris... m_damage.m_bCreatedDebris = LTTRUE; m_damage.SetCanDamage(LTFALSE);//bi.pCharacter->CanDamageBody()); m_damage.SetApplyDamagePhysics(LTFALSE);//bi.pCharacter->CanDamageBody()); m_damage.SetMass(g_pModelButeMgr->GetModelMass(m_eModelId)); // Let us get hit by decay powder m_damage.ClearCantDamageTypes(DamageTypeToFlag(DT_GADGET_DECAYPOWDER)); switch ( g_pModelButeMgr->GetModelType(m_eModelId) ) { case eModelTypeVehicle: { m_eDeathType = CD_GIB; } break; } CDestructible* pDest = bi.pCharacter->GetDestructible(); if (pDest) { m_eDamageType = pDest->GetDeathType(); VEC_COPY(m_vDeathDir, pDest->GetDeathDir()); VEC_NORM(m_vDeathDir); VEC_MULSCALAR(m_vDeathDir, m_vDeathDir, 1.0f + (pDest->GetDeathDamage() / pDest->GetMaxHitPoints())); } LTFLOAT fHitPts = pDest->GetMaxHitPoints(); m_damage.Reset(fHitPts, 0.0f); m_damage.SetHitPoints(fHitPts); m_damage.SetMaxHitPoints(fHitPts); m_damage.SetArmorPoints(0.0f); m_damage.SetMaxArmorPoints(0.0f); // Copy our user flags over, setting our surface type to flesh uint32 dwUsrFlags = g_pLTServer->GetObjectUserFlags(m_hObject) | USRFLG_NIGHT_INFRARED; dwUsrFlags |= SurfaceToUserFlag(ST_FLESH); g_pLTServer->SetObjectUserFlags(m_hObject, dwUsrFlags); // Make sure model doesn't slide all over the place... g_pLTServer->SetFrictionCoefficient(m_hObject, 500.0f); LTVector vDims; g_pLTServer->GetObjectDims(bi.pCharacter->m_hObject, &vDims); // Set the dims. If we can't set the dims that big, set them // as big as possible... if (g_pLTServer->SetObjectDims2(m_hObject, &vDims) == LT_ERROR) { g_pLTServer->SetObjectDims2(m_hObject, &vDims); } // Create the box used for weapon impact detection... CreateHitBox(bi); LTFLOAT r, g, b, a; g_pLTServer->GetObjectColor(bi.pCharacter->m_hObject, &r, &g, &b, &a); g_pLTServer->SetObjectColor(m_hObject, r, g, b, a); LTVector vScale; g_pLTServer->GetObjectScale(bi.pCharacter->m_hObject, &vScale); g_pLTServer->ScaleObject(m_hObject, &vScale); // Copy our animation over HMODELANIM hAni = g_pLTServer->GetModelAnimation(bi.pCharacter->m_hObject); g_pLTServer->SetModelAnimation(m_hObject, hAni); g_pLTServer->SetModelLooping(m_hObject, LTFALSE); // Copy the flags from the character to us uint32 dwFlags = g_pLTServer->GetObjectFlags(bi.pCharacter->m_hObject); m_dwFlags |= FLAG_REMOVEIFOUTSIDE; g_pLTServer->SetObjectFlags(m_hObject, dwFlags); // Move the attachments aggregate from the char to us... if (!m_pAttachments && bi.eBodyState != eBodyStateLaser) { m_hWeaponItem = bi.pCharacter->TransferWeapon(m_hObject); // Make sure we're playing the correct ani... if (m_hWeaponItem) { uint32 dwAni = g_pLTServer->GetAnimIndex(m_hWeaponItem, "Hand"); if (dwAni != INVALID_ANI) { g_pLTServer->SetModelAnimation(m_hWeaponItem, dwAni); g_pLTServer->SetModelLooping(m_hWeaponItem, LTFALSE); } } } if (!m_pAttachments) { m_pAttachments = bi.pCharacter->TransferAttachments(); if (m_pAttachments) { AddAggregate(m_pAttachments); m_pAttachments->ReInit(m_hObject); } } // Set up the spears bi.pCharacter->TransferSpears(this); // Set our state SetState(bi.eBodyState); }
LTBOOL CBulletTrailFX::Update() { if (!m_hObject || !m_pClientDE) return LTFALSE; LTFLOAT fTime = m_pClientDE->GetTime(); if (m_bFirstUpdate) { // See if we can figure out what color bubbles to make, based on the // container we start in... HLOCALOBJ objList[1]; uint32 dwNum = m_pClientDE->GetPointContainers(&m_vStartPos, objList, 1); if (dwNum > 0 && objList[0]) { uint32 dwUserFlags; m_pClientDE->GetObjectUserFlags(objList[0], &dwUserFlags); if (dwUserFlags & USRFLG_VISIBLE) { uint16 dwCode; if (m_pClientDE->GetContainerCode(objList[0], &dwCode)) { GetLiquidColorRange((ContainerCode)dwCode, &m_vColor1, &m_vColor2); } } } // Move the particle system to the correct position... m_pClientDE->SetObjectPos(m_hObject, &m_vStartPos); m_bFirstUpdate = LTFALSE; m_fStartTime = fTime; m_fLastTime = fTime; VEC_INIT(m_vLastPos); // Find the end position... ClientIntersectQuery iQuery; ClientIntersectInfo iInfo; LTVector vTemp, vEndPoint; VEC_MULSCALAR(vTemp, m_vDir, MAX_TRAIL_LENGTH); VEC_ADD(vEndPoint, m_vStartPos, vTemp); VEC_COPY(iQuery.m_From, m_vStartPos); VEC_COPY(iQuery.m_To, vEndPoint); if (m_pClientDE->IntersectSegment(&iQuery, &iInfo)) { VEC_SUB(vEndPoint, iInfo.m_Point, m_vStartPos); m_fDistance = VEC_MAG(vEndPoint); } if (m_fDistance <= 0.0f || m_fFadeTime <= 0.0f) return LTFALSE; // Calculate the trail velocity... m_fTrailVel = m_fDistance / m_fFadeTime; VEC_MULSCALAR(m_vDir, m_vDir, m_fTrailVel); } // Check to see if we should just wait for last bubble to go away... if (fTime > m_fStartTime + m_fFadeTime) { if (fTime > m_fLastTime + m_fLifeTime) { return LTFALSE; } LTFLOAT fScale = (m_fLifeTime - (fTime - m_fLastTime)) / m_fLifeTime; // m_pClientDE->SetParticleSystemColorScale(m_hObject, fScale); LTFLOAT r, g, b, a; m_pClientDE->GetObjectColor(m_hObject, &r, &g, &b, &a); m_pClientDE->SetObjectColor(m_hObject, r, g, b, fScale); return LTTRUE; } // Create the necessary particles... LTFLOAT fTimeOffset = g_pGameClientShell->GetFrameTime(); // Calculate distance traveled this frame... LTFLOAT fDist = m_fTrailVel * fTimeOffset; if (fDist > m_fDistance) fDist = m_fDistance; m_fDistTraveled += fDist; if (m_fDistTraveled > m_fDistance) { fDist = m_fDistance - (m_fDistTraveled - fDist); if (fDist <= 0.0f) return LTTRUE; } // Calculate number of particles to create... LTFLOAT fNumParticles = fDist * m_fNumParticles / m_fDistance; // Calculate starting bubble position... LTVector vCurPos, vPos, vDelta, vTemp, vDriftVel, vColor; VEC_MULSCALAR(vTemp, m_vDir, fTimeOffset); VEC_ADD(vCurPos, m_vLastPos, vTemp); // What is the range of colors? LTFLOAT fRange = m_vColor2.x - m_vColor1.x; // Fill the distance between the last projectile position, and it's // current position with bubbles... VEC_SUB(vTemp, vCurPos, m_vLastPos); VEC_MULSCALAR(vDelta, vTemp, 1.0f/fNumParticles); VEC_COPY(vPos, m_vLastPos); LTFLOAT fLifeTime = 100.0f; LTFLOAT fOffset = 0.0f; LTVector vDriftOffset; VEC_SET(vDriftOffset, 0.0f, 0.0f, 0.0f); int nNumParticles = GetNumParticles((int)fNumParticles); for (int i=0; i < nNumParticles; i++) { // Build the individual bubbless... for (int j=0; j < 1; j++) { VEC_COPY(vTemp, vPos); VEC_SET(vDriftVel, 0.0f, GetRandom(5.0f, 6.0f), 0.0f); vTemp.x += GetRandom(-fOffset, fOffset); vTemp.y += GetRandom(-fOffset, fOffset); vTemp.z += GetRandom(-fOffset, fOffset); GetRandomColorInRange(vColor); m_pClientDE->AddParticle(m_hObject, &vTemp, &vDriftVel, &vColor, fLifeTime); } VEC_ADD(vPos, vPos, vDelta); } VEC_COPY(m_vLastPos, vCurPos); m_fLastTime = fTime; return LTTRUE; }
void CDebris::Create(DVector vDir, DFLOAT fDamage) { if (!g_pServerDE) return; // HCLASS hClass = g_pServerDE->GetClass( "CClientGibFX" ); // if( !hClass ) // return; VEC_NEGATE(vDir, vDir); DFLOAT fVelFactor = 1.0f; // DDWORD nType = m_eType*10; // if (nType == SURFTYPE_STONE || nType == SURFTYPE_METAL) // fVelFactor = 0.75f; DFLOAT fVel = 50.0f + fDamage; vDir.y -= 1.0f; VEC_NORM(vDir); VEC_MULSCALAR(vDir, vDir, fVel); // ObjectCreateStruct ocStruct; // INIT_OBJECTCREATESTRUCT(ocStruct); DVector vPos; g_pServerDE->GetObjectPos(m_hObject, &vPos); if (m_bExploding) AddExplosion(vPos); // VEC_COPY(ocStruct.m_Pos, vPos); // g_pServerDE->GetObjectRotation(m_hObject, &ocStruct.m_Rotation); DVector vDims; g_pServerDE->GetObjectDims( m_hObject, &vDims ); DDWORD dwCustom = (m_hstrModel1 || m_hstrTexture1 || m_hstrSound) ? TYPEFLAG_CUSTOM : 0; // CClientGibFX* pGib; if (m_bStone /* && (pGib = (CClientGibFX*)g_pServerDE->CreateObject(hClass, &ocStruct)) */) { // pGib->Setup(&vPos, &vDir, &vDims, SURFTYPE_STONE/10 | SIZE_SMALL | dwCustom, m_fScale, m_nAmount, // m_hstrModel1, m_hstrTexture1, m_hstrSound); SetupClientGibFX(&vPos, &vDir, &vDims, SURFTYPE_STONE/10 | SIZE_SMALL | dwCustom, m_fScale, m_nAmount, m_hstrModel1, m_hstrTexture1, m_hstrSound); } if (m_bMetal /* && (pGib = (CClientGibFX*)g_pServerDE->CreateObject(hClass, &ocStruct)) */) { // pGib->Setup(&vPos, &vDir, &vDims, SURFTYPE_METAL/10 | SIZE_SMALL | dwCustom, m_fScale, m_nAmount, // m_hstrModel1, m_hstrTexture1, m_hstrSound); SetupClientGibFX(&vPos, &vDir, &vDims, SURFTYPE_METAL/10 | SIZE_SMALL | dwCustom, m_fScale, m_nAmount, m_hstrModel1, m_hstrTexture1, m_hstrSound); } if (m_bWood /* && (pGib = (CClientGibFX*)g_pServerDE->CreateObject(hClass, &ocStruct)) */) { // pGib->Setup(&vPos, &vDir, &vDims, SURFTYPE_WOOD/10 | SIZE_SMALL | dwCustom, m_fScale, m_nAmount, // m_hstrModel1, m_hstrTexture1, m_hstrSound); SetupClientGibFX(&vPos, &vDir, &vDims, SURFTYPE_WOOD/10 | SIZE_SMALL | dwCustom, m_fScale, m_nAmount, m_hstrModel1, m_hstrTexture1, m_hstrSound); } if (m_bTerrain /*&& (pGib = (CClientGibFX*)g_pServerDE->CreateObject(hClass, &ocStruct)) */) { // pGib->Setup(&vPos, &vDir, &vDims, SURFTYPE_TERRAIN/10 | SIZE_SMALL | dwCustom, m_fScale, m_nAmount, // m_hstrModel1, m_hstrTexture1, m_hstrSound); SetupClientGibFX(&vPos, &vDir, &vDims, SURFTYPE_TERRAIN/10 | SIZE_SMALL | dwCustom, m_fScale, m_nAmount, m_hstrModel1, m_hstrTexture1, m_hstrSound); } if (m_bPlastic /*&& (pGib = (CClientGibFX*)g_pServerDE->CreateObject(hClass, &ocStruct))*/) { // pGib->Setup(&vPos, &vDir, &vDims, SURFTYPE_PLASTIC/10 | SIZE_SMALL | dwCustom, m_fScale, m_nAmount, // m_hstrModel1, m_hstrTexture1, m_hstrSound); SetupClientGibFX(&vPos, &vDir, &vDims, SURFTYPE_PLASTIC/10 | SIZE_SMALL | dwCustom, m_fScale, m_nAmount, m_hstrModel1, m_hstrTexture1, m_hstrSound); } if (m_bGlass /*&& (pGib = (CClientGibFX*)g_pServerDE->CreateObject(hClass, &ocStruct))*/) { // pGib->Setup(&vPos, &vDir, &vDims, SURFTYPE_GLASS/10 | SIZE_SMALL | dwCustom, m_fScale, m_nAmount, // m_hstrModel1, m_hstrTexture1, m_hstrSound); SetupClientGibFX(&vPos, &vDir, &vDims, SURFTYPE_GLASS/10 | SIZE_SMALL | dwCustom, m_fScale, m_nAmount, m_hstrModel1, m_hstrTexture1, m_hstrSound); } if (m_bFlesh /*&& (pGib = (CClientGibFX*)g_pServerDE->CreateObject(hClass, &ocStruct))*/) { // pGib->Setup(&vPos, &vDir, &vDims, SURFTYPE_FLESH/10 | SIZE_SMALL | dwCustom, m_fScale, m_nAmount, // m_hstrModel1, m_hstrTexture1, m_hstrSound); SetupClientGibFX(&vPos, &vDir, &vDims, SURFTYPE_FLESH/10 | SIZE_SMALL | dwCustom, m_fScale, m_nAmount, m_hstrModel1, m_hstrTexture1, m_hstrSound); } if (m_bLiquid /*&& (pGib = (CClientGibFX*)g_pServerDE->CreateObject(hClass, &ocStruct))*/) { // pGib->Setup(&vPos, &vDir, &vDims, SURFTYPE_LIQUID/10 | SIZE_SMALL | dwCustom, m_fScale, m_nAmount, // m_hstrModel1, m_hstrTexture1, m_hstrSound); SetupClientGibFX(&vPos, &vDir, &vDims, SURFTYPE_LIQUID/10 | SIZE_SMALL | dwCustom, m_fScale, m_nAmount, m_hstrModel1, m_hstrTexture1, m_hstrSound); } if (m_bEnergy /*&& (pGib = (CClientGibFX*)g_pServerDE->CreateObject(hClass, &ocStruct))*/) { // pGib->Setup(&vPos, &vDir, &vDims, SURFTYPE_ENERGY/10 | SIZE_SMALL | dwCustom, m_fScale, m_nAmount, // m_hstrModel1, m_hstrTexture1, m_hstrSound); SetupClientGibFX(&vPos, &vDir, &vDims, SURFTYPE_ENERGY/10 | SIZE_SMALL | dwCustom, m_fScale, m_nAmount, m_hstrModel1, m_hstrTexture1, m_hstrSound); } }
DBOOL CSmokePuffFX::Update() { if(!m_hObject || !m_pClientDE) return DFALSE; DFLOAT fTime = m_pClientDE->GetTime(); if (m_fStartTime < 0) { m_fStartTime = m_fLastTime = fTime; } // Make sure we update our position relative to the server object (if the // server object is valid)... if (m_hServerObject) { DVector vServPos; m_pClientDE->GetObjectPos(m_hServerObject, &vServPos); m_pClientDE->SetObjectPos(m_hObject, &vServPos); } // Check to see if we should just wait for last smoke puff to go away... DFLOAT fTimeDelta = fTime - m_fStartTime; if (fTimeDelta > m_fLifeTime) { return DFALSE; } if (m_fDriftDeceleration) { DFLOAT fDecel = 1 - m_pClientDE->GetFrameTime() * m_fDriftDeceleration; VEC_MULSCALAR(m_vMinDriftVel, m_vMinDriftVel, fDecel); VEC_MULSCALAR(m_vMaxDriftVel, m_vMaxDriftVel, fDecel); } DFLOAT fScale = ((m_fLifeTime - fTimeDelta) / m_fLifeTime) * m_fMaxAlpha; // Adjust the alpha DFLOAT 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 add some more smoke... if (fTime > m_fLastTime + m_fParticleCreateDelta && (fTimeDelta < m_fCreateLifetime) ) { DVector vDriftVel, vColor, vPos; // What is the range of colors? DFLOAT fRange = m_vColor2.x - m_vColor1.x; // Build the individual smoke puffs... for (DDWORD j=0; j < m_nNumParticles; j++) { DFLOAT fX, fY, fAngle, fRadius; fAngle = GetRandom(-MATH_PI, MATH_PI); fRadius = GetRandom(0.0f, m_fVolumeRadius); fX = fRadius * (DFLOAT)cos(fAngle); fY = fRadius * (DFLOAT)sin(fAngle); VEC_SET(vPos, fX, -2.0f, fY); VEC_SET(vDriftVel, GetRandom(m_vMinDriftVel.x, m_vMaxDriftVel.x), GetRandom(m_vMinDriftVel.y, m_vMaxDriftVel.y), GetRandom(m_vMinDriftVel.z, m_vMaxDriftVel.z)); if (!m_bIgnoreWind) { VEC_ADD(vDriftVel, vDriftVel, g_vWorldWindVel); } DFLOAT fOffset = GetRandom(m_vColor1.x, m_vColor2.x); DFLOAT fPercent = 1.0f; if (fRange > 0.01) { fPercent = fOffset / fRange; } vColor.x = m_vColor1.x + fOffset; fOffset = fPercent * (m_vColor2.y - m_vColor1.y); vColor.y = m_vColor1.y + fOffset; fOffset = fPercent * (m_vColor2.z - m_vColor1.z); vColor.z = m_vColor1.z + fOffset; DFLOAT fLifeTime = GetRandom(m_fMinParticleLife, m_fMaxParticleLife); m_pClientDE->AddParticle(m_hObject, &vPos, &vDriftVel, &vColor, fLifeTime); } m_fLastTime = fTime; } return DTRUE; }
void CNodeController::UpdateScriptControl(NCSTRUCT *pNodeControl) { LTFLOAT fTime = g_pLTClient->GetTime() - pNodeControl->fScriptTime; ModelNScript eScript = (ModelNScript)pNodeControl->nScript; int nCurPt = pNodeControl->nCurrentScriptPt; int nLastPt = pNodeControl->nLastScriptPt; // g_pLTClient->CPrint("Running node script!"); // Check to see if the script is over... and make it invalid if so if(fTime > g_pModelButeMgr->GetNScriptPtTime(eScript, nLastPt)) { // g_pLTClient->CPrint("Ending node script!"); pNodeControl->bValid = LTFALSE; return; } // Get access to the controls... ILTMath *pMathLT = g_pLTClient->GetMathLT(); // Get the current script point while(fTime > g_pModelButeMgr->GetNScriptPtTime(eScript, nCurPt)) nCurPt++; // Calculate the scale value from the last position to the current LTFLOAT fPtTime1 = g_pModelButeMgr->GetNScriptPtTime(eScript, nCurPt - 1); LTFLOAT fPtTime2 = g_pModelButeMgr->GetNScriptPtTime(eScript, nCurPt); LTFLOAT fScale = (fTime - fPtTime1) / (fPtTime2 - fPtTime1); //---------------------------------------------------------------------------- // Setup the initial position vector LTVector vPos; // Get a direction vector from the last position to the current LTVector vPosDir = g_pModelButeMgr->GetNScriptPtPosOffset(eScript, nCurPt) - g_pModelButeMgr->GetNScriptPtPosOffset(eScript, nCurPt - 1); VEC_MULSCALAR(vPosDir, vPosDir, fScale); vPos = g_pModelButeMgr->GetNScriptPtPosOffset(eScript, nCurPt - 1) + vPosDir; //---------------------------------------------------------------------------- // Setup the initial rotation vector LTVector vRot; // Get a direction rotation from the last position to the current LTVector vRotDir = g_pModelButeMgr->GetNScriptPtRotOffset(eScript, nCurPt) - g_pModelButeMgr->GetNScriptPtRotOffset(eScript, nCurPt - 1); VEC_MULSCALAR(vRotDir, vRotDir, fScale); vRot = g_pModelButeMgr->GetNScriptPtRotOffset(eScript, nCurPt - 1) + vRotDir; // Calculate the rotation... LTRotation rRot; LTVector vR, vU, vF; rRot.Init(); pMathLT->GetRotationVectors(rRot, vR, vU, vF); pMathLT->RotateAroundAxis(rRot, vR, vRot.x); pMathLT->RotateAroundAxis(rRot, vU, vRot.y); pMathLT->RotateAroundAxis(rRot, vF, vRot.z); //---------------------------------------------------------------------------- // Setup the matrix using the offset position and rotation LTMatrix m1; pMathLT->SetupTransformationMatrix(m1, vPos, rRot); m_aNodes[pNodeControl->eModelNode].matTransform = m_aNodes[pNodeControl->eModelNode].matTransform * m1; }
DBOOL CMarkSFX::CreateObject(CClientDE *pClientDE) { if (!CSpecialFX::CreateObject(pClientDE)) return DFALSE; CSFXMgr* psfxMgr = g_pBloodClientShell->GetSFXMgr(); if (!psfxMgr) return DFALSE; // Before we create a new buillet hole see if there is already another // bullet hole close by that we could use instead... CSpecialFXList* pList = psfxMgr->GetBulletHoleFXList(); if (!pList) return DFALSE; int nNumBulletHoles = pList->GetSize(); HOBJECT hMoveObj = DNULL; HOBJECT hObj = DNULL; DFLOAT fClosestMarkDist = REGION_DIAMETER; DBYTE nNumInRegion = 0; DVector vPos; for (int i=0; i < nNumBulletHoles; i++) { if ((*pList)[i]) { hObj = (*pList)[i]->GetObject(); if (hObj) { pClientDE->GetObjectPos(hObj, &vPos); DFLOAT fDist = VEC_DISTSQR(vPos, m_Pos); if (fDist < REGION_DIAMETER) { if (fDist < fClosestMarkDist) { fClosestMarkDist = fDist; hMoveObj = hObj; } if (++nNumInRegion > MAX_MARKS_IN_REGION) { // Just move this bullet-hole to the correct pos, and // remove thyself... pClientDE->SetObjectPos(hMoveObj, &m_Pos); return DFALSE; } } } } } // Setup the mark... ObjectCreateStruct createStruct; INIT_OBJECTCREATESTRUCT(createStruct); createStruct.m_ObjectType = OT_SPRITE; _mbscpy((unsigned char*)createStruct.m_Filename, (const unsigned char*)m_pClientDE->GetStringData( m_hstrSprite )); createStruct.m_Flags = FLAG_VISIBLE | FLAG_ROTATEABLESPRITE; VEC_COPY(createStruct.m_Pos, m_Pos); ROT_COPY( createStruct.m_Rotation, m_Rotation ); m_hObject = pClientDE->CreateObject(&createStruct); m_pClientDE->SetObjectScale(m_hObject, &m_vScale); // See what it hit DVector vU, vR; pClientDE->GetRotationVectors(&m_Rotation, &vU, &vR, &m_vForward); ClientIntersectQuery iq; ClientIntersectInfo ii; iq.m_Flags = INTERSECT_OBJECTS | INTERSECT_HPOLY; VEC_COPY(iq.m_From, vPos); // Get start point at the last known position. VEC_MULSCALAR(iq.m_To, m_vForward, -1.0f); VEC_ADD(iq.m_To, iq.m_To, iq.m_From); // Get destination point slightly past where we should be // Hit something! try to clip against it. (since this is only being used for bullet marks, if (pClientDE->IntersectSegment(&iq, &ii)) { HPOLY hPoly = ii.m_hPoly; pClientDE->ClipSprite(m_hObject, hPoly); } m_pClientDE->SetObjectColor(m_hObject, 0.1f, 0.1f, 0.1f, 1.0f); return DTRUE; }
LTBOOL CBaseParticleSystemFX::Update() { if (!CSpecialFX::Update() || !m_hObject || !m_pClientDE) return LTFALSE; // See if we should rotate this bad-boy... if (m_vRotVel.x != 0.0f || m_vRotVel.y != 0.0f || m_vRotVel.z != 0.0f) { LTFLOAT fDelta = g_pGameClientShell->GetFrameTime(); LTRotation rRot; m_pClientDE->GetObjectRotation(m_hObject, &rRot); LTVector vTemp; VEC_MULSCALAR(vTemp, m_vRotVel, fDelta); VEC_ADD(m_vRotAmount, m_vRotAmount, vTemp); if (m_vRotVel.x != 0.0f) m_pClientDE->EulerRotateX(&rRot, m_vRotAmount.x); if (m_vRotVel.y != 0.0f) m_pClientDE->EulerRotateY(&rRot, m_vRotAmount.y); if (m_vRotVel.z != 0.0f) m_pClientDE->EulerRotateZ(&rRot, m_vRotAmount.z); m_pClientDE->SetObjectRotation(m_hObject, &rRot); } // Update each particles scale / alpha if necessary... LTParticle *pCur, *pTail; if (m_basecs.bAdjustParticleScale || m_basecs.bAdjustParticleAlpha) { if (m_pClientDE->GetParticles(m_hObject, &pCur, &pTail)) { LTFLOAT fLifetime = 0.0f, fTotalLifetime = 0.0f; LTFLOAT fAlphaRange = m_basecs.fEndParticleAlpha - m_basecs.fStartParticleAlpha; LTFLOAT fScaleRange = m_basecs.fEndParticleScale - m_basecs.fStartParticleScale; LTVector vColorRange = m_vColor2 - m_vColor1; while (pCur && pCur != pTail) { m_pClientDE->GetParticleLifetime(m_hObject, pCur, fLifetime); m_pClientDE->GetParticleTotalLifetime(m_hObject, pCur, fTotalLifetime); if (fLifetime > 0.0f && fTotalLifetime > 0.0f) { LTFLOAT fLifePercent = 1.0f - (fLifetime / fTotalLifetime); // Adjust scale... if (m_basecs.bAdjustParticleScale) { pCur->m_Size = m_fRadius * (m_basecs.fStartParticleScale + (fScaleRange * fLifePercent)); } // Adjust alpha... if (m_basecs.bAdjustParticleAlpha) { pCur->m_Alpha = m_basecs.fStartParticleAlpha + (fAlphaRange * fLifePercent); } } pCur = pCur->m_pNext; } } } // Make sure we update our position relative to the server object // (if the server object is valid and the client isn't controling // the particle system pos)... if (m_hServerObject && !m_basecs.bClientControlsPos) { LTVector vNewPos; m_pClientDE->GetObjectPos(m_hServerObject, &vNewPos); vNewPos += m_vPosOffset; m_pClientDE->SetObjectPos(m_hObject, &vNewPos); } return LTTRUE; }
LTBOOL CParticleTrailSegmentFX::Update() { if (!m_hObject || !m_pClientDE) return LTFALSE; if (!CBaseParticleSystemFX::Update()) return LTFALSE; CGameSettings* pSettings = g_pInterfaceMgr->GetSettings(); if (!pSettings) return LTFALSE; uint8 nDetailLevel = pSettings->SpecialFXSetting(); LTFLOAT fTime = m_pClientDE->GetTime(); if (m_bFirstUpdate) { if (!m_hServerObject) return LTFALSE; m_bFirstUpdate = LTFALSE; m_fStartTime = fTime; m_fLastTime = fTime; // Where is the server (moving) object... LTVector vPos, vTemp; m_pClientDE->GetObjectPos(m_hServerObject, &vPos); // Current position is relative to the particle system's postion (i.e., // each puff of Particle is some distance away from the particle system's /// position)... m_pClientDE->GetObjectPos(m_hObject, &vTemp); VEC_SUB(vPos, vPos, vTemp); VEC_COPY(m_vLastPos, vPos); } // Check to see if we should just wait for last Particle puff to go away... if (m_bWantRemove || (fTime > m_fStartTime + m_fFadeTime)) { if (fTime > m_fLastTime + m_fLifeTime) { return LTFALSE; } LTFLOAT fScale = (m_fLifeTime - (fTime - m_fLastTime)) / m_fLifeTime; LTFLOAT r, g, b, a; m_pClientDE->GetObjectColor(m_hObject, &r, &g, &b, &a); m_pClientDE->SetObjectColor(m_hObject, r, g, b, fScale); return LTTRUE; } // See if it is time to create a new Particle puff... if ((fTime > m_fLastTime + m_fOffsetTime) && m_hServerObject) { LTVector vCurPos, vPos, vDelta, vTemp, vDriftVel, vColor; // Calculate Particle puff position... // Where is the server (moving) object... m_pClientDE->GetObjectPos(m_hServerObject, &vCurPos); // Current position is relative to the particle system's postion (i.e., // each puff of Particle is some distance away from the particle system's /// position)... m_pClientDE->GetObjectPos(m_hObject, &vTemp); VEC_SUB(vCurPos, vCurPos, vTemp); // How long has it been since the last Particle puff? LTFLOAT fTimeOffset = fTime - m_fLastTime; // What is the range of colors? LTFLOAT fRange = m_vColor2.x - m_vColor1.x; // Fill the distance between the last projectile position, and it's // current position with Particle puffs... int nNumSteps = (m_fLastTime > 0) ? (((m_nType & PT_BLOOD) || (m_nType & PT_GIBSMOKE)) ? 20 : 5): 1; if (nDetailLevel != RS_HIGH) { nNumSteps /= 2; } VEC_SUB(vTemp, vCurPos, m_vLastPos); VEC_MULSCALAR(vDelta, vTemp, 1.0f/float(nNumSteps)); VEC_COPY(vPos, m_vLastPos); LTFLOAT fCurLifeTime = 10.0f; if (nDetailLevel == RS_HIGH) { fCurLifeTime /= 2; } LTFLOAT fLifeTimeOffset = fTimeOffset / float(nNumSteps); LTFLOAT fOffset = 0.5f; int nNumPerPuff = GetNumParticles(m_nNumPerPuff); for (int i=0; i < nNumSteps; i++) { // Build the individual Particle puffs... for (int j=0; j < nNumPerPuff; j++) { VEC_COPY(vTemp, vPos); if (m_bIgnoreWind) { VEC_SET(vDriftVel, GetRandom(-m_vDriftOffset.x*2.0f, -m_vDriftOffset.x), GetRandom(5.0f, 6.0f), GetRandom(-m_vDriftOffset.z, m_vDriftOffset.z)); } else { VEC_SET(vDriftVel, g_vWorldWindVel.x + GetRandom(-m_vDriftOffset.x*2.0f, -m_vDriftOffset.x), g_vWorldWindVel.y + GetRandom(5.0f, 6.0f), g_vWorldWindVel.z + GetRandom(-m_vDriftOffset.z, m_vDriftOffset.z)); } vTemp.x += GetRandom(-fOffset, fOffset); vTemp.y += GetRandom(-fOffset, fOffset); vTemp.z += GetRandom(-fOffset, fOffset); GetRandomColorInRange(vColor); m_pClientDE->AddParticle(m_hObject, &vTemp, &vDriftVel, &vColor, fCurLifeTime); } VEC_ADD(vPos, vPos, vDelta); fCurLifeTime += fLifeTimeOffset; } m_fLastTime = fTime; VEC_COPY(m_vLastPos, vCurPos); } return LTTRUE; }