hl2_src-leak-2017/src/game/server/ai_saverestore.cpp

192 lines
4.5 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "isaverestore.h"
#include "saverestore_utlvector.h"
#include "ai_saverestore.h"
#include "ai_basenpc.h"
#include "ai_squad.h"
#include "ai_network.h"
#include "ai_networkmanager.h"
#ifdef HL2_DLL
#include "npc_playercompanion.h"
#endif // HL2_DLL
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static short AI_SAVE_RESTORE_VERSION = 2;
//-----------------------------------------------------------------------------
class CAI_SaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler
{
public:
const char *GetBlockName()
{
return "AI";
}
//---------------------------------
void Save( ISave *pSave )
{
pSave->StartBlock( "Squads" );
short nSquads = (short)g_AI_SquadManager.NumSquads();
pSave->WriteShort( &nSquads );
AISquadsIter_t iter;
string_t squadName;
CAI_Squad* pSquad = g_AI_SquadManager.GetFirstSquad( &iter );
while (pSquad)
{
squadName = MAKE_STRING( pSquad->GetName() );
pSave->WriteString( "", &squadName ); // Strings require a header to be read properly
pSave->WriteAll( pSquad );
pSquad = g_AI_SquadManager.GetNextSquad( &iter );
}
pSave->EndBlock();
//---------------------------------
pSave->StartBlock( "Enemies" );
short nMemories = 0;
CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs();
int i;
for ( i = 0; i < g_AI_Manager.NumAIs(); i++ )
{
if ( ppAIs[i]->GetEnemies() )
nMemories++;
}
pSave->WriteShort( &nMemories );
for ( i = 0; i < g_AI_Manager.NumAIs(); i++ )
{
if ( ppAIs[i]->GetEnemies() )
{
CBaseEntity *p = ppAIs[i];
pSave->WriteEntityPtr( &p );
pSave->WriteAll( ppAIs[i]->GetEnemies() );
}
}
pSave->EndBlock();
}
//---------------------------------
void WriteSaveHeaders( ISave *pSave )
{
pSave->WriteShort( &AI_SAVE_RESTORE_VERSION );
}
//---------------------------------
void ReadRestoreHeaders( IRestore *pRestore )
{
// No reason why any future version shouldn't try to retain backward compatability. The default here is to not do so.
short version;
pRestore->ReadShort( &version );
m_fDoLoad = ( version == AI_SAVE_RESTORE_VERSION );
}
//---------------------------------
void Restore( IRestore *pRestore, bool createPlayers )
{
// Initialize the squads (as there's no spawn)
CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs();
int i;
for ( i = 0; i < g_AI_Manager.NumAIs(); i++ )
{
ppAIs[i]->InitSquad();
}
if ( m_fDoLoad )
{
pRestore->StartBlock();
// Fixup all the squads
CAI_Squad ignored;
CAI_Squad *pSquad;
string_t squadName;
int nSavedSquads = pRestore->ReadShort();
while ( nSavedSquads-- )
{
int sizeData = pRestore->SkipHeader();
pRestore->ReadString( &squadName, 1, sizeData );
pSquad = g_AI_SquadManager.FindSquad( squadName );
if ( !pSquad )
pSquad = &ignored; // if all of the AIs in a squad failed to spawn, there would be no squad
pRestore->ReadAll( pSquad );
}
pRestore->EndBlock();
//---------------------------------
// Now load memories for unsquadded npcs
pRestore->StartBlock();
CAI_Enemies ignoredMem;
short nMemories = pRestore->ReadShort();
CBaseEntity *pAI;
while ( nMemories-- )
{
pRestore->ReadEntityPtr( &pAI );
if ( pAI )
pRestore->ReadAll( ((CAI_BaseNPC *)pAI)->GetEnemies() );
else
pRestore->ReadAll( &ignoredMem ); // AI probably failed to spawn
}
pRestore->EndBlock();
}
if ( g_AI_Manager.NumAIs() && g_pBigAINet->NumNodes() == 0 && !g_pAINetworkManager->NetworksLoaded() )
{
Msg( "***\n");
Msg( "ERROR: Loaded save game with no node graph. Load map and build node graph first!\n");
Msg( "***\n");
CAI_BaseNPC::m_nDebugBits |= bits_debugDisableAI;
g_pAINetworkManager->MarkDontSaveGraph();
}
}
void PostRestore( void )
{
#ifdef HL2_DLL
// We need this list to be regenerated
OverrideMoveCache_ForceRepopulateList();
#endif // HL2_DLL
}
private:
bool m_fDoLoad;
};
//-----------------------------------------------------------------------------
CAI_SaveRestoreBlockHandler g_AI_SaveRestoreBlockHandler;
//-------------------------------------
ISaveRestoreBlockHandler *GetAISaveRestoreBlockHandler()
{
return &g_AI_SaveRestoreBlockHandler;
}
//=============================================================================