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; }
void Body::FacePos(const LTVector& vTargetPos) { if (!g_pLTServer || !m_hObject) return; LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); LTVector vDir; VEC_SUB(vDir, vTargetPos, vPos); if ( vDir.MagSqr() == 0.0f ) { // Facing the same position... this would be a divide by zero case // when we normalize. So just return. return; } vDir.y = 0.0f; // Don't look up/down VEC_NORM(vDir); LTRotation rRot; LTVector temp(0,1,0); g_pMathLT->AlignRotation(rRot, vDir, temp); g_pLTServer->SetObjectRotation(m_hObject, &rRot); }
void CPlayerCamera::PointAtPosition(DVector pos, DRotation rRot, DVector pointFrom) { if (!m_pClientDE) return; // m_pServerDE->GetObjectPos(m_hObject, &vPos); // vTargetPos.y = vPos.y; // Don't look up/down. DVector vDir; VEC_SUB(vDir, pos, pointFrom); VEC_NORM(vDir); m_pClientDE->AlignRotation(&m_rRotation, &vDir, NULL); //m_Angles.Copy(m_Target.m_Angles); //m_Angles.z = angles.z; //m_Angles.x = angles.x; /* DVector vAngles; VEC_INIT(vAngles); m_rRotation = rRot; DFLOAT diffX = pos.x - m_vPos.x; DFLOAT diffY = pos.z - m_vPos.z; vAngles.y = (DFLOAT)atan2(diffX, diffY); DVector target, copy; DVector up, right, forward; m_pClientDE->GetRotationVectors(&m_rRotation, &up, &right, &forward); VEC_SUB(copy, pos, pointFrom); target = Apply(right, up, forward, copy); diffX = target.z; diffY = target.y; //DFLOAT temp = -ATan2(diffY,diffX); //if(Abs(temp - m_Angles.x) < .5) vAngles.x = (DFLOAT)-atan2(diffY, diffX); //PrintVector(pos); //GetClientShell().CPrint("X = " + RealStr(m_Angles.x)); DRotation rOldRot; ROT_COPY(rOldRot, m_rRotation); m_pClientDE->SetupEuler(&m_rRotation, vAngles.x, vAngles.y, vAngles.z); // Make sure rotation is valid... m_pClientDE->GetRotationVectors(&m_rRotation, &up, &right, &forward); if (up.y < 0) ROT_COPY(m_rRotation, rOldRot); */ }
inline bool d3d_ClipSprite(SpriteInstance *pInstance, HPOLY hPoly, T **ppPoints, uint32 *pnPoints, T *pOut) { LTPlane thePlane; float dot, d1, d2; SPolyVertex *pPrevPoint, *pCurPoint, *pEndPoint; LTVector vecTo; T *pVerts; uint32 nVerts; WorldPoly *pPoly; if(g_have_world == false) return false; // Get the correct poly. pPoly = world_bsp_client->GetPolyFromHPoly(hPoly); if(!pPoly) return false; // First see if the viewer is on the frontside of the poly. dot = pPoly->GetPlane()->DistTo(g_ViewParams.m_Pos); if(dot <= 0.01f) return false; pVerts = *ppPoints; nVerts = *pnPoints; // Clip on each edge plane. pEndPoint = &pPoly->GetVertices()[pPoly->GetNumVertices()]; pPrevPoint = pEndPoint - 1; for(pCurPoint=pPoly->GetVertices(); pCurPoint != pEndPoint; ) { VEC_SUB(vecTo, pCurPoint->m_Vertex->m_Vec, pPrevPoint->m_Vertex->m_Vec); VEC_CROSS(thePlane.m_Normal, vecTo, pPoly->GetPlane()->m_Normal); VEC_NORM(thePlane.m_Normal); thePlane.m_Dist = VEC_DOT(thePlane.m_Normal, pCurPoint->m_Vertex->m_Vec); #define CLIPTEST PLANETEST #define DOCLIP DOPLANECLIP #include "polyclip.h" #undef CLIPTEST #undef DOCLIP pPrevPoint = pCurPoint; ++pCurPoint; } *ppPoints = pVerts; *pnPoints = nVerts; return true; }
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); } }
LTBOOL CGibFX::OkToRemoveGib(HLOCALOBJ hGib) { if (!m_pClientDE || !g_pGameClientShell || !hGib) return LTTRUE; // The only constraint is that the client isn't currently looking // at the model... HLOCALOBJ hCamera = g_pGameClientShell->GetCamera(); if (!hCamera) return LTTRUE; LTVector vPos, vCamPos; m_pClientDE->GetObjectPos(hGib, &vPos); m_pClientDE->GetObjectPos(hCamera, &vCamPos); // Determine if the client can see us... LTVector vDir; VEC_SUB(vDir, vPos, vCamPos); LTRotation rRot; LTVector vU, vR, vF; m_pClientDE->GetObjectRotation(hCamera, &rRot); m_pClientDE->GetRotationVectors(&rRot, &vU, &vR, &vF); VEC_NORM(vDir); VEC_NORM(vF); LTFLOAT fMul = VEC_DOT(vDir, vF); if (fMul <= 0.0f) return LTTRUE; // Client is looking our way, don't remove it yet... return LTFALSE; }
DBOOL CMovement::ClearToPoint(DVector vStart, DVector vDestPos, DVector vDims, IntersectInfo* IInfo) { GlobalFilterFnData globalFilterFnData; CServerDE* pServerDE = BaseClass::GetServerDE(); if (!pServerDE) return DFALSE; DFLOAT fDim = (DFLOAT)sqrt((vDims.x * vDims.x) + (vDims.z * vDims.z)) + 0.1f; IntersectQuery IQuery; IQuery.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID; IQuery.m_FilterFn = GlobalFilterFn; globalFilterFnData.m_dwFlags = IGNORE_CHARACTER; globalFilterFnData.m_nIgnoreObjects = 1; globalFilterFnData.m_hIgnoreObjects = &m_hObject; IQuery.m_pUserData = &globalFilterFnData; DVector vDir; DRotation rRot; VEC_SUB(vDir, vDestPos, vStart); VEC_NORM(vDir); pServerDE->AlignRotation(&rRot, &vDir, &m_vUp); DVector vU,vR,vF; pServerDE->GetRotationVectors(&rRot,&vU,&vR,&vF); //check the right side VEC_ADDSCALED(IQuery.m_From, vStart, vR, fDim); VEC_ADDSCALED(IQuery.m_To, vDestPos, vR, fDim); if(pServerDE->IntersectSegment(&IQuery, IInfo)) { return DFALSE; } //check the left side VEC_ADDSCALED(IQuery.m_From, vStart, vR, (fDim * -1.0f)); VEC_ADDSCALED(IQuery.m_To,vDestPos, vR, (fDim * -1.0f)); if(pServerDE->IntersectSegment(&IQuery, IInfo)) { return DFALSE; } return DTRUE; }
DBOOL UndeadGideon::Fire(DBOOL bAltFire) { DVector vPos, vDir; DRotation rRot; // Sanity check (GK 9/18/98) if (!m_InventoryMgr.GetCurrentWeapon()) return DFALSE; m_pServerDE->GetModelNodeTransform(m_hObject,"head",&vPos,&rRot); VEC_SUB(vDir, m_vTargetPos, vPos); VEC_NORM(vDir); vDir.x = m_MoveObj.GetForwardVector().x; vDir.z = m_MoveObj.GetForwardVector().z; m_pServerDE->AlignRotation(&rRot, &vDir, DNULL); DDWORD m_nFiredWeapon = m_InventoryMgr.FireCurrentWeapon(&vPos, &rRot, bAltFire); return DTRUE; }
DBOOL Naga::Fire(DBOOL bAltFire) { DVector vPos, vDir; DRotation rRot; // Sanity check (GK 9/18/98) if (!m_InventoryMgr.GetCurrentWeapon()) return DFALSE; switch(m_InventoryMgr.GetCurrentWeapon()->GetType()) { case WEAP_NAGA_EYEBEAM: { m_pServerDE->GetModelNodeTransform(m_hObject,"head_gun",&vPos,&rRot); VEC_SUB(vDir, m_vTargetPos, vPos); break; } case WEAP_NAGA_SPIKE: { m_pServerDE->GetModelNodeTransform(m_hObject,"l_gun",&vPos,&rRot); VEC_SUB(vDir, m_vTargetPos, vPos); break; } default: { m_pServerDE->GetObjectPos(m_hObject,&vPos); VEC_SUB(vDir, m_vTargetPos, vPos); break; } } VEC_NORM(vDir); m_pServerDE->AlignRotation(&rRot, &vDir, DNULL); m_InventoryMgr.FireCurrentWeapon(&vPos, &rRot, bAltFire); return DTRUE; }
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::MoveCameraToPosition(DVector pos, DVector vStartPos, DFLOAT deltaTime) { if (!m_pClientDE || !m_hTarget) return; DFLOAT nCurrentTime = m_pClientDE->GetTime(); // Handle transition if (m_eCameraMode == GOINGFIRSTPERSON || m_eCameraMode == GOINGCHASE || m_eCameraMode == DEATH) { if (nCurrentTime > m_fTransitionStart + m_fTransitionTime) { switch (m_eCameraMode) { case GOINGFIRSTPERSON: m_eCameraMode = FIRSTPERSON; break; case GOINGCHASE: m_eCameraMode = CHASE; break; } } else { // vStartPos is starting pos, pos is the position we want DFLOAT percentage = (nCurrentTime - m_fTransitionStart) / (m_fTransitionTime); DVector vMagnitude; VEC_SUB (vMagnitude, pos, vStartPos); VEC_MULSCALAR (vMagnitude, vMagnitude, percentage); VEC_ADD (pos, vStartPos, vMagnitude); } } DVector dir; VEC_SUB(dir, pos, m_vPos); DFLOAT multiplier = 1.0f; // 0.5f; DVector toMove; VEC_MULSCALAR(toMove, dir, multiplier); DFLOAT moveMag; if(m_bSlide) { moveMag = VEC_MAG(toMove); if(moveMag > VEC_MAG(dir)) moveMag = VEC_MAG(dir); if (toMove.x != 0.0f || toMove.y != 0.0f || toMove.z != 0.0f) { VEC_NORM(toMove); } VEC_MULSCALAR(toMove, toMove, moveMag); VEC_ADD(m_vPos, m_vPos, toMove); } else { VEC_COPY(m_vPos, pos); } }
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); }
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); } }
void CNodeController::UpdateHeadFollowPosControl(NCSTRUCT *pNodeControl) { LTVector vPos; LTRotation rRot; LTransform transform; LTVector vU, vR, vF; //---------------------------------------------------------------------- // Get information about the control node... // *** NOTE: On the head node... vU faces forward, vR faces down, vF faces right *** // Get access to the controls... ILTMath *pMathLT = g_pLTClient->GetMathLT(); ILTModel *pModelLT = g_pLTClient->GetModelLT(); ILTTransform *pTransformLT = g_pLTClient->GetTransformLT(); // Get the transform of the node we're controlling pModelLT->GetNodeTransform(GetCFX()->GetServerObj(), m_aNodes[pNodeControl->eModelNode].hModelNode, transform, LTTRUE); // Decompose the transform into the position and rotation pTransformLT->Get(transform, vPos, rRot); pMathLT->GetRotationVectors(rRot, vR, vU, vF); // Get information about the follow position... LTVector vObjPos = pNodeControl->vFollowPos; // Turn the follow control off if the expire time has past if(pNodeControl->fFollowExpireTime <= 0.0f) { pNodeControl->fFollowExpireTime = 0.0f; pNodeControl->bFollowOn = LTFALSE; } else pNodeControl->fFollowExpireTime -= g_pGameClientShell->GetFrameTime(); //---------------------------------------------------------------------- // Setup the rotation matrix to directly follow the destination position // Get the direction that we're going to face... LTVector vDir = vObjPos - vPos; // Setup some temp vectors that are on the x/z plane... LTVector vTempU, vTempF, vTempDir; vTempU = vU; vTempU.y = 0.0f; vTempF = vF; vTempF.y = 0.0f; vTempDir = vDir; vTempDir.y = 0.0f; VEC_NORM(vTempU); VEC_NORM(vTempF); VEC_NORM(vTempDir); // Get the dot products between the dir vector and the up and forward to determine the rotation angles LTFLOAT fDotUDir = VEC_DOT(vTempU, vTempDir); LTFLOAT fDotFDir = VEC_DOT(vTempF, vTempDir); LTFLOAT fDotRDir = 0.0f; // Init the vectors to get a rotation matrix from... LTVector vRotAxisR(1.0f, 0.0f, 0.0f); // Get the first rotation angle LTFLOAT fAngle1 = pNodeControl->bFollowOn ? fDotUDir : 1.0f; if(fAngle1 < -0.1f) fAngle1 = -0.1f; // HACK! Limit the head rotation fAngle1 = (1.0f - fAngle1) * MATH_HALFPI; if(fDotFDir < 0.0f) fAngle1 *= -1.0f; // Do a full rotation around the first axis so we can get an angle for the second axis LTFLOAT fTempAngle = pNodeControl->bFollowOn ? ((1.0f - fDotUDir) * MATH_HALFPI) : 0.0f; pMathLT->RotateAroundAxis(rRot, vR, (fDotFDir < 0.0f) ? -fTempAngle : fTempAngle); pMathLT->GetRotationVectors(rRot, vR, vU, vF); VEC_NORM(vDir); fDotUDir = VEC_DOT(vU, vDir); fDotRDir = VEC_DOT(vR, vDir); // Get the second rotation angle LTFLOAT fAngle2 = pNodeControl->bFollowOn ? fDotUDir : 1.0f; if(fAngle2 < 0.25f) fAngle2 = 0.25f; // HACK! Limit the head rotation fAngle2 = (1.0f - fAngle2) * MATH_HALFPI; if(fDotRDir > 0.0f) fAngle2 *= -1.0f; // Calculate a max rotation value LTFLOAT fRotMax = (pNodeControl->fFollowRate * g_pGameClientShell->GetFrameTime() / 180.0f) * MATH_PI; // Interpolate the angles based off the previous angle if(fAngle1 > pNodeControl->vFollowAngles.y + fRotMax) fAngle1 = pNodeControl->vFollowAngles.y + fRotMax; else if(fAngle1 < pNodeControl->vFollowAngles.y - fRotMax) fAngle1 = pNodeControl->vFollowAngles.y - fRotMax; if(fAngle2 > pNodeControl->vFollowAngles.x + fRotMax) fAngle2 = pNodeControl->vFollowAngles.x + fRotMax; else if(fAngle2 < pNodeControl->vFollowAngles.x - fRotMax) fAngle2 = pNodeControl->vFollowAngles.x - fRotMax; // Create a new rotation and rotate around each controlled axis LTRotation rNewRot; rNewRot.Init(); pMathLT->RotateAroundAxis(rNewRot, vRotAxisR, fAngle1); pNodeControl->vFollowAngles.y = fAngle1; pMathLT->GetRotationVectors(rNewRot, vR, vU, vF); pMathLT->RotateAroundAxis(rNewRot, vF, fAngle2); pNodeControl->vFollowAngles.x = fAngle2; // If we're turned off and back at the start rotation... make the control invalid if(!pNodeControl->bFollowOn && pNodeControl->vFollowAngles.x == 0.0f && pNodeControl->vFollowAngles.y == 0.0f) { pNodeControl->bValid = LTFALSE; return; } // Create a rotation matrix and apply it to the current offset matrix LTMatrix m1; pMathLT->SetupRotationMatrix(m1, rNewRot); m_aNodes[pNodeControl->eModelNode].matTransform = m_aNodes[pNodeControl->eModelNode].matTransform * m1; }
int evals_evecs(double eval[3], double evec[9], const double _M00, const double _M01, const double _M02, const double _M11, const double _M12, const double _M22) { double r0[3], r1[3], r2[3], crs[3], len, dot; double mean, norm, rnorm, Q, R, QQQ, D, theta, M00, M01, M02, M11, M12, M22; double epsilon = 1.0E-12; int roots; /* copy the given matrix elements */ M00 = _M00; M01 = _M01; M02 = _M02; M11 = _M11; M12 = _M12; M22 = _M22; /* ** subtract out the eigenvalue mean (will add back to evals later); ** helps with numerical stability */ mean = (M00 + M11 + M22)/3.0; M00 -= mean; M11 -= mean; M22 -= mean; /* ** divide out L2 norm of eigenvalues (will multiply back later); ** this too seems to help with stability */ norm = sqrt(M00*M00 + 2*M01*M01 + 2*M02*M02 + M11*M11 + 2*M12*M12 + M22*M22); rnorm = norm ? 1.0/norm : 1.0; M00 *= rnorm; M01 *= rnorm; M02 *= rnorm; M11 *= rnorm; M12 *= rnorm; M22 *= rnorm; /* this code is a mix of prior Teem code and ideas from Eberly's "Eigensystems for 3 x 3 Symmetric Matrices (Revisited)" */ Q = (M01*M01 + M02*M02 + M12*M12 - M00*M11 - M00*M22 - M11*M22)/3.0; QQQ = Q*Q*Q; R = (M00*M11*M22 + M02*(2*M01*M12 - M02*M11) - M00*M12*M12 - M01*M01*M22)/2.0; D = QQQ - R*R; if (D > epsilon) { /* three distinct roots- this is the most common case */ double mm, ss, cc; theta = atan2(sqrt(D), R)/3.0; mm = sqrt(Q); ss = sin(theta); cc = cos(theta); eval[0] = 2*mm*cc; eval[1] = mm*(-cc + sqrt(3.0)*ss); eval[2] = mm*(-cc - sqrt(3.0)*ss); roots = ROOT_THREE; /* else D is near enough to zero */ } else if (R < -epsilon || epsilon < R) { double U; /* one double root and one single root */ U = airCbrt(R); /* cube root function */ if (U > 0) { eval[0] = 2*U; eval[1] = -U; eval[2] = -U; } else { eval[0] = -U; eval[1] = -U; eval[2] = 2*U; } roots = ROOT_SINGLE_DOUBLE; } else { /* a triple root! */ eval[0] = eval[1] = eval[2] = 0.0; roots = ROOT_TRIPLE; } /* r0, r1, r2 are the vectors we manipulate to find the nullspaces of M - lambda*I */ VEC_SET(r0, 0.0, M01, M02); VEC_SET(r1, M01, 0.0, M12); VEC_SET(r2, M02, M12, 0.0); if (ROOT_THREE == roots) { r0[0] = M00 - eval[0]; r1[1] = M11 - eval[0]; r2[2] = M22 - eval[0]; nullspace1(evec+0, r0, r1, r2); r0[0] = M00 - eval[1]; r1[1] = M11 - eval[1]; r2[2] = M22 - eval[1]; nullspace1(evec+3, r0, r1, r2); r0[0] = M00 - eval[2]; r1[1] = M11 - eval[2]; r2[2] = M22 - eval[2]; nullspace1(evec+6, r0, r1, r2); } else if (ROOT_SINGLE_DOUBLE == roots) { if (eval[1] == eval[2]) { /* one big (eval[0]) , two small (eval[1,2]) */ r0[0] = M00 - eval[0]; r1[1] = M11 - eval[0]; r2[2] = M22 - eval[0]; nullspace1(evec+0, r0, r1, r2); r0[0] = M00 - eval[1]; r1[1] = M11 - eval[1]; r2[2] = M22 - eval[1]; nullspace2(evec+3, evec+6, r0, r1, r2); } else { /* two big (eval[0,1]), one small (eval[2]) */ r0[0] = M00 - eval[0]; r1[1] = M11 - eval[0]; r2[2] = M22 - eval[0]; nullspace2(evec+0, evec+3, r0, r1, r2); r0[0] = M00 - eval[2]; r1[1] = M11 - eval[2]; r2[2] = M22 - eval[2]; nullspace1(evec+6, r0, r1, r2); } } else { /* ROOT_TRIPLE == roots; use any basis for eigenvectors */ VEC_SET(evec+0, 1, 0, 0); VEC_SET(evec+3, 0, 1, 0); VEC_SET(evec+6, 0, 0, 1); } /* we always make sure its really orthonormal; keeping fixed the eigenvector associated with the largest-magnitude eigenvalue */ if (ABS(eval[0]) > ABS(eval[2])) { /* normalize evec+0 but don't move it */ VEC_NORM(evec+0, len); dot = VEC_DOT(evec+0, evec+3); VEC_SCL_SUB(evec+3, dot, evec+0); VEC_NORM(evec+3, len); dot = VEC_DOT(evec+0, evec+6); VEC_SCL_SUB(evec+6, dot, evec+0); dot = VEC_DOT(evec+3, evec+6); VEC_SCL_SUB(evec+6, dot, evec+3); VEC_NORM(evec+6, len); } else { /* normalize evec+6 but don't move it */ VEC_NORM(evec+6, len); dot = VEC_DOT(evec+6, evec+3); VEC_SCL_SUB(evec+3, dot, evec+6); VEC_NORM(evec+3, len); dot = VEC_DOT(evec+3, evec+0); VEC_SCL_SUB(evec+0, dot, evec+3); dot = VEC_DOT(evec+6, evec+0); VEC_SCL_SUB(evec+0, dot, evec+6); VEC_NORM(evec+0, len); } /* to be nice, make it right-handed */ VEC_CROSS(crs, evec+0, evec+3); if (0 > VEC_DOT(crs, evec+6)) { VEC_SCL(evec+6, -1); } /* multiply back by eigenvalue L2 norm */ eval[0] /= rnorm; eval[1] /= rnorm; eval[2] /= rnorm; /* add back in the eigenvalue mean */ eval[0] += mean; eval[1] += mean; eval[2] += mean; return roots; }
void CProjectile::AddImpact(DVector vPoint, DVector vNormal, HOBJECT hObj) { // Compute a normal vector // Cast a ray to see what we hit DVector tempPos; IntersectQuery iq; IntersectInfo ii; SurfaceType eType = SURFTYPE_UNKNOWN; DBYTE nFX = 0; VEC_NORM(m_vDir); VEC_MULSCALAR(m_vDir, m_vDir, 2.0f); VEC_SUB(iq.m_From, vPoint, m_vDir); VEC_MULSCALAR(m_vDir, m_vDir, 10.0f); VEC_ADD(iq.m_To, vPoint, m_vDir); iq.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID; iq.m_FilterFn = NULL; iq.m_pUserData = NULL; if (hObj && g_pServerDE->IntersectSegment(&iq, &ii)) { VEC_COPY(vNormal, ii.m_Plane.m_Normal); eType = GetSurfaceType(ii.m_hObject, ii.m_hPoly); VEC_COPY(tempPos, ii.m_Point); } else // Fake it { VEC_NEGATE(vNormal, m_vDir); VEC_COPY(tempPos, vPoint); } if(m_bExplosion) { AddExplosion(tempPos, vNormal); nFX |= WFX_SCREENSHAKE; } if(m_bClientFX) { CServerDE* pServerDE = BaseClass::GetServerDE(); if (!pServerDE) return; /* ObjectCreateStruct theStruct; INIT_OBJECTCREATESTRUCT(theStruct); VEC_COPY(theStruct.m_Pos, vPoint); HCLASS hClass = pServerDE->GetClass("CClientWeaponSFX"); CClientWeaponSFX *pWeaponFX = DNULL; if(hClass) pWeaponFX = (CClientWeaponSFX*)pServerDE->CreateObject(hClass, &theStruct); */ DDWORD nFX = WFX_SCREENSHAKE; DDWORD nExtras = WFX_EXTRA_DAMAGE; WeaponFXExtras ext; ext.fDamage = m_fDamage; // if(pWeaponFX) SendWeaponSFXMessage(&vPoint, &vPoint, &vNormal, &vNormal, nFX, nExtras, &ext); } }
DBOOL CRainFX::Update() { if (!m_hObject || !m_pClientDE) return DFALSE; DFLOAT fTime = m_pClientDE->GetTime(); if (m_bFirstUpdate) { m_fLastTime = m_pClientDE->GetTime(); m_bFirstUpdate = DFALSE; return DTRUE; } // Make sure it is time to update... if (fTime < m_fLastTime + m_fNextUpdate) { return DTRUE; } //set our new position based on the server object if(m_hServerObject) { DVector vPos,vUp,vRight; m_pClientDE->GetObjectPos(m_hServerObject, &vPos); m_pClientDE->SetObjectPos(m_hObject,&vPos); DRotation rRot; m_pClientDE->GetObjectRotation(m_hServerObject, &rRot); m_pClientDE->SetObjectRotation(m_hObject,&rRot); m_pClientDE->GetRotationVectors(&rRot,&vUp,&vRight,&m_vDirection); } else return DFALSE; // Total time it's been active... m_fTimeLen += fTime - m_fLastTime; m_fLastTime = fTime; //SCHLEGZ 5/1/98 7:07:33 PM: added time limit to the rain effect itself if(m_fTimeLimit && m_fTimeLen > m_fTimeLimit) { WantRemove(); return DFALSE; } // How much time it's accounted for by adding particles... DFLOAT fAddedTime = m_nParticlesAdded / m_fAreaDensity; // Ok, how many to add this frame.... int nToAdd = (int) floor( m_fAreaDensity * (m_fTimeLen - fAddedTime) ); m_nParticlesAdded += nToAdd; DVector vel, vOffset; DBOOL bAddTrails = DFALSE; VEC_COPY(vel, m_vDirection); if (vel.x == 0.0f && vel.y == 0.0f && vel.z == 0.0f) vel.y = -1.0f; VEC_COPY(vOffset, vel); VEC_NORM(vOffset); bAddTrails = (!m_bGravity || (vel.x == 0 && vel.z == 0 && m_fSpread == 0)); if (!bAddTrails) nToAdd *= 6; for(int i=0; i < nToAdd; i++) { DVector vPos, vTmp, vTmpVel; vPos.x = GetRandom(-m_vDims.x, m_vDims.x); vPos.y = GetRandom(-m_vDims.y, m_vDims.y); vPos.z = GetRandom(-m_vDims.z, m_vDims.z); VEC_MULSCALAR(vTmpVel, vel, GetRandom(0.8f, 1.2f)); if (m_fSpread) { DFLOAT fOffset = GetRandom(-m_fSpread, m_fSpread); vTmpVel.x += fOffset; fOffset = GetRandom(-m_fSpread, m_fSpread); vTmpVel.z += fOffset; } // Add the particles if (bAddTrails) { // Set up colors for particle stream DVector vPartColors[6]; vPartColors[0].x = GetRandom(m_vColor1.x, m_vColor2.x); vPartColors[0].y = GetRandom(m_vColor1.y, m_vColor2.y); vPartColors[0].z = GetRandom(m_vColor1.z, m_vColor2.z); VEC_MULSCALAR(vPartColors[1], vPartColors[0], 0.8f); VEC_MULSCALAR(vPartColors[2], vPartColors[0], 0.6f); VEC_MULSCALAR(vPartColors[3], vPartColors[0], 0.4f); VEC_MULSCALAR(vPartColors[4], vPartColors[0], 0.2f); VEC_MULSCALAR(vPartColors[5], vPartColors[0], 0.2f); m_pClientDE->AddParticle(m_hObject, &vPos, &vTmpVel, &vPartColors[0], m_fLifetime); VEC_MULSCALAR(vTmp, vOffset, -3.0f); VEC_ADD(vPos, vPos, vTmp); m_pClientDE->AddParticle(m_hObject, &vPos, &vTmpVel, &vPartColors[1], m_fLifetime); VEC_MULSCALAR(vTmp, vOffset, -4.0f); VEC_ADD(vPos, vPos, vTmp); m_pClientDE->AddParticle(m_hObject, &vPos, &vTmpVel, &vPartColors[2], m_fLifetime); VEC_MULSCALAR(vTmp, vOffset, -5.0f); VEC_ADD(vPos, vPos, vTmp); m_pClientDE->AddParticle(m_hObject, &vPos, &vTmpVel, &vPartColors[3], m_fLifetime); VEC_MULSCALAR(vTmp, vOffset, -6.0f); VEC_ADD(vPos, vPos, vTmp); m_pClientDE->AddParticle(m_hObject, &vPos, &vTmpVel, &vPartColors[4], m_fLifetime); VEC_MULSCALAR(vTmp, vOffset, -7.0f); VEC_ADD(vPos, vPos, vTmp); m_pClientDE->AddParticle(m_hObject, &vPos, &vTmpVel, &vPartColors[5], m_fLifetime); } else { DVector vPartColor; vPartColor.x = GetRandom(m_vColor1.x, m_vColor2.x); vPartColor.y = GetRandom(m_vColor1.y, m_vColor2.y); vPartColor.z = GetRandom(m_vColor1.z, m_vColor2.z); m_pClientDE->AddParticle(m_hObject, &vPos, &vTmpVel, &vPartColor, m_fLifetime); } } // Determine when next update should occur... if (m_cs.fPulse > 0.001f) { m_fNextUpdate = m_cs.fPulse * GetRandom(0.01f, 1.0f); } else { m_fNextUpdate = 0.01f; } return DTRUE; }
DBOOL CCastLineFX::Update() { if(!m_hObject || !m_pClientDE || !m_hServerObject) return DFALSE; if (m_bWantRemove) { return DFALSE; } DRotation rRot; m_pClientDE->GetObjectRotation(m_hServerObject, &rRot); m_pClientDE->SetObjectRotation(m_hObject, &rRot); DVector vPos; m_pClientDE->GetObjectPos(m_hServerObject, &vPos); m_pClientDE->SetObjectPos(m_hObject, &vPos); if (m_bFirstUpdate) { m_bFirstUpdate = DFALSE; DELine line; // Set first vertex... VEC_SET(line.m_Points[0].m_Pos, 0.0f, 0.0f, 0.0f); line.m_Points[0].r = m_vStartColor.x; line.m_Points[0].g = m_vStartColor.y; line.m_Points[0].b = m_vStartColor.z; line.m_Points[0].a = m_fStartAlpha; // Set second vertex (cast a ray to find it)... DVector vEndPoint, vU, vR, vF; m_pClientDE->GetRotationVectors(&rRot, &vU, &vR, &vF); VEC_NORM(vF); DFLOAT fDistance = 10000.0f; // Far, far, away... if (!m_hCastTo) { ClientIntersectQuery iQuery; ClientIntersectInfo iInfo; VEC_COPY(iQuery.m_From, vPos); VEC_COPY(iQuery.m_Direction, vF); iQuery.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID; if (m_pClientDE->CastRay(&iQuery, &iInfo)) { VEC_COPY(vEndPoint, iInfo.m_Point); fDistance = VEC_MAG(vEndPoint); } } else { m_pClientDE->GetObjectPos(m_hCastTo, &vEndPoint); VEC_SUB(vEndPoint, vEndPoint, vPos); fDistance = VEC_MAG(vEndPoint); } VEC_SET(vEndPoint, 0.0f, 0.0f, 1.0f); VEC_MULSCALAR(vEndPoint, vEndPoint, fDistance); VEC_COPY(line.m_Points[1].m_Pos, vEndPoint); line.m_Points[1].r = m_vEndColor.x; line.m_Points[1].g = m_vEndColor.y; line.m_Points[1].b = m_vEndColor.z; line.m_Points[1].a = m_fEndAlpha; m_pClientDE->AddLine(m_hObject, &line); } return DTRUE; }
void SoccerBall::Update( ) { DVector vVel, vAccel, vAccelAdd, vPos, vForward, vCross, vTemp, vTemp2; CollisionInfo collInfo; float fVelMag, fDistTraveled, fTime, fRotAmount, fExp; DRotation rRot; g_pServerDE->GetObjectPos( m_hObject, &vPos ); g_pServerDE->GetVelocity( m_hObject, &vVel ); fVelMag = VEC_MAG( vVel ); fTime = g_pServerDE->GetTime( ); // Remove the ball if it's been sitting around for a while. if( fTime > m_fRespawnTime ) { g_pServerDE->RemoveObject( m_hObject ); return; } // Update the on ground info g_pServerDE->GetStandingOn( m_hObject, &collInfo ); m_bOnGround = ( collInfo.m_hObject ) ? DTRUE : DFALSE; if( m_bOnGround ) { m_fLastTimeOnGround = fTime; } // Get how far we've traveled. VEC_SUB( vForward, vPos, m_vLastPos ); fDistTraveled = VEC_MAG( vForward ); VEC_COPY( m_vLastPos, vPos ); // Rotate the ball if( fDistTraveled > 0.0f ) { VEC_MULSCALAR( vForward, vForward, 1.0f / fDistTraveled ); if( m_bOnGround ) { VEC_COPY( m_vLastNormal, collInfo.m_Plane.m_Normal ); VEC_CROSS( vCross, vForward, m_vLastNormal ); fRotAmount = VEC_MAG( vCross ) * fDistTraveled / m_fRadius; } else { VEC_CROSS( vCross, vForward, m_vLastNormal ); fRotAmount = VEC_MAG( vCross ) * fDistTraveled / m_fRadius; } if( fRotAmount > 0.0f ) { VEC_NORM( vCross ); g_pServerDE->GetObjectRotation( m_hObject, &rRot ); g_pServerDE->RotateAroundAxis( &rRot, &vCross, fRotAmount ); g_pServerDE->SetObjectRotation( m_hObject, &rRot ); } } // Adjust the velocity and accel if( fVelMag < MINBALLVEL ) { VEC_INIT( vVel ); g_pServerDE->SetVelocity( m_hObject, &vVel ); } else if( fVelMag > MAXBALLVEL ) { VEC_MULSCALAR( vVel, vVel, MAXBALLVEL / fVelMag ); g_pServerDE->SetVelocity( m_hObject, &vVel ); } else { // new velocity is given by: v = ( a / k ) + ( v_0 - a / k ) * exp( -k * t ) g_pServerDE->GetAcceleration( m_hObject, &vAccel ); fExp = ( float )exp( -BALLDRAG * g_pServerDE->GetFrameTime( )); VEC_DIVSCALAR( vTemp, vAccel, BALLDRAG ); VEC_SUB( vTemp2, vVel, vTemp ); VEC_MULSCALAR( vTemp2, vTemp2, fExp ); VEC_ADD( vVel, vTemp2, vTemp ); g_pServerDE->SetVelocity( m_hObject, &vVel ); } // Make sure we're rolling if we're on a slope. This counteracts the way the // engine stops objects on slopes. if( m_bOnGround ) { if( collInfo.m_Plane.m_Normal.y < 0.9f && fabs( vVel.y ) < 50.0f ) { g_pServerDE->GetGlobalForce( &vAccelAdd ); vAccel.y += vAccelAdd.y * 0.5f; g_pServerDE->SetAcceleration( m_hObject, &vAccel ); } } // Play a bounce sound if enough time has elapsed if( m_bBounced ) { if( fTime > m_fLastBounceTime + TIMEBETWEENBOUNCESOUNDS ) { // Play a bounce sound... PlaySoundFromPos( &vPos, "Sounds_ao\\events\\soccerball.wav", 750, SOUNDPRIORITY_MISC_MEDIUM ); } m_bBounced = DFALSE; } g_pServerDE->SetNextUpdate( m_hObject, 0.001f ); }
DBOOL CParticleStreamFX::AddParticles() { if(!m_hObject || !m_pClientDE) return DFALSE; DVector minOffset, maxOffset; DFLOAT minVel, maxVel; DFLOAT minLife, maxLife; DFLOAT spread; DFLOAT ratio, time = m_pClientDE->GetTime(); DDWORD num; if(!m_bState) return DTRUE; num = m_nNumParticles; VEC_SET(minOffset, -m_fPosRadius, -m_fPosRadius, -m_fPosRadius); VEC_SET(maxOffset, m_fPosRadius, m_fPosRadius, m_fPosRadius); minVel = m_fMinVel; maxVel = m_fMaxVel; minLife = m_fMinLife; maxLife = m_fMaxLife; spread = m_fSpread; if((m_bState == 1) || (m_bState == 3)) { // Set the ratio to ramp the values with if(m_bState == 1) { ratio = (time - m_fTriggerTime) / m_fRampTime; if(ratio >= 1.0f) { ratio = 1.0f; m_bState = 2; } } else { ratio = 1.0f - ((time - m_fTriggerTime) / m_fRampTime); if(ratio <= 0.0f) { ratio = 0.0f; m_bState = 0; return DTRUE; } } // Check which elements of the stream we should ramp... and calculate new values if(m_bRampFlags & PSTREAM_RAMP_NUM) num = (DDWORD)(num * ratio); if(m_bRampFlags & PSTREAM_RAMP_OFFSET) { VEC_MULSCALAR(minOffset, minOffset, ratio); VEC_MULSCALAR(maxOffset, maxOffset, ratio); } if(m_bRampFlags & PSTREAM_RAMP_VEL) { minVel *= ratio; maxVel *= ratio; spread *= ratio; } if(m_bRampFlags & PSTREAM_RAMP_LIFE) { minLife *= ratio; maxLife *= ratio; } } // Add the particles one by one... (instead of AddParticles... cause I wanted the spread) for(DDWORD i = 0; i < num; i++) { DVector pos, vel, vSpread, color; DFLOAT life = GetRandom(minLife, maxLife); VEC_SET(pos, GetRandom(minOffset.x, maxOffset.x), GetRandom(minOffset.y, maxOffset.y), GetRandom(minOffset.z, maxOffset.z)); VEC_SET(vSpread, GetRandom(-spread, spread), GetRandom(-spread, spread), GetRandom(-spread, spread)); VEC_MULSCALAR(vel, m_vDir, maxVel); VEC_ADD(vel, vel, vSpread); VEC_NORM(vel); VEC_MULSCALAR(vel, vel, GetRandom(minVel, maxVel)); GetRandomColorInRange(color); m_pClientDE->AddParticle(m_hObject, &pos, &vel, &color, life); } // Make sure we know when the last batch of particles were added m_fLastAddTime = time; return DTRUE; }
DVector CPlayerCamera::FindOptimalCameraPosition() { DVector pos; VEC_INIT(pos); if (!m_pClientDE || !m_hTarget) return pos; DVector up, right, forward, dir; DFLOAT distToOptimal; DVector TargetPlusOffset; DVector vTargetPos; m_pClientDE->GetObjectPos(m_hTarget, &vTargetPos); DRotation rRot; m_pClientDE->GetObjectRotation(m_hTarget, &rRot); if (Equal(vTargetPos, m_vLastTargetPos) && Equal(rRot, m_rLastTargetRot) && m_eCameraMode != DEATH) { return m_vLastOptPos; } else { VEC_COPY(m_vLastTargetPos, vTargetPos); ROT_COPY(m_rLastTargetRot, rRot); } DVector vTemp; if (m_eCameraMode == DEATH) { VEC_COPY(vTemp, m_TargetDeathOffset); } else { VEC_COPY(vTemp, m_TargetChaseOffset); } VEC_ADD(vTemp, vTargetPos, vTemp); VEC_COPY(TargetPlusOffset, vTemp); m_pClientDE->GetRotationVectors(&rRot, &up, &right, &forward); // pos = TargetPlusOffset + right*m_OptX + up*m_OptY + forward*m_OptZ; DVector vTemp1, vTemp2; if (m_eCameraMode == DEATH) { VEC_MULSCALAR(vTemp, right, m_DeathOptX); VEC_MULSCALAR(vTemp2, forward, m_DeathOptZ); } else { VEC_MULSCALAR(vTemp, right, m_OptX); VEC_MULSCALAR(vTemp2, forward, m_OptZ); } VEC_MULSCALAR(vTemp1, up, m_OptY); ClientIntersectQuery iQuery; ClientIntersectInfo iInfo; VEC_ADD(vTemp, vTemp, vTemp1); VEC_ADD(vTemp, vTemp, vTemp2); VEC_ADD(pos, TargetPlusOffset, vTemp); VEC_SUB(vTemp, TargetPlusOffset, pos); distToOptimal = VEC_MAG(vTemp); VEC_SUB(dir, pos, TargetPlusOffset); VEC_NORM(dir); VEC_COPY(iQuery.m_From, TargetPlusOffset); VEC_COPY(iQuery.m_To, pos); if (m_pClientDE->IntersectSegment(&iQuery, &iInfo)) { VEC_SUB(vTemp, iInfo.m_Point, TargetPlusOffset); // If there was something in the way, move in front of that thing. if (VEC_MAG(vTemp) < distToOptimal) { VEC_ADD(pos, iInfo.m_Point, iInfo.m_Plane.m_Normal); } } #ifdef DOING_EXTRA_CHECKS // Make sure we aren't clipping into walls... DFLOAT fClipDistance = 100.0f; // 15.0f; DBOOL bClipRightIssues = DTRUE; DBOOL bClipUpIssues = DTRUE; // Check for walls to the right... VEC_MULSCALAR(vTemp, right, fClipDistance); VEC_ADD(vTemp, pos, vTemp); VEC_COPY(iQuery.m_From, pos); VEC_COPY(iQuery.m_To, vTemp); if (m_pClientDE->IntersectSegment(&iQuery, &iInfo)) { VEC_SUB(vTemp, iInfo.m_Point, pos); DFLOAT fDist = (fClipDistance - VEC_MAG(vTemp)); VEC_MULSCALAR(vTemp, right, -fDist) VEC_ADD(pos, pos, vTemp); } else { bClipRightIssues = DFALSE; } // If we didn't adjust for a wall to the right, check walls to the left... if (!bClipRightIssues) { VEC_MULSCALAR(vTemp, right, -fClipDistance); VEC_ADD(vTemp, pos, vTemp); VEC_COPY(iQuery.m_From, pos); VEC_COPY(iQuery.m_To, vTemp); if (m_pClientDE->IntersectSegment(&iQuery, &iInfo)) { VEC_SUB(vTemp, iInfo.m_Point, pos); DFLOAT fDist = (fClipDistance - VEC_MAG(vTemp)); VEC_MULSCALAR(vTemp, right, fDist) VEC_ADD(pos, pos, vTemp); } } // Check for ceilings... VEC_MULSCALAR(vTemp, up, fClipDistance); VEC_ADD(vTemp, pos, vTemp); VEC_COPY(iQuery.m_From, pos); VEC_COPY(iQuery.m_To, vTemp); if (m_pClientDE->IntersectSegment(&iQuery, &iInfo)) { VEC_SUB(vTemp, iInfo.m_Point, pos); DFLOAT fDist = (fClipDistance - VEC_MAG(vTemp)); VEC_MULSCALAR(vTemp, up, -fDist) VEC_ADD(pos, pos, vTemp); } else { bClipUpIssues = DFALSE; } // If we didn't hit any ceilings, check for floors... if (!bClipUpIssues) { VEC_MULSCALAR(vTemp, up, -fClipDistance); VEC_ADD(vTemp, pos, vTemp); VEC_COPY(iQuery.m_From, pos); VEC_COPY(iQuery.m_To, vTemp); if (m_pClientDE->IntersectSegment(&iQuery, &iInfo)) { VEC_SUB(vTemp, iInfo.m_Point, pos); DFLOAT fDist = (fClipDistance - VEC_MAG(vTemp)); VEC_MULSCALAR(vTemp, up, fDist) VEC_ADD(pos, pos, vTemp); } } #endif // DOING_EXTRA_CHECKS VEC_COPY(m_vLastOptPos, pos); return pos; }
void VolumeBrush::UpdatePhysics(ContainerPhysics* pCPStruct) { if (m_bHidden || !pCPStruct || !pCPStruct->m_hObject) return; LTFLOAT fUpdateDelta = g_pLTServer->GetFrameTime(); // Let the character know if they are in liquid... if (IsLiquid(m_eContainerCode) && IsCharacter(pCPStruct->m_hObject)) { CCharacter* pCharacter = (CCharacter*)g_pLTServer->HandleToObject(pCPStruct->m_hObject); if (pCharacter) { pCharacter->UpdateInLiquid(this, pCPStruct); } } // Player container physics is done on the client... if (!IsPlayer(pCPStruct->m_hObject)) { // Dampen velocity based on the viscosity of the container... LTVector vVel, vCurVel; vVel = vCurVel = pCPStruct->m_Velocity; if (m_fViscosity > 0.0f && VEC_MAG(vCurVel) > 1.0f) { LTVector vDir; VEC_COPY(vDir, vCurVel); VEC_NORM(vDir); LTFLOAT fAdjust = MAX_CONTAINER_VISCOSITY * m_fViscosity * fUpdateDelta; vVel = (vDir * fAdjust); if (VEC_MAG(vVel) < VEC_MAG(vCurVel)) { VEC_SUB(vVel, vCurVel, vVel); } else { VEC_INIT(vVel); } vVel += (m_vCurrent * fUpdateDelta); pCPStruct->m_Velocity = vVel; } // Do special liquid handling... if (IsLiquid(m_eContainerCode)) { UpdateLiquidPhysics(pCPStruct); } } // Update damage... // Make damage relative to update delta... LTFLOAT fDamage = 0.0f; if (m_fDamage > 0.0f) { fDamage = m_fDamage * fUpdateDelta; } // Damage using progressive damage. This insures that the correct // damage effect is shown on the client... if (fDamage) { DamageStruct damage; damage.eType = m_eDamageType; damage.fDamage = fDamage; damage.hDamager = m_hObject; // Use progressive damage... damage.fDuration = 0.25f; damage.hContainer = m_hObject; damage.DoDamage(this, pCPStruct->m_hObject); } }