summaryrefslogtreecommitdiff
path: root/game/server/tf/bot_npc/bot_npc_decoy.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/server/tf/bot_npc/bot_npc_decoy.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/server/tf/bot_npc/bot_npc_decoy.cpp')
-rw-r--r--game/server/tf/bot_npc/bot_npc_decoy.cpp246
1 files changed, 246 insertions, 0 deletions
diff --git a/game/server/tf/bot_npc/bot_npc_decoy.cpp b/game/server/tf/bot_npc/bot_npc_decoy.cpp
new file mode 100644
index 0000000..757a467
--- /dev/null
+++ b/game/server/tf/bot_npc/bot_npc_decoy.cpp
@@ -0,0 +1,246 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+// bot_npc_decoy.cpp
+// A NextBot non-player decoy that imitates a real player
+// Michael Booth, January 2011
+
+#include "cbase.h"
+#include "tf_player.h"
+#include "tf_gamerules.h"
+#include "tf_team.h"
+#include "nav_mesh/tf_nav_area.h"
+#include "bot_npc_decoy.h"
+#include "econ_wearable.h"
+
+LINK_ENTITY_TO_CLASS( bot_npc_decoy, CBotNPCDecoy );
+PRECACHE_REGISTER( bot_npc_decoy );
+
+ConVar tf_decoy_lifetime( "tf_decoy_lifetime", "5", FCVAR_CHEAT, "The lifetime of a decoy, in seconds" );
+
+
+//-----------------------------------------------------------------------------------------------------
+CBotNPCDecoy::CBotNPCDecoy()
+{
+ ALLOCATE_INTENTION_INTERFACE( CBotNPCDecoy );
+
+ m_locomotor = new CBotNPCDecoyLocomotion( this );
+ m_body = new CBotNPCBody( this );
+
+ m_eyeOffset = vec3_origin;
+}
+
+
+//-----------------------------------------------------------------------------------------------------
+CBotNPCDecoy::~CBotNPCDecoy()
+{
+ DEALLOCATE_INTENTION_INTERFACE;
+
+ if ( m_locomotor )
+ delete m_locomotor;
+
+ if ( m_body )
+ delete m_body;
+}
+
+//-----------------------------------------------------------------------------------------------------
+void CBotNPCDecoy::Precache()
+{
+ BaseClass::Precache();
+}
+
+
+//-----------------------------------------------------------------------------------------------------
+void CBotNPCDecoy::Spawn( void )
+{
+ BaseClass::Spawn();
+
+ SetCollisionGroup( COLLISION_GROUP_NONE );
+ SetSolid( SOLID_NONE );
+ AddSolidFlags( FSOLID_NOT_SOLID );
+
+ CTFPlayer *owner = ToTFPlayer( GetOwnerEntity() );
+ if ( !owner )
+ {
+ Warning( "Decoy spawned without an owner\n" );
+ return;
+ }
+
+ int ownerClass = owner->m_Shared.InCond( TF_COND_DISGUISED ) ? owner->m_Shared.GetDisguiseClass() : owner->GetPlayerClass()->GetClassIndex();
+ int ownerTeam = owner->m_Shared.InCond( TF_COND_DISGUISED ) ? owner->m_Shared.GetDisguiseTeam() : owner->GetTeamNumber();
+
+ SetModel( GetPlayerClassData( ownerClass )->m_szModelName );
+ ChangeTeam( ownerTeam );
+
+ if ( ownerTeam == TF_TEAM_BLUE )
+ {
+ m_nSkin = 1;
+ }
+ else
+ {
+ m_nSkin = 0;
+ }
+
+ SetAbsOrigin( owner->GetAbsOrigin() );
+ SetAbsAngles( owner->GetAbsAngles() );
+ SetAbsVelocity( owner->GetAbsVelocity() );
+
+ Vector headPos;
+ QAngle headAngles;
+ if ( GetAttachment( "head", headPos, headAngles ) )
+ {
+ m_eyeOffset = headPos - GetAbsOrigin();
+ }
+
+ CTFWeaponBase *theirWeapon = owner->m_Shared.GetDisguiseWeapon();
+ if ( !theirWeapon )
+ {
+ theirWeapon = owner->GetActiveTFWeapon();
+ }
+
+ if ( theirWeapon )
+ {
+ CBaseAnimating *weapon = (CBaseAnimating *)CreateEntityByName( "prop_dynamic" );
+ if ( weapon )
+ {
+ weapon->SetModel( theirWeapon->GetWorldModel() );
+
+ // bonemerge the weapon into our model
+ weapon->FollowEntity( this, true );
+
+ // choose the appropriate run animation for this weapon
+ switch( theirWeapon->GetTFWpnData().m_iWeaponType )
+ {
+ case TF_WPN_TYPE_PRIMARY:
+ m_runActivity = ACT_MP_RUN_PRIMARY;
+ break;
+
+ case TF_WPN_TYPE_SECONDARY:
+ m_runActivity = ACT_MP_RUN_SECONDARY;
+ break;
+
+ case TF_WPN_TYPE_MELEE:
+ default:
+ m_runActivity = ACT_MP_RUN_MELEE;
+ break;
+ }
+ }
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------
+unsigned int CBotNPCDecoy::PhysicsSolidMaskForEntity( void ) const
+{
+ // Only collide with the other team
+ int teamContents = ( GetTeamNumber() == TF_TEAM_RED ) ? CONTENTS_BLUETEAM : CONTENTS_REDTEAM;
+
+ return BaseClass::PhysicsSolidMaskForEntity() | teamContents;
+}
+
+
+//---------------------------------------------------------------------------------------------
+bool CBotNPCDecoy::ShouldCollide( int collisionGroup, int contentsMask ) const
+{
+ if ( collisionGroup == COLLISION_GROUP_PLAYER_MOVEMENT )
+ {
+ switch( GetTeamNumber() )
+ {
+ case TF_TEAM_RED:
+ if ( !( contentsMask & CONTENTS_REDTEAM ) )
+ return false;
+ break;
+
+ case TF_TEAM_BLUE:
+ if ( !( contentsMask & CONTENTS_BLUETEAM ) )
+ return false;
+ break;
+ }
+ }
+
+ return BaseClass::ShouldCollide( collisionGroup, contentsMask );
+}
+
+
+//---------------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+float CBotNPCDecoyLocomotion::GetRunSpeed( void ) const
+{
+ CTFPlayer *owner = ToTFPlayer( GetBot()->GetEntity()->GetOwnerEntity() );
+ if ( !owner )
+ {
+ return 0.0f;
+ }
+
+ int ownerClass = owner->m_Shared.InCond( TF_COND_DISGUISED ) ? owner->m_Shared.GetDisguiseClass() : owner->GetPlayerClass()->GetClassIndex();
+ return GetPlayerClassData( ownerClass )->m_flMaxSpeed;
+}
+
+
+//---------------------------------------------------------------------------------------------
+// return maximum acceleration of locomotor
+float CBotNPCDecoyLocomotion::GetMaxAcceleration( void ) const
+{
+ return 1500.0f;
+}
+
+
+//---------------------------------------------------------------------------------------------
+// return maximum deceleration of locomotor
+float CBotNPCDecoyLocomotion::GetMaxDeceleration( void ) const
+{
+ return 1500.0f;
+}
+
+
+//---------------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+class CBotNPCDecoyBehavior : public Action< CBotNPCDecoy >
+{
+public:
+ virtual ActionResult< CBotNPCDecoy > OnStart( CBotNPCDecoy *me, Action< CBotNPCDecoy > *priorAction )
+ {
+ m_timer.Start( tf_decoy_lifetime.GetFloat() );
+
+ // play running animation
+ if ( !me->GetBodyInterface()->IsActivity( me->GetRunActivity() ) )
+ {
+ me->GetBodyInterface()->StartActivity( me->GetRunActivity() );
+ }
+
+ return Continue();
+ }
+
+ virtual ActionResult< CBotNPCDecoy > Update( CBotNPCDecoy *me, float interval )
+ {
+ if ( m_timer.IsElapsed() )
+ {
+ // we're out of time
+ UTIL_Remove( me );
+ return Done( "Lifetime expired" );
+ }
+
+ CTFPlayer *owner = ToTFPlayer( me->GetOwnerEntity() );
+ if ( !owner )
+ {
+ UTIL_Remove( me );
+ return Done( "No owner!" );
+ }
+
+ Vector forward;
+ me->GetVectors( &forward, NULL, NULL );
+
+ me->GetLocomotionInterface()->SetDesiredSpeed( FLT_MAX ); // this is just a rate limiter
+ me->GetLocomotionInterface()->Run();
+ me->GetLocomotionInterface()->Approach( me->GetAbsOrigin() + 100.0f * forward );
+
+ return Continue();
+ }
+
+ virtual const char *GetName( void ) const { return "Behavior"; } // return name of this action
+
+private:
+ CountdownTimer m_timer;
+};
+
+
+IMPLEMENT_INTENTION_INTERFACE( CBotNPCDecoy, CBotNPCDecoyBehavior );
+