|
|
|
/***
|
|
|
|
*
|
|
|
|
* 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 "monsters.h"
|
|
|
|
#include "schedule.h"
|
|
|
|
#include "player.h"
|
|
|
|
#include "weapons.h"
|
|
|
|
|
|
|
|
#define GENEWORM_LEVEL0 0
|
|
|
|
#define GENEWORM_LEVEL1 1
|
|
|
|
|
|
|
|
#define GENEWORM_LEVEL0_HEIGHT 244
|
|
|
|
#define GENEWORM_LEVEL1_HEIGHT 304
|
|
|
|
|
|
|
|
|
|
|
|
#define GENEWORM_SKIN_EYE_OPEN 0
|
|
|
|
#define GENEWORM_SKIN_EYE_LEFT 1
|
|
|
|
#define GENEWORM_SKIN_EYE_RIGHT 2
|
|
|
|
#define GENEWORM_SKIN_EYE_CLOSED 3
|
|
|
|
|
|
|
|
#define GENEWORM_ATTACHMENT_MOUTH 0
|
|
|
|
#define GENEWORM_ATTACHMENT_SPAWN 1
|
|
|
|
#define GENEWORM_ATTACHMENT_RIGHTEYE 1
|
|
|
|
#define GENEWORM_ATTACHMENT_LEFTEYE 1
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
// Monster's Anim Events Go Here
|
|
|
|
//=========================================================
|
|
|
|
|
|
|
|
#define GENEWORM_AE_BEAM ( 0 ) // Toxic beam attack (sprite trail)
|
|
|
|
#define GENEWORM_AE_PORTAL ( 2 ) // Create a portal that spawns an enemy.
|
|
|
|
|
|
|
|
#define GENEWORM_AE_MELEE_LEFT1 ( 3 ) // Play hit sound
|
|
|
|
#define GENEWORM_AE_MELEE_LEFT2 ( 4 ) // Activates the trigger_geneworm_hit
|
|
|
|
|
|
|
|
#define GENEWORM_AE_MELEE_RIGHT1 ( 5 ) // Play hit sound
|
|
|
|
#define GENEWORM_AE_MELEE_RIGHT2 ( 6 ) // Activates the trigger_geneworm_hit
|
|
|
|
|
|
|
|
#define GENEWORM_AE_MELEE_FORWARD1 ( 7 ) // Play hit sound
|
|
|
|
#define GENEWORM_AE_MELEE_FORWARD2 ( 8 ) // Activates the trigger_geneworm_hit
|
|
|
|
|
|
|
|
#define GENEWORM_AE_MAD ( 9 ) // Room starts shaking!
|
|
|
|
|
|
|
|
#define GENEWORM_AE_EYEPAIN ( 1012 ) // Still put here (In case we need to toggle eye pain status)
|
|
|
|
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
// CGeneWormCloud
|
|
|
|
//=========================================================
|
|
|
|
|
|
|
|
class CGeneWormCloud : public CBaseEntity
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
void Spawn();
|
|
|
|
void Precache();
|
|
|
|
void TurnOn();
|
|
|
|
void RunGeneWormCloud(float frames);
|
|
|
|
static CGeneWormCloud *LaunchCloud(const Vector origin, const Vector aim, float velocity, edict_t *pOwner, float fadeTime);
|
|
|
|
void CreateCloud(const Vector origin);
|
|
|
|
|
|
|
|
virtual int Save(CSave &save);
|
|
|
|
virtual int Restore(CRestore &restore);
|
|
|
|
static TYPEDESCRIPTION m_SaveData[];
|
|
|
|
|
|
|
|
void EXPORT GeneWormCloudThink();
|
|
|
|
void EXPORT CloudTouch( CBaseEntity *pOther );
|
|
|
|
|
|
|
|
int m_maxFrame;
|
|
|
|
|
|
|
|
float m_fadeScale;
|
|
|
|
float m_fadeRender;
|
|
|
|
float m_lastTime;
|
|
|
|
float m_birthtime;
|
|
|
|
|
|
|
|
BOOL m_bLaunched;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
LINK_ENTITY_TO_CLASS(env_genewormcloud, CGeneWormCloud)
|
|
|
|
|
|
|
|
TYPEDESCRIPTION CGeneWormCloud::m_SaveData[] =
|
|
|
|
{
|
|
|
|
DEFINE_FIELD(CGeneWormCloud, m_maxFrame, FIELD_INTEGER),
|
|
|
|
DEFINE_FIELD(CGeneWormCloud, m_fadeScale, FIELD_FLOAT),
|
|
|
|
DEFINE_FIELD(CGeneWormCloud, m_fadeRender, FIELD_FLOAT),
|
|
|
|
DEFINE_FIELD(CGeneWormCloud, m_birthtime, FIELD_TIME),
|
|
|
|
DEFINE_FIELD(CGeneWormCloud, m_lastTime, FIELD_TIME),
|
|
|
|
DEFINE_FIELD(CGeneWormCloud, m_bLaunched, FIELD_BOOLEAN),
|
|
|
|
};
|
|
|
|
|
|
|
|
IMPLEMENT_SAVERESTORE(CGeneWormCloud, CBaseEntity)
|
|
|
|
|
|
|
|
void CGeneWormCloud::Precache()
|
|
|
|
{
|
|
|
|
PRECACHE_MODEL("sprites/ballsmoke.spr");
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGeneWormCloud::Spawn()
|
|
|
|
{
|
|
|
|
Precache();
|
|
|
|
|
|
|
|
pev->solid = SOLID_BBOX;
|
|
|
|
pev->effects = 0;
|
|
|
|
pev->frame = 0;
|
|
|
|
|
|
|
|
UTIL_SetSize(pev, Vector(0,0,0), Vector(0,0,0));
|
|
|
|
SET_MODEL(ENT(pev), "sprites/ballsmoke.spr");
|
|
|
|
|
|
|
|
m_maxFrame = MODEL_FRAMES(pev->modelindex)-1;
|
|
|
|
pev->scale = 0.01;
|
|
|
|
m_lastTime = gpGlobals->time;
|
|
|
|
m_birthtime = gpGlobals->time;
|
|
|
|
|
|
|
|
m_fadeScale = 0;
|
|
|
|
m_bLaunched = FALSE;
|
|
|
|
|
|
|
|
SetTouch(&CGeneWormCloud::CloudTouch);
|
|
|
|
SetThink(&CGeneWormCloud::GeneWormCloudThink);
|
|
|
|
|
|
|
|
pev->nextthink = gpGlobals->time;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGeneWormCloud::CloudTouch(CBaseEntity *pOther)
|
|
|
|
{
|
|
|
|
if (ENT(pOther->pev) == pev->owner || (ENT(pOther->pev) == VARS(pev->owner)->owner))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(pOther->pev->takedamage)
|
|
|
|
pOther->TakeDamage(pev, pev, 5, DMG_ACID);
|
|
|
|
|
|
|
|
pev->nextthink = gpGlobals->time;
|
|
|
|
SetThink(NULL);
|
|
|
|
UTIL_Remove(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CGeneWormCloud::TurnOn()
|
|
|
|
{
|
|
|
|
pev->effects = 0;
|
|
|
|
|
|
|
|
if(pev->framerate != 0 && m_maxFrame > 1 && pev->spawnflags & FL_SWIM)
|
|
|
|
{
|
|
|
|
m_lastTime = gpGlobals->time;
|
|
|
|
pev->nextthink = gpGlobals->time;
|
|
|
|
pev->frame = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pev->frame = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGeneWormCloud::RunGeneWormCloud(float frames)
|
|
|
|
{
|
|
|
|
if(m_bLaunched)
|
|
|
|
{
|
|
|
|
pev->renderamt -= m_fadeRender;
|
|
|
|
|
|
|
|
if(pev->scale >= 4.5)
|
|
|
|
{
|
|
|
|
pev->scale = 0;
|
|
|
|
UTIL_Remove(this);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pev->scale += 0.1;
|
|
|
|
|
|
|
|
pev->frame += frames;
|
|
|
|
|
|
|
|
if(pev->frame > m_maxFrame && m_maxFrame > 0)
|
|
|
|
{
|
|
|
|
pev->frame = m_maxFrame;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGeneWormCloud::GeneWormCloudThink()
|
|
|
|
{
|
|
|
|
TraceResult tr;
|
|
|
|
|
|
|
|
float frames = (gpGlobals->time - m_lastTime) * pev->framerate;
|
|
|
|
|
|
|
|
UTIL_TraceHull(pev->origin, pev->origin, ignore_monsters, point_hull, ENT(pev), &tr);
|
|
|
|
|
|
|
|
if(tr.fAllSolid && tr.fStartSolid && gpGlobals->time - m_birthtime >= 0.75)
|
|
|
|
{
|
|
|
|
UTIL_Remove(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
RunGeneWormCloud(frames);
|
|
|
|
|
|
|
|
pev->nextthink = gpGlobals->time + 0.1;
|
|
|
|
m_lastTime = gpGlobals->time;
|
|
|
|
}
|
|
|
|
|
|
|
|
CGeneWormCloud *CGeneWormCloud::LaunchCloud(const Vector origin, const Vector aim, float velocity, edict_t *pOwner, float fadeTime)
|
|
|
|
{
|
|
|
|
CGeneWormCloud *pCloud = GetClassPtr((CGeneWormCloud*)NULL);
|
|
|
|
UTIL_SetOrigin(pCloud->pev, origin);
|
|
|
|
pCloud->Spawn();
|
|
|
|
|
|
|
|
UTIL_MakeVectors(aim);
|
|
|
|
|
|
|
|
pCloud->pev->owner = pOwner;
|
|
|
|
|
|
|
|
pCloud->pev->skin = 0;
|
|
|
|
pCloud->pev->body = 0;
|
|
|
|
pCloud->pev->aiment = 0;
|
|
|
|
pCloud->pev->movetype = MOVETYPE_NOCLIP;
|
|
|
|
|
|
|
|
pCloud->pev->velocity = aim * velocity;
|
|
|
|
pCloud->m_fadeScale = 2.5 / fadeTime;
|
|
|
|
pCloud->m_fadeRender = (pCloud->pev->renderamt - 7) / fadeTime;
|
|
|
|
|
|
|
|
pCloud->m_bLaunched = TRUE;
|
|
|
|
|
|
|
|
return pCloud;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGeneWormCloud::CreateCloud(const Vector origin)
|
|
|
|
{
|
|
|
|
UTIL_SetOrigin(pev, origin);
|
|
|
|
|
|
|
|
SetThink(&CGeneWormCloud::GeneWormCloudThink);
|
|
|
|
SetTouch(&CGeneWormCloud::CloudTouch);
|
|
|
|
}
|
|
|
|
|
|
|
|
//========================================================
|
|
|
|
// CGeneWormSpawn
|
|
|
|
//========================================================
|
|
|
|
|
|
|
|
class CGeneWormSpawn : public CBaseEntity
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
void Spawn();
|
|
|
|
void Precache();
|
|
|
|
virtual int Save(CSave &save);
|
|
|
|
virtual int Restore(CRestore &restore);
|
|
|
|
static CGeneWormSpawn *LaunchSpawn(Vector origin, Vector aim, float speed, edict_t *pOwner);
|
|
|
|
|
|
|
|
void EXPORT SpawnTouch(CBaseEntity *pOther) { }
|
|
|
|
void EXPORT SpawnThink();
|
|
|
|
|
|
|
|
static TYPEDESCRIPTION m_SaveData[];
|
|
|
|
float m_flBirthTime;
|
|
|
|
int m_maxFrame;
|
|
|
|
BOOL m_bTrooperDropped;
|
|
|
|
};
|
|
|
|
|
|
|
|
LINK_ENTITY_TO_CLASS(env_genewormspawn, CGeneWormSpawn)
|
|
|
|
|
|
|
|
TYPEDESCRIPTION CGeneWormSpawn::m_SaveData[] =
|
|
|
|
{
|
|
|
|
DEFINE_FIELD(CGeneWormSpawn, m_flBirthTime, FIELD_TIME),
|
|
|
|
DEFINE_FIELD(CGeneWormSpawn, m_bTrooperDropped, FIELD_BOOLEAN),
|
|
|
|
DEFINE_FIELD(CGeneWormSpawn, m_maxFrame, FIELD_INTEGER),
|
|
|
|
};
|
|
|
|
|
|
|
|
IMPLEMENT_SAVERESTORE(CGeneWormSpawn, CBaseEntity)
|
|
|
|
|
|
|
|
void CGeneWormSpawn::Precache()
|
|
|
|
{
|
|
|
|
PRECACHE_MODEL("sprites/tele1.spr");
|
|
|
|
PRECACHE_MODEL("sprites/boss_glow.spr");
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGeneWormSpawn::Spawn()
|
|
|
|
{
|
|
|
|
Precache();
|
|
|
|
pev->classname = MAKE_STRING("env_genewormspawn");
|
|
|
|
|
|
|
|
pev->solid = SOLID_BBOX;
|
|
|
|
pev->movetype = MOVETYPE_NOCLIP;
|
|
|
|
pev->effects = 0;
|
|
|
|
pev->frame = 0;
|
|
|
|
pev->scale = 1.5;
|
|
|
|
pev->rendermode = kRenderTransAdd;
|
|
|
|
pev->renderamt = 255;
|
|
|
|
|
|
|
|
SET_MODEL(ENT(pev), "sprites/tele1.spr");
|
|
|
|
UTIL_SetSize(pev, g_vecZero, g_vecZero);
|
|
|
|
|
|
|
|
m_maxFrame = g_engfuncs.pfnModelFrames(pev->modelindex) - 1;
|
|
|
|
|
|
|
|
if(pev->angles.y != 0 && pev->angles.z == 0)
|
|
|
|
{
|
|
|
|
pev->angles.z = pev->angles.y;
|
|
|
|
pev->angles.y = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_bTrooperDropped = FALSE;
|
|
|
|
m_flBirthTime = gpGlobals->time;
|
|
|
|
|
|
|
|
SetTouch(&CGeneWormSpawn::SpawnTouch);
|
|
|
|
SetThink(&CGeneWormSpawn::SpawnThink);
|
|
|
|
|
|
|
|
pev->nextthink = gpGlobals->time + 0.1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGeneWormSpawn::SpawnThink()
|
|
|
|
{
|
|
|
|
CBaseEntity *player;
|
|
|
|
|
|
|
|
pev->effects = 0;
|
|
|
|
pev->framerate = 10;
|
|
|
|
|
|
|
|
if((pev->origin - pev->owner->v.origin).Length() > 1050)
|
|
|
|
{
|
|
|
|
pev->velocity = g_vecZero;
|
|
|
|
|
|
|
|
if(gpGlobals->time - m_flBirthTime >= 2.5)
|
|
|
|
{
|
|
|
|
if(!m_bTrooperDropped)
|
|
|
|
{
|
|
|
|
EMIT_SOUND_DYN(ENT(pev), CHAN_ITEM, "debris/beamstart2.wav", 1, 0.4, 0, 100);
|
|
|
|
Create("monster_shocktrooper", pev->origin, pev->angles, ENT(pev));
|
|
|
|
m_bTrooperDropped = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pev->scale -= 0.25;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(pev->scale <= 0)
|
|
|
|
UTIL_Remove(this);
|
|
|
|
|
|
|
|
if(pev->frame >= m_maxFrame)
|
|
|
|
pev->frame = 0;
|
|
|
|
else
|
|
|
|
pev->frame++;
|
|
|
|
|
|
|
|
if(pev->scale < 3.2)
|
|
|
|
pev->scale += 0.1;
|
|
|
|
|
|
|
|
if((player = UTIL_FindEntityByClassname(0, "player")))
|
|
|
|
{
|
|
|
|
if((player->pev->origin - pev->origin).Length() <= 96)
|
|
|
|
player->TakeDamage(VARS(player->pev), VARS(player->pev), 5, DMG_SHOCK);
|
|
|
|
}
|
|
|
|
|
|
|
|
pev->nextthink = gpGlobals->time + 0.1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CGeneWormSpawn *CGeneWormSpawn::LaunchSpawn(Vector origin, Vector aim, float speed, edict_t *pOwner)
|
|
|
|
{
|
|
|
|
CGeneWormSpawn *WormSpawn = GetClassPtr((CGeneWormSpawn*)NULL);
|
|
|
|
|
|
|
|
UTIL_MakeVectors(aim);
|
|
|
|
UTIL_SetOrigin(WormSpawn->pev, origin);
|
|
|
|
|
|
|
|
WormSpawn->Spawn();
|
|
|
|
WormSpawn->pev->velocity = aim * speed;
|
|
|
|
WormSpawn->pev->owner = pOwner;
|
|
|
|
|
|
|
|
|
|
|
|
return WormSpawn;
|
|
|
|
}
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
// CGeneWorm
|
|
|
|
//=========================================================
|
|
|
|
class CGeneWorm : public CBaseMonster
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
int Save(CSave &save);
|
|
|
|
int Restore(CRestore &restore);
|
|
|
|
static TYPEDESCRIPTION m_SaveData[];
|
|
|
|
|
|
|
|
void Spawn(void);
|
|
|
|
void Precache(void);
|
|
|
|
int Classify(void) { return CLASS_ALIEN_MONSTER; }
|
|
|
|
void Killed(entvars_t *pevAttacker, int iGib);
|
|
|
|
void TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
|
|
|
|
void FireHurtTargets(const char *targetName, CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value);
|
|
|
|
|
|
|
|
void SetObjectCollisionBox(void)
|
|
|
|
{
|
|
|
|
pev->absmin = pev->origin + Vector( -437, -720, -332 );
|
|
|
|
pev->absmax = pev->origin + Vector( 425, 164, 355 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void HandleAnimEvent(MonsterEvent_t *pEvent);
|
|
|
|
|
|
|
|
void EXPORT StartThink(void);
|
|
|
|
void EXPORT HuntThink(void);
|
|
|
|
void EXPORT CrashTouch(CBaseEntity *pOther);
|
|
|
|
void EXPORT DyingThink(void);
|
|
|
|
void EXPORT NullThink(void);
|
|
|
|
void EXPORT CommandUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value);
|
|
|
|
void EXPORT HitTouch( CBaseEntity *pOther );
|
|
|
|
|
|
|
|
void NextActivity(void);
|
|
|
|
|
|
|
|
void TrackHead();
|
|
|
|
|
|
|
|
int TakeDamage(entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType);
|
|
|
|
|
|
|
|
void PainSound(void);
|
|
|
|
void DeathSound(void);
|
|
|
|
void IdleSound(void);
|
|
|
|
|
|
|
|
BOOL ClawAttack();
|
|
|
|
|
|
|
|
Vector m_posTarget;
|
|
|
|
|
|
|
|
CGeneWormCloud *m_pCloud;
|
|
|
|
CGeneWormSpawn *m_orificeGlow;
|
|
|
|
CSprite *m_pBall;
|
|
|
|
|
|
|
|
float m_flLastSeen;
|
|
|
|
float m_flOrificeOpenTime;
|
|
|
|
float m_flSpitStartTime;
|
|
|
|
float m_flMadDelayTime;
|
|
|
|
float m_flTakeHitTime;
|
|
|
|
float m_flHitTime;
|
|
|
|
float m_flNextMeleeTime;
|
|
|
|
float m_flNextRangeTime;
|
|
|
|
float m_flDeathStart;
|
|
|
|
|
|
|
|
BOOL m_fActivated;
|
|
|
|
BOOL m_fRightEyeHit;
|
|
|
|
BOOL m_fLeftEyeHit;
|
|
|
|
BOOL m_fGetMad;
|
|
|
|
BOOL m_fOrificeHit;
|
|
|
|
BOOL m_fSpiting;
|
|
|
|
BOOL m_fSpawningTrooper;
|
|
|
|
BOOL m_fHasEntered;
|
|
|
|
|
|
|
|
int m_iHitTimes;
|
|
|
|
int m_iMaxHitTimes;
|
|
|
|
int m_iWasHit;
|
|
|
|
|
|
|
|
static const char *pAttackSounds[];
|
|
|
|
static const char *pDeathSounds[];
|
|
|
|
static const char *pEntrySounds[];
|
|
|
|
static const char *pPainSounds[];
|
|
|
|
static const char *pIdleSounds[];
|
|
|
|
static const char *pEyePainSounds[];
|
|
|
|
};
|
|
|
|
|
|
|
|
LINK_ENTITY_TO_CLASS(monster_geneworm, CGeneWorm)
|
|
|
|
|
|
|
|
TYPEDESCRIPTION CGeneWorm::m_SaveData[] =
|
|
|
|
{
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_posTarget, FIELD_POSITION_VECTOR),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_flLastSeen, FIELD_TIME),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_pCloud, FIELD_CLASSPTR),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_orificeGlow, FIELD_CLASSPTR),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_pBall, FIELD_CLASSPTR),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_iHitTimes, FIELD_INTEGER),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_iMaxHitTimes, FIELD_INTEGER),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_iWasHit, FIELD_INTEGER),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_flNextMeleeTime, FIELD_TIME),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_flNextRangeTime, FIELD_TIME),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_fRightEyeHit, FIELD_BOOLEAN),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_fLeftEyeHit, FIELD_BOOLEAN),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_fOrificeHit, FIELD_BOOLEAN),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_flOrificeOpenTime, FIELD_TIME),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_fSpawningTrooper, FIELD_BOOLEAN),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_fActivated, FIELD_BOOLEAN),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_flDeathStart, FIELD_TIME),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_fHasEntered, FIELD_BOOLEAN),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_flMadDelayTime, FIELD_TIME),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_fGetMad, FIELD_BOOLEAN),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_fSpiting, FIELD_BOOLEAN),
|
|
|
|
DEFINE_FIELD(CGeneWorm, m_flSpitStartTime, FIELD_TIME),
|
|
|
|
};
|
|
|
|
IMPLEMENT_SAVERESTORE(CGeneWorm, CBaseMonster)
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
//=========================================================
|
|
|
|
|
|
|
|
const char *CGeneWorm::pAttackSounds[] =
|
|
|
|
{
|
|
|
|
"geneworm/geneworm_attack_mounted_gun.wav",
|
|
|
|
"geneworm/geneworm_attack_mounted_rocket.wav",
|
|
|
|
"geneworm/geneworm_beam_attack.wav",
|
|
|
|
"geneworm/geneworm_big_attack_forward.wav",
|
|
|
|
};
|
|
|
|
|
|
|
|
const char *CGeneWorm::pDeathSounds[] =
|
|
|
|
{
|
|
|
|
"geneworm/geneworm_death.wav",
|
|
|
|
};
|
|
|
|
|
|
|
|
const char *CGeneWorm::pEntrySounds[] =
|
|
|
|
{
|
|
|
|
"geneworm/geneworm_entry.wav",
|
|
|
|
};
|
|
|
|
|
|
|
|
const char *CGeneWorm::pPainSounds[] =
|
|
|
|
{
|
|
|
|
"geneworm/geneworm_final_pain1.wav",
|
|
|
|
"geneworm/geneworm_final_pain2.wav",
|
|
|
|
"geneworm/geneworm_final_pain3.wav",
|
|
|
|
"geneworm/geneworm_final_pain4.wav",
|
|
|
|
};
|
|
|
|
|
|
|
|
const char *CGeneWorm::pIdleSounds[] =
|
|
|
|
{
|
|
|
|
"geneworm/geneworm_idle1.wav",
|
|
|
|
"geneworm/geneworm_idle2.wav",
|
|
|
|
"geneworm/geneworm_idle3.wav",
|
|
|
|
"geneworm/geneworm_idle4.wav",
|
|
|
|
};
|
|
|
|
|
|
|
|
const char *CGeneWorm::pEyePainSounds[] =
|
|
|
|
{
|
|
|
|
"geneworm/geneworm_shot_in_eye.wav",
|
|
|
|
};
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
// Spawn
|
|
|
|
//=========================================================
|
|
|
|
void CGeneWorm::Spawn()
|
|
|
|
{
|
|
|
|
Precache();
|
|
|
|
// motor
|
|
|
|
pev->movetype = MOVETYPE_FLY;
|
|
|
|
pev->solid = SOLID_NOT;
|
|
|
|
|
|
|
|
|
|
|
|
SET_MODEL(ENT(pev), "models/geneworm.mdl");
|
|
|
|
UTIL_SetSize(pev, Vector( -437, -720, -332 ), Vector( 425, 164, 355 ));
|
|
|
|
UTIL_SetOrigin(pev, pev->origin);
|
|
|
|
|
|
|
|
pev->flags |= FL_MONSTER;
|
|
|
|
pev->takedamage = DAMAGE_AIM;
|
|
|
|
pev->health = gSkillData.gwormHealth;
|
|
|
|
pev->view_ofs = Vector(0, 0, 192);
|
|
|
|
|
|
|
|
pev->sequence = 0;
|
|
|
|
ResetSequenceInfo();
|
|
|
|
|
|
|
|
InitBoneControllers();
|
|
|
|
|
|
|
|
pev->deadflag = DEAD_NO;
|
|
|
|
pev->renderamt = 0;
|
|
|
|
pev->rendermode = kRenderTransTexture;
|
|
|
|
pev->effects = 0;
|
|
|
|
|
|
|
|
m_bloodColor = BLOOD_COLOR_GREEN;
|
|
|
|
|
|
|
|
m_iHitTimes = 0;
|
|
|
|
m_iMaxHitTimes = 5;
|
|
|
|
m_MonsterState = MONSTERSTATE_IDLE;
|
|
|
|
|
|
|
|
m_flSpitStartTime = gpGlobals->time;
|
|
|
|
m_flOrificeOpenTime = gpGlobals->time;
|
|
|
|
m_flMadDelayTime = gpGlobals->time;
|
|
|
|
m_flTakeHitTime = 0;
|
|
|
|
m_flHitTime = 0;
|
|
|
|
|
|
|
|
m_iWasHit = FALSE;
|
|
|
|
m_fRightEyeHit = FALSE;
|
|
|
|
m_fLeftEyeHit = FALSE;
|
|
|
|
m_fGetMad = FALSE;
|
|
|
|
m_fOrificeHit = FALSE;
|
|
|
|
m_fActivated = FALSE;
|
|
|
|
m_fHasEntered = FALSE;
|
|
|
|
m_pCloud = NULL;
|
|
|
|
|
|
|
|
UTIL_SetOrigin(pev, pev->origin);
|
|
|
|
|
|
|
|
SetThink(&CGeneWorm::StartThink);
|
|
|
|
|
|
|
|
pev->nextthink = gpGlobals->time + 0.1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
// Precache - precaches all resources this monster needs
|
|
|
|
//=========================================================
|
|
|
|
void CGeneWorm::Precache()
|
|
|
|
{
|
|
|
|
PRECACHE_MODEL("models/geneworm.mdl");
|
|
|
|
|
|
|
|
PRECACHE_SOUND_ARRAY(pAttackSounds);
|
|
|
|
PRECACHE_SOUND_ARRAY(pDeathSounds);
|
|
|
|
PRECACHE_SOUND_ARRAY(pEntrySounds);
|
|
|
|
PRECACHE_SOUND_ARRAY(pPainSounds);
|
|
|
|
PRECACHE_SOUND_ARRAY(pIdleSounds);
|
|
|
|
PRECACHE_SOUND_ARRAY(pEyePainSounds);
|
|
|
|
PRECACHE_SOUND("debris/beamstart7.wav");
|
|
|
|
PRECACHE_SOUND("debris/beamstart2.wav");
|
|
|
|
PRECACHE_MODEL("sprites/tele1.spr");
|
|
|
|
PRECACHE_MODEL("sprites/ballsmoke.spr");
|
|
|
|
PRECACHE_MODEL("sprites/boss_glow.spr");
|
|
|
|
UTIL_PrecacheOther("monster_shocktrooper");
|
|
|
|
}
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
//
|
|
|
|
//=========================================================
|
|
|
|
void CGeneWorm::StartThink(void)
|
|
|
|
{
|
|
|
|
Vector vecEyePos, vecEyeAng;
|
|
|
|
|
|
|
|
GetAttachment(0, vecEyePos, vecEyeAng);
|
|
|
|
|
|
|
|
pev->view_ofs = vecEyePos - pev->origin;
|
|
|
|
|
|
|
|
pev->frame = 0;
|
|
|
|
pev->sequence = LookupSequence("entry");
|
|
|
|
ResetSequenceInfo();
|
|
|
|
m_flNextMeleeTime = gpGlobals->time;
|
|
|
|
m_flNextRangeTime = gpGlobals->time;
|
|
|
|
|
|
|
|
SetUse(&CGeneWorm::CommandUse);
|
|
|
|
SetTouch(&CGeneWorm::HitTouch);
|
|
|
|
SetThink(&CGeneWorm::HuntThink);
|
|
|
|
|
|
|
|
pev->nextthink = gpGlobals->time + 0.1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CGeneWorm::HitTouch( CBaseEntity *pOther )
|
|
|
|
{
|
|
|
|
TraceResult tr = UTIL_GetGlobalTrace();
|
|
|
|
|
|
|
|
if( pOther->pev->modelindex == pev->modelindex )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if( m_flHitTime > gpGlobals->time )
|
|
|
|
return;
|
|
|
|
|
|
|
|
// only look at the ones where the player hit me
|
|
|
|
if( tr.pHit == NULL || tr.pHit->v.modelindex != pev->modelindex )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if( tr.iHitgroup == 0 )
|
|
|
|
{
|
|
|
|
pOther->TakeDamage( pev, pev, 20, DMG_CRUSH );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CGeneWorm::Killed(entvars_t *pevAttacker, int iGib)
|
|
|
|
{
|
|
|
|
CBaseMonster::Killed(pevAttacker, iGib);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGeneWorm::DyingThink(void)
|
|
|
|
{
|
|
|
|
pev->nextthink = gpGlobals->time + 0.1;
|
|
|
|
GlowShellUpdate();
|
|
|
|
|
|
|
|
DispatchAnimEvents();
|
|
|
|
StudioFrameAdvance();
|
|
|
|
|
|
|
|
if(pev->deadflag == DEAD_DYING)
|
|
|
|
{
|
|
|
|
pev->renderamt--;
|
|
|
|
|
|
|
|
if( pev->renderamt == 0 )
|
|
|
|
UTIL_Remove( this );
|
|
|
|
|
|
|
|
if(gpGlobals->time - m_flDeathStart >= 15)
|
|
|
|
{
|
|
|
|
CBaseEntity* player = UTIL_FindEntityByClassname(0, "player");
|
|
|
|
if (player)
|
|
|
|
{
|
|
|
|
CBaseEntity* teleport = UTIL_FindEntityByTargetname(0, "GeneWormTeleport");
|
|
|
|
if (teleport)
|
|
|
|
teleport->Touch(player);
|
|
|
|
FireTargets("GeneWormTeleport", player, player, USE_ON, 1.0);
|
|
|
|
}
|
|
|
|
m_flDeathStart = gpGlobals->time + 999;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(pev->deadflag == DEAD_NO)
|
|
|
|
{
|
|
|
|
pev->frame = 0;
|
|
|
|
pev->sequence = LookupSequence("death");
|
|
|
|
|
|
|
|
ResetSequenceInfo();
|
|
|
|
|
|
|
|
pev->renderfx = 0;
|
|
|
|
pev->rendermode = kRenderTransTexture;
|
|
|
|
pev->renderamt = 255;
|
|
|
|
pev->solid = SOLID_NOT;
|
|
|
|
|
|
|
|
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "geneworm/geneworm_death.wav", 1, 0.1, 0, 100);
|
|
|
|
|
|
|
|
FireTargets("GeneWormDead", this, this, USE_TOGGLE, 0);
|
|
|
|
|
|
|
|
m_flDeathStart = gpGlobals->time;
|
|
|
|
pev->deadflag = DEAD_DYING;
|
|
|
|
|
|
|
|
if(m_pCloud)
|
|
|
|
{
|
|
|
|
UTIL_Remove(m_pCloud);
|
|
|
|
m_pCloud = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_orificeGlow)
|
|
|
|
{
|
|
|
|
UTIL_Remove(m_orificeGlow);
|
|
|
|
m_orificeGlow = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_pBall)
|
|
|
|
{
|
|
|
|
UTIL_Remove(m_pBall);
|
|
|
|
m_pBall = NULL;
|
|
|
|
}
|
|
|
|
CBaseEntity* entity = NULL;
|
|
|
|
while((entity = UTIL_FindEntityByClassname(entity, "monster_shocktrooper")))
|
|
|
|
entity->SUB_StartFadeOut();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//=========================================================
|
|
|
|
//=========================================================
|
|
|
|
|
|
|
|
void CGeneWorm::FireHurtTargets(const char *targetName, CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
|
|
|
|
{
|
|
|
|
edict_t *pentTarget = NULL;
|
|
|
|
|
|
|
|
if( !targetName )
|
|
|
|
return;
|
|
|
|
|
|
|
|
ALERT( at_aiconsole, "Firing: (%s)\n", targetName );
|
|
|
|
|
|
|
|
for( ; ; )
|
|
|
|
{
|
|
|
|
pentTarget = FIND_ENTITY_BY_TARGETNAME( pentTarget, targetName );
|
|
|
|
if( FNullEnt( pentTarget ) )
|
|
|
|
break;
|
|
|
|
|
|
|
|
CBaseEntity *pTarget = CBaseEntity::Instance( pentTarget );
|
|
|
|
if( pTarget && !( pTarget->pev->flags & FL_NOTARGET ) )
|
|
|
|
{
|
|
|
|
ALERT( at_aiconsole, "Found: %s, firing (%s)\n", STRING( pTarget->pev->classname ), targetName );
|
|
|
|
pTarget->Use( pActivator, pCaller, useType, value );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
//=========================================================
|
|
|
|
void CGeneWorm::NextActivity(void)
|
|
|
|
{
|
|
|
|
if (m_flLastSeen + 15 < gpGlobals->time)
|
|
|
|
{
|
|
|
|
if (m_hEnemy != 0)
|
|
|
|
{
|
|
|
|
if ((pev->origin - m_hEnemy->pev->origin).Length() > 700)
|
|
|
|
m_hEnemy = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_hEnemy == 0)
|
|
|
|
{
|
|
|
|
Look(4096);
|
|
|
|
m_hEnemy = BestVisibleEnemy();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_fGetMad)
|
|
|
|
{
|
|
|
|
pev->sequence = LookupSequence("mad");
|
|
|
|
m_flMadDelayTime = gpGlobals->time;
|
|
|
|
m_fGetMad = FALSE;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_fRightEyeHit && m_fLeftEyeHit)
|
|
|
|
{
|
|
|
|
if(gpGlobals->time <= m_flOrificeOpenTime && !m_fOrificeHit)
|
|
|
|
{
|
|
|
|
pev->sequence = LookupSequence("bigpain2");
|
|
|
|
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "geneworm/geneworm_final_pain2.wav", VOL_NORM, 0.1, 0, 100);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_flOrificeOpenTime = gpGlobals->time;
|
|
|
|
|
|
|
|
if(!m_fSpawningTrooper)
|
|
|
|
{
|
|
|
|
pev->sequence = LookupSequence("bigpain4");
|
|
|
|
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "geneworm/geneworm_final_pain4.wav", VOL_NORM, 0.1, 0, 100);
|
|
|
|
m_fSpawningTrooper = TRUE;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_fLeftEyeHit = FALSE;
|
|
|
|
m_fRightEyeHit = FALSE;
|
|
|
|
m_fOrificeHit = FALSE;
|
|
|
|
m_fSpawningTrooper = FALSE;
|
|
|
|
pev->skin = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ClawAttack())
|
|
|
|
return;
|
|
|
|
|
|
|
|
pev->sequence = LookupSequence("idle");
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGeneWorm::TrackHead()
|
|
|
|
{
|
|
|
|
Vector vecMouthPos, vecMouthAngle;
|
|
|
|
GetAttachment(0, vecMouthPos, vecMouthAngle);
|
|
|
|
Vector angles = UTIL_VecToAngles(m_posTarget - vecMouthPos);
|
|
|
|
float diff = UTIL_AngleDiff(angles.y, pev->angles.y);
|
|
|
|
if (diff < -30)
|
|
|
|
{
|
|
|
|
diff = -30;
|
|
|
|
}
|
|
|
|
else if (diff > 30)
|
|
|
|
{
|
|
|
|
diff = 30;
|
|
|
|
}
|
|
|
|
SetBoneController(0, diff);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL CGeneWorm::ClawAttack()
|
|
|
|
{
|
|
|
|
Vector targetAngle;
|
|
|
|
const char *sound;
|
|
|
|
|
|
|
|
if(m_hEnemy)
|
|
|
|
{
|
|
|
|
m_posTarget = m_hEnemy->pev->origin;
|
|
|
|
targetAngle = UTIL_VecToAngles(m_posTarget - pev->origin);
|
|
|
|
float AngleDiff = UTIL_AngleDiff(targetAngle.y, pev->angles.y);
|
|
|
|
|
|
|
|
if(m_flNextRangeTime <= gpGlobals->time)
|
|
|
|
{
|
|
|
|
if((m_posTarget - pev->origin).Length() >= 1200)
|
|
|
|
pev->sequence = LookupSequence("dattack1");
|
|
|
|
else if(AngleDiff > 10)
|
|
|
|
pev->sequence = LookupSequence("dattack2");
|
|
|
|
else if(AngleDiff < 0)
|
|
|
|
pev->sequence = LookupSequence("dattack3");
|
|
|
|
|
|
|
|
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "geneworm/geneworm_beam_attack.wav", 1, 0.1, 0, 100);
|
|
|
|
|
|
|
|
m_flNextRangeTime = gpGlobals->time + RANDOM_FLOAT(10,15);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_flNextMeleeTime <= gpGlobals->time)
|
|
|
|
{
|
|
|
|
if(m_posTarget.z <= pev->origin.z)
|
|
|
|
pev->sequence = LookupSequence("melee3");
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(AngleDiff >= 10)
|
|
|
|
{
|
|
|
|
pev->sequence = LookupSequence("melee1");
|
|
|
|
sound = "geneworm/geneworm_attack_mounted_rocket.wav";
|
|
|
|
}
|
|
|
|
else if(AngleDiff <= -2)
|
|
|
|
{
|
|
|
|
pev->sequence = LookupSequence("melee2");
|
|
|
|
sound = "geneworm/geneworm_big_attack_forward.wav";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pev->sequence = LookupSequence("melee3");
|
|
|
|
sound = "geneworm/geneworm_attack_mounted_gun.wav";
|
|
|
|
}
|
|
|
|
|
|
|
|
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, sound, 1, 0.1, 0, 100);
|
|
|
|
|
|
|
|
m_flNextMeleeTime = gpGlobals->time + RANDOM_FLOAT(3,5);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGeneWorm::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType)
|
|
|
|
{
|
|
|
|
if(FClassnameIs(pevAttacker, "monster_penguin"))
|
|
|
|
{
|
|
|
|
pev->health = 0;
|
|
|
|
SetThink(&CGeneWorm::DyingThink);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(gpGlobals->time <= m_flTakeHitTime)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(ptr->iHitgroup != 5 && ptr->iHitgroup != 4 && ptr->iHitgroup != 6)
|
|
|
|
{
|
|
|
|
if(pev->dmgtime != gpGlobals->time|| RANDOM_LONG(0, 10) <= 0)
|
|
|
|
{
|
|
|
|
if(FClassnameIs(pevAttacker, "env_laser"))
|
|
|
|
{
|
|
|
|
UTIL_Sparks(ptr->vecEndPos);
|
|
|
|
}
|
|
|
|
else if(bitsDamageType & DMG_BULLET)
|
|
|
|
{
|
|
|
|
UTIL_Ricochet(ptr->vecEndPos, RANDOM_LONG(1, 2));
|
|
|
|
}
|
|
|
|
pev->dmgtime = gpGlobals->time;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(FClassnameIs(pevAttacker, "env_laser"))
|
|
|
|
{
|
|
|
|
if(!m_fHasEntered)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(ptr->iHitgroup == 4 && !m_fLeftEyeHit && FStrEq("left_eye_laser", STRING(pevAttacker->targetname)))
|
|
|
|
{
|
|
|
|
m_fLeftEyeHit = TRUE;
|
|
|
|
m_iWasHit = 1;
|
|
|
|
|
|
|
|
if(!m_fRightEyeHit)
|
|
|
|
{
|
|
|
|
pev->skin = GENEWORM_SKIN_EYE_LEFT;
|
|
|
|
|
|
|
|
if(gpGlobals->time - m_flMadDelayTime >= 6)
|
|
|
|
m_fGetMad = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pev->skin = GENEWORM_SKIN_EYE_CLOSED;
|
|
|
|
m_flOrificeOpenTime = gpGlobals->time + 20;
|
|
|
|
m_fGetMad = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
UTIL_BloodDrips(ptr->vecEndPos, ptr->vecEndPos, m_bloodColor, 256);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ptr->iHitgroup == 5 && !m_fRightEyeHit && FStrEq("right_eye_laser", STRING(pevAttacker->targetname)))
|
|
|
|
{
|
|
|
|
m_fRightEyeHit = TRUE;
|
|
|
|
m_iWasHit = 1;
|
|
|
|
|
|
|
|
if(!m_fLeftEyeHit)
|
|
|
|
{
|
|
|
|
pev->skin = GENEWORM_SKIN_EYE_RIGHT;
|
|
|
|
|
|
|
|
if(gpGlobals->time - m_flMadDelayTime >= 6)
|
|
|
|
m_fGetMad = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pev->skin = GENEWORM_SKIN_EYE_CLOSED;
|
|
|
|
m_flOrificeOpenTime = gpGlobals->time + 20;
|
|
|
|
m_fGetMad = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
UTIL_BloodDrips(ptr->vecEndPos, ptr->vecEndPos, m_bloodColor, 256);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_flOrificeOpenTime >= gpGlobals->time && m_pBall && ptr->iHitgroup == 6 && !m_fOrificeHit)
|
|
|
|
{
|
|
|
|
pev->health -= flDamage;
|
|
|
|
|
|
|
|
if(pev->health <= 0)
|
|
|
|
{
|
|
|
|
if(m_iHitTimes < m_iMaxHitTimes)
|
|
|
|
{
|
|
|
|
UTIL_BloodDecalTrace(ptr, m_bloodColor);
|
|
|
|
pev->health = gSkillData.gwormHealth;
|
|
|
|
m_iHitTimes++;
|
|
|
|
m_fOrificeHit = TRUE;
|
|
|
|
m_flOrificeOpenTime = gpGlobals->time;
|
|
|
|
m_iWasHit = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_iWasHit = 2;
|
|
|
|
SetThink(&CGeneWorm::DyingThink);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGeneWorm::HuntThink(void)
|
|
|
|
{
|
|
|
|
pev->nextthink = gpGlobals->time + 0.1;
|
|
|
|
GlowShellUpdate();
|
|
|
|
|
|
|
|
if(!m_fActivated)
|
|
|
|
return;
|
|
|
|
|
|
|
|
DispatchAnimEvents();
|
|
|
|
StudioFrameAdvance();
|
|
|
|
|
|
|
|
if (m_iWasHit > 1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(pev->rendermode == kRenderTransTexture)
|
|
|
|
{
|
|
|
|
if(pev->renderamt < 248)
|
|
|
|
pev->renderamt += 3;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pev->renderamt = 255;
|
|
|
|
pev->renderfx = 0;
|
|
|
|
pev->rendermode = kRenderNormal;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_iWasHit)
|
|
|
|
{
|
|
|
|
if(m_fSequenceFinished)
|
|
|
|
{
|
|
|
|
m_fHasEntered = TRUE;
|
|
|
|
int oldSeq = pev->sequence;
|
|
|
|
NextActivity();
|
|
|
|
if (pev->sequence != oldSeq || !m_fSequenceLoops)
|
|
|
|
{
|
|
|
|
pev->frame = 0;
|
|
|
|
ResetSequenceInfo();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (m_iWasHit == 1)
|
|
|
|
{
|
|
|
|
UTIL_Remove(m_pCloud);
|
|
|
|
m_pCloud = NULL;
|
|
|
|
m_fSpiting = FALSE;
|
|
|
|
|
|
|
|
int iDir = 1;
|
|
|
|
const char* painAnimation = 0;
|
|
|
|
const char* painSound = "geneworm/geneworm_shot_in_eye.wav";
|
|
|
|
if (m_fLeftEyeHit && m_fRightEyeHit)
|
|
|
|
{
|
|
|
|
if (!m_fOrificeHit)
|
|
|
|
{
|
|
|
|
painAnimation = "bigpain1";
|
|
|
|
painSound = "geneworm/geneworm_final_pain1.wav";
|
|
|
|
|
|
|
|
if(!m_pBall)
|
|
|
|
{
|
|
|
|
Vector pos, angle;
|
|
|
|
GetAttachment(GENEWORM_ATTACHMENT_SPAWN, pos, angle);
|
|
|
|
m_pBall = CSprite::SpriteCreate( "sprites/boss_glow.spr", pos, TRUE );
|
|
|
|
if( m_pBall )
|
|
|
|
{
|
|
|
|
m_pBall->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxNoDissipation );
|
|
|
|
m_pBall->SetAttachment( edict(), 2 );
|
|
|
|
m_pBall->SetScale( 1.5 );
|
|
|
|
m_pBall->pev->framerate = 10.0;
|
|
|
|
m_pBall->TurnOn();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
painAnimation = "bigpain3";
|
|
|
|
painSound = "geneworm/geneworm_final_pain3.wav";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (m_fLeftEyeHit)
|
|
|
|
{
|
|
|
|
painAnimation = "eyepain1";
|
|
|
|
}
|
|
|
|
else if (m_fRightEyeHit)
|
|
|
|
{
|
|
|
|
painAnimation = "eyepain2";
|
|
|
|
}
|
|
|
|
|
|
|
|
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, painSound, VOL_NORM, 0.1, 0, 100);
|
|
|
|
|
|
|
|
if (painAnimation)
|
|
|
|
{
|
|
|
|
pev->sequence = FindTransition(pev->sequence, LookupSequence(painAnimation), &iDir);
|
|
|
|
if (iDir > 0)
|
|
|
|
{
|
|
|
|
pev->frame = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pev->frame = 255;
|
|
|
|
}
|
|
|
|
ResetSequenceInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
m_iWasHit = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_fRightEyeHit)
|
|
|
|
{
|
|
|
|
Vector vecOrigin, vecAngles;
|
|
|
|
GetAttachment(GENEWORM_ATTACHMENT_RIGHTEYE, vecOrigin, vecAngles);
|
|
|
|
|
|
|
|
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
|
|
|
|
WRITE_BYTE( TE_ELIGHT );
|
|
|
|
WRITE_SHORT( entindex() ); // entity, attachment
|
|
|
|
WRITE_COORD( vecOrigin.x ); // origin
|
|
|
|
WRITE_COORD( vecOrigin.y );
|
|
|
|
WRITE_COORD( vecOrigin.z );
|
|
|
|
WRITE_COORD( 48 ); // radius
|
|
|
|
WRITE_BYTE( 128 ); // R
|
|
|
|
WRITE_BYTE( 255 ); // G
|
|
|
|
WRITE_BYTE( 128 ); // B
|
|
|
|
WRITE_BYTE( 1 ); // life * 10
|
|
|
|
WRITE_COORD( 2 ); // decay
|
|
|
|
MESSAGE_END();
|
|
|
|
}
|
|
|
|
if (!m_fLeftEyeHit)
|
|
|
|
{
|
|
|
|
Vector vecOrigin, vecAngles;
|
|
|
|
GetAttachment(GENEWORM_ATTACHMENT_LEFTEYE, vecOrigin, vecAngles);
|
|
|
|
|
|
|
|
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
|
|
|
|
WRITE_BYTE( TE_ELIGHT );
|
|
|
|
WRITE_SHORT( entindex() ); // entity, attachment
|
|
|
|
WRITE_COORD( vecOrigin.x ); // origin
|
|
|
|
WRITE_COORD( vecOrigin.y );
|
|
|
|
WRITE_COORD( vecOrigin.z );
|
|
|
|
WRITE_COORD( 48 ); // radius
|
|
|
|
WRITE_BYTE( 128 ); // R
|
|
|
|
WRITE_BYTE( 255 ); // G
|
|
|
|
WRITE_BYTE( 128 ); // B
|
|
|
|
WRITE_BYTE( 1 ); // life * 10
|
|
|
|
WRITE_COORD( 1 ); // decay
|
|
|
|
MESSAGE_END();
|
|
|
|
}
|
|
|
|
if (m_pBall)
|
|
|
|
{
|
|
|
|
Vector pos, angle;
|
|
|
|
GetAttachment(GENEWORM_ATTACHMENT_SPAWN, pos, angle);
|
|
|
|
UTIL_SetOrigin(m_pBall->pev, pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_hEnemy)
|
|
|
|
{
|
|
|
|
m_posTarget = m_hEnemy->pev->origin;
|
|
|
|
m_posTarget.z += 24;
|
|
|
|
TrackHead();
|
|
|
|
|
|
|
|
if(m_fSpiting && gpGlobals->time - m_flSpitStartTime <= 2)
|
|
|
|
{
|
|
|
|
Vector pos, angle;
|
|
|
|
|
|
|
|
GetAttachment(0, pos, angle);
|
|
|
|
|
|
|
|
angle = (m_hEnemy->pev->origin - pos).Normalize();
|
|
|
|
|
|
|
|
m_pCloud = CGeneWormCloud::LaunchCloud(pos, angle, 700, ENT(pev), 0.15);
|
|
|
|
m_pCloud->pev->rendermode = 3;
|
|
|
|
m_pCloud->pev->rendercolor.x = 0;
|
|
|
|
m_pCloud->pev->rendercolor.y = 255;
|
|
|
|
m_pCloud->pev->rendercolor.z = 0;
|
|
|
|
m_pCloud->pev->renderfx = 14;
|
|
|
|
m_pCloud = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_fSpiting = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetBoneController(0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//=========================================================
|
|
|
|
//=========================================================
|
|
|
|
|
|
|
|
void CGeneWorm::HandleAnimEvent(MonsterEvent_t *pEvent)
|
|
|
|
{
|
|
|
|
switch (pEvent->event)
|
|
|
|
{
|
|
|
|
case GENEWORM_AE_BEAM:
|
|
|
|
m_fSpiting = TRUE;
|
|
|
|
m_flSpitStartTime = gpGlobals->time;
|
|
|
|
break;
|
|
|
|
case GENEWORM_AE_PORTAL:
|
|
|
|
{
|
|
|
|
Vector vecPos, vecAng;
|
|
|
|
|
|
|
|
if(m_pBall)
|
|
|
|
{
|
|
|
|
UTIL_Remove(m_pBall);
|
|
|
|
m_pBall = NULL;
|
|
|
|
|
|
|
|
GetAttachment(GENEWORM_ATTACHMENT_SPAWN, vecPos, vecAng);
|
|
|
|
vecAng = pev->angles;
|
|
|
|
|
|
|
|
m_orificeGlow = CGeneWormSpawn::LaunchSpawn(vecPos, -vecAng, 1.25, ENT(pev));
|
|
|
|
pev->health = gSkillData.gwormHealth;
|
|
|
|
|
|
|
|
m_orificeGlow = NULL;
|
|
|
|
|
|
|
|
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "debris/beamstart7.wav", 1, 0.1, 0, RANDOM_LONG(-5, 5)+100);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case GENEWORM_AE_MELEE_LEFT1:
|
|
|
|
FireHurtTargets("GeneWormLeftSlash", this, this, USE_TOGGLE, 1);
|
|
|
|
break;
|
|
|
|
case GENEWORM_AE_MELEE_LEFT2:
|
|
|
|
FireHurtTargets("GeneWormLeftSlash", this, this, USE_TOGGLE, 0);
|
|
|
|
break;
|
|
|
|
case GENEWORM_AE_MELEE_RIGHT1:
|
|
|
|
FireHurtTargets("GeneWormRightSlash", this, this, USE_TOGGLE, 1);
|
|
|
|
break;
|
|
|
|
case GENEWORM_AE_MELEE_RIGHT2:
|
|
|
|
FireHurtTargets("GeneWormRightSlash", this, this, USE_TOGGLE, 0);
|
|
|
|
break;
|
|
|
|
case GENEWORM_AE_MELEE_FORWARD1:
|
|
|
|
FireHurtTargets("GeneWormCenterSlash", this, this, USE_TOGGLE, 1);
|
|
|
|
break;
|
|
|
|
case GENEWORM_AE_MELEE_FORWARD2:
|
|
|
|
FireHurtTargets("GeneWormCenterSlash", this, this, USE_TOGGLE, 0);
|
|
|
|
break;
|
|
|
|
case GENEWORM_AE_MAD:
|
|
|
|
FireHurtTargets("GeneWormWallHit", this, this, USE_TOGGLE, 0);
|
|
|
|
UTIL_ScreenShake(pev->origin, 24, 3, 5, 2048);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGeneWorm::CommandUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
|
|
|
|
{
|
|
|
|
if(useType == USE_TOGGLE && !m_fActivated)
|
|
|
|
{
|
|
|
|
pev->sequence = LookupSequence("entry");
|
|
|
|
pev->frame = 0;
|
|
|
|
ResetSequenceInfo();
|
|
|
|
pev->rendermode = kRenderTransTexture;
|
|
|
|
pev->renderfx = 0;
|
|
|
|
pev->renderamt = 0;
|
|
|
|
|
|
|
|
m_fActivated = TRUE;
|
|
|
|
|
|
|
|
pev->solid = SOLID_BBOX;
|
|
|
|
|
|
|
|
UTIL_SetOrigin(pev, pev->origin);
|
|
|
|
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, pEntrySounds[0], 1, 0.1, 0, 100);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int CGeneWorm::TakeDamage(entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGeneWorm::PainSound(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGeneWorm::DeathSound(void)
|
|
|
|
{
|
|
|
|
EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pDeathSounds), 2, ATTN_NORM);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGeneWorm::IdleSound(void)
|
|
|
|
{
|
|
|
|
EMIT_SOUND(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pIdleSounds), VOL_NORM, ATTN_NORM);
|
|
|
|
}
|