Portable Half-Life SDK. GoldSource and Xash3D. Crossplatform.
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

/***
*
* 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;
}
}