This commit is contained in:
nephacks
2025-06-04 03:22:50 +02:00
parent f234f23848
commit f12416cffd
14243 changed files with 6446499 additions and 26 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,65 @@
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
// Author: Matthew D. Campbell (matt@turtlerockstudios.com), 2004
#include "cbase.h"
#include "buy_preset_debug.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#ifdef _DEBUG
#define BUY_PRESET_DEBUGGING 1
#else
#define BUY_PRESET_DEBUGGING 0
#endif
#if BUY_PRESET_DEBUGGING
static ConVar cl_preset_debug( "cl_preset_debug", "0", 0, "Controls debug information about buy presets" );
//--------------------------------------------------------------------------------------------------------------
bool IsPresetDebuggingEnabled()
{
return cl_preset_debug.GetInt() >= 1.0f;
}
//--------------------------------------------------------------------------------------------------------------
bool IsPresetFullCostDebuggingEnabled()
{
return cl_preset_debug.GetInt() == 2.0f;
}
//--------------------------------------------------------------------------------------------------------------
bool IsPresetCurrentCostDebuggingEnabled()
{
return cl_preset_debug.GetInt() == 3.0f;
}
#else // ! BUY_PRESET_DEBUGGING
//--------------------------------------------------------------------------------------------------------------
bool IsPresetDebuggingEnabled()
{
return false;
}
//--------------------------------------------------------------------------------------------------------------
bool IsPresetFullCostDebuggingEnabled()
{
return false;
}
//--------------------------------------------------------------------------------------------------------------
bool IsPresetCurrentCostDebuggingEnabled()
{
return false;
}
#endif // ! BUY_PRESET_DEBUGGING
//--------------------------------------------------------------------------------------------------------------

View File

@ -0,0 +1,25 @@
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef BUY_PRESET_DEBUG_H
#define BUY_PRESET_DEBUG_H
#ifdef _WIN32
#pragma once
#endif
//--------------------------------------------------------------------------------------------------------------
// Utility functions for the debugging macros below
bool IsPresetDebuggingEnabled(); ///< cl_preset_debug >= 1.0f
bool IsPresetFullCostDebuggingEnabled(); ///< cl_preset_debug == 2.0f
bool IsPresetCurrentCostDebuggingEnabled(); ///< cl_preset_debug == 3.0f
//--------------------------------------------------------------------------------------------------------------
// Macros for conditional debugging of buy presets
#define PRESET_DEBUG if (IsPresetDebuggingEnabled()) DevMsg
#define FULLCOST_DEBUG if (IsPresetFullCostDebuggingEnabled()) DevMsg
#define CURRENTCOST_DEBUG if (IsPresetCurrentCostDebuggingEnabled()) DevMsg
#endif // BUY_PRESET_DEBUG_H

View File

@ -0,0 +1,368 @@
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose: BuyPresetWeapon implementation, and misc knowledge relating to weapons
//
//=============================================================================
#include "cbase.h"
#include "buy_preset_debug.h"
#include "buy_presets.h"
#include "weapon_csbase.h"
#include "cs_ammodef.h"
#include "cs_gamerules.h"
#include "bot/shared_util.h"
#include <vgui/ILocalize.h>
#include <vgui_controls/Controls.h>
#include "c_cs_player.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//--------------------------------------------------------------------------------------------------------------
struct WeaponDisplayNameInfo
{
CSWeaponID id;
const char *displayName;
};
//--------------------------------------------------------------------------------------------------------------
// NOTE: Array must be NULL-terminated
static WeaponDisplayNameInfo weaponDisplayNameInfo[] =
{
{ WEAPON_DEAGLE, "#Cstrike_TitlesTXT_DesertEagle" },
{ WEAPON_ELITE, "#Cstrike_TitlesTXT_Beretta96G" },
{ WEAPON_FIVESEVEN, "#Cstrike_TitlesTXT_ESFiveSeven" },
{ WEAPON_GLOCK, "#Cstrike_TitlesTXT_Glock18" },
{ WEAPON_P228, "#Cstrike_TitlesTXT_P228" },
{ WEAPON_USP, "#Cstrike_TitlesTXT_USP45" },
{ WEAPON_AK47, "#Cstrike_TitlesTXT_AK47" },
{ WEAPON_AUG, "#Cstrike_TitlesTXT_Aug" },
{ WEAPON_AWP, "#Cstrike_TitlesTXT_ArcticWarfareMagnum" },
{ WEAPON_FAMAS, "#Cstrike_TitlesTXT_Famas" },
{ WEAPON_G3SG1, "#Cstrike_TitlesTXT_G3SG1" },
{ WEAPON_GALIL, "#Cstrike_TitlesTXT_Galil" },
{ WEAPON_GALILAR, "#Cstrike_TitlesTXT_GalilAR" },
{ WEAPON_M249, "#Cstrike_TitlesTXT_ESM249" },
{ WEAPON_M3, "#Cstrike_TitlesTXT_Leone12" },
{ WEAPON_M4A1, "#Cstrike_TitlesTXT_M4A1_Short" },
{ WEAPON_MAC10, "#Cstrike_TitlesTXT_Mac10_Short" },
{ WEAPON_MP5NAVY, "#Cstrike_TitlesTXT_mp5navy" },
{ WEAPON_P90, "#Cstrike_TitlesTXT_ESC90" },
{ WEAPON_SCOUT, "#Cstrike_TitlesTXT_Scout" },
{ WEAPON_SG550, "#Cstrike_TitlesTXT_SG550" },
{ WEAPON_SG552, "#Cstrike_TitlesTXT_SG552" },
{ WEAPON_TMP, "#Cstrike_TitlesTXT_tmp" },
{ WEAPON_UMP45, "#Cstrike_TitlesTXT_KMUMP45" },
{ WEAPON_XM1014, "#Cstrike_TitlesTXT_AutoShotgun" },
{ WEAPON_BIZON, "#Cstrike_TitlesTXT_Bizon" },
{ WEAPON_MAG7, "#Cstrike_TitlesTXT_Mag7" },
{ WEAPON_NEGEV, "#Cstrike_TitlesTXT_Negev" },
{ WEAPON_SAWEDOFF, "#Cstrike_TitlesTXT_Sawedoff" },
{ WEAPON_TEC9, "#Cstrike_TitlesTXT_Tec9" },
{ WEAPON_TASER, "#Cstrike_TitlesTXT_Taser" },
{ WEAPON_HKP2000, "#Cstrike_TitlesTXT_HKP2000" },
{ WEAPON_MP7, "#Cstrike_TitlesTXT_MP7" },
{ WEAPON_MP9, "#Cstrike_TitlesTXT_MP9" },
{ WEAPON_NOVA, "#Cstrike_TitlesTXT_Nova" },
{ WEAPON_P250, "#Cstrike_TitlesTXT_P250" },
{ WEAPON_SCAR17, "#Cstrike_TitlesTXT_Scar17" },
{ WEAPON_SCAR20, "#Cstrike_TitlesTXT_Scar20" },
{ WEAPON_SG556, "#Cstrike_TitlesTXT_SG556" },
{ WEAPON_SSG08, "#Cstrike_TitlesTXT_SSG08" },
{ WEAPON_NONE, "#Cstrike_CurrentWeapon" }
};
//--------------------------------------------------------------------------------------------------------------
/**
* Returns the display name for a weapon, based on it's weaponID
*/
const wchar_t* WeaponIDToDisplayName( CSWeaponID weaponID )
{
for( int i=0; weaponDisplayNameInfo[i].displayName; ++i )
if ( weaponDisplayNameInfo[i].id == weaponID )
return g_pVGuiLocalize->Find( weaponDisplayNameInfo[i].displayName );
return NULL;
}
//--------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------
BuyPresetWeapon::BuyPresetWeapon()
{
m_name = NULL;
m_weaponID = WEAPON_NONE;
m_ammoType = AMMO_CLIPS;
m_ammoAmount = 0;
m_fillAmmo = true;
}
//--------------------------------------------------------------------------------------------------------------
BuyPresetWeapon::BuyPresetWeapon( CSWeaponID weaponID )
{
m_name = WeaponIDToDisplayName( weaponID );
m_weaponID = weaponID;
m_ammoType = AMMO_CLIPS;
m_ammoAmount = (weaponID == WEAPON_NONE) ? 0 : 1;
m_fillAmmo = true;
}
//--------------------------------------------------------------------------------------------------------------
/*
BuyPresetWeapon& BuyPresetWeapon::operator= (const BuyPresetWeapon& other)
{
m_name = other.m_name;
m_weaponID = other.m_weaponID;
m_ammoType = other.m_ammoType;
m_ammoAmount = other.m_ammoAmount;
m_fillAmmo = other.m_fillAmmo;
return *this;
}
*/
//--------------------------------------------------------------------------------------------------------------
/**
* Sets the WEAPON_* weapon ID (and resets ammo, etc)
*/
void BuyPresetWeapon::SetWeaponID( CSWeaponID weaponID )
{
m_name = WeaponIDToDisplayName( weaponID );
m_weaponID = weaponID;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Returns the number of clips that will have to be bought for the specified BuyPresetWeapon
*/
int CalcClipsNeeded( const BuyPresetWeapon *pWeapon, const CCSWeaponInfo *pInfo, const int ammo[MAX_AMMO_TYPES] )
{
if ( !pWeapon || !pInfo )
return 0;
int maxRounds = GetCSAmmoDef()->MaxCarry( pInfo->GetPrimaryAmmoType(), C_CSPlayer::GetLocalCSPlayer() );
int buySize = GetCSAmmoDef()->GetBuySize( pInfo->GetPrimaryAmmoType() );
int numClips = 0;
if ( buySize && pInfo->GetPrimaryAmmoType() >= 0 )
{
switch ( pWeapon->GetAmmoType() )
{
case AMMO_CLIPS:
numClips = pWeapon->GetAmmoAmount();
if ( pWeapon->GetCSWeaponID() == WEAPON_NONE && numClips >= 4 )
{
numClips = ceil(maxRounds/(float)buySize);
}
numClips = MIN( ceil(maxRounds/(float)buySize), numClips );
numClips -= ammo[pInfo->GetPrimaryAmmoType() ]/buySize;
if ( numClips < 0 || ammo[pInfo->GetPrimaryAmmoType() ] == maxRounds )
{
numClips = 0;
}
break;
case AMMO_ROUNDS:
{
int roundsNeeded = pWeapon->GetAmmoAmount() - ammo[pInfo->GetPrimaryAmmoType() ];
if ( roundsNeeded > 0 )
{
numClips = ceil(roundsNeeded/(float)buySize);
}
else
{
numClips = 0;
}
}
break;
case AMMO_PERCENT:
{
int roundsNeeded = maxRounds*pWeapon->GetAmmoAmount() - ammo[pInfo->GetPrimaryAmmoType() ];
roundsNeeded *= 0.01f;
if ( roundsNeeded > 0 )
{
numClips = ceil(roundsNeeded/(float)buySize);
}
else
{
numClips = 0;
}
}
break;
}
}
return numClips;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Returns true if the client can currently buy the weapon according to class/gamemode restrictions. Returns
* true also if the player owns the weapon already.
*/
bool CanBuyWeapon( CSWeaponID currentPrimaryID, CSWeaponID currentSecondaryID, CSWeaponID weaponID )
{
C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
if ( !pPlayer )
return false;
const CCSWeaponInfo *info = GetWeaponInfo( weaponID );
if ( !info )
return false;
/// @TODO: assasination maps have a specific set of weapons that can be used in them.
if ( info->GetUsedByTeam() != TEAM_UNASSIGNED && pPlayer->GetTeamNumber() != info->GetUsedByTeam() )
return false;
return true;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Returns true if the CSWeaponType is a primary class
*/
static bool IsPrimaryWeaponClassID( CSWeaponType classId )
{
switch (classId)
{
case WEAPONTYPE_SUBMACHINEGUN:
case WEAPONTYPE_SHOTGUN:
case WEAPONTYPE_MACHINEGUN:
case WEAPONTYPE_RIFLE:
case WEAPONTYPE_SNIPER_RIFLE:
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Returns true if the weapon ID is for a primary weapon
*/
static bool IsPrimaryWeaponID( CSWeaponID id )
{
const CCSWeaponInfo *info = GetWeaponInfo( id );
if ( !info )
return false;
return IsPrimaryWeaponClassID( info->GetWeaponType() );
}
//--------------------------------------------------------------------------------------------------------------
/**
* Returns true if the CSWeaponType is a secondary class
*/
static bool IsSecondaryWeaponClassID( CSWeaponType classId )
{
return (classId == WEAPONTYPE_PISTOL);
}
//--------------------------------------------------------------------------------------------------------------
/**
* Returns true if the weapon ID is for a secondary weapon
*/
static bool IsSecondaryWeaponID( CSWeaponID id )
{
const CCSWeaponInfo *info = GetWeaponInfo( id );
if ( !info )
return false;
return IsSecondaryWeaponClassID( info->GetWeaponType() );
}
//--------------------------------------------------------------------------------------------------------------
/**
* Fills the ammo array with the ammo currently owned by the local player
*/
void FillClientAmmo( int ammo[MAX_AMMO_TYPES] )
{
int i;
for ( i=0; i<MAX_AMMO_TYPES; ++i )
{
ammo[i] = 0;
}
C_CSPlayer *localPlayer = CCSPlayer::GetLocalCSPlayer();
if ( !localPlayer )
return;
for ( i=0; i<WEAPON_MAX; ++i )
{
CSWeaponID gameWeaponID = (CSWeaponID)i;
if ( gameWeaponID == WEAPON_NONE || gameWeaponID >= EQUIPMENT_FIRST )
continue;
const CCSWeaponInfo *info = GetWeaponInfo( gameWeaponID );
if ( !info )
continue;
int clientAmmoType = info->GetPrimaryAmmoType();
int clientAmmoCount = localPlayer->GetAmmoCount( clientAmmoType );
if ( clientAmmoCount > 0 )
{
ammo[ clientAmmoType ] = MAX( ammo[ clientAmmoType ], clientAmmoCount );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: returns the weapon in the specified slot
//-----------------------------------------------------------------------------
CWeaponCSBase *GetWeaponInSlot( int iSlot, int iSlotPos )
{
C_CSPlayer *player = C_CSPlayer::GetLocalCSPlayer();
if ( !player )
return NULL;
for ( int i = 0; i < MAX_WEAPONS; i++ )
{
CWeaponCSBase *pWeapon = assert_cast< CWeaponCSBase * >(player->GetWeapon(i));
if ( pWeapon == NULL )
continue;
if ( pWeapon->GetSlot() == iSlot && pWeapon->GetPosition() == iSlotPos )
return pWeapon;
}
return NULL;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Returns the client's WEAPON_* value for the currently owned weapon, or WEAPON_NONE if no weapon is owned
*/
CSWeaponID GetClientWeaponID( bool primary )
{
C_CSPlayer *localPlayer = CCSPlayer::GetLocalCSPlayer();
if ( !localPlayer )
return WEAPON_NONE;
int slot = (primary)?0:1;
CWeaponCSBase *pWeapon = GetWeaponInSlot( slot, slot );
if ( !pWeapon )
return WEAPON_NONE;
return pWeapon->GetCSWeaponID();
}
//--------------------------------------------------------------------------------------------------------------

View File

@ -0,0 +1,454 @@
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "buy_preset_debug.h"
#include "buy_presets.h"
#include "weapon_csbase.h"
#include "game/client/iviewport.h"
#include "filesystem.h"
#include <vgui/ILocalize.h>
#include <vgui_controls/Controls.h>
#include "c_cs_player.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
BuyPresetManager *TheBuyPresets = NULL;
#if USE_BUY_PRESETS
//--------------------------------------------------------------------------------------------------------------
ConVar cl_buy_favorite_quiet( "cl_buy_favorite_quiet", "0", FCVAR_ARCHIVE | FCVAR_CLIENTCMD_CAN_EXECUTE, "Skips the prompt when saving a buy favorite in the buy menu" );
ConVar cl_buy_favorite_nowarn( "cl_buy_favorite_nowarn", "0", FCVAR_ARCHIVE | FCVAR_CLIENTCMD_CAN_EXECUTE, "Skips the error prompt when saving an invalid buy favorite" );
//--------------------------------------------------------------------------------------------------------------
static void PrintBuyPresetUsage( void )
{
if ( TheBuyPresets->GetNumPresets() )
{
Msg( "usage: cl_buy_favorite <1...%d>\n", TheBuyPresets->GetNumPresets() );
for ( int i=0; i<TheBuyPresets->GetNumPresets(); ++i )
{
const BuyPreset *preset = TheBuyPresets->GetPreset( i );
if ( preset && preset->GetName() && preset->GetName()[0] )
{
char buffer[64];
g_pVGuiLocalize->ConvertUnicodeToANSI( preset->GetName(), buffer, sizeof( buffer ) );
Msg( " %d. %s\n", i+1, buffer );
}
}
}
else
{
Msg( "cl_buy_favorite: no favorites are defined\n" );
}
}
//--------------------------------------------------------------------------------------------------------------
/**
* Callback function for handling the "cl_buy_favorite" command
*/
CON_COMMAND_F( cl_buy_favorite, "Purchase a favorite weapon/equipment loadout", FCVAR_CLIENTCMD_CAN_EXECUTE )
{
if ( !engine->IsConnected() )
return;
if ( !TheBuyPresets )
TheBuyPresets = new BuyPresetManager();
if ( args.ArgC() != 2 )
{
PRESET_DEBUG( "cl_buy_favorite: no favorite specified\n" );
PrintBuyPresetUsage();
return;
}
int presetIndex = atoi( args[1] ) - 1;
if ( presetIndex < 0 || presetIndex >= TheBuyPresets->GetNumPresets() )
{
PRESET_DEBUG( "cl_buy_favorite: favorite %d doesn't exist\n", presetIndex );
PrintBuyPresetUsage();
return;
}
TheBuyPresets->PurchasePreset( presetIndex );
}
//--------------------------------------------------------------------------------------------------------------
/**
* Callback function for handling the "cl_buy_favorite_set" command
*/
CON_COMMAND_F( cl_buy_favorite_set, "Saves the current loadout as a favorite", FCVAR_CLIENTCMD_CAN_EXECUTE )
{
if ( !engine->IsConnected() )
return;
if ( !TheBuyPresets )
TheBuyPresets = new BuyPresetManager();
if ( args.ArgC() != 2 )
{
PRESET_DEBUG( "cl_buy_favorite_set: no favorite specified\n" );
PrintBuyPresetUsage();
return;
}
int presetIndex = atoi( args[ 1 ] ) - 1;
if ( presetIndex < 0 || presetIndex >= TheBuyPresets->GetNumPresets() )
{
PRESET_DEBUG( "cl_buy_favorite_set: favorite %d doesn't exist\n", presetIndex );
PrintBuyPresetUsage();
return;
}
const BuyPreset *preset = TheBuyPresets->GetPreset( presetIndex );
if ( !preset )
{
return;
}
WeaponSet ws;
TheBuyPresets->GetCurrentLoadout( &ws );
BuyPreset newPreset( *preset );
newPreset.ReplaceSet( 0, ws );
TheBuyPresets->SetPreset( presetIndex, &newPreset );
TheBuyPresets->Save();
C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
if ( pPlayer )
{
pPlayer->EmitSound( "BuyPreset.Updated" );
}
}
//--------------------------------------------------------------------------------------------------------------
/**
* Callback function for handling the "cl_buy_favorite_reset" command
*/
void __CmdFunc_BuyPresetsReset(void)
{
if ( !engine->IsConnected() )
return;
if ( !TheBuyPresets )
TheBuyPresets = new BuyPresetManager();
C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
if ( !pPlayer || ( pPlayer->GetTeamNumber() != TEAM_CT && pPlayer->GetTeamNumber() != TEAM_TERRORIST ) )
{
return;
}
TheBuyPresets->ResetEditToDefaults();
TheBuyPresets->SetPresets( TheBuyPresets->GetEditPresets() );
TheBuyPresets->Save();
}
ConCommand cl_buy_favorite_reset( "cl_buy_favorite_reset", __CmdFunc_BuyPresetsReset, "Reset favorite loadouts to the default", FCVAR_CLIENTCMD_CAN_EXECUTE );
#endif // USE_BUY_PRESETS
//--------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------
/**
* Creates the BuyPresetManager singleton
*/
BuyPresetManager::BuyPresetManager()
{
m_loadedTeam = TEAM_UNASSIGNED;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Resets the BuyPresetManager, loading BuyPresets from disk. If no presets are defined, it loads the
* default presets instead.
*/
void BuyPresetManager::VerifyLoadedTeam( void )
{
#if USE_BUY_PRESETS
C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
if ( !pPlayer )
return;
int playerTeam = pPlayer->GetTeamNumber();
if ( playerTeam == m_loadedTeam )
return;
if ( playerTeam != TEAM_CT && playerTeam != TEAM_TERRORIST )
return;
m_presets.RemoveAll();
const char *filename = "cfg/BuyPresets_TER.vdf";
if ( playerTeam == TEAM_CT )
{
filename = "cfg/BuyPresets_CT.vdf";
}
KeyValues *data;
KeyValues *presetKey;
data = new KeyValues( "Presets" );
bool fileExists = data->LoadFromFile( filesystem, filename, NULL );
presetKey = data->GetFirstSubKey();
while ( presetKey )
{
BuyPreset preset;
preset.Parse( presetKey );
m_presets.AddToTail(preset);
presetKey = presetKey->GetNextKey();
}
if ( !m_presets.Count() )
{
const char *filename = "cfg/BuyPresetsDefault_TER.vdf";
if ( playerTeam == TEAM_CT )
{
filename = "cfg/BuyPresetsDefault_CT.vdf";
}
KeyValues *data;
KeyValues *presetKey;
data = new KeyValues( "Presets" );
data->LoadFromFile( filesystem, filename, NULL );
presetKey = data->GetFirstSubKey();
while ( presetKey )
{
BuyPreset preset;
preset.Parse( presetKey );
m_presets.AddToTail(preset);
presetKey = presetKey->GetNextKey();
}
data->deleteThis();
}
// Guarantee we have at least this many presets, even if they are blank
while ( m_presets.Count() < NUM_PRESETS )
{
BuyPreset preset;
m_presets.AddToTail(preset);
}
data->deleteThis();
m_editPresets = m_presets;
if ( !fileExists )
Save();
#endif // USE_BUY_PRESETS
}
//--------------------------------------------------------------------------------------------------------------
/**
* Loads the default presets into the editing presets (e.g. when hitting the "Use Defaults" button)
*/
void BuyPresetManager::ResetEditToDefaults( void )
{
#if USE_BUY_PRESETS
VerifyLoadedTeam();
C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
if ( !pPlayer )
return;
int playerTeam = pPlayer->GetTeamNumber();
if ( playerTeam != TEAM_CT && playerTeam != TEAM_TERRORIST )
return;
m_editPresets.RemoveAll();
const char *filename = "cfg/BuyPresetsDefault_TER.vdf";
if ( playerTeam == TEAM_CT )
{
filename = "cfg/BuyPresetsDefault_CT.vdf";
}
KeyValues *data;
KeyValues *presetKey;
data = new KeyValues( "Presets" );
data->LoadFromFile( filesystem, filename, NULL );
presetKey = data->GetFirstSubKey();
while ( presetKey )
{
BuyPreset preset;
preset.Parse( presetKey );
m_editPresets.AddToTail(preset);
presetKey = presetKey->GetNextKey();
}
data->deleteThis();
#endif // USE_BUY_PRESETS
}
//--------------------------------------------------------------------------------------------------------------
/**
* Saves the current BuyPresets to disk
*/
void BuyPresetManager::Save()
{
#if USE_BUY_PRESETS
C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
if ( !pPlayer )
return;
const char *filename = "cfg/BuyPresets_TER.vdf";
switch ( pPlayer->GetTeamNumber() )
{
case TEAM_CT:
filename = "cfg/BuyPresets_CT.vdf";
break;
case TEAM_TERRORIST:
filename = "cfg/BuyPresets_TER.vdf";
break;
default:
return; // don't bother saving presets unless we're on a team
}
KeyValues *data = new KeyValues( "Presets" );
for( int i=0; i<m_presets.Count(); ++i )
{
m_presets[i].Save( data );
}
data->SaveToFile( filesystem, filename, NULL );
data->deleteThis();
#endif // USE_BUY_PRESETS
}
//--------------------------------------------------------------------------------------------------------------
/**
* Returns the specified "live" preset, or NULL if it doesn't exist
*/
const BuyPreset * BuyPresetManager::GetPreset( int index ) const
{
if ( index < 0 || index >= m_presets.Count() )
{
return NULL;
}
return &(m_presets[index]);
}
//--------------------------------------------------------------------------------------------------------------
void BuyPresetManager::SetPreset( int index, const BuyPreset *preset )
{
if ( index < 0 || index >= m_presets.Count() || !preset )
{
return;
}
m_presets[index] = *preset;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Returns the specified editing preset, or NULL if it doesn't exist
*/
BuyPreset * BuyPresetManager::GetEditPreset( int index )
{
if ( index < 0 || index >= m_editPresets.Count() )
{
return NULL;
}
return &(m_editPresets[index]);
}
//--------------------------------------------------------------------------------------------------------------
/**
* Generates and sends buy commands to buy a specific preset
*/
void BuyPresetManager::PurchasePreset( int presetIndex )
{
if ( presetIndex >= 0 && presetIndex < m_presets.Count() )
{
const BuyPreset *preset = &(m_presets[presetIndex]);
int setIndex;
for ( setIndex = 0; setIndex < preset->GetNumSets(); ++setIndex )
{
// Try to buy this weapon set.
const WeaponSet *itemSet = preset->GetSet( setIndex );
if ( itemSet )
{
int currentCost;
WeaponSet currentSet;
itemSet->GetCurrent( currentCost, currentSet );
if ( currentCost > 0 )
{
PRESET_DEBUG( "cl_buy_favorite: buying %ls for a total of $%d.\n",
preset->GetName(),
currentCost );
char buf[BUY_PRESET_COMMAND_LEN];
currentSet.GenerateBuyCommands( buf );
// Send completed string
PRESET_DEBUG( "%s\n", buf );
engine->ClientCmd( buf );
return;
}
else if ( currentCost == 0 )
{
C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
if ( pPlayer )
{
pPlayer->EmitSound( "BuyPreset.AlreadyBought" );
}
// We have everything already. Let the player know.
if ( setIndex == 0 )
{
PRESET_DEBUG( "cl_buy_favorite: already have a complete %ls set.\n", preset->GetName() );
}
else
{
PRESET_DEBUG( "cl_buy_favorite: can't afford anything better from %ls.\n", preset->GetName() );
}
return;
}
}
}
C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
if ( pPlayer )
{
pPlayer->EmitSound( "BuyPreset.CantBuy" );
}
PRESET_DEBUG( "cl_buy_favorite: can't afford anything better from %ls.\n", preset->GetName() );
return;
}
// We failed to buy anything. Let the player know.
C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
if ( pPlayer )
{
pPlayer->EmitSound( "BuyPreset.CantBuy" );
}
PRESET_DEBUG( "cl_buy_favorite: preset %d doesn't exist.\n", presetIndex );
}
//--------------------------------------------------------------------------------------------------------------

View File

@ -0,0 +1,269 @@
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef BUY_PRESETS_H
#define BUY_PRESETS_H
#ifdef _WIN32
#pragma once
#endif
#define USE_BUY_PRESETS 1
/**
* CLASS STRUCTURE:
* Buy presets are managed by TheBuyPresetManager, which has a list of BuyPreset objects.
* Each BuyPreset has a list of fallback WeaponSets. Each WeaponSet is a complete set of
* weapons and equipment that could be purchased by a buy preset.
*
* BUYING:
* When purchasing a buy preset, the fallback WeaponSets are considered in order from first
* to last. When one is deemed to be purchasable, the buy commands are generated and
* processing stops.
*
* EDITING:
* When editing buy presets, TheBuyPresetManager maintains a second list of BuyPresets, to
* allow an all-or-nothing undo system. The editing is done on two main VGUI menus: a
* list of the four main buy presets (CBuyPresetEditMainMenu), and a menu showing the
* fallbacks for a single preset (CBuyPresetEditOutfitListMenu).
*
* Presets and fallbacks can be copied, created, deleted, etc from these pages. From the
* fallback menu, a wizard can edit the contents of a fallback, specifying primary weapon,
* pistol, and equipment.
*/
#include "weapon_csbase.h"
#include <keyvalues.h>
#include <utlvector.h>
class BuyPreset;
class CCSWeaponInfo;
//--------------------------------------------------------------------------------------------------------------
enum BuyPresetStringSizes
{
BUY_PRESET_COMMAND_LEN = 256,
MaxBuyPresetName = 64,
MaxBuyPresetImageFname = 64,
};
enum AmmoSizeType
{
AMMO_PERCENT,
AMMO_CLIPS,
AMMO_ROUNDS
};
enum { NUM_PRESETS = 4 };
//--------------------------------------------------------------------------------------------------------------
/**
* A BuyPresetWeapon stores the mp.dll version of the WeaponID, the increment for buying ammo (clips, rounds, etc),
* the number of increments to buy, etc. This is the basic info for buying a weapon that is present in an
* item set.
*/
class BuyPresetWeapon
{
public:
BuyPresetWeapon();
explicit BuyPresetWeapon( CSWeaponID weaponID );
//BuyPresetWeapon& operator= (const BuyPresetWeapon& other); // default implementation should work
const wchar_t* GetName() const { return m_name; } ///< Returns the display name corresponding to the weapon ID
CSWeaponID GetCSWeaponID() const { return m_weaponID; } ///< Returns the WEAPON_* weapon ID
void SetWeaponID( CSWeaponID weaponID ); ///< Sets the WEAPON_* weapon ID (and resets ammo, etc)
void SetAmmoType( AmmoSizeType ammoType ) { m_ammoType = ammoType; } ///< Sets the ammo type - percent (unused), clips, or rounds (unused)
void SetAmmoAmount( int ammoAmount ) { m_ammoAmount = ammoAmount; } ///< Sets the amount of ammo, in units relevant to the ammo type
void SetFillAmmo( bool fill ) { m_fillAmmo = fill; } ///< Sets whether the weapon's ammo should be topped off
AmmoSizeType GetAmmoType() const { return m_ammoType; } ///< Returns ammo type - percent (unused), clips, or rounds (unused)
int GetAmmoAmount() const { return m_ammoAmount; } ///< Returns the amount of ammo, in units relevant to the ammo type
bool GetFillAmmo() const { return m_fillAmmo; } ///< Returns true if the weapon's ammo should be topped off
protected:
const wchar_t *m_name;
CSWeaponID m_weaponID;
AmmoSizeType m_ammoType;
int m_ammoAmount;
bool m_fillAmmo;
};
typedef CUtlVector< BuyPresetWeapon > BuyPresetWeaponList;
//--------------------------------------------------------------------------------------------------------------
/**
* A WeaponSet is part of a buy preset. Each buy preset is composed of a series of (fallback) WeaponSets.
* The WeaponSet contains a snapshot of a set of weapons and equipment that should be bought.
*/
class WeaponSet
{
public:
WeaponSet();
void GetCurrent( int& cost, WeaponSet& ws ) const; ///< Generates a WeaponSet containing only items that would be bought right now
void GetFromScratch( int& cost, WeaponSet& ws ) const; ///< Generates a WeaponSet containing everything that would be bought from scratch
void GenerateBuyCommands( char command[BUY_PRESET_COMMAND_LEN] ) const; ///< Generates a list of commands to buy the current WeaponSet.
int FullCost() const; ///< Calculates the full cost of the WeaponSet, including all optional items
void Reset( void );
const BuyPresetWeapon& GetPrimaryWeapon() const { return m_primaryWeapon; }
const BuyPresetWeapon& GetSecondaryWeapon() const { return m_secondaryWeapon; }
BuyPresetWeapon m_primaryWeapon;
BuyPresetWeapon m_secondaryWeapon;
// Equipment --------------------------------
int m_armor;
bool m_helmet;
bool m_smokeGrenade;
bool m_HEGrenade;
int m_flashbangs;
bool m_defuser;
bool m_nightvision;
};
typedef CUtlVector< WeaponSet > WeaponSetList;
//--------------------------------------------------------------------------------------------------------------
/**
* The BuyPreset is a complete representation of a buy preset. Essentially, it consists of the preset name,
* whether or not the preset is used for autobuy, and a list of fallback WeaponSets.
*/
class BuyPreset
{
public:
BuyPreset();
~BuyPreset();
BuyPreset(const BuyPreset& other);
void SetName( const wchar_t *name );
const wchar_t * GetName() const { return m_name; }
void Parse( KeyValues *data ); ///< Populates data from a KeyValues structure, for loading
void Save( KeyValues *data ); ///< Fills in a KeyValues structure with data, for saving
int GetNumSets() const { return m_weaponList.Count(); } ///< Returns the number of fallback WeaponSets
const WeaponSet * GetSet( int index ) const; ///< Returns the specified fallback WeaponSet, or NULL if it doesn't exist
int FullCost() const; ///< Calculates the full cost of the preset, which is exactly the full cost of the first fallback WeaponSet
// editing functions --------------------
void DeleteSet( int index ); ///< Deletes a fallback
void SwapSet( int firstIndex, int secondIndex ); ///< Switches the order of two fallbacks
void ReplaceSet( int index, const WeaponSet& weaponSet ); ///< Replaces a fallback with the supplied WeaponSet
private:
wchar_t m_name[MaxBuyPresetName];
WeaponSetList m_weaponList;
};
typedef CUtlVector< BuyPreset > BuyPresetList;
//--------------------------------------------------------------------------------------------------------------
/**
* The BuyPresetManager singleton manages saving/loading/buying the individual BuyPresets. It also tracks the
* ownership of some items that aren't explicitly known by the client (defuser, nightvision).
*
* Two sets of BuyPresets are maintained - the live set used for purchasing, and a set that is acted upon for
* editing. This provides the basic save changes/abandon changes ability when editing presets.
*/
class BuyPresetManager
{
public:
BuyPresetManager();
void Save();
void PurchasePreset( int presetIndex ); ///< Generates and sends buy commands to buy a specific preset
int GetNumPresets() { VerifyLoadedTeam(); return m_presets.Count(); }
const BuyPreset * GetPreset( int index ) const; ///< Returns the specified "live" preset, or NULL if it doesn't exist
void SetPreset( int index, const BuyPreset *preset );
void SetPresets( const BuyPresetList& presets ) { m_presets = presets; }
void SetEditPresets( const BuyPresetList& presets ) { m_editPresets = presets; }
int GetNumEditPresets() const { return m_editPresets.Count(); }
BuyPreset * GetEditPreset( int index ); ///< Returns the specified editing preset, or NULL if it doesn't exist
const CUtlVector< BuyPreset >& GetEditPresets() const { return m_editPresets; }
void ResetEditPresets() { m_editPresets = m_presets; } ///< Resets the editing presets to the live presets (e.g. when starting editing)
void ResetEditToDefaults( void ); ///< Loads the default presets into the editing presets (e.g. when hitting the "Use Defaults" button)
void GetCurrentLoadout( WeaponSet *weaponSet );
private:
BuyPresetList m_presets; ///< Current (live) presets
BuyPresetList m_editPresets; ///< BuyPresets used when editing
int m_loadedTeam;
void VerifyLoadedTeam( void );
};
//--------------------------------------------------------------------------------------------------------------
extern BuyPresetManager *TheBuyPresets;
//--------------------------------------------------------------------------------------------------------------
/**
* Functions for controlling the display of the various buy preset editing menus. Opening one closes any
* others open.
*/
enum { REOPEN_YES, REOPEN_NO, REOPEN_DONTCHANGE }; ///< Determines if we need to re-open the buy menu when done editing.
void ShowBuyPresetMainMenu( bool runUpdate, int reopenBuyMenu ); ///< Open the main preset editing menu
void ShowBuyPresetEditMenu( int presetIndex ); ///< Open the menu for editing the list of fallbacks for an individual preset
//--------------------------------------------------------------------------------------------------------------
/**
* Constructs a list of weapons that will satisfy the any unfinished weapon-specific career tasks:
* 1. If there are no unfinished career tasks, the source list is returned
* 2. If there are unfinished career tasks, all weapons that can be used for the tasks are added
* to the front of the list. This list of career weapons is sorted according to the order of
* weapons in the source list, so that if any weapons in the source list can be used for career
* tasks, they will be.
*/
BuyPresetWeaponList CareerWeaponList( const BuyPresetWeaponList& source, bool isPrimary, CSWeaponID currentClientID );
//--------------------------------------------------------------------------------------------------------------
/**
* Returns the number of clips that will have to be bought for the specified BuyPresetWeapon
*/
class CCSWeaponInfo;
int CalcClipsNeeded( const BuyPresetWeapon *pWeapon, const CCSWeaponInfo *pInfo, const int ammo[MAX_AMMO_TYPES] );
//--------------------------------------------------------------------------------------------------------------
/**
* Fills the ammo array with the ammo currently owned by the local player
*/
void FillClientAmmo( int ammo[MAX_AMMO_TYPES] );
//--------------------------------------------------------------------------------------------------------------
/**
* Returns true if the client can currently buy the weapon according to class/gamemode restrictions. Returns
* true also if the player owns the weapon already.
*/
bool CanBuyWeapon( CSWeaponID currentPrimaryID, CSWeaponID currentSecondaryID, CSWeaponID weaponID );
//--------------------------------------------------------------------------------------------------------------
/**
* Returns the display name for a weapon, based on it's weaponID
*/
const wchar_t* WeaponIDToDisplayName( CSWeaponID weaponID );
//--------------------------------------------------------------------------------------------------------------
// If our weapon is NONE, we want to be able to buy up to this many clips for the current gun we're holding
enum { NUM_CLIPS_FOR_CURRENT = 4 };
#if USE_BUY_PRESETS
extern ConVar cl_buy_favorite_quiet;
extern ConVar cl_buy_favorite_nowarn;
#endif // USE_BUY_PRESETS
#endif // BUY_PRESETS_H