/* ***** BEGIN LICENSE BLOCK *****
Version: MPL 1.1/LGPL 2.1/GPL 2.0

The contents of this file are subject to the Mozilla Public License Version 
1.1 (the "License"); you may not use this file except in compliance with
...
for the specific language governing rights and limitations under the
License.

The Original Code is for Luminous Forts.

The Initial Developer of the Original Code is Hekar Khani.
Portions created by the Hekar Khani are Copyright (C) 2010
Hekar Khani. All Rights Reserved.

Contributor(s):
  Hekar Khani <hekark@gmail.com>

Alternatively, the contents of this file may be used under the terms of
either of the GNU General Public License Version 2 or later (the "GPL"),
...
the terms of any one of the MPL, the GPL or the LGPL.

***** END LICENSE BLOCK ***** */


/*===============================================================
	Server
	Model Entity

	Taken from HL2DM ammo charger code.

	Last Updated Oct 15 2009
===============================================================*/

#include "cbase.h"
#include "HealthChargers.h"
LINK_ENTITY_TO_CLASS(item_suitcharger, CNewWallHealth);
#if 0
#include "CArmorCharger.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

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 ),
	DEFINE_KEYFIELD( m_iTeamNum, FIELD_INTEGER, "team" ),

	// 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 = m_iMaxArmor;
	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 = 2;
		
		// 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 );
		}
	}
}

#endif // 0