const char *BotProfile::GetWeaponPreferenceAsString(int i) const { if (i < 0 || i >= m_weaponPreferenceCount) return nullptr; return WeaponIDToAlias(m_weaponPreference[i]); }
/** * Return true if this profile has a pistol weapon preference */ bool BotProfile::HasPistolPreference( void ) const { for( int i=0; i<m_weaponPreferenceCount; ++i ) if (AliasToWeaponClass( WeaponIDToAlias( m_weaponPreference[i] ) ) == WEAPONCLASS_PISTOL) return true; return false; }
// Games implementing advanced bot support should override this. const char *CPlayerInfoManager::WeaponIdToAlias(int weaponId) { #if defined( TF_DLL ) return WeaponIdToAlias(weaponId); #elif defined ( CSTRIKE_DLL ) || defined ( DOD_DLL ) || defined ( SDK_DLL ) return WeaponIDToAlias(weaponId); #endif return "MOD_DIDNT_IMPLEMENT_ME"; }
// Return true if this profile has a primary weapon preference bool BotProfile::HasPrimaryPreference() const { for (int i = 0; i < m_weaponPreferenceCount; i++) { int weaponClass = AliasToWeaponClass(WeaponIDToAlias(m_weaponPreference[i])); if (weaponClass == WEAPONCLASS_SUBMACHINEGUN || weaponClass == WEAPONCLASS_SHOTGUN || weaponClass == WEAPONCLASS_MACHINEGUN || weaponClass == WEAPONCLASS_RIFLE || weaponClass == WEAPONCLASS_SNIPERRIFLE) return true; } return false; }
CSDKWeaponInfo* CSDKWeaponInfo::GetWeaponInfo(SDKWeaponID eWeapon) { const char* pszAlias = WeaponIDToAlias( eWeapon ); Assert(pszAlias); if (!pszAlias) return NULL; char szName[128]; Q_snprintf( szName, sizeof( szName ), "weapon_%s", pszAlias ); WEAPON_FILE_INFO_HANDLE hWeaponFile = LookupWeaponInfoSlot( szName ); if (hWeaponFile == GetInvalidWeaponInfoHandle()) { Assert(hWeaponFile != GetInvalidWeaponInfoHandle()); return NULL; } return static_cast< CSDKWeaponInfo* >( GetFileWeaponInfoFromHandle( hWeaponFile ) ); }
void CSDKGameRules::PlayerSpawn( CBasePlayer *p ) { CSDKPlayer *pPlayer = ToSDKPlayer( p ); int team = pPlayer->GetTeamNumber(); if( team != TEAM_SPECTATOR ) { #if defined ( SDK_USE_PLAYERCLASSES ) if( pPlayer->m_Shared.DesiredPlayerClass() == PLAYERCLASS_RANDOM ) { ChooseRandomClass( pPlayer ); ClientPrint( pPlayer, HUD_PRINTTALK, "#game_now_as", GetPlayerClassName( pPlayer->m_Shared.PlayerClass(), team ) ); } else { pPlayer->m_Shared.SetPlayerClass( pPlayer->m_Shared.DesiredPlayerClass() ); } int playerclass = pPlayer->m_Shared.PlayerClass(); if( playerclass != PLAYERCLASS_UNDEFINED ) { //Assert( PLAYERCLASS_UNDEFINED < playerclass && playerclass < NUM_PLAYERCLASSES ); CSDKTeam *pTeam = GetGlobalSDKTeam( team ); const CSDKPlayerClassInfo &pClassInfo = pTeam->GetPlayerClassInfo( playerclass ); Assert( pClassInfo.m_iTeam == team ); pPlayer->SetModel( pClassInfo.m_szPlayerModel ); pPlayer->SetHitboxSet( 0 ); char buf[64]; int bufsize = sizeof(buf); //Give weapons // Primary weapon Q_snprintf( buf, bufsize, "weapon_%s", WeaponIDToAlias(pClassInfo.m_iPrimaryWeapon) ); CBaseEntity *pPrimaryWpn = pPlayer->GiveNamedItem( buf ); Assert( pPrimaryWpn ); // Secondary weapon CBaseEntity *pSecondaryWpn = NULL; if ( pClassInfo.m_iSecondaryWeapon != WEAPON_NONE ) { Q_snprintf( buf, bufsize, "weapon_%s", WeaponIDToAlias(pClassInfo.m_iSecondaryWeapon) ); pSecondaryWpn = pPlayer->GiveNamedItem( buf ); } // Melee weapon if ( pClassInfo.m_iMeleeWeapon ) { Q_snprintf( buf, bufsize, "weapon_%s", WeaponIDToAlias(pClassInfo.m_iMeleeWeapon) ); pPlayer->GiveNamedItem( buf ); } CWeaponSDKBase *pWpn = NULL; // Primary Ammo pWpn = dynamic_cast<CWeaponSDKBase *>(pPrimaryWpn); if( pWpn ) { int iNumClip = pWpn->GetSDKWpnData().m_iDefaultAmmoClips - 1; //account for one clip in the gun int iClipSize = pWpn->GetSDKWpnData().iMaxClip1; pPlayer->GiveAmmo( iNumClip * iClipSize, pWpn->GetSDKWpnData().szAmmo1 ); } // Secondary Ammo if ( pSecondaryWpn ) { pWpn = dynamic_cast<CWeaponSDKBase *>(pSecondaryWpn); if( pWpn ) { int iNumClip = pWpn->GetSDKWpnData().m_iDefaultAmmoClips - 1; //account for one clip in the gun int iClipSize = pWpn->GetSDKWpnData().iMaxClip1; pPlayer->GiveAmmo( iNumClip * iClipSize, pWpn->GetSDKWpnData().szAmmo1 ); } } // Grenade Type 1 if ( pClassInfo.m_iGrenType1 != WEAPON_NONE ) { Q_snprintf( buf, bufsize, "weapon_%s", WeaponIDToAlias(pClassInfo.m_iGrenType1) ); CBaseEntity *pGrenade = pPlayer->GiveNamedItem( buf ); Assert( pGrenade ); pWpn = dynamic_cast<CWeaponSDKBase *>(pGrenade); if( pWpn ) { pPlayer->GiveAmmo( pClassInfo.m_iNumGrensType1 - 1, pWpn->GetSDKWpnData().szAmmo1 ); } } // Grenade Type 2 if ( pClassInfo.m_iGrenType2 != WEAPON_NONE ) { Q_snprintf( buf, bufsize, "weapon_%s", WeaponIDToAlias(pClassInfo.m_iGrenType2) ); CBaseEntity *pGrenade2 = pPlayer->GiveNamedItem( buf ); Assert( pGrenade2 ); pWpn = dynamic_cast<CWeaponSDKBase *>(pGrenade2); if( pWpn ) { pPlayer->GiveAmmo( pClassInfo.m_iNumGrensType2 - 1, pWpn->GetSDKWpnData().szAmmo1 ); } } pPlayer->Weapon_Switch( (CBaseCombatWeapon *)pPrimaryWpn ); // DevMsg("setting spawn armor to: %d\n", pClassInfo.m_iArmor ); pPlayer->SetSpawnArmorValue( pClassInfo.m_iArmor ); } else { // Assert( !"Player spawning with PLAYERCLASS_UNDEFINED" ); pPlayer->SetModel( SDK_PLAYER_MODEL ); } #else pPlayer->GiveDefaultItems(); #endif // SDK_USE_PLAYERCLASSES pPlayer->SetMaxSpeed( 600 ); } }
//-------------------------------------------------------------------------------------------------------------- void BuyState::OnUpdate( CCSBot *me ) { char cmdBuffer[256]; // wait for a Navigation Mesh if (!TheNavMesh->IsLoaded()) return; // apparently we cant buy things in the first few seconds, so wait a bit if (m_isInitialDelay) { const float waitToBuyTime = 0.25f; if (gpGlobals->curtime - me->GetStateTimestamp() < waitToBuyTime) return; m_isInitialDelay = false; } // if we're done buying and still in the freeze period, wait if (m_doneBuying) { if (CSGameRules()->IsMultiplayer() && CSGameRules()->IsFreezePeriod()) { // make sure we're locked and loaded me->EquipBestWeapon( MUST_EQUIP ); me->Reload(); me->ResetStuckMonitor(); return; } me->Idle(); return; } // If we're supposed to buy a specific weapon for debugging, do so and then bail const char *cheatWeaponString = bot_loadout.GetString(); if ( cheatWeaponString && *cheatWeaponString ) { CUtlVector<char*, CUtlMemory<char*> > loadout; Q_SplitString( cheatWeaponString, " ", loadout ); for ( int i=0; i<loadout.Count(); ++i ) { const char *item = loadout[i]; if ( FStrEq( item, "vest" ) ) { me->GiveNamedItem( "item_kevlar" ); } else if ( FStrEq( item, "vesthelm" ) ) { me->GiveNamedItem( "item_assaultsuit" ); } else if ( FStrEq( item, "defuser" ) ) { if ( me->GetTeamNumber() == TEAM_CT ) { me->GiveDefuser(); } } else if ( FStrEq( item, "nvgs" ) ) { me->m_bHasNightVision = true; } else if ( FStrEq( item, "primammo" ) ) { me->AttemptToBuyAmmo( 0 ); } else if ( FStrEq( item, "secammo" ) ) { me->AttemptToBuyAmmo( 1 ); } else { me->GiveWeapon( item ); } } m_doneBuying = true; return; } if (!me->IsInBuyZone()) { m_doneBuying = true; CONSOLE_ECHO( "%s bot spawned outside of a buy zone (%d, %d, %d)\n", (me->GetTeamNumber() == TEAM_CT) ? "CT" : "Terrorist", (int)me->GetAbsOrigin().x, (int)me->GetAbsOrigin().y, (int)me->GetAbsOrigin().z ); return; } // try to buy some weapons const float buyInterval = 0.02f; if (gpGlobals->curtime - me->GetStateTimestamp() > buyInterval) { me->m_stateTimestamp = gpGlobals->curtime; bool isPreferredAllDisallowed = true; // try to buy our preferred weapons first if (m_prefIndex < me->GetProfile()->GetWeaponPreferenceCount() && bot_randombuy.GetBool() == false ) { // need to retry because sometimes first buy fails?? const int maxPrefRetries = 2; if (m_prefRetries >= maxPrefRetries) { // try to buy next preferred weapon ++m_prefIndex; m_prefRetries = 0; return; } int weaponPreference = me->GetProfile()->GetWeaponPreference( m_prefIndex ); // don't buy it again if we still have one from last round char weaponPreferenceName[32]; Q_snprintf( weaponPreferenceName, sizeof(weaponPreferenceName), "weapon_%s", me->GetProfile()->GetWeaponPreferenceAsString( m_prefIndex ) ); if( me->Weapon_OwnsThisType(weaponPreferenceName) )//Prefs and buyalias use the short version, this uses the long { // done with buying preferred weapon m_prefIndex = 9999; return; } if (me->HasShield() && weaponPreference == WEAPON_SHIELDGUN) { // done with buying preferred weapon m_prefIndex = 9999; return; } const char *buyAlias = NULL; if (weaponPreference == WEAPON_SHIELDGUN) { if (TheCSBots()->AllowTacticalShield()) buyAlias = "shield"; } else { buyAlias = WeaponIDToAlias( weaponPreference ); WeaponType type = GetWeaponType( buyAlias ); switch( type ) { case PISTOL: if (!TheCSBots()->AllowPistols()) buyAlias = NULL; break; case SHOTGUN: if (!TheCSBots()->AllowShotguns()) buyAlias = NULL; break; case SUB_MACHINE_GUN: if (!TheCSBots()->AllowSubMachineGuns()) buyAlias = NULL; break; case RIFLE: if (!TheCSBots()->AllowRifles()) buyAlias = NULL; break; case MACHINE_GUN: if (!TheCSBots()->AllowMachineGuns()) buyAlias = NULL; break; case SNIPER_RIFLE: if (!TheCSBots()->AllowSnipers()) buyAlias = NULL; break; } } if (buyAlias) { Q_snprintf( cmdBuffer, 256, "buy %s\n", buyAlias ); CCommand args; args.Tokenize( cmdBuffer ); me->ClientCommand( args ); me->PrintIfWatched( "Tried to buy preferred weapon %s.\n", buyAlias ); isPreferredAllDisallowed = false; } ++m_prefRetries; // bail out so we dont waste money on other equipment // unless everything we prefer has been disallowed, then buy at random if (isPreferredAllDisallowed == false) return; } // if we have no preferred primary weapon (or everything we want is disallowed), buy at random if (!me->HasPrimaryWeapon() && (isPreferredAllDisallowed || !me->GetProfile()->HasPrimaryPreference())) { if (m_buyShield) { // buy a shield CCommand args; args.Tokenize( "buy shield" ); me->ClientCommand( args ); me->PrintIfWatched( "Tried to buy a shield.\n" ); } else { // build list of allowable weapons to buy BuyInfo *masterPrimary = (me->GetTeamNumber() == TEAM_TERRORIST) ? primaryWeaponBuyInfoT : primaryWeaponBuyInfoCT; BuyInfo *stockPrimary[ PRIMARY_WEAPON_BUY_COUNT ]; int stockPrimaryCount = 0; // dont choose sniper rifles as often const float sniperRifleChance = 50.0f; bool wantSniper = (RandomFloat( 0, 100 ) < sniperRifleChance) ? true : false; if ( bot_randombuy.GetBool() ) { wantSniper = true; } for( int i=0; i<PRIMARY_WEAPON_BUY_COUNT; ++i ) { if ((masterPrimary[i].type == SHOTGUN && TheCSBots()->AllowShotguns()) || (masterPrimary[i].type == SUB_MACHINE_GUN && TheCSBots()->AllowSubMachineGuns()) || (masterPrimary[i].type == RIFLE && TheCSBots()->AllowRifles()) || (masterPrimary[i].type == SNIPER_RIFLE && TheCSBots()->AllowSnipers() && wantSniper) || (masterPrimary[i].type == MACHINE_GUN && TheCSBots()->AllowMachineGuns())) { stockPrimary[ stockPrimaryCount++ ] = &masterPrimary[i]; } } if (stockPrimaryCount) { // buy primary weapon if we don't have one int which; // on hard difficulty levels, bots try to buy preferred weapons on the first pass if (m_retries == 0 && TheCSBots()->GetDifficultyLevel() >= BOT_HARD && bot_randombuy.GetBool() == false ) { // count up available preferred weapons int prefCount = 0; for( which=0; which<stockPrimaryCount; ++which ) if (stockPrimary[which]->preferred) ++prefCount; if (prefCount) { int whichPref = RandomInt( 0, prefCount-1 ); for( which=0; which<stockPrimaryCount; ++which ) if (stockPrimary[which]->preferred && whichPref-- == 0) break; } else { // no preferred weapons available, just pick randomly which = RandomInt( 0, stockPrimaryCount-1 ); } } else { which = RandomInt( 0, stockPrimaryCount-1 ); } Q_snprintf( cmdBuffer, 256, "buy %s\n", stockPrimary[ which ]->buyAlias ); CCommand args; args.Tokenize( cmdBuffer ); me->ClientCommand( args ); me->PrintIfWatched( "Tried to buy %s.\n", stockPrimary[ which ]->buyAlias ); } } } // // If we now have a weapon, or have tried for too long, we're done // if (me->HasPrimaryWeapon() || m_retries++ > 5) { // primary ammo CCommand args; if (me->HasPrimaryWeapon()) { args.Tokenize( "buy primammo" ); me->ClientCommand( args ); } // buy armor last, to make sure we bought a weapon first args.Tokenize( "buy vesthelm" ); me->ClientCommand( args ); args.Tokenize( "buy vest" ); me->ClientCommand( args ); // pistols - if we have no preferred pistol, buy at random if (TheCSBots()->AllowPistols() && !me->GetProfile()->HasPistolPreference()) { if (m_buyPistol) { int which = RandomInt( 0, SECONDARY_WEAPON_BUY_COUNT-1 ); const char *what = NULL; if (me->GetTeamNumber() == TEAM_TERRORIST) what = secondaryWeaponBuyInfoT[ which ].buyAlias; else what = secondaryWeaponBuyInfoCT[ which ].buyAlias; Q_snprintf( cmdBuffer, 256, "buy %s\n", what ); args.Tokenize( cmdBuffer ); me->ClientCommand( args ); // only buy one pistol m_buyPistol = false; } // make sure we have enough pistol ammo args.Tokenize( "buy secammo" ); me->ClientCommand( args ); } // buy a grenade if we wish, and we don't already have one if (m_buyGrenade && !me->HasGrenade()) { if (UTIL_IsTeamAllBots( me->GetTeamNumber() )) { // only allow Flashbangs if everyone on the team is a bot (dont want to blind our friendly humans) float rnd = RandomFloat( 0, 100 ); if (rnd < 10) { args.Tokenize( "buy smokegrenade" ); me->ClientCommand( args ); // smoke grenade } else if (rnd < 35) { args.Tokenize( "buy flashbang" ); me->ClientCommand( args ); // flashbang } else { args.Tokenize( "buy hegrenade" ); me->ClientCommand( args ); // he grenade } } else { if (RandomFloat( 0, 100 ) < 10) { args.Tokenize( "buy smokegrenade" ); // smoke grenade me->ClientCommand( args ); } else { args.Tokenize( "buy hegrenade" ); // he grenade me->ClientCommand( args ); } } } if (m_buyDefuseKit) { args.Tokenize( "buy defuser" ); me->ClientCommand( args ); } m_doneBuying = true; } } }
// This runs on both the client and the server. // On the server, it only does the damage calculations. // On the client, it does all the effects. void FX_FireBullets( int iPlayerIndex, const Vector &vOrigin, const QAngle &vAngles, int iWeaponID, int iMode, int iSeed, float flSpread ) { bool bDoEffects = true; #ifdef CLIENT_DLL C_SDKPlayer *pPlayer = ToSDKPlayer( ClientEntityList().GetBaseEntity( iPlayerIndex ) ); #else CSDKPlayer *pPlayer = ToSDKPlayer( UTIL_PlayerByIndex( iPlayerIndex) ); #endif const char * weaponAlias = WeaponIDToAlias( iWeaponID ); if ( !weaponAlias ) { DevMsg("FX_FireBullets: weapon alias for ID %i not found\n", iWeaponID ); return; } char wpnName[128]; Q_snprintf( wpnName, sizeof( wpnName ), "weapon_%s", weaponAlias ); WEAPON_FILE_INFO_HANDLE hWpnInfo = LookupWeaponInfoSlot( wpnName ); if ( hWpnInfo == GetInvalidWeaponInfoHandle() ) { DevMsg("FX_FireBullets: LookupWeaponInfoSlot failed for weapon %s\n", wpnName ); return; } CSDKWeaponInfo *pWeaponInfo = static_cast< CSDKWeaponInfo* >( GetFileWeaponInfoFromHandle( hWpnInfo ) ); #ifdef CLIENT_DLL // Do the firing animation event. if ( pPlayer && !pPlayer->IsDormant() ) { pPlayer->m_PlayerAnimState->DoAnimationEvent( PLAYERANIMEVENT_ATTACK_PRIMARY ); } #else // if this is server code, send the effect over to client as temp entity // Dispatch one message for all the bullet impacts and sounds. TE_FireBullets( iPlayerIndex, vOrigin, vAngles, iWeaponID, iMode, iSeed, flSpread ); bDoEffects = false; // no effects on server #endif iSeed++; int iDamage = pWeaponInfo->m_iDamage; int iAmmoType = pWeaponInfo->iAmmoType; WeaponSound_t sound_type = SINGLE; if ( bDoEffects) { FX_WeaponSound( iPlayerIndex, sound_type, vOrigin, pWeaponInfo ); } // Fire bullets, calculate impacts & effects if ( !pPlayer ) return; StartGroupingSounds(); #if !defined (CLIENT_DLL) // Move other players back to history positions based on local player's lag lagcompensation->StartLagCompensation( pPlayer, LAG_COMPENSATE_BOUNDS ); #endif for ( int iBullet=0; iBullet < pWeaponInfo->m_iBullets; iBullet++ ) { RandomSeed( iSeed ); // init random system with this seed // Get circular gaussian spread. float x, y; x = RandomFloat( -0.5, 0.5 ) + RandomFloat( -0.5, 0.5 ); y = RandomFloat( -0.5, 0.5 ) + RandomFloat( -0.5, 0.5 ); iSeed++; // use new seed for next bullet pPlayer->FireBullet( vOrigin, vAngles, flSpread, iDamage, iAmmoType, pPlayer, bDoEffects, x,y ); } #if !defined (CLIENT_DLL) lagcompensation->FinishLagCompensation( pPlayer ); #endif EndGroupingSounds(); }
void BuyState::__MAKE_VHOOK(OnUpdate)(CCSBot *me) { // wait for a Navigation Mesh if (!TheNavAreaList.size()) return; // apparently we cant buy things in the first few seconds, so wait a bit if (m_isInitialDelay) { const float waitToBuyTime = 2.0f; // 0.25f; if (gpGlobals->time - me->GetStateTimestamp() < waitToBuyTime) return; m_isInitialDelay = false; } // if we're done buying and still in the freeze period, wait if (m_doneBuying) { if (CSGameRules()->IsMultiplayer() && CSGameRules()->IsFreezePeriod()) { #ifdef REGAMEDLL_FIXES // make sure we're locked and loaded me->EquipBestWeapon(MUST_EQUIP); me->Reload(); me->ResetStuckMonitor(); #endif return; } me->Idle(); #ifdef REGAMEDLL_FIXES return; #endif } // is the bot spawned outside of a buy zone? if (!(me->m_signals.GetState() & SIGNAL_BUY)) { m_doneBuying = true; UTIL_DPrintf("%s bot spawned outside of a buy zone (%d, %d, %d)\n", (me->m_iTeam == CT) ? "CT" : "Terrorist", int(me->pev->origin.x), int(me->pev->origin.y), int(me->pev->origin.z)); return; } // try to buy some weapons const float buyInterval = 0.2f; // 0.02f if (gpGlobals->time - me->GetStateTimestamp() > buyInterval) { me->m_stateTimestamp = gpGlobals->time; bool isPreferredAllDisallowed = true; // try to buy our preferred weapons first if (m_prefIndex < me->GetProfile()->GetWeaponPreferenceCount()) { // need to retry because sometimes first buy fails?? const int maxPrefRetries = 2; if (m_prefRetries >= maxPrefRetries) { // try to buy next preferred weapon ++m_prefIndex; m_prefRetries = 0; return; } int weaponPreference = me->GetProfile()->GetWeaponPreference(m_prefIndex); // don't buy it again if we still have one from last round CBasePlayerWeapon *weapon = me->GetActiveWeapon(); if (weapon != NULL && weapon->m_iId == weaponPreference) { // done with buying preferred weapon m_prefIndex = 9999; return; } if (me->HasShield() && weaponPreference == WEAPON_SHIELDGUN) { // done with buying preferred weapon m_prefIndex = 9999; return; } const char *buyAlias = NULL; if (weaponPreference == WEAPON_SHIELDGUN) { if (TheCSBots()->AllowTacticalShield()) buyAlias = "shield"; } else { buyAlias = WeaponIDToAlias(weaponPreference); WeaponType type = GetWeaponType(buyAlias); switch (type) { case PISTOL: if (!TheCSBots()->AllowPistols()) buyAlias = NULL; break; case SHOTGUN: if (!TheCSBots()->AllowShotguns()) buyAlias = NULL; break; case SUB_MACHINE_GUN: if (!TheCSBots()->AllowSubMachineGuns()) buyAlias = NULL; break; case RIFLE: if (!TheCSBots()->AllowRifles()) buyAlias = NULL; break; case MACHINE_GUN: if (!TheCSBots()->AllowMachineGuns()) buyAlias = NULL; break; case SNIPER_RIFLE: if (!TheCSBots()->AllowSnipers()) buyAlias = NULL; break; } } if (buyAlias) { me->ClientCommand(buyAlias); me->PrintIfWatched("Tried to buy preferred weapon %s.\n", buyAlias); isPreferredAllDisallowed = false; } ++m_prefRetries; // bail out so we dont waste money on other equipment // unless everything we prefer has been disallowed, then buy at random if (isPreferredAllDisallowed == false) return; } // if we have no preferred primary weapon (or everything we want is disallowed), buy at random if (!me->m_bHasPrimary && (isPreferredAllDisallowed || !me->GetProfile()->HasPrimaryPreference())) { if (m_buyShield) { // buy a shield me->ClientCommand("shield"); me->PrintIfWatched("Tried to buy a shield.\n"); } else { // build list of allowable weapons to buy BuyInfo *masterPrimary = (me->m_iTeam == TERRORIST) ? primaryWeaponBuyInfoT : primaryWeaponBuyInfoCT; BuyInfo *stockPrimary[ PRIMARY_WEAPON_BUY_COUNT ]; int stockPrimaryCount = 0; // dont choose sniper rifles as often const float sniperRifleChance = 50.0f; bool wantSniper = (RANDOM_FLOAT(0, 100) < sniperRifleChance) ? true : false; for (int i = 0; i < PRIMARY_WEAPON_BUY_COUNT; ++i) { if ((masterPrimary[i].type == SHOTGUN && TheCSBots()->AllowShotguns()) || (masterPrimary[i].type == SUB_MACHINE_GUN && TheCSBots()->AllowSubMachineGuns()) || (masterPrimary[i].type == RIFLE && TheCSBots()->AllowRifles()) || (masterPrimary[i].type == SNIPER_RIFLE && TheCSBots()->AllowSnipers() && wantSniper) || (masterPrimary[i].type == MACHINE_GUN && TheCSBots()->AllowMachineGuns())) { stockPrimary[ stockPrimaryCount++ ] = &masterPrimary[i]; } } if (stockPrimaryCount) { // buy primary weapon if we don't have one int which; // on hard difficulty levels, bots try to buy preferred weapons on the first pass if (m_retries == 0 && TheCSBots()->GetDifficultyLevel() >= BOT_HARD) { // count up available preferred weapons int prefCount = 0; for (which = 0; which < stockPrimaryCount; ++which) { if (stockPrimary[which]->preferred) ++prefCount; } if (prefCount) { int whichPref = RANDOM_LONG(0, prefCount - 1); for (which = 0; which < stockPrimaryCount; ++which) { if (stockPrimary[which]->preferred && whichPref-- == 0) break; } } else { // no preferred weapons available, just pick randomly which = RANDOM_LONG(0, stockPrimaryCount - 1); } } else { which = RANDOM_LONG(0, stockPrimaryCount - 1); } me->ClientCommand(stockPrimary[ which ]->buyAlias); me->PrintIfWatched("Tried to buy %s.\n", stockPrimary[ which ]->buyAlias); } } } // If we now have a weapon, or have tried for too long, we're done if (me->m_bHasPrimary || m_retries++ > 5) { // primary ammo if (me->m_bHasPrimary) { me->ClientCommand("primammo"); } // buy armor last, to make sure we bought a weapon first me->ClientCommand("vesthelm"); me->ClientCommand("vest"); // pistols - if we have no preferred pistol, buy at random if (TheCSBots()->AllowPistols() && !me->GetProfile()->HasPistolPreference()) { if (m_buyPistol) { int which = RANDOM_LONG(0, SECONDARY_WEAPON_BUY_COUNT - 1); if (me->m_iTeam == TERRORIST) me->ClientCommand(secondaryWeaponBuyInfoT[ which ].buyAlias); else me->ClientCommand(secondaryWeaponBuyInfoCT[ which ].buyAlias); // only buy one pistol m_buyPistol = false; } me->ClientCommand("secammo"); } // buy a grenade if we wish, and we don't already have one if (m_buyGrenade && !me->HasGrenade()) { if (UTIL_IsTeamAllBots(me->m_iTeam)) { // only allow Flashbangs if everyone on the team is a bot (dont want to blind our friendly humans) float rnd = RANDOM_FLOAT(0, 100); if (rnd < 10.0f) { // smoke grenade me->ClientCommand("sgren"); } else if (rnd < 35.0f) { // flashbang me->ClientCommand("flash"); } else { // he grenade me->ClientCommand("hegren"); } } else { if (RANDOM_FLOAT(0, 100) < 10.0f) { // smoke grenade me->ClientCommand("sgren"); } else { // he grenade me->ClientCommand("hegren"); } } } if (m_buyDefuseKit) { me->ClientCommand("defuser"); } m_doneBuying = true; } } }
/* <22ce5a> ../cstrike/dlls/weapontype.cpp:276 */ WeaponClassType WeaponIDToWeaponClass(int id) { return AliasToWeaponClass(WeaponIDToAlias(id)); }
bool CGEStats::GetFavoriteWeapon( int iPlayer, GEWeaponSort &fav ) { if ( iPlayer < 0 || iPlayer >= m_pPlayerStats.Count() ) return false; GEPlayerStats *stats = m_pPlayerStats[iPlayer]; CBasePlayer *pPlayer = ToBasePlayer( m_pPlayerStats[iPlayer]->GetPlayer() ); if ( !pPlayer || !stats ) return false; // We want raw kills, NOT score int playerFrags = pPlayer->FragCount(); float roundtime = gpGlobals->curtime - m_flRoundStartTime; // Avoid divide by zero! if ( roundtime == 0.0f ) roundtime = 0.5f; CUtlVector<GEWeaponSort*> weapons; float killPercent; for ( int i=WEAPON_NONE+1; i < WEAPON_RANDOM; i++ ) // Go up to WEAPON_RANDOM to exclude tokens. { GEWeaponSort *entry = new GEWeaponSort; if ( GEGameplay()->IsInFinalIntermission() ) { entry->m_iPercentage = stats->m_iMatchWeapons[i]; } else { // Avoid divide by zero! if ( playerFrags == 0 ) killPercent = 0.0f; else killPercent = (float)stats->m_iWeaponsKills[i] / (float)playerFrags; if ( roundtime < 1.0f ) entry->m_iPercentage = 0; else entry->m_iPercentage = 100 * ( ((float)stats->m_iWeaponsHeldTime[i] / roundtime) + killPercent ); } entry->m_iWeaponID = i; weapons.AddToTail( entry ); } weapons.Sort( &CGEStats::WeaponSort ); // Only give them a fav weapon if they have a percentage fav.m_iPercentage = weapons[0]->m_iPercentage; if ( fav.m_iPercentage ) fav.m_iWeaponID = weapons[0]->m_iWeaponID; else fav.m_iWeaponID = WEAPON_NONE; #ifdef _DEBUG DevMsg( "%s's weapon stats:\n", pPlayer->GetPlayerName() ); DevMsg( "Frags: %i, Roundtime: %0.2f\n", playerFrags, roundtime ); for ( int i=0; i < WEAPON_MAX-2; i++ ) { if ( weapons[i]->m_iPercentage ) DevMsg( "%s : %i\n", WeaponIDToAlias( weapons[i]->m_iWeaponID ), weapons[i]->m_iPercentage ); } DevMsg( "Favorite Weapon: %s\n", WeaponIDToAlias( fav.m_iWeaponID ) ); #endif weapons.PurgeAndDeleteElements(); return true; }