LTBOOL WorldFilterFn(HOBJECT hObj, void *pUserData) { if ( IsMainWorld(hObj) ) { return LTTRUE; } return LTFALSE; }
LTBOOL GroundFilterFn(HOBJECT hObj, void *pUserData) { if ( IsMainWorld(hObj) || (OT_WORLDMODEL == g_pLTServer->GetObjectType(hObj)) ) { return LTTRUE; } return LTFALSE; }
bool GroundFilterFn(HOBJECT hObj, void *pUserData) { if ( IsMainWorld(hObj) || (OT_WORLDMODEL == GetObjectType(hObj)) ) { return true; } return false; }
bool WorldFilterFn(HOBJECT hObj, void *pUserData) { if ( IsMainWorld(hObj) ) { return true; } return false; }
void CProjectileFX::HandleTouch(CollisionInfo *pInfo) { if (!m_pClientDE || !pInfo || !pInfo->m_hObject || !g_pGameClientShell) return; // Let it get out of our bounding box... CMoveMgr* pMoveMgr = g_pPlayerMgr->GetMoveMgr(); if (pMoveMgr) { // Don't colide with the move mgr object... HLOCALOBJ hMoveObj = pMoveMgr->GetObject(); if (pInfo->m_hObject == hMoveObj) return; // Don't colide with the player object... HLOCALOBJ hPlayerObj = m_pClientDE->GetClientObject(); if (pInfo->m_hObject == hPlayerObj) return; } // See if we want to impact on this object... uint32 dwUsrFlags; g_pCommonLT->GetObjectFlags(pInfo->m_hObject, OFT_User, dwUsrFlags); if (dwUsrFlags & USRFLG_IGNORE_PROJECTILES) return; LTBOOL bIsWorld = IsMainWorld(pInfo->m_hObject); // Don't impact on non-solid objects... uint32 dwFlags; g_pCommonLT->GetObjectFlags(pInfo->m_hObject, OFT_Flags, dwFlags); if (!bIsWorld && !(dwFlags & FLAG_SOLID)) return; // See if we hit the sky... if (bIsWorld) { SurfaceType eType = GetSurfaceType(pInfo->m_hPoly); if (eType == ST_SKY) { m_bWantRemove = LTTRUE; return; } else if (eType == ST_INVISIBLE) { // Keep going, ignore this object... return; } } Detonate(pInfo); }
float AINavMeshLinkAbstract::FindFloor( const LTVector& vPos, const LTVector& vDir, float fOffset ) { IntersectQuery IQuery; IntersectInfo IInfo; IQuery.m_From = vPos + ( vDir * fOffset ); IQuery.m_To = IQuery.m_From; IQuery.m_To.y -= 10000.f; IQuery.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID | INTERSECT_HPOLY; IQuery.m_FilterFn = GroundFilterFn; if( g_pLTServer->IntersectSegment(IQuery, &IInfo) && (IsMainWorld(IInfo.m_hObject) || (OT_WORLDMODEL == GetObjectType(IInfo.m_hObject) ) ) ) { return IInfo.m_Point.y; } return vPos.y; }
// ----------------------------------------------------------------------- // // // ROUTINE: CAIUtils::FindTrueCeilingHeight // // PURPOSE: Find height of the ceiling above an AI at some position. // // ----------------------------------------------------------------------- // LTBOOL CAIUtils::FindTrueCeilingHeight(float flCheckDist, const LTVector& vDims, const LTVector& vPos, LTFLOAT* pfFloorHeight) { AIASSERT( pfFloorHeight, m_hObject, "CAIHuman::FindFloorHeight: fFloorHeight is NULL" ); IntersectQuery IQuery; IntersectInfo IInfo; IQuery.m_From = LTVector(vPos.x, vPos.y - vDims.y, vPos.z); IQuery.m_To = LTVector(vPos.x, vPos.y + flCheckDist, vPos.z); IQuery.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID; IQuery.m_FilterFn = GroundFilterFn; g_cIntersectSegmentCalls++; if (g_pLTServer->IntersectSegment(&IQuery, &IInfo) && (IsMainWorld(IInfo.m_hObject) || (OT_WORLDMODEL == GetObjectType(IInfo.m_hObject)))) { *pfFloorHeight = IInfo.m_Point.y; return LTTRUE; } return LTFALSE; }
void CProjectile::Detonate(HOBJECT hObj) { if (m_bDetonated) return; // Make sure we don't detonate if a cinematic is playing (i.e., // make sure the user doesn't disrupt the cinematic)... if (Camera::IsActive()) { RemoveObject(); return; } m_bDetonated = LTTRUE; SurfaceType eType = ST_UNKNOWN; LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); // Determine the normal of the surface we are impacting on... LTVector vNormal(0.0f, 1.0f, 0.0f); if (hObj) { if (IsMainWorld(hObj) || g_pLTServer->GetObjectType(hObj) == OT_WORLDMODEL) { CollisionInfo info; g_pLTServer->GetLastCollision(&info); if (info.m_hPoly) { eType = GetSurfaceType(info.m_hPoly); } LTPlane plane = info.m_Plane; vNormal = plane.m_Normal; // Calculate where we really hit the plane... LTVector vVel, vP0, vP1, vDir; g_pLTServer->GetVelocity(m_hObject, &vVel); vDir = vVel; vDir.Norm(); vP1 = vPos; vVel *= g_pLTServer->GetFrameTime(); vP0 = vP1 - vVel; vP1 += vVel; // Make sure we don't tunnel through an object... IntersectInfo iInfo; IntersectQuery qInfo; qInfo.m_Flags = INTERSECT_HPOLY | INTERSECT_OBJECTS | IGNORE_NONSOLID; qInfo.m_From = vP0; qInfo.m_To = vPos; qInfo.m_FilterFn = SpecificObjectFilterFn; qInfo.m_pUserData = m_hObject; if (g_pLTServer->IntersectSegment(&qInfo, &iInfo)) { vPos = iInfo.m_Point - vDir; eType = GetSurfaceType(iInfo); vNormal = iInfo.m_Plane.m_Normal; } else { //g_pLTServer->CPrint("P0 = %.2f, %.2f, %.2f", VEC_EXPAND(vP0)); //g_pLTServer->CPrint("P1 = %.2f, %.2f, %.2f", VEC_EXPAND(vP1)); //LTVector vDist = vP1 - vP0; //g_pLTServer->CPrint("Distance from P0 to P1: %.2f", vDist.Mag()); LTFLOAT fDot1 = VEC_DOT(vNormal, vP0) - info.m_Plane.m_Dist; LTFLOAT fDot2 = VEC_DOT(vNormal, vP1) - info.m_Plane.m_Dist; if (fDot1 < 0.0f && fDot2 < 0.0f || fDot1 > 0.0f && fDot2 > 0.0f) { vPos = vP1; } else { LTFLOAT fPercent = -fDot1 / (fDot2 - fDot1); //g_pLTServer->CPrint("Percent: %.2f", fPercent); VEC_LERP(vPos, vP0, vP1, fPercent); } } LTRotation rRot; g_pLTServer->AlignRotation(&rRot, &vNormal, LTNULL); g_pLTServer->SetObjectRotation(m_hObject, &rRot); // g_pLTServer->CPrint("Pos = %.2f, %.2f, %.2f", VEC_EXPAND(vPos)); } } else { // Since hObj was null, this means the projectile's lifetime was up, // so we just blew-up in the air. eType = ST_AIR; } if (eType == ST_UNKNOWN) { eType = GetSurfaceType(hObj); } AddImpact(hObj, m_vFlashPos, vPos, vNormal, eType); // Handle impact damage... if (hObj) { HOBJECT hDamager = m_hFiredFrom ? m_hFiredFrom : m_hObject; ImpactDamageObject(hDamager, hObj); } //g_pLTServer->CPrint("Server end pos (%.2f, %.2f, %.2f)", vPos.x, vPos.y, vPos.z); //g_pLTServer->CPrint("Server fly time %.2f", g_pLTServer->GetTime() - m_fStartTime); // Remove projectile from world... RemoveObject(); }
void CProjectile::HandleTouch(HOBJECT hObj) { if (m_bObjectRemoved) return; // Don't process any touches until this has been cleared... if (m_bProcessInvImpact) return; // Let it get out of our bounding box... if (hObj == m_hFiredFrom) return; CCharacterHitBox* pHitBox = LTNULL; // If we've hit a character (or body), let its hit box take control... if (IsCharacter(hObj)) { CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(hObj); if (pChar) { hObj = pChar->GetHitBox(); } } else if (IsBody(hObj)) { Body* pBody = (Body*)g_pLTServer->HandleToObject(hObj); if (pBody) { hObj = pBody->GetHitBox(); } } if (IsCharacterHitBox(hObj)) { pHitBox = (CCharacterHitBox*)g_pLTServer->HandleToObject(hObj); if (!pHitBox) return; if (pHitBox->GetModelObject() == m_hFiredFrom) return; } // Don't hit our own type of projectiles (for multi-projectile weapons // and projectiles that stick to objects)... if (IsKindOf(hObj, m_hObject)) { CProjectile* pObj = (CProjectile*)g_pLTServer->HandleToObject(hObj); if (pObj) { if (pObj->GetFiredFrom() == m_hFiredFrom) { return; } } } // See if we want to impact on this object... uint32 dwUsrFlags = g_pLTServer->GetObjectUserFlags(hObj); if (dwUsrFlags & USRFLG_IGNORE_PROJECTILES) return; LTBOOL bIsWorld = IsMainWorld(hObj); // Don't impact on non-solid objects...unless it is a CharacterHitBox // object... uint32 dwFlags = g_pLTServer->GetObjectFlags(hObj); if (!bIsWorld && !(dwFlags & FLAG_SOLID)) { if (pHitBox) { // See if we really impacted on the box... if (pHitBox->DidProjectileImpact(this)) { // This is the object that we really hit... hObj = pHitBox->GetModelObject(); } else { return; } } else if (!(dwFlags & FLAG_RAYHIT)) { // If we have ray hit set to true, projectiles should // impact on us too... return; } } // See if we hit the sky... if (bIsWorld || (OT_WORLDMODEL == g_pLTServer->GetObjectType(hObj))) { CollisionInfo info; g_pLTServer->GetLastCollision(&info); SurfaceType eType = GetSurfaceType(info); if (eType == ST_SKY) { RemoveObject(); return; } else if (eType == ST_INVISIBLE) { // Update 1.002 [KLS] - If multiplayer and we hit an invisible // surface, just treat it like a normal surface... if (!IsMultiplayerGame()) { m_bProcessInvImpact = LTTRUE; g_pLTServer->GetObjectPos(m_hObject, &m_vInvisNewPos); g_pLTServer->GetVelocity(m_hObject, &m_vInvisVel); m_vInvisNewPos += (m_vInvisVel * g_pLTServer->GetFrameTime()); // Make sure this new position is inside the world...else // just blow up... if (LT_INSIDE == g_pLTServer->Common()->GetPointStatus(&m_vInvisNewPos)) { return; } } } } HandleImpact(hObj); }
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 CWeaponFX::CreateBloodSplatFX() { CGameSettings* pSettings = g_pInterfaceMgr->GetSettings(); if (!pSettings || !pSettings->Gore()) return; CSFXMgr* psfxMgr = g_pGameClientShell->GetSFXMgr(); if (!psfxMgr) return; CSpecialFX* pFX = LTNULL; LTFLOAT fRange = g_vtBloodSplatsRange.GetFloat(); // See if we should make some blood splats... ClientIntersectQuery iQuery; IntersectInfo iInfo; iQuery.m_From = m_vPos; LTVector vDir = m_vDir; // Create some blood splats... int nNumSplats = GetRandom((int)g_vtBloodSplatsMinNum.GetFloat(), (int)g_vtBloodSplatsMaxNum.GetFloat()); LTVector vU, vR, vF; g_pLTClient->GetRotationVectors(&m_rDirRot, &vU, &vR, &vF); for (int i=0; i < nNumSplats; i++) { LTVector vDir = m_vDir; // Perturb direction after first splat... if (i > 0) { float fPerturb = g_vtBloodSplatsPerturb.GetFloat(); float fRPerturb = (GetRandom(-fPerturb, fPerturb))/1000.0f; float fUPerturb = (GetRandom(-fPerturb, fPerturb))/1000.0f; vDir += (vR * fRPerturb); vDir += (vU * fUPerturb); } iQuery.m_To = vDir * fRange; iQuery.m_To += m_vPos; iQuery.m_Flags = IGNORE_NONSOLID | INTERSECT_HPOLY; if (g_pLTClient->IntersectSegment(&iQuery, &iInfo) && IsMainWorld(iInfo.m_hObject)) { SurfaceType eType = GetSurfaceType(iInfo); if (eType == ST_SKY || eType == ST_INVISIBLE) { return; // Don't leave blood on the sky } LTBOOL bBigBlood = (LTBOOL)GetConsoleInt("BigBlood", 0); // Create a blood splat... BSCREATESTRUCT sc; g_pLTClient->AlignRotation(&(sc.rRot), &(iInfo.m_Plane.m_Normal), LTNULL); // Randomly rotate the blood splat g_pLTClient->RotateAroundAxis(&(sc.rRot), &(iInfo.m_Plane.m_Normal), GetRandom(0.0f, MATH_CIRCLE)); LTVector vTemp = vDir * -2.0f; sc.vPos = iInfo.m_Point + vTemp; // Off the wall a bit sc.vVel.Init(0.0f, 0.0f, 0.0f); sc.vInitialScale.Init(1.0f, 1.0f, 1.0f); sc.vInitialScale.x = GetRandom(g_vtBloodSplatsMinScale.GetFloat(), g_vtBloodSplatsMaxScale.GetFloat()); if (bBigBlood) sc.vInitialScale.x *= g_vtBigBloodSizeScale.GetFloat(); sc.vInitialScale.y = sc.vInitialScale.x; sc.vFinalScale = sc.vInitialScale; sc.dwFlags = FLAG_VISIBLE | FLAG_ROTATEABLESPRITE | FLAG_NOLIGHT; sc.fLifeTime = GetRandom(g_vtBloodSplatsMinLifetime.GetFloat(), g_vtBloodSplatsMaxLifetime.GetFloat()); if (bBigBlood) sc.fLifeTime *= g_vtBigBloodLifeScale.GetFloat(); sc.fInitialAlpha = 1.0f; sc.fFinalAlpha = 0.0f; sc.nType = OT_SPRITE; sc.bMultiply = LTTRUE; char* pBloodFiles[] = { "Sfx\\Test\\Spr\\BloodL1.spr", "Sfx\\Test\\Spr\\BloodL2.spr", "Sfx\\Test\\Spr\\BloodL3.spr", "Sfx\\Test\\Spr\\BloodL4.spr" }; sc.pFilename = pBloodFiles[GetRandom(0,3)]; pFX = psfxMgr->CreateSFX(SFX_SCALE_ID, &sc); if (pFX) pFX->Update(); } else if (i==0) { // Didn't hit anything straight back, do don't bother to // do anymore... return; } } }
void CTargetMgr::CheckForIntersect(float &fDistAway) { m_hTarget = LTNULL; m_ActivationData.Init(); uint32 dwUsrFlags = 0; const float fMaxDist = 100000.0f; // Cast ray from the camera to see if there is an object to activate... LTRotation rRot; LTVector vPos; HLOCALOBJ hCamera = g_pPlayerMgr->GetCamera(); g_pLTClient->GetObjectPos(hCamera, &vPos); g_pLTClient->GetObjectRotation(hCamera, &rRot); m_ActivationData.m_vPos = vPos; m_ActivationData.m_rRot = rRot; IntersectQuery IQuery; IntersectInfo IInfo; IQuery.m_From = vPos; IQuery.m_To = IQuery.m_From + (rRot.Forward() * fMaxDist); // NOTE the use of the CHECK_FROM_POINT_INSIDE_OBJECTS flag. This flag will // make sure that any objects that m_From is inside are considered IQuery.m_Flags = CHECK_FROM_POINT_INSIDE_OBJECTS | INTERSECT_HPOLY | INTERSECT_OBJECTS | IGNORE_NONSOLID; IQuery.m_FilterActualIntersectFn = ActivateFilterFn; IQuery.m_pActualIntersectUserData = (void*)&IQuery; IQuery.m_PolyFilterFn = DoVectorPolyFilterFn; // [KLS 8/3/02] - ActivateFilterFn may save an object to use that may not be // the best activation choice (i.e., a fallback choice). However, if a // better choice isn't found, the fallback choice should be used. That // fallback choice is stored in g_adFallbackActivationObject so we clear // it here... g_adFallbackActivationObject.Init(); if (g_pLTClient->IntersectSegment(&IQuery, &IInfo)) { m_ActivationData.m_vIntersect = IInfo.m_Point; if (IsMainWorld(IInfo.m_hObject)) { if (IInfo.m_hPoly != INVALID_HPOLY) { SurfaceType eType = GetSurfaceType(IInfo.m_hPoly); SURFACE *pSurf = g_pSurfaceMgr->GetSurface(eType); // See if the surface we tried to activate has an activation // sound...If so, the user can activate it... if (pSurf && pSurf->szActivationSnd[0] && pSurf->fActivationSndRadius > 0) { m_hTarget = IInfo.m_hObject; m_ActivationData.m_hTarget = m_hTarget; m_ActivationData.m_nSurfaceType = eType; } } } else { LTVector vObjPos = m_ActivationData.m_vIntersect; vObjPos -= vPos; if (vObjPos.Mag() <= fMaxDist) { m_hTarget = IInfo.m_hObject; m_ActivationData.m_hTarget = m_hTarget; } } // Calculate how far away the object is... LTVector vDist = m_ActivationData.m_vIntersect - vPos; fDistAway = vDist.Mag(); } // [KLS 8/3/02] - Use the fallback object if we have one and we didn't // find another object more suitable object... bool bCanUseFallback = (m_ActivationData.m_hTarget ? false : true); if (!bCanUseFallback) { // We can still use the fallback object if it isn't the world or a // world model... if (IsMainWorld(m_ActivationData.m_hTarget) || OT_WORLDMODEL == GetObjectType(m_ActivationData.m_hTarget)) { bCanUseFallback = true; } } if ( bCanUseFallback && g_adFallbackActivationObject.m_hTarget ) { // Ok we hit the fallback object reset some of our target data LTVector vObjPos; g_pLTClient->GetObjectPos(g_adFallbackActivationObject.m_hTarget, &vObjPos); m_ActivationData.m_vIntersect = vObjPos; vObjPos -= vPos; if (vObjPos.Mag() <= fMaxDist) { m_hTarget = g_adFallbackActivationObject.m_hTarget; m_ActivationData.m_hTarget = m_hTarget; } // Calculate how far away the object is... LTVector vDist = m_ActivationData.m_vIntersect - vPos; fDistAway = vDist.Mag(); } }
void CTargetMgr::CheckForIntersect(float &fDistAway) { m_hTarget = NULL; m_ActivationData.Init(); // Cast ray from the camera to see if there is an object to activate... LTRotation const& rRot = g_pPlayerMgr->GetPlayerCamera()->GetCameraRotation( );; LTVector const& vPos = g_pPlayerMgr->GetPlayerCamera()->GetCameraPos( ); m_ActivationData.m_vPos = vPos; m_ActivationData.m_rRot = rRot; IntersectQuery IQuery; IntersectInfo IInfo; IQuery.m_From = vPos; IQuery.m_To = IQuery.m_From + (rRot.Forward() * kMaxDistance); // NOTE the use of the CHECK_FROM_POINT_INSIDE_OBJECTS flag. This flag will // make sure that any objects that m_From is inside are considered IQuery.m_Flags = CHECK_FROM_POINT_INSIDE_OBJECTS | INTERSECT_HPOLY | INTERSECT_OBJECTS | IGNORE_NONSOLID; IQuery.m_FilterActualIntersectFn = ActivateFilterFn; IQuery.m_pActualIntersectUserData = (void*)&IQuery; IQuery.m_PolyFilterFn = NULL; // [KLS 8/3/02] - ActivateFilterFn may save an object to use that may not be // the best activation choice (i.e., a fallback choice). However, if a // better choice isn't found, the fallback choice should be used. That // fallback choice is stored in g_adFallbackActivationObject so we clear // it here... g_adFallbackActivationObject.Init(); if (g_pLTClient->IntersectSegment(IQuery, &IInfo)) { m_ActivationData.m_vIntersect = IInfo.m_Point; bool bHitSky = false; if (IsMainWorld(IInfo.m_hObject)) { if (IInfo.m_hPoly != INVALID_HPOLY) { SurfaceType eType = GetSurfaceType(IInfo.m_hPoly); HSURFACE hSurf = g_pSurfaceDB->GetSurface(eType); // See if the surface we tried to activate has an activation // sound...If so, the user can activate it... if (hSurf) { HRECORD hActSnd = g_pSurfaceDB->GetRecordLink(hSurf,SrfDB_Srf_rActivationSnd); if (hActSnd && g_pSoundDB->GetFloat(hActSnd,SndDB_fOuterRadius) > 0) { m_hTarget = IInfo.m_hObject; m_ActivationData.m_hTarget = m_hTarget; m_ActivationData.m_nSurfaceType = eType; m_ActivationData.m_hActivateSnd = hActSnd; } bHitSky = (ST_SKY == eType); } } } else { LTVector vObjPos = m_ActivationData.m_vIntersect; vObjPos -= vPos; if (vObjPos.Mag() <= kMaxDistance) { m_hTarget = IInfo.m_hObject; m_ActivationData.m_hTarget = m_hTarget; } } // Calculate how far away the object is... LTVector vDist = m_ActivationData.m_vIntersect - vPos; if (bHitSky) fDistAway = kMaxDistance; else fDistAway = vDist.Mag(); } // [KLS 8/3/02] - Use the fallback object if we have one and we didn't // find another object more suitable object... bool bCanUseFallback = (m_ActivationData.m_hTarget ? false : true); if (!bCanUseFallback) { // We can still use the fallback object if it isn't the world or a // world model... if (IsMainWorld(m_ActivationData.m_hTarget) || OT_WORLDMODEL == GetObjectType(m_ActivationData.m_hTarget)) { bCanUseFallback = true; } } if ( bCanUseFallback && g_adFallbackActivationObject.m_hTarget ) { // Ok we hit the fallback object reset some of our target data LTVector vObjPos; g_pLTClient->GetObjectPos(g_adFallbackActivationObject.m_hTarget, &vObjPos); m_ActivationData.m_vIntersect = vObjPos; vObjPos -= vPos; if (vObjPos.Mag() <= kMaxDistance) { m_hTarget = g_adFallbackActivationObject.m_hTarget; m_ActivationData.m_hTarget = m_hTarget; } // Calculate how far away the object is... LTVector vDist = m_ActivationData.m_vIntersect - vPos; fDistAway = vDist.Mag(); } }
void Prop::HandleAttachmentTouch( HOBJECT hToucher ) { if( !hToucher || !m_bAttachmentShotOff ) return; // Don't touch the owner... if( hToucher == m_hAttachmentOwner ) return; // Or any non-solid objects... uint32 dwToucherFlags; g_pCommonLT->GetObjectFlags( hToucher, OFT_Flags, dwToucherFlags ); if( !(dwToucherFlags & FLAG_SOLID) ) return; CollisionInfo info; g_pLTServer->GetLastCollision( &info ); LTVector vVel; g_pPhysicsLT->GetVelocity( m_hObject, &vVel ); // Calculate where we really hit the world... if( IsMainWorld( hToucher )) { LTVector vPos, vCurVel, vP0, vP1; g_pLTServer->GetObjectPos( m_hObject, &vPos ); vP1 = vPos; vCurVel = vVel * g_pLTServer->GetFrameTime(); vP0 = vP1 - vCurVel; vP1 += vCurVel; LTFLOAT fDot1 = VEC_DOT( info.m_Plane.m_Normal, vP0 ) - info.m_Plane.m_Dist; LTFLOAT fDot2 = VEC_DOT( info.m_Plane.m_Normal, vP1 ) - info.m_Plane.m_Dist; if( fDot1 < 0.0f && fDot2 < 0.0f || fDot1 > 0.0f && fDot2 > 0.0f ) { vPos = vP1; } else { LTFLOAT fPercent = -fDot1 / (fDot2 - fDot1); VEC_LERP( vPos, vP0, vP1, fPercent); } // Set our new "real" pos... g_pLTServer->SetObjectPos( m_hObject, &vPos ); } // If we're on the ground (or an object), stop movement... CollisionInfo standingInfo; g_pLTServer->GetStandingOn( m_hObject, &standingInfo ); CollisionInfo* pInfo = standingInfo.m_hObject ? &standingInfo : &info; if( pInfo->m_hObject ) { // Don't stop on walls... if( pInfo->m_Plane.m_Normal.y > 0.75f ) { vVel.Init(); // Turn off gravity, solid, and touch notify.... uint32 dwFlags = FLAG_POINTCOLLIDE | FLAG_NOSLIDING | FLAG_TOUCH_NOTIFY | FLAG_GRAVITY; g_pCommonLT->SetObjectFlags( m_hObject, OFT_Flags, 0, dwFlags ); // Rotate to rest... if( m_bRotating ) { LTRotation rRot( 0.0f, m_fYaw, 0.0f ); g_pLTServer->SetObjectRotation( m_hObject, &rRot ); m_bRotating = false; StartFade( s_vtAttachmentFadeDuration.GetFloat(), s_vtAttachmentFadeDelay.GetFloat() ); } } } // Remove the stoping velocity... vVel = -info.m_vStopVel; g_pPhysicsLT->SetVelocity( m_hObject, &vVel ); }
void CSpear::HandleImpact(HOBJECT hObj) { if (!g_vtSpearStickPercentage.IsInitted()) { g_vtSpearStickPercentage.Init(g_pLTServer, "SpearStickPercent", LTNULL, 0.9f); } if (!m_pAmmoData || !m_pAmmoData->pProjectileFX) { CProjectile::HandleImpact(hObj); return; } CollisionInfo info; g_pLTServer->GetLastCollision(&info); LTVector vPos, vVel, vCurVel, vP0, vP1; g_pLTServer->GetObjectPos(m_hObject, &vPos); LTRotation rRot; g_pLTServer->GetObjectRotation(m_hObject, &rRot); // Should we break the spear? enum SpearAction { eSpearActionBreak, eSpearActionStickWorld, eSpearActionStickAI, eSpearActionStickPlayer, eSpearActionStickBody }; SpearAction eSpearAction = eSpearActionBreak; // Randomly break even if we could sometimes stick... if (GetRandom(0.0, 1.0f) > g_vtSpearStickPercentage.GetFloat()) { eSpearAction = eSpearActionBreak; } else if (IsMainWorld(hObj)) { // Calculate where we really hit the world... g_pLTServer->GetVelocity(m_hObject, &vVel); vP1 = vPos; vCurVel = vVel * g_pLTServer->GetFrameTime(); vP0 = vP1 - vCurVel; vP1 += vCurVel; LTFLOAT fDot1 = VEC_DOT(info.m_Plane.m_Normal, vP0) - info.m_Plane.m_Dist; LTFLOAT fDot2 = VEC_DOT(info.m_Plane.m_Normal, vP1) - info.m_Plane.m_Dist; if (fDot1 < 0.0f && fDot2 < 0.0f || fDot1 > 0.0f && fDot2 > 0.0f) { vPos = vP1; } else { LTFLOAT fPercent = -fDot1 / (fDot2 - fDot1); VEC_LERP(vPos, vP0, vP1, fPercent); } // Set our new "real" pos... g_pLTServer->SetObjectPos(m_hObject, &vPos); eSpearAction = eSpearActionStickWorld; } else if (IsMoveable(hObj)) { if (IsAI(hObj)) { // Attach to a AI eSpearAction = eSpearActionStickAI; } else if (IsPlayer(hObj)) { // Attach to a Player eSpearAction = eSpearActionStickPlayer; } else if (IsBody(hObj)) { // Attach to a body eSpearAction = eSpearActionStickBody; } else { // Could probably come up with a way to attach to moveable // non-character objects (like doors), but it is much easier // to just break it ;)... eSpearAction = eSpearActionBreak; } } // If the surface is too hard, the spear will just break when // it hits it... SurfaceType eSurf = GetSurfaceType(info); SURFACE* pSurf = g_pSurfaceMgr->GetSurface(eSurf); if ((eSpearActionBreak == eSpearAction) || ((eSpearActionStickWorld == eSpearAction) && pSurf && pSurf->fHardness > 0.5)) { // Create spear debris... DEBRIS* pDebris = g_pDebrisMgr->GetDebris(m_pAmmoData->szName); if (pDebris) { vVel.Norm(); LTVector vNegVel = -vVel; CreatePropDebris(vPos, vNegVel, pDebris->nId); } CProjectile::HandleImpact(hObj); return; } // Create the Spear powerup... char szSpawn[512]; sprintf(szSpawn, "AmmoBox AmmoType1 %s;AmmoCount1 1;Filename %s;Skin %s", m_pAmmoData->szName, m_pAmmoData->pProjectileFX->szModel, m_pAmmoData->pProjectileFX->szSkin); LTVector vScale = m_pAmmoData->pProjectileFX->vModelScale; // Make sure the spear sticks out a little ways... vVel.Norm(); vPos -= (vVel * vScale.z/2.0f); if (eSpearActionStickWorld == eSpearAction) { g_pLTServer->AlignRotation(&rRot, &vVel, LTNULL); } BaseClass* pClass = SpawnObject(szSpawn, LTVector(-10000,-10000,-10000), rRot); if (pClass) { g_pLTServer->ScaleObject(pClass->m_hObject, &vScale); LTVector vDims; g_pLTServer->GetObjectDims(pClass->m_hObject, &vDims); vDims.x *= vScale.x; vDims.y *= vScale.y; vDims.z *= vScale.z; g_pLTServer->SetObjectDims(pClass->m_hObject, &vDims); // We don't want other projectiles to impact on us... //uint32 dwUsrFlags = g_pLTServer->GetObjectUserFlags(pClass->m_hObject); //dwUsrFlags |= USRFLG_IGNORE_PROJECTILES; //g_pLTServer->SetObjectUserFlags(pClass->m_hObject, dwUsrFlags); if ( eSpearActionStickAI == eSpearAction || eSpearActionStickPlayer == eSpearAction ) { g_pLTServer->SetObjectUserFlags(pClass->m_hObject, g_pLTServer->GetObjectUserFlags(pClass->m_hObject) & ~USRFLG_GLOW); g_pLTServer->SetObjectFlags(pClass->m_hObject, g_pLTServer->GetObjectFlags(pClass->m_hObject) & ~FLAG_TOUCH_NOTIFY); if ( eSpearActionStickPlayer == eSpearAction ) { g_pLTServer->SetObjectUserFlags(pClass->m_hObject, g_pLTServer->GetObjectUserFlags(pClass->m_hObject) | USRFLG_ATTACH_HIDE1SHOW3); } // Attach it to the character CCharacter* pCharacter = (CCharacter*)g_pLTServer->HandleToObject(hObj); pCharacter->AddSpear(pClass->m_hObject, pCharacter->GetModelNodeLastHit(), rRot); } else if ( eSpearActionStickBody == eSpearAction ) { g_pLTServer->SetObjectUserFlags(pClass->m_hObject, g_pLTServer->GetObjectUserFlags(pClass->m_hObject) & ~USRFLG_GLOW); g_pLTServer->SetObjectFlags(pClass->m_hObject, g_pLTServer->GetObjectFlags(pClass->m_hObject) & ~FLAG_TOUCH_NOTIFY); // Attach it to the body Body* pBody = (Body*)g_pLTServer->HandleToObject(hObj); pBody->AddSpear(pClass->m_hObject, rRot); } else // ( eSpearActionStickWorld == eSpearAction ) { // Move it to the right position in the world g_pLTServer->SetObjectPos(pClass->m_hObject, &vPos); } } CProjectile::HandleImpact(hObj); }
LTBOOL GroundFilterFn(HOBJECT hObj, void *pUserData) { return ( IsMainWorld(hObj) || (OT_WORLDMODEL == g_pLTClient->GetObjectType(hObj)) ); }