diff options
Diffstat (limited to 'game/server/tf/bot/behavior/nav_entities')
6 files changed, 420 insertions, 0 deletions
diff --git a/game/server/tf/bot/behavior/nav_entities/tf_bot_nav_ent_destroy_entity.cpp b/game/server/tf/bot/behavior/nav_entities/tf_bot_nav_ent_destroy_entity.cpp new file mode 100644 index 0000000..4218c3d --- /dev/null +++ b/game/server/tf/bot/behavior/nav_entities/tf_bot_nav_ent_destroy_entity.cpp @@ -0,0 +1,156 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// tf_bot_nav_ent_destroy_entity.h +// Destroy the given entity, under nav entity control +// Michael Booth, September 2009 + +#include "cbase.h" +#include "nav_mesh.h" +#include "tf_player.h" +#include "bot/tf_bot.h" +#include "bot/behavior/nav_entities/tf_bot_nav_ent_destroy_entity.h" + +extern ConVar tf_bot_path_lookahead_range; + +//--------------------------------------------------------------------------------------------- +CTFBotNavEntDestroyEntity::CTFBotNavEntDestroyEntity( const CFuncNavPrerequisite *prereq ) +{ + m_prereq = prereq; +} + + +//--------------------------------------------------------------------------------------------- +ActionResult< CTFBot > CTFBotNavEntDestroyEntity::OnStart( CTFBot *me, Action< CTFBot > *priorAction ) +{ + if ( m_prereq == NULL ) + { + return Done( "Prerequisite has been removed before we started" ); + } + + m_path.SetMinLookAheadDistance( me->GetDesiredPathLookAheadRange() ); + + m_wasIgnoringEnemies = me->HasAttribute( CTFBot::IGNORE_ENEMIES ); + + m_isReadyToLaunchSticky = true; + + return Continue(); +} + + +//--------------------------------------------------------------------------------------------- +void CTFBotNavEntDestroyEntity::DetonateStickiesWhenSet( CTFBot *me, CTFPipebombLauncher *stickyLauncher ) const +{ + if ( !stickyLauncher ) + return; + + if ( stickyLauncher->GetPipeBombCount() >= 8 || me->GetAmmoCount( TF_AMMO_SECONDARY ) <= 0 ) + { + // stickies laid - detonate them once they are on the ground + const CUtlVector< CHandle< CTFGrenadePipebombProjectile > > &pipeVector = stickyLauncher->GetPipeBombVector(); + + int i; + for( i=0; i<pipeVector.Count(); ++i ) + { + if ( pipeVector[i].Get() && !pipeVector[i]->m_bTouched ) + { + break; + } + } + + if ( i == pipeVector.Count() ) + { + // stickies are on the ground + me->PressAltFireButton(); + } + } +} + + +//--------------------------------------------------------------------------------------------- +ActionResult< CTFBot > CTFBotNavEntDestroyEntity::Update( CTFBot *me, float interval ) +{ + if ( m_prereq == NULL ) + { + return Done( "Prerequisite has been removed" ); + } + + CBaseEntity *target = m_prereq->GetTaskEntity(); + if ( target == NULL ) + { + return Done( "Target entity is NULL" ); + } + + float attackRange = me->GetMaxAttackRange(); + + if ( m_prereq->GetTaskValue() > 0.0f ) + { + attackRange = MIN( attackRange, m_prereq->GetTaskValue() ); + } + + if ( me->IsDistanceBetweenLessThan( target, attackRange ) && me->GetVisionInterface()->IsLineOfSightClearToEntity( target ) ) + { + me->SetAttribute( CTFBot::IGNORE_ENEMIES ); + + me->GetBodyInterface()->AimHeadTowards( target->WorldSpaceCenter(), IBody::CRITICAL, 0.2f, NULL, "Aiming at target we need to destroy to progress" ); + + if ( me->GetBodyInterface()->IsHeadAimingOnTarget() ) + { + // attack + if ( me->IsPlayerClass( TF_CLASS_DEMOMAN ) ) + { + // demomen use stickybombs to destroy the barrier + CTFWeaponBase *myCurrentWeapon = me->m_Shared.GetActiveTFWeapon(); + CTFPipebombLauncher *stickyLauncher = dynamic_cast< CTFPipebombLauncher * >( me->Weapon_GetSlot( TF_WPN_TYPE_SECONDARY ) ); + + if ( myCurrentWeapon && myCurrentWeapon->GetWeaponID() != TF_WEAPON_PIPEBOMBLAUNCHER ) + { + me->Weapon_Switch( stickyLauncher ); + } + + if ( m_isReadyToLaunchSticky ) + { + me->PressFireButton(); + } + + m_isReadyToLaunchSticky = !m_isReadyToLaunchSticky; + + DetonateStickiesWhenSet( me, stickyLauncher ); + + return Continue(); + } + + me->EquipBestWeaponForThreat( NULL ); + me->PressFireButton(); + } + + return Continue(); + } + + + if ( !m_wasIgnoringEnemies ) + { + me->ClearAttribute( CTFBot::IGNORE_ENEMIES ); + } + + // move into view of our target + if ( m_repathTimer.IsElapsed() ) + { + m_repathTimer.Start( RandomFloat( 1.0f, 2.0f ) ); + + CTFBotPathCost cost( me, FASTEST_ROUTE ); + m_path.Compute( me, target->GetAbsOrigin(), cost ); + } + + m_path.Update( me ); + + return Continue(); +} + + +//--------------------------------------------------------------------------------------------- +void CTFBotNavEntDestroyEntity::OnEnd( CTFBot *me, Action< CTFBot > *nextAction ) +{ + if ( !m_wasIgnoringEnemies ) + { + me->ClearAttribute( CTFBot::IGNORE_ENEMIES ); + } +} diff --git a/game/server/tf/bot/behavior/nav_entities/tf_bot_nav_ent_destroy_entity.h b/game/server/tf/bot/behavior/nav_entities/tf_bot_nav_ent_destroy_entity.h new file mode 100644 index 0000000..87dbc15 --- /dev/null +++ b/game/server/tf/bot/behavior/nav_entities/tf_bot_nav_ent_destroy_entity.h @@ -0,0 +1,35 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// tf_bot_nav_ent_destroy_entity.h +// Destroy the given entity, under nav entity control +// Michael Booth, September 2009 + +#ifndef TF_BOT_NAV_ENT_DESTROY_ENTITY_H +#define TF_BOT_NAV_ENT_DESTROY_ENTITY_H + +#include "Path/NextBotPathFollow.h" +#include "NextBot/NavMeshEntities/func_nav_prerequisite.h" +#include "tf_weapon_pipebomblauncher.h" + +class CTFBotNavEntDestroyEntity : public Action< CTFBot > +{ +public: + CTFBotNavEntDestroyEntity( const CFuncNavPrerequisite *prereq ); + + virtual ActionResult< CTFBot > OnStart( CTFBot *me, Action< CTFBot > *priorAction ); + virtual ActionResult< CTFBot > Update( CTFBot *me, float interval ); + virtual void OnEnd( CTFBot *me, Action< CTFBot > *nextAction ); + + virtual const char *GetName( void ) const { return "NavEntDestroyEntity"; }; + +private: + CHandle< CFuncNavPrerequisite > m_prereq; + PathFollower m_path; // how we get to the target + CountdownTimer m_repathTimer; + bool m_wasIgnoringEnemies; + + void DetonateStickiesWhenSet( CTFBot *me, CTFPipebombLauncher *stickyLauncher ) const; + bool m_isReadyToLaunchSticky; +}; + + +#endif // TF_BOT_NAV_ENT_DESTROY_ENTITY_H diff --git a/game/server/tf/bot/behavior/nav_entities/tf_bot_nav_ent_move_to.cpp b/game/server/tf/bot/behavior/nav_entities/tf_bot_nav_ent_move_to.cpp new file mode 100644 index 0000000..22b7f03 --- /dev/null +++ b/game/server/tf/bot/behavior/nav_entities/tf_bot_nav_ent_move_to.cpp @@ -0,0 +1,110 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// tf_bot_nav_ent_move_to.cpp +// Move onto target and wait, as directed by nav entity +// Michael Booth, September 2009 + +#include "cbase.h" +#include "nav_mesh.h" +#include "tf_player.h" +#include "bot/tf_bot.h" +#include "bot/behavior/nav_entities/tf_bot_nav_ent_move_to.h" + +extern ConVar tf_bot_path_lookahead_range; + +//--------------------------------------------------------------------------------------------- +CTFBotNavEntMoveTo::CTFBotNavEntMoveTo( const CFuncNavPrerequisite *prereq ) +{ + m_prereq = prereq; + m_pGoalArea = NULL; +} + + +//--------------------------------------------------------------------------------------------- +ActionResult< CTFBot > CTFBotNavEntMoveTo::OnStart( CTFBot *me, Action< CTFBot > *priorAction ) +{ + if ( m_prereq == NULL ) + { + return Done( "Prerequisite has been removed before we started" ); + } + + m_path.SetMinLookAheadDistance( me->GetDesiredPathLookAheadRange() ); + m_waitTimer.Invalidate(); + + CBaseEntity *target = m_prereq->GetTaskEntity(); + if ( target == NULL ) + { + return Done( "Prerequisite target entity is NULL" ); + } + + Extent targetExtent; + targetExtent.Init( target ); + + // pick random ground position within target entity as move-to goal + m_goalPosition = targetExtent.lo + Vector( RandomFloat( 0.0f, targetExtent.SizeX() ), RandomFloat( 0.0f, targetExtent.SizeY() ), targetExtent.SizeZ() ); + + TheNavMesh->GetSimpleGroundHeight( m_goalPosition, &m_goalPosition.z ); + + m_pGoalArea = (CTFNavArea*)TheNavMesh->GetNavArea( m_goalPosition ); + if ( !m_pGoalArea ) + { + return Done( "There's no nav area for the goal position" ); + } + + return Continue(); +} + + +//--------------------------------------------------------------------------------------------- +ActionResult< CTFBot > CTFBotNavEntMoveTo::Update( CTFBot *me, float interval ) +{ + if ( m_prereq == NULL ) + { + return Done( "Prerequisite has been removed" ); + } + + if ( !m_prereq->IsEnabled() ) + { + return Done( "Prerequisite has been disabled" ); + } + + const CKnownEntity *threat = me->GetVisionInterface()->GetPrimaryKnownThreat(); + if ( threat && threat->IsVisibleRecently() ) + { + // prepare to fight + me->EquipBestWeaponForThreat( threat ); + } + + if ( m_waitTimer.HasStarted() ) + { + if ( m_waitTimer.IsElapsed() ) + { + return Done( "Wait duration elapsed" ); + } + } + else + { + // move to the goal area + if ( m_pGoalArea == me->GetLastKnownArea() ) + { + // in area + m_waitTimer.Start( m_prereq->GetTaskValue() ); + } + else + { + if ( m_repathTimer.IsElapsed() ) + { + m_repathTimer.Start( RandomFloat( 1.0f, 2.0f ) ); + + CTFBotPathCost cost( me, FASTEST_ROUTE ); + m_path.Compute( me, m_goalPosition, cost ); + } + + // move into position + m_path.Update( me ); + } + } + + return Continue(); +} + + diff --git a/game/server/tf/bot/behavior/nav_entities/tf_bot_nav_ent_move_to.h b/game/server/tf/bot/behavior/nav_entities/tf_bot_nav_ent_move_to.h new file mode 100644 index 0000000..53295af --- /dev/null +++ b/game/server/tf/bot/behavior/nav_entities/tf_bot_nav_ent_move_to.h @@ -0,0 +1,35 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// tf_bot_nav_ent_move_to.h +// Move onto target and wait, as directed by nav entity +// Michael Booth, September 2009 + +#ifndef TF_BOT_NAV_ENT_MOVE_TO_H +#define TF_BOT_NAV_ENT_MOVE_TO_H + +#include "Path/NextBotPathFollow.h" +#include "NextBot/NavMeshEntities/func_nav_prerequisite.h" + + +class CTFBotNavEntMoveTo : public Action< CTFBot > +{ +public: + CTFBotNavEntMoveTo( const CFuncNavPrerequisite *prereq ); + + virtual ActionResult< CTFBot > OnStart( CTFBot *me, Action< CTFBot > *priorAction ); + virtual ActionResult< CTFBot > Update( CTFBot *me, float interval ); + + virtual const char *GetName( void ) const { return "NavEntMoveTo"; }; + +private: + CHandle< CFuncNavPrerequisite > m_prereq; + Vector m_goalPosition; // specific position within entity to move to + CTFNavArea* m_pGoalArea; + + CountdownTimer m_waitTimer; + + PathFollower m_path; // how we get to the loot + CountdownTimer m_repathTimer; +}; + + +#endif // TF_BOT_NAV_ENT_MOVE_TO_H diff --git a/game/server/tf/bot/behavior/nav_entities/tf_bot_nav_ent_wait.cpp b/game/server/tf/bot/behavior/nav_entities/tf_bot_nav_ent_wait.cpp new file mode 100644 index 0000000..d55d7fd --- /dev/null +++ b/game/server/tf/bot/behavior/nav_entities/tf_bot_nav_ent_wait.cpp @@ -0,0 +1,56 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// tf_bot_nav_ent_wait.cpp +// Wait for awhile, as directed by nav entity +// Michael Booth, September 2009 + +#include "cbase.h" +#include "nav_mesh.h" +#include "tf_player.h" +#include "bot/tf_bot.h" +#include "bot/behavior/nav_entities/tf_bot_nav_ent_wait.h" + +extern ConVar tf_bot_path_lookahead_range; + +//--------------------------------------------------------------------------------------------- +CTFBotNavEntWait::CTFBotNavEntWait( const CFuncNavPrerequisite *prereq ) +{ + m_prereq = prereq; +} + + +//--------------------------------------------------------------------------------------------- +ActionResult< CTFBot > CTFBotNavEntWait::OnStart( CTFBot *me, Action< CTFBot > *priorAction ) +{ + if ( m_prereq == NULL ) + { + return Done( "Prerequisite has been removed before we started" ); + } + + m_timer.Start( m_prereq->GetTaskValue() ); + + return Continue(); +} + + +//--------------------------------------------------------------------------------------------- +ActionResult< CTFBot > CTFBotNavEntWait::Update( CTFBot *me, float interval ) +{ + if ( m_prereq == NULL ) + { + return Done( "Prerequisite has been removed" ); + } + + if ( !m_prereq->IsEnabled() ) + { + return Done( "Prerequisite has been disabled" ); + } + + if ( m_timer.IsElapsed() ) + { + return Done( "Wait time elapsed" ); + } + + return Continue(); +} + + diff --git a/game/server/tf/bot/behavior/nav_entities/tf_bot_nav_ent_wait.h b/game/server/tf/bot/behavior/nav_entities/tf_bot_nav_ent_wait.h new file mode 100644 index 0000000..72de0e8 --- /dev/null +++ b/game/server/tf/bot/behavior/nav_entities/tf_bot_nav_ent_wait.h @@ -0,0 +1,28 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// tf_bot_nav_ent_wait.h +// Wait for awhile, as directed by nav entity +// Michael Booth, September 2009 + +#ifndef TF_BOT_NAV_ENT_WAIT_H +#define TF_BOT_NAV_ENT_WAIT_H + +#include "NextBot/NavMeshEntities/func_nav_prerequisite.h" + + +class CTFBotNavEntWait : public Action< CTFBot > +{ +public: + CTFBotNavEntWait( const CFuncNavPrerequisite *prereq ); + + virtual ActionResult< CTFBot > OnStart( CTFBot *me, Action< CTFBot > *priorAction ); + virtual ActionResult< CTFBot > Update( CTFBot *me, float interval ); + + virtual const char *GetName( void ) const { return "NavEntWait"; }; + +private: + CHandle< CFuncNavPrerequisite > m_prereq; + CountdownTimer m_timer; +}; + + +#endif // TF_BOT_NAV_ENT_WAIT_H |