//========= 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