예제 #1
0
void CClientLeafSystem::RemoveRenderable( ClientRenderHandle_t handle )
{
	// This can happen upon level shutdown
	if (!m_Renderables.IsValidIndex(handle))
		return;

	// Reset the render handle in the entity.
	IClientRenderable *pRenderable = m_Renderables[handle].m_pRenderable;
	Assert( handle == pRenderable->RenderHandle() );
	pRenderable->RenderHandle() = INVALID_CLIENT_RENDER_HANDLE;

	// Reemove the renderable from the dirty list
	if ( m_Renderables[handle].m_Flags & RENDER_FLAGS_HASCHANGED )
	{
		// NOTE: This isn't particularly fast (linear search),
		// but I'm assuming it's an unusual case where we remove 
		// renderables that are changing or that m_DirtyRenderables usually
		// only has a couple entries
		int i = m_DirtyRenderables.Find( handle );
		Assert( i != m_DirtyRenderables.InvalidIndex() );
		m_DirtyRenderables.FastRemove( i ); 
	}

	if ( IsViewModelRenderGroup( (RenderGroup_t)m_Renderables[handle].m_RenderGroup ) )
	{
		RemoveFromViewModelList( handle );
	}

	RemoveFromTree( handle );
	m_Renderables.Remove( handle );
}
예제 #2
0
static void GoToMarketplaceForOffer()
{
#ifdef _X360
	// Stop installing to the hard drive, otherwise STFC fragmentation hazard, as multiple non sequential HDD writes will occur.
	// This needs to be done before the DLC might be downloaded to the HDD, otherwise it could be fragmented.
	// We restart the installer on DLC download completion. We do not handle the cancel/abort case. The installer
	// will restart through the pre-dlc path, i.e. after attract or exiting a map back to the main menu.
	if ( g_pXboxInstaller )
		g_pXboxInstaller->Stop();

	// See if we need to free some of the queries
	for ( int k = 0; k < g_arrMarketPlaceQueries.Count(); ++ k )
	{
		X360MarketPlaceQuery *pQuery = g_arrMarketPlaceQueries[k];
		if ( XHasOverlappedIoCompleted( &pQuery->xOverlapped ) )
		{
			delete pQuery;
			g_arrMarketPlaceQueries.FastRemove( k -- );
		}
	}

	// Allocate a new query
	X360MarketPlaceQuery *pQuery = new X360MarketPlaceQuery;
	memset( pQuery, 0, sizeof( *pQuery ) );
	pQuery->uiOfferID = g_MarketplaceEntryPoint.uiOfferID;
	g_arrMarketPlaceQueries.AddToTail( pQuery );

	// Open the marketplace entry point
	int iSlot = CBaseModPanel::GetSingleton().GetLastActiveUserId();
	int iCtrlr = XBX_GetUserIsGuest( iSlot ) ? XBX_GetPrimaryUserId() : XBX_GetUserId( iSlot );
	xonline->XShowMarketplaceDownloadItemsUI( iCtrlr,
		g_MarketplaceEntryPoint.dwEntryPoint, &pQuery->uiOfferID, 1,
		&pQuery->hResult, &pQuery->xOverlapped );
#endif
}
예제 #3
0
//-----------------------------------------------------------------------------
// Makes sure all entries in the KD tree are in the correct position
//-----------------------------------------------------------------------------
void CDirtySpatialPartitionEntityList::OnPreQuery( SpatialPartitionListMask_t listMask )
{
#ifdef CLIENT_DLL
	if ( !( listMask & PARTITION_CLIENT_GAME_EDICTS ) )
		return;

	// FIXME: This should really be an assertion... feh!
	if ( !C_BaseEntity::IsAbsRecomputationsEnabled() )
	{
		m_mutex.Lock();
		return;
	}

#else
	if ( !( listMask & PARTITION_SERVER_GAME_EDICTS ) )
		return;
#endif

	m_mutex.Lock();

	CUtlVector< CBaseHandle > vecStillDirty;

	int nDirtyEntityCount = m_DirtyEntities.Count();
	while ( nDirtyEntityCount > 0 )
	{
		CBaseHandle handle;
		handle = m_DirtyEntities[nDirtyEntityCount-1];

#ifndef CLIENT_DLL
		CBaseEntity *pEntity = gEntList.GetBaseEntity( handle );
#else
		CBaseEntity *pEntity = cl_entitylist->GetBaseEntityFromHandle( handle );
#endif
		
		m_DirtyEntities.FastRemove( nDirtyEntityCount-1 );

		if ( pEntity )
		{
			// If an entity is in the middle of bone setup, don't call UpdatePartition
			//  which can cause it to redo bone setup on the same frame causing a recursive
			//  call to bone setup.
			if ( !pEntity->IsEFlagSet( EFL_SETTING_UP_BONES ) )
			{
				pEntity->CollisionProp()->UpdatePartition();
			}
			else
			{
				vecStillDirty.AddToTail( handle );
			}
		}

		nDirtyEntityCount = m_DirtyEntities.Count();
	}

	if ( vecStillDirty.Count() > 0 )
	{
		m_DirtyEntities = vecStillDirty;
	}
}
void CSecobModportal1List::RemoveFromList( CNPC_SecobModportal1 *pSecobModportal1 )
{
	int index = m_list.Find( pSecobModportal1 );
	if ( index != m_list.InvalidIndex() )
	{
		m_list.FastRemove( index );
	}
}
예제 #5
0
void CBullseyeList::RemoveFromList( CNPC_Bullseye *pBullseye )
{
	int index = m_list.Find( pBullseye );
	if ( index != m_list.InvalidIndex() )
	{
		m_list.FastRemove( index );
	}
}
예제 #6
0
CModelLookupContext::~CModelLookupContext()
{
	if ( m_lookupIndex >= 0 )
	{
		Assert(m_lookupIndex == (g_ModelLookup.Count()-1));
		g_ModelLookup.FastRemove(m_lookupIndex);
		g_ModelLookupIndex = g_ModelLookup.Count()-1;
	}
}
예제 #7
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CCollisionEvent::UpdateFluidEvents( void )
{
	for ( int i = m_fluidEvents.Count()-1; i >= 0; --i )
	{
		if ( (gpGlobals->curtime - m_fluidEvents[i].impactTime) > FLUID_TIME_MAX )
		{
			m_fluidEvents.FastRemove(i);
		}
	}
}
예제 #8
0
// Remove noitfication for an entity
void CNotifyList::RemoveEntity( CBaseEntity *pNotify, CBaseEntity *pWatched )
{
	for ( int i = m_notifyList.Count(); --i >= 0; )
	{
		if ( m_notifyList[i].pNotify == pNotify && m_notifyList[i].pWatched == pWatched)
		{
			m_notifyList.FastRemove(i);
		}
	}
}
예제 #9
0
// UNDONE: Slow linear search?
void CNotifyList::ClearEntity( CBaseEntity *pNotify )
{
	for ( int i = m_notifyList.Count(); --i >= 0; )
	{
		if ( m_notifyList[i].pNotify == pNotify || m_notifyList[i].pWatched == pNotify)
		{
			m_notifyList.FastRemove(i);
		}
	}
}
void CAI_FollowManager::RemoveGroup( AI_FollowGroup_t *pGroup )
{
	for ( int i = 0; i < m_groups.Count(); i++ )
	{
		if ( m_groups[i] == pGroup )
		{
			delete m_groups[i];
			m_groups.FastRemove(i);
			return;
		}
	}
}
예제 #11
0
// NOTE: This assumes entity pointers are sorted to simplify search!
void CCollisionEvent::UpdatePenetrateEvents()
{
	const float MAX_PENETRATION_TIME = 3.0f;

	for ( int i = m_penetrateEvents.Count()-1; i >= 0; --i )
	{
		float timeSincePenetration = gpGlobals->curtime - m_penetrateEvents[i].timeStamp;
		if ( timeSincePenetration > 0.1f )
		{
			m_penetrateEvents.FastRemove(i);
			continue;
		}
		float timeInPenetration = m_penetrateEvents[i].timeStamp - m_penetrateEvents[i].startTime;
		// it's been too long, just give up and disable collisions
		if ( timeInPenetration > MAX_PENETRATION_TIME )
		{
			PhysDisableEntityCollisions( m_penetrateEvents[i].pEntity0, m_penetrateEvents[i].pEntity1 );
			m_penetrateEvents.FastRemove(i);
			continue;
		}
	}
}
// this samples the lighting at each sample and removes any unnecessary samples
void CompressAmbientSampleList( CUtlVector<ambientsample_t> &list )
{
	Vector testCube[6];
	for ( int i = 0; i < list.Count(); i++ )
	{
		if ( list.Count() > 1 )
		{
			Mod_LeafAmbientColorAtPos( testCube, list[i].pos, list, i );
			if ( CubeDeltaGammaSpace(testCube, list[i].cube) < 3 )
			{
				list.FastRemove(i);
				i--;
			}
		}
	}
}
예제 #13
0
파일: ragdoll.cpp 프로젝트: BoXorz/MSS
    void Update()
    {
        if ( tickCount > gpGlobals->tickcount )
        {
            list.RemoveAll();
            return;
        }

        for ( int i = list.Count()-1; i >= 0; --i )
        {
            if ( list[i].tickCount != gpGlobals->tickcount )
            {
                list.FastRemove(i);
            }
        }
    }
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
bool CDarknessLightSourcesSystem::AreThereLightSourcesWithinRadius( CBaseEntity *pLooker, float flRadius )
{
	float flRadiusSqr = (flRadius * flRadius);
	for ( int i = m_LightSources.Count() - 1; i >= 0; i-- )
	{
		// Removed?
		if ( m_LightSources[i].hEntity == NULL || m_LightSources[i].hEntity->IsMarkedForDeletion() )
		{
			m_LightSources.FastRemove( i );
			continue;
		}

		CBaseEntity *pLightSource = m_LightSources[i].hEntity;

		// Close enough to a light source?
		float flDistanceSqr = (pLooker->WorldSpaceCenter() - pLightSource->GetAbsOrigin()).LengthSqr();
		if ( flDistanceSqr < flRadiusSqr )
		{
			trace_t tr;
			AI_TraceLine( pLooker->EyePosition(), pLightSource->GetAbsOrigin(), MASK_SOLID_BRUSHONLY, pLooker, COLLISION_GROUP_NONE, &tr );

			if ( g_debug_darkness.GetBool() )
			{
				if (tr.fraction != 1.0)
				{
					NDebugOverlay::Line( pLooker->WorldSpaceCenter(), tr.endpos, 255,0,0,true, 0.1);
				}
				else
				{
					NDebugOverlay::Line( pLooker->WorldSpaceCenter(), tr.endpos, 0,255,0,true, 0.1);
					NDebugOverlay::Line( pLightSource->GetAbsOrigin(), tr.endpos, 255,0,0,true, 0.1);
				}
			}

			if ( tr.fraction == 1.0 )
				return true;
		}
	}

	return false;
}
예제 #15
0
void CTilegenAction_FilterCandidatesByDirection::Execute( CLayoutSystem *pLayoutSystem )
{
	CUtlVector< CRoomCandidate > *pRoomCandidateList = pLayoutSystem->GetRoomCandidateList();
	if ( pRoomCandidateList->Count() == 0 )
	{
		return;
	}

	const char *pDirection = m_pDirectionExpression->Evaluate( pLayoutSystem->GetFreeVariables() );
	int nThreshold = m_pThresholdExpression->Evaluate( pLayoutSystem->GetFreeVariables() );
	nThreshold = MAX( 0, nThreshold );
	ExitDirection_t direction = GetDirectionFromString( pDirection );
	if ( direction < EXITDIR_BEGIN || direction >= EXITDIR_END )
	{
		Log_Warning( LOG_TilegenLayoutSystem, "Invalid direction specified: %s.\n", pDirection );
		return;
	}

	// First go through and figure out the highest score
	int nHighScore = INT_MIN;
	for ( int i = 0; i < pRoomCandidateList->Count(); ++ i )
	{
		const CRoomCandidate *pCandidate = &pRoomCandidateList->Element( i );
		int nScore = ComputeScore( direction, pCandidate->m_iXPos, pCandidate->m_iYPos );
		if ( nScore > nHighScore )
		{
			nHighScore = nScore;
		}
	}

	// Now go through and set the chance of each candidate to 1.0f for any with that score or 0.0f for those with a lower score
	// @TODO: allow for specifying a numerical range in which candidates are chosen
	for ( int i = pRoomCandidateList->Count() - 1; i >= 0; -- i )
	{
		const CRoomCandidate *pCandidate = &pRoomCandidateList->Element( i );
		if ( ComputeScore( direction, pCandidate->m_iXPos, pCandidate->m_iYPos ) < ( nHighScore - nThreshold ) )
		{
			pRoomCandidateList->FastRemove( i );
		}
	}
}
예제 #16
0
//-----------------------------------------------------------------------------
// Purpose: Update the active sounds, dequeue any events and move the ramps
//-----------------------------------------------------------------------------
void CSoundControllerImp::SystemUpdate( void )
{
	float time = g_pEffects->Time();
	float deltaTime = time - m_flLastTime;
	
	// handle clock resets
	if ( deltaTime < 0 )
		deltaTime = 0;

	m_flLastTime = time;

	while ( m_commandList.Count() )
	{
		SoundCommand_t *pCmd = m_commandList.ElementAtHead();
		// Commands are sorted by time.
		// process any that should occur by the current time
		if ( time >= pCmd->m_time )
		{
			m_commandList.RemoveAtHead();
			ProcessCommand( pCmd );
			delete pCmd;
		}
		else
		{
			break;
		}
	}

	// NOTE: Because this loop goes from the end to the beginning
	// we can fast remove inside it without breaking the indexing
	for ( int i = m_soundList.Count()-1; i >=0; i-- )
	{
		CSoundPatch *pNode = m_soundList[i];
		if ( !pNode->Update( time, deltaTime ) )
		{
			pNode->Reset();
			m_soundList.FastRemove( i );
		}
	}
}
예제 #17
0
//-----------------------------------------------------------------------------
// Purpose: Called by the sound system whenever a sound is played so that
//			active microphones can have a chance to pick up the sound.
// Output : Returns whether or not the sound was swallowed by the microphone.
//			Swallowed sounds should not be played by the sound system.
//-----------------------------------------------------------------------------
bool CEnvMicrophone::OnSoundPlayed( int entindex, const char *soundname, soundlevel_t soundlevel, float flVolume, int iFlags, int iPitch, const Vector *pOrigin, float soundtime, CUtlVector< Vector >& soundorigins )
{
	bool bSwallowed = false;

	// Loop through all registered microphones and tell them the sound was just played
	int iCount = s_Microphones.Count();
	if ( iCount > 0 )
	{
		// Iterate backwards because we might be deleting microphones.
		for ( int i = iCount - 1; i >= 0; i-- )
		{
			if ( s_Microphones[i] )
			{
				MicrophoneResult_t eResult = s_Microphones[i]->SoundPlayed(
					entindex, 
					soundname, 
					soundlevel, 
					flVolume, 
					iFlags, 
					iPitch, 
					pOrigin, 
					soundtime,
					soundorigins );

				if ( eResult == MicrophoneResult_Swallow )
				{
					// Microphone told us to swallow it
					bSwallowed = true;
				}
				else if ( eResult == MicrophoneResult_Remove )
				{
					s_Microphones.FastRemove( i );
				}
			}
		}
	}

	return bSwallowed;
}
예제 #18
0
void CGlobalEntityList::OnRemoveEntity( IHandleEntity *pEnt, CBaseHandle handle )
{
#ifdef DEBUG
	if ( !g_fInCleanupDelete )
	{
		int i;
		for ( i = 0; i < g_DeleteList.Count(); i++ )
		{
			if ( g_DeleteList[i]->GetEntityHandle() == pEnt )
			{
				g_DeleteList.FastRemove( i );
				Msg( "ERROR: Entity being destroyed but previously threaded on g_DeleteList\n" );
				break;
			}
		}
	}
#endif

	CBaseEntity *pBaseEnt = static_cast<IServerUnknown*>(pEnt)->GetBaseEntity();
	if ( pBaseEnt->edict() )
		m_iNumEdicts--;

	m_iNumEnts--;
}
예제 #19
0
void CTilegenAction_FilterCandidatesForLinearGrowth::Execute( CLayoutSystem *pLayoutSystem )
{
	CUtlVector< CRoomCandidate > *pRoomCandidateList = pLayoutSystem->GetRoomCandidateList();
	if ( pRoomCandidateList->Count() == 0 )
	{
		return;
	}

	int nThreshold = m_pThresholdExpression->Evaluate( pLayoutSystem->GetFreeVariables() );
	if ( nThreshold < 0 ) nThreshold = INT_MAX;
	
	// First go through and find the most recently placed source room.
	int nHighestPlacementIndex = -1;
	for ( int i = 0; i < pRoomCandidateList->Count(); ++ i )
	{
		const CRoomCandidate *pCandidate = &pRoomCandidateList->Element( i );
		const CRoom *pSourceRoom = pCandidate->m_pExit->pSourceRoom;
		if ( pSourceRoom->m_nPlacementIndex > nHighestPlacementIndex )
		{
			nHighestPlacementIndex = pSourceRoom->m_nPlacementIndex;
		}
	}

	CMapLayout *pMapLayout = pLayoutSystem->GetMapLayout();
	int nMinimumPlacementIndex = pMapLayout->m_PlacedRooms.Count() - 1 - nThreshold;

	// Now go through and remove any candidates not within the threshold of the most recently placed source room.
	for ( int i = pRoomCandidateList->Count() - 1; i >= 0; -- i )
	{
		const CRoomCandidate *pCandidate = &pRoomCandidateList->Element( i );
		if ( pCandidate->m_pExit->pSourceRoom->m_nPlacementIndex < nHighestPlacementIndex || pCandidate->m_pExit->pSourceRoom->m_nPlacementIndex < nMinimumPlacementIndex )
		{
			pRoomCandidateList->FastRemove( i );
		}
	}
}
예제 #20
0
void CTilegenAction_AddConnectorRoomCandidates::Execute( CLayoutSystem *pLayoutSystem )
{
	CUtlVector< const CRoomTemplate * > roomTemplateList;
	if ( m_pTargetRoomTemplate != NULL )
	{
		Assert( m_pTargetRoomTemplateFilter == NULL && m_pTargetThemeNameExpression == NULL );
		roomTemplateList.AddToTail( m_pTargetRoomTemplate );
	}
	else
	{
		Assert( m_pTargetRoomTemplateFilter != NULL	&& m_pTargetThemeNameExpression != NULL );

		if ( m_pLevelTheme == NULL )
		{
			const char *pThemeName = m_pTargetThemeNameExpression->Evaluate( pLayoutSystem->GetFreeVariables() );
			m_pLevelTheme = CLevelTheme::FindTheme( pThemeName );
			if ( m_pLevelTheme == NULL )
			{
				Log_Warning( LOG_TilegenLayoutSystem, "Theme %s not found.\n", pThemeName );
				pLayoutSystem->OnError();
				return;
			}
		}

		BuildRoomTemplateList( pLayoutSystem, m_pLevelTheme, m_pTargetRoomTemplateFilter, true, &roomTemplateList );
	}

	// Build a list of exit types we're looking for
	CUtlVector< CExit > desiredMatchingExits;
	for ( int i = 0; i < roomTemplateList.Count(); ++ i )
	{
		const CRoomTemplate *pTemplate = roomTemplateList[i];
		for ( int j = 0; j < pTemplate->m_Exits.Count(); ++ j )
		{
			desiredMatchingExits.AddToTail( CExit( 
				0, 0, CRoomTemplateExit::GetOppositeDirection( pTemplate->m_Exits[j]->m_ExitDirection ), 
				pTemplate->m_Exits[j]->m_szExitTag, NULL, false ) );
		}
	}

	// Build up a room of connector candidates
	pLayoutSystem->ExecuteAction( m_pAddConnectorCandidates, NULL );

	// Filter the set down by eliminating candidates which don't connect to the desired direction.
	CUtlVector< CRoomCandidate > *pRoomCandidateList = pLayoutSystem->GetRoomCandidateList();
	CUtlVector< CExit > newOpenExits;
	for ( int i = pRoomCandidateList->Count() - 1; i >= 0; -- i )
	{
		bool bMatch = false;
		newOpenExits.RemoveAll();

		// Figure out which new exits would be open as a result of placing this room candidate.
		BuildOpenExitList( pRoomCandidateList->Element( i ), pLayoutSystem->GetMapLayout(), &newOpenExits );

		// For every new open exit potentially created by this candidate,
		// see if one of them could connect to one of our desired exits.
		for ( int j = 0; j < newOpenExits.Count(); ++ j )
		{
			const CExit *pNewOpenExit = &newOpenExits[j];
			for ( int k = 0; k < desiredMatchingExits.Count(); ++ k )
			{
				const CExit *pDesiredMatchingExit = &desiredMatchingExits[k];
				if ( pNewOpenExit->ExitDirection == pDesiredMatchingExit->ExitDirection && 
					 Q_stricmp( pNewOpenExit->m_szExitTag, pDesiredMatchingExit->m_szExitTag ) == 0 )
				{
					// Found a match!
					bMatch = true;
					break;
				}
			}
			if ( bMatch ) break;
		}

		if ( !bMatch )
		{
			pRoomCandidateList->FastRemove( i );
		}
	}
}
// add the sample to the list.  If we exceed the maximum number of samples, the worst sample will
// be discarded.  This has the effect of converging on the best samples when enough are added.
void AddSampleToList( CUtlVector<ambientsample_t> &list, const Vector &samplePosition, Vector *pCube )
{
	const int MAX_SAMPLES = 16;

	int index = list.AddToTail();
	list[index].pos = samplePosition;
	for ( int i = 0; i < 6; i++ )
	{
		list[index].cube[i] = pCube[i];
	}

	if ( list.Count() <= MAX_SAMPLES )
		return;

	int nearestNeighborIndex = 0;
	float nearestNeighborDist = FLT_MAX;
	float nearestNeighborTotal = 0;
	for ( int i = 0; i < list.Count(); i++ )
	{
		int closestIndex = 0;
		float closestDist = FLT_MAX;
		float totalDC = 0;
		for ( int j = 0; j < list.Count(); j++ )
		{
			if ( j == i )
				continue;
			float dist = (list[i].pos - list[j].pos).Length();
			float maxDC = 0;
			for ( int k = 0; k < 6; k++ )
			{
				// color delta is computed per-component, per cube side
				for (int s = 0; s < 3; s++ )
				{
					float dc = fabs(list[i].cube[k][s] - list[j].cube[k][s]);
					maxDC = max(maxDC,dc);
				}
				totalDC += maxDC;
			}
			// need a measurable difference in color or we'll just rely on position
			if ( maxDC < 1e-4f )
			{
				maxDC = 0;
			}
			else if ( maxDC > 1.0f )
			{
				maxDC = 1.0f;
			}
			// selection criteria is 10% distance, 90% color difference
			// choose samples that fill the space (large distance from each other)
			// and have largest color variation
			float distanceFactor = 0.1f + (maxDC * 0.9f);
			dist *= distanceFactor;

			// find the "closest" sample to this one
			if ( dist < closestDist )
			{
				closestDist = dist;
				closestIndex = j;
			}
		}
		// the sample with the "closest" neighbor is rejected
		if ( closestDist < nearestNeighborDist || (closestDist == nearestNeighborDist && totalDC < nearestNeighborTotal) )
		{
			nearestNeighborDist = closestDist;
			nearestNeighborIndex = i;
		}
	}
	list.FastRemove( nearestNeighborIndex );
}
예제 #22
0
void CClientLeafSystem::RemoveFromViewModelList( ClientRenderHandle_t handle )
{
	int i = m_ViewModels.Find( handle );
	Assert( i != m_ViewModels.InvalidIndex() );
	m_ViewModels.FastRemove( i );
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
bool CDarknessLightSourcesSystem::IsEntityVisibleToTarget( CBaseEntity *pLooker, CBaseEntity *pTarget )
{
	if ( pTarget->IsEffectActive( EF_BRIGHTLIGHT ) || pTarget->IsEffectActive( EF_DIMLIGHT ) )
		return true;

	bool bDebug = g_debug_darkness.GetBool();
	if ( bDebug && pLooker )
	{
		bDebug = (pLooker->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) != 0;
	}

	trace_t tr;

	// Loop through all the light sources. Do it backwards, so we can remove dead ones.
	for ( int i = m_LightSources.Count() - 1; i >= 0; i-- )
	{
		// Removed?
		if ( m_LightSources[i].hEntity == NULL || m_LightSources[i].hEntity->IsMarkedForDeletion() )
		{
			m_LightSources.FastRemove( i );
			continue;
		}

		CInfoDarknessLightSource *pLightSource = m_LightSources[i].hEntity;

		// Close enough to a light source?
		float flDistanceSqr = (pTarget->WorldSpaceCenter() - pLightSource->GetAbsOrigin()).LengthSqr();
		if ( flDistanceSqr < m_LightSources[i].flLightRadiusSqr )
		{
			if ( pLightSource->ShouldIgnoreLOS() )
			{
				if ( bDebug )
				{
					NDebugOverlay::Line( pTarget->WorldSpaceCenter(), pLightSource->GetAbsOrigin(), 0,255,0,true, 0.1);
				}
				return true;
			}

			// Check LOS from the light to the target
			CTraceFilterSkipTwoEntities filter( pTarget, pLooker, COLLISION_GROUP_NONE );
			AI_TraceLine( pTarget->WorldSpaceCenter(), pLightSource->GetAbsOrigin(), MASK_OPAQUE, &filter, &tr );
			if ( tr.fraction == 1.0 )
			{
				if ( bDebug )
				{
					NDebugOverlay::Line( tr.startpos, tr.endpos, 0,255,0,true, 0.1);
				}
				return true;
			}

			if ( bDebug )
			{
				NDebugOverlay::Line( tr.startpos, tr.endpos, 255,0,0,true, 0.1);
				NDebugOverlay::Line( tr.endpos, pLightSource->GetAbsOrigin(), 128,0,0,true, 0.1);
			}

			// If the target is within the radius of the light, don't do sillhouette checks
			continue;
		}

 		if ( !pLooker )
			continue;

		// Between a light source and the looker?
		Vector vecLookerToLight = (pLightSource->GetAbsOrigin() - pLooker->WorldSpaceCenter());
		Vector vecLookerToTarget = (pTarget->WorldSpaceCenter() - pLooker->WorldSpaceCenter());
		float flDistToSource = VectorNormalize( vecLookerToLight );
		float flDistToTarget = VectorNormalize( vecLookerToTarget );
 		float flDot = DotProduct( vecLookerToLight, vecLookerToTarget );
		if ( flDot > 0 )
		{
			// Make sure the target is in front of the lightsource
			if ( flDistToTarget < flDistToSource )
			{
				if ( bDebug )
				{
					NDebugOverlay::Line( pLooker->WorldSpaceCenter(), pLooker->WorldSpaceCenter() + (vecLookerToLight * 128), 255,255,255,true, 0.1);
					NDebugOverlay::Line( pLooker->WorldSpaceCenter(), pLooker->WorldSpaceCenter() + (vecLookerToTarget * 128), 255,0,0,true, 0.1);
				}

				// Now, we need to find out if the light source is obscured by anything. 
				// To do this, we want to calculate the point of intersection between the light source 
				// sphere and the line from the looker through the target. 
 				float flASqr = (flDistToSource * flDistToSource);
				float flB = -2 * flDistToSource * flDot;
				float flCSqr = m_LightSources[i].flLightRadiusSqr;
				float flDesc = (flB * flB) - (4 * (flASqr - flCSqr));
				if ( flDesc >= 0 )
				{
 					float flLength = (-flB - sqrt(flDesc)) / 2;
  					Vector vecSpherePoint = pLooker->WorldSpaceCenter() + (vecLookerToTarget * flLength);

					// We've got the point of intersection. See if we can see it.
					CTraceFilterSkipTwoEntities filter( pTarget, pLooker, COLLISION_GROUP_NONE );
					AI_TraceLine( pLooker->EyePosition(), vecSpherePoint, MASK_SOLID_BRUSHONLY, &filter, &tr );

					if ( bDebug )
					{
						if (tr.fraction != 1.0)
						{
							NDebugOverlay::Line( pLooker->WorldSpaceCenter(), vecSpherePoint, 255,0,0,true, 0.1);
						}
						else
						{
							NDebugOverlay::Line( pLooker->WorldSpaceCenter(), vecSpherePoint, 0,255,0,true, 0.1);
							NDebugOverlay::Line( pLightSource->GetAbsOrigin(), vecSpherePoint, 255,0,0,true, 0.1);
						}
					}

					if ( tr.fraction == 1.0 )
						return true;
				}
			}
		}
	}

	return false;
}
예제 #24
0
//-----------------------------------------------------------------------------
// Purpose: Apply noise to the eye position.
// UNDONE: Feedback a bit of this into the view model position.  It shakes too much
//-----------------------------------------------------------------------------
void CViewEffects::CalcShake( void )
{
	float	fraction, freq;

	// We'll accumulate the aggregate shake for this frame into these data members.
	m_vecShakeAppliedOffset.Init(0, 0, 0);
	m_flShakeAppliedAngle = 0;
	float flRumbleAngle = 0;

	bool bShow = shake_show.GetBool();

	int nShakeCount = m_ShakeList.Count();

	for ( int nShake = nShakeCount - 1; nShake >= 0; nShake-- )
	{
		screenshake_t *pShake = m_ShakeList.Element( nShake );

		if ( pShake->endtime == 0 )
		{
			// Shouldn't be any such shakes in the list.
			Assert( false );
			continue;
		}

		if ( ( gpGlobals->curtime > pShake->endtime ) || 
			pShake->duration <= 0 || 
			pShake->amplitude <= 0 || 
			pShake->frequency <= 0 )
		{
			// Retire this shake.
			delete m_ShakeList.Element( nShake );
			m_ShakeList.FastRemove( nShake );
			continue;
		}

		if ( bShow )
		{
			con_nprint_t np;
			np.time_to_live = 2.0f;
			np.fixed_width_font = true;
			np.color[0] = 1.0;
			np.color[1] = 0.8;
			np.color[2] = 0.1;
			np.index = nShake + 2;

			engine->Con_NXPrintf( &np, "%02d: dur(%8.2f) amp(%8.2f) freq(%8.2f)", nShake + 1, (double)pShake->duration, (double)pShake->amplitude, (double)pShake->frequency );
		}

		if ( gpGlobals->curtime > pShake->nextShake )
		{
			// Higher frequency means we recalc the extents more often and perturb the display again
			pShake->nextShake = gpGlobals->curtime + (1.0f / pShake->frequency);

			// Compute random shake extents (the shake will settle down from this)
			for (int i = 0; i < 3; i++ )
			{
				pShake->offset[i] = random->RandomFloat( -pShake->amplitude, pShake->amplitude );
			}

			pShake->angle = random->RandomFloat( -pShake->amplitude*0.25, pShake->amplitude*0.25 );
		}

		// Ramp down amplitude over duration (fraction goes from 1 to 0 linearly with slope 1/duration)
		fraction = ( pShake->endtime - gpGlobals->curtime ) / pShake->duration;

		// Ramp up frequency over duration
		if ( fraction )
		{
			freq = (pShake->frequency / fraction);
		}
		else
		{
			freq = 0;
		}

		// square fraction to approach zero more quickly
		fraction *= fraction;

		// Sine wave that slowly settles to zero
		float angle = gpGlobals->curtime * freq;
		if ( angle > 1e8 )
		{
			angle = 1e8;
		}
		fraction = fraction * sin( angle );
		
		if( pShake->command != SHAKE_START_NORUMBLE )
		{
			// As long as this isn't a NO RUMBLE effect, then accumulate rumble
			flRumbleAngle += pShake->angle * fraction;
		}

		if( pShake->command != SHAKE_START_RUMBLEONLY )
		{
			// As long as this isn't a RUMBLE ONLY effect, then accumulate screen shake
			
			// Add to view origin
			m_vecShakeAppliedOffset += pShake->offset * fraction;

			// Add to roll
			m_flShakeAppliedAngle += pShake->angle * fraction;
		}

		// Drop amplitude a bit, less for higher frequency shakes
		pShake->amplitude -= pShake->amplitude * ( gpGlobals->frametime / (pShake->duration * pShake->frequency) );
	}

	// Feed this to the rumble system!
	UpdateScreenShakeRumble( flRumbleAngle );
}
void CGEObjectives::OnThink( void )
{
	if ( m_flNextThink > gpGlobals->curtime )
		return;

	// If we aren't drawing, don't think
	CBasePlayer *pLocalPlayer = CBasePlayer::GetLocalPlayer();
	if ( !ShouldDraw() || !pLocalPlayer )
	{
		ThinkAdvance( 0.5f );
		return;
	}

	// Clear our validity flags
	for ( int i=0; i < m_vObjectives.Count(); i++ )
		m_vObjectives[i]->valid = false;

	int plr_serial = pLocalPlayer->GetRefEHandle().ToInt();
	vgui::HFont text_font = scheme()->GetIScheme( GetScheme() )->GetFont("GETargetID", true);

	// Go through our Radar Resource to get any new entities / updates to existing ones
	for( int i=0; i < MAX_NET_RADAR_ENTS; ++i )
	{
		if ( !g_RR->IsObjective(i) || g_RR->GetState(i) != RADAR_STATE_DRAW )
			continue;

		int team = g_RR->GetObjectiveTeam(i);
		int serial = g_RR->GetEntSerial(i);
		const char *tkn = g_RR->GetObjectiveToken(i);
		bool tkn_held = true;
		if ( tkn[0] == '!' )
		{
			tkn++;
			tkn_held = false;
		}

		if ( serial != plr_serial
			&& (team == TEAM_UNASSIGNED || team == pLocalPlayer->GetTeamNumber())
			&& (!tkn[0] || (pLocalPlayer->Weapon_OwnsThisType(tkn) != NULL) == tkn_held)
			&& (!pLocalPlayer->GetObserverTarget() || pLocalPlayer->GetObserverTarget()->GetRefEHandle().ToInt() != serial))
		{
			GEObjective *obj = FindObjective( serial );
			if ( !obj )
			{
				// New objective! Initialize us
				obj = new GEObjective;
				obj->hEnt = EHANDLE::FromIndex( serial );
				obj->curr_pos = g_RR->GetOrigin(i);
				obj->pulse_mod = 0;
				obj->refText[0] = '\0';
				obj->text[0] = L'\0';
				m_vObjectives.AddToTail( obj );
			}
			
			// Ensure text is the same
			if ( Q_strcmp( obj->refText, g_RR->GetObjectiveText(i) ) )
			{
				Q_strncpy( obj->refText, g_RR->GetObjectiveText(i), 32 );
				GEUTIL_ParseLocalization( obj->text, 16, g_RR->GetObjectiveText(i) );
				GEUTIL_GetTextSize( obj->text, text_font, obj->txtW, obj->txtH );
			}
			
			obj->last_pos = obj->curr_pos;
			obj->curr_pos = g_RR->GetOrigin(i);
			obj->min_dist = max( g_RR->GetObjectiveMinDist(i), OBJ_ABS_MIN_DIST );
			obj->update_time = gpGlobals->curtime;
			obj->pulse = g_RR->GetObjectivePulse(i);
			obj->color = g_RR->GetObjectiveColor(i);
			obj->valid = true;
		}
	}

	// Delete defunct objectives
	for ( int i=0; i < m_vObjectives.Count(); i++ )
	{
		if ( !m_vObjectives[i]->valid )
		{
			GEObjective *obj = m_vObjectives[i];
			m_vObjectives.FastRemove(i);
			delete obj;
		}
	}

	ThinkAdvance( RADAR_THINK_INT * 0.75f );
}
예제 #26
0
//---------------------------------------------------------
// Count of all the weapons in the world of my type and
// see if we have a surplus. If there is a surplus, try
// to find suitable candidates for removal.
//
// Right now we just remove the first weapons we find that
// are behind the player, or are out of the player's PVS. 
// Later, we may want to score the results so that we
// removed the farthest gun that's not in the player's 
// viewcone, etc.
//
// Some notes and thoughts:
//
// This code is designed NOT to remove weapons that are 
// hand-placed by level designers. It should only clean
// up weapons dropped by dead NPCs, which is useful in
// situations where enemies are spawned in for a sustained
// period of time.
//
// Right now we PREFER to remove weapons that are not in the
// player's PVS, but this could be opposite of what we 
// really want. We may only want to conduct the cleanup on
// weapons that are IN the player's PVS.
//---------------------------------------------------------
void CGameWeaponManager::Think()
{
	int i;

	// Don't have to think all that often. 
	SetNextThink( gpGlobals->curtime + 2.0 );

	const char *pszWeaponName = STRING( m_iszWeaponName );

	CUtlVector<CBaseEntity *> candidates( 0, 64 );

	if ( m_bExpectingWeapon )
	{
		CBaseCombatWeapon *pWeapon = NULL;
		// Firstly, count the total number of weapons of this type in the world.
		// Also count how many of those can potentially be removed.
		pWeapon = assert_cast<CBaseCombatWeapon *>(gEntList.FindEntityByClassname( pWeapon, pszWeaponName ));

		while( pWeapon )
		{
			if( !pWeapon->IsEffectActive( EF_NODRAW ) && pWeapon->IsRemoveable() )
			{
				candidates.AddToTail( pWeapon );
			}

			pWeapon = assert_cast<CBaseCombatWeapon *>(gEntList.FindEntityByClassname( pWeapon, pszWeaponName ));
		}
	}
	else
	{
		for ( i = 0; i < m_ManagedNonWeapons.Count(); i++)
		{
			CBaseEntity *pEntity = m_ManagedNonWeapons[i];
			if ( pEntity )
			{
				Assert( pEntity->m_iClassname == m_iszWeaponName );
				if ( !pEntity->IsEffectActive( EF_NODRAW ) )
				{
					candidates.AddToTail( pEntity );
				}
			}
			else
			{
				m_ManagedNonWeapons.FastRemove( i-- );
			}
		}
	}

	// Calculate the surplus.
	int surplus = candidates.Count() - m_iMaxPieces;

	// Based on what the player can see, try to clean up the world by removing weapons that
	// the player cannot see right at the moment.
	CBaseEntity *pCandidate;
	for ( i = 0; i < candidates.Count() && surplus > 0; i++ )
	{
		bool fRemovedOne = false;

		pCandidate = candidates[i];
		Assert( !pCandidate->IsEffectActive( EF_NODRAW ) );

//		if ( gpGlobals->maxClients == 1 )
		{
			CBasePlayer *pPlayer = UTIL_GetNearestVisiblePlayer(pCandidate);
			// Nodraw serves as a flag that this weapon is already being removed since
			// all we're really doing inside this loop is marking them for removal by
			// the entity system. We don't want to count the same weapon as removed
			// more than once.
			if( !UTIL_FindClientInPVS( pCandidate->edict() ) )
			{
				fRemovedOne = true;
			}
			else if( !pPlayer->FInViewCone( pCandidate ) )
			{
				fRemovedOne = true;
			}
			else if ( UTIL_DistApprox( pPlayer->GetAbsOrigin(), pCandidate->GetAbsOrigin() ) > (30*12) )
			{
				fRemovedOne = true;
			}
		}
//		else
//		{
//			fRemovedOne = true;
//		}

		if( fRemovedOne )
		{
			pCandidate->AddEffects( EF_NODRAW );
			UTIL_Remove( pCandidate );

			DevMsg( 2, "Surplus %s removed\n", pszWeaponName);
			surplus--;
		}
	}
}
예제 #27
0
//---------------------------------------------------------
// Purpose: See if it is time to poll and do so. 
//
// SOON: We need to load-balance this. 
//---------------------------------------------------------
void CVisibilityMonitor::FrameUpdatePostEntityThink()
{
	if( gpGlobals->curtime < m_flTimeNextPoll )
		return;

	m_flTimeNextPoll = gpGlobals->curtime + vismon_poll_frequency.GetFloat();

	int iDebugging = debug_visibility_monitor.GetInt();

	if( m_Entities.Count() > m_iMaxEntitiesPerThink )
		m_iMaxEntitiesPerThink = m_Entities.Count();

	if( iDebugging > 1 )
	{
		Msg("\nVisMon: Polling now. (Frequency: %f)\n", m_flPollFrequency );
		Msg("VisMon: Time: %f - Tracking %d Entities. (Max:%d)\n", gpGlobals->curtime, m_Entities.Count(), m_iMaxEntitiesPerThink );
	}

	// Cleanup, dump entities that have been removed since we last polled.
	for ( int i = 0 ; i < m_Entities.Count() ; i++ )
	{
		if ( m_Entities[i].entity == NULL )
		{
			m_Entities.FastRemove(i);
			if ( i >= m_Entities.Count() )
			{
				break;
			}
		}
	}

	int numTraces = 0;
	bool bHitTraceLimit = false;

	if( m_iStartElement >= m_Entities.Count() )
	{
		if( iDebugging > 1 )
		{
			Msg("VisMon: RESET\n");
		}

		m_iStartElement = 0;
	}

	if( iDebugging > 1 )
	{
		Msg("VisMon: Starting at element: %d\n", m_iStartElement );
	}

	for( int i = m_iStartElement ; i < m_Entities.Count() ; i++ )
	{
		for( int j = 1 ; j <= gpGlobals->maxClients ; j++ )
		{
			CBasePlayer *pPlayer =UTIL_PlayerByIndex( j );

			if( pPlayer != NULL && pPlayer->IsAlive() && !pPlayer->IsBot() )
			{
				int memoryBit = 1 << j; // The bit that is used to remember whether a given entity has been seen by a given player.

				CBaseEntity *pSeeEntity = m_Entities[ i ].entity.Get();

				if( pSeeEntity == NULL )
				{
					continue;
				}

				if( !(m_Entities[i].memory & memoryBit) )
				{
					// If this player hasn't seen this entity yet, check it.
					if( EntityIsVisibleToPlayer( m_Entities[i], pPlayer, &numTraces ) )
					{
						bool bIgnore = false;

						if( m_Entities[i].pfnEvaluator != NULL && !m_Entities[i].pfnEvaluator( m_Entities[i].entity, pPlayer ) )
						{
							bIgnore = true;
						}

						// See it! Generate our event.
						if( iDebugging > 0 )
						{
							if( bIgnore )
							{
								Msg("VisMon: Player %s IGNORING VISIBILE Entity: %s\n", pPlayer->GetDebugName(), pSeeEntity->GetDebugName() );
								NDebugOverlay::Cross3D( pSeeEntity->WorldSpaceCenter(), 16, 255, 0, 0, false, 10.0f );
							}
							else
							{
								Msg("VisMon: Player %s sees Entity: %s\n", pPlayer->GetDebugName(), pSeeEntity->GetDebugName() );
								NDebugOverlay::Cross3D( pSeeEntity->WorldSpaceCenter(), 16, 0, 255, 0, false, 10.0f );
							}
						}

						if( !bIgnore )
						{
							bool bGenerateEvent = true;

							if( m_Entities[i].pfnCallback != NULL )
							{
								// Make the callback, and let it determine whether to generate the simple event.
								bGenerateEvent = m_Entities[i].pfnCallback( m_Entities[i].entity, pPlayer );
							}

							if( bGenerateEvent )
							{
								// No callback, generate the generic game event.
								IGameEvent * event = gameeventmanager->CreateEvent( "entity_visible" );
								if ( event )
								{
									event->SetInt( "userid", pPlayer->GetUserID() );
									event->SetInt( "subject", pSeeEntity->entindex() );
									event->SetString( "classname", pSeeEntity->GetClassname() );
									event->SetString( "entityname", STRING( pSeeEntity->GetEntityName() ) );
									gameeventmanager->FireEvent( event );
								}
							}

							// Remember that this entity was visible to the player
							m_Entities[i].memory |= memoryBit;
						}
					}
				}
			}
		}

		if( numTraces >= vismon_trace_limit.GetInt() )
		{
			if( iDebugging > 1 )
			{
				Msg("VisMon: MAX Traces. Stopping after element %d\n", i );
			}

			m_iStartElement = i + 1; // Pick up here next think.
			bHitTraceLimit = true;
			break;
		}
	}

	if( !bHitTraceLimit )
	{
		m_iStartElement = 0;
	}

	if( numTraces > m_iMaxTracesPerThink )
		m_iMaxTracesPerThink = numTraces;

	if( iDebugging > 1 )
	{
		Msg("VisMon: %d traces performed during this polling cycle (Max: %d)\n\n", numTraces, m_iMaxTracesPerThink );
	}
}