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,527 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Projectile shot from the MP5
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// $Log: $
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
|
||||
#include "cbase.h"
|
||||
#include "soundent.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
#include "ai_senses.h"
|
||||
#include "hl1_npc_snark.h"
|
||||
#include "SoundEmitterSystem/isoundemittersystembase.h"
|
||||
|
||||
|
||||
ConVar sk_snark_health ( "sk_snark_health", "0" );
|
||||
ConVar sk_snark_dmg_bite ( "sk_snark_dmg_bite", "0" );
|
||||
ConVar sk_snark_dmg_pop ( "sk_snark_dmg_pop", "0" );
|
||||
|
||||
|
||||
LINK_ENTITY_TO_CLASS( monster_snark, CSnark);
|
||||
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Save/Restore
|
||||
//---------------------------------------------------------
|
||||
BEGIN_DATADESC( CSnark )
|
||||
DEFINE_FIELD( m_flDie, FIELD_TIME ),
|
||||
DEFINE_FIELD( m_vecTarget, FIELD_VECTOR ),
|
||||
DEFINE_FIELD( m_flNextHunt, FIELD_TIME ),
|
||||
DEFINE_FIELD( m_flNextHit, FIELD_TIME ),
|
||||
DEFINE_FIELD( m_posPrev, FIELD_POSITION_VECTOR ),
|
||||
DEFINE_FIELD( m_hOwner, FIELD_EHANDLE ),
|
||||
DEFINE_FIELD( m_iMyClass, FIELD_INTEGER ),
|
||||
|
||||
DEFINE_ENTITYFUNC( SuperBounceTouch ),
|
||||
DEFINE_THINKFUNC( HuntThink ),
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
#define SQUEEK_DETONATE_DELAY 15.0
|
||||
#define SNARK_EXPLOSION_VOLUME 512
|
||||
|
||||
|
||||
enum w_squeak_e {
|
||||
WSQUEAK_IDLE1 = 0,
|
||||
WSQUEAK_FIDGET,
|
||||
WSQUEAK_JUMP,
|
||||
WSQUEAK_RUN,
|
||||
};
|
||||
|
||||
float CSnark::m_flNextBounceSoundTime = 0;
|
||||
|
||||
void CSnark::Precache( void )
|
||||
{
|
||||
BaseClass::Precache();
|
||||
|
||||
PrecacheModel( "models/w_squeak2.mdl" );
|
||||
|
||||
PrecacheScriptSound( "Snark.Die" );
|
||||
PrecacheScriptSound( "Snark.Gibbed" );
|
||||
PrecacheScriptSound( "Snark.Squeak" );
|
||||
PrecacheScriptSound( "Snark.Deploy" );
|
||||
PrecacheScriptSound( "Snark.Bounce" );
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CSnark::Spawn( void )
|
||||
{
|
||||
Precache();
|
||||
|
||||
SetSolid( SOLID_BBOX );
|
||||
AddSolidFlags( FSOLID_NOT_STANDABLE );
|
||||
SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_CUSTOM );
|
||||
SetFriction(1.0);
|
||||
|
||||
SetModel( "models/w_squeak2.mdl" );
|
||||
UTIL_SetSize( this, Vector( -4, -4, 0 ), Vector( 4, 4, 8 ) );
|
||||
|
||||
SetBloodColor( BLOOD_COLOR_YELLOW );
|
||||
|
||||
SetTouch( &CSnark::SuperBounceTouch );
|
||||
SetThink( &CSnark::HuntThink );
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
|
||||
m_flNextHit = gpGlobals->curtime;
|
||||
m_flNextHunt = gpGlobals->curtime + 1E6;
|
||||
m_flNextBounceSoundTime = gpGlobals->curtime;
|
||||
|
||||
AddFlag( FL_AIMTARGET | FL_NPC );
|
||||
m_takedamage = DAMAGE_YES;
|
||||
|
||||
m_iHealth = sk_snark_health.GetFloat();
|
||||
m_iMaxHealth = m_iHealth;
|
||||
|
||||
SetGravity( UTIL_ScaleForGravity( 400 ) ); // use a lower gravity for snarks
|
||||
SetFriction( 0.5 );
|
||||
|
||||
SetDamage( sk_snark_dmg_pop.GetFloat() );
|
||||
|
||||
m_flDie = gpGlobals->curtime + SQUEEK_DETONATE_DELAY;
|
||||
|
||||
m_flFieldOfView = 0; // 180 degrees
|
||||
|
||||
if ( GetOwnerEntity() )
|
||||
m_hOwner = GetOwnerEntity();
|
||||
|
||||
m_flNextBounceSoundTime = gpGlobals->curtime;// reset each time a snark is spawned.
|
||||
|
||||
SetSequence( WSQUEAK_RUN );
|
||||
ResetSequenceInfo( );
|
||||
|
||||
m_iMyClass = CLASS_NONE;
|
||||
|
||||
m_posPrev = Vector( 0, 0, 0 );
|
||||
}
|
||||
|
||||
|
||||
Class_T CSnark::Classify( void )
|
||||
{
|
||||
if ( m_iMyClass != CLASS_NONE )
|
||||
return m_iMyClass; // protect against recursion
|
||||
|
||||
if ( GetEnemy() != NULL )
|
||||
{
|
||||
m_iMyClass = CLASS_INSECT; // no one cares about it
|
||||
switch( GetEnemy()->Classify( ) )
|
||||
{
|
||||
case CLASS_PLAYER:
|
||||
case CLASS_HUMAN_PASSIVE:
|
||||
case CLASS_HUMAN_MILITARY:
|
||||
m_iMyClass = CLASS_NONE;
|
||||
return CLASS_ALIEN_MILITARY; // barney's get mad, grunts get mad at it
|
||||
}
|
||||
m_iMyClass = CLASS_NONE;
|
||||
}
|
||||
|
||||
return CLASS_ALIEN_BIOWEAPON;
|
||||
}
|
||||
|
||||
|
||||
void CSnark::Event_Killed( const CTakeDamageInfo &inputInfo )
|
||||
{
|
||||
// pev->model = iStringNull;// make invisible
|
||||
SetThink( &CSnark::SUB_Remove );
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
SetTouch( NULL );
|
||||
|
||||
// since squeak grenades never leave a body behind, clear out their takedamage now.
|
||||
// Squeaks do a bit of radius damage when they pop, and that radius damage will
|
||||
// continue to call this function unless we acknowledge the Squeak's death now. (sjb)
|
||||
m_takedamage = DAMAGE_NO;
|
||||
|
||||
// play squeek blast
|
||||
CPASAttenuationFilter filter( this, 0.5 );
|
||||
EmitSound( filter, entindex(), "Snark.Die" );
|
||||
|
||||
CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), SNARK_EXPLOSION_VOLUME, 3.0 );
|
||||
|
||||
UTIL_BloodDrips( WorldSpaceCenter(), Vector( 0, 0, 0 ), BLOOD_COLOR_YELLOW, 80 );
|
||||
|
||||
if ( m_hOwner != NULL )
|
||||
{
|
||||
RadiusDamage( CTakeDamageInfo( this, m_hOwner, GetDamage(), DMG_BLAST ), GetAbsOrigin(), GetDamage() * 2.5, CLASS_NONE, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
RadiusDamage( CTakeDamageInfo( this, this, GetDamage(), DMG_BLAST ), GetAbsOrigin(), GetDamage() * 2.5, CLASS_NONE, NULL );
|
||||
}
|
||||
|
||||
// reset owner so death message happens
|
||||
if ( m_hOwner != NULL )
|
||||
SetOwnerEntity( m_hOwner );
|
||||
|
||||
CTakeDamageInfo info = inputInfo;
|
||||
int iGibDamage = g_pGameRules->Damage_GetShouldGibCorpse();
|
||||
info.SetDamageType( iGibDamage );
|
||||
|
||||
BaseClass::Event_Killed( info );
|
||||
}
|
||||
|
||||
|
||||
bool CSnark::Event_Gibbed( const CTakeDamageInfo &info )
|
||||
{
|
||||
CPASAttenuationFilter filter( this );
|
||||
EmitSound( filter, entindex(), "Snark.Gibbed" );
|
||||
|
||||
return BaseClass::Event_Gibbed( info );
|
||||
}
|
||||
|
||||
|
||||
void CSnark::HuntThink( void )
|
||||
{
|
||||
if (!IsInWorld())
|
||||
{
|
||||
SetTouch( NULL );
|
||||
UTIL_Remove( this );
|
||||
return;
|
||||
}
|
||||
|
||||
StudioFrameAdvance( );
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
|
||||
//FIXME: There's a problem in this movetype that causes it to set a ground entity but never recheck to clear it
|
||||
// For now, we stomp it clear and force it to revalidate -- jdw
|
||||
|
||||
SetGroundEntity( NULL );
|
||||
PhysicsStepRecheckGround();
|
||||
|
||||
// explode when ready
|
||||
if ( gpGlobals->curtime >= m_flDie )
|
||||
{
|
||||
g_vecAttackDir = GetAbsVelocity();
|
||||
VectorNormalize( g_vecAttackDir );
|
||||
m_iHealth = -1;
|
||||
CTakeDamageInfo info( this, this, 1, DMG_GENERIC );
|
||||
Event_Killed( info );
|
||||
return;
|
||||
}
|
||||
|
||||
// float
|
||||
if ( GetWaterLevel() != 0)
|
||||
{
|
||||
if ( GetMoveType() == MOVETYPE_FLYGRAVITY )
|
||||
{
|
||||
SetMoveType( MOVETYPE_FLY, MOVECOLLIDE_FLY_CUSTOM );
|
||||
}
|
||||
|
||||
Vector vecVel = GetAbsVelocity();
|
||||
vecVel *= 0.9;
|
||||
vecVel.z += 8.0;
|
||||
SetAbsVelocity( vecVel );
|
||||
}
|
||||
else if ( GetMoveType() == MOVETYPE_FLY )
|
||||
{
|
||||
SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_CUSTOM );
|
||||
}
|
||||
|
||||
// return if not time to hunt
|
||||
if ( m_flNextHunt > gpGlobals->curtime )
|
||||
return;
|
||||
|
||||
m_flNextHunt = gpGlobals->curtime + 2.0;
|
||||
|
||||
Vector vecFlat = GetAbsVelocity();
|
||||
vecFlat.z = 0;
|
||||
VectorNormalize( vecFlat );
|
||||
|
||||
if ( GetEnemy() == NULL || !GetEnemy()->IsAlive() )
|
||||
{
|
||||
// find target, bounce a bit towards it.
|
||||
GetSenses()->Look( 1024 );
|
||||
SetEnemy( BestEnemy() );
|
||||
}
|
||||
|
||||
// squeek if it's about time blow up
|
||||
if ( (m_flDie - gpGlobals->curtime <= 0.5) && (m_flDie - gpGlobals->curtime >= 0.3) )
|
||||
{
|
||||
CPASAttenuationFilter filter( this );
|
||||
EmitSound( filter, entindex(), "Snark.Squeak" );
|
||||
CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 256, 0.25 );
|
||||
}
|
||||
|
||||
// higher pitch as squeeker gets closer to detonation time
|
||||
float flpitch = 155.0 - 60.0 * ( (m_flDie - gpGlobals->curtime) / SQUEEK_DETONATE_DELAY );
|
||||
if ( flpitch < 80 )
|
||||
flpitch = 80;
|
||||
|
||||
if ( GetEnemy() != NULL )
|
||||
{
|
||||
if ( FVisible( GetEnemy() ) )
|
||||
{
|
||||
m_vecTarget = GetEnemy()->EyePosition() - GetAbsOrigin();
|
||||
VectorNormalize( m_vecTarget );
|
||||
}
|
||||
|
||||
float flVel = GetAbsVelocity().Length();
|
||||
float flAdj = 50.0 / ( flVel + 10.0 );
|
||||
|
||||
if ( flAdj > 1.2 )
|
||||
flAdj = 1.2;
|
||||
|
||||
// ALERT( at_console, "think : enemy\n");
|
||||
|
||||
// ALERT( at_console, "%.0f %.2f %.2f %.2f\n", flVel, m_vecTarget.x, m_vecTarget.y, m_vecTarget.z );
|
||||
|
||||
SetAbsVelocity( GetAbsVelocity() * flAdj + (m_vecTarget * 300) );
|
||||
}
|
||||
|
||||
if ( GetFlags() & FL_ONGROUND )
|
||||
{
|
||||
SetLocalAngularVelocity( QAngle( 0, 0, 0 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
QAngle angVel = GetLocalAngularVelocity();
|
||||
if ( angVel == QAngle( 0, 0, 0 ) )
|
||||
{
|
||||
angVel.x = random->RandomFloat( -100, 100 );
|
||||
angVel.z = random->RandomFloat( -100, 100 );
|
||||
SetLocalAngularVelocity( angVel );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ( GetAbsOrigin() - m_posPrev ).Length() < 1.0 )
|
||||
{
|
||||
Vector vecVel = GetAbsVelocity();
|
||||
vecVel.x = random->RandomFloat( -100, 100 );
|
||||
vecVel.y = random->RandomFloat( -100, 100 );
|
||||
SetAbsVelocity( vecVel );
|
||||
}
|
||||
|
||||
m_posPrev = GetAbsOrigin();
|
||||
|
||||
QAngle angles;
|
||||
VectorAngles( GetAbsVelocity(), angles );
|
||||
angles.z = 0;
|
||||
angles.x = 0;
|
||||
SetAbsAngles( angles );
|
||||
}
|
||||
|
||||
unsigned int CSnark::PhysicsSolidMaskForEntity( void ) const
|
||||
{
|
||||
unsigned int iMask = BaseClass::PhysicsSolidMaskForEntity();
|
||||
|
||||
iMask &= ~CONTENTS_MONSTERCLIP;
|
||||
|
||||
return iMask;
|
||||
}
|
||||
|
||||
|
||||
// Custom collision that provides a good bounce when we hit walls
|
||||
// and also gives gravity velocity so the snarks fall off of edges.
|
||||
void CSnark::ResolveFlyCollisionCustom( trace_t &trace, Vector &vecVelocity )
|
||||
{
|
||||
// Get the impact surface's friction.
|
||||
float flSurfaceFriction;
|
||||
physprops->GetPhysicsProperties( trace.surface.surfaceProps, NULL, NULL, &flSurfaceFriction, NULL );
|
||||
|
||||
Vector vecAbsVelocity = GetAbsVelocity();
|
||||
|
||||
// If we hit a wall
|
||||
if ( trace.plane.normal.z <= 0.7 ) // Floor
|
||||
{
|
||||
Vector vecDir = vecAbsVelocity;
|
||||
|
||||
float speed = vecDir.Length();
|
||||
|
||||
VectorNormalize( vecDir );
|
||||
|
||||
float hitDot = DotProduct( trace.plane.normal, -vecDir );
|
||||
|
||||
Vector vReflection = 2.0f * trace.plane.normal * hitDot + vecDir;
|
||||
|
||||
SetAbsVelocity( vReflection * speed * 0.6f );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Stop if on ground.
|
||||
// Get the total velocity (player + conveyors, etc.)
|
||||
VectorAdd( vecAbsVelocity, GetBaseVelocity(), vecVelocity );
|
||||
float flSpeedSqr = DotProduct( vecVelocity, vecVelocity );
|
||||
|
||||
// Verify that we have an entity.
|
||||
CBaseEntity *pEntity = trace.m_pEnt;
|
||||
Assert( pEntity );
|
||||
|
||||
if ( vecVelocity.z < ( 800 * gpGlobals->frametime ) )
|
||||
{
|
||||
vecAbsVelocity.z = 0.0f;
|
||||
|
||||
// Recompute speedsqr based on the new absvel
|
||||
VectorAdd( vecAbsVelocity, GetBaseVelocity(), vecVelocity );
|
||||
flSpeedSqr = DotProduct( vecVelocity, vecVelocity );
|
||||
}
|
||||
SetAbsVelocity( vecAbsVelocity );
|
||||
|
||||
if ( flSpeedSqr < ( 30 * 30 ) )
|
||||
{
|
||||
if ( pEntity->IsStandable() )
|
||||
{
|
||||
SetGroundEntity( pEntity );
|
||||
}
|
||||
|
||||
// Reset velocities.
|
||||
SetAbsVelocity( vec3_origin );
|
||||
SetLocalAngularVelocity( vec3_angle );
|
||||
}
|
||||
else
|
||||
{
|
||||
vecAbsVelocity += GetBaseVelocity();
|
||||
vecAbsVelocity *= ( 1.0f - trace.fraction ) * gpGlobals->frametime * flSurfaceFriction;
|
||||
PhysicsPushEntity( vecAbsVelocity, &trace );
|
||||
}
|
||||
}
|
||||
|
||||
void CSnark::SuperBounceTouch( CBaseEntity *pOther )
|
||||
{
|
||||
float flpitch;
|
||||
trace_t tr;
|
||||
tr = CBaseEntity::GetTouchTrace( );
|
||||
|
||||
// don't hit the guy that launched this grenade
|
||||
if ( GetOwnerEntity() && ( pOther == GetOwnerEntity() ) )
|
||||
return;
|
||||
|
||||
// at least until we've bounced once
|
||||
SetOwnerEntity( NULL );
|
||||
|
||||
QAngle angles = GetAbsAngles();
|
||||
angles.x = 0;
|
||||
angles.z = 0;
|
||||
SetAbsAngles( angles );
|
||||
|
||||
// avoid bouncing too much
|
||||
if ( m_flNextHit > gpGlobals->curtime)
|
||||
return;
|
||||
|
||||
// higher pitch as squeeker gets closer to detonation time
|
||||
flpitch = 155.0 - 60.0 * ( ( m_flDie - gpGlobals->curtime ) / SQUEEK_DETONATE_DELAY );
|
||||
|
||||
if ( pOther->m_takedamage && m_flNextAttack < gpGlobals->curtime )
|
||||
{
|
||||
// attack!
|
||||
|
||||
// make sure it's me who has touched them
|
||||
if ( tr.m_pEnt == pOther )
|
||||
{
|
||||
// and it's not another squeakgrenade
|
||||
if ( tr.m_pEnt->GetModelIndex() != GetModelIndex() )
|
||||
{
|
||||
// ALERT( at_console, "hit enemy\n");
|
||||
ClearMultiDamage();
|
||||
|
||||
Vector vecForward;
|
||||
AngleVectors( GetAbsAngles(), &vecForward );
|
||||
|
||||
if ( m_hOwner != NULL )
|
||||
{
|
||||
CTakeDamageInfo info( this, m_hOwner, sk_snark_dmg_bite.GetFloat(), DMG_SLASH );
|
||||
CalculateMeleeDamageForce( &info, vecForward, tr.endpos );
|
||||
pOther->DispatchTraceAttack( info, vecForward, &tr );
|
||||
}
|
||||
else
|
||||
{
|
||||
CTakeDamageInfo info( this, this, sk_snark_dmg_bite.GetFloat(), DMG_SLASH );
|
||||
CalculateMeleeDamageForce( &info, vecForward, tr.endpos );
|
||||
pOther->DispatchTraceAttack( info, vecForward, &tr );
|
||||
}
|
||||
|
||||
ApplyMultiDamage();
|
||||
|
||||
SetDamage( GetDamage() + sk_snark_dmg_pop.GetFloat() ); // add more explosion damage
|
||||
// m_flDie += 2.0; // add more life
|
||||
|
||||
// make bite sound
|
||||
CPASAttenuationFilter filter( this );
|
||||
CSoundParameters params;
|
||||
if ( GetParametersForSound( "Snark.Deploy", params, NULL ) )
|
||||
{
|
||||
EmitSound_t ep( params );
|
||||
ep.m_nPitch = (int)flpitch;
|
||||
|
||||
EmitSound( filter, entindex(), ep );
|
||||
}
|
||||
m_flNextAttack = gpGlobals->curtime + 0.5;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ALERT( at_console, "been hit\n");
|
||||
}
|
||||
}
|
||||
|
||||
m_flNextHit = gpGlobals->curtime + 0.1;
|
||||
m_flNextHunt = gpGlobals->curtime;
|
||||
|
||||
if ( g_pGameRules->IsMultiplayer() )
|
||||
{
|
||||
// in multiplayer, we limit how often snarks can make their bounce sounds to prevent overflows.
|
||||
if ( gpGlobals->curtime < m_flNextBounceSoundTime )
|
||||
{
|
||||
// too soon!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !( GetFlags() & FL_ONGROUND ) )
|
||||
{
|
||||
// play bounce sound
|
||||
CPASAttenuationFilter filter2( this );
|
||||
|
||||
CSoundParameters params;
|
||||
if ( GetParametersForSound( "Snark.Bounce", params, NULL ) )
|
||||
{
|
||||
EmitSound_t ep( params );
|
||||
ep.m_nPitch = (int)flpitch;
|
||||
|
||||
EmitSound( filter2, entindex(), ep );
|
||||
}
|
||||
|
||||
CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 256, 0.25 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// skittering sound
|
||||
CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 100, 0.1 );
|
||||
}
|
||||
|
||||
m_flNextBounceSoundTime = gpGlobals->curtime + 0.5;// half second.
|
||||
}
|
||||
|
||||
|
||||
bool CSnark::IsValidEnemy( CBaseEntity *pEnemy )
|
||||
{
|
||||
return CHL1BaseNPC::IsValidEnemy( pEnemy );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user