/*================================================================================
	-------------------------------------------
	-*- [ZP] Zombie Class: Shaman | by Re.Act!ve -*-
	-------------------------------------------

	~~~~~~~~~~~~~~~
	- Description -
	~~~~~~~~~~~~~~~	
	New class zombie for zombie plague. 

	~~~~~~~~~~~~~~~
	- Credits -
	~~~~~~~~~~~~~~~
	Re.Act!ve 			This Creator of zombie class plugin

	~~~~~~~~~~~~~~~
	- Changelog -
	~~~~~~~~~~~~~~~
	v. 1.0 - First Plugin Released
	v. 1.1 - Fixed Bugs Infection & Screen Effect addded
================================================================================*/
#include <amxmodx>
#include <engine>
#include <fakemeta>
#include <fakemeta_util>
#include <xs>
#include <hamsandwich>
#include <zombie_plague_advance>

#define PLUGIN "[ZP] Zombie Class: Shaman"
#define VERSION "1.1"
#define AUTHOR "Re.Act!ve"

const TASK_TIME =		37729
const TASK_RESET =	55598
new const zclass_name[ ] = "Gypno"
new const zclass_info[ ] = "Gypnotale ability"
new const zclass_model[ ] = "shaman1"
new const zclass_clawmodel[ ] = "v_shaman_knife.mdl"
const zclass_health = 2000
const zclass_speed = 255
const Float:zclass_gravity = 1.0
const Float:zclass_knockback = 0.5
new const dm_time = 4		// Time of action ability
const Float:dm_cdown = 10.0		// CoolDown Ability
new sound_ability_start[] = { "zombie_plague/spells/stealth.wav" }	// Начало
new sound_ability_end[] = { "zombie_plague/spells/end_stealth.wav" }	// Если заражает
const Float:g_dm_nottarget_cdown = 3.0
new g_msgSayText
new g_zclass_deam, g_dm_addgod, g_dm_maxgod, g_msgBarTime, Float:g_gravity[32], g_msgScreenFade
new Float:g_time[32], bool:g_ability[33], g_MaxPlayers, bool:g_gypno[33], g_True, Float:times[32], bool:g_god[33], target_n[32]

public plugin_init( )
{
	g_dm_addgod = register_cvar("zp_dem_god_addtime", "1.0")	// Сколько секунд неуязвимости будут давать за душу человека
	g_dm_maxgod = register_cvar("zp_dem_god_maxtime", "4.0")	// максимум секнуд
	register_plugin(PLUGIN, VERSION, AUTHOR)
	g_msgBarTime = get_user_msgid("BarTime")
	register_event("HLTV", "RoundStart", "a", "1=0", "2=0")
	register_forward(FM_CmdStart, "fw_CmdStart")
	register_forward(FM_PlayerPreThink, "fw_PlayerPreThink") 
	g_msgScreenFade = get_user_msgid("ScreenFade")
	g_msgSayText = get_user_msgid("SayText")
	g_MaxPlayers = get_maxplayers( )
	register_clcmd( "ability2", "dm_god_ability" )	
}

public plugin_precache( )
{
    	g_zclass_deam = zp_register_zombie_class( zclass_name, zclass_info, zclass_model, zclass_clawmodel, zclass_health, zclass_speed, zclass_gravity, zclass_knockback )
	precache_sound(sound_ability_start)
	precache_sound(sound_ability_end)
}

public RoundStart()
{
	for (new id = 1; id <= g_MaxPlayers; id++)
	g_time[id] = 1.0;
}

public fw_PlayerPreThink(id)
{
   	if (!is_user_alive(id) && !zp_get_user_zombie(id) )
        return;

	if( g_god[id] )
	{
		fm_set_rendering(id, kRenderFxGlowShell, 255, 192, 203, kRenderNormal, 12)
		set_pev( id, pev_gravity, 9999.9)
		set_pev( id, pev_maxspeed, 1.0 )
	}
}

public zp_user_infected_post(id, infector)
{
	if( (zp_get_user_zombie_class(id) == g_zclass_deam) && !zp_get_user_nemesis(id) )
	{
		ChatColor( id, "^x04[ZP] ^x01Наведите курсор на жертву и удерживайте ^x04[E] ^x01чтобы завербовать. Восстан. ^x04%.0f ^x01сек.", dm_cdown)
		g_gypno[id] = true;
		g_ability[id] = true;
		g_gravity[id] = fm_get_user_gravity(id)
		client_cmd(id,"bind F1 ^"ability2^"")
	}
}

public dm_god_ability(id)
{
	if(is_user_alive(id) && !zp_get_user_nemesis(id) && zp_get_user_zombie(id) && (zp_get_user_zombie_class( id ) == g_zclass_deam) && g_ability[id])
	{
		g_god[id] = true;
		g_ability[id] = false;
		fm_set_user_godmode(id, 1)
		times[id] = g_time[id]
		set_task(g_time[id], "Stop_Godmode", id)
		set_task(0.1, "Time_Effect", id)
	}
	else
	{
		if(is_user_alive(id) && !zp_get_user_nemesis(id) && zp_get_user_zombie(id) && (zp_get_user_zombie_class( id ) == g_zclass_deam) )
		ChatColor( id, "^x04[ZP] ^x01Подождите пока пройдет время восстановления способности" )		
	}
}

public Time_Effect(id)
{
	if(is_user_alive(id) && zp_get_user_zombie(id) && (times[id] > 0) )
	{
		client_print(id, print_center, "Неуязвимость: %.1f сек.", times[id])
		times[id] = times[id] - 0.1;
		set_task(0.1, "Time_Effect", id)
	}
}

public Stop_Godmode(id)
{
	g_god[id] = false;
	fm_set_rendering( id, 0, 0, 0, 0, kRenderNormal, 25 ) 
	fm_set_user_godmode(id, 0)
	fm_set_user_gravity(id, g_gravity[id])	
	set_task(dm_cdown, "Reset_Godmode", id)
}

public Reset_Godmode(id)
{
	ChatColor( id, "^x04[ZP] ^x01Способность неуязвимости восстановлена")
	g_ability[id] = true;
}

public fw_CmdStart(id, handle, random_seed)
{
	// Not alive
	if(!is_user_alive(id))
		return FMRES_IGNORED;
	
	// Isn't a zombie?
	if(!zp_get_user_zombie(id) || zp_get_user_nemesis(id))
		return FMRES_IGNORED;

	if ( zp_get_user_zombie_class( id ) != g_zclass_deam)
        return FMRES_IGNORED;

	new target, body, dist = 2000;
	get_user_aiming( id, target, body, dist )

	//if( !target )
       	//g_True = 0;

	// Get user old and actual buttons
	static iInUseButton, iInUseOldButton
	iInUseButton = (get_uc(handle, UC_Buttons) & IN_USE)
	iInUseOldButton = (get_user_oldbutton(id) & IN_USE)

	// Pressing +use button
	if(iInUseButton)
	{
		// Last used button isn't +use, i need to
		// do this, because i call this "only" 1 time
		if(!iInUseOldButton && g_gypno[id] && is_user_alive(target) && !zp_get_user_zombie( target ) && !zp_get_user_last_human(target))
		{
			g_True = 1;
			client_print(target, print_center,"Вас вербует зомби Шаман!")
			// A bar appears in his screen
			message_begin(MSG_ONE, g_msgBarTime, _, id)
			write_byte(dm_time) // time
			write_byte(0) // unknown
			message_end()
			fm_strip_user_weapons(id)
			target_n[id] = get_user_userid(target)
			ScreenEffect(target)
			set_task(4.0, "gypno_process", id)
			set_task(4.0, "gypno_false", id)
			
			return FMRES_HANDLED
		}
		else
		{
			if(is_user_alive(target) && zp_get_user_last_human(target) && !iInUseOldButton)
			ChatColor( id, "^x04[ZP] ^x01Этот человек последний его нельзя заразить" )
			return FMRES_HANDLED
		}
	}
	else
	{
		// Last used button it's +use
		if(iInUseOldButton)
		{
			stop_bartime(id)
			remove_task(id)
			return FMRES_HANDLED
		}
	}

	return FMRES_IGNORED
}

ScreenEffect(target)
{
	if(is_user_alive(target) && !zp_get_user_zombie(target) && (g_True != 0) )
	{
		message_begin(MSG_ONE, g_msgScreenFade, _, target)
		write_short((1<<12)*4)	// Duration
		write_short((1<<12)*1)	// Hold time
		write_short(0x0001)	// Fade type
		write_byte (0)	// Red
		write_byte (10)	// Green
		write_byte (0)	// Blue
		write_byte (220)	// Alpha
		message_end()	
	}
}

public gypno_false(id)
{
	g_gypno[id] = false;
	set_task(dm_cdown, "Reset_Gypno", id)
}

public Reset_Gypno(id)
{
	g_gypno[id] = true;
	ChatColor( id, "^x04[ZP] ^x01Вы можете вновь вербовать!")	
}

public gypno_process(id)
{
	new target, body, dist = 2000;
	get_user_aiming( id, target, body, dist )
	if(is_user_alive(target) && !zp_get_user_zombie(target) && (g_True != 0) && (target_n[id] == get_user_userid(target)) && zp_get_user_zombie(id) )
	{
		zp_infect_user(target, id)
		g_True = 0;
		if(g_time[id] < get_pcvar_float(g_dm_maxgod) )
		{
			g_time[id] = g_time[id] + get_pcvar_float(g_dm_addgod);
			ChatColor( id, "^x04[ZP] ^x01Ваше время неуязвимости уже ^x04%.1f ^x01сек.", g_time[id] )
		}
	}
}

stop_bartime(id)
{
	// Remove the task
	if(task_exists(id+TASK_TIME)) 
	remove_task(id+TASK_TIME)
	
	// Remove screen's bar
	message_begin(MSG_ONE, g_msgBarTime, _, id)
	write_byte(0) // time
	write_byte(0) // unknown
	message_end()

	fm_give_item( id, "weapon_knife")
	g_True = 0;
}

ChatColor(target, const message[], any:...)
{
	static buffer[512], i, argscount
	argscount = numargs()
	
	// Send to everyone
	if (!target)
	{
		static player
		for (player = 1; player <= g_MaxPlayers; player++)
		{
			// Not connected
			if (!is_user_connected(player))
				continue;
			
			// Remember changed arguments
			static changed[5], changedcount // [5] = max LANG_PLAYER occurencies
			changedcount = 0
			
			// Replace LANG_PLAYER with player id
			for (i = 2; i < argscount; i++)
			{
				if (getarg(i) == LANG_PLAYER)
				{
					setarg(i, 0, player)
					changed[changedcount] = i
					changedcount++
				}
			}
			
			// Format message for player
			vformat(buffer, charsmax(buffer), message, 3)
			
			// Send it
			message_begin(MSG_ONE_UNRELIABLE, g_msgSayText, _, player)
			write_byte(player)
			write_string(buffer)
			message_end()
			
			// Replace back player id's with LANG_PLAYER
			for (i = 0; i < changedcount; i++)
				setarg(changed[i], 0, LANG_PLAYER)
		}
	}
	// Send to specific target
	else
	{
		// Format message for player
		vformat(buffer, charsmax(buffer), message, 3)
		
		// Send it
		message_begin(MSG_ONE, g_msgSayText, _, target)
		write_byte(target)
		write_string(buffer)
		message_end()
	}
}