mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-08 01:39:36 +00:00
add hl1,portal,dod source code
This commit is contained in:
@@ -0,0 +1,516 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: barnacle - stationary ceiling mounted 'fishing' monster
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "hl1_npc_barnacle.h"
|
||||
#include "npcevent.h"
|
||||
#include "gib.h"
|
||||
#include "ai_default.h"
|
||||
#include "activitylist.h"
|
||||
#include "hl2_player.h"
|
||||
#include "vstdlib/random.h"
|
||||
#include "physics_saverestore.h"
|
||||
#include "vcollide_parse.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
|
||||
ConVar sk_barnacle_health( "sk_barnacle_health","25");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Private activities.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ACT_EAT = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Interactions
|
||||
//-----------------------------------------------------------------------------
|
||||
int g_interactionBarnacleVictimDangle = 0;
|
||||
int g_interactionBarnacleVictimReleased = 0;
|
||||
int g_interactionBarnacleVictimGrab = 0;
|
||||
|
||||
LINK_ENTITY_TO_CLASS( monster_barnacle, CNPC_Barnacle );
|
||||
IMPLEMENT_CUSTOM_AI( monster_barnacle, CNPC_Barnacle );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Initialize the custom schedules
|
||||
// Input :
|
||||
// Output :
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_Barnacle::InitCustomSchedules(void)
|
||||
{
|
||||
INIT_CUSTOM_AI(CNPC_Barnacle);
|
||||
|
||||
ADD_CUSTOM_ACTIVITY(CNPC_Barnacle, ACT_EAT);
|
||||
|
||||
g_interactionBarnacleVictimDangle = CBaseCombatCharacter::GetInteractionID();
|
||||
g_interactionBarnacleVictimReleased = CBaseCombatCharacter::GetInteractionID();
|
||||
g_interactionBarnacleVictimGrab = CBaseCombatCharacter::GetInteractionID();
|
||||
}
|
||||
|
||||
|
||||
BEGIN_DATADESC( CNPC_Barnacle )
|
||||
|
||||
DEFINE_FIELD( m_flAltitude, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flKillVictimTime, FIELD_TIME ),
|
||||
DEFINE_FIELD( m_cGibs, FIELD_INTEGER ),// barnacle loads up on gibs each time it kills something.
|
||||
DEFINE_FIELD( m_fLiftingPrey, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( m_flTongueAdj, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flIgnoreTouchesUntil, FIELD_TIME ),
|
||||
|
||||
// Function pointers
|
||||
DEFINE_THINKFUNC( BarnacleThink ),
|
||||
DEFINE_THINKFUNC( WaitTillDead ),
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
//=========================================================
|
||||
// Classify - indicates this monster's place in the
|
||||
// relationship table.
|
||||
//=========================================================
|
||||
Class_T CNPC_Barnacle::Classify ( void )
|
||||
{
|
||||
return CLASS_ALIEN_MONSTER;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// HandleAnimEvent - catches the monster-specific messages
|
||||
// that occur when tagged animation frames are played.
|
||||
//
|
||||
// Returns number of events handled, 0 if none.
|
||||
//=========================================================
|
||||
void CNPC_Barnacle::HandleAnimEvent( animevent_t *pEvent )
|
||||
{
|
||||
switch( pEvent->event )
|
||||
{
|
||||
case BARNACLE_AE_PUKEGIB:
|
||||
CGib::SpawnRandomGibs( this, 1, GIB_HUMAN );
|
||||
break;
|
||||
default:
|
||||
BaseClass::HandleAnimEvent( pEvent );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Spawn
|
||||
//=========================================================
|
||||
void CNPC_Barnacle::Spawn()
|
||||
{
|
||||
Precache( );
|
||||
|
||||
SetModel( "models/barnacle.mdl" );
|
||||
UTIL_SetSize( this, Vector(-16, -16, -32), Vector(16, 16, 0) );
|
||||
|
||||
SetSolid( SOLID_BBOX );
|
||||
AddSolidFlags( FSOLID_NOT_STANDABLE );
|
||||
SetMoveType( MOVETYPE_NONE );
|
||||
SetBloodColor( BLOOD_COLOR_GREEN );
|
||||
m_iHealth = sk_barnacle_health.GetFloat();
|
||||
m_flFieldOfView = 0.5;// indicates the width of this monster's forward view cone ( as a dotproduct result )
|
||||
m_NPCState = NPC_STATE_NONE;
|
||||
m_flKillVictimTime = 0;
|
||||
m_cGibs = 0;
|
||||
m_fLiftingPrey = FALSE;
|
||||
m_takedamage = DAMAGE_YES;
|
||||
|
||||
InitBoneControllers();
|
||||
InitTonguePosition();
|
||||
|
||||
// set eye position
|
||||
SetDefaultEyeOffset();
|
||||
|
||||
SetActivity ( ACT_IDLE );
|
||||
|
||||
SetThink ( &CNPC_Barnacle::BarnacleThink );
|
||||
SetNextThink( gpGlobals->curtime + 0.5f );
|
||||
//Do not have a shadow
|
||||
AddEffects( EF_NOSHADOW );
|
||||
|
||||
m_flIgnoreTouchesUntil = gpGlobals->curtime;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input :
|
||||
// Output :
|
||||
//-----------------------------------------------------------------------------
|
||||
int CNPC_Barnacle::OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo )
|
||||
{
|
||||
CTakeDamageInfo info = inputInfo;
|
||||
if ( info.GetDamageType() & DMG_CLUB )
|
||||
{
|
||||
info.SetDamage( m_iHealth );
|
||||
}
|
||||
|
||||
return BaseClass::OnTakeDamage_Alive( info );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Initialize tongue position when first spawned
|
||||
// Input :
|
||||
// Output :
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_Barnacle::InitTonguePosition( void )
|
||||
{
|
||||
CBaseEntity *pTouchEnt;
|
||||
float flLength;
|
||||
|
||||
pTouchEnt = TongueTouchEnt( &flLength );
|
||||
m_flAltitude = flLength;
|
||||
|
||||
Vector origin;
|
||||
QAngle angle;
|
||||
|
||||
GetAttachment( "TongueEnd", origin, angle );
|
||||
|
||||
m_flTongueAdj = origin.z - GetAbsOrigin().z;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_Barnacle::BarnacleThink ( void )
|
||||
{
|
||||
CBaseEntity *pTouchEnt;
|
||||
float flLength;
|
||||
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
|
||||
if (CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI)
|
||||
{
|
||||
// AI Disabled, don't do anything
|
||||
}
|
||||
else if ( GetEnemy() != NULL )
|
||||
{
|
||||
// barnacle has prey.
|
||||
|
||||
if ( !GetEnemy()->IsAlive() )
|
||||
{
|
||||
// someone (maybe even the barnacle) killed the prey. Reset barnacle.
|
||||
m_fLiftingPrey = FALSE;// indicate that we're not lifting prey.
|
||||
SetEnemy( NULL );
|
||||
return;
|
||||
}
|
||||
|
||||
CBaseCombatCharacter* pVictim = GetEnemyCombatCharacterPointer();
|
||||
Assert( pVictim );
|
||||
|
||||
if ( m_fLiftingPrey )
|
||||
{
|
||||
|
||||
if ( GetEnemy() != NULL && pVictim->m_lifeState == LIFE_DEAD )
|
||||
{
|
||||
// crap, someone killed the prey on the way up.
|
||||
SetEnemy( NULL );
|
||||
m_fLiftingPrey = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
// still pulling prey.
|
||||
Vector vecNewEnemyOrigin = GetEnemy()->GetLocalOrigin();
|
||||
vecNewEnemyOrigin.x = GetLocalOrigin().x;
|
||||
vecNewEnemyOrigin.y = GetLocalOrigin().y;
|
||||
|
||||
// guess as to where their neck is
|
||||
// FIXME: remove, ask victim where their neck is
|
||||
vecNewEnemyOrigin.x -= 6 * cos(GetEnemy()->GetLocalAngles().y * M_PI/180.0);
|
||||
vecNewEnemyOrigin.y -= 6 * sin(GetEnemy()->GetLocalAngles().y * M_PI/180.0);
|
||||
|
||||
m_flAltitude -= BARNACLE_PULL_SPEED;
|
||||
vecNewEnemyOrigin.z += BARNACLE_PULL_SPEED;
|
||||
|
||||
if ( fabs( GetLocalOrigin().z - ( vecNewEnemyOrigin.z + GetEnemy()->GetViewOffset().z ) ) < BARNACLE_BODY_HEIGHT )
|
||||
{
|
||||
// prey has just been lifted into position ( if the victim origin + eye height + 8 is higher than the bottom of the barnacle, it is assumed that the head is within barnacle's body )
|
||||
m_fLiftingPrey = FALSE;
|
||||
|
||||
CPASAttenuationFilter filter( this );
|
||||
EmitSound( filter, entindex(), "Barnacle.Bite");
|
||||
|
||||
// Take a while to kill the player
|
||||
m_flKillVictimTime = gpGlobals->curtime + 10;
|
||||
|
||||
if ( pVictim )
|
||||
{
|
||||
pVictim->DispatchInteraction( g_interactionBarnacleVictimDangle, NULL, this );
|
||||
SetActivity ( (Activity)ACT_EAT );
|
||||
}
|
||||
}
|
||||
|
||||
CBaseEntity *pEnemy = GetEnemy();
|
||||
|
||||
trace_t trace;
|
||||
UTIL_TraceEntity( pEnemy, pEnemy->GetAbsOrigin(), vecNewEnemyOrigin, MASK_SOLID_BRUSHONLY, pEnemy, COLLISION_GROUP_NONE, &trace );
|
||||
|
||||
if( trace.fraction != 1.0 )
|
||||
{
|
||||
// The victim cannot be moved from their current origin to this new origin. So drop them.
|
||||
SetEnemy( NULL );
|
||||
m_fLiftingPrey = FALSE;
|
||||
|
||||
if( pEnemy->MyCombatCharacterPointer() )
|
||||
{
|
||||
pEnemy->MyCombatCharacterPointer()->DispatchInteraction( g_interactionBarnacleVictimReleased, NULL, this );
|
||||
}
|
||||
|
||||
// Ignore touches long enough to let the victim move away.
|
||||
m_flIgnoreTouchesUntil = gpGlobals->curtime + 1.5;
|
||||
|
||||
SetActivity( ACT_IDLE );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
UTIL_SetOrigin ( GetEnemy(), vecNewEnemyOrigin );
|
||||
}
|
||||
else
|
||||
{
|
||||
// prey is lifted fully into feeding position and is dangling there.
|
||||
|
||||
if ( m_flKillVictimTime != -1 && gpGlobals->curtime > m_flKillVictimTime )
|
||||
{
|
||||
// kill!
|
||||
if ( pVictim )
|
||||
{
|
||||
// DMG_CRUSH added so no physics force is generated
|
||||
pVictim->TakeDamage( CTakeDamageInfo( this, this, pVictim->m_iHealth, DMG_SLASH | DMG_ALWAYSGIB | DMG_CRUSH ) );
|
||||
m_cGibs = 3;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// bite prey every once in a while
|
||||
if ( pVictim && ( random->RandomInt( 0, 49 ) == 0 ) )
|
||||
{
|
||||
CPASAttenuationFilter filter( this );
|
||||
EmitSound( filter, entindex(), "Barnacle.Chew" );
|
||||
|
||||
if ( pVictim )
|
||||
{
|
||||
pVictim->DispatchInteraction( g_interactionBarnacleVictimDangle, NULL, this );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// barnacle has no prey right now, so just idle and check to see if anything is touching the tongue.
|
||||
|
||||
// If idle and no nearby client, don't think so often. Client should be out of PVS and not within 50 feet.
|
||||
if ( !UTIL_FindClientInPVS(edict()) )
|
||||
{
|
||||
CBasePlayer *pPlayer = UTIL_PlayerByIndex(1);
|
||||
|
||||
if( pPlayer )
|
||||
{
|
||||
Vector vecDist = pPlayer->GetAbsOrigin() - GetAbsOrigin();
|
||||
|
||||
if( vecDist.Length2DSqr() >= Square(600.0f) )
|
||||
{
|
||||
SetNextThink( gpGlobals->curtime + 1.5f );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( IsActivityFinished() )
|
||||
{// this is done so barnacle will fidget.
|
||||
SetActivity ( ACT_IDLE );
|
||||
}
|
||||
|
||||
if ( m_cGibs && random->RandomInt(0,99) == 1 )
|
||||
{
|
||||
// cough up a gib.
|
||||
CGib::SpawnRandomGibs( this, 1, GIB_HUMAN );
|
||||
m_cGibs--;
|
||||
|
||||
CPASAttenuationFilter filter( this );
|
||||
EmitSound( filter, entindex(), "Barnacle.Chew" );
|
||||
}
|
||||
|
||||
pTouchEnt = TongueTouchEnt( &flLength );
|
||||
|
||||
//NDebugOverlay::Box( GetAbsOrigin() - Vector( 0, 0, flLength ), Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 255,0,0, 0, 0.1 );
|
||||
|
||||
if ( pTouchEnt != NULL )
|
||||
{
|
||||
// tongue is fully extended, and is touching someone.
|
||||
CBaseCombatCharacter* pBCC = (CBaseCombatCharacter *)pTouchEnt;
|
||||
|
||||
// FIXME: humans should return neck position
|
||||
Vector vecGrabPos = pTouchEnt->GetAbsOrigin();
|
||||
|
||||
if ( pBCC && pBCC->DispatchInteraction( g_interactionBarnacleVictimGrab, &vecGrabPos, this ) )
|
||||
{
|
||||
CPASAttenuationFilter filter( this );
|
||||
EmitSound( filter, entindex(), "Barnacle.Alert" );
|
||||
|
||||
SetSequenceByName ( "attack1" );
|
||||
|
||||
SetEnemy( pTouchEnt );
|
||||
|
||||
pTouchEnt->SetMoveType( MOVETYPE_FLY );
|
||||
pTouchEnt->SetAbsVelocity( vec3_origin );
|
||||
pTouchEnt->SetBaseVelocity( vec3_origin );
|
||||
Vector origin = GetAbsOrigin();
|
||||
origin.z = pTouchEnt->GetAbsOrigin().z;
|
||||
pTouchEnt->SetLocalOrigin( origin );
|
||||
|
||||
m_fLiftingPrey = TRUE;// indicate that we should be lifting prey.
|
||||
m_flKillVictimTime = -1;// set this to a bogus time while the victim is lifted.
|
||||
|
||||
m_flAltitude = (GetAbsOrigin().z - vecGrabPos.z);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// calculate a new length for the tongue to be clear of anything else that moves under it.
|
||||
if ( m_flAltitude < flLength )
|
||||
{
|
||||
// if tongue is higher than is should be, lower it kind of slowly.
|
||||
m_flAltitude += BARNACLE_PULL_SPEED;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flAltitude = flLength;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ALERT( at_console, "tounge %f\n", m_flAltitude + m_flTongueAdj );
|
||||
//NDebugOverlay::Box( GetAbsOrigin() - Vector( 0, 0, m_flAltitude ), Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 255,255,255, 0, 0.1 );
|
||||
|
||||
SetBoneController( 0, -(m_flAltitude + m_flTongueAdj) );
|
||||
StudioFrameAdvance();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_Barnacle::Event_Killed( const CTakeDamageInfo &info )
|
||||
{
|
||||
AddSolidFlags( FSOLID_NOT_SOLID );
|
||||
m_takedamage = DAMAGE_NO;
|
||||
m_lifeState = LIFE_DEAD;
|
||||
if ( GetEnemy() != NULL )
|
||||
{
|
||||
CBaseCombatCharacter *pVictim = GetEnemyCombatCharacterPointer();
|
||||
|
||||
if ( pVictim )
|
||||
{
|
||||
pVictim->DispatchInteraction( g_interactionBarnacleVictimReleased, NULL, this );
|
||||
}
|
||||
}
|
||||
|
||||
CGib::SpawnRandomGibs( this, 4, GIB_HUMAN );
|
||||
|
||||
CPASAttenuationFilter filter( this );
|
||||
EmitSound( filter, entindex(), "Barnacle.Die" );
|
||||
|
||||
SetActivity ( ACT_DIESIMPLE );
|
||||
SetBoneController( 0, 0 );
|
||||
|
||||
StudioFrameAdvance();
|
||||
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
SetThink ( &CNPC_Barnacle::WaitTillDead );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_Barnacle::WaitTillDead ( void )
|
||||
{
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
|
||||
StudioFrameAdvance();
|
||||
DispatchAnimEvents ( this );
|
||||
|
||||
if ( IsActivityFinished() )
|
||||
{
|
||||
// death anim finished.
|
||||
StopAnimation();
|
||||
SetThink ( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Precache - precaches all resources this monster needs
|
||||
//=========================================================
|
||||
void CNPC_Barnacle::Precache()
|
||||
{
|
||||
PrecacheModel("models/barnacle.mdl");
|
||||
|
||||
PrecacheScriptSound( "Barnacle.Bite" );
|
||||
PrecacheScriptSound( "Barnacle.Chew" );
|
||||
PrecacheScriptSound( "Barnacle.Alert" );
|
||||
PrecacheScriptSound( "Barnacle.Die" );
|
||||
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// TongueTouchEnt - does a trace along the barnacle's tongue
|
||||
// to see if any entity is touching it. Also stores the length
|
||||
// of the trace in the int pointer provided.
|
||||
//=========================================================
|
||||
#define BARNACLE_CHECK_SPACING 8
|
||||
CBaseEntity *CNPC_Barnacle::TongueTouchEnt ( float *pflLength )
|
||||
{
|
||||
trace_t tr;
|
||||
float length;
|
||||
|
||||
// trace once to hit architecture and see if the tongue needs to change position.
|
||||
UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() - Vector ( 0 , 0 , 2048 ),
|
||||
MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
length = fabs( GetAbsOrigin().z - tr.endpos.z );
|
||||
// Pull it up a tad
|
||||
length -= 16;
|
||||
if ( pflLength )
|
||||
{
|
||||
*pflLength = length;
|
||||
}
|
||||
|
||||
// Don't try to touch any prey.
|
||||
if ( m_flIgnoreTouchesUntil > gpGlobals->curtime )
|
||||
return NULL;
|
||||
|
||||
Vector delta = Vector( BARNACLE_CHECK_SPACING, BARNACLE_CHECK_SPACING, 0 );
|
||||
Vector mins = GetAbsOrigin() - delta;
|
||||
Vector maxs = GetAbsOrigin() + delta;
|
||||
maxs.z = GetAbsOrigin().z;
|
||||
|
||||
// Take our current tongue's length or a point higher if we hit a wall
|
||||
// NOTENOTE: (this relieves the need to know if the tongue is currently moving)
|
||||
mins.z -= MIN( m_flAltitude, length );
|
||||
|
||||
CBaseEntity *pList[10];
|
||||
int count = UTIL_EntitiesInBox( pList, 10, mins, maxs, (FL_CLIENT|FL_NPC) );
|
||||
if ( count )
|
||||
{
|
||||
for ( int i = 0; i < count; i++ )
|
||||
{
|
||||
CBaseCombatCharacter *pVictim = ToBaseCombatCharacter( pList[ i ] );
|
||||
|
||||
bool bCanHurt = false;
|
||||
|
||||
if ( IRelationType( pList[i] ) == D_HT || IRelationType( pList[i] ) == D_FR )
|
||||
bCanHurt = true;
|
||||
|
||||
if ( pList[i] != this && bCanHurt == true && pVictim->m_lifeState == LIFE_ALIVE )
|
||||
{
|
||||
return pList[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
Reference in New Issue
Block a user