diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/server/cstrike/bot/states/cs_bot_hide.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/server/cstrike/bot/states/cs_bot_hide.cpp')
| -rw-r--r-- | game/server/cstrike/bot/states/cs_bot_hide.cpp | 549 |
1 files changed, 549 insertions, 0 deletions
diff --git a/game/server/cstrike/bot/states/cs_bot_hide.cpp b/game/server/cstrike/bot/states/cs_bot_hide.cpp new file mode 100644 index 0000000..9afd1e8 --- /dev/null +++ b/game/server/cstrike/bot/states/cs_bot_hide.cpp @@ -0,0 +1,549 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +// Author: Michael S. Booth ([email protected]), 2003 + +#include "cbase.h" +#include "cs_simple_hostage.h" +#include "cs_bot.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//-------------------------------------------------------------------------------------------------------------- +/** + * Begin moving to a nearby hidey-hole. + * NOTE: Do not forget this state may include a very long "move-to" time to get to our hidey spot! + */ +void HideState::OnEnter( CCSBot *me ) +{ + m_isAtSpot = false; + m_isLookingOutward = false; + + // if duration is "infinite", set it to a reasonably long time to prevent infinite camping + if (m_duration < 0.0f) + { + m_duration = RandomFloat( 30.0f, 60.0f ); + } + + // decide whether to "ambush" or not - never set to false so as not to override external setting + if (RandomFloat( 0.0f, 100.0f ) < 50.0f) + { + m_isHoldingPosition = true; + } + + // if we are holding position, decide for how long + if (m_isHoldingPosition) + { + m_holdPositionTime = RandomFloat( 3.0f, 10.0f ); + } + else + { + m_holdPositionTime = 0.0f; + } + + m_heardEnemy = false; + m_firstHeardEnemyTime = 0.0f; + m_retry = 0; + + if (me->IsFollowing()) + { + m_leaderAnchorPos = GetCentroid( me->GetFollowLeader() ); + } + + // if we are a sniper, we need to periodically pause while we retreat to squeeze off a shot or two + if (me->IsSniper()) + { + // start off paused to allow a final shot before retreating + m_isPaused = false; + m_pauseTimer.Invalidate(); + } +} + +//-------------------------------------------------------------------------------------------------------------- +/** + * Move to a nearby hidey-hole. + * NOTE: Do not forget this state may include a very long "move-to" time to get to our hidey spot! + */ +void HideState::OnUpdate( CCSBot *me ) +{ + Vector myOrigin = GetCentroid( me ); + + // wait until finished reloading to leave hide state + if (!me->IsReloading()) + { + // if we are momentarily hiding while following someone, check to see if he has moved on + if (me->IsFollowing()) + { + CCSPlayer *leader = static_cast<CCSPlayer *>( static_cast<CBaseEntity *>( me->GetFollowLeader() ) ); + Vector leaderOrigin = GetCentroid( leader ); + + // BOTPORT: Determine walk/run velocity thresholds + float runThreshold = 200.0f; + if (leader->GetAbsVelocity().IsLengthGreaterThan( runThreshold )) + { + // leader is running, stay with him + me->Follow( leader ); + return; + } + + // if leader has moved, stay with him + const float followRange = 250.0f; + if ((m_leaderAnchorPos - leaderOrigin).IsLengthGreaterThan( followRange )) + { + me->Follow( leader ); + return; + } + } + + // if we see a nearby buddy in combat, join him + /// @todo - Perhaps tie in to TakeDamage(), so it works for human players, too + + // + // Scenario logic + // + switch( TheCSBots()->GetScenario() ) + { + case CCSBotManager::SCENARIO_DEFUSE_BOMB: + { + if (me->GetTeamNumber() == TEAM_CT) + { + // if we are just holding position (due to a radio order) and the bomb has just planted, go defuse it + if (me->GetTask() == CCSBot::HOLD_POSITION && + TheCSBots()->IsBombPlanted() && + TheCSBots()->GetBombPlantTimestamp() > me->GetStateTimestamp()) + { + me->Idle(); + return; + } + + // if we are guarding the defuser and he dies/gives up, stop hiding (to choose another defuser) + if (me->GetTask() == CCSBot::GUARD_BOMB_DEFUSER && TheCSBots()->GetBombDefuser() == NULL) + { + me->Idle(); + return; + } + + // if we are guarding the loose bomb and it is picked up, stop hiding + if (me->GetTask() == CCSBot::GUARD_LOOSE_BOMB && TheCSBots()->GetLooseBomb() == NULL) + { + me->GetChatter()->TheyPickedUpTheBomb(); + me->Idle(); + return; + } + + // if we are guarding a bombsite and the bomb is dropped and we hear about it, stop guarding + if (me->GetTask() == CCSBot::GUARD_BOMB_ZONE && me->GetGameState()->IsLooseBombLocationKnown()) + { + me->Idle(); + return; + } + + // if we are guarding (bombsite, initial encounter, etc) and the bomb is planted, go defuse it + if (me->IsDoingScenario() && me->GetTask() != CCSBot::GUARD_BOMB_DEFUSER && TheCSBots()->IsBombPlanted()) + { + me->Idle(); + return; + } + + } + else // TERRORIST + { + // if we are near the ticking bomb and someone starts defusing it, attack! + if (TheCSBots()->GetBombDefuser()) + { + Vector defuserOrigin = GetCentroid( TheCSBots()->GetBombDefuser() ); + Vector toDefuser = defuserOrigin - myOrigin; + + const float hearDefuseRange = 2000.0f; + if (toDefuser.IsLengthLessThan( hearDefuseRange )) + { + // if we are nearby, attack, otherwise move to the bomb (which will cause us to attack when we see defuser) + if (me->CanSeePlantedBomb()) + { + me->Attack( TheCSBots()->GetBombDefuser() ); + } + else + { + me->MoveTo( defuserOrigin, FASTEST_ROUTE ); + me->InhibitLookAround( 10.0f ); + } + + return; + } + } + } + break; + } + + //-------------------------------------------------------------------------------------------------- + case CCSBotManager::SCENARIO_RESCUE_HOSTAGES: + { + // if we're guarding the hostages and they all die or are taken, do something else + if (me->GetTask() == CCSBot::GUARD_HOSTAGES) + { + if (me->GetGameState()->AreAllHostagesBeingRescued() || me->GetGameState()->AreAllHostagesGone()) + { + me->Idle(); + return; + } + } + else if (me->GetTask() == CCSBot::GUARD_HOSTAGE_RESCUE_ZONE) + { + // if we stumble across a hostage, guard it + CHostage *hostage = me->GetGameState()->GetNearestVisibleFreeHostage(); + if (hostage) + { + // we see a free hostage, guard it + Vector hostageOrigin = GetCentroid( hostage ); + CNavArea *area = TheNavMesh->GetNearestNavArea( hostageOrigin ); + if (area) + { + me->SetTask( CCSBot::GUARD_HOSTAGES ); + me->Hide( area ); + me->PrintIfWatched( "I'm guarding hostages I found\n" ); + // don't chatter here - he'll tell us when he's in his hiding spot + return; + } + } + } + } + } + + + bool isSettledInSniper = (me->IsSniper() && m_isAtSpot) ? true : false; + + // only investigate noises if we are initiating attacks, and we aren't a "settled in" sniper + // dont investigate noises if we are reloading + if (!me->IsReloading() && + !isSettledInSniper && + me->GetDisposition() == CCSBot::ENGAGE_AND_INVESTIGATE) + { + // if we are holding position, and have heard the enemy nearby, investigate after our hold time is up + if (m_isHoldingPosition && m_heardEnemy && (gpGlobals->curtime - m_firstHeardEnemyTime > m_holdPositionTime)) + { + /// @todo We might need to remember specific location of last enemy noise here + me->InvestigateNoise(); + return; + } + + // investigate nearby enemy noises + if (me->HeardInterestingNoise()) + { + // if we are holding position, check if enough time has elapsed since we first heard the enemy + if (m_isAtSpot && m_isHoldingPosition) + { + if (!m_heardEnemy) + { + // first time we heard the enemy + m_heardEnemy = true; + m_firstHeardEnemyTime = gpGlobals->curtime; + me->PrintIfWatched( "Heard enemy, holding position for %f2.1 seconds...\n", m_holdPositionTime ); + } + } + else + { + // not holding position - investigate enemy noise + me->InvestigateNoise(); + return; + } + } + } + } // end reloading check + + // look around + me->UpdateLookAround(); + + // if we are at our hiding spot, crouch and wait + if (m_isAtSpot) + { + me->ResetStuckMonitor(); + + CNavArea *area = TheNavMesh->GetNavArea( m_hidingSpot ); + if ( !area || !( area->GetAttributes() & NAV_MESH_STAND ) ) + { + me->Crouch(); + } + + // check if duration has expired + if (m_hideTimer.IsElapsed()) + { + if (me->GetTask() == CCSBot::GUARD_LOOSE_BOMB) + { + // if we're guarding the loose bomb, continue to guard it but pick a new spot + me->Hide( TheCSBots()->GetLooseBombArea() ); + return; + } + else if (me->GetTask() == CCSBot::GUARD_BOMB_ZONE) + { + // if we're guarding a bombsite, continue to guard it but pick a new spot + const CCSBotManager::Zone *zone = TheCSBots()->GetClosestZone( myOrigin ); + if (zone) + { + CNavArea *area = TheCSBots()->GetRandomAreaInZone( zone ); + if (area) + { + me->Hide( area ); + return; + } + } + } + else if (me->GetTask() == CCSBot::GUARD_HOSTAGE_RESCUE_ZONE) + { + // if we're guarding a rescue zone, continue to guard this or another rescue zone + if (me->GuardRandomZone()) + { + me->SetTask( CCSBot::GUARD_HOSTAGE_RESCUE_ZONE ); + me->PrintIfWatched( "Continuing to guard hostage rescue zones\n" ); + me->SetDisposition( CCSBot::OPPORTUNITY_FIRE ); + me->GetChatter()->GuardingHostageEscapeZone( IS_PLAN ); + return; + } + } + + me->Idle(); + return; + } + +/* + // if we are watching for an approaching noisy enemy, anticipate and fire before they round the corner + /// @todo Need to check if we are looking at an ENEMY_NOISE here + const float veryCloseNoise = 250.0f; + if (me->IsLookingAtSpot() && me->GetNoiseRange() < veryCloseNoise) + { + // fire! + me->PrimaryAttack(); + me->PrintIfWatched( "Firing at anticipated enemy coming around the corner!\n" ); + } +*/ + + // if we have a shield, hide behind it + if (me->HasShield() && !me->IsProtectedByShield()) + me->SecondaryAttack(); + + // while sitting at our hiding spot, if we are being attacked but can't see our attacker, move somewhere else + const float hurtRecentlyTime = 1.0f; + if (!me->IsEnemyVisible() && me->GetTimeSinceAttacked() < hurtRecentlyTime) + { + me->Idle(); + return; + } + + // encourage the human player + if (!me->IsDoingScenario()) + { + if (me->GetTeamNumber() == TEAM_CT) + { + if (me->GetTask() == CCSBot::GUARD_BOMB_ZONE && + me->IsAtHidingSpot() && + TheCSBots()->IsBombPlanted()) + { + if (me->GetNearbyEnemyCount() == 0) + { + const float someTime = 30.0f; + const float littleTime = 11.0; + + if (TheCSBots()->GetBombTimeLeft() > someTime) + me->GetChatter()->Encourage( "BombsiteSecure", RandomFloat( 10.0f, 15.0f ) ); + else if (TheCSBots()->GetBombTimeLeft() > littleTime) + me->GetChatter()->Encourage( "WaitingForHumanToDefuseBomb", RandomFloat( 5.0f, 8.0f ) ); + else + me->GetChatter()->Encourage( "WaitingForHumanToDefuseBombPanic", RandomFloat( 3.0f, 4.0f ) ); + } + } + + if (me->GetTask() == CCSBot::GUARD_HOSTAGES && me->IsAtHidingSpot()) + { + if (me->GetNearbyEnemyCount() == 0) + { + CHostage *hostage = me->GetGameState()->GetNearestVisibleFreeHostage(); + if (hostage) + { + me->GetChatter()->Encourage( "WaitingForHumanToRescueHostages", RandomFloat( 10.0f, 15.0f ) ); + } + } + } + } + } + } + else + { + // we are moving to our hiding spot + + // snipers periodically pause and fire while retreating + if (me->IsSniper() && me->IsEnemyVisible()) + { + if (m_isPaused) + { + if (m_pauseTimer.IsElapsed()) + { + // get moving + m_isPaused = false; + m_pauseTimer.Start( RandomFloat( 1.0f, 3.0f ) ); + } + else + { + me->Wait( 0.2f ); + } + } + else + { + if (m_pauseTimer.IsElapsed()) + { + // pause for a moment + m_isPaused = true; + m_pauseTimer.Start( RandomFloat( 0.5f, 1.5f ) ); + } + } + } + + // if a Player is using this hiding spot, give up + float range; + CCSPlayer *camper = static_cast<CCSPlayer *>( UTIL_GetClosestPlayer( m_hidingSpot, &range ) ); + + const float closeRange = 75.0f; + if (camper && camper != me && range < closeRange && me->IsVisible( camper, CHECK_FOV )) + { + // player is in our hiding spot + me->PrintIfWatched( "Someone's in my hiding spot - picking another...\n" ); + + const int maxRetries = 3; + if (m_retry++ >= maxRetries) + { + me->PrintIfWatched( "Can't find a free hiding spot, giving up.\n" ); + me->Idle(); + return; + } + + // pick another hiding spot near where we were planning on hiding + me->Hide( TheNavMesh->GetNavArea( m_hidingSpot ) ); + + return; + } + + Vector toSpot; + toSpot.x = m_hidingSpot.x - myOrigin.x; + toSpot.y = m_hidingSpot.y - myOrigin.y; + toSpot.z = m_hidingSpot.z - me->GetFeetZ(); // use feet location + range = toSpot.Length(); + + // look outwards as we get close to our hiding spot + if (!me->IsEnemyVisible() && !m_isLookingOutward) + { + const float lookOutwardRange = 200.0f; + const float nearSpotRange = 10.0f; + if (range < lookOutwardRange && range > nearSpotRange) + { + m_isLookingOutward = true; + + toSpot.x /= range; + toSpot.y /= range; + toSpot.z /= range; + + me->SetLookAt( "Face outward", me->EyePosition() - 1000.0f * toSpot, PRIORITY_HIGH, 3.0f ); + } + } + + const float atDist = 20.0f; + if (range < atDist) + { + //------------------------------------- + // Just reached our hiding spot + // + m_isAtSpot = true; + m_hideTimer.Start( m_duration ); + + // make sure our approach points are valid, since we'll be watching them + me->ComputeApproachPoints(); + me->ClearLookAt(); + + // ready our weapon and prepare to attack + me->EquipBestWeapon( me->IsUsingGrenade() ); + me->SetDisposition( CCSBot::OPPORTUNITY_FIRE ); + + // if we are a sniper, update our task + if (me->GetTask() == CCSBot::MOVE_TO_SNIPER_SPOT) + { + me->SetTask( CCSBot::SNIPING ); + } + else if (me->GetTask() == CCSBot::GUARD_INITIAL_ENCOUNTER) + { + const float campChatterChance = 20.0f; + if (RandomFloat( 0, 100 ) < campChatterChance) + { + me->GetChatter()->Say( "WaitingHere" ); + } + } + + + // determine which way to look + trace_t result; + float outAngle = 0.0f; + float outAngleRange = 0.0f; + for( float angle = 0.0f; angle < 360.0f; angle += 45.0f ) + { + UTIL_TraceLine( me->EyePosition(), me->EyePosition() + 1000.0f * Vector( BotCOS(angle), BotSIN(angle), 0.0f ), MASK_PLAYERSOLID, me, COLLISION_GROUP_NONE, &result ); + + if (result.fraction > outAngleRange) + { + outAngle = angle; + outAngleRange = result.fraction; + } + } + + me->SetLookAheadAngle( outAngle ); + + } + + // move to hiding spot + if (me->UpdatePathMovement() != CCSBot::PROGRESSING && !m_isAtSpot) + { + // we couldn't get to our hiding spot - pick another + me->PrintIfWatched( "Can't get to my hiding spot - finding another...\n" ); + + // search from hiding spot, since we know it was valid + const Vector *pos = FindNearbyHidingSpot( me, m_hidingSpot, m_range, me->IsSniper() ); + if (pos == NULL) + { + // no available hiding spots + me->PrintIfWatched( "No available hiding spots - hiding where I'm at.\n" ); + + // hide where we are + m_hidingSpot.x = myOrigin.x; + m_hidingSpot.x = myOrigin.y; + m_hidingSpot.z = me->GetFeetZ(); + } + else + { + m_hidingSpot = *pos; + } + + // build a path to our new hiding spot + if (me->ComputePath( m_hidingSpot, FASTEST_ROUTE ) == false) + { + me->PrintIfWatched( "Can't pathfind to hiding spot\n" ); + me->Idle(); + return; + } + } + } +} + +//-------------------------------------------------------------------------------------------------------------- +void HideState::OnExit( CCSBot *me ) +{ + m_isHoldingPosition = false; + + me->StandUp(); + me->ResetStuckMonitor(); + //me->ClearLookAt(); + me->ClearApproachPoints(); + + // if we have a shield, put it away + if (me->HasShield() && me->IsProtectedByShield()) + me->SecondaryAttack(); +} |