You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
325 lines
6.8 KiB
325 lines
6.8 KiB
/*** |
|
* |
|
* 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. |
|
* |
|
****/ |
|
|
|
|
|
#include "extdll.h" |
|
#include "util.h" |
|
#include "cbase.h" |
|
#include "monsters.h" |
|
#include "weapons.h" |
|
#include "nodes.h" |
|
#include "player.h" |
|
#include "soundent.h" |
|
#include "gamerules.h" |
|
#include "decals.h" |
|
#include "sporegrenade.h" |
|
|
|
LINK_ENTITY_TO_CLASS(spore, CSpore) |
|
|
|
TYPEDESCRIPTION CSpore::m_SaveData[] = |
|
{ |
|
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(CSpore, CGrenade) |
|
|
|
int gSporeExplode, gSporeExplodeC; |
|
|
|
void CSpore::Precache(void) |
|
{ |
|
PRECACHE_MODEL("models/spore.mdl"); |
|
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 CSpore::Spawn() |
|
{ |
|
Precache(); |
|
|
|
if (m_SporeType == GRENADE) |
|
pev->movetype = MOVETYPE_BOUNCE; |
|
else |
|
pev->movetype = MOVETYPE_FLY; |
|
|
|
pev->solid = SOLID_BBOX; |
|
|
|
SET_MODEL(edict(), "models/spore.mdl"); |
|
|
|
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_flIgniteTime = gpGlobals->time; |
|
|
|
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) |
|
{ |
|
UTIL_Remove(m_hSprite); |
|
m_hSprite = 0; |
|
} |
|
|
|
EMIT_SOUND(edict(), CHAN_WEAPON, "weapons/splauncher_impact.wav", VOL_NORM, ATTN_NORM); |
|
|
|
const Vector vecDir = pev->velocity.Normalize(); |
|
|
|
TraceResult tr; |
|
|
|
UTIL_TraceLine( |
|
pev->origin, pev->origin + vecDir * (m_SporeType == GRENADE ? 64 : 32), |
|
dont_ignore_monsters, edict(), &tr); |
|
|
|
UTIL_DecalTrace(&tr, DECAL_SPR_SPLT1 + RANDOM_LONG(0, 2)); |
|
|
|
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( 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 CSpore::FlyThink() |
|
{ |
|
const float flDelay = m_bIsAI ? 4.0 : 2.0; |
|
|
|
if (m_SporeType != GRENADE || (gpGlobals->time <= m_flIgniteTime + flDelay)) |
|
{ |
|
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; |
|
} |
|
}
|
|
|