Browse Source

Update spore launcher

opforfixed
Roman Chistokhodov 5 years ago
parent
commit
b1c7892f23
  1. 278
      dlls/gearbox/spore_ammo.cpp
  2. 251
      dlls/gearbox/sporegrenade.cpp
  3. 22
      dlls/gearbox/sporegrenade.h
  4. 123
      dlls/gearbox/sporelauncher.cpp
  5. 2
      dlls/player.cpp

278
dlls/gearbox/spore_ammo.cpp

@ -21,187 +21,195 @@
#include "nodes.h" #include "nodes.h"
#include "player.h" #include "player.h"
#include "gamerules.h" #include "gamerules.h"
#include "xen.h" #include "sporegrenade.h"
class CSporeFruit : public CActAnimating class CSporeAmmo : public CBaseEntity
{ {
public: public:
void Spawn( void ); void Spawn( void );
void Precache( void ); void Precache( void );
void Touch(CBaseEntity *pOther); void EXPORT BornThink ( void );
void Think(void); void EXPORT IdleThink ( void );
void EXPORT AmmoTouch ( CBaseEntity *pOther );
int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType );
virtual int Save(CSave &save); int Save( CSave &save );
virtual int Restore(CRestore &restore); int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[]; static TYPEDESCRIPTION m_SaveData[];
BOOL m_fAmmoReady; virtual int SizeForGrapple() { return GRAPPLE_FIXED; }
private:
int m_iExplode;
BOOL borntime;
float m_flTimeSporeIdle;
}; };
LINK_ENTITY_TO_CLASS(spore_fruit, CSporeFruit);
TYPEDESCRIPTION CSporeFruit::m_SaveData[] = typedef enum
{ {
DEFINE_FIELD(CSporeFruit, m_fAmmoReady, FIELD_BOOLEAN), SPOREAMMO_IDLE = 0,
}; SPOREAMMO_SPAWNUP,
SPOREAMMO_SNATCHUP,
SPOREAMMO_SPAWNDOWN,
SPOREAMMO_SNATCHDOWN,
SPOREAMMO_IDLE1,
SPOREAMMO_IDLE2,
} SPOREAMMO;
IMPLEMENT_SAVERESTORE(CSporeFruit, CActAnimating); LINK_ENTITY_TO_CLASS( ammo_spore, CSporeAmmo )
void CSporeFruit::Spawn(void) TYPEDESCRIPTION CSporeAmmo::m_SaveData[] =
{ {
Precache(); DEFINE_FIELD( CSporeAmmo, m_flTimeSporeIdle, FIELD_TIME ),
DEFINE_FIELD( CSporeAmmo, borntime, FIELD_BOOLEAN ),
};
IMPLEMENT_SAVERESTORE( CSporeAmmo, CBaseEntity )
void CSporeAmmo :: Precache( void )
{
PRECACHE_MODEL("models/spore_ammo.mdl");
m_iExplode = PRECACHE_MODEL ("sprites/spore_exp_c_01.spr");
PRECACHE_SOUND("weapons/spore_ammo.wav");
UTIL_PrecacheOther ( "spore" );
}
//=========================================================
// Spawn
//=========================================================
void CSporeAmmo :: Spawn( void )
{
Precache( );
SET_MODEL(ENT(pev), "models/spore_ammo.mdl"); SET_MODEL(ENT(pev), "models/spore_ammo.mdl");
UTIL_SetSize(pev, Vector( -16, -16, -16 ), Vector( 16, 16, 16 ));
pev->takedamage = DAMAGE_YES;
pev->solid = SOLID_BBOX;
pev->movetype = MOVETYPE_NONE; pev->movetype = MOVETYPE_NONE;
pev->solid = SOLID_TRIGGER; pev->framerate = 1.0;
UTIL_SetSize(pev, Vector(-16, -16, 0), Vector(16, 16, 8)); pev->animtime = gpGlobals->time + 0.1;
SetActivity(ACT_IDLE);
pev->sequence = SPOREAMMO_IDLE1;
pev->body = 1;
Vector vecOrigin = pev->origin;
vecOrigin.z += 16;
UTIL_SetOrigin( pev, vecOrigin );
pev->angles.x -= 90;// :3
SetThink (&CSporeAmmo::IdleThink);
SetTouch (&CSporeAmmo::AmmoTouch);
m_flTimeSporeIdle = gpGlobals->time + 20;
pev->nextthink = gpGlobals->time + 0.1; pev->nextthink = gpGlobals->time + 0.1;
pev->frame = 0;
// idle
// spawnup
// snatchup
// spawndn
// snatchdn
// idle2
// idle3
int i;
int seq = LookupSequence("idle");
if (seq != -1)
{
for (i = 0; i < ACT_FLINCH_RIGHTLEG; i++)
{
if (seq == LookupActivity(i))
{
break;
}
}
} }
seq = LookupSequence("spawnup"); //=========================================================
if (seq != -1) // Override all damage
{ //=========================================================
for (i = 0; i < ACT_FLINCH_RIGHTLEG; i++) int CSporeAmmo::TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType )
{ {
if (seq == LookupActivity(i)) if (!borntime) // rigth '!borntime' // blast in anytime 'borntime || !borntime'
{ {
break; Vector vecSrc = pev->origin + gpGlobals->v_forward * -32;
}
}
}
seq = LookupSequence("snatchup"); MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
if (seq != -1) WRITE_BYTE( TE_EXPLOSION ); // This makes a dynamic light and the explosion sprites/sound
{ WRITE_COORD( vecSrc.x ); // Send to PAS because of the sound
for (i = 0; i < ACT_FLINCH_RIGHTLEG; i++) WRITE_COORD( vecSrc.y );
{ WRITE_COORD( vecSrc.z );
if (seq == LookupActivity(i)) WRITE_SHORT( m_iExplode );
{ WRITE_BYTE( 25 ); // scale * 10
break; WRITE_BYTE( 12 ); // framerate
} WRITE_BYTE( TE_EXPLFLAG_NOSOUND );
} MESSAGE_END();
}
seq = LookupSequence("spawndn");
if (seq != -1)
{
for (i = 0; i < ACT_FLINCH_RIGHTLEG; i++)
{
if (seq == LookupActivity(i))
{
break;
}
}
}
seq = LookupSequence("snatchdn"); //ALERT( at_console, "angles %f %f %f\n", pev->angles.x, pev->angles.y, pev->angles.z );
if (seq != -1)
{
for (i = 0; i < ACT_FLINCH_RIGHTLEG; i++)
{
if (seq == LookupActivity(i))
{
break;
}
}
}
seq = LookupSequence("idle2"); Vector angles = pev->angles;
if (seq != -1) angles.x -= 90;
{ angles.y += 180;
for (i = 0; i < ACT_FLINCH_RIGHTLEG; i++)
{ Vector vecLaunchDir = angles;
if (seq == LookupActivity(i))
{ vecLaunchDir.x += RANDOM_FLOAT( -20, 20 );
break; vecLaunchDir.y += RANDOM_FLOAT( -20, 20 );
} vecLaunchDir.z += RANDOM_FLOAT( -20, 20 );
UTIL_MakeVectors( vecLaunchDir );
CSporeGrenade::ShootTimed(pevAttacker, vecSrc, gpGlobals->v_forward * 800, false);
pev->framerate = 1.0;
pev->animtime = gpGlobals->time + 0.1;
pev->sequence = SPOREAMMO_SNATCHDOWN;
pev->body = 0;
borntime = 1;
m_flTimeSporeIdle = gpGlobals->time + 1;
SetThink (&CSporeAmmo::IdleThink);
return 1;
} }
return 0;
} }
seq = LookupSequence("idle3"); //=========================================================
if (seq != -1) // Thinking begin
{ //=========================================================
for (i = 0; i < ACT_FLINCH_RIGHTLEG; i++) void CSporeAmmo :: BornThink ( void )
{ {
if (seq == LookupActivity(i)) pev->nextthink = gpGlobals->time + 0.1;
{
break;
}
}
}
} if ( m_flTimeSporeIdle > gpGlobals->time )
return;
void CSporeFruit::Precache(void) pev->sequence = SPOREAMMO_SPAWNDOWN;
{ pev->framerate = 1.0;
PRECACHE_MODEL("models/spore_ammo.mdl"); pev->animtime = gpGlobals->time + 0.1;
pev->body = 1;
borntime = 0;
SetThink (&CSporeAmmo::IdleThink);
m_flTimeSporeIdle = gpGlobals->time + 16;
} }
void CSporeFruit::Think(void) void CSporeAmmo :: IdleThink ( void )
{ {
StudioFrameAdvance();
pev->nextthink = gpGlobals->time + 0.1; pev->nextthink = gpGlobals->time + 0.1;
if ( m_flTimeSporeIdle > gpGlobals->time )
return;
switch (GetActivity()) if (borntime)
{
case ACT_CROUCH:
if (m_fSequenceFinished)
{ {
SetActivity(ACT_CROUCHIDLE); pev->sequence = SPOREAMMO_IDLE;
}
break;
case ACT_CROUCHIDLE: m_flTimeSporeIdle = gpGlobals->time + 10;
if (gpGlobals->time > pev->dmgtime) SetThink(&CSporeAmmo::BornThink);
{ return;
SetActivity(ACT_STAND);
} }
break; else
{
case ACT_STAND: pev->sequence = SPOREAMMO_IDLE1;
if (m_fSequenceFinished)
SetActivity(ACT_IDLE);
break;
case ACT_IDLE:
default:
break;
} }
} }
void CSporeAmmo :: AmmoTouch ( CBaseEntity *pOther )
void CSporeFruit::Touch(CBaseEntity *pOther)
{
if (pOther->IsPlayer())
{ {
if (GetActivity() == ACT_IDLE || GetActivity() == ACT_STAND) if ( !pOther->IsPlayer() )
return;
if (borntime)
return;
int bResult = (pOther->GiveAmmo( AMMO_SPORE_GIVE, "spores", SPORE_MAX_CARRY ) != -1);
if (bResult)
{ {
SetActivity(ACT_CROUCH); EMIT_SOUND(ENT(pev), CHAN_ITEM, "weapons/spore_ammo.wav", 1, ATTN_NORM);
}
pev->framerate = 1.0;
pev->animtime = gpGlobals->time + 0.1;
pev->sequence = SPOREAMMO_SNATCHDOWN;
pev->body = 0;
borntime = 1;
m_flTimeSporeIdle = gpGlobals->time + 1;
SetThink (&CSporeAmmo::IdleThink);
} }
} }

251
dlls/gearbox/sporegrenade.cpp

@ -27,33 +27,31 @@
#include "sporegrenade.h" #include "sporegrenade.h"
#include "gearbox_weapons.h" #include "gearbox_weapons.h"
LINK_ENTITY_TO_CLASS(monster_spore, CSporeGrenade); LINK_ENTITY_TO_CLASS(spore, CSporeGrenade)
TYPEDESCRIPTION CSporeGrenade::m_SaveData[] = TYPEDESCRIPTION CSporeGrenade::m_SaveData[] =
{ {
DEFINE_FIELD(CSporeGrenade, m_pSporeGlow, FIELD_CLASSPTR), DEFINE_FIELD(CSporeGrenade, m_pSporeGlow, FIELD_CLASSPTR),
DEFINE_FIELD(CSporeGrenade, m_flNextSpriteTrailSpawn, FIELD_TIME),
}; };
IMPLEMENT_SAVERESTORE(CSporeGrenade, CGrenade); IMPLEMENT_SAVERESTORE(CSporeGrenade, CBaseMonster)
int gSporeExplode, gSporeExplodeC; int gSporeExplode, gSporeExplodeC;
void CSporeGrenade::Precache(void) void CSporeGrenade::Precache(void)
{ {
PRECACHE_MODEL("models/spore.mdl");
PRECACHE_MODEL("sprites/glow02.spr"); PRECACHE_MODEL("sprites/glow02.spr");
g_sModelIndexTinySpit = PRECACHE_MODEL("sprites/tinyspit.spr");
gSporeExplode = PRECACHE_MODEL ("sprites/spore_exp_01.spr"); gSporeExplode = PRECACHE_MODEL ("sprites/spore_exp_01.spr");
gSporeExplodeC = PRECACHE_MODEL ("sprites/spore_exp_c_01.spr"); gSporeExplodeC = PRECACHE_MODEL ("sprites/spore_exp_c_01.spr");
PRECACHE_SOUND("weapons/splauncher_bounce.wav");
PRECACHE_SOUND("weapons/splauncher_impact.wav");
} }
// UNDONE: temporary scorching for PreAlpha - find a less sleazy permenant solution. void CSporeGrenade::Explode(TraceResult *pTrace)
void CSporeGrenade::Explode(TraceResult *pTrace, int bitsDamageType)
{ {
//float flRndSound;// sound randomizer
pev->model = iStringNull;//invisible
pev->solid = SOLID_NOT;// intangible pev->solid = SOLID_NOT;// intangible
pev->takedamage = DAMAGE_NO; pev->takedamage = DAMAGE_NO;
// Pull out of the wall a bit // Pull out of the wall a bit
@ -93,6 +91,19 @@ void CSporeGrenade::Explode(TraceResult *pTrace, int bitsDamageType)
WRITE_BYTE( 155 ); // framerate WRITE_BYTE( 155 ); // framerate
MESSAGE_END(); MESSAGE_END();
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( 12 ); // radius * 0.1
WRITE_BYTE( 0 ); // r
WRITE_BYTE( 180 ); // g
WRITE_BYTE( 0 ); // b
WRITE_BYTE( 20 ); // time * 10
WRITE_BYTE( 20 ); // decay * 0.1
MESSAGE_END( );
// Play explode sound. // Play explode sound.
EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/splauncher_impact.wav", 1, ATTN_NORM); EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/splauncher_impact.wav", 1, ATTN_NORM);
@ -105,72 +116,37 @@ void CSporeGrenade::Explode(TraceResult *pTrace, int bitsDamageType)
pev->owner = NULL; // can't traceline attack owner if this is set pev->owner = NULL; // can't traceline attack owner if this is set
RadiusDamage(pev, pevOwner, pev->dmg, CLASS_NONE, bitsDamageType); RadiusDamage(pev, pevOwner, pev->dmg, CLASS_NONE, DMG_BLAST);
// Place a decal on the surface that was hit. // Place a decal on the surface that was hit.
#if FEATURE_OPFOR_DECALS
UTIL_DecalTrace(pTrace, DECAL_SPR_SPLT1 + RANDOM_LONG(0, 2));
#else
UTIL_DecalTrace(pTrace, DECAL_YBLOOD5 + RANDOM_LONG(0, 1)); UTIL_DecalTrace(pTrace, DECAL_YBLOOD5 + RANDOM_LONG(0, 1));
#endif
pev->effects |= EF_NODRAW;
SetThink(&CSporeGrenade::Smoke);
pev->velocity = g_vecZero;
pev->nextthink = gpGlobals->time + 0.3;
if (m_pSporeGlow)
{
UTIL_Remove(m_pSporeGlow);
m_pSporeGlow = NULL;
}
}
void CSporeGrenade::Smoke(void)
{
if (UTIL_PointContents(pev->origin) == CONTENTS_WATER)
{
UTIL_Bubbles(pev->origin - Vector(64, 64, 64), pev->origin + Vector(64, 64, 64), 100);
}
UTIL_Remove(this); UTIL_Remove(this);
} }
void CSporeGrenade::Killed(entvars_t *pevAttacker, int iGib)
{
Detonate();
}
// Timed grenade, this think is called when time runs out.
void CSporeGrenade::DetonateUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
{
SetThink(&CSporeGrenade::Detonate);
pev->nextthink = gpGlobals->time;
}
void CSporeGrenade::PreDetonate(void)
{
CSoundEnt::InsertSound(bits_SOUND_DANGER, pev->origin, 400, 0.3);
SetThink(&CSporeGrenade::Detonate);
pev->nextthink = gpGlobals->time + 1;
}
void CSporeGrenade::Detonate(void) void CSporeGrenade::Detonate(void)
{ {
TraceResult tr; TraceResult tr;
Vector vecSpot;// trace starts here! Vector vecSpot = pev->origin + Vector(0, 0, 8);
vecSpot = pev->origin + Vector(0, 0, 8);
UTIL_TraceLine(vecSpot, vecSpot + Vector(0, 0, -40), ignore_monsters, ENT(pev), &tr); UTIL_TraceLine(vecSpot, vecSpot + Vector(0, 0, -40), ignore_monsters, ENT(pev), &tr);
Explode(&tr, DMG_BLAST); Explode(&tr);
} }
void CSporeGrenade::BounceSound(void) void CSporeGrenade::BounceSound(void)
{ {
switch (RANDOM_LONG(0, 2)) DangerSound();
{ EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/splauncher_bounce.wav", 0.25, ATTN_NORM);
case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/spore_hit1.wav", 0.25, ATTN_NORM); break;
case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/spore_hit2.wav", 0.25, ATTN_NORM); break;
case 2: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/spore_hit3.wav", 0.25, ATTN_NORM); break;
} }
void CSporeGrenade::DangerSound()
{
CSoundEnt::InsertSound(bits_SOUND_DANGER, pev->origin + pev->velocity * 0.5, pev->velocity.Length(), 0.2);
} }
void CSporeGrenade::TumbleThink(void) void CSporeGrenade::TumbleThink(void)
@ -181,7 +157,6 @@ void CSporeGrenade::TumbleThink(void)
return; return;
} }
StudioFrameAdvance();
pev->nextthink = gpGlobals->time + 0.1; pev->nextthink = gpGlobals->time + 0.1;
if (pev->dmgtime - 1 < gpGlobals->time) if (pev->dmgtime - 1 < gpGlobals->time)
@ -193,18 +168,13 @@ void CSporeGrenade::TumbleThink(void)
{ {
SetThink(&CSporeGrenade::Detonate); SetThink(&CSporeGrenade::Detonate);
} }
if (pev->waterlevel != 0)
{
pev->velocity = pev->velocity * 0.5;
pev->framerate = 0.2;
}
// Spawn particles. // Spawn particles.
SpawnTrailParticles( SpawnTrailParticles(
pev->origin, // position pev->origin, // position
-pev->velocity.Normalize(), // dir -pev->velocity.Normalize(), // dir
g_sModelIndexTinySpit, // modelindex g_sModelIndexTinySpit, // modelindex
RANDOM_LONG( 5, 10 ), // count RANDOM_LONG( 2, 4 ), // count
RANDOM_FLOAT(10, 15), // speed RANDOM_FLOAT(10, 15), // speed
RANDOM_FLOAT(2, 3) * 100); // noise ( client will divide by 100 ) RANDOM_FLOAT(2, 3) * 100); // noise ( client will divide by 100 )
} }
@ -222,11 +192,9 @@ void CSporeGrenade::ExplodeTouch(CBaseEntity *pOther)
vecSpot = pev->origin - pev->velocity.Normalize() * 32; vecSpot = pev->origin - pev->velocity.Normalize() * 32;
UTIL_TraceLine(vecSpot, vecSpot + pev->velocity.Normalize() * 64, ignore_monsters, ENT(pev), &tr); UTIL_TraceLine(vecSpot, vecSpot + pev->velocity.Normalize() * 64, ignore_monsters, ENT(pev), &tr);
Explode(&tr, DMG_BLAST); Explode(&tr);
} }
void CSporeGrenade::DangerSoundThink(void) void CSporeGrenade::DangerSoundThink(void)
{ {
if (!IsInWorld()) if (!IsInWorld())
@ -235,14 +203,9 @@ void CSporeGrenade::DangerSoundThink(void)
return; return;
} }
CSoundEnt::InsertSound(bits_SOUND_DANGER, pev->origin + pev->velocity * 0.5, pev->velocity.Length(), 0.2); DangerSound();
pev->nextthink = gpGlobals->time + 0.2; pev->nextthink = gpGlobals->time + 0.2;
if (pev->waterlevel != 0)
{
pev->velocity = pev->velocity * 0.5;
}
// Spawn particles. // Spawn particles.
SpawnTrailParticles( SpawnTrailParticles(
pev->origin, // position pev->origin, // position
@ -255,93 +218,32 @@ void CSporeGrenade::DangerSoundThink(void)
void CSporeGrenade::BounceTouch(CBaseEntity *pOther) void CSporeGrenade::BounceTouch(CBaseEntity *pOther)
{ {
#if 0 if ( !pOther->pev->takedamage )
// don't hit the guy that launched this grenade
if (pOther->edict() == pev->owner)
return;
#endif
// only do damage if we're moving fairly fast
if (m_flNextAttack < gpGlobals->time && pev->velocity.Length() > 100)
{
entvars_t *pevOwner = VARS(pev->owner);
if (pevOwner)
{ {
TraceResult tr = UTIL_GetGlobalTrace(); if (!(pev->flags & FL_ONGROUND)) {
ClearMultiDamage(); if (pev->dmg_save < gpGlobals->time) {
pOther->TraceAttack(pevOwner, 1, gpGlobals->v_forward, &tr, DMG_CLUB);
ApplyMultiDamage(pev, pevOwner);
}
m_flNextAttack = gpGlobals->time + 1.0; // debounce
}
Vector vecTestVelocity;
// pev->avelocity = Vector (300, 300, 300);
// this is my heuristic for modulating the grenade velocity because grenades dropped purely vertical
// or thrown very far tend to slow down too quickly for me to always catch just by testing velocity.
// trimming the Z velocity a bit seems to help quite a bit.
vecTestVelocity = pev->velocity;
vecTestVelocity.z *= 1.25; // 0.45
if (!m_fRegisteredSound && vecTestVelocity.Length() <= 60)
{
//ALERT( at_console, "Grenade Registered!: %f\n", vecTestVelocity.Length() );
// grenade is moving really slow. It's probably very close to where it will ultimately stop moving.
// go ahead and emit the danger sound.
// register a radius louder than the explosion, so we make sure everyone gets out of the way
CSoundEnt::InsertSound(bits_SOUND_DANGER, pev->origin, pev->dmg / 0.4, 0.3);
m_fRegisteredSound = TRUE;
}
if (pev->flags & FL_ONGROUND)
{
// add a bit of static friction
pev->velocity = pev->velocity * 0.01;
pev->sequence = RANDOM_LONG(1, 1);
}
else
{
// play bounce sound
BounceSound(); BounceSound();
pev->dmg_save = gpGlobals->time + 0.1;
} }
pev->framerate = pev->velocity.Length() / 200.0; } else {
if (pev->framerate > 1.0) pev->velocity = pev->velocity * 0.9;
pev->framerate = 1;
else if (pev->framerate < 0.5)
pev->framerate = 0;
} }
if (pev->flags & FL_SWIM)
void CSporeGrenade::SlideTouch(CBaseEntity *pOther)
{
// don't hit the guy that launched this grenade
if (pOther->edict() == pev->owner)
return;
// pev->avelocity = Vector (300, 300, 300);
if (pev->flags & FL_ONGROUND)
{
// add a bit of static friction
pev->velocity = pev->velocity * 0.95;
if (pev->velocity.x != 0 || pev->velocity.y != 0)
{ {
// maintain sliding sound pev->velocity = pev->velocity * 0.5;
} }
} }
else else
{ {
BounceSound(); TraceResult tr = UTIL_GetGlobalTrace();
Explode(&tr);
} }
} }
void CSporeGrenade::Spawn(void) void CSporeGrenade::Spawn(void)
{ {
Precache();
pev->classname = MAKE_STRING("spore");
pev->movetype = MOVETYPE_BOUNCE; pev->movetype = MOVETYPE_BOUNCE;
pev->solid = SOLID_BBOX; pev->solid = SOLID_BBOX;
@ -349,13 +251,9 @@ void CSporeGrenade::Spawn(void)
SET_MODEL(ENT(pev), "models/spore.mdl"); SET_MODEL(ENT(pev), "models/spore.mdl");
UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0)); UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0));
pev->gravity = 0.5; // 0.5 //pev->gravity = 0.5;
pev->friction = 0.2; // 0.8
pev->dmg = gSkillData.plrDmgSpore; pev->dmg = gSkillData.plrDmgSpore;
m_fRegisteredSound = FALSE;
m_flNextSpriteTrailSpawn = gpGlobals->time;
m_pSporeGlow = CSprite::SpriteCreate("sprites/glow02.spr", pev->origin, FALSE); m_pSporeGlow = CSprite::SpriteCreate("sprites/glow02.spr", pev->origin, FALSE);
@ -367,65 +265,54 @@ void CSporeGrenade::Spawn(void)
} }
} }
CGrenade * CSporeGrenade::ShootTimed(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time) CBaseEntity* CSporeGrenade::ShootTimed(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, bool ai)
{ {
CSporeGrenade *pGrenade = GetClassPtr((CSporeGrenade *)NULL); CSporeGrenade *pGrenade = GetClassPtr((CSporeGrenade *)NULL);
pGrenade->Spawn();
UTIL_SetOrigin(pGrenade->pev, vecStart); UTIL_SetOrigin(pGrenade->pev, vecStart);
pGrenade->Spawn();
pGrenade->pev->velocity = vecVelocity; pGrenade->pev->velocity = vecVelocity;
pGrenade->pev->angles = UTIL_VecToAngles(pGrenade->pev->velocity); pGrenade->pev->angles = UTIL_VecToAngles(pGrenade->pev->velocity);
pGrenade->pev->owner = ENT(pevOwner); pGrenade->pev->owner = ENT(pevOwner);
pGrenade->SetTouch(&CSporeGrenade::BounceTouch); // Bounce if touched pGrenade->SetTouch(&CSporeGrenade::BounceTouch); // Bounce if touched
// Take one second off of the desired detonation time and set the think to PreDetonate. PreDetonate float lifetime = 2.0;
// will insert a DANGER sound into the world sound list and delay detonation for one second so that if (ai) {
// the grenade explodes after the exact amount of time specified in the call to ShootTimed(). lifetime = 4.0;
pGrenade->pev->gravity = 0.5;
pGrenade->pev->dmgtime = gpGlobals->time + time; pGrenade->pev->friction = 0.9;
}
pGrenade->pev->dmgtime = gpGlobals->time + lifetime;
pGrenade->SetThink(&CSporeGrenade::TumbleThink); pGrenade->SetThink(&CSporeGrenade::TumbleThink);
pGrenade->pev->nextthink = gpGlobals->time + 0.1; pGrenade->pev->nextthink = gpGlobals->time + 0.1;
if (time < 0.1) if (lifetime < 0.1)
{ {
pGrenade->pev->nextthink = gpGlobals->time; pGrenade->pev->nextthink = gpGlobals->time;
pGrenade->pev->velocity = Vector(0, 0, 0); pGrenade->pev->velocity = Vector(0, 0, 0);
} }
pGrenade->pev->sequence = RANDOM_LONG(3, 6);
pGrenade->pev->framerate = 1.0;
// Tumble through the air
// pGrenade->pev->avelocity.x = -400;
pGrenade->pev->gravity = 0.5;
pGrenade->pev->friction = 0.2; // 0.8
SET_MODEL(ENT(pGrenade->pev), "models/spore.mdl");
pGrenade->pev->dmg = gSkillData.plrDmgSpore;
return pGrenade; return pGrenade;
} }
CGrenade *CSporeGrenade::ShootContact(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity) CBaseEntity *CSporeGrenade::ShootContact(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity)
{ {
CSporeGrenade *pGrenade = GetClassPtr((CSporeGrenade *)NULL); CSporeGrenade *pGrenade = GetClassPtr((CSporeGrenade *)NULL);
UTIL_SetOrigin(pGrenade->pev, vecStart);
pGrenade->Spawn(); pGrenade->Spawn();
pGrenade->pev->movetype = MOVETYPE_FLY; pGrenade->pev->movetype = MOVETYPE_FLY;
UTIL_SetOrigin(pGrenade->pev, vecStart);
pGrenade->pev->velocity = vecVelocity; pGrenade->pev->velocity = vecVelocity;
pGrenade->pev->angles = UTIL_VecToAngles(pGrenade->pev->velocity); pGrenade->pev->angles = UTIL_VecToAngles(pGrenade->pev->velocity);
pGrenade->pev->owner = ENT(pevOwner); pGrenade->pev->owner = ENT(pevOwner);
// make monsters afaid of it while in the air // make monsters afraid of it while in the air
pGrenade->SetThink(&CSporeGrenade::DangerSoundThink); pGrenade->SetThink(&CSporeGrenade::DangerSoundThink);
pGrenade->pev->nextthink = gpGlobals->time; pGrenade->pev->nextthink = gpGlobals->time;
// Tumble in air
// Explode on contact // Explode on contact
pGrenade->SetTouch(&CSporeGrenade::ExplodeTouch); pGrenade->SetTouch(&CSporeGrenade::ExplodeTouch);
pGrenade->pev->dmg = gSkillData.plrDmgSpore; pGrenade->pev->gravity = 0.5;
pGrenade->pev->friction = 0.7;
return pGrenade; return pGrenade;
} }
@ -464,3 +351,13 @@ void CSporeGrenade::SpawnExplosionParticles(const Vector& origin, const Vector&
WRITE_BYTE(noise); // noise ( client will divide by 100 ) WRITE_BYTE(noise); // noise ( client will divide by 100 )
MESSAGE_END(); MESSAGE_END();
} }
void CSporeGrenade::UpdateOnRemove()
{
CBaseMonster::UpdateOnRemove();
if (m_pSporeGlow)
{
UTIL_Remove(m_pSporeGlow);
m_pSporeGlow = NULL;
}
}

22
dlls/gearbox/sporegrenade.h

@ -16,9 +16,8 @@
#ifndef SPORE_GRENADE_H #ifndef SPORE_GRENADE_H
#define SPORE_GRENADE_H #define SPORE_GRENADE_H
// Contact/Timed spore grenade // Contact/Timed spore grenade
class CSporeGrenade : public CGrenade class CSporeGrenade : public CBaseMonster
{ {
public: public:
virtual int Save(CSave &save); virtual int Save(CSave &save);
@ -29,30 +28,25 @@ public:
void Precache(void); void Precache(void);
void Spawn(void); void Spawn(void);
static CGrenade *ShootTimed(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time); static CBaseEntity *ShootTimed(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, bool ai);
static CGrenade *ShootContact(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity); static CBaseEntity *ShootContact(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity);
void Explode(TraceResult *pTrace, int bitsDamageType); void Explode(TraceResult *pTrace);
void EXPORT Smoke(void);
void EXPORT BounceTouch(CBaseEntity *pOther); void EXPORT BounceTouch(CBaseEntity *pOther);
void EXPORT SlideTouch(CBaseEntity *pOther);
void EXPORT ExplodeTouch(CBaseEntity *pOther); void EXPORT ExplodeTouch(CBaseEntity *pOther);
void EXPORT DangerSoundThink(void); void EXPORT DangerSoundThink(void);
void EXPORT PreDetonate(void);
void EXPORT Detonate(void); void EXPORT Detonate(void);
void EXPORT DetonateUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value);
void EXPORT TumbleThink(void); void EXPORT TumbleThink(void);
void EXPORT FlyThink(void);
virtual void BounceSound(void); void BounceSound(void);
virtual int BloodColor(void) { return DONT_BLEED; } void DangerSound();
virtual void Killed(entvars_t *pevAttacker, int iGib);
static void SpawnTrailParticles(const Vector& origin, const Vector& direction, int modelindex, int count, float speed, float noise); static void SpawnTrailParticles(const Vector& origin, const Vector& direction, int modelindex, int count, float speed, float noise);
static void SpawnExplosionParticles(const Vector& origin, const Vector& direction, int modelindex, int count, float speed, float noise); static void SpawnExplosionParticles(const Vector& origin, const Vector& direction, int modelindex, int count, float speed, float noise);
void UpdateOnRemove();
CSprite* m_pSporeGlow; CSprite* m_pSporeGlow;
float m_flNextSpriteTrailSpawn;
}; };
#endif // SPORE_GRENADE_H #endif // SPORE_GRENADE_H

123
dlls/gearbox/sporelauncher.cpp

@ -21,8 +21,9 @@
#include "nodes.h" #include "nodes.h"
#include "player.h" #include "player.h"
#include "gamerules.h" #include "gamerules.h"
#include "xen.h" #ifndef CLIENT_DLL
#include "sporegrenade.h" #include "sporegrenade.h"
#endif
// special deathmatch shotgun spreads // special deathmatch shotgun spreads
#define VECTOR_CONE_DM_SHOTGUN Vector( 0.08716, 0.04362, 0.00 )// 10 degrees by 5 degrees #define VECTOR_CONE_DM_SHOTGUN Vector( 0.08716, 0.04362, 0.00 )// 10 degrees by 5 degrees
@ -40,7 +41,7 @@ enum sporelauncher_e {
SPLAUNCHER_IDLE2 SPLAUNCHER_IDLE2
}; };
LINK_ENTITY_TO_CLASS(weapon_sporelauncher, CSporelauncher); LINK_ENTITY_TO_CLASS(weapon_sporelauncher, CSporelauncher)
void CSporelauncher::Spawn() void CSporelauncher::Spawn()
{ {
@ -71,7 +72,7 @@ void CSporelauncher::Precache(void)
PRECACHE_MODEL("sprites/bigspit.spr"); PRECACHE_MODEL("sprites/bigspit.spr");
m_iSquidSpitSprite = PRECACHE_MODEL("sprites/tinyspit.spr"); m_iSquidSpitSprite = PRECACHE_MODEL("sprites/tinyspit.spr");
UTIL_PrecacheOther("monster_spore"); UTIL_PrecacheOther("spore");
m_usSporeFire = PRECACHE_EVENT(1, "events/spore.sc"); m_usSporeFire = PRECACHE_EVENT(1, "events/spore.sc");
} }
@ -92,7 +93,7 @@ int CSporelauncher::AddToPlayer(CBasePlayer *pPlayer)
int CSporelauncher::GetItemInfo(ItemInfo *p) int CSporelauncher::GetItemInfo(ItemInfo *p)
{ {
p->pszName = STRING(pev->classname); p->pszName = STRING(pev->classname);
p->pszAmmo1 = "Spores"; p->pszAmmo1 = "spores";
p->iMaxAmmo1 = SPORE_MAX_CARRY; p->iMaxAmmo1 = SPORE_MAX_CARRY;
p->pszAmmo2 = NULL; p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1; p->iMaxAmmo2 = -1;
@ -115,21 +116,8 @@ BOOL CSporelauncher::Deploy()
void CSporelauncher::PrimaryAttack() void CSporelauncher::PrimaryAttack()
{ {
// don't fire underwater
if (m_pPlayer->pev->waterlevel == 3)
{
PlayEmptySound();
m_flNextPrimaryAttack = GetNextAttackDelay(0.15);
return;
}
if (m_iClip <= 0) if (m_iClip <= 0)
{
Reload();
if (m_iClip == 0)
PlayEmptySound();
return; return;
}
m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME; m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH; m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;
@ -145,25 +133,13 @@ void CSporelauncher::PrimaryAttack()
// m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH; // m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH;
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
Vector vecSrc = m_pPlayer->GetGunPosition();
Vector vecAiming = m_pPlayer->GetAutoaimVector(AUTOAIM_5DEGREES);
Vector vecDir;
Vector vecVel;
UTIL_MakeVectors( m_pPlayer->pev->v_angle ); UTIL_MakeVectors( m_pPlayer->pev->v_angle );
Vector vecSrc = m_pPlayer->GetGunPosition( ) + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -8;
vecSrc = vecSrc + gpGlobals->v_forward * 16;
vecSrc = vecSrc + gpGlobals->v_right * 8;
vecSrc = vecSrc + gpGlobals->v_up * -12;
vecVel = gpGlobals->v_forward * 900;
vecDir = gpGlobals->v_forward + gpGlobals->v_right + gpGlobals->v_up;
vecDir = vecDir;
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
CSporeGrenade::ShootContact(m_pPlayer->pev, vecSrc, vecVel); UTIL_MakeVectors( m_pPlayer->pev->v_angle );
CSporeGrenade::ShootContact( m_pPlayer->pev, vecSrc, gpGlobals->v_forward * 1500 );
#endif #endif
PLAYBACK_EVENT_FULL( PLAYBACK_EVENT_FULL(
@ -173,9 +149,9 @@ void CSporelauncher::PrimaryAttack()
0.0, 0.0,
(float *)&g_vecZero, (float *)&g_vecZero,
(float *)&g_vecZero, (float *)&g_vecZero,
vecDir.x, vecSrc.x,
vecDir.y, vecSrc.y,
*(int*)&vecDir.z, *(int*)&vecSrc.z,
m_iSquidSpitSprite, m_iSquidSpitSprite,
0, 0,
TRUE); TRUE);
@ -202,20 +178,8 @@ void CSporelauncher::PrimaryAttack()
void CSporelauncher::SecondaryAttack(void) void CSporelauncher::SecondaryAttack(void)
{ {
// don't fire underwater
if (m_pPlayer->pev->waterlevel == 3)
{
PlayEmptySound();
m_flNextPrimaryAttack = GetNextAttackDelay(0.15);
return;
}
if (m_iClip <= 0) if (m_iClip <= 0)
{
Reload();
PlayEmptySound();
return; return;
}
m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME; m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH; m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;
@ -230,29 +194,16 @@ void CSporelauncher::SecondaryAttack(void)
flags = 0; flags = 0;
#endif #endif
m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH; //m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH;
// player "shoot" animation // player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1); m_pPlayer->SetAnimation(PLAYER_ATTACK1);
Vector vecSrc = m_pPlayer->GetGunPosition();
Vector vecAiming = m_pPlayer->GetAutoaimVector(AUTOAIM_2DEGREES);
Vector vecDir;
Vector vecVel;
UTIL_MakeVectors( m_pPlayer->pev->v_angle ); UTIL_MakeVectors( m_pPlayer->pev->v_angle );
Vector vecSrc = m_pPlayer->GetGunPosition( ) + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -8;
vecSrc = vecSrc + gpGlobals->v_forward * 16;
vecSrc = vecSrc + gpGlobals->v_right * 8;
vecSrc = vecSrc + gpGlobals->v_up * -12;
vecVel = gpGlobals->v_forward * 800;
vecDir = gpGlobals->v_forward + gpGlobals->v_right + gpGlobals->v_up;
vecDir = vecDir;
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
CSporeGrenade::ShootTimed(m_pPlayer->pev, vecSrc, vecVel, RANDOM_FLOAT(5, 6)); UTIL_MakeVectors( m_pPlayer->pev->v_angle );
CSporeGrenade::ShootTimed(m_pPlayer->pev, vecSrc, gpGlobals->v_forward * 1000, false);
#endif #endif
PLAYBACK_EVENT_FULL( PLAYBACK_EVENT_FULL(
@ -262,9 +213,9 @@ void CSporelauncher::SecondaryAttack(void)
0.0, 0.0,
(float *)&g_vecZero, (float *)&g_vecZero,
(float *)&g_vecZero, (float *)&g_vecZero,
vecDir.x, vecSrc.x,
vecDir.y, vecSrc.y,
*(int*)&vecDir.z, *(int*)&vecSrc.z,
m_iSquidSpitSprite, m_iSquidSpitSprite,
0, 0,
0); 0);
@ -366,45 +317,23 @@ void CSporelauncher::WeaponIdle(void)
{ {
int iAnim; int iAnim;
float flRand = UTIL_SharedRandomFloat(m_pPlayer->random_seed, 0, 1); float flRand = UTIL_SharedRandomFloat(m_pPlayer->random_seed, 0, 1);
if (flRand <= 0.5) if (flRand <= 0.4)
{ {
iAnim = SPLAUNCHER_IDLE; iAnim = SPLAUNCHER_IDLE;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.0f; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.0f;
} }
else else if (flRand <= 0.8)
{ {
iAnim = SPLAUNCHER_IDLE2; iAnim = SPLAUNCHER_IDLE2;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 4.0f; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 4.0f;
} }
else
SendWeaponAnim(iAnim);
}
}
}
class CSporeAmmo : public CBasePlayerAmmo
{
void Spawn(void)
{ {
Precache(); iAnim = SPLAUNCHER_FIDGET;
SET_MODEL(ENT(pev), "models/spore.mdl"); m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 4.0f;
CBasePlayerAmmo::Spawn();
} }
void Precache(void)
{ SendWeaponAnim(iAnim);
PRECACHE_MODEL("models/spore.mdl");
PRECACHE_SOUND("weapons/spore_ammo.wav");
} }
BOOL AddAmmo(CBaseEntity *pOther)
{
int bResult = (pOther->GiveAmmo(AMMO_SPORE_GIVE, "Spores", SPORE_MAX_CARRY) != -1);
if (bResult)
{
EMIT_SOUND(ENT(pev), CHAN_ITEM, "weapons/spore_ammo.wav", 1, ATTN_NORM);
} }
return bResult;
} }
};
LINK_ENTITY_TO_CLASS(ammo_spore, CSporeAmmo);

2
dlls/player.cpp

@ -1132,7 +1132,7 @@ void CBasePlayer::TabulateAmmo()
ammo_556 = AmmoInventory( GetAmmoIndex( "556" ) ); ammo_556 = AmmoInventory( GetAmmoIndex( "556" ) );
ammo_762 = AmmoInventory( GetAmmoIndex( "762" ) ); ammo_762 = AmmoInventory( GetAmmoIndex( "762" ) );
ammo_shocks = AmmoInventory( GetAmmoIndex( "Shocks" ) ); ammo_shocks = AmmoInventory( GetAmmoIndex( "Shocks" ) );
ammo_spores = AmmoInventory( GetAmmoIndex( "Spores" ) ); ammo_spores = AmmoInventory( GetAmmoIndex( "spores" ) );
} }
/* /*

Loading…
Cancel
Save