summaryrefslogtreecommitdiff
path: root/game/server/tf/halloween/zombie/zombie_behavior
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/halloween/zombie/zombie_behavior
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/server/tf/halloween/zombie/zombie_behavior')
-rw-r--r--game/server/tf/halloween/zombie/zombie_behavior/zombie_attack.cpp303
-rw-r--r--game/server/tf/halloween/zombie/zombie_behavior/zombie_attack.h36
-rw-r--r--game/server/tf/halloween/zombie/zombie_behavior/zombie_spawn.cpp29
-rw-r--r--game/server/tf/halloween/zombie/zombie_behavior/zombie_spawn.h22
-rw-r--r--game/server/tf/halloween/zombie/zombie_behavior/zombie_special_attack.cpp68
-rw-r--r--game/server/tf/halloween/zombie/zombie_behavior/zombie_special_attack.h25
6 files changed, 483 insertions, 0 deletions
diff --git a/game/server/tf/halloween/zombie/zombie_behavior/zombie_attack.cpp b/game/server/tf/halloween/zombie/zombie_behavior/zombie_attack.cpp
new file mode 100644
index 0000000..0438e05
--- /dev/null
+++ b/game/server/tf/halloween/zombie/zombie_behavior/zombie_attack.cpp
@@ -0,0 +1,303 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+//
+//
+//=============================================================================
+#include "cbase.h"
+
+#include "tf_player.h"
+#include "tf_gamerules.h"
+#include "tf_team.h"
+#include "nav_mesh/tf_nav_area.h"
+
+#include "../zombie.h"
+#include "zombie_attack.h"
+#include "zombie_special_attack.h"
+
+#define ZOMBIE_CHASE_MIN_DURATION 3.0f
+
+ConVar tf_halloween_zombie_damage( "tf_halloween_zombie_damage", "10", FCVAR_CHEAT, "How much damage a zombie melee hit does." );
+
+
+//----------------------------------------------------------------------------------
+ActionResult< CZombie > CZombieAttack::OnStart( CZombie *me, Action< CZombie > *priorAction )
+{
+ // smooth out the bot's path following by moving toward a point farther down the path
+ m_path.SetMinLookAheadDistance( 100.0f );
+
+ // start animation
+ me->GetBodyInterface()->StartActivity( ACT_MP_RUN_MELEE );
+
+ m_specialAttackTimer.Start( RandomFloat( 5.f, 10.f ) );
+
+ return Continue();
+}
+
+
+//----------------------------------------------------------------------------------
+bool CZombieAttack::IsPotentiallyChaseable( CZombie *me, CBaseCombatCharacter *victim )
+{
+ if ( !victim )
+ {
+ return false;
+ }
+
+ if ( !victim->IsAlive() )
+ {
+ // victim is dead - pick a new one
+ return false;
+ }
+
+ CTFNavArea *victimArea = (CTFNavArea *)victim->GetLastKnownArea();
+ if ( !victimArea || victimArea->HasAttributeTF( TF_NAV_SPAWN_ROOM_BLUE | TF_NAV_SPAWN_ROOM_RED ) )
+ {
+ // unreachable - pick a new victim
+ return false;
+ }
+
+ if ( victim->GetGroundEntity() != NULL )
+ {
+ Vector victimAreaPos;
+ victimArea->GetClosestPointOnArea( victim->GetAbsOrigin(), &victimAreaPos );
+ if ( ( victim->GetAbsOrigin() - victimAreaPos ).AsVector2D().IsLengthGreaterThan( 50.0f ) )
+ {
+ // off the mesh and unreachable - pick a new victim
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+//----------------------------------------------------------------------------------
+void CZombieAttack::SelectVictim( CZombie *me )
+{
+ if ( IsPotentiallyChaseable( me, m_attackTarget ) && !m_attackTargetFocusTimer.IsElapsed() )
+ {
+ // Continue chasing current target
+ return;
+ }
+
+ // pick a new victim to chase
+ CBaseCombatCharacter *newVictim = NULL;
+ CUtlVector< CTFPlayer * > playerVector;
+
+ // collect everyone
+ if ( me->GetTeamNumber() == TF_TEAM_RED )
+ {
+ CollectPlayers( &playerVector, TF_TEAM_BLUE, COLLECT_ONLY_LIVING_PLAYERS );
+ }
+ else if ( me->GetTeamNumber() == TF_TEAM_BLUE )
+ {
+ CollectPlayers( &playerVector, TF_TEAM_RED, COLLECT_ONLY_LIVING_PLAYERS );
+ }
+ else
+ {
+ CollectPlayers( &playerVector, TF_TEAM_RED, COLLECT_ONLY_LIVING_PLAYERS );
+ CollectPlayers( &playerVector, TF_TEAM_BLUE, COLLECT_ONLY_LIVING_PLAYERS, APPEND_PLAYERS );
+ }
+
+ float victimRangeSq = FLT_MAX;
+ // find closest player
+ for( int i=0; i<playerVector.Count(); ++i )
+ {
+ CTFPlayer *pPlayer = playerVector[i];
+ if ( !IsPotentiallyChaseable( me, pPlayer ) )
+ {
+ continue;
+ }
+
+ // ignore stealth player
+ if ( pPlayer->m_Shared.IsStealthed() )
+ {
+ if ( !pPlayer->m_Shared.InCond( TF_COND_BURNING ) &&
+ !pPlayer->m_Shared.InCond( TF_COND_URINE ) &&
+ !pPlayer->m_Shared.InCond( TF_COND_STEALTHED_BLINK ) &&
+ !pPlayer->m_Shared.InCond( TF_COND_BLEEDING ) )
+ {
+ // cloaked spies are invisible to us
+ continue;
+ }
+ }
+
+ // ignore player who disguises as my team
+ if ( pPlayer->m_Shared.InCond( TF_COND_DISGUISED ) && pPlayer->m_Shared.GetDisguiseTeam() == me->GetTeamNumber() )
+ {
+ continue;
+ }
+
+ // ignore ghost players
+ if ( pPlayer->m_Shared.InCond( TF_COND_HALLOWEEN_GHOST_MODE ) )
+ {
+ continue;
+ }
+
+ float rangeSq = me->GetRangeSquaredTo( pPlayer );
+ if ( rangeSq < victimRangeSq )
+ {
+ newVictim = pPlayer;
+ victimRangeSq = rangeSq;
+ }
+ }
+
+ // find closest zombie
+ for ( int i=0; i<IZombieAutoList::AutoList().Count(); ++i )
+ {
+ CZombie* pZombie = static_cast< CZombie* >( IZombieAutoList::AutoList()[i] );
+ if ( pZombie->GetTeamNumber() == me->GetTeamNumber() )
+ {
+ continue;
+ }
+
+ if ( !IsPotentiallyChaseable( me, pZombie ) )
+ {
+ continue;
+ }
+
+ float rangeSq = me->GetRangeSquaredTo( pZombie );
+ if ( rangeSq < victimRangeSq )
+ {
+ newVictim = pZombie;
+ victimRangeSq = rangeSq;
+ }
+ }
+
+ if ( newVictim )
+ {
+ // we have a new victim
+ m_attackTargetFocusTimer.Start( ZOMBIE_CHASE_MIN_DURATION );
+ }
+
+ m_attackTarget = newVictim;
+}
+
+
+//----------------------------------------------------------------------------------
+ActionResult< CZombie > CZombieAttack::Update( CZombie *me, float interval )
+{
+ if ( !me->IsAlive() )
+ {
+ return Done();
+ }
+
+ if ( !m_tauntTimer.IsElapsed() )
+ {
+ // wait for taunt to finish
+ return Continue();
+ }
+
+ SelectVictim( me );
+
+ if ( m_attackTarget == NULL || !m_attackTarget->IsAlive() )
+ {
+ return Continue();
+ }
+
+ // chase after our chase victim
+ const float standAndSwingRange = 50.0f;
+
+ bool isLineOfSightClear = me->IsLineOfSightClear( m_attackTarget );
+
+ if ( me->IsRangeGreaterThan( m_attackTarget, standAndSwingRange ) || !isLineOfSightClear )
+ {
+ if ( m_path.GetAge() > 0.5f )
+ {
+ CZombiePathCost cost( me );
+ m_path.Compute( me, m_attackTarget, cost );
+ }
+
+ m_path.Update( me );
+ }
+
+ // claw at attack target if they are in range
+ const float zombieSwingRange = 150.0f;
+ if ( me->IsRangeLessThan( m_attackTarget, zombieSwingRange ) )
+ {
+ me->GetLocomotionInterface()->FaceTowards( m_attackTarget->WorldSpaceCenter() );
+
+ // swing!
+ if ( !me->IsPlayingGesture( ACT_MP_ATTACK_STAND_MELEE ) )
+ {
+ me->AddGesture( ACT_MP_ATTACK_STAND_MELEE );
+ }
+
+ const float zombieAttackRange = me->GetAttackRange();
+ if ( me->IsRangeLessThan( m_attackTarget, zombieAttackRange ) )
+ {
+ if ( me->GetSkeletonType() == 1 && m_specialAttackTimer.IsElapsed() )
+ {
+ m_specialAttackTimer.Start( RandomFloat( 5.f, 10.f ) );
+ return SuspendFor( new CZombieSpecialAttack, "Do Special Attack!" );
+ }
+
+ if ( m_attackTimer.IsElapsed() )
+ {
+ m_attackTimer.Start( RandomFloat( 0.8f, 1.2f ) );
+
+ Vector toVictim = m_attackTarget->WorldSpaceCenter() - me->WorldSpaceCenter();
+ toVictim.NormalizeInPlace();
+
+ // hit!
+ CBaseEntity *pAttacker = me->GetOwnerEntity() ? me->GetOwnerEntity() : me;
+ CTakeDamageInfo info( pAttacker, pAttacker, me->GetAttackDamage(), DMG_SLASH );
+ info.SetDamageCustom( TF_DMG_CUSTOM_SPELL_SKELETON );
+ CalculateMeleeDamageForce( &info, toVictim, me->WorldSpaceCenter(), 5.0f );
+ m_attackTarget->TakeDamage( info );
+ }
+ }
+ }
+
+ if ( !me->GetBodyInterface()->IsActivity( ACT_MP_RUN_MELEE ) )
+ {
+ me->GetBodyInterface()->StartActivity( ACT_MP_RUN_MELEE );
+ }
+
+ return Continue();
+}
+
+
+//---------------------------------------------------------------------------------------------
+EventDesiredResult< CZombie > CZombieAttack::OnStuck( CZombie *me )
+{
+ // if we're stuck just die
+ CTakeDamageInfo info( me, me, 99999.9f, DMG_SLASH );
+ me->TakeDamage( info );
+
+ return TryContinue( RESULT_TRY );
+}
+
+
+//---------------------------------------------------------------------------------------------
+EventDesiredResult< CZombie > CZombieAttack::OnContact( CZombie *me, CBaseEntity *other, CGameTrace *result )
+{
+ if ( other->IsPlayer() )
+ {
+ CTFPlayer *pTFPlayer = ToTFPlayer( other );
+ if ( pTFPlayer )
+ {
+ if ( pTFPlayer->IsAlive() && me->GetTeamNumber() != TF_TEAM_HALLOWEEN && me->GetTeamNumber() != pTFPlayer->GetTeamNumber() )
+ {
+ // force attack the thing we bumped into
+ // this prevents us from being stuck on dispensers, for example
+ m_attackTarget = pTFPlayer;
+ m_attackTargetFocusTimer.Start( ZOMBIE_CHASE_MIN_DURATION );
+ }
+ }
+ }
+
+ return TryContinue( RESULT_TRY );
+}
+
+
+//---------------------------------------------------------------------------------------------
+EventDesiredResult< CZombie > CZombieAttack::OnOtherKilled( CZombie *me, CBaseCombatCharacter *victim, const CTakeDamageInfo &info )
+{
+ /*if ( victim && victim->IsPlayer() && me->GetLocomotionInterface()->IsOnGround() )
+ {
+ me->AddGestureSequence( me->LookupSequence( "taunt06" ) );
+ m_tauntTimer.Start( 3.0f );
+ }*/
+
+ return TryContinue( RESULT_TRY );
+}
diff --git a/game/server/tf/halloween/zombie/zombie_behavior/zombie_attack.h b/game/server/tf/halloween/zombie/zombie_behavior/zombie_attack.h
new file mode 100644
index 0000000..476ffc0
--- /dev/null
+++ b/game/server/tf/halloween/zombie/zombie_behavior/zombie_attack.h
@@ -0,0 +1,36 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+//
+//
+//=============================================================================
+#ifndef ZOMBIE_ATTACK_H
+#define ZOMBIE_ATTACK_H
+
+//---------------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+class CZombieAttack : public Action< CZombie >
+{
+public:
+ virtual ActionResult< CZombie > OnStart( CZombie *me, Action< CZombie > *priorAction );
+ virtual ActionResult< CZombie > Update( CZombie *me, float interval );
+
+ virtual EventDesiredResult< CZombie > OnStuck( CZombie *me );
+ virtual EventDesiredResult< CZombie > OnContact( CZombie *me, CBaseEntity *other, CGameTrace *result = NULL );
+ virtual EventDesiredResult< CZombie > OnOtherKilled( CZombie *me, CBaseCombatCharacter *victim, const CTakeDamageInfo &info );
+
+ virtual const char *GetName( void ) const { return "Attack"; } // return name of this action
+
+private:
+ PathFollower m_path;
+
+ CHandle< CBaseCombatCharacter > m_attackTarget;
+ CountdownTimer m_attackTimer;
+ CountdownTimer m_specialAttackTimer;
+ CountdownTimer m_attackTargetFocusTimer;
+ CountdownTimer m_tauntTimer;
+
+ bool IsPotentiallyChaseable( CZombie *me, CBaseCombatCharacter *victim );
+ void SelectVictim( CZombie *me );
+};
+
+#endif // ZOMBIE_ATTACK_H
diff --git a/game/server/tf/halloween/zombie/zombie_behavior/zombie_spawn.cpp b/game/server/tf/halloween/zombie/zombie_behavior/zombie_spawn.cpp
new file mode 100644
index 0000000..87d8e43
--- /dev/null
+++ b/game/server/tf/halloween/zombie/zombie_behavior/zombie_spawn.cpp
@@ -0,0 +1,29 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+//
+//
+//=============================================================================
+#include "cbase.h"
+
+#include "tf_shareddefs.h"
+#include "../zombie.h"
+#include "zombie_attack.h"
+#include "zombie_spawn.h"
+
+ActionResult< CZombie > CZombieSpawn::OnStart( CZombie *me, Action< CZombie > *priorAction )
+{
+ me->GetBodyInterface()->StartActivity( ACT_TRANSITION );
+
+ return Continue();
+}
+
+
+ActionResult< CZombie > CZombieSpawn::Update( CZombie *me, float interval )
+{
+ if ( me->IsActivityFinished() )
+ {
+ return ChangeTo( new CZombieAttack, "Start Attack!" );
+ }
+
+ return Continue();
+} \ No newline at end of file
diff --git a/game/server/tf/halloween/zombie/zombie_behavior/zombie_spawn.h b/game/server/tf/halloween/zombie/zombie_behavior/zombie_spawn.h
new file mode 100644
index 0000000..863fee6
--- /dev/null
+++ b/game/server/tf/halloween/zombie/zombie_behavior/zombie_spawn.h
@@ -0,0 +1,22 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+//
+//
+//=============================================================================
+#ifndef ZOMBIE_SPAWN_H
+#define ZOMBIE_SPAWN_H
+
+//---------------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+class CZombieSpawn : public Action< CZombie >
+{
+public:
+ virtual ActionResult< CZombie > OnStart( CZombie *me, Action< CZombie > *priorAction );
+ virtual ActionResult< CZombie > Update( CZombie *me, float interval );
+
+ virtual const char *GetName( void ) const { return "Spawn"; } // return name of this action
+
+private:
+};
+
+#endif // ZOMBIE_SPAWN_H
diff --git a/game/server/tf/halloween/zombie/zombie_behavior/zombie_special_attack.cpp b/game/server/tf/halloween/zombie/zombie_behavior/zombie_special_attack.cpp
new file mode 100644
index 0000000..ee2ca3c
--- /dev/null
+++ b/game/server/tf/halloween/zombie/zombie_behavior/zombie_special_attack.cpp
@@ -0,0 +1,68 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+//
+//
+//=============================================================================
+#include "cbase.h"
+
+#include "tf_player.h"
+#include "tf_gamerules.h"
+#include "tf_fx.h"
+
+#include "../zombie.h"
+#include "zombie_special_attack.h"
+
+ActionResult< CZombie > CZombieSpecialAttack::OnStart( CZombie *me, Action< CZombie > *priorAction )
+{
+ me->GetBodyInterface()->StartActivity( ACT_SPECIAL_ATTACK1 );
+
+ m_stompTimer.Start( 1 );
+
+ return Continue();
+}
+
+
+ActionResult< CZombie > CZombieSpecialAttack::Update( CZombie *me, float interval )
+{
+ if ( m_stompTimer.HasStarted() && m_stompTimer.IsElapsed() )
+ {
+ DoSpecialAttack( me );
+ m_stompTimer.Invalidate();
+ }
+
+ if ( me->IsActivityFinished() )
+ {
+ return Done();
+ }
+
+ return Continue();
+}
+
+
+void CZombieSpecialAttack::DoSpecialAttack( CZombie *me )
+{
+ CPVSFilter filter( me->GetAbsOrigin() );
+ TE_TFParticleEffect( filter, 0.0, "bomibomicon_ring", me->GetAbsOrigin(), vec3_angle );
+
+ int nTargetTeam = TEAM_ANY;
+ if ( me->GetTeamNumber() != TF_TEAM_HALLOWEEN )
+ {
+ nTargetTeam = me->GetTeamNumber() == TF_TEAM_RED ? TF_TEAM_BLUE : TF_TEAM_RED;
+ }
+
+ CUtlVector< CTFPlayer* > pushedPlayers;
+ TFGameRules()->PushAllPlayersAway( me->GetAbsOrigin(), 200.f, 500.f, nTargetTeam, &pushedPlayers );
+
+ CBaseEntity *pAttacker = me->GetOwnerEntity() ? me->GetOwnerEntity() : me;
+ for ( int i=0; i<pushedPlayers.Count(); ++i )
+ {
+ Vector toVictim = pushedPlayers[i]->WorldSpaceCenter() - me->WorldSpaceCenter();
+ toVictim.NormalizeInPlace();
+
+ // hit!
+ CTakeDamageInfo info( pAttacker, pAttacker, me->GetAttackDamage(), DMG_SLASH );
+ info.SetDamageCustom( TF_DMG_CUSTOM_SPELL_SKELETON );
+ CalculateMeleeDamageForce( &info, toVictim, me->WorldSpaceCenter(), 5.0f );
+ pushedPlayers[i]->TakeDamage( info );
+ }
+}
diff --git a/game/server/tf/halloween/zombie/zombie_behavior/zombie_special_attack.h b/game/server/tf/halloween/zombie/zombie_behavior/zombie_special_attack.h
new file mode 100644
index 0000000..b8689fb
--- /dev/null
+++ b/game/server/tf/halloween/zombie/zombie_behavior/zombie_special_attack.h
@@ -0,0 +1,25 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+//
+//
+//=============================================================================
+#ifndef ZOMBIE_SPECIAL_ATTACK_H
+#define ZOMBIE_SPECIAL_ATTACK_H
+
+//---------------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------------
+class CZombieSpecialAttack : public Action< CZombie >
+{
+public:
+ virtual ActionResult< CZombie > OnStart( CZombie *me, Action< CZombie > *priorAction );
+ virtual ActionResult< CZombie > Update( CZombie *me, float interval );
+
+ virtual const char *GetName( void ) const { return "Special Attack"; } // return name of this action
+private:
+
+ void DoSpecialAttack( CZombie *me );
+
+ CountdownTimer m_stompTimer;
+};
+
+#endif // ZOMBIE_SPECIAL_ATTACK_H