mirror of
https://github.com/nillerusr/source-engine.git
synced 2024-12-23 14:46:53 +00:00
778 lines
17 KiB
C++
778 lines
17 KiB
C++
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//
|
||
|
//=============================================================================//
|
||
|
/*
|
||
|
|
||
|
===== h_battery.cpp ========================================================
|
||
|
|
||
|
battery-related code
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "gamerules.h"
|
||
|
#include "player.h"
|
||
|
#include "engine/IEngineSound.h"
|
||
|
#include "in_buttons.h"
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include "tier0/memdbgon.h"
|
||
|
|
||
|
static ConVar sk_suitcharger( "sk_suitcharger","0" );
|
||
|
static ConVar sk_suitcharger_citadel( "sk_suitcharger_citadel","0" );
|
||
|
static ConVar sk_suitcharger_citadel_maxarmor( "sk_suitcharger_citadel_maxarmor","0" );
|
||
|
|
||
|
#define SF_CITADEL_RECHARGER 0x2000
|
||
|
#define SF_KLEINER_RECHARGER 0x4000 // Gives only 25 health
|
||
|
|
||
|
class CRecharge : public CBaseToggle
|
||
|
{
|
||
|
public:
|
||
|
DECLARE_CLASS( CRecharge, CBaseToggle );
|
||
|
|
||
|
void Spawn( );
|
||
|
bool CreateVPhysics();
|
||
|
int DrawDebugTextOverlays(void);
|
||
|
void Off(void);
|
||
|
void Recharge(void);
|
||
|
bool KeyValue( const char *szKeyName, const char *szValue );
|
||
|
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||
|
virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() | FCAP_CONTINUOUS_USE); }
|
||
|
|
||
|
private:
|
||
|
void InputRecharge( inputdata_t &inputdata );
|
||
|
|
||
|
float MaxJuice() const;
|
||
|
void UpdateJuice( int newJuice );
|
||
|
|
||
|
DECLARE_DATADESC();
|
||
|
|
||
|
float m_flNextCharge;
|
||
|
int m_iReactivate ; // DeathMatch Delay until reactvated
|
||
|
int m_iJuice;
|
||
|
int m_iOn; // 0 = off, 1 = startup, 2 = going
|
||
|
float m_flSoundTime;
|
||
|
|
||
|
int m_nState;
|
||
|
|
||
|
COutputFloat m_OutRemainingCharge;
|
||
|
COutputEvent m_OnHalfEmpty;
|
||
|
COutputEvent m_OnEmpty;
|
||
|
COutputEvent m_OnFull;
|
||
|
COutputEvent m_OnPlayerUse;
|
||
|
};
|
||
|
|
||
|
BEGIN_DATADESC( CRecharge )
|
||
|
|
||
|
DEFINE_FIELD( m_flNextCharge, FIELD_TIME ),
|
||
|
DEFINE_FIELD( m_iReactivate, FIELD_INTEGER),
|
||
|
DEFINE_FIELD( m_iJuice, FIELD_INTEGER),
|
||
|
DEFINE_FIELD( m_iOn, FIELD_INTEGER),
|
||
|
DEFINE_FIELD( m_flSoundTime, FIELD_TIME ),
|
||
|
DEFINE_FIELD( m_nState, FIELD_INTEGER ),
|
||
|
|
||
|
// Function Pointers
|
||
|
DEFINE_FUNCTION( Off ),
|
||
|
DEFINE_FUNCTION( Recharge ),
|
||
|
|
||
|
DEFINE_OUTPUT(m_OutRemainingCharge, "OutRemainingCharge"),
|
||
|
DEFINE_OUTPUT(m_OnHalfEmpty, "OnHalfEmpty" ),
|
||
|
DEFINE_OUTPUT(m_OnEmpty, "OnEmpty" ),
|
||
|
DEFINE_OUTPUT(m_OnFull, "OnFull" ),
|
||
|
DEFINE_OUTPUT(m_OnPlayerUse, "OnPlayerUse" ),
|
||
|
|
||
|
DEFINE_INPUTFUNC( FIELD_VOID, "Recharge", InputRecharge ),
|
||
|
|
||
|
END_DATADESC()
|
||
|
|
||
|
|
||
|
LINK_ENTITY_TO_CLASS(func_recharge, CRecharge);
|
||
|
|
||
|
|
||
|
bool CRecharge::KeyValue( const char *szKeyName, const char *szValue )
|
||
|
{
|
||
|
if ( FStrEq(szKeyName, "style") ||
|
||
|
FStrEq(szKeyName, "height") ||
|
||
|
FStrEq(szKeyName, "value1") ||
|
||
|
FStrEq(szKeyName, "value2") ||
|
||
|
FStrEq(szKeyName, "value3"))
|
||
|
{
|
||
|
}
|
||
|
else if (FStrEq(szKeyName, "dmdelay"))
|
||
|
{
|
||
|
m_iReactivate = atoi(szValue);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return BaseClass::KeyValue( szKeyName, szValue );
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void CRecharge::Spawn()
|
||
|
{
|
||
|
Precache( );
|
||
|
|
||
|
SetSolid( SOLID_BSP );
|
||
|
SetMoveType( MOVETYPE_PUSH );
|
||
|
|
||
|
SetModel( STRING( GetModelName() ) );
|
||
|
|
||
|
UpdateJuice( MaxJuice() );
|
||
|
|
||
|
m_nState = 0;
|
||
|
|
||
|
CreateVPhysics();
|
||
|
}
|
||
|
|
||
|
bool CRecharge::CreateVPhysics()
|
||
|
{
|
||
|
VPhysicsInitStatic();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
int CRecharge::DrawDebugTextOverlays(void)
|
||
|
{
|
||
|
int text_offset = BaseClass::DrawDebugTextOverlays();
|
||
|
|
||
|
if (m_debugOverlays & OVERLAY_TEXT_BIT)
|
||
|
{
|
||
|
char tempstr[512];
|
||
|
Q_snprintf(tempstr,sizeof(tempstr),"Charge left: %i", m_iJuice );
|
||
|
EntityText(text_offset,tempstr,0);
|
||
|
text_offset++;
|
||
|
}
|
||
|
return text_offset;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Max juice for recharger
|
||
|
//-----------------------------------------------------------------------------
|
||
|
float CRecharge::MaxJuice() const
|
||
|
{
|
||
|
if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) )
|
||
|
{
|
||
|
return sk_suitcharger_citadel.GetFloat();
|
||
|
}
|
||
|
|
||
|
return sk_suitcharger.GetFloat();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : newJuice -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CRecharge::UpdateJuice( int newJuice )
|
||
|
{
|
||
|
bool reduced = newJuice < m_iJuice;
|
||
|
if ( reduced )
|
||
|
{
|
||
|
// Fire 1/2 way output and/or empyt output
|
||
|
int oneHalfJuice = (int)(MaxJuice() * 0.5f);
|
||
|
if ( newJuice <= oneHalfJuice && m_iJuice > oneHalfJuice )
|
||
|
{
|
||
|
m_OnHalfEmpty.FireOutput( this, this );
|
||
|
}
|
||
|
|
||
|
if ( newJuice <= 0 )
|
||
|
{
|
||
|
m_OnEmpty.FireOutput( this, this );
|
||
|
}
|
||
|
}
|
||
|
else if ( newJuice != m_iJuice &&
|
||
|
newJuice == (int)MaxJuice() )
|
||
|
{
|
||
|
m_OnFull.FireOutput( this, this );
|
||
|
}
|
||
|
m_iJuice = newJuice;
|
||
|
}
|
||
|
|
||
|
void CRecharge::InputRecharge( inputdata_t &inputdata )
|
||
|
{
|
||
|
Recharge();
|
||
|
}
|
||
|
|
||
|
void CRecharge::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
||
|
{
|
||
|
// if it's not a player, ignore
|
||
|
if ( !pActivator || !pActivator->IsPlayer() )
|
||
|
return;
|
||
|
|
||
|
// Only usable if you have the HEV suit on
|
||
|
if ( !((CBasePlayer *)pActivator)->IsSuitEquipped() )
|
||
|
{
|
||
|
if (m_flSoundTime <= gpGlobals->curtime)
|
||
|
{
|
||
|
m_flSoundTime = gpGlobals->curtime + 0.62;
|
||
|
EmitSound( "SuitRecharge.Deny" );
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// if there is no juice left, turn it off
|
||
|
if (m_iJuice <= 0)
|
||
|
{
|
||
|
m_nState = 1;
|
||
|
Off();
|
||
|
}
|
||
|
|
||
|
// if the player doesn't have the suit, or there is no juice left, make the deny noise
|
||
|
if ( m_iJuice <= 0 )
|
||
|
{
|
||
|
if (m_flSoundTime <= gpGlobals->curtime)
|
||
|
{
|
||
|
m_flSoundTime = gpGlobals->curtime + 0.62;
|
||
|
EmitSound( "SuitRecharge.Deny" );
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
SetNextThink( gpGlobals->curtime + 0.25 );
|
||
|
SetThink(&CRecharge::Off);
|
||
|
|
||
|
// Time to recharge yet?
|
||
|
if (m_flNextCharge >= gpGlobals->curtime)
|
||
|
return;
|
||
|
|
||
|
// Make sure that we have a caller
|
||
|
if (!pActivator)
|
||
|
return;
|
||
|
|
||
|
m_hActivator = pActivator;
|
||
|
|
||
|
//only recharge the player
|
||
|
|
||
|
if (!m_hActivator->IsPlayer() )
|
||
|
return;
|
||
|
|
||
|
// Play the on sound or the looping charging sound
|
||
|
if (!m_iOn)
|
||
|
{
|
||
|
m_iOn++;
|
||
|
EmitSound( "SuitRecharge.Start" );
|
||
|
m_flSoundTime = 0.56 + gpGlobals->curtime;
|
||
|
|
||
|
m_OnPlayerUse.FireOutput( pActivator, this );
|
||
|
}
|
||
|
|
||
|
if ((m_iOn == 1) && (m_flSoundTime <= gpGlobals->curtime))
|
||
|
{
|
||
|
m_iOn++;
|
||
|
CPASAttenuationFilter filter( this, "SuitRecharge.ChargingLoop" );
|
||
|
filter.MakeReliable();
|
||
|
EmitSound( filter, entindex(), "SuitRecharge.ChargingLoop" );
|
||
|
}
|
||
|
|
||
|
CBasePlayer *pl = (CBasePlayer *) m_hActivator.Get();
|
||
|
|
||
|
// charge the player
|
||
|
int nMaxArmor = 100;
|
||
|
int nIncrementArmor = 1;
|
||
|
if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) )
|
||
|
{
|
||
|
nMaxArmor = sk_suitcharger_citadel_maxarmor.GetInt();
|
||
|
nIncrementArmor = 10;
|
||
|
|
||
|
// Also give health for the citadel version.
|
||
|
if( pActivator->GetHealth() < pActivator->GetMaxHealth() )
|
||
|
{
|
||
|
pActivator->TakeHealth( 5, DMG_GENERIC );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pl->ArmorValue() < nMaxArmor)
|
||
|
{
|
||
|
UpdateJuice( m_iJuice - nIncrementArmor );
|
||
|
pl->IncrementArmorValue( nIncrementArmor, nMaxArmor );
|
||
|
}
|
||
|
|
||
|
// Send the output.
|
||
|
float flRemaining = m_iJuice / MaxJuice();
|
||
|
m_OutRemainingCharge.Set(flRemaining, pActivator, this);
|
||
|
|
||
|
// govern the rate of charge
|
||
|
m_flNextCharge = gpGlobals->curtime + 0.1;
|
||
|
}
|
||
|
|
||
|
void CRecharge::Recharge(void)
|
||
|
{
|
||
|
UpdateJuice( MaxJuice() );
|
||
|
m_nState = 0;
|
||
|
SetThink( &CRecharge::SUB_DoNothing );
|
||
|
}
|
||
|
|
||
|
void CRecharge::Off(void)
|
||
|
{
|
||
|
// Stop looping sound.
|
||
|
if (m_iOn > 1)
|
||
|
{
|
||
|
StopSound( "SuitRecharge.ChargingLoop" );
|
||
|
}
|
||
|
|
||
|
m_iOn = 0;
|
||
|
|
||
|
if ((!m_iJuice) && ( ( m_iReactivate = g_pGameRules->FlHEVChargerRechargeTime() ) > 0) )
|
||
|
{
|
||
|
SetNextThink( gpGlobals->curtime + m_iReactivate );
|
||
|
SetThink(&CRecharge::Recharge);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SetThink( NULL );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//NEW
|
||
|
class CNewRecharge : public CBaseAnimating
|
||
|
{
|
||
|
public:
|
||
|
DECLARE_CLASS( CNewRecharge, CBaseAnimating );
|
||
|
|
||
|
void Spawn( );
|
||
|
bool CreateVPhysics();
|
||
|
int DrawDebugTextOverlays(void);
|
||
|
void Off(void);
|
||
|
void Recharge(void);
|
||
|
bool KeyValue( const char *szKeyName, const char *szValue );
|
||
|
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||
|
virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() | m_iCaps ); }
|
||
|
|
||
|
void SetInitialCharge( void );
|
||
|
|
||
|
private:
|
||
|
void InputRecharge( inputdata_t &inputdata );
|
||
|
void InputSetCharge( inputdata_t &inputdata );
|
||
|
float MaxJuice() const;
|
||
|
void UpdateJuice( int newJuice );
|
||
|
void Precache( void );
|
||
|
|
||
|
DECLARE_DATADESC();
|
||
|
|
||
|
float m_flNextCharge;
|
||
|
int m_iReactivate ; // DeathMatch Delay until reactvated
|
||
|
int m_iJuice;
|
||
|
int m_iOn; // 0 = off, 1 = startup, 2 = going
|
||
|
float m_flSoundTime;
|
||
|
|
||
|
int m_nState;
|
||
|
int m_iCaps;
|
||
|
int m_iMaxJuice;
|
||
|
|
||
|
COutputFloat m_OutRemainingCharge;
|
||
|
COutputEvent m_OnHalfEmpty;
|
||
|
COutputEvent m_OnEmpty;
|
||
|
COutputEvent m_OnFull;
|
||
|
COutputEvent m_OnPlayerUse;
|
||
|
|
||
|
virtual void StudioFrameAdvance ( void );
|
||
|
float m_flJuice;
|
||
|
};
|
||
|
|
||
|
BEGIN_DATADESC( CNewRecharge )
|
||
|
|
||
|
DEFINE_FIELD( m_flNextCharge, FIELD_TIME ),
|
||
|
DEFINE_FIELD( m_iReactivate, FIELD_INTEGER),
|
||
|
DEFINE_FIELD( m_iJuice, FIELD_INTEGER),
|
||
|
DEFINE_FIELD( m_iOn, FIELD_INTEGER),
|
||
|
DEFINE_FIELD( m_flSoundTime, FIELD_TIME ),
|
||
|
DEFINE_FIELD( m_nState, FIELD_INTEGER ),
|
||
|
DEFINE_FIELD( m_iCaps, FIELD_INTEGER ),
|
||
|
DEFINE_FIELD( m_iMaxJuice, FIELD_INTEGER ),
|
||
|
|
||
|
// Function Pointers
|
||
|
DEFINE_FUNCTION( Off ),
|
||
|
DEFINE_FUNCTION( Recharge ),
|
||
|
|
||
|
DEFINE_OUTPUT(m_OutRemainingCharge, "OutRemainingCharge"),
|
||
|
DEFINE_OUTPUT(m_OnHalfEmpty, "OnHalfEmpty" ),
|
||
|
DEFINE_OUTPUT(m_OnEmpty, "OnEmpty" ),
|
||
|
DEFINE_OUTPUT(m_OnFull, "OnFull" ),
|
||
|
DEFINE_OUTPUT(m_OnPlayerUse, "OnPlayerUse" ),
|
||
|
DEFINE_FIELD( m_flJuice, FIELD_FLOAT ),
|
||
|
|
||
|
DEFINE_INPUTFUNC( FIELD_VOID, "Recharge", InputRecharge ),
|
||
|
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetCharge", InputSetCharge ),
|
||
|
|
||
|
END_DATADESC()
|
||
|
|
||
|
|
||
|
LINK_ENTITY_TO_CLASS( item_suitcharger, CNewRecharge);
|
||
|
|
||
|
#define HEALTH_CHARGER_MODEL_NAME "models/props_combine/suit_charger001.mdl"
|
||
|
#define CHARGE_RATE 0.25f
|
||
|
#define CHARGES_PER_SECOND 1 / CHARGE_RATE
|
||
|
#define CITADEL_CHARGES_PER_SECOND 10 / CHARGE_RATE
|
||
|
#define CALLS_PER_SECOND 7.0f * CHARGES_PER_SECOND
|
||
|
|
||
|
|
||
|
bool CNewRecharge::KeyValue( const char *szKeyName, const char *szValue )
|
||
|
{
|
||
|
if ( FStrEq(szKeyName, "style") ||
|
||
|
FStrEq(szKeyName, "height") ||
|
||
|
FStrEq(szKeyName, "value1") ||
|
||
|
FStrEq(szKeyName, "value2") ||
|
||
|
FStrEq(szKeyName, "value3"))
|
||
|
{
|
||
|
}
|
||
|
else if (FStrEq(szKeyName, "dmdelay"))
|
||
|
{
|
||
|
m_iReactivate = atoi(szValue);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return BaseClass::KeyValue( szKeyName, szValue );
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void CNewRecharge::Precache( void )
|
||
|
{
|
||
|
PrecacheModel( HEALTH_CHARGER_MODEL_NAME );
|
||
|
|
||
|
PrecacheScriptSound( "SuitRecharge.Deny" );
|
||
|
PrecacheScriptSound( "SuitRecharge.Start" );
|
||
|
PrecacheScriptSound( "SuitRecharge.ChargingLoop" );
|
||
|
|
||
|
}
|
||
|
|
||
|
void CNewRecharge::SetInitialCharge( void )
|
||
|
{
|
||
|
if ( HasSpawnFlags( SF_KLEINER_RECHARGER ) )
|
||
|
{
|
||
|
// The charger in Kleiner's lab.
|
||
|
m_iMaxJuice = 25.0f;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) )
|
||
|
{
|
||
|
m_iMaxJuice = sk_suitcharger_citadel.GetFloat();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_iMaxJuice = sk_suitcharger.GetFloat();
|
||
|
}
|
||
|
|
||
|
void CNewRecharge::Spawn()
|
||
|
{
|
||
|
Precache( );
|
||
|
|
||
|
SetMoveType( MOVETYPE_NONE );
|
||
|
SetSolid( SOLID_VPHYSICS );
|
||
|
CreateVPhysics();
|
||
|
|
||
|
SetModel( HEALTH_CHARGER_MODEL_NAME );
|
||
|
AddEffects( EF_NOSHADOW );
|
||
|
|
||
|
ResetSequence( LookupSequence( "idle" ) );
|
||
|
|
||
|
SetInitialCharge();
|
||
|
|
||
|
UpdateJuice( MaxJuice() );
|
||
|
|
||
|
m_nState = 0;
|
||
|
m_iCaps = FCAP_CONTINUOUS_USE;
|
||
|
|
||
|
CreateVPhysics();
|
||
|
|
||
|
m_flJuice = m_iJuice;
|
||
|
|
||
|
m_iReactivate = 0;
|
||
|
|
||
|
SetCycle( 1.0f - ( m_flJuice / MaxJuice() ) );
|
||
|
}
|
||
|
|
||
|
bool CNewRecharge::CreateVPhysics()
|
||
|
{
|
||
|
VPhysicsInitStatic();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
int CNewRecharge::DrawDebugTextOverlays(void)
|
||
|
{
|
||
|
int text_offset = BaseClass::DrawDebugTextOverlays();
|
||
|
|
||
|
if (m_debugOverlays & OVERLAY_TEXT_BIT)
|
||
|
{
|
||
|
char tempstr[512];
|
||
|
Q_snprintf(tempstr,sizeof(tempstr),"Charge left: %i", m_iJuice );
|
||
|
EntityText(text_offset,tempstr,0);
|
||
|
text_offset++;
|
||
|
}
|
||
|
return text_offset;
|
||
|
}
|
||
|
|
||
|
void CNewRecharge::StudioFrameAdvance( void )
|
||
|
{
|
||
|
m_flPlaybackRate = 0;
|
||
|
|
||
|
float flMaxJuice = MaxJuice() + 0.1f;
|
||
|
float flNewJuice = 1.0f - (float)( m_flJuice / flMaxJuice );
|
||
|
|
||
|
SetCycle( flNewJuice );
|
||
|
// Msg( "Cycle: %f - Juice: %d - m_flJuice :%f - Interval: %f\n", (float)GetCycle(), (int)m_iJuice, (float)m_flJuice, GetAnimTimeInterval() );
|
||
|
|
||
|
if ( !m_flPrevAnimTime )
|
||
|
{
|
||
|
m_flPrevAnimTime = gpGlobals->curtime;
|
||
|
}
|
||
|
|
||
|
// Latch prev
|
||
|
m_flPrevAnimTime = m_flAnimTime;
|
||
|
// Set current
|
||
|
m_flAnimTime = gpGlobals->curtime;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Max juice for recharger
|
||
|
//-----------------------------------------------------------------------------
|
||
|
float CNewRecharge::MaxJuice() const
|
||
|
{
|
||
|
return m_iMaxJuice;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : newJuice -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CNewRecharge::UpdateJuice( int newJuice )
|
||
|
{
|
||
|
bool reduced = newJuice < m_iJuice;
|
||
|
if ( reduced )
|
||
|
{
|
||
|
// Fire 1/2 way output and/or empyt output
|
||
|
int oneHalfJuice = (int)(MaxJuice() * 0.5f);
|
||
|
if ( newJuice <= oneHalfJuice && m_iJuice > oneHalfJuice )
|
||
|
{
|
||
|
m_OnHalfEmpty.FireOutput( this, this );
|
||
|
}
|
||
|
|
||
|
if ( newJuice <= 0 )
|
||
|
{
|
||
|
m_OnEmpty.FireOutput( this, this );
|
||
|
}
|
||
|
}
|
||
|
else if ( newJuice != m_iJuice &&
|
||
|
newJuice == (int)MaxJuice() )
|
||
|
{
|
||
|
m_OnFull.FireOutput( this, this );
|
||
|
}
|
||
|
m_iJuice = newJuice;
|
||
|
}
|
||
|
|
||
|
void CNewRecharge::InputRecharge( inputdata_t &inputdata )
|
||
|
{
|
||
|
Recharge();
|
||
|
}
|
||
|
|
||
|
void CNewRecharge::InputSetCharge( inputdata_t &inputdata )
|
||
|
{
|
||
|
ResetSequence( LookupSequence( "idle" ) );
|
||
|
|
||
|
int iJuice = inputdata.value.Int();
|
||
|
|
||
|
m_flJuice = m_iMaxJuice = m_iJuice = iJuice;
|
||
|
StudioFrameAdvance();
|
||
|
}
|
||
|
|
||
|
void CNewRecharge::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
||
|
{
|
||
|
// if it's not a player, ignore
|
||
|
if ( !pActivator || !pActivator->IsPlayer() )
|
||
|
return;
|
||
|
|
||
|
CBasePlayer *pPlayer = static_cast<CBasePlayer *>(pActivator);
|
||
|
|
||
|
// Reset to a state of continuous use.
|
||
|
m_iCaps = FCAP_CONTINUOUS_USE;
|
||
|
|
||
|
if ( m_iOn )
|
||
|
{
|
||
|
float flCharges = CHARGES_PER_SECOND;
|
||
|
float flCalls = CALLS_PER_SECOND;
|
||
|
|
||
|
if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) )
|
||
|
flCharges = CITADEL_CHARGES_PER_SECOND;
|
||
|
|
||
|
m_flJuice -= flCharges / flCalls;
|
||
|
StudioFrameAdvance();
|
||
|
}
|
||
|
|
||
|
// Only usable if you have the HEV suit on
|
||
|
if ( !pPlayer->IsSuitEquipped() )
|
||
|
{
|
||
|
if (m_flSoundTime <= gpGlobals->curtime)
|
||
|
{
|
||
|
m_flSoundTime = gpGlobals->curtime + 0.62;
|
||
|
EmitSound( "SuitRecharge.Deny" );
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// if there is no juice left, turn it off
|
||
|
if ( m_iJuice <= 0 )
|
||
|
{
|
||
|
// Start our deny animation over again
|
||
|
ResetSequence( LookupSequence( "emptyclick" ) );
|
||
|
|
||
|
m_nState = 1;
|
||
|
|
||
|
// Shut off
|
||
|
Off();
|
||
|
|
||
|
// Play a deny sound
|
||
|
if ( m_flSoundTime <= gpGlobals->curtime )
|
||
|
{
|
||
|
m_flSoundTime = gpGlobals->curtime + 0.62;
|
||
|
EmitSound( "SuitRecharge.Deny" );
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Get our maximum armor value
|
||
|
int nMaxArmor = 100;
|
||
|
if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) )
|
||
|
{
|
||
|
nMaxArmor = sk_suitcharger_citadel_maxarmor.GetInt();
|
||
|
}
|
||
|
|
||
|
int nIncrementArmor = 1;
|
||
|
|
||
|
// The citadel charger gives more per charge and also gives health
|
||
|
if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) )
|
||
|
{
|
||
|
nIncrementArmor = 10;
|
||
|
|
||
|
#ifdef HL2MP
|
||
|
nIncrementArmor = 2;
|
||
|
#endif
|
||
|
|
||
|
// Also give health for the citadel version.
|
||
|
if ( pActivator->GetHealth() < pActivator->GetMaxHealth() && m_flNextCharge < gpGlobals->curtime )
|
||
|
{
|
||
|
pActivator->TakeHealth( 5, DMG_GENERIC );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If we're over our limit, debounce our keys
|
||
|
if ( pPlayer->ArmorValue() >= nMaxArmor)
|
||
|
{
|
||
|
// Citadel charger must also be at max health
|
||
|
if ( !HasSpawnFlags(SF_CITADEL_RECHARGER) || ( HasSpawnFlags( SF_CITADEL_RECHARGER ) && pActivator->GetHealth() >= pActivator->GetMaxHealth() ) )
|
||
|
{
|
||
|
// Make the user re-use me to get started drawing health.
|
||
|
pPlayer->m_afButtonPressed &= ~IN_USE;
|
||
|
m_iCaps = FCAP_IMPULSE_USE;
|
||
|
|
||
|
EmitSound( "SuitRecharge.Deny" );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// This is bumped out if used within the time period
|
||
|
SetNextThink( gpGlobals->curtime + CHARGE_RATE );
|
||
|
SetThink( &CNewRecharge::Off );
|
||
|
|
||
|
// Time to recharge yet?
|
||
|
if ( m_flNextCharge >= gpGlobals->curtime )
|
||
|
return;
|
||
|
|
||
|
// Play the on sound or the looping charging sound
|
||
|
if ( !m_iOn )
|
||
|
{
|
||
|
m_iOn++;
|
||
|
EmitSound( "SuitRecharge.Start" );
|
||
|
m_flSoundTime = 0.56 + gpGlobals->curtime;
|
||
|
|
||
|
m_OnPlayerUse.FireOutput( pActivator, this );
|
||
|
}
|
||
|
|
||
|
if ((m_iOn == 1) && (m_flSoundTime <= gpGlobals->curtime))
|
||
|
{
|
||
|
m_iOn++;
|
||
|
CPASAttenuationFilter filter( this, "SuitRecharge.ChargingLoop" );
|
||
|
filter.MakeReliable();
|
||
|
EmitSound( filter, entindex(), "SuitRecharge.ChargingLoop" );
|
||
|
}
|
||
|
|
||
|
// Give armor if we need it
|
||
|
if ( pPlayer->ArmorValue() < nMaxArmor )
|
||
|
{
|
||
|
UpdateJuice( m_iJuice - nIncrementArmor );
|
||
|
pPlayer->IncrementArmorValue( nIncrementArmor, nMaxArmor );
|
||
|
}
|
||
|
|
||
|
// Send the output.
|
||
|
float flRemaining = m_iJuice / MaxJuice();
|
||
|
m_OutRemainingCharge.Set(flRemaining, pActivator, this);
|
||
|
|
||
|
// govern the rate of charge
|
||
|
m_flNextCharge = gpGlobals->curtime + 0.1;
|
||
|
}
|
||
|
|
||
|
void CNewRecharge::Recharge(void)
|
||
|
{
|
||
|
EmitSound( "SuitRecharge.Start" );
|
||
|
ResetSequence( LookupSequence( "idle" ) );
|
||
|
|
||
|
UpdateJuice( MaxJuice() );
|
||
|
|
||
|
m_nState = 0;
|
||
|
m_flJuice = m_iJuice;
|
||
|
m_iReactivate = 0;
|
||
|
StudioFrameAdvance();
|
||
|
|
||
|
SetThink( &CNewRecharge::SUB_DoNothing );
|
||
|
}
|
||
|
|
||
|
void CNewRecharge::Off(void)
|
||
|
{
|
||
|
// Stop looping sound.
|
||
|
if (m_iOn > 1)
|
||
|
{
|
||
|
StopSound( "SuitRecharge.ChargingLoop" );
|
||
|
}
|
||
|
|
||
|
if ( m_nState == 1 )
|
||
|
{
|
||
|
SetCycle( 1.0f );
|
||
|
}
|
||
|
|
||
|
m_iOn = 0;
|
||
|
m_flJuice = m_iJuice;
|
||
|
|
||
|
if ( m_iReactivate == 0 )
|
||
|
{
|
||
|
if ((!m_iJuice) && g_pGameRules->FlHEVChargerRechargeTime() > 0 )
|
||
|
{
|
||
|
if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) )
|
||
|
{
|
||
|
m_iReactivate = g_pGameRules->FlHEVChargerRechargeTime() * 2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_iReactivate = g_pGameRules->FlHEVChargerRechargeTime();
|
||
|
}
|
||
|
SetNextThink( gpGlobals->curtime + m_iReactivate );
|
||
|
SetThink(&CNewRecharge::Recharge);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SetThink( NULL );
|
||
|
}
|
||
|
}
|
||
|
}
|