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.

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 );
}