diff --git a/dlls/combat.cpp b/dlls/combat.cpp index d5eb9c7a..1b573243 100644 --- a/dlls/combat.cpp +++ b/dlls/combat.cpp @@ -910,7 +910,7 @@ int CBaseMonster::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, f return 0; } - if( ( bitsDamageType & DMG_ENERGYBEAM ) && FClassnameIs( pevAttacker, "shock" ) ) + if( ( bitsDamageType & DMG_ENERGYBEAM ) && FClassnameIs( pevAttacker, "shock_beam" ) ) { GlowShellOn( Vector( 0, 220, 255 ), .5f ); } @@ -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) || (( bitsDamageType & DMG_ENERGYBEAM ) && FClassnameIs( pevAttacker, "shock" )) ) + if( (bitsDamageType & DMG_GIB_CORPSE) || (( bitsDamageType & DMG_ENERGYBEAM ) && FClassnameIs( pevInflictor, "shock_beam" )) ) { if( pev->health <= flDamage ) { diff --git a/dlls/gamerules.cpp b/dlls/gamerules.cpp index 725a93ba..909244e8 100644 --- a/dlls/gamerules.cpp +++ b/dlls/gamerules.cpp @@ -376,7 +376,7 @@ void CGameRules::RefreshSkillData ( void ) gSkillData.plrDmgGrapple = GetSkillCvar( "sk_plr_grapple" ); gSkillData.plrDmgEagle = GetSkillCvar( "sk_plr_eagle" ); gSkillData.plrDmgDisplacer = GetSkillCvar( "sk_plr_displacer_self" ); - gSkillData.plrDmgShockroach = GetSkillCvar( "sk_plr_shockroachs" ); + gSkillData.plrDmgShockroachSingleplayer = GetSkillCvar( "sk_plr_shockroachs" ); gSkillData.plrDmgSpore = GetSkillCvar( "sk_plr_spore" ); gSkillData.plrDmg762 = GetSkillCvar( "sk_plr_762_bullet" ); gSkillData.plrDmg556 = GetSkillCvar( "sk_plr_556_bullet" ); @@ -384,7 +384,7 @@ void CGameRules::RefreshSkillData ( void ) gSkillData.monDmg762 = GetSkillCvar( "sk_plr_762_bullet" ); gSkillData.monDmg556 = GetSkillCvar( "sk_plr_556_bullet" ); gSkillData.monDmgDisplacer = GetSkillCvar( "sk_plr_displacer_other" ); - gSkillData.monDmgShockroach = GetSkillCvar( "sk_plr_shockroachm" ); + gSkillData.plrDmgShockroachMultiplayer = GetSkillCvar( "sk_plr_shockroachm" ); // HEALTH/CHARGE gSkillData.suitchargerCapacity = GetSkillCvar( "sk_suitcharger" ); diff --git a/dlls/gearbox/shock.cpp b/dlls/gearbox/shock.cpp index e596436d..40c34f20 100644 --- a/dlls/gearbox/shock.cpp +++ b/dlls/gearbox/shock.cpp @@ -28,87 +28,93 @@ #include "soundent.h" #include "game.h" #include "weapons.h" - -#define SHOCK_BEAM_LENGTH 64 -#define SHOCK_BEAM_LENGTH_HALF SHOCK_BEAM_LENGTH * 0.5f - -#define SHOCK_BEAM_WIDTH 50 +#include "gamerules.h" +#include "customentity.h" //========================================================= // Shockrifle projectile //========================================================= -class CShock : public CBaseEntity +class CShock : public CBaseAnimating { public: void Spawn(void); + void Precache(); - static void Shoot(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity); + static void Shoot(entvars_t *pevOwner, const Vector angles, const Vector vecStart, const Vector vecVelocity); void Touch(CBaseEntity *pOther); - void EXPORT ShockThink(void); + void EXPORT FlyThink(); virtual int Save(CSave &save); virtual int Restore(CRestore &restore); static TYPEDESCRIPTION m_SaveData[]; - void CreateBeam(const Vector& start, const Vector& end, int width); - void ClearBeam(); - void UpdateBeam(const Vector& start, const Vector& end); - void ComputeBeamPositions(Vector* pos1, Vector* pos2); + void CreateEffects(); + void ClearEffects(); CBeam *m_pBeam; - Vector m_vecBeamStart, m_vecBeamEnd; + CBeam *m_pNoise; + CSprite *m_pSprite; }; -LINK_ENTITY_TO_CLASS(shock, CShock); +LINK_ENTITY_TO_CLASS(shock_beam, CShock) TYPEDESCRIPTION CShock::m_SaveData[] = { - DEFINE_ARRAY(CShock, m_pBeam, FIELD_CLASSPTR, 1), - DEFINE_FIELD(CShock, m_vecBeamStart, FIELD_POSITION_VECTOR), - DEFINE_FIELD(CShock, m_vecBeamEnd, FIELD_POSITION_VECTOR), + DEFINE_FIELD(CShock, m_pBeam, FIELD_CLASSPTR), + DEFINE_FIELD(CShock, m_pNoise, FIELD_CLASSPTR), + DEFINE_FIELD(CShock, m_pSprite, FIELD_CLASSPTR), }; -IMPLEMENT_SAVERESTORE(CShock, CBaseEntity); +IMPLEMENT_SAVERESTORE(CShock, CBaseAnimating) void CShock::Spawn(void) { + Precache(); pev->movetype = MOVETYPE_FLY; - pev->classname = MAKE_STRING("shock"); - pev->solid = SOLID_BBOX; - pev->rendermode = kRenderTransAdd; - pev->renderamt = 170; - pev->renderfx = kRenderFxNoDissipation; - - SET_MODEL(ENT(pev), "sprites/flare3.spr"); - pev->frame = 0; - pev->scale = 0.4; + pev->classname = MAKE_STRING("shock_beam"); + SET_MODEL(ENT(pev), "models/shock_effect.mdl"); + UTIL_SetOrigin(pev, pev->origin); + if ( g_pGameRules->IsMultiplayer() ) + pev->dmg = gSkillData.plrDmgShockroachMultiplayer; + else + pev->dmg = gSkillData.plrDmgShockroachSingleplayer; UTIL_SetSize(pev, Vector(-4, -4, -4), Vector(4, 4, 4)); - // Make beam NULL to avoid assertions. - m_pBeam = 0; - - ComputeBeamPositions(&m_vecBeamStart, &m_vecBeamEnd); - - // Create the beam. - //CreateBeam(m_vecBeamStart, m_vecBeamEnd, SHOCK_BEAM_WIDTH); - - SetThink(&CShock::ShockThink); - pev->nextthink = gpGlobals->time + 0.1f; + CreateEffects(); + SetThink( &CShock::FlyThink ); + pev->nextthink = gpGlobals->time; } -void CShock::ShockThink(void) +void CShock::Precache() { - pev->nextthink = gpGlobals->time + 0.01f; - - ComputeBeamPositions(&m_vecBeamStart, &m_vecBeamEnd); - - // Update the beam. - UpdateBeam(m_vecBeamStart, m_vecBeamEnd); + PRECACHE_MODEL("sprites/flare3.spr"); + PRECACHE_MODEL("sprites/lgtning.spr"); + PRECACHE_MODEL("models/shock_effect.mdl"); + PRECACHE_SOUND("weapons/shock_impact.wav"); } -void CShock::Shoot(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity) +void CShock::FlyThink() +{ + if (pev->waterlevel == 3) + { + entvars_t *pevOwner = VARS(pev->owner); + const int iVolume = RANDOM_FLOAT(0.8f, 1); + const int iPitch = RANDOM_FLOAT(80, 110); + EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "weapons/shock_impact.wav", iVolume, ATTN_NORM, 0, iPitch); + RadiusDamage(pev->origin, pev, pevOwner ? pevOwner : pev, pev->dmg * 3, 144, CLASS_NONE, DMG_SHOCK | DMG_ALWAYSGIB ); + ClearEffects(); + SetThink( &CBaseEntity::SUB_Remove ); + pev->nextthink = gpGlobals->time; + } + else + { + pev->nextthink = gpGlobals->time + 0.05; + } +} + +void CShock::Shoot(entvars_t *pevOwner, const Vector angles, const Vector vecStart, const Vector vecVelocity) { CShock *pShock = GetClassPtr((CShock *)NULL); pShock->Spawn(); @@ -116,8 +122,8 @@ void CShock::Shoot(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity) UTIL_SetOrigin(pShock->pev, vecStart); pShock->pev->velocity = vecVelocity; pShock->pev->owner = ENT(pevOwner); + pShock->pev->angles = angles; - pShock->SetThink(&CShock::ShockThink); pShock->pev->nextthink = gpGlobals->time; } @@ -152,7 +158,7 @@ void CShock::Touch(CBaseEntity *pOther) WRITE_BYTE( 10 ); // decay * 0.1 MESSAGE_END( ); - ClearBeam(); + ClearEffects(); if (!pOther->pev->takedamage) { // make a splat on the wall @@ -160,22 +166,29 @@ void CShock::Touch(CBaseEntity *pOther) int iContents = UTIL_PointContents(pev->origin); - // Create sparks + // Create sparks if (iContents != CONTENTS_WATER) { UTIL_Sparks(tr.vecEndPos); } - UTIL_Remove(this); } else { 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); + int damageType = DMG_ENERGYBEAM; + if (pOther->pev->deadflag == DEAD_DEAD) + { + damageType |= DMG_ALWAYSGIB; + } + else + { + CBaseMonster* pMonster = pOther->MyMonsterPointer(); + if (pMonster) + pMonster->GlowShellOn( Vector( 0, 220, 255 ), .5f ); + } + pOther->TraceAttack(pev, pev->dmg, pev->velocity.Normalize(), &tr, damageType ); + ApplyMultiDamage(pev, pevOwner ? pevOwner : pev); if (pOther->IsPlayer() && (UTIL_PointContents(pev->origin) != CONTENTS_WATER)) { const Vector position = tr.vecEndPos; @@ -187,69 +200,60 @@ void CShock::Touch(CBaseEntity *pOther) MESSAGE_END(); } } - UTIL_Remove(this); + SetThink( &CBaseEntity::SUB_Remove ); + pev->nextthink = gpGlobals->time; } -//========================================================= -// Purpose: -//========================================================= -void CShock::CreateBeam(const Vector& start, const Vector& end, int width) +void CShock::CreateEffects() { + m_pSprite = CSprite::SpriteCreate( "sprites/flare3.spr", pev->origin, FALSE ); + m_pSprite->SetAttachment( edict(), 0 ); + m_pSprite->pev->scale = 0.4; + m_pSprite->SetTransparency( kRenderTransAdd, 255, 255, 255, 170, kRenderFxNoDissipation ); + m_pSprite->pev->spawnflags |= SF_SPRITE_TEMPORARY; + m_pSprite->pev->flags |= FL_SKIPLOCALHOST; + + m_pBeam = CBeam::BeamCreate( "sprites/lgtning.spr", 30 ); + if (m_pBeam) { - ClearBeam(); - } - - m_pBeam = CBeam::BeamCreate("sprites/lgtning.spr", width); - if (!m_pBeam) - return; - - m_pBeam->PointsInit(start, end); - 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(40); - m_pBeam->SetFlags(SF_BEAM_SHADEIN | SF_BEAM_SHADEOUT); -} - - -//========================================================= -// Purpose: -//========================================================= -void CShock::ClearBeam() -{ - if (m_pBeam) - { - UTIL_Remove(m_pBeam); - m_pBeam = NULL; - } -} - -void CShock::UpdateBeam(const Vector& start, const Vector& end) -{ - if (!m_pBeam) - { - // Create the beam if not already created. - CreateBeam(start, end, SHOCK_BEAM_WIDTH); - } - else - { - m_pBeam->SetStartPos(start); - m_pBeam->SetEndPos(end); + m_pBeam->EntsInit( entindex(), entindex() ); + m_pBeam->SetStartAttachment( 1 ); + m_pBeam->SetEndAttachment( 2 ); + m_pBeam->SetBrightness( 190 ); + m_pBeam->SetScrollRate( 20 ); + m_pBeam->SetNoise( 20 ); + m_pBeam->SetFlags( BEAM_FSHADEOUT ); + m_pBeam->SetColor( 0, 255, 255 ); + m_pBeam->pev->spawnflags = SF_BEAM_TEMPORARY; m_pBeam->RelinkBeam(); } + + m_pNoise = CBeam::BeamCreate( "sprites/lgtning.spr", 30 ); + + if (m_pNoise) + { + m_pNoise->EntsInit( entindex(), entindex() ); + m_pNoise->SetStartAttachment( 1 ); + m_pNoise->SetEndAttachment( 2 ); + m_pNoise->SetBrightness( 190 ); + m_pNoise->SetScrollRate( 20 ); + m_pNoise->SetNoise( 65 ); + m_pNoise->SetFlags( BEAM_FSHADEOUT ); + m_pNoise->SetColor( 255, 255, 173 ); + m_pNoise->pev->spawnflags = SF_BEAM_TEMPORARY; + m_pNoise->RelinkBeam(); + } } -void CShock::ComputeBeamPositions(Vector* pos1, Vector* pos2) +void CShock::ClearEffects() { - const Vector vel = pev->velocity.Normalize(); - UTIL_MakeVectors( pev->angles ); + UTIL_Remove( m_pBeam ); + m_pBeam = NULL; - /* 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); + UTIL_Remove( m_pNoise ); + m_pNoise = NULL; + + UTIL_Remove( m_pSprite ); + m_pSprite = NULL; } diff --git a/dlls/gearbox/shockrifle.cpp b/dlls/gearbox/shockrifle.cpp index 01f0abc6..b49f81f0 100644 --- a/dlls/gearbox/shockrifle.cpp +++ b/dlls/gearbox/shockrifle.cpp @@ -67,7 +67,7 @@ void CShockrifle::Precache(void) m_usShockFire = PRECACHE_EVENT(1, "events/shock.sc"); - UTIL_PrecacheOther("shock"); + UTIL_PrecacheOther("shock_beam"); } int CShockrifle::AddToPlayer(CBasePlayer *pPlayer) @@ -136,7 +136,17 @@ void CShockrifle::PrimaryAttack() return; } + if (m_pPlayer->pev->waterlevel == 3) + { #ifndef CLIENT_DLL + RadiusDamage(m_pPlayer->pev->origin, m_pPlayer->pev, m_pPlayer->pev, 300, 144, CLASS_NONE, DMG_SHOCK | DMG_ALWAYSGIB ); +#endif + return; + } + +#ifndef CLIENT_DLL + Vector anglesAim = m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle; + anglesAim.x = -anglesAim.x; UTIL_MakeVectors(m_pPlayer->pev->v_angle); Vector vecSrc; @@ -146,8 +156,8 @@ void CShockrifle::PrimaryAttack() vecSrc = vecSrc + gpGlobals->v_right * 8; vecSrc = vecSrc + gpGlobals->v_up * -12; - CBaseEntity *pShock = CBaseEntity::Create("shock", vecSrc, m_pPlayer->pev->v_angle, m_pPlayer->edict()); - pShock->pev->velocity = gpGlobals->v_forward * 900; + CBaseEntity *pShock = CBaseEntity::Create("shock_beam", vecSrc, anglesAim, m_pPlayer->edict()); + pShock->pev->velocity = gpGlobals->v_forward * 2000; m_flRechargeTime = gpGlobals->time + 0.5; #endif diff --git a/dlls/gearbox/strooper.cpp b/dlls/gearbox/strooper.cpp index 7ff68164..320fc97b 100644 --- a/dlls/gearbox/strooper.cpp +++ b/dlls/gearbox/strooper.cpp @@ -362,9 +362,10 @@ void CStrooper::HandleAnimEvent(MonsterEvent_t *pEvent) vecGunAngles = (m_vecEnemyLKP - vecGunPos).Normalize(); } - CBaseEntity *pShock = CBaseEntity::Create("shock", vecGunPos, pev->angles, edict()); + CBaseEntity *pShock = CBaseEntity::Create("shock_beam", vecGunPos, pev->angles, edict()); vecGunAngles.z += RANDOM_FLOAT( -0.05, 0 ); - pShock->pev->velocity = vecGunAngles * 900; + pShock->pev->velocity = vecGunAngles * 2000; + pShock->pev->nextthink = gpGlobals->time; // Play fire sound. EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/shock_fire.wav", 1, ATTN_NORM); diff --git a/dlls/monsters.cpp b/dlls/monsters.cpp index 3b122ce5..5c967c72 100644 --- a/dlls/monsters.cpp +++ b/dlls/monsters.cpp @@ -527,9 +527,8 @@ void CBaseMonster::MonsterThink( void ) { pev->nextthink = gpGlobals->time + 0.1;// keep monster thinking. - GlowShellUpdate(); - RunAI(); + GlowShellUpdate(); float flInterval = StudioFrameAdvance( ); // animate @@ -3429,7 +3428,7 @@ void CBaseMonster::GlowShellUpdate( void ) { if( m_glowShellUpdate ) { - if( gpGlobals->time > m_glowShellTime ) + if( gpGlobals->time > m_glowShellTime || pev->deadflag == DEAD_DEAD ) GlowShellOff(); } } diff --git a/dlls/monsterstate.cpp b/dlls/monsterstate.cpp index b830ee4f..48419ebd 100644 --- a/dlls/monsterstate.cpp +++ b/dlls/monsterstate.cpp @@ -99,8 +99,6 @@ void CBaseMonster::RunAI( void ) CheckAmmo(); } - if (m_glowShellUpdate && pev->deadflag == DEAD_DEAD) - GlowShellOff(); FCheckAITrigger(); PrescheduleThink(); diff --git a/dlls/multiplay_gamerules.cpp b/dlls/multiplay_gamerules.cpp index f8599408..4f643e4b 100644 --- a/dlls/multiplay_gamerules.cpp +++ b/dlls/multiplay_gamerules.cpp @@ -196,7 +196,7 @@ void CHalfLifeMultiplay::RefreshSkillData( void ) gSkillData.plrDmgDisplacer = 5; // Shockroach - gSkillData.plrDmgShockroach = 10; + gSkillData.plrDmgShockroachSingleplayer = 10; // Spore gSkillData.plrDmgSpore = 50; @@ -217,7 +217,7 @@ void CHalfLifeMultiplay::RefreshSkillData( void ) gSkillData.monDmgDisplacer = 250; // Shockroach - gSkillData.monDmgShockroach = 15; + gSkillData.plrDmgShockroachMultiplayer = 15; // Displacer radius gSkillData.displacerDmgRadius = 300; diff --git a/dlls/skill.h b/dlls/skill.h index a24f43f6..b68a8fd8 100644 --- a/dlls/skill.h +++ b/dlls/skill.h @@ -207,7 +207,7 @@ struct skilldata_t float plrDmgGrapple; float plrDmgEagle; float plrDmgDisplacer; - float plrDmgShockroach; + float plrDmgShockroachSingleplayer; float plrDmgSpore; float plrDmg762; float plrDmg556; @@ -216,7 +216,7 @@ struct skilldata_t float monDmg762; float monDmg556; float monDmgDisplacer; - float monDmgShockroach; + float plrDmgShockroachMultiplayer; float displacerDmgRadius; };