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.

649 lines
20 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "tf_dropped_weapon.h"
  9. #ifdef CLIENT_DLL
  10. #include "c_tf_player.h"
  11. #include "model_types.h"
  12. #endif // CLIENT_DLL
  13. #ifdef GAME_DLL
  14. #include "tf_player.h"
  15. #include "tf_weaponbase.h"
  16. #include "tf_weapon_medigun.h"
  17. #include "tf_gamerules.h"
  18. #include "tf_weapon_bottle.h"
  19. #endif // GAME_DLL
  20. #ifdef GAME_DLL
  21. ConVar tf_dropped_weapon_lifetime( "tf_dropped_weapon_lifetime", "30", FCVAR_CHEAT );
  22. EXTERN_SEND_TABLE( DT_ScriptCreatedItem );
  23. LINK_ENTITY_TO_CLASS( tf_dropped_weapon, CTFDroppedWeapon );
  24. PRECACHE_REGISTER( tf_dropped_weapon );
  25. #else
  26. EXTERN_RECV_TABLE( DT_ScriptCreatedItem );
  27. #endif
  28. IMPLEMENT_NETWORKCLASS_ALIASED( TFDroppedWeapon, DT_TFDroppedWeapon );
  29. BEGIN_NETWORK_TABLE( CTFDroppedWeapon, DT_TFDroppedWeapon )
  30. #if !defined( CLIENT_DLL )
  31. SendPropDataTable( SENDINFO_DT(m_Item), &REFERENCE_SEND_TABLE(DT_ScriptCreatedItem) ),
  32. SendPropFloat( SENDINFO( m_flChargeLevel ) ),
  33. #else
  34. RecvPropDataTable( RECVINFO_DT(m_Item), 0, &REFERENCE_RECV_TABLE(DT_ScriptCreatedItem) ),
  35. RecvPropFloat( RECVINFO( m_flChargeLevel ) ),
  36. #endif
  37. END_NETWORK_TABLE()
  38. IMPLEMENT_AUTO_LIST( IDroppedWeaponAutoList );
  39. //-----------------------------------------------------------------------------
  40. CTFDroppedWeapon::CTFDroppedWeapon()
  41. #ifdef GAME_DLL
  42. : m_nClip( 0 )
  43. , m_nAmmo( 0 )
  44. , m_nDetonated( 0 )
  45. , m_flEnergy( 0.f )
  46. , m_flEffectBarRegenTime( 0.f )
  47. #endif
  48. {
  49. #ifdef CLIENT_DLL
  50. m_pGlowEffect = NULL;
  51. m_bShouldGlowForLocalPlayer = false;
  52. m_flOldChargeLevel = 0.f;
  53. #endif // CLIENT_DLL
  54. m_flChargeLevel.Set( 0.f );
  55. }
  56. //-----------------------------------------------------------------------------
  57. CTFDroppedWeapon::~CTFDroppedWeapon()
  58. {
  59. #ifdef CLIENT_DLL
  60. if ( m_worldmodelStatTrakAddon )
  61. {
  62. m_worldmodelStatTrakAddon->Remove();
  63. }
  64. if ( m_effect )
  65. {
  66. ParticleProp()->StopEmission( m_effect );
  67. m_effect = NULL;
  68. }
  69. DestroyGlowEffect();
  70. #endif // CLIENT_DLL
  71. }
  72. //-----------------------------------------------------------------------------
  73. void CTFDroppedWeapon::Spawn()
  74. {
  75. #ifdef GAME_DLL
  76. SetModel( STRING( GetModelName() ) );
  77. SetMoveType( MOVETYPE_FLYGRAVITY );
  78. SetSolid( SOLID_BBOX );
  79. SetBlocksLOS( false );
  80. AddEFlags( EFL_NO_ROTORWASH_PUSH );
  81. // This will make them not collide with the player, but will collide
  82. // against other items + weapons
  83. SetCollisionGroup( COLLISION_GROUP_DEBRIS );
  84. CollisionProp()->UseTriggerBounds( true, ITEM_PICKUP_BOX_BLOAT );
  85. // Create the object in the physics system
  86. int nSolidFlags = GetSolidFlags() | FSOLID_NOT_STANDABLE;
  87. if ( VPhysicsInitNormal( SOLID_VPHYSICS, nSolidFlags, false ) == NULL )
  88. {
  89. SetSolid( SOLID_BBOX );
  90. AddSolidFlags( nSolidFlags );
  91. // If it's not physical, drop it to the floor
  92. if ( UTIL_DropToFloor( this, MASK_SOLID ) == 0 )
  93. {
  94. Warning( "Item %s fell out of level at %f,%f,%f\n", GetClassname(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z);
  95. UTIL_Remove( this );
  96. return;
  97. }
  98. }
  99. #endif // GAME_DLL
  100. BaseClass::Spawn();
  101. #ifdef GAME_DLL
  102. SetContextThink( &CTFDroppedWeapon::SUB_Remove, gpGlobals->curtime + tf_dropped_weapon_lifetime.GetFloat(), "RemoveThink" );
  103. #endif // GAME_DLL
  104. }
  105. #ifdef CLIENT_DLL
  106. //-----------------------------------------------------------------------------
  107. void CTFDroppedWeapon::OnPreDataChanged( DataUpdateType_t updateType )
  108. {
  109. BaseClass::OnPreDataChanged( updateType );
  110. m_flOldChargeLevel = m_flChargeLevel;
  111. }
  112. //-----------------------------------------------------------------------------
  113. void CTFDroppedWeapon::OnDataChanged( DataUpdateType_t updateType )
  114. {
  115. BaseClass::OnDataChanged( updateType );
  116. if ( updateType == DATA_UPDATE_CREATED )
  117. {
  118. // if its startrak attach a model to it
  119. if ( m_Item.GetItemID() != INVALID_ITEM_ID )
  120. {
  121. int iStrangeType = -1;
  122. for ( int i = 0; i < GetKillEaterAttrCount(); i++ )
  123. {
  124. if ( m_Item.FindAttribute( GetKillEaterAttr_Score( i ) ) )
  125. {
  126. iStrangeType = i;
  127. break;
  128. }
  129. }
  130. // It's strange, does it have module as well?
  131. if ( iStrangeType != -1 )
  132. {
  133. CAttribute_String attrModule;
  134. static CSchemaAttributeDefHandle pAttr_module( "weapon_uses_stattrak_module" );
  135. if ( m_Item.FindAttribute( pAttr_module, &attrModule ) && attrModule.has_value() )
  136. {
  137. static CSchemaAttributeDefHandle pAttr_moduleScale( "weapon_stattrak_module_scale" );
  138. // Does it have a stat track module
  139. float flScale = 1.0f;
  140. uint32 unFloatAsUint32 = 1;
  141. if ( m_Item.FindAttribute( pAttr_moduleScale, &unFloatAsUint32 ) )
  142. {
  143. flScale = (float&)unFloatAsUint32;
  144. }
  145. C_BaseAnimating *pStatTrakEnt = new class C_BaseAnimating;
  146. if ( pStatTrakEnt && pStatTrakEnt->InitializeAsClientEntity( "models/weapons/c_models/stattrack.mdl", RENDER_GROUP_OPAQUE_ENTITY ) )
  147. {
  148. pStatTrakEnt->AddEffects( EF_BONEMERGE );
  149. pStatTrakEnt->AddEffects( EF_BONEMERGE_FASTCULL );
  150. m_worldmodelStatTrakAddon = pStatTrakEnt;
  151. pStatTrakEnt->SetParent( this );
  152. pStatTrakEnt->SetLocalOrigin( vec3_origin );
  153. pStatTrakEnt->UpdatePartitionListEntry();
  154. pStatTrakEnt->CollisionProp()->MarkPartitionHandleDirty();
  155. pStatTrakEnt->SetModelScale( flScale );
  156. pStatTrakEnt->UpdateVisibility();
  157. pStatTrakEnt->SetBodygroup( 1, 1 );
  158. pStatTrakEnt->m_nSkin = m_Item.GetTeamNumber(); // Use the "Sad" skin
  159. //pStatTrakEnt->SetModelScale( 2.0f );
  160. // //if ( !cl_righthand.GetBool() )
  161. // //{
  162. // // pStatTrakEnt->SetBodygroup( 0, 1 ); // use a special mirror-image stattrak module that appears correct for lefties
  163. // //}
  164. RemoveEffects( EF_NODRAW );
  165. }
  166. }
  167. }
  168. // Normal Attached models (ie festive lights)
  169. const CEconItemDefinition *pItemDef = m_Item.GetItemDefinition();
  170. if ( pItemDef )
  171. {
  172. // Update the state of additional model attachments
  173. m_vecAttachedModels.Purge();
  174. int iTeamNumber = m_Item.GetTeamNumber();
  175. int iAttachedModels = pItemDef->GetNumAttachedModels( iTeamNumber );
  176. for ( int i = 0; i < iAttachedModels; i++ )
  177. {
  178. attachedmodel_t *pModel = pItemDef->GetAttachedModelData( iTeamNumber, i );
  179. int iModelIndex = modelinfo->GetModelIndex( pModel->m_pszModelName );
  180. if ( iModelIndex >= 0 )
  181. {
  182. AttachedModelData_t attachedModelData;
  183. attachedModelData.m_pModel = modelinfo->GetModel( iModelIndex );
  184. attachedModelData.m_iModelDisplayFlags = pModel->m_iModelDisplayFlags;
  185. m_vecAttachedModels.AddToTail( attachedModelData );
  186. }
  187. }
  188. // Festive
  189. {
  190. static CSchemaAttributeDefHandle pAttr_is_festivized( "is_festivized" );
  191. if ( pAttr_is_festivized && m_Item.FindAttribute( pAttr_is_festivized ) )
  192. {
  193. int iAttachedFestiveModels = pItemDef->GetNumAttachedModelsFestivized( iTeamNumber );
  194. if ( iAttachedFestiveModels )
  195. {
  196. for ( int i = 0; i < iAttachedFestiveModels; i++ )
  197. {
  198. attachedmodel_t *pModel = pItemDef->GetAttachedModelDataFestivized( iTeamNumber, i );
  199. int iModelIndex = modelinfo->GetModelIndex( pModel->m_pszModelName );
  200. if ( iModelIndex >= 0 )
  201. {
  202. AttachedModelData_t attachedModelData;
  203. attachedModelData.m_pModel = modelinfo->GetModel( iModelIndex );
  204. attachedModelData.m_iModelDisplayFlags = pModel->m_iModelDisplayFlags;
  205. m_vecAttachedModels.AddToTail( attachedModelData );
  206. }
  207. }
  208. }
  209. }
  210. }
  211. }
  212. SetupParticleEffect();
  213. }
  214. SetNextClientThink( CLIENT_THINK_ALWAYS );
  215. }
  216. if ( m_flOldChargeLevel != m_flChargeLevel )
  217. {
  218. float flRem = fmod( m_flChargeLevel, 0.1f );
  219. if ( flRem < 0.01f )
  220. {
  221. ParticleProp()->Create( "drain_effect", PATTACH_POINT_FOLLOW, LookupAttachment( "muzzle" ) );
  222. EmitSound( "Medigun.DrainCharge" );
  223. }
  224. }
  225. }
  226. //-----------------------------------------------------------------------------
  227. void CTFDroppedWeapon::ModifyEmitSoundParams( EmitSound_t &params )
  228. {
  229. params.m_nPitch = RemapVal( m_flChargeLevel, 0.f, 1.f, 90, 180 );
  230. params.m_nFlags |= SND_CHANGE_PITCH;
  231. }
  232. //-----------------------------------------------------------------------------
  233. bool CTFDroppedWeapon::OnInternalDrawModel( ClientModelRenderInfo_t *pInfo )
  234. {
  235. if ( !BaseClass::OnInternalDrawModel( pInfo ) )
  236. return false;
  237. // Draw Attached Models
  238. // Draw our attached models as well
  239. for ( int i = 0; i < m_vecAttachedModels.Size(); i++ )
  240. {
  241. const AttachedModelData_t& attachedModel = m_vecAttachedModels[i];
  242. if ( attachedModel.m_pModel && ( attachedModel.m_iModelDisplayFlags & kAttachedModelDisplayFlag_WorldModel ) )
  243. {
  244. ClientModelRenderInfo_t infoAttached = *pInfo;
  245. infoAttached.pRenderable = this;
  246. infoAttached.instance = MODEL_INSTANCE_INVALID;
  247. infoAttached.entity_index = this->index;
  248. infoAttached.pModel = attachedModel.m_pModel;
  249. infoAttached.pModelToWorld = &infoAttached.modelToWorld;
  250. // Turns the origin + angles into a matrix
  251. AngleMatrix( infoAttached.angles, infoAttached.origin, infoAttached.modelToWorld );
  252. DrawModelState_t state;
  253. matrix3x4_t *pBoneToWorld;
  254. bool bMarkAsDrawn = modelrender->DrawModelSetup( infoAttached, &state, NULL, &pBoneToWorld );
  255. DoInternalDrawModel( &infoAttached, ( bMarkAsDrawn && ( infoAttached.flags & STUDIO_RENDER ) ) ? &state : NULL, pBoneToWorld );
  256. }
  257. }
  258. return true;
  259. }
  260. //-----------------------------------------------------------------------------
  261. // Purpose: Get an econ material override for the given team.
  262. // Returns: NULL if there is no override.
  263. //-----------------------------------------------------------------------------
  264. IMaterial *CTFDroppedWeapon::GetEconWeaponMaterialOverride( int iTeam )
  265. {
  266. CEconItemView *pItemView = GetItem();
  267. if ( !pItemView )
  268. return NULL;
  269. return pItemView->GetMaterialOverride( iTeam );
  270. }
  271. //-----------------------------------------------------------------------------
  272. void CTFDroppedWeapon::SetupParticleEffect()
  273. {
  274. attachedparticlesystem_t *pParticleSystem = NULL;
  275. // do community_sparkle effect if this is a community item?
  276. const int iQualityParticleType = m_Item.GetQualityParticleType();
  277. if ( iQualityParticleType > 0 )
  278. {
  279. pParticleSystem = GetItemSchema()->GetAttributeControlledParticleSystem( iQualityParticleType );
  280. }
  281. if ( !pParticleSystem )
  282. {
  283. // does this hat even have a particle effect
  284. static CSchemaAttributeDefHandle pAttrDef_AttachParticleEffect( "attach particle effect" );
  285. uint32 iValue = 0;
  286. if ( !m_Item.FindAttribute( pAttrDef_AttachParticleEffect, &iValue ) )
  287. {
  288. return;
  289. }
  290. const float& value_as_float = (float&)iValue;
  291. pParticleSystem = GetItemSchema()->GetAttributeControlledParticleSystem( value_as_float );
  292. }
  293. // failed to find any particle effect
  294. if ( !pParticleSystem )
  295. {
  296. return;
  297. }
  298. // Team Color
  299. if ( GetTeamNumber() == TF_TEAM_BLUE && V_stristr( pParticleSystem->pszSystemName, "_teamcolor_red" ))
  300. {
  301. static char pBlue[256];
  302. V_StrSubst( pParticleSystem->pszSystemName, "_teamcolor_red", "_teamcolor_blue", pBlue, 256 );
  303. pParticleSystem = GetItemSchema()->FindAttributeControlledParticleSystem( pBlue );
  304. if ( !pParticleSystem )
  305. {
  306. return;
  307. }
  308. }
  309. // World model effect
  310. // Stop it on both the viewmodel & the world model, because it may be removed due to first/thirdperson switch
  311. static char pszTempName[256];
  312. const char* pszSystemName = pParticleSystem->pszSystemName;
  313. // Weapon Remap for a Base Effect to be used on a specific weapon
  314. if ( pParticleSystem->bUseSuffixName && m_Item.GetItemDefinition()->GetParticleSuffix() )
  315. {
  316. V_strcpy_safe( pszTempName, pszSystemName );
  317. V_strcat_safe( pszTempName, "_" );
  318. V_strcat_safe( pszTempName, m_Item.GetItemDefinition()->GetParticleSuffix() );
  319. pszSystemName = pszTempName;
  320. }
  321. m_effect = ParticleProp()->Create( pszSystemName, PATTACH_ABSORIGIN_FOLLOW );
  322. if ( m_effect )
  323. {
  324. for ( int i=0; i<ARRAYSIZE( pParticleSystem->pszControlPoints ); ++i )
  325. {
  326. const char *pszAttachmentName = pParticleSystem->pszControlPoints[i];
  327. if ( pszAttachmentName && pszAttachmentName[0] != '\0' )
  328. {
  329. ParticleProp()->AddControlPoint( m_effect, i, this, PATTACH_POINT_FOLLOW, pParticleSystem->pszControlPoints[i] );
  330. }
  331. }
  332. }
  333. }
  334. //-----------------------------------------------------------------------------
  335. void CTFDroppedWeapon::ClientThink()
  336. {
  337. C_TFPlayer *pTFPlayer = C_TFPlayer::GetLocalTFPlayer();
  338. bool bShouldGlowForLocalPlayer = pTFPlayer && pTFPlayer->IsAlive() && pTFPlayer->CanPickupDroppedWeapon( this ) && pTFPlayer->IsLineOfSightClear( this );
  339. if ( bShouldGlowForLocalPlayer )
  340. {
  341. // ignore the item that the player's equipped
  342. int iLoadoutSlot = 0;
  343. CTFItemDefinition *pItemDef = m_Item.GetStaticData();
  344. if ( pItemDef )
  345. {
  346. int iClass = pTFPlayer->GetPlayerClass()->GetClassIndex();
  347. iLoadoutSlot = pItemDef->GetLoadoutSlot( iClass );
  348. CTFWeaponBase *pWeapon = dynamic_cast< CTFWeaponBase* >( pTFPlayer->GetEntityForLoadoutSlot( iLoadoutSlot ) );
  349. if ( pWeapon && *pWeapon->GetAttributeContainer()->GetItem() == m_Item )
  350. {
  351. bShouldGlowForLocalPlayer = false;
  352. }
  353. }
  354. }
  355. if ( m_bShouldGlowForLocalPlayer != bShouldGlowForLocalPlayer )
  356. {
  357. m_bShouldGlowForLocalPlayer = bShouldGlowForLocalPlayer;
  358. UpdateGlowEffect();
  359. }
  360. }
  361. //-----------------------------------------------------------------------------
  362. void CTFDroppedWeapon::UpdateGlowEffect( void )
  363. {
  364. // destroy the existing effect
  365. if ( m_pGlowEffect )
  366. {
  367. DestroyGlowEffect();
  368. }
  369. // create a new effect if we have a cart
  370. if ( m_bShouldGlowForLocalPlayer )
  371. {
  372. Vector color = Vector( 0.745f, 0.773f, 0.157f );
  373. m_pGlowEffect = new CGlowObject( this, color, 1.0, true );
  374. }
  375. }
  376. //-----------------------------------------------------------------------------
  377. void CTFDroppedWeapon::DestroyGlowEffect( void )
  378. {
  379. if ( m_pGlowEffect )
  380. {
  381. delete m_pGlowEffect;
  382. m_pGlowEffect = NULL;
  383. }
  384. }
  385. //-----------------------------------------------------------------------------
  386. bool CTFDroppedWeapon::IsVisibleToTargetID( void ) const
  387. {
  388. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  389. if ( !pLocalPlayer )
  390. return false;
  391. return pLocalPlayer->CanPickupDroppedWeapon( this );
  392. }
  393. #endif // CLIENT_DLL
  394. #ifdef GAME_DLL
  395. #define MAX_DROPPED_WEAPON_COUNT 32
  396. //-----------------------------------------------------------------------------
  397. CTFDroppedWeapon *CTFDroppedWeapon::Create( CTFPlayer *pLastOwner, const Vector &vecOrigin, const QAngle &vecAngles, const char *pszModelName, const CEconItemView *pItem )
  398. {
  399. // don't drop weapon in MVM
  400. if ( TFGameRules()->IsMannVsMachineMode() )
  401. return NULL;
  402. int nNumRemoved = 0;
  403. // make sure we clean up the same item that was dropped before dropping a new one
  404. for ( int i=0; i<CTFDroppedWeapon::AutoList().Count(); ++i )
  405. {
  406. CTFDroppedWeapon *pDroppedWeapon = static_cast< CTFDroppedWeapon* >( CTFDroppedWeapon::AutoList()[i] );
  407. if ( pDroppedWeapon->m_Item.GetItemID() == pItem->GetItemID() && pDroppedWeapon->m_Item.GetItemDefIndex() == pItem->GetItemDefIndex() && pDroppedWeapon->m_hPlayer.Get() == pLastOwner )
  408. {
  409. UTIL_Remove( pDroppedWeapon );
  410. nNumRemoved++;
  411. }
  412. }
  413. // if we're still going over max dropped weapon count, remove more items
  414. int nNumToRemove = CTFDroppedWeapon::AutoList().Count() - nNumRemoved - MAX_DROPPED_WEAPON_COUNT;
  415. for ( int i=0; i<CTFDroppedWeapon::AutoList().Count() && nNumToRemove > 0; ++i )
  416. {
  417. CTFDroppedWeapon *pDroppedWeapon = static_cast< CTFDroppedWeapon* >( CTFDroppedWeapon::AutoList()[i] );
  418. // skip item that we already marked for deletion
  419. if ( pDroppedWeapon->IsMarkedForDeletion() )
  420. continue;
  421. UTIL_Remove( pDroppedWeapon );
  422. nNumToRemove--;
  423. }
  424. CTFDroppedWeapon *pDroppedWeapon = static_cast<CTFDroppedWeapon*>( CBaseAnimating::CreateNoSpawn( "tf_dropped_weapon", vecOrigin, vecAngles ) );
  425. if ( pDroppedWeapon )
  426. {
  427. pDroppedWeapon->SetModelName( AllocPooledString( pszModelName ) );
  428. pDroppedWeapon->SetItem( pItem );
  429. DispatchSpawn( pDroppedWeapon );
  430. }
  431. return pDroppedWeapon;
  432. }
  433. //-----------------------------------------------------------------------------
  434. void CTFDroppedWeapon::InitDroppedWeapon( CTFPlayer *pPlayer, CTFWeaponBase *pWeapon, bool bSwap, bool bIsSuicide /*= false*/ )
  435. {
  436. m_hPlayer = pPlayer;
  437. // Calculate the initial impulse on the weapon.
  438. Vector vecImpulse( 0.0f, 0.0f, 0.0f );
  439. float flImpulseScale = 0.f;
  440. if ( bSwap && pPlayer )
  441. {
  442. Vector vecForward, vecUp;
  443. AngleVectors( pPlayer->EyeAngles(), &vecForward, NULL, &vecUp );
  444. vecImpulse += Vector(0,0,1.5); //vecUp * 0.5f;
  445. vecImpulse += vecForward * 1.0f;
  446. flImpulseScale = 250.f;
  447. }
  448. else
  449. {
  450. Vector vecRight, vecUp;
  451. AngleVectors( EyeAngles(), NULL, &vecRight, &vecUp );
  452. vecImpulse += vecUp * random->RandomFloat( -0.25, 0.25 );
  453. vecImpulse += vecRight * random->RandomFloat( -0.25, 0.25 );
  454. flImpulseScale = random->RandomFloat( 100.f, 150.f );
  455. }
  456. VectorNormalize( vecImpulse );
  457. vecImpulse *= flImpulseScale;
  458. vecImpulse += GetAbsVelocity();
  459. if ( VPhysicsGetObject() )
  460. {
  461. // We can probably remove this when the mass on the weapons is correct!
  462. VPhysicsGetObject()->SetMass( 25.0f );
  463. AngularImpulse angImpulse( 0, random->RandomFloat( 0, 100 ), 0 );
  464. VPhysicsGetObject()->SetVelocityInstantaneous( &vecImpulse, &angImpulse );
  465. }
  466. m_nSkin = pWeapon->GetSkin();
  467. m_nClip = pWeapon->IsEnergyWeapon() ? pWeapon->GetMaxClip1() : pWeapon->Clip1();
  468. m_nAmmo = pPlayer->GetAmmoCount( pWeapon->GetPrimaryAmmoType() );
  469. m_flEnergy = pWeapon->Energy_GetEnergy();
  470. m_flNextPrimaryAttack = pWeapon->m_flNextPrimaryAttack;
  471. m_flNextSecondaryAttack = pWeapon->m_flNextSecondaryAttack;
  472. if ( bIsSuicide )
  473. {
  474. m_flChargeLevel = 0.f;
  475. }
  476. else
  477. {
  478. CWeaponMedigun *pMedigun = dynamic_cast< CWeaponMedigun* >( pWeapon );
  479. if ( pMedigun )
  480. {
  481. m_flChargeLevel.Set( pMedigun->GetChargeLevel() );
  482. if ( m_flChargeLevel > 0.f )
  483. {
  484. SetContextThink( &CTFDroppedWeapon::ChargeLevelDegradeThink, gpGlobals->curtime + 0.1f, "ChargeLevelDegradeThink" );
  485. }
  486. }
  487. }
  488. CTFStickBomb *pStickBomb = dynamic_cast< CTFStickBomb* >( pWeapon );
  489. if ( pStickBomb )
  490. {
  491. m_nDetonated = pStickBomb->GetDetonated();
  492. }
  493. // Capture bar regen (Jarate, base ball)
  494. m_flEffectBarRegenTime = pWeapon->m_flEffectBarRegenTime;
  495. //DevMsg( "Dropped weapon with: clip[%d] ammo[%d] energy[%f]\n", m_nClip, m_nAmmo, m_flEnergy );
  496. }
  497. //-----------------------------------------------------------------------------
  498. void CTFDroppedWeapon::InitPickedUpWeapon( CTFPlayer *pPlayer, CTFWeaponBase *pWeapon )
  499. {
  500. // clear the context think
  501. SetContextThink( NULL, 0, "ChargeLevelDegradeThink" );
  502. // preserve the ammo
  503. int nCurrentMetal = pPlayer->GetAmmoCount( TF_AMMO_METAL );
  504. pWeapon->m_iClip1 = m_nClip;
  505. if ( pWeapon->GetPrimaryAmmoType() != -1 )
  506. {
  507. pPlayer->SetAmmoCount( m_nAmmo, pWeapon->GetPrimaryAmmoType() );
  508. }
  509. // SetAmmoCount can override metal for some weapon
  510. // Make sure engineer don't gain metal by picking up weapon
  511. pPlayer->SetAmmoCount( nCurrentMetal, TF_AMMO_METAL );
  512. pWeapon->Energy_SetEnergy( m_flEnergy );
  513. CWeaponMedigun *pMedigun = dynamic_cast< CWeaponMedigun* >( pWeapon );
  514. if ( pMedigun )
  515. {
  516. pMedigun->SetChargeLevel( m_flChargeLevel );
  517. }
  518. CTFStickBomb *pStickBomb = dynamic_cast< CTFStickBomb* >( pWeapon );
  519. if ( pStickBomb )
  520. {
  521. pStickBomb->SetDetonated( m_nDetonated );
  522. }
  523. // stomp the team color
  524. if ( pWeapon->GetAttributeContainer() && pWeapon->GetAttributeContainer()->GetItem() )
  525. {
  526. pWeapon->GetAttributeContainer()->GetItem()->SetTeamNumber( GetItem()->GetTeamNumber() );
  527. }
  528. pWeapon->m_flEffectBarRegenTime = m_flEffectBarRegenTime;
  529. pWeapon->m_flNextPrimaryAttack = m_flNextPrimaryAttack;
  530. pWeapon->m_flNextSecondaryAttack = m_flNextSecondaryAttack;
  531. }
  532. //-----------------------------------------------------------------------------
  533. void CTFDroppedWeapon::ChargeLevelDegradeThink()
  534. {
  535. m_flChargeLevel.Set( m_flChargeLevel - 0.01f );
  536. if ( m_flChargeLevel < 0.f )
  537. {
  538. m_flChargeLevel.Set( 0.f );
  539. SetContextThink( NULL, 0, "ChargeLevelDegradeThink" );
  540. return;
  541. }
  542. SetContextThink( &CTFDroppedWeapon::ChargeLevelDegradeThink, gpGlobals->curtime + 0.1f, "ChargeLevelDegradeThink" );
  543. }
  544. //-----------------------------------------------------------------------------
  545. void CTFDroppedWeapon::SetItem( const CEconItemView *pItem )
  546. {
  547. if ( pItem )
  548. m_Item.CopyFrom( *pItem );
  549. }
  550. #endif // GAME_DLL