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.
1330 lines
32 KiB
1330 lines
32 KiB
/*** |
|
* |
|
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. |
|
* |
|
* This product contains software technology licensed from Id |
|
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. |
|
* All Rights Reserved. |
|
* |
|
* This source code contains proprietary and confidential information of |
|
* Valve LLC and its suppliers. Access to this code is restricted to |
|
* persons who have executed a written SDK license with Valve. Any access, |
|
* use or distribution of this code by or to any unlicensed person is illegal. |
|
* |
|
****/ |
|
|
|
//========================================================= |
|
// Generic Monster - purely for scripted sequence work. |
|
//========================================================= |
|
#include "extdll.h" |
|
#include "util.h" |
|
#include "cbase.h" |
|
#include "nodes.h" |
|
#include "monsters.h" |
|
#include "schedule.h" |
|
#include "soundent.h" |
|
#include "weapons.h" |
|
#include "player.h" |
|
#include "genericmonster.h" |
|
|
|
|
|
//========================================================= |
|
// Monster's defines |
|
//========================================================= |
|
#define PITWORM_HEIGHT 584 |
|
#define PITWORM_EYE_OFFSET Vector(0, 0, 445) |
|
#define PITWORM_EYEBLAST_ATTACK_DIST 512 // 464 |
|
#define PITWORM_EYEBLAST_DURATION 3.03f // 0.49 approximatly. (49 miliseconds) |
|
|
|
#define PITWORM_CONTROLLER_EYE_YAW 0 |
|
#define PITWORM_CONTROLLER_EYE_PITCH 1 |
|
#define PITWORM_CONTROLLER_BODY_YAW 2 |
|
|
|
#define PITWORM_EYE_PITCH_MIN -45 |
|
#define PITWORM_EYE_PITCH_MAX 45 |
|
#define PITWORM_EYE_YAW_MIN -45 |
|
#define PITWORM_EYE_YAW_MAX 45 |
|
#define PITWORM_BODY_YAW_MIN -50 |
|
#define PITWORM_BODY_YAW_MAX 50 |
|
|
|
#define NUM_PITWORM_LEVELS 4 |
|
|
|
#define PITWORM_LEVEL0 0 // Pitworm's 'foot' level | when player is at First level 1. |
|
#define PITWORM_LEVEL1 1 // First level | player goes to waste station door 1 or 2. |
|
#define PITWORM_LEVEL2 2 // Second level | player goes to narrow corridor that leads to stairs. |
|
#define PITWORM_LEVEL3 3 // Third level | entry room, steam vent and valve pressure controls. |
|
|
|
#define PITWORM_LEVEL0_HEIGHT -632 // Pitworm's 'foot' level | when player is at First level 1. | (Hammer units) |
|
#define PITWORM_LEVEL1_HEIGHT -48 // First level | player goes to waste station door 1 or 2. | (Hammer units) |
|
#define PITWORM_LEVEL2_HEIGHT 208 // Second level | player goes to narrow corridor that leads to stairs. | (Hammer units) |
|
#define PITWORM_LEVEL3_HEIGHT 304 // Third level | entry room, steam vent and valve pressure controls. | (Hammer units) |
|
|
|
|
|
#define PITWORM_LEVEL0_VIEWOFFSET Vector(0, 0, PITWORM_HEIGHT) |
|
#define PITWORM_LEVEL1_VIEWOFFSET Vector(0, 0, 256) |
|
#define PITWORM_LEVEL2_VIEWOFFSET Vector(0, 0, 96) |
|
#define PITWORM_LEVEL3_VIEWOFFSET PITWORM_LEVEL2_VIEWOFFSET |
|
|
|
//========================================================= |
|
// Monster's Anim Events Go Here |
|
//========================================================= |
|
|
|
#define PITWORM_AE_SWIPE ( 1 ) |
|
#define PITWORM_AE_EYEBLAST_START ( 2 ) |
|
#define PITWORM_AE_EYEBLAST_END ( 4 ) |
|
|
|
//========================================================= |
|
// CPitWorm |
|
//========================================================= |
|
class CPitWorm : public CBaseMonster |
|
{ |
|
public: |
|
|
|
int Save(CSave &save); |
|
int Restore(CRestore &restore); |
|
static TYPEDESCRIPTION m_SaveData[]; |
|
|
|
virtual int ObjectCaps(void) { return CBaseMonster::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } |
|
|
|
void Spawn(void); |
|
void Precache(void); |
|
int Classify(void); |
|
|
|
void IdleSound( void ); |
|
void AlertSound( void ); |
|
void DeathSound( void ); |
|
void PainSound( void ); |
|
|
|
void AngrySound( void ); |
|
void FlinchSound( void ); |
|
void SwipeSound( void ); |
|
void BeamSound( void ); |
|
|
|
void SetObjectCollisionBox(void); |
|
void HandleAnimEvent(MonsterEvent_t *pEvent); |
|
int TakeDamage(entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType); |
|
|
|
int CanPlaySequence(BOOL fDisregardState); |
|
|
|
void EXPORT StartupThink(void); |
|
void EXPORT DyingThink(void); |
|
void EXPORT StartupUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); |
|
void EXPORT NullThink(void); |
|
void EXPORT CommandUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); |
|
void EXPORT HuntThink(void); |
|
|
|
void EXPORT WormTouch(CBaseEntity* pOther); |
|
|
|
void FloatSequence(void); |
|
void NextActivity(void); |
|
|
|
void Flight(void); |
|
|
|
|
|
Vector m_avelocity; |
|
|
|
Vector m_vecTarget; |
|
Vector m_posTarget; |
|
|
|
Vector m_vecDesired; |
|
Vector m_posDesired; |
|
|
|
float m_flMinZ; |
|
float m_flMaxZ; |
|
|
|
float m_flLastSeen; |
|
float m_flPrevSeen; |
|
|
|
int m_iLevel; |
|
|
|
float m_flAdj; |
|
float m_distDesired; |
|
|
|
int Level( float dz ); |
|
|
|
const Vector& IdealPosition(const int level) const; |
|
const Vector& IdealPosition(const float dz) const; |
|
const Vector& IdealPosition(CBaseEntity* pEnemy) const; |
|
|
|
void UpdateBodyControllers( void ); |
|
void UpdateBodyYaw( void ); |
|
void UpdateEyeYaw( void ); |
|
void UpdateEyePitch( void ); |
|
|
|
void CreateBeam(const Vector& src, const Vector& target, int width); |
|
void DestroyBeam(void); |
|
void UpdateBeam(const Vector& src, const Vector& target); |
|
|
|
void SetupBeamPoints(CBaseEntity* pEnemy, Vector* vecleft, Vector* vecRight); |
|
void UpdateBeamPoints( CBaseEntity* pEnemy, Vector* vecTarget ); |
|
|
|
void CreateGlow(void); |
|
void DestroyGlow(void); |
|
void EyeOff(void); |
|
void EyeOn(int level); |
|
void EyeUpdate(void); |
|
|
|
float m_flInitialYaw; |
|
Vector m_spawnAngles; |
|
Vector m_vecLevels[NUM_PITWORM_LEVELS]; |
|
|
|
CBeam* m_pBeam; |
|
float m_flBeamYaw; |
|
float m_flBeamTime; |
|
BOOL m_fBeamOn; |
|
CSprite* m_pEyeGlow; |
|
int m_eyeBrightness; |
|
|
|
Vector m_vecGoalAngles; |
|
Vector m_vecCurAngles; |
|
|
|
float m_flNextAttackTime; |
|
float m_flNextIdleSoundTime; |
|
|
|
static const char* pHitSilo[]; |
|
static const char* pClangSounds[]; |
|
static const char* pAngrySounds[]; |
|
static const char* pSwipeSounds[]; |
|
static const char* pFlinchSounds[]; |
|
|
|
static const char* pAlertSounds[]; |
|
static const char* pIdleSounds[]; |
|
static const char* pDeathSounds[]; |
|
}; |
|
|
|
LINK_ENTITY_TO_CLASS(monster_pitworm, CPitWorm); |
|
LINK_ENTITY_TO_CLASS(monster_pitworm_up, CPitWorm); |
|
|
|
//========================================================= |
|
// Save & Restore |
|
//========================================================= |
|
TYPEDESCRIPTION CPitWorm::m_SaveData[] = |
|
{ |
|
DEFINE_FIELD(CPitWorm, m_avelocity, FIELD_VECTOR), |
|
|
|
DEFINE_FIELD(CPitWorm, m_vecTarget, FIELD_VECTOR), |
|
DEFINE_FIELD(CPitWorm, m_posTarget, FIELD_POSITION_VECTOR), |
|
DEFINE_FIELD(CPitWorm, m_vecDesired, FIELD_VECTOR), |
|
DEFINE_FIELD(CPitWorm, m_posDesired, FIELD_POSITION_VECTOR), |
|
DEFINE_FIELD(CPitWorm, m_flMinZ, FIELD_FLOAT), |
|
DEFINE_FIELD(CPitWorm, m_flMaxZ, FIELD_FLOAT), |
|
|
|
DEFINE_FIELD(CPitWorm, m_flLastSeen, FIELD_TIME), |
|
DEFINE_FIELD(CPitWorm, m_flPrevSeen, FIELD_TIME), |
|
DEFINE_FIELD(CPitWorm, m_iLevel, FIELD_INTEGER), |
|
DEFINE_FIELD(CPitWorm, m_flAdj, FIELD_FLOAT), |
|
DEFINE_FIELD(CPitWorm, m_distDesired, FIELD_FLOAT), |
|
|
|
DEFINE_FIELD(CPitWorm, m_flInitialYaw, FIELD_FLOAT), |
|
DEFINE_FIELD(CPitWorm, m_spawnAngles, FIELD_VECTOR), |
|
DEFINE_ARRAY(CPitWorm, m_vecLevels, FIELD_POSITION_VECTOR, NUM_PITWORM_LEVELS), |
|
DEFINE_FIELD(CPitWorm, m_pBeam, FIELD_CLASSPTR), |
|
DEFINE_FIELD(CPitWorm, m_flBeamTime, FIELD_TIME), |
|
DEFINE_FIELD(CPitWorm, m_flBeamYaw, FIELD_FLOAT), |
|
DEFINE_FIELD(CPitWorm, m_fBeamOn, FIELD_BOOLEAN), |
|
DEFINE_FIELD(CPitWorm, m_pEyeGlow, FIELD_CLASSPTR), |
|
DEFINE_FIELD(CPitWorm, m_eyeBrightness, FIELD_INTEGER), |
|
|
|
DEFINE_FIELD(CPitWorm, m_vecGoalAngles, FIELD_VECTOR), |
|
DEFINE_FIELD(CPitWorm, m_vecCurAngles, FIELD_VECTOR), |
|
DEFINE_FIELD(CPitWorm, m_flNextAttackTime, FIELD_TIME), |
|
DEFINE_FIELD(CPitWorm, m_flNextIdleSoundTime, FIELD_TIME), |
|
}; |
|
|
|
IMPLEMENT_SAVERESTORE(CPitWorm, CBaseMonster); |
|
|
|
|
|
const char *CPitWorm::pHitSilo[] = |
|
{ |
|
"tentacle/te_strike1.wav", |
|
"tentacle/te_strike2.wav", |
|
}; |
|
|
|
const char* CPitWorm::pClangSounds[] = |
|
{ |
|
"pitworm/clang1.wav", |
|
"pitworm/clang2.wav", |
|
"pitworm/clang3.wav", |
|
}; |
|
|
|
const char* CPitWorm::pAngrySounds[] = |
|
{ |
|
"pitworm/pit_worm_angry1.wav", |
|
"pitworm/pit_worm_angry2.wav", |
|
"pitworm/pit_worm_angry3.wav", |
|
}; |
|
|
|
|
|
const char* CPitWorm::pSwipeSounds[] = |
|
{ |
|
"pitworm/pit_worm_attack_swipe1.wav", |
|
"pitworm/pit_worm_attack_swipe2.wav", |
|
"pitworm/pit_worm_attack_swipe3.wav", |
|
}; |
|
|
|
|
|
const char* CPitWorm::pFlinchSounds[] = |
|
{ |
|
"pitworm/pit_worm_flinch1.wav", |
|
"pitworm/pit_worm_flinch2.wav", |
|
}; |
|
|
|
const char* CPitWorm::pAlertSounds[] = |
|
{ |
|
"pitworm/pit_worm_alert.wav", |
|
}; |
|
|
|
const char* CPitWorm::pIdleSounds[] = |
|
{ |
|
"pitworm/pit_worm_idle1.wav", |
|
"pitworm/pit_worm_idle2.wav", |
|
"pitworm/pit_worm_idle3.wav", |
|
}; |
|
|
|
const char* CPitWorm::pDeathSounds[] = |
|
{ |
|
"pitworm/pit_worm_death.wav", |
|
}; |
|
|
|
|
|
|
|
static const char* g_pszPitwormAnims[] = |
|
{ |
|
"idle", |
|
"idle2", |
|
"attack", |
|
"scream", |
|
"attacklow", |
|
"doorclaw1", |
|
"doorclaw2", |
|
"doorclaw3", |
|
"eyeblast", |
|
"platclaw1", |
|
"platclaw2", |
|
"flinch1", |
|
"flinch2", |
|
"death", |
|
}; |
|
|
|
typedef enum |
|
{ |
|
PITWORM_ANIM_IDLE, |
|
PITWORM_ANIM_IDLE2, |
|
PITWORM_ANIM_ATTACK, |
|
PITWORM_ANIM_SCREAM, |
|
PITWORM_ANIM_ATTACKLOW, |
|
PITWORM_ANIM_DOORCLAW1, |
|
PITWORM_ANIM_DOORCLAR2, |
|
PITWORM_ANIM_DOORCLAR3, |
|
PITWORM_ANIM_EYEBLAST, |
|
PITWORM_ANIM_PLATCLAW1, |
|
PITWORM_ANIM_PLATCLAW2, |
|
PITWORM_ANIM_FLINCH1, |
|
PITWORM_ANIM_FLINCH2, |
|
PITWORM_ANIM_DEATH, |
|
|
|
} PITWORM_ANIM; |
|
|
|
|
|
|
|
//========================================================= |
|
// Spawn |
|
//========================================================= |
|
void CPitWorm::Spawn() |
|
{ |
|
Precache(); |
|
|
|
pev->movetype = MOVETYPE_FLY; |
|
pev->solid = SOLID_BBOX; |
|
|
|
SET_MODEL(ENT(pev), "models/pit_worm_up.mdl"); |
|
UTIL_SetSize(pev, Vector(-32, -32, 0), Vector(32, 32, 64)); |
|
UTIL_SetOrigin(pev, pev->origin); |
|
|
|
// Set fields common to all monsters |
|
pev->flags |= FL_MONSTER; |
|
pev->takedamage = DAMAGE_NO; |
|
pev->health = 999; |
|
pev->view_ofs = PITWORM_EYE_OFFSET; |
|
|
|
m_flFieldOfView = -1; |
|
|
|
pev->sequence = 0; |
|
ResetSequenceInfo(); |
|
|
|
InitBoneControllers(); |
|
|
|
SetThink(&CPitWorm::StartupThink); |
|
pev->nextthink = gpGlobals->time + 0.1; |
|
|
|
m_spawnAngles = pev->angles; |
|
m_flInitialYaw = m_spawnAngles.y; |
|
pev->ideal_yaw = m_flInitialYaw; |
|
|
|
m_IdealMonsterState = MONSTERSTATE_IDLE;// Assume monster will be idle, until proven otherwise |
|
|
|
m_IdealActivity = ACT_IDLE; |
|
|
|
m_flDistTooFar = 1024.0; |
|
m_flDistLook = 2048.0; |
|
|
|
// set eye position |
|
SetEyePosition(); |
|
|
|
m_flLastSeen = 0.0f; |
|
m_flPrevSeen = 0.0f; |
|
m_iLevel = PITWORM_LEVEL1; |
|
|
|
m_pBeam = NULL; |
|
m_flBeamYaw = 0.0f; |
|
m_fBeamOn = FALSE; |
|
m_eyeBrightness = 0; |
|
|
|
m_vecCurAngles = Vector(0, pev->angles.y, 0); |
|
m_vecGoalAngles = Vector(0, pev->angles.y, 0); |
|
m_flNextAttackTime = gpGlobals->time; |
|
m_flNextIdleSoundTime = gpGlobals->time; |
|
|
|
// Create the eye glow. |
|
CreateGlow(); |
|
} |
|
|
|
//========================================================= |
|
// Precache - precaches all resources this monster needs |
|
//========================================================= |
|
void CPitWorm::Precache() |
|
{ |
|
PRECACHE_MODEL("models/pit_worm_up.mdl"); |
|
|
|
PRECACHE_SOUND_ARRAY(pHitSilo); |
|
|
|
PRECACHE_SOUND("pitworm/pit_worm_alert.wav"); |
|
PRECACHE_SOUND("pitworm/pit_worm_attack_eyeblast.wav"); |
|
PRECACHE_SOUND("pitworm/pit_worm_attack_eyeblast_impact.wav"); |
|
PRECACHE_SOUND("pitworm/pit_worm_death.wav"); |
|
|
|
PRECACHE_SOUND_ARRAY(pClangSounds); |
|
PRECACHE_SOUND_ARRAY(pAngrySounds); |
|
PRECACHE_SOUND_ARRAY(pSwipeSounds); |
|
PRECACHE_SOUND_ARRAY(pFlinchSounds); |
|
PRECACHE_SOUND_ARRAY(pIdleSounds); |
|
|
|
PRECACHE_MODEL("sprites/gworm_beam_02.spr"); |
|
PRECACHE_MODEL("sprites/glow_grn.spr"); |
|
|
|
} |
|
|
|
//========================================================= |
|
// Classify |
|
//========================================================= |
|
int CPitWorm::Classify(void) |
|
{ |
|
return CLASS_ALIEN_MONSTER; |
|
} |
|
|
|
//========================================================= |
|
// IdleSound |
|
//========================================================= |
|
void CPitWorm::IdleSound(void) |
|
{ |
|
EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pIdleSounds), 1, ATTN_NORM); |
|
} |
|
|
|
//========================================================= |
|
// AlertSound |
|
//========================================================= |
|
void CPitWorm::AlertSound(void) |
|
{ |
|
EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pAlertSounds), 1, ATTN_NORM); |
|
} |
|
|
|
//========================================================= |
|
// DeathSound |
|
//========================================================= |
|
void CPitWorm::DeathSound(void) |
|
{ |
|
EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pDeathSounds), 1, ATTN_NORM); |
|
} |
|
|
|
//========================================================= |
|
// PainSound |
|
//========================================================= |
|
void CPitWorm::PainSound(void) |
|
{ |
|
|
|
} |
|
|
|
//========================================================= |
|
// AngrySound |
|
//========================================================= |
|
void CPitWorm::AngrySound(void) |
|
{ |
|
EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pAngrySounds), 1, ATTN_NORM); |
|
} |
|
|
|
//========================================================= |
|
// FlinchSound |
|
//========================================================= |
|
void CPitWorm::FlinchSound(void) |
|
{ |
|
EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pFlinchSounds), 1, ATTN_NORM); |
|
} |
|
|
|
//========================================================= |
|
// SwipeSound |
|
//========================================================= |
|
void CPitWorm::SwipeSound(void) |
|
{ |
|
EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pSwipeSounds), 1, ATTN_NORM); |
|
} |
|
|
|
//========================================================= |
|
// BeamSound |
|
//========================================================= |
|
void CPitWorm::BeamSound(void) |
|
{ |
|
EMIT_SOUND(ENT(pev), CHAN_VOICE, "pitworm/pit_worm_attack_eyeblast.wav", 2, ATTN_NORM); |
|
} |
|
|
|
|
|
//========================================================= |
|
// SetObjectCollisionBox |
|
//========================================================= |
|
void CPitWorm::SetObjectCollisionBox(void) |
|
{ |
|
pev->absmin = pev->origin + Vector(-96, -96, 0); |
|
pev->absmax = pev->origin + Vector(96, 96, 512); |
|
} |
|
|
|
//========================================================= |
|
// HandleAnimEvent |
|
//========================================================= |
|
void CPitWorm::HandleAnimEvent(MonsterEvent_t *pEvent) |
|
{ |
|
switch (pEvent->event) |
|
{ |
|
case PITWORM_AE_SWIPE: // bang |
|
{ |
|
Vector vecSrc, vecAngles; |
|
GetAttachment(1, vecSrc, vecAngles); |
|
|
|
if (m_hEnemy) |
|
{ |
|
vecSrc = m_hEnemy->pev->origin; |
|
} |
|
|
|
UTIL_EmitAmbientSound(ENT(pev), vecSrc, RANDOM_SOUND_ARRAY(pHitSilo), 1.0, ATTN_NORM, 0, 100); |
|
|
|
UTIL_ScreenShake(vecSrc, 6.0, 3.0, 1.0, 128); |
|
|
|
// Trace a hull around to see if we hit an enemy. |
|
TraceResult tr; |
|
UTIL_TraceHull(vecSrc, vecSrc + Vector(0, -64, 0), dont_ignore_monsters, head_hull, ENT(pev), &tr); |
|
|
|
CBaseEntity *pHurt = CBaseEntity::Instance(tr.pHit); |
|
if (pHurt) |
|
pHurt->TakeDamage(VARS(pev), VARS(pev), gSkillData.pwormDmgSwipe, DMG_CLUB | DMG_SLASH); |
|
|
|
// Shake the screen. |
|
UTIL_ScreenShake(vecSrc, 6.0, 3.0, 1.0, 128); |
|
|
|
gpGlobals->force_retouch++; |
|
} |
|
break; |
|
|
|
case PITWORM_AE_EYEBLAST_START: // start killing swing |
|
{ |
|
ALERT(at_console, "PITWORM_AE_EYEBLAST_START\n"); |
|
|
|
// Remove the beam if not NULL. |
|
DestroyBeam(); |
|
|
|
Vector src, angles; |
|
GetAttachment(0, src, angles); |
|
|
|
// Create a new beam. |
|
CreateBeam(src, src, 40); |
|
|
|
// Turn eye glow on. |
|
EyeOn( 255 ); |
|
|
|
// Reset beam yaw. |
|
m_flBeamYaw = 0.0f; |
|
m_flBeamTime = gpGlobals->time + PITWORM_EYEBLAST_DURATION; |
|
} |
|
break; |
|
|
|
|
|
case PITWORM_AE_EYEBLAST_END: // end killing swing |
|
{ |
|
#if 0 |
|
//ALERT(at_console, "PITWORM_AE_EYEBLAST_END\n"); |
|
DestroyBeam(); |
|
|
|
// Turn eye glow off. |
|
EyeOff(); |
|
|
|
// Reset beam yaw. |
|
m_flBeamYaw = 0.0f; |
|
|
|
// Reset beam time. |
|
m_flBeamTime = 0.0f; |
|
#endif |
|
} |
|
break; |
|
|
|
default: |
|
CBaseMonster::HandleAnimEvent(pEvent); |
|
} |
|
} |
|
|
|
|
|
|
|
void CPitWorm::CommandUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) |
|
{ |
|
switch (useType) |
|
{ |
|
case USE_OFF: |
|
//ALERT(at_console, "USE_OFF\n"); |
|
break; |
|
case USE_ON: |
|
//ALERT(at_console, "USE_ON\n"); |
|
break; |
|
case USE_SET: |
|
//ALERT(at_console, "USE_SET\n"); |
|
break; |
|
case USE_TOGGLE: |
|
{ |
|
m_fSequenceFinished = TRUE; |
|
pev->health = 0; |
|
|
|
SetThink(&CPitWorm::DyingThink); |
|
pev->nextthink = gpGlobals->time; |
|
} |
|
// ALERT(at_console, "USE_TOGGLE\n"); |
|
break; |
|
} |
|
} |
|
|
|
|
|
//========================================================= |
|
// |
|
//========================================================= |
|
int CPitWorm::TakeDamage(entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType) |
|
{ |
|
if (flDamage > pev->health) |
|
{ |
|
pev->health = 1; |
|
} |
|
else |
|
{ |
|
pev->health -= flDamage; |
|
} |
|
return 1; |
|
} |
|
|
|
//========================================================= |
|
// StartupThink |
|
//========================================================= |
|
void CPitWorm::StartupThink(void) |
|
{ |
|
m_flAdj = 350; |
|
Vector src = pev->origin; |
|
|
|
CBaseEntity *pEntity = NULL; |
|
|
|
pEntity = UTIL_FindEntityByTargetname(NULL, "pw_tleveldead"); |
|
if (pEntity) |
|
m_vecLevels[PITWORM_LEVEL0] = pEntity->pev->origin; |
|
else |
|
m_vecLevels[PITWORM_LEVEL0] = Vector(src.x, src.y, PITWORM_LEVEL0_HEIGHT); |
|
|
|
pEntity = UTIL_FindEntityByTargetname(NULL, "pw_tlevel1"); |
|
if (pEntity) |
|
m_vecLevels[PITWORM_LEVEL1] = pEntity->pev->origin; |
|
else |
|
m_vecLevels[PITWORM_LEVEL1] = Vector(src.x, src.y, PITWORM_LEVEL2_HEIGHT); |
|
|
|
pEntity = UTIL_FindEntityByTargetname(NULL, "pw_tlevel2"); |
|
if (pEntity) |
|
m_vecLevels[PITWORM_LEVEL2] = pEntity->pev->origin; |
|
else |
|
m_vecLevels[PITWORM_LEVEL2] = Vector(src.x, src.y, PITWORM_LEVEL2_HEIGHT); |
|
|
|
pEntity = UTIL_FindEntityByTargetname(NULL, "pw_tlevel3"); |
|
if (pEntity) |
|
m_vecLevels[PITWORM_LEVEL3] = pEntity->pev->origin; |
|
else |
|
m_vecLevels[PITWORM_LEVEL3] = Vector(src.x, src.y, PITWORM_LEVEL3_HEIGHT); |
|
|
|
// Set altitude limits. |
|
m_flMinZ = m_vecLevels[PITWORM_LEVEL0].z; |
|
m_flMaxZ = m_vecLevels[PITWORM_LEVEL3].z; |
|
|
|
// Set default level. |
|
UTIL_SetOrigin(pev, IdealPosition( m_iLevel ) ); |
|
|
|
SetThink(&CPitWorm::HuntThink); |
|
SetUse(&CPitWorm::CommandUse); |
|
pev->nextthink = gpGlobals->time + 0.1; |
|
} |
|
|
|
//========================================================= |
|
// |
|
//========================================================= |
|
void CPitWorm::StartupUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) |
|
{ |
|
SetThink(&CPitWorm::HuntThink); |
|
pev->nextthink = gpGlobals->time + 0.1; |
|
SetUse(&CPitWorm::CommandUse); |
|
} |
|
|
|
//========================================================= |
|
// NullThink |
|
//========================================================= |
|
void CPitWorm::NullThink(void) |
|
{ |
|
StudioFrameAdvance(); |
|
pev->nextthink = gpGlobals->time + 0.5; |
|
} |
|
|
|
//========================================================= |
|
// DyingThink |
|
//========================================================= |
|
void CPitWorm::DyingThink(void) |
|
{ |
|
pev->nextthink = gpGlobals->time + 0.1; |
|
DispatchAnimEvents(); |
|
StudioFrameAdvance(); |
|
|
|
if (pev->deadflag == DEAD_NO) |
|
{ |
|
// Destroy the glow. |
|
DestroyGlow(); |
|
|
|
DeathSound(); |
|
pev->deadflag = DEAD_DYING; |
|
} |
|
|
|
if (pev->deadflag == DEAD_DYING) |
|
{ |
|
Flight(); |
|
|
|
if (fabs(pev->origin.z - m_flMaxZ) < 16) |
|
{ |
|
pev->velocity = Vector(0, 0, 0); |
|
pev->deadflag = DEAD_DEAD; |
|
} |
|
} |
|
|
|
if (m_fSequenceFinished) |
|
{ |
|
if (pev->sequence != LookupSequence("death")) |
|
{ |
|
pev->sequence = LookupSequence("death"); |
|
pev->frame = 0; |
|
pev->framerate = 0.2f; // Set the framerate manually until we find a better fix. |
|
} |
|
else |
|
{ |
|
UTIL_Remove(this); |
|
} |
|
} |
|
} |
|
|
|
//========================================================= |
|
// HuntThink |
|
//========================================================= |
|
void CPitWorm::HuntThink(void) |
|
{ |
|
pev->nextthink = gpGlobals->time + 0.1; |
|
DispatchAnimEvents(); |
|
StudioFrameAdvance(); |
|
|
|
// Update the eye glow. |
|
EyeUpdate(); |
|
|
|
if (m_hEnemy) |
|
{ |
|
// Update body controllers. |
|
UpdateBodyControllers(); |
|
|
|
//float flDist = (m_hEnemy->pev->origin - m_vecLevels[m_iLevel]).Length(); |
|
//ALERT(at_console, "pitworm: Distance from eye %f\n", flDist); |
|
|
|
|
|
// Update beam if we need to. |
|
if (m_fBeamOn) |
|
{ |
|
if (m_flBeamTime > gpGlobals->time && !m_fSequenceFinished) |
|
{ |
|
Vector src, target, angles; |
|
GetAttachment(0, src, angles); |
|
UpdateBeamPoints(m_hEnemy, &target); |
|
|
|
TraceResult tr; |
|
UTIL_TraceLine(src, src + ((target - src).Normalize() * 1000), dont_ignore_monsters, ENT(pev), &tr); |
|
|
|
UpdateBeam(src, tr.vecEndPos); |
|
|
|
// Test to see if we hit |
|
CBaseEntity *pHurt = CBaseEntity::Instance(tr.pHit); |
|
if (pHurt) |
|
pHurt->TakeDamage(VARS(pev), VARS(pev), gSkillData.pwormDmgBeam, DMG_BURN); |
|
} |
|
else |
|
{ |
|
// Remove the beam. |
|
DestroyBeam(); |
|
|
|
// Turn eye glow off. |
|
EyeOff(); |
|
|
|
// Reset beam yaw. |
|
m_flBeamYaw = 0.0f; |
|
|
|
// Reset beam time. |
|
m_flBeamTime = 0.0f; |
|
} |
|
|
|
pev->nextthink = gpGlobals->time + 0.01f; |
|
return; |
|
} |
|
} |
|
|
|
switch (m_iLevel) |
|
{ |
|
case PITWORM_LEVEL0: pev->view_ofs = PITWORM_EYE_OFFSET; break; |
|
case PITWORM_LEVEL1: pev->view_ofs = PITWORM_EYE_OFFSET; break; |
|
case PITWORM_LEVEL2: pev->view_ofs = PITWORM_EYE_OFFSET; break; |
|
case PITWORM_LEVEL3: pev->view_ofs = PITWORM_EYE_OFFSET; break; |
|
} |
|
{ |
|
float currentZ = pev->origin.z; |
|
float desiredZ = m_posDesired.z - m_flAdj; |
|
|
|
if (currentZ > desiredZ) |
|
{ |
|
pev->origin.z -= 8; |
|
|
|
if (pev->origin.z < desiredZ) |
|
pev->origin.z = desiredZ; |
|
} |
|
else if (currentZ < desiredZ) |
|
{ |
|
pev->origin.z += 8; |
|
|
|
if (pev->origin.z > desiredZ) |
|
pev->origin.z = desiredZ; |
|
} |
|
} |
|
|
|
// if dead, force cancelation of current animation |
|
if (pev->health <= 0) |
|
{ |
|
SetThink(&CPitWorm::DyingThink); |
|
m_fSequenceFinished = TRUE; |
|
return; |
|
} |
|
|
|
// get new sequence |
|
if (m_fSequenceFinished) |
|
{ |
|
pev->frame = 0; |
|
NextActivity(); |
|
ResetSequenceInfo(); |
|
} |
|
|
|
// look for current enemy |
|
if (m_hEnemy != NULL) |
|
{ |
|
// Update level based on enemy's altitude (z). |
|
m_iLevel = Level(m_hEnemy->pev->origin.z); |
|
|
|
if (FVisible(m_hEnemy)) |
|
{ |
|
if (m_flLastSeen < gpGlobals->time - 5) |
|
m_flPrevSeen = gpGlobals->time; |
|
|
|
m_flLastSeen = gpGlobals->time; |
|
m_posTarget = m_hEnemy->pev->origin; |
|
m_vecTarget = (m_posTarget - pev->origin).Normalize(); |
|
m_vecDesired = m_vecTarget; |
|
m_posDesired = IdealPosition(m_iLevel); |
|
} |
|
else |
|
{ |
|
//m_flAdj = min(m_flAdj + 10, 1000); |
|
} |
|
} |
|
|
|
if (m_flNextIdleSoundTime < gpGlobals->time) |
|
{ |
|
//IdleSound(); |
|
// Use flinch sounds. |
|
FlinchSound(); |
|
m_flNextIdleSoundTime = gpGlobals->time + RANDOM_LONG(4.0f, 4.1f); |
|
} |
|
|
|
// don't go too high |
|
if (m_posDesired.z > m_flMaxZ) |
|
m_posDesired.z = m_flMaxZ; |
|
|
|
// don't go too low |
|
if (m_posDesired.z < m_flMinZ) |
|
m_posDesired.z = m_flMinZ; |
|
|
|
Flight(); |
|
} |
|
|
|
|
|
void CPitWorm::Flight(void) |
|
{ |
|
} |
|
|
|
|
|
|
|
//========================================================= |
|
// |
|
//========================================================= |
|
void CPitWorm::WormTouch(CBaseEntity* pOther) |
|
{ |
|
pev->nextthink = gpGlobals->time + 0.1f; |
|
SetTouch(NULL); |
|
} |
|
|
|
//========================================================= |
|
// |
|
//========================================================= |
|
int CPitWorm::CanPlaySequence(BOOL fDisregardState) |
|
{ |
|
return TRUE; |
|
} |
|
|
|
//========================================================= |
|
// NextActivity |
|
//========================================================= |
|
void CPitWorm::NextActivity() |
|
{ |
|
UTIL_MakeAimVectors(pev->angles); |
|
|
|
Vector forward = gpGlobals->v_forward; |
|
forward.z = 0; |
|
|
|
//float flDist = (m_vecTarget - pev->origin).Length(); |
|
float flDist = (m_vecDesired - m_vecLevels[m_iLevel]).Length(); |
|
float flDot = DotProduct(m_vecDesired, forward); |
|
float flDotSpawnAngles = DotProduct(m_vecDesired, m_spawnAngles); |
|
|
|
#if 0 |
|
if (m_hEnemy != NULL && !m_hEnemy->IsAlive()) |
|
{ |
|
m_hEnemy = NULL; |
|
} |
|
|
|
if (m_flLastSeen + 15 < gpGlobals->time) |
|
{ |
|
m_hEnemy = NULL; |
|
} |
|
#else |
|
|
|
if (m_hEnemy == NULL) |
|
{ |
|
m_flLastSeen = gpGlobals->time; |
|
m_hEnemy = UTIL_PlayerByIndex(1); |
|
} |
|
#endif |
|
|
|
if (m_hEnemy == NULL) |
|
{ |
|
Look(4096); |
|
m_hEnemy = BestVisibleEnemy(); |
|
} |
|
|
|
//pev->sequence = LookupSequence("idle2"); |
|
//return; |
|
|
|
if (m_hEnemy != NULL) |
|
{ |
|
m_vecDesired = m_hEnemy->pev->origin; |
|
flDist = (m_vecDesired - m_vecLevels[m_iLevel]).Length(); |
|
flDot = DotProduct(m_vecDesired, forward); |
|
flDotSpawnAngles = DotProduct(m_vecDesired, Vector(0, -1, 0)); |
|
|
|
if (m_flLastSeen + 5 > gpGlobals->time && (m_flNextAttackTime < gpGlobals->time)) |
|
{ |
|
float flEnemyZ = m_hEnemy->pev->origin.z; |
|
|
|
Vector enemyDir = m_hEnemy->pev->origin - pev->origin; |
|
Vector spawnAngles = m_spawnAngles; |
|
Vector up = CrossProduct(enemyDir, spawnAngles); |
|
|
|
if (m_iLevel < PITWORM_LEVEL3) |
|
{ |
|
if (FVisible(m_hEnemy) && flDot > 0.95f) |
|
{ |
|
if (flDist > PITWORM_EYEBLAST_ATTACK_DIST) |
|
{ |
|
pev->sequence = LookupSequence("eyeblast"); |
|
BeamSound(); |
|
} |
|
else |
|
{ |
|
pev->sequence = LookupSequence("attacklow"); |
|
SwipeSound(); |
|
} |
|
} |
|
else |
|
{ |
|
if (up.z < 0) |
|
{ |
|
pev->sequence = LookupSequence("doorclaw2"); |
|
} |
|
else |
|
{ |
|
if (m_iLevel < PITWORM_LEVEL2) |
|
{ |
|
pev->sequence = LookupSequence("doorclaw3"); |
|
} |
|
else |
|
{ |
|
pev->sequence = LookupSequence("doorclaw1"); |
|
} |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
if (flDist > PITWORM_EYEBLAST_ATTACK_DIST) |
|
{ |
|
pev->sequence = LookupSequence("eyeblast"); |
|
BeamSound(); |
|
} |
|
else |
|
{ |
|
if (up.z < 0) |
|
{ |
|
pev->sequence = LookupSequence("platclaw1"); |
|
|
|
if (RANDOM_LONG(0,1) == 1) SwipeSound(); |
|
} |
|
else |
|
{ |
|
pev->sequence = LookupSequence("platclaw2"); |
|
if (RANDOM_LONG(0, 1) == 1) SwipeSound(); |
|
} |
|
} |
|
} |
|
|
|
m_flNextAttackTime = gpGlobals->time + RANDOM_FLOAT(3, 3.1f); |
|
return; |
|
} |
|
} |
|
|
|
if (m_hEnemy) |
|
{ |
|
pev->sequence = LookupSequence("idle2"); |
|
return; |
|
} |
|
|
|
FloatSequence(); |
|
} |
|
|
|
//========================================================= |
|
// FloatSequence |
|
//========================================================= |
|
void CPitWorm::FloatSequence(void) |
|
{ |
|
switch(RANDOM_LONG(0, 1)) |
|
{ |
|
case 0: |
|
pev->sequence = LookupSequence("idle"); |
|
break; |
|
|
|
case 1: |
|
pev->sequence = LookupSequence("idle2"); |
|
break; |
|
} |
|
} |
|
|
|
//========================================================= |
|
// IdealPosition |
|
//========================================================= |
|
int CPitWorm::Level( float dz ) |
|
{ |
|
if (dz < PITWORM_LEVEL1_HEIGHT) |
|
return PITWORM_LEVEL0; |
|
|
|
if (dz < PITWORM_LEVEL2_HEIGHT) |
|
return PITWORM_LEVEL1; |
|
|
|
if (dz < PITWORM_LEVEL3_HEIGHT) |
|
return PITWORM_LEVEL2; |
|
|
|
return PITWORM_LEVEL3; |
|
} |
|
|
|
//========================================================= |
|
// IdealPosition |
|
//========================================================= |
|
const Vector& CPitWorm::IdealPosition(const int level) const |
|
{ |
|
switch (level) |
|
{ |
|
case PITWORM_LEVEL0: |
|
return m_vecLevels[PITWORM_LEVEL0]; |
|
case PITWORM_LEVEL1: |
|
return m_vecLevels[PITWORM_LEVEL1]; |
|
case PITWORM_LEVEL2: |
|
return m_vecLevels[PITWORM_LEVEL2]; |
|
case PITWORM_LEVEL3: |
|
return m_vecLevels[PITWORM_LEVEL3]; |
|
} |
|
|
|
return m_vecLevels[PITWORM_LEVEL3]; |
|
} |
|
|
|
//========================================================= |
|
// IdealPosition |
|
//========================================================= |
|
const Vector& CPitWorm::IdealPosition(const float dz) const |
|
{ |
|
if (dz < PITWORM_LEVEL1_HEIGHT) |
|
return m_vecLevels[PITWORM_LEVEL0]; |
|
|
|
if (dz < PITWORM_LEVEL2_HEIGHT) |
|
return m_vecLevels[PITWORM_LEVEL1]; |
|
|
|
if (dz < PITWORM_LEVEL3_HEIGHT) |
|
return m_vecLevels[PITWORM_LEVEL2]; |
|
|
|
return m_vecLevels[PITWORM_LEVEL3]; |
|
} |
|
|
|
//========================================================= |
|
// IdealPosition |
|
//========================================================= |
|
const Vector& CPitWorm::IdealPosition(CBaseEntity* pEnemy) const |
|
{ |
|
return IdealPosition(pEnemy->pev->origin.z); |
|
} |
|
|
|
#define clamp( val, min, max ) ( ((val) > (max)) ? (max) : ( ((val) < (min)) ? (min) : (val) ) ) |
|
|
|
//========================================================= |
|
// UpdateBodyControllers |
|
//========================================================= |
|
void CPitWorm::UpdateBodyControllers( void ) |
|
{ |
|
if (!m_hEnemy) |
|
return; |
|
|
|
ASSERT( m_hEnemy ); |
|
|
|
Vector vecGoal = m_hEnemy->EyePosition(); |
|
Vector vecEye = EyePosition(); |
|
|
|
Vector target = (vecGoal - vecEye).Normalize(); |
|
Vector angles = UTIL_VecToAngles(target); |
|
float yaw = UTIL_VecToYaw(target); |
|
float pitch = angles.x; |
|
float initialYaw = m_flInitialYaw; |
|
float targetYaw = yaw - m_flInitialYaw; |
|
|
|
|
|
if (pitch < -180) |
|
pitch += 360; |
|
|
|
if (pitch > 180) |
|
pitch -= 360; |
|
|
|
float bodyPitch = 0; |
|
float bodyYaw = clamp(targetYaw, PITWORM_BODY_YAW_MIN, PITWORM_BODY_YAW_MAX); |
|
|
|
|
|
float targetBody = (fabs(targetYaw) * (bodyYaw - 5)) / 90; |
|
|
|
// Convert value to clamp it between min / max value of bone controller. |
|
float eyePitch = pitch; |
|
float eyeYaw = (targetBody * PITWORM_EYE_YAW_MAX) / PITWORM_BODY_YAW_MAX; |
|
|
|
|
|
// Clamp those values (ensure they stay between min / max). |
|
eyePitch = clamp(eyePitch, PITWORM_EYE_PITCH_MIN, PITWORM_EYE_PITCH_MAX); |
|
eyeYaw = clamp(eyeYaw, PITWORM_EYE_YAW_MIN, PITWORM_EYE_YAW_MAX); |
|
|
|
#if 0 |
|
// Just for debug. |
|
ALERT(at_console, "Body pitch: %f\n", bodyPitch); |
|
ALERT(at_console, "Body yaw: %f\n", bodyYaw); |
|
ALERT(at_console, "Eye yaw: %f\n", eyeYaw); |
|
ALERT(at_console, "Eye pitch: %f\n", eyePitch); |
|
#endif |
|
|
|
// Update body yaw controller value. |
|
SetBoneController(PITWORM_CONTROLLER_BODY_YAW, bodyYaw); |
|
|
|
// Update eye pitch controller value. |
|
SetBoneController(PITWORM_CONTROLLER_EYE_PITCH, -eyePitch); |
|
|
|
// Update eye yaw contoller value. |
|
SetBoneController(PITWORM_CONTROLLER_EYE_YAW, eyeYaw); |
|
} |
|
|
|
//========================================================= |
|
// CreateBeam |
|
//========================================================= |
|
void CPitWorm::CreateBeam(const Vector& src, const Vector& target, int width) |
|
{ |
|
m_pBeam = CBeam::BeamCreate("sprites/gworm_beam_02.spr", width); |
|
if (m_pBeam) |
|
{ |
|
m_pBeam->PointsInit(src, target); |
|
m_pBeam->SetBrightness( 200 ); |
|
m_pBeam->SetColor( 0, 255, 0 ); |
|
m_pBeam->SetNoise( 0 ); |
|
m_pBeam->SetFrame( 0 ); |
|
m_pBeam->SetScrollRate( 10 ); |
|
m_pBeam->RelinkBeam(); |
|
|
|
m_fBeamOn = TRUE; |
|
} |
|
} |
|
|
|
//========================================================= |
|
// DestroyBeam |
|
//========================================================= |
|
void CPitWorm::DestroyBeam(void) |
|
{ |
|
if (m_pBeam) |
|
{ |
|
UTIL_Remove(m_pBeam); |
|
m_pBeam = NULL; |
|
|
|
m_fBeamOn = FALSE; |
|
} |
|
} |
|
|
|
//========================================================= |
|
// UpdateBeam |
|
//========================================================= |
|
void CPitWorm::UpdateBeam(const Vector& src, const Vector& target) |
|
{ |
|
if (m_pBeam) |
|
{ |
|
m_pBeam->SetStartPos(src); |
|
m_pBeam->SetEndPos(target); |
|
m_pBeam->SetColor(0, 255, 0); |
|
m_pBeam->SetBrightness( 200 ); |
|
m_pBeam->RelinkBeam(); |
|
} |
|
} |
|
|
|
//========================================================= |
|
// SetupBeamPoints |
|
//========================================================= |
|
void CPitWorm::SetupBeamPoints(CBaseEntity* pEnemy, Vector* vecleft, Vector* vecRight ) |
|
{ |
|
Vector pos; |
|
Vector forward, right, up; |
|
|
|
pos = pEnemy->pev->origin + Vector(0, 0, 4); |
|
|
|
if (pEnemy->IsPlayer()) |
|
UTIL_MakeAimVectors(pEnemy->pev->v_angle); |
|
else |
|
UTIL_MakeAimVectors(pEnemy->pev->angles); |
|
|
|
forward = gpGlobals->v_forward; |
|
right = gpGlobals->v_right; |
|
up = gpGlobals->v_up; |
|
|
|
|
|
Vector beamLeft, beamRight; |
|
|
|
*vecleft = pos + (right * -16); |
|
*vecRight = pos + (right * 64); |
|
} |
|
|
|
//========================================================= |
|
// UpdateBeamPoints |
|
//========================================================= |
|
void CPitWorm::UpdateBeamPoints(CBaseEntity* pEnemy, Vector* target) |
|
{ |
|
Vector left, right; |
|
Vector dir; |
|
float delta; |
|
|
|
delta = 1.0f / PITWORM_EYEBLAST_DURATION; // 0.24 approximatly. (248 miliseconds) |
|
|
|
// Update beam yaw. |
|
m_flBeamYaw += delta; |
|
|
|
// Convert to distance to make the correct interpolation. |
|
float flDist = (80* m_flBeamYaw) / PITWORM_EYEBLAST_DURATION; |
|
|
|
SetupBeamPoints( pEnemy, &left, &right ); |
|
|
|
// Direction from right to left. |
|
dir = (left - right).Normalize(); |
|
|
|
// This is the result representing the next beam target |
|
// position along the player's left and right computed beam |
|
// positions. |
|
*target = right + (dir * flDist); |
|
} |
|
|
|
//========================================================= |
|
// CreateGlow |
|
//========================================================= |
|
void CPitWorm::CreateGlow( void ) |
|
{ |
|
m_pEyeGlow = CSprite::SpriteCreate("sprites/glow_grn.spr", pev->origin, TRUE); |
|
m_pEyeGlow->SetTransparency(kRenderGlow, 255, 255, 255, 0, kRenderFxNoDissipation); |
|
m_pEyeGlow->SetAttachment(edict(), 1); |
|
m_pEyeGlow->SetScale( 1.5f ); |
|
} |
|
|
|
//========================================================= |
|
// DestroyGlow |
|
//========================================================= |
|
void CPitWorm::DestroyGlow( void ) |
|
{ |
|
if (m_pEyeGlow) |
|
{ |
|
UTIL_Remove(m_pEyeGlow); |
|
m_pEyeGlow = NULL; |
|
} |
|
} |
|
|
|
//========================================================= |
|
// EyeOn |
|
//========================================================= |
|
void CPitWorm::EyeOn(int level) |
|
{ |
|
m_eyeBrightness = level; |
|
} |
|
|
|
//========================================================= |
|
// EyeOff |
|
//========================================================= |
|
void CPitWorm::EyeOff(void) |
|
{ |
|
m_eyeBrightness = 0; |
|
} |
|
|
|
//========================================================= |
|
// EyeUpdate |
|
//========================================================= |
|
void CPitWorm::EyeUpdate(void) |
|
{ |
|
if (m_pEyeGlow) |
|
{ |
|
m_pEyeGlow->pev->renderamt = UTIL_Approach(m_eyeBrightness, m_pEyeGlow->pev->renderamt, 100); |
|
if (m_pEyeGlow->pev->renderamt == 0) |
|
m_pEyeGlow->pev->effects |= EF_NODRAW; |
|
else |
|
m_pEyeGlow->pev->effects &= ~EF_NODRAW; |
|
UTIL_SetOrigin(m_pEyeGlow->pev, pev->origin); |
|
} |
|
} |