summaryrefslogtreecommitdiff
path: root/game/shared/tf/tf_weapon_lunchbox.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/shared/tf/tf_weapon_lunchbox.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/shared/tf/tf_weapon_lunchbox.cpp')
-rw-r--r--game/shared/tf/tf_weapon_lunchbox.cpp430
1 files changed, 430 insertions, 0 deletions
diff --git a/game/shared/tf/tf_weapon_lunchbox.cpp b/game/shared/tf/tf_weapon_lunchbox.cpp
new file mode 100644
index 0000000..bfb646e
--- /dev/null
+++ b/game/shared/tf/tf_weapon_lunchbox.cpp
@@ -0,0 +1,430 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+//
+//=============================================================================
+#include "cbase.h"
+#include "tf_weapon_lunchbox.h"
+#include "tf_fx_shared.h"
+
+// Client specific.
+#ifdef CLIENT_DLL
+#include "c_tf_player.h"
+// Server specific.
+#else
+#include "tf_player.h"
+#include "entity_healthkit.h"
+#include "econ_item_view.h"
+#include "econ_item_system.h"
+#include "tf_gamestats.h"
+#endif
+
+//=============================================================================
+//
+// Weapon Lunchbox tables.
+//
+IMPLEMENT_NETWORKCLASS_ALIASED( TFLunchBox, DT_WeaponLunchBox )
+
+BEGIN_NETWORK_TABLE( CTFLunchBox, DT_WeaponLunchBox )
+END_NETWORK_TABLE()
+
+BEGIN_PREDICTION_DATA( CTFLunchBox )
+END_PREDICTION_DATA()
+
+LINK_ENTITY_TO_CLASS( tf_weapon_lunchbox, CTFLunchBox );
+PRECACHE_WEAPON_REGISTER( tf_weapon_lunchbox );
+
+//=============================================================================
+
+IMPLEMENT_NETWORKCLASS_ALIASED( TFLunchBox_Drink, DT_TFLunchBox_Drink )
+
+BEGIN_NETWORK_TABLE( CTFLunchBox_Drink, DT_TFLunchBox_Drink )
+END_NETWORK_TABLE()
+
+BEGIN_PREDICTION_DATA( CTFLunchBox_Drink )
+END_PREDICTION_DATA()
+
+LINK_ENTITY_TO_CLASS( tf_weapon_lunchbox_drink, CTFLunchBox_Drink );
+PRECACHE_WEAPON_REGISTER( tf_weapon_lunchbox_drink );
+
+// Server specific.
+#ifndef CLIENT_DLL
+BEGIN_DATADESC( CTFLunchBox )
+END_DATADESC()
+#endif
+
+#define LUNCHBOX_DROP_MODEL "models/items/plate.mdl"
+#define LUNCHBOX_STEAK_DROP_MODEL "models/items/plate_steak.mdl"
+#define LUNCHBOX_ROBOT_DROP_MODEL "models/items/plate_robo_sandwich.mdl"
+#define LUNCHBOX_FESTIVE_DROP_MODEL "models/items/plate_sandwich_xmas.mdl"
+#define LUNCHBOX_CHOCOLATE_BAR "models/props_halloween/halloween_medkit_small.mdl"
+
+#define LUNCHBOX_DROPPED_MINS Vector( -17, -17, -10 )
+#define LUNCHBOX_DROPPED_MAXS Vector( 17, 17, 10 )
+
+static const char *s_pszLunchboxMaxHealThink = "LunchboxMaxHealThink";
+
+//=============================================================================
+//
+// Weapon Lunchbox functions.
+//
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CTFLunchBox::CTFLunchBox()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFLunchBox::UpdateOnRemove( void )
+{
+#ifndef CLIENT_DLL
+ // If we're removed, we remove any dropped powerups. This prevents an exploit
+ // where they switch classes away & back to get another lunchbox to drop with.
+ if ( m_hThrownPowerup )
+ {
+ UTIL_Remove( m_hThrownPowerup );
+ }
+#endif
+
+ BaseClass::UpdateOnRemove();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFLunchBox::Precache( void )
+{
+ if ( DropAllowed() )
+ {
+ PrecacheModel( "models/items/medkit_medium.mdl" );
+ PrecacheModel( "models/items/medkit_medium_bday.mdl" );
+ PrecacheModel( LUNCHBOX_DROP_MODEL );
+ PrecacheModel( LUNCHBOX_STEAK_DROP_MODEL );
+ PrecacheModel( LUNCHBOX_ROBOT_DROP_MODEL );
+ PrecacheModel( LUNCHBOX_FESTIVE_DROP_MODEL );
+ PrecacheModel( LUNCHBOX_CHOCOLATE_BAR );
+ }
+
+ BaseClass::Precache();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFLunchBox::WeaponReset( void )
+{
+ BaseClass::WeaponReset();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CTFLunchBox::UsesPrimaryAmmo( void )
+{
+ return CBaseCombatWeapon::UsesPrimaryAmmo();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CTFLunchBox::DropAllowed( void )
+{
+ CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() );
+ if ( pOwner )
+ {
+ if ( pOwner->m_Shared.InCond( TF_COND_TAUNTING ) )
+ return false;
+ }
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFLunchBox::PrimaryAttack( void )
+{
+ CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() );
+ if ( !pOwner )
+ return;
+
+ if ( !HasAmmo() )
+ return;
+
+#if GAME_DLL
+ pOwner->Taunt();
+ m_flNextPrimaryAttack = pOwner->GetTauntRemoveTime() + 0.1f;
+#else
+ m_flNextPrimaryAttack = gpGlobals->curtime + 2.0f; // this will be corrected by the game server
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFLunchBox::SecondaryAttack( void )
+{
+ if ( !DropAllowed() )
+ return;
+
+ CTFPlayer *pPlayer = ToTFPlayer( GetPlayerOwner() );
+ if ( !pPlayer )
+ return;
+
+ if ( !HasAmmo() )
+ return;
+
+#ifndef CLIENT_DLL
+
+ if ( m_hThrownPowerup )
+ {
+ UTIL_Remove( m_hThrownPowerup );
+ }
+
+ // Throw out the medikit
+ Vector vecSrc = pPlayer->EyePosition() + Vector(0,0,-8);
+ QAngle angForward = pPlayer->EyeAngles() + QAngle(-10,0,0);
+
+ int nLunchBoxType = GetLunchboxType();
+
+ const char *pszHealthKit;
+ switch ( nLunchBoxType )
+ {
+ case LUNCHBOX_ADDS_MAXHEALTH:
+ pszHealthKit = "item_healthkit_small";
+ break;
+
+ case LUNCHBOX_ADDS_AMMO:
+ pszHealthKit = "item_healthammokit";
+ break;
+
+ default:
+ pszHealthKit = "item_healthkit_medium";
+ }
+
+ CHealthKit *pMedKit = assert_cast<CHealthKit*>( CBaseEntity::Create( pszHealthKit, vecSrc, angForward, pPlayer ) );
+
+ if ( pMedKit )
+ {
+ Vector vecForward, vecRight, vecUp;
+ AngleVectors( angForward, &vecForward, &vecRight, &vecUp );
+ Vector vecVelocity = vecForward * 500.0;
+
+ if ( nLunchBoxType == LUNCHBOX_ADDS_MINICRITS )
+ {
+ pMedKit->SetModel( LUNCHBOX_STEAK_DROP_MODEL );
+ }
+ else if ( nLunchBoxType == LUNCHBOX_STANDARD_ROBO )
+ {
+ pMedKit->SetModel( LUNCHBOX_ROBOT_DROP_MODEL );
+ pMedKit->m_nSkin = ( pPlayer->GetTeamNumber() == TF_TEAM_RED ) ? 0 : 1;
+ }
+ else if ( nLunchBoxType == LUNCHBOX_STANDARD_FESTIVE )
+ {
+ pMedKit->SetModel( LUNCHBOX_FESTIVE_DROP_MODEL );
+ pMedKit->m_nSkin = ( pPlayer->GetTeamNumber() == TF_TEAM_RED ) ? 0 : 1;
+ }
+ else if ( nLunchBoxType == LUNCHBOX_ADDS_MAXHEALTH )
+ {
+ pMedKit->SetModel( LUNCHBOX_CHOCOLATE_BAR );
+ }
+ else
+ {
+ pMedKit->SetModel( LUNCHBOX_DROP_MODEL );
+ }
+
+ // clear out the overrides so the thrown sandvich/steak look correct in either vision mode
+ pMedKit->ClearModelIndexOverrides();
+
+ pMedKit->SetAbsAngles( vec3_angle );
+ pMedKit->SetSize( LUNCHBOX_DROPPED_MINS, LUNCHBOX_DROPPED_MAXS );
+
+ // the thrower has to wait 0.3 to pickup the powerup (so he can throw it while running forward)
+ pMedKit->DropSingleInstance( vecVelocity, pPlayer, 0.3 );
+ }
+
+ m_hThrownPowerup = pMedKit;
+#endif
+
+ pPlayer->RemoveAmmo( m_pWeaponInfo->GetWeaponData( m_iWeaponMode ).m_iAmmoPerShot, m_iPrimaryAmmoType );
+ g_pGameRules->SwitchToNextBestWeapon( pPlayer, this );
+
+ StartEffectBarRegen();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFLunchBox::DrainAmmo( bool bForceCooldown )
+{
+ CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() );
+ if ( !pOwner )
+ return;
+
+#ifdef GAME_DLL
+
+ int iLunchboxType = GetLunchboxType();
+ // If we're damaged while eating/taunting, bForceCooldown will be true
+ if ( pOwner->IsPlayerClass( TF_CLASS_HEAVYWEAPONS ) )
+ {
+ if ( pOwner->GetHealth() < pOwner->GetMaxHealth() || GetLunchboxType() == LUNCHBOX_ADDS_MINICRITS || iLunchboxType == LUNCHBOX_ADDS_MAXHEALTH || bForceCooldown )
+ {
+ StartEffectBarRegen();
+ }
+ else // Full health regular sandwhich, I can eat forever
+ {
+ return;
+ }
+ }
+ else if ( pOwner->IsPlayerClass( TF_CLASS_SCOUT ) )
+ {
+ StartEffectBarRegen();
+ }
+
+ // Strange Tracking. Only go through if we have ammo at this point.
+ if ( !pOwner->IsBot() && pOwner->GetAmmoCount( m_iPrimaryAmmoType ) > 0 )
+ {
+ EconEntity_OnOwnerKillEaterEventNoPartner( dynamic_cast<CEconEntity *>( this ), pOwner, kKillEaterEvent_FoodEaten );
+ }
+
+ pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType );
+#else
+
+ pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType );
+ StartEffectBarRegen();
+
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFLunchBox::Detach( void )
+{
+#ifdef GAME_DLL
+ // Terrible - but for now, we're the only place that adds this (custom) attribute
+ if ( GetLunchboxType() == LUNCHBOX_ADDS_MAXHEALTH )
+ {
+ CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() );
+ if ( pOwner )
+ {
+ // Prevents use-then-switch-class exploit (heavy->scout)
+ // Not a big deal in pubs, but it can mess with competitive
+ pOwner->RemoveCustomAttribute( "hidden maxhealth non buffed" );
+ }
+ }
+#endif
+
+ BaseClass::Detach();
+}
+
+#ifdef GAME_DLL
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CTFLunchBox::ApplyBiteEffects( CTFPlayer *pPlayer )
+{
+ int nLunchBoxType = GetLunchboxType();
+
+ if ( nLunchBoxType == LUNCHBOX_ADDS_MAXHEALTH )
+ {
+ // add 50 health to player for 30 seconds
+ pPlayer->AddCustomAttribute( "hidden maxhealth non buffed", 50.f, 30.f );
+ }
+ else if ( nLunchBoxType == LUNCHBOX_ADDS_MINICRITS )
+ {
+ static const float s_fSteakSandwichDuration = 16.0f;
+
+ // Steak sandvich.
+ pPlayer->m_Shared.AddCond( TF_COND_ENERGY_BUFF, s_fSteakSandwichDuration );
+ pPlayer->m_Shared.AddCond( TF_COND_CANNOT_SWITCH_FROM_MELEE, s_fSteakSandwichDuration );
+ pPlayer->m_Shared.SetBiteEffectWasApplied();
+
+ return;
+ }
+
+ // Then heal the player
+ int iHeal = ( nLunchBoxType == LUNCHBOX_ADDS_MAXHEALTH ) ? 25 : 75;
+ int iHealType = DMG_GENERIC;
+ if ( nLunchBoxType == LUNCHBOX_ADDS_MAXHEALTH && pPlayer->GetHealth() < 400 )
+ {
+ iHealType = DMG_IGNORE_MAXHEALTH;
+ iHeal = Min( 25, 400 - pPlayer->GetHealth() );
+ }
+
+ float flHealScale = 1.0f;
+ CALL_ATTRIB_HOOK_FLOAT( flHealScale, lunchbox_healing_scale );
+ iHeal = iHeal * flHealScale;
+
+ int iHealed = pPlayer->TakeHealth( iHeal, iHealType );
+
+ if ( iHealed > 0 )
+ {
+ CTF_GameStats.Event_PlayerHealedOther( pPlayer, iHealed );
+ }
+
+ // Restore ammo if applicable
+ if ( nLunchBoxType == LUNCHBOX_ADDS_AMMO )
+ {
+ int maxPrimary = pPlayer->GetMaxAmmo( TF_AMMO_PRIMARY );
+ pPlayer->GiveAmmo( maxPrimary * 0.25, TF_AMMO_PRIMARY, true );
+ }
+}
+#endif // GAME_DLL
+
+//-----------------------------------------------------------------------------
+// Purpose: Energy Drink
+//-----------------------------------------------------------------------------
+CTFLunchBox_Drink::CTFLunchBox_Drink()
+{
+}
+
+#ifdef CLIENT_DLL
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CTFLunchBox_Drink::Holster( CBaseCombatWeapon *pSwitchingTo )
+{
+ CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() );
+ if ( pOwner && pOwner->IsLocalPlayer() )
+ {
+ C_BaseEntity *pParticleEnt = pOwner->GetViewModel(0);
+ if ( pParticleEnt )
+ {
+ pOwner->StopViewModelParticles( pParticleEnt );
+ }
+ }
+
+ return BaseClass::Holster( pSwitchingTo );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+const char* CTFLunchBox_Drink::ModifyEventParticles( const char* token )
+{
+ if ( GetLunchboxType() == LUNCHBOX_ADDS_MINICRITS )
+ {
+ if ( FStrEq( token, "energydrink_splash") )
+ {
+ CEconItemView *pItem = m_AttributeManager.GetItem();
+ int iSystems = pItem->GetStaticData()->GetNumAttachedParticles( GetTeamNumber() );
+ for ( int i = 0; i < iSystems; i++ )
+ {
+ attachedparticlesystem_t *pSystem = pItem->GetStaticData()->GetAttachedParticleData( GetTeamNumber(),i );
+ if ( pSystem->iCustomType == 1 )
+ {
+ return pSystem->pszSystemName;
+ }
+ }
+ }
+ }
+
+ return BaseClass::ModifyEventParticles( token );
+}
+
+#endif // CLIENT_DLL \ No newline at end of file