diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/server/genericmonster.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/server/genericmonster.cpp')
| -rw-r--r-- | mp/src/game/server/genericmonster.cpp | 944 |
1 files changed, 472 insertions, 472 deletions
diff --git a/mp/src/game/server/genericmonster.cpp b/mp/src/game/server/genericmonster.cpp index 44c25de5..ed1be819 100644 --- a/mp/src/game/server/genericmonster.cpp +++ b/mp/src/game/server/genericmonster.cpp @@ -1,472 +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();
-}
+//========= 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(); +} |