Update spore launcher

This commit is contained in:
Roman Chistokhodov 2019-07-31 00:42:13 +03:00
parent 8a28ac5749
commit b1c7892f23
5 changed files with 293 additions and 465 deletions

View File

@ -21,187 +21,195 @@
#include "nodes.h"
#include "player.h"
#include "gamerules.h"
#include "xen.h"
#include "sporegrenade.h"
class CSporeFruit : public CActAnimating
class CSporeAmmo : public CBaseEntity
{
public:
void Spawn(void);
void Precache(void);
void Touch(CBaseEntity *pOther);
void Think(void);
void Spawn( void );
void Precache( void );
void EXPORT BornThink ( 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);
virtual int Restore(CRestore &restore);
static TYPEDESCRIPTION m_SaveData[];
int Save( CSave &save );
int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
BOOL m_fAmmoReady;
private:
virtual int SizeForGrapple() { return GRAPPLE_FIXED; }
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;
LINK_ENTITY_TO_CLASS( ammo_spore, CSporeAmmo )
TYPEDESCRIPTION CSporeAmmo::m_SaveData[] =
{
DEFINE_FIELD( CSporeAmmo, m_flTimeSporeIdle, FIELD_TIME ),
DEFINE_FIELD( CSporeAmmo, borntime, FIELD_BOOLEAN ),
};
IMPLEMENT_SAVERESTORE( CSporeAmmo, CBaseEntity )
IMPLEMENT_SAVERESTORE(CSporeFruit, CActAnimating);
void CSporeFruit::Spawn(void)
{
Precache();
SET_MODEL(ENT(pev), "models/spore_ammo.mdl");
pev->movetype = MOVETYPE_NONE;
pev->solid = SOLID_TRIGGER;
UTIL_SetSize(pev, Vector(-16, -16, 0), Vector(16, 16, 8));
SetActivity(ACT_IDLE);
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)
{
for (i = 0; i < ACT_FLINCH_RIGHTLEG; i++)
{
if (seq == LookupActivity(i))
{
break;
}
}
}
seq = LookupSequence("snatchup");
if (seq != -1)
{
for (i = 0; i < ACT_FLINCH_RIGHTLEG; i++)
{
if (seq == LookupActivity(i))
{
break;
}
}
}
seq = LookupSequence("spawndn");
if (seq != -1)
{
for (i = 0; i < ACT_FLINCH_RIGHTLEG; i++)
{
if (seq == LookupActivity(i))
{
break;
}
}
}
seq = LookupSequence("snatchdn");
if (seq != -1)
{
for (i = 0; i < ACT_FLINCH_RIGHTLEG; i++)
{
if (seq == LookupActivity(i))
{
break;
}
}
}
seq = LookupSequence("idle2");
if (seq != -1)
{
for (i = 0; i < ACT_FLINCH_RIGHTLEG; i++)
{
if (seq == LookupActivity(i))
{
break;
}
}
}
seq = LookupSequence("idle3");
if (seq != -1)
{
for (i = 0; i < ACT_FLINCH_RIGHTLEG; i++)
{
if (seq == LookupActivity(i))
{
break;
}
}
}
}
void CSporeFruit::Precache(void)
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");
UTIL_SetSize(pev, Vector( -16, -16, -16 ), Vector( 16, 16, 16 ));
pev->takedamage = DAMAGE_YES;
pev->solid = SOLID_BBOX;
pev->movetype = MOVETYPE_NONE;
pev->framerate = 1.0;
pev->animtime = gpGlobals->time + 0.1;
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;
}
void CSporeFruit::Think(void)
//=========================================================
// Override all damage
//=========================================================
int CSporeAmmo::TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType )
{
if (!borntime) // rigth '!borntime' // blast in anytime 'borntime || !borntime'
{
Vector vecSrc = pev->origin + gpGlobals->v_forward * -32;
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
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
WRITE_COORD( vecSrc.y );
WRITE_COORD( vecSrc.z );
WRITE_SHORT( m_iExplode );
WRITE_BYTE( 25 ); // scale * 10
WRITE_BYTE( 12 ); // framerate
WRITE_BYTE( TE_EXPLFLAG_NOSOUND );
MESSAGE_END();
//ALERT( at_console, "angles %f %f %f\n", pev->angles.x, pev->angles.y, pev->angles.z );
Vector angles = pev->angles;
angles.x -= 90;
angles.y += 180;
Vector vecLaunchDir = angles;
vecLaunchDir.x += RANDOM_FLOAT( -20, 20 );
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;
}
//=========================================================
// Thinking begin
//=========================================================
void CSporeAmmo :: BornThink ( void )
{
StudioFrameAdvance();
pev->nextthink = gpGlobals->time + 0.1;
switch (GetActivity())
if ( m_flTimeSporeIdle > gpGlobals->time )
return;
pev->sequence = SPOREAMMO_SPAWNDOWN;
pev->framerate = 1.0;
pev->animtime = gpGlobals->time + 0.1;
pev->body = 1;
borntime = 0;
SetThink (&CSporeAmmo::IdleThink);
m_flTimeSporeIdle = gpGlobals->time + 16;
}
void CSporeAmmo :: IdleThink ( void )
{
pev->nextthink = gpGlobals->time + 0.1;
if ( m_flTimeSporeIdle > gpGlobals->time )
return;
if (borntime)
{
case ACT_CROUCH:
if (m_fSequenceFinished)
{
SetActivity(ACT_CROUCHIDLE);
}
break;
pev->sequence = SPOREAMMO_IDLE;
case ACT_CROUCHIDLE:
if (gpGlobals->time > pev->dmgtime)
{
SetActivity(ACT_STAND);
}
break;
case ACT_STAND:
if (m_fSequenceFinished)
SetActivity(ACT_IDLE);
break;
case ACT_IDLE:
default:
break;
m_flTimeSporeIdle = gpGlobals->time + 10;
SetThink(&CSporeAmmo::BornThink);
return;
}
else
{
pev->sequence = SPOREAMMO_IDLE1;
}
}
void CSporeFruit::Touch(CBaseEntity *pOther)
void CSporeAmmo :: AmmoTouch ( CBaseEntity *pOther )
{
if (pOther->IsPlayer())
if ( !pOther->IsPlayer() )
return;
if (borntime)
return;
int bResult = (pOther->GiveAmmo( AMMO_SPORE_GIVE, "spores", SPORE_MAX_CARRY ) != -1);
if (bResult)
{
if (GetActivity() == ACT_IDLE || GetActivity() == ACT_STAND)
{
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);
}
}
}

View File

@ -27,33 +27,31 @@
#include "sporegrenade.h"
#include "gearbox_weapons.h"
LINK_ENTITY_TO_CLASS(monster_spore, CSporeGrenade);
LINK_ENTITY_TO_CLASS(spore, CSporeGrenade)
TYPEDESCRIPTION CSporeGrenade::m_SaveData[] =
{
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;
void CSporeGrenade::Precache(void)
{
PRECACHE_MODEL("models/spore.mdl");
PRECACHE_MODEL("sprites/glow02.spr");
g_sModelIndexTinySpit = PRECACHE_MODEL("sprites/tinyspit.spr");
gSporeExplode = PRECACHE_MODEL ("sprites/spore_exp_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, int bitsDamageType)
void CSporeGrenade::Explode(TraceResult *pTrace)
{
//float flRndSound;// sound randomizer
pev->model = iStringNull;//invisible
pev->solid = SOLID_NOT;// intangible
pev->takedamage = DAMAGE_NO;
// Pull out of the wall a bit
@ -93,6 +91,19 @@ void CSporeGrenade::Explode(TraceResult *pTrace, int bitsDamageType)
WRITE_BYTE( 155 ); // framerate
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.
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
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.
#if FEATURE_OPFOR_DECALS
UTIL_DecalTrace(pTrace, DECAL_SPR_SPLT1 + RANDOM_LONG(0, 2));
#else
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);
}
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)
{
TraceResult tr;
Vector vecSpot;// trace starts here!
vecSpot = pev->origin + Vector(0, 0, 8);
Vector vecSpot = pev->origin + Vector(0, 0, 8);
UTIL_TraceLine(vecSpot, vecSpot + Vector(0, 0, -40), ignore_monsters, ENT(pev), &tr);
Explode(&tr, DMG_BLAST);
Explode(&tr);
}
void CSporeGrenade::BounceSound(void)
{
switch (RANDOM_LONG(0, 2))
{
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;
}
DangerSound();
EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/splauncher_bounce.wav", 0.25, ATTN_NORM);
}
void CSporeGrenade::DangerSound()
{
CSoundEnt::InsertSound(bits_SOUND_DANGER, pev->origin + pev->velocity * 0.5, pev->velocity.Length(), 0.2);
}
void CSporeGrenade::TumbleThink(void)
@ -181,7 +157,6 @@ void CSporeGrenade::TumbleThink(void)
return;
}
StudioFrameAdvance();
pev->nextthink = gpGlobals->time + 0.1;
if (pev->dmgtime - 1 < gpGlobals->time)
@ -193,25 +168,20 @@ void CSporeGrenade::TumbleThink(void)
{
SetThink(&CSporeGrenade::Detonate);
}
if (pev->waterlevel != 0)
{
pev->velocity = pev->velocity * 0.5;
pev->framerate = 0.2;
}
// Spawn particles.
SpawnTrailParticles(
pev->origin, // position
-pev->velocity.Normalize(), // dir
g_sModelIndexTinySpit, // modelindex
RANDOM_LONG( 5, 10 ), // count
RANDOM_LONG( 2, 4 ), // count
RANDOM_FLOAT(10, 15), // speed
RANDOM_FLOAT(2, 3) * 100); // noise ( client will divide by 100 )
}
//
// Contact grenade, explode when it touches something
//
//
void CSporeGrenade::ExplodeTouch(CBaseEntity *pOther)
{
TraceResult tr;
@ -222,11 +192,9 @@ void CSporeGrenade::ExplodeTouch(CBaseEntity *pOther)
vecSpot = pev->origin - pev->velocity.Normalize() * 32;
UTIL_TraceLine(vecSpot, vecSpot + pev->velocity.Normalize() * 64, ignore_monsters, ENT(pev), &tr);
Explode(&tr, DMG_BLAST);
Explode(&tr);
}
void CSporeGrenade::DangerSoundThink(void)
{
if (!IsInWorld())
@ -235,127 +203,57 @@ void CSporeGrenade::DangerSoundThink(void)
return;
}
CSoundEnt::InsertSound(bits_SOUND_DANGER, pev->origin + pev->velocity * 0.5, pev->velocity.Length(), 0.2);
DangerSound();
pev->nextthink = gpGlobals->time + 0.2;
if (pev->waterlevel != 0)
{
pev->velocity = pev->velocity * 0.5;
}
// Spawn particles.
SpawnTrailParticles(
pev->origin, // position
-pev->velocity.Normalize(), // dir
g_sModelIndexTinySpit, // modelindex
RANDOM_LONG(5, 10), // count
RANDOM_LONG( 5, 10), // count
RANDOM_FLOAT(10, 15), // speed
RANDOM_FLOAT(2, 3) * 100); // noise ( client will divide by 100 )
}
void CSporeGrenade::BounceTouch(CBaseEntity *pOther)
{
#if 0
// 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)
if ( !pOther->pev->takedamage )
{
entvars_t *pevOwner = VARS(pev->owner);
if (pevOwner)
{
TraceResult tr = UTIL_GetGlobalTrace();
ClearMultiDamage();
pOther->TraceAttack(pevOwner, 1, gpGlobals->v_forward, &tr, DMG_CLUB);
ApplyMultiDamage(pev, pevOwner);
if (!(pev->flags & FL_ONGROUND)) {
if (pev->dmg_save < gpGlobals->time) {
BounceSound();
pev->dmg_save = gpGlobals->time + 0.1;
}
} else {
pev->velocity = pev->velocity * 0.9;
}
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();
}
pev->framerate = pev->velocity.Length() / 200.0;
if (pev->framerate > 1.0)
pev->framerate = 1;
else if (pev->framerate < 0.5)
pev->framerate = 0;
}
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)
if (pev->flags & FL_SWIM)
{
// maintain sliding sound
pev->velocity = pev->velocity * 0.5;
}
}
else
{
BounceSound();
TraceResult tr = UTIL_GetGlobalTrace();
Explode(&tr);
}
}
void CSporeGrenade::Spawn(void)
{
Precache();
pev->classname = MAKE_STRING("spore");
pev->movetype = MOVETYPE_BOUNCE;
pev->solid = SOLID_BBOX;
SET_MODEL(ENT(pev), "models/spore.mdl");
UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0));
pev->gravity = 0.5; // 0.5
pev->friction = 0.2; // 0.8
//pev->gravity = 0.5;
pev->dmg = gSkillData.plrDmgSpore;
m_fRegisteredSound = FALSE;
m_flNextSpriteTrailSpawn = gpGlobals->time;
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);
pGrenade->Spawn();
UTIL_SetOrigin(pGrenade->pev, vecStart);
pGrenade->Spawn();
pGrenade->pev->velocity = vecVelocity;
pGrenade->pev->angles = UTIL_VecToAngles(pGrenade->pev->velocity);
pGrenade->pev->owner = ENT(pevOwner);
pGrenade->SetTouch(&CSporeGrenade::BounceTouch); // Bounce if touched
// Take one second off of the desired detonation time and set the think to PreDetonate. PreDetonate
// will insert a DANGER sound into the world sound list and delay detonation for one second so that
// the grenade explodes after the exact amount of time specified in the call to ShootTimed().
pGrenade->pev->dmgtime = gpGlobals->time + time;
float lifetime = 2.0;
if (ai) {
lifetime = 4.0;
pGrenade->pev->gravity = 0.5;
pGrenade->pev->friction = 0.9;
}
pGrenade->pev->dmgtime = gpGlobals->time + lifetime;
pGrenade->SetThink(&CSporeGrenade::TumbleThink);
pGrenade->pev->nextthink = gpGlobals->time + 0.1;
if (time < 0.1)
if (lifetime < 0.1)
{
pGrenade->pev->nextthink = gpGlobals->time;
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;
}
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);
UTIL_SetOrigin(pGrenade->pev, vecStart);
pGrenade->Spawn();
pGrenade->pev->movetype = MOVETYPE_FLY;
UTIL_SetOrigin(pGrenade->pev, vecStart);
pGrenade->pev->velocity = vecVelocity;
pGrenade->pev->angles = UTIL_VecToAngles(pGrenade->pev->velocity);
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->pev->nextthink = gpGlobals->time;
// Tumble in air
// Explode on contact
pGrenade->SetTouch(&CSporeGrenade::ExplodeTouch);
pGrenade->pev->dmg = gSkillData.plrDmgSpore;
pGrenade->pev->gravity = 0.5;
pGrenade->pev->friction = 0.7;
return pGrenade;
}
@ -464,3 +351,13 @@ void CSporeGrenade::SpawnExplosionParticles(const Vector& origin, const Vector&
WRITE_BYTE(noise); // noise ( client will divide by 100 )
MESSAGE_END();
}
void CSporeGrenade::UpdateOnRemove()
{
CBaseMonster::UpdateOnRemove();
if (m_pSporeGlow)
{
UTIL_Remove(m_pSporeGlow);
m_pSporeGlow = NULL;
}
}

View File

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

View File

@ -21,8 +21,9 @@
#include "nodes.h"
#include "player.h"
#include "gamerules.h"
#include "xen.h"
#ifndef CLIENT_DLL
#include "sporegrenade.h"
#endif
// special deathmatch shotgun spreads
#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
};
LINK_ENTITY_TO_CLASS(weapon_sporelauncher, CSporelauncher);
LINK_ENTITY_TO_CLASS(weapon_sporelauncher, CSporelauncher)
void CSporelauncher::Spawn()
{
@ -71,7 +72,7 @@ void CSporelauncher::Precache(void)
PRECACHE_MODEL("sprites/bigspit.spr");
m_iSquidSpitSprite = PRECACHE_MODEL("sprites/tinyspit.spr");
UTIL_PrecacheOther("monster_spore");
UTIL_PrecacheOther("spore");
m_usSporeFire = PRECACHE_EVENT(1, "events/spore.sc");
}
@ -92,7 +93,7 @@ int CSporelauncher::AddToPlayer(CBasePlayer *pPlayer)
int CSporelauncher::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = "Spores";
p->pszAmmo1 = "spores";
p->iMaxAmmo1 = SPORE_MAX_CARRY;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
@ -115,21 +116,8 @@ BOOL CSporelauncher::Deploy()
void CSporelauncher::PrimaryAttack()
{
// don't fire underwater
if (m_pPlayer->pev->waterlevel == 3)
{
PlayEmptySound();
m_flNextPrimaryAttack = GetNextAttackDelay(0.15);
return;
}
if (m_iClip <= 0)
{
Reload();
if (m_iClip == 0)
PlayEmptySound();
return;
}
m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;
@ -145,38 +133,26 @@ void CSporelauncher::PrimaryAttack()
// m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH;
Vector vecSrc = m_pPlayer->GetGunPosition();
Vector vecAiming = m_pPlayer->GetAutoaimVector(AUTOAIM_5DEGREES);
Vector vecDir;
Vector vecVel;
UTIL_MakeVectors(m_pPlayer->pev->v_angle);
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;
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
UTIL_MakeVectors( m_pPlayer->pev->v_angle );
Vector vecSrc = m_pPlayer->GetGunPosition( ) + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -8;
#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
PLAYBACK_EVENT_FULL(
flags,
m_pPlayer->edict(),
m_usSporeFire,
0.0,
(float *)&g_vecZero,
(float *)&g_vecZero,
vecDir.x,
vecDir.y,
*(int*)&vecDir.z,
m_iSquidSpitSprite,
m_pPlayer->edict(),
m_usSporeFire,
0.0,
(float *)&g_vecZero,
(float *)&g_vecZero,
vecSrc.x,
vecSrc.y,
*(int*)&vecSrc.z,
m_iSquidSpitSprite,
0,
TRUE);
@ -202,20 +178,8 @@ void CSporelauncher::PrimaryAttack()
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)
{
Reload();
PlayEmptySound();
return;
}
m_pPlayer->m_iWeaponVolume = LOUD_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;
@ -230,43 +194,30 @@ void CSporelauncher::SecondaryAttack(void)
flags = 0;
#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
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);
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;
UTIL_MakeVectors( m_pPlayer->pev->v_angle );
Vector vecSrc = m_pPlayer->GetGunPosition( ) + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -8;
#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
PLAYBACK_EVENT_FULL(
flags,
flags,
m_pPlayer->edict(),
m_usSporeFire,
0.0,
m_usSporeFire,
0.0,
(float *)&g_vecZero,
(float *)&g_vecZero,
vecDir.x,
vecDir.y,
*(int*)&vecDir.z,
vecSrc.x,
vecSrc.y,
*(int*)&vecSrc.z,
m_iSquidSpitSprite,
0,
0,
0);
if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
@ -366,45 +317,23 @@ void CSporelauncher::WeaponIdle(void)
{
int iAnim;
float flRand = UTIL_SharedRandomFloat(m_pPlayer->random_seed, 0, 1);
if (flRand <= 0.5)
if (flRand <= 0.4)
{
iAnim = SPLAUNCHER_IDLE;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.0f;
}
else
else if (flRand <= 0.8)
{
iAnim = SPLAUNCHER_IDLE2;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 4.0f;
}
else
{
iAnim = SPLAUNCHER_FIDGET;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 4.0f;
}
SendWeaponAnim(iAnim);
}
}
}
class CSporeAmmo : public CBasePlayerAmmo
{
void Spawn(void)
{
Precache();
SET_MODEL(ENT(pev), "models/spore.mdl");
CBasePlayerAmmo::Spawn();
}
void Precache(void)
{
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);

View File

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