summaryrefslogtreecommitdiff
path: root/game/client/tf/c_tf_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/tf/c_tf_stickybolt.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/client/tf/c_tf_stickybolt.cpp')
-rw-r--r--game/client/tf/c_tf_stickybolt.cpp240
1 files changed, 240 insertions, 0 deletions
diff --git a/game/client/tf/c_tf_stickybolt.cpp b/game/client/tf/c_tf_stickybolt.cpp
new file mode 100644
index 0000000..19b89c6
--- /dev/null
+++ b/game/client/tf/c_tf_stickybolt.cpp
@@ -0,0 +1,240 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: TF version of the stickybolt code.
+// I broke off our own version because I didn't want to accidentally break HL2.
+// $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"
+#include "c_tf_player.h"
+#include "GameEventListener.h"
+#include "tf_shareddefs.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+extern IPhysicsSurfaceProps *physprops;
+IPhysicsObject *GetWorldPhysObject( void );
+
+//-----------------------------------------------------------------------------
+// Purpose: Creates a Bolt in the world and Ragdolls
+// For Attached Bolts on players look at hud_bowcharge "arrow_impact" which should be moved here
+//-----------------------------------------------------------------------------
+void CreateCrossbowBoltTF( const Vector &vecOrigin, const Vector &vecDirection, const int iFlags, unsigned char nColor )
+{
+ const char* pszModelName = NULL;
+ float flDirOffset = 5.0f;
+ float flScale = 1.0f;
+ float flLifeTime = 30.0f;
+ switch ( iFlags )
+ {
+ case TF_PROJECTILE_STICKY_BALL:
+ pszModelName = g_pszArrowModels[MODEL_SNOWBALL];
+ break;
+ case TF_PROJECTILE_ARROW:
+ pszModelName = g_pszArrowModels[MODEL_ARROW_REGULAR];
+ break;
+ case TF_PROJECTILE_BUILDING_REPAIR_BOLT:
+ pszModelName = g_pszArrowModels[MODEL_ARROW_BUILDING_REPAIR];
+ flDirOffset = -2.0f;
+ break;
+ case TF_PROJECTILE_FESTIVE_ARROW:
+ pszModelName = g_pszArrowModels[MODEL_FESTIVE_ARROW_REGULAR];
+ break;
+ case TF_PROJECTILE_HEALING_BOLT:
+#ifdef STAGING_ONLY
+ case TF_PROJECTILE_MILK_BOLT:
+#endif
+ pszModelName = g_pszArrowModels[MODEL_SYRINGE];
+ flDirOffset = 0.0f;
+ flScale = 3.0f;
+ break;
+ case TF_PROJECTILE_FESTIVE_HEALING_BOLT:
+ pszModelName = g_pszArrowModels[MODEL_FESTIVE_HEALING_BOLT];
+ flScale = 2.5f;
+ break;
+ case TF_PROJECTILE_BREAD_MONSTER:
+ case TF_PROJECTILE_BREADMONSTER_JARATE:
+ case TF_PROJECTILE_BREADMONSTER_MADMILK:
+ pszModelName = g_pszArrowModels[MODEL_BREAD_MONSTER];
+ flLifeTime = 8.0f;
+ flScale = 2.5f;
+ break;
+ case TF_PROJECTILE_GRAPPLINGHOOK:
+ pszModelName = g_pszArrowModels[MODEL_GRAPPLINGHOOK];
+ flDirOffset = 0.0f;
+ flLifeTime = 0.1f;
+ break;
+#ifdef STAGING_ONLY
+ case TF_PROJECTILE_THROWING_KNIFE:
+ pszModelName = g_pszArrowModels[MODEL_THROWING_KNIFE];
+ break;
+ case TF_PROJECTILE_SNIPERBULLET:
+ pszModelName = g_pszArrowModels[MODEL_SYRINGE];
+ break;
+#endif // STAGING_ONLY
+ default:
+ // Unsupported Model
+ Assert( 0 );
+ pszModelName = g_pszArrowModels[MODEL_ARROW_REGULAR];
+ return;
+ }
+ model_t *pModel = (model_t *)engine->LoadModel( pszModelName );
+
+ QAngle vAngles;
+ VectorAngles( vecDirection, vAngles );
+ C_LocalTempEntity *arrow = tempents->SpawnTempModel( pModel, vecOrigin - vecDirection * flDirOffset, vAngles, Vector(0, 0, 0 ), flLifeTime, FTENT_NONE );
+
+ if ( arrow )
+ {
+ arrow->SetModelScale( flScale );
+ arrow->m_nSkin = nColor;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void StickRagdollNowTF(
+ const Vector &vecOrigin,
+ const Vector &vecDirection,
+ const ClientEntityHandle_t &entHandle,
+ const int boneIndexAttached,
+ const int physicsBoneIndex,
+ const int iShooterIndex,
+ const int iHitGroup,
+ const int iVictim,
+ const int iFlags,
+ unsigned char nColor
+) {
+ Ray_t shotRay;
+ trace_t tr;
+
+ UTIL_TraceLine( vecOrigin - vecDirection * 16, vecOrigin + vecDirection * 64, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr );
+ if ( tr.surface.flags & SURF_SKY )
+ return;
+
+ C_BaseAnimating *pModel = dynamic_cast< C_BaseAnimating * >( entHandle.Get() );
+ if ( pModel )
+ {
+ IPhysicsObject *pPhysicsObject = NULL;
+ ragdoll_t *pRagdollT = NULL;
+ if ( pModel->m_pRagdoll )
+ {
+ CRagdoll *pCRagdoll = dynamic_cast < CRagdoll * > ( pModel->m_pRagdoll );
+ if ( pCRagdoll )
+ {
+ pRagdollT = pCRagdoll->GetRagdoll();
+ if ( physicsBoneIndex < pRagdollT->listCount )
+ {
+ pPhysicsObject = pRagdollT->list[physicsBoneIndex].pObject;
+ }
+ }
+ }
+
+ IPhysicsObject *pReference = GetWorldPhysObject();
+
+ if ( pReference == NULL || pPhysicsObject == NULL )
+ return;
+
+ float frand = (float) rand() / VALVE_RAND_MAX;
+ Vector adjust = vecDirection*7 + vecDirection * frand * 7;
+
+ Vector vecBonePos;
+ QAngle boneAngles;
+ pPhysicsObject->GetPosition( &vecBonePos, &boneAngles );
+
+ QAngle angles;
+ pPhysicsObject->SetPosition( vecOrigin-adjust, boneAngles, true );
+
+ pPhysicsObject->EnableMotion( false );
+
+ int nNodeIndex = pRagdollT->list[physicsBoneIndex].parentIndex;
+
+ // find largest mass bone
+ float flTargetMass = 0;
+ for ( int i = 0; i < pRagdollT->listCount; i++ )
+ {
+ flTargetMass = MAX(flTargetMass, pRagdollT->list[i].pObject->GetMass() );
+ }
+
+ // walk the chain of bones from the pinned bone to the root and set each to the max mass
+ // This helps transmit the impulses required to stabilize the constraint -- it keeps the body from
+ // leaving the constraint because of some high mass bone hanging at the other end of the chain
+ while ( nNodeIndex >= 0 )
+ {
+ if ( pRagdollT->list[nNodeIndex].pConstraint )
+ {
+ float flCurrentMass = pRagdollT->list[nNodeIndex].pObject->GetMass();
+ flCurrentMass = MAX(flCurrentMass, flTargetMass);
+ pRagdollT->list[nNodeIndex].pObject->SetMass( flCurrentMass );
+ }
+ nNodeIndex = pRagdollT->list[nNodeIndex].parentIndex;
+ }
+ }
+
+ UTIL_ImpactTrace( &tr, 0 );
+
+ CreateCrossbowBoltTF( vecOrigin, vecDirection, iFlags, nColor );
+
+ //Achievement stuff.
+ if ( iHitGroup == HITGROUP_HEAD )
+ {
+ CTFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
+
+ if ( pLocalPlayer && pLocalPlayer->entindex() == iShooterIndex )
+ {
+ CTFPlayer *pVictim = ToTFPlayer( UTIL_PlayerByIndex( iVictim ) );
+
+ if ( pVictim && pVictim->IsPlayerClass( TF_CLASS_HEAVYWEAPONS ) )
+ {
+ IGameEvent *event = gameeventmanager->CreateEvent( "player_pinned" );
+
+ if ( event )
+ {
+ gameeventmanager->FireEventClientSide( event );
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void StickyBoltCallbackTF( const CEffectData &data )
+{
+ StickRagdollNowTF(
+ data.m_vOrigin,
+ data.m_vNormal,
+ data.m_hEntity,
+ data.m_nAttachmentIndex,
+ data.m_nMaterial,
+ data.m_nHitBox,
+ data.m_nDamageType,
+ data.m_nSurfaceProp,
+ data.m_fFlags,
+ data.m_nColor
+ );
+}
+
+DECLARE_CLIENT_EFFECT( "TFBoltImpact", StickyBoltCallbackTF ); \ No newline at end of file