You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
6.9 KiB
250 lines
6.9 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "ai_default.h" |
|
#include "ai_task.h" |
|
#include "ai_schedule.h" |
|
#include "ai_node.h" |
|
#include "ai_hull.h" |
|
#include "ai_hint.h" |
|
#include "ai_squad.h" |
|
#include "ai_senses.h" |
|
#include "ai_navigator.h" |
|
#include "ai_motor.h" |
|
#include "ai_behavior.h" |
|
#include "ai_baseactor.h" |
|
#include "ai_behavior_lead.h" |
|
#include "ai_behavior_follow.h" |
|
#include "ai_behavior_standoff.h" |
|
#include "ai_behavior_assault.h" |
|
#include "npc_playercompanion.h" |
|
#include "soundent.h" |
|
#include "game.h" |
|
#include "npcevent.h" |
|
#include "activitylist.h" |
|
#include "vstdlib/random.h" |
|
#include "engine/IEngineSound.h" |
|
#include "sceneentity.h" |
|
#include "ai_behavior_functank.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
#define BARNEY_MODEL "models/barney.mdl" |
|
|
|
ConVar sk_barney_health( "sk_barney_health","0"); |
|
|
|
//========================================================= |
|
// Barney activities |
|
//========================================================= |
|
|
|
class CNPC_Barney : public CNPC_PlayerCompanion |
|
{ |
|
public: |
|
DECLARE_CLASS( CNPC_Barney, CNPC_PlayerCompanion ); |
|
DECLARE_SERVERCLASS(); |
|
DECLARE_DATADESC(); |
|
|
|
virtual void Precache() |
|
{ |
|
// Prevents a warning |
|
SelectModel( ); |
|
BaseClass::Precache(); |
|
|
|
PrecacheScriptSound( "NPC_Barney.FootstepLeft" ); |
|
PrecacheScriptSound( "NPC_Barney.FootstepRight" ); |
|
PrecacheScriptSound( "NPC_Barney.Die" ); |
|
|
|
PrecacheInstancedScene( "scenes/Expressions/BarneyIdle.vcd" ); |
|
PrecacheInstancedScene( "scenes/Expressions/BarneyAlert.vcd" ); |
|
PrecacheInstancedScene( "scenes/Expressions/BarneyCombat.vcd" ); |
|
} |
|
|
|
void Spawn( void ); |
|
void SelectModel(); |
|
Class_T Classify( void ); |
|
void Weapon_Equip( CBaseCombatWeapon *pWeapon ); |
|
|
|
bool CreateBehaviors( void ); |
|
|
|
void HandleAnimEvent( animevent_t *pEvent ); |
|
|
|
bool ShouldLookForBetterWeapon() { return false; } |
|
|
|
void OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior ); |
|
|
|
void DeathSound( const CTakeDamageInfo &info ); |
|
void GatherConditions(); |
|
void UseFunc( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); |
|
|
|
CAI_FuncTankBehavior m_FuncTankBehavior; |
|
COutputEvent m_OnPlayerUse; |
|
|
|
DEFINE_CUSTOM_AI; |
|
}; |
|
|
|
|
|
LINK_ENTITY_TO_CLASS( npc_barney, CNPC_Barney ); |
|
|
|
//--------------------------------------------------------- |
|
// |
|
//--------------------------------------------------------- |
|
IMPLEMENT_SERVERCLASS_ST(CNPC_Barney, DT_NPC_Barney) |
|
END_SEND_TABLE() |
|
|
|
|
|
//--------------------------------------------------------- |
|
// Save/Restore |
|
//--------------------------------------------------------- |
|
BEGIN_DATADESC( CNPC_Barney ) |
|
// m_FuncTankBehavior |
|
DEFINE_OUTPUT( m_OnPlayerUse, "OnPlayerUse" ), |
|
DEFINE_USEFUNC( UseFunc ), |
|
END_DATADESC() |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CNPC_Barney::SelectModel() |
|
{ |
|
SetModelName( AllocPooledString( BARNEY_MODEL ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CNPC_Barney::Spawn( void ) |
|
{ |
|
Precache(); |
|
|
|
m_iHealth = 80; |
|
|
|
m_iszIdleExpression = MAKE_STRING("scenes/Expressions/BarneyIdle.vcd"); |
|
m_iszAlertExpression = MAKE_STRING("scenes/Expressions/BarneyAlert.vcd"); |
|
m_iszCombatExpression = MAKE_STRING("scenes/Expressions/BarneyCombat.vcd"); |
|
|
|
BaseClass::Spawn(); |
|
|
|
AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL | EFL_NO_PHYSCANNON_INTERACTION ); |
|
|
|
NPCInit(); |
|
|
|
SetUse( &CNPC_Barney::UseFunc ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : |
|
//----------------------------------------------------------------------------- |
|
Class_T CNPC_Barney::Classify( void ) |
|
{ |
|
return CLASS_PLAYER_ALLY_VITAL; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
//----------------------------------------------------------------------------- |
|
void CNPC_Barney::Weapon_Equip( CBaseCombatWeapon *pWeapon ) |
|
{ |
|
BaseClass::Weapon_Equip( pWeapon ); |
|
|
|
if( hl2_episodic.GetBool() && FClassnameIs( pWeapon, "weapon_ar2" ) ) |
|
{ |
|
// Allow Barney to defend himself at point-blank range in c17_05. |
|
pWeapon->m_fMinRange1 = 0.0f; |
|
} |
|
} |
|
|
|
//--------------------------------------------------------- |
|
//--------------------------------------------------------- |
|
void CNPC_Barney::HandleAnimEvent( animevent_t *pEvent ) |
|
{ |
|
switch( pEvent->event ) |
|
{ |
|
case NPC_EVENT_LEFTFOOT: |
|
{ |
|
EmitSound( "NPC_Barney.FootstepLeft", pEvent->eventtime ); |
|
} |
|
break; |
|
case NPC_EVENT_RIGHTFOOT: |
|
{ |
|
EmitSound( "NPC_Barney.FootstepRight", pEvent->eventtime ); |
|
} |
|
break; |
|
|
|
default: |
|
BaseClass::HandleAnimEvent( pEvent ); |
|
break; |
|
} |
|
} |
|
|
|
//------------------------------------------------------------------------------ |
|
//------------------------------------------------------------------------------ |
|
void CNPC_Barney::DeathSound( const CTakeDamageInfo &info ) |
|
{ |
|
// Sentences don't play on dead NPCs |
|
SentenceStop(); |
|
|
|
EmitSound( "npc_barney.die" ); |
|
|
|
} |
|
|
|
bool CNPC_Barney::CreateBehaviors( void ) |
|
{ |
|
BaseClass::CreateBehaviors(); |
|
AddBehavior( &m_FuncTankBehavior ); |
|
|
|
return true; |
|
} |
|
|
|
void CNPC_Barney::OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior ) |
|
{ |
|
if ( pNewBehavior == &m_FuncTankBehavior ) |
|
{ |
|
m_bReadinessCapable = false; |
|
} |
|
else if ( pOldBehavior == &m_FuncTankBehavior ) |
|
{ |
|
m_bReadinessCapable = IsReadinessCapable(); |
|
} |
|
|
|
BaseClass::OnChangeRunningBehavior( pOldBehavior, pNewBehavior ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
//----------------------------------------------------------------------------- |
|
void CNPC_Barney::GatherConditions() |
|
{ |
|
BaseClass::GatherConditions(); |
|
|
|
// Handle speech AI. Don't do AI speech if we're in scripts unless permitted by the EnableSpeakWhileScripting input. |
|
if ( m_NPCState == NPC_STATE_IDLE || m_NPCState == NPC_STATE_ALERT || m_NPCState == NPC_STATE_COMBAT || |
|
( ( m_NPCState == NPC_STATE_SCRIPT ) && CanSpeakWhileScripting() ) ) |
|
{ |
|
DoCustomSpeechAI(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
//----------------------------------------------------------------------------- |
|
void CNPC_Barney::UseFunc( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) |
|
{ |
|
m_bDontUseSemaphore = true; |
|
SpeakIfAllowed( TLK_USE ); |
|
m_bDontUseSemaphore = false; |
|
|
|
m_OnPlayerUse.FireOutput( pActivator, pCaller ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// |
|
// Schedules |
|
// |
|
//----------------------------------------------------------------------------- |
|
|
|
AI_BEGIN_CUSTOM_NPC( npc_barney, CNPC_Barney ) |
|
|
|
AI_END_CUSTOM_NPC()
|
|
|