You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
240 lines
7.0 KiB
240 lines
7.0 KiB
![]()
4 years ago
|
//========= 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 );
|