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.
787 lines
21 KiB
787 lines
21 KiB
![]()
4 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
//=============================================================================
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "tf_item_powerup_bottle.h"
|
||
|
#include "tf_gamerules.h"
|
||
|
|
||
|
#ifdef GAME_DLL
|
||
|
#include "tf_player.h"
|
||
|
#include "tf_obj_sentrygun.h"
|
||
|
#include "tf_weapon_medigun.h"
|
||
|
#endif
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include "tier0/memdbgon.h"
|
||
|
|
||
|
|
||
|
#ifndef GAME_DLL
|
||
|
extern ConVar cl_hud_minmode;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
LINK_ENTITY_TO_CLASS( tf_powerup_bottle, CTFPowerupBottle );
|
||
|
IMPLEMENT_NETWORKCLASS_ALIASED( TFPowerupBottle, DT_TFPowerupBottle )
|
||
|
|
||
|
// Network Table --
|
||
|
BEGIN_NETWORK_TABLE( CTFPowerupBottle, DT_TFPowerupBottle )
|
||
|
#if defined( GAME_DLL )
|
||
|
SendPropBool( SENDINFO( m_bActive ) ),
|
||
|
SendPropInt( SENDINFO( m_usNumCharges ), -1, SPROP_UNSIGNED ),
|
||
|
#else
|
||
|
RecvPropBool( RECVINFO( m_bActive ) ),
|
||
|
RecvPropInt( RECVINFO( m_usNumCharges ) ),
|
||
|
#endif // GAME_DLL
|
||
|
END_NETWORK_TABLE()
|
||
|
// -- Network Table
|
||
|
|
||
|
// Data Desc --
|
||
|
BEGIN_DATADESC( CTFPowerupBottle )
|
||
|
END_DATADESC()
|
||
|
// -- Data Desc
|
||
|
|
||
|
PRECACHE_REGISTER( tf_powerup_bottle );
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// SHARED CODE
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
CTFPowerupBottle::CTFPowerupBottle() : CTFWearable()
|
||
|
{
|
||
|
m_bActive = false;
|
||
|
m_usNumCharges = 0;
|
||
|
m_flLastSpawnTime = 0.f;
|
||
|
|
||
|
#ifdef TF_CLIENT_DLL
|
||
|
ListenForGameEvent( "player_spawn" );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void CTFPowerupBottle::Precache( void )
|
||
|
{
|
||
|
PrecacheModel( "models/player/items/mvm_loot/all_class/mvm_flask_generic.mdl" );
|
||
|
PrecacheModel( "models/player/items/mvm_loot/all_class/mvm_flask_krit.mdl" );
|
||
|
PrecacheModel( "models/player/items/mvm_loot/all_class/mvm_flask_uber.mdl" );
|
||
|
PrecacheModel( "models/player/items/mvm_loot/all_class/mvm_flask_tele.mdl" );
|
||
|
PrecacheModel( "models/player/items/mvm_loot/all_class/mvm_flask_ammo.mdl" );
|
||
|
PrecacheModel( "models/player/items/mvm_loot/all_class/mvm_flask_build.mdl" );
|
||
|
|
||
|
BaseClass::Precache();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Reset the bottle to its initial state
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFPowerupBottle::Reset( void )
|
||
|
{
|
||
|
m_bActive = false;
|
||
|
SetNumCharges( 0 );
|
||
|
|
||
|
#ifdef GAME_DLL
|
||
|
class CAttributeIterator_ZeroRefundableCurrency : public IEconItemUntypedAttributeIterator
|
||
|
{
|
||
|
public:
|
||
|
CAttributeIterator_ZeroRefundableCurrency( CAttributeList *pAttrList )
|
||
|
: m_pAttrList( pAttrList )
|
||
|
{
|
||
|
Assert( m_pAttrList );
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
virtual bool OnIterateAttributeValueUntyped( const CEconItemAttributeDefinition *pAttrDef )
|
||
|
{
|
||
|
if ( ::FindAttribute( m_pAttrList, pAttrDef ) )
|
||
|
{
|
||
|
m_pAttrList->SetRuntimeAttributeRefundableCurrency( pAttrDef, 0 );
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
CAttributeList *m_pAttrList;
|
||
|
};
|
||
|
|
||
|
CAttributeIterator_ZeroRefundableCurrency it( GetAttributeList() );
|
||
|
GetAttributeList()->IterateAttributes( &it );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
PowerupBottleType_t CTFPowerupBottle::GetPowerupType( void ) const
|
||
|
{
|
||
|
int iHasCritBoost = 0;
|
||
|
CALL_ATTRIB_HOOK_INT( iHasCritBoost, critboost );
|
||
|
if ( iHasCritBoost )
|
||
|
{
|
||
|
return POWERUP_BOTTLE_CRITBOOST;
|
||
|
}
|
||
|
|
||
|
int iHasUbercharge = 0;
|
||
|
CALL_ATTRIB_HOOK_INT( iHasUbercharge, ubercharge );
|
||
|
if ( iHasUbercharge )
|
||
|
{
|
||
|
return POWERUP_BOTTLE_UBERCHARGE;
|
||
|
}
|
||
|
|
||
|
int iHasRecall = 0;
|
||
|
CALL_ATTRIB_HOOK_INT( iHasRecall, recall );
|
||
|
if ( iHasRecall )
|
||
|
{
|
||
|
return POWERUP_BOTTLE_RECALL;
|
||
|
}
|
||
|
|
||
|
int iHasRefillAmmo = 0;
|
||
|
CALL_ATTRIB_HOOK_INT( iHasRefillAmmo, refill_ammo );
|
||
|
if ( iHasRefillAmmo )
|
||
|
{
|
||
|
return POWERUP_BOTTLE_REFILL_AMMO;
|
||
|
}
|
||
|
|
||
|
int iHasInstaBuildingUpgrade = 0;
|
||
|
CALL_ATTRIB_HOOK_INT( iHasInstaBuildingUpgrade, building_instant_upgrade );
|
||
|
if ( iHasInstaBuildingUpgrade )
|
||
|
{
|
||
|
return POWERUP_BOTTLE_BUILDINGS_INSTANT_UPGRADE;
|
||
|
}
|
||
|
|
||
|
#ifdef STAGING_ONLY
|
||
|
int iSeeCashThroughWall = 0;
|
||
|
CALL_ATTRIB_HOOK_INT( iSeeCashThroughWall, mvm_see_cash_through_wall );
|
||
|
if ( iSeeCashThroughWall )
|
||
|
{
|
||
|
return POWERUP_BOTTLE_SEE_CASH_THROUGH_WALL;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return POWERUP_BOTTLE_NONE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFPowerupBottle::ReapplyProvision( void )
|
||
|
{
|
||
|
// let the base class do what it needs to do in terms of adding/removing itself from old and new owners
|
||
|
BaseClass::ReapplyProvision();
|
||
|
|
||
|
CBaseEntity *pOwner = GetOwnerEntity();
|
||
|
IHasAttributes *pOwnerAttribInterface = GetAttribInterface( pOwner );
|
||
|
if ( pOwnerAttribInterface )
|
||
|
{
|
||
|
if ( m_bActive )
|
||
|
{
|
||
|
if ( !pOwnerAttribInterface->GetAttributeManager()->IsBeingProvidedToBy( this ) )
|
||
|
{
|
||
|
GetAttributeManager()->ProvideTo( pOwner );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
GetAttributeManager()->StopProvidingTo( pOwner );
|
||
|
}
|
||
|
|
||
|
#ifdef GAME_DLL
|
||
|
bool bBottleShared = false;
|
||
|
CTFPlayer *pTFPlayer = dynamic_cast< CTFPlayer* >( pOwner );
|
||
|
if ( pTFPlayer )
|
||
|
{
|
||
|
float flDuration = 0;
|
||
|
CALL_ATTRIB_HOOK_FLOAT( flDuration, powerup_duration );
|
||
|
|
||
|
// Add extra time?
|
||
|
CALL_ATTRIB_HOOK_INT_ON_OTHER( pTFPlayer, flDuration, canteen_specialist );
|
||
|
|
||
|
// This block of code checks if a medic has the ability to
|
||
|
// share bottle charges with their heal target
|
||
|
int iShareBottle = 0;
|
||
|
CWeaponMedigun *pMedigun = NULL;
|
||
|
CTFPlayer *pHealTarget = NULL;
|
||
|
if ( pTFPlayer->IsPlayerClass( TF_CLASS_MEDIC ) )
|
||
|
{
|
||
|
pMedigun = dynamic_cast<CWeaponMedigun *>( pTFPlayer->GetActiveWeapon() );
|
||
|
if ( pMedigun )
|
||
|
{
|
||
|
pHealTarget = ToTFPlayer( pMedigun->GetHealTarget() );
|
||
|
if ( pHealTarget )
|
||
|
{
|
||
|
CALL_ATTRIB_HOOK_INT_ON_OTHER( pTFPlayer, iShareBottle, canteen_specialist );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// special stuff for conditions
|
||
|
int iHasCritBoost = 0;
|
||
|
CALL_ATTRIB_HOOK_INT( iHasCritBoost, critboost );
|
||
|
if ( iHasCritBoost != 0 )
|
||
|
{
|
||
|
if ( m_bActive )
|
||
|
{
|
||
|
pTFPlayer->m_Shared.AddCond( TF_COND_CRITBOOSTED_USER_BUFF, flDuration );
|
||
|
|
||
|
if ( iShareBottle && pHealTarget )
|
||
|
{
|
||
|
pHealTarget->m_Shared.AddCond( TF_COND_CRITBOOSTED_USER_BUFF, flDuration );
|
||
|
bBottleShared = true;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pTFPlayer->m_Shared.RemoveCond( TF_COND_CRITBOOSTED_USER_BUFF, true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int iHasUbercharge = 0;
|
||
|
CALL_ATTRIB_HOOK_INT( iHasUbercharge, ubercharge );
|
||
|
if ( iHasUbercharge )
|
||
|
{
|
||
|
if ( m_bActive )
|
||
|
{
|
||
|
pTFPlayer->m_Shared.AddCond( TF_COND_INVULNERABLE_USER_BUFF, flDuration );
|
||
|
|
||
|
// Shield sentries
|
||
|
if ( pTFPlayer->IsPlayerClass( TF_CLASS_ENGINEER ) )
|
||
|
{
|
||
|
for ( int i = pTFPlayer->GetObjectCount()-1; i >= 0; i-- )
|
||
|
{
|
||
|
CObjectSentrygun *pSentry = dynamic_cast<CObjectSentrygun *>( pTFPlayer->GetObject(i) );
|
||
|
if ( pSentry && !pSentry->IsCarried() )
|
||
|
{
|
||
|
pSentry->SetShieldLevel( SHIELD_MAX, flDuration );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if ( iShareBottle && pHealTarget )
|
||
|
{
|
||
|
pHealTarget->m_Shared.AddCond( TF_COND_INVULNERABLE_USER_BUFF, flDuration, pTFPlayer );
|
||
|
bBottleShared = true;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pTFPlayer->m_Shared.RemoveCond( TF_COND_INVULNERABLE_USER_BUFF, true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int iHasRecall = 0;
|
||
|
CALL_ATTRIB_HOOK_INT( iHasRecall, recall );
|
||
|
if ( iHasRecall )
|
||
|
{
|
||
|
if ( m_bActive )
|
||
|
{
|
||
|
pTFPlayer->ForceRespawn();
|
||
|
pTFPlayer->m_Shared.AddCond( TF_COND_SPEED_BOOST, 7.f );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int iHasRefillAmmo = 0;
|
||
|
CALL_ATTRIB_HOOK_INT( iHasRefillAmmo, refill_ammo );
|
||
|
if ( iHasRefillAmmo )
|
||
|
{
|
||
|
if ( m_bActive )
|
||
|
{
|
||
|
// Refill weapon clips
|
||
|
for ( int i = 0; i < MAX_WEAPONS; i++ )
|
||
|
{
|
||
|
CBaseCombatWeapon *pWeapon = pTFPlayer->GetWeapon(i);
|
||
|
if ( !pWeapon )
|
||
|
continue;
|
||
|
|
||
|
// ACHIEVEMENT_TF_MVM_USE_AMMO_BOTTLE
|
||
|
if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() )
|
||
|
{
|
||
|
if ( ( pWeapon->UsesPrimaryAmmo() && !pWeapon->HasPrimaryAmmo() ) ||
|
||
|
( pWeapon->UsesSecondaryAmmo() && !pWeapon->HasSecondaryAmmo() ) )
|
||
|
{
|
||
|
pTFPlayer->AwardAchievement( ACHIEVEMENT_TF_MVM_USE_AMMO_BOTTLE );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pWeapon->GiveDefaultAmmo();
|
||
|
|
||
|
if ( iShareBottle && pHealTarget )
|
||
|
{
|
||
|
CBaseCombatWeapon *pPatientWeapon = pHealTarget->GetWeapon(i);
|
||
|
if ( !pPatientWeapon )
|
||
|
continue;
|
||
|
|
||
|
pPatientWeapon->GiveDefaultAmmo();
|
||
|
bBottleShared = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// And give the player ammo
|
||
|
for ( int iAmmo = 0; iAmmo < TF_AMMO_COUNT; ++iAmmo )
|
||
|
{
|
||
|
pTFPlayer->GiveAmmo( pTFPlayer->GetMaxAmmo(iAmmo), iAmmo, true, kAmmoSource_Resupply );
|
||
|
|
||
|
if ( iShareBottle && pHealTarget )
|
||
|
{
|
||
|
pHealTarget->GiveAmmo( pHealTarget->GetMaxAmmo(iAmmo), iAmmo, true, kAmmoSource_Resupply );
|
||
|
bBottleShared = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int iHasInstaBuildingUpgrade = 0;
|
||
|
CALL_ATTRIB_HOOK_INT( iHasInstaBuildingUpgrade, building_instant_upgrade );
|
||
|
if ( iHasInstaBuildingUpgrade )
|
||
|
{
|
||
|
if ( m_bActive )
|
||
|
{
|
||
|
for ( int i = pTFPlayer->GetObjectCount()-1; i >= 0; i-- )
|
||
|
{
|
||
|
CBaseObject *pObj = pTFPlayer->GetObject(i);
|
||
|
if ( pObj )
|
||
|
{
|
||
|
int nMaxLevel = pObj->GetMaxUpgradeLevel();
|
||
|
|
||
|
// If object is carried, set the target max and move on
|
||
|
if ( pObj->IsCarried() )
|
||
|
{
|
||
|
pObj->SetHighestUpgradeLevel( nMaxLevel );
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// If we're already at max level, heal
|
||
|
if ( pObj->GetUpgradeLevel() == nMaxLevel )
|
||
|
{
|
||
|
pObj->SetHealth( pObj->GetMaxHealth() );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() )
|
||
|
{
|
||
|
if ( pObj->GetType() == OBJ_SENTRYGUN )
|
||
|
{
|
||
|
IGameEvent *event = gameeventmanager->CreateEvent( "mvm_quick_sentry_upgrade" );
|
||
|
if ( event )
|
||
|
{
|
||
|
event->SetInt( "player", GetOwnerEntity()->entindex() );
|
||
|
gameeventmanager->FireEvent( event );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pObj->DoQuickBuild( true );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ACHIEVEMENT_TF_MVM_MEDIC_SHARE_BOTTLES
|
||
|
if ( bBottleShared )
|
||
|
{
|
||
|
IGameEvent *event = gameeventmanager->CreateEvent( "mvm_medic_powerup_shared" );
|
||
|
if ( event )
|
||
|
{
|
||
|
event->SetInt( "player", pTFPlayer->entindex() );
|
||
|
gameeventmanager->FireEvent( event );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Removes the item and deactivates any effect
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFPowerupBottle::UnEquip( CBasePlayer* pOwner )
|
||
|
{
|
||
|
BaseClass::UnEquip( pOwner );
|
||
|
RemoveEffect();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CTFPowerupBottle::Use()
|
||
|
{
|
||
|
if ( !m_bActive && GetNumCharges() > 0 )
|
||
|
{
|
||
|
if ( !AllowedToUse() )
|
||
|
return false;
|
||
|
|
||
|
#ifdef GAME_DLL
|
||
|
// Use up one charge worth of refundable money when a charge is used
|
||
|
class CAttributeIterator_ConsumeOneRefundableCharge : public IEconItemUntypedAttributeIterator
|
||
|
{
|
||
|
public:
|
||
|
CAttributeIterator_ConsumeOneRefundableCharge( CAttributeList *pAttrList, int iNumCharges )
|
||
|
: m_pAttrList( pAttrList )
|
||
|
, m_iNumCharges( iNumCharges )
|
||
|
{
|
||
|
Assert( m_pAttrList );
|
||
|
Assert( m_iNumCharges > 0 );
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
virtual bool OnIterateAttributeValueUntyped( const CEconItemAttributeDefinition *pAttrDef )
|
||
|
{
|
||
|
if ( ::FindAttribute( m_pAttrList, pAttrDef ) )
|
||
|
{
|
||
|
int nRefundableCurrency = m_pAttrList->GetRuntimeAttributeRefundableCurrency( pAttrDef );
|
||
|
if ( nRefundableCurrency > 0 )
|
||
|
{
|
||
|
m_pAttrList->SetRuntimeAttributeRefundableCurrency( pAttrDef, nRefundableCurrency - (nRefundableCurrency / m_iNumCharges) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Backwards compatibility -- assume any number of attributes.
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
CAttributeList *m_pAttrList;
|
||
|
int m_iNumCharges;
|
||
|
};
|
||
|
|
||
|
CAttributeIterator_ConsumeOneRefundableCharge it( GetAttributeList(), GetNumCharges() );
|
||
|
GetAttributeList()->IterateAttributes( &it );
|
||
|
#endif
|
||
|
|
||
|
float flDuration = 0;
|
||
|
CALL_ATTRIB_HOOK_FLOAT( flDuration, powerup_duration );
|
||
|
|
||
|
// Add extra time?
|
||
|
CTFPlayer *pOwner = ToTFPlayer( GetOwnerEntity() );
|
||
|
if ( pOwner )
|
||
|
{
|
||
|
CALL_ATTRIB_HOOK_INT_ON_OTHER( pOwner, flDuration, canteen_specialist );
|
||
|
}
|
||
|
IGameEvent *event = gameeventmanager->CreateEvent( "player_used_powerup_bottle" );
|
||
|
if ( event )
|
||
|
{
|
||
|
event->SetInt( "player", GetOwnerEntity()->entindex() );
|
||
|
event->SetInt( "type", GetPowerupType() );
|
||
|
event->SetFloat( "time", flDuration );
|
||
|
gameeventmanager->FireEvent( event );
|
||
|
}
|
||
|
|
||
|
#ifdef GAME_DLL
|
||
|
if ( pOwner )
|
||
|
{
|
||
|
EconEntity_OnOwnerKillEaterEventNoPartner( dynamic_cast<CEconEntity *>( this ), pOwner, kKillEaterEvent_PowerupBottlesUsed );
|
||
|
|
||
|
// we consumed an upgrade - forget it
|
||
|
pOwner->ForgetFirstUpgradeForItem( GetAttributeContainer()->GetItem() );
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
SetNumCharges( GetNumCharges() - 1 );
|
||
|
m_bActive = true;
|
||
|
ReapplyProvision();
|
||
|
|
||
|
SetContextThink( &CTFPowerupBottle::StatusThink, gpGlobals->curtime + flDuration, "PowerupBottleThink" );
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFPowerupBottle::StatusThink()
|
||
|
{
|
||
|
RemoveEffect();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFPowerupBottle::RemoveEffect()
|
||
|
{
|
||
|
m_bActive = false;
|
||
|
ReapplyProvision();
|
||
|
SetContextThink( NULL, 0, "PowerupBottleThink" );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFPowerupBottle::SetNumCharges( uint8 usNumCharges )
|
||
|
{
|
||
|
static CSchemaAttributeDefHandle pAttrDef_PowerupCharges( "powerup charges" );
|
||
|
|
||
|
m_usNumCharges = usNumCharges;
|
||
|
|
||
|
if ( !pAttrDef_PowerupCharges )
|
||
|
return;
|
||
|
|
||
|
CEconItemView *pEconItemView = GetAttributeContainer()->GetItem();
|
||
|
if ( !pEconItemView )
|
||
|
return;
|
||
|
|
||
|
pEconItemView->GetAttributeList()->SetRuntimeAttributeValue( pAttrDef_PowerupCharges, float( usNumCharges ) );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
uint8 CTFPowerupBottle::GetNumCharges() const
|
||
|
{
|
||
|
return m_usNumCharges;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
uint8 CTFPowerupBottle::GetMaxNumCharges() const
|
||
|
{
|
||
|
int iMaxNumCharges = 0;
|
||
|
CALL_ATTRIB_HOOK_INT( iMaxNumCharges, powerup_max_charges );
|
||
|
|
||
|
// Default canteen has 3 charges. Medic canteen specialist allows purchasing 3 more charges.
|
||
|
// If anything else increases max charges, we need to refactor how canteen specialist is handled.
|
||
|
Assert( iMaxNumCharges >= 0 && iMaxNumCharges <= 6 );
|
||
|
|
||
|
iMaxNumCharges = Min( iMaxNumCharges, 6 );
|
||
|
|
||
|
return (uint8)iMaxNumCharges;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CTFPowerupBottle::AllowedToUse()
|
||
|
{
|
||
|
if ( TFGameRules() && !( TFGameRules()->State_Get() == GR_STATE_BETWEEN_RNDS || TFGameRules()->State_Get() == GR_STATE_RND_RUNNING ) )
|
||
|
return false;
|
||
|
|
||
|
CTFPlayer *pPlayer = ToTFPlayer( GetOwnerEntity() );
|
||
|
if ( !pPlayer )
|
||
|
return false;
|
||
|
|
||
|
if ( pPlayer->IsObserver() || !pPlayer->IsAlive() )
|
||
|
return false;
|
||
|
|
||
|
#ifdef GAME_DLL
|
||
|
m_flLastSpawnTime = pPlayer->GetSpawnTime();
|
||
|
#endif
|
||
|
|
||
|
if ( gpGlobals->curtime < m_flLastSpawnTime + 0.7f )
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
const char* CTFPowerupBottle::GetEffectLabelText( void )
|
||
|
{
|
||
|
#ifndef GAME_DLL
|
||
|
if ( cl_hud_minmode.GetBool() )
|
||
|
{
|
||
|
return "#TF_PVE_UsePowerup_MinMode";
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
switch ( GetPowerupType() )
|
||
|
{
|
||
|
case POWERUP_BOTTLE_CRITBOOST:
|
||
|
return "#TF_PVE_UsePowerup_CritBoost";
|
||
|
|
||
|
case POWERUP_BOTTLE_UBERCHARGE:
|
||
|
return "#TF_PVE_UsePowerup_Ubercharge";
|
||
|
|
||
|
case POWERUP_BOTTLE_RECALL:
|
||
|
return "#TF_PVE_UsePowerup_Recall";
|
||
|
|
||
|
case POWERUP_BOTTLE_REFILL_AMMO:
|
||
|
return "#TF_PVE_UsePowerup_RefillAmmo";
|
||
|
|
||
|
case POWERUP_BOTTLE_BUILDINGS_INSTANT_UPGRADE:
|
||
|
return "#TF_PVE_UsePowerup_BuildinginstaUpgrade";
|
||
|
|
||
|
case POWERUP_BOTTLE_RADIUS_STEALTH:
|
||
|
return "#TF_PVE_UsePowerup_RadiusStealth";
|
||
|
#ifdef STAGING_ONLY
|
||
|
case POWERUP_BOTTLE_SEE_CASH_THROUGH_WALL:
|
||
|
return "#TF_PVE_UsePowerup_SeeCashThroughWall";
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
return "#TF_PVE_UsePowerup_CritBoost";
|
||
|
}
|
||
|
|
||
|
const char* CTFPowerupBottle::GetEffectIconName( void )
|
||
|
{
|
||
|
switch ( GetPowerupType() )
|
||
|
{
|
||
|
case POWERUP_BOTTLE_CRITBOOST:
|
||
|
return "../hud/ico_powerup_critboost_red";
|
||
|
|
||
|
case POWERUP_BOTTLE_UBERCHARGE:
|
||
|
return "../hud/ico_powerup_ubercharge_red";
|
||
|
|
||
|
case POWERUP_BOTTLE_RECALL:
|
||
|
return "../hud/ico_powerup_recall_red";
|
||
|
|
||
|
case POWERUP_BOTTLE_REFILL_AMMO:
|
||
|
return "../hud/ico_powerup_refill_ammo_red";
|
||
|
|
||
|
case POWERUP_BOTTLE_BUILDINGS_INSTANT_UPGRADE:
|
||
|
return "../hud/ico_powerup_building_instant_red";
|
||
|
|
||
|
case POWERUP_BOTTLE_RADIUS_STEALTH:
|
||
|
return "../vgui/achievements/tf_soldier_kill_spy_killer";
|
||
|
#ifdef STAGING_ONLY
|
||
|
case POWERUP_BOTTLE_SEE_CASH_THROUGH_WALL:
|
||
|
return "../vgui/achievements/tf_mvm_earn_money_bonus";
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
return "../hud/ico_powerup_critboost_red";
|
||
|
}
|
||
|
|
||
|
#ifdef TF_CLIENT_DLL
|
||
|
void CTFPowerupBottle::FireGameEvent( IGameEvent *event )
|
||
|
{
|
||
|
const char *pszEventName = event->GetName();
|
||
|
|
||
|
if ( FStrEq( pszEventName, "player_spawn" ) )
|
||
|
{
|
||
|
CTFPlayer *pTFOwner = ToTFPlayer( GetOwnerEntity() );
|
||
|
if ( !pTFOwner )
|
||
|
return;
|
||
|
|
||
|
const int nUserID = event->GetInt( "userid" );
|
||
|
CTFPlayer *pPlayer = ToTFPlayer( UTIL_PlayerByUserId( nUserID ) );
|
||
|
if ( pPlayer && pPlayer == pTFOwner )
|
||
|
{
|
||
|
m_flLastSpawnTime = gpGlobals->curtime;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int CTFPowerupBottle::GetWorldModelIndex( void )
|
||
|
{
|
||
|
if ( IsBasePowerUpBottle() && ( GetNumCharges() > 0 ) )
|
||
|
{
|
||
|
switch ( GetPowerupType() )
|
||
|
{
|
||
|
case POWERUP_BOTTLE_CRITBOOST:
|
||
|
return modelinfo->GetModelIndex( "models/player/items/mvm_loot/all_class/mvm_flask_krit.mdl" );
|
||
|
|
||
|
case POWERUP_BOTTLE_UBERCHARGE:
|
||
|
return modelinfo->GetModelIndex( "models/player/items/mvm_loot/all_class/mvm_flask_uber.mdl" );
|
||
|
|
||
|
case POWERUP_BOTTLE_RECALL:
|
||
|
return modelinfo->GetModelIndex( "models/player/items/mvm_loot/all_class/mvm_flask_tele.mdl" );
|
||
|
|
||
|
case POWERUP_BOTTLE_REFILL_AMMO:
|
||
|
return modelinfo->GetModelIndex( "models/player/items/mvm_loot/all_class/mvm_flask_ammo.mdl" );
|
||
|
|
||
|
case POWERUP_BOTTLE_BUILDINGS_INSTANT_UPGRADE:
|
||
|
return modelinfo->GetModelIndex( "models/player/items/mvm_loot/all_class/mvm_flask_build.mdl" );
|
||
|
|
||
|
case POWERUP_BOTTLE_RADIUS_STEALTH:
|
||
|
#ifdef STAGING_ONLY
|
||
|
case POWERUP_BOTTLE_SEE_CASH_THROUGH_WALL:
|
||
|
#endif
|
||
|
return modelinfo->GetModelIndex( "models/player/items/mvm_loot/all_class/mvm_flask_tele.mdl" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return BaseClass::GetWorldModelIndex();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
int CTFPowerupBottle::GetSkin()
|
||
|
{
|
||
|
if ( !IsBasePowerUpBottle() )
|
||
|
{
|
||
|
return ( ( GetNumCharges() > 0 ) ? 1 : 0 );
|
||
|
}
|
||
|
|
||
|
return BaseClass::GetSkin();
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef CLIENT_DLL
|
||
|
// ******************************************************************************************
|
||
|
// CEquipMvMCanteenNotification - Client notification to equip a canteen
|
||
|
// ******************************************************************************************
|
||
|
void CEquipMvMCanteenNotification::Accept()
|
||
|
{
|
||
|
m_bHasTriggered = true;
|
||
|
|
||
|
CPlayerInventory *pLocalInv = TFInventoryManager()->GetLocalInventory();
|
||
|
if ( !pLocalInv )
|
||
|
{
|
||
|
MarkForDeletion();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
|
||
|
if ( !pLocalPlayer )
|
||
|
{
|
||
|
MarkForDeletion();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// try to equip non-stock-spellbook first
|
||
|
static CSchemaItemDefHandle pItemDef_Robo( "Battery Canteens" );
|
||
|
static CSchemaItemDefHandle pItemDef_KritzOrTreat( "Kritz Or Treat Canteen" );
|
||
|
static CSchemaItemDefHandle pItemDef_Canteen( "Power Up Canteen (MvM)" );
|
||
|
static CSchemaItemDefHandle pItemDef_DefaultCanteen( "Default Power Up Canteen (MvM)" );
|
||
|
|
||
|
CEconItemView *pCanteen= NULL;
|
||
|
|
||
|
Assert( pItemDef_Robo );
|
||
|
Assert( pItemDef_KritzOrTreat );
|
||
|
Assert( pItemDef_Canteen );
|
||
|
Assert( pItemDef_DefaultCanteen );
|
||
|
|
||
|
for ( int i = 0; i < pLocalInv->GetItemCount(); ++i )
|
||
|
{
|
||
|
CEconItemView *pItem = pLocalInv->GetItem( i );
|
||
|
Assert( pItem );
|
||
|
|
||
|
if ( pItem->GetItemDefinition() == pItemDef_Robo
|
||
|
|| pItem->GetItemDefinition() == pItemDef_KritzOrTreat
|
||
|
|| pItem->GetItemDefinition() == pItemDef_Canteen
|
||
|
|| pItem->GetItemDefinition() == pItemDef_DefaultCanteen
|
||
|
) {
|
||
|
pCanteen = pItem;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Default item becomes a spellbook in this mode
|
||
|
itemid_t iItemId = INVALID_ITEM_ID;
|
||
|
if ( pCanteen )
|
||
|
{
|
||
|
iItemId = pCanteen->GetItemID();
|
||
|
}
|
||
|
|
||
|
TFInventoryManager()->EquipItemInLoadout( pLocalPlayer->GetPlayerClass()->GetClassIndex(), LOADOUT_POSITION_ACTION, iItemId );
|
||
|
|
||
|
// Tell the GC to tell server that we should respawn if we're in a respawn room
|
||
|
GCSDK::CGCMsg< GCSDK::MsgGCEmpty_t > msg( k_EMsgGCRespawnPostLoadoutChange );
|
||
|
GCClientSystem()->BSendMessage( msg );
|
||
|
|
||
|
MarkForDeletion();
|
||
|
}
|
||
|
|
||
|
//===========================================================================================
|
||
|
void CEquipMvMCanteenNotification::UpdateTick()
|
||
|
{
|
||
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
|
||
|
if ( pLocalPlayer )
|
||
|
{
|
||
|
CTFPowerupBottle *pCanteen = dynamic_cast<CTFPowerupBottle*>( TFInventoryManager()->GetItemInLoadoutForClass( pLocalPlayer->GetPlayerClass()->GetClassIndex(), LOADOUT_POSITION_ACTION ) );
|
||
|
if ( pCanteen )
|
||
|
{
|
||
|
MarkForDeletion();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif // client
|
||
|
|