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.

250 lines
8.2 KiB

  1. //
  2. // Purpose:
  3. //
  4. // $NoKeywords: $
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "quest_objective_manager.h"
  8. #include "gcsdk/gcclient.h"
  9. #include "gc_clientsystem.h"
  10. #include "econ_quests.h"
  11. #include "steamworks_gamestats.h"
  12. #include "tf_gamerules.h"
  13. #include "entity_halloween_pickup.h"
  14. #ifdef CLIENT_DLL
  15. #include "econ_notifications.h"
  16. #include "tf_item_inventory.h"
  17. #include "clientmode_tf.h"
  18. #endif
  19. // memdbgon must be the last include file in a .cpp file!!!
  20. #include "tier0/memdbgon.h"
  21. extern ConVar tf_mm_trusted;
  22. CQuestObjectiveManager::CQuestObjectiveManager()
  23. {}
  24. CQuestObjectiveManager::~CQuestObjectiveManager()
  25. {
  26. SO_TRACKER_SPEW( "Destroying CQuestObjectiveManager\n", SO_TRACKER_SPEW_ITEM_TRACKER_MANAGEMENT );
  27. Shutdown();
  28. if ( steamapicontext && steamapicontext->SteamUser() )
  29. {
  30. CSteamID steamID = steamapicontext->SteamUser()->GetSteamID();
  31. GCClientSystem()->GetGCClient()->RemoveSOCacheListener( steamID, this );
  32. }
  33. }
  34. CSOTrackerManager::SOTrackerMap_t::KeyType_t CQuestObjectiveManager::GetKeyForObjectTracker( const CSharedObject* pItem, CSteamID steamIDOwner )
  35. {
  36. return assert_cast< const CEconItem* >( pItem )->GetItemID();
  37. }
  38. bool CQuestObjectiveManager::ShouldTrackObject( const CSteamID & steamIDOwner, const CSharedObject *pObject ) const
  39. {
  40. // We only care about items!
  41. if( pObject->GetTypeID() != CEconItem::k_nTypeID )
  42. return false;
  43. CEconItem *pItem = (CEconItem *)pObject;
  44. const GameItemDefinition_t* pItemDef = pItem->GetItemDefinition();
  45. // Not a quest? Don't care
  46. if ( pItemDef->GetQuestDef() == NULL )
  47. {
  48. SO_TRACKER_SPEW( CFmtStr( "Not accepting item %llu with defindex %d. It doesn't have a quest def.\n", pItem->GetID(), pItemDef->GetDefinitionIndex() ), SO_TRACKER_SPEW_TRACKER_ACCEPTANCE );
  49. return false;
  50. }
  51. // We only create trackers for identified items
  52. if ( IsQuestItemUnidentified( pItem ) )
  53. {
  54. SO_TRACKER_SPEW( CFmtStr( "Not accepting item %llu with defindex %d. It's not identified.\n", pItem->GetID(), pItemDef->GetDefinitionIndex() ), SO_TRACKER_SPEW_TRACKER_ACCEPTANCE );
  55. return false;
  56. }
  57. SO_TRACKER_SPEW( CFmtStr( "Accepting item %llu with defindex %d.\n", pItem->GetID(), pItemDef->GetDefinitionIndex() ), SO_TRACKER_SPEW_TRACKER_ACCEPTANCE );
  58. return true;
  59. }
  60. int CQuestObjectiveManager::CompareRecords( const ::google::protobuf::Message* pNewProtoMsg, const ::google::protobuf::Message* pExistingProtoMsg ) const
  61. {
  62. const CMsgGCQuestObjective_PointsChange* pNew = assert_cast< const CMsgGCQuestObjective_PointsChange* >( pNewProtoMsg );
  63. const CMsgGCQuestObjective_PointsChange* pExisting = assert_cast< const CMsgGCQuestObjective_PointsChange* >( pExistingProtoMsg );
  64. int nNewPoints = pNew->standard_points() + pNew->bonus_points();
  65. int nExistingPoints = pExisting->standard_points() + pExisting->bonus_points();
  66. return nNewPoints - nExistingPoints;
  67. }
  68. #ifdef CLIENT_DLL
  69. void CQuestObjectiveManager::UpdateFromServer( itemid_t nID, uint32 nStandardPoints, uint32 nBonusPoints )
  70. {
  71. CQuestItemTracker* pTracker = assert_cast< CQuestItemTracker* >( GetTracker( nID ) );
  72. if ( pTracker )
  73. {
  74. pTracker->UpdateFromServer( nStandardPoints, nBonusPoints );
  75. }
  76. else
  77. {
  78. SO_TRACKER_SPEW( CFmtStr( "Got update from server, but itemID: %llu doesn't exist!", nID ), SO_TRACKER_SPEW_OBJECTIVES );
  79. }
  80. }
  81. #endif // CLIENT_DLL
  82. #ifdef GAME_DLL
  83. void CQuestObjectiveManager::SendMessageForCommit( const ::google::protobuf::Message* pProtoMessage ) const
  84. {
  85. GCSDK::CProtoBufMsg< CMsgGCQuestObjective_PointsChange > msg( k_EMsgGCQuestObjective_PointsChange );
  86. msg.Body() = *assert_cast< const CMsgGCQuestObjective_PointsChange* >( pProtoMessage );
  87. GCClientSystem()->BSendMessage( msg );
  88. }
  89. #endif
  90. CFmtStr CQuestObjectiveManager::GetDebugObjectDescription( const CSharedObject* pSObject ) const
  91. {
  92. const CEconItem* pItem = assert_cast< const CEconItem* >( pSObject );
  93. return CFmtStr( "%llu (%s)", pItem->GetItemID(), pItem->GetItemDefinition()->GetQuestDef()->GetRolledNameForItem( pItem ) );
  94. }
  95. CBaseSOTracker* CQuestObjectiveManager::AllocateNewTracker( const CSharedObject* pItem, CSteamID steamIDOwner, CSOTrackerManager* pManager ) const
  96. {
  97. return new CQuestItemTracker( pItem, steamIDOwner, pManager );
  98. }
  99. ::google::protobuf::Message* CQuestObjectiveManager::AllocateNewProtoMessage() const
  100. {
  101. return new CMsgGCQuestObjective_PointsChange();
  102. }
  103. //-----------------------------------------------------------------------------
  104. // Purpose: Handle the GC responding to an earlier commit. Remove any unacknowledged
  105. // commits records we have.
  106. //-----------------------------------------------------------------------------
  107. void CQuestObjectiveManager::OnCommitRecieved( const ::google::protobuf::Message* pProtoMsg )
  108. {
  109. const CMsgGCQuestObjective_PointsChange* pPointsChangeMsg = assert_cast< const CMsgGCQuestObjective_PointsChange* >( pProtoMsg );
  110. // Check if we should update points. This happens when the record comes from a server
  111. // where the player has disconnected from (this could be ourselves).
  112. if ( pPointsChangeMsg->update_base_points() )
  113. {
  114. CQuestItemTracker* pItemTracker = assert_cast<CQuestItemTracker*>( GetTracker( pPointsChangeMsg->quest_item_id() ) );
  115. if ( pItemTracker )
  116. {
  117. pItemTracker->UpdatePointsFromSOItem();
  118. }
  119. }
  120. }
  121. #ifdef GAME_DLL
  122. CON_COMMAND( tf_quests_spew_trackers, "Spews all currently active quest trackers" )
  123. {
  124. QuestObjectiveManager()->Spew();
  125. }
  126. CON_COMMAND( ensure_so_trackers_for_steamid, "Ensures a steamID has all the trackers it should have, with extra spew along the way" )
  127. {
  128. if ( args.ArgC() != 2 )
  129. {
  130. Warning( "Need the 64bit representation of a steamID as well\n" );
  131. return;
  132. }
  133. CSteamID steamID( (uint32)V_atoi( args[1] ),
  134. // GetUniverse() DOESNT WORK on servers, so we're hacking this for now
  135. #ifdef STAGING_ONLY
  136. k_EUniverseDev,
  137. #else
  138. k_EUniversePublic,
  139. #endif
  140. k_EAccountTypeIndividual );
  141. if ( !steamID.IsValid() )
  142. {
  143. Warning( "SteamID is not valid!\n" );
  144. return;
  145. }
  146. g_nQuestSpewFlags |= SO_TRACKER_SPEW_TRACKER_ACCEPTANCE;
  147. QuestObjectiveManager()->EnsureTrackersForPlayer( steamID );
  148. g_nQuestSpewFlags &= ~SO_TRACKER_SPEW_TRACKER_ACCEPTANCE;
  149. }
  150. #endif
  151. #if ( defined( DEBUG ) || defined( STAGING_ONLY ) ) && defined( GAME_DLL )
  152. CON_COMMAND( tf_quests_spew_unacknowledged_commits, "Spews info on all unacknowledged commits" )
  153. {
  154. QuestObjectiveManager()->DBG_SpewPendingCommits();
  155. }
  156. #endif // ( defined( DEBUG ) || defined( STAGING_ONLY ) ) && defined( GAME_DLL )
  157. #ifdef GAME_DLL
  158. //-----------------------------------------------------------------------------
  159. // Purpose: GC Msg handler for points change response
  160. //-----------------------------------------------------------------------------
  161. class CGCQuestObjective_PointsChangeResponse : public GCSDK::CGCClientJob
  162. {
  163. public:
  164. CGCQuestObjective_PointsChangeResponse( GCSDK::CGCClient *pClient ) : GCSDK::CGCClientJob( pClient ) {}
  165. virtual bool BYieldingRunGCJob( GCSDK::IMsgNetPacket *pNetPacket )
  166. {
  167. GCSDK::CProtoBufMsg< CMsgGCQuestObjective_PointsChange > msg( pNetPacket );
  168. QuestObjectiveManager()->AcknowledgeCommit( &msg.Body(), msg.Body().quest_item_id() );
  169. return true;
  170. }
  171. };
  172. GC_REG_JOB( GCSDK::CGCClient, CGCQuestObjective_PointsChangeResponse, "CGCQuestObjective_PointsChangeResponse", k_EMsgGCQuestObjective_PointsChange, GCSDK::k_EServerTypeGCClient );
  173. #endif // GAME_DLL
  174. #if ( defined( DEBUG ) || defined( STAGING_ONLY ) ) && defined( GAME_DLL )
  175. CON_COMMAND( tf_quests_complete_all, "Completes all quests" )
  176. {
  177. QuestObjectiveManager()->DBG_CompleteQuests();
  178. }
  179. void CQuestObjectiveManager::DBG_CompleteQuests()
  180. {
  181. CTFPlayer *pPlayer = ToTFPlayer( UTIL_GetCommandClient() );
  182. if ( !pPlayer )
  183. return;
  184. CSteamID steamIDForPlayer;
  185. if ( !pPlayer->GetSteamID( &steamIDForPlayer ) )
  186. return;
  187. CTFPlayerInventory* pInv = TFInventoryManager()->GetInventoryForPlayer( steamIDForPlayer );
  188. if ( pInv )
  189. {
  190. int iCount = pInv->GetItemCount();
  191. for ( int i = 0; i < iCount; i++ )
  192. {
  193. CEconItemView *pItem = pInv->GetItem(i);
  194. if ( !pItem )
  195. continue;
  196. if( !pItem->GetStaticData() || !pItem->GetStaticData()->GetQuestDef() )
  197. continue;
  198. CQuestItemTracker* pTracker = assert_cast<CQuestItemTracker*>( GetTracker( pItem->GetItemID() ) );
  199. if ( pTracker )
  200. {
  201. pTracker->DBG_CompleteQuest();
  202. }
  203. }
  204. }
  205. }
  206. #endif // ( defined( DEBUG ) || defined( STAGING_ONLY ) ) && defined( GAME_DLL )