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.
227 lines
5.5 KiB
227 lines
5.5 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 "gamerules.h" |
|
#include "pipebomb.h" |
|
|
|
LINK_ENTITY_TO_CLASS(monster_pipebomb, CPipeBombGrenade); |
|
|
|
|
|
TYPEDESCRIPTION CPipeBombGrenade::m_SaveData[] = |
|
{ |
|
DEFINE_FIELD(CPipeBombGrenade, m_hOwner, FIELD_EHANDLE), |
|
DEFINE_FIELD(CPipeBombGrenade, m_thrownByPlayer, FIELD_INTEGER), |
|
}; |
|
|
|
IMPLEMENT_SAVERESTORE(CPipeBombGrenade, CGrenade); |
|
|
|
//========================================================= |
|
// Deactivate - do whatever it is we do to an orphaned |
|
// satchel when we don't want it in the world anymore. |
|
//========================================================= |
|
void CPipeBombGrenade::Deactivate(void) |
|
{ |
|
pev->solid = SOLID_NOT; |
|
UTIL_Remove(this); |
|
} |
|
|
|
|
|
void CPipeBombGrenade::Spawn(void) |
|
{ |
|
Precache(); |
|
// motor |
|
pev->movetype = MOVETYPE_BOUNCE; |
|
pev->solid = SOLID_BBOX; |
|
|
|
SET_MODEL(ENT(pev), "models/w_pipebomb.mdl"); |
|
//UTIL_SetSize(pev, Vector( -16, -16, -4), Vector(16, 16, 32)); // Old box -- size of headcrab monsters/players get blocked by this |
|
UTIL_SetSize(pev, Vector(-4, -4, -4), Vector(4, 4, 4)); // Uses point-sized, and can be stepped over |
|
UTIL_SetOrigin(pev, pev->origin); |
|
|
|
SetTouch(&CPipeBombGrenade::BombSlide); |
|
SetUse(&CPipeBombGrenade::DetonateUse); |
|
SetThink(&CPipeBombGrenade::BombThink); |
|
pev->nextthink = gpGlobals->time + 0.1; |
|
|
|
pev->gravity = 0.5; |
|
pev->friction = 0.8; |
|
|
|
pev->dmg = gSkillData.plrDmgSatchel; |
|
// ResetSequenceInfo( ); |
|
pev->sequence = 1; |
|
} |
|
|
|
|
|
void CPipeBombGrenade::BombSlide(CBaseEntity *pOther) |
|
{ |
|
entvars_t *pevOther = pOther->pev; |
|
|
|
// don't hit the guy that launched this grenade |
|
if (pOther->edict() == pev->owner) |
|
return; |
|
|
|
// pev->avelocity = Vector (300, 300, 300); |
|
pev->gravity = 1;// normal gravity now |
|
|
|
// HACKHACK - On ground isn't always set, so look for ground underneath |
|
TraceResult tr; |
|
UTIL_TraceLine(pev->origin, pev->origin - Vector(0, 0, 10), ignore_monsters, edict(), &tr); |
|
|
|
if (tr.flFraction < 1.0) |
|
{ |
|
// add a bit of static friction |
|
pev->velocity = pev->velocity * 0.95; |
|
pev->avelocity = pev->avelocity * 0.9; |
|
// play sliding sound, volume based on velocity |
|
} |
|
if (!(pev->flags & FL_ONGROUND) && pev->velocity.Length2D() > 10) |
|
{ |
|
BounceSound(); |
|
} |
|
StudioFrameAdvance(); |
|
} |
|
|
|
|
|
void CPipeBombGrenade::BombThink(void) |
|
{ |
|
StudioFrameAdvance(); |
|
pev->nextthink = gpGlobals->time + 0.1; |
|
|
|
if (!IsInWorld()) |
|
{ |
|
UTIL_Remove(this); |
|
return; |
|
} |
|
|
|
if (pev->waterlevel == 3) |
|
{ |
|
pev->movetype = MOVETYPE_FLY; |
|
pev->velocity = pev->velocity * 0.8; |
|
pev->avelocity = pev->avelocity * 0.9; |
|
pev->velocity.z += 8; |
|
} |
|
else if (pev->waterlevel == 0) |
|
{ |
|
pev->movetype = MOVETYPE_BOUNCE; |
|
} |
|
else |
|
{ |
|
pev->velocity.z -= 8; |
|
} |
|
if ((pev->flags & FL_ONGROUND) && pev->velocity.Length() <= 1) |
|
{ |
|
if (pev->owner != NULL) |
|
{ |
|
m_hOwner = CBaseEntity::Instance(pev->owner); |
|
pev->owner = NULL; |
|
} |
|
|
|
SetThink(NULL); |
|
SetTouch(&CPipeBombGrenade::PickupTouch); |
|
} |
|
} |
|
|
|
void CPipeBombGrenade::Precache(void) |
|
{ |
|
PRECACHE_MODEL("models/w_pipebomb.mdl"); |
|
PRECACHE_SOUND("weapons/pb_bounce1.wav"); |
|
PRECACHE_SOUND("weapons/pb_bounce2.wav"); |
|
PRECACHE_SOUND("weapons/pb_bounce3.wav"); |
|
} |
|
|
|
void CPipeBombGrenade::BounceSound(void) |
|
{ |
|
switch (RANDOM_LONG(0, 2)) |
|
{ |
|
case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/pb_bounce1.wav", 1, ATTN_NORM); break; |
|
case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/pb_bounce2.wav", 1, ATTN_NORM); break; |
|
case 2: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/pb_bounce3.wav", 1, ATTN_NORM); break; |
|
} |
|
} |
|
|
|
void CPipeBombGrenade::PickupTouch(CBaseEntity* pOther) |
|
{ |
|
if (pOther != m_hOwner || !pOther->IsPlayer()) |
|
return; |
|
|
|
CBasePlayer* pPlayer = (CBasePlayer*)pOther; |
|
|
|
|
|
CPipeBomb *pSatchel = (CPipeBomb*)Create("weapon_pipebomb", pPlayer->pev->origin, pPlayer->pev->angles); |
|
if (pSatchel) |
|
{ |
|
BOOL found = FALSE; |
|
CBasePlayerItem* pItem = NULL; |
|
for (int i = 0; i < MAX_ITEM_TYPES && !found; i++) |
|
{ |
|
pItem = pPlayer->m_rgpPlayerItems[i]; |
|
|
|
while (pItem) |
|
{ |
|
if (pItem->m_iId == WEAPON_PIPEBOMB) |
|
{ |
|
((CPipeBomb*)pItem)->m_chargeReady = 2; |
|
((CPipeBomb*)pItem)->WeaponIdle(); |
|
found = TRUE; |
|
break; |
|
} |
|
|
|
pItem = pItem->m_pNext; |
|
} |
|
} |
|
} |
|
|
|
SetThink(&CPipeBombGrenade::SUB_Remove); |
|
SetTouch(NULL); |
|
pev->nextthink = gpGlobals->time; |
|
|
|
//ALERT(at_console, "Pickup touch.\n"); |
|
} |
|
|
|
//========================================================= |
|
// DeactivateSatchels - removes all satchels owned by |
|
// the provided player. Should only be used upon death. |
|
// |
|
// Made this global on purpose. |
|
//========================================================= |
|
void DeactivatePipebombs(CBasePlayer *pOwner) |
|
{ |
|
edict_t *pFind; |
|
|
|
pFind = FIND_ENTITY_BY_CLASSNAME(NULL, "monster_pipebomb"); |
|
|
|
while (!FNullEnt(pFind)) |
|
{ |
|
CBaseEntity *pEnt = CBaseEntity::Instance(pFind); |
|
CPipeBombGrenade *pPipebomb = (CPipeBombGrenade *)pEnt; |
|
|
|
if (pPipebomb) |
|
{ |
|
if (pPipebomb->pev->owner == pOwner->edict()) |
|
{ |
|
pPipebomb->Deactivate(); |
|
} |
|
} |
|
|
|
pFind = FIND_ENTITY_BY_CLASSNAME(pFind, "monster_pipebomb"); |
|
} |
|
} |