mirror of
https://github.com/celisej567/source-engine.git
synced 2026-01-05 22:09:59 +03:00
1
This commit is contained in:
649
game/shared/tf/tf_dropped_weapon.cpp
Normal file
649
game/shared/tf/tf_dropped_weapon.cpp
Normal file
@@ -0,0 +1,649 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
#include "tf_dropped_weapon.h"
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
#include "c_tf_player.h"
|
||||
#include "model_types.h"
|
||||
#endif // CLIENT_DLL
|
||||
|
||||
#ifdef GAME_DLL
|
||||
#include "tf_player.h"
|
||||
#include "tf_weaponbase.h"
|
||||
#include "tf_weapon_medigun.h"
|
||||
#include "tf_gamerules.h"
|
||||
#include "tf_weapon_bottle.h"
|
||||
#endif // GAME_DLL
|
||||
|
||||
|
||||
#ifdef GAME_DLL
|
||||
ConVar tf_dropped_weapon_lifetime( "tf_dropped_weapon_lifetime", "30", FCVAR_CHEAT );
|
||||
|
||||
EXTERN_SEND_TABLE( DT_ScriptCreatedItem );
|
||||
|
||||
LINK_ENTITY_TO_CLASS( tf_dropped_weapon, CTFDroppedWeapon );
|
||||
|
||||
PRECACHE_REGISTER( tf_dropped_weapon );
|
||||
#else
|
||||
EXTERN_RECV_TABLE( DT_ScriptCreatedItem );
|
||||
#endif
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( TFDroppedWeapon, DT_TFDroppedWeapon );
|
||||
|
||||
BEGIN_NETWORK_TABLE( CTFDroppedWeapon, DT_TFDroppedWeapon )
|
||||
#if !defined( CLIENT_DLL )
|
||||
SendPropDataTable( SENDINFO_DT(m_Item), &REFERENCE_SEND_TABLE(DT_ScriptCreatedItem) ),
|
||||
SendPropFloat( SENDINFO( m_flChargeLevel ) ),
|
||||
#else
|
||||
RecvPropDataTable( RECVINFO_DT(m_Item), 0, &REFERENCE_RECV_TABLE(DT_ScriptCreatedItem) ),
|
||||
RecvPropFloat( RECVINFO( m_flChargeLevel ) ),
|
||||
#endif
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
IMPLEMENT_AUTO_LIST( IDroppedWeaponAutoList );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
CTFDroppedWeapon::CTFDroppedWeapon()
|
||||
#ifdef GAME_DLL
|
||||
: m_nClip( 0 )
|
||||
, m_nAmmo( 0 )
|
||||
, m_nDetonated( 0 )
|
||||
, m_flEnergy( 0.f )
|
||||
, m_flEffectBarRegenTime( 0.f )
|
||||
#endif
|
||||
{
|
||||
#ifdef CLIENT_DLL
|
||||
m_pGlowEffect = NULL;
|
||||
m_bShouldGlowForLocalPlayer = false;
|
||||
m_flOldChargeLevel = 0.f;
|
||||
#endif // CLIENT_DLL
|
||||
|
||||
m_flChargeLevel.Set( 0.f );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
CTFDroppedWeapon::~CTFDroppedWeapon()
|
||||
{
|
||||
#ifdef CLIENT_DLL
|
||||
if ( m_worldmodelStatTrakAddon )
|
||||
{
|
||||
m_worldmodelStatTrakAddon->Remove();
|
||||
}
|
||||
|
||||
if ( m_effect )
|
||||
{
|
||||
ParticleProp()->StopEmission( m_effect );
|
||||
m_effect = NULL;
|
||||
}
|
||||
|
||||
DestroyGlowEffect();
|
||||
#endif // CLIENT_DLL
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFDroppedWeapon::Spawn()
|
||||
{
|
||||
#ifdef GAME_DLL
|
||||
SetModel( STRING( GetModelName() ) );
|
||||
|
||||
SetMoveType( MOVETYPE_FLYGRAVITY );
|
||||
SetSolid( SOLID_BBOX );
|
||||
SetBlocksLOS( false );
|
||||
AddEFlags( EFL_NO_ROTORWASH_PUSH );
|
||||
|
||||
// This will make them not collide with the player, but will collide
|
||||
// against other items + weapons
|
||||
SetCollisionGroup( COLLISION_GROUP_DEBRIS );
|
||||
CollisionProp()->UseTriggerBounds( true, ITEM_PICKUP_BOX_BLOAT );
|
||||
|
||||
// Create the object in the physics system
|
||||
int nSolidFlags = GetSolidFlags() | FSOLID_NOT_STANDABLE;
|
||||
|
||||
if ( VPhysicsInitNormal( SOLID_VPHYSICS, nSolidFlags, false ) == NULL )
|
||||
{
|
||||
SetSolid( SOLID_BBOX );
|
||||
AddSolidFlags( nSolidFlags );
|
||||
|
||||
// If it's not physical, drop it to the floor
|
||||
if ( UTIL_DropToFloor( this, MASK_SOLID ) == 0 )
|
||||
{
|
||||
Warning( "Item %s fell out of level at %f,%f,%f\n", GetClassname(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z);
|
||||
UTIL_Remove( this );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GAME_DLL
|
||||
BaseClass::Spawn();
|
||||
|
||||
#ifdef GAME_DLL
|
||||
SetContextThink( &CTFDroppedWeapon::SUB_Remove, gpGlobals->curtime + tf_dropped_weapon_lifetime.GetFloat(), "RemoveThink" );
|
||||
#endif // GAME_DLL
|
||||
}
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFDroppedWeapon::OnPreDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnPreDataChanged( updateType );
|
||||
|
||||
m_flOldChargeLevel = m_flChargeLevel;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFDroppedWeapon::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
// if its startrak attach a model to it
|
||||
if ( m_Item.GetItemID() != INVALID_ITEM_ID )
|
||||
{
|
||||
int iStrangeType = -1;
|
||||
for ( int i = 0; i < GetKillEaterAttrCount(); i++ )
|
||||
{
|
||||
if ( m_Item.FindAttribute( GetKillEaterAttr_Score( i ) ) )
|
||||
{
|
||||
iStrangeType = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// It's strange, does it have module as well?
|
||||
if ( iStrangeType != -1 )
|
||||
{
|
||||
CAttribute_String attrModule;
|
||||
static CSchemaAttributeDefHandle pAttr_module( "weapon_uses_stattrak_module" );
|
||||
if ( m_Item.FindAttribute( pAttr_module, &attrModule ) && attrModule.has_value() )
|
||||
{
|
||||
static CSchemaAttributeDefHandle pAttr_moduleScale( "weapon_stattrak_module_scale" );
|
||||
// Does it have a stat track module
|
||||
float flScale = 1.0f;
|
||||
uint32 unFloatAsUint32 = 1;
|
||||
if ( m_Item.FindAttribute( pAttr_moduleScale, &unFloatAsUint32 ) )
|
||||
{
|
||||
flScale = (float&)unFloatAsUint32;
|
||||
}
|
||||
|
||||
C_BaseAnimating *pStatTrakEnt = new class C_BaseAnimating;
|
||||
if ( pStatTrakEnt && pStatTrakEnt->InitializeAsClientEntity( "models/weapons/c_models/stattrack.mdl", RENDER_GROUP_OPAQUE_ENTITY ) )
|
||||
{
|
||||
pStatTrakEnt->AddEffects( EF_BONEMERGE );
|
||||
pStatTrakEnt->AddEffects( EF_BONEMERGE_FASTCULL );
|
||||
|
||||
m_worldmodelStatTrakAddon = pStatTrakEnt;
|
||||
pStatTrakEnt->SetParent( this );
|
||||
pStatTrakEnt->SetLocalOrigin( vec3_origin );
|
||||
pStatTrakEnt->UpdatePartitionListEntry();
|
||||
pStatTrakEnt->CollisionProp()->MarkPartitionHandleDirty();
|
||||
pStatTrakEnt->SetModelScale( flScale );
|
||||
pStatTrakEnt->UpdateVisibility();
|
||||
|
||||
pStatTrakEnt->SetBodygroup( 1, 1 );
|
||||
|
||||
pStatTrakEnt->m_nSkin = m_Item.GetTeamNumber(); // Use the "Sad" skin
|
||||
|
||||
//pStatTrakEnt->SetModelScale( 2.0f );
|
||||
// //if ( !cl_righthand.GetBool() )
|
||||
// //{
|
||||
// // pStatTrakEnt->SetBodygroup( 0, 1 ); // use a special mirror-image stattrak module that appears correct for lefties
|
||||
// //}
|
||||
|
||||
RemoveEffects( EF_NODRAW );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Normal Attached models (ie festive lights)
|
||||
const CEconItemDefinition *pItemDef = m_Item.GetItemDefinition();
|
||||
if ( pItemDef )
|
||||
{
|
||||
// Update the state of additional model attachments
|
||||
m_vecAttachedModels.Purge();
|
||||
int iTeamNumber = m_Item.GetTeamNumber();
|
||||
int iAttachedModels = pItemDef->GetNumAttachedModels( iTeamNumber );
|
||||
for ( int i = 0; i < iAttachedModels; i++ )
|
||||
{
|
||||
attachedmodel_t *pModel = pItemDef->GetAttachedModelData( iTeamNumber, i );
|
||||
|
||||
int iModelIndex = modelinfo->GetModelIndex( pModel->m_pszModelName );
|
||||
if ( iModelIndex >= 0 )
|
||||
{
|
||||
AttachedModelData_t attachedModelData;
|
||||
attachedModelData.m_pModel = modelinfo->GetModel( iModelIndex );
|
||||
attachedModelData.m_iModelDisplayFlags = pModel->m_iModelDisplayFlags;
|
||||
m_vecAttachedModels.AddToTail( attachedModelData );
|
||||
}
|
||||
}
|
||||
|
||||
// Festive
|
||||
{
|
||||
static CSchemaAttributeDefHandle pAttr_is_festivized( "is_festivized" );
|
||||
if ( pAttr_is_festivized && m_Item.FindAttribute( pAttr_is_festivized ) )
|
||||
{
|
||||
int iAttachedFestiveModels = pItemDef->GetNumAttachedModelsFestivized( iTeamNumber );
|
||||
if ( iAttachedFestiveModels )
|
||||
{
|
||||
|
||||
for ( int i = 0; i < iAttachedFestiveModels; i++ )
|
||||
{
|
||||
attachedmodel_t *pModel = pItemDef->GetAttachedModelDataFestivized( iTeamNumber, i );
|
||||
|
||||
int iModelIndex = modelinfo->GetModelIndex( pModel->m_pszModelName );
|
||||
if ( iModelIndex >= 0 )
|
||||
{
|
||||
AttachedModelData_t attachedModelData;
|
||||
attachedModelData.m_pModel = modelinfo->GetModel( iModelIndex );
|
||||
attachedModelData.m_iModelDisplayFlags = pModel->m_iModelDisplayFlags;
|
||||
m_vecAttachedModels.AddToTail( attachedModelData );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetupParticleEffect();
|
||||
}
|
||||
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
|
||||
if ( m_flOldChargeLevel != m_flChargeLevel )
|
||||
{
|
||||
float flRem = fmod( m_flChargeLevel, 0.1f );
|
||||
if ( flRem < 0.01f )
|
||||
{
|
||||
ParticleProp()->Create( "drain_effect", PATTACH_POINT_FOLLOW, LookupAttachment( "muzzle" ) );
|
||||
EmitSound( "Medigun.DrainCharge" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFDroppedWeapon::ModifyEmitSoundParams( EmitSound_t ¶ms )
|
||||
{
|
||||
params.m_nPitch = RemapVal( m_flChargeLevel, 0.f, 1.f, 90, 180 );
|
||||
params.m_nFlags |= SND_CHANGE_PITCH;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFDroppedWeapon::OnInternalDrawModel( ClientModelRenderInfo_t *pInfo )
|
||||
{
|
||||
if ( !BaseClass::OnInternalDrawModel( pInfo ) )
|
||||
return false;
|
||||
|
||||
// Draw Attached Models
|
||||
// Draw our attached models as well
|
||||
for ( int i = 0; i < m_vecAttachedModels.Size(); i++ )
|
||||
{
|
||||
const AttachedModelData_t& attachedModel = m_vecAttachedModels[i];
|
||||
|
||||
if ( attachedModel.m_pModel && ( attachedModel.m_iModelDisplayFlags & kAttachedModelDisplayFlag_WorldModel ) )
|
||||
{
|
||||
ClientModelRenderInfo_t infoAttached = *pInfo;
|
||||
|
||||
infoAttached.pRenderable = this;
|
||||
infoAttached.instance = MODEL_INSTANCE_INVALID;
|
||||
infoAttached.entity_index = this->index;
|
||||
infoAttached.pModel = attachedModel.m_pModel;
|
||||
|
||||
infoAttached.pModelToWorld = &infoAttached.modelToWorld;
|
||||
|
||||
// Turns the origin + angles into a matrix
|
||||
AngleMatrix( infoAttached.angles, infoAttached.origin, infoAttached.modelToWorld );
|
||||
|
||||
DrawModelState_t state;
|
||||
matrix3x4_t *pBoneToWorld;
|
||||
bool bMarkAsDrawn = modelrender->DrawModelSetup( infoAttached, &state, NULL, &pBoneToWorld );
|
||||
DoInternalDrawModel( &infoAttached, ( bMarkAsDrawn && ( infoAttached.flags & STUDIO_RENDER ) ) ? &state : NULL, pBoneToWorld );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Get an econ material override for the given team.
|
||||
// Returns: NULL if there is no override.
|
||||
//-----------------------------------------------------------------------------
|
||||
IMaterial *CTFDroppedWeapon::GetEconWeaponMaterialOverride( int iTeam )
|
||||
{
|
||||
CEconItemView *pItemView = GetItem();
|
||||
if ( !pItemView )
|
||||
return NULL;
|
||||
|
||||
return pItemView->GetMaterialOverride( iTeam );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFDroppedWeapon::SetupParticleEffect()
|
||||
{
|
||||
attachedparticlesystem_t *pParticleSystem = NULL;
|
||||
|
||||
// do community_sparkle effect if this is a community item?
|
||||
const int iQualityParticleType = m_Item.GetQualityParticleType();
|
||||
if ( iQualityParticleType > 0 )
|
||||
{
|
||||
pParticleSystem = GetItemSchema()->GetAttributeControlledParticleSystem( iQualityParticleType );
|
||||
}
|
||||
|
||||
if ( !pParticleSystem )
|
||||
{
|
||||
// does this hat even have a particle effect
|
||||
static CSchemaAttributeDefHandle pAttrDef_AttachParticleEffect( "attach particle effect" );
|
||||
uint32 iValue = 0;
|
||||
if ( !m_Item.FindAttribute( pAttrDef_AttachParticleEffect, &iValue ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const float& value_as_float = (float&)iValue;
|
||||
pParticleSystem = GetItemSchema()->GetAttributeControlledParticleSystem( value_as_float );
|
||||
}
|
||||
|
||||
// failed to find any particle effect
|
||||
if ( !pParticleSystem )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Team Color
|
||||
if ( GetTeamNumber() == TF_TEAM_BLUE && V_stristr( pParticleSystem->pszSystemName, "_teamcolor_red" ))
|
||||
{
|
||||
static char pBlue[256];
|
||||
V_StrSubst( pParticleSystem->pszSystemName, "_teamcolor_red", "_teamcolor_blue", pBlue, 256 );
|
||||
pParticleSystem = GetItemSchema()->FindAttributeControlledParticleSystem( pBlue );
|
||||
if ( !pParticleSystem )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// World model effect
|
||||
// Stop it on both the viewmodel & the world model, because it may be removed due to first/thirdperson switch
|
||||
static char pszTempName[256];
|
||||
const char* pszSystemName = pParticleSystem->pszSystemName;
|
||||
|
||||
// Weapon Remap for a Base Effect to be used on a specific weapon
|
||||
if ( pParticleSystem->bUseSuffixName && m_Item.GetItemDefinition()->GetParticleSuffix() )
|
||||
{
|
||||
V_strcpy_safe( pszTempName, pszSystemName );
|
||||
V_strcat_safe( pszTempName, "_" );
|
||||
V_strcat_safe( pszTempName, m_Item.GetItemDefinition()->GetParticleSuffix() );
|
||||
pszSystemName = pszTempName;
|
||||
}
|
||||
|
||||
m_effect = ParticleProp()->Create( pszSystemName, PATTACH_ABSORIGIN_FOLLOW );
|
||||
if ( m_effect )
|
||||
{
|
||||
for ( int i=0; i<ARRAYSIZE( pParticleSystem->pszControlPoints ); ++i )
|
||||
{
|
||||
const char *pszAttachmentName = pParticleSystem->pszControlPoints[i];
|
||||
if ( pszAttachmentName && pszAttachmentName[0] != '\0' )
|
||||
{
|
||||
ParticleProp()->AddControlPoint( m_effect, i, this, PATTACH_POINT_FOLLOW, pParticleSystem->pszControlPoints[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFDroppedWeapon::ClientThink()
|
||||
{
|
||||
C_TFPlayer *pTFPlayer = C_TFPlayer::GetLocalTFPlayer();
|
||||
bool bShouldGlowForLocalPlayer = pTFPlayer && pTFPlayer->IsAlive() && pTFPlayer->CanPickupDroppedWeapon( this ) && pTFPlayer->IsLineOfSightClear( this );
|
||||
if ( bShouldGlowForLocalPlayer )
|
||||
{
|
||||
// ignore the item that the player's equipped
|
||||
int iLoadoutSlot = 0;
|
||||
CTFItemDefinition *pItemDef = m_Item.GetStaticData();
|
||||
if ( pItemDef )
|
||||
{
|
||||
int iClass = pTFPlayer->GetPlayerClass()->GetClassIndex();
|
||||
iLoadoutSlot = pItemDef->GetLoadoutSlot( iClass );
|
||||
CTFWeaponBase *pWeapon = dynamic_cast< CTFWeaponBase* >( pTFPlayer->GetEntityForLoadoutSlot( iLoadoutSlot ) );
|
||||
if ( pWeapon && *pWeapon->GetAttributeContainer()->GetItem() == m_Item )
|
||||
{
|
||||
bShouldGlowForLocalPlayer = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_bShouldGlowForLocalPlayer != bShouldGlowForLocalPlayer )
|
||||
{
|
||||
m_bShouldGlowForLocalPlayer = bShouldGlowForLocalPlayer;
|
||||
UpdateGlowEffect();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFDroppedWeapon::UpdateGlowEffect( void )
|
||||
{
|
||||
// destroy the existing effect
|
||||
if ( m_pGlowEffect )
|
||||
{
|
||||
DestroyGlowEffect();
|
||||
}
|
||||
|
||||
// create a new effect if we have a cart
|
||||
if ( m_bShouldGlowForLocalPlayer )
|
||||
{
|
||||
Vector color = Vector( 0.745f, 0.773f, 0.157f );
|
||||
m_pGlowEffect = new CGlowObject( this, color, 1.0, true );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFDroppedWeapon::DestroyGlowEffect( void )
|
||||
{
|
||||
if ( m_pGlowEffect )
|
||||
{
|
||||
delete m_pGlowEffect;
|
||||
m_pGlowEffect = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFDroppedWeapon::IsVisibleToTargetID( void ) const
|
||||
{
|
||||
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
|
||||
if ( !pLocalPlayer )
|
||||
return false;
|
||||
return pLocalPlayer->CanPickupDroppedWeapon( this );
|
||||
}
|
||||
|
||||
#endif // CLIENT_DLL
|
||||
|
||||
#ifdef GAME_DLL
|
||||
#define MAX_DROPPED_WEAPON_COUNT 32
|
||||
//-----------------------------------------------------------------------------
|
||||
CTFDroppedWeapon *CTFDroppedWeapon::Create( CTFPlayer *pLastOwner, const Vector &vecOrigin, const QAngle &vecAngles, const char *pszModelName, const CEconItemView *pItem )
|
||||
{
|
||||
// don't drop weapon in MVM
|
||||
if ( TFGameRules()->IsMannVsMachineMode() )
|
||||
return NULL;
|
||||
|
||||
int nNumRemoved = 0;
|
||||
|
||||
// make sure we clean up the same item that was dropped before dropping a new one
|
||||
for ( int i=0; i<CTFDroppedWeapon::AutoList().Count(); ++i )
|
||||
{
|
||||
CTFDroppedWeapon *pDroppedWeapon = static_cast< CTFDroppedWeapon* >( CTFDroppedWeapon::AutoList()[i] );
|
||||
if ( pDroppedWeapon->m_Item.GetItemID() == pItem->GetItemID() && pDroppedWeapon->m_Item.GetItemDefIndex() == pItem->GetItemDefIndex() && pDroppedWeapon->m_hPlayer.Get() == pLastOwner )
|
||||
{
|
||||
UTIL_Remove( pDroppedWeapon );
|
||||
nNumRemoved++;
|
||||
}
|
||||
}
|
||||
|
||||
// if we're still going over max dropped weapon count, remove more items
|
||||
int nNumToRemove = CTFDroppedWeapon::AutoList().Count() - nNumRemoved - MAX_DROPPED_WEAPON_COUNT;
|
||||
for ( int i=0; i<CTFDroppedWeapon::AutoList().Count() && nNumToRemove > 0; ++i )
|
||||
{
|
||||
CTFDroppedWeapon *pDroppedWeapon = static_cast< CTFDroppedWeapon* >( CTFDroppedWeapon::AutoList()[i] );
|
||||
|
||||
// skip item that we already marked for deletion
|
||||
if ( pDroppedWeapon->IsMarkedForDeletion() )
|
||||
continue;
|
||||
|
||||
UTIL_Remove( pDroppedWeapon );
|
||||
nNumToRemove--;
|
||||
}
|
||||
|
||||
CTFDroppedWeapon *pDroppedWeapon = static_cast<CTFDroppedWeapon*>( CBaseAnimating::CreateNoSpawn( "tf_dropped_weapon", vecOrigin, vecAngles ) );
|
||||
if ( pDroppedWeapon )
|
||||
{
|
||||
pDroppedWeapon->SetModelName( AllocPooledString( pszModelName ) );
|
||||
pDroppedWeapon->SetItem( pItem );
|
||||
DispatchSpawn( pDroppedWeapon );
|
||||
}
|
||||
|
||||
return pDroppedWeapon;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFDroppedWeapon::InitDroppedWeapon( CTFPlayer *pPlayer, CTFWeaponBase *pWeapon, bool bSwap, bool bIsSuicide /*= false*/ )
|
||||
{
|
||||
m_hPlayer = pPlayer;
|
||||
|
||||
// Calculate the initial impulse on the weapon.
|
||||
Vector vecImpulse( 0.0f, 0.0f, 0.0f );
|
||||
float flImpulseScale = 0.f;
|
||||
if ( bSwap && pPlayer )
|
||||
{
|
||||
Vector vecForward, vecUp;
|
||||
AngleVectors( pPlayer->EyeAngles(), &vecForward, NULL, &vecUp );
|
||||
vecImpulse += Vector(0,0,1.5); //vecUp * 0.5f;
|
||||
vecImpulse += vecForward * 1.0f;
|
||||
flImpulseScale = 250.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector vecRight, vecUp;
|
||||
AngleVectors( EyeAngles(), NULL, &vecRight, &vecUp );
|
||||
vecImpulse += vecUp * random->RandomFloat( -0.25, 0.25 );
|
||||
vecImpulse += vecRight * random->RandomFloat( -0.25, 0.25 );
|
||||
flImpulseScale = random->RandomFloat( 100.f, 150.f );
|
||||
}
|
||||
VectorNormalize( vecImpulse );
|
||||
vecImpulse *= flImpulseScale;
|
||||
vecImpulse += GetAbsVelocity();
|
||||
|
||||
if ( VPhysicsGetObject() )
|
||||
{
|
||||
// We can probably remove this when the mass on the weapons is correct!
|
||||
VPhysicsGetObject()->SetMass( 25.0f );
|
||||
AngularImpulse angImpulse( 0, random->RandomFloat( 0, 100 ), 0 );
|
||||
VPhysicsGetObject()->SetVelocityInstantaneous( &vecImpulse, &angImpulse );
|
||||
}
|
||||
|
||||
m_nSkin = pWeapon->GetSkin();
|
||||
|
||||
m_nClip = pWeapon->IsEnergyWeapon() ? pWeapon->GetMaxClip1() : pWeapon->Clip1();
|
||||
m_nAmmo = pPlayer->GetAmmoCount( pWeapon->GetPrimaryAmmoType() );
|
||||
m_flEnergy = pWeapon->Energy_GetEnergy();
|
||||
m_flNextPrimaryAttack = pWeapon->m_flNextPrimaryAttack;
|
||||
m_flNextSecondaryAttack = pWeapon->m_flNextSecondaryAttack;
|
||||
|
||||
if ( bIsSuicide )
|
||||
{
|
||||
m_flChargeLevel = 0.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
CWeaponMedigun *pMedigun = dynamic_cast< CWeaponMedigun* >( pWeapon );
|
||||
if ( pMedigun )
|
||||
{
|
||||
m_flChargeLevel.Set( pMedigun->GetChargeLevel() );
|
||||
if ( m_flChargeLevel > 0.f )
|
||||
{
|
||||
SetContextThink( &CTFDroppedWeapon::ChargeLevelDegradeThink, gpGlobals->curtime + 0.1f, "ChargeLevelDegradeThink" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CTFStickBomb *pStickBomb = dynamic_cast< CTFStickBomb* >( pWeapon );
|
||||
if ( pStickBomb )
|
||||
{
|
||||
m_nDetonated = pStickBomb->GetDetonated();
|
||||
}
|
||||
|
||||
// Capture bar regen (Jarate, base ball)
|
||||
m_flEffectBarRegenTime = pWeapon->m_flEffectBarRegenTime;
|
||||
|
||||
//DevMsg( "Dropped weapon with: clip[%d] ammo[%d] energy[%f]\n", m_nClip, m_nAmmo, m_flEnergy );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFDroppedWeapon::InitPickedUpWeapon( CTFPlayer *pPlayer, CTFWeaponBase *pWeapon )
|
||||
{
|
||||
// clear the context think
|
||||
SetContextThink( NULL, 0, "ChargeLevelDegradeThink" );
|
||||
|
||||
// preserve the ammo
|
||||
int nCurrentMetal = pPlayer->GetAmmoCount( TF_AMMO_METAL );
|
||||
pWeapon->m_iClip1 = m_nClip;
|
||||
if ( pWeapon->GetPrimaryAmmoType() != -1 )
|
||||
{
|
||||
pPlayer->SetAmmoCount( m_nAmmo, pWeapon->GetPrimaryAmmoType() );
|
||||
}
|
||||
// SetAmmoCount can override metal for some weapon
|
||||
// Make sure engineer don't gain metal by picking up weapon
|
||||
pPlayer->SetAmmoCount( nCurrentMetal, TF_AMMO_METAL );
|
||||
pWeapon->Energy_SetEnergy( m_flEnergy );
|
||||
|
||||
CWeaponMedigun *pMedigun = dynamic_cast< CWeaponMedigun* >( pWeapon );
|
||||
if ( pMedigun )
|
||||
{
|
||||
pMedigun->SetChargeLevel( m_flChargeLevel );
|
||||
}
|
||||
|
||||
CTFStickBomb *pStickBomb = dynamic_cast< CTFStickBomb* >( pWeapon );
|
||||
if ( pStickBomb )
|
||||
{
|
||||
pStickBomb->SetDetonated( m_nDetonated );
|
||||
}
|
||||
|
||||
// stomp the team color
|
||||
if ( pWeapon->GetAttributeContainer() && pWeapon->GetAttributeContainer()->GetItem() )
|
||||
{
|
||||
pWeapon->GetAttributeContainer()->GetItem()->SetTeamNumber( GetItem()->GetTeamNumber() );
|
||||
}
|
||||
|
||||
pWeapon->m_flEffectBarRegenTime = m_flEffectBarRegenTime;
|
||||
pWeapon->m_flNextPrimaryAttack = m_flNextPrimaryAttack;
|
||||
pWeapon->m_flNextSecondaryAttack = m_flNextSecondaryAttack;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFDroppedWeapon::ChargeLevelDegradeThink()
|
||||
{
|
||||
m_flChargeLevel.Set( m_flChargeLevel - 0.01f );
|
||||
|
||||
if ( m_flChargeLevel < 0.f )
|
||||
{
|
||||
m_flChargeLevel.Set( 0.f );
|
||||
SetContextThink( NULL, 0, "ChargeLevelDegradeThink" );
|
||||
return;
|
||||
}
|
||||
|
||||
SetContextThink( &CTFDroppedWeapon::ChargeLevelDegradeThink, gpGlobals->curtime + 0.1f, "ChargeLevelDegradeThink" );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFDroppedWeapon::SetItem( const CEconItemView *pItem )
|
||||
{
|
||||
if ( pItem )
|
||||
m_Item.CopyFrom( *pItem );
|
||||
}
|
||||
#endif // GAME_DLL
|
||||
Reference in New Issue
Block a user