diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/c_stickybolt.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/client/c_stickybolt.cpp')
| -rw-r--r-- | game/client/c_stickybolt.cpp | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/game/client/c_stickybolt.cpp b/game/client/c_stickybolt.cpp new file mode 100644 index 0000000..bf3c72e --- /dev/null +++ b/game/client/c_stickybolt.cpp @@ -0,0 +1,176 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Implements the Sticky Bolt code. This constraints ragdolls to the world +// after being hit by a crossbow bolt. If something here is acting funny +// let me know - Adrian. +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $Log: $ +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "c_basetempentity.h" +#include "fx.h" +#include "decals.h" +#include "iefx.h" +#include "engine/IEngineSound.h" +#include "materialsystem/imaterialvar.h" +#include "IEffects.h" +#include "engine/IEngineTrace.h" +#include "vphysics/constraints.h" +#include "engine/ivmodelinfo.h" +#include "tempent.h" +#include "c_te_legacytempents.h" +#include "engine/ivdebugoverlay.h" +#include "c_te_effect_dispatch.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +extern IPhysicsSurfaceProps *physprops; +IPhysicsObject *GetWorldPhysObject( void ); + +extern ITempEnts* tempents; + +class CRagdollBoltEnumerator : public IPartitionEnumerator +{ +public: + //Forced constructor + CRagdollBoltEnumerator( Ray_t& shot, Vector vOrigin ) + { + m_rayShot = shot; + m_vWorld = vOrigin; + } + + //Actual work code + IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ) + { + C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( pHandleEntity->GetRefEHandle() ); + if ( pEnt == NULL ) + return ITERATION_CONTINUE; + + C_BaseAnimating *pModel = static_cast< C_BaseAnimating * >( pEnt ); + + if ( pModel == NULL ) + return ITERATION_CONTINUE; + + trace_t tr; + enginetrace->ClipRayToEntity( m_rayShot, MASK_SHOT, pModel, &tr ); + + IPhysicsObject *pPhysicsObject = NULL; + + //Find the real object we hit. + if( tr.physicsbone >= 0 ) + { + if ( pModel->m_pRagdoll ) + { + CRagdoll *pCRagdoll = dynamic_cast < CRagdoll * > ( pModel->m_pRagdoll ); + + if ( pCRagdoll ) + { + ragdoll_t *pRagdollT = pCRagdoll->GetRagdoll(); + + if ( tr.physicsbone < pRagdollT->listCount ) + { + pPhysicsObject = pRagdollT->list[tr.physicsbone].pObject; + } + } + } + } + + if ( pPhysicsObject == NULL ) + return ITERATION_CONTINUE; + + if ( tr.fraction < 1.0 ) + { + IPhysicsObject *pReference = GetWorldPhysObject(); + + if ( pReference == NULL || pPhysicsObject == NULL ) + return ITERATION_CONTINUE; + + float flMass = pPhysicsObject->GetMass(); + pPhysicsObject->SetMass( flMass * 2 ); + + constraint_ballsocketparams_t ballsocket; + ballsocket.Defaults(); + + pReference->WorldToLocal( &ballsocket.constraintPosition[0], m_vWorld ); + pPhysicsObject->WorldToLocal( &ballsocket.constraintPosition[1], tr.endpos ); + + physenv->CreateBallsocketConstraint( pReference, pPhysicsObject, NULL, ballsocket ); + + //Play a sound + CPASAttenuationFilter filter( pEnt ); + + EmitSound_t ep; + ep.m_nChannel = CHAN_VOICE; + ep.m_pSoundName = "Weapon_Crossbow.BoltSkewer"; + ep.m_flVolume = 1.0f; + ep.m_SoundLevel = SNDLVL_NORM; + ep.m_pOrigin = &pEnt->GetAbsOrigin(); + + C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, ep ); + + return ITERATION_STOP; + } + + return ITERATION_CONTINUE; + } + +private: + Ray_t m_rayShot; + Vector m_vWorld; +}; + +void CreateCrossbowBolt( const Vector &vecOrigin, const Vector &vecDirection ) +{ + model_t *pModel = (model_t *)engine->LoadModel( "models/crossbow_bolt.mdl" ); + + QAngle vAngles; + + VectorAngles( vecDirection, vAngles ); + + if ( gpGlobals->maxClients > 1 ) + { + tempents->SpawnTempModel( pModel, vecOrigin - vecDirection * 8, vAngles, Vector(0, 0, 0 ), 30.0f, FTENT_NONE ); + } + else + { + tempents->SpawnTempModel( pModel, vecOrigin - vecDirection * 8, vAngles, Vector(0, 0, 0 ), 1, FTENT_NEVERDIE ); + } +} + +void StickRagdollNow( const Vector &vecOrigin, const Vector &vecDirection ) +{ + Ray_t shotRay; + trace_t tr; + + UTIL_TraceLine( vecOrigin, vecOrigin + vecDirection * 16, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr ); + + if ( tr.surface.flags & SURF_SKY ) + return; + + Vector vecEnd = vecOrigin - vecDirection * 128; + + shotRay.Init( vecOrigin, vecEnd ); + + CRagdollBoltEnumerator ragdollEnum( shotRay, vecOrigin ); + ::partition->EnumerateElementsAlongRay( PARTITION_CLIENT_RESPONSIVE_EDICTS, shotRay, false, &ragdollEnum ); + + CreateCrossbowBolt( vecOrigin, vecDirection ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : &data - +//----------------------------------------------------------------------------- +void StickyBoltCallback( const CEffectData &data ) +{ + StickRagdollNow( data.m_vOrigin, data.m_vNormal ); +} + +DECLARE_CLIENT_EFFECT( "BoltImpact", StickyBoltCallback );
\ No newline at end of file |