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/cs_bot_event.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/cs_bot_event.cpp')
| -rw-r--r-- | game/server/cstrike/bot/cs_bot_event.cpp | 427 |
1 files changed, 427 insertions, 0 deletions
diff --git a/game/server/cstrike/bot/cs_bot_event.cpp b/game/server/cstrike/bot/cs_bot_event.cpp new file mode 100644 index 0000000..24bdae4 --- /dev/null +++ b/game/server/cstrike/bot/cs_bot_event.cpp @@ -0,0 +1,427 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +// Author: Michael S. Booth ([email protected]), 2003 + +#include "cbase.h" +#include "cs_gamerules.h" +#include "KeyValues.h" + +#include "cs_bot.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//-------------------------------------------------------------------------------------------------------------- +/** + * Checks if the bot can hear the event + */ +void CCSBot::OnAudibleEvent( IGameEvent *event, CBasePlayer *player, float range, PriorityType priority, bool isHostile, bool isFootstep, const Vector *actualOrigin ) +{ + /// @todo Listen to non-player sounds + if (player == NULL) + return; + + // don't pay attention to noise that friends make + if (!IsEnemy( player )) + return; + + Vector playerOrigin = GetCentroid( player ); + Vector myOrigin = GetCentroid( this ); + + // If the event occurs far from the triggering player, it may override the origin + if ( actualOrigin ) + { + playerOrigin = *actualOrigin; + } + + // check if noise is close enough for us to hear + const Vector *newNoisePosition = &playerOrigin; + float newNoiseDist = (myOrigin - *newNoisePosition).Length(); + if (newNoiseDist < range) + { + // we heard the sound + if ((IsLocalPlayerWatchingMe() && cv_bot_debug.GetInt() == 3) || cv_bot_debug.GetInt() == 4) + { + PrintIfWatched( "Heard noise (%s from %s, pri %s, time %3.1f)\n", + (FStrEq( "weapon_fire", event->GetName() )) ? "Weapon fire " : "", + (player) ? player->GetPlayerName() : "NULL", + (priority == PRIORITY_HIGH) ? "HIGH" : ((priority == PRIORITY_MEDIUM) ? "MEDIUM" : "LOW"), + gpGlobals->curtime ); + } + + // should we pay attention to it + // if noise timestamp is zero, there is no prior noise + if (m_noiseTimestamp > 0.0f) + { + // only overwrite recent sound if we are louder (closer), or more important - if old noise was long ago, its faded + const float shortTermMemoryTime = 3.0f; + if (gpGlobals->curtime - m_noiseTimestamp < shortTermMemoryTime) + { + // prior noise is more important - ignore new one + if (priority < m_noisePriority) + return; + + float oldNoiseDist = (myOrigin - m_noisePosition).Length(); + if (newNoiseDist >= oldNoiseDist) + return; + } + } + + // find the area in which the noise occured + /// @todo Better handle when noise occurs off the nav mesh + /// @todo Make sure noise area is not through a wall or ceiling from source of noise + /// @todo Change GetNavTravelTime to better deal with NULL destination areas + CNavArea *noiseArea = TheNavMesh->GetNearestNavArea( *newNoisePosition ); + if (noiseArea == NULL) + { + PrintIfWatched( " *** Noise occurred off the nav mesh - ignoring!\n" ); + return; + } + + m_noiseArea = noiseArea; + + // remember noise priority + m_noisePriority = priority; + + // randomize noise position in the area a bit - hearing isn't very accurate + // the closer the noise is, the more accurate our placement + /// @todo Make sure not to pick a position on the opposite side of ourselves. + const float maxErrorRadius = 400.0f; + const float maxHearingRange = 2000.0f; + float errorRadius = maxErrorRadius * newNoiseDist/maxHearingRange; + + m_noisePosition.x = newNoisePosition->x + RandomFloat( -errorRadius, errorRadius ); + m_noisePosition.y = newNoisePosition->y + RandomFloat( -errorRadius, errorRadius ); + + // note the *travel distance* to the noise + m_noiseTravelDistance = GetTravelDistanceToPlayer( (CCSPlayer *)player ); + + // make sure noise position remains in the same area + m_noiseArea->GetClosestPointOnArea( m_noisePosition, &m_noisePosition ); + + // note when we heard the noise + m_noiseTimestamp = gpGlobals->curtime; + + // if we hear a nearby enemy, become alert + const float nearbyNoiseRange = 1000.0f; + if (m_noiseTravelDistance < nearbyNoiseRange && m_noiseTravelDistance > 0.0f) + { + BecomeAlert(); + } + } +} + + +//-------------------------------------------------------------------------------------------------------------- +void CCSBot::OnHEGrenadeDetonate( IGameEvent *event ) +{ + if ( !IsAlive() ) + return; + + // don't react to our own events + CBasePlayer *player = UTIL_PlayerByUserId( event->GetInt( "userid" ) ); + if ( player == this ) + return; + + OnAudibleEvent( event, player, 99999.0f, PRIORITY_HIGH, true ); // hegrenade_detonate +} + + +//-------------------------------------------------------------------------------------------------------------- +void CCSBot::OnFlashbangDetonate( IGameEvent *event ) +{ + if ( !IsAlive() ) + return; + + // don't react to our own events + CBasePlayer *player = UTIL_PlayerByUserId( event->GetInt( "userid" ) ); + if ( player == this ) + return; + + OnAudibleEvent( event, player, 1000.0f, PRIORITY_LOW, true ); // flashbang_detonate +} + + +//-------------------------------------------------------------------------------------------------------------- +void CCSBot::OnSmokeGrenadeDetonate( IGameEvent *event ) +{ + if ( !IsAlive() ) + return; + + // don't react to our own events + CBasePlayer *player = UTIL_PlayerByUserId( event->GetInt( "userid" ) ); + if ( player == this ) + return; + + OnAudibleEvent( event, player, 1000.0f, PRIORITY_LOW, true ); // smokegrenade_detonate +} + + +//-------------------------------------------------------------------------------------------------------------- +void CCSBot::OnGrenadeBounce( IGameEvent *event ) +{ + if ( !IsAlive() ) + return; + + // don't react to our own events + CBasePlayer *player = UTIL_PlayerByUserId( event->GetInt( "userid" ) ); + if ( player == this ) + return; + + OnAudibleEvent( event, player, 500.0f, PRIORITY_LOW, true ); // grenade_bounce +} + + +//-------------------------------------------------------------------------------------------------------------- +void CCSBot::OnBulletImpact( IGameEvent *event ) +{ + if ( !IsAlive() ) + return; + + // don't react to our own events + CBasePlayer *player = UTIL_PlayerByUserId( event->GetInt( "userid" ) ); + if ( player == this ) + return; + + // Construct an origin for the sound, since it can be far from the originating player + Vector actualOrigin; + actualOrigin.x = event->GetFloat( "x", 0.0f ); + actualOrigin.y = event->GetFloat( "y", 0.0f ); + actualOrigin.z = event->GetFloat( "z", 0.0f ); + + /// @todo Ignoring bullet impact events for now - we dont want bots to look directly at them! + //OnAudibleEvent( event, player, 1100.0f, PRIORITY_MEDIUM, true, false, &actualOrigin ); // bullet_impact +} + + +//-------------------------------------------------------------------------------------------------------------- +void CCSBot::OnBreakProp( IGameEvent *event ) +{ + if ( !IsAlive() ) + return; + + // don't react to our own events + CBasePlayer *player = UTIL_PlayerByUserId( event->GetInt( "userid" ) ); + if ( player == this ) + return; + + OnAudibleEvent( event, player, 1100.0f, PRIORITY_MEDIUM, true ); // break_prop +} + + +//-------------------------------------------------------------------------------------------------------------- +void CCSBot::OnBreakBreakable( IGameEvent *event ) +{ + if ( !IsAlive() ) + return; + + // don't react to our own events + CBasePlayer *player = UTIL_PlayerByUserId( event->GetInt( "userid" ) ); + if ( player == this ) + return; + + OnAudibleEvent( event, player, 1100.0f, PRIORITY_MEDIUM, true ); // break_glass +} + + +//-------------------------------------------------------------------------------------------------------------- +void CCSBot::OnDoorMoving( IGameEvent *event ) +{ + if ( !IsAlive() ) + return; + + // don't react to our own events + CBasePlayer *player = UTIL_PlayerByUserId( event->GetInt( "userid" ) ); + if ( player == this ) + return; + + OnAudibleEvent( event, player, 1100.0f, PRIORITY_MEDIUM, false ); // door_moving +} + + +//-------------------------------------------------------------------------------------------------------------- +void CCSBot::OnHostageFollows( IGameEvent *event ) +{ + if ( !IsAlive() ) + return; + + // don't react to our own events + CBasePlayer *player = UTIL_PlayerByUserId( event->GetInt( "userid" ) ); + if ( player == this ) + return; + + // player_follows needs a player + if (player == NULL) + return; + + // don't pay attention to noise that friends make + if (!IsEnemy( player )) + return; + + Vector playerOrigin = GetCentroid( player ); + Vector myOrigin = GetCentroid( this ); + const float range = 1200.0f; + + // this is here so T's not only act on the noise, but look at it, too + if (GetTeamNumber() == TEAM_TERRORIST) + { + // make sure we can hear the noise + if ((playerOrigin - myOrigin).IsLengthGreaterThan( range )) + return; + + // tell our teammates that the hostages are being taken + GetChatter()->HostagesBeingTaken(); + + // only move if we hear them being rescued and can't see any hostages + if (GetGameState()->GetNearestVisibleFreeHostage() == NULL) + { + // since we are guarding the hostages, presumably we know where they are + // if we're close enough to "hear" this event, either go to where the event occured, + // or head for an escape zone to head them off + if (GetTask() != CCSBot::GUARD_HOSTAGE_RESCUE_ZONE) + { + //const float headOffChance = 33.3f; + if (true) // || RandomFloat( 0, 100 ) < headOffChance) + { + // head them off at a rescue zone + if (GuardRandomZone()) + { + SetTask( CCSBot::GUARD_HOSTAGE_RESCUE_ZONE ); + SetDisposition( CCSBot::OPPORTUNITY_FIRE ); + PrintIfWatched( "Trying to beat them to an escape zone!\n" ); + } + } + else + { + SetTask( SEEK_AND_DESTROY ); + StandUp(); + Run(); + MoveTo( playerOrigin, FASTEST_ROUTE ); + } + } + } + } + else + { + // CT's don't care about this noise + return; + } + + OnAudibleEvent( event, player, range, PRIORITY_MEDIUM, false ); // hostage_follows +} + + +//-------------------------------------------------------------------------------------------------------------- +void CCSBot::OnRoundEnd( IGameEvent *event ) +{ + // Morale adjustments happen even for dead players + int winner = event->GetInt( "winner" ); + switch ( winner ) + { + case WINNER_TER: + if (GetTeamNumber() == TEAM_CT) + { + DecreaseMorale(); + } + else + { + IncreaseMorale(); + } + break; + + case WINNER_CT: + if (GetTeamNumber() == TEAM_CT) + { + IncreaseMorale(); + } + else + { + DecreaseMorale(); + } + break; + + default: + break; + } + + m_gameState.OnRoundEnd( event ); + + if ( !IsAlive() ) + return; + + if ( event->GetInt( "winner" ) == WINNER_TER ) + { + if (GetTeamNumber() == TEAM_TERRORIST) + GetChatter()->CelebrateWin(); + } + else if ( event->GetInt( "winner" ) == WINNER_CT ) + { + if (GetTeamNumber() == TEAM_CT) + GetChatter()->CelebrateWin(); + } +} + + +//-------------------------------------------------------------------------------------------------------------- +void CCSBot::OnRoundStart( IGameEvent *event ) +{ + m_gameState.OnRoundStart( event ); +} + + +//-------------------------------------------------------------------------------------------------------------- +void CCSBot::OnHostageRescuedAll( IGameEvent *event ) +{ + m_gameState.OnHostageRescuedAll( event ); +} + + +//-------------------------------------------------------------------------------------------------------------- +void CCSBot::OnNavBlocked( IGameEvent *event ) +{ + if ( event->GetBool( "blocked" ) ) + { + unsigned int areaID = event->GetInt( "area" ); + if ( areaID ) + { + // An area was blocked off. Reset our path if it has this area on it. + for( int i=0; i<m_pathLength; ++i ) + { + const ConnectInfo *info = &m_path[ i ]; + if ( info->area && info->area->GetID() == areaID ) + { + DestroyPath(); + return; + } + } + } + } +} + + +//-------------------------------------------------------------------------------------------------------------- +/** + * Invoked when bot enters a nav area + */ +void CCSBot::OnEnteredNavArea( CNavArea *newArea ) +{ + // assume that we "clear" an area of enemies when we enter it + newArea->SetClearedTimestamp( GetTeamNumber()-1 ); + + // if we just entered a 'stop' area, set the flag + if ( newArea->GetAttributes() & NAV_MESH_STOP ) + { + m_isStopping = true; + } + + /// @todo Flag these areas as spawn areas during load + if (IsAtEnemySpawn()) + { + m_hasVisitedEnemySpawn = true; + } +} |