area51/Support/TriggerEx/TriggerEx_Manager.cpp
Andrew Sampson 431f72b93a source
2021-08-27 19:22:41 -07:00

351 lines
10 KiB
C++

///////////////////////////////////////////////////////////////////////////////
//
// TriggerEx_Manager.cpp
//
///////////////////////////////////////////////////////////////////////////////
//=========================================================================
// INCLUDES
//=========================================================================
#include "..\Support\TriggerEx\TriggerEx_Manager.hpp"
#include "gamelib\StatsMgr.hpp"
//=========================================================================
// GLOBALS
//=========================================================================
trigger_ex_mngr g_TriggerExMgr;
s32 g_TriggerAdvLogicCount = 0;
#ifndef CONFIG_RETAIL
f32 fLastTriggerUpdateDeltaTime = 0.0f;
xtick xtLastTriggerUpdateTime = 0;
#endif
//=========================================================================
// TRIGGER_MNGR
//=========================================================================
trigger_ex_mngr::trigger_ex_mngr( )
{
m_ClassList[TRIGGER_EX_NO_UPDATE] = NULL;
m_ClassList[TRIGGER_EX_UPDATE] = NULL;
}
//=============================================================================
trigger_ex_object* trigger_ex_mngr::GetTriggerPtr( guid TriggerGuid )
{
object* pObject = NULL;
if ( SMP_UTIL_IsGuidOfType ( &pObject, TriggerGuid , trigger_ex_object::GetRTTI() ) == FALSE )
{
return NULL;
}
return (trigger_ex_object*) pObject;
}
//=============================================================================
void trigger_ex_mngr::OnUpdate ( f32 DeltaTime )
{
STAT_LOGGER( temp, k_stats_TriggerSystem );
#ifndef CONFIG_RETAIL
xtLastTriggerUpdateTime = g_ObjMgr.GetGameTime();
fLastTriggerUpdateDeltaTime = DeltaTime;
#endif
//note this must be const reference, as its possible in some situations for the list to become
//empty due to all active triggers being removed...
const guid& rHeadGuid = m_ClassList[TRIGGER_EX_UPDATE];
if (rHeadGuid == NULL)
return;
trigger_ex_object* pCurrentTrigger = GetTriggerPtr ( rHeadGuid );
ASSERT( pCurrentTrigger );
while(1)
{
guid Next = pCurrentTrigger->m_Next;
//Note within ExecuteLogic the pCurrentTrigger can be destroyed and unregistered, so
//that is why we store away the guids Next and not access pCurrentTrigger after calling
//ExecuteLogic...
pCurrentTrigger->ExecuteLogic( DeltaTime );
pCurrentTrigger = NULL;
//HeadGuid can change after ExecuteLogic because triggers can be
//removed, or destroyed from the active list..
if ( rHeadGuid == Next || rHeadGuid == NULL )
break;
pCurrentTrigger = GetTriggerPtr ( Next );
if (pCurrentTrigger == NULL)
break;
}
}
//=============================================================================
void trigger_ex_mngr::TriggerSleep ( trigger_ex_object & rTrigger )
{
if (rTrigger.m_TriggerSlot == TRIGGER_EX_NO_UPDATE)
return;
UnregisterTrigger( rTrigger );
RegisterTrigger ( rTrigger );
}
//=============================================================================
void trigger_ex_mngr::TriggerAwake ( trigger_ex_object & rTrigger )
{
if (rTrigger.m_TriggerSlot == TRIGGER_EX_UPDATE)
return;
UnregisterTrigger( rTrigger );
RegisterTrigger ( rTrigger );
}
//=============================================================================
void trigger_ex_mngr::RegisterTrigger ( trigger_ex_object & rTrigger )
{
//PDL::Insert the new trigger into the proper update list, depending upon
// their update need. Sleeping triggers go into the non-update list.
//TODO: implement a priority queue for the updating triggers much more effiecnt
// than iterating through all updateable triggers.... -ddn
//The list is cyclic.....
guid* pHeadGuid = NULL;
if ( rTrigger.IsAwake() )
{
pHeadGuid = &m_ClassList[TRIGGER_EX_UPDATE];
rTrigger.m_TriggerSlot = TRIGGER_EX_UPDATE;
}
else
{
pHeadGuid = &m_ClassList[TRIGGER_EX_NO_UPDATE];
rTrigger.m_TriggerSlot = TRIGGER_EX_NO_UPDATE;
}
guid NewTriggerGuid = rTrigger.GetGuid();
if (*pHeadGuid == NULL)
{
rTrigger.m_Next = NewTriggerGuid;
rTrigger.m_Prev = NewTriggerGuid;
*pHeadGuid = NewTriggerGuid;
return;
}
trigger_ex_object* pTriggerHead = GetTriggerPtr ( *pHeadGuid );
trigger_ex_object* pTriggerHeadPrev = NULL;
ASSERT( pTriggerHead );
pTriggerHeadPrev = GetTriggerPtr ( pTriggerHead->m_Prev );
ASSERT( pTriggerHeadPrev );
//check if we have a single element cyclic list
if ( pTriggerHead == pTriggerHeadPrev )
{
pTriggerHead->m_Next = NewTriggerGuid;
pTriggerHead->m_Prev = NewTriggerGuid;
rTrigger.m_Next = *pHeadGuid;
rTrigger.m_Prev = *pHeadGuid;
return;
}
//Insert the new trigger into the tail end of the cyclic list
rTrigger.m_Next = *pHeadGuid;
rTrigger.m_Prev = pTriggerHeadPrev->GetGuid();
pTriggerHeadPrev->m_Next = NewTriggerGuid;
pTriggerHead->m_Prev = NewTriggerGuid;
return;
}
//=============================================================================
void trigger_ex_mngr::UnregisterTrigger ( trigger_ex_object & rTrigger )
{
//PDL::Delete the trigger from the list
//The list is cyclic...
guid DeleteTriggerGuid = rTrigger.GetGuid();
guid* pHeadGuid = NULL;
if ( rTrigger.m_TriggerSlot >=0 && rTrigger.m_TriggerSlot < TRIGGER_EX_CLASS_END )
{
pHeadGuid = &m_ClassList[rTrigger.m_TriggerSlot];
}
else
{
x_DebugMsg( "trigger_ex_mngr::UnregisterTrigger, Cannot find slot for given trigger." );
ASSERT(0);
return;
}
if ( *pHeadGuid == NULL )
return;
trigger_ex_object* pDeleteTrigger = GetTriggerPtr ( DeleteTriggerGuid );
trigger_ex_object* pDeleteTriggerPrev = NULL;
trigger_ex_object* pDeleteTriggerNext = NULL;
ASSERT( pDeleteTrigger );
pDeleteTriggerPrev = GetTriggerPtr ( pDeleteTrigger->m_Prev );
pDeleteTriggerNext = GetTriggerPtr ( pDeleteTrigger->m_Next );
//Check for single element cyclic link list
if ( pDeleteTrigger == pDeleteTriggerPrev )
{
*pHeadGuid = NULL;
return;
}
//HACK - until we get someone to figure these triggers out, don't want them crashes Level Black
//Check for 2nd to last element
if (pDeleteTriggerNext == NULL)
{
pDeleteTriggerNext = pDeleteTriggerPrev;
}
if ( pDeleteTriggerPrev && pDeleteTriggerNext)
{
//Remove the delete trigger from the cyclic list...
pDeleteTriggerPrev->m_Next = pDeleteTriggerNext->GetGuid();
pDeleteTriggerNext->m_Prev = pDeleteTriggerPrev->GetGuid();
if ( *pHeadGuid == DeleteTriggerGuid )
{
*pHeadGuid = pDeleteTriggerNext->GetGuid();
}
}
else
{
*pHeadGuid = NULL;
}
return;
}
//=============================================================================
#ifndef CONFIG_RETAIL
void trigger_ex_mngr::DumpData( const char* pFileName )
{
X_FILE* pFile = x_fopen( pFileName, "wt" );
ASSERT( pFile );
x_DebugMsg("Starting trigger dump.....\n");
x_fprintf( pFile, "GBL_ADV_LGC_CNT = %d\n", g_TriggerAdvLogicCount);
x_fprintf( pFile, "Last_Delta_Time = %g\n", fLastTriggerUpdateDeltaTime);
x_fprintf( pFile, "Last_Game_Time = %g\n\n", x_TicksToMs(xtLastTriggerUpdateTime));
x_fprintf( pFile, "A TYPE TYPDF GUID GG ADVLGC CNT CST CAS CAI NUT EXE TIME \n" );
x_fprintf( pFile, "= ==== ===== ========:======== == ====== === === ==== === ======== ======== \n" );
slot_id SlotID = g_ObjMgr.GetFirst(object::TYPE_TRIGGER_EX);
while( SlotID != SLOT_NULL )
{
object* pObject = g_ObjMgr.GetObjectBySlot( SlotID );
if( pObject != NULL )
{
trigger_ex_object& TriggerObject = trigger_ex_object::GetSafeType( *pObject );
TriggerObject.DumpData(pFile);
}
SlotID = g_ObjMgr.GetNext( SlotID );
}
x_fprintf( pFile, "\n=================================================================\n" );
x_fprintf( pFile, "=================================================================\n\n" );
const guid& rHeadGuid = m_ClassList[TRIGGER_EX_UPDATE];
if (rHeadGuid != NULL)
{
trigger_ex_object* pCurrentTrigger = GetTriggerPtr ( rHeadGuid );
ASSERT( pCurrentTrigger );
while(1)
{
guid Next = pCurrentTrigger->m_Next;
x_fprintf( pFile, "%08X:%08X\n",
(u32)((pCurrentTrigger->GetGuid()>>32)&0xFFFFFFFF),
(u32)((pCurrentTrigger->GetGuid()>>0 )&0xFFFFFFFF));
pCurrentTrigger = NULL;
if ( rHeadGuid == Next || rHeadGuid == NULL )
break;
pCurrentTrigger = GetTriggerPtr ( Next );
if (pCurrentTrigger == NULL)
break;
}
}
x_fclose(pFile);
/*
text_out DataFile;
DataFile.OpenFile( pFileName );
DataFile.AddHeader("TriggerData",g_ObjMgr.GetNumInstances(object::TYPE_TRIGGER_EX));
slot_id SlotID = g_ObjMgr.GetFirst(object::TYPE_TRIGGER_EX);
while( SlotID != SLOT_NULL )
{
object* pObject = g_ObjMgr.GetObjectBySlot( SlotID );
if( pObject != NULL )
{
trigger_ex_object& TriggerObject = trigger_ex_object::GetSafeType( *pObject );
TriggerObject.DumpData(DataFile);
}
SlotID = g_ObjMgr.GetNext( SlotID );
}
const guid& rHeadGuid = m_ClassList[TRIGGER_EX_UPDATE];
if (rHeadGuid != NULL)
{
trigger_ex_object* pCurrentTrigger = GetTriggerPtr ( rHeadGuid );
ASSERT( pCurrentTrigger );
while(1)
{
guid Next = pCurrentTrigger->m_Next;
DataFile.AddHeader("TgrMgrLstObj",1);
DataFile.AddGuid ("Guid", pCurrentTrigger->GetGuid() );
pCurrentTrigger = NULL;
if ( rHeadGuid == Next || rHeadGuid == NULL )
break;
pCurrentTrigger = GetTriggerPtr ( Next );
if (pCurrentTrigger == NULL)
break;
}
}
DataFile.CloseFile();
*/
}
#endif //CONFIG_RETAIL