|
|
@ -46,14 +46,14 @@ |
|
|
|
|
|
|
|
|
|
|
|
// Movement constants
|
|
|
|
// Movement constants
|
|
|
|
|
|
|
|
|
|
|
|
#define LEECH_ACCELERATE 10 |
|
|
|
#define LEECH_ACCELERATE 10 |
|
|
|
#define LEECH_CHECK_DIST 45 |
|
|
|
#define LEECH_CHECK_DIST 45 |
|
|
|
#define LEECH_SWIM_SPEED 50 |
|
|
|
#define LEECH_SWIM_SPEED 50 |
|
|
|
#define LEECH_SWIM_ACCEL 80 |
|
|
|
#define LEECH_SWIM_ACCEL 80 |
|
|
|
#define LEECH_SWIM_DECEL 10 |
|
|
|
#define LEECH_SWIM_DECEL 10 |
|
|
|
#define LEECH_TURN_RATE 90 |
|
|
|
#define LEECH_TURN_RATE 90 |
|
|
|
#define LEECH_SIZEX 10 |
|
|
|
#define LEECH_SIZEX 10 |
|
|
|
#define LEECH_FRAMETIME 0.1 |
|
|
|
#define LEECH_FRAMETIME 0.1 |
|
|
|
|
|
|
|
|
|
|
|
#define DEBUG_BEAMS 0 |
|
|
|
#define DEBUG_BEAMS 0 |
|
|
|
|
|
|
|
|
|
|
@ -71,10 +71,10 @@ public: |
|
|
|
void EXPORT DeadThink( void ); |
|
|
|
void EXPORT DeadThink( void ); |
|
|
|
void Touch( CBaseEntity *pOther ) |
|
|
|
void Touch( CBaseEntity *pOther ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if ( pOther->IsPlayer() ) |
|
|
|
if( pOther->IsPlayer() ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// If the client is pushing me, give me some base velocity
|
|
|
|
// If the client is pushing me, give me some base velocity
|
|
|
|
if ( gpGlobals->trace_ent && gpGlobals->trace_ent == edict() ) |
|
|
|
if( gpGlobals->trace_ent && gpGlobals->trace_ent == edict() ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pev->basevelocity = pOther->pev->velocity; |
|
|
|
pev->basevelocity = pOther->pev->velocity; |
|
|
|
pev->flags |= FL_BASEVELOCITY; |
|
|
|
pev->flags |= FL_BASEVELOCITY; |
|
|
@ -84,8 +84,8 @@ public: |
|
|
|
|
|
|
|
|
|
|
|
void SetObjectCollisionBox( void ) |
|
|
|
void SetObjectCollisionBox( void ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pev->absmin = pev->origin + Vector(-8,-8,0); |
|
|
|
pev->absmin = pev->origin + Vector( -8, -8, 0 ); |
|
|
|
pev->absmax = pev->origin + Vector(8,8,2); |
|
|
|
pev->absmax = pev->origin + Vector( 8, 8, 2 ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void AttackSound( void ); |
|
|
|
void AttackSound( void ); |
|
|
@ -98,38 +98,38 @@ public: |
|
|
|
|
|
|
|
|
|
|
|
// Base entity functions
|
|
|
|
// Base entity functions
|
|
|
|
void HandleAnimEvent( MonsterEvent_t *pEvent ); |
|
|
|
void HandleAnimEvent( MonsterEvent_t *pEvent ); |
|
|
|
int BloodColor( void ) { return DONT_BLEED; } |
|
|
|
int BloodColor( void ) { return DONT_BLEED; } |
|
|
|
void Killed( entvars_t *pevAttacker, int iGib ); |
|
|
|
void Killed( entvars_t *pevAttacker, int iGib ); |
|
|
|
void Activate( void ); |
|
|
|
void Activate( void ); |
|
|
|
int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ); |
|
|
|
int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ); |
|
|
|
int Classify( void ) { return CLASS_INSECT; } |
|
|
|
int Classify( void ) { return CLASS_INSECT; } |
|
|
|
int IRelationship( CBaseEntity *pTarget ); |
|
|
|
int IRelationship( CBaseEntity *pTarget ); |
|
|
|
|
|
|
|
|
|
|
|
virtual int Save( CSave &save ); |
|
|
|
virtual int Save( CSave &save ); |
|
|
|
virtual int Restore( CRestore &restore ); |
|
|
|
virtual int Restore( CRestore &restore ); |
|
|
|
static TYPEDESCRIPTION m_SaveData[]; |
|
|
|
static TYPEDESCRIPTION m_SaveData[]; |
|
|
|
|
|
|
|
|
|
|
|
static const char *pAttackSounds[]; |
|
|
|
static const char *pAttackSounds[]; |
|
|
|
static const char *pAlertSounds[]; |
|
|
|
static const char *pAlertSounds[]; |
|
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
private: |
|
|
|
// UNDONE: Remove unused boid vars, do group behavior
|
|
|
|
// UNDONE: Remove unused boid vars, do group behavior
|
|
|
|
float m_flTurning;// is this boid turning?
|
|
|
|
float m_flTurning;// is this boid turning?
|
|
|
|
BOOL m_fPathBlocked;// TRUE if there is an obstacle ahead
|
|
|
|
BOOL m_fPathBlocked;// TRUE if there is an obstacle ahead
|
|
|
|
float m_flAccelerate; |
|
|
|
float m_flAccelerate; |
|
|
|
float m_obstacle; |
|
|
|
float m_obstacle; |
|
|
|
float m_top; |
|
|
|
float m_top; |
|
|
|
float m_bottom; |
|
|
|
float m_bottom; |
|
|
|
float m_height; |
|
|
|
float m_height; |
|
|
|
float m_waterTime; |
|
|
|
float m_waterTime; |
|
|
|
float m_sideTime; // Timer to randomly check clearance on sides
|
|
|
|
float m_sideTime; // Timer to randomly check clearance on sides
|
|
|
|
float m_zTime; |
|
|
|
float m_zTime; |
|
|
|
float m_stateTime; |
|
|
|
float m_stateTime; |
|
|
|
float m_attackSoundTime; |
|
|
|
float m_attackSoundTime; |
|
|
|
|
|
|
|
|
|
|
|
#if DEBUG_BEAMS |
|
|
|
#if DEBUG_BEAMS |
|
|
|
CBeam *m_pb; |
|
|
|
CBeam *m_pb; |
|
|
|
CBeam *m_pt; |
|
|
|
CBeam *m_pt; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -169,20 +169,20 @@ const char *CLeech::pAlertSounds[] = |
|
|
|
void CLeech::Spawn( void ) |
|
|
|
void CLeech::Spawn( void ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Precache(); |
|
|
|
Precache(); |
|
|
|
SET_MODEL(ENT(pev), "models/leech.mdl"); |
|
|
|
SET_MODEL( ENT( pev ), "models/leech.mdl" ); |
|
|
|
// Just for fun
|
|
|
|
// Just for fun
|
|
|
|
// SET_MODEL(ENT(pev), "models/icky.mdl");
|
|
|
|
// SET_MODEL( ENT( pev ), "models/icky.mdl" );
|
|
|
|
|
|
|
|
|
|
|
|
//UTIL_SetSize( pev, g_vecZero, g_vecZero );
|
|
|
|
//UTIL_SetSize( pev, g_vecZero, g_vecZero );
|
|
|
|
UTIL_SetSize( pev, Vector(-1,-1,0), Vector(1,1,2)); |
|
|
|
UTIL_SetSize( pev, Vector( -1, -1, 0 ), Vector( 1, 1, 2 ) ); |
|
|
|
// Don't push the minz down too much or the water check will fail because this entity is really point-sized
|
|
|
|
// Don't push the minz down too much or the water check will fail because this entity is really point-sized
|
|
|
|
pev->solid = SOLID_SLIDEBOX; |
|
|
|
pev->solid = SOLID_SLIDEBOX; |
|
|
|
pev->movetype = MOVETYPE_FLY; |
|
|
|
pev->movetype = MOVETYPE_FLY; |
|
|
|
SetBits(pev->flags, FL_SWIM); |
|
|
|
SetBits( pev->flags, FL_SWIM ); |
|
|
|
pev->health = gSkillData.leechHealth; |
|
|
|
pev->health = gSkillData.leechHealth; |
|
|
|
|
|
|
|
|
|
|
|
m_flFieldOfView = -0.5; // 180 degree FOV
|
|
|
|
m_flFieldOfView = -0.5; // 180 degree FOV
|
|
|
|
m_flDistLook = 750; |
|
|
|
m_flDistLook = 750; |
|
|
|
MonsterInit(); |
|
|
|
MonsterInit(); |
|
|
|
SetThink( &CLeech::SwimThink ); |
|
|
|
SetThink( &CLeech::SwimThink ); |
|
|
|
SetUse( NULL ); |
|
|
|
SetUse( NULL ); |
|
|
@ -204,12 +204,12 @@ void CLeech::Activate( void ) |
|
|
|
void CLeech::RecalculateWaterlevel( void ) |
|
|
|
void CLeech::RecalculateWaterlevel( void ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Calculate boundaries
|
|
|
|
// Calculate boundaries
|
|
|
|
Vector vecTest = pev->origin - Vector(0,0,400); |
|
|
|
Vector vecTest = pev->origin - Vector( 0, 0, 400 ); |
|
|
|
|
|
|
|
|
|
|
|
TraceResult tr; |
|
|
|
TraceResult tr; |
|
|
|
|
|
|
|
|
|
|
|
UTIL_TraceLine(pev->origin, vecTest, missile, edict(), &tr); |
|
|
|
UTIL_TraceLine( pev->origin, vecTest, missile, edict(), &tr ); |
|
|
|
if ( tr.flFraction != 1.0 ) |
|
|
|
if( tr.flFraction != 1.0 ) |
|
|
|
m_bottom = tr.vecEndPos.z + 1; |
|
|
|
m_bottom = tr.vecEndPos.z + 1; |
|
|
|
else |
|
|
|
else |
|
|
|
m_bottom = vecTest.z; |
|
|
|
m_bottom = vecTest.z; |
|
|
@ -227,7 +227,7 @@ void CLeech::RecalculateWaterlevel( void ) |
|
|
|
void CLeech::SwitchLeechState( void ) |
|
|
|
void CLeech::SwitchLeechState( void ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
m_stateTime = gpGlobals->time + RANDOM_FLOAT( 3, 6 ); |
|
|
|
m_stateTime = gpGlobals->time + RANDOM_FLOAT( 3, 6 ); |
|
|
|
if ( m_MonsterState == MONSTERSTATE_COMBAT ) |
|
|
|
if( m_MonsterState == MONSTERSTATE_COMBAT ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
m_hEnemy = NULL; |
|
|
|
m_hEnemy = NULL; |
|
|
|
SetState( MONSTERSTATE_IDLE ); |
|
|
|
SetState( MONSTERSTATE_IDLE ); |
|
|
@ -238,7 +238,7 @@ void CLeech::SwitchLeechState( void ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Look( m_flDistLook ); |
|
|
|
Look( m_flDistLook ); |
|
|
|
CBaseEntity *pEnemy = BestVisibleEnemy(); |
|
|
|
CBaseEntity *pEnemy = BestVisibleEnemy(); |
|
|
|
if ( pEnemy && pEnemy->pev->waterlevel != 0 ) |
|
|
|
if( pEnemy && pEnemy->pev->waterlevel != 0 ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
m_hEnemy = pEnemy; |
|
|
|
m_hEnemy = pEnemy; |
|
|
|
SetState( MONSTERSTATE_COMBAT ); |
|
|
|
SetState( MONSTERSTATE_COMBAT ); |
|
|
@ -250,36 +250,36 @@ void CLeech::SwitchLeechState( void ) |
|
|
|
|
|
|
|
|
|
|
|
int CLeech::IRelationship( CBaseEntity *pTarget ) |
|
|
|
int CLeech::IRelationship( CBaseEntity *pTarget ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if ( pTarget->IsPlayer() ) |
|
|
|
if( pTarget->IsPlayer() ) |
|
|
|
return R_DL; |
|
|
|
return R_DL; |
|
|
|
return CBaseMonster::IRelationship( pTarget ); |
|
|
|
return CBaseMonster::IRelationship( pTarget ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void CLeech::AttackSound( void ) |
|
|
|
void CLeech::AttackSound( void ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if ( gpGlobals->time > m_attackSoundTime ) |
|
|
|
if( gpGlobals->time > m_attackSoundTime ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
EMIT_SOUND_DYN ( ENT(pev), CHAN_VOICE, pAttackSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackSounds)-1) ], 1.0, ATTN_NORM, 0, PITCH_NORM ); |
|
|
|
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pAttackSounds[RANDOM_LONG( 0, ARRAYSIZE( pAttackSounds ) - 1 )], 1.0, ATTN_NORM, 0, PITCH_NORM ); |
|
|
|
m_attackSoundTime = gpGlobals->time + 0.5; |
|
|
|
m_attackSoundTime = gpGlobals->time + 0.5; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void CLeech::AlertSound( void ) |
|
|
|
void CLeech::AlertSound( void ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
EMIT_SOUND_DYN ( ENT(pev), CHAN_VOICE, pAlertSounds[ RANDOM_LONG(0,ARRAYSIZE(pAlertSounds)-1) ], 1.0, ATTN_NORM * 0.5, 0, PITCH_NORM ); |
|
|
|
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, pAlertSounds[RANDOM_LONG( 0, ARRAYSIZE( pAlertSounds ) - 1 )], 1.0, ATTN_NORM * 0.5, 0, PITCH_NORM ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void CLeech::Precache( void ) |
|
|
|
void CLeech::Precache( void ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int i; |
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
//PRECACHE_MODEL("models/icky.mdl");
|
|
|
|
//PRECACHE_MODEL( "models/icky.mdl" );
|
|
|
|
PRECACHE_MODEL("models/leech.mdl"); |
|
|
|
PRECACHE_MODEL( "models/leech.mdl" ); |
|
|
|
|
|
|
|
|
|
|
|
for ( i = 0; i < ARRAYSIZE( pAttackSounds ); i++ ) |
|
|
|
for( i = 0; i < ARRAYSIZE( pAttackSounds ); i++ ) |
|
|
|
PRECACHE_SOUND((char *)pAttackSounds[i]); |
|
|
|
PRECACHE_SOUND( (char *)pAttackSounds[i] ); |
|
|
|
for ( i = 0; i < ARRAYSIZE( pAlertSounds ); i++ ) |
|
|
|
for( i = 0; i < ARRAYSIZE( pAlertSounds ); i++ ) |
|
|
|
PRECACHE_SOUND((char *)pAlertSounds[i]); |
|
|
|
PRECACHE_SOUND( (char *)pAlertSounds[i] ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int CLeech::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ) |
|
|
|
int CLeech::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ) |
|
|
@ -287,9 +287,9 @@ int CLeech::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float f |
|
|
|
pev->velocity = g_vecZero; |
|
|
|
pev->velocity = g_vecZero; |
|
|
|
|
|
|
|
|
|
|
|
// Nudge the leech away from the damage
|
|
|
|
// Nudge the leech away from the damage
|
|
|
|
if ( pevInflictor ) |
|
|
|
if( pevInflictor ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pev->velocity = (pev->origin - pevInflictor->origin).Normalize() * 25; |
|
|
|
pev->velocity = ( pev->origin - pevInflictor->origin ).Normalize() * 25; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return CBaseMonster::TakeDamage( pevInflictor, pevAttacker, flDamage, bitsDamageType ); |
|
|
|
return CBaseMonster::TakeDamage( pevInflictor, pevAttacker, flDamage, bitsDamageType ); |
|
|
@ -304,7 +304,7 @@ void CLeech::HandleAnimEvent( MonsterEvent_t *pEvent ) |
|
|
|
CBaseEntity *pEnemy; |
|
|
|
CBaseEntity *pEnemy; |
|
|
|
|
|
|
|
|
|
|
|
pEnemy = m_hEnemy; |
|
|
|
pEnemy = m_hEnemy; |
|
|
|
if ( pEnemy != NULL ) |
|
|
|
if( pEnemy != NULL ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Vector dir, face; |
|
|
|
Vector dir, face; |
|
|
|
|
|
|
|
|
|
|
@ -315,7 +315,7 @@ void CLeech::HandleAnimEvent( MonsterEvent_t *pEvent ) |
|
|
|
dir = dir.Normalize(); |
|
|
|
dir = dir.Normalize(); |
|
|
|
face = face.Normalize(); |
|
|
|
face = face.Normalize(); |
|
|
|
|
|
|
|
|
|
|
|
if ( DotProduct(dir, face) > 0.9 ) // Only take damage if the leech is facing the prey
|
|
|
|
if( DotProduct( dir, face ) > 0.9 ) // Only take damage if the leech is facing the prey
|
|
|
|
pEnemy->TakeDamage( pev, pev, gSkillData.leechDmgBite, DMG_SLASH ); |
|
|
|
pEnemy->TakeDamage( pev, pev, gSkillData.leechDmgBite, DMG_SLASH ); |
|
|
|
} |
|
|
|
} |
|
|
|
m_stateTime -= 2; |
|
|
|
m_stateTime -= 2; |
|
|
@ -333,7 +333,7 @@ void CLeech::MakeVectors( void ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Vector tmp = pev->angles; |
|
|
|
Vector tmp = pev->angles; |
|
|
|
tmp.x = -tmp.x; |
|
|
|
tmp.x = -tmp.x; |
|
|
|
UTIL_MakeVectors ( tmp ); |
|
|
|
UTIL_MakeVectors( tmp ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
@ -341,8 +341,8 @@ void CLeech::MakeVectors( void ) |
|
|
|
//
|
|
|
|
//
|
|
|
|
float CLeech::ObstacleDistance( CBaseEntity *pTarget ) |
|
|
|
float CLeech::ObstacleDistance( CBaseEntity *pTarget ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
TraceResult tr; |
|
|
|
TraceResult tr; |
|
|
|
Vector vecTest; |
|
|
|
Vector vecTest; |
|
|
|
|
|
|
|
|
|
|
|
// use VELOCITY, not angles, not all boids point the direction they are flying
|
|
|
|
// use VELOCITY, not angles, not all boids point the direction they are flying
|
|
|
|
//Vector vecDir = UTIL_VecToAngles( pev->velocity );
|
|
|
|
//Vector vecDir = UTIL_VecToAngles( pev->velocity );
|
|
|
@ -350,58 +350,58 @@ float CLeech::ObstacleDistance( CBaseEntity *pTarget ) |
|
|
|
|
|
|
|
|
|
|
|
// check for obstacle ahead
|
|
|
|
// check for obstacle ahead
|
|
|
|
vecTest = pev->origin + gpGlobals->v_forward * LEECH_CHECK_DIST; |
|
|
|
vecTest = pev->origin + gpGlobals->v_forward * LEECH_CHECK_DIST; |
|
|
|
UTIL_TraceLine(pev->origin, vecTest, missile, edict(), &tr); |
|
|
|
UTIL_TraceLine( pev->origin, vecTest, missile, edict(), &tr ); |
|
|
|
|
|
|
|
|
|
|
|
if ( tr.fStartSolid ) |
|
|
|
if( tr.fStartSolid ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pev->speed = -LEECH_SWIM_SPEED * 0.5; |
|
|
|
pev->speed = -LEECH_SWIM_SPEED * 0.5; |
|
|
|
// ALERT( at_console, "Stuck from (%f %f %f) to (%f %f %f)\n", pev->oldorigin.x, pev->oldorigin.y, pev->oldorigin.z, pev->origin.x, pev->origin.y, pev->origin.z );
|
|
|
|
//ALERT( at_console, "Stuck from (%f %f %f) to (%f %f %f)\n", pev->oldorigin.x, pev->oldorigin.y, pev->oldorigin.z, pev->origin.x, pev->origin.y, pev->origin.z );
|
|
|
|
// UTIL_SetOrigin( pev, pev->oldorigin );
|
|
|
|
//UTIL_SetOrigin( pev, pev->oldorigin );
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if ( tr.flFraction != 1.0 ) |
|
|
|
if( tr.flFraction != 1.0 ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if ( (pTarget == NULL || tr.pHit != pTarget->edict()) ) |
|
|
|
if( ( pTarget == NULL || tr.pHit != pTarget->edict() ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return tr.flFraction; |
|
|
|
return tr.flFraction; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
if ( fabs(m_height - pev->origin.z) > 10 ) |
|
|
|
if( fabs( m_height - pev->origin.z ) > 10 ) |
|
|
|
return tr.flFraction; |
|
|
|
return tr.flFraction; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if ( m_sideTime < gpGlobals->time ) |
|
|
|
if( m_sideTime < gpGlobals->time ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// extra wide checks
|
|
|
|
// extra wide checks
|
|
|
|
vecTest = pev->origin + gpGlobals->v_right * LEECH_SIZEX * 2 + gpGlobals->v_forward * LEECH_CHECK_DIST; |
|
|
|
vecTest = pev->origin + gpGlobals->v_right * LEECH_SIZEX * 2 + gpGlobals->v_forward * LEECH_CHECK_DIST; |
|
|
|
UTIL_TraceLine(pev->origin, vecTest, missile, edict(), &tr); |
|
|
|
UTIL_TraceLine( pev->origin, vecTest, missile, edict(), &tr ); |
|
|
|
if (tr.flFraction != 1.0) |
|
|
|
if( tr.flFraction != 1.0 ) |
|
|
|
return tr.flFraction; |
|
|
|
return tr.flFraction; |
|
|
|
|
|
|
|
|
|
|
|
vecTest = pev->origin - gpGlobals->v_right * LEECH_SIZEX * 2 + gpGlobals->v_forward * LEECH_CHECK_DIST; |
|
|
|
vecTest = pev->origin - gpGlobals->v_right * LEECH_SIZEX * 2 + gpGlobals->v_forward * LEECH_CHECK_DIST; |
|
|
|
UTIL_TraceLine(pev->origin, vecTest, missile, edict(), &tr); |
|
|
|
UTIL_TraceLine( pev->origin, vecTest, missile, edict(), &tr ); |
|
|
|
if (tr.flFraction != 1.0) |
|
|
|
if( tr.flFraction != 1.0 ) |
|
|
|
return tr.flFraction; |
|
|
|
return tr.flFraction; |
|
|
|
|
|
|
|
|
|
|
|
// Didn't hit either side, so stop testing for another 0.5 - 1 seconds
|
|
|
|
// Didn't hit either side, so stop testing for another 0.5 - 1 seconds
|
|
|
|
m_sideTime = gpGlobals->time + RANDOM_FLOAT(0.5,1); |
|
|
|
m_sideTime = gpGlobals->time + RANDOM_FLOAT( 0.5, 1 ); |
|
|
|
} |
|
|
|
} |
|
|
|
return 1.0; |
|
|
|
return 1.0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void CLeech::DeadThink( void ) |
|
|
|
void CLeech::DeadThink( void ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if ( m_fSequenceFinished ) |
|
|
|
if( m_fSequenceFinished ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if ( m_Activity == ACT_DIEFORWARD ) |
|
|
|
if( m_Activity == ACT_DIEFORWARD ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
SetThink( NULL ); |
|
|
|
SetThink( NULL ); |
|
|
|
StopAnimation(); |
|
|
|
StopAnimation(); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
else if ( pev->flags & FL_ONGROUND ) |
|
|
|
else if( pev->flags & FL_ONGROUND ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pev->solid = SOLID_NOT; |
|
|
|
pev->solid = SOLID_NOT; |
|
|
|
SetActivity(ACT_DIEFORWARD); |
|
|
|
SetActivity(ACT_DIEFORWARD); |
|
|
@ -411,13 +411,13 @@ void CLeech::DeadThink( void ) |
|
|
|
pev->nextthink = gpGlobals->time + 0.1; |
|
|
|
pev->nextthink = gpGlobals->time + 0.1; |
|
|
|
|
|
|
|
|
|
|
|
// Apply damage velocity, but keep out of the walls
|
|
|
|
// Apply damage velocity, but keep out of the walls
|
|
|
|
if ( pev->velocity.x != 0 || pev->velocity.y != 0 ) |
|
|
|
if( pev->velocity.x != 0 || pev->velocity.y != 0 ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
TraceResult tr; |
|
|
|
TraceResult tr; |
|
|
|
|
|
|
|
|
|
|
|
// Look 0.5 seconds ahead
|
|
|
|
// Look 0.5 seconds ahead
|
|
|
|
UTIL_TraceLine(pev->origin, pev->origin + pev->velocity * 0.5, missile, edict(), &tr); |
|
|
|
UTIL_TraceLine( pev->origin, pev->origin + pev->velocity * 0.5, missile, edict(), &tr ); |
|
|
|
if (tr.flFraction != 1.0) |
|
|
|
if( tr.flFraction != 1.0 ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pev->velocity.x = 0; |
|
|
|
pev->velocity.x = 0; |
|
|
|
pev->velocity.y = 0; |
|
|
|
pev->velocity.y = 0; |
|
|
@ -427,27 +427,27 @@ void CLeech::DeadThink( void ) |
|
|
|
|
|
|
|
|
|
|
|
void CLeech::UpdateMotion( void ) |
|
|
|
void CLeech::UpdateMotion( void ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
float flapspeed = (pev->speed - m_flAccelerate) / LEECH_ACCELERATE; |
|
|
|
float flapspeed = ( pev->speed - m_flAccelerate ) / LEECH_ACCELERATE; |
|
|
|
m_flAccelerate = m_flAccelerate * 0.8 + pev->speed * 0.2; |
|
|
|
m_flAccelerate = m_flAccelerate * 0.8 + pev->speed * 0.2; |
|
|
|
|
|
|
|
|
|
|
|
if (flapspeed < 0) |
|
|
|
if( flapspeed < 0 ) |
|
|
|
flapspeed = -flapspeed; |
|
|
|
flapspeed = -flapspeed; |
|
|
|
flapspeed += 1.0; |
|
|
|
flapspeed += 1.0; |
|
|
|
if (flapspeed < 0.5) |
|
|
|
if( flapspeed < 0.5 ) |
|
|
|
flapspeed = 0.5; |
|
|
|
flapspeed = 0.5; |
|
|
|
if (flapspeed > 1.9) |
|
|
|
if( flapspeed > 1.9 ) |
|
|
|
flapspeed = 1.9; |
|
|
|
flapspeed = 1.9; |
|
|
|
|
|
|
|
|
|
|
|
pev->framerate = flapspeed; |
|
|
|
pev->framerate = flapspeed; |
|
|
|
|
|
|
|
|
|
|
|
if ( !m_fPathBlocked ) |
|
|
|
if( !m_fPathBlocked ) |
|
|
|
pev->avelocity.y = pev->ideal_yaw; |
|
|
|
pev->avelocity.y = pev->ideal_yaw; |
|
|
|
else |
|
|
|
else |
|
|
|
pev->avelocity.y = pev->ideal_yaw * m_obstacle; |
|
|
|
pev->avelocity.y = pev->ideal_yaw * m_obstacle; |
|
|
|
|
|
|
|
|
|
|
|
if ( pev->avelocity.y > 150 ) |
|
|
|
if( pev->avelocity.y > 150 ) |
|
|
|
m_IdealActivity = ACT_TURN_LEFT; |
|
|
|
m_IdealActivity = ACT_TURN_LEFT; |
|
|
|
else if ( pev->avelocity.y < -150 ) |
|
|
|
else if( pev->avelocity.y < -150 ) |
|
|
|
m_IdealActivity = ACT_TURN_RIGHT; |
|
|
|
m_IdealActivity = ACT_TURN_RIGHT; |
|
|
|
else |
|
|
|
else |
|
|
|
m_IdealActivity = ACT_SWIM; |
|
|
|
m_IdealActivity = ACT_SWIM; |
|
|
@ -456,9 +456,9 @@ void CLeech::UpdateMotion( void ) |
|
|
|
float targetPitch, delta; |
|
|
|
float targetPitch, delta; |
|
|
|
delta = m_height - pev->origin.z; |
|
|
|
delta = m_height - pev->origin.z; |
|
|
|
|
|
|
|
|
|
|
|
if ( delta < -10 ) |
|
|
|
if( delta < -10 ) |
|
|
|
targetPitch = -30; |
|
|
|
targetPitch = -30; |
|
|
|
else if ( delta > 10 ) |
|
|
|
else if( delta > 10 ) |
|
|
|
targetPitch = 30; |
|
|
|
targetPitch = 30; |
|
|
|
else |
|
|
|
else |
|
|
|
targetPitch = 0; |
|
|
|
targetPitch = 0; |
|
|
@ -466,13 +466,13 @@ void CLeech::UpdateMotion( void ) |
|
|
|
pev->angles.x = UTIL_Approach( targetPitch, pev->angles.x, 60 * LEECH_FRAMETIME ); |
|
|
|
pev->angles.x = UTIL_Approach( targetPitch, pev->angles.x, 60 * LEECH_FRAMETIME ); |
|
|
|
|
|
|
|
|
|
|
|
// bank
|
|
|
|
// bank
|
|
|
|
pev->avelocity.z = - (pev->angles.z + (pev->avelocity.y * 0.25)); |
|
|
|
pev->avelocity.z = -( pev->angles.z + ( pev->avelocity.y * 0.25 ) ); |
|
|
|
|
|
|
|
|
|
|
|
if ( m_MonsterState == MONSTERSTATE_COMBAT && HasConditions( bits_COND_CAN_MELEE_ATTACK1 ) ) |
|
|
|
if( m_MonsterState == MONSTERSTATE_COMBAT && HasConditions( bits_COND_CAN_MELEE_ATTACK1 ) ) |
|
|
|
m_IdealActivity = ACT_MELEE_ATTACK1; |
|
|
|
m_IdealActivity = ACT_MELEE_ATTACK1; |
|
|
|
|
|
|
|
|
|
|
|
// Out of water check
|
|
|
|
// Out of water check
|
|
|
|
if ( !pev->waterlevel ) |
|
|
|
if( !pev->waterlevel ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pev->movetype = MOVETYPE_TOSS; |
|
|
|
pev->movetype = MOVETYPE_TOSS; |
|
|
|
m_IdealActivity = ACT_TWITCH; |
|
|
|
m_IdealActivity = ACT_TWITCH; |
|
|
@ -482,10 +482,10 @@ void CLeech::UpdateMotion( void ) |
|
|
|
pev->angles.z = 0; |
|
|
|
pev->angles.z = 0; |
|
|
|
pev->angles.x = 0; |
|
|
|
pev->angles.x = 0; |
|
|
|
|
|
|
|
|
|
|
|
if ( pev->framerate < 1.0 ) |
|
|
|
if( pev->framerate < 1.0 ) |
|
|
|
pev->framerate = 1.0; |
|
|
|
pev->framerate = 1.0; |
|
|
|
} |
|
|
|
} |
|
|
|
else if ( pev->movetype == MOVETYPE_TOSS ) |
|
|
|
else if( pev->movetype == MOVETYPE_TOSS ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pev->movetype = MOVETYPE_FLY; |
|
|
|
pev->movetype = MOVETYPE_FLY; |
|
|
|
pev->flags &= ~FL_ONGROUND; |
|
|
|
pev->flags &= ~FL_ONGROUND; |
|
|
@ -493,25 +493,25 @@ void CLeech::UpdateMotion( void ) |
|
|
|
m_waterTime = gpGlobals->time + 2; // Recalc again soon, water may be rising
|
|
|
|
m_waterTime = gpGlobals->time + 2; // Recalc again soon, water may be rising
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if ( m_Activity != m_IdealActivity ) |
|
|
|
if( m_Activity != m_IdealActivity ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
SetActivity ( m_IdealActivity ); |
|
|
|
SetActivity( m_IdealActivity ); |
|
|
|
} |
|
|
|
} |
|
|
|
float flInterval = StudioFrameAdvance(); |
|
|
|
float flInterval = StudioFrameAdvance(); |
|
|
|
DispatchAnimEvents ( flInterval ); |
|
|
|
DispatchAnimEvents( flInterval ); |
|
|
|
#if DEBUG_BEAMS |
|
|
|
#if DEBUG_BEAMS |
|
|
|
if ( !m_pb ) |
|
|
|
if( !m_pb ) |
|
|
|
m_pb = CBeam::BeamCreate( "sprites/laserbeam.spr", 5 ); |
|
|
|
m_pb = CBeam::BeamCreate( "sprites/laserbeam.spr", 5 ); |
|
|
|
if ( !m_pt ) |
|
|
|
if( !m_pt ) |
|
|
|
m_pt = CBeam::BeamCreate( "sprites/laserbeam.spr", 5 ); |
|
|
|
m_pt = CBeam::BeamCreate( "sprites/laserbeam.spr", 5 ); |
|
|
|
m_pb->PointsInit( pev->origin, pev->origin + gpGlobals->v_forward * LEECH_CHECK_DIST ); |
|
|
|
m_pb->PointsInit( pev->origin, pev->origin + gpGlobals->v_forward * LEECH_CHECK_DIST ); |
|
|
|
m_pt->PointsInit( pev->origin, pev->origin - gpGlobals->v_right * (pev->avelocity.y*0.25) ); |
|
|
|
m_pt->PointsInit( pev->origin, pev->origin - gpGlobals->v_right * ( pev->avelocity.y * 0.25 ) ); |
|
|
|
if ( m_fPathBlocked ) |
|
|
|
if( m_fPathBlocked ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
float color = m_obstacle * 30; |
|
|
|
float color = m_obstacle * 30; |
|
|
|
if ( m_obstacle == 1.0 ) |
|
|
|
if( m_obstacle == 1.0 ) |
|
|
|
color = 0; |
|
|
|
color = 0; |
|
|
|
if ( color > 255 ) |
|
|
|
if( color > 255 ) |
|
|
|
color = 255; |
|
|
|
color = 255; |
|
|
|
m_pb->SetColor( 255, (int)color, (int)color ); |
|
|
|
m_pb->SetColor( 255, (int)color, (int)color ); |
|
|
|
} |
|
|
|
} |
|
|
@ -523,16 +523,16 @@ void CLeech::UpdateMotion( void ) |
|
|
|
|
|
|
|
|
|
|
|
void CLeech::SwimThink( void ) |
|
|
|
void CLeech::SwimThink( void ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
TraceResult tr; |
|
|
|
TraceResult tr; |
|
|
|
float flLeftSide; |
|
|
|
float flLeftSide; |
|
|
|
float flRightSide; |
|
|
|
float flRightSide; |
|
|
|
float targetSpeed; |
|
|
|
float targetSpeed; |
|
|
|
float targetYaw = 0; |
|
|
|
float targetYaw = 0; |
|
|
|
CBaseEntity *pTarget; |
|
|
|
CBaseEntity *pTarget; |
|
|
|
|
|
|
|
|
|
|
|
if ( FNullEnt( FIND_CLIENT_IN_PVS( edict() ) ) ) |
|
|
|
if( FNullEnt( FIND_CLIENT_IN_PVS( edict() ) ) ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pev->nextthink = gpGlobals->time + RANDOM_FLOAT(1,1.5); |
|
|
|
pev->nextthink = gpGlobals->time + RANDOM_FLOAT( 1, 1.5 ); |
|
|
|
pev->velocity = g_vecZero; |
|
|
|
pev->velocity = g_vecZero; |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
@ -541,10 +541,10 @@ void CLeech::SwimThink( void ) |
|
|
|
|
|
|
|
|
|
|
|
targetSpeed = LEECH_SWIM_SPEED; |
|
|
|
targetSpeed = LEECH_SWIM_SPEED; |
|
|
|
|
|
|
|
|
|
|
|
if ( m_waterTime < gpGlobals->time ) |
|
|
|
if( m_waterTime < gpGlobals->time ) |
|
|
|
RecalculateWaterlevel(); |
|
|
|
RecalculateWaterlevel(); |
|
|
|
|
|
|
|
|
|
|
|
if ( m_stateTime < gpGlobals->time ) |
|
|
|
if( m_stateTime < gpGlobals->time ) |
|
|
|
SwitchLeechState(); |
|
|
|
SwitchLeechState(); |
|
|
|
|
|
|
|
|
|
|
|
ClearConditions( bits_COND_CAN_MELEE_ATTACK1 ); |
|
|
|
ClearConditions( bits_COND_CAN_MELEE_ATTACK1 ); |
|
|
@ -552,47 +552,47 @@ void CLeech::SwimThink( void ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
case MONSTERSTATE_COMBAT: |
|
|
|
case MONSTERSTATE_COMBAT: |
|
|
|
pTarget = m_hEnemy; |
|
|
|
pTarget = m_hEnemy; |
|
|
|
if ( !pTarget ) |
|
|
|
if( !pTarget ) |
|
|
|
SwitchLeechState(); |
|
|
|
SwitchLeechState(); |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Chase the enemy's eyes
|
|
|
|
// Chase the enemy's eyes
|
|
|
|
m_height = pTarget->pev->origin.z + pTarget->pev->view_ofs.z - 5; |
|
|
|
m_height = pTarget->pev->origin.z + pTarget->pev->view_ofs.z - 5; |
|
|
|
// Clip to viable water area
|
|
|
|
// Clip to viable water area
|
|
|
|
if ( m_height < m_bottom ) |
|
|
|
if( m_height < m_bottom ) |
|
|
|
m_height = m_bottom; |
|
|
|
m_height = m_bottom; |
|
|
|
else if ( m_height > m_top ) |
|
|
|
else if( m_height > m_top ) |
|
|
|
m_height = m_top; |
|
|
|
m_height = m_top; |
|
|
|
Vector location = pTarget->pev->origin - pev->origin; |
|
|
|
Vector location = pTarget->pev->origin - pev->origin; |
|
|
|
location.z += (pTarget->pev->view_ofs.z); |
|
|
|
location.z += (pTarget->pev->view_ofs.z); |
|
|
|
if ( location.Length() < 40 ) |
|
|
|
if( location.Length() < 40 ) |
|
|
|
SetConditions( bits_COND_CAN_MELEE_ATTACK1 ); |
|
|
|
SetConditions( bits_COND_CAN_MELEE_ATTACK1 ); |
|
|
|
// Turn towards target ent
|
|
|
|
// Turn towards target ent
|
|
|
|
targetYaw = UTIL_VecToYaw( location ); |
|
|
|
targetYaw = UTIL_VecToYaw( location ); |
|
|
|
|
|
|
|
|
|
|
|
targetYaw = UTIL_AngleDiff( targetYaw, UTIL_AngleMod( pev->angles.y ) ); |
|
|
|
targetYaw = UTIL_AngleDiff( targetYaw, UTIL_AngleMod( pev->angles.y ) ); |
|
|
|
|
|
|
|
|
|
|
|
if ( targetYaw < (-LEECH_TURN_RATE*0.75) ) |
|
|
|
if( targetYaw < ( -LEECH_TURN_RATE * 0.75 ) ) |
|
|
|
targetYaw = (-LEECH_TURN_RATE*0.75); |
|
|
|
targetYaw = ( -LEECH_TURN_RATE * 0.75 ); |
|
|
|
else if ( targetYaw > (LEECH_TURN_RATE*0.75) ) |
|
|
|
else if( targetYaw > ( LEECH_TURN_RATE * 0.75 ) ) |
|
|
|
targetYaw = (LEECH_TURN_RATE*0.75); |
|
|
|
targetYaw = ( LEECH_TURN_RATE * 0.75 ); |
|
|
|
else |
|
|
|
else |
|
|
|
targetSpeed *= 2; |
|
|
|
targetSpeed *= 2; |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
default: |
|
|
|
default: |
|
|
|
if ( m_zTime < gpGlobals->time ) |
|
|
|
if( m_zTime < gpGlobals->time ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
float newHeight = RANDOM_FLOAT( m_bottom, m_top ); |
|
|
|
float newHeight = RANDOM_FLOAT( m_bottom, m_top ); |
|
|
|
m_height = 0.5 * m_height + 0.5 * newHeight; |
|
|
|
m_height = 0.5 * m_height + 0.5 * newHeight; |
|
|
|
m_zTime = gpGlobals->time + RANDOM_FLOAT( 1, 4 ); |
|
|
|
m_zTime = gpGlobals->time + RANDOM_FLOAT( 1, 4 ); |
|
|
|
} |
|
|
|
} |
|
|
|
if ( RANDOM_LONG( 0, 100 ) < 10 ) |
|
|
|
if( RANDOM_LONG( 0, 100 ) < 10 ) |
|
|
|
targetYaw = RANDOM_LONG( -30, 30 ); |
|
|
|
targetYaw = RANDOM_LONG( -30, 30 ); |
|
|
|
pTarget = NULL; |
|
|
|
pTarget = NULL; |
|
|
|
|
|
|
|
|
|
|
|
// oldorigin test
|
|
|
|
// oldorigin test
|
|
|
|
if ( (pev->origin - pev->oldorigin).Length() < 1 ) |
|
|
|
if( ( pev->origin - pev->oldorigin ).Length() < 1 ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// If leech didn't move, there must be something blocking it, so try to turn
|
|
|
|
// If leech didn't move, there must be something blocking it, so try to turn
|
|
|
|
m_sideTime = 0; |
|
|
|
m_sideTime = 0; |
|
|
@ -602,14 +602,14 @@ void CLeech::SwimThink( void ) |
|
|
|
|
|
|
|
|
|
|
|
m_obstacle = ObstacleDistance( pTarget ); |
|
|
|
m_obstacle = ObstacleDistance( pTarget ); |
|
|
|
pev->oldorigin = pev->origin; |
|
|
|
pev->oldorigin = pev->origin; |
|
|
|
if ( m_obstacle < 0.1 ) |
|
|
|
if( m_obstacle < 0.1 ) |
|
|
|
m_obstacle = 0.1; |
|
|
|
m_obstacle = 0.1; |
|
|
|
|
|
|
|
|
|
|
|
// is the way ahead clear?
|
|
|
|
// is the way ahead clear?
|
|
|
|
if ( m_obstacle == 1.0 ) |
|
|
|
if( m_obstacle == 1.0 ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// if the leech is turning, stop the trend.
|
|
|
|
// if the leech is turning, stop the trend.
|
|
|
|
if ( m_flTurning != 0 ) |
|
|
|
if( m_flTurning != 0 ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
m_flTurning = 0; |
|
|
|
m_flTurning = 0; |
|
|
|
} |
|
|
|
} |
|
|
@ -625,55 +625,55 @@ void CLeech::SwimThink( void ) |
|
|
|
// IF we get this far in the function, the leader's path is blocked!
|
|
|
|
// IF we get this far in the function, the leader's path is blocked!
|
|
|
|
m_fPathBlocked = TRUE; |
|
|
|
m_fPathBlocked = TRUE; |
|
|
|
|
|
|
|
|
|
|
|
if ( m_flTurning == 0 )// something in the way and leech is not already turning to avoid
|
|
|
|
if( m_flTurning == 0 )// something in the way and leech is not already turning to avoid
|
|
|
|
{ |
|
|
|
{ |
|
|
|
Vector vecTest; |
|
|
|
Vector vecTest; |
|
|
|
// measure clearance on left and right to pick the best dir to turn
|
|
|
|
// measure clearance on left and right to pick the best dir to turn
|
|
|
|
vecTest = pev->origin + (gpGlobals->v_right * LEECH_SIZEX) + (gpGlobals->v_forward * LEECH_CHECK_DIST); |
|
|
|
vecTest = pev->origin + ( gpGlobals->v_right * LEECH_SIZEX ) + ( gpGlobals->v_forward * LEECH_CHECK_DIST ); |
|
|
|
UTIL_TraceLine(pev->origin, vecTest, missile, edict(), &tr); |
|
|
|
UTIL_TraceLine( pev->origin, vecTest, missile, edict(), &tr ); |
|
|
|
flRightSide = tr.flFraction; |
|
|
|
flRightSide = tr.flFraction; |
|
|
|
|
|
|
|
|
|
|
|
vecTest = pev->origin + (gpGlobals->v_right * -LEECH_SIZEX) + (gpGlobals->v_forward * LEECH_CHECK_DIST); |
|
|
|
vecTest = pev->origin + ( gpGlobals->v_right * -LEECH_SIZEX ) + ( gpGlobals->v_forward * LEECH_CHECK_DIST ); |
|
|
|
UTIL_TraceLine(pev->origin, vecTest, missile, edict(), &tr); |
|
|
|
UTIL_TraceLine( pev->origin, vecTest, missile, edict(), &tr ); |
|
|
|
flLeftSide = tr.flFraction; |
|
|
|
flLeftSide = tr.flFraction; |
|
|
|
|
|
|
|
|
|
|
|
// turn left, right or random depending on clearance ratio
|
|
|
|
// turn left, right or random depending on clearance ratio
|
|
|
|
float delta = (flRightSide - flLeftSide); |
|
|
|
float delta = ( flRightSide - flLeftSide ); |
|
|
|
if ( delta > 0.1 || (delta > -0.1 && RANDOM_LONG(0,100)<50) ) |
|
|
|
if( delta > 0.1 || ( delta > -0.1 && RANDOM_LONG( 0, 100 ) < 50 ) ) |
|
|
|
m_flTurning = -LEECH_TURN_RATE; |
|
|
|
m_flTurning = -LEECH_TURN_RATE; |
|
|
|
else |
|
|
|
else |
|
|
|
m_flTurning = LEECH_TURN_RATE; |
|
|
|
m_flTurning = LEECH_TURN_RATE; |
|
|
|
} |
|
|
|
} |
|
|
|
pev->speed = UTIL_Approach( -(LEECH_SWIM_SPEED*0.5), pev->speed, LEECH_SWIM_DECEL * LEECH_FRAMETIME * m_obstacle ); |
|
|
|
pev->speed = UTIL_Approach( -( LEECH_SWIM_SPEED * 0.5 ), pev->speed, LEECH_SWIM_DECEL * LEECH_FRAMETIME * m_obstacle ); |
|
|
|
pev->velocity = gpGlobals->v_forward * pev->speed; |
|
|
|
pev->velocity = gpGlobals->v_forward * pev->speed; |
|
|
|
} |
|
|
|
} |
|
|
|
pev->ideal_yaw = m_flTurning + targetYaw; |
|
|
|
pev->ideal_yaw = m_flTurning + targetYaw; |
|
|
|
UpdateMotion(); |
|
|
|
UpdateMotion(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void CLeech::Killed(entvars_t *pevAttacker, int iGib) |
|
|
|
void CLeech::Killed( entvars_t *pevAttacker, int iGib ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Vector vecSplatDir; |
|
|
|
Vector vecSplatDir; |
|
|
|
TraceResult tr; |
|
|
|
TraceResult tr; |
|
|
|
|
|
|
|
|
|
|
|
//ALERT(at_aiconsole, "Leech: killed\n");
|
|
|
|
//ALERT(at_aiconsole, "Leech: killed\n");
|
|
|
|
// tell owner ( if any ) that we're dead.This is mostly for MonsterMaker functionality.
|
|
|
|
// tell owner ( if any ) that we're dead.This is mostly for MonsterMaker functionality.
|
|
|
|
CBaseEntity *pOwner = CBaseEntity::Instance(pev->owner); |
|
|
|
CBaseEntity *pOwner = CBaseEntity::Instance( pev->owner ); |
|
|
|
if (pOwner) |
|
|
|
if( pOwner ) |
|
|
|
pOwner->DeathNotice(pev); |
|
|
|
pOwner->DeathNotice( pev ); |
|
|
|
|
|
|
|
|
|
|
|
// When we hit the ground, play the "death_end" activity
|
|
|
|
// When we hit the ground, play the "death_end" activity
|
|
|
|
if ( pev->waterlevel ) |
|
|
|
if( pev->waterlevel ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pev->angles.z = 0; |
|
|
|
pev->angles.z = 0; |
|
|
|
pev->angles.x = 0; |
|
|
|
pev->angles.x = 0; |
|
|
|
pev->origin.z += 1; |
|
|
|
pev->origin.z += 1; |
|
|
|
pev->avelocity = g_vecZero; |
|
|
|
pev->avelocity = g_vecZero; |
|
|
|
if ( RANDOM_LONG( 0, 99 ) < 70 ) |
|
|
|
if( RANDOM_LONG( 0, 99 ) < 70 ) |
|
|
|
pev->avelocity.y = RANDOM_LONG( -720, 720 ); |
|
|
|
pev->avelocity.y = RANDOM_LONG( -720, 720 ); |
|
|
|
|
|
|
|
|
|
|
|
pev->gravity = 0.02; |
|
|
|
pev->gravity = 0.02; |
|
|
|
ClearBits(pev->flags, FL_ONGROUND); |
|
|
|
ClearBits( pev->flags, FL_ONGROUND ); |
|
|
|
SetActivity( ACT_DIESIMPLE ); |
|
|
|
SetActivity( ACT_DIESIMPLE ); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|