//========= Copyright Valve Corporation, All rights reserved. ============// // //============================================================================= #ifndef TF_ACHIEVEMENT_DATA_H #define TF_ACHIEVEMENT_DATA_H #pragma once #include "UtlSortVector.h" #define MAX_ACHIEVEMENT_HISTORY_SLOTS 4 #define MAX_ACHIEVEMENT_DAMAGE_HISTORY_SLOTS 128 //============================================================================= // Custom class to manage lists of history events. Maintains a prioritized list of // events, but includes two extra features: // - Maximum size of the number of entries in the queue. // - Ensures each associated-entity in the entries appears only once in the queue. template class CHistoryVector : public CUtlSortVector { public: CHistoryVector() { } void InsertHistory( T const &element ) { LessFunc less; // Make sure it's not in the list already for ( int i = 0; i < this->Count(); i++ ) { if ( less.HistoryMatch( this->Element(i), element ) ) { this->Remove( i ); break; } } CUtlSortVector::Insert( element ); // Remove the oldest entry if we're over max size if ( this->Count() > maxSize ) { this->Remove( this->Count()-1 ); } } }; //============================================================================= // Data stored in players for achievement handling struct EntityHistory_t { EHANDLE hEntity; EHANDLE hObject; float flTimeDamage; }; struct EntityDamageHistory_t : public EntityHistory_t { int nDamageAmount; }; class CEntityHistoryLess { public: bool Less( const EntityHistory_t &dmg1, const EntityHistory_t &dmg2, void *pCtx ) { return (dmg1.flTimeDamage > dmg2.flTimeDamage); } bool HistoryMatch( const EntityHistory_t &dmg1, const EntityHistory_t &dmg2 ) { return (dmg1.hEntity == dmg2.hEntity); } }; // Allow duplicate (source) entries with this type; HistoryMatch always returns false class CEntityDamageHistoryLess { public: bool Less( const EntityDamageHistory_t &dmg1, const EntityDamageHistory_t &dmg2, void *pCtx ) { return ( dmg2.flTimeDamage < dmg1.flTimeDamage ); } bool HistoryMatch( const EntityDamageHistory_t &dmg1, const EntityDamageHistory_t &dmg2 ) { return false; } }; // Achievement Tracking container class CAchievementData { public: void ClearHistories( void ) { aDamagers.RemoveAll(); aDamageEvents.RemoveAll(); aTargets.RemoveAll(); aSentryDamagers.RemoveAll(); aPushers.RemoveAll(); } void AddDamagerToHistory( EHANDLE hDamager ); EntityHistory_t *GetDamagerHistory( int i ) { if (i >= aDamagers.Count()) return NULL; return &aDamagers[i]; } int CountDamagersWithinTime( float flTime ); bool IsDamagerInHistory( CBaseEntity *pTarget, float flTimeWindow ); void DumpDamagers( void ); // Capture the last 64 damage events - duplicates allowed void AddDamageEventToHistory( EHANDLE hAttacker, float flDmgAmount = 0.f ); EntityDamageHistory_t *GetDamageEventHistory( int i ) { if ( i >= aDamageEvents.Count() ) return NULL; return &aDamageEvents[i]; } int GetDamageEventHistoryCount( void ) { return aDamageEvents.Count(); } bool IsEntityInDamageEventHistory( CBaseEntity *pEntity, float flTimeWindow ); int GetAmountForDamagerInEventHistory( CBaseEntity *pEntity, float flTimeWindow ); void AddTargetToHistory( EHANDLE hTarget ); bool IsTargetInHistory( CBaseEntity *pTarget, float flTimeWindow ); EntityHistory_t *GetTargetHistory( int i ) { if (i >= aTargets.Count()) return NULL; return &aTargets[i]; } int CountTargetsWithinTime( float flTime ); void AddSentryDamager( EHANDLE hDamager, EHANDLE hObject ); EntityHistory_t *IsSentryDamagerInHistory( CBaseEntity *pDamager, float flTimeWindow ); void AddPusherToHistory( EHANDLE hPlayer ); bool IsPusherInHistory( CBaseEntity *pPlayer, float flTimeWindow ); private: CHistoryVector< EntityHistory_t, CEntityHistoryLess, MAX_ACHIEVEMENT_HISTORY_SLOTS > aDamagers; CHistoryVector< EntityDamageHistory_t, CEntityDamageHistoryLess, MAX_ACHIEVEMENT_DAMAGE_HISTORY_SLOTS > aDamageEvents; // Duplicates allowed CHistoryVector< EntityHistory_t, CEntityHistoryLess, MAX_ACHIEVEMENT_HISTORY_SLOTS > aTargets; CHistoryVector< EntityHistory_t, CEntityHistoryLess, MAX_ACHIEVEMENT_HISTORY_SLOTS > aSentryDamagers; CHistoryVector< EntityHistory_t, CEntityHistoryLess, MAX_ACHIEVEMENT_HISTORY_SLOTS > aPushers; }; #endif