Team Fortress 2 Source Code as on 22/4/2020
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.
 
 
 
 
 
 

286 lines
6.5 KiB

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "tf_weapon_bottle.h"
#include "decals.h"
// Client specific.
#ifdef CLIENT_DLL
#include "c_tf_player.h"
// Server specific.
#else
#include "tf_player.h"
#include "tf_fx.h"
#include "tf_gamerules.h"
#endif
//=============================================================================
//
// Weapon Bottle tables.
//
IMPLEMENT_NETWORKCLASS_ALIASED( TFBottle, DT_TFWeaponBottle )
BEGIN_NETWORK_TABLE( CTFBottle, DT_TFWeaponBottle )
#if defined( CLIENT_DLL )
RecvPropBool( RECVINFO( m_bBroken ) )
#else
SendPropBool( SENDINFO( m_bBroken ) )
#endif
END_NETWORK_TABLE()
BEGIN_PREDICTION_DATA( CTFBottle )
END_PREDICTION_DATA()
LINK_ENTITY_TO_CLASS( tf_weapon_bottle, CTFBottle );
PRECACHE_WEAPON_REGISTER( tf_weapon_bottle );
//=============================================================================
//
// Weapon Stickbomb tables.
//
IMPLEMENT_NETWORKCLASS_ALIASED( TFStickBomb, DT_TFWeaponStickBomb )
#ifdef CLIENT_DLL
void RecvProxy_Detonated( const CRecvProxyData *pData, void *pStruct, void *pOut );
#endif
BEGIN_NETWORK_TABLE( CTFStickBomb, DT_TFWeaponStickBomb )
#if defined( CLIENT_DLL )
RecvPropInt( RECVINFO( m_iDetonated ), 0, RecvProxy_Detonated )
#else
SendPropInt( SENDINFO( m_iDetonated ), 1, SPROP_UNSIGNED )
#endif
END_NETWORK_TABLE()
BEGIN_PREDICTION_DATA( CTFStickBomb )
END_PREDICTION_DATA()
LINK_ENTITY_TO_CLASS( tf_weapon_stickbomb, CTFStickBomb );
PRECACHE_WEAPON_REGISTER( tf_weapon_stickbomb );
#ifdef STAGING_ONLY
#define TF_WEAPON_STICKBOMB_NORMAL_MODEL "models/workshop/weapons/c_models/c_caber/c_caber.mdl"
#define TF_WEAPON_STICKBOMB_BROKEN_MODEL "models/workshop/weapons/c_models/c_caber/c_caber_exploded.mdl"
#else
#define TF_WEAPON_STICKBOMB_NORMAL_MODEL "models/weapons/c_models/c_caber/c_caber.mdl"
#define TF_WEAPON_STICKBOMB_BROKEN_MODEL "models/weapons/c_models/c_caber/c_caber_exploded.mdl"
#endif
//=============================================================================
#define TF_BOTTLE_SWITCHGROUP 1
#define TF_BOTTLE_NOTBROKEN 0
#define TF_BOTTLE_BROKEN 1
//=============================================================================
//
// Weapon Bottle functions.
//
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTFBottle::CTFBottle()
{
}
void CTFBottle::WeaponReset( void )
{
BaseClass::WeaponReset();
m_bBroken = false;
}
bool CTFBottle::DefaultDeploy( char *szViewModel, char *szWeaponModel, int iActivity, char *szAnimExt )
{
bool bRet = BaseClass::DefaultDeploy( szViewModel, szWeaponModel, iActivity, szAnimExt );
if ( bRet )
{
SwitchBodyGroups();
}
return bRet;
}
void CTFBottle::SwitchBodyGroups( void )
{
int iState = 0;
if ( m_bBroken == true )
{
iState = 1;
}
SetBodygroup( TF_BOTTLE_SWITCHGROUP, iState );
CTFPlayer *pTFPlayer = ToTFPlayer( GetOwner() );
if ( pTFPlayer && pTFPlayer->GetActiveWeapon() == this )
{
if ( pTFPlayer->GetViewModel() )
{
pTFPlayer->GetViewModel()->SetBodygroup( TF_BOTTLE_SWITCHGROUP, iState );
}
}
}
void CTFBottle::Smack( void )
{
BaseClass::Smack();
if ( ConnectedHit() && IsCurrentAttackACrit() )
{
m_bBroken = true;
SwitchBodyGroups();
}
}
CTFStickBomb::CTFStickBomb()
: CTFBottle()
{
m_iDetonated = 0;
}
void CTFStickBomb::Precache( void )
{
BaseClass::Precache();
PrecacheModel( TF_WEAPON_STICKBOMB_NORMAL_MODEL );
PrecacheModel( TF_WEAPON_STICKBOMB_BROKEN_MODEL );
}
void CTFStickBomb::Smack( void )
{
CTFWeaponBaseMelee::Smack();
// Stick bombs detonate once, on impact.
if ( m_iDetonated == 0 && ConnectedHit() )
{
m_iDetonated = 1;
m_bBroken = true;
SwitchBodyGroups();
#ifdef GAME_DLL
CTFPlayer *pTFPlayer = ToTFPlayer( GetOwner() );
if ( pTFPlayer )
{
Vector vecForward;
AngleVectors( pTFPlayer->EyeAngles(), &vecForward );
Vector vecSwingStart = pTFPlayer->Weapon_ShootPosition();
Vector vecSwingEnd = vecSwingStart + vecForward * GetSwingRange();
Vector explosion = vecSwingStart;
CPVSFilter filter( explosion );
// Halloween Spell
int iHalloweenSpell = 0;
int iCustomParticleIndex = INVALID_STRING_INDEX;
if ( TF_IsHolidayActive( kHoliday_HalloweenOrFullMoon ) )
{
CALL_ATTRIB_HOOK_INT_ON_OTHER( this, iHalloweenSpell, halloween_pumpkin_explosions );
if ( iHalloweenSpell > 0 )
{
iCustomParticleIndex = GetParticleSystemIndex( "halloween_explosion" );
}
}
TE_TFExplosion( filter, 0.0f, explosion, Vector(0,0,1), TF_WEAPON_GRENADELAUNCHER, pTFPlayer->entindex(), -1, SPECIAL1, iCustomParticleIndex );
int dmgType = DMG_BLAST | DMG_USEDISTANCEMOD;
if ( IsCurrentAttackACrit() )
dmgType |= DMG_CRITICAL;
CTakeDamageInfo info( pTFPlayer, pTFPlayer, this, explosion, explosion, 75.0f, dmgType, TF_DMG_CUSTOM_STICKBOMB_EXPLOSION, &explosion );
CTFRadiusDamageInfo radiusinfo( &info, explosion, 100.f );
TFGameRules()->RadiusDamage( radiusinfo );
}
#endif
}
}
void CTFStickBomb::WeaponReset( void )
{
BaseClass::WeaponReset();
m_iDetonated = 0;
SwitchBodyGroups();
}
void CTFStickBomb::WeaponRegenerate( void )
{
BaseClass::WeaponRegenerate();
m_iDetonated = 0;
SetContextThink( &CTFStickBomb::SwitchBodyGroups, gpGlobals->curtime + 0.01f, "SwitchBodyGroups" );
}
void CTFStickBomb::SwitchBodyGroups( void )
{
#ifdef CLIENT_DLL
if ( !GetViewmodelAttachment() )
return;
if ( m_iDetonated == 1 )
{
GetViewmodelAttachment()->SetModel( TF_WEAPON_STICKBOMB_BROKEN_MODEL );
}
else
{
GetViewmodelAttachment()->SetModel( TF_WEAPON_STICKBOMB_NORMAL_MODEL );
}
#endif
}
const char *CTFStickBomb::GetWorldModel( void ) const
{
if ( m_iDetonated == 1 )
{
return TF_WEAPON_STICKBOMB_BROKEN_MODEL;
}
else
{
return BaseClass::GetWorldModel();
}
}
#ifdef CLIENT_DLL
int CTFStickBomb::GetWorldModelIndex( void )
{
if ( !modelinfo )
return BaseClass::GetWorldModelIndex();
if ( m_iDetonated == 1 )
{
m_iWorldModelIndex = modelinfo->GetModelIndex( TF_WEAPON_STICKBOMB_BROKEN_MODEL );
return m_iWorldModelIndex;
}
else
{
m_iWorldModelIndex = modelinfo->GetModelIndex( TF_WEAPON_STICKBOMB_NORMAL_MODEL );
return m_iWorldModelIndex;
}
}
#endif
#ifdef CLIENT_DLL
void RecvProxy_Detonated( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
C_TFStickBomb* pBomb = (C_TFStickBomb*) pStruct;
if ( pData->m_Value.m_Int != pBomb->GetDetonated() )
{
pBomb->SetDetonated( pData->m_Value.m_Int );
pBomb->SwitchBodyGroups();
}
}
#endif