summaryrefslogtreecommitdiff
path: root/game/server/hl1/hl1_npc_zombie.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/server/hl1/hl1_npc_zombie.cpp')
-rw-r--r--game/server/hl1/hl1_npc_zombie.cpp307
1 files changed, 307 insertions, 0 deletions
diff --git a/game/server/hl1/hl1_npc_zombie.cpp b/game/server/hl1/hl1_npc_zombie.cpp
new file mode 100644
index 0000000..12874bb
--- /dev/null
+++ b/game/server/hl1/hl1_npc_zombie.cpp
@@ -0,0 +1,307 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: A slow-moving, once-human headcrab victim with only melee attacks.
+//
+// UNDONE: Make head take 100% damage, body take 30% damage.
+// UNDONE: Don't flinch every time you get hit.
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "game.h"
+#include "ai_default.h"
+#include "ai_schedule.h"
+#include "ai_hull.h"
+#include "ai_route.h"
+#include "npcevent.h"
+#include "hl1_npc_zombie.h"
+#include "gib.h"
+//#include "AI_Interactions.h"
+#include "ndebugoverlay.h"
+#include "vstdlib/random.h"
+#include "engine/IEngineSound.h"
+
+ConVar sk_zombie_health( "sk_zombie_health","50");
+ConVar sk_zombie_dmg_one_slash( "sk_zombie_dmg_one_slash", "20" );
+ConVar sk_zombie_dmg_both_slash( "sk_zombie_dmg_both_slash", "40" );
+
+
+
+LINK_ENTITY_TO_CLASS( monster_zombie, CNPC_Zombie );
+
+
+//=========================================================
+// Spawn
+//=========================================================
+void CNPC_Zombie::Spawn()
+{
+ Precache( );
+
+ SetModel( "models/zombie.mdl" );
+
+ SetRenderColor( 255, 255, 255, 255 );
+
+ SetHullType(HULL_HUMAN);
+ SetHullSizeNormal();
+
+ SetSolid( SOLID_BBOX );
+ AddSolidFlags( FSOLID_NOT_STANDABLE );
+ SetMoveType( MOVETYPE_STEP );
+ m_bloodColor = BLOOD_COLOR_GREEN;
+ m_iHealth = sk_zombie_health.GetFloat();
+ //pev->view_ofs = VEC_VIEW;// position of the eyes relative to monster's origin.
+ m_flFieldOfView = 0.5;
+ m_NPCState = NPC_STATE_NONE;
+ CapabilitiesClear();
+ CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_INNATE_MELEE_ATTACK1 | bits_CAP_DOORS_GROUP );
+
+ NPCInit();
+}
+
+//=========================================================
+// Precache - precaches all resources this monster needs
+//=========================================================
+void CNPC_Zombie::Precache()
+{
+ PrecacheModel( "models/zombie.mdl" );
+
+ PrecacheScriptSound( "Zombie.AttackHit" );
+ PrecacheScriptSound( "Zombie.AttackMiss" );
+ PrecacheScriptSound( "Zombie.Pain" );
+ PrecacheScriptSound( "Zombie.Idle" );
+ PrecacheScriptSound( "Zombie.Alert" );
+ PrecacheScriptSound( "Zombie.Attack" );
+
+ BaseClass::Precache();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns this monster's place in the relationship table.
+//-----------------------------------------------------------------------------
+Class_T CNPC_Zombie::Classify( void )
+{
+ return CLASS_ALIEN_MONSTER;
+}
+
+//=========================================================
+// HandleAnimEvent - catches the monster-specific messages
+// that occur when tagged animation frames are played.
+//=========================================================
+void CNPC_Zombie::HandleAnimEvent( animevent_t *pEvent )
+{
+ Vector v_forward, v_right;
+ switch( pEvent->event )
+ {
+ case ZOMBIE_AE_ATTACK_RIGHT:
+ {
+ // do stuff for this event.
+ // ALERT( at_console, "Slash right!\n" );
+
+ Vector vecMins = GetHullMins();
+ Vector vecMaxs = GetHullMaxs();
+ vecMins.z = vecMins.x;
+ vecMaxs.z = vecMaxs.x;
+
+ CBaseEntity *pHurt = CheckTraceHullAttack( 70, vecMins, vecMaxs, sk_zombie_dmg_one_slash.GetFloat(), DMG_SLASH );
+ CPASAttenuationFilter filter( this );
+ if ( pHurt )
+ {
+ if ( pHurt->GetFlags() & ( FL_NPC | FL_CLIENT ) )
+ {
+ pHurt->ViewPunch( QAngle( 5, 0, 18 ) );
+
+ GetVectors( &v_forward, &v_right, NULL );
+
+ pHurt->SetAbsVelocity( pHurt->GetAbsVelocity() - v_right * 100 );
+ }
+ // Play a random attack hit sound
+ EmitSound( filter, entindex(), "Zombie.AttackHit" );
+ }
+ else // Play a random attack miss sound
+ EmitSound( filter, entindex(), "Zombie.AttackMiss" );
+
+ if ( random->RandomInt( 0, 1 ) )
+ AttackSound();
+ }
+ break;
+
+ case ZOMBIE_AE_ATTACK_LEFT:
+ {
+ // do stuff for this event.
+ // ALERT( at_console, "Slash left!\n" );
+ Vector vecMins = GetHullMins();
+ Vector vecMaxs = GetHullMaxs();
+ vecMins.z = vecMins.x;
+ vecMaxs.z = vecMaxs.x;
+
+ CBaseEntity *pHurt = CheckTraceHullAttack( 70, vecMins, vecMaxs, sk_zombie_dmg_one_slash.GetFloat(), DMG_SLASH );
+
+ CPASAttenuationFilter filter2( this );
+ if ( pHurt )
+ {
+ if ( pHurt->GetFlags() & ( FL_NPC | FL_CLIENT ) )
+ {
+ pHurt->ViewPunch( QAngle ( 5, 0, -18 ) );
+
+ GetVectors( &v_forward, &v_right, NULL );
+
+ pHurt->SetAbsVelocity( pHurt->GetAbsVelocity() - v_right * 100 );
+ }
+ EmitSound( filter2, entindex(), "Zombie.AttackHit" );
+ }
+ else
+ {
+ EmitSound( filter2, entindex(), "Zombie.AttackMiss" );
+ }
+
+ if ( random->RandomInt( 0,1 ) )
+ AttackSound();
+ }
+ break;
+
+ case ZOMBIE_AE_ATTACK_BOTH:
+ {
+ // do stuff for this event.
+ Vector vecMins = GetHullMins();
+ Vector vecMaxs = GetHullMaxs();
+ vecMins.z = vecMins.x;
+ vecMaxs.z = vecMaxs.x;
+
+ CBaseEntity *pHurt = CheckTraceHullAttack( 70, vecMins, vecMaxs, sk_zombie_dmg_both_slash.GetFloat(), DMG_SLASH );
+
+
+ CPASAttenuationFilter filter3( this );
+ if ( pHurt )
+ {
+ if ( pHurt->GetFlags() & ( FL_NPC | FL_CLIENT ) )
+ {
+ pHurt->ViewPunch( QAngle ( 5, 0, 0 ) );
+
+ GetVectors( &v_forward, &v_right, NULL );
+ pHurt->SetAbsVelocity( pHurt->GetAbsVelocity() - v_right * 100 );
+ }
+ EmitSound( filter3, entindex(), "Zombie.AttackHit" );
+ }
+ else
+ EmitSound( filter3, entindex(),"Zombie.AttackMiss" );
+
+ if ( random->RandomInt( 0,1 ) )
+ AttackSound();
+ }
+ break;
+
+ default:
+ BaseClass::HandleAnimEvent( pEvent );
+ break;
+ }
+}
+
+
+static float DamageForce( const Vector &size, float damage )
+{
+ float force = damage * ((32 * 32 * 72.0) / (size.x * size.y * size.z)) * 5;
+
+ if ( force > 1000.0)
+ {
+ force = 1000.0;
+ }
+
+ return force;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : pInflictor -
+// pAttacker -
+// flDamage -
+// bitsDamageType -
+// Output : int
+//-----------------------------------------------------------------------------
+int CNPC_Zombie::OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo )
+{
+ CTakeDamageInfo info = inputInfo;
+
+ // Take 30% damage from bullets
+ if ( info.GetDamageType() == DMG_BULLET )
+ {
+ Vector vecDir = GetAbsOrigin() - info.GetInflictor()->WorldSpaceCenter();
+ VectorNormalize( vecDir );
+ float flForce = DamageForce( WorldAlignSize(), info.GetDamage() );
+ SetAbsVelocity( GetAbsVelocity() + vecDir * flForce );
+ info.ScaleDamage( 0.3f );
+ }
+
+ // HACK HACK -- until we fix this.
+ if ( IsAlive() )
+ PainSound( info );
+
+ return BaseClass::OnTakeDamage_Alive( info );
+}
+
+void CNPC_Zombie::PainSound( const CTakeDamageInfo &info )
+{
+ if ( random->RandomInt(0,5) < 2)
+ {
+ CPASAttenuationFilter filter( this );
+ EmitSound( filter, entindex(), "Zombie.Pain" );
+ }
+}
+
+void CNPC_Zombie::AlertSound( void )
+{
+ CPASAttenuationFilter filter( this );
+ EmitSound( filter, entindex(), "Zombie.Alert" );
+}
+
+void CNPC_Zombie::IdleSound( void )
+{
+ // Play a random idle sound
+ CPASAttenuationFilter filter( this );
+ EmitSound( filter, entindex(), "Zombie.Idle" );
+}
+
+void CNPC_Zombie::AttackSound( void )
+{
+ // Play a random attack sound
+ CPASAttenuationFilter filter( this );
+ EmitSound( filter, entindex(), "Zombie.Attack" );
+}
+
+int CNPC_Zombie::MeleeAttack1Conditions ( float flDot, float flDist )
+{
+ if ( flDist > 64)
+ {
+ return COND_TOO_FAR_TO_ATTACK;
+ }
+ else if (flDot < 0.7)
+ {
+ return 0;
+ }
+ else if (GetEnemy() == NULL)
+ {
+ return 0;
+ }
+
+ return COND_CAN_MELEE_ATTACK1;
+}
+
+void CNPC_Zombie::RemoveIgnoredConditions ( void )
+{
+ if ( GetActivity() == ACT_MELEE_ATTACK1 )
+ {
+ // Nothing stops an attacking zombie.
+ ClearCondition( COND_LIGHT_DAMAGE );
+ ClearCondition( COND_HEAVY_DAMAGE );
+ }
+
+ if (( GetActivity() == ACT_SMALL_FLINCH ) || ( GetActivity() == ACT_BIG_FLINCH ))
+ {
+ if (m_flNextFlinch < gpGlobals->curtime)
+ m_flNextFlinch = gpGlobals->curtime + ZOMBIE_FLINCH_DELAY;
+ }
+
+ BaseClass::RemoveIgnoredConditions();
+}