161 lines
4.9 KiB
C++
161 lines
4.9 KiB
C++
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================//
|
|
|
|
#include "cbase.h"
|
|
|
|
#ifdef GAME_DLL
|
|
|
|
#include "isaverestore.h"
|
|
#include "saverestore_utlvector.h"
|
|
#include "achievement_saverestore.h"
|
|
#include "achievementmgr.h"
|
|
#include "baseachievement.h"
|
|
#include "utlmap.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
static short ACHIEVEMENT_SAVE_RESTORE_VERSION = 2;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
class CAchievementSaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler
|
|
{
|
|
public:
|
|
const char *GetBlockName()
|
|
{
|
|
return "Achievement";
|
|
}
|
|
|
|
//---------------------------------
|
|
|
|
void Save( ISave *pSave )
|
|
{
|
|
CAchievementMgr *pAchievementMgr = dynamic_cast<CAchievementMgr *>( engine->GetAchievementMgr() );
|
|
if ( !pAchievementMgr )
|
|
return;
|
|
|
|
// save global achievement mgr state to separate file if there have been any changes, so in case of a crash
|
|
// the global state is consistent with last save game
|
|
pAchievementMgr->SaveGlobalStateIfDirty();
|
|
|
|
pSave->StartBlock( "Achievements" );
|
|
int iTotalAchievements = pAchievementMgr->GetAchievementCount();
|
|
short nSaveCount = 0;
|
|
// count how many achievements should be saved.
|
|
for ( int i = 0; i < iTotalAchievements; i++ )
|
|
{
|
|
// We only save games in SP games so the assumption of SINGLE_PLAYER_SLOT is valid
|
|
IAchievement *pAchievement = pAchievementMgr->GetAchievementByIndex( i, SINGLE_PLAYER_SLOT );
|
|
if ( pAchievement->ShouldSaveWithGame() )
|
|
{
|
|
nSaveCount++;
|
|
}
|
|
}
|
|
// Write # of saved achievements
|
|
pSave->WriteShort( &nSaveCount );
|
|
// Write out each achievement
|
|
for ( int i = 0; i < iTotalAchievements; i++ )
|
|
{
|
|
// We only save games in SP games so the assumption of SINGLE_PLAYER_SLOT is valid
|
|
IAchievement *pAchievement = pAchievementMgr->GetAchievementByIndex( i, SINGLE_PLAYER_SLOT );
|
|
if ( pAchievement->ShouldSaveWithGame() )
|
|
{
|
|
CBaseAchievement *pBaseAchievement = dynamic_cast< CBaseAchievement * >( pAchievement );
|
|
if ( pBaseAchievement )
|
|
{
|
|
short iAchievementID = (short) pBaseAchievement->GetAchievementID();
|
|
// write the achievement ID
|
|
pSave->WriteShort( &iAchievementID );
|
|
// write the achievement data
|
|
pSave->WriteAll( pBaseAchievement, pBaseAchievement->GetDataDescMap() );
|
|
}
|
|
}
|
|
}
|
|
pSave->EndBlock();
|
|
}
|
|
|
|
//---------------------------------
|
|
|
|
void WriteSaveHeaders( ISave *pSave )
|
|
{
|
|
pSave->WriteShort( &ACHIEVEMENT_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 );
|
|
// only load if version matches and if we are loading a game, not a transition
|
|
m_fDoLoad = ( ( version == ACHIEVEMENT_SAVE_RESTORE_VERSION ) &&
|
|
( ( MapLoad_LoadGame == gpGlobals->eLoadType ) || ( MapLoad_NewGame == gpGlobals->eLoadType ) )
|
|
);
|
|
}
|
|
|
|
//---------------------------------
|
|
|
|
void Restore( IRestore *pRestore, bool createPlayers )
|
|
{
|
|
CAchievementMgr *pAchievementMgr = dynamic_cast<CAchievementMgr *>( engine->GetAchievementMgr() );
|
|
if ( !pAchievementMgr )
|
|
return;
|
|
|
|
if ( m_fDoLoad )
|
|
{
|
|
pAchievementMgr->PreRestoreSavedGame();
|
|
|
|
pRestore->StartBlock();
|
|
// read # of achievements
|
|
int nSavedAchievements = pRestore->ReadShort();
|
|
|
|
while ( nSavedAchievements-- )
|
|
{
|
|
// read achievement ID
|
|
int iAchievementID = pRestore->ReadShort();
|
|
// find the corresponding achievement object
|
|
// We only save games in SP games so the assumption of SINGLE_PLAYER_SLOT is valid
|
|
CBaseAchievement *pAchievement = pAchievementMgr->GetAchievementByID( iAchievementID, SINGLE_PLAYER_SLOT );
|
|
Assert( pAchievement ); // It's a bug if we don't understand this achievement
|
|
if ( pAchievement )
|
|
{
|
|
// read achievement data
|
|
pRestore->ReadAll( pAchievement, pAchievement->GetDataDescMap() );
|
|
}
|
|
else
|
|
{
|
|
// if we don't recognize the achievement for some reason, read and discard the data and keep going
|
|
CBaseAchievement ignored;
|
|
pRestore->ReadAll( &ignored, ignored.GetDataDescMap() );
|
|
}
|
|
}
|
|
pRestore->EndBlock();
|
|
|
|
pAchievementMgr->PostRestoreSavedGame();
|
|
}
|
|
}
|
|
|
|
private:
|
|
bool m_fDoLoad;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
CAchievementSaveRestoreBlockHandler g_AchievementSaveRestoreBlockHandler;
|
|
|
|
//-------------------------------------
|
|
|
|
ISaveRestoreBlockHandler *GetAchievementSaveRestoreBlockHandler()
|
|
{
|
|
return &g_AchievementSaveRestoreBlockHandler;
|
|
}
|
|
|
|
|
|
#endif // GAME_DLL
|