/*** * * 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 "effects.h" #include "weapons.h" #include "displacerball.h" #include "shock.h" #include "sporegrenade.h" //========================================================= // CPitwormGibShooter //========================================================= class CPitwormGib : public CBaseEntity { public: void Spawn(); void Precache(); void EXPORT GibFloat(); }; LINK_ENTITY_TO_CLASS(pitworm_gib, CPitwormGib) void CPitwormGib::Precache() { PRECACHE_MODEL("models/pit_worm_gibs.mdl"); } void CPitwormGib::Spawn() { Precache(); pev->movetype = MOVETYPE_BOUNCE; pev->friction = 0.55; // deading the bounce a bit pev->renderamt = 255; pev->rendermode = kRenderNormal; pev->renderfx = kRenderFxNone; pev->solid = SOLID_NOT; pev->classname = MAKE_STRING( "pitworm_gib" ); SET_MODEL( ENT( pev ), "models/pit_worm_gibs.mdl" ); UTIL_SetSize( pev, Vector( -8, -8, -4 ), Vector( 8, 8, 16 ) ); pev->nextthink = gpGlobals->time + 0.1; SetThink(&CPitwormGib::GibFloat); } void CPitwormGib::GibFloat() { 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) { pev->velocity.z -= 8; } else { pev->movetype = MOVETYPE_BOUNCE; pev->velocity.z -= 8; } pev->nextthink = gpGlobals->time + 0.1; } class CPitwormGibShooter : public CBaseDelay { public: void Spawn(); void Precache(void); void KeyValue( KeyValueData *pkvd ); void EXPORT ShootThink( void ); void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); CPitwormGib *CreateGib(void); virtual int Save( CSave &save ); virtual int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; int m_iGibModelIndex; float m_flGibVelocity; }; TYPEDESCRIPTION CPitwormGibShooter::m_SaveData[] = { DEFINE_FIELD( CPitwormGibShooter, m_flGibVelocity, FIELD_FLOAT ), }; IMPLEMENT_SAVERESTORE( CPitwormGibShooter, CBaseDelay ) LINK_ENTITY_TO_CLASS(pitworm_gibshooter, CPitwormGibShooter) void CPitwormGibShooter::Precache(void) { m_iGibModelIndex = PRECACHE_MODEL("models/pit_worm_gibs.mdl"); UTIL_PrecacheOther("pitworm_gib"); } void CPitwormGibShooter::Spawn() { Precache(); pev->solid = SOLID_NOT; pev->effects = EF_NODRAW; if( m_flDelay == 0 ) { m_flDelay = 0.1; } SetMovedir( pev ); pev->body = MODEL_FRAMES( m_iGibModelIndex ); } void CPitwormGibShooter::KeyValue( KeyValueData *pkvd ) { if( FStrEq( pkvd->szKeyName, "m_flVelocity" ) ) { m_flGibVelocity = atof( pkvd->szValue ); pkvd->fHandled = TRUE; } else { CBaseDelay::KeyValue( pkvd ); } } void CPitwormGibShooter::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { SetThink( &CPitwormGibShooter::ShootThink ); pev->nextthink = gpGlobals->time; } CPitwormGib *CPitwormGibShooter::CreateGib(void) { if (CVAR_GET_FLOAT("violence_hgibs") == 0) return NULL; CPitwormGib *pGib = GetClassPtr((CPitwormGib *)NULL); pGib->Spawn(); if (pev->body <= 1) { ALERT(at_aiconsole, "PitwormGibShooter Body is <= 1!\n"); } pGib->pev->body = RANDOM_LONG(0, pev->body - 1); return pGib; } void CPitwormGibShooter::ShootThink() { UTIL_MakeVectors(pev->angles); CPitwormGib *pGib = CreateGib(); if (pGib) { pGib->pev->origin = pev->origin; pGib->pev->velocity = gpGlobals->v_forward * m_flGibVelocity; } SetThink( &CBaseEntity::SUB_Remove ); pev->nextthink = gpGlobals->time + 0.1; } enum { BLOWERCANNON_SPOREROCKET = 1, BLOWERCANNON_SPOREGRENADE, BLOWERCANNON_SHOCKBEAM, BLOWERCANNON_DISPLACERBALL, }; enum { BLOWERCANNON_TOGGLE = 1, BLOWERCANNON_FIRE, }; class CBlowerCannon : public CBaseEntity { public: void Spawn( void ); void Precache( void ); void KeyValue(KeyValueData* pkvd); void EXPORT BlowerCannonThink( void ); void EXPORT BlowerCannonStart( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); void EXPORT BlowerCannonStop( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); virtual int Save(CSave &save); virtual int Restore(CRestore &restore); static TYPEDESCRIPTION m_SaveData[]; int m_iWeapType; float m_flDelay; int m_iFireType; int m_iZOffSet; }; LINK_ENTITY_TO_CLASS(env_blowercannon, CBlowerCannon) TYPEDESCRIPTION CBlowerCannon::m_SaveData[] = { DEFINE_FIELD(CBlowerCannon, m_iFireType, FIELD_INTEGER), DEFINE_FIELD(CBlowerCannon, m_iWeapType, FIELD_INTEGER), DEFINE_FIELD(CBlowerCannon, m_iZOffSet, FIELD_INTEGER), DEFINE_FIELD(CBlowerCannon, m_flDelay, FIELD_FLOAT), }; IMPLEMENT_SAVERESTORE( CBlowerCannon, CBaseEntity ) void CBlowerCannon::KeyValue(KeyValueData *pkvd) { if (FStrEq(pkvd->szKeyName, "firetype")) { m_iFireType = (int)atoi(pkvd->szValue); pkvd->fHandled = TRUE; } else if (FStrEq(pkvd->szKeyName, "delay")) { m_flDelay = (float)atof(pkvd->szValue); pkvd->fHandled = TRUE; } else if (FStrEq(pkvd->szKeyName, "weaptype")) { m_iWeapType = (int)atoi(pkvd->szValue); pkvd->fHandled = TRUE; } else if (FStrEq(pkvd->szKeyName, "zoffset")) { m_iZOffSet = (int)atoi(pkvd->szValue); pkvd->fHandled = TRUE; } else pkvd->fHandled = FALSE; } void CBlowerCannon::Spawn(void) { Precache(); UTIL_SetSize( pev, Vector(-16, -16, -16), Vector( 16, 16, 16 ) ); pev->solid = SOLID_TRIGGER; if (m_flDelay <= 0.0f) m_flDelay = 1.0f; SetUse( &CBlowerCannon::BlowerCannonStart ); } void CBlowerCannon::Precache( void ) { UTIL_PrecacheOther( "shock_beam" ); UTIL_PrecacheOther( "displacer_ball" ); UTIL_PrecacheOther( "spore" ); } void CBlowerCannon::BlowerCannonStart( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { SetUse( &CBlowerCannon::BlowerCannonStop ); SetThink( &CBlowerCannon::BlowerCannonThink ); pev->nextthink = gpGlobals->time + m_flDelay; } void CBlowerCannon::BlowerCannonStop( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { SetUse( &CBlowerCannon::BlowerCannonStart ); SetThink( NULL ); } void CBlowerCannon::BlowerCannonThink( void ) { CBaseEntity *pTarget = GetNextTarget(); if( pTarget ) { Vector direction = pTarget->pev->origin - pev->origin; direction.z = m_iZOffSet + pTarget->pev->origin.z - pev->origin.z; Vector angles = UTIL_VecToAngles( direction ); UTIL_MakeVectors( angles ); switch (m_iWeapType) { case BLOWERCANNON_SPOREROCKET: CSpore::CreateSpore(pev->origin, angles, this, CSpore::ROCKET, false, false); break; case BLOWERCANNON_SPOREGRENADE: 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); break; case BLOWERCANNON_DISPLACERBALL: CDisplacerBall::Shoot(pev, pev->origin, gpGlobals->v_forward * 500, angles); break; default: ALERT(at_console, "Unknown projectile type in blowercannon: %d\n", m_iWeapType); break; } } if( m_iFireType == BLOWERCANNON_FIRE ) { SetUse( &CBlowerCannon::BlowerCannonStart ); SetThink( NULL ); } pev->nextthink = gpGlobals->time + m_flDelay; }