void CClientStreamer::Restream ( bool bMovedFar ) { // Limit distance stream in/out rate // Vehicles might have to ignore this to reduce blocking loads elsewhere. int iMaxOut = 6; int iMaxIn = 6; if ( bMovedFar ) { iMaxOut = 1000; iMaxIn = 1000; } // Do we have any elements waiting to be streamed out? while ( !m_ToStreamOut.empty () ) { CClientStreamElement* pElement = m_ToStreamOut.front (); // Make sure we have no stream-references if ( pElement->GetTotalStreamReferences () == 0 ) { // Stream out 1 of them per frame pElement->InternalStreamOut (); iMaxOut--; } m_ToStreamOut.remove ( pElement ); if ( iMaxOut <= 0 ) break; } static std::vector < CClientStreamElement* > ClosestStreamedOutList; static std::vector < CClientStreamElement* > FurthestStreamedInList; ClosestStreamedOutList.clear(); FurthestStreamedInList.clear(); bool bReachedLimit = ReachedLimit (); // Loop through our active elements list (they should be ordered closest to furthest) list < CClientStreamElement* > ::iterator iter = m_ActiveElements.begin (); for ( ; iter != m_ActiveElements.end (); iter++ ) { CClientStreamElement* pElement = *iter; float fElementDistanceExp = pElement->GetExpDistance (); // Is this element streamed in? if ( pElement->IsStreamedIn () ) { if ( IS_VEHICLE ( pElement ) ) { CClientVehicle* pVehicle = DynamicCast < CClientVehicle > ( pElement ); if ( pVehicle ) { if ( pVehicle->GetOccupant ( ) && IS_PLAYER ( pVehicle->GetOccupant ( ) ) ) { CClientPlayer* pPlayer = DynamicCast < CClientPlayer > ( pVehicle->GetOccupant ( ) ); if ( pPlayer->GetLastPuresyncType ( ) == PURESYNC_TYPE_LIGHTSYNC ) { // if the last packet was ls he shouldn't be streamed in m_ToStreamOut.push_back ( pElement ); } } // Is this a trailer? if ( pVehicle->GetTowedByVehicle ( ) != NULL ) { // Don't stream it out (this is handled by the towing vehicle) continue; } } } if ( IS_PLAYER ( pElement ) ) { CClientPlayer* pPlayer = DynamicCast < CClientPlayer > ( pElement ); if ( pPlayer->GetLastPuresyncType ( ) == PURESYNC_TYPE_LIGHTSYNC ) { // if the last packet was ls he isn't/shouldn't be streamed in m_ToStreamOut.push_back ( pElement ); } } // Too far away? Use the threshold so we won't flicker load it if it's on the border moving. if ( fElementDistanceExp > m_fMaxDistanceThreshold ) { // Unstream it now? if ( iMaxOut > 0 ) { // Make sure we have no stream-references if ( pElement->GetTotalStreamReferences () == 0 ) { // Stream out now pElement->InternalStreamOut (); iMaxOut--; } m_ToStreamOut.remove ( pElement ); } else { // or later m_ToStreamOut.push_back ( pElement ); } } else { FurthestStreamedInList.push_back( pElement ); } } else { // Same dimension as us? if ( pElement->GetDimension () == m_usDimension ) { // Too far away? Stop here. if ( fElementDistanceExp > m_fMaxDistanceExp ) continue; if ( IS_VEHICLE ( pElement ) ) { CClientVehicle* pVehicle = DynamicCast < CClientVehicle > ( pElement ); if ( pVehicle && pVehicle->GetOccupant ( ) && IS_PLAYER ( pVehicle->GetOccupant ( ) )) { CClientPlayer* pPlayer = DynamicCast < CClientPlayer > ( pVehicle->GetOccupant ( ) ); if ( pPlayer->GetLastPuresyncType ( ) == PURESYNC_TYPE_LIGHTSYNC ) { // if the last packet was ls he isn't streaming in soon. continue; } } if ( pVehicle && pVehicle->GetTowedByVehicle ( ) ) { // Streaming in of towed vehicles is done in CClientVehicle::StreamIn by the towing vehicle continue; } } if ( IS_PLAYER ( pElement ) ) { CClientPlayer* pPlayer = DynamicCast < CClientPlayer > ( pElement ); if ( pPlayer->GetLastPuresyncType ( ) == PURESYNC_TYPE_LIGHTSYNC ) { // if the last packet was ls he isn't streaming in soon. continue; } } // If attached and attached-to is streamed out, don't consider for streaming in CClientStreamElement* pAttachedTo = DynamicCast< CClientStreamElement >( pElement->GetAttachedTo() ); if ( pAttachedTo && !pAttachedTo->IsStreamedIn() ) { // ...unless attached to low LOD version CClientObject* pAttachedToObject = DynamicCast < CClientObject > ( pAttachedTo ); CClientObject* pObject = DynamicCast < CClientObject > ( pElement ); if ( !pObject || !pAttachedToObject || pObject->IsLowLod () == pAttachedToObject->IsLowLod () ) continue; } // Not room to stream in more elements? if ( bReachedLimit ) { // Add to the list that might be streamed in during the final phase if ( (int)ClosestStreamedOutList.size() < iMaxIn ) // (only add if there is a chance it will be used) ClosestStreamedOutList.push_back( pElement ); } else { // Stream in the new element. Don't do it instantly unless moved from far away. pElement->InternalStreamIn ( bMovedFar ); bReachedLimit = ReachedLimit (); if ( !bReachedLimit ) { iMaxIn--; if ( iMaxIn <= 0 ) break; } } } } } // Complex code of doom: // ClosestStreamedOutList is {nearest to furthest} list of streamed out elements within streaming distance // FurthestStreamedInList is {nearest to furthest} list of streamed in elements if ( bReachedLimit ) { // Check 'furthest streamed in' against 'closest streamed out' to see if the state can be swapped int iFurthestStreamedInIndex = FurthestStreamedInList.size() - 1; uint uiClosestStreamedOutIndex = 0; for( uint i = 0 ; i < 10 ; i++ ) { // Check limits for this frame if ( iMaxIn <= 0 || iMaxOut <= 0 ) break; // Check indicies are valid if ( iFurthestStreamedInIndex < 0 ) break; if ( uiClosestStreamedOutIndex >= ClosestStreamedOutList.size() ) break; // See if ClosestStreamedOut is nearer than FurthestStreamedIn CClientStreamElement* pFurthestStreamedIn = FurthestStreamedInList[ iFurthestStreamedInIndex ]; CClientStreamElement* pClosestStreamedOut = ClosestStreamedOutList[ uiClosestStreamedOutIndex ]; if ( pClosestStreamedOut->GetExpDistance () >= pFurthestStreamedIn->GetExpDistance () ) break; // Stream out FurthestStreamedIn candidate if possible if ( pFurthestStreamedIn->GetTotalStreamReferences () == 0 ) { // Stream out now pFurthestStreamedIn->InternalStreamOut (); iMaxOut--; } m_ToStreamOut.remove ( pFurthestStreamedIn ); iFurthestStreamedInIndex--; // Always advance to the next candidate // Stream in ClosestStreamedOut candidate if possible if ( !ReachedLimit () ) { // Stream in the new element. No need to do it instantly unless moved from far away. pClosestStreamedOut->InternalStreamIn ( bMovedFar ); iMaxIn--; uiClosestStreamedOutIndex++; } } } }
void CNametags::DrawFromAim() { unsigned long ulCurrentTime = CClientTime::GetTime(); // Got any players that are not local? if (m_pPlayerManager->Count() > 1) { // Grab the local player CClientPlayer* pLocalPlayer = m_pPlayerManager->GetLocalPlayer(); if (pLocalPlayer) { // Grab the current time and the camera unsigned long ulCurrentTime = CClientTime::GetTime(); CCamera* pCamera = g_pGame->GetCamera(); // Grab our controller state CControllerState State; g_pGame->GetPad()->GetCurrentControllerState(&State); // Grab our current weapon slot. Use screen center if melee or none CVector vecStart; CVector vecTarget; eWeaponSlot eSlot = pLocalPlayer->GetCurrentWeaponSlot(); if (eSlot == WEAPONSLOT_TYPE_UNARMED || eSlot == WEAPONSLOT_TYPE_MELEE || eSlot == WEAPONSLOT_TYPE_RIFLE || eSlot == WEAPONSLOT_TYPE_THROWN || eSlot == WEAPONSLOT_TYPE_SPECIAL || eSlot == WEAPONSLOT_TYPE_GIFT || eSlot == WEAPONSLOT_TYPE_PARACHUTE || eSlot == WEAPONSLOT_TYPE_DETONATOR) { // Grab the active cam CCamera* pCamera = g_pGame->GetCamera(); CCam* pActive = pCamera->GetCam(pCamera->GetActiveCam()); // Grab the camera matrix CMatrix matCamera; pCamera->GetMatrix(&matCamera); vecStart = matCamera.vPos; // Range float fRange; eWeaponType eWeapon = pLocalPlayer->GetCurrentWeaponType(); float fSkill = pLocalPlayer->GetStat(g_pGame->GetStats()->GetSkillStatIndex(eWeapon)); CWeaponStat* pWeaponStat = g_pGame->GetWeaponStatManager()->GetWeaponStatsFromSkillLevel(eWeapon, fSkill); if (pWeaponStat) { fRange = pWeaponStat->GetTargetRange(); } else { fRange = MELEE_VISIBLE_RANGE; } // Find the target position CVector vecFront = *pActive->GetFront(); vecFront.Normalize(); vecTarget = *pActive->GetSource() + vecFront * fRange; } else { // Grab the weapon and keysync state. If it exists and he holds Target down CWeapon* pPlayerWeapon = pLocalPlayer->GetWeapon(); if (pPlayerWeapon && State.RightShoulder1) { // Grab the gun muzzle position eWeaponType eWeapon = pLocalPlayer->GetCurrentWeaponType(); float fSkill = pLocalPlayer->GetStat(g_pGame->GetStats()->GetSkillStatIndex(eWeapon)); CWeaponStat* pWeaponStat = g_pGame->GetWeaponStatManager()->GetWeaponStatsFromSkillLevel(eWeapon, fSkill); CVector vecGunMuzzle = *pWeaponStat->GetFireOffset(); pLocalPlayer->GetTransformedBonePosition(BONE_RIGHTWRIST, vecGunMuzzle); // Grab the target point pCamera->Find3rdPersonCamTargetVector(AIM_VISIBLE_RANGE, &vecGunMuzzle, &vecStart, &vecTarget); } else { // Grab the active cam CCam* pActive = pCamera->GetCam(pCamera->GetActiveCam()); // Grab the camera matrix CMatrix matCamera; pCamera->GetMatrix(&matCamera); vecStart = matCamera.vPos; // Find the target position CVector vecFront = *pActive->GetFront(); vecFront.Normalize(); vecTarget = *pActive->GetSource() + vecFront * MELEE_VISIBLE_RANGE; } } // Ignore the local player for this pLocalPlayer->WorldIgnore(true); // Do the raycast CColPoint* pColPoint = NULL; CEntity* pEntity = NULL; SLineOfSightFlags flags; flags.bCheckBuildings = true; flags.bCheckVehicles = true; flags.bCheckPeds = true; flags.bCheckObjects = true; flags.bCheckDummies = true; flags.bSeeThroughStuff = true; flags.bIgnoreSomeObjectsForCamera = false; flags.bShootThroughStuff = true; g_pGame->GetWorld()->ProcessLineOfSight(&vecStart, &vecTarget, &pColPoint, &pEntity, flags); if (pColPoint) pColPoint->Destroy(); // Un-ignore the local player pLocalPlayer->WorldIgnore(false); // Did we find an entity? if (pEntity) { // Grab the CClientEntity belonging to this game_sa entity CClientEntity* pClientEntity = reinterpret_cast<CClientEntity*>(pEntity->GetStoredPointer()); if (pClientEntity) { // Is it a vehicle? Is it a ped? eClientEntityType EntityType = pClientEntity->GetType(); if (EntityType == CCLIENTVEHICLE) { CClientVehicle* pClientVehicle = static_cast<CClientVehicle*>(pClientEntity); // Set the current time as the last draw time for all players inside CClientPed* pPed; int i; for (i = 0; i < 8; i++) { // Grab this seat's occupant and set its last nametag show time to now pPed = pClientVehicle->GetOccupant(i); if (pPed && pPed->GetType() == CCLIENTPLAYER) { static_cast<CClientPlayer*>(pPed)->SetLastNametagShow(ulCurrentTime); } } } else if (EntityType == CCLIENTPLAYER) { // Grab the player this entity is CClientPlayer* pClientPlayer = static_cast<CClientPlayer*>(pClientEntity); if (pClientPlayer) { // Set now as the last time we had the cursor above him pClientPlayer->SetLastNametagShow(ulCurrentTime); } } } } // Grab the local player vehicle CClientVehicle* pLocalVehicle = pLocalPlayer->GetOccupiedVehicle(); // Draw the nametags we need to CClientPlayer* pPlayer; CClientStreamElement* pElement; list<CClientStreamElement*>::const_iterator iter = m_pPlayerStreamer->ActiveElementsBegin(); for (; iter != m_pPlayerStreamer->ActiveElementsEnd(); ++iter) { pElement = *iter; if (!pElement->IsStreamedIn()) continue; if (pElement->GetType() != CCLIENTPLAYER) continue; pPlayer = static_cast<CClientPlayer*>(pElement); if (pPlayer->IsLocalPlayer()) continue; // Is he in the same vehicle as the local player? if (pLocalVehicle && pPlayer->GetOccupiedVehicle() == pLocalVehicle) { pPlayer->SetLastNametagShow(ulCurrentTime); } // Can we show this player's nametag unsigned long ulLastNametagShow = pPlayer->GetLastNametagShow(); if (ulLastNametagShow != 0 && ulCurrentTime <= ulLastNametagShow + NAMETAG_END_FADE_TIME) { unsigned long ulLastNametagShow = pPlayer->GetLastNametagShow(); // Calculate the alpha modifier float fAlphaTimeModifier; if (ulCurrentTime < ulLastNametagShow + NAMETAG_BEGIN_FADE_TIME) { fAlphaTimeModifier = 1.0f; } else { fAlphaTimeModifier = 1.0f - (ulCurrentTime - ulLastNametagShow - NAMETAG_BEGIN_FADE_TIME) / 1000.0f; } // Calculate the alpha for the nametag unsigned char ucAlpha = static_cast<unsigned char>(180.0f * fAlphaTimeModifier); // Draw it DrawTagForPlayer(pPlayer, ucAlpha); } } } } }