From f56bb35301836e56582a575a75864392a0177875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Mon, 2 Dec 2013 19:31:46 -0800 Subject: Fix line endings. WHAMMY. --- mp/src/game/server/gib.cpp | 1358 ++++++++++++++++++++++---------------------- 1 file changed, 679 insertions(+), 679 deletions(-) (limited to 'mp/src/game/server/gib.cpp') diff --git a/mp/src/game/server/gib.cpp b/mp/src/game/server/gib.cpp index 4d64fa19..a5dec6da 100644 --- a/mp/src/game/server/gib.cpp +++ b/mp/src/game/server/gib.cpp @@ -1,679 +1,679 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// Purpose: A gib is a chunk of a body, or a piece of wood/metal/rocks/etc. -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//===========================================================================// - -#include "cbase.h" -#include "gib.h" -#include "soundent.h" -#include "func_break.h" // For materials -#include "player.h" -#include "vstdlib/random.h" -#include "ai_utils.h" -#include "EntityFlame.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern Vector g_vecAttackDir; // In globals.cpp - -BEGIN_DATADESC( CGib ) - - // gibs are not saved/restored -// DEFINE_FIELD( m_bloodColor, FIELD_INTEGER ), -// DEFINE_FIELD( m_hSprite, FIELD_EHANDLE ), -// DEFINE_FIELD( m_cBloodDecals, FIELD_INTEGER ), -// DEFINE_FIELD( m_material, FIELD_INTEGER ), -// DEFINE_FIELD( m_lifeTime, FIELD_TIME ), -// DEFINE_FIELD( m_pSprite, CSprite ), -// DEFINE_FIELD( m_hFlame, FIELD_EHANDLE ), - -// DEFINE_FIELD( m_hPhysicsAttacker, FIELD_EHANDLE ), -// DEFINE_FIELD( m_flLastPhysicsInfluenceTime, FIELD_TIME ), - -// DEFINE_FIELD( m_bForceRemove, FIELD_BOOLEAN ), - - // Function pointers - DEFINE_ENTITYFUNC( BounceGibTouch ), - DEFINE_ENTITYFUNC( StickyGibTouch ), - DEFINE_THINKFUNC( WaitTillLand ), - DEFINE_THINKFUNC( DieThink ), - -END_DATADESC() - - -// HACKHACK -- The gib velocity equations don't work -void CGib::LimitVelocity( void ) -{ - Vector vecNewVelocity = GetAbsVelocity(); - float length = VectorNormalize( vecNewVelocity ); - - // ceiling at 1500. The gib velocity equation is not bounded properly. Rather than tune it - // in 3 separate places again, I'll just limit it here. - if ( length > 1500.0 ) - { - vecNewVelocity *= 1500; // This should really be sv_maxvelocity * 0.75 or something - SetAbsVelocity( vecNewVelocity ); - } -} - - -void CGib::SpawnStickyGibs( CBaseEntity *pVictim, Vector vecOrigin, int cGibs ) -{ - int i; - - if ( g_Language.GetInt() == LANGUAGE_GERMAN ) - { - // no sticky gibs in germany right now! - return; - } - - for ( i = 0 ; i < cGibs ; i++ ) - { - CGib *pGib = (CGib *)CreateEntityByName( "gib" ); - - pGib->Spawn( "models/stickygib.mdl" ); - pGib->m_nBody = random->RandomInt(0,2); - - if ( pVictim ) - { - pGib->SetLocalOrigin( - Vector( vecOrigin.x + random->RandomFloat( -3, 3 ), - vecOrigin.y + random->RandomFloat( -3, 3 ), - vecOrigin.z + random->RandomFloat( -3, 3 ) ) ); - - // make the gib fly away from the attack vector - Vector vecNewVelocity = g_vecAttackDir * -1; - - // mix in some noise - vecNewVelocity.x += random->RandomFloat ( -0.15, 0.15 ); - vecNewVelocity.y += random->RandomFloat ( -0.15, 0.15 ); - vecNewVelocity.z += random->RandomFloat ( -0.15, 0.15 ); - - vecNewVelocity *= 900; - - QAngle vecAngVelocity( random->RandomFloat ( 250, 400 ), random->RandomFloat ( 250, 400 ), 0 ); - pGib->SetLocalAngularVelocity( vecAngVelocity ); - - // copy owner's blood color - pGib->SetBloodColor( pVictim->BloodColor() ); - - pGib->AdjustVelocityBasedOnHealth( pVictim->m_iHealth, vecNewVelocity ); - pGib->SetAbsVelocity( vecNewVelocity ); - - pGib->SetMoveType( MOVETYPE_FLYGRAVITY ); - pGib->RemoveSolidFlags( FSOLID_NOT_SOLID ); - pGib->SetCollisionBounds( vec3_origin, vec3_origin ); - pGib->SetTouch ( &CGib::StickyGibTouch ); - pGib->SetThink (NULL); - } - pGib->LimitVelocity(); - } -} - -void CGib::SpawnHeadGib( CBaseEntity *pVictim ) -{ - CGib *pGib = CREATE_ENTITY( CGib, "gib" ); - - if ( g_Language.GetInt() == LANGUAGE_GERMAN ) - { - pGib->Spawn( "models/germangibs.mdl" );// throw one head - pGib->m_nBody = 0; - } - else - { - pGib->Spawn( "models/gibs/hgibs.mdl" );// throw one head - pGib->m_nBody = 0; - } - - if ( pVictim ) - { - Vector vecNewVelocity = pGib->GetAbsVelocity(); - - pGib->SetLocalOrigin( pVictim->EyePosition() ); - - edict_t *pentPlayer = UTIL_FindClientInPVS( pGib->edict() ); - - if ( random->RandomInt ( 0, 100 ) <= 5 && pentPlayer ) - { - // 5% chance head will be thrown at player's face. - CBasePlayer *player = (CBasePlayer *)CBaseEntity::Instance( pentPlayer ); - if ( player ) - { - vecNewVelocity = ( player->EyePosition() ) - pGib->GetAbsOrigin(); - VectorNormalize(vecNewVelocity); - vecNewVelocity *= 300; - vecNewVelocity.z += 100; - } - } - else - { - vecNewVelocity = Vector (random->RandomFloat(-100,100), random->RandomFloat(-100,100), random->RandomFloat(200,300)); - } - - QAngle vecNewAngularVelocity = pGib->GetLocalAngularVelocity(); - vecNewAngularVelocity.x = random->RandomFloat ( 100, 200 ); - vecNewAngularVelocity.y = random->RandomFloat ( 100, 300 ); - pGib->SetLocalAngularVelocity( vecNewAngularVelocity ); - - // copy owner's blood color - pGib->SetBloodColor( pVictim->BloodColor() ); - pGib->AdjustVelocityBasedOnHealth( pVictim->m_iHealth, vecNewVelocity ); - pGib->SetAbsVelocity( vecNewVelocity ); - } - pGib->LimitVelocity(); -} - - -//----------------------------------------------------------------------------- -// Blood color (see BLOOD_COLOR_* macros in baseentity.h) -//----------------------------------------------------------------------------- -void CGib::SetBloodColor( int nBloodColor ) -{ - m_bloodColor = nBloodColor; -} - - -//------------------------------------------------------------------------------ -// A little piece of duplicated code -//------------------------------------------------------------------------------ -void CGib::AdjustVelocityBasedOnHealth( int nHealth, Vector &vecVelocity ) -{ - if ( nHealth > -50) - { - vecVelocity *= 0.7; - } - else if ( nHealth > -200) - { - vecVelocity *= 2; - } - else - { - vecVelocity *= 4; - } -} - - -//------------------------------------------------------------------------------ -// Purpose : Initialize a gibs position and velocity -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGib::InitGib( CBaseEntity *pVictim, float fMinVelocity, float fMaxVelocity ) -{ - // ------------------------------------------------------------------------ - // If have a pVictim spawn the gib somewhere in the pVictim's bounding volume - // ------------------------------------------------------------------------ - if ( pVictim ) - { - // Find a random position within the bounding box (add 1 to Z to get it out of the ground) - Vector vecOrigin; - pVictim->CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1, 1, 1 ), &vecOrigin ); - vecOrigin.z += 1.0f; - SetAbsOrigin( vecOrigin ); - - // make the gib fly away from the attack vector - Vector vecNewVelocity = g_vecAttackDir * -1; - - // mix in some noise - vecNewVelocity.x += random->RandomFloat ( -0.25, 0.25 ); - vecNewVelocity.y += random->RandomFloat ( -0.25, 0.25 ); - vecNewVelocity.z += random->RandomFloat ( -0.25, 0.25 ); - - vecNewVelocity *= random->RandomFloat ( fMaxVelocity, fMinVelocity ); - - QAngle vecNewAngularVelocity = GetLocalAngularVelocity(); - vecNewAngularVelocity.x = random->RandomFloat ( 100, 200 ); - vecNewAngularVelocity.y = random->RandomFloat ( 100, 300 ); - SetLocalAngularVelocity( vecNewAngularVelocity ); - - // copy owner's blood color - SetBloodColor( pVictim->BloodColor() ); - - AdjustVelocityBasedOnHealth( pVictim->m_iHealth, vecNewVelocity ); - - // Attempt to be physical if we can - if ( VPhysicsInitNormal( SOLID_BBOX, 0, false ) ) - { - IPhysicsObject *pObj = VPhysicsGetObject(); - - if ( pObj != NULL ) - { - AngularImpulse angImpulse = RandomAngularImpulse( -500, 500 ); - pObj->AddVelocity( &vecNewVelocity, &angImpulse ); - } - } - else - { - SetSolid( SOLID_BBOX ); - SetCollisionBounds( vec3_origin, vec3_origin ); - SetAbsVelocity( vecNewVelocity ); - } - - SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - } - - LimitVelocity(); -} - -//------------------------------------------------------------------------------ -// Purpose : Given an .mdl file with gibs and the number of gibs in the file -// spawns them in pVictim's bounding box -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGib::SpawnSpecificGibs( CBaseEntity* pVictim, - int nNumGibs, - float vMinVelocity, - float vMaxVelocity, - const char* cModelName, - float flLifetime) -{ - for (int i=0;iSpawn( cModelName ); - pGib->m_nBody = i; - pGib->InitGib( pVictim, vMinVelocity, vMaxVelocity ); - pGib->m_lifeTime = flLifetime; - - if ( pVictim != NULL ) - { - pGib->SetOwnerEntity( pVictim ); - } - } -} - -//------------------------------------------------------------------------------ -// Purpose : Spawn random gibs of the given gib type -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGib::SpawnRandomGibs( CBaseEntity *pVictim, int cGibs, GibType_e eGibType ) -{ - int cSplat; - - for ( cSplat = 0 ; cSplat < cGibs ; cSplat++ ) - { - CGib *pGib = CREATE_ENTITY( CGib, "gib" ); - - if ( g_Language.GetInt() == LANGUAGE_GERMAN ) - { - pGib->Spawn( "models/germangibs.mdl" ); - pGib->m_nBody = random->RandomInt(0,GERMAN_GIB_COUNT-1); - } - else - { - switch (eGibType) - { - case GIB_HUMAN: - // human pieces - pGib->Spawn( "models/gibs/hgibs.mdl" ); - pGib->m_nBody = random->RandomInt(1,HUMAN_GIB_COUNT-1);// start at one to avoid throwing random amounts of skulls (0th gib) - break; - case GIB_ALIEN: - // alien pieces - pGib->Spawn( "models/gibs/agibs.mdl" ); - pGib->m_nBody = random->RandomInt(0,ALIEN_GIB_COUNT-1); - break; - } - } - pGib->InitGib( pVictim, 300, 400); - } -} - -//========================================================= -// WaitTillLand - in order to emit their meaty scent from -// the proper location, gibs should wait until they stop -// bouncing to emit their scent. That's what this function -// does. -//========================================================= -void CGib::WaitTillLand ( void ) -{ - if (!IsInWorld()) - { - UTIL_Remove( this ); - return; - } - - if ( GetAbsVelocity() == vec3_origin ) - { - SetRenderColorA( 255 ); - m_nRenderMode = kRenderTransTexture; - if ( GetMoveType() != MOVETYPE_VPHYSICS ) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - } - SetLocalAngularVelocity( vec3_angle ); - - SetNextThink( gpGlobals->curtime + m_lifeTime ); - SetThink ( &CGib::SUB_FadeOut ); - - if ( GetSprite() ) - { - CSprite *pSprite = dynamic_cast( GetSprite() ); - - if ( pSprite ) - { - //Adrian - Why am I doing this? Check InitPointGib for the answer! - if ( m_lifeTime == 0 ) - m_lifeTime = random->RandomFloat( 1, 3 ); - - pSprite->FadeAndDie( m_lifeTime ); - } - } - - if ( GetFlame() ) - { - CEntityFlame *pFlame = dynamic_cast< CEntityFlame*>( GetFlame() ); - - if ( pFlame ) - { - pFlame->SetLifetime( 1.0f ); - } - } - - // If you bleed, you stink! - if ( m_bloodColor != DONT_BLEED ) - { - // ok, start stinkin! - // FIXME: It's too easy to fill up the sound queue with all these meat sounds - // CSoundEnt::InsertSound ( SOUND_MEAT, GetAbsOrigin(), 384, 25 ); - } - } - else - { - // wait and check again in another half second. - SetNextThink( gpGlobals->curtime + 0.5f ); - } -} - -bool CGib::SUB_AllowedToFade( void ) -{ - if( VPhysicsGetObject() ) - { - if( VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD || GetEFlags() & EFL_IS_BEING_LIFTED_BY_BARNACLE ) - return false; - } - - CBasePlayer *pPlayer = ( AI_IsSinglePlayer() ) ? UTIL_GetLocalPlayer() : NULL; - - if ( pPlayer && pPlayer->FInViewCone( this ) && m_bForceRemove == false ) - { - return false; - } - - return true; -} - - -void CGib::DieThink ( void ) -{ - if ( GetSprite() ) - { - CSprite *pSprite = dynamic_cast( GetSprite() ); - - if ( pSprite ) - { - pSprite->FadeAndDie( 0.0 ); - } - } - - if ( GetFlame() ) - { - CEntityFlame *pFlame = dynamic_cast< CEntityFlame*>( GetFlame() ); - - if ( pFlame ) - { - pFlame->SetLifetime( 1.0f ); - } - } - - if ( g_pGameRules->IsMultiplayer() ) - { - UTIL_Remove( this ); - } - else - { - SetThink ( &CGib::SUB_FadeOut ); - SetNextThink( gpGlobals->curtime ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGib::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - - if ( pPlayer ) - { - pPlayer->PickupObject( this ); - } -} - -//----------------------------------------------------------------------------- -// Physics Attacker -//----------------------------------------------------------------------------- -void CGib::SetPhysicsAttacker( CBasePlayer *pEntity, float flTime ) -{ - m_hPhysicsAttacker = pEntity; - m_flLastPhysicsInfluenceTime = flTime; -} - - -//----------------------------------------------------------------------------- -// Purpose: Keep track of physgun influence -//----------------------------------------------------------------------------- -void CGib::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - SetPhysicsAttacker( pPhysGunUser, gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGib::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) -{ - SetPhysicsAttacker( pPhysGunUser, gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CBasePlayer *CGib::HasPhysicsAttacker( float dt ) -{ - if (gpGlobals->curtime - dt <= m_flLastPhysicsInfluenceTime) - { - return m_hPhysicsAttacker; - } - return NULL; -} - - -// -// Gib bounces on the ground or wall, sponges some blood down, too! -// -void CGib::BounceGibTouch ( CBaseEntity *pOther ) -{ - Vector vecSpot; - trace_t tr; - - IPhysicsObject *pPhysics = VPhysicsGetObject(); - - if ( pPhysics ) - return; - - //if ( random->RandomInt(0,1) ) - // return;// don't bleed everytime - if (GetFlags() & FL_ONGROUND) - { - SetAbsVelocity( GetAbsVelocity() * 0.9 ); - QAngle angles = GetLocalAngles(); - angles.x = 0; - angles.z = 0; - SetLocalAngles( angles ); - - QAngle angVel = GetLocalAngularVelocity(); - angVel.x = 0; - angVel.z = 0; - SetLocalAngularVelocity( vec3_angle ); - } - else - { - if ( g_Language.GetInt() != LANGUAGE_GERMAN && m_cBloodDecals > 0 && m_bloodColor != DONT_BLEED ) - { - vecSpot = GetAbsOrigin() + Vector ( 0 , 0 , 8 );//move up a bit, and trace down. - UTIL_TraceLine ( vecSpot, vecSpot + Vector ( 0, 0, -24 ), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr); - - UTIL_BloodDecalTrace( &tr, m_bloodColor ); - - m_cBloodDecals--; - } - - if ( m_material != matNone && random->RandomInt(0,2) == 0 ) - { - float volume; - float zvel = fabs(GetAbsVelocity().z); - - volume = 0.8f * MIN(1.0, ((float)zvel) / 450.0f); - - CBreakable::MaterialSoundRandom( entindex(), (Materials)m_material, volume ); - } - } -} - -// -// Sticky gib puts blood on the wall and stays put. -// -void CGib::StickyGibTouch ( CBaseEntity *pOther ) -{ - Vector vecSpot; - trace_t tr; - - SetThink ( &CGib::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 10 ); - - if ( !FClassnameIs( pOther, "worldspawn" ) ) - { - SetNextThink( gpGlobals->curtime ); - return; - } - - UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + GetAbsVelocity() * 32, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr); - - UTIL_BloodDecalTrace( &tr, m_bloodColor ); - - Vector vecForward = tr.plane.normal * -1; - QAngle angles; - VectorAngles( vecForward, angles ); - SetLocalAngles( angles ); - SetAbsVelocity( vec3_origin ); - SetLocalAngularVelocity( vec3_angle ); - SetMoveType( MOVETYPE_NONE ); -} - -// -// Throw a chunk -// -void CGib::Spawn( const char *szGibModel ) -{ - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - SetFriction(0.55); // deading the bounce a bit - - // sometimes an entity inherits the edict from a former piece of glass, - // and will spawn using the same render FX or m_nRenderMode! bad! - SetRenderColorA( 255 ); - m_nRenderMode = kRenderNormal; - m_nRenderFX = kRenderFxNone; - - // hopefully this will fix the VELOCITY TOO LOW crap - m_takedamage = DAMAGE_EVENTS_ONLY; - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - - SetModel( szGibModel ); - -#ifdef HL1_DLL - SetElasticity( 1.0 ); - UTIL_SetSize( this, vec3_origin, vec3_origin ); -#endif//HL1_DLL - - SetNextThink( gpGlobals->curtime + 4 ); - m_lifeTime = 25; - SetTouch ( &CGib::BounceGibTouch ); - - m_bForceRemove = false; - - m_material = matNone; - m_cBloodDecals = 5;// how many blood decals this gib can place (1 per bounce until none remain). - -} - - -//----------------------------------------------------------------------------- -// Spawn a gib with a finite lifetime, after which it will fade out. -//----------------------------------------------------------------------------- -void CGib::Spawn( const char *szGibModel, float flLifetime ) -{ - Spawn( szGibModel ); - m_lifeTime = flLifetime; - SetThink ( &CGib::SUB_FadeOut ); - SetNextThink( gpGlobals->curtime + m_lifeTime ); -} - - -LINK_ENTITY_TO_CLASS( gib, CGib ); - -CBaseEntity *CreateRagGib( const char *szModel, const Vector &vecOrigin, const QAngle &vecAngles, const Vector &vecForce, float flFadeTime, bool bShouldIgnite ) -{ - CRagGib *pGib; - - pGib = (CRagGib*)CreateEntityByName( "raggib" ); - - pGib->SetLocalAngles( vecAngles ); - - if ( !pGib ) - { - Msg( "**Can't create ragdoll gib!\n" ); - return NULL; - } - - if ( bShouldIgnite ) - { - CBaseAnimating *pAnimating = pGib->GetBaseAnimating(); - if (pAnimating != NULL ) - { - pAnimating->Ignite( random->RandomFloat( 8.0, 12.0 ), false ); - } - } - - pGib->Spawn( szModel, vecOrigin, vecForce, flFadeTime ); - - return pGib; -} - -void CRagGib::Spawn( const char *szModel, const Vector &vecOrigin, const Vector &vecForce, float flFadeTime = 0.0 ) -{ - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_SOLID ); - SetModel( szModel ); - UTIL_SetSize(this, vec3_origin, vec3_origin); - UTIL_SetOrigin( this, vecOrigin ); - if ( !BecomeRagdollOnClient( vecForce ) ) - { - AddSolidFlags( FSOLID_NOT_STANDABLE ); - RemoveSolidFlags( FSOLID_NOT_SOLID ); - if( flFadeTime > 0.0 ) - { - SUB_StartFadeOut( flFadeTime ); - } - } -} - -LINK_ENTITY_TO_CLASS( raggib, CRagGib ); +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: A gib is a chunk of a body, or a piece of wood/metal/rocks/etc. +// +// $Workfile: $ +// $Date: $ +// $NoKeywords: $ +//===========================================================================// + +#include "cbase.h" +#include "gib.h" +#include "soundent.h" +#include "func_break.h" // For materials +#include "player.h" +#include "vstdlib/random.h" +#include "ai_utils.h" +#include "EntityFlame.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +extern Vector g_vecAttackDir; // In globals.cpp + +BEGIN_DATADESC( CGib ) + + // gibs are not saved/restored +// DEFINE_FIELD( m_bloodColor, FIELD_INTEGER ), +// DEFINE_FIELD( m_hSprite, FIELD_EHANDLE ), +// DEFINE_FIELD( m_cBloodDecals, FIELD_INTEGER ), +// DEFINE_FIELD( m_material, FIELD_INTEGER ), +// DEFINE_FIELD( m_lifeTime, FIELD_TIME ), +// DEFINE_FIELD( m_pSprite, CSprite ), +// DEFINE_FIELD( m_hFlame, FIELD_EHANDLE ), + +// DEFINE_FIELD( m_hPhysicsAttacker, FIELD_EHANDLE ), +// DEFINE_FIELD( m_flLastPhysicsInfluenceTime, FIELD_TIME ), + +// DEFINE_FIELD( m_bForceRemove, FIELD_BOOLEAN ), + + // Function pointers + DEFINE_ENTITYFUNC( BounceGibTouch ), + DEFINE_ENTITYFUNC( StickyGibTouch ), + DEFINE_THINKFUNC( WaitTillLand ), + DEFINE_THINKFUNC( DieThink ), + +END_DATADESC() + + +// HACKHACK -- The gib velocity equations don't work +void CGib::LimitVelocity( void ) +{ + Vector vecNewVelocity = GetAbsVelocity(); + float length = VectorNormalize( vecNewVelocity ); + + // ceiling at 1500. The gib velocity equation is not bounded properly. Rather than tune it + // in 3 separate places again, I'll just limit it here. + if ( length > 1500.0 ) + { + vecNewVelocity *= 1500; // This should really be sv_maxvelocity * 0.75 or something + SetAbsVelocity( vecNewVelocity ); + } +} + + +void CGib::SpawnStickyGibs( CBaseEntity *pVictim, Vector vecOrigin, int cGibs ) +{ + int i; + + if ( g_Language.GetInt() == LANGUAGE_GERMAN ) + { + // no sticky gibs in germany right now! + return; + } + + for ( i = 0 ; i < cGibs ; i++ ) + { + CGib *pGib = (CGib *)CreateEntityByName( "gib" ); + + pGib->Spawn( "models/stickygib.mdl" ); + pGib->m_nBody = random->RandomInt(0,2); + + if ( pVictim ) + { + pGib->SetLocalOrigin( + Vector( vecOrigin.x + random->RandomFloat( -3, 3 ), + vecOrigin.y + random->RandomFloat( -3, 3 ), + vecOrigin.z + random->RandomFloat( -3, 3 ) ) ); + + // make the gib fly away from the attack vector + Vector vecNewVelocity = g_vecAttackDir * -1; + + // mix in some noise + vecNewVelocity.x += random->RandomFloat ( -0.15, 0.15 ); + vecNewVelocity.y += random->RandomFloat ( -0.15, 0.15 ); + vecNewVelocity.z += random->RandomFloat ( -0.15, 0.15 ); + + vecNewVelocity *= 900; + + QAngle vecAngVelocity( random->RandomFloat ( 250, 400 ), random->RandomFloat ( 250, 400 ), 0 ); + pGib->SetLocalAngularVelocity( vecAngVelocity ); + + // copy owner's blood color + pGib->SetBloodColor( pVictim->BloodColor() ); + + pGib->AdjustVelocityBasedOnHealth( pVictim->m_iHealth, vecNewVelocity ); + pGib->SetAbsVelocity( vecNewVelocity ); + + pGib->SetMoveType( MOVETYPE_FLYGRAVITY ); + pGib->RemoveSolidFlags( FSOLID_NOT_SOLID ); + pGib->SetCollisionBounds( vec3_origin, vec3_origin ); + pGib->SetTouch ( &CGib::StickyGibTouch ); + pGib->SetThink (NULL); + } + pGib->LimitVelocity(); + } +} + +void CGib::SpawnHeadGib( CBaseEntity *pVictim ) +{ + CGib *pGib = CREATE_ENTITY( CGib, "gib" ); + + if ( g_Language.GetInt() == LANGUAGE_GERMAN ) + { + pGib->Spawn( "models/germangibs.mdl" );// throw one head + pGib->m_nBody = 0; + } + else + { + pGib->Spawn( "models/gibs/hgibs.mdl" );// throw one head + pGib->m_nBody = 0; + } + + if ( pVictim ) + { + Vector vecNewVelocity = pGib->GetAbsVelocity(); + + pGib->SetLocalOrigin( pVictim->EyePosition() ); + + edict_t *pentPlayer = UTIL_FindClientInPVS( pGib->edict() ); + + if ( random->RandomInt ( 0, 100 ) <= 5 && pentPlayer ) + { + // 5% chance head will be thrown at player's face. + CBasePlayer *player = (CBasePlayer *)CBaseEntity::Instance( pentPlayer ); + if ( player ) + { + vecNewVelocity = ( player->EyePosition() ) - pGib->GetAbsOrigin(); + VectorNormalize(vecNewVelocity); + vecNewVelocity *= 300; + vecNewVelocity.z += 100; + } + } + else + { + vecNewVelocity = Vector (random->RandomFloat(-100,100), random->RandomFloat(-100,100), random->RandomFloat(200,300)); + } + + QAngle vecNewAngularVelocity = pGib->GetLocalAngularVelocity(); + vecNewAngularVelocity.x = random->RandomFloat ( 100, 200 ); + vecNewAngularVelocity.y = random->RandomFloat ( 100, 300 ); + pGib->SetLocalAngularVelocity( vecNewAngularVelocity ); + + // copy owner's blood color + pGib->SetBloodColor( pVictim->BloodColor() ); + pGib->AdjustVelocityBasedOnHealth( pVictim->m_iHealth, vecNewVelocity ); + pGib->SetAbsVelocity( vecNewVelocity ); + } + pGib->LimitVelocity(); +} + + +//----------------------------------------------------------------------------- +// Blood color (see BLOOD_COLOR_* macros in baseentity.h) +//----------------------------------------------------------------------------- +void CGib::SetBloodColor( int nBloodColor ) +{ + m_bloodColor = nBloodColor; +} + + +//------------------------------------------------------------------------------ +// A little piece of duplicated code +//------------------------------------------------------------------------------ +void CGib::AdjustVelocityBasedOnHealth( int nHealth, Vector &vecVelocity ) +{ + if ( nHealth > -50) + { + vecVelocity *= 0.7; + } + else if ( nHealth > -200) + { + vecVelocity *= 2; + } + else + { + vecVelocity *= 4; + } +} + + +//------------------------------------------------------------------------------ +// Purpose : Initialize a gibs position and velocity +// Input : +// Output : +//------------------------------------------------------------------------------ +void CGib::InitGib( CBaseEntity *pVictim, float fMinVelocity, float fMaxVelocity ) +{ + // ------------------------------------------------------------------------ + // If have a pVictim spawn the gib somewhere in the pVictim's bounding volume + // ------------------------------------------------------------------------ + if ( pVictim ) + { + // Find a random position within the bounding box (add 1 to Z to get it out of the ground) + Vector vecOrigin; + pVictim->CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1, 1, 1 ), &vecOrigin ); + vecOrigin.z += 1.0f; + SetAbsOrigin( vecOrigin ); + + // make the gib fly away from the attack vector + Vector vecNewVelocity = g_vecAttackDir * -1; + + // mix in some noise + vecNewVelocity.x += random->RandomFloat ( -0.25, 0.25 ); + vecNewVelocity.y += random->RandomFloat ( -0.25, 0.25 ); + vecNewVelocity.z += random->RandomFloat ( -0.25, 0.25 ); + + vecNewVelocity *= random->RandomFloat ( fMaxVelocity, fMinVelocity ); + + QAngle vecNewAngularVelocity = GetLocalAngularVelocity(); + vecNewAngularVelocity.x = random->RandomFloat ( 100, 200 ); + vecNewAngularVelocity.y = random->RandomFloat ( 100, 300 ); + SetLocalAngularVelocity( vecNewAngularVelocity ); + + // copy owner's blood color + SetBloodColor( pVictim->BloodColor() ); + + AdjustVelocityBasedOnHealth( pVictim->m_iHealth, vecNewVelocity ); + + // Attempt to be physical if we can + if ( VPhysicsInitNormal( SOLID_BBOX, 0, false ) ) + { + IPhysicsObject *pObj = VPhysicsGetObject(); + + if ( pObj != NULL ) + { + AngularImpulse angImpulse = RandomAngularImpulse( -500, 500 ); + pObj->AddVelocity( &vecNewVelocity, &angImpulse ); + } + } + else + { + SetSolid( SOLID_BBOX ); + SetCollisionBounds( vec3_origin, vec3_origin ); + SetAbsVelocity( vecNewVelocity ); + } + + SetCollisionGroup( COLLISION_GROUP_DEBRIS ); + } + + LimitVelocity(); +} + +//------------------------------------------------------------------------------ +// Purpose : Given an .mdl file with gibs and the number of gibs in the file +// spawns them in pVictim's bounding box +// Input : +// Output : +//------------------------------------------------------------------------------ +void CGib::SpawnSpecificGibs( CBaseEntity* pVictim, + int nNumGibs, + float vMinVelocity, + float vMaxVelocity, + const char* cModelName, + float flLifetime) +{ + for (int i=0;iSpawn( cModelName ); + pGib->m_nBody = i; + pGib->InitGib( pVictim, vMinVelocity, vMaxVelocity ); + pGib->m_lifeTime = flLifetime; + + if ( pVictim != NULL ) + { + pGib->SetOwnerEntity( pVictim ); + } + } +} + +//------------------------------------------------------------------------------ +// Purpose : Spawn random gibs of the given gib type +// Input : +// Output : +//------------------------------------------------------------------------------ +void CGib::SpawnRandomGibs( CBaseEntity *pVictim, int cGibs, GibType_e eGibType ) +{ + int cSplat; + + for ( cSplat = 0 ; cSplat < cGibs ; cSplat++ ) + { + CGib *pGib = CREATE_ENTITY( CGib, "gib" ); + + if ( g_Language.GetInt() == LANGUAGE_GERMAN ) + { + pGib->Spawn( "models/germangibs.mdl" ); + pGib->m_nBody = random->RandomInt(0,GERMAN_GIB_COUNT-1); + } + else + { + switch (eGibType) + { + case GIB_HUMAN: + // human pieces + pGib->Spawn( "models/gibs/hgibs.mdl" ); + pGib->m_nBody = random->RandomInt(1,HUMAN_GIB_COUNT-1);// start at one to avoid throwing random amounts of skulls (0th gib) + break; + case GIB_ALIEN: + // alien pieces + pGib->Spawn( "models/gibs/agibs.mdl" ); + pGib->m_nBody = random->RandomInt(0,ALIEN_GIB_COUNT-1); + break; + } + } + pGib->InitGib( pVictim, 300, 400); + } +} + +//========================================================= +// WaitTillLand - in order to emit their meaty scent from +// the proper location, gibs should wait until they stop +// bouncing to emit their scent. That's what this function +// does. +//========================================================= +void CGib::WaitTillLand ( void ) +{ + if (!IsInWorld()) + { + UTIL_Remove( this ); + return; + } + + if ( GetAbsVelocity() == vec3_origin ) + { + SetRenderColorA( 255 ); + m_nRenderMode = kRenderTransTexture; + if ( GetMoveType() != MOVETYPE_VPHYSICS ) + { + AddSolidFlags( FSOLID_NOT_SOLID ); + } + SetLocalAngularVelocity( vec3_angle ); + + SetNextThink( gpGlobals->curtime + m_lifeTime ); + SetThink ( &CGib::SUB_FadeOut ); + + if ( GetSprite() ) + { + CSprite *pSprite = dynamic_cast( GetSprite() ); + + if ( pSprite ) + { + //Adrian - Why am I doing this? Check InitPointGib for the answer! + if ( m_lifeTime == 0 ) + m_lifeTime = random->RandomFloat( 1, 3 ); + + pSprite->FadeAndDie( m_lifeTime ); + } + } + + if ( GetFlame() ) + { + CEntityFlame *pFlame = dynamic_cast< CEntityFlame*>( GetFlame() ); + + if ( pFlame ) + { + pFlame->SetLifetime( 1.0f ); + } + } + + // If you bleed, you stink! + if ( m_bloodColor != DONT_BLEED ) + { + // ok, start stinkin! + // FIXME: It's too easy to fill up the sound queue with all these meat sounds + // CSoundEnt::InsertSound ( SOUND_MEAT, GetAbsOrigin(), 384, 25 ); + } + } + else + { + // wait and check again in another half second. + SetNextThink( gpGlobals->curtime + 0.5f ); + } +} + +bool CGib::SUB_AllowedToFade( void ) +{ + if( VPhysicsGetObject() ) + { + if( VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD || GetEFlags() & EFL_IS_BEING_LIFTED_BY_BARNACLE ) + return false; + } + + CBasePlayer *pPlayer = ( AI_IsSinglePlayer() ) ? UTIL_GetLocalPlayer() : NULL; + + if ( pPlayer && pPlayer->FInViewCone( this ) && m_bForceRemove == false ) + { + return false; + } + + return true; +} + + +void CGib::DieThink ( void ) +{ + if ( GetSprite() ) + { + CSprite *pSprite = dynamic_cast( GetSprite() ); + + if ( pSprite ) + { + pSprite->FadeAndDie( 0.0 ); + } + } + + if ( GetFlame() ) + { + CEntityFlame *pFlame = dynamic_cast< CEntityFlame*>( GetFlame() ); + + if ( pFlame ) + { + pFlame->SetLifetime( 1.0f ); + } + } + + if ( g_pGameRules->IsMultiplayer() ) + { + UTIL_Remove( this ); + } + else + { + SetThink ( &CGib::SUB_FadeOut ); + SetNextThink( gpGlobals->curtime ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CGib::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) +{ + CBasePlayer *pPlayer = ToBasePlayer( pActivator ); + + if ( pPlayer ) + { + pPlayer->PickupObject( this ); + } +} + +//----------------------------------------------------------------------------- +// Physics Attacker +//----------------------------------------------------------------------------- +void CGib::SetPhysicsAttacker( CBasePlayer *pEntity, float flTime ) +{ + m_hPhysicsAttacker = pEntity; + m_flLastPhysicsInfluenceTime = flTime; +} + + +//----------------------------------------------------------------------------- +// Purpose: Keep track of physgun influence +//----------------------------------------------------------------------------- +void CGib::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) +{ + SetPhysicsAttacker( pPhysGunUser, gpGlobals->curtime ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CGib::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) +{ + SetPhysicsAttacker( pPhysGunUser, gpGlobals->curtime ); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +CBasePlayer *CGib::HasPhysicsAttacker( float dt ) +{ + if (gpGlobals->curtime - dt <= m_flLastPhysicsInfluenceTime) + { + return m_hPhysicsAttacker; + } + return NULL; +} + + +// +// Gib bounces on the ground or wall, sponges some blood down, too! +// +void CGib::BounceGibTouch ( CBaseEntity *pOther ) +{ + Vector vecSpot; + trace_t tr; + + IPhysicsObject *pPhysics = VPhysicsGetObject(); + + if ( pPhysics ) + return; + + //if ( random->RandomInt(0,1) ) + // return;// don't bleed everytime + if (GetFlags() & FL_ONGROUND) + { + SetAbsVelocity( GetAbsVelocity() * 0.9 ); + QAngle angles = GetLocalAngles(); + angles.x = 0; + angles.z = 0; + SetLocalAngles( angles ); + + QAngle angVel = GetLocalAngularVelocity(); + angVel.x = 0; + angVel.z = 0; + SetLocalAngularVelocity( vec3_angle ); + } + else + { + if ( g_Language.GetInt() != LANGUAGE_GERMAN && m_cBloodDecals > 0 && m_bloodColor != DONT_BLEED ) + { + vecSpot = GetAbsOrigin() + Vector ( 0 , 0 , 8 );//move up a bit, and trace down. + UTIL_TraceLine ( vecSpot, vecSpot + Vector ( 0, 0, -24 ), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr); + + UTIL_BloodDecalTrace( &tr, m_bloodColor ); + + m_cBloodDecals--; + } + + if ( m_material != matNone && random->RandomInt(0,2) == 0 ) + { + float volume; + float zvel = fabs(GetAbsVelocity().z); + + volume = 0.8f * MIN(1.0, ((float)zvel) / 450.0f); + + CBreakable::MaterialSoundRandom( entindex(), (Materials)m_material, volume ); + } + } +} + +// +// Sticky gib puts blood on the wall and stays put. +// +void CGib::StickyGibTouch ( CBaseEntity *pOther ) +{ + Vector vecSpot; + trace_t tr; + + SetThink ( &CGib::SUB_Remove ); + SetNextThink( gpGlobals->curtime + 10 ); + + if ( !FClassnameIs( pOther, "worldspawn" ) ) + { + SetNextThink( gpGlobals->curtime ); + return; + } + + UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + GetAbsVelocity() * 32, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr); + + UTIL_BloodDecalTrace( &tr, m_bloodColor ); + + Vector vecForward = tr.plane.normal * -1; + QAngle angles; + VectorAngles( vecForward, angles ); + SetLocalAngles( angles ); + SetAbsVelocity( vec3_origin ); + SetLocalAngularVelocity( vec3_angle ); + SetMoveType( MOVETYPE_NONE ); +} + +// +// Throw a chunk +// +void CGib::Spawn( const char *szGibModel ) +{ + SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); + SetFriction(0.55); // deading the bounce a bit + + // sometimes an entity inherits the edict from a former piece of glass, + // and will spawn using the same render FX or m_nRenderMode! bad! + SetRenderColorA( 255 ); + m_nRenderMode = kRenderNormal; + m_nRenderFX = kRenderFxNone; + + // hopefully this will fix the VELOCITY TOO LOW crap + m_takedamage = DAMAGE_EVENTS_ONLY; + SetSolid( SOLID_BBOX ); + AddSolidFlags( FSOLID_NOT_STANDABLE ); + SetCollisionGroup( COLLISION_GROUP_DEBRIS ); + + SetModel( szGibModel ); + +#ifdef HL1_DLL + SetElasticity( 1.0 ); + UTIL_SetSize( this, vec3_origin, vec3_origin ); +#endif//HL1_DLL + + SetNextThink( gpGlobals->curtime + 4 ); + m_lifeTime = 25; + SetTouch ( &CGib::BounceGibTouch ); + + m_bForceRemove = false; + + m_material = matNone; + m_cBloodDecals = 5;// how many blood decals this gib can place (1 per bounce until none remain). + +} + + +//----------------------------------------------------------------------------- +// Spawn a gib with a finite lifetime, after which it will fade out. +//----------------------------------------------------------------------------- +void CGib::Spawn( const char *szGibModel, float flLifetime ) +{ + Spawn( szGibModel ); + m_lifeTime = flLifetime; + SetThink ( &CGib::SUB_FadeOut ); + SetNextThink( gpGlobals->curtime + m_lifeTime ); +} + + +LINK_ENTITY_TO_CLASS( gib, CGib ); + +CBaseEntity *CreateRagGib( const char *szModel, const Vector &vecOrigin, const QAngle &vecAngles, const Vector &vecForce, float flFadeTime, bool bShouldIgnite ) +{ + CRagGib *pGib; + + pGib = (CRagGib*)CreateEntityByName( "raggib" ); + + pGib->SetLocalAngles( vecAngles ); + + if ( !pGib ) + { + Msg( "**Can't create ragdoll gib!\n" ); + return NULL; + } + + if ( bShouldIgnite ) + { + CBaseAnimating *pAnimating = pGib->GetBaseAnimating(); + if (pAnimating != NULL ) + { + pAnimating->Ignite( random->RandomFloat( 8.0, 12.0 ), false ); + } + } + + pGib->Spawn( szModel, vecOrigin, vecForce, flFadeTime ); + + return pGib; +} + +void CRagGib::Spawn( const char *szModel, const Vector &vecOrigin, const Vector &vecForce, float flFadeTime = 0.0 ) +{ + SetSolid( SOLID_BBOX ); + AddSolidFlags( FSOLID_NOT_SOLID ); + SetModel( szModel ); + UTIL_SetSize(this, vec3_origin, vec3_origin); + UTIL_SetOrigin( this, vecOrigin ); + if ( !BecomeRagdollOnClient( vecForce ) ) + { + AddSolidFlags( FSOLID_NOT_STANDABLE ); + RemoveSolidFlags( FSOLID_NOT_SOLID ); + if( flFadeTime > 0.0 ) + { + SUB_StartFadeOut( flFadeTime ); + } + } +} + +LINK_ENTITY_TO_CLASS( raggib, CRagGib ); -- cgit v1.2.3