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.
1173 lines
37 KiB
1173 lines
37 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Shared interface to the tech tree & individual technologies |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
#include "cbase.h" |
|
|
|
#ifndef CLIENT_DLL |
|
#include "tf_player.h" |
|
#include "tf_team.h" |
|
#include "info_customtech.h" |
|
#endif |
|
#include "techtree.h" |
|
|
|
bool ParseTechnologyFile( CUtlVector< CBaseTechnology* > &pTechnologyList, IFileSystem* pFileSystem, int nTeamNumber, char *sFileName ); |
|
|
|
// Color codes for resources |
|
rescolor sResourceColor = { 64, 255, 64 }; |
|
|
|
// Prototype names for resources |
|
char sResourceName[] = "Jojierium"; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CBaseTechnology::CBaseTechnology( void ) |
|
{ |
|
m_nTechLevel = 0; |
|
ZeroPreferences(); |
|
SetAvailable( false ); |
|
SetActive( false ); |
|
SetPreferred( false ); |
|
SetVoters( 0 ); |
|
SetCost( 0 ); |
|
SetDirty( false ); |
|
m_fResourceLevel = 0; |
|
memset( m_ClassResults, 0, sizeof( m_ClassResults ) ); |
|
memset( m_pszName, 0, sizeof( m_pszName ) ); |
|
memset( m_pszPrintName, 0, sizeof( m_pszPrintName ) ); |
|
memset( m_pszDescription, 0, sizeof( m_pszDescription ) ); |
|
memset( m_pszTeamSoundFile, 0, sizeof( m_pszTeamSoundFile ) ); |
|
memset( m_apszContainedTechs, 0, sizeof( m_apszContainedTechs ) ); |
|
memset( m_pContainedTechs, 0, sizeof(m_pContainedTechs) ); |
|
memset( m_apszDependentTechs, 0, sizeof( m_apszDependentTechs ) ); |
|
memset( m_pDependentTechs, 0, sizeof(m_pDependentTechs) ); |
|
m_iContainedTechs = 0; |
|
m_iDependentTechs = 0; |
|
m_iTeamSound = 0; |
|
m_bGoalTechnology = false; |
|
m_bClassUpgrade = false; |
|
m_bVehicle = false; |
|
m_bTechLevelUpgrade = false; |
|
m_bResourceTech = false; |
|
|
|
memset( m_szTextureName, 0, sizeof( m_szTextureName ) ); |
|
m_nTextureID = 0; |
|
|
|
memset( m_szButtonName, 0, sizeof( m_szButtonName ) ); |
|
|
|
m_nNumWeaponAssociations = 0; |
|
memset( m_rgszWeaponAssociation, 0, sizeof( m_rgszWeaponAssociation ) ); |
|
|
|
SetHidden( false ); |
|
ResetHintsGiven(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CBaseTechnology::~CBaseTechnology( void ) |
|
{ |
|
} |
|
|
|
static bool NameStartsWith( const char *name, const char *prefix ) |
|
{ |
|
if ( !name || !name[ 0 ] || !prefix || !prefix[ 0 ] ) |
|
return false; |
|
|
|
if ( !strnicmp( name, prefix, strlen( prefix ) ) ) |
|
return true; |
|
|
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Set the technology name |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetName( const char *pName ) |
|
{ |
|
Q_strncpy( m_pszName, pName, sizeof(m_pszName) ); |
|
|
|
// Determine special information about this technology |
|
m_bClassUpgrade = NameStartsWith( pName, "class_" ); |
|
m_bVehicle = NameStartsWith( pName, "vehicle_" ); |
|
m_bTechLevelUpgrade = NameStartsWith( pName, "tech_level_" ); |
|
// HACK: Assume global techs relate to resources for now |
|
m_bResourceTech = NameStartsWith( pName, "g_" ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Set the technology print name |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetPrintName( const char *pName ) |
|
{ |
|
Q_strncpy( m_pszPrintName, pName, sizeof(m_pszPrintName) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Set the technology description |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetDescription( const char *pDesc ) |
|
{ |
|
Q_strncpy( m_pszDescription, pDesc, sizeof(m_pszDescription) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *pName - |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetButtonName( const char *pName ) |
|
{ |
|
Q_strncpy( m_szButtonName, pName, sizeof(m_szButtonName) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Set the technology level |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetLevel( int iLevel ) |
|
{ |
|
m_nTechLevel = iLevel; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *texture - |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetTextureName( const char *texture ) |
|
{ |
|
Q_strncpy( m_szTextureName, texture, sizeof( m_szTextureName ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : id - |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetTextureId( int id ) |
|
{ |
|
m_nTextureID = id; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Set the technologies resource costs |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetCost( float fResourceCost ) |
|
{ |
|
m_fResourceCost = fResourceCost; |
|
|
|
RecalculateOverallLevel(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Set a specific class's sound |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetClassResultSound( int iClass, const char *pSound ) |
|
{ |
|
if (!pSound) |
|
return; |
|
|
|
Assert( iClass >= 0 && iClass < TFCLASS_CLASS_COUNT ); |
|
|
|
// Class of 0 is the team's sound file |
|
if ( iClass == 0 ) |
|
{ |
|
Q_strncpy( m_pszTeamSoundFile, pSound, sizeof(m_pszTeamSoundFile) ); |
|
} |
|
else |
|
{ |
|
m_ClassResults[iClass].bClassTouched = true; |
|
Q_strncpy( m_ClassResults[iClass].pszSoundFile, pSound, sizeof(m_ClassResults[iClass].pszSoundFile) ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : associate - |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetClassResultAssociateWeapons( int iClass, bool associate ) |
|
{ |
|
Assert( iClass >= 0 && iClass < TFCLASS_CLASS_COUNT ); |
|
|
|
m_ClassResults[iClass].m_bAssociateWeaponsForClass = associate; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Set a specific class's precached sound |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetClassResultSound( int iClass, int iSound ) |
|
{ |
|
Assert( iClass >= 0 && iClass < TFCLASS_CLASS_COUNT ); |
|
|
|
// Class of 0 is the team's sound file |
|
if ( iClass == 0 ) |
|
{ |
|
m_iTeamSound = iSound; |
|
} |
|
else |
|
{ |
|
m_ClassResults[iClass].iSound = iSound; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Set a specific class's description |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetClassResultDescription( int iClass, const char *pDesc ) |
|
{ |
|
if (!pDesc) |
|
return; |
|
|
|
Assert( iClass > 0 && iClass < TFCLASS_CLASS_COUNT ); |
|
m_ClassResults[iClass].bClassTouched = true; |
|
|
|
Q_strncpy( m_ClassResults[iClass].pszDescription, pDesc, sizeof(m_ClassResults[iClass].pszDescription) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Add a technology contained within this one |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::AddContainedTechnology( const char *pszTech ) |
|
{ |
|
Q_strncpy( m_apszContainedTechs[ m_iContainedTechs ], pszTech, sizeof(m_apszContainedTechs[0]) ); |
|
m_iContainedTechs++; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Add a technology dependency within this one |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::AddDependentTechnology( const char *pszTech ) |
|
{ |
|
Q_strncpy( m_apszDependentTechs[ m_iDependentTechs ], pszTech, sizeof(m_apszDependentTechs[0]) ); |
|
m_iDependentTechs++; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Returns true if this technology affects the specified class |
|
//----------------------------------------------------------------------------- |
|
bool CBaseTechnology::AffectsClass( int iClass ) |
|
{ |
|
// If this technology directly affects this class, return true |
|
if ( m_ClassResults[ iClass ].bClassTouched ) |
|
return true; |
|
|
|
// If not, do any of our contained techs affect the specified class |
|
for (int i = 0; i < m_iContainedTechs; i++ ) |
|
{ |
|
if ( m_pContainedTechs[i] ) |
|
{ |
|
if ( m_pContainedTechs[i]->AffectsClass( iClass ) ) |
|
return true; |
|
} |
|
} |
|
|
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CBaseTechnology::IsClassUpgrade( void ) |
|
{ |
|
return m_bClassUpgrade; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CBaseTechnology::IsVehicle( void ) |
|
{ |
|
return m_bVehicle; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CBaseTechnology::IsResourceTech( void ) |
|
{ |
|
return m_bResourceTech; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CBaseTechnology::IsTechLevelUpgrade( void ) |
|
{ |
|
return m_bTechLevelUpgrade; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Returns the level to which this technology belongs |
|
// Output : int |
|
//----------------------------------------------------------------------------- |
|
int CBaseTechnology::GetLevel( void ) |
|
{ |
|
return m_nTechLevel; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Cost of technology in resource specified |
|
//----------------------------------------------------------------------------- |
|
float CBaseTechnology::GetResourceCost( void ) |
|
{ |
|
return m_fResourceCost; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Retrieves the current amount of resources spent on the technology |
|
//----------------------------------------------------------------------------- |
|
float CBaseTechnology::GetResourceLevel( void ) |
|
{ |
|
return m_fResourceLevel; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Sets a resource level to an amount |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetResourceLevel( float flResourceLevel ) |
|
{ |
|
if ( m_fResourceLevel == flResourceLevel ) |
|
return; |
|
|
|
m_fResourceLevel = flResourceLevel; |
|
|
|
// Update my level & watchers |
|
RecalculateOverallLevel(); |
|
UpdateWatchers(); |
|
|
|
// Force me to be resent to clients |
|
SetDirty( true ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Increase the level of the specified resource spent on this technology |
|
// Output : Returns true if the technology's had enough resources to be bought |
|
//----------------------------------------------------------------------------- |
|
bool CBaseTechnology::IncreaseResourceLevel( float flResourcesToSpend ) |
|
{ |
|
SetResourceLevel( m_fResourceLevel + flResourcesToSpend ); |
|
|
|
// Have my costs been met? |
|
if ( GetResourceLevel() < GetResourceCost() ) |
|
return false; |
|
|
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Figure out my overall owned percentage |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::RecalculateOverallLevel( void ) |
|
{ |
|
if ( !GetResourceCost() ) |
|
{ |
|
m_flOverallOwnedPercentage = 0; |
|
} |
|
else |
|
{ |
|
m_flOverallOwnedPercentage = GetResourceLevel() / GetResourceCost(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
float CBaseTechnology::GetOverallLevel( void ) |
|
{ |
|
return m_flOverallOwnedPercentage; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Force this technology to complete itself |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::ForceComplete( void ) |
|
{ |
|
SetResourceLevel( GetResourceCost() ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CBaseTechnology::IsAGoalTechnology( void ) |
|
{ |
|
return m_bGoalTechnology; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetGoalTechnology( bool bGoal ) |
|
{ |
|
m_bGoalTechnology = bGoal; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Returns the name of this technology |
|
// Output : const |
|
//----------------------------------------------------------------------------- |
|
const char *CBaseTechnology::GetName( void ) |
|
{ |
|
return m_pszName; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Returns printable name of this technology |
|
// Output : const |
|
//----------------------------------------------------------------------------- |
|
const char *CBaseTechnology::GetPrintName( void ) |
|
{ |
|
return m_pszPrintName; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : const char |
|
//----------------------------------------------------------------------------- |
|
const char *CBaseTechnology::GetButtonName( void ) |
|
{ |
|
return m_szButtonName; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : const char |
|
//----------------------------------------------------------------------------- |
|
const char *CBaseTechnology::GetTextureName(void ) |
|
{ |
|
return m_szTextureName; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : int |
|
//----------------------------------------------------------------------------- |
|
int CBaseTechnology::GetTextureId( void ) |
|
{ |
|
return m_nTextureID; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Returns description for item |
|
// Output : const char |
|
//----------------------------------------------------------------------------- |
|
const char *CBaseTechnology::GetDescription( int iPlayerClass ) |
|
{ |
|
// If we have a custom description for the local player's class, return that instead |
|
if ( AffectsClass( iPlayerClass ) ) |
|
{ |
|
if ( m_ClassResults[iPlayerClass].pszDescription ) |
|
return m_ClassResults[iPlayerClass].pszDescription; |
|
} |
|
|
|
// Otherwise, return the general description |
|
return m_pszDescription; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Returns sound filename to play for this technology |
|
//----------------------------------------------------------------------------- |
|
const char *CBaseTechnology::GetSoundFile( int iClass ) |
|
{ |
|
// Class of 0 is the team sound |
|
if ( !iClass ) |
|
return m_pszTeamSoundFile; |
|
|
|
Assert(iClass > 0 && iClass < TFCLASS_CLASS_COUNT ); |
|
return m_ClassResults[iClass].pszSoundFile; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Returns sound to play for this technology |
|
//----------------------------------------------------------------------------- |
|
int CBaseTechnology::GetSound( int iClass ) |
|
{ |
|
// Class of 0 is the team sound |
|
if ( !iClass ) |
|
return m_iTeamSound; |
|
|
|
Assert(iClass > 0 && iClass < TFCLASS_CLASS_COUNT ); |
|
return m_ClassResults[iClass].iSound; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : iClass - |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CBaseTechnology::GetAssociateWeaponsForClass( int iClass ) |
|
{ |
|
if ( !iClass ) |
|
return false; |
|
|
|
Assert(iClass > 0 && iClass < TFCLASS_CLASS_COUNT ); |
|
return m_ClassResults[iClass].m_bAssociateWeaponsForClass; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Returns whether the technology is available to the team |
|
// Input : state - |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetAvailable( bool state ) |
|
{ |
|
if ( state != m_bAvailable ) |
|
{ |
|
SetDirty( true ); |
|
} |
|
|
|
m_bAvailable = state; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Determine whether team posses the technology |
|
// Output : Returns 1 if available, 0 otherwise |
|
//----------------------------------------------------------------------------- |
|
int CBaseTechnology::GetAvailable( void ) |
|
{ |
|
return m_bAvailable; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Zero out team preference counters |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::ZeroPreferences( void ) |
|
{ |
|
if ( m_nPreferenceCount ) |
|
{ |
|
SetDirty( true ); |
|
} |
|
|
|
m_nPreferenceCount = 0; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Increment preference counter |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::IncrementPreferences( void ) |
|
{ |
|
m_nPreferenceCount++; |
|
SetDirty( true ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Retrieve preference count |
|
//----------------------------------------------------------------------------- |
|
int CBaseTechnology::GetPreferenceCount( void ) |
|
{ |
|
return m_nPreferenceCount; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
int CBaseTechnology::GetNumWeaponAssociations( void ) |
|
{ |
|
return m_nNumWeaponAssociations; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : char const |
|
//----------------------------------------------------------------------------- |
|
const char *CBaseTechnology::GetAssociatedWeapon( int index ) |
|
{ |
|
if ( index < 0 || index >= m_nNumWeaponAssociations ) |
|
{ |
|
return ""; |
|
} |
|
|
|
return m_rgszWeaponAssociation[ index ]; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *weaponname - |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::AddAssociatedWeapon( const char *weaponname ) |
|
{ |
|
if ( m_nNumWeaponAssociations >= MAX_ASSOCIATED_WEAPONS ) |
|
{ |
|
Assert( !"CBaseTechnology::AddAssociatedWeapon: m_nNumWeaponAssociations >= MAX_ASSOCIATED_WEAPONS" ); |
|
return; |
|
} |
|
Q_strncpy( m_rgszWeaponAssociation[ m_nNumWeaponAssociations++ ], weaponname, TECHNOLOGY_WEAPONNAME_LENGTH ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int CBaseTechnology::GetNumberContainedTechs( void ) |
|
{ |
|
return m_iContainedTechs; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
const char *CBaseTechnology::GetContainedTechName( int iTech ) |
|
{ |
|
Assert( iTech >= 0 && iTech < m_iContainedTechs ); |
|
return m_apszContainedTechs[ iTech ]; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetContainedTech( int iTech, CBaseTechnology *pTech ) |
|
{ |
|
Assert( iTech >= 0 && iTech < m_iContainedTechs ); |
|
m_pContainedTechs[iTech] = pTech; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int CBaseTechnology::GetNumberDependentTechs( void ) |
|
{ |
|
return m_iDependentTechs; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
const char *CBaseTechnology::GetDependentTechName( int iTech ) |
|
{ |
|
Assert( iTech >= 0 && iTech < m_iDependentTechs ); |
|
return m_apszDependentTechs[ iTech ]; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetDependentTech( int iTech, CBaseTechnology *pTech ) |
|
{ |
|
Assert( iTech >= 0 && iTech < m_iDependentTechs ); |
|
Assert( pTech ); |
|
m_pDependentTechs[iTech] = pTech; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Return true if this tech depends on the specified tech |
|
//----------------------------------------------------------------------------- |
|
bool CBaseTechnology::DependsOn( CBaseTechnology *pTech ) |
|
{ |
|
for ( int i = 0; i < GetNumberDependentTechs(); i++ ) |
|
{ |
|
if ( m_pDependentTechs[i] == pTech ) |
|
return true; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Return true if this tech has a dependent tech that's not been completed yet |
|
//----------------------------------------------------------------------------- |
|
bool CBaseTechnology::HasInactiveDependencies( void ) |
|
{ |
|
for ( int i = 0; i < GetNumberDependentTechs(); i++ ) |
|
{ |
|
// This condition can occur if there's a bug in the .txt file |
|
// where a tech is told to depend on a non-existent tech |
|
if (!m_pDependentTechs[i]) |
|
continue; |
|
|
|
// Client uses m_bActive, Server uses m_bAvailable (?) |
|
if ( m_pDependentTechs[i]->GetAvailable() == false && m_pDependentTechs[i]->GetActive() == false ) |
|
return true; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Dirty bit, used for fast knowledge of when to resend techs |
|
//----------------------------------------------------------------------------- |
|
bool CBaseTechnology::IsDirty( void ) |
|
{ |
|
return m_bDirty; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetDirty( bool bDirty ) |
|
{ |
|
m_bDirty = bDirty; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Set availability state for item |
|
// Input : state - |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetActive( bool state ) |
|
{ |
|
m_bActive = state; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Retrieve availability state |
|
//----------------------------------------------------------------------------- |
|
bool CBaseTechnology::GetActive( void ) |
|
{ |
|
return m_bActive; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Set whether this is our local preferred item |
|
// Input : state - |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetPreferred( bool state ) |
|
{ |
|
m_bPreferred = state; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Retrieve local preferred state |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CBaseTechnology::GetPreferred( void ) |
|
{ |
|
return m_bPreferred; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Set the number of players preferring this tech |
|
// Input : voters - |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetVoters( int voters ) |
|
{ |
|
m_nVoters = voters; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Get the number of players preferring this tech |
|
// Output : int |
|
//----------------------------------------------------------------------------- |
|
int CBaseTechnology::GetVoters( void ) |
|
{ |
|
return m_nVoters; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : hide - |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetHidden( bool hide ) |
|
{ |
|
m_bHidden = hide; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CBaseTechnology::IsHidden( void ) |
|
{ |
|
return m_bHidden; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::ResetHintsGiven( void ) |
|
{ |
|
m_HintsGiven.RemoveAll(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CBaseTechnology::GetHintsGiven( int type ) |
|
{ |
|
if ( m_HintsGiven.Find( type ) != m_HintsGiven.InvalidIndex() ) |
|
{ |
|
return true; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : given - |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::SetHintsGiven( int type, bool given ) |
|
{ |
|
if ( given ) |
|
{ |
|
if ( m_HintsGiven.Find( type ) != m_HintsGiven.InvalidIndex() ) |
|
return; |
|
|
|
m_HintsGiven.AddToTail( type ); |
|
} |
|
else |
|
{ |
|
int idx = m_HintsGiven.Find( type ); |
|
if ( idx == m_HintsGiven.InvalidIndex() ) |
|
return; |
|
|
|
m_HintsGiven.Remove( idx ); |
|
} |
|
} |
|
|
|
//==================================================================================================================== |
|
// EVIL GAME DLL ONLY CODE FOR TECHNOLOGIES |
|
//==================================================================================================================== |
|
#ifndef CLIENT_DLL |
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::AddTechnologyToPlayer( CBaseTFPlayer *pPlayer ) |
|
{ |
|
// Tell playerclasses listed to recalculate their technologies, only if they're listed in the class results |
|
if ( pPlayer->PlayerClass() ) |
|
{ |
|
if ( m_ClassResults[ pPlayer->PlayerClass() ].bClassTouched ) |
|
{ |
|
CPlayerClass *pPlayerClass = pPlayer->GetPlayerClass(); |
|
pPlayerClass->GainedNewTechnology( this ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::AddTechnologyToTeam( CTFTeam *pTeam ) |
|
{ |
|
SetAvailable( true ); |
|
|
|
// Enable all the technologies this group contains |
|
if ( m_iContainedTechs ) |
|
{ |
|
for (int i = 0; i < m_iContainedTechs; i++ ) |
|
{ |
|
if ( m_pContainedTechs[i] ) |
|
{ |
|
pTeam->EnableTechnology( m_pContainedTechs[i] ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: A technology watcher entity wants to register as a watcher for this technology |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::RegisterWatcher( CInfoCustomTechnology *pWatcher ) |
|
{ |
|
m_aWatchers.AddToTail( pWatcher ); |
|
pWatcher->UpdateTechPercentage( 0 ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::UpdateWatchers( void ) |
|
{ |
|
// Tell all my watchers |
|
for (int i = 0; i < m_aWatchers.Size(); i++ ) |
|
{ |
|
m_aWatchers[i]->UpdateTechPercentage( GetOverallLevel() ); |
|
} |
|
} |
|
#else |
|
//----------------------------------------------------------------------------- |
|
// Purpose: Client DLL UpdateWatchers does nothing |
|
//----------------------------------------------------------------------------- |
|
void CBaseTechnology::UpdateWatchers( void ) |
|
{ |
|
} |
|
#endif |
|
|
|
|
|
|
|
|
|
//==================================================================================================================== |
|
// SHARED TECHNOLOGY TREE |
|
//==================================================================================================================== |
|
//----------------------------------------------------------------------------- |
|
// Purpose: Construct raw technology tree |
|
// Output : |
|
//----------------------------------------------------------------------------- |
|
CTechnologyTree::CTechnologyTree( IFileSystem* pFileSystem, int nTeamNumber ) |
|
{ |
|
// Reset preference counter |
|
ClearPreferenceCount(); |
|
|
|
// Parse the list from the data file |
|
if ( ParseTechnologyFile( m_Technologies, pFileSystem, nTeamNumber, "scripts/technologytree.txt" ) == false ) |
|
{ |
|
Assert(0); |
|
return; |
|
} |
|
|
|
LinkContainedTechnologies(); |
|
LinkDependentTechnologies(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Link all the contained technologies |
|
//----------------------------------------------------------------------------- |
|
void CTechnologyTree::LinkContainedTechnologies( void ) |
|
{ |
|
for ( int i=0; i < m_Technologies.Size(); i++) |
|
{ |
|
for ( int j = 0; j < m_Technologies[i]->GetNumberContainedTechs(); j++ ) |
|
{ |
|
const char *pName = m_Technologies[i]->GetContainedTechName( j ); |
|
CBaseTechnology *pTech = GetTechnology( pName ); |
|
if ( pTech ) |
|
{ |
|
m_Technologies[i]->SetContainedTech( j, pTech ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Link all the dependent technologies |
|
//----------------------------------------------------------------------------- |
|
void CTechnologyTree::LinkDependentTechnologies( void ) |
|
{ |
|
for ( int i=0; i < m_Technologies.Size(); i++) |
|
{ |
|
for ( int j = 0; j < m_Technologies[i]->GetNumberDependentTechs(); j++ ) |
|
{ |
|
const char *pName = m_Technologies[i]->GetDependentTechName( j ); |
|
CBaseTechnology *pTech = GetTechnology( pName ); |
|
if ( pTech ) |
|
{ |
|
m_Technologies[i]->SetDependentTech( j, pTech ); |
|
} |
|
else |
|
{ |
|
Warning("Unable to find dependent technology %s!\n", pName ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CTechnologyTree::~CTechnologyTree( void ) |
|
{ |
|
Shutdown(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Delete all items in the tree |
|
//----------------------------------------------------------------------------- |
|
void CTechnologyTree::Shutdown( void ) |
|
{ |
|
// Loop through all used items |
|
int iSize = m_Technologies.Size(); |
|
for ( int i = iSize-1; i >= 0; i-- ) |
|
{ |
|
CBaseTechnology *pItem = m_Technologies[ i ]; |
|
delete pItem; |
|
} |
|
m_Technologies.Purge(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Add a new technology to the tree |
|
//----------------------------------------------------------------------------- |
|
void CTechnologyTree::AddTechnologyFile( IFileSystem* pFileSystem, int nTeamNumber, char *sFileName ) |
|
{ |
|
ParseTechnologyFile( m_Technologies, pFileSystem, nTeamNumber, sFileName ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Get the index of the specified item |
|
//----------------------------------------------------------------------------- |
|
int CTechnologyTree::GetIndex( CBaseTechnology *pItem ) |
|
{ |
|
for ( int i=0; i < m_Technologies.Size(); i++) |
|
{ |
|
if ( m_Technologies[i] == pItem ) |
|
return i; |
|
} |
|
|
|
return -1; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Retrieve item by index |
|
//----------------------------------------------------------------------------- |
|
CBaseTechnology *CTechnologyTree::GetTechnology( int index ) |
|
{ |
|
if ( index < 0 || index >= m_Technologies.Size() ) |
|
return NULL; |
|
|
|
return m_Technologies[ index ]; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CBaseTechnology* CTechnologyTree::GetTechnology( const char *pName ) |
|
{ |
|
for ( int i=0; i < m_Technologies.Size(); i++) |
|
{ |
|
if( stricmp( pName, m_Technologies[i]->GetName() ) == 0 ) |
|
return m_Technologies[i]; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Return current number of objects |
|
// Output : int |
|
//----------------------------------------------------------------------------- |
|
int CTechnologyTree::GetNumberTechnologies( void ) |
|
{ |
|
return m_Technologies.Size(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Set preferred item ( turns off all other preferences first ) |
|
//----------------------------------------------------------------------------- |
|
void CTechnologyTree::SetPreferredTechnology( CBaseTechnology *pItem ) |
|
{ |
|
// Turn all of the others off |
|
for ( int i = 0; i < m_Technologies.Size(); i++ ) |
|
{ |
|
CBaseTechnology *item = m_Technologies[ i ]; |
|
item->SetPreferred( false ); |
|
} |
|
|
|
// Turn this one on |
|
if ( pItem ) |
|
{ |
|
pItem->SetPreferred( true ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Get the technology preferred by this client |
|
//----------------------------------------------------------------------------- |
|
CBaseTechnology* CTechnologyTree::GetPreferredTechnology( void ) |
|
{ |
|
// Turn all of the others off |
|
for ( int i = 0; i < m_Technologies.Size(); i++ ) |
|
{ |
|
CBaseTechnology *item = m_Technologies[ i ]; |
|
if ( item->GetPreferred() ) |
|
return item; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Get the number of players who've voted on techs |
|
//----------------------------------------------------------------------------- |
|
int CTechnologyTree::GetPreferenceCount( void ) |
|
{ |
|
return m_nPreferenceCount; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Zero global preference counters |
|
//----------------------------------------------------------------------------- |
|
void CTechnologyTree::ClearPreferenceCount( void ) |
|
{ |
|
m_nPreferenceCount = 0; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Increment preference counter |
|
//----------------------------------------------------------------------------- |
|
void CTechnologyTree::IncrementPreferences( void ) |
|
{ |
|
m_nPreferenceCount++; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Return the most voted-for technologies |
|
// Input : iDesireLevel: 1 = Most voted for, 2 = 2nd most voted for, etc |
|
//----------------------------------------------------------------------------- |
|
CBaseTechnology *CTechnologyTree::GetDesiredTechnology( int iDesireLevel ) |
|
{ |
|
Assert( iDesireLevel > 0 && iDesireLevel < m_Technologies.Size() ); |
|
|
|
// Dump the techs into a temporary array |
|
CBaseTechnology *pSortedTechs[ MAX_TECHNOLOGIES ]; |
|
int iMaxTech = 0; |
|
for ( int i = 0; i < m_Technologies.Size(); i++ ) |
|
{ |
|
// Skip Techs that are already available |
|
CBaseTechnology *technology = m_Technologies[i]; |
|
if(!technology) |
|
continue; |
|
|
|
if ( technology->GetAvailable() == false ) |
|
{ |
|
pSortedTechs[iMaxTech] = m_Technologies[i]; |
|
iMaxTech++; |
|
} |
|
} |
|
|
|
// Not enough unresearched techs? |
|
if ( iMaxTech < iDesireLevel ) |
|
return NULL; |
|
|
|
// Bubble sort the tech array into order of desire |
|
int swapped = 1; |
|
while ( swapped ) |
|
{ |
|
swapped = 0; |
|
for ( int i = 1; i < iMaxTech; i++ ) |
|
{ |
|
if ( pSortedTechs[i]->GetPreferenceCount() > pSortedTechs[i-1]->GetPreferenceCount() ) |
|
{ |
|
CBaseTechnology *pTemp = pSortedTechs[i]; |
|
pSortedTechs[i] = pSortedTechs[i-1]; |
|
pSortedTechs[i-1] = pTemp; |
|
swapped = 1; |
|
} |
|
} |
|
} |
|
|
|
return pSortedTechs[ iDesireLevel - 1 ]; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Find out what percentage of techs in a given level this team owns |
|
//----------------------------------------------------------------------------- |
|
float CTechnologyTree::GetPercentageOfTechLevelOwned( int iTechLevel ) |
|
{ |
|
float fTotalTechs = 0; |
|
float fTechsOwned = 0; |
|
|
|
for ( int i = 0; i < m_Technologies.Size(); i++ ) |
|
{ |
|
CBaseTechnology *technology = m_Technologies[i]; |
|
if ( !technology ) |
|
continue; |
|
|
|
if ( technology->GetLevel() != iTechLevel ) |
|
continue; |
|
|
|
fTotalTechs++; |
|
|
|
// Do we have it? |
|
if ( technology->GetAvailable() ) |
|
{ |
|
fTechsOwned++; |
|
} |
|
} |
|
|
|
if ( !fTotalTechs ) |
|
return 0.0; |
|
|
|
return ( fTechsOwned / fTotalTechs ); |
|
}
|
|
|