//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
//=============================================================================//


#include "cbase.h"
#include "hl1_items.h"
#include "ammodef.h"


#define WEAPONBOX_MODEL "models/w_weaponbox.mdl"


class CWeaponBox : public CHL1Item
{
public:
	DECLARE_CLASS( CWeaponBox, CHL1Item );

	void Spawn( void );
	void Precache( void );
	bool KeyValue( const char *szKeyName, const char *szValue );
	void BoxTouch( CBaseEntity *pPlayer );

	DECLARE_DATADESC();

private:
	bool		PackAmmo( char *szName, int iCount );
	int			GiveAmmo( int iCount, char *szName, int iMax, int *pIndex = NULL );
	
	int			m_cAmmoTypes;	// how many ammo types packed into this box (if packed by a level designer)
	string_t	m_rgiszAmmo[MAX_AMMO_SLOTS];	// ammo names
	int			m_rgAmmo[MAX_AMMO_SLOTS];		// ammo quantities
};
LINK_ENTITY_TO_CLASS(weaponbox, CWeaponBox);
PRECACHE_REGISTER(weaponbox);

BEGIN_DATADESC( CWeaponBox )
	DEFINE_ARRAY( m_rgiszAmmo, FIELD_STRING, MAX_AMMO_SLOTS ),
	DEFINE_ARRAY( m_rgAmmo, FIELD_INTEGER, MAX_AMMO_SLOTS ),
	DEFINE_FIELD( m_cAmmoTypes, FIELD_INTEGER ),

	DEFINE_ENTITYFUNC( BoxTouch ),
END_DATADESC()


bool CWeaponBox::KeyValue( const char *szKeyName, const char *szValue )
{
	if ( m_cAmmoTypes < MAX_AMMO_SLOTS )
	{
		if ( PackAmmo( (char *)szKeyName, atoi( szValue ) ) )
		{
			m_cAmmoTypes++;// count this new ammo type.

			return true;
		}
	}
	else
	{
		Warning( "WeaponBox too full! only %d ammotypes allowed\n", MAX_AMMO_SLOTS );
	}

	return BaseClass::KeyValue( szKeyName, szValue );
}

void CWeaponBox::Spawn( void )
{ 
	Precache();
	SetModel( WEAPONBOX_MODEL );
	BaseClass::Spawn();

	PrecacheScriptSound( "Item.Pickup" );

	SetTouch( &CWeaponBox::BoxTouch );
}


void CWeaponBox::Precache( void )
{
	PrecacheModel( WEAPONBOX_MODEL );
}


void CWeaponBox::BoxTouch( CBaseEntity *pOther )
{
	if ( !( GetFlags() & FL_ONGROUND ) )
	{
		return;
	}

	if ( !pOther->IsPlayer() )
	{
		// only players may touch a weaponbox.
		return;
	}

	if ( !pOther->IsAlive() )
	{
		// no dead guys.
		return;
	}

	CBasePlayer *pPlayer = (CBasePlayer *)pOther;
	int i;

// dole out ammo
	for ( i = 0 ; i < MAX_AMMO_SLOTS ; i++ )
	{
		if ( m_rgiszAmmo[ i ] != NULL_STRING )
		{
			// there's some ammo of this type. 
			pPlayer->GiveAmmo( m_rgAmmo[ i ], (char *)STRING( m_rgiszAmmo[ i ] ) );

			// now empty the ammo from the weaponbox since we just gave it to the player
			m_rgiszAmmo[ i ]	= NULL_STRING;
			m_rgAmmo[ i ]		= 0;
		}
	}

	CPASAttenuationFilter filter( pOther, "Item.Pickup" );
	EmitSound( filter, pOther->entindex(), "Item.Pickup" );

	SetTouch(NULL);
	if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO )
	{
		UTIL_Remove( this );
	}
}


bool CWeaponBox::PackAmmo( char *szName, int iCount )
{
	char szConvertedName[ 32 ];

	if ( FStrEq( szName, "" ) )
	{
		// error here
		Warning( "NULL String in PackAmmo!\n" );
		return false;
	}
	
	Q_snprintf( szConvertedName, sizeof( szConvertedName ), "%s", szName );
	if ( !stricmp( szName, "bolts" ) )
	{
		Q_snprintf( szConvertedName, sizeof( szConvertedName ), "XBowBolt" );
	}
	if ( !stricmp( szName, "uranium" ) )
	{
		Q_snprintf( szConvertedName, sizeof( szConvertedName ), "Uranium" );
	}
	if ( !stricmp( szName, "9mm" ) )
	{
		Q_snprintf( szConvertedName, sizeof( szConvertedName ), "9mmRound" );
	}
	if ( !stricmp( szName, "Hand Grenade" ) )
	{
		Q_snprintf( szConvertedName, sizeof( szConvertedName ), "Grenade" );
	}
	if ( !stricmp( szName, "Hornets" ) )
	{
		Q_snprintf( szConvertedName, sizeof( szConvertedName ), "Hornet" );
	}
	if ( !stricmp( szName, "ARgrenades" ) )
	{
		Q_snprintf( szConvertedName, sizeof( szConvertedName ), "MP5_Grenade" );
	}
	if ( !stricmp( szName, "357" ) )
	{
		Q_snprintf( szConvertedName, sizeof( szConvertedName ), "357Round" );
	}
	if ( !stricmp( szName, "rockets" ) )
	{
		Q_snprintf( szConvertedName, sizeof( szConvertedName ), "RPG_Rocket" );
	}
	if ( !stricmp( szName, "Satchel Charge" ) )
	{
		Q_snprintf( szConvertedName, sizeof( szConvertedName ), "Satchel" );
	}
	if ( !stricmp( szName, "buckshot" ) )
	{
		Q_snprintf( szConvertedName, sizeof( szConvertedName ), "Buckshot" );
	}
	if ( !stricmp( szName, "Snarks" ) )
	{
		Q_snprintf( szConvertedName, sizeof( szConvertedName ), "Snark" );
	}
	if ( !stricmp( szName, "Trip Mine" ) )
	{
		Q_snprintf( szConvertedName, sizeof( szConvertedName ), "TripMine" );
	}

	int iMaxCarry = GetAmmoDef()->MaxCarry( GetAmmoDef()->Index( szConvertedName ) );

	if ( iMaxCarry > 0 && iCount > 0 )
	{
		//ALERT ( at_console, "Packed %d rounds of %s\n", iCount, STRING(iszName) );
		GiveAmmo( iCount, szConvertedName, iMaxCarry );
		return true;
	}

	return false;
}

//=========================================================
// CWeaponBox - GiveAmmo
//=========================================================
int CWeaponBox::GiveAmmo( int iCount, char *szName, int iMax, int *pIndex )
{
	int i;

	for ( i = 1; ( i < MAX_AMMO_SLOTS ) && ( m_rgiszAmmo[i] != NULL_STRING ); i++ )
	{
		if ( stricmp( szName, STRING( m_rgiszAmmo[i] ) ) == 0 )
		{
			if (pIndex)
				*pIndex = i;

			int iAdd = MIN( iCount, iMax - m_rgAmmo[i]);
			if (iCount == 0 || iAdd > 0)
			{
				m_rgAmmo[i] += iAdd;

				return i;
			}
			return -1;
		}
	}

	if (i < MAX_AMMO_SLOTS)
	{
		if (pIndex)
			*pIndex = i;

		m_rgiszAmmo[i]	= AllocPooledString( szName );
		m_rgAmmo[i]		= iCount;

		return i;
	}
	Warning( "out of named ammo slots\n");
	return i;
}