/*	Copyright © 2009, ConnorMcLeod

	Drop All Weapons On Death is free software;
	you can redistribute it and/or modify it under the terms of the
	GNU General Public License as published by the Free Software Foundation.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Drop All Weapons On Death; if not, write to the
	Free Software Foundation, Inc., 59 Temple Place - Suite 330,
	Boston, MA 02111-1307, USA.
*/

#include <amxmodx>
#include <fakemeta>
#include <hamsandwich>

#define PLUGIN "Drop All Weapons On Death"
#define AUTHOR "ConnorMcLeod"
#define VERSION "0.1.2"

#define WPNBX_CUSTOM -64815

// "weapon_..." offsets
// nades specific
#define	m_flPinPulledOutTime	31
// all weapons :
#define	m_pPlayer			41
#define	m_pNext			42
#define	m_iId			43

// "player" offsets
// Store only slots 1,2 and 4 values cause we won't drop knife and let the game drop c4
new const m_rgpPlayerItems_plr[] = {368, 369, 371}
#define	m_pActiveItem			373
#define	m_rgAmmo_Player_Slot0	376

// "weaponbox" offsets
#define	m_rgiszAmmo_Slot0		41
#define	m_rgAmmo_Slot0			73
new const m_rgpPlayerItems_wpnbx[] = {34, 35, 36, 37, 38, 39}

new const g_iMaxAmmo[] = {
	0, 30, 90, 200, 90,
	32, 100, 100, 35, 52,
	120, 2, 1, 1, 1
}

const NADES_BS = (1<<CSW_HEGRENADE)|(1<<CSW_FLASHBANG)|(1<<CSW_SMOKEGRENADE)

new g_iszAmmoNames[sizeof(g_iMaxAmmo)]

public plugin_init()
{
	register_plugin(PLUGIN, VERSION, AUTHOR)

	register_event("HLTV", "Event_HLTV_New_Round", "a", "1=0", "2=0")

	RegisterHam(Ham_Killed, "player", "Player_Killed")

	new szAmmoNames[][] = {
		"", "338Magnum", "762Nato", "556NatoBox", "556Nato",
		"buckshot", "45ACP", "57mm", "50AE", "357SIG",
		"9mm", "Flashbang", "HEGrenade", "SmokeGrenade", "C4"
	}

	for(new i=1; i<sizeof(szAmmoNames); i++)
	{
		g_iszAmmoNames[i] = engfunc(EngFunc_AllocString, szAmmoNames[i])
	}
}

public Event_HLTV_New_Round()
{
	new iWpnBx
	new szClassName[] = "classname"
	new szWeaponBox[] = "weaponbox"
	while( (iWpnBx = engfunc(EngFunc_FindEntityByString, iWpnBx, szClassName, szWeaponBox)) > 0 )
	{
		// make sure we only remove our weaponboxes
		if( pev(iWpnBx, pev_iuser3) == WPNBX_CUSTOM )
		{
			WeaponBox_Killed(iWpnBx)
		}
	}
}

public Player_Killed( id )
{
	new iActiveItem = get_pdata_cbase(id, m_pActiveItem, 5)
	new bLaunch
	if( pev_valid( iActiveItem ) )
	{
		if(	NADES_BS & (1<<get_pdata_int(iActiveItem, m_iId, 4))
		&&	get_pdata_float(iActiveItem, m_flPinPulledOutTime, 4) > -1.0	)
		{
			bLaunch = true
		}
		else
		{
			ExecuteHam(Ham_Item_Holster, iActiveItem, 1)
		}
	}

	new iWeapon, iWeaponBox, iAmmoId, iBpAmmo, iNextWeapon
	new szWeapon[20], szModel[26]
	new Float:flOrigin[3], Float:flAngles[3], Float:flWpnBxOrig[3]
	
	pev(id, pev_origin, flOrigin)
	pev(id, pev_angles, flAngles)

	flAngles[0] = 0.0
	flAngles[2] = 0.0

	static iszWeaponBox
	if( !iszWeaponBox )
	{
		iszWeaponBox = engfunc(EngFunc_AllocString, "weaponbox")
	}

	for(new i; i<sizeof(m_rgpPlayerItems_plr); i++)
	{
		iWeapon = get_pdata_cbase(id, m_rgpPlayerItems_plr[i], 5)
		while( pev_valid( iWeapon ) )
		{
			iNextWeapon = get_pdata_cbase(iWeapon, m_pNext, 4)
			if( i != 2 || !bLaunch || iWeapon != iActiveItem )
			{
				iWeaponBox = engfunc(EngFunc_CreateNamedEntity, iszWeaponBox)
				if( pev_valid(iWeaponBox) )
				{
					set_pev(iWeaponBox, pev_iuser3, WPNBX_CUSTOM)

					set_pev(iWeaponBox, pev_owner, id)

					flWpnBxOrig[0] = flOrigin[0] + random_num(-50,50)
					flWpnBxOrig[1] = flOrigin[1] + random_num(-50,50)
					flWpnBxOrig[2] = flOrigin[2]
					engfunc(EngFunc_SetOrigin, iWeaponBox, flWpnBxOrig)

					set_pev(iWeaponBox, pev_angles, flAngles)
					ExecuteHam(Ham_Spawn, iWeaponBox)

					if( !WeaponBox_PackWeapon(iWeaponBox, iWeapon, id) )
					{
						set_pev(iWeaponBox, pev_flags, FL_KILLME)
					}
					else
					{
						iAmmoId = ExecuteHam(Ham_Item_PrimaryAmmoIndex, iWeapon)

						iBpAmmo = get_pdata_int(id, m_rgAmmo_Player_Slot0 + iAmmoId, 5)
						set_pdata_int(id, m_rgAmmo_Player_Slot0 + iAmmoId, 0, 5)				

						WeaponBox_PackAmmo(iWeaponBox, iAmmoId, iBpAmmo)

						pev(iWeapon, pev_classname, szWeapon, charsmax(szWeapon))

						replace(szWeapon, charsmax(szWeapon), "navy", "")
						formatex(szModel, charsmax(szModel), "models/w_%s.mdl", szWeapon[7])
						engfunc(EngFunc_SetModel, iWeaponBox, szModel)
					}
				}
			}
			iWeapon = iNextWeapon
		}
	}
	return HAM_HANDLED
}

WeaponBox_PackWeapon(iWeaponBox, iWeapon, id)
{
	if( !ExecuteHam(Ham_RemovePlayerItem, id, iWeapon) )
	{
		return 0
	}

	new iWeaponSlot = ExecuteHam(Ham_Item_ItemSlot, iWeapon)

	set_pdata_cbase(iWeaponBox, m_rgpPlayerItems_wpnbx[ iWeaponSlot ], iWeapon, 4)
	set_pdata_cbase(iWeapon, m_pNext, -1, 4)

	set_pev(iWeapon, pev_spawnflags, pev(iWeapon, pev_spawnflags) | SF_NORESPAWN)
	set_pev(iWeapon, pev_movetype, MOVETYPE_NONE)
	set_pev(iWeapon, pev_solid, SOLID_NOT)
	set_pev(iWeapon, pev_effects, EF_NODRAW)
	set_pev(iWeapon, pev_modelindex, 0)
	set_pev(iWeapon, pev_model, 0)
	set_pev(iWeapon, pev_owner, iWeaponBox)
	set_pdata_cbase(iWeapon, m_pPlayer, -1, 4)

	return 1
}

WeaponBox_Killed(iWpnBx)
{
	new iWeapon
	for(new i=0; i<sizeof(m_rgpPlayerItems_wpnbx); i++)
	{
		iWeapon = get_pdata_cbase(iWpnBx, m_rgpPlayerItems_wpnbx[ i ], 4)
		if( pev_valid(iWeapon) )
		{
			set_pev(iWeapon, pev_flags, FL_KILLME)
		}
		// don't implement pNext system as it's a custom weaponbox that doesn't use it
	}
	set_pev(iWpnBx, pev_flags, FL_KILLME)
}

WeaponBox_PackAmmo(iWeaponBox, iAmmoId, iCount)
{
	new iMaxCarry = g_iMaxAmmo[iAmmoId]

	if( iCount > iMaxCarry )
	{
		iCount = iMaxCarry
	}

	set_pdata_int(iWeaponBox, m_rgiszAmmo_Slot0, g_iszAmmoNames[iAmmoId], 4)	
	set_pdata_int(iWeaponBox, m_rgAmmo_Slot0, iCount, 4)
}