From 39ed87570bdb2f86969d4be821c94b722dc71179 Mon Sep 17 00:00:00 2001 From: Joe Ludwig Date: Wed, 26 Jun 2013 15:22:04 -0700 Subject: First version of the SOurce SDK 2013 --- mp/src/game/server/genericmonster.cpp | 472 ++++++++++++++++++++++++++++++++++ 1 file changed, 472 insertions(+) create mode 100644 mp/src/game/server/genericmonster.cpp (limited to 'mp/src/game/server/genericmonster.cpp') diff --git a/mp/src/game/server/genericmonster.cpp b/mp/src/game/server/genericmonster.cpp new file mode 100644 index 00000000..44c25de5 --- /dev/null +++ b/mp/src/game/server/genericmonster.cpp @@ -0,0 +1,472 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +//========================================================= +// Generic NPC - purely for scripted sequence work. +//========================================================= +#include "cbase.h" +#include "npcevent.h" +#include "ai_basenpc.h" +#include "ai_hull.h" +#include "KeyValues.h" +#include "engine/IEngineSound.h" +#include "physics_bone_follower.h" +#include "ai_baseactor.h" +#include "ai_senses.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// For holograms, make them not solid so the player can walk through them +#define SF_GENERICNPC_NOTSOLID (1 << 16) + +//========================================================= +// NPC's Anim Events Go Here +//========================================================= + +class CGenericNPC : public CAI_BaseNPC +{ +public: + DECLARE_CLASS( CGenericNPC, CAI_BaseNPC ); + + void Spawn( void ); + void Precache( void ); + float MaxYawSpeed( void ); + Class_T Classify ( void ); + void HandleAnimEvent( animevent_t *pEvent ); + int GetSoundInterests ( void ); + + void TempGunEffect( void ); +}; + +LINK_ENTITY_TO_CLASS( monster_generic, CGenericNPC ); + +//========================================================= +// Classify - indicates this NPC's place in the +// relationship table. +//========================================================= +Class_T CGenericNPC::Classify ( void ) +{ + return CLASS_NONE; +} + + +//========================================================= +// MaxYawSpeed - allows each sequence to have a different +// turn rate associated with it. +//========================================================= +float CGenericNPC::MaxYawSpeed ( void ) +{ + return 90; +} + +//--------------------------------------------------------- +// !!!TEMP +// !!!TEMP +// !!!TEMP +// !!!TEMP +// +// (sjb) +//--------------------------------------------------------- +void CGenericNPC::TempGunEffect( void ) +{ + QAngle vecAngle; + Vector vecDir, vecShot; + Vector vecMuzzle, vecButt; + + GetAttachment( 2, vecMuzzle, vecAngle ); + GetAttachment( 3, vecButt, vecAngle ); + + vecDir = vecMuzzle - vecButt; + VectorNormalize( vecDir ); + + // CPVSFilter filter( GetAbsOrigin() ); + //te->ShowLine( filter, 0.0, vecSpot, vecSpot + vecForward ); + //UTIL_Sparks( vecMuzzle ); + + bool fSound = false; + + if( random->RandomInt( 0, 3 ) == 0 ) + { + fSound = true; + } + + Vector start = vecMuzzle + vecDir * 64; + Vector end = vecMuzzle + vecDir * 4096; + UTIL_Tracer( start, end, 0, TRACER_DONT_USE_ATTACHMENT, 5500, fSound ); + CPASAttenuationFilter filter2( this, "GenericNPC.GunSound" ); + EmitSound( filter2, entindex(), "GenericNPC.GunSound" ); +} + + +//========================================================= +// HandleAnimEvent - catches the NPC-specific messages +// that occur when tagged animation frames are played. +//========================================================= +void CGenericNPC::HandleAnimEvent( animevent_t *pEvent ) +{ + switch( pEvent->event ) + { + case 1: + // TEMPORARLY. Makes the May 2001 sniper demo work (sjb) + TempGunEffect(); + break; + + default: + BaseClass::HandleAnimEvent( pEvent ); + break; + } +} + +//========================================================= +// GetSoundInterests - generic NPC can't hear. +//========================================================= +int CGenericNPC::GetSoundInterests ( void ) +{ + return NULL; +} + +//========================================================= +// Spawn +//========================================================= +void CGenericNPC::Spawn() +{ + Precache(); + + SetModel( STRING( GetModelName() ) ); + +/* + if ( FStrEq( STRING( GetModelName() ), "models/player.mdl" ) ) + UTIL_SetSize(this, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX); + else + UTIL_SetSize(this, VEC_HULL_MIN, VEC_HULL_MAX); +*/ + + if ( FStrEq( STRING( GetModelName() ), "models/player.mdl" ) || FStrEq( STRING( GetModelName() ), "models/holo.mdl" ) ) + UTIL_SetSize(this, VEC_HULL_MIN, VEC_HULL_MAX); + else + UTIL_SetSize(this, NAI_Hull::Mins(HULL_HUMAN), NAI_Hull::Maxs(HULL_HUMAN)); + + SetSolid( SOLID_BBOX ); + AddSolidFlags( FSOLID_NOT_STANDABLE ); + SetMoveType( MOVETYPE_STEP ); + m_bloodColor = BLOOD_COLOR_RED; + m_iHealth = 8; + m_flFieldOfView = 0.5;// indicates the width of this NPC's forward view cone ( as a dotproduct result ) + m_NPCState = NPC_STATE_NONE; + + CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_OPEN_DOORS ); + + NPCInit(); + if ( !HasSpawnFlags(SF_GENERICNPC_NOTSOLID) ) + { + trace_t tr; + UTIL_TraceEntity( this, GetAbsOrigin(), GetAbsOrigin(), MASK_SOLID, &tr ); + if ( tr.startsolid ) + { + Msg("Placed npc_generic in solid!!! (%s)\n", STRING(GetModelName()) ); + m_spawnflags |= SF_GENERICNPC_NOTSOLID; + } + } + + if ( HasSpawnFlags(SF_GENERICNPC_NOTSOLID) ) + { + AddSolidFlags( FSOLID_NOT_SOLID ); + m_takedamage = DAMAGE_NO; + VPhysicsDestroyObject(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: precaches all resources this NPC needs +//----------------------------------------------------------------------------- +void CGenericNPC::Precache() +{ + BaseClass::Precache(); + + PrecacheModel( STRING( GetModelName() ) ); + + PrecacheScriptSound( "GenericNPC.GunSound" ); +} + +// a really large health is set to make sure these never die. +const int TOO_MUCH_HEALTH_TO_DIE = 1000; +//======================================================================================= +// Furniture: A dumb "NPC" that is uses in scripted sequences +// where an NPC needs to be frame locked with a prop. +//======================================================================================= +class CNPC_Furniture : public CAI_BaseActor +{ + DECLARE_CLASS( CNPC_Furniture, CAI_BaseActor ); + DECLARE_DATADESC(); +public: + void Spawn( void ); + void Precache( void ); + void Die( void ); + void UpdateEfficiency( bool bInPVS ) { SetEfficiency( ( GetSleepState() != AISS_AWAKE ) ? AIE_DORMANT : AIE_NORMAL ); SetMoveEfficiency( AIME_NORMAL ); } + Class_T Classify ( void ); + float MaxYawSpeed( void ){ return 0; } + virtual int ObjectCaps( void ); + bool CreateVPhysics( void ); + void NPCThink( void ); + void UpdateOnRemove( void ); + int SelectSchedule( void ); + void OnRestore( void ); + int OnTakeDamage( const CTakeDamageInfo &info ) + { + if ( m_iHealth <= info.GetDamage() ) + m_iHealth = info.GetDamage() + TOO_MUCH_HEALTH_TO_DIE; + return BaseClass::OnTakeDamage(info); + } + + void DrawDebugGeometryOverlays(void); + + void SetPlayerAvoidState( void ); + void InputDisablePlayerCollision( inputdata_t &inputdata ); + void InputEnablePlayerCollision( inputdata_t &inputdata ); + void UpdateBoneFollowerState( void ); + +private: + // Contained Bone Follower manager + CBoneFollowerManager m_BoneFollowerManager; +}; + +LINK_ENTITY_TO_CLASS( monster_furniture, CNPC_Furniture ); +LINK_ENTITY_TO_CLASS( npc_furniture, CNPC_Furniture ); + +//----------------------------------------------------------------------------- +// Save/load +//----------------------------------------------------------------------------- + +BEGIN_DATADESC( CNPC_Furniture ) + DEFINE_EMBEDDED( m_BoneFollowerManager ), + DEFINE_INPUTFUNC( FIELD_VOID, "DisablePlayerCollision", InputDisablePlayerCollision ), + DEFINE_INPUTFUNC( FIELD_VOID, "EnablePlayerCollision", InputEnablePlayerCollision ), + +END_DATADESC() + +//----------------------------------------------------------------------------- +// Purpose: This used to have something to do with bees flying, but +// now it only initializes moving furniture in scripted sequences +//----------------------------------------------------------------------------- +void CNPC_Furniture::Spawn( ) +{ + Precache(); + + SetModel( STRING(GetModelName()) ); + + SetMoveType( MOVETYPE_STEP ); + SetSolid( SOLID_BBOX ); + + // Our collision, if needed, will be done through bone followers + AddSolidFlags( FSOLID_NOT_SOLID ); + + SetBloodColor( DONT_BLEED ); + m_iHealth = TOO_MUCH_HEALTH_TO_DIE; //wow + m_takedamage = DAMAGE_AIM; + SetSequence( 0 ); + SetCycle( 0 ); + SetNavType( NAV_FLY ); + AddFlag( FL_FLY ); + + CapabilitiesAdd( bits_CAP_MOVE_FLY | bits_CAP_TURN_HEAD | bits_CAP_ANIMATEDFACE ); + + AddEFlags( EFL_NO_MEGAPHYSCANNON_RAGDOLL ); + +// pev->nextthink += 1.0; +// SetThink (WalkMonsterDelay); + + ResetSequenceInfo( ); + SetCycle( 0 ); + NPCInit(); + + // Furniture needs to block LOS + SetBlocksLOS( true ); + + // Furniture just wastes CPU doing sensing code, since all they do is idle and play scripts + GetSenses()->AddSensingFlags( SENSING_FLAGS_DONT_LOOK | SENSING_FLAGS_DONT_LISTEN ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CNPC_Furniture::Precache( void ) +{ + PrecacheModel( STRING( GetModelName() ) ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CNPC_Furniture::ObjectCaps( void ) +{ + // HL2 furniture transitions +#ifdef HL2_DLL + return CAI_BaseNPC::ObjectCaps(); +#else + return (CAI_BaseNPC::ObjectCaps() & ~FCAP_ACROSS_TRANSITION); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Furniture is killed +//----------------------------------------------------------------------------- +void CNPC_Furniture::Die( void ) +{ + SetThink ( &CNPC_Furniture::SUB_Remove ); + SetNextThink( gpGlobals->curtime ); +} + +//----------------------------------------------------------------------------- +// Purpose: ID's Furniture as neutral (noone will attack it) +//----------------------------------------------------------------------------- +Class_T CNPC_Furniture::Classify ( void ) +{ + return CLASS_NONE; +} + +//------------------------------------------------------------------------------ +// Purpose: +//------------------------------------------------------------------------------ +bool CNPC_Furniture::CreateVPhysics( void ) +{ +#ifndef HL2_DLL + return false; +#endif + + if ( !m_BoneFollowerManager.GetNumBoneFollowers() ) + { + KeyValues *modelKeyValues = new KeyValues(""); + if ( modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), modelinfo->GetModelKeyValueText( GetModel() ) ) ) + { + // Do we have a bone follower section? + KeyValues *pkvBoneFollowers = modelKeyValues->FindKey("bone_followers"); + if ( pkvBoneFollowers ) + { + // Loop through the list and create the bone followers + KeyValues *pBone = pkvBoneFollowers->GetFirstSubKey(); + while ( pBone ) + { + // Add it to the list + const char *pBoneName = pBone->GetString(); + m_BoneFollowerManager.AddBoneFollower( this, pBoneName ); + + pBone = pBone->GetNextKey(); + } + } + } + modelKeyValues->deleteThis(); + } + + return true; +} + +void CNPC_Furniture::InputDisablePlayerCollision( inputdata_t &inputdata ) +{ + SetCollisionGroup( COLLISION_GROUP_NPC_ACTOR ); + UpdateBoneFollowerState(); +} + +void CNPC_Furniture::InputEnablePlayerCollision( inputdata_t &inputdata ) +{ + SetCollisionGroup( COLLISION_GROUP_NPC ); + UpdateBoneFollowerState(); +} + +void CNPC_Furniture::UpdateBoneFollowerState( void ) +{ + if ( m_BoneFollowerManager.GetNumBoneFollowers() ) + { + physfollower_t* pBone = m_BoneFollowerManager.GetBoneFollower( 0 ); + + if ( pBone && pBone->hFollower && pBone->hFollower->GetCollisionGroup() != GetCollisionGroup() ) + { + for ( int i = 0; i < m_BoneFollowerManager.GetNumBoneFollowers(); i++ ) + { + pBone = m_BoneFollowerManager.GetBoneFollower( i ); + + if ( pBone && pBone->hFollower ) + { + pBone->hFollower->SetCollisionGroup( GetCollisionGroup() ); + } + } + } + } +} + +void CNPC_Furniture::SetPlayerAvoidState( void ) +{ + +} +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CNPC_Furniture::NPCThink( void ) +{ + BaseClass::NPCThink(); + + // Update follower bones + m_BoneFollowerManager.UpdateBoneFollowers(this); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CNPC_Furniture::UpdateOnRemove( void ) +{ + m_BoneFollowerManager.DestroyBoneFollowers(); + + BaseClass::UpdateOnRemove(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : int +//----------------------------------------------------------------------------- +int CNPC_Furniture::SelectSchedule( void ) +{ + switch( m_NPCState ) + { + case NPC_STATE_NONE: + case NPC_STATE_PRONE: + case NPC_STATE_IDLE: + case NPC_STATE_ALERT: + case NPC_STATE_COMBAT: + case NPC_STATE_DEAD: + return SCHED_WAIT_FOR_SCRIPT; + + case NPC_STATE_SCRIPT: + return BaseClass::SelectSchedule(); + + default: + DevWarning( 2, "Invalid State for SelectSchedule!\n" ); + break; + } + + return SCHED_FAIL; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CNPC_Furniture::OnRestore( void ) +{ + // Recreate any bone followers we have + CreateVPhysics(); + + BaseClass::OnRestore(); +} +void CNPC_Furniture::DrawDebugGeometryOverlays( void ) +{ + //ugh + if ( m_debugOverlays & OVERLAY_NPC_ZAP_BIT ) + { + m_debugOverlays &= ~OVERLAY_NPC_ZAP_BIT; + } + + BaseClass::DrawDebugGeometryOverlays(); +} -- cgit v1.2.3