Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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.

251 lines
8.2 KiB

5 years ago
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "quest_objective_manager.h"
#include "gcsdk/gcclient.h"
#include "gc_clientsystem.h"
#include "econ_quests.h"
#include "steamworks_gamestats.h"
#include "tf_gamerules.h"
#include "entity_halloween_pickup.h"
#ifdef CLIENT_DLL
#include "econ_notifications.h"
#include "tf_item_inventory.h"
#include "clientmode_tf.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern ConVar tf_mm_trusted;
CQuestObjectiveManager::CQuestObjectiveManager()
{}
CQuestObjectiveManager::~CQuestObjectiveManager()
{
SO_TRACKER_SPEW( "Destroying CQuestObjectiveManager\n", SO_TRACKER_SPEW_ITEM_TRACKER_MANAGEMENT );
Shutdown();
if ( steamapicontext && steamapicontext->SteamUser() )
{
CSteamID steamID = steamapicontext->SteamUser()->GetSteamID();
GCClientSystem()->GetGCClient()->RemoveSOCacheListener( steamID, this );
}
}
CSOTrackerManager::SOTrackerMap_t::KeyType_t CQuestObjectiveManager::GetKeyForObjectTracker( const CSharedObject* pItem, CSteamID steamIDOwner )
{
return assert_cast< const CEconItem* >( pItem )->GetItemID();
}
bool CQuestObjectiveManager::ShouldTrackObject( const CSteamID & steamIDOwner, const CSharedObject *pObject ) const
{
// We only care about items!
if( pObject->GetTypeID() != CEconItem::k_nTypeID )
return false;
CEconItem *pItem = (CEconItem *)pObject;
const GameItemDefinition_t* pItemDef = pItem->GetItemDefinition();
// Not a quest? Don't care
if ( pItemDef->GetQuestDef() == NULL )
{
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 );
return false;
}
// We only create trackers for identified items
if ( IsQuestItemUnidentified( pItem ) )
{
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 );
return false;
}
SO_TRACKER_SPEW( CFmtStr( "Accepting item %llu with defindex %d.\n", pItem->GetID(), pItemDef->GetDefinitionIndex() ), SO_TRACKER_SPEW_TRACKER_ACCEPTANCE );
return true;
}
int CQuestObjectiveManager::CompareRecords( const ::google::protobuf::Message* pNewProtoMsg, const ::google::protobuf::Message* pExistingProtoMsg ) const
{
const CMsgGCQuestObjective_PointsChange* pNew = assert_cast< const CMsgGCQuestObjective_PointsChange* >( pNewProtoMsg );
const CMsgGCQuestObjective_PointsChange* pExisting = assert_cast< const CMsgGCQuestObjective_PointsChange* >( pExistingProtoMsg );
int nNewPoints = pNew->standard_points() + pNew->bonus_points();
int nExistingPoints = pExisting->standard_points() + pExisting->bonus_points();
return nNewPoints - nExistingPoints;
}
#ifdef CLIENT_DLL
void CQuestObjectiveManager::UpdateFromServer( itemid_t nID, uint32 nStandardPoints, uint32 nBonusPoints )
{
CQuestItemTracker* pTracker = assert_cast< CQuestItemTracker* >( GetTracker( nID ) );
if ( pTracker )
{
pTracker->UpdateFromServer( nStandardPoints, nBonusPoints );
}
else
{
SO_TRACKER_SPEW( CFmtStr( "Got update from server, but itemID: %llu doesn't exist!", nID ), SO_TRACKER_SPEW_OBJECTIVES );
}
}
#endif // CLIENT_DLL
#ifdef GAME_DLL
void CQuestObjectiveManager::SendMessageForCommit( const ::google::protobuf::Message* pProtoMessage ) const
{
GCSDK::CProtoBufMsg< CMsgGCQuestObjective_PointsChange > msg( k_EMsgGCQuestObjective_PointsChange );
msg.Body() = *assert_cast< const CMsgGCQuestObjective_PointsChange* >( pProtoMessage );
GCClientSystem()->BSendMessage( msg );
}
#endif
CFmtStr CQuestObjectiveManager::GetDebugObjectDescription( const CSharedObject* pSObject ) const
{
const CEconItem* pItem = assert_cast< const CEconItem* >( pSObject );
return CFmtStr( "%llu (%s)", pItem->GetItemID(), pItem->GetItemDefinition()->GetQuestDef()->GetRolledNameForItem( pItem ) );
}
CBaseSOTracker* CQuestObjectiveManager::AllocateNewTracker( const CSharedObject* pItem, CSteamID steamIDOwner, CSOTrackerManager* pManager ) const
{
return new CQuestItemTracker( pItem, steamIDOwner, pManager );
}
::google::protobuf::Message* CQuestObjectiveManager::AllocateNewProtoMessage() const
{
return new CMsgGCQuestObjective_PointsChange();
}
//-----------------------------------------------------------------------------
// Purpose: Handle the GC responding to an earlier commit. Remove any unacknowledged
// commits records we have.
//-----------------------------------------------------------------------------
void CQuestObjectiveManager::OnCommitRecieved( const ::google::protobuf::Message* pProtoMsg )
{
const CMsgGCQuestObjective_PointsChange* pPointsChangeMsg = assert_cast< const CMsgGCQuestObjective_PointsChange* >( pProtoMsg );
// Check if we should update points. This happens when the record comes from a server
// where the player has disconnected from (this could be ourselves).
if ( pPointsChangeMsg->update_base_points() )
{
CQuestItemTracker* pItemTracker = assert_cast<CQuestItemTracker*>( GetTracker( pPointsChangeMsg->quest_item_id() ) );
if ( pItemTracker )
{
pItemTracker->UpdatePointsFromSOItem();
}
}
}
#ifdef GAME_DLL
CON_COMMAND( tf_quests_spew_trackers, "Spews all currently active quest trackers" )
{
QuestObjectiveManager()->Spew();
}
CON_COMMAND( ensure_so_trackers_for_steamid, "Ensures a steamID has all the trackers it should have, with extra spew along the way" )
{
if ( args.ArgC() != 2 )
{
Warning( "Need the 64bit representation of a steamID as well\n" );
return;
}
CSteamID steamID( (uint32)V_atoi( args[1] ),
// GetUniverse() DOESNT WORK on servers, so we're hacking this for now
#ifdef STAGING_ONLY
k_EUniverseDev,
#else
k_EUniversePublic,
#endif
k_EAccountTypeIndividual );
if ( !steamID.IsValid() )
{
Warning( "SteamID is not valid!\n" );
return;
}
g_nQuestSpewFlags |= SO_TRACKER_SPEW_TRACKER_ACCEPTANCE;
QuestObjectiveManager()->EnsureTrackersForPlayer( steamID );
g_nQuestSpewFlags &= ~SO_TRACKER_SPEW_TRACKER_ACCEPTANCE;
}
#endif
#if ( defined( DEBUG ) || defined( STAGING_ONLY ) ) && defined( GAME_DLL )
CON_COMMAND( tf_quests_spew_unacknowledged_commits, "Spews info on all unacknowledged commits" )
{
QuestObjectiveManager()->DBG_SpewPendingCommits();
}
#endif // ( defined( DEBUG ) || defined( STAGING_ONLY ) ) && defined( GAME_DLL )
#ifdef GAME_DLL
//-----------------------------------------------------------------------------
// Purpose: GC Msg handler for points change response
//-----------------------------------------------------------------------------
class CGCQuestObjective_PointsChangeResponse : public GCSDK::CGCClientJob
{
public:
CGCQuestObjective_PointsChangeResponse( GCSDK::CGCClient *pClient ) : GCSDK::CGCClientJob( pClient ) {}
virtual bool BYieldingRunGCJob( GCSDK::IMsgNetPacket *pNetPacket )
{
GCSDK::CProtoBufMsg< CMsgGCQuestObjective_PointsChange > msg( pNetPacket );
QuestObjectiveManager()->AcknowledgeCommit( &msg.Body(), msg.Body().quest_item_id() );
return true;
}
};
GC_REG_JOB( GCSDK::CGCClient, CGCQuestObjective_PointsChangeResponse, "CGCQuestObjective_PointsChangeResponse", k_EMsgGCQuestObjective_PointsChange, GCSDK::k_EServerTypeGCClient );
#endif // GAME_DLL
#if ( defined( DEBUG ) || defined( STAGING_ONLY ) ) && defined( GAME_DLL )
CON_COMMAND( tf_quests_complete_all, "Completes all quests" )
{
QuestObjectiveManager()->DBG_CompleteQuests();
}
void CQuestObjectiveManager::DBG_CompleteQuests()
{
CTFPlayer *pPlayer = ToTFPlayer( UTIL_GetCommandClient() );
if ( !pPlayer )
return;
CSteamID steamIDForPlayer;
if ( !pPlayer->GetSteamID( &steamIDForPlayer ) )
return;
CTFPlayerInventory* pInv = TFInventoryManager()->GetInventoryForPlayer( steamIDForPlayer );
if ( pInv )
{
int iCount = pInv->GetItemCount();
for ( int i = 0; i < iCount; i++ )
{
CEconItemView *pItem = pInv->GetItem(i);
if ( !pItem )
continue;
if( !pItem->GetStaticData() || !pItem->GetStaticData()->GetQuestDef() )
continue;
CQuestItemTracker* pTracker = assert_cast<CQuestItemTracker*>( GetTracker( pItem->GetItemID() ) );
if ( pTracker )
{
pTracker->DBG_CompleteQuest();
}
}
}
}
#endif // ( defined( DEBUG ) || defined( STAGING_ONLY ) ) && defined( GAME_DLL )