/* Plugin generated by AMXX-Studio */
/*********************************************************************************

Superweapon -- M4 with M203 Edition

This plugin supply a sort of special weapon: M4A1 with M203 grenade launcher.

The M203 can launch 2 type of grenades: He-grenade & Gas-grenade.

He-grenade can hurt players spang with blast damage & Gas-grenade hurt player who touch the "gas".



----------------------------------------------------------------------------------
Modul & Require:

<amxmisc>
<cstrike>
<fakemeta>



----------------------------------------------------------------------------------
CAVR:


SW_SpawnMode 0|1|2	//define superweapon spawn mode, 
//"0" means superweapon never spawn but can been buy by client command, (admin still can give it to any player by admin command)
//"1" means auto, superweapon will auto spawn in general maps(DE|CS|AS|ES)
//"2" means superweapon will auto spawn in all type of maps
		
SW_M4StripMode 0	//
//"0" means only strip superweapon(still keep default m4a1) 
//"1" means strip the holder's superweapon & default m4a1


SW_M4Price 8000		//m4 with m203's price, include all type of grenades with max amount

SW_MaxAmount_TE 3	//max amount of terrorists can holded m4 with m203


SW_MaxAmount_CT 3	//max amount of cts can holded m4 with m203

	
SW_GrenadeTK 0		//40mm hegrenade team kill,"0" is secundum server's rule, "1" is TK in any case


SW_GrenadeRT 3.0	//grenade reload time


SW_HeGrenadeMD 100	//40mm he grenade max damage


SW_HeGrenadeDR 400	//40mm he grenade damage radius


SW_HeGrenadeMC 3	//40mm he grenade's max amount can been carried


SW_HeGrenadePR 500	//40mm he grenade's price


SW_GasGrenadeMD 100	//40mm gas grenade max damage


SW_GasGrenadeDR 100	//40mm gas grenade damage radius


SW_GasGrenadeMC 1	//40mm gas grenade's max amount can been carried


SW_GasGrenadePR 500	//40mm gas grenade's price




----------------------------------------------------------------------------------
About the superweapon spawn:

Generally(can change by CVAR or Admin), superweapons will spawn after 1th round, stochastic 

locality in map, with specifically amount(by CVAR setting).




----------------------------------------------------------------------------------
Command:

1.Admin command(ADMIN_IMMUNITY): give or strip player's superweapon

amx_sw_m4 <#id | name> <give | strip>

{<#playerindex|name(can be partial)> <g(means give M4A1/W M203)|s(means strip target's superweapon if he has>}")


2.Admin command(ADMIN_IMMUNITY): change superweapon mode

amx_sw_set <0 | 1 | 2>


"0" means stop SW mode(also strip all sw)

"1" means start it by CVAR(SW_SpawnMode)'s setting

"2" means start anywise


3.Player command:


(a)open superweapon menu

When player's Current weapon is "superweapon", press "spray key" will openning menu of grenade setting,

menu include:

(1).Switch current grenade type to he-grenade
(2).Switch current grenade type to gas-grenade
(3).Setting|Offload muffler
(4).Buy he-grenade
(5).Buy gas-grenade


(b)

When sw spawn mode is "0", player type "say /buyswm4" can buy sw by certain condition

4.Fire 40mm grenade:

press "+attack2" key to launch grenade 




----------------------------------------------------------------------------------
Credit:

code and more:	VEN & more

model maker:	Ankalar, CJ, TinSoldier, S7ok3, Dirtball, Pr0d!gy, Ritual, Rob O, Jennifer!!,
		SureShot, Nightshade, Sas.stu, -X-, Vunsata



*********************************************************************************/

#include <amxmodx>
#include <amxmisc>
#include <cstrike>
#include <fakemeta>

#define PLUGIN "Ryu_SuperWeapon"
#define VERSION "0.4"
#define AUTHOR "CZ*Ryu"

#define MAXPLAYERS 32
#define MAXNUM 64	

#define SW_BOX_PARAM_NOTOUCH 0
#define SW_BOX_PARAM_TRIGGER 1

#define SW_BOX_SILEN_OFF 0
#define SW_BOX_SILEN_ON 1

//grenade tyep, ItemPickup & Scenario: grenade type(he|gasun-use) sprite string num constant, 
#define TYPE_HENADE 0
#define TYPE_GASNADE 1
#define TYPE_INCENDIARY 2
#define NOT_SHOW_NUM 10

//team kill check constant
#define HURT_ENEMY 0
#define HURT_TEAMMATE 1
#define HURT_SELF 2
#define HURT_NONE 3

//effect entity
#define EFFECT_EXPLO 0
#define EFFECT_BLOOD 1

#pragma dynamic 32768


//common value
new iRoundCount
new iServerTK		//expression of server's team-kill rule

new bool:bIsCsSeries = false
new bool:bHasNewWeapon = true
new bool:bRightMapType = false
new bool:bSpawnSwBox

//team
new const TE = 1
new const CT = 2
new const SPECTATOR = 3

//icon state constant
new const CLEAR = 0
new const SHOW = 1

//take count of superweapon
new const COUNT = 1

//task id
new const iTaskSpanwSwBox = 33333
new const iTaskBuyTimeOver = 33334

//message id
new iDeathMsgID
new iItemPickupMsgID
new iSayTextMsgID
new iScenarioMsgID
new iStatusIconMsgID

new const sNadeStateString[2][] = {"dmg_rad", "item_healthkit"}//,"dmg_heat"}

//------ pcvar -------------------------------
new cvar_SwSpawnMode_num
new cvar_SwM4Price_num
new cvar_SwM4StripMode_num
new cvar_SwMaxHolders_TE_num
new cvar_SwMaxHolders_CT_num
new cvar_SwNadeReloadTime_flo
new cvar_SwNadeTeamKill_num
//40mm hegrenade
new cvar_SwNadeMaxDmg_HE_num
new cvar_SwNadeDmgRadius_HE_num
new cvar_SwNadeMaxCarried_HE_num
new cvar_SwNadePrice_HE_num
//40mm gas grenade
new cvar_SwNadeMaxDmg_GAS_num
new cvar_SwNadeDmgRadius_GAS_num
new cvar_SwNadeMaxCarried_GAS_num
new cvar_SwNadePrice_GAS_num


new iSwSpawnMode
new iSwM4Price
new iSwM4StripMode
new bool:bSwNadeTK
new Float:fSwNadeReloadTime	//grenade reload time
new iSwNadePrice[2]		//[0] is hegrenade's price, [1] store gas grenade's
new iSwNadeMaxCarried[2]		//how many grenades can been tote, [0] is hegrenade, [1] store gas grenade
new Float:fSwNadeMaxDmg_HE	//hegrenade max damage
new sSwNadeMaxDmg_GAS[4]		//gas grenade max damage
new Float:fSwNadeDmgRadius[2]	//grenade damage radius


//---------------------------------------------

//correlative variable of superweapon spawn
new iInfoEntAmount			//count of player spawn points
new Float:fInfoEntOrigin[MAXNUM][3]	//origin of player spawn points
new iGhostEntID[MAXNUM]			//assistant entity(for get superweapon spawn point) id
new bool:bGhostEntRemoved = false
new const sGhostEntClassname[] = "Sw_AssistEntity"


new const sSwClassname_Prefix[] = "Sw_"

new const	sSwM4BoxClassname[] = "Sw_Box_M4withM203"
new const	sSwM4BoxSpriteClassname[] = "Sw_Sprite"
new		sSwM4BoxSprite[] = "sprites/3dmflaora.spr"
new		iSwM4MaxAmount			//max sueprweapon amount
new		iSwM4MaxTeamHolders[4]		//max sueprweapon amount of each team(te|ct) can hold
new 		iSwM4CurTeamHolders[4]	//current amount of each team hold
new const	iSwM4WeaponID = CSW_M4A1
new		sSwM4WeaponName[] = "weapon_m4a1"
new const	sSwM4Model_v[] = "models/v_m4a1_sw.mdl"
new const	sSwM4Model_p[] = "models/p_m4a1_sw.mdl"
new const	sSwM4Model_w[] = "models/w_m4a1_sw.mdl"


//some player personal parameter
new iUserHoldSwM4[MAXPLAYERS+1] = 0	//player(id) has superweapon?
new iUserNadeCurType[MAXPLAYERS+1]	//player current animated type of grenade
new iUserNadeAmount[MAXPLAYERS+1][3]	//player's 40mm grenade amount, [0] is "he", [1] is "gas"
new iUserTouchTimes[MAXPLAYERS+1]
new iUserHasHurtEnt[MAXPLAYERS+1]
new iSwM4SilenStatus[MAXPLAYERS+1]
new iSwM4ClipAmmo[MAXPLAYERS+1]
new iSwM4BpAmmo[MAXPLAYERS+1]
new bool:bRestartAttempt[MAXPLAYERS+1]


new bool:bInBuyzone[MAXPLAYERS+1] = true
new bool:bNadeReloaded[MAXPLAYERS+1] = true
new bool:bInBuyTime
new bool:bInFreezeTime


//grenade's value
//menu
new iSwNadeMenuID
new sSwNadeMenuBody[512]
new sSwNadeMenuTitle[] = "M4withM203"
new iMenuKeys = MENU_KEY_1|MENU_KEY_2|MENU_KEY_3|MENU_KEY_4|MENU_KEY_5|MENU_KEY_0

new iSwNadeSprite_Trail
new iSwNadeSprite_GasExplode
new iSwNadeSprite_GasFog

new const sSwNadeClassname[2][] = {"Sw_Grenade_HE","Sw_Grenade_GAS"}	//40mm grenade(type he & gas) of m203
new const sSwNadeFakeGasClassname[] = "Sw_FakeGas"
new const sSwNadeFakeHurtClassname[] = "Sw_HurtEnt"
new const sSwNadeSprite_Trail[] = "sprites/smoke.spr"
new const sSwNadeSprite_GasExplode[] = "sprites/WXplo1.spr"
new const sSwNadeSprite_GasFog[] = "sprites/fakefog.spr"
new const sSwNadeModel_w[] = "models/grenade.mdl"
new sSwNadeSound_Launch[] = "launch40mm.wav"
new sSwNadeSound_Buy[] = "items/gunpickup2.wav"
new sSwNadeSound_Change[] = "items/gunpickup1.wav"
new sSwNadeSound_GasExplode[] = "weapons/sg_explode.wav"
new sSwNadeSound_UseUp[] = "weapons/dryfire_rifle.wav"

new sMsgCannotGetSw[] = "^x03 It is max amount of^x03 your team^x04 can took superweapons now, cannot take more."
new sMsgStripSw[] = "^x03 Sorry! System strip you superweapon by max team-holders's limit."
new sMsgNotInBuyzone[] = "^x04 Not in your^x03 team's buyzone"
new sMsgNotInBuyTime[] = "^x03 Buy time is over!"

//some common constant
new const sClassname[] = "classname"
new const sWeaponbox[] = "weaponbox"
new const sPlayer[] = "player"
new const sFuncBreakable[] = "func_breakable"
new const sFuncPushable[] = "func_pushable"
new const sHostageEntity[] = "hostage_entity"
new const sMonsterScientist[] = "monster_scientist"

new const sInfoPlayerStart[] = "info_player_start"
new const sInfoPlayerDeathmatch[] = "info_player_deathmatch"

new const sNamedEntEnvSprite[] = "env_sprite"
new const sNamedEntEnvExplosion[] = "env_explosion"
new const sNamedEntEnvBlood[] = "env_blood"
new const sNamedEntInfoTarget[] = "info_target"
new const sNamedEntTriggerHurt[] = "trigger_hurt"

new const sModel_Weaponbox_w[] = "models/w_weaponbox.mdl"
new const sModel_M4_w[] = "models/w_m4a1.mdl"
new const sModel_Prefix_w[] = "models/w_"

new iSwEffectID[2]
new const sSwEffectClassname[] = "Sw_EffectEnt"

//stock const
stock const pev_SwBox_Param_e = pev_euser1
stock const pev_SwBox_Silen_e = pev_euser2
stock const pev_SwBox_ClipAmmo_e = pev_euser3
stock const pev_SwBox_BpAmmo_e = pev_euser4
stock const pev_SwBox_HeAmount_i = pev_iuser1
stock const pev_SwBox_GasAmount_i = pev_iuser2
stock const pev_SwNade_HurtEnt_i = pev_iuser1
//stock const pev_SwNade_ExploPoint_v = pev_vuser1


new const iPrimaryWeaponTable[] = {
	CSW_AK47,
	CSW_M4A1,
	CSW_AWP,
	CSW_MP5NAVY,
	CSW_SG552,
	CSW_AUG,
	CSW_SCOUT,
	CSW_UMP45,
	CSW_P90,
	CSW_M249,
	CSW_M3,
	CSW_XM1014,
	CSW_TMP,
	CSW_MAC10,
	CSW_G3SG1,
	CSW_SG550,
	CSW_GALIL,
	CSW_FAMAS,
	2		//shield
}

public plugin_init()
{
	register_plugin(PLUGIN, VERSION, AUTHOR)
	
	iDeathMsgID = get_user_msgid("DeathMsg")
	iItemPickupMsgID = get_user_msgid("ItemPickup")
	iSayTextMsgID = get_user_msgid("SayText")
	iScenarioMsgID = get_user_msgid("Scenario")
	iStatusIconMsgID = get_user_msgid("StatusIcon")
	
	register_event("HLTV", "event_new_round", "a", "1=0", "2=0")
	register_event("ResetHUD", "event_client_spawn", "be")
	register_event("CurWeapon", "event_check_superweapon", "be", "1>0", "2=22")
	register_event("TextMsg", "event_reset_round", "a", "2&#Game_C", "2&#Game_w")
	register_event("StatusIcon", "event_check_in_buyzone", "be", "2=buyzone")
	register_event("DeathMsg", "event_DeathMsg", "a")//, "4=65536")//DMG_NERVEGAS
	
	register_logevent("logevent_round_start", 2, "0=World triggered", "1=Round_Start")
	
	register_forward(FM_Touch, "forward_touch")
	register_forward(FM_SetModel, "forward_reset_model")
	register_forward(FM_CmdStart, "forward_CmdStart")
	register_forward(FM_Think, "forward_SW_think")
	
	iSwNadeMenuID = register_menuid(sSwNadeMenuTitle)
	register_menucmd(iSwNadeMenuID, 1023, "menu_SwGrenade_option")
	
	register_clcmd("fullupdate", "hook_clcmd_fullupdate")
	register_concmd("amx_sw_m4", "hook_concmd_sw_m4",ADMIN_IMMUNITY, "{<#playerindex|name(can be partial)> <g(means give M4A1/W M203)|s(means strip target's superweapon if he has>}")
	register_concmd("amx_sw_set", "hook_concmd_sw_set",ADMIN_IMMUNITY, "{<0>|<1>|<2>, ^"0^" stop SW mode(also strip all sw) & ^"1^" start it by SW_SpawnMode's setting & ^"2^" start anywise}")
	register_clcmd("say /buyswm4", "hook_clcmd_buyswm4")
	
	cvar_SwSpawnMode_num = register_cvar("SW_SpawnMode", "0")//define superweapon appear mode, 
	//"0" means superweapon never spawn but can been buy by client command, (admin still can give it to any player by admin command)
	//"1" means auto, superweapon will auto spawn in general maps
	//"2" means superweapon will auto spawn in all type of maps
		
	cvar_SwM4Price_num = register_cvar("SW_M4Price", "8000")//m4 with m203's price, include all type of grenades with max amount
	
	cvar_SwM4StripMode_num = register_cvar("SW_M4StripMode", "1")
	//"0" means only strip superweapon(still keep default m4a1) 
	//"1" means strip the holder's superweapon & default m4a1
	
	cvar_SwMaxHolders_TE_num = register_cvar("SW_MaxAmount_TE", "3")//max amount of terrorists can holded m4 with m203
	cvar_SwMaxHolders_CT_num = register_cvar("SW_MaxAmount_CT", "3")//max amount of cts can holded m4 with m203
	
	cvar_SwNadeTeamKill_num = register_cvar("SW_GrenadeTK", "0")//grenade team kill,"0" is secundum server's rule, "1" is TK in any case
	cvar_SwNadeReloadTime_flo = register_cvar("SW_GrenadeRT", "3.0")//grenade reload time
	
	cvar_SwNadeMaxDmg_HE_num = register_cvar("SW_HeGrenadeMD", "100")		//40mm he grenade max damage
	cvar_SwNadeDmgRadius_HE_num = register_cvar("SW_HeGrenadeDR", "400")	//40mm he grenade damage radius
	cvar_SwNadeMaxCarried_HE_num = register_cvar("SW_HeGrenadeMC", "2")		//40mm he grenade's max amount can been took
	cvar_SwNadePrice_HE_num = register_cvar("SW_HeGrenadePR", "500")		//40mm he grenade's price
	
	cvar_SwNadeMaxDmg_GAS_num = register_cvar("SW_GasGrenadeMD", "100")	//40mm gas grenade max damage
	cvar_SwNadeDmgRadius_GAS_num = register_cvar("SW_GasGrenadeDR", "100")	//40mm gas grenade damage radius
	cvar_SwNadeMaxCarried_GAS_num = register_cvar("SW_GasGrenadeMC", "1")	//40mm gas grenade's max amount can been took
	cvar_SwNadePrice_GAS_num = register_cvar("SW_GasGrenadePR", "500")	//40mm gas grenade's price
	
	iInfoEntAmount = get_InfoEnt_origin()
	
	new len = format(sSwNadeMenuBody, 511, "\w[ M4 with M203 option group ]^n^n")
	len += format(sSwNadeMenuBody[len], 511 - len, "\y1.Switch current grenade type to he-grenade^n")
	len += format(sSwNadeMenuBody[len], 511 - len, "\y2.Switch current grenade type to gas-grenade^n")
	len += format(sSwNadeMenuBody[len], 511 - len, "\y3.Setting|Offload muffler^n")
	len += format(sSwNadeMenuBody[len], 511 - len, "\w4.Buy he-grenade^n")
	len += format(sSwNadeMenuBody[len], 511 - len, "\w5.Buy gas-grenade^n^n")
	format(sSwNadeMenuBody[len], 511 - len, "\r0.Exit")
	
	iSwSpawnMode = get_pcvar_num(cvar_SwSpawnMode_num)
	switch ( iSwSpawnMode )
	{
		case 0:
		{
			bSpawnSwBox = false
			bRightMapType = false
		}
		case 1:
		{
			bRightMapType = ( engfunc(EngFunc_FindEntityByString, -1, sClassname, sHostageEntity)
			|| engfunc(EngFunc_FindEntityByString, -1, sClassname, sMonsterScientist)
			|| engfunc(EngFunc_FindEntityByString, -1, sClassname, "func_hostage_rescue")
			|| engfunc(EngFunc_FindEntityByString, -1, sClassname, "info_hostage_rescue")
			|| engfunc(EngFunc_FindEntityByString, -1, sClassname, "func_bomb_target")
			|| engfunc(EngFunc_FindEntityByString, -1, sClassname, "info_bomb_target")
			|| engfunc(EngFunc_FindEntityByString, -1, sClassname, "func_vip_start")
			|| engfunc(EngFunc_FindEntityByString, -1, sClassname, "info_vip_start")
			|| engfunc(EngFunc_FindEntityByString, -1, sClassname, "func_vip_safetyzone")
			|| engfunc(EngFunc_FindEntityByString, -1, sClassname, "func_escapezone") )?true:false
			bSpawnSwBox = bRightMapType
		}
		case 2:
		{
			bSpawnSwBox = true
			bRightMapType = true
		}
	}
	
	iServerTK = HURT_TEAMMATE
	if ( cvar_exists("mp_friendlyfire") )
		iServerTK = ( get_cvar_num("mp_friendlyfire") )?HURT_TEAMMATE:HURT_NONE
}

public plugin_precache()
{
	new sModName[32]
	get_modname(sModName,31)
	if ( equal(sModName,"cstrike") || equal(sModName,"czero") )
		bIsCsSeries = true
	else if ( equal(sModName,"csv15") || equal(sModName,"cs13") )
	{
		bIsCsSeries = true
		bHasNewWeapon = false
	}
	if ( !bIsCsSeries )
		pause("ae")
	
	precache_model(sSwM4Model_v)
	precache_model(sSwM4Model_p)
	precache_model(sSwM4Model_w)

	precache_model(sSwNadeModel_w)
		
	precache_sound(sSwNadeSound_Launch)
	precache_sound(sSwNadeSound_Buy)	//buy grenades
	precache_sound(sSwNadeSound_Change)	//grenades type change
	precache_sound(sSwNadeSound_GasExplode)
	precache_sound(sSwNadeSound_UseUp)
	
	precache_model(sSwM4BoxSprite)
	iSwNadeSprite_Trail = precache_model(sSwNadeSprite_Trail)
	iSwNadeSprite_GasExplode = precache_model(sSwNadeSprite_GasExplode)
	iSwNadeSprite_GasFog = precache_model(sSwNadeSprite_GasFog)
	
	return PLUGIN_CONTINUE
}

public event_new_round()
{
	iRoundCount++
	new iSpawnAmount = get_cvar_param()
	new iMaxEntities = global_get(glb_maxEntities)
	new i,sClass[32]
	for ( i=MAXPLAYERS+1; i<iMaxEntities; i++ )
	{
		if ( !pev_valid(i) )
			continue
		pev(i, pev_classname, sClass, sizeof sClass - 1 )
		if ( equal(sClass, sSwClassname_Prefix, 3) )
			engfunc(EngFunc_RemoveEntity, i)
	}
	create_effect_entity()
	if ( !bGhostEntRemoved )
		bGhostEntRemoved = remove_GhostEnt()
	if ( bSpawnSwBox && iRoundCount > 1 && iSpawnAmount > 0 )
		bGhostEntRemoved = bool:spawn_GhostEnt(iSpawnAmount)
	return PLUGIN_CONTINUE
}			

public hook_clcmd_fullupdate(id)
{
	return PLUGIN_HANDLED
}

public event_client_spawn(id)
{
	new iMenuID,iKeys
	get_user_menu(id, iMenuID, iKeys)
	if ( iMenuID == iSwNadeMenuID )
		client_cmd(id, "slot10")
	
	if ( bRestartAttempt[id] )
	{
		bRestartAttempt[id] = false
		return
	}
	
	iUserHasHurtEnt[id] = 0
	bNadeReloaded[id] = true
	if ( iUserHoldSwM4[id] > MAXPLAYERS && pev(id, pev_weapons) & (1<<iSwM4WeaponID) )
	{
		iUserNadeCurType[id] = TYPE_HENADE
		manage_StatusIcon_hud(id, SHOW, iUserNadeAmount[id][TYPE_HENADE])
		manage_Scenario_hud(id, SHOW)
		engclient_cmd(id, sSwM4WeaponName)
	}		
	else
		reset_player(id)
}

public event_check_in_buyzone(id)
{//check superweapon holder in buyzone
	bInBuyzone[id] = bool:read_data(1)
}

public event_check_superweapon(id)
{
	if ( iUserHoldSwM4[id] < MAXPLAYERS )
		return
	iSwM4ClipAmmo[id] = read_data(3)
	reset_superweapon(id)
}

public logevent_round_start()
{
	new message[128]
	format(message, 127, "^x04 When^x03 Current^x04 weapon is^x03 ^"superweapon^"^x04, press^x03 ^"spray key^"^x04 will openning menu of grenade setting")
	color_saytext(message, MSG_ALL, _, 4)
	if ( iSwSpawnMode == 0 )
	{
		format(message, 127, "^x04 Note: ^x03 say /buyswm4^x04 is the command for buy M4withm203 in this mode")
		color_saytext(message, MSG_ALL, _, 1)
	}
	bInFreezeTime = false
}

public event_DeathMsg()
{
	remove_HurtEnt(read_data(2))
}

public client_disconnect(id)
{
	bInBuyzone[id] = false
	bNadeReloaded[id] = true
	remove_HurtEnt(id)
}

public event_reset_round()
{
	iRoundCount = 0
	bGhostEntRemoved = false
	
	for ( new i=1; i<=MAXPLAYERS; i++ )
	{
		iUserHoldSwM4[i] = 0
		iUserNadeAmount[i][TYPE_HENADE] = 0
		iUserNadeAmount[i][TYPE_GASNADE] =0
		iUserTouchTimes[i] = 0
		bNadeReloaded[i] = true
		if ( is_user_alive(i) )
			bRestartAttempt[i] = true
	}
	return PLUGIN_CONTINUE
}

public hook_clcmd_buyswm4(id)
{
	if ( iSwSpawnMode != 0 )
	{
		client_print(id, print_center, "Can not buy superweapon in this mode!")
		return PLUGIN_HANDLED
	}
	if ( iUserHoldSwM4[id] > MAXPLAYERS || !is_user_alive(id) )
		return PLUGIN_HANDLED
	if ( !bInBuyTime )
	{
		color_saytext(sMsgNotInBuyTime, MSG_ONE, id, 4)
		return PLUGIN_HANDLED
	}
	if ( !bInBuyzone[id] )
	{
		color_saytext(sMsgNotInBuyzone, MSG_ONE, id)
		return PLUGIN_HANDLED
	}
	new iMoney = cs_get_user_money(id)
	if ( iMoney < iSwM4Price )
	{
		new message[64]
		format(message, 63, "^x04 You hasn't enough money,^x03 M4 with M203^x04 price is^x03 $%d", iSwM4Price)
		color_saytext(message, MSG_ONE, id)
		return PLUGIN_HANDLED
	}
	new iTeam = get_user_team(id)
	if ( iSwM4CurTeamHolders[iTeam] >= iSwM4MaxTeamHolders[iTeam] )
	{
		color_saytext(sMsgCannotGetSw, MSG_ONE,id)
		return PLUGIN_HANDLED
	}
	if ( give_superweapon(id, iTeam) > MAXPLAYERS )
		cs_set_user_money(id, iMoney - iSwM4Price, 1)
	return PLUGIN_HANDLED
}

public hook_concmd_sw_set(id, level, cid)
{
	if ( !cmd_access(id, level, cid, 2) )
		return PLUGIN_HANDLED
	new arg[128],iParam
	read_argv(1,arg,1)
	iParam = str_to_num(arg[0])
	if ( (2 < iParam < 0) )
		return PLUGIN_HANDLED
	switch ( iParam )
	{
		case 0:
		{
			bSpawnSwBox = false
			iParam = -1
			while ( (iParam = engfunc(EngFunc_FindEntityByString, iParam, sClassname, sSwM4BoxClassname)) > MAXPLAYERS )
				remove_superweapon_box(iParam)
			for ( iParam=1; iParam<=MAXPLAYERS; iParam++ )
			{
				if ( is_user_alive(iParam) )
				{
					reset_player(iParam, COUNT)
					engclient_cmd(iParam, "lastinv")
					engclient_cmd(iParam, "lastinv")
				}
			}
			format(arg, 127, "^x04*** OMG! Admin had^x03 strip^x04 all^x03 superweapon^x04 ***")
			color_saytext(arg, MSG_ALL, _, 1)
		}
		case 1:
			bSpawnSwBox = iSwSpawnMode > 0?bRightMapType:false
		case 2:
			bSpawnSwBox = true
	}
	
	if ( bSpawnSwBox )
		format(arg, 127, "^x04*** LOL!^x03 SUPERWEAPONS^x04 will appear somewhere from next round! ***")
	else
		format(arg, 127, "^x04*** OMG!^x03 SUPERWEAPONS^x04 will^x03 NOT^x04 auto appear from next round! ***")
	color_saytext(arg, MSG_ALL, _, 1)
	return PLUGIN_HANDLED
}

public hook_concmd_sw_m4(id, level, cid)
{//admin command for giving superweapon
	if ( !cmd_access(id, level, cid, 3) )
		return PLUGIN_HANDLED
	new target,arg[128]
	read_argv(1,arg,31)
	if ( arg[0] == '#' )
	{
		new sz[31]
		copy(sz, sizeof(arg)-1, arg[1])
		target = str_to_num(sz)
	}
	else
		target = find_player("bl", arg)
	if ( !is_user_alive(target) )
		return PLUGIN_HANDLED
	
	read_argv(2,arg,1)
	switch ( arg[0] )
	{
		case 's':
		{
			if ( iUserHoldSwM4[target] <= MAXPLAYERS )
				return PLUGIN_HANDLED
			switch ( iSwM4StripMode )
			{
				case 0://strip sw & keep default m4
				{
					reset_player(target, COUNT)
					engclient_cmd(target, "lastinv")
					engclient_cmd(target, "lastinv")
				}
				case 1://strip m4
				{
					iUserHoldSwM4[target] *= -1
					engclient_cmd(target, "drop", sSwM4WeaponName)
				}
			}
			console_print(id, "target: %d --- command: strip --- strip mode: %d", target, iSwM4StripMode)
		}
		case 'g':
		{
			if ( iUserHoldSwM4[target] > MAXPLAYERS )
				return PLUGIN_HANDLED
			new i,num = bHasNewWeapon?19:16
			new iTeam = get_user_team(target)
			new iParam = engfunc(EngFunc_FindEntityByString, -1, sClassname, sSwM4BoxClassname)
			if ( iParam  > MAXPLAYERS )
				remove_superweapon_box(iParam)//remove one superweapon box for keep total amount
			else//if cannot find superweapon box, strip any teammate or other superweapon holder for keep total amount
			{
				iParam = 0
				for ( i=1; i<=MAXPLAYERS; i++ )
				{
					if ( iUserHoldSwM4[i] <= MAXPLAYERS )
						continue
					iParam = i
					if ( get_user_team(iParam) == iTeam )//strip teammate's sueprweapon first, for keep max team sw amount
						break
				}
				if ( iParam && is_user_alive(iParam) )
				{
					reset_player(iParam, COUNT)
					engclient_cmd(iParam, "lastinv")
					engclient_cmd(iParam, "lastinv")
					color_saytext(sMsgStripSw, MSG_ONE, iParam, 1)
				}
			}
			if ( cs_get_user_hasprim(target) )
			{
				for ( i=0; i<num; i++ )
				{//check & drop prim weapon from the player who gave superweapon
					iParam = iPrimaryWeaponTable[i]
					if ( pev(target, pev_weapons) & (1<<iParam) )
					{
						get_weaponname(iParam, arg, 31)
						engclient_cmd(target, "drop", arg)
						break
					}
				}
			}	
			give_superweapon(target, iTeam)
			console_print(id, "target: %d --- command: give", target)
			console_print(id, "teamholders: %d", iSwM4CurTeamHolders[iTeam])
		}
	}
	return PLUGIN_HANDLED
}

public task_buy_time_over()
{
	bInBuyTime = false
}

public task_spawn_SwBox(param[])
{
	new iSpawnAmount = param[0]
	new iCount,ent,iSpriteEnt,Float:fOrigin[3]
	
	while ( iCount++ <= iSpawnAmount )
	{
		ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, sNamedEntInfoTarget))
		if ( ent <= MAXPLAYERS )
			continue
		iSpriteEnt = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, sNamedEntEnvSprite))
		if ( iSpriteEnt <= MAXPLAYERS )
		{
			engfunc(EngFunc_RemoveEntity, ent)
			continue
		}
		fm_set_kvd(iSpriteEnt, "renderfx", "14", sNamedEntEnvSprite)
		fm_set_kvd(iSpriteEnt, "rendermode", "5", sNamedEntEnvSprite)//kRenderTransAdd
		fm_set_kvd(iSpriteEnt, "renderamt", "100", sNamedEntEnvSprite)//transparence(1~255)
		fm_set_kvd(iSpriteEnt, "rendercolor", "50 255 50", sNamedEntEnvSprite)
		fm_set_kvd(iSpriteEnt, "framerate", "2", sNamedEntEnvSprite)
		fm_set_kvd(iSpriteEnt, "model", sSwM4BoxSprite, sNamedEntEnvSprite)
		fm_set_kvd(iSpriteEnt, "scale", "1.3", sNamedEntEnvSprite)
		set_pev(iSpriteEnt, pev_spawnflags, pev(iSpriteEnt, pev_spawnflags) | SF_SPRITE_STARTON)
		set_pev(iSpriteEnt, pev_spawnflags, pev(iSpriteEnt, pev_spawnflags) | SF_SPRITE_TEMPORARY)
		dllfunc(DLLFunc_Spawn, iSpriteEnt)
					
		pev(iGhostEntID[random(iInfoEntAmount)], pev_origin, fOrigin)
		
		set_pev(ent, pev_classname, sSwM4BoxClassname)
		engfunc(EngFunc_SetModel, ent, sSwM4Model_w)
		set_pev(ent, pev_origin, fOrigin)
		set_pev(ent, pev_mins, {-16.0,-16.0,-16.0})
		set_pev(ent, pev_maxs, {16.0,16.0,16.0})
		set_pev(ent, pev_solid, SOLID_TRIGGER)
		set_pev(ent, pev_movetype, MOVETYPE_BOUNCE)
	
		set_pev(ent, pev_SwBox_Param_e, iSpriteEnt)//stroe effect sprite entity id
		set_pev(ent, pev_SwBox_ClipAmmo_e, 30)
		set_pev(ent, pev_SwBox_BpAmmo_e, 90)
		set_pev(ent, pev_SwBox_HeAmount_i, iSwNadeMaxCarried[TYPE_HENADE])
		set_pev(ent, pev_SwBox_GasAmount_i, iSwNadeMaxCarried[TYPE_GASNADE])
			
		set_pev(iSpriteEnt, pev_classname, sSwM4BoxSpriteClassname)
		set_pev(iSpriteEnt, pev_origin, fOrigin)
		set_pev(iSpriteEnt, pev_aiment, ent)
		set_pev(iSpriteEnt, pev_movetype, MOVETYPE_FOLLOW)
	
		set_pev(ent, pev_nextthink, fCurrentTime() + 1.5)
	}
	set_hudmessage(0, 255, 0, -1.0, 0.00, 1, 6.0, 15.0, 0.15, 0.15, 4)
	show_hudmessage(0,"SuperWeapon^nM4A1 w/ M203 : with greande launcher...")
	bGhostEntRemoved = remove_GhostEnt()

	return PLUGIN_CONTINUE
}

public forward_reset_model(iEnt, sModel[])
{
	if ( iEnt <= MAXPLAYERS || equal(sModel, sModel_Weaponbox_w) )
		return FMRES_IGNORED
	
	//switch ( bInBuyTime )
	
	if ( equal(sModel, sModel_Prefix_w, 9) )
	{
		static classname[32]
		pev(iEnt, pev_classname, classname, sizeof classname - 1)
		if ( !equal(classname, sWeaponbox) )//filtrate throwed grenades
			return FMRES_IGNORED
		static owner
		owner = pev(iEnt, pev_owner)
		if ( (0 < owner <= MAXPLAYERS) && iUserHoldSwM4[owner] != 0 )
		{
			new bool:bOwnerAlive = bool:is_user_alive(owner)
			if (  equal(sModel, sModel_M4_w) )
			{
				if ( iUserHoldSwM4[owner] > MAXPLAYERS )
				{					
					new ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, sNamedEntInfoTarget))
					if ( !pev_valid(ent) )
						return FMRES_IGNORED
					new Float:fVector[3]
					set_pev(ent, pev_classname, sSwM4BoxClassname)
					engfunc(EngFunc_SetModel, ent, sSwM4Model_w)
					set_pev(ent, pev_solid, SOLID_TRIGGER)
					set_pev(ent, pev_SwBox_Param_e, SW_BOX_PARAM_NOTOUCH)
					set_pev(ent, pev_SwBox_Silen_e, iSwM4SilenStatus[owner])
					set_pev(ent, pev_SwBox_ClipAmmo_e, iSwM4ClipAmmo[owner])
					set_pev(ent, pev_SwBox_BpAmmo_e, !bOwnerAlive?0:iSwM4BpAmmo[owner])
					set_pev(ent, pev_SwBox_HeAmount_i, iUserNadeAmount[owner][TYPE_HENADE])
					set_pev(ent, pev_SwBox_GasAmount_i, iUserNadeAmount[owner][TYPE_GASNADE])
					
					//reset_player(owner, COUNT)
					
					set_pev(ent, pev_movetype, MOVETYPE_TOSS)
					pev(iEnt, pev_origin, fVector)
					set_pev(ent, pev_origin, fVector)
					pev(iEnt, pev_angles, fVector)
					set_pev(ent, pev_angles, fVector)
					pev(iEnt, pev_velocity, fVector)
					set_pev(ent, pev_velocity, fVector)
					
					set_pev(ent, pev_nextthink, fCurrentTime() + 0.5)
				}					
				set_pev(iEnt, pev_nextthink, fCurrentTime())
				reset_player(owner, COUNT)
			}
			else if ( bOwnerAlive && pev(owner, pev_weapons) & (1<<iSwM4WeaponID) )
				reset_superweapon(owner)
		}
	}
	return FMRES_IGNORED
}

public forward_SW_think(ent)
{
	if ( ent <= MAXPLAYERS )
		return
	static classname[32]
	pev(ent, pev_classname, classname, sizeof classname - 1)
	if ( !equal(classname, sSwClassname_Prefix, 3) )
		return
	switch ( classname[3] )
	{
		case 'H'://hurt entity
		{
			iUserHasHurtEnt[pev(ent, pev_owner)] = 0
			engfunc(EngFunc_RemoveEntity, ent)
		}			
		case 'F'://"fake gas" entity
			engfunc(EngFunc_RemoveEntity, ent)
		case 'B'://"fake weapon box"
		{
			new iParam = pev(ent, pev_SwBox_Param_e)
			switch ( iParam )
			{
				case SW_BOX_PARAM_NOTOUCH:	set_pev(ent, pev_SwBox_Param_e, SW_BOX_PARAM_TRIGGER)//delay for "touch"
				case SW_BOX_PARAM_TRIGGER:	return//is dropped by player
				default://spawn by system
				{
					new Float:fVector[3]
					fVector[0] = random_float(0.0, 359.99)
					fVector[1] = random_float(0.0, 359.99)
					fVector[2] = random_float(0.0, 359.99)
					set_pev(ent, pev_angles, fVector)
					fVector[0] = random_float(-300.0, 300.0)
					fVector[1] = random_float(-300.0, 300.0)
					fVector[2] = random_float(-300.0, 300.0)
					set_pev(ent, pev_velocity, fVector)
					set_pev(ent, pev_nextthink, fCurrentTime() + 1.0)
				}
			}
		}
	}
}

public forward_CmdStart(id, uc_handle, seed)
{//check M203 launched
	if ( !is_user_alive(id) || !iUserHoldSwM4[id] )
		return
	static cmd,type
	if ( get_user_weapon(id, cmd, type) != iSwM4WeaponID )
		return
	if ( (cmd = get_uc(uc_handle, UC_Buttons)) & IN_ATTACK2 )
	{
		cmd &= ~IN_ATTACK2
		set_uc(uc_handle, UC_Buttons, cmd)
		if ( bInFreezeTime || !bNadeReloaded[id] )
			return
		type = iUserNadeCurType[id]
		if ( iUserNadeAmount[id][type] < 1 )
		{
			emit_sound(id, CHAN_WEAPON, sSwNadeSound_UseUp, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
			return
		}
		launch_grenade(id, type)
		return
	}
	if ( get_uc(uc_handle, UC_Impulse) ==  201 )
	{
		set_uc(uc_handle, UC_Impulse, 0)
		show_menu(id, iMenuKeys, sSwNadeMenuBody, -1, sSwNadeMenuTitle)
	}
}

public menu_SwGrenade_option(id, iKey)
{
	if ( !iUserHoldSwM4[id] || !is_user_alive(id) )
	{
		client_cmd(id, "slot10")
		return PLUGIN_HANDLED
	}
	new bool:HoldMenu = false
	switch ( iKey )
	{
		case 0:
		{
			manage_StatusIcon_hud(id, CLEAR, iUserNadeAmount[id][iUserNadeCurType[id]])
			iUserNadeCurType[id] = TYPE_HENADE
			manage_StatusIcon_hud(id, SHOW, iUserNadeAmount[id][TYPE_HENADE])
			manage_Scenario_hud(id, SHOW)
		}
		case 1:
		{
			manage_StatusIcon_hud(id, CLEAR, iUserNadeAmount[id][iUserNadeCurType[id]])
			iUserNadeCurType[id] = TYPE_GASNADE
			manage_StatusIcon_hud(id, SHOW, iUserNadeAmount[id][TYPE_GASNADE])
			manage_Scenario_hud(id, SHOW)
		}
		case 2:
		{
			engclient_cmd(id, sSwM4WeaponName)
			new iWeaponID = iUserHoldSwM4[id]
			new iSilen = abs(iSwM4SilenStatus[id] - 1)
			cs_set_weapon_silen(iWeaponID, iSilen, 0)
			iSwM4SilenStatus[id] = iSilen
			engclient_cmd(id, "lastinv")
			client_cmd(id, sSwM4WeaponName)
		}
		case 3:
			HoldMenu = bool:check_buy_grenade(id, TYPE_HENADE)
		case 4:
			HoldMenu = bool:check_buy_grenade(id, TYPE_GASNADE)
		default:
			return PLUGIN_HANDLED
	}
	if ( HoldMenu )
	{
		new clip,ammo
		if ( get_user_weapon(id, clip, ammo) == iSwM4WeaponID )
			show_menu(id, iMenuKeys, sSwNadeMenuBody, -1, sSwNadeMenuTitle)
		return PLUGIN_HANDLED
	}
	if ( iKey == 3 || iKey == 4 )//cannot buy
		client_cmd(id, "slot10")
	else if ( iKey != 2 )//just change grenade estate(he|gas)
		emit_sound(id, CHAN_VOICE, sSwNadeSound_Change, VOL_NORM, ATTN_NONE, 0, PITCH_NORM)		
	return PLUGIN_HANDLED
}

public launch_grenade(id, type)
{//check grenade amount & launch
	new Float: fOrigin[3], Float:fAngle[3],Float: fVelocity[3]
	pev(id, pev_origin, fOrigin)
	pev(id, pev_view_ofs, fAngle)
	fOrigin[0] += fAngle[0]
	fOrigin[1] += fAngle[1]
	fOrigin[2] += fAngle[2]
	fm_velocity_by_aim(id, 2.0, fVelocity, fAngle)
	fAngle[0] *= -1.0
	//create hurt ent
	new iHurtEnt = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, sNamedEntTriggerHurt))
	if ( iHurtEnt <= MAXPLAYERS )
		return
	fm_set_kvd(iHurtEnt, "dmg", "100.0", sNamedEntTriggerHurt)
	fm_set_kvd(iHurtEnt, "damagetype", "64", sNamedEntTriggerHurt)//in many case, DMG_BULLET cannot break the breakable object at once, so use DMG_BLAST)
	set_pev(iHurtEnt, pev_spawnflags, pev(iHurtEnt, pev_spawnflags) | SF_TRIGGER_HURT_NO_CLIENTS)
	set_pev(iHurtEnt, pev_spawnflags, pev(iHurtEnt, pev_spawnflags) | SF_TRIGGER_HURT_TARGETONCE)
	dllfunc(DLLFunc_Spawn, iHurtEnt)
	//create grenade ent
	new ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, sNamedEntInfoTarget))
	if ( ent <= MAXPLAYERS )
	{
		engfunc(EngFunc_RemoveEntity, iHurtEnt)
		return
	}
	set_pev(ent, pev_classname, sSwNadeClassname[type])
	engfunc(EngFunc_SetModel, ent, sSwNadeModel_w)
	set_pev(ent, pev_mins, Float:{-1.0, -1.0, -1.0})
	set_pev(ent, pev_maxs, Float:{1.0, 1.0, 1.0})
	set_pev(ent, pev_origin, fOrigin)
	fOrigin[0] += fVelocity[0]
	fOrigin[1] += fVelocity[1]
	fOrigin[2] += fVelocity[2]
	set_pev(iHurtEnt, pev_origin, fOrigin)
	set_pev(iHurtEnt, pev_movetype, MOVETYPE_TOSS)
	set_pev(ent, pev_movetype, MOVETYPE_BOUNCE)
	set_pev(iHurtEnt, pev_gravity, 0.55)//"0.55" is the gravity param of grenade which throw by player
	set_pev(ent, pev_gravity, 0.55)
	fVelocity[0] *= 1000.0
	fVelocity[1] *= 1000.0
	fVelocity[2] *= 1000.0	
	set_pev(iHurtEnt, pev_velocity, fVelocity)
	set_pev(ent, pev_velocity, fVelocity)
	set_pev(ent, pev_owner, id)
	set_pev(ent, pev_angles, fAngle)
	set_pev(ent, pev_solid, SOLID_BBOX)
	set_pev(ent, pev_SwNade_HurtEnt_i, iHurtEnt)//store the enitty id
	
	emit_sound(id, CHAN_VOICE, sSwNadeSound_Launch, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)//launch sound
	
	bNadeReloaded[id] = false
	manage_StatusIcon_hud(id, CLEAR, iUserNadeAmount[id][iUserNadeCurType[id]])
	iUserNadeAmount[id][type]--
	manage_StatusIcon_hud(id, SHOW, iUserNadeAmount[id][type])
	remove_task(id)
	set_task(fSwNadeReloadTime, "task_m203_reloaded", id)//fake reload
	//show grenade trail	
	message_begin( MSG_BROADCAST, SVC_TEMPENTITY )
	write_byte(TE_BEAMFOLLOW)
	write_short(ent)//entity
	write_short(iSwNadeSprite_Trail)//model
	write_byte(6)//10)//life
	write_byte(3)//5)//width
	write_byte(abs(type-1) * 100)//r, hegrenade
	write_byte(type * 100)//g, gas-grenade
	write_byte(0)//b
	write_byte(100)//brightness
	message_end()//move PHS/PVS data sending into here (SEND_ALL, SEND_PVS, SEND_PHS)
	
	new message[64]
	if ( iUserNadeAmount[id][type] < 1 )
	{
		switch ( type )
		{
			case TYPE_HENADE:
			{
				message[0] = 0x03
				format(message[1], 62, " *** Run out of 40mm hegrenade ***")
			}
			case TYPE_GASNADE:
			{
				message[0] = 0x04
				format(message[1], 62, " *** Run out of 40mm gas-grenade ***")
			}
			//case TYPE_INCENDIARY:
		}
		color_saytext(message, MSG_ONE, id, 1)
		return
	}
	format(message, 63, "^x03 M203 reloading...")
	color_saytext(message, MSG_ONE, id, 3)
	return
}

public task_m203_reloaded(id)
{
	if ( !bNadeReloaded[id] )
		bNadeReloaded[id] = true
	if ( is_user_alive(id) )
	{
		new type = iUserNadeCurType[id]
		manage_StatusIcon_hud(id, CLEAR, iUserNadeAmount[id][type])
		manage_StatusIcon_hud(id, SHOW, iUserNadeAmount[id][type])//reset estate of reloadded
	}
}

public forward_touch(ptr, ptd)
{
	if ( !pev_valid(ptr) )
		return FMRES_IGNORED
	
	static classname[32]
	pev(ptr, pev_classname, classname, sizeof classname - 1)
	if ( equal(classname, sSwClassname_Prefix, 3) )
	{//"Sw_Grenade_HE" | "Sw_Grenade_GAS" | "Sw_FakeGas" | "Sw_Box_M4withM203"
		new iParam,Float:fVector[3]
		switch ( classname[3] )
		{
			case 'G'://it is grenade launch by m203	
			{
				switch ( classname[11] )
				{
					case 'H'://hegrenade
						grenade_explode(ptr, TYPE_HENADE)
					case 'G'://gas-grenade
					{
						pev(ptr, pev_velocity, fVector)
						if ( pev(ptr, pev_SwNade_HurtEnt_i) > MAXPLAYERS )//first time touch
						{
							//engfunc(EngFunc_RemoveEntity, pev(ptr, pev_SwNade_HurtEnt_i))// iParam)
							//set_pev(ptr, pev_SwNade_HurtEnt_i, 0)
							fVector[0] *= 0.01
							fVector[1] *= 0.01
							fVector[2] *= 0.01
							set_pev(ptr, pev_velocity, fVector)
							grenade_explode(ptr, TYPE_GASNADE)
						}
						else
						{
							fVector[0] *= 0.8
							fVector[1] *= 0.8
							fVector[2] *= 0.45
							set_pev(ptr, pev_velocity, fVector)
						}
						return FMRES_SUPERCEDE
					}
				}
			}
			case 'F'://it is "fake gas" entity
			{
				if ( !pev_valid(ptd) || !is_user_alive(ptd) || iUserHasHurtEnt[ptd] > MAXPLAYERS )
					return FMRES_IGNORED
				
				pev(ptr, pev_origin, fVector)
				//pev(ptr, pev_SwNade_ExploPoint_v, fVector)
				if ( estimate_take_hurt(fVector, ptd, ptr) != 1.0 )
					return FMRES_IGNORED
				
				iParam = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, sNamedEntTriggerHurt))
				if ( iParam <= MAXPLAYERS )
					return FMRES_IGNORED
				iUserHasHurtEnt[ptd] = iParam
				set_pev(iParam, pev_owner, ptd)
				set_pev(iParam, pev_classname, sSwNadeFakeHurtClassname)
				
				fm_set_kvd(iParam, "delay", "1.5", sNamedEntTriggerHurt)
				fm_set_kvd(iParam, "dmg", sSwNadeMaxDmg_GAS, sNamedEntTriggerHurt)
				fm_set_kvd(iParam, "damagetype", "65536", sNamedEntTriggerHurt)//damage type DMG_NERVEGAS
				//fm_set_kvd(iParam, "master", 
				set_pev(iParam, pev_spawnflags, pev(iParam, pev_spawnflags) | SF_TRIGGER_HURT_CLIENTONLYFIRE)
				set_pev(iParam, pev_spawnflags, pev(iParam, pev_spawnflags) | SF_TRIGGER_HURT_CLIENTONLYTOUCH)
				dllfunc(DLLFunc_Spawn, iParam)
				
				pev(ptd, pev_origin, fVector)
				set_pev(iParam, pev_origin, fVector)
				set_pev(iParam, pev_aiment, ptd)
				set_pev(iParam, pev_movetype, MOVETYPE_FOLLOW)
				set_pev(iParam, pev_nextthink, fCurrentTime() + 3.0)
			}
			case 'B'://fake superwepaon box
			{
				if ( pev(ptr, pev_SwBox_Param_e) != SW_BOX_PARAM_NOTOUCH && is_user_alive(ptd) && !iUserHoldSwM4[ptd] && !cs_get_user_vip(ptd) && !cs_get_user_hasprim(ptd) )
				{
					iParam = get_user_team(ptd)
					if ( iSwM4CurTeamHolders[iParam] < iSwM4MaxTeamHolders[iParam] )
					{						
						if ( give_superweapon(ptd, iParam, ptr) > MAXPLAYERS )
							remove_superweapon_box(ptr)
					}
					else if ( iUserTouchTimes[ptd] < 3 )
					{
						iUserTouchTimes[ptd]++
						color_saytext(sMsgCannotGetSw, MSG_ONE_UNRELIABLE, ptd)
					}
				}
			}
		}
	}
	return FMRES_IGNORED
}

public grenade_explode(ptr, type)
{
	new Float:fPoint[3]
	engfunc(EngFunc_RemoveEntity, pev(ptr, pev_SwNade_HurtEnt_i))
	set_pev(ptr, pev_SwNade_HurtEnt_i, 0)
	if ( type == TYPE_GASNADE )
	{
		pev(ptr, pev_angles, fPoint)
		fPoint[1] += 90.0
		set_pev(ptr, pev_angles, fPoint)
		
		message_begin(MSG_BROADCAST, SVC_TEMPENTITY, _)
		write_byte(TE_KILLBEAM)
		write_short(ptr)//entity
		message_end()
		
		if ( task_exists(ptr) )
			remove_task(ptr)
		set_task(1.5, "task_gas_explode", ptr)
		return
	}
	new attacker = pev(ptr, pev_owner)
	new iAttackerTeam = get_user_team(attacker)
	new victim = -1
	new Float:fOrigin[3],Float:fDistance,Float:fDamage,Float:fTakeDamage
	new AttackerName[32],classname[32]
	new iParam,iTeamKill
	
	pev(ptr, pev_origin, fPoint)
	fPoint[2] += 1.0
	manage_effect_env(EFFECT_EXPLO, fPoint, ptr)
	engfunc(EngFunc_RemoveEntity, ptr)
	
	get_user_name(attacker, AttackerName, 31)
	while ( ( victim = engfunc(EngFunc_FindEntityInSphere, victim, fPoint, fSwNadeDmgRadius[TYPE_HENADE]) ) > 0 )
	{//check things in damage radius
		if ( !pev_valid(victim) )
			continue
		pev(victim, pev_takedamage, fTakeDamage)
		if ( fTakeDamage == DAMAGE_NO )//godmode?
			continue
		pev(victim, pev_classname, classname, 31)
		iParam = 0
		if ( equal(classname, sPlayer) && is_user_alive(victim) )
			iParam = 1
		else if ( equal(classname, sFuncBreakable) || equal(classname, sFuncPushable) )
			iParam = 2
		else if ( equal(classname, sHostageEntity) || equal(classname, sMonsterScientist) )
			iParam = 3
		if ( !iParam )
			continue//if not right ent, ignored
		
		pev(victim, pev_origin, fOrigin)
		fDistance = get_distance_f(fOrigin, fPoint)
		fDamage = fSwNadeMaxDmg_HE - floatmul(fSwNadeMaxDmg_HE, floatdiv(fDistance, fSwNadeDmgRadius[TYPE_HENADE]))//get the damage value
		fDamage *= estimate_take_hurt(fPoint, victim, 0)//adjust
		if ( fDamage < 0 && iParam != 2 )
			continue
		switch ( iParam )
		{
			case 1://player
			{
				//if ( is_user_alive(victim) )
				//{
				manage_effect_action(victim, fOrigin, fPoint, fDistance, fDamage * 8.0)
				iTeamKill = check_team_kill(attacker, victim, iAttackerTeam)
				if ( iTeamKill != 3 )
				{
					manage_effect_env(EFFECT_BLOOD, fOrigin, victim)//make bloody effect
					manage_player_damage(attacker, victim, iTeamKill, fDamage, AttackerName)
				}
				//}
			}
			case 2://breakable|pushable ent
			{
				if( fDamage <= 0 )
					fDamage = floatdiv(fSwNadeMaxDmg_HE, 2.0)
				fm_fakedamage(victim, "grenade", fDamage, DMG_BLAST)
			}
			case 3://hostage
			{
				manage_effect_action(victim, fOrigin, fPoint, fDistance, fDamage * 8.0)
				client_print(0, print_chat, "%s hurt a hostage.", AttackerName)
				fm_fakedamage(victim, "grenade", fDamage, DMG_BLAST)//64)
			}
		}
	}
	return
}

public task_gas_explode(ent)
{
	if ( !pev_valid(ent) )
		return
	
	new Float:fExplodePoint[3],iOrigin[3],iParam
	pev(ent, pev_origin, fExplodePoint)
	fExplodePoint[2] += 1.0
	engfunc(EngFunc_RemoveEntity, ent)
	
	iOrigin[0] = floatround(fExplodePoint[0])
	iOrigin[1] = floatround(fExplodePoint[1])
	iOrigin[2] = floatround(fExplodePoint[2])
/*
TE_EXPLOSION                3        // Additive sprite, 2 dynamic lights, flickering particles, explosion sound, move vertically 8 pps
The Explosion effect has some flags to control performance/aesthetic features:
TE_EXPLFLAG_NONE            0        // All flags clear makes default Half-Life explosion
TE_EXPLFLAG_NOADDITIVE      1        // Sprite will be drawn opaque (ensure that the sprite you send is a non-additive sprite)
TE_EXPLFLAG_NODLIGHTS       2        // Do not render dynamic lights
TE_EXPLFLAG_NOSOUND         4        // Do not play client explosion sound
TE_EXPLFLAG_NOPARTICLES     8        // Do not draw particles
*/
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY, iOrigin)
	write_byte(TE_EXPLOSION)
	write_coord(iOrigin[0])//position.x)
	write_coord(iOrigin[1])//position.y)
	write_coord(iOrigin[2])//position.z)
	write_short(iSwNadeSprite_GasExplode)//sprite index)
	write_byte(10)//scale in 0.1's)
	write_byte(0)//framerate)
	write_byte(4)//flags)
	message_end()
	
	iParam = engfunc(EngFunc_PointContents, fExplodePoint)
	if ( iParam == CONTENTS_WATER || iParam == CONTENTS_LAVA )
		return
	new Float:fParam,Float:fMins[3],Float:fMaxs[3],iFakeGas
	emit_sound(0, CHAN_VOICE, sSwNadeSound_GasExplode, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
	fParam = fSwNadeDmgRadius[TYPE_GASNADE]
	iParam = floatround(fParam)
/*
to keep network traffic low, this message has associated flags that fit into a byte:
TEFIRE_FLAG_ALLFLOAT        1        // All sprites will drift upwards as they animate
TEFIRE_FLAG_SOMEFLOAT       2        // Some of the sprites will drift upwards. (50% chance)
TEFIRE_FLAG_LOOP            4        // If set, sprite plays at 15 fps, otherwise plays at whatever rate stretches the animation over the sprite's duration.
TEFIRE_FLAG_ALPHA           8        // If set, sprite is rendered alpha blended at 50% else, opaque
TEFIRE_FLAG_PLANAR          16       // If set, all fire sprites have same initial Z instead of randomly filling a cube. 
*/	
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY, iOrigin)
	write_byte(TE_FIREFIELD)
	write_coord(iOrigin[0])
	write_coord(iOrigin[1])
	write_coord(iOrigin[2])
	write_short(iParam)//radius) (fire is made in a square around origin. -radius, -radius to radius, radius)
	write_short(iSwNadeSprite_GasFog)//modelindex)
	write_byte(10)//count)
	write_byte(24)//flags)
	write_byte(150)//duration (in seconds) * 10) (will be randomized a bit)
	message_end()

	fMaxs[0] = fParam
	fMaxs[1] = fParam
	fMaxs[2] = 30.0
	
	fMins[0] = fMaxs[0] * -1.0
	fMins[1] = fMaxs[1] * -1.0
	fMins[2] = fMaxs[2] * -1.0

	iFakeGas = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, sNamedEntInfoTarget))//sNamedEntTriggerHurt))//sNamedEntInfoTarget))
	if ( iFakeGas <= MAXPLAYERS )
		return
	set_pev(iFakeGas, pev_classname, sSwNadeFakeGasClassname)
	engfunc(EngFunc_SetModel, iFakeGas, sSwNadeModel_w)
	set_pev(iFakeGas, pev_mins, fMins)
	set_pev(iFakeGas, pev_maxs, fMaxs)
	set_pev(iFakeGas, pev_effects, EF_NODRAW)
	set_pev(iFakeGas, pev_solid, SOLID_TRIGGER)
	set_pev(iFakeGas, pev_movetype, MOVETYPE_FLY)
	//set_pev(iFakeGas, pev_SwNade_ExploPoint_v, fExplodePoint)//store explode origin
	set_pev(iFakeGas, pev_origin, fExplodePoint)
	set_pev(iFakeGas, pev_nextthink, fCurrentTime() + 15.0)
}
	
/*
waterlevel 0 - not in water
waterlevel 1 - feet in water
waterlevel 2 - waist in water
waterlevel 3 - head in water			

EngFunc_TraceLine,// void ) (const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr);

dont_ignore_monsters = 0
ignore_monsters = 1
missile = 2

Returned by TraceLine
typedef struct
	{
	int		fAllSolid;			// if true, plane is not valid
	int		fStartSolid;		// if true, the initial point was in a solid area
	int		fInOpen;
	int		fInWater;
	float	flFraction;			// time completed, 1.0 = didn't hit anything
	vec3_t	vecEndPos;			// final position
	float	flPlaneDist;
	vec3_t	vecPlaneNormal;		// surface normal at impact
	edict_t	*pHit;				// entity the surface is on
	int		iHitgroup;			// 0 == generic, non zero is specific body part
	} TraceResult;

from : combat.cpp

//
// RadiusDamage - this entity is exploding, or otherwise needs to inflict damage upon entities within a certain range.
// 
// only damage ents that can clearly be seen by the explosion!

	
void RadiusDamage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, float flRadius, int iClassIgnore, int bitsDamageType )
{
	CBaseEntity *pEntity = NULL;
	TraceResult	tr;
	float		flAdjustedDamage, falloff;
	Vector		vecSpot;

	if ( flRadius )
		falloff = flDamage / flRadius;
	else
		falloff = 1.0;

	int bInWater = (UTIL_PointContents ( vecSrc ) == CONTENTS_WATER);

	vecSrc.z += 1;// in case grenade is lying on the ground

	if ( !pevAttacker )
		pevAttacker = pevInflictor;

	// iterate on all entities in the vicinity.
	while ((pEntity = UTIL_FindEntityInSphere( pEntity, vecSrc, flRadius )) != NULL)
	{
		if ( pEntity->pev->takedamage != DAMAGE_NO )
		{
			// UNDONE: this should check a damage mask, not an ignore
			if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore )
			{// houndeyes don't hurt other houndeyes with their attack
				continue;
			}

			// blast's don't tavel into or out of water
			if (bInWater && pEntity->pev->waterlevel == 0)
				continue;
			if (!bInWater && pEntity->pev->waterlevel == 3)
				continue;

			vecSpot = pEntity->BodyTarget( vecSrc );
			
			UTIL_TraceLine ( vecSrc, vecSpot, dont_ignore_monsters, ENT(pevInflictor), &tr );

			if ( tr.flFraction == 1.0 || tr.pHit == pEntity->edict() )
			{// the explosion can 'see' this entity, so hurt them!
				if (tr.fStartSolid)
				{
					// if we're stuck inside them, fixup the position and distance
					tr.vecEndPos = vecSrc;
					tr.flFraction = 0.0;
				}
				
				// decrease damage for an ent that's farther from the bomb.
				flAdjustedDamage = ( vecSrc - tr.vecEndPos ).Length() * falloff;
				flAdjustedDamage = flDamage - flAdjustedDamage;
			
				if ( flAdjustedDamage < 0 )
				{
					flAdjustedDamage = 0;
				}
			
				// ALERT( at_console, "hit %s\n", STRING( pEntity->pev->classname ) );
				if (tr.flFraction != 1.0)
				{
					ClearMultiDamage( );
					pEntity->TraceAttack( pevInflictor, flAdjustedDamage, (tr.vecEndPos - vecSrc).Normalize( ), &tr, bitsDamageType );
					ApplyMultiDamage( pevInflictor, pevAttacker );
				}
				else
				{
					pEntity->TakeDamage ( pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType );
				}
			}
		}
	}
}
*/

//////////////////  stock ///////////////////////////

stock get_InfoEnt_origin()
{
	new num =0,ent = -1
	while ( (ent = engfunc(EngFunc_FindEntityByString, ent, sClassname, sInfoPlayerStart)) > 0 )
	{
		pev(ent, pev_origin, fInfoEntOrigin[num])
		num++
		if ( num >= floatround(float(MAXNUM) * 0.5) )
			break
	}
	ent = -1
	while ( (ent = engfunc(EngFunc_FindEntityByString, ent, sClassname, sInfoPlayerDeathmatch)) > 0 )
	{
		pev(ent, pev_origin, fInfoEntOrigin[num])
		num++
		if ( num >= MAXNUM )
			break
	}
	return num
}

stock spawn_GhostEnt(iSpawnAmount)
{//for get "superweapon box"'s spawn ponit
	new num,ent,Float:velocity[3]//,Float:origin[3]
	while ( (ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, sNamedEntInfoTarget))) > MAXPLAYERS )
	{
		set_pev(ent, pev_classname, sGhostEntClassname)
		set_pev(ent, pev_origin, fInfoEntOrigin[random(iInfoEntAmount)])
		set_pev(ent, pev_solid, SOLID_TRIGGER)
		set_pev(ent, pev_movetype, MOVETYPE_BOUNCE)
		set_pev(ent, pev_mins, Float:{-16.0,-16.0,-16.0})
		set_pev(ent, pev_maxs, Float:{16.0,16.0,16.0})
		
		velocity[0] = float( (2500 + random(501)) * (!random(2)?- 1:1) )
		velocity[1] = float( (2500 + random(501)) * (!random(2)? -1:1) )
		velocity[2] = float( (2500 + random(501)) * (!random(2)? -1:1) )
		
		set_pev(ent, pev_velocity, velocity)
		iGhostEntID[num] = ent
		num++
		if ( num >= iInfoEntAmount )
			break
	}
	
	if ( task_exists(iTaskSpanwSwBox) )
		remove_task(iTaskSpanwSwBox)
	new param[1]
	param[0] = iSpawnAmount
	set_task(3.5, "task_spawn_SwBox", iTaskSpanwSwBox, param, 1)
	
	return 0
}
		
stock bool:remove_GhostEnt()
{
	new ent = -1
	while ( (ent = engfunc(EngFunc_FindEntityByString, ent, sClassname, sGhostEntClassname)) > MAXPLAYERS )
		engfunc(EngFunc_RemoveEntity, ent)
	return true
}

stock get_cvar_param()
{
	new iTeam,i
	
	iSwM4Price = get_pcvar_num(cvar_SwM4Price_num)
	iSwM4StripMode = get_pcvar_num(cvar_SwM4StripMode_num)
	
	iSwM4MaxAmount = (iSwM4MaxTeamHolders[TE] = get_pcvar_num(cvar_SwMaxHolders_TE_num)) + (iSwM4MaxTeamHolders[CT] = get_pcvar_num(cvar_SwMaxHolders_CT_num))
		
	bSwNadeTK = bool:get_pcvar_num(cvar_SwNadeTeamKill_num)
	fSwNadeReloadTime = get_pcvar_float(cvar_SwNadeReloadTime_flo)
	
	fSwNadeMaxDmg_HE = float(get_pcvar_num(cvar_SwNadeMaxDmg_HE_num)*2)
	fSwNadeDmgRadius[TYPE_HENADE] = float(get_pcvar_num(cvar_SwNadeDmgRadius_HE_num))
	iSwNadeMaxCarried[TYPE_HENADE] = get_pcvar_num(cvar_SwNadeMaxCarried_HE_num)
	iSwNadePrice[TYPE_HENADE] = get_pcvar_num(cvar_SwNadePrice_HE_num)
	
	num_to_str(floatround(float(get_pcvar_num(cvar_SwNadeMaxDmg_GAS_num)) / 7.0), sSwNadeMaxDmg_GAS, sizeof sSwNadeMaxDmg_GAS - 1)
	fSwNadeDmgRadius[TYPE_GASNADE] = float(get_pcvar_num(cvar_SwNadeDmgRadius_GAS_num))
	iSwNadeMaxCarried[TYPE_GASNADE] = get_pcvar_num(cvar_SwNadeMaxCarried_GAS_num)
	iSwNadePrice[TYPE_GASNADE] = get_pcvar_num(cvar_SwNadePrice_GAS_num)
	
	bInBuyTime = true
	bInFreezeTime = true
	
	if ( task_exists(iTaskBuyTimeOver) )
		remove_task(iTaskBuyTimeOver)
	set_task((get_cvar_float("mp_buytime") * 60.0), "task_buy_time_over",iTaskBuyTimeOver)
	
	
	iSwM4CurTeamHolders[TE] = 0
	iSwM4CurTeamHolders[CT] = 0

	for ( i=1; i<=MAXPLAYERS; i++ )
	{
		if ( !iUserHoldSwM4[i] )
			continue
		if ( !is_user_alive(i) )
		{
			iUserHoldSwM4[i] = 0
			continue
		}
		iTeam = get_user_team(i)
		if ( iSwM4CurTeamHolders[iTeam] >= iSwM4MaxTeamHolders[iTeam] || !(pev(i, pev_weapons) & (1<<iSwM4WeaponID)) )
		{
			iUserHoldSwM4[i] = 0
			continue
		}
		iSwM4CurTeamHolders[iTeam]++
	}
	return (iSwM4MaxAmount - iSwM4CurTeamHolders[TE] - iSwM4CurTeamHolders[CT])
}

stock create_effect_entity()
{
	new iEnt = -1
	while ( (iEnt = engfunc(EngFunc_FindEntityByString, iEnt, sClassname, sSwEffectClassname)) > MAXPLAYERS )
		engfunc(EngFunc_RemoveEntity, iEnt)
	//explosion
	iEnt = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, sNamedEntEnvExplosion))
	if ( iEnt <= MAXPLAYERS )
		create_effect_entity()
	fm_set_kvd(iEnt, "iMagnitude", "100", sNamedEntEnvExplosion)//flSpriteScale = ( m_iMagnitude - 50) * 0.6;
	set_pev(iEnt, pev_spawnflags, pev(iEnt, pev_spawnflags) | SF_ENVEXPLOSION_NODAMAGE)
	set_pev(iEnt, pev_spawnflags, pev(iEnt, pev_spawnflags) | SF_ENVEXPLOSION_REPEATABLE)
	dllfunc(DLLFunc_Spawn, iEnt)
	set_pev(iEnt, pev_classname, sSwEffectClassname)
	set_pev(iEnt, pev_origin, {8192,8192,8192})
	iSwEffectID[EFFECT_EXPLO] = iEnt
	//blood	
	iEnt = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, sNamedEntEnvBlood))
	if ( iEnt <= MAXPLAYERS )
		create_effect_entity()		
	fm_set_kvd(iEnt, "color", "2", sNamedEntEnvBlood)//black/white = 0, yellow = 1, red = 2
	fm_set_kvd(iEnt, "amount", "100", sNamedEntEnvBlood)
	set_pev(iEnt, pev_spawnflags, pev(iEnt, pev_spawnflags) | SF_BLOOD_RANDOM)
	set_pev(iEnt, pev_spawnflags, pev(iEnt, pev_spawnflags) | SF_BLOOD_DECAL)
	dllfunc(DLLFunc_Spawn, iEnt)
	set_pev(iEnt, pev_classname, sSwEffectClassname)
	set_pev(iEnt, pev_origin, {8192,8192,8192})
	iSwEffectID[EFFECT_BLOOD] = iEnt
	return 1
}

stock check_buy_grenade(id, type)
{
	new message[64]
	if (  !bInBuyTime  )
	{
		color_saytext(sMsgNotInBuyTime, MSG_ONE, id, 4)
		return 0
	}
	if ( !bInBuyzone[id] )
	{
		color_saytext(sMsgNotInBuyzone, MSG_ONE, id)
		return  0
	}
	if( cs_get_user_money(id) < iSwNadePrice[type] )
	{
		switch ( type )
		{
			case TYPE_HENADE:
				format(message, 63, "^x01 You hasn't enough money,^x03 hegrenade^x01 price is^x03 $%d", iSwNadePrice[TYPE_HENADE])
			case TYPE_GASNADE:
				format(message, 63, "^x01 You hasn't enough money,^x04 gas-grenade^x01 price is^x04 $%d", iSwNadePrice[TYPE_GASNADE])
		}
		color_saytext(message, MSG_ONE, id, 1)
		return 0
	}
	if ( iUserNadeAmount[id][type] >= iSwNadeMaxCarried[type] )
	{
		switch ( type )
		{
			case TYPE_HENADE:
				format(message, 63, "^x01 Max carried amount of^x03 hegrenades^x01 is^x03 %d", iSwNadeMaxCarried[TYPE_HENADE])
			case TYPE_GASNADE:
				format(message, 63, "^x01 Max carried amount of^x04 gas-grenades^x01 is^x04 %d", iSwNadeMaxCarried[TYPE_GASNADE])
		}
		color_saytext(message, MSG_ONE, id, 1)
		return 0
	}
	emit_sound(id, CHAN_VOICE, sSwNadeSound_Buy, VOL_NORM, ATTN_NONE, 0, PITCH_NORM)
	manage_StatusIcon_hud(id, CLEAR, iUserNadeAmount[id][iUserNadeCurType[id]])
	iUserNadeAmount[id][type]++
	iUserNadeCurType[id] = type
	manage_StatusIcon_hud(id, SHOW, iUserNadeAmount[id][type])//show number of grenade on left middle screen
	manage_ItemPickup_hud(id, type)//show fake ammo icon on right screen
	manage_Scenario_hud(id, SHOW)
	return cs_set_user_money(id, cs_get_user_money(id) - iSwNadePrice[type], 1)//set player's money
}

stock manage_effect_env(iEffect, Float:fOrigin[3], iUserEnt)
{
	if ( !iUserEnt )
		return 0
	new param = iSwEffectID[iEffect]
	if ( param <= MAXPLAYERS )
	{
		create_effect_entity()
		manage_effect_env(iEffect, fOrigin, iUserEnt)
	}
	set_pev(param, pev_origin, fOrigin)
	dllfunc(DLLFunc_Use, param, iUserEnt)
	set_pev(param, pev_origin, {8192.0,8192.0,8192.0})
	return 1
}

stock manage_effect_action(iEnt, Float:fEntOrigin[3], Float:fPoint[3], Float:fDistance, Float:fDamage)
{
	new Float:fTime = floatdiv(fDistance, fDamage)
	new Float:fVelocity[3]
	fVelocity[0] = floatdiv((fEntOrigin[0] - fPoint[0]), fTime)
	fVelocity[1] = floatdiv((fEntOrigin[1] - fPoint[1]), fTime)
	fVelocity[2] = floatdiv((fEntOrigin[2] - fPoint[2]), fTime)
	set_pev(iEnt, pev_velocity, fVelocity)
	return 1
}

stock Float:estimate_take_hurt(Float:fPoint[3], ent, ignored) 
{
	new Float:fOrigin[3]
	new tr
	new Float:fFraction
	pev(ent, pev_origin, fOrigin)
	//UTIL_TraceLine ( vecSpot, vecSpot + Vector ( 0, 0, -40 ),  ignore_monsters, ENT(pev), & tr)
	engfunc(EngFunc_TraceLine, fPoint, fOrigin, DONT_IGNORE_MONSTERS, ignored, tr)
	get_tr2(tr, TR_flFraction, fFraction)
	if ( fFraction == 1.0 || get_tr2( tr, TR_pHit ) == ent )//no valid enity between the explode point & player
		return 1.0
	return 0.6//if has fraise, lessen blast hurt
}

stock Float:fCurrentTime()
{
	new Float:fTime
	global_get(glb_time, fTime)
	return fTime
}

stock remove_HurtEnt(id)
{
	new ent = iUserHasHurtEnt[id]
	iUserHasHurtEnt[id] = 0
	if ( !pev_valid(ent) )
		return 0
	new classname[16]
	pev(ent, pev_classname, classname, sizeof classname - 1 )
	if ( equal(classname, sSwNadeFakeHurtClassname) )
		engfunc(EngFunc_RemoveEntity, ent)
	return 1
}

stock emake_deathmsg(killer, victim, headshot, weapon[])
{//Thanks VEN & dutchmeat !
	emessage_begin(MSG_ALL,iDeathMsgID,{0,0,0},0)
	ewrite_byte(killer)
	ewrite_byte(victim)
	
	ewrite_byte(headshot)
	/*
	new mod_name[32]
	get_modname(mod_name,31)
	if ( equal(mod_name,"cstrike") || equal(mod_name,"czero") || equal(mod_name,"csv15") || equal(mod_name,"cs13") )
		ewrite_byte(headshot)
	*/
	
	ewrite_string(weapon)
	emessage_end()
	return 1
}

stock reset_superweapon(id)
{
	set_pev(id, pev_viewmodel2, sSwM4Model_v)
	set_pev(id, pev_weaponmodel2, sSwM4Model_p)
	iSwM4BpAmmo[id] = cs_get_user_bpammo(id, iSwM4WeaponID)
	return 1
}

stock reset_player(id, count = 0, iTeam = 0)
{
	new type = iUserNadeCurType[id]
	manage_StatusIcon_hud(id, CLEAR, iUserNadeAmount[id][type])
	manage_Scenario_hud(id, CLEAR)
	iUserHoldSwM4[id] = 0
	iUserNadeAmount[id][TYPE_HENADE] = 0
	iUserNadeAmount[id][TYPE_GASNADE] = 0
	iUserTouchTimes[id] = 0
	if ( !iTeam )
		iTeam = get_user_team(id)
	if ( count == COUNT && ( iTeam == TE || iTeam == CT ) )
		iSwM4CurTeamHolders[iTeam]--
	new iMenuID,iKeys
	get_user_menu(id, iMenuID, iKeys)
	if ( iMenuID == iSwNadeMenuID )
		client_cmd(id, "slot10")
	return iTeam
}

stock remove_superweapon_box(ent)
{
	if ( ent <= MAXPLAYERS )
		return 0
	new iSpriteEnt = pev(ent, pev_SwBox_Param_e)
	if ( iSpriteEnt > MAXPLAYERS )
		engfunc(EngFunc_RemoveEntity, iSpriteEnt)
	engfunc(EngFunc_RemoveEntity, ent)
	return 1
}

stock give_superweapon(id, iTeam, ptr = 0)
{
	if ( !iTeam || iTeam == SPECTATOR )
		return 0
	new ent = fm_give_item(id, sSwM4WeaponName)
	if ( ent <= MAXPLAYERS )
		return 0
	if ( ptr > MAXPLAYERS )
	{//by "pickup"
		new bpammo = clamp((cs_get_user_bpammo(id, iSwM4WeaponID) + pev(ptr, pev_SwBox_BpAmmo_e)), 0, 90)
		new iSilen = pev(ptr, pev_SwBox_Silen_e)
		iUserNadeAmount[id][TYPE_HENADE] = pev(ptr, pev_SwBox_HeAmount_i)
		iUserNadeAmount[id][TYPE_GASNADE] = pev(ptr, pev_SwBox_GasAmount_i)
		iSwM4SilenStatus[id] = iSilen
		cs_set_weapon_silen(ent, iSilen, 0)
		cs_set_weapon_ammo(ent, pev(ptr, pev_SwBox_ClipAmmo_e))
		cs_set_user_bpammo(id, iSwM4WeaponID, bpammo)
	}
	else
	{//by admin command or buy
		iUserNadeAmount[id][TYPE_HENADE] = iSwNadeMaxCarried[TYPE_HENADE]
		iUserNadeAmount[id][TYPE_GASNADE] = iSwNadeMaxCarried[TYPE_GASNADE]
		cs_set_user_bpammo(id, iSwM4WeaponID, 90)
	}
	iSwM4CurTeamHolders[iTeam]++
	iUserHoldSwM4[id] = ent
	//bNadeReloaded[id] = true
	iUserNadeCurType[id] = TYPE_HENADE
	manage_StatusIcon_hud(id, SHOW, iUserNadeAmount[id][TYPE_HENADE])
	manage_Scenario_hud(id, SHOW)
	engclient_cmd(id, "lastinv")
	client_cmd(id, sSwM4WeaponName)
	return ent
}

stock manage_StatusIcon_hud(id, act, amount)
{//grenade number on the player's left middle screen
	if ( !is_user_connected(id) )//|| !is_user_alive(id) )
		return 0
	new icon[16]
	new type = iUserNadeCurType[id]
	//new IconStatus = act
	new green = amount > 0?160:0
	if ( act == SHOW )
	{
		if ( !iUserHoldSwM4[id] || !is_user_alive(id) )
			act = CLEAR
		else
			act = !bNadeReloaded[id] && amount?2:1//flash or not
	}
	amount >= NOT_SHOW_NUM?format(icon, 15, sNadeStateString[type]):format(icon, 15, "number_%d", amount)
	message_begin(MSG_ONE, iStatusIconMsgID, _, id)
	write_byte(act)// status
	write_string(icon)// sprite name
	write_byte(abs(green - 160))// red
	write_byte(green)// green
	write_byte(0)// blue
	return message_end()
}

stock manage_ItemPickup_hud(id,type)
{
	if ( !is_user_connected(id) && !is_user_alive(id) )
		return 0
	//show fake hegrenade|gas-grenade ammo, on right screen
	message_begin(MSG_ONE, iItemPickupMsgID, _, id)
	write_string(sNadeStateString[type])
	return message_end()
}

stock manage_Scenario_hud(id, act)
{//show current grenade state on down screen front of "money" icon
	if ( !is_user_connected(id) && !is_user_alive(id) )
		return 0
	
	if ( act == CLEAR )
	{
		message_begin(MSG_ONE, iScenarioMsgID, _, id)
		write_byte(0)//  Active
		return message_end()
	}
	new type = iUserNadeCurType[id]
	message_begin(MSG_ONE, iScenarioMsgID, _, id)
	write_byte(1)//  Active
	write_string(sNadeStateString[type])//  Sprite
	write_byte(100)//  Alpha
	write_short(0)//  FlashRate
	write_short(0)//  Unknown
	return message_end()
}
	
stock check_team_kill(attacker, victim, iAttackerTeam)
{
	if ( attacker == victim )
		return HURT_SELF
	if ( iAttackerTeam == get_user_team(victim) )
	{
		if ( bSwNadeTK )//force TK?
			return HURT_TEAMMATE
		return iServerTK//by server TK rule
	}
	return HURT_ENEMY
}
	

stock manage_player_damage(attacker, victim, iTeamKill, Float:damage, AttackerName[])
{
	fm_fakedamage(victim, "grenade", damage, DMG_BLAST)//64
	if ( iTeamKill == HURT_TEAMMATE )
		client_print(0,print_chat,"%s attacked a teammate",AttackerName)
	if( is_user_alive(victim) )
		return 0
	emake_deathmsg(attacker, victim, 0, "grenade")//make death message
	if ( !is_user_connected(attacker) )
		return 0
	switch ( iTeamKill )
	{
		case HURT_ENEMY:
		{
			set_pev(attacker, pev_frags, pev(attacker, pev_frags) + 1.0)
			cs_set_user_money(attacker, cs_get_user_money(attacker)+300, 1)
		}
		case HURT_TEAMMATE:
		{
			set_pev(attacker, pev_frags, pev(attacker, pev_frags) - 1.0)
			cs_set_user_money(attacker, cs_get_user_money(attacker)-3300, 1)
		}
		default:{}//	return 0
	}
	return 1
}

////////////////////////////// color_saytext ////////////////////////////////////////////
/*
color_by_team = 1  use TE's team-color(red)
color_by_team = 2  use CT's team-color(blue)
color_by_team = 3  use SPEC's team-color(gray)
color_by_team = 4  use everyone's team-color(TE use red, CT use blue, SPECTATOR use gray)
*/
stock color_saytext(message[], dest, id = 0, color_by_team = 0 )
{
	if ( (dest == MSG_ONE || dest == MSG_ONE_UNRELIABLE ) && !id )
		return 0
	new pList[32],pNum,i,color
	if ( color_by_team > 3 )//by current definiens, affirm MSG_ALL
	{
		get_players(pList, pNum)
		for ( i=0; i<pNum; i++ )
		{
			color = pList[i]
			message_begin(MSG_ONE, iSayTextMsgID, {0,0,0}, color)
			write_byte(color)
			write_string(message)
			message_end()
		}
		return 1
	}
	if ( color_by_team && color_by_team < 3 )//if use te or ct's team-color
	{
		new iParam
		get_players(pList, pNum)
		for ( i=0; i<pNum; i++ )
		{
			iParam = pList[i]
			if ( get_user_team(iParam) == color_by_team )
			{
				color = iParam
				break
			}
		}
	}
	if ( !color )//if cannot find any player by team or not const id, use gray color
		color = (color_by_team == 3 || !id )?33:id
	message_begin(dest, iSayTextMsgID, {0,0,0}, (dest == MSG_ONE || dest == MSG_ONE_UNRELIABLE)?id: 0)
	write_byte(color)
	write_string(message)
	return message_end()
}

/////////////////// VEN's Fakemeta Utilities,thanks ////////////////////////////////////

stock fm_velocity_by_aim(iIndex, Float:fDistance, Float:fVelocity[3], Float:fViewAngle[3])
{
	//new Float:fViewAngle[3]
	pev(iIndex, pev_v_angle, fViewAngle)
	fVelocity[0] = floatcos(fViewAngle[1], degrees) * fDistance
	fVelocity[1] = floatsin(fViewAngle[1], degrees) * fDistance
	fVelocity[2] = floatcos(fViewAngle[0]+90.0, degrees) * fDistance
	return 1
}

stock fm_find_ent_by_owner(index, const classname[], owner, jghgtype = 0)
{
	new strtype[11] = "classname", ent = index
	switch (jghgtype)
	{
		case 1: copy(strtype, 6, "target")
		case 2: copy(strtype, 10, "targetname")
	}
	while ((ent = engfunc(EngFunc_FindEntityByString, ent, strtype, classname)) && pev(ent, pev_owner) != owner) {}
	return ent
}

/*
stock fm_find_ent_by_model(index, const classname[], const model[])
{
	new ent = index, mdl[72]
	while ( (ent = engfunc(EngFunc_FindEntityByString, ent, sClassname, classname)) > 0 )
	{
		pev(ent, pev_model, mdl, 71)
		if ( equal(mdl, model) )
			return ent
	}
	return 0
}
*/

stock fm_set_kvd(entity, const key[], const value[], const classname[] = "")
{
	if ( classname[0] )
		set_kvd(0, KV_ClassName, classname)
	else
	{
		new class[32]
		pev(entity, pev_classname, class, 31)
		set_kvd(0, KV_ClassName, class)
	}
	set_kvd(0, KV_KeyName, key)
	set_kvd(0, KV_Value, value)
	set_kvd(0, KV_fHandled, 0)
	return dllfunc(DLLFunc_KeyValue, entity, 0)
}

stock fm_fakedamage(victim, const classname[], Float:takedmgdamage, damagetype)
{
	new entity = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, sNamedEntTriggerHurt))
	if ( !entity )
		return 0
	new value[16]
	format(value, 15, "%f", floatmul(takedmgdamage, 2.0))
	fm_set_kvd(entity, "dmg", value, sNamedEntTriggerHurt)
	format(value, 15, "%i", damagetype)
	fm_set_kvd(entity, "damagetype", value, sNamedEntTriggerHurt)
	fm_set_kvd(entity, "origin", "8192 8192 8192", sNamedEntTriggerHurt)
	dllfunc(DLLFunc_Spawn, entity)
	set_pev(entity, pev_classname, classname)
	dllfunc(DLLFunc_Touch, entity, victim)
	engfunc(EngFunc_RemoveEntity, entity)
	return 1
}

stock fm_give_item(index, const item[])
{
	if ( !equal(item, "weapon_", 7) && !equal(item, "ammo_", 5) && !equal(item, "item_", 5) && !equal(item, "tf_weapon_", 10) )
		return 0
	new ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, item))
	if ( !pev_valid(ent) )
		return 0
	new Float:origin[3]
	pev(index, pev_origin, origin)
	set_pev(ent, pev_origin, origin)
	set_pev(ent, pev_spawnflags, pev(ent, pev_spawnflags) | SF_NORESPAWN)
	dllfunc(DLLFunc_Spawn, ent)
	new save = pev(ent, pev_solid)
	dllfunc(DLLFunc_Touch, ent, index)
	if (pev(ent, pev_solid) != save)
		return ent
	engfunc(EngFunc_RemoveEntity, ent)
	return -1
}
