diff options
Diffstat (limited to 'game/server/hl1/hl1_npc_zombie.cpp')
| -rw-r--r-- | game/server/hl1/hl1_npc_zombie.cpp | 307 |
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(); +} |