diff options
Diffstat (limited to 'game/client/tf/c_tf_stickybolt.cpp')
| -rw-r--r-- | game/client/tf/c_tf_stickybolt.cpp | 240 |
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 |