From b5f145197da40c8fb198fccf40b48c47a2d0fa44 Mon Sep 17 00:00:00 2001 From: Roman Chistokhodov Date: Fri, 1 Sep 2017 01:36:07 +0300 Subject: [PATCH] Shock trooper, shock effect and spore grenade fixes (#8) --- dlls/basemonster.h | 2 +- dlls/combat.cpp | 9 +--- dlls/gearbox/shock.cpp | 87 +++++++++++++++++++++++------------ dlls/gearbox/shockrifle.cpp | 2 +- dlls/gearbox/sporegrenade.cpp | 30 ++++++++---- dlls/gearbox/sporegrenade.h | 2 +- dlls/gearbox/strooper.cpp | 57 ++++++++++++++++++++--- dlls/hgrunt.h | 4 +- dlls/monsters.cpp | 48 ++++++++++--------- dlls/monsterstate.cpp | 3 +- 10 files changed, 163 insertions(+), 81 deletions(-) diff --git a/dlls/basemonster.h b/dlls/basemonster.h index 340c7c30..21d543fe 100644 --- a/dlls/basemonster.h +++ b/dlls/basemonster.h @@ -337,7 +337,7 @@ public: void GlowShellOff( void ); void GlowShellUpdate( void ); - float m_glowShellStartTime; + float m_glowShellTime; float m_glowShellDuration; Vector m_glowShellColor; BOOL m_glowShellUpdate; diff --git a/dlls/combat.cpp b/dlls/combat.cpp index 9cb56cf9..d5eb9c7a 100644 --- a/dlls/combat.cpp +++ b/dlls/combat.cpp @@ -912,7 +912,7 @@ int CBaseMonster::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, f if( ( bitsDamageType & DMG_ENERGYBEAM ) && FClassnameIs( pevAttacker, "shock" ) ) { - GlowShellOn( Vector( 0, 255, 255 ), .5f ); + GlowShellOn( Vector( 0, 220, 255 ), .5f ); } // react to the damage (get mad) @@ -986,7 +986,7 @@ int CBaseMonster::DeadTakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacke } #endif // kill the corpse if enough damage was done to destroy the corpse and the damage is of a type that is allowed to destroy the corpse. - if( bitsDamageType & DMG_GIB_CORPSE ) + if( (bitsDamageType & DMG_GIB_CORPSE) || (( bitsDamageType & DMG_ENERGYBEAM ) && FClassnameIs( pevAttacker, "shock" )) ) { if( pev->health <= flDamage ) { @@ -998,11 +998,6 @@ int CBaseMonster::DeadTakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacke pev->health -= flDamage * 0.1; } - if( ( bitsDamageType & DMG_ENERGYBEAM ) && FClassnameIs( pevAttacker, "shock" ) ) - { - GlowShellOn( Vector( 0, 255, 255 ), .5f ); - } - return 1; } diff --git a/dlls/gearbox/shock.cpp b/dlls/gearbox/shock.cpp index 922cf76b..e596436d 100644 --- a/dlls/gearbox/shock.cpp +++ b/dlls/gearbox/shock.cpp @@ -29,7 +29,7 @@ #include "game.h" #include "weapons.h" -#define SHOCK_BEAM_LENGTH 48 +#define SHOCK_BEAM_LENGTH 64 #define SHOCK_BEAM_LENGTH_HALF SHOCK_BEAM_LENGTH * 0.5f #define SHOCK_BEAM_WIDTH 50 @@ -53,7 +53,7 @@ public: void CreateBeam(const Vector& start, const Vector& end, int width); void ClearBeam(); void UpdateBeam(const Vector& start, const Vector& end); - void ComputeBeamPositions(const Vector& vel, Vector* pos1, Vector* pos2); + void ComputeBeamPositions(Vector* pos1, Vector* pos2); CBeam *m_pBeam; Vector m_vecBeamStart, m_vecBeamEnd; @@ -76,20 +76,20 @@ void CShock::Spawn(void) pev->classname = MAKE_STRING("shock"); pev->solid = SOLID_BBOX; - pev->rendermode = kRenderTransAlpha; - pev->renderamt = 0; + pev->rendermode = kRenderTransAdd; + pev->renderamt = 170; + pev->renderfx = kRenderFxNoDissipation; - SET_MODEL(ENT(pev), "sprites/bigspit.spr"); + SET_MODEL(ENT(pev), "sprites/flare3.spr"); pev->frame = 0; - pev->scale = 0.5; + pev->scale = 0.4; - UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0)); + UTIL_SetSize(pev, Vector(-4, -4, -4), Vector(4, 4, 4)); // Make beam NULL to avoid assertions. m_pBeam = 0; - Vector vDir = pev->velocity.Normalize(); - ComputeBeamPositions(vDir, &m_vecBeamStart, &m_vecBeamEnd); + ComputeBeamPositions(&m_vecBeamStart, &m_vecBeamEnd); // Create the beam. //CreateBeam(m_vecBeamStart, m_vecBeamEnd, SHOCK_BEAM_WIDTH); @@ -102,8 +102,7 @@ void CShock::ShockThink(void) { pev->nextthink = gpGlobals->time + 0.01f; - Vector vDir = pev->velocity.Normalize(); - ComputeBeamPositions(vDir, &m_vecBeamStart, &m_vecBeamEnd); + ComputeBeamPositions(&m_vecBeamStart, &m_vecBeamEnd); // Update the beam. UpdateBeam(m_vecBeamStart, m_vecBeamEnd); @@ -128,7 +127,7 @@ void CShock::Touch(CBaseEntity *pOther) if (ENT(pOther->pev) == pev->owner) return; - TraceResult tr; + TraceResult tr = UTIL_GetGlobalTrace( ); int iPitch, iVolume; // Lower the volume if touched entity is not a player. @@ -140,13 +139,24 @@ void CShock::Touch(CBaseEntity *pOther) // splat sound EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "weapons/shock_impact.wav", iVolume, ATTN_NORM, 0, iPitch); + MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin ); + WRITE_BYTE(TE_DLIGHT); + WRITE_COORD(pev->origin.x); // X + WRITE_COORD(pev->origin.y); // Y + WRITE_COORD(pev->origin.z); // Z + WRITE_BYTE( 8 ); // radius * 0.1 + WRITE_BYTE( 0 ); // r + WRITE_BYTE( 255 ); // g + WRITE_BYTE( 255 ); // b + WRITE_BYTE( 10 ); // time * 10 + WRITE_BYTE( 10 ); // decay * 0.1 + MESSAGE_END( ); + ClearBeam(); if (!pOther->pev->takedamage) { - // make a splat on the wall - UTIL_TraceLine(pev->origin, pev->origin + pev->velocity * 10, dont_ignore_monsters, ENT(pev), &tr); - UTIL_DecalTrace(&tr, DECAL_BIGSHOT1 + RANDOM_LONG(0, 2)); + UTIL_DecalTrace(&tr, DECAL_SMALLSCORCH1 + RANDOM_LONG(0, 2)); int iContents = UTIL_PointContents(pev->origin); @@ -155,18 +165,29 @@ void CShock::Touch(CBaseEntity *pOther) { UTIL_Sparks(tr.vecEndPos); } + UTIL_Remove(this); } else { - pOther->TakeDamage(pev, pev, gSkillData.monDmgShockroach, DMG_ENERGYBEAM | DMG_ALWAYSGIB); + ClearMultiDamage(); + entvars_t *pevOwner = VARS(pev->owner); + float damage = gSkillData.monDmgShockroach; + if (pevOwner && (pevOwner->flags | FL_CLIENT)) + damage = gSkillData.plrDmgShockroach; + pOther->TraceAttack(pev, damage, pev->velocity.Normalize(), &tr, DMG_ENERGYBEAM ); + ApplyMultiDamage(pev, pev); + if (pOther->IsPlayer() && (UTIL_PointContents(pev->origin) != CONTENTS_WATER)) + { + const Vector position = tr.vecEndPos; + MESSAGE_BEGIN( MSG_ONE, SVC_TEMPENTITY, NULL, pOther->pev ); + WRITE_BYTE( TE_SPARKS ); + WRITE_COORD( position.x ); + WRITE_COORD( position.y ); + WRITE_COORD( position.z ); + MESSAGE_END(); + } } - - - // Clear the beam. - ClearBeam(); - - SetThink(&CShock::SUB_Remove); - pev->nextthink = gpGlobals->time; + UTIL_Remove(this); } //========================================================= @@ -184,11 +205,11 @@ void CShock::CreateBeam(const Vector& start, const Vector& end, int width) return; m_pBeam->PointsInit(start, end); - m_pBeam->SetColor(180, 255, 250); + m_pBeam->SetColor(140, 255, 220); m_pBeam->SetBrightness(RANDOM_LONG(24, 25) * 10); m_pBeam->SetFrame(0); m_pBeam->SetScrollRate(10); - m_pBeam->SetNoise(20); + m_pBeam->SetNoise(40); m_pBeam->SetFlags(SF_BEAM_SHADEIN | SF_BEAM_SHADEOUT); } @@ -220,9 +241,15 @@ void CShock::UpdateBeam(const Vector& start, const Vector& end) } } -void CShock::ComputeBeamPositions(const Vector& vel, Vector* pos1, Vector* pos2) +void CShock::ComputeBeamPositions(Vector* pos1, Vector* pos2) { - Vector vNormVelocity = pev->velocity.Normalize(); - *pos1 = pev->origin + (vNormVelocity * SHOCK_BEAM_LENGTH_HALF); - *pos2 = pev->origin + (vNormVelocity * -SHOCK_BEAM_LENGTH_HALF); -} \ No newline at end of file + const Vector vel = pev->velocity.Normalize(); + UTIL_MakeVectors( pev->angles ); + + /* Little aside so beam and sprite won't blend into white ball when looking right into shock beam direction. + * This should replicate the Opposing Force behavior + */ + const Vector origin = pev->origin - gpGlobals->v_right * 6; + *pos1 = origin + (vel * SHOCK_BEAM_LENGTH_HALF); + *pos2 = origin + (vel * -SHOCK_BEAM_LENGTH_HALF/2); +} diff --git a/dlls/gearbox/shockrifle.cpp b/dlls/gearbox/shockrifle.cpp index 2293703a..01f0abc6 100644 --- a/dlls/gearbox/shockrifle.cpp +++ b/dlls/gearbox/shockrifle.cpp @@ -63,7 +63,7 @@ void CShockrifle::Precache(void) PRECACHE_SOUND("weapons/shock_recharge.wav"); PRECACHE_MODEL("sprites/lgtning.spr"); - PRECACHE_MODEL("sprites/bigspit.spr");// spit projectile. + PRECACHE_MODEL("sprites/flare3.spr"); m_usShockFire = PRECACHE_EVENT(1, "events/shock.sc"); diff --git a/dlls/gearbox/sporegrenade.cpp b/dlls/gearbox/sporegrenade.cpp index b5c0ef1a..faf2ddc6 100644 --- a/dlls/gearbox/sporegrenade.cpp +++ b/dlls/gearbox/sporegrenade.cpp @@ -37,9 +37,13 @@ TYPEDESCRIPTION CSporeGrenade::m_SaveData[] = IMPLEMENT_SAVERESTORE(CSporeGrenade, CGrenade); +int gSporeExplode, gSporeExplodeC; + void CSporeGrenade::Precache(void) { - PRECACHE_MODEL("sprites/glow01.spr"); + PRECACHE_MODEL("sprites/glow02.spr"); + gSporeExplode = PRECACHE_MODEL ("sprites/spore_exp_01.spr"); + gSporeExplodeC = PRECACHE_MODEL ("sprites/spore_exp_c_01.spr"); } // UNDONE: temporary scorching for PreAlpha - find a less sleazy permenant solution. @@ -75,9 +79,19 @@ void CSporeGrenade::Explode(TraceResult *pTrace, int bitsDamageType) vecSpraySpot, // position pTrace->vecPlaneNormal, // direction g_sModelIndexTinySpit, // modelindex - RANDOM_LONG(8, 10), // count + RANDOM_LONG(40, 50), // count flSpraySpeed, // speed - RANDOM_FLOAT(10, 20) * 10); // noise + RANDOM_FLOAT(600, 640)); // noise + + MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin ); + WRITE_BYTE( TE_SPRITE ); + WRITE_COORD( pev->origin.x ); + WRITE_COORD( pev->origin.y ); + WRITE_COORD( pev->origin.z ); + WRITE_SHORT( RANDOM_LONG( 0, 1 ) ? gSporeExplode : gSporeExplodeC ); + WRITE_BYTE( 25 ); // scale * 10 + WRITE_BYTE( 155 ); // framerate + MESSAGE_END(); // Play explode sound. EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/splauncher_impact.wav", 1, ATTN_NORM); @@ -343,13 +357,13 @@ void CSporeGrenade::Spawn(void) m_flNextSpriteTrailSpawn = gpGlobals->time; - m_pSporeGlow = CSprite::SpriteCreate("sprites/glow01.spr", pev->origin, FALSE); + m_pSporeGlow = CSprite::SpriteCreate("sprites/glow02.spr", pev->origin, FALSE); if (m_pSporeGlow) { - m_pSporeGlow->SetTransparency(kRenderGlow, 217, 241, 152, 200, kRenderFxNoDissipation); - m_pSporeGlow->SetAttachment(edict(), 1); - m_pSporeGlow->SetScale(.5f); + m_pSporeGlow->SetTransparency(kRenderGlow, 150, 158, 19, 155, kRenderFxNoDissipation); + m_pSporeGlow->SetAttachment(edict(), 0); + m_pSporeGlow->SetScale(.75f); } } @@ -449,4 +463,4 @@ void CSporeGrenade::SpawnExplosionParticles(const Vector& origin, const Vector& WRITE_BYTE(speed); // speed WRITE_BYTE(noise); // noise ( client will divide by 100 ) MESSAGE_END(); -} \ No newline at end of file +} diff --git a/dlls/gearbox/sporegrenade.h b/dlls/gearbox/sporegrenade.h index 1977f101..9d9515f8 100644 --- a/dlls/gearbox/sporegrenade.h +++ b/dlls/gearbox/sporegrenade.h @@ -55,4 +55,4 @@ public: float m_flNextSpriteTrailSpawn; }; -#endif // SPORE_GRENADE_H \ No newline at end of file +#endif // SPORE_GRENADE_H diff --git a/dlls/gearbox/strooper.cpp b/dlls/gearbox/strooper.cpp index 66937c8c..7ff68164 100644 --- a/dlls/gearbox/strooper.cpp +++ b/dlls/gearbox/strooper.cpp @@ -51,6 +51,7 @@ extern Schedule_t slGruntTossGrenadeCover[]; #define STROOPER_NUM_HEADS 2 // how many grunt heads are there? #define STROOPER_MINIMUM_HEADSHOT_DAMAGE 15 // must do at least this much damage in one shot to head to score a headshot kill #define STROOPER_SENTENCE_VOLUME (float)0.35 // volume of grunt sentences +#define STROOPER_MUZZLEFLASH "sprites/muzzle_shock.spr" #define STROOPER_SHOCKRIFLE (1 << 0) #define STROOPER_HANDGRENADE (1 << 1) @@ -102,6 +103,7 @@ enum TASK_STROOPER_CHECK_FIRE, }; +int iStrooperMuzzleFlash; //========================================================= // shocktrooper @@ -127,6 +129,8 @@ public: Schedule_t *GetSchedule(void); Schedule_t *GetScheduleOfType(int Type); + void SpeakSentence(); + static TYPEDESCRIPTION m_SaveData[]; BOOL m_fRightClaw; @@ -166,7 +170,22 @@ enum STROOPER_SENT_TAUNT, } STROOPER_SENTENCE_TYPES; +void CStrooper::SpeakSentence( void ) +{ + if( m_iSentence == STROOPER_SENT_NONE ) + { + // no sentence cued up. + return; + } + + if( FOkToSpeak() ) + { + SENTENCEG_PlayRndSz( ENT( pev ), pGruntSentences[m_iSentence], STROOPER_SENTENCE_VOLUME, STROOPER_ATTN, 0, m_voicePitch ); + JustSpoke(); + } +} +#define STROOPER_GIB_COUNT 8 //========================================================= // GibMonster - make gun fly through the air. //========================================================= @@ -193,7 +212,14 @@ void CStrooper::GibMonster(void) } } - CBaseMonster::GibMonster(); + EMIT_SOUND( ENT( pev ), CHAN_WEAPON, "common/bodysplat.wav", 1, ATTN_NORM ); + + if( CVAR_GET_FLOAT( "violence_agibs" ) != 0 ) // Should never get here, but someone might call it directly + { + CGib::SpawnRandomGibs( pev, 6, "models/strooper_gibs.mdl", STROOPER_GIB_COUNT ); // Throw alien gibs + } + SetThink( &CBaseEntity::SUB_Remove ); + pev->nextthink = gpGlobals->time; } void CStrooper::IdleSound(void) @@ -251,9 +277,6 @@ int CStrooper::Classify(void) //========================================================= void CStrooper::HandleAnimEvent(MonsterEvent_t *pEvent) { - Vector vecShootDir; - Vector vecShootOrigin; - switch (pEvent->event) { case STROOPER_AE_DROP_GUN: @@ -320,12 +343,27 @@ void CStrooper::HandleAnimEvent(MonsterEvent_t *pEvent) GetAttachment(0, vecGunPos, vecGunAngles); + MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecGunPos ); + WRITE_BYTE( TE_SPRITE ); + WRITE_COORD( vecGunPos.x ); // pos + WRITE_COORD( vecGunPos.y ); + WRITE_COORD( vecGunPos.z ); + WRITE_SHORT( iStrooperMuzzleFlash ); // model + WRITE_BYTE( 4 ); // size * 10 + WRITE_BYTE( 196 ); // brightness + MESSAGE_END(); + if (m_hEnemy) { - vecGunAngles = (m_hEnemy->EyePosition() - pev->origin).Normalize(); + vecGunAngles = (m_hEnemy->EyePosition() - vecGunPos).Normalize(); + } + else + { + vecGunAngles = (m_vecEnemyLKP - vecGunPos).Normalize(); } - CBaseEntity *pShock = CBaseEntity::Create("shock", vecGunPos, vecGunAngles, edict()); + CBaseEntity *pShock = CBaseEntity::Create("shock", vecGunPos, pev->angles, edict()); + vecGunAngles.z += RANDOM_FLOAT( -0.05, 0 ); pShock->pev->velocity = vecGunAngles * 900; // Play fire sound. @@ -337,6 +375,7 @@ void CStrooper::HandleAnimEvent(MonsterEvent_t *pEvent) case STROOPER_AE_KICK: { + EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, "zombie/claw_miss2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM + RANDOM_LONG( -5, 5 ) ); CBaseEntity *pHurt = Kick(); if (pHurt) @@ -383,7 +422,7 @@ void CStrooper::Spawn() pev->solid = SOLID_SLIDEBOX; pev->movetype = MOVETYPE_STEP; - m_bloodColor = BLOOD_COLOR_RED; + m_bloodColor = BLOOD_COLOR_GREEN; pev->effects = 0; pev->health = gSkillData.strooperHealth; m_flFieldOfView = 0.2;// indicates the width of this monster's forward view cone ( as a dotproduct result ) @@ -422,6 +461,9 @@ void CStrooper::Spawn() void CStrooper::Precache() { PRECACHE_MODEL("models/strooper.mdl"); + PRECACHE_MODEL("models/strooper_gibs.mdl"); + iStrooperMuzzleFlash = PRECACHE_MODEL(STROOPER_MUZZLEFLASH); + PRECACHE_SOUND("shocktrooper/shock_trooper_attack.wav"); PRECACHE_SOUND("shocktrooper/shock_trooper_die1.wav"); PRECACHE_SOUND("shocktrooper/shock_trooper_die2.wav"); @@ -435,6 +477,7 @@ void CStrooper::Precache() PRECACHE_SOUND("shocktrooper/shock_trooper_pain5.wav"); PRECACHE_SOUND("weapons/shock_fire.wav"); + PRECACHE_SOUND("weapons/shock_impact.wav"); PRECACHE_SOUND("zombie/claw_miss2.wav");// because we use the basemonster SWIPE animation event diff --git a/dlls/hgrunt.h b/dlls/hgrunt.h index 229ef317..4e33c36f 100644 --- a/dlls/hgrunt.h +++ b/dlls/hgrunt.h @@ -44,7 +44,7 @@ public: void Shotgun(void); void PrescheduleThink(void); virtual void GibMonster(void); - void SpeakSentence(void); + virtual void SpeakSentence(void); int Save(CSave &save); int Restore(CRestore &restore); @@ -101,4 +101,4 @@ public: int m_iSpriteTexture; // Don't save, precache }; -#endif // HGRUNT_H \ No newline at end of file +#endif // HGRUNT_H diff --git a/dlls/monsters.cpp b/dlls/monsters.cpp index df3ee9cb..3b122ce5 100644 --- a/dlls/monsters.cpp +++ b/dlls/monsters.cpp @@ -106,8 +106,7 @@ TYPEDESCRIPTION CBaseMonster::m_SaveData[] = DEFINE_FIELD( CBaseMonster, m_scriptState, FIELD_INTEGER ), DEFINE_FIELD( CBaseMonster, m_pCine, FIELD_CLASSPTR ), - DEFINE_FIELD( CBaseMonster, m_glowShellStartTime, FIELD_TIME ), - DEFINE_FIELD( CBaseMonster, m_glowShellDuration, FIELD_FLOAT ), + DEFINE_FIELD( CBaseMonster, m_glowShellTime, FIELD_TIME ), DEFINE_FIELD( CBaseMonster, m_glowShellColor, FIELD_VECTOR ), DEFINE_FIELD( CBaseMonster, m_glowShellUpdate, FIELD_BOOLEAN ), @@ -3393,41 +3392,44 @@ BOOL CBaseMonster::ShouldFadeOnDeath( void ) void CBaseMonster::GlowShellOn( Vector color, float flDuration ) { - m_prevRenderMode = pev->rendermode; - m_prevRenderColor = pev->rendercolor; - m_prevRenderAmt = pev->renderamt; - m_prevRenderFx = pev->renderfx; - - pev->renderamt = 5; - pev->rendercolor = color; - pev->renderfx = kRenderFxGlowShell; - //pev->rendermode = kRenderGlow; + if (!m_glowShellUpdate) + { + m_prevRenderMode = pev->rendermode; + m_prevRenderColor = pev->rendercolor; + m_prevRenderAmt = pev->renderamt; + m_prevRenderFx = pev->renderfx; - m_glowShellColor = color; + pev->renderamt = 5; + pev->rendercolor = color; + pev->renderfx = kRenderFxGlowShell; + //pev->rendermode = kRenderGlow; - m_glowShellDuration = flDuration; - m_glowShellStartTime = gpGlobals->time; + m_glowShellColor = color; - m_glowShellUpdate = TRUE; + m_glowShellUpdate = TRUE; + } + m_glowShellTime = gpGlobals->time + flDuration; } void CBaseMonster::GlowShellOff( void ) { - pev->renderamt = m_prevRenderAmt; - pev->rendercolor = m_prevRenderColor; - pev->renderfx = m_prevRenderFx; - pev->rendermode = m_prevRenderMode; + if (m_glowShellUpdate) + { + pev->renderamt = m_prevRenderAmt; + pev->rendercolor = m_prevRenderColor; + pev->renderfx = m_prevRenderFx; + pev->rendermode = m_prevRenderMode; - m_glowShellDuration = 0.0f; - m_glowShellStartTime = 0.0f; + m_glowShellTime = 0.0f; - m_glowShellUpdate = FALSE; + m_glowShellUpdate = FALSE; + } } void CBaseMonster::GlowShellUpdate( void ) { if( m_glowShellUpdate ) { - if( ( gpGlobals->time - m_glowShellStartTime ) > m_glowShellDuration ) + if( gpGlobals->time > m_glowShellTime ) GlowShellOff(); } } diff --git a/dlls/monsterstate.cpp b/dlls/monsterstate.cpp index f29664dc..b830ee4f 100644 --- a/dlls/monsterstate.cpp +++ b/dlls/monsterstate.cpp @@ -99,7 +99,8 @@ void CBaseMonster::RunAI( void ) CheckAmmo(); } - + if (m_glowShellUpdate && pev->deadflag == DEAD_DEAD) + GlowShellOff(); FCheckAITrigger(); PrescheduleThink();