source-engine/game/server/hl2/grenade_brickbat.cpp
FluorescentCIAAfricanAmerican 3bf9df6b27 1
2020-04-22 12:56:21 -04:00

275 lines
7.0 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Things thrown from the hand
//
//=============================================================================//
#include "cbase.h"
#include "player.h"
#include "ammodef.h"
#include "gamerules.h"
#include "grenade_brickbat.h"
#include "weapon_brickbat.h"
#include "soundent.h"
#include "decals.h"
#include "IEffects.h"
#include "engine/IEngineSound.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// Global Savedata for changelevel trigger
BEGIN_DATADESC( CGrenade_Brickbat )
DEFINE_FIELD( m_nType, FIELD_INTEGER ),
DEFINE_FIELD( m_bExplodes, FIELD_BOOLEAN ),
DEFINE_FIELD( m_bBounceToFlat, FIELD_BOOLEAN ),
// Function Pointers
DEFINE_FUNCTION( BrickbatTouch ),
DEFINE_FUNCTION( BrickbatThink ),
END_DATADESC()
LINK_ENTITY_TO_CLASS( brickbat, CGrenade_Brickbat );
void CGrenade_Brickbat::Spawn( void )
{
SetCollisionGroup( COLLISION_GROUP_PROJECTILE );
SetTouch( BrickbatTouch );
SetThink( BrickbatThink );
SetNextThink( gpGlobals->curtime + 0.1f );
m_takedamage = DAMAGE_YES;
m_iHealth = 1;
SetGravity( 1.0 );
SetSequence( 1 );
CreateVPhysics();
}
bool CGrenade_Brickbat::CreateVPhysics()
{
VPhysicsInitNormal( SOLID_VPHYSICS, 0, false );
IPhysicsObject *pPhysics = VPhysicsGetObject();
if ( pPhysics )
{
// we want world touches
unsigned int flags = pPhysics->GetCallbackFlags();
pPhysics->SetCallbackFlags( flags | CALLBACK_GLOBAL_TOUCH_STATIC );
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
void CGrenade_Brickbat::BrickbatTouch( CBaseEntity *pOther )
{
// -----------------------------------------------------------
// Might be physically simulated so get my velocity manually
// -----------------------------------------------------------
Vector vVelocity;
GetVelocity(&vVelocity,NULL);
// -----------------------------------
// Do damage if we moving fairly fast
// -----------------------------------
if (vVelocity.Length() > 100)
{
if (GetThrower())
{
trace_t tr;
tr = CBaseEntity::GetTouchTrace( );
ClearMultiDamage( );
Vector forward;
AngleVectors( GetLocalAngles(), &forward );
CTakeDamageInfo info( this, GetThrower(), m_flDamage, DMG_CRUSH );
CalculateMeleeDamageForce( &info, forward, tr.endpos );
pOther->DispatchTraceAttack( info, forward, &tr );
ApplyMultiDamage();
}
// If this thrown item explodes, blow it up
if (m_bExplodes)
{
Detonate();
return;
}
}
else if (pOther->GetFlags() & FL_CLIENT)
{
SpawnBrickbatWeapon();
return;
}
}
//------------------------------------------------------------------------------
// Purpose : Brickbat grenade turns back into a brickbat weapon
// Input :
// Output :
//------------------------------------------------------------------------------
void CGrenade_Brickbat::SpawnBrickbatWeapon( void )
{
CWeaponBrickbat *pBrickbat = (CWeaponBrickbat*)CBaseEntity::CreateNoSpawn(
"weapon_brickbat", GetLocalOrigin(), GetLocalAngles(), NULL );
// Spawn after we set the ammo type so the correct model is used
if (pBrickbat)
{
pBrickbat->m_iCurrentAmmoType = m_nType;
pBrickbat->Spawn();
VPhysicsDestroyObject();
SetThink(NULL);
UTIL_Remove(this);
}
}
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void CGrenade_Brickbat::BrickbatThink( void )
{
// -----------------------------------------------------------
// Might be physically simulated so get my velocity manually
// -----------------------------------------------------------
Vector vVelocity;
AngularImpulse vAngVel;
GetVelocity(&vVelocity,&vAngVel);
// See if I can lose my owner (has dropper moved out of way?)
// Want do this so owner can throw the brickbat
if (GetOwnerEntity())
{
trace_t tr;
Vector vUpABit = GetAbsOrigin();
vUpABit.z += 5.0;
CBaseEntity* saveOwner = GetOwnerEntity();
SetOwnerEntity( NULL );
UTIL_TraceEntity( this, GetAbsOrigin(), vUpABit, MASK_SOLID, &tr );
if ( tr.startsolid || tr.fraction != 1.0 )
{
SetOwnerEntity( saveOwner );
}
}
// ---------------------------------------------------------------
// Make sure we're not resting on a living thing's bounding box
// ---------------------------------------------------------------
if (vVelocity.Length() < 0.01)
{
trace_t tr;
UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector(0,0,10), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
if ( tr.fraction < 1.0 && tr.m_pEnt)
{
CBaseEntity *pEntity = tr.m_pEnt;
if (pEntity->GetFlags() & (FL_CLIENT | FL_NPC))
{
// --------------------
// Bounce me off
// --------------------
Vector vNewVel;
vNewVel.y = 100;
vNewVel.x = random->RandomInt(-100,100);
vNewVel.z = random->RandomInt(-100,100);
// If physically simulated
IPhysicsObject *pPhysicsObject = VPhysicsGetObject();
if ( pPhysicsObject )
{
pPhysicsObject->AddVelocity( &vNewVel, &vAngVel );
}
// Otherwise
else
{
SetAbsVelocity( vNewVel );
}
}
}
}
if (vVelocity.Length() < 0.01)
{
SpawnBrickbatWeapon();
}
SetNextThink( gpGlobals->curtime + 0.1f );
}
//=====================================================================
// > Rock
//=====================================================================
class CGrenadeRockBB : public CGrenade_Brickbat
{
public:
DECLARE_CLASS( CGrenadeRockBB, CGrenade_Brickbat );
void Spawn(void)
{
m_nType = BRICKBAT_ROCK;
SetModel( "models/props_junk/Rock001a.mdl" );
BaseClass::Spawn();
}
void Precache( void )
{
PrecacheModel("models/props_junk/Rock001a.mdl");
BaseClass::Precache();
}
};
LINK_ENTITY_TO_CLASS( grenade_rockbb, CGrenadeRockBB );
PRECACHE_REGISTER(grenade_rockbb);
//=====================================================================
// > BeerBottle
//=====================================================================
class CGrenadeBottle : public CGrenade_Brickbat
{
public:
DECLARE_CLASS( CGrenadeBottle, CGrenade_Brickbat );
void Spawn(void)
{
m_nType = BRICKBAT_BOTTLE;
m_bExplodes = true;
SetModel( "models/weapons/w_bb_bottle.mdl" );
BaseClass::Spawn();
}
void Precache( void );
void Detonate( void );
};
void CGrenadeBottle::Precache( void )
{
PrecacheModel("models/weapons/w_bb_bottle.mdl");
PrecacheScriptSound( "GrenadeBottle.Detonate" );
BaseClass::Precache();
}
void CGrenadeBottle::Detonate( void )
{
trace_t trace;
UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + GetAbsVelocity(), MASK_SOLID, this, COLLISION_GROUP_NONE, &trace);
UTIL_DecalTrace( &trace, "BeerSplash" );
EmitSound( "GrenadeBottle.Detonate" );
CSoundEnt::InsertSound(SOUND_COMBAT, GetAbsOrigin(), 400, 0.5);
UTIL_Remove( this );
}
LINK_ENTITY_TO_CLASS( grenade_beerbottle, CGrenadeBottle );
PRECACHE_REGISTER(grenade_beerbottle);