#include <amxmodx>
#include <amxmisc>
#include <engine>
#include <hamsandwich>
#include <dhudmessage>
#include <fakemeta>
#include <fakemeta_util>
#include <fun>
#include <next21_DR_secondary>
#include <next21_DR_core>

#define PLUGIN "n21_Deathrun_Night"
#define VERSION "1.0"
#define AUTHOR "Psycrow"

#define DHUD_POSITION 255, 0, 0, -1.0, 0.2, 0, 0.0, 0.5, 0.0, 0.8
#define get_gun_owner(%1)	get_pdata_cbase(%1, 41, 4)
#define TASKID 1337
#define TASKID_DF 1228

#define KnifeVModel		"models/n21_deathrun/chainsaw/v_chainsaw.mdl"
#define KnifePModel		"models/n21_deathrun/chainsaw/p_chainsaw.mdl"
#define MaskModel		"models/next21_hats/hockey_mask.mdl"

#define Lifes 20
#define Spint_Text 		"Ускорение (E)"

new ModeId, bool:in_night[33], bool:in_butcher[33], g_manic_lifes[33], bool:g_in_sprint[33], g_maxplayers, g_syncHudMessage, g_InfoTarget
new Mask_Ent
new Trie:tSoundKnife
static sound_butcher[] 			= "n21_deathrun/butcher.wav"


public plugin_precache()
{
	tSoundKnife = TrieCreate()
	new Trie:tPrecached = TrieCreate()
	
	new const szOldSounds[ ][ ] = {
		"weapons/knife_hit1.wav", 
		"weapons/knife_hit2.wav", 
		"weapons/knife_hit3.wav", 
		"weapons/knife_hit4.wav", 
		"weapons/knife_stab.wav", 
		"weapons/knife_hitwall1.wav", 
		"weapons/knife_slash1.wav", 
		"weapons/knife_slash2.wav", 
		"weapons/knife_deploy1.wav" 
	}
	
	new const szNewSounds[][] = {
		"n21_deathrun/chainsaw/chainsaw_hit1.wav",
		"n21_deathrun/chainsaw/chainsaw_hit2.wav",
		"n21_deathrun/chainsaw/chainsaw_hit1.wav",
		"n21_deathrun/chainsaw/chainsaw_hit2.wav",
		"n21_deathrun/chainsaw/chainsaw_stab.wav",
		"n21_deathrun/chainsaw/chainsaw_hitwall.wav",
		"n21_deathrun/chainsaw/chainsaw_miss.wav",
		"n21_deathrun/chainsaw/chainsaw_miss.wav",
		"n21_deathrun/chainsaw/chainsaw_deploy.wav"
	}
	
	for(new i; i < sizeof szOldSounds; i++)
	{
		if(!TrieKeyExists(tPrecached, szNewSounds[i]))
		{
			TrieSetCell(tPrecached, szNewSounds[i], 1)
			precache_sound(szNewSounds[i])
		}
		
		TrieSetString(tSoundKnife, szOldSounds[i], szNewSounds[i])
	}
	
	precache_sound(sound_butcher)
	precache_model(KnifeVModel)
	precache_model(KnifePModel)
	precache_model(MaskModel)

}

public plugin_init()
{
	register_plugin(PLUGIN, VERSION, AUTHOR)
	
	ModeId = n21_dr_mode_registration("Ночь", "Убегайте как можно скорее!", 4, 255, 0, 0, 5)
		
	register_logevent("NewRound", 2, "1=Round_Start")
	RegisterHam(Ham_Use,"func_button","UseButton",0)
	RegisterHam(Ham_Item_Deploy, "weapon_knife", "CurWeapon", 1)
	RegisterHam(Ham_TakeDamage, "player", "ham_FallDmg")
	RegisterHam(Ham_Player_PreThink, "player", "Ham_PreThink_player")
	register_forward(FM_EmitSound, "EmitSound")
	
	register_event("SendAudio", "task_extra_close", "a", "2&%!MRAD_terwin")   
	register_event("SendAudio", "task_extra_close", "a", "2&%!MRAD_ctwin") 
	register_event("SendAudio", "task_extra_close", "a", "2&%!MRAD_draw") 
	register_event("TextMsg", "task_extra_close", "a", "2&#Game_C", "2&#Game_w", "2&#Game_will_restart_in")
	
	set_task(1.0, "InfoSprint", _, _, _, "b")
	
	g_maxplayers = get_maxplayers()
	g_syncHudMessage = CreateHudSyncObj()
	g_InfoTarget = engfunc(EngFunc_AllocString, "info_target")
}

public task_extra_close()
{
	remove_task(TASKID_DF)
	remove_task(TASKID)
}

public client_connect(id)
{
	in_night[id] = false
	in_butcher[id] = false
}

public client_disconnect(id)
{
	if(in_night[id])
	{
		set_task(3.0,"SetNewButcher", TASKID_DF)
		if(is_valid_ent(Mask_Ent) && Mask_Ent)
			remove_entity(Mask_Ent)
	}
}

public n21_dr_set_mode(id, mode)
	if(mode == ModeId)
	{
		in_night[id] = true
		new args[2]
		args[0] = id
		args[1] = 15
		ButcherBegin(args)
	}

public CurWeapon(weapon)
{
	new id = get_gun_owner(weapon)
	
	if(in_butcher[id])
	{
		set_pev(id, pev_viewmodel2, KnifeVModel)
		set_pev(id, pev_weaponmodel2, KnifePModel)
	}
}

public NewRound()
{	
	for(new i=1; i<=g_maxplayers; i++)
	{	
		if(in_night[i])
			in_night[i] = false
			
		if(in_butcher[i])	
		{
			in_butcher[i] = false
			set_pev(i, pev_viewmodel2, "models/v_knife.mdl")
			set_pev(i, pev_weaponmodel2, "models/p_knife.mdl")
		}
	}
	
	if(is_valid_ent(Mask_Ent) && Mask_Ent)
		remove_entity(Mask_Ent)
	
	set_lights("#OFF")
}

public InfoSprint()
{
	for (new id=1; id <= g_maxplayers; id++)
	{
		if(is_user_connected(id))
		{
			if(in_butcher[id] && is_user_alive(id))
			{
				set_hudmessage(255,0,0, 0.01, 0.71, 0, 0.0, 1.2, 0.0, 0.0, -1)
				ShowSyncHudMsg(id, g_syncHudMessage, Spint_Text)
			}
		}
	}
}

public Ham_PreThink_player(id)
{
	if(!in_butcher[id])
		return PLUGIN_CONTINUE
	
	if(g_in_sprint[id])
	{
		if(!AllowSprint(id))
		{
			n21_dr_set_maxspeed(id, 0.0)
			g_in_sprint[id] = false
			
		}
	}
	else
	{
		if(AllowSprint(id))
		{
			n21_dr_set_maxspeed(id, 500.0)
			g_in_sprint[id] = true
		}
	}
	
	return PLUGIN_CONTINUE
}

public ButcherBegin(put_args[])
{
	new id = put_args[0]
	new second = put_args[1]
	
	if(!is_user_alive(id))
		return PLUGIN_CONTINUE
		
	set_dhudmessage(DHUD_POSITION)
	
	if(second == 0)
	{
		Butcher(id)
		show_dhudmessage(0, "Началась кровавая ночь")
		
		new Players[32] 
		new Count, i, player 	
		get_players(Players, Count, "ahe","CT") 
		for (i=0; i<Count; i++)
		{
			player = Players[i]
			
			ham_strip_weapon(player,"weapon_glock18")
			ham_strip_weapon(player,"weapon_usp")
			client_cmd(player, "impulse 100")
		}
		
		return PLUGIN_CONTINUE
	}
	
	show_dhudmessage(0, "До появления маньяка %d сек.", second)
	
	second--
	
	new args[2]
	args[0] = id
	args[1] = second
	set_task(1.0, "ButcherBegin", TASKID, args, 2)
	
	return PLUGIN_CONTINUE
}

public Butcher(id)
{
	if(!is_user_alive(id) || !in_night[id])
		return PLUGIN_CONTINUE
	
	in_butcher[id] = true
	g_manic_lifes[id] = Lifes
	set_lights("b")
	client_cmd(0, "spk %s", sound_butcher)
	fm_set_user_health(id, 1000)
	
	new Float:origin[3]
	new ent = find_ent_by_class(-1,"info_player_start")
	pev(ent,pev_origin,origin)
	set_pev(id, pev_origin, origin)
	
	ham_strip_weapon(id,"weapon_glock18")
	ham_strip_weapon(id,"weapon_usp")
	set_pev(id, pev_viewmodel2, KnifeVModel)
	set_pev(id, pev_weaponmodel2, KnifePModel)	
	
	Mask_Ent = engfunc(EngFunc_CreateNamedEntity, g_InfoTarget)
	if(is_valid_ent(Mask_Ent))
	{
		set_pev(Mask_Ent, pev_movetype, MOVETYPE_FOLLOW)
		set_pev(Mask_Ent, pev_aiment, id)
		set_pev(Mask_Ent, pev_rendermode, kRenderNormal)
		set_pev(Mask_Ent, pev_renderamt, 0.0)
		engfunc(EngFunc_SetModel, Mask_Ent, MaskModel)
	}
	
	return PLUGIN_CONTINUE
}

public SetNewButcher()
{
	new Players[32], Count
	get_players(Players, Count, "ahe","TERRORIST") 

	in_night[Players[0]] = true
	Butcher(Players[0])
}

public ham_FallDmg(Victim, Gun, Attacker, Float:damage)
{
	if(!is_user_connected(Victim))
		return HAM_IGNORED
		
	if(n21_in_duel())
		return HAM_IGNORED
	
	if(is_user_connected(Attacker))
	{
		if(get_user_weapon(Attacker) == CSW_USP)
			ham_strip_weapon(Attacker,"weapon_usp")
			
		if(pev(Attacker,pev_solid) == SOLID_NOT)
			SetHamParamFloat(4, 0.0)
	}
	
	if(!is_user_connected(Attacker))
	{
		if(in_butcher[Victim] && g_manic_lifes[Victim])
		{
			SetHamParamFloat(4, 0.0)
			
			new Float:origin[3]
			new ent = find_ent_by_class(-1,"info_player_start")
			pev(ent, pev_origin, origin)
			set_pev(Victim, pev_origin, origin)
			n21_teleport_cp(Victim)
			
			g_manic_lifes[Victim]--
		}
	}
	
	return HAM_IGNORED
}

public UseButton(ent, id, idactivator, use_type, Float:value)
{
	if(!is_user_connected(id))
		return HAM_SUPERCEDE  
	
	if(ModeId == n21_dr_get_mode_id() && in_night[id] && !in_butcher[id])
		return HAM_SUPERCEDE  
		
	return HAM_IGNORED   
}


public EmitSound(id, channel, const sample[], Float:volume, Float:attn, flags, pitch)
{
	if(!is_user_connected(id))
		return FMRES_IGNORED
	
	if(!in_butcher[id])
		return FMRES_IGNORED
	
	static szNewSound[256]
	
	if(TrieGetString(tSoundKnife, sample, szNewSound, charsmax(szNewSound)))
	{ 
		emit_sound(id, channel, szNewSound, volume, attn, flags, pitch)
		return FMRES_SUPERCEDE
	}
	
	return FMRES_IGNORED
}

stock ham_strip_weapon(id,weapon[])
{
	if(!equal(weapon,"weapon_",7)) return 0
 
	new wId = get_weaponid(weapon)
	if(!wId) return 0
 
	new wEnt
	while((wEnt = engfunc(EngFunc_FindEntityByString,wEnt,"classname",weapon)) && pev(wEnt,pev_owner) != id) {}
	if(!wEnt) return 0
 
	if(get_user_weapon(id) == wId) ExecuteHamB(Ham_Weapon_RetireWeapon,wEnt)
 
	if(!ExecuteHamB(Ham_RemovePlayerItem,id,wEnt)) return 0
	ExecuteHamB(Ham_Item_Kill,wEnt)
 
	set_pev(id,pev_weapons,pev(id,pev_weapons) & ~(1<<wId))
     
	return 1
}

bool:AllowSprint(id)
{
	if(!is_user_alive(id))
		return false
		
	if(!in_butcher[id])	
		return false
		
	if(!(pev(id, pev_flags) & FL_ONGROUND))
		return false
		
	if(pev(id, pev_flags) & FL_INWATER)
		return false
		
	static buttons
	buttons = pev(id, pev_button)
		
	if(!is_user_bot(id) && (!(buttons & IN_FORWARD)) || (!(buttons & IN_USE)) || ((buttons & IN_DUCK)))
		return false
		
	return true
}
