Shock trooper, shock effect and spore grenade fixes (#8)

This commit is contained in:
Roman Chistokhodov 2017-09-01 01:36:07 +03:00 committed by Andrey Akhmichin
parent d0f80fe930
commit b5f145197d
10 changed files with 163 additions and 81 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}
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);
}

View File

@ -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");

View File

@ -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();
}
}

View File

@ -55,4 +55,4 @@ public:
float m_flNextSpriteTrailSpawn;
};
#endif // SPORE_GRENADE_H
#endif // SPORE_GRENADE_H

View File

@ -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

View File

@ -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
#endif // HGRUNT_H

View File

@ -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;
if (!m_glowShellUpdate)
{
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;
pev->renderamt = 5;
pev->rendercolor = color;
pev->renderfx = kRenderFxGlowShell;
//pev->rendermode = kRenderGlow;
m_glowShellColor = color;
m_glowShellColor = color;
m_glowShellDuration = flDuration;
m_glowShellStartTime = gpGlobals->time;
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();
}
}

View File

@ -99,7 +99,8 @@ void CBaseMonster::RunAI( void )
CheckAmmo();
}
if (m_glowShellUpdate && pev->deadflag == DEAD_DEAD)
GlowShellOff();
FCheckAITrigger();
PrescheduleThink();