LTBOOL CBaseParticleSystemFX::CreateObject(ILTClient *pClientDE) { if (!CSpecialFX::CreateObject(pClientDE)) return LTFALSE; LTVector vPos = m_vPos; LTRotation rRot; rRot.Init(); // Use server object position if a position wasn't specified... if (m_hServerObject) { LTVector vZero(0, 0, 0), vServObjPos; if (vPos.Equals(vZero)) { pClientDE->GetObjectPos(m_hServerObject, &vServObjPos); vPos = vServObjPos; } else { m_basecs.bClientControlsPos = LTTRUE; } // Calculate our offset from the server object... m_vPosOffset = vPos - vServObjPos; } // Use the specified rotation if applicable if (!m_rRot.IsIdentity()) { rRot = m_rRot; } ObjectCreateStruct createStruct; INIT_OBJECTCREATESTRUCT(createStruct); createStruct.m_ObjectType = OT_PARTICLESYSTEM; createStruct.m_Flags = FLAG_VISIBLE | FLAG_UPDATEUNSEEN | FLAG_FOGDISABLE; createStruct.m_Pos = vPos; createStruct.m_Rotation = rRot; m_hObject = m_pClientDE->CreateObject(&createStruct); // Setup the ParticleSystem... return SetupSystem(); }
LTBOOL CProjectile::UpdateDoVectorValues(SURFACE & surf, LTFLOAT fThickness, LTVector vImpactPos, LTVector & vFrom, LTVector & vTo) { // See if we've traveled the distance... LTVector vDistTraveled = vImpactPos - m_vFirePos; LTFLOAT fDist = m_fRange - vDistTraveled.Mag(); if (fDist < 1.0f) return LTTRUE; // Just dampen based on the bute file values, don't worry about the // surface thinkness... m_fInstDamage *= surf.fBulletDamageDampen; fDist *= surf.fBulletRangeDampen; int nPerturb = surf.nMaxShootThroughPerturb; if (nPerturb) { LTRotation rRot; g_pLTServer->AlignRotation(&rRot, &m_vDir, LTNULL); LTVector vU, vR, vF; g_pLTServer->GetRotationVectors(&rRot, &vU, &vR, &vF); LTFLOAT fRPerturb = ((LTFLOAT)GetRandom(-nPerturb, nPerturb))/1000.0f; LTFLOAT fUPerturb = ((LTFLOAT)GetRandom(-nPerturb, nPerturb))/1000.0f; m_vDir += (vR * fRPerturb); m_vDir += (vU * fUPerturb); m_vDir.Norm(); } // Make sure we move the from position... if (vFrom.Equals(vImpactPos, 1.0f)) { vFrom += m_vDir; } else { vFrom = vImpactPos; } vTo = vFrom + (m_vDir * fDist); return LTFALSE; }
LTBOOL CProjectile::HandleVectorImpact(IntersectInfo & iInfo, LTVector & vFrom, LTVector & vTo) { // Get the surface type... SurfaceType eSurfType = GetSurfaceType(iInfo); // See if we hit an invisible surface... if (eSurfType == ST_INVISIBLE) { if (!CalcInvisibleImpact(iInfo, eSurfType)) { SURFACE* pSurf = g_pSurfaceMgr->GetSurface(eSurfType); if (!pSurf) return LTTRUE; return UpdateDoVectorValues(*pSurf, 0, iInfo.m_Point, vFrom, vTo); } } // See if we hit an object that should be damaged... LTBOOL bHitWorld = IsMainWorld(iInfo.m_hObject); if (!bHitWorld && eSurfType != ST_LIQUID) { ImpactDamageObject(m_hFiredFrom, iInfo.m_hObject); } // If the fire position is the initial fire position, use the flash // position when building the impact special fx... LTVector vFirePos = (vFrom.Equals(m_vFirePos) ? m_vFlashPos : vFrom); AddImpact(iInfo.m_hObject, vFirePos, iInfo.m_Point, iInfo.m_Plane.m_Normal, eSurfType); // See if we can shoot through the surface... SURFACE* pSurf = g_pSurfaceMgr->GetSurface(eSurfType); if (!pSurf) return LTTRUE; // Done. if (pSurf->bCanShootThrough) { int nMaxThickness = pSurf->nMaxShootThroughThickness; if (nMaxThickness == 0) { // Special case of always being able to shoot through surface... // Calculate new values for next DoVector iteration... return UpdateDoVectorValues(*pSurf, 0, iInfo.m_Point, vFrom, vTo); } // Test if object/wall intersected is thin enough to be shot // through... // Test object case first... if (!bHitWorld && iInfo.m_hObject) { // Test to see if we can shoot through the object... LTVector vDims; g_pLTServer->GetObjectDims(iInfo.m_hObject, &vDims); if (vDims.x*2.0f >= nMaxThickness && vDims.y*2.0f >= nMaxThickness && vDims.z*2.0f >= nMaxThickness) { // Can't shoot through this object... return LTTRUE; } } // Determine if we shot through the wall/object... IntersectInfo iTestInfo; IntersectQuery qTestInfo; qTestInfo.m_From = iInfo.m_Point + (m_vDir * (LTFLOAT)(nMaxThickness + 1)); qTestInfo.m_To = iInfo.m_Point - m_vDir; qTestInfo.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID | INTERSECT_HPOLY; qTestInfo.m_FilterFn = DoVectorFilterFn; qTestInfo.m_pUserData = m_hFiredFrom; if (g_pLTServer->IntersectSegment(&qTestInfo, &iTestInfo)) { // Calculate new values for next DoVector iteration... LTVector vThickness = iTestInfo.m_Point - iInfo.m_Point; return UpdateDoVectorValues(*pSurf, vThickness.Mag(), iTestInfo.m_Point, vFrom, vTo); } } return LTTRUE; }
void Breakable::UpdateFalling() { LTVector vOldPos; g_pLTServer->GetObjectPos(m_hObject, &vOldPos); LTVector vPos = vOldPos; vPos += (m_vVel * g_pLTServer->GetFrameTime()); LTBOOL bDone = LTFALSE; if (vPos.y < m_vFinalPos.y) { vPos.y = m_vFinalPos.y; bDone = LTTRUE; } g_pLTServer->TeleportObject(m_hObject, &vPos); if (vPos.Equals(m_vFinalPos, 10.0f)) { bDone = LTTRUE; } if (bDone) { m_bFalling = LTFALSE; uint32 dwFlags = g_pLTServer->GetObjectFlags(m_hObject); dwFlags |= FLAG_SOLID; g_pLTServer->SetObjectFlags(m_hObject, dwFlags); g_pLTServer->SetNextUpdate(m_hObject, 0.0f); // Create impact fx... CreateImpactFX(); if (m_bDestroyOnImpact) { Destroy(); } else { // Play the impact sound... if (m_hstrImpactSound) { LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); char* pSnd = g_pLTServer->GetStringData(m_hstrImpactSound); if (pSnd) { g_pServerSoundMgr->PlaySoundFromPos(vPos, pSnd, m_fImpactSoundRadius, SOUNDPRIORITY_MISC_MEDIUM); } } } } }