Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

191 lines
4.5 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "isaverestore.h"
  9. #include "saverestore_utlvector.h"
  10. #include "ai_saverestore.h"
  11. #include "ai_basenpc.h"
  12. #include "ai_squad.h"
  13. #include "ai_network.h"
  14. #include "ai_networkmanager.h"
  15. #ifdef HL2_DLL
  16. #include "npc_playercompanion.h"
  17. #endif // HL2_DLL
  18. // memdbgon must be the last include file in a .cpp file!!!
  19. #include "tier0/memdbgon.h"
  20. static short AI_SAVE_RESTORE_VERSION = 2;
  21. //-----------------------------------------------------------------------------
  22. class CAI_SaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler
  23. {
  24. public:
  25. const char *GetBlockName()
  26. {
  27. return "AI";
  28. }
  29. //---------------------------------
  30. void Save( ISave *pSave )
  31. {
  32. pSave->StartBlock( "Squads" );
  33. short nSquads = (short)g_AI_SquadManager.NumSquads();
  34. pSave->WriteShort( &nSquads );
  35. AISquadsIter_t iter;
  36. string_t squadName;
  37. CAI_Squad* pSquad = g_AI_SquadManager.GetFirstSquad( &iter );
  38. while (pSquad)
  39. {
  40. squadName = MAKE_STRING( pSquad->GetName() );
  41. pSave->WriteString( "", &squadName ); // Strings require a header to be read properly
  42. pSave->WriteAll( pSquad );
  43. pSquad = g_AI_SquadManager.GetNextSquad( &iter );
  44. }
  45. pSave->EndBlock();
  46. //---------------------------------
  47. pSave->StartBlock( "Enemies" );
  48. short nMemories = 0;
  49. CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs();
  50. int i;
  51. for ( i = 0; i < g_AI_Manager.NumAIs(); i++ )
  52. {
  53. if ( ppAIs[i]->GetEnemies() )
  54. nMemories++;
  55. }
  56. pSave->WriteShort( &nMemories );
  57. for ( i = 0; i < g_AI_Manager.NumAIs(); i++ )
  58. {
  59. if ( ppAIs[i]->GetEnemies() )
  60. {
  61. CBaseEntity *p = ppAIs[i];
  62. pSave->WriteEntityPtr( &p );
  63. pSave->WriteAll( ppAIs[i]->GetEnemies() );
  64. }
  65. }
  66. pSave->EndBlock();
  67. }
  68. //---------------------------------
  69. void WriteSaveHeaders( ISave *pSave )
  70. {
  71. pSave->WriteShort( &AI_SAVE_RESTORE_VERSION );
  72. }
  73. //---------------------------------
  74. void ReadRestoreHeaders( IRestore *pRestore )
  75. {
  76. // No reason why any future version shouldn't try to retain backward compatability. The default here is to not do so.
  77. short version;
  78. pRestore->ReadShort( &version );
  79. m_fDoLoad = ( version == AI_SAVE_RESTORE_VERSION );
  80. }
  81. //---------------------------------
  82. void Restore( IRestore *pRestore, bool createPlayers )
  83. {
  84. // Initialize the squads (as there's no spawn)
  85. CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs();
  86. int i;
  87. for ( i = 0; i < g_AI_Manager.NumAIs(); i++ )
  88. {
  89. ppAIs[i]->InitSquad();
  90. }
  91. if ( m_fDoLoad )
  92. {
  93. pRestore->StartBlock();
  94. // Fixup all the squads
  95. CAI_Squad ignored;
  96. CAI_Squad *pSquad;
  97. string_t squadName;
  98. int nSavedSquads = pRestore->ReadShort();
  99. while ( nSavedSquads-- )
  100. {
  101. int sizeData = pRestore->SkipHeader();
  102. pRestore->ReadString( &squadName, 1, sizeData );
  103. pSquad = g_AI_SquadManager.FindSquad( squadName );
  104. if ( !pSquad )
  105. pSquad = &ignored; // if all of the AIs in a squad failed to spawn, there would be no squad
  106. pRestore->ReadAll( pSquad );
  107. }
  108. pRestore->EndBlock();
  109. //---------------------------------
  110. // Now load memories for unsquadded npcs
  111. pRestore->StartBlock();
  112. CAI_Enemies ignoredMem;
  113. short nMemories = pRestore->ReadShort();
  114. CBaseEntity *pAI;
  115. while ( nMemories-- )
  116. {
  117. pRestore->ReadEntityPtr( &pAI );
  118. if ( pAI )
  119. pRestore->ReadAll( ((CAI_BaseNPC *)pAI)->GetEnemies() );
  120. else
  121. pRestore->ReadAll( &ignoredMem ); // AI probably failed to spawn
  122. }
  123. pRestore->EndBlock();
  124. }
  125. if ( g_AI_Manager.NumAIs() && g_pBigAINet->NumNodes() == 0 && !g_pAINetworkManager->NetworksLoaded() )
  126. {
  127. Msg( "***\n");
  128. Msg( "ERROR: Loaded save game with no node graph. Load map and build node graph first!\n");
  129. Msg( "***\n");
  130. CAI_BaseNPC::m_nDebugBits |= bits_debugDisableAI;
  131. g_pAINetworkManager->MarkDontSaveGraph();
  132. }
  133. }
  134. void PostRestore( void )
  135. {
  136. #ifdef HL2_DLL
  137. // We need this list to be regenerated
  138. OverrideMoveCache_ForceRepopulateList();
  139. #endif // HL2_DLL
  140. }
  141. private:
  142. bool m_fDoLoad;
  143. };
  144. //-----------------------------------------------------------------------------
  145. CAI_SaveRestoreBlockHandler g_AI_SaveRestoreBlockHandler;
  146. //-------------------------------------
  147. ISaveRestoreBlockHandler *GetAISaveRestoreBlockHandler()
  148. {
  149. return &g_AI_SaveRestoreBlockHandler;
  150. }
  151. //=============================================================================