Make spore behavior match original. Remove redundant declarations (#229)

This commit is contained in:
Roman Chistokhodov 2021-12-11 05:32:19 +03:00 committed by GitHub
parent 31f428b299
commit 310493aaeb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 360 additions and 440 deletions

View File

@ -18,6 +18,10 @@
#include "cbase.h"
#include "monsters.h"
#include "effects.h"
#include "weapons.h"
#include "displacerball.h"
#include "shock.h"
#include "sporegrenade.h"
//=========================================================
// CPitwormGibShooter
@ -176,10 +180,6 @@ void CPitwormGibShooter::ShootThink()
pev->nextthink = gpGlobals->time + 0.1;
}
#include "displacerball.h"
#include "shock.h"
#include "sporegrenade.h"
enum
{
BLOWERCANNON_SPOREROCKET = 1,
@ -298,10 +298,10 @@ void CBlowerCannon::BlowerCannonThink( void )
switch (m_iWeapType)
{
case BLOWERCANNON_SPOREROCKET:
CSporeGrenade::ShootContact(pev, pev->origin, gpGlobals->v_forward * 1500);
CSpore::CreateSpore(pev->origin, angles, this, CSpore::ROCKET, false, false);
break;
case BLOWERCANNON_SPOREGRENADE:
CSporeGrenade::ShootTimed(pev, pev->origin, gpGlobals->v_forward * 700, false);
CSpore::CreateSpore(pev->origin, angles, this, CSpore::GRENADE, false, false);
break;
case BLOWERCANNON_SHOCKBEAM:
CShock::Shoot(pev, pev->angles, pev->origin, gpGlobals->v_forward * 2000);

View File

@ -1,26 +0,0 @@
/***
*
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
#ifndef GEARBOX_WEAPONS_H
#define GEARBOX_WEAPONS_H
extern DLL_GLOBAL short g_sModelIndexSpore1;
extern DLL_GLOBAL short g_sModelIndexSpore2;
extern DLL_GLOBAL short g_sModelIndexSpore3;
extern DLL_GLOBAL short g_sModelIndexBigSpit;
extern DLL_GLOBAL short g_sModelIndexTinySpit;
#endif // GEARBOX_WEAPONS_H

View File

@ -28,20 +28,13 @@ class CSporeAmmo : public CBaseEntity
public:
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 );
int Save( CSave &save );
int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
virtual int SizeForGrapple() { return GRAPPLE_FIXED; }
int m_iExplode;
BOOL borntime;
float m_flTimeSporeIdle;
};
@ -58,13 +51,6 @@ typedef enum
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 )
void CSporeAmmo :: Precache( void )
{
PRECACHE_MODEL("models/spore_ammo.mdl");
@ -83,23 +69,22 @@ void CSporeAmmo :: Spawn( void )
pev->takedamage = DAMAGE_YES;
pev->solid = SOLID_BBOX;
pev->movetype = MOVETYPE_NONE;
pev->framerate = 1.0;
pev->animtime = gpGlobals->time + 0.1;
pev->framerate = 1.0f;
pev->health = 1.0f;
pev->animtime = gpGlobals->time;
pev->sequence = SPOREAMMO_IDLE1;
pev->sequence = SPOREAMMO_SPAWNDOWN;
pev->body = 1;
Vector vecOrigin = pev->origin;
vecOrigin.z += 16;
UTIL_SetOrigin( pev, vecOrigin );
pev->origin.z += 16;
UTIL_SetOrigin( pev, pev->origin );
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 + 4;
}
//=========================================================
@ -107,7 +92,7 @@ void CSporeAmmo :: Spawn( void )
//=========================================================
int CSporeAmmo::TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType )
{
if (!borntime) // rigth '!borntime' // blast in anytime 'borntime || !borntime'
if (pev->body != 0)
{
Vector vecSrc = pev->origin + gpGlobals->v_forward * -32;
@ -135,68 +120,57 @@ int CSporeAmmo::TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, flo
vecLaunchDir.y += RANDOM_FLOAT( -20, 20 );
vecLaunchDir.z += RANDOM_FLOAT( -20, 20 );
CSpore* pSpore = CSpore::CreateSpore(pev->origin, vecLaunchDir, this, CSpore::GRENADE, false, true);
UTIL_MakeVectors( vecLaunchDir );
CSporeGrenade::ShootTimed(pevAttacker, vecSrc, gpGlobals->v_forward * 800, false);
pSpore->pev->velocity = gpGlobals->v_forward * 800;
pev->framerate = 1.0;
pev->frame = 0;
pev->animtime = gpGlobals->time + 0.1;
pev->sequence = SPOREAMMO_SNATCHDOWN;
pev->body = 0;
borntime = 1;
m_flTimeSporeIdle = gpGlobals->time + 1;
pev->nextthink = gpGlobals->time + 0.66f;
SetThink (&CSporeAmmo::IdleThink);
return 1;
}
return 0;
}
//=========================================================
// Thinking begin
//=========================================================
void CSporeAmmo :: BornThink ( void )
{
pev->nextthink = gpGlobals->time + 0.1;
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)
switch (pev->sequence)
{
pev->sequence = SPOREAMMO_IDLE;
m_flTimeSporeIdle = gpGlobals->time + 10;
SetThink(&CSporeAmmo::BornThink);
return;
}
else
case SPOREAMMO_SPAWNDOWN:
{
pev->sequence = SPOREAMMO_IDLE1;
pev->animtime = gpGlobals->time;
pev->frame = 0;
break;
}
case SPOREAMMO_SNATCHDOWN:
{
pev->sequence = SPOREAMMO_IDLE;
pev->animtime = gpGlobals->time;
pev->frame = 0;
pev->nextthink = gpGlobals->time + 10.0f;
break;
}
case SPOREAMMO_IDLE:
{
pev->body = 1;
pev->sequence = SPOREAMMO_SPAWNDOWN;
pev->animtime = gpGlobals->time;
pev->frame = 0;
pev->nextthink = gpGlobals->time + 4.0f;
break;
}
default:
break;
}
}
void CSporeAmmo :: AmmoTouch ( CBaseEntity *pOther )
{
if ( !pOther->IsPlayer() )
return;
if (borntime)
if ( !pOther->IsPlayer() || pev->body == 0 )
return;
int bResult = (pOther->GiveAmmo( AMMO_SPORE_GIVE, "spores", SPORE_MAX_CARRY ) != -1);
@ -204,12 +178,10 @@ void CSporeAmmo :: AmmoTouch ( CBaseEntity *pOther )
{
EMIT_SOUND(ENT(pev), CHAN_ITEM, "weapons/spore_ammo.wav", 1, ATTN_NORM);
pev->framerate = 1.0;
pev->animtime = gpGlobals->time + 0.1;
pev->frame = 0;
pev->animtime = gpGlobals->time;
pev->sequence = SPOREAMMO_SNATCHDOWN;
pev->body = 0;
borntime = 1;
m_flTimeSporeIdle = gpGlobals->time + 1;
SetThink (&CSporeAmmo::IdleThink);
pev->nextthink = gpGlobals->time + 0.66f;
}
}

View File

@ -25,335 +25,301 @@
#include "gamerules.h"
#include "decals.h"
#include "sporegrenade.h"
#include "gearbox_weapons.h"
LINK_ENTITY_TO_CLASS(spore, CSporeGrenade)
LINK_ENTITY_TO_CLASS(spore, CSpore)
TYPEDESCRIPTION CSporeGrenade::m_SaveData[] =
TYPEDESCRIPTION CSpore::m_SaveData[] =
{
DEFINE_FIELD(CSporeGrenade, m_pSporeGlow, FIELD_CLASSPTR),
DEFINE_FIELD(CSpore, m_SporeType, FIELD_INTEGER),
DEFINE_FIELD(CSpore, m_flIgniteTime, FIELD_TIME),
DEFINE_FIELD(CSpore, m_bIsAI, FIELD_BOOLEAN),
DEFINE_FIELD(CSpore, m_hSprite, FIELD_EHANDLE)
};
IMPLEMENT_SAVERESTORE(CSporeGrenade, CBaseMonster)
IMPLEMENT_SAVERESTORE(CSpore, CGrenade)
int gSporeExplode, gSporeExplodeC;
void CSporeGrenade::Precache(void)
void CSpore::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_MODEL("sprites/glow01.spr");
m_iBlow = PRECACHE_MODEL("sprites/spore_exp_01.spr");
m_iBlowSmall = PRECACHE_MODEL("sprites/spore_exp_c_01.spr");
m_iSpitSprite = m_iTrail = PRECACHE_MODEL("sprites/tinyspit.spr");
PRECACHE_SOUND("weapons/splauncher_bounce.wav");
PRECACHE_SOUND("weapons/splauncher_impact.wav");
}
void CSporeGrenade::Explode(TraceResult *pTrace)
{
pev->solid = SOLID_NOT;// intangible
pev->takedamage = DAMAGE_NO;
// Pull out of the wall a bit
if (pTrace->flFraction != 1.0)
{
pev->origin = pTrace->vecEndPos + (pTrace->vecPlaneNormal * (pev->dmg - 24) * 0.6);
}
Vector vecSpraySpot = pTrace->vecEndPos;
float flSpraySpeed = RANDOM_LONG(10, 15);
// If the trace is pointing up, then place
// spawn position a few units higher.
if (pTrace->vecPlaneNormal.z > 0)
{
vecSpraySpot = vecSpraySpot + (pTrace->vecPlaneNormal * 8);
flSpraySpeed *= 2; // Double the speed to make them fly higher
// in the air.
}
// Spawn small particles at the explosion origin.
SpawnExplosionParticles(
vecSpraySpot, // position
pTrace->vecPlaneNormal, // direction
g_sModelIndexTinySpit, // modelindex
RANDOM_LONG(40, 50), // count
flSpraySpeed, // speed
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();
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);
CSoundEnt::InsertSound(bits_SOUND_COMBAT, pev->origin, NORMAL_EXPLOSION_VOLUME, 3.0);
entvars_t *pevOwner;
if (pev->owner)
pevOwner = VARS(pev->owner);
else
pevOwner = NULL;
pev->owner = NULL; // can't traceline attack owner if this is set
RadiusDamage(pev, pevOwner, pev->dmg, CLASS_NONE, DMG_BLAST);
// Place a decal on the surface that was hit.
UTIL_DecalTrace(pTrace, DECAL_SPR_SPLT1 + RANDOM_LONG(0, 2));
UTIL_Remove(this);
}
void CSporeGrenade::Detonate(void)
{
TraceResult tr;
Vector vecSpot = pev->origin + Vector(0, 0, 8);
UTIL_TraceLine(vecSpot, vecSpot + Vector(0, 0, -40), ignore_monsters, ENT(pev), &tr);
Explode(&tr);
}
void CSporeGrenade::BounceSound(void)
{
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)
{
if (!IsInWorld())
{
UTIL_Remove(this);
return;
}
pev->nextthink = gpGlobals->time + 0.1;
if (pev->dmgtime - 1 < gpGlobals->time)
{
CSoundEnt::InsertSound(bits_SOUND_DANGER, pev->origin + pev->velocity * (pev->dmgtime - gpGlobals->time), 400, 0.1);
}
if (pev->dmgtime <= gpGlobals->time)
{
SetThink(&CSporeGrenade::Detonate);
}
// Spawn particles.
SpawnTrailParticles(
pev->origin, // position
-pev->velocity.Normalize(), // dir
g_sModelIndexTinySpit, // modelindex
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;
Vector vecSpot;// trace starts here!
pev->enemy = pOther->edict();
vecSpot = pev->origin - pev->velocity.Normalize() * 32;
UTIL_TraceLine(vecSpot, vecSpot + pev->velocity.Normalize() * 64, ignore_monsters, ENT(pev), &tr);
Explode(&tr);
}
void CSporeGrenade::DangerSoundThink(void)
{
if (!IsInWorld())
{
UTIL_Remove(this);
return;
}
DangerSound();
pev->nextthink = gpGlobals->time + 0.2;
// Spawn particles.
SpawnTrailParticles(
pev->origin, // position
-pev->velocity.Normalize(), // dir
g_sModelIndexTinySpit, // modelindex
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 ( !pOther->pev->takedamage )
{
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;
}
if (pev->flags & FL_SWIM)
{
pev->velocity = pev->velocity * 0.5;
}
}
else
{
TraceResult tr = UTIL_GetGlobalTrace();
Explode(&tr);
}
}
void CSporeGrenade::Spawn(void)
void CSpore::Spawn()
{
Precache();
pev->classname = MAKE_STRING("spore");
pev->movetype = MOVETYPE_BOUNCE;
if (m_SporeType == GRENADE)
pev->movetype = MOVETYPE_BOUNCE;
else
pev->movetype = MOVETYPE_FLY;
pev->solid = SOLID_BBOX;
SET_MODEL(ENT(pev), "models/spore.mdl");
UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0));
SET_MODEL(edict(), "models/spore.mdl");
//pev->gravity = 0.5;
UTIL_SetSize(pev, g_vecZero, g_vecZero);
UTIL_SetOrigin(pev, pev->origin);
SetThink(&CSpore::FlyThink);
if (m_SporeType == GRENADE)
{
SetTouch(&CSpore::MyBounceTouch);
if (!m_bPuked)
{
pev->angles.x -= RANDOM_LONG(-5, 5) + 30;
}
}
else
{
SetTouch(&CSpore::RocketTouch);
}
UTIL_MakeVectors(pev->angles);
if (!m_bIsAI)
{
if (m_SporeType != GRENADE)
{
pev->velocity = gpGlobals->v_forward * 1200;
}
pev->gravity = 1;
}
else
{
pev->gravity = 0.5;
pev->friction = 0.7;
}
pev->dmg = gSkillData.plrDmgSpore;
m_pSporeGlow = CSprite::SpriteCreate("sprites/glow02.spr", pev->origin, FALSE);
m_flIgniteTime = gpGlobals->time;
if (m_pSporeGlow)
pev->nextthink = gpGlobals->time + 0.01;
CSprite* sprite = CSprite::SpriteCreate("sprites/glow01.spr", pev->origin, false);
if (sprite) {
sprite->SetTransparency(kRenderTransAdd, 180, 180, 40, 100, kRenderFxDistort);
sprite->SetScale(0.8);
sprite->SetAttachment(edict(), 0);
m_hSprite = sprite;
}
m_fRegisteredSound = false;
m_flSoundDelay = gpGlobals->time;
}
void CSpore::BounceSound()
{
//Nothing
}
void CSpore::IgniteThink()
{
SetThink(NULL);
SetTouch(NULL);
if (m_hSprite)
{
m_pSporeGlow->SetTransparency(kRenderGlow, 150, 158, 19, 155, kRenderFxNoDissipation);
m_pSporeGlow->SetAttachment(edict(), 0);
m_pSporeGlow->SetScale(.75f);
}
}
CBaseEntity* CSporeGrenade::ShootTimed(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, bool ai)
{
CSporeGrenade *pGrenade = GetClassPtr((CSporeGrenade *)NULL);
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
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 (lifetime < 0.1)
{
pGrenade->pev->nextthink = gpGlobals->time;
pGrenade->pev->velocity = Vector(0, 0, 0);
UTIL_Remove(m_hSprite);
m_hSprite = 0;
}
return pGrenade;
}
EMIT_SOUND(edict(), CHAN_WEAPON, "weapons/splauncher_impact.wav", VOL_NORM, ATTN_NORM);
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;
pGrenade->pev->velocity = vecVelocity;
pGrenade->pev->angles = UTIL_VecToAngles(pGrenade->pev->velocity);
pGrenade->pev->owner = ENT(pevOwner);
const Vector vecDir = pev->velocity.Normalize();
// make monsters afraid of it while in the air
pGrenade->SetThink(&CSporeGrenade::DangerSoundThink);
pGrenade->pev->nextthink = gpGlobals->time;
TraceResult tr;
// Explode on contact
pGrenade->SetTouch(&CSporeGrenade::ExplodeTouch);
UTIL_TraceLine(
pev->origin, pev->origin + vecDir * (m_SporeType == GRENADE ? 64 : 32),
dont_ignore_monsters, edict(), &tr);
pGrenade->pev->gravity = 0.5;
pGrenade->pev->friction = 0.7;
UTIL_DecalTrace(&tr, DECAL_SPR_SPLT1 + RANDOM_LONG(0, 2));
return pGrenade;
}
void CSporeGrenade::SpawnTrailParticles(const Vector& origin, const Vector& direction, int modelindex, int count, float speed, float noise)
{
MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, origin);
MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin);
WRITE_BYTE(TE_SPRITE_SPRAY);
WRITE_COORD(origin.x); // pos
WRITE_COORD(origin.y);
WRITE_COORD(origin.z);
WRITE_COORD(direction.x); // dir
WRITE_COORD(direction.y);
WRITE_COORD(direction.z);
WRITE_SHORT(modelindex); // model
WRITE_BYTE(count); // count
WRITE_BYTE(speed); // speed
WRITE_BYTE(noise); // noise ( client will divide by 100 )
WRITE_COORD( pev->origin.x );
WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z );
WRITE_COORD( tr.vecPlaneNormal.x );
WRITE_COORD( tr.vecPlaneNormal.y );
WRITE_COORD( tr.vecPlaneNormal.z );
WRITE_SHORT(m_iSpitSprite);
WRITE_BYTE(100);
WRITE_BYTE(40);
WRITE_BYTE(180);
MESSAGE_END();
MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin);
WRITE_BYTE(TE_DLIGHT);
WRITE_COORD( pev->origin.x );
WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z );
WRITE_BYTE(10);
WRITE_BYTE(15);
WRITE_BYTE(220);
WRITE_BYTE(40);
WRITE_BYTE(5);
WRITE_BYTE(10);
MESSAGE_END();
MESSAGE_BEGIN(MSG_PVS, 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) ? m_iBlow : m_iBlowSmall);
WRITE_BYTE(20);
WRITE_BYTE(128);
MESSAGE_END();
MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin);
WRITE_BYTE(TE_SPRITE_SPRAY);
WRITE_COORD( pev->origin.x );
WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z );
WRITE_COORD(RANDOM_FLOAT(-1, 1));
WRITE_COORD(1);
WRITE_COORD(RANDOM_FLOAT(-1, 1));
WRITE_SHORT(m_iTrail);
WRITE_BYTE(2);
WRITE_BYTE(20);
WRITE_BYTE(80);
MESSAGE_END();
::RadiusDamage(pev->origin, pev, VARS(pev->owner), pev->dmg, 200, CLASS_NONE, DMG_ALWAYSGIB | DMG_BLAST);
SetThink(&CSpore::SUB_Remove);
pev->nextthink = gpGlobals->time;
}
void CSporeGrenade::SpawnExplosionParticles(const Vector& origin, const Vector& direction, int modelindex, int count, float speed, float noise)
void CSpore::FlyThink()
{
const float flDelay = m_bIsAI ? 4.0 : 2.0;
MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, origin);
WRITE_BYTE(TE_SPRITE_SPRAY);
WRITE_COORD(origin.x); // pos
WRITE_COORD(origin.y);
WRITE_COORD(origin.z);
WRITE_COORD(direction.x); // dir
WRITE_COORD(direction.y);
WRITE_COORD(direction.z);
WRITE_SHORT(modelindex); // model
WRITE_BYTE(count); // count
WRITE_BYTE(speed); // speed
WRITE_BYTE(noise); // noise ( client will divide by 100 )
MESSAGE_END();
}
void CSporeGrenade::UpdateOnRemove()
{
CBaseMonster::UpdateOnRemove();
if (m_pSporeGlow)
if (m_SporeType != GRENADE || (gpGlobals->time <= m_flIgniteTime + flDelay))
{
UTIL_Remove(m_pSporeGlow);
m_pSporeGlow = NULL;
Vector velocity = pev->velocity.Normalize();
MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin);
WRITE_BYTE(TE_SPRITE_SPRAY);
WRITE_COORD( pev->origin.x );
WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z );
WRITE_COORD( velocity.x );
WRITE_COORD( velocity.y );
WRITE_COORD( velocity.z );
WRITE_SHORT(m_iTrail);
WRITE_BYTE(2);
WRITE_BYTE(20);
WRITE_BYTE(80);
MESSAGE_END();
}
else
{
SetThink(&CSpore::IgniteThink);
}
pev->nextthink = gpGlobals->time + 0.03;
}
void CSpore::GibThink()
{
//Nothing
}
void CSpore::RocketTouch(CBaseEntity* pOther)
{
if (pOther->pev->takedamage != DAMAGE_NO)
{
pOther->TakeDamage(pev, VARS(pev->owner), gSkillData.plrDmgSpore, DMG_GENERIC);
}
IgniteThink();
}
void CSpore::MyBounceTouch(CBaseEntity* pOther)
{
if (pOther->pev->takedamage == DAMAGE_NO)
{
if (pOther->edict() != pev->owner)
{
if (gpGlobals->time > m_flSoundDelay)
{
CSoundEnt::InsertSound(bits_SOUND_DANGER, pev->origin, (int)(pev->dmg * 2.5f), 0.3);
m_flSoundDelay = gpGlobals->time + 1.0;
}
if ((pev->flags & FL_ONGROUND) != 0)
{
pev->velocity = pev->velocity * 0.5;
}
else
{
EMIT_SOUND_DYN(edict(), CHAN_VOICE, "weapons/splauncher_bounce.wav", 0.25, ATTN_NORM, 0, PITCH_NORM);
}
}
}
else
{
pOther->TakeDamage(pev, VARS(pev->owner), gSkillData.plrDmgSpore, DMG_GENERIC);
IgniteThink();
}
}
CSpore* CSpore::CreateSpore(const Vector& vecOrigin, const Vector& vecAngles, CBaseEntity* pOwner, SporeType sporeType, bool bIsAI, bool bPuked)
{
CSpore* pSpore = GetClassPtr<CSpore>(NULL);
UTIL_SetOrigin(pSpore->pev, vecOrigin);
pSpore->m_SporeType = sporeType;
if (bIsAI)
{
pSpore->pev->velocity = vecAngles;
pSpore->pev->angles = UTIL_VecToAngles(vecAngles);
}
else
{
pSpore->pev->angles = vecAngles;
}
pSpore->m_bIsAI = bIsAI;
pSpore->m_bPuked = bPuked;
pSpore->Spawn();
pSpore->pev->owner = pOwner->edict();
pSpore->pev->classname = MAKE_STRING("spore");
return pSpore;
}
void CSpore::UpdateOnRemove()
{
CGrenade::UpdateOnRemove();
if (m_hSprite)
{
UTIL_Remove(m_hSprite);
m_hSprite = 0;
}
}

View File

@ -17,36 +17,54 @@
#define SPORE_GRENADE_H
// Contact/Timed spore grenade
class CSporeGrenade : public CBaseMonster
class CSpore : public CGrenade
{
public:
virtual int Save(CSave &save);
virtual int Restore(CRestore &restore);
enum SporeType
{
ROCKET = 1,
GRENADE = 2
};
static TYPEDESCRIPTION m_SaveData[];
public:
#ifndef CLIENT_DLL
int Save(CSave& save);
int Restore(CRestore& restore);
void Precache(void);
void Spawn(void);
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);
void EXPORT BounceTouch(CBaseEntity *pOther);
void EXPORT ExplodeTouch(CBaseEntity *pOther);
void EXPORT DangerSoundThink(void);
void EXPORT Detonate(void);
void EXPORT TumbleThink(void);
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);
static TYPEDESCRIPTION m_SaveData[];
#endif
void Precache();
void Spawn();
void UpdateOnRemove();
CSprite* m_pSporeGlow;
void BounceSound();
void EXPORT IgniteThink();
void EXPORT FlyThink();
void EXPORT GibThink();
void EXPORT RocketTouch(CBaseEntity* pOther);
void EXPORT MyBounceTouch(CBaseEntity* pOther);
static CSpore* CreateSpore(
const Vector& vecOrigin, const Vector& vecAngles, CBaseEntity* pOwner,
SporeType sporeType, bool bIsAI, bool bPuked);
private:
int m_iBlow;
int m_iBlowSmall;
int m_iSpitSprite;
int m_iTrail;
SporeType m_SporeType;
float m_flIgniteTime;
float m_flSoundDelay;
BOOL m_bIsAI;
EHANDLE m_hSprite;
BOOL m_bPuked;
};
#endif // SPORE_GRENADE_H

View File

@ -134,12 +134,16 @@ void CSporelauncher::PrimaryAttack()
// m_pPlayer->pev->effects = (int)(m_pPlayer->pev->effects) | EF_MUZZLEFLASH;
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
UTIL_MakeVectors( m_pPlayer->pev->v_angle );
Vector vecAngles = m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle;
UTIL_MakeVectors(vecAngles);
Vector vecSrc = m_pPlayer->GetGunPosition( ) + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -8;
#if !CLIENT_DLL
UTIL_MakeVectors( m_pPlayer->pev->v_angle );
CSporeGrenade::ShootContact( m_pPlayer->pev, vecSrc, gpGlobals->v_forward * 1500 );
CSpore* pSpore = CSpore::CreateSpore(vecSrc, vecAngles, m_pPlayer, CSpore::ROCKET, false, false);
UTIL_MakeVectors(vecAngles);
pSpore->pev->velocity = pSpore->pev->velocity + DotProduct(pSpore->pev->velocity, gpGlobals->v_forward) * gpGlobals->v_forward;
#endif
PLAYBACK_EVENT_FULL(
@ -198,12 +202,16 @@ void CSporelauncher::SecondaryAttack(void)
// player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
UTIL_MakeVectors( m_pPlayer->pev->v_angle );
Vector vecAngles = m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle;
UTIL_MakeVectors(vecAngles);
Vector vecSrc = m_pPlayer->GetGunPosition( ) + gpGlobals->v_forward * 16 + gpGlobals->v_right * 8 + gpGlobals->v_up * -8;
#if !CLIENT_DLL
UTIL_MakeVectors( m_pPlayer->pev->v_angle );
CSporeGrenade::ShootTimed(m_pPlayer->pev, vecSrc, gpGlobals->v_forward * 1000, false);
CSpore* pSpore = CSpore::CreateSpore( vecSrc, vecAngles, m_pPlayer, CSpore::GRENADE, false, false);
UTIL_MakeVectors(vecAngles);
pSpore->pev->velocity = m_pPlayer->pev->velocity + 800 * gpGlobals->v_forward;
#endif
PLAYBACK_EVENT_FULL(

View File

@ -313,7 +313,7 @@ void CStrooper::HandleAnimEvent(MonsterEvent_t *pEvent)
{
UTIL_MakeVectors(pev->angles);
// CGrenade::ShootTimed( pev, pev->origin + gpGlobals->v_forward * 34 + Vector (0, 0, 32), m_vecTossVelocity, 3.5 );
CSporeGrenade::ShootTimed(pev, pev->origin + Vector(0,0,98), m_vecTossVelocity, 3.5);
CSpore::CreateSpore(pev->origin + Vector(0, 0, 98), m_vecTossVelocity, this, CSpore::GRENADE, true, false);
m_fThrowGrenade = FALSE;
m_flNextGrenadeCheck = gpGlobals->time + 6;// wait six seconds before even looking again to see if a grenade can be thrown.

View File

@ -30,7 +30,6 @@
#include "soundent.h"
#include "decals.h"
#include "gamerules.h"
#include "gearbox_weapons.h"
extern CGraph WorldGraph;
extern int gEvilImpulse101;
@ -47,13 +46,6 @@ DLL_GLOBAL short g_sModelIndexBubbles;// holds the index for the bubbles model
DLL_GLOBAL short g_sModelIndexBloodDrop;// holds the sprite index for the initial blood
DLL_GLOBAL short g_sModelIndexBloodSpray;// holds the sprite index for splattered blood
DLL_GLOBAL short g_sModelIndexSpore1; // holds the index for the spore explosion 1
DLL_GLOBAL short g_sModelIndexSpore2; // holds the index for the spore explosion 2
DLL_GLOBAL short g_sModelIndexSpore3; // holds the index for the spore explosion 3
DLL_GLOBAL short g_sModelIndexBigSpit; // holds the index for the bullsquid big spit.
DLL_GLOBAL short g_sModelIndexTinySpit; // holds the index for the bullsquid tiny spit.
ItemInfo CBasePlayerItem::ItemInfoArray[MAX_WEAPONS];
AmmoInfo CBasePlayerItem::AmmoInfoArray[MAX_AMMO_SLOTS];
@ -418,13 +410,6 @@ void W_Precache( void )
// Used by spore grenades.
PRECACHE_MODEL( "models/spore.mdl" );
g_sModelIndexSpore1 = PRECACHE_MODEL( "sprites/spore_exp_01.spr" );
g_sModelIndexSpore2 = PRECACHE_MODEL( "sprites/spore_exp_b_01.spr" );
g_sModelIndexSpore3 = PRECACHE_MODEL( "sprites/spore_exp_c_01.spr" );
g_sModelIndexBigSpit = PRECACHE_MODEL( "sprites/bigspit.spr" );
g_sModelIndexTinySpit = PRECACHE_MODEL( "sprites/tinyspit.spr" );
PRECACHE_SOUND( "weapons/splauncher_impact.wav" );//explosion aftermaths
PRECACHE_SOUND( "weapons/spore_hit1.wav" );//sporegrenade

View File

@ -427,9 +427,6 @@ extern DLL_GLOBAL short g_sModelIndexSpore1;
extern DLL_GLOBAL short g_sModelIndexSpore2;
extern DLL_GLOBAL short g_sModelIndexSpore3;
extern DLL_GLOBAL short g_sModelIndexBigSpit;
extern DLL_GLOBAL short g_sModelIndexTinySpit;
extern void ClearMultiDamage(void);
extern void ApplyMultiDamage(entvars_t* pevInflictor, entvars_t* pevAttacker );
extern void AddMultiDamage( entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamage, int bitsDamageType);