bool CWeaponFireDesc::FindEventHandler (const CString &sEvent, SEventHandlerDesc *retEvent) const // FindEventHandler // // Returns an event handler (if found) { // Look for an event handler at the weapon fire level ICCItem *pCode; if (m_Events.FindEvent(sEvent, &pCode)) { if (retEvent) { retEvent->pExtension = m_pExtension; retEvent->pCode = pCode; } return true; } // Then look for an event handler at the item level CItemType *pDevice; CItemType *pAmmo = GetWeaponType(&pDevice); if (pAmmo && pAmmo->FindEventHandler(sEvent, retEvent)) return true; if (pDevice && pAmmo != pDevice && pDevice->FindEventHandler(sEvent, retEvent)) return true; // Otherwise, we have no event return false; }
bool CAIActionAttack::ValidateContextPreconditions( CAI* pAI, CAIWorldState& wsWorldStateGoal, bool bIsPlanning ) { // No target. if( !pAI->HasTarget( kTarget_Character | kTarget_CombatOpportunity | kTarget_Object ) ) { return false; } // Target is not visible. if( m_bValidateVisibility ) { if( ( !pAI->GetAIBlackBoard()->GetBBTargetVisibleFromWeapon() ) && ( !IsAI( pAI->GetTarget()->GetVisionBlocker() ) ) ) { return false; } } // AI does not have a weapon of the correct type if (!AIWeaponUtils::HasWeaponType(pAI, GetWeaponType(), bIsPlanning)) { return false; } // Target is not in range. if (!AIWeaponUtils::IsInRange(pAI, GetWeaponType(), bIsPlanning)) { return false; } // AI does not have any ammo required by this weapon type. if ( !AIWeaponUtils::HasAmmo(pAI, GetWeaponType(), bIsPlanning ) ) { return false; } return true; }
void CAIActionAttack::ActivateAction( CAI* pAI, CAIWorldState& wsWorldStateGoal ) { super::ActivateAction( pAI, wsWorldStateGoal ); // Set our weapon of the desired type as current weapon. pAI->SetCurrentWeapon( GetWeaponType() ); // Set animate state. pAI->SetState( kState_Animate ); // Set attack animation. CAnimationProps animProps; SetAttackAnimProps( pAI, &animProps ); CAIStateAnimate* pStateAnimate = (CAIStateAnimate*)( pAI->GetState() ); pStateAnimate->SetAnimation( animProps, GetLoopAttackAnimation( pAI ) ); // Turn off any automatic reloading that may have been previously set. pAI->GetAIBlackBoard()->SetBBAutoReload( false ); // Get the target. HOBJECT hTarget = NULL; if( pAI->HasTarget( kTarget_Character | kTarget_Object | kTarget_CombatOpportunity) ) { hTarget = pAI->GetAIBlackBoard()->GetBBTargetObject(); } // Play attack sound. // Only play if we've been targeting someone for at least 5 seconds. // This ensures we first play higher priority reaction sounds. if( ( m_bPlayAISound && pAI->GetAIBlackBoard()->GetBBTargetVisibleFromWeapon() ) && ( pAI->GetAIBlackBoard()->GetBBTargetChangeTime() < g_pLTServer->GetTime() - 10.f ) ) { if( IsTurret( hTarget ) ) { g_pAISoundMgr->RequestAISound( pAI->m_hObject, kAIS_TurretStress, kAISndCat_Event, hTarget, 0.f ); } else if( g_pAICoordinator->FindAlly( pAI->m_hObject, NULL ) ) { g_pAISoundMgr->RequestAISound( pAI->m_hObject, kAIS_Attack, kAISndCat_Combat, hTarget, 0.f ); } } // Torso tracking. pAI->GetAIBlackBoard()->SetBBTargetTrackerFlags( kTrackerFlag_AimAt ); pAI->GetAIBlackBoard()->SetBBFaceTarget( true ); }
eWeaponHandType CGoods::GetWeaponHandType() { eWeaponType eWT=GetWeaponType(); if(eWT!=WHT_UNKNOWN) { if(eWT==WT_SINGLE_SWORD || eWT==WT_SINGLE_KNIFE || eWT==WT_SINGLE_HAMMER) return WHT_SINGLE_HAND; else return WHT_DOUBLE_HAND; } else return WHT_UNKNOWN; }
bool CWeaponFireDesc::FireOnFragment (const CDamageSource &Source, CSpaceObject *pShot, const CVector &vHitPos, CSpaceObject *pNearestObj, CSpaceObject *pTarget) // FireOnFragment // // Event fires when a shot fragments. If we return TRUE then we skip the default // fragmentation event. { SEventHandlerDesc Event; if (FindEventHandler(evtOnFragment, &Event)) { // Setup arguments CCodeChainCtx CCCtx; CCCtx.SaveAndDefineSourceVar(pShot); CCCtx.DefineSpaceObject(CONSTLIT("aNearestObj"), pNearestObj); CCCtx.DefineSpaceObject(CONSTLIT("aTargetObj"), pTarget); CCCtx.DefineVector(CONSTLIT("aHitPos"), vHitPos); CCCtx.DefineInteger(CONSTLIT("aHitDir"), (pShot ? pShot->GetRotation() : 0)); CCCtx.DefineItemType(CONSTLIT("aWeaponType"), GetWeaponType()); CCCtx.DefineString(CONSTLIT("aWeaponFragment"), m_sUNID); CSpaceObject *pAttacker = Source.GetObj(); CCCtx.DefineSpaceObject(CONSTLIT("aCause"), pShot); CCCtx.DefineSpaceObject(CONSTLIT("aAttacker"), pAttacker); CCCtx.DefineSpaceObject(CONSTLIT("aOrderGiver"), (pAttacker ? pAttacker->GetOrderGiver(Source.GetCause()) : NULL)); ICCItem *pResult = CCCtx.Run(Event); if (pResult->IsError()) pShot->ReportEventError(ON_FRAGMENT_EVENT, pResult); // If we return Nil, then we continue processing bool bResult; if (pResult->IsNil()) bResult = false; // Otherwise, we skip fragmentation else bResult = true; CCCtx.Discard(pResult); return bResult; } else return false; }
// Calculate weapon range using efficient stuffs float CPlayer::GetWeaponRangeFromSlot( uint uiSlot ) { eWeaponType eWeapon = static_cast < eWeaponType > ( GetWeaponType ( uiSlot ) ); float fSkill = GetPlayerStat ( CWeaponStatManager::GetSkillStatIndex ( eWeapon ) ); if ( fSkill != m_fWeaponRangeLastSkill || eWeapon != m_eWeaponRangeLastWeapon || CWeaponStat::GetAllWeaponStatsRevision() != m_uiWeaponRangeLastStatsRevision ) { m_fWeaponRangeLastSkill = fSkill; m_eWeaponRangeLastWeapon = eWeapon; m_uiWeaponRangeLastStatsRevision = CWeaponStat::GetAllWeaponStatsRevision(); m_fWeaponRangeLast = g_pGame->GetWeaponStatManager ( )->GetWeaponRangeFromSkillLevel ( eWeapon, fSkill ); } return m_fWeaponRangeLast; }
void ItemDef :: Debug_WriteReport(ReportBuffer &report) { report.AddLine("%s [%d] lev:%d, qlev:%d", mDisplayName.c_str(), mID, mLevel, mQualityLevel); report.AddLine("%s | %s | %s", GetEquipType(mEquipType), GetArmorType(mArmorType), GetWeaponType(mWeaponType)); report.AddLine("str:%d, dex:%d, con:%d, psy:%d, spi:%d", mBonusStrength, mBonusDexterity, mBonusConstitution, mBonusPsyche, mBonusSpirit); report.AddLine("armor:%d, dmg:%d-%d", mArmorResistMelee, mWeaponDamageMin, mWeaponDamageMax); if(mFlavorText.size() > 0) { std::string tmp = mFlavorText; size_t pos; pos = tmp.find(FLAVOR_TEXT_HEADER); if(pos != string::npos) tmp.erase(pos, strlen(FLAVOR_TEXT_HEADER)); pos = tmp.find(FLAVOR_TEXT_FOOTER); if(pos != string::npos) tmp.erase(pos, strlen(FLAVOR_TEXT_FOOTER)); report.AddLine("flavor:%s", tmp.c_str()); } report.AddLine(NULL); }
bool CAIActionAttack::ValidateAction( CAI* pAI ) { if( !super::ValidateAction( pAI ) ) { return false; } // Target is not visible. // And target is not obscured by an AI. if( m_bValidateVisibility) { if ( !pAI->GetAIBlackBoard()->GetBBTargetVisibleFromWeapon() && ( !IsAI( pAI->GetTarget()->GetVisionBlocker() ) ) ) { return false; } } // Target is not in range. if ( m_bInterruptActionIfEnemyIsOutOfRange ) { if( pAI->GetAIBlackBoard()->GetBBWeaponStatus(GetWeaponType()) != kRangeStatus_Ok ) { return false; } } // Weapon is unloaded. SAIWORLDSTATE_PROP* pProp = pAI->GetAIWorldState()->GetWSProp( kWSK_WeaponLoaded, pAI->m_hObject ); if( pProp && !pProp->bWSValue ) { return false; } return true; }
bool CAIActionAttackGrenade::ValidateContextPreconditions( CAI* pAI, CAIWorldState& wsWorldStateGoal, bool bIsPlanning ) { // Target is not visible. if( !pAI->HasTarget( kTarget_Character | kTarget_Object ) ) { return false; } // AI does not have a weapon of the correct type if (!AIWeaponUtils::HasWeaponType(pAI, GetWeaponType(), bIsPlanning)) { return false; } // AI does not have any ammo for this weapon. if ( !AIWeaponUtils::HasAmmo( pAI, GetWeaponType(), bIsPlanning ) ) { return false; } // At a node that does not allow grenade throwing. bool bAtNode = false; bool bStraightPathCheckRequired = true; SAIWORLDSTATE_PROP* pProp = pAI->GetAIWorldState()->GetWSProp( kWSK_AtNode, pAI->m_hObject ); if( pProp && pProp->hWSValue ) { AINode* pNode = (AINode*)g_pLTServer->HandleToObject( pProp->hWSValue ); if( !pNode ) { return false; } if( !pNode->AllowThrowGrenades() ) { return false; } if( !pNode->IsNodeValid( pAI, pAI->GetPosition(), pAI->GetAIBlackBoard()->GetBBTargetObject(), kThreatPos_TargetPos, kNodeStatus_ThreatOutsideFOV ) ) { return false; } bStraightPathCheckRequired = pNode->RequiresStraightPathToThrowGrenades(); bAtNode = true; } // Target is not in range. if (!AIWeaponUtils::IsInRange(pAI, GetWeaponType(), bIsPlanning)) { return false; } // Someone else has thrown a grenade recently. CAIWMFact factQuery; factQuery.SetFactType(kFact_Knowledge); factQuery.SetKnowledgeType(kKnowledge_NextGrenadeTime); CAIWMFact* pFact = g_pAIWorkingMemoryCentral->FindWMFact(factQuery); if(pFact && g_pLTServer->GetTime() < pFact->GetTime() ) { return false; } // Throw at the last known position. CAIWMFact factTargetQuery; HOBJECT hTarget = pAI->GetAIBlackBoard()->GetBBTargetObject(); factTargetQuery.SetFactType( kFact_Character ); factTargetQuery.SetTargetObject( hTarget ); pFact = pAI->GetAIWorkingMemory()->FindWMFact( factTargetQuery ); if( !pFact ) { return false; } LTVector vTargetPos = pFact->GetPos(); /*** // Only throw a grenade when not at a node when there is a // straight path to the target. This is to ensure the // grenade won't bounce back and kill the thrower. if( bStraightPathCheckRequired ) { if( !g_pAIPathMgrNavMesh->StraightPathExists( pAI, pAI->GetCharTypeMask(), pAI->GetPosition(), vTargetPos, pAI->GetLastNavMeshPoly(), 0.f ) ) { return false; } } ***/ /*** // Don't throw if someone is closer to the target than me, // because I might hit them! if( pAI != g_pCharacterMgr->FindNearestAIAlly( pAI, vTargetPos ) ) { return false; } ***/ // Get the grenade explosion radius. HAMMO hAmmo = AIWeaponUtils::GetWeaponAmmo( pAI, GetWeaponType(), bIsPlanning ); HAMMODATA hAmmoData = g_pWeaponDB->GetAmmoData(hAmmo,true); float fRadius = g_pWeaponDB->GetFloat( hAmmoData, WDB_AMMO_fAreaDamageRadius ); fRadius *= 1.2f; // Don't throw if we're in the radius! if( pAI->GetPosition().DistSqr( vTargetPos ) < fRadius * fRadius ) { return false; } // Don't throw if an ally is in the blast radius. if( g_pCharacterMgr->FindAIAllyInRadius( pAI, vTargetPos, fRadius ) ) { return false; } /*** // Don't throw grenade at allies. CTList<CCharacter*> lstChars; if( g_pCharacterMgr->FindCharactersWithinRadius( &lstChars, vTargetPos, fRadius, CCharacterMgr::kList_AIs ) ) { // Iterate over characters in grenade's radius. CCharacter** pCur = lstChars.GetItem(TLIT_FIRST); while( pCur ) { CCharacter* pChar = (CCharacter*)*pCur; pCur = lstChars.GetItem(TLIT_NEXT); // Skip the AI himself. if( pChar == pAI ) { continue; } // Action is invalid if grenade could hit someone // that the AI does not hate. if( g_pCharacterDB->GetStance( pAI->GetAlignment(), pChar->GetAlignment() ) != kCharStance_Hate ) { return false; } } } ***/ // Throw a grenade. return true; }
bool CAIActionAttackLungeUncloaked::ValidateContextPreconditions( CAI* pAI, CAIWorldState& wsWorldStateGoal, bool bIsPlanning ) { // AI doesn't have a target. if (!pAI->HasTarget( kTarget_Character )) { return false; } // Target is not visible. if( !pAI->GetAIBlackBoard()->GetBBTargetVisibleFromWeapon() ) { return false; } // AI does not have a weapon of the correct type if (!AIWeaponUtils::HasWeaponType(pAI, GetWeaponType(), bIsPlanning)) { return false; } // AI does not have any ammo for this weapon. if ( !AIWeaponUtils::HasAmmo( pAI, GetWeaponType(), bIsPlanning ) ) { return false; } // Someone else is lunging. Only one AI may lunge at a time. CAIWMFact factQuery; factQuery.SetFactType( kFact_Knowledge ); factQuery.SetKnowledgeType( kKnowledge_Lunging ); CAIWMFact* pFact = g_pAIWorkingMemoryCentral->FindWMFact(factQuery); if( pFact ) { // Clear records of dead AI. if( IsDeadAI( pFact->GetSourceObject() ) ) { g_pAIWorkingMemoryCentral->ClearWMFacts( factQuery ); } else return false; } // Bail if the Action's SmartObject record does not exist. AIDB_SmartObjectRecord* pSmartObjectRecord = g_pAIDB->GetAISmartObjectRecord( m_pActionRecord->eSmartObjectID ); if( !pSmartObjectRecord ) { return false; } // Someone has lunged too recently. if( pSmartObjectRecord->fTimeout > 0.f ) { factQuery.SetFactType( kFact_Knowledge ); factQuery.SetKnowledgeType( kKnowledge_NextLungeTime ); pFact = g_pAIWorkingMemoryCentral->FindWMFact(factQuery); if( pFact && ( pFact->GetTime() > g_pLTServer->GetTime() ) ) { return false; } } // Bail if the AI does not have the desire to lunge. // The desire indicates the max range of the lunge. CAIWMFact factDesireQuery; factDesireQuery.SetFactType( kFact_Desire ); factDesireQuery.SetDesireType( kDesire_Lunge ); CAIWMFact* pDesireFact = pAI->GetAIWorkingMemory()->FindWMFact( factDesireQuery ); if( !pDesireFact ) { return false; } // Target must be in range. LTVector vTarget = pAI->GetAIBlackBoard()->GetBBTargetPosition(); float fDistSqr = vTarget.DistSqr( pAI->GetPosition() ); // Target too close. if( fDistSqr < pSmartObjectRecord->fMinDist * pSmartObjectRecord->fMinDist ) { return false; } // Target too far. float fMaxDist = GetLungeMaxDist( pAI, pDesireFact ); if( fDistSqr > fMaxDist * fMaxDist ) { return false; } // No straight path to the target. LTVector vDir = vTarget - pAI->GetPosition(); vDir.Normalize(); LTVector vDest = pAI->GetPosition() + ( vDir * ( fMaxDist + 50.f ) ); if( !g_pAIPathMgrNavMesh->StraightPathExists( pAI, pAI->GetCharTypeMask(), pAI->GetPosition(), vDest, pAI->GetAIBlackBoard()->GetBBTargetReachableNavMeshPoly(), pAI->GetRadius() ) ) { return false; } // Lunge! return true; }
//-------------------------------------------------------------------------------------------------------------- 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; } } }
void CPlayerStats::UpdatePlayerWeapon(uint8 nWeapon, LTBOOL bForce) { if (!m_pClientShell) return; if (m_nCurrentWeapon == nWeapon && !bForce) return; if (GetWeaponType((RiotWeaponId)nWeapon) == MELEE && m_pClientShell) { // we will not be drawing the ammo count, so make sure all of it gets removed... m_pClientShell->AddToClearScreenCount(); } m_nCurrentWeapon = nWeapon; if (m_hAmmoIcon) { m_pClientDE->DeleteSurface (m_hAmmoIcon); m_hAmmoIcon = LTNULL; } char strFilename[MAX_CS_FILENAME_LEN]; switch (nWeapon) { case GUN_PULSERIFLE_ID: SAFE_STRCPY(strFilename, "interface/Ammo_PulseRifle.pcx"); break; case GUN_SPIDER_ID: SAFE_STRCPY(strFilename, "interface/Ammo_Spider.pcx"); break; case GUN_BULLGUT_ID: SAFE_STRCPY(strFilename, "interface/Ammo_Bullgut.pcx"); break; case GUN_SNIPERRIFLE_ID: SAFE_STRCPY(strFilename, "interface/Ammo_SniperRifle.pcx"); break; case GUN_JUGGERNAUT_ID: SAFE_STRCPY(strFilename, "interface/Ammo_Juggernaut.pcx"); break; case GUN_SHREDDER_ID: SAFE_STRCPY(strFilename, "interface/Ammo_Shredder.pcx"); break; case GUN_REDRIOT_ID: SAFE_STRCPY(strFilename, "interface/Ammo_RedRiot.pcx"); break; case GUN_COLT45_ID: SAFE_STRCPY(strFilename, "interface/Ammo_Colt45.pcx"); break; case GUN_SHOTGUN_ID: SAFE_STRCPY(strFilename, "interface/Ammo_Shotgun.pcx"); break; case GUN_ASSAULTRIFLE_ID: SAFE_STRCPY(strFilename, "interface/Ammo_AssaultRifle.pcx"); break; case GUN_ENERGYGRENADE_ID: SAFE_STRCPY(strFilename, "interface/Ammo_EnergyGrenade.pcx"); break; case GUN_KATOGRENADE_ID: SAFE_STRCPY(strFilename, "interface/Ammo_KatoGrenade.pcx"); break; case GUN_MAC10_ID: SAFE_STRCPY(strFilename, "interface/Ammo_Mac10.pcx"); break; case GUN_TOW_ID: SAFE_STRCPY(strFilename, "interface/Ammo_Tow.pcx"); break; case GUN_LASERCANNON_ID: SAFE_STRCPY(strFilename, "interface/Ammo_LaserCannon.pcx"); break; // handle the melee weapons (turn off ammo display) case GUN_SQUEAKYTOY_ID: case GUN_ENERGYBATON_ID: case GUN_ENERGYBLADE_ID: case GUN_KATANA_ID: case GUN_MONOKNIFE_ID: case GUN_TANTO_ID: { SetDrawAmmo (LTFALSE); return; } default: SAFE_STRCPY(strFilename, ""); break; } if (!m_pClientShell->IsVehicleMode()) { SetDrawAmmo (LTTRUE); } if (strFilename[0] != '\0') m_hAmmoIcon = m_pClientDE->CreateSurfaceFromBitmap (strFilename); if (m_hAmmoIcon) { m_pClientDE->GetSurfaceDims (m_hAmmoIcon, &m_cxAmmoIcon, &m_cyAmmoIcon); } m_bAmmoChanged = LTTRUE; Update(); }
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; } } }
//Nothing important, just used to write out arbitrary data to a file to help with whatever //sorting or data analysis is needed at the time. void ItemDef :: Debug_WriteToStream(FILE *output) { fprintf(output, "%d;%d;%d;%d;", mID, mQualityLevel, mLevel, mMinUseLevel); fprintf(output, "%s;%s;%s;%s;", mDisplayName.c_str(), GetEquipType(mEquipType), GetArmorType(mArmorType), GetWeaponType(mWeaponType)); if(mBonusStrength != 0) fprintf(output, "%d;", mBonusStrength); else fputc(';', output); if(mBonusDexterity != 0) fprintf(output, "%d;", mBonusDexterity); else fputc(';', output); if(mBonusConstitution != 0) fprintf(output, "%d;", mBonusConstitution); else fputc(';', output); if(mBonusPsyche != 0) fprintf(output, "%d;", mBonusPsyche); else fputc(';', output); if(mBonusSpirit != 0) fprintf(output, "%d;", mBonusSpirit); else fputc(';', output); fprintf(output, "%d;%d;", mArmorResistMelee, mValue); if(mWeaponDamageMax != 0) fprintf(output, "%d-%d;", mWeaponDamageMin, mWeaponDamageMax); else fputc(';', output); switch(mBindingType) { case BIND_ON_EQUIP: fputs("E;", output); break; case BIND_ON_PICKUP: fputs("P;", output); break; default: fputc(';', output); break; } fprintf(output, "%s;%s;", mSv1.c_str(), mFlavorText.c_str()); fputs("\r\n", output); }