/*** * * 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 "sporegrenade.h" 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; }; typedef enum { 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 ) 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; } //========================================================= // 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 ) { 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) { pev->sequence = SPOREAMMO_IDLE; m_flTimeSporeIdle = gpGlobals->time + 10; SetThink(&CSporeAmmo::BornThink); return; } else { pev->sequence = SPOREAMMO_IDLE1; } } void CSporeAmmo :: AmmoTouch ( CBaseEntity *pOther ) { if ( !pOther->IsPlayer() ) return; if (borntime) return; 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); 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); } }