summaryrefslogtreecommitdiff
path: root/game/client/c_stickybolt.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/c_stickybolt.cpp
downloadarchived-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.cpp176
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