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.
1195 lines
34 KiB
1195 lines
34 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//============================================================================= |
|
|
|
#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 "cstrike/bot/shared_util.h" |
|
#include "vgui/ILocalize.h" |
|
#include <vgui_controls/Controls.h> |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
extern ConVar cl_rebuy; |
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
/** |
|
* Returns true if the local player is a CT and the map is a defuse map. |
|
*/ |
|
static bool CanBuyDefuser() |
|
{ |
|
C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer(); |
|
return ( pPlayer && pPlayer->GetTeamNumber() == TEAM_CT && CSGameRules()->IsBombDefuseMap() ); |
|
} |
|
|
|
|
|
void BuyPresetManager::GetCurrentLoadout( WeaponSet *weaponSet ) |
|
{ |
|
if ( !weaponSet ) |
|
return; |
|
|
|
C_CSPlayer *player = C_CSPlayer::GetLocalCSPlayer(); |
|
if ( !player ) |
|
return; |
|
|
|
CWeaponCSBase *pWeapon; |
|
const CCSWeaponInfo *pInfo; |
|
|
|
int ammo[MAX_AMMO_TYPES]; |
|
memset( ammo, 0, sizeof(ammo) ); |
|
FillClientAmmo( ammo ); |
|
|
|
weaponSet->Reset(); |
|
|
|
// Grab current armor values |
|
weaponSet->m_armor = ( player->ArmorValue() > 0 ) ? 100 : 0; |
|
weaponSet->m_helmet = player->HasHelmet(); |
|
|
|
// Grab current smoke grenade |
|
pWeapon = dynamic_cast< CWeaponCSBase * >(player->GetCSWeapon( WEAPON_SMOKEGRENADE )); |
|
pInfo = GetWeaponInfo( WEAPON_SMOKEGRENADE ); |
|
int ammoType = (pInfo)?pInfo->iAmmoType:0; |
|
weaponSet->m_smokeGrenade = (pWeapon && player->GetAmmoCount( ammoType )); |
|
|
|
// Grab current HE grenade |
|
pWeapon = dynamic_cast< CWeaponCSBase * >(player->GetCSWeapon( WEAPON_HEGRENADE )); |
|
pInfo = GetWeaponInfo( WEAPON_HEGRENADE ); |
|
ammoType = (pInfo)?pInfo->iAmmoType:0; |
|
weaponSet->m_HEGrenade = (pWeapon && player->GetAmmoCount( ammoType )); |
|
|
|
// Grab current flashbangs |
|
pWeapon = dynamic_cast< CWeaponCSBase * >(player->GetCSWeapon( WEAPON_FLASHBANG )); |
|
pInfo = GetWeaponInfo( WEAPON_FLASHBANG ); |
|
ammoType = (pInfo)?pInfo->iAmmoType:0; |
|
weaponSet->m_flashbangs = (!pWeapon) ? 0 : player->GetAmmoCount( ammoType ); |
|
|
|
// Grab current equipment |
|
weaponSet->m_defuser = player->HasDefuser(); |
|
weaponSet->m_nightvision = player->HasNightVision(); |
|
|
|
// Grab current primary weapon |
|
CSWeaponID primaryID = GetClientWeaponID( true ); ///< The local player's current primary weapon |
|
pInfo = GetWeaponInfo( primaryID ); |
|
if ( pInfo ) |
|
{ |
|
int roundsNeeded = ammo[pInfo->iAmmoType]; |
|
int buySize = GetCSAmmoDef()->GetBuySize( pInfo->iAmmoType ); |
|
int numClips = ceil(roundsNeeded/(float)buySize); |
|
|
|
weaponSet->m_primaryWeapon.SetWeaponID( primaryID ); |
|
weaponSet->m_primaryWeapon.SetAmmoType( AMMO_CLIPS ); |
|
weaponSet->m_primaryWeapon.SetAmmoAmount( numClips ); |
|
weaponSet->m_primaryWeapon.SetFillAmmo( false ); |
|
} |
|
|
|
// Grab current pistol |
|
CSWeaponID secondaryID = GetClientWeaponID( false ); ///< The local player's current pistol |
|
pInfo = GetWeaponInfo( secondaryID ); |
|
if ( pInfo ) |
|
{ |
|
int roundsNeeded = ammo[pInfo->iAmmoType]; |
|
int buySize = GetCSAmmoDef()->GetBuySize( pInfo->iAmmoType ); |
|
int numClips = ceil(roundsNeeded/(float)buySize); |
|
|
|
weaponSet->m_secondaryWeapon.SetWeaponID( secondaryID ); |
|
weaponSet->m_secondaryWeapon.SetAmmoType( AMMO_CLIPS ); |
|
weaponSet->m_secondaryWeapon.SetAmmoAmount( numClips ); |
|
weaponSet->m_secondaryWeapon.SetFillAmmo( false ); |
|
} |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
//-------------------------------------------------------------------------------------------------------------- |
|
WeaponSet::WeaponSet() |
|
{ |
|
Reset(); |
|
} |
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
/** |
|
* Sets reasonable defaults for an empty weapon set: no primary/secondary weapons, no equipment, and |
|
* everything optional. |
|
*/ |
|
void WeaponSet::Reset() |
|
{ |
|
BuyPresetWeapon blank; |
|
m_primaryWeapon = blank; |
|
m_secondaryWeapon = blank; |
|
|
|
m_armor = 0; |
|
m_helmet = false; |
|
m_smokeGrenade = false; |
|
m_HEGrenade = false; |
|
m_flashbangs = 0; |
|
m_defuser = false; |
|
m_nightvision = false; |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
/** |
|
* Constructs a WeaponSet containing everything that could be purchased right now. The cost is also |
|
* returned, and is -1 if the set is not purchasable (as opposed to completely purchased already, in |
|
* which case cost is 0.) |
|
*/ |
|
void WeaponSet::GetCurrent( int& cost, WeaponSet& ws ) const |
|
{ |
|
cost = -1; |
|
ws.Reset(); |
|
|
|
if ( !engine->IsConnected() ) |
|
return; |
|
|
|
C_CSPlayer *player = CCSPlayer::GetLocalCSPlayer(); |
|
if ( !player ) |
|
return; |
|
|
|
if ( player->GetTeamNumber() != TEAM_CT && player->GetTeamNumber() != TEAM_TERRORIST ) |
|
return; |
|
|
|
// we're connected, and a valid team, so we can purchase |
|
cost = 0; |
|
|
|
if ( player->IsVIP() ) |
|
return; // can't buy anything as the VIP |
|
|
|
int iHelmetPrice = HELMET_PRICE; |
|
int iKevlarPrice = KEVLAR_PRICE; |
|
int iNVGPrice = NVG_PRICE; |
|
|
|
if ( CSGameRules()->IsBlackMarket() ) |
|
{ |
|
iHelmetPrice = CSGameRules()->GetBlackMarketPriceForWeapon( WEAPON_ASSAULTSUIT ) - CSGameRules()->GetBlackMarketPriceForWeapon( WEAPON_KEVLAR ); |
|
iKevlarPrice = CSGameRules()->GetBlackMarketPriceForWeapon( WEAPON_KEVLAR ); |
|
iNVGPrice = CSGameRules()->GetBlackMarketPriceForWeapon( WEAPON_NVG ); |
|
} |
|
|
|
//------------------------------------------------------------------------- |
|
//------------------------------------------------------------------------- |
|
// Buy any required items |
|
|
|
//------------------------------------------------------------------------- |
|
// Armor |
|
if ( m_armor > player->ArmorValue() ) |
|
{ |
|
cost += iKevlarPrice; |
|
ws.m_armor = 100; |
|
} |
|
|
|
if ( (m_helmet && m_armor > 0) && !player->HasHelmet() ) |
|
{ |
|
cost += iHelmetPrice; |
|
ws.m_armor = 100; |
|
ws.m_helmet = true; |
|
} |
|
|
|
CWeaponCSBase *pWeapon; |
|
CCSWeaponInfo *pInfo; |
|
|
|
//------------------------------------------------------------------------- |
|
// Smoke grenade |
|
pWeapon = dynamic_cast< CWeaponCSBase * >(player->GetCSWeapon( WEAPON_SMOKEGRENADE )); |
|
pInfo = GetWeaponInfo( WEAPON_SMOKEGRENADE ); |
|
int ammoType = (pInfo)?pInfo->iAmmoType:0; |
|
|
|
bool hasSmokeGrenade = (pWeapon && player->GetAmmoCount( ammoType )); |
|
if ( m_smokeGrenade && !hasSmokeGrenade ) |
|
{ |
|
cost += pInfo->GetWeaponPrice(); |
|
ws.m_smokeGrenade = true; |
|
hasSmokeGrenade = true; |
|
} |
|
|
|
//------------------------------------------------------------------------- |
|
// HE grenade |
|
pWeapon = dynamic_cast< CWeaponCSBase * >(player->GetCSWeapon( WEAPON_HEGRENADE )); |
|
pInfo = GetWeaponInfo( WEAPON_HEGRENADE ); |
|
ammoType = (pInfo)?pInfo->iAmmoType:0; |
|
|
|
bool hasHEGrenade = (pWeapon && player->GetAmmoCount( ammoType )); |
|
if ( m_HEGrenade && !hasHEGrenade ) |
|
{ |
|
cost += pInfo->GetWeaponPrice(); |
|
ws.m_HEGrenade = true; |
|
hasHEGrenade = true; |
|
} |
|
|
|
//------------------------------------------------------------------------- |
|
// Flashbang grenades |
|
pWeapon = dynamic_cast< CWeaponCSBase * >(player->GetCSWeapon( WEAPON_FLASHBANG )); |
|
pInfo = GetWeaponInfo( WEAPON_FLASHBANG ); |
|
ammoType = (pInfo)?pInfo->iAmmoType:0; |
|
|
|
int numFlashbangs = (!pWeapon) ? 0 : player->GetAmmoCount( ammoType ); |
|
if ( m_flashbangs && numFlashbangs < m_flashbangs ) |
|
{ |
|
int count = m_flashbangs - numFlashbangs; |
|
cost += pInfo->GetWeaponPrice() * count; |
|
ws.m_flashbangs = count; |
|
numFlashbangs += count; |
|
} |
|
|
|
//------------------------------------------------------------------------- |
|
// defuser |
|
if ( m_defuser && player->GetTeamNumber() == TEAM_CT && !player->HasDefuser() && CanBuyDefuser() ) |
|
{ |
|
cost += DEFUSEKIT_PRICE; |
|
ws.m_defuser = true; |
|
} |
|
|
|
//------------------------------------------------------------------------- |
|
// nightvision goggles |
|
if ( m_nightvision && !player->HasNightVision() ) |
|
{ |
|
cost += iNVGPrice; |
|
ws.m_nightvision = true; |
|
} |
|
|
|
//------------------------------------------------------------------------- |
|
// Construct a list of weapons to buy from. |
|
CSWeaponID primaryID = GetClientWeaponID( true ); ///< The local player's current primary weapon |
|
CSWeaponID secondaryID = GetClientWeaponID( false ); ///< The local player's current pistol |
|
|
|
BuyPresetWeaponList primaryWeapons; |
|
primaryWeapons.AddToTail( m_primaryWeapon ); |
|
|
|
BuyPresetWeaponList secondaryWeapons; |
|
secondaryWeapons.AddToTail( m_secondaryWeapon ); |
|
|
|
/** |
|
* Determine best weapons & ammo to purchase |
|
* |
|
* For each primary weapon in the list, do the following until one satisfies the current money situation: |
|
* 1. buy primary weapon and its ammo (NEED TO WATCH FOR WEAPONS PLAYER CANNOT BUY!!!) |
|
* 2. for each non-optional secondary weapon (if any), |
|
* try to buy it and its ammo |
|
* 3. when a set can be purchased, add it to the total cost and stop processing |
|
* If we can't purchase the primary weapon, or a required secondary weapon, the WeaponSet can't be bought, |
|
* so we return -1. |
|
* |
|
* To find if a weapon is owned, we can compare it's weaponID to either primaryID or secondaryID from above. |
|
*/ |
|
|
|
int currentCost = cost; |
|
int ammo[MAX_AMMO_TYPES]; |
|
memset( ammo, 0, sizeof(ammo) ); |
|
FillClientAmmo( ammo ); |
|
const BuyPresetWeapon *primaryWeaponToBuy = NULL; |
|
const BuyPresetWeapon *secondaryWeaponToBuy = NULL; |
|
int primaryClipsToBuy = 0; |
|
int secondaryClipsToBuy = 0; |
|
int currentNonWeaponCost = currentCost; |
|
bool doneBuyingWeapons = false; |
|
|
|
int currentCash = player->GetAccount(); |
|
|
|
//------------------------------------------------------------------------- |
|
// Try to buy the primary weapon |
|
int i; |
|
for ( i=0; i<primaryWeapons.Count() && !doneBuyingWeapons; ++i ) |
|
{ |
|
const BuyPresetWeapon *primaryWeapon = &primaryWeapons[i]; |
|
primaryWeaponToBuy = NULL; |
|
int primaryClips = 0; |
|
primaryClipsToBuy = 0; |
|
currentCost = currentNonWeaponCost; |
|
FillClientAmmo( ammo ); |
|
|
|
CSWeaponID weaponID = primaryWeapon->GetWeaponID(); |
|
if ( weaponID == WEAPON_NONE ) |
|
weaponID = primaryID; |
|
|
|
CCSWeaponInfo *primaryInfo = GetWeaponInfo( weaponID ); |
|
int primaryAmmoCost = 0; |
|
int primaryAmmoBuySize = 0; |
|
if ( primaryInfo ) |
|
{ |
|
primaryClips = CalcClipsNeeded( primaryWeapon, primaryInfo, ammo ); |
|
int primaryWeaponCost = ( weaponID != primaryID ) ? primaryInfo->GetWeaponPrice() : 0; |
|
primaryAmmoCost = GetCSAmmoDef()->GetCost( primaryInfo->iAmmoType ); |
|
primaryAmmoBuySize = GetCSAmmoDef()->GetBuySize( primaryInfo->iAmmoType ); |
|
currentCost += primaryWeaponCost; |
|
currentCost += primaryAmmoCost * primaryClips; |
|
ammo[primaryInfo->iAmmoType] += primaryClips * primaryAmmoBuySize; |
|
|
|
CURRENTCOST_DEBUG("\t%5.5d (%s)\n", primaryWeaponCost, WeaponIDToAlias( weaponID )); |
|
CURRENTCOST_DEBUG("\t%5.5d (ammo x %d)\n", primaryAmmoCost * primaryClips, primaryClips); |
|
if ( currentCash < currentCost ) |
|
{ |
|
currentCost = currentNonWeaponCost; // can't afford it, so try the next weapon |
|
continue; |
|
} |
|
|
|
// check for as_* maps, and CTs buying AK47s, etc |
|
if ( !CanBuyWeapon(primaryID, secondaryID, weaponID) && weaponID != primaryID ) |
|
{ |
|
currentCost = currentNonWeaponCost; // can't buy it, so try the next weapon |
|
continue; |
|
} |
|
|
|
primaryWeaponToBuy = primaryWeapon; |
|
primaryClipsToBuy = primaryClips; |
|
} |
|
|
|
if ( !secondaryWeapons.Count() ) |
|
{ |
|
CURRENTCOST_DEBUG("\t\t\tDone buying weapons (no secondary)\n"); |
|
break; |
|
} |
|
|
|
//------------------------------------------------------------------------- |
|
// Try to buy a (required) secondary weapon to go with primaryWeaponToBuy. |
|
// If not, reset cost to not reflect either weapon, so we can look at buying |
|
// the next primary weapon in the list. |
|
int j; |
|
for ( j=0; j<secondaryWeapons.Count(); ++j ) |
|
{ |
|
const BuyPresetWeapon *secondaryWeapon = &secondaryWeapons[j]; |
|
|
|
// reset ammo counts and cost |
|
secondaryWeaponToBuy = NULL; |
|
secondaryClipsToBuy = 0; |
|
currentCost = currentNonWeaponCost; |
|
FillClientAmmo( ammo ); |
|
|
|
// add in ammo we're already buying for the primary weapon to the client's actual ammo |
|
if ( primaryInfo ) |
|
{ |
|
currentCost += ( weaponID != primaryID ) ? primaryInfo->GetWeaponPrice() : 0; |
|
currentCost += primaryAmmoCost * primaryClips; |
|
ammo[primaryInfo->iAmmoType] += primaryClips * primaryAmmoBuySize; |
|
} |
|
|
|
int currentCostWithoutSecondary = currentCost; |
|
|
|
CSWeaponID weaponID = secondaryWeapon->GetWeaponID(); |
|
if ( weaponID == WEAPON_NONE ) |
|
weaponID = secondaryID; |
|
|
|
CCSWeaponInfo *secondaryInfo = GetWeaponInfo( weaponID ); |
|
if ( !secondaryInfo ) |
|
{ |
|
currentCost = currentCostWithoutSecondary; |
|
continue; |
|
} |
|
|
|
int secondaryClips = CalcClipsNeeded( secondaryWeapon, secondaryInfo, ammo ); |
|
int secondaryWeaponCost = ( weaponID != secondaryID ) ? secondaryInfo->GetWeaponPrice() : 0; |
|
int secondaryAmmoCost = GetCSAmmoDef()->GetCost( secondaryInfo->iAmmoType ); |
|
int secondaryAmmoBuySize = GetCSAmmoDef()->GetBuySize( secondaryInfo->iAmmoType ); |
|
currentCost += secondaryWeaponCost; |
|
currentCost += secondaryAmmoCost * secondaryClips; |
|
ammo[secondaryInfo->iAmmoType] += secondaryClips * secondaryAmmoBuySize; |
|
|
|
CURRENTCOST_DEBUG("\t%5.5d (%s)\n", secondaryWeaponCost, WeaponIDToAlias( weaponID )); |
|
CURRENTCOST_DEBUG("\t%5.5d (ammo x %d)\n", secondaryAmmoCost * secondaryClips, secondaryClips); |
|
if ( currentCash < currentCost ) |
|
{ |
|
currentCost = currentCostWithoutSecondary; // can't afford it, so skip |
|
continue; |
|
} |
|
|
|
// check for as_* maps, and CTs buying elites, etc |
|
if ( !CanBuyWeapon(primaryID, secondaryID, weaponID) && weaponID != secondaryID ) |
|
{ |
|
currentCost = currentCostWithoutSecondary; // can't buy it, so skip |
|
continue; |
|
} |
|
|
|
// We found both a primary and secondary weapon to buy. Stop looking for more. |
|
secondaryWeaponToBuy = secondaryWeapon; |
|
secondaryClipsToBuy = secondaryClips; |
|
doneBuyingWeapons = true; |
|
CURRENTCOST_DEBUG("\t\t\tDone buying weapons (primary && secondary)\n"); |
|
break; |
|
} |
|
} |
|
|
|
// Update our cost to reflect the weapons and ammo purchased |
|
cost = currentCost; |
|
|
|
if ( primaryWeaponToBuy ) |
|
{ |
|
BuyPresetWeapon weapon = *primaryWeaponToBuy; |
|
weapon.SetAmmoAmount( primaryClipsToBuy ); |
|
weapon.SetAmmoType( AMMO_CLIPS ); |
|
ws.m_primaryWeapon = weapon; |
|
} |
|
else |
|
{ |
|
// If we failed to buy a primary weapon, and one was in the list, bail - the player can't afford this WeaponSet. |
|
for ( int i=0; i<primaryWeapons.Count(); ++i ) |
|
{ |
|
int weaponID = primaryWeapons[i].GetWeaponID(); |
|
if ( weaponID != WEAPON_NONE ) |
|
{ |
|
cost = -1; |
|
ws.Reset(); |
|
return; |
|
} |
|
} |
|
} |
|
|
|
if ( secondaryWeaponToBuy ) |
|
{ |
|
BuyPresetWeapon weapon = *secondaryWeaponToBuy; |
|
weapon.SetAmmoAmount( secondaryClipsToBuy ); |
|
weapon.SetAmmoType( AMMO_CLIPS ); |
|
ws.m_secondaryWeapon = weapon; |
|
} |
|
else |
|
{ |
|
// If we failed to buy a required secondary weapon, and one was in the list, bail - the player can't afford this WeaponSet. |
|
for ( int i=0; i<secondaryWeapons.Count(); ++i ) |
|
{ |
|
int weaponID = secondaryWeapons[i].GetWeaponID(); |
|
if ( weaponID != WEAPON_NONE ) |
|
{ |
|
cost = -1; |
|
ws.Reset(); |
|
return; |
|
} |
|
} |
|
} |
|
|
|
//------------------------------------------------------------------------- |
|
// now any extra ammo, in rebuy order |
|
const char *remainder = SharedParse( cl_rebuy.GetString() ); |
|
const char *token; |
|
|
|
while ( remainder ) |
|
{ |
|
token = SharedGetToken(); |
|
if ( !token || !*token ) |
|
return; |
|
|
|
if ( !stricmp( token, "PrimaryAmmo" ) ) |
|
{ |
|
if ( primaryWeaponToBuy ) |
|
{ |
|
CSWeaponID id = primaryWeaponToBuy->GetWeaponID(); |
|
if ( id == WEAPON_NONE ) |
|
id = primaryID; |
|
|
|
if ( primaryWeaponToBuy->GetFillAmmo() ) |
|
{ |
|
const CCSWeaponInfo *info = GetWeaponInfo( id ); |
|
if ( info ) |
|
{ |
|
int maxRounds = GetCSAmmoDef()->MaxCarry( info->iAmmoType ); |
|
int ammoCost = GetCSAmmoDef()->GetCost( info->iAmmoType ); |
|
int ammoBuySize = GetCSAmmoDef()->GetBuySize( info->iAmmoType ); |
|
int roundsLeft = maxRounds - ammo[info->iAmmoType]; |
|
int clipsLeft = (ammoBuySize > 0) ? ceil(roundsLeft / (float)ammoBuySize) : 0; |
|
while ( clipsLeft > 0 && cost + ammoCost <= currentCash ) |
|
{ |
|
ws.m_primaryWeapon.SetAmmoAmount( ws.m_primaryWeapon.GetAmmoAmount() + 1 ); |
|
--clipsLeft; |
|
ammo[info->iAmmoType] += MIN(maxRounds, ammoBuySize); |
|
cost += ammoCost; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
else if ( !stricmp( token, "SecondaryAmmo" ) ) |
|
{ |
|
if ( secondaryWeaponToBuy ) |
|
{ |
|
if ( secondaryWeaponToBuy->GetFillAmmo() ) |
|
{ |
|
CSWeaponID weaponID = secondaryWeaponToBuy->GetWeaponID(); |
|
if ( weaponID == WEAPON_NONE ) |
|
weaponID = secondaryID; |
|
|
|
const CCSWeaponInfo *info = GetWeaponInfo( weaponID ); |
|
if ( info ) |
|
{ |
|
int maxRounds = GetCSAmmoDef()->MaxCarry( info->iAmmoType ); |
|
int ammoCost = GetCSAmmoDef()->GetCost( info->iAmmoType ); |
|
int ammoBuySize = GetCSAmmoDef()->GetBuySize( info->iAmmoType ); |
|
int roundsLeft = maxRounds - ammo[info->iAmmoType]; |
|
int clipsLeft = (ammoBuySize > 0) ? ceil(roundsLeft / (float)ammoBuySize) : 0; |
|
while ( clipsLeft > 0 && cost + ammoCost <= currentCash ) |
|
{ |
|
ws.m_secondaryWeapon.SetAmmoAmount( ws.m_secondaryWeapon.GetAmmoAmount() + 1 ); |
|
--clipsLeft; |
|
ammo[info->iAmmoType] += MIN(maxRounds, ammoBuySize); |
|
cost += ammoCost; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
remainder = SharedParse( remainder ); |
|
} |
|
|
|
if ( cost > currentCash ) |
|
{ |
|
cost = -1; // can't buy it |
|
ws.Reset(); |
|
} |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
/** |
|
* Constructs a WeaponSet containing everything that can be purchased. |
|
* The cost (including extra cash) is also calculated and returned. |
|
*/ |
|
void WeaponSet::GetFromScratch( int& cost, WeaponSet& ws ) const |
|
{ |
|
cost = 0; |
|
ws.Reset(); |
|
|
|
int ammo[MAX_AMMO_TYPES]; |
|
memset( ammo, 0, sizeof(ammo) ); |
|
|
|
int iHelmetPrice = HELMET_PRICE; |
|
int iKevlarPrice = KEVLAR_PRICE; |
|
int iNVGPrice = NVG_PRICE; |
|
|
|
if ( CSGameRules()->IsBlackMarket() ) |
|
{ |
|
iHelmetPrice = CSGameRules()->GetBlackMarketPriceForWeapon( WEAPON_ASSAULTSUIT ) - CSGameRules()->GetBlackMarketPriceForWeapon( WEAPON_KEVLAR ); |
|
iKevlarPrice = CSGameRules()->GetBlackMarketPriceForWeapon( WEAPON_KEVLAR ); |
|
iNVGPrice = CSGameRules()->GetBlackMarketPriceForWeapon( WEAPON_NVG ); |
|
} |
|
|
|
//------------------------------------------------------------------------- |
|
// Primary weapon |
|
CCSWeaponInfo *primaryInfo = GetWeaponInfo( m_primaryWeapon.GetWeaponID() ); |
|
if ( primaryInfo ) |
|
{ |
|
int primaryClips = CalcClipsNeeded( &m_primaryWeapon, primaryInfo, ammo ); |
|
int primaryWeaponCost = primaryInfo->GetWeaponPrice(); |
|
int primaryAmmoCost = GetCSAmmoDef()->GetCost( primaryInfo->iAmmoType ); |
|
int primaryAmmoBuySize = GetCSAmmoDef()->GetBuySize( primaryInfo->iAmmoType ); |
|
cost += primaryWeaponCost; |
|
cost += primaryAmmoCost * primaryClips; |
|
ammo[primaryInfo->iAmmoType] += primaryClips * primaryAmmoBuySize; |
|
|
|
ws.m_primaryWeapon = m_primaryWeapon; |
|
ws.m_primaryWeapon.SetAmmoAmount( primaryClips ); |
|
ws.m_primaryWeapon.SetAmmoType( AMMO_CLIPS ); |
|
ws.m_primaryWeapon.SetFillAmmo( false ); |
|
} |
|
|
|
//------------------------------------------------------------------------- |
|
// secondary weapon |
|
CCSWeaponInfo *secondaryInfo = GetWeaponInfo( m_secondaryWeapon.GetWeaponID() ); |
|
if ( secondaryInfo ) |
|
{ |
|
int secondaryClips = CalcClipsNeeded( &m_secondaryWeapon, secondaryInfo, ammo ); |
|
int secondaryWeaponCost = secondaryInfo->GetWeaponPrice(); |
|
int secondaryAmmoCost = GetCSAmmoDef()->GetCost( secondaryInfo->iAmmoType ); |
|
int secondaryAmmoBuySize = GetCSAmmoDef()->GetBuySize( secondaryInfo->iAmmoType ); |
|
cost += secondaryWeaponCost; |
|
cost += secondaryAmmoCost * secondaryClips; |
|
ammo[secondaryInfo->iAmmoType] += secondaryClips * secondaryAmmoBuySize; |
|
|
|
ws.m_secondaryWeapon = m_secondaryWeapon; |
|
ws.m_secondaryWeapon.SetAmmoAmount( secondaryClips ); |
|
ws.m_secondaryWeapon.SetAmmoType( AMMO_CLIPS ); |
|
ws.m_secondaryWeapon.SetFillAmmo( false ); |
|
} |
|
|
|
//------------------------------------------------------------------------- |
|
// equipment |
|
if ( m_armor ) |
|
{ |
|
cost += (m_helmet) ? (iKevlarPrice + iHelmetPrice) : iKevlarPrice; |
|
ws.m_armor = m_armor; |
|
ws.m_helmet = m_helmet; |
|
} |
|
|
|
if ( m_smokeGrenade ) |
|
{ |
|
CCSWeaponInfo *pInfo = GetWeaponInfo( WEAPON_SMOKEGRENADE ); |
|
cost += ( pInfo ) ? pInfo->GetWeaponPrice() : 0; |
|
ws.m_smokeGrenade = m_smokeGrenade; |
|
} |
|
|
|
if ( m_HEGrenade ) |
|
{ |
|
CCSWeaponInfo *pInfo = GetWeaponInfo( WEAPON_HEGRENADE ); |
|
cost += ( pInfo ) ? pInfo->GetWeaponPrice() : 0; |
|
ws.m_HEGrenade = m_HEGrenade; |
|
} |
|
|
|
CCSWeaponInfo *pInfo = GetWeaponInfo( WEAPON_FLASHBANG ); |
|
cost += ( pInfo ) ? pInfo->GetWeaponPrice() * m_flashbangs : 0; |
|
ws.m_flashbangs = m_flashbangs; |
|
|
|
if ( m_defuser ) |
|
{ |
|
cost += DEFUSEKIT_PRICE; |
|
ws.m_defuser = m_defuser; |
|
} |
|
|
|
if ( m_nightvision ) |
|
{ |
|
cost += iNVGPrice; |
|
ws.m_nightvision = m_nightvision; |
|
} |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
/** |
|
* Convenience function that wraps GetFromScratch() and discards the generated WeaponSet. Returns the cost |
|
* to buy the full WeaponSet from scratch. |
|
*/ |
|
int WeaponSet::FullCost() const |
|
{ |
|
WeaponSet fullSet; |
|
int cost = 0; |
|
GetFromScratch( cost, fullSet ); |
|
return cost; |
|
} |
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
/** |
|
* Generates a list of buy commands that will buy the current WeaponSet. |
|
*/ |
|
void WeaponSet::GenerateBuyCommands( char command[BUY_PRESET_COMMAND_LEN] ) const |
|
{ |
|
command[0] = 0; |
|
char *tmp = command; |
|
int remainder = BUY_PRESET_COMMAND_LEN; |
|
int i; |
|
|
|
CSWeaponID primaryID = GetClientWeaponID( true ); ///< The local player's current primary weapon |
|
CSWeaponID secondaryID = GetClientWeaponID( false ); ///< The local player's current pistol |
|
|
|
//------------------------------------------------------------------------- |
|
// Primary weapon |
|
CSWeaponID weaponID = m_primaryWeapon.GetWeaponID(); |
|
if ( weaponID == WEAPON_NONE ) |
|
weaponID = primaryID; |
|
const CCSWeaponInfo *primaryInfo = GetWeaponInfo( weaponID ); |
|
if ( primaryInfo ) |
|
{ |
|
if ( weaponID != primaryID ) |
|
{ |
|
tmp = BufPrintf( tmp, remainder, "buy %s\n", WeaponIDToAlias(weaponID) ); |
|
} |
|
for ( i=0; i<m_primaryWeapon.GetAmmoAmount(); ++i ) |
|
{ |
|
tmp = BufPrintf( tmp, remainder, "buyammo1\n" ); |
|
} |
|
} |
|
|
|
//------------------------------------------------------------------------- |
|
// secondary weapon |
|
weaponID = m_secondaryWeapon.GetWeaponID(); |
|
if ( weaponID == WEAPON_NONE ) |
|
weaponID = secondaryID; |
|
const CCSWeaponInfo *secondaryInfo = GetWeaponInfo( weaponID ); |
|
if ( secondaryInfo ) |
|
{ |
|
if ( weaponID != secondaryID ) |
|
{ |
|
tmp = BufPrintf( tmp, remainder, "buy %s\n", WeaponIDToAlias(weaponID) ); |
|
} |
|
for ( i=0; i<m_secondaryWeapon.GetAmmoAmount(); ++i ) |
|
{ |
|
tmp = BufPrintf( tmp, remainder, "buyammo2\n" ); |
|
} |
|
} |
|
|
|
//------------------------------------------------------------------------- |
|
// equipment |
|
if ( m_armor ) |
|
{ |
|
if ( m_helmet ) |
|
{ |
|
tmp = BufPrintf( tmp, remainder, "buy vesthelm\n" ); |
|
} |
|
else |
|
{ |
|
tmp = BufPrintf( tmp, remainder, "buy vest\n" ); |
|
} |
|
} |
|
|
|
if ( m_smokeGrenade ) |
|
{ |
|
tmp = BufPrintf( tmp, remainder, "buy smokegrenade\n" ); |
|
} |
|
|
|
if ( m_HEGrenade ) |
|
{ |
|
tmp = BufPrintf( tmp, remainder, "buy hegrenade\n" ); |
|
} |
|
|
|
for ( i=0; i<m_flashbangs; ++i ) |
|
{ |
|
tmp = BufPrintf( tmp, remainder, "buy flashbang\n" ); |
|
} |
|
|
|
if ( m_defuser ) |
|
{ |
|
tmp = BufPrintf( tmp, remainder, "buy defuser\n" ); |
|
} |
|
|
|
if ( m_nightvision ) |
|
{ |
|
tmp = BufPrintf( tmp, remainder, "buy nvgs\n" ); |
|
} |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
/** |
|
* Return images out of a subdir, so when the buy preset system resizes the images, they don't resize in the |
|
* main buy menu. |
|
*/ |
|
const char *ImageFnameFromWeaponID( CSWeaponID weaponID, bool isPrimary ) |
|
{ |
|
switch (weaponID) |
|
{ |
|
case WEAPON_NONE: |
|
return "gfx/vgui/defaultweapon"; |
|
case WEAPON_SCOUT: |
|
return "gfx/vgui/scout"; |
|
case WEAPON_XM1014: |
|
return "gfx/vgui/xm1014"; |
|
case WEAPON_MAC10: |
|
return "gfx/vgui/mac10"; |
|
case WEAPON_AUG: |
|
return "gfx/vgui/aug"; |
|
case WEAPON_UMP45: |
|
return "gfx/vgui/ump45"; |
|
case WEAPON_SG550: |
|
return "gfx/vgui/sg550"; |
|
case WEAPON_GALIL: |
|
return "gfx/vgui/galil"; |
|
case WEAPON_FAMAS: |
|
return "gfx/vgui/famas"; |
|
case WEAPON_AWP: |
|
return "gfx/vgui/awp"; |
|
case WEAPON_MP5NAVY: |
|
return "gfx/vgui/mp5"; |
|
case WEAPON_M249: |
|
return "gfx/vgui/m249"; |
|
case WEAPON_M3: |
|
return "gfx/vgui/m3"; |
|
case WEAPON_M4A1: |
|
return "gfx/vgui/m4a1"; |
|
case WEAPON_TMP: |
|
return "gfx/vgui/tmp"; |
|
case WEAPON_G3SG1: |
|
return "gfx/vgui/g3sg1"; |
|
case WEAPON_SG552: |
|
return "gfx/vgui/sg552"; |
|
case WEAPON_AK47: |
|
return "gfx/vgui/ak47"; |
|
case WEAPON_P90: |
|
return "gfx/vgui/p90"; |
|
case WEAPON_SHIELDGUN: |
|
return "gfx/vgui/shield"; |
|
|
|
case WEAPON_USP: |
|
return "gfx/vgui/usp45"; |
|
case WEAPON_GLOCK: |
|
return "gfx/vgui/glock18"; |
|
case WEAPON_DEAGLE: |
|
return "gfx/vgui/deserteagle"; |
|
case WEAPON_ELITE: |
|
return "gfx/vgui/elites"; |
|
case WEAPON_P228: |
|
return "gfx/vgui/p228"; |
|
case WEAPON_FIVESEVEN: |
|
return "gfx/vgui/fiveseven"; |
|
|
|
default: |
|
return ""; |
|
} |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
//-------------------------------------------------------------------------------------------------------------- |
|
BuyPreset::BuyPreset() |
|
{ |
|
SetName( L"" ); |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
BuyPreset::BuyPreset( const BuyPreset& other ) |
|
{ |
|
*this = other; |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
BuyPreset::~BuyPreset() |
|
{ |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
void BuyPreset::SetName( const wchar_t *name ) |
|
{ |
|
wcsncpy( m_name, name, MaxBuyPresetName ); |
|
if ( m_name[0] == 0 ) |
|
{ |
|
const wchar_t * defaultName = g_pVGuiLocalize->Find( "#Cstrike_BuyPresetBlank" ); |
|
if ( defaultName ) |
|
{ |
|
wcsncpy( m_name, defaultName, MaxBuyPresetName ); |
|
} |
|
} |
|
m_name[MaxBuyPresetName-1] = 0; |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
// Parse KeyValues string into a BuyPresetWeapon vector |
|
static void ParseWeaponString( const char *str, BuyPresetWeaponList& weapons, bool isPrimary ) |
|
{ |
|
weapons.RemoveAll(); |
|
|
|
if ( !str ) |
|
return; |
|
|
|
const char *remainder = SharedParse( str ); |
|
const char *token; |
|
|
|
const int BufLen = 32; |
|
char tmpBuf[BufLen]; |
|
tmpBuf[0] = '\0'; |
|
char weaponBuf[BufLen]; |
|
weaponBuf[0] = '\0'; |
|
char clipModifier = 0; |
|
int numClips = 0; |
|
|
|
while ( remainder ) |
|
{ |
|
token = SharedGetToken(); |
|
if ( !token || strlen(token) >= BufLen ) |
|
return; |
|
|
|
Q_strncpy( tmpBuf, token, BufLen ); |
|
tmpBuf[BufLen - 1] = 0; |
|
char *tmp = tmpBuf; |
|
while ( *tmp ) |
|
{ |
|
if ( *tmp == '/' ) |
|
{ |
|
*tmp = ' '; |
|
} |
|
++tmp; |
|
} |
|
// sscanf is safe, since the size of the string being scanned is at least as small as any individual destination buffer |
|
if ( sscanf( tmpBuf, "%s %d%c", weaponBuf, &numClips, &clipModifier ) != 3 ) |
|
return; |
|
|
|
CSWeaponID weaponID = AliasToWeaponID( weaponBuf ); |
|
if ( weaponID != WEAPON_NONE ) |
|
{ |
|
const CCSWeaponInfo *info = GetWeaponInfo( weaponID ); |
|
if ( info ) |
|
{ |
|
int maxRounds = GetCSAmmoDef()->MaxCarry( info->iAmmoType ); |
|
int buySize = GetCSAmmoDef()->GetBuySize( info->iAmmoType ); |
|
numClips = MIN(ceil(maxRounds/(float)buySize), MAX(0, numClips)); |
|
if ( ((!isPrimary) ^ IsPrimaryWeapon( weaponID )) == 0 ) |
|
return; |
|
} |
|
else |
|
{ |
|
numClips = MIN(NUM_CLIPS_FOR_CURRENT, MAX(0, numClips)); |
|
} |
|
} |
|
else |
|
{ |
|
numClips = MIN(NUM_CLIPS_FOR_CURRENT, MAX(0, numClips)); |
|
} |
|
|
|
BuyPresetWeapon weapon( weaponID ); |
|
weapon.SetAmmoType( AMMO_CLIPS ); |
|
weapon.SetAmmoAmount( numClips ); |
|
weapon.SetFillAmmo( (clipModifier == '+') ); |
|
weapons.AddToTail( weapon ); |
|
|
|
remainder = SharedParse( remainder ); |
|
} |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
/** |
|
* Populates data from a KeyValues structure, for loading |
|
*/ |
|
void BuyPreset::Parse( KeyValues *data ) |
|
{ |
|
m_name[0] = 0; |
|
m_weaponList.RemoveAll(); |
|
|
|
if (!data) |
|
return; |
|
|
|
//------------------------------------------------------------------------- |
|
// Read name |
|
wcsncpy( m_name, data->GetWString( "PresetName", L""), MaxBuyPresetName ); |
|
m_name[ MaxBuyPresetName - 1 ] = 0; |
|
PRESET_DEBUG( "Parsing Buy Preset %ls\n", m_name ); |
|
|
|
int version = data->GetInt( "Version", 0 ); |
|
if ( version < 4 || version > 4 ) |
|
{ |
|
PRESET_DEBUG( "Invalid preset version %d\n", version ); |
|
return; |
|
} |
|
|
|
const char *primaryString = data->GetString( "Primary", NULL ); |
|
const char *secondaryString = data->GetString( "Secondary", NULL ); |
|
const char *equipmentString = data->GetString( "Equipment", NULL ); |
|
|
|
CUtlVector< BuyPresetWeapon > weapons; |
|
ParseWeaponString( primaryString, weapons, true ); |
|
|
|
WeaponSet ws; |
|
if ( weapons.Count() ) |
|
ws.m_primaryWeapon = weapons[0]; |
|
|
|
weapons.RemoveAll(); |
|
ParseWeaponString( secondaryString, weapons, false ); |
|
if ( weapons.Count() ) |
|
ws.m_secondaryWeapon = weapons[0]; |
|
|
|
// parse equipment |
|
if ( equipmentString ) |
|
{ |
|
const char *remainder = SharedParse( equipmentString ); |
|
const char *token; |
|
|
|
const int BufLen = 32; |
|
char tmpBuf[BufLen]; |
|
char itemBuf[BufLen]; |
|
int intVal; |
|
|
|
while ( remainder ) |
|
{ |
|
token = SharedGetToken(); |
|
if ( !token || Q_strlen(token) >= BufLen ) |
|
break; |
|
|
|
Q_strncpy( tmpBuf, token, BufLen ); |
|
tmpBuf[BufLen - 1] = 0; |
|
char *tmp = tmpBuf; |
|
while ( *tmp ) |
|
{ |
|
if ( *tmp == '/' ) |
|
{ |
|
*tmp = ' '; |
|
} |
|
++tmp; |
|
} |
|
// sscanf is safe, since the size of the string being scanned is at least as small as any individual destination buffer |
|
if ( sscanf( tmpBuf, "%s %d", itemBuf, &intVal ) != 2 ) |
|
break; |
|
|
|
if ( !strcmp( itemBuf, "vest" ) ) |
|
{ |
|
ws.m_armor = (intVal > 0) ? 100 : 0; |
|
ws.m_helmet = false; |
|
} |
|
else if ( !strcmp( itemBuf, "vesthelm" ) ) |
|
{ |
|
ws.m_armor = (intVal > 0) ? 100 : 0; |
|
ws.m_helmet = true; |
|
} |
|
else if ( !strcmp( itemBuf, "defuser" ) ) |
|
{ |
|
ws.m_defuser = (intVal > 0); |
|
} |
|
else if ( !strcmp( itemBuf, "nvgs" ) ) |
|
{ |
|
ws.m_nightvision = (intVal > 0); |
|
} |
|
else if ( !strcmp( itemBuf, "sgren" ) ) |
|
{ |
|
ws.m_smokeGrenade = (intVal > 0); |
|
} |
|
else if ( !strcmp( itemBuf, "hegren" ) ) |
|
{ |
|
ws.m_HEGrenade = (intVal > 0); |
|
} |
|
else if ( !strcmp( itemBuf, "flash" ) ) |
|
{ |
|
ws.m_flashbangs = MIN( 2, MAX( 0, intVal ) ); |
|
} |
|
|
|
remainder = SharedParse( remainder ); |
|
} |
|
|
|
m_weaponList.AddToTail( ws ); |
|
} |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
// Build a string of weapons+ammo for KeyValues saving/loading |
|
static const char* ConstructWeaponString( const BuyPresetWeapon& weapon ) |
|
{ |
|
const int WeaponLen = 1024; |
|
static char weaponString[WeaponLen]; |
|
weaponString[0] = 0; |
|
int remainder = WeaponLen; |
|
char *tmp = weaponString; |
|
|
|
tmp = BufPrintf( tmp, remainder, "%s/%d%c", |
|
WeaponIDToAlias( weapon.GetWeaponID() ), |
|
weapon.GetAmmoAmount(), |
|
(weapon.GetFillAmmo()) ? '+' : '=' ); |
|
return weaponString; |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
/** |
|
* Fills in a KeyValues structure with data, for saving |
|
*/ |
|
void BuyPreset::Save( KeyValues *data ) |
|
{ |
|
//------------------------------------------------------------------------- |
|
// Save name and version |
|
KeyValues *presetKey = data->CreateNewKey(); |
|
presetKey->SetWString( "PresetName", m_name ); |
|
|
|
/** |
|
* Version History |
|
* --------------- |
|
* |
|
* PRE-RELEASE |
|
* 1. 2/2004 |
|
* First-pass implementation. Allowed for multiple weapons per fallback. |
|
* Individual items could be marked optional. Cash reserve could be specified. |
|
* 2. 3/2004 |
|
* Second-pass implementation. Removed multiple weapons per fallback. The |
|
* pistol could be marked optional. A preset could be marked as 'use for |
|
* Autobuy'. |
|
* |
|
* CZ RELEASE |
|
* 3. 4/22/2004 |
|
* The first released version. Removed optional/required status. Also |
|
* removed the cash reserve and autobuy status. Corresponds to streamlined |
|
* editing interface mocked up by Greg Coomer. |
|
* |
|
* CS:S RELEASE |
|
* 4. 3/10/2004 |
|
* Removed fallbacks to correspond to new UI. |
|
*/ |
|
presetKey->SetInt( "Version", 4 ); |
|
if ( m_weaponList.Count() > 0 ) |
|
{ |
|
//------------------------------------------------------------------------- |
|
// Save a fallback WeaponSet |
|
const WeaponSet& ws = m_weaponList[0]; |
|
|
|
presetKey->SetString( "Primary", ConstructWeaponString( ws.m_primaryWeapon ) ); |
|
presetKey->SetString( "Secondary", ConstructWeaponString( ws.m_secondaryWeapon ) ); |
|
|
|
presetKey->SetString( "Equipment", |
|
SharedVarArgs("vest%s/%d flash/%d sgren/%d hegren/%d defuser/%d nvgs/%d", |
|
(ws.m_helmet)?"helm":"", ws.m_armor, |
|
ws.m_flashbangs, |
|
ws.m_smokeGrenade, |
|
ws.m_HEGrenade, |
|
ws.m_defuser, |
|
ws.m_nightvision |
|
) ); |
|
} |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
/** |
|
* Calculates the full cost of the preset, which is exactly the full cost of the first fallback WeaponSet |
|
*/ |
|
int BuyPreset::FullCost() const |
|
{ |
|
if ( m_weaponList.Count() == 0 ) |
|
return 0; |
|
|
|
return m_weaponList[0].FullCost(); |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
/** |
|
* Returns the specified fallback WeaponSet, or NULL if it doesn't exist |
|
*/ |
|
const WeaponSet * BuyPreset::GetSet( int index ) const |
|
{ |
|
if ( index < 0 || index >= m_weaponList.Count() ) |
|
return NULL; |
|
|
|
return &(m_weaponList[index]); |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
/** |
|
* Deletes a fallback |
|
*/ |
|
void BuyPreset::DeleteSet( int index ) |
|
{ |
|
if ( index < 0 || index >= m_weaponList.Count() ) |
|
return; |
|
|
|
m_weaponList.Remove( index ); |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
/** |
|
* Switches the order of two fallbacks |
|
*/ |
|
void BuyPreset::SwapSet( int firstIndex, int secondIndex ) |
|
{ |
|
if ( firstIndex < 0 || firstIndex >= m_weaponList.Count() ) |
|
return; |
|
|
|
if ( secondIndex < 0 || secondIndex >= m_weaponList.Count() ) |
|
return; |
|
|
|
WeaponSet tmpSet = m_weaponList[firstIndex]; |
|
m_weaponList[firstIndex] = m_weaponList[secondIndex]; |
|
m_weaponList[secondIndex] = tmpSet; |
|
} |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
/** |
|
* Replaces a fallback with the supplied WeaponSet |
|
*/ |
|
void BuyPreset::ReplaceSet( int index, const WeaponSet& weaponSet ) |
|
{ |
|
if ( index < 0 || index > m_weaponList.Count() ) |
|
return; |
|
|
|
if ( index == m_weaponList.Count() ) |
|
{ |
|
m_weaponList.AddToTail( weaponSet ); |
|
} |
|
else |
|
{ |
|
m_weaponList[index] = weaponSet; |
|
} |
|
} |
|
|
|
//--------------------------------------------------------------------------------------------------------------
|
|
|