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.
1174 lines
37 KiB
1174 lines
37 KiB
5 years ago
|
//========= 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 );
|
||
|
}
|