void CClientThinkList::SetNextClientThink( ClientEntityHandle_t hEnt, float nextTime ) { if ( nextTime == CLIENT_THINK_NEVER ) { RemoveThinkable( hEnt ); } else { IClientThinkable *pThink = ClientEntityList().GetClientThinkableFromHandle( hEnt ); if ( pThink ) { ClientThinkHandle_t hThink = pThink->GetThinkHandle(); // Add it to the list if it's not already in there. if ( hThink == INVALID_THINK_HANDLE ) { hThink = (ClientThinkHandle_t)m_ThinkEntries.AddToTail(); pThink->SetThinkHandle( hThink ); GetThinkEntry( hThink )->m_hEnt = hEnt; } // Set the next think time.. GetThinkEntry( hThink )->m_flNextClientThink = nextTime; } } }
//----------------------------------------------------------------------------- // Add entity to frame think list //----------------------------------------------------------------------------- void CClientThinkList::AddEntityToFrameThinkList( ThinkEntry_t *pEntry, bool bAlwaysChain, int &nCount, ThinkEntry_t **ppFrameThinkList ) { // We may already have processed this owing to hierarchy rules if ( pEntry->m_nIterEnum == m_nIterEnum ) return; // If we're not thinking this frame, we don't have to worry about thinking after our parents bool bThinkThisInterval = ( pEntry->m_flNextClientThink == CLIENT_THINK_ALWAYS ) || ( pEntry->m_flNextClientThink <= gpGlobals->curtime ); // This logic makes it so that if a child thinks, // *all* hierarchical parents + grandparents will think first, even if some // of the parents don't need to think this frame if ( !bThinkThisInterval && !bAlwaysChain ) return; // Respect hierarchy C_BaseEntity *pEntity = ClientEntityList().GetBaseEntityFromHandle( pEntry->m_hEnt ); if ( pEntity ) { C_BaseEntity *pParent = pEntity->GetMoveParent(); if ( pParent && (pParent->GetThinkHandle() != INVALID_THINK_HANDLE) ) { ThinkEntry_t *pParentEntry = GetThinkEntry( pParent->GetThinkHandle() ); AddEntityToFrameThinkList( pParentEntry, true, nCount, ppFrameThinkList ); } } if ( !bThinkThisInterval ) return; // Add the entry into the list pEntry->m_nIterEnum = m_nIterEnum; ppFrameThinkList[nCount++] = pEntry; }
void CClientThinkList::SetNextClientThink( ClientEntityHandle_t hEnt, float flNextTime ) { if ( flNextTime == CLIENT_THINK_NEVER ) { RemoveThinkable( hEnt ); return; } IClientThinkable *pThink = ClientEntityList().GetClientThinkableFromHandle( hEnt ); if ( !pThink ) return; ClientThinkHandle_t hThink = pThink->GetThinkHandle(); if ( m_bInThinkLoop ) { // Queue up all changes int i = m_aChangeList.AddToTail(); m_aChangeList[i].m_hEnt = hEnt; m_aChangeList[i].m_hThink = hThink; m_aChangeList[i].m_flNextTime = flNextTime; return; } // Add it to the list if it's not already in there. if ( hThink == INVALID_THINK_HANDLE ) { hThink = (ClientThinkHandle_t)m_ThinkEntries.AddToTail(); pThink->SetThinkHandle( hThink ); ThinkEntry_t *pEntry = GetThinkEntry( hThink ); pEntry->m_hEnt = hEnt; pEntry->m_nIterEnum = -1; pEntry->m_flLastClientThink = 0.0f; } Assert( GetThinkEntry( hThink )->m_hEnt == hEnt ); GetThinkEntry( hThink )->m_flNextClientThink = flNextTime; }
//----------------------------------------------------------------------------- // Removes the thinkable from the list //----------------------------------------------------------------------------- void CClientThinkList::RemoveThinkable( ClientEntityHandle_t hEnt ) { IClientThinkable *pThink = ClientEntityList().GetClientThinkableFromHandle( hEnt ); if ( pThink ) { ClientThinkHandle_t hThink = pThink->GetThinkHandle(); if ( hThink != INVALID_THINK_HANDLE ) { Assert( GetThinkEntry( hThink )->m_hEnt == hEnt ); RemoveThinkable( hThink ); } } }
//----------------------------------------------------------------------------- // Removes the thinkable from the list //----------------------------------------------------------------------------- void CClientThinkList::RemoveThinkable( ClientThinkHandle_t hThink ) { if ( hThink == INVALID_THINK_HANDLE ) return; if ( m_bInThinkLoop ) { // Queue up all changes int i = m_aChangeList.AddToTail(); m_aChangeList[i].m_hEnt = INVALID_CLIENTENTITY_HANDLE; m_aChangeList[i].m_hThink = hThink; m_aChangeList[i].m_flNextTime = CLIENT_THINK_NEVER; return; } ThinkEntry_t *pEntry = GetThinkEntry( hThink ); IClientThinkable *pThink = ClientEntityList().GetClientThinkableFromHandle( pEntry->m_hEnt ); if ( pThink ) { pThink->SetThinkHandle( INVALID_THINK_HANDLE ); } m_ThinkEntries.Remove( (unsigned long)hThink ); }
//----------------------------------------------------------------------------- // Sets the client think //----------------------------------------------------------------------------- void CClientThinkList::SetNextClientThink( ClientThinkHandle_t hThink, float flNextTime ) { if ( hThink == INVALID_THINK_HANDLE ) return; if ( m_bInThinkLoop ) { // Queue up all changes int i = m_aChangeList.AddToTail(); m_aChangeList[i].m_hEnt = INVALID_CLIENTENTITY_HANDLE; m_aChangeList[i].m_hThink = hThink; m_aChangeList[i].m_flNextTime = flNextTime; return; } if ( flNextTime == CLIENT_THINK_NEVER ) { RemoveThinkable( hThink ); } else { GetThinkEntry( hThink )->m_flNextClientThink = flNextTime; } }