//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #include "cbase.h" #include "dod_baserocket.h" #include "explode.h" #include "dod_shareddefs.h" #include "dod_gamerules.h" #include "fx_dod_shared.h" BEGIN_DATADESC( CDODBaseRocket ) // Function Pointers DEFINE_FUNCTION( RocketTouch ), DEFINE_THINKFUNC( FlyThink ), END_DATADESC() IMPLEMENT_SERVERCLASS_ST( CDODBaseRocket, DT_DODBaseRocket ) SendPropVector( SENDINFO( m_vInitialVelocity ), 20, // nbits 0, // flags -3000, // low value 3000 // high value ) END_NETWORK_TABLE() LINK_ENTITY_TO_CLASS( base_rocket, CDODBaseRocket ); //----------------------------------------------------------------------------- // Constructor //----------------------------------------------------------------------------- CDODBaseRocket::CDODBaseRocket() { } CDODBaseRocket::~CDODBaseRocket() { } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CDODBaseRocket::Precache( void ) { PrecacheScriptSound( "Weapon_Bazooka.Shoot" ); PrecacheParticleSystem( "rockettrail" ); } ConVar mp_rocketdamage( "mp_rocketdamage", "150", FCVAR_GAMEDLL | FCVAR_CHEAT ); ConVar mp_rocketradius( "mp_rocketradius", "200", FCVAR_GAMEDLL | FCVAR_CHEAT ); //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CDODBaseRocket::Spawn( void ) { Precache(); SetSolid( SOLID_BBOX ); Assert( GetModel() ); //derived classes must have set model UTIL_SetSize( this, -Vector(2,2,2), Vector(2,2,2) ); SetTouch( &CDODBaseRocket::RocketTouch ); SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_CUSTOM ); m_takedamage = DAMAGE_NO; SetGravity( 0.1 ); SetDamage( mp_rocketdamage.GetFloat() ); AddFlag( FL_OBJECT ); SetCollisionGroup( COLLISION_GROUP_PROJECTILE ); EmitSound( "Weapon_Bazooka.Shoot" ); m_flCollideWithTeammatesTime = gpGlobals->curtime + 0.25; m_bCollideWithTeammates = false; SetThink( &CDODBaseRocket::FlyThink ); SetNextThink( gpGlobals->curtime ); } unsigned int CDODBaseRocket::PhysicsSolidMaskForEntity( void ) const { int teamContents = 0; if ( m_bCollideWithTeammates == false ) { // Only collide with the other team teamContents = ( GetTeamNumber() == TEAM_ALLIES ) ? CONTENTS_TEAM1 : CONTENTS_TEAM2; } else { // Collide with both teams teamContents = CONTENTS_TEAM1 | CONTENTS_TEAM2; } return BaseClass::PhysicsSolidMaskForEntity() | CONTENTS_HITBOX | teamContents; } //----------------------------------------------------------------------------- // Purpose: Stops any kind of tracking and shoots dumb //----------------------------------------------------------------------------- void CDODBaseRocket::Fire( void ) { SetThink( NULL ); SetMoveType( MOVETYPE_FLY ); SetModel("models/weapons/w_missile.mdl"); UTIL_SetSize( this, vec3_origin, vec3_origin ); EmitSound( "Weapon_Bazooka.Shoot" ); } //----------------------------------------------------------------------------- // The actual explosion //----------------------------------------------------------------------------- void CDODBaseRocket::DoExplosion( trace_t *pTrace ) { /* // Explode ExplosionCreate( GetAbsOrigin(), //DMG_ROCKET GetAbsAngles(), GetOwnerEntity(), GetDamage(), //magnitude mp_rocketradius.GetFloat(), //radius SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODLIGHTS | SF_ENVEXPLOSION_NOSMOKE, 0.0f, //explosion force this); //inflictor */ // Pull out of the wall a bit if ( pTrace->fraction != 1.0 ) { SetAbsOrigin( pTrace->endpos + (pTrace->plane.normal * 0.6) ); } // Explosion effect on client Vector vecOrigin = GetAbsOrigin(); CPVSFilter filter( vecOrigin ); TE_DODExplosion( filter, 0.0f, vecOrigin, pTrace->plane.normal ); CTakeDamageInfo info( this, GetOwnerEntity(), vec3_origin, GetAbsOrigin(), GetDamage(), DMG_BLAST, 0 ); RadiusDamage( info, vecOrigin, mp_rocketradius.GetFloat() /* GetDamageRadius() */, CLASS_NONE, NULL ); // stun players in a radius const float flStunDamage = 75; const float flRadius = 150; CTakeDamageInfo stunInfo( this, GetOwnerEntity(), vec3_origin, GetAbsOrigin(), flStunDamage, DMG_STUN ); DODGameRules()->RadiusStun( stunInfo, GetAbsOrigin(), flRadius ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CDODBaseRocket::Explode( void ) { // Don't explode against the skybox. Just pretend that // the missile flies off into the distance. const trace_t &tr = CBaseEntity::GetTouchTrace(); const trace_t *p = &tr; trace_t *newTrace = const_cast(p); DoExplosion( newTrace ); if ( newTrace->m_pEnt && !newTrace->m_pEnt->IsPlayer() ) UTIL_DecalTrace( newTrace, "Scorch" ); StopSound( "Weapon_Bazooka.Shoot" ); UTIL_Remove( this ); } //----------------------------------------------------------------------------- // Purpose: // Input : *pOther - //----------------------------------------------------------------------------- void CDODBaseRocket::RocketTouch( CBaseEntity *pOther ) { Assert( pOther ); if ( !pOther->IsSolid() || pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS) ) return; if ( pOther->GetCollisionGroup() == COLLISION_GROUP_WEAPON ) return; // if we hit the skybox, just disappear const trace_t &tr = CBaseEntity::GetTouchTrace(); const trace_t *p = &tr; trace_t *newTrace = const_cast(p); if( tr.surface.flags & SURF_SKY ) { UTIL_Remove( this ); return; } if( !pOther->IsPlayer() && pOther->m_takedamage == DAMAGE_YES ) { CTakeDamageInfo info; info.SetAttacker( this ); info.SetInflictor( this ); info.SetDamage( 50 ); info.SetDamageForce( vec3_origin ); // don't worry about this not having a damage force. // It will explode on touch and impart its own forces info.SetDamageType( DMG_CLUB ); Vector dir; AngleVectors( GetAbsAngles(), &dir ); pOther->DispatchTraceAttack( info, dir, newTrace ); ApplyMultiDamage(); if( pOther->IsAlive() ) { Explode(); } // if it's not alive, continue flying } else { Explode(); } } void CDODBaseRocket::FlyThink( void ) { QAngle angles; VectorAngles( GetAbsVelocity(), angles ); SetAbsAngles( angles ); if ( gpGlobals->curtime > m_flCollideWithTeammatesTime && m_bCollideWithTeammates == false ) { m_bCollideWithTeammates = true; } SetNextThink( gpGlobals->curtime + 0.1f ); } //----------------------------------------------------------------------------- // Purpose: // // Input : &vecOrigin - // &vecAngles - // NULL - // // Output : CDODBaseRocket //----------------------------------------------------------------------------- CDODBaseRocket *CDODBaseRocket::Create( const char *szClassname, const Vector &vecOrigin, const QAngle &vecAngles, CBaseEntity *pOwner = NULL ) { CDODBaseRocket *pMissile = (CDODBaseRocket *) CBaseEntity::Create( szClassname, vecOrigin, vecAngles, pOwner ); pMissile->SetOwnerEntity( pOwner ); pMissile->Spawn(); Vector vecForward; AngleVectors( vecAngles, &vecForward ); Vector vRocket = vecForward * 1300; pMissile->SetAbsVelocity( vRocket ); pMissile->SetupInitialTransmittedGrenadeVelocity( vRocket ); pMissile->SetAbsAngles( vecAngles ); // remember what team we should be on pMissile->ChangeTeam( pOwner->GetTeamNumber() ); return pMissile; } void CDODBaseRocket::SetupInitialTransmittedGrenadeVelocity( const Vector &velocity ) { m_vInitialVelocity = velocity; }