⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hl1_npc_bigmomma.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#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_Route.h"
#include	"soundent.h"
#include	"game.h"
#include	"NPCEvent.h"
#include	"EntityList.h"
#include	"activitylist.h"
#include	"animation.h"
#include	"basecombatweapon.h"
#include	"IEffects.h"
#include	"vstdlib/random.h"
#include	"engine/IEngineSound.h"
#include	"ammodef.h"
#include	"hl1_ai_basenpc.h"
#include	"AI_Navigator.h"
#include	"decals.h"
#include	"effect_dispatch_data.h"
#include	"te_effect_dispatch.h"
#include	"Sprite.h"

ConVar sk_bigmomma_health_factor( "sk_bigmomma_health_factor", "1" );
ConVar sk_bigmomma_dmg_slash( "sk_bigmomma_dmg_slash", "50" );
ConVar sk_bigmomma_dmg_blast( "sk_bigmomma_dmg_blast", "100" );
ConVar sk_bigmomma_radius_blast( "sk_bigmomma_radius_blast", "250" );

extern ConVar sv_gravity;


//=========================================================
// Monster's Anim Events Go Here
//=========================================================
#define	BIG_AE_STEP1				1		// Footstep left
#define	BIG_AE_STEP2				2		// Footstep right
#define	BIG_AE_STEP3				3		// Footstep back left
#define	BIG_AE_STEP4				4		// Footstep back right
#define BIG_AE_SACK					5		// Sack slosh
#define BIG_AE_DEATHSOUND			6		// Death sound

#define	BIG_AE_MELEE_ATTACKBR		8		// Leg attack
#define	BIG_AE_MELEE_ATTACKBL		9		// Leg attack
#define	BIG_AE_MELEE_ATTACK1		10		// Leg attack
#define BIG_AE_MORTAR_ATTACK1		11		// Launch a mortar
#define BIG_AE_LAY_CRAB				12		// Lay a headcrab
#define BIG_AE_JUMP_FORWARD			13		// Jump up and forward
#define BIG_AE_SCREAM				14		// alert sound
#define BIG_AE_PAIN_SOUND			15		// pain sound
#define BIG_AE_ATTACK_SOUND			16		// attack sound
#define BIG_AE_BIRTH_SOUND			17		// birth sound
#define BIG_AE_EARLY_TARGET			50		// Fire target early


enum
{
	SCHED_NODE_FAIL = LAST_SHARED_SCHEDULE,
	SCHED_BIG_NODE,
};

enum
{
	TASK_MOVE_TO_NODE_RANGE = LAST_SHARED_TASK,		// Move within node range
	TASK_FIND_NODE,									// Find my next node
	TASK_PLAY_NODE_PRESEQUENCE,						// Play node pre-script
	TASK_PLAY_NODE_SEQUENCE,						// Play node script
	TASK_PROCESS_NODE,								// Fire targets, etc.
	TASK_WAIT_NODE,									// Wait at the node
	TASK_NODE_DELAY,								// Delay walking toward node for a bit. You've failed to get there
	TASK_NODE_YAW,									// Get the best facing direction for this node
	TASK_CHECK_NODE_PROXIMITY,
};

// User defined conditions
//#define bits_COND_NODE_SEQUENCE			( COND_SPECIAL1 )		// pev->netname contains the name of a sequence to play

// Attack distance constants
#define	BIG_ATTACKDIST		170
#define BIG_MORTARDIST		800
#define BIG_MAXCHILDREN		6			// Max # of live headcrab children


#define bits_MEMORY_CHILDPAIR		(bits_MEMORY_CUSTOM1)
#define bits_MEMORY_ADVANCE_NODE	(bits_MEMORY_CUSTOM2)
#define bits_MEMORY_COMPLETED_NODE	(bits_MEMORY_CUSTOM3)
#define bits_MEMORY_FIRED_NODE		(bits_MEMORY_CUSTOM4)

int gSpitSprite, gSpitDebrisSprite;


Vector VecCheckSplatToss( CBaseEntity *pEntity, const Vector &vecSpot1, Vector vecSpot2, float maxHeight );
void MortarSpray( const Vector &position, const Vector &direction, int spriteModel, int count );

#define SF_INFOBM_RUN		0x0001
#define SF_INFOBM_WAIT		0x0002

//=========================================================
// Mortar shot entity
//=========================================================
class CBMortar : public CBaseAnimating
{
	DECLARE_CLASS( CBMortar, CBaseAnimating );
public:
	void Spawn( void );

	static CBMortar *Shoot( CBaseEntity *pOwner, Vector vecStart, Vector vecVelocity );
	void Touch( CBaseEntity *pOther );
	void Animate( void );

	float	m_flDmgTime;

	DECLARE_DATADESC();

	int  m_maxFrame;
	int  m_iFrame;

	CSprite* pSprite;
};

LINK_ENTITY_TO_CLASS( bmortar, CBMortar );

BEGIN_DATADESC( CBMortar )
	DEFINE_FIELD( CBMortar, m_maxFrame, FIELD_INTEGER ),
	DEFINE_FIELD( CBMortar, m_flDmgTime, FIELD_FLOAT ),
	DEFINE_FUNCTION( CBMortar, Animate ),
END_DATADESC()


// AI Nodes for Big Momma
class CInfoBM : public CPointEntity
{
	DECLARE_CLASS( CInfoBM, CPointEntity );
public:
	void Spawn( void );
	bool KeyValue( const char *szKeyName, const char *szValue );

	// name in pev->targetname
	// next in pev->target
	// radius in pev->scale
	// health in pev->health
	// Reach target in pev->message
	// Reach delay in pev->speed
	// Reach sequence in pev->netname
	
	DECLARE_DATADESC();

	int		m_preSequence;
	int		m_curSequence;
	float   m_flRadius;
	float   m_flDelay;
	string_t m_iszReachTarget;
	string_t m_iszReachSequence;
	string_t m_iszPreSequence;
	const char *m_iszNameHack;

	COutputEvent m_OnAnimationEvent;
};

LINK_ENTITY_TO_CLASS( info_bigmomma, CInfoBM );

BEGIN_DATADESC( CInfoBM )
	DEFINE_FIELD( CInfoBM, m_flRadius, FIELD_FLOAT ),
	DEFINE_FIELD( CInfoBM, m_flDelay, FIELD_FLOAT ),
	DEFINE_KEYFIELD( CInfoBM, m_iszReachTarget, FIELD_STRING, "reachtarget" ),
	DEFINE_KEYFIELD( CInfoBM, m_iszReachSequence, FIELD_STRING, "reachsequence" ),
	DEFINE_KEYFIELD( CInfoBM, m_iszPreSequence, FIELD_STRING, "presequence" ),
	DEFINE_OUTPUT( CInfoBM, m_OnAnimationEvent, "OnAnimationEvent" ),
END_DATADESC()


void CInfoBM::Spawn( void )
{
	BaseClass::Spawn();

//	Msg( "Name %s\n", STRING( GetEntityName() ) );
}

bool CInfoBM::KeyValue( const char *szKeyName, const char *szValue ) 
{
	if (FStrEq( szKeyName, "radius"))
	{
		m_flRadius = atof( szValue );
		return true;
	}
	else if (FStrEq( szKeyName, "reachdelay" ))
	{
		m_flDelay = atof( szValue);
		return true;
	}
	else if (FStrEq( szKeyName, "health" ))
	{
		m_iHealth = atoi( szValue );
		return true;
	}

	return BaseClass::KeyValue(szKeyName, szValue );
}

// UNDONE:	
//
#define BIG_CHILDCLASS		"monster_babycrab"


class CNPC_BigMomma : public CHL1BaseNPC
{
	DECLARE_CLASS( CNPC_BigMomma, CHL1BaseNPC );
public:

	void Spawn( void );
	void Precache( void );

	static const char *pChildDieSounds[];
	static const char *pSackSounds[];
	static const char *pDeathSounds[];
	static const char *pAttackSounds[];
	static const char *pAttackHitSounds[];
	static const char *pBirthSounds[];
	static const char *pAlertSounds[];
	static const char *pPainSounds[];
	static const char *pFootSounds[];
	
	Class_T	Classify( void ) { return CLASS_ALIEN_MONSTER; };
	void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr );
	int	OnTakeDamage( const CTakeDamageInfo &info );
	void HandleAnimEvent( animevent_t *pEvent );
	void LayHeadcrab( void );
	void LaunchMortar( void );
	void DeathNotice( CBaseEntity *pevChild );

	int MeleeAttack1Conditions( float flDot, float flDist );	// Slash
	int MeleeAttack2Conditions( float flDot, float flDist );	// Lay a crab
	int RangeAttack1Conditions( float flDot, float flDist );	// Mortar launch


	BOOL CanLayCrab( void ) 
	{ 
		if ( m_crabTime < gpGlobals->curtime && m_crabCount < BIG_MAXCHILDREN )
		{
			// Don't spawn crabs inside each other
			Vector mins = GetAbsOrigin() - Vector( 32, 32, 0 );
			Vector maxs = GetAbsOrigin() + Vector( 32, 32, 0 );

			CBaseEntity *pList[2];
			int count = UTIL_EntitiesInBox( pList, 2, mins, maxs, FL_NPC );
			for ( int i = 0; i < count; i++ )
			{
				if ( pList[i] != this )	// Don't hurt yourself!
					return COND_NONE;
			}
			return COND_CAN_MELEE_ATTACK2;
		}

		return COND_NONE;
	}

	void Activate ( void );

	void NodeReach( void );
	void NodeStart( string_t iszNextNode );
	bool ShouldGoToNode( void );
	
	const char *GetNodeSequence( void )
	{
		CInfoBM *pTarget = (CInfoBM*)GetTarget();

		if ( pTarget && FClassnameIs( pTarget, "info_bigmomma" ) )
		{
			return STRING( pTarget->m_iszReachSequence );	// netname holds node sequence
		}
		
		return NULL;
	}


	const char *GetNodePresequence( void )
	{
		CInfoBM *pTarget = (CInfoBM *)GetTarget();

		if ( pTarget && FClassnameIs( pTarget, "info_bigmomma" ) )
		{
			return STRING( pTarget->m_iszPreSequence );
		}
		return NULL;
	}

	float GetNodeDelay( void )
	{
		CInfoBM *pTarget = (CInfoBM *)GetTarget();

		if ( pTarget && FClassnameIs( pTarget, "info_bigmomma" ) )
		{
			return pTarget->m_flDelay;	// Speed holds node delay
		}
		return 0;
	}

	float GetNodeRange( void )
	{
		CInfoBM *pTarget = (CInfoBM *)GetTarget();

		if ( pTarget && FClassnameIs( pTarget, "info_bigmomma" ) )
		{
			return pTarget->m_flRadius;	// Scale holds node delay
		}

		return 1e6;
	}

	float GetNodeYaw( void )
	{
		CBaseEntity *pTarget = GetTarget();

		if ( pTarget )
		{
			if ( pTarget->GetAbsAngles().y != 0 )
				 return pTarget->GetAbsAngles().y;
		}
		
		return GetAbsAngles().y;
	}
	
	// Restart the crab count on each new level
	void OnRestore( void )
	{
		BaseClass::OnRestore();
		m_crabCount = 0;
	}

	virtual void SetObjectCollisionBox( void )
	{
		SetAbsMins( GetAbsOrigin() + Vector( -95, -95, 0 ) );
		SetAbsMaxs( GetAbsOrigin() + Vector( 95, 95, 190 ) );
	}

	int SelectSchedule( void );
	void StartTask( const Task_t *pTask );
	void RunTask( const Task_t *pTask );

	float MaxYawSpeed( void );

	DECLARE_DATADESC();

	DEFINE_CUSTOM_AI;

	/*	int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );

	void		RunTask( Task_t *pTask );
	void		StartTask( Task_t *pTask );
	Schedule_t	*GetSchedule( void );
	Schedule_t	*GetScheduleOfType( int Type );
	void		TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType );

	void SetYawSpeed( void );

	CUSTOM_SCHEDULES;
*/
private:
	float	m_nodeTime;
	float	m_crabTime;
	float	m_mortarTime;
	float	m_painSoundTime;
	int		m_crabCount;
	float	m_flDmgTime;

	bool	m_bDoneWithPath;

	string_t m_iszTarget;
	string_t m_iszNetName;
	float	m_flWait;

	Vector m_vTossDir;

	
};


BEGIN_DATADESC( CNPC_BigMomma )
	DEFINE_FIELD( CNPC_BigMomma, m_nodeTime, FIELD_TIME ),
	DEFINE_FIELD( CNPC_BigMomma, m_crabTime, FIELD_TIME ),
	DEFINE_FIELD( CNPC_BigMomma, m_mortarTime, FIELD_TIME ),
	DEFINE_FIELD( CNPC_BigMomma, m_painSoundTime, FIELD_TIME ),
	DEFINE_KEYFIELD( CNPC_BigMomma, m_iszNetName, FIELD_STRING, "netname" ),
	DEFINE_FIELD( CNPC_BigMomma, m_flWait, FIELD_TIME ),
	DEFINE_FIELD( CNPC_BigMomma, m_iszTarget, FIELD_STRING ),
END_DATADESC()


LINK_ENTITY_TO_CLASS ( monster_bigmomma, CNPC_BigMomma );

const char *CNPC_BigMomma::pChildDieSounds[] = 
{
	"gonarch/gon_childdie1.wav",
	"gonarch/gon_childdie2.wav",
	"gonarch/gon_childdie3.wav",
};

const char *CNPC_BigMomma::pSackSounds[] = 
{
	"gonarch/gon_sack1.wav",
	"gonarch/gon_sack2.wav",
	"gonarch/gon_sack3.wav",
};

const char *CNPC_BigMomma::pDeathSounds[] = 
{
	"gonarch/gon_die1.wav",
};

const char *CNPC_BigMomma::pAttackSounds[] = 
{
	"gonarch/gon_attack1.wav",
	"gonarch/gon_attack2.wav",
	"gonarch/gon_attack3.wav",
};
const char *CNPC_BigMomma::pAttackHitSounds[] = 
{
	"zombie/claw_strike1.wav",
	"zombie/claw_strike2.wav",
	"zombie/claw_strike3.wav",
};

const char *CNPC_BigMomma::pBirthSounds[] = 
{
	"gonarch/gon_birth1.wav",
	"gonarch/gon_birth2.wav",
	"gonarch/gon_birth3.wav",
};

const char *CNPC_BigMomma::pAlertSounds[] = 
{
	"gonarch/gon_alert1.wav",
	"gonarch/gon_alert2.wav",
	"gonarch/gon_alert3.wav",
};

const char *CNPC_BigMomma::pPainSounds[] = 
{
	"gonarch/gon_pain2.wav",
	"gonarch/gon_pain4.wav",
	"gonarch/gon_pain5.wav",
};

const char *CNPC_BigMomma::pFootSounds[] = 
{
	"gonarch/gon_step1.wav",
	"gonarch/gon_step2.wav",
	"gonarch/gon_step3.wav",
};

//=========================================================
// Spawn
//=========================================================
void CNPC_BigMomma::Spawn()
{
	Precache( );

	SetModel( "models/big_mom.mdl" );
	UTIL_SetSize( this, Vector( -32, -32, 0 ), Vector( 32, 32, 64 ) );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -