diff options
Diffstat (limited to 'game/shared/tf2/tf_shareddefs.cpp')
| -rw-r--r-- | game/shared/tf2/tf_shareddefs.cpp | 605 |
1 files changed, 605 insertions, 0 deletions
diff --git a/game/shared/tf2/tf_shareddefs.cpp b/game/shared/tf2/tf_shareddefs.cpp new file mode 100644 index 0000000..32d63be --- /dev/null +++ b/game/shared/tf2/tf_shareddefs.cpp @@ -0,0 +1,605 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Data shared between the client & game dlls +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "tf_shareddefs.h" +#include "tier0/dbg.h" +#include "basetypes.h" +#include <KeyValues.h> + +#ifndef CLIENT_DLL + + #include "tf_team.h" + #include "tf_class_commando.h" + #include "tf_class_defender.h" + #include "tf_class_escort.h" + #include "tf_class_infiltrator.h" + #include "tf_class_medic.h" + #include "tf_class_recon.h" + #include "tf_class_sniper.h" + #include "tf_class_support.h" + #include "tf_class_sapper.h" + #include "tf_class_pyro.h" + +#else + + #include "c_tfteam.h" + #include "c_tf_class_commando.h" + #include "c_tf_class_defender.h" + #include "c_tf_class_escort.h" + #include "c_tf_class_infiltrator.h" + #include "c_tf_class_medic.h" + #include "c_tf_class_recon.h" + #include "c_tf_class_sniper.h" + #include "c_tf_class_support.h" + #include "c_tf_class_sapper.h" + #include "c_tf_class_pyro.h" + +#define CTFTeam C_TFTeam +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +ConVar inv_demo( "inv_demo","0", FCVAR_REPLICATED, "Invasion demo." ); +ConVar lod_effect_distance( "lod_effect_distance","3240000", FCVAR_REPLICATED, "Distance at which effects LOD." ); +ConVar tf_cheapobjects( "tf_cheapobjects","0", FCVAR_REPLICATED, "Set to 1 and all objects will cost 0" ); + + +//-------------------------------------------------------------------------- +// OBJECTS +//-------------------------------------------------------------------------- +static int g_iClassInfo_Undecided[] = +{ + OBJ_LAST +}; + +static int g_iClassInfo_Recon[] = +{ + OBJ_WAGON, + OBJ_LAST +}; + +static int g_iClassInfo_Commando[] = +{ + OBJ_POWERPACK, + OBJ_VEHICLE_BOOST, + OBJ_DRAGONSTEETH, + OBJ_MANNED_MISSILELAUNCHER, + OBJ_SANDBAG_BUNKER, + OBJ_DRAGONSTEETH, + + OBJ_LAST +}; + +static int g_iClassInfo_Medic[] = +{ + OBJ_POWERPACK, + OBJ_SELFHEAL, + OBJ_BUFF_STATION, + OBJ_MANNED_PLASMAGUN, + OBJ_SANDBAG_BUNKER, + OBJ_BUNKER, + OBJ_DRAGONSTEETH, + OBJ_SHIELDWALL, + + OBJ_LAST +}; + +static int g_iClassInfo_Defender[] = +{ + OBJ_POWERPACK, + OBJ_SENTRYGUN_PLASMA, + OBJ_MANNED_MISSILELAUNCHER, + OBJ_BARBED_WIRE, + OBJ_DRAGONSTEETH, + OBJ_TOWER, + OBJ_SANDBAG_BUNKER, + OBJ_BUNKER, + OBJ_DRIVER_MACHINEGUN, + //OBJ_MORTAR, + + OBJ_LAST +}; + +static int g_iClassInfo_Sniper[] = +{ + OBJ_WAGON, + OBJ_LAST +}; + +static int g_iClassInfo_Support[] = +{ + OBJ_WAGON, + OBJ_LAST +}; + +static int g_iClassInfo_Escort[] = +{ + OBJ_SHIELDWALL, + OBJ_MANNED_SHIELD, + OBJ_SANDBAG_BUNKER, + OBJ_BUNKER, + + OBJ_LAST +}; + +static int g_iClassInfo_Sapper[] = +{ + OBJ_POWERPACK, + OBJ_DRAGONSTEETH, + OBJ_TOWER, + OBJ_SANDBAG_BUNKER, + OBJ_MANNED_PLASMAGUN, + + OBJ_LAST +}; + +static int g_iClassInfo_Infiltrator[] = +{ + OBJ_WAGON, + OBJ_LAST +}; + +static int g_iClassInfo_Pyro[] = +{ + OBJ_WAGON, + OBJ_LAST +}; + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool IsObjectAnUpgrade( int iObjectType ) +{ + return ( iObjectType >= OBJ_SELFHEAL && iObjectType < OBJ_BATTERING_RAM ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool IsObjectAVehicle( int iObjectType ) +{ + return ( iObjectType >= OBJ_BATTERING_RAM && iObjectType < OBJ_TOWER ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool IsObjectADefensiveBuilding( int iObjectType ) +{ + return ( iObjectType >= OBJ_TOWER ); +} + +//-------------------------------------------------------------------------- +// PLAYER CLASSES +//-------------------------------------------------------------------------- + +#if defined( CLIENT_DLL ) + + #define DEFINE_PLAYERCLASS_ALLOC_FNS( className, iClass ) \ + C_PlayerClass* AllocClient##className##( C_BaseTFPlayer *pPlayer ) \ + { \ + return new C_PlayerClass##className##( pPlayer ); \ + } \ + CPlayerClass* AllocServer##className##( CBaseTFPlayer *pPlayer ) \ + { \ + Assert( false ); \ + return NULL; \ + } + + #define GENERATE_PLAYERCLASS_INFO( className ) \ + AllocClient##className##, AllocServer##className, NULL + + + // ------------------------------------------------------------------------------------- // + // DT_AllPlayerClasses recv table. + // ------------------------------------------------------------------------------------- // + + BEGIN_RECV_TABLE_NOBASE( C_AllPlayerClasses, DT_AllPlayerClasses ) + RecvPropDataTable( RECVINFO_DT(m_pClasses[TFCLASS_COMMANDO]), 0, &REFERENCE_RECV_TABLE( DT_PlayerClassCommandoData ), DataTableRecvProxy_PointerDataTable ), + RecvPropDataTable( RECVINFO_DT(m_pClasses[TFCLASS_DEFENDER]), 0, &REFERENCE_RECV_TABLE( DT_PlayerClassDefenderData ), DataTableRecvProxy_PointerDataTable ), + RecvPropDataTable( RECVINFO_DT(m_pClasses[TFCLASS_ESCORT]), 0, &REFERENCE_RECV_TABLE( DT_PlayerClassEscortData ), DataTableRecvProxy_PointerDataTable ), + RecvPropDataTable( RECVINFO_DT(m_pClasses[TFCLASS_INFILTRATOR]), 0, &REFERENCE_RECV_TABLE( DT_PlayerClassInfiltratorData ), DataTableRecvProxy_PointerDataTable ), + RecvPropDataTable( RECVINFO_DT(m_pClasses[TFCLASS_MEDIC]), 0, &REFERENCE_RECV_TABLE( DT_PlayerClassMedicData ), DataTableRecvProxy_PointerDataTable ), + RecvPropDataTable( RECVINFO_DT(m_pClasses[TFCLASS_RECON]), 0, &REFERENCE_RECV_TABLE( DT_PlayerClassReconData ), DataTableRecvProxy_PointerDataTable ), + RecvPropDataTable( RECVINFO_DT(m_pClasses[TFCLASS_SNIPER]), 0, &REFERENCE_RECV_TABLE( DT_PlayerClassSniperData ), DataTableRecvProxy_PointerDataTable ), + RecvPropDataTable( RECVINFO_DT(m_pClasses[TFCLASS_SUPPORT]), 0, &REFERENCE_RECV_TABLE( DT_PlayerClassSupportData ), DataTableRecvProxy_PointerDataTable ), + RecvPropDataTable( RECVINFO_DT(m_pClasses[TFCLASS_SAPPER]), 0, &REFERENCE_RECV_TABLE( DT_PlayerClassSapperData ), DataTableRecvProxy_PointerDataTable ) + END_RECV_TABLE() + +#else + + #define DEFINE_PLAYERCLASS_ALLOC_FNS( className, iClass ) \ + ConVar class_##className##_health( "class_" #className "_health", "0", FCVAR_NONE, #className "'s max health" ); \ + C_PlayerClass* AllocClient##className##( C_BaseTFPlayer *pPlayer ) \ + { \ + Assert( false ); \ + return NULL; \ + } \ + CPlayerClass* AllocServer##className##( CBaseTFPlayer *pPlayer ) \ + { \ + return new CPlayerClass##className##( pPlayer, iClass ); \ + } + + #define GENERATE_PLAYERCLASS_INFO( className ) \ + AllocClient##className##, AllocServer##className, &class_##className##_health + + + // ------------------------------------------------------------------------------------- // + // DT_AllPlayerClasses recv table. + // ------------------------------------------------------------------------------------- // + + BEGIN_SEND_TABLE_NOBASE( CAllPlayerClasses, DT_AllPlayerClasses ) + SendPropDataTable( SENDINFO_DT(m_pClasses[TFCLASS_COMMANDO]), &REFERENCE_SEND_TABLE( DT_PlayerClassCommandoData ), SendProxy_DataTablePtrToDataTable ), + SendPropDataTable( SENDINFO_DT(m_pClasses[TFCLASS_DEFENDER]), &REFERENCE_SEND_TABLE( DT_PlayerClassDefenderData ), SendProxy_DataTablePtrToDataTable ), + SendPropDataTable( SENDINFO_DT(m_pClasses[TFCLASS_ESCORT]), &REFERENCE_SEND_TABLE( DT_PlayerClassEscortData ), SendProxy_DataTablePtrToDataTable ), + SendPropDataTable( SENDINFO_DT(m_pClasses[TFCLASS_INFILTRATOR]),&REFERENCE_SEND_TABLE( DT_PlayerClassInfiltratorData ), SendProxy_DataTablePtrToDataTable ), + SendPropDataTable( SENDINFO_DT(m_pClasses[TFCLASS_MEDIC]), &REFERENCE_SEND_TABLE( DT_PlayerClassMedicData ), SendProxy_DataTablePtrToDataTable ), + SendPropDataTable( SENDINFO_DT(m_pClasses[TFCLASS_RECON]), &REFERENCE_SEND_TABLE( DT_PlayerClassReconData ), SendProxy_DataTablePtrToDataTable ), + SendPropDataTable( SENDINFO_DT(m_pClasses[TFCLASS_SNIPER]), &REFERENCE_SEND_TABLE( DT_PlayerClassSniperData ), SendProxy_DataTablePtrToDataTable ), + SendPropDataTable( SENDINFO_DT(m_pClasses[TFCLASS_SUPPORT]), &REFERENCE_SEND_TABLE( DT_PlayerClassSupportData ), SendProxy_DataTablePtrToDataTable ), + SendPropDataTable( SENDINFO_DT(m_pClasses[TFCLASS_SAPPER]), &REFERENCE_SEND_TABLE( DT_PlayerClassSapperData ), SendProxy_DataTablePtrToDataTable ) + END_SEND_TABLE() + +#endif + + + +// ------------------------------------------------------------------------------------- // +// CAllPlayerClasses implementation. +// ------------------------------------------------------------------------------------- // + +CAllPlayerClasses::CAllPlayerClasses( PLAYER_TYPE *pPlayer ) +{ + for ( int i=0; i < TFCLASS_CLASS_COUNT; i++ ) + { + m_pClasses[i] = NULL; + +#if defined( CLIENT_DLL ) + if ( GetTFClassInfo( i )->m_pClientAlloc ) + m_pClasses[i] = GetTFClassInfo( i )->m_pClientAlloc( pPlayer ); +#else + if ( GetTFClassInfo( i )->m_pServerAlloc ) + m_pClasses[i] = GetTFClassInfo( i )->m_pServerAlloc( pPlayer ); +#endif + } +} + +CAllPlayerClasses::~CAllPlayerClasses() +{ + for ( int i=0; i < TFCLASS_CLASS_COUNT; i++ ) + { + delete m_pClasses[i]; + } +} + +PLAYER_CLASS_TYPE* CAllPlayerClasses::GetPlayerClass( int iClass ) +{ + Assert( iClass >= 0 && iClass < TFCLASS_CLASS_COUNT ); + return m_pClasses[iClass]; +} + + + +DEFINE_PLAYERCLASS_ALLOC_FNS( Recon, TFCLASS_RECON ); +DEFINE_PLAYERCLASS_ALLOC_FNS( Commando, TFCLASS_COMMANDO ); +DEFINE_PLAYERCLASS_ALLOC_FNS( Medic, TFCLASS_MEDIC ); +DEFINE_PLAYERCLASS_ALLOC_FNS( Defender, TFCLASS_DEFENDER ); +DEFINE_PLAYERCLASS_ALLOC_FNS( Sniper, TFCLASS_SNIPER ); +DEFINE_PLAYERCLASS_ALLOC_FNS( Support, TFCLASS_SUPPORT ); +DEFINE_PLAYERCLASS_ALLOC_FNS( Escort, TFCLASS_ESCORT ); +DEFINE_PLAYERCLASS_ALLOC_FNS( Sapper, TFCLASS_SAPPER ); +DEFINE_PLAYERCLASS_ALLOC_FNS( Infiltrator, TFCLASS_INFILTRATOR ); +DEFINE_PLAYERCLASS_ALLOC_FNS( Pyro, TFCLASS_PYRO ); + +CTFClassInfo g_TFClassInfos[ TFCLASS_CLASS_COUNT ] = +{ + { "Undecided", g_iClassInfo_Undecided, false, NULL, NULL, NULL }, + { "Recon", g_iClassInfo_Recon, false, GENERATE_PLAYERCLASS_INFO( Recon ) }, + { "Commando", g_iClassInfo_Commando, true, GENERATE_PLAYERCLASS_INFO( Commando ) }, + { "Medic", g_iClassInfo_Medic, true, GENERATE_PLAYERCLASS_INFO( Medic ) }, + { "Defender", g_iClassInfo_Defender, true, GENERATE_PLAYERCLASS_INFO( Defender ) }, + { "Sniper", g_iClassInfo_Sniper, false, GENERATE_PLAYERCLASS_INFO( Sniper ) }, + { "Support", g_iClassInfo_Support, false, GENERATE_PLAYERCLASS_INFO( Support ) }, + { "Escort", g_iClassInfo_Escort, true, GENERATE_PLAYERCLASS_INFO( Escort ) }, + { "Sapper", g_iClassInfo_Sapper, true, GENERATE_PLAYERCLASS_INFO( Sapper ) }, + { "Infiltrator",g_iClassInfo_Infiltrator, false, GENERATE_PLAYERCLASS_INFO( Infiltrator ) }, + { "Pyro", g_iClassInfo_Pyro, false, GENERATE_PLAYERCLASS_INFO( Pyro ) } +}; + + +const CTFClassInfo* GetTFClassInfo( int i ) +{ + Assert( i >= 0 && i < TFCLASS_CLASS_COUNT ); + return &g_TFClassInfos[i]; +} + + +// ------------------------------------------------------------------------------------------------ // +// CObjectInfo tables. +// ------------------------------------------------------------------------------------------------ // + +CObjectInfo::CObjectInfo( char *pObjectName ) +{ + m_pObjectName = pObjectName; + m_pClassName = NULL; + m_flBuildTime = -9999; + m_nMaxObjects = -9999; + m_Cost = -9999; + m_CostMultiplierPerInstance = -999; + m_UpgradeCost = -9999; + m_MaxUpgradeLevel = -9999; + m_pBuilderWeaponName = NULL; + m_pBuilderPlacementString = NULL; + m_SelectionSlot = -9999; + m_SelectionPosition = -9999; + m_bSolidToPlayerMovement = false; + m_flSapperAttachTime = -9999; + m_pIconActive = NULL; +} + + +CObjectInfo::~CObjectInfo() +{ + delete [] m_pClassName; + delete [] m_pStatusName; + delete [] m_pBuilderWeaponName; + delete [] m_pBuilderPlacementString; + delete [] m_pIconActive; +} + + +CObjectInfo g_ObjectInfos[OBJ_LAST] = +{ + CObjectInfo( "OBJ_POWERPACK" ), + CObjectInfo( "OBJ_RESUPPLY" ), + CObjectInfo( "OBJ_SENTRYGUN_PLASMA" ), + CObjectInfo( "OBJ_SENTRYGUN_ROCKET_LAUNCHER" ), + CObjectInfo( "OBJ_SHIELDWALL" ), + CObjectInfo( "OBJ_RESOURCEPUMP" ), + CObjectInfo( "OBJ_RESPAWN_STATION" ), + CObjectInfo( "OBJ_RALLYFLAG" ), + CObjectInfo( "OBJ_MANNED_PLASMAGUN" ), + CObjectInfo( "OBJ_MANNED_MISSILELAUNCHER" ), + CObjectInfo( "OBJ_MANNED_SHIELD" ), + CObjectInfo( "OBJ_EMPGENERATOR" ), + CObjectInfo( "OBJ_BUFF_STATION" ), + CObjectInfo( "OBJ_BARBED_WIRE" ), + CObjectInfo( "OBJ_MCV_SELECTION_PANEL" ), + CObjectInfo( "OBJ_MAPDEFINED" ), + CObjectInfo( "OBJ_MORTAR" ), + CObjectInfo( "OBJ_SELFHEAL" ), + CObjectInfo( "OBJ_ARMOR_UPGRADE" ), + CObjectInfo( "OBJ_VEHICLE_BOOST" ), + CObjectInfo( "OBJ_EXPLOSIVES" ), + CObjectInfo( "OBJ_DRIVER_MACHINEGUN" ), + CObjectInfo( "OBJ_BATTERING_RAM" ), + CObjectInfo( "OBJ_SIEGE_TOWER" ), + CObjectInfo( "OBJ_WAGON" ), + CObjectInfo( "OBJ_FLATBED" ), + CObjectInfo( "OBJ_VEHICLE_MORTAR" ), + CObjectInfo( "OBJ_VEHICLE_TELEPORT_STATION" ), + CObjectInfo( "OBJ_VEHICLE_TANK" ), + CObjectInfo( "OBJ_VEHICLE_MOTORCYCLE" ), + CObjectInfo( "OBJ_WALKER_STRIDER" ), + CObjectInfo( "OBJ_WALKER_MINI_STRIDER" ), + CObjectInfo( "OBJ_TOWER" ), + CObjectInfo( "OBJ_TUNNEL" ), + CObjectInfo( "OBJ_SANDBAG_BUNKER" ), + CObjectInfo( "OBJ_BUNKER" ), + CObjectInfo( "OBJ_DRAGONSTEETH" ), +}; + + +char* ReadAndAllocStringValue( KeyValues *pSub, const char *pName, const char *pFilename ) +{ + const char *pValue = pSub->GetString( pName, NULL ); + if ( !pValue ) + { + DevWarning( "Can't get key value '%s' from file '%s'.\n", pName, pFilename ); + return ""; + } + + int len = Q_strlen( pValue ) + 1; + char *pAlloced = new char[ len ]; + Assert( pAlloced ); + Q_strncpy( pAlloced, pValue, len ); + return pAlloced; +} + + +bool AreObjectInfosLoaded() +{ + return g_ObjectInfos[0].m_pClassName != NULL; +} + + +void LoadObjectInfos( IBaseFileSystem *pFileSystem ) +{ + const char *pFilename = "scripts/objects.txt"; + + // Make sure this stuff hasn't already been loaded. + Assert( !AreObjectInfosLoaded() ); + + KeyValues *pValues = new KeyValues( "Object descriptions" ); + if ( !pValues->LoadFromFile( pFileSystem, pFilename, "GAME" ) ) + { + Error( "Can't open %s for object info.", pFilename ); + pValues->deleteThis(); + return; + } + + // Now read each class's information in. + for ( int iObj=0; iObj < ARRAYSIZE( g_ObjectInfos ); iObj++ ) + { + CObjectInfo *pInfo = &g_ObjectInfos[iObj]; + KeyValues *pSub = pValues->FindKey( pInfo->m_pObjectName ); + if ( !pSub ) + { + Error( "Missing section '%s' from %s.", pInfo->m_pObjectName, pFilename ); + pValues->deleteThis(); + return; + } + + // Read all the info in. + if ( (pInfo->m_flBuildTime = pSub->GetFloat( "BuildTime", -999 )) == -999 || + (pInfo->m_nMaxObjects = pSub->GetInt( "MaxObjects", -999 )) == -999 || + (pInfo->m_Cost = pSub->GetInt( "Cost", -999 )) == -999 || + (pInfo->m_CostMultiplierPerInstance = pSub->GetFloat( "CostMultiplier", -999 )) == -999 || + (pInfo->m_UpgradeCost = pSub->GetInt( "UpgradeCost", -999 )) == -999 || + (pInfo->m_MaxUpgradeLevel = pSub->GetInt( "MaxUpgradeLevel", -999 )) == -999 || + (pInfo->m_SelectionSlot = pSub->GetInt( "SelectionSlot", -999 )) == -999 || + (pInfo->m_SelectionPosition = pSub->GetInt( "SelectionPosition", -999 )) == -999 || + (pInfo->m_flSapperAttachTime = pSub->GetInt( "SapperAttachTime", -999 )) == -999 ) + { + Error( "Missing data for object '%s' in %s.", pInfo->m_pObjectName, pFilename ); + pValues->deleteThis(); + return; + } + + pInfo->m_pClassName = ReadAndAllocStringValue( pSub, "ClassName", pFilename ); + pInfo->m_pStatusName = ReadAndAllocStringValue( pSub, "StatusName", pFilename ); + pInfo->m_pBuilderWeaponName = ReadAndAllocStringValue( pSub, "BuilderWeaponName", pFilename ); + pInfo->m_pBuilderPlacementString = ReadAndAllocStringValue( pSub, "BuilderPlacementString", pFilename ); + pInfo->m_bSolidToPlayerMovement = pSub->GetInt( "SolidToPlayerMovement", 0 ) ? true : false; + pInfo->m_pIconActive = ReadAndAllocStringValue( pSub, "Icon", pFilename ); + } + + pValues->deleteThis(); +} + + +const CObjectInfo* GetObjectInfo( int iObject ) +{ + Assert( iObject >= 0 && iObject < OBJ_LAST ); + Assert( AreObjectInfosLoaded() ); + return &g_ObjectInfos[iObject]; +} + + +//----------------------------------------------------------------------------- +// Purpose: Return true if the specified class is allowed to build the specified object type +//----------------------------------------------------------------------------- +bool ClassCanBuild( int iClass, int iObjectType ) +{ + for ( int i = 0; i < OBJ_LAST; i++ ) + { + // Hit the end? + if ( g_TFClassInfos[iClass].m_pClassObjects[i] == OBJ_LAST ) + return false; + + // Found it? + if ( g_TFClassInfos[iClass].m_pClassObjects[i] == iObjectType ) + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: Return the cost of another object of the specified type +// If bLast is set, return the cost of the last built object of the specified type +//----------------------------------------------------------------------------- + +int CalculateObjectCost( int iObjectType, int iNumberOfObjects, int iTeam, bool bLast ) +{ + if ( tf_cheapobjects.GetInt() ) + { + return 0; + } + + // Find out how much the next object should cost + if ( bLast ) + { + iNumberOfObjects = MAX(0,iNumberOfObjects-1); + } + + int iCost = GetObjectInfo( iObjectType )->m_Cost; + + // If a cost is negative, it means the first object of that type is free, and then + // it counts up as normal, using the negative value. + if ( iCost < 0 ) + { + if ( iNumberOfObjects == 0 ) + return 0; + iCost *= -1; + iNumberOfObjects--; + } + + // MCVs have special rules: The team's first one is always free + if ( iObjectType == OBJ_VEHICLE_TELEPORT_STATION ) + { + CTFTeam *pTeam = (CTFTeam *)GetGlobalTeam(iTeam); + if ( pTeam && pTeam->GetNumObjects(OBJ_VEHICLE_TELEPORT_STATION) == 0 ) + { + iCost = 0; + } + } + + // Human objects cost less across the board + if ( iTeam == TEAM_HUMANS ) + { + iCost = ( ((float)iCost) * 0.8 ); + } + + // Calculate the cost based upon the number of objects + for ( int i = 0; i < iNumberOfObjects; i++ ) + { + iCost *= GetObjectInfo( iObjectType )->m_CostMultiplierPerInstance; + } + + return iCost; +} + +//----------------------------------------------------------------------------- +// Purpose: Calculate the cost to upgrade an object of a specific type +//----------------------------------------------------------------------------- +int CalculateObjectUpgrade( int iObjectType, int iObjectLevel ) +{ + // Max level? + if ( iObjectLevel >= GetObjectInfo( iObjectType )->m_MaxUpgradeLevel ) + return 0; + + int iCost = GetObjectInfo( iObjectType )->m_UpgradeCost; + for ( int i = 0; i < (iObjectLevel - 1); i++ ) + { + iCost *= OBJECT_UPGRADE_COST_MULTIPLIER_PER_LEVEL; + } + + return iCost; +} + +//-------------------------------------------------------------------------- +// MORTAR +//-------------------------------------------------------------------------- +// Names for each mortar ammo type +char *MortarAmmoNames[ MA_LASTAMMOTYPE ] = +{ + "Normal Rounds", + //"Smoke Rounds", + "Cluster Rounds", + "Starburst Rounds", +}; + +// Techs needs for each mortar ammo type +char *MortarAmmoTechs[ MA_LASTAMMOTYPE ] = +{ + "", + //"mortar_ammo_smoke", + "mortar_ammo_cluster", + "mortar_ammo_starburst", +}; + +// Max amounts of each mortar ammo type in a single mortar +int MortarAmmoMax[ MA_LASTAMMOTYPE ] = +{ + -1, // -1 is infinite ammo + //20, + 20, + 10, +}; |