Zombie Class Pack

Descarcari si discutii despre diverse resurse din Counter-Strike.

Moderators: Moderatori, Moderatori ajutători

Locked
User avatar
Rainq
Fost administrator
Fost administrator
Posts: 381
Joined: Mon Jan 18, 2021 7:25 am
Status: Citesc forumul TheXForce.RO...!
Detinator Steam: Da
SteamID: mrainq
Gaming experience: Nu spun..
Reputatie: Fost administrator
Nume anterior: Light
Fost detinator zm.thexforce.ro
Fost detinator dr.thexforce.ro
Location: Bucureşti
Has thanked: 2 times
Been thanked: 1 time
Contact:

Zombie Class Pack

Post by Rainq »

Am un mic pack de zombie class cso asa ca am decis sa-l impartasesc si cu voi,poate pe unii dintre voi va ajuta acest pack,e luat de pe internet oricum de pe site-uri rusesti insa am zis pentru cei ce nu intra pe alte site-uri in afara de cele din ro ,am zis sa pun si aici acest pack.
Mai jos o sa va las imagini cu pack-ul,majoritatea au .sma dar unele nu au .sma

Pack: Image

Part1: Image
Part2: Image
Part3: Image
Part4: Image
Part5: Image



aici sunt zombi din l4d2 si inca cativa,ii traduceti voi din rusa in romana https://www.mediafire.com/file/m41t8ng6 ... M.rar/file
Last edited by [M]Maasym. on Sat Jun 25, 2022 7:30 pm, edited 1 time in total.
Reason: Link download editat
Image
User avatar
Rainq
Fost administrator
Fost administrator
Posts: 381
Joined: Mon Jan 18, 2021 7:25 am
Status: Citesc forumul TheXForce.RO...!
Detinator Steam: Da
SteamID: mrainq
Gaming experience: Nu spun..
Reputatie: Fost administrator
Nume anterior: Light
Fost detinator zm.thexforce.ro
Fost detinator dr.thexforce.ro
Location: Bucureşti
Has thanked: 2 times
Been thanked: 1 time
Contact:

Classe ZM CSO

Post by Rainq »

cso_class_boss_demon.sma

Code: Select all

#include <amxmodx>
#include <engine>
#include <fakemeta>
#include <zombieplague>

new const PLUGIN[]  = "[ZP] CROW ZOMBIE";
new const VERSION[] = "1.0";
new const AUTHOR[]  = "v3x+Roadrage";

new g_zclass_crow
new bool:has_jp[33];

new const CVAR_JP_SPEED[]  = "jp_speed";

// Crow Zombie Atributes
new const zclass_name[] = { "Демон" } // name
new const zclass_info[] = { "\y|Летает| \r[BOSS]" } // description
new const zclass_model[] = { "boss_demon" } // model
new const zclass_clawmodel[] = { "v_demon.mdl" } // claw model
const zclass_health = 3500 // health
const zclass_speed = 270 // speed
const Float:zclass_gravity = 0.6 // gravity
const Float:zclass_knockback = 1.5 // knockback

public plugin_init()
{
	register_plugin(PLUGIN , VERSION , AUTHOR);
	register_cvar(CVAR_JP_SPEED    , "280");
}

public plugin_precache()
{
	g_zclass_crow = zp_register_zombie_class(zclass_name, zclass_info, zclass_model, zclass_clawmodel, zclass_health, zclass_speed, zclass_gravity, zclass_knockback)
}

public zp_user_infected_pre(id) 
{ 
    if(!(get_user_flags(id) & ADMIN_BAN)) 
	{ 
        if (zp_get_user_next_class(id) == g_zclass_crow) 
		{ 
            zp_set_user_zombie_class(id, 0) 
            client_print(id, print_center, "Данный зомби класс только для Боссов!") 
            client_print(id, print_chat, "Данный зомби класс только для Боссов. Ваш зомби изменен обратно!") 
        }     
    } 
}  

public client_PreThink(id) 
{
	if(!is_user_alive(id) || !zp_get_user_zombie(id)) return PLUGIN_CONTINUE
	if(zp_get_user_zombie_class(id) != g_zclass_crow) return PLUGIN_CONTINUE
	
	new Float:fAim[3] , Float:fVelocity[3];
	VelocityByAim(id , get_cvar_num(CVAR_JP_SPEED) , fAim);
	
	if(!(get_user_button(id) & IN_JUMP))
	{
		fVelocity[0] = fAim[0];
		fVelocity[1] = fAim[1];
		fVelocity[2] = fAim[2];
		
		set_user_velocity(id , fVelocity);
		fm_set_rendering(id, kRenderFxGlowShell, 255, 0, 0, kRenderNormal, 16);
	}
	return PLUGIN_CONTINUE;
}

// User Infected forward
public zp_user_infected_post(id, infector)
{		
	if (zp_get_user_zombie_class(id) == g_zclass_crow)
	{
		has_jp[id] = true
	}	
}

// Set entity's rendering type (from fakemeta_util)
stock fm_set_rendering(entity, fx = kRenderFxNone, r = 255, g = 255, b = 255, render = kRenderNormal, amount = 16)
{
	static Float:color[3]
	color[0] = float(r)
	color[1] = float(g)
	color[2] = float(b)
	
	set_pev(entity, pev_renderfx, fx)
	set_pev(entity, pev_rendercolor, color)
	set_pev(entity, pev_rendermode, render)
	set_pev(entity, pev_renderamt, float(amount))
}
cso_class_deimos.sma

Code: Select all

#pragma tabsize 0
#include <amxmodx>
#include <amxmisc>
#include <fakemeta>
#include <engine>
#include <cstrike>
#include <hamsandwich>
#include <zombieplague>

#define PLUGIN "Zombie Class Deimos"
#define VERSION "1.2.3"
#define AUTHOR "NST Team / Zombie-rus"

new spr_skill[] = "g_tentacle"
new const light_classname[] = "nst_deimos_skill"

new sprites_exp_index, sprites_trail_index

new g_wait[33], g_check[33], g_useskill[33], g_msgStatusIcon, g_zclass_deimos, g_msgScreenFade, g_msgScreenShake
new g_CurWeapon[33], g_bombmodelwpn[64]

native zp_get_user_level(id)

const WPN_NOT_DROP = ((1<<2)|(1<<CSW_HEGRENADE)|(1<<CSW_SMOKEGRENADE)|(1<<CSW_FLASHBANG)|(1<<CSW_KNIFE)|(1<<CSW_C4))
enum (+= 100)
{
	TASK_WAIT = 2000,
	TASK_ATTACK,
	TASK_BOT_USE_SKILL,
	TASK_USE_SKILL
}
// IDs inside tasks
#define ID_WAIT (taskid - TASK_WAIT)
#define ID_ATTACK (taskid - TASK_ATTACK)
#define ID_BOT_USE_SKILL (taskid - TASK_BOT_USE_SKILL)
#define ID_USE_SKILL (taskid - TASK_USE_SKILL)

const m_flTimeWeaponIdle = 48
const m_flNextAttack = 83

new const sprites_exp[] = "sprites/deimosexp.spr"
new const sprites_trail[] = "sprites/trail.spr"
new const sound_skill_start[] = "zombie_plague/deimos_skill_start.wav"
new const sound_skill_hit[] = "zombie_plague/deimos_skill_hit.wav"
const skill_dmg = 0
const skill_anim = 11
const Float:skill_time_wait = 12.0

new const zclass_name[] = { "Деймос" }
new const zclass_info[] = { "\y|Жало G| \r[3 LVL]" }
new const zclass_model[] = { "zombie_deimos_imp" }
new const zclass_clawmodel[] = { "v_knife_stonedeimos.mdl" }
const zclass_health = 4700
const zclass_speed = 240
const Float:zclass_gravity = 1.0
const Float:zclass_knockback = 1.0

#define OFFSET_MODELINDEX 491
#define OFFSET_LINUX 5 

new index, defaultindex

new const WeaponNames[][] =
{
		"", "weapon_p228", "", "weapon_scout", "weapon_hegrenade", "weapon_xm1014", "weapon_c4", "weapon_mac10",
		"weapon_aug", "weapon_smokegrenade", "weapon_elite", "weapon_fiveseven", "weapon_ump45", "weapon_sg550",
		"weapon_galil", "weapon_famas", "weapon_usp", "weapon_glock18", "weapon_awp", "weapon_mp5navy", "weapon_m249",
		"weapon_m3", "weapon_m4a1", "weapon_tmp", "weapon_g3sg1", "weapon_flashbang", "weapon_deagle", "weapon_sg552",
		"weapon_ak47", "weapon_knife", "weapon_p90"
}

const FFADE_IN = 		0x0000

public plugin_init()
{
	register_plugin(PLUGIN, VERSION, AUTHOR)
	
	// msg
	g_msgStatusIcon = get_user_msgid("StatusIcon")
	
	// Events
	register_logevent("logevent_round_start",2, "1=Round_Start")
	register_event("HLTV", "event_round_start", "a", "1=0", "2=0")
	register_event("DeathMsg", "Death", "a")
	register_event("CurWeapon", "Event_CurrentWeapon", "be", "1=1")

	for (new i = 1; i < sizeof WeaponNames; i++)
	if (WeaponNames[i][0]) RegisterHam(Ham_Item_Deploy, WeaponNames[i], "fw_Weapon_Deploy_Post", 1)
	
	// FM Forwards
	register_forward(FM_CmdStart, "fw_CmdStart")
	register_forward(FM_Touch, "fw_Touch")

	// Cmd
	register_concmd("drop", "use_skill")
}

public zp_user_infected_pre(id) 
{
	if (zp_get_user_next_class(id) == g_zclass_deimos)
	{
		if(zp_get_user_level(id) < 3)
		{
		    zp_set_user_zombie_class(id, 0)
			client_print(id, print_chat, "Вы не достигли 3 уровня!")
		}
		else
			zp_set_user_zombie_class(id, g_zclass_deimos)
	}
}

public plugin_precache()
{
	formatex(g_bombmodelwpn, charsmax(g_bombmodelwpn), "models/zombie_plague/v_zombibomb_stonedeimos.mdl")
	
	engfunc(EngFunc_PrecacheModel, g_bombmodelwpn)
	
	g_zclass_deimos = zp_register_zombie_class(zclass_name, zclass_info, zclass_model, zclass_clawmodel, zclass_health, zclass_speed, zclass_gravity, zclass_knockback)
	
	sprites_exp_index = precache_model(sprites_exp)
	sprites_trail_index = precache_model(sprites_trail)
	precache_sound(sound_skill_start)
	precache_sound(sound_skill_hit)
	
	index = precache_model("models/player/zombie_deimos_imp/zombie_deimos_imp.mdl")
    defaultindex = precache_model("models/player.mdl")
}

public Event_CurrentWeapon(id) g_CurWeapon[id] = read_data(2)

public event_round_start()
{
	for (new id=1; id<33; id++)
	{
		if (!is_user_connected(id)) continue;
		
		reset_value_player(id)
		StatusIcon(id, spr_skill, 0)
	}
}

public zp_user_infected_post(id, infector)
{
    set_wpnmodel(id)
	fm_set_user_model_index(id, index)
}

public zp_user_humanized_post(id, survivor)
{
	fm_set_user_model_index(id, defaultindex)
}

public logevent_round_start()
{
	for (new id=1; id<33; id++)
	{
		if (!is_user_connected(id)) continue;
		if (is_user_bot(id))
		{
			if (task_exists(id+TASK_BOT_USE_SKILL)) remove_task(id+TASK_BOT_USE_SKILL)
			set_task(float(random_num(5,15)), "bot_use_skill", id+TASK_BOT_USE_SKILL)
		}
	}
}

public Death()
{
	new victim = read_data(2) 
	StatusIcon(victim, spr_skill, 0)
	reset_value_player(victim)
}

public fw_Weapon_Deploy_Post(weapon_ent)
{
	static id; id = get_pdata_cbase(weapon_ent, 41, 4)

	static weaponid ; weaponid = cs_get_weapon_id(weapon_ent)

	g_CurWeapon[id] = weaponid
	
	replace_weapon_models(id, weaponid)
}

public client_connect(id)
{
	reset_value_player(id)
}

public client_disconnect(id)
{
	reset_value_player(id)
}

reset_value_player(id)
{
	if (task_exists(id+TASK_WAIT)) remove_task(id+TASK_WAIT)
	if (task_exists(id+TASK_BOT_USE_SKILL)) remove_task(id+TASK_BOT_USE_SKILL)

	g_wait[id] = 0
	g_check[id] = 0
	g_useskill[id] = 0
}

// bot use skill

public bot_use_skill(taskid)
{
	new id = ID_BOT_USE_SKILL
	if (!is_user_bot(id)) return;

	use_skill(id)
	if (task_exists(taskid)) remove_task(taskid)
	set_task(float(random_num(5,15)), "bot_use_skill", id+TASK_BOT_USE_SKILL)
}

public use_skill(id)
{
	if (!is_user_alive(id)) return PLUGIN_CONTINUE
	
	new health = get_user_health(id) - skill_dmg
	if ((zp_get_user_zombie_class(id) == g_zclass_deimos) && (zp_get_user_zombie(id)) && (!g_wait[id]) && (health>0) && (get_user_weapon(id)==CSW_KNIFE))
	{
		g_useskill[id] = 1
		
		// set health
		fm_set_user_health(id, health)
		
		// set time wait
		new Float:timewait = skill_time_wait
		
		g_wait[id] = 1
		if (task_exists(id+TASK_WAIT)) remove_task(id+TASK_WAIT)
		set_task(timewait, "RemoveWait", id+TASK_WAIT)
		return PLUGIN_HANDLED
	}
	
	return PLUGIN_CONTINUE
}

public task_use_skill(taskid)
{
	new id = ID_USE_SKILL
	
	// play anim & sound
	play_weapon_anim(id, 8)
	set_weapons_timeidle(id, skill_time_wait)
	set_player_nextattack(id, 0.5)
	PlayEmitSound(id, sound_skill_start)
	entity_set_int(id, EV_INT_sequence, skill_anim)
	
	// attack
	if (task_exists(id+TASK_ATTACK)) remove_task(id+TASK_ATTACK)
	set_task(0.5, "launch_light", id+TASK_ATTACK)
}

public launch_light(taskid)
{
	new id = ID_ATTACK
	if (task_exists(id+TASK_ATTACK)) remove_task(id+TASK_ATTACK)
	
	if (!is_user_alive(id)) return;
	
	// check
	new Float: fOrigin[3], Float:fAngle[3],Float: fVelocity[3]
	pev(id, pev_origin, fOrigin)
	pev(id, pev_view_ofs, fAngle)
	fm_velocity_by_aim(id, 2.0, fVelocity, fAngle)
	fAngle[0] *= -1.0
	
	// create ent
	new ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
	set_pev(ent, pev_classname, light_classname)
	engfunc(EngFunc_SetModel, ent, "models/w_hegrenade.mdl")
	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(ent, pev_movetype, MOVETYPE_BOUNCE)
	set_pev(ent, pev_gravity, 0.01)
	fVelocity[0] *= 1000
	fVelocity[1] *= 1000
	fVelocity[2] *= 1000
	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)						//store the enitty id
	
	// invisible ent
	fm_set_rendering(ent, kRenderFxGlowShell, 0, 0, 0, kRenderTransAlpha, 0)
	
	// show trail	
	message_begin( MSG_BROADCAST, SVC_TEMPENTITY )
	write_byte(TE_BEAMFOLLOW)
	write_short(ent)				//entity
	write_short(sprites_trail_index)		//model
	write_byte(5)		//10)//life
	write_byte(3)		//5)//width
	write_byte(102)					//r, hegrenade
	write_byte(45)					//g, gas-grenade
	write_byte(145)					//b
	write_byte(200)		//brightness
	message_end()					//move PHS/PVS data sending into here (SEND_ALL, SEND_PVS, SEND_PHS)
	
	//client_print(0, print_chat, "phong")
	return;
}

public fw_Touch(ent, victim)
{
	if (!pev_valid(ent)) return FMRES_IGNORED
	
	new EntClassName[32]
	entity_get_string(ent, EV_SZ_classname, EntClassName, charsmax(EntClassName))
	
	if (equal(EntClassName, light_classname)) 
	{
		light_exp(ent, victim)
		remove_entity(ent)
		return FMRES_IGNORED
	}
	
	return FMRES_IGNORED
}

light_exp(ent, victim)
{
	if (!pev_valid(ent)) return;
	
	// drop current wpn of victim
	new attacker = pev(ent, pev_owner)
	if (is_user_alive(victim) && !zp_get_user_survivor(victim) && (zp_get_user_zombie(attacker) != zp_get_user_zombie(victim)))
	{
		new wpn, wpnname[32]
		wpn = get_user_weapon(victim)
		if( !(WPN_NOT_DROP & (1<<wpn)) && get_weaponname(wpn, wpnname, charsmax(wpnname)) )
		{
			engclient_cmd(victim, "drop", wpnname)
		    
			screen_effects(victim)
		}
	}
	
	// create effect
	static Float:origin[3];
	pev(ent, pev_origin, origin);
	message_begin(MSG_BROADCAST,SVC_TEMPENTITY); 
	write_byte(TE_EXPLOSION); // TE_EXPLOSION
	write_coord(floatround(origin[0])); // origin x
	write_coord(floatround(origin[1])); // origin y
	write_coord(floatround(origin[2])); // origin z
	write_short(sprites_exp_index); // sprites
	write_byte(40); // scale in 0.1's
	write_byte(30); // framerate
	write_byte(14); // flags 
	message_end(); // message end
	
	// play sound exp
	PlayEmitSound(ent, sound_skill_hit)
}

public RemoveWait(taskid)
{
	new id = ID_WAIT
	g_wait[id] = 0
	if (task_exists(taskid)) remove_task(taskid)
}

public fw_CmdStart(id, uc_handle, seed)
{
	if (!is_user_alive(id)) return FMRES_IGNORED
	
	if (zp_get_user_zombie_class(id) == g_zclass_deimos && zp_get_user_zombie(id))
	{
		// show status icon help
		if (g_wait[id] && g_check[id] != 2)
		{
			g_check[id] = 2
			StatusIcon(id, spr_skill, 2)
		}
		else if (!g_wait[id] && g_check[id] != 1)
		{
			g_check[id] = 1
			StatusIcon(id, spr_skill, 1)
		}
		
		// use skill
		if (g_useskill[id])
		{
			set_uc(uc_handle, UC_Buttons, IN_ATTACK2)
			g_useskill[id] = 0
			entity_set_int(id, EV_INT_sequence, skill_anim)
			
			if (task_exists(id+TASK_USE_SKILL)) remove_task(id+TASK_USE_SKILL)
			set_task(0.0, "task_use_skill", id+TASK_USE_SKILL)
		}
	}
	else if (g_check[id])
	{
		// hide status icon
		g_check[id] = 0
		StatusIcon(id, spr_skill, 0)
	}
	
	//client_print(id, print_chat, "[%i]", set_animation(id))
	return FMRES_IGNORED
}

set_wpnmodel(id)
{
	if (!is_user_alive(id)) return;

	new wpn = get_user_weapon(id)

	if (wpn == CSW_HEGRENADE || wpn == CSW_FLASHBANG || wpn == CSW_SMOKEGRENADE)
	{
    set_pev(id, pev_viewmodel2, g_bombmodelwpn)
	}
	
}

PlayEmitSound(id, const sound[])
{
	emit_sound(id, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
}

StatusIcon(id, sprname[], run)
{	
	if (!is_user_connected(id)) return;
	
	message_begin(MSG_ONE, g_msgStatusIcon, {0,0,0}, id);
	write_byte(run); // status (0=hide, 1=show, 2=flash)
	write_string(sprname); // sprite name
	message_end();
}

play_weapon_anim(player, anim)
{
	set_pev(player, pev_weaponanim, anim)
	message_begin(MSG_ONE, SVC_WEAPONANIM, {0, 0, 0}, player)
	write_byte(anim)
	write_byte(pev(player, pev_body))
	message_end()
}

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
}

get_weapon_ent(id, weaponid)
{
	static wname[32], weapon_ent
	get_weaponname(weaponid, wname, charsmax(wname))
	weapon_ent = fm_find_ent_by_owner(-1, wname, id)
	return weapon_ent
}
set_weapons_timeidle(id, Float:timeidle)
{
	new entwpn = get_weapon_ent(id, get_user_weapon(id))
	if (pev_valid(entwpn)) set_pdata_float(entwpn, m_flTimeWeaponIdle, timeidle+3.0, 4)
}
set_player_nextattack(id, Float:nexttime)
{
	set_pdata_float(id, m_flNextAttack, nexttime, 4)
}
// Set player's health (from fakemeta_util)
stock fm_set_user_health(id, health)
{
	(health > 0) ? set_pev(id, pev_health, float(health)) : dllfunc(DLLFunc_ClientKill, id);
}
// Set entity's rendering type (from fakemeta_util)
stock fm_set_rendering(entity, fx = kRenderFxNone, r = 255, g = 255, b = 255, render = kRenderNormal, amount = 16)
{
	static Float:color[3]
	color[0] = float(r)
	color[1] = float(g)
	color[2] = float(b)
	
	set_pev(entity, pev_renderfx, fx)
	set_pev(entity, pev_rendercolor, color)
	set_pev(entity, pev_rendermode, render)
	set_pev(entity, pev_renderamt, float(amount))
}
// Find entity by its owner (from fakemeta_util)
stock fm_find_ent_by_owner(entity, const classname[], owner)
{
	while ((entity = engfunc(EngFunc_FindEntityByString, entity, "classname", classname)) && pev(entity, pev_owner) != owner) { /* keep looping */ }
	return entity;
}

replace_weapon_models(id, weaponid)
{
	if (zp_get_user_zombie_class(id) == g_zclass_deimos && zp_get_user_zombie(id))
	{
		switch(weaponid)
		{
			case CSW_HEGRENADE:
			{
				set_pev(id, pev_viewmodel2, g_bombmodelwpn)
			}
			case CSW_SMOKEGRENADE:
			{
				set_pev(id, pev_viewmodel2, g_bombmodelwpn)
			}
			case CSW_FLASHBANG:
			{
				set_pev(id, pev_viewmodel2, g_bombmodelwpn)
			}
		}
	}
}

screen_effects(victim)
{
	// Screen Fade
	message_begin(MSG_ONE_UNRELIABLE, g_msgScreenFade, _, victim)
	write_short ( 1<<13 ) // Duration
	write_short ( 1<<14 ) // Hold Time
	write_short ( FFADE_IN ) // Fade type
	write_byte ( random_num ( 50, 200 ) ) // Red amount
	write_byte ( random_num ( 50, 200 ) ) // Green amount
	write_byte ( random_num ( 50, 200 ) ) // Blue amount
	write_byte ( random_num ( 50, 200 ) ) // Alpha
	message_end ( )
	// Screen Shake
	message_begin(MSG_ONE_UNRELIABLE, g_msgScreenShake, _, victim)
	write_short ( 0xFFFF ) // Amplitude
	write_short ( 1<<13 ) // Duration
	write_short ( 0xFFFF ) // Frequency
	message_end ( )
}

stock fm_set_user_model_index(id, value)
{
    set_pdata_int(id, OFFSET_MODELINDEX, value, OFFSET_LINUX)
} 
cso_class_energyball.sma

Code: Select all

#include < amxmodx >
#include < fakemeta >
#include < hamsandwich >
#include < xs >
#include < fun >
#include < cstrike > 
#include < engine >
#include < zombieplague >

#define is_valid_player(%1) (1 <= %1 <= maxplayers)

#define PLUGIN_NAME	"[ZP] Class: Energy Ball"
#define PLUGIN_VERSION	"1.2"
#define PLUGIN_AUTHOR	"Jim"

new const sound_hit[ ] = "player/bhit_helmet-1.wav"

const OFFSET_LINUX = 5
const OFFSET_PAINSHOCK = 108 // ConnorMcLeod

#define IsPlayer(%1)    (1 <= %1 <= maxplayers)

new bool:g_has_pain_shock_free[33]

#define ICON_HIDE 0
#define ICON_SHOW 1
#define SUPPORT_BOT_TO_USE
//#define FIRST_ZOMBIE_CANT_USE
#define HAVE_DYNAMIC_LIGHT_EFFECT
//#define WHEN_HITED_DROP_WEAPON
#define WHEN_HITED_CANT_SHOOT
#define WHEN_HITED_CANT_MOVE
#define WHEN_DAMAGE_OVER_HEALTH_INFECT
#define WHEN_DAMAGE_MAKE_FAIL
#define HITED_ZOMBIE_KNOCKBACK

#if defined WHEN_DAMAGE_MAKE_FAIL
#define SUPPORT_CZBOT
#define Damage_Check_Time_Range 2.0
#define Get_Amount_Of_Damage 300.0
#endif

#define Hit_Attack2_Key_Time 0.1
#define Make_EnergyBall_Time 0.1
#define EnergyBall_Deduct_Speed 0
#define Short_Dist_Cant_Shoot 10
const Float:Damage_Survivor_Multiplier = 1.0

#define Task_ID_1 param[0]+5333

#if defined WHEN_HITED_DROP_WEAPON

const PRIMARY_WEAPONS_BIT_SUM = (1<<CSW_SCOUT)|(1<<CSW_XM1014)|(1<<CSW_MAC10)|(1<<CSW_AUG)|(1<<CSW_UMP45)|(1<<CSW_SG550)|(1<<CSW_GALIL)|(1<<CSW_FAMAS)|
	(1<<CSW_AWP)|(1<<CSW_MP5NAVY)|(1<<CSW_M249)|(1<<CSW_M3)|(1<<CSW_M4A1)|(1<<CSW_TMP)|(1<<CSW_G3SG1)|(1<<CSW_SG552)|(1<<CSW_AK47)|(1<<CSW_P90)

const SECONDARY_WEAPONS_BIT_SUM = (1<<CSW_P228)|(1<<CSW_ELITE)|(1<<CSW_FIVESEVEN)|(1<<CSW_USP)|(1<<CSW_GLOCK18)|(1<<CSW_DEAGLE)
#endif

const OFFSET_flNextPrimaryAttack = 46
const OFFSET_flNextSecondaryAttack = 47
const OFFSET_flTimeWeaponIdle = 48

const OFFSET_LINUX_WEAPONS = 4 

new const zclass_name[] = { "Энерджи" }
new const zclass_info[] = { "\y|Стреляет| \r[ADMIN]" }
new const zclass_model[] = { "energy_ball" }
new const zclass_clawmodel[] = {"energy_ball/v_energeball.mdl" }
const zclass_health = 5000
const zclass_speed = 240
const Float:zclass_gravity = 0.80
const Float:zclass_knockback = 0.80

new gCvarDamageMultiplier, gCvarShouldPlaySound


new const EnergyBall_P_Model[] = { "models/zombie_plague/energy_ball/p_snowball.mdl" }
new const EnergyBall_W_Model[] = { "models/zombie_plague/energy_ball/w_snowball.mdl" }
new const EnergyBall_Make_Sound[] = { "zombie_plague/energy_ball/electro4.wav" }
new const EnergyBall_Shoot_Sound[] = { "zombie_plague/energy_ball/gauss2.wav" }
new const EnergyBall_Touch_Sound[][] = { "zombie_plague/energy_ball/ric_conc-1.wav", "zombie_plague/energy_ball/ric_conc-2.wav" } 
new const EnergyBall_Hit_Pain_Sound[] = { "zombie_plague/energy_ball/zompain.wav" } 
new const g_vgrenade[] = { "models/zombie_plague/energy_ball/v_psihoball.mdl" }

new g_zclass_energyball

new i_cooldown_time[33]

new g_shoot_times, g_speed, g_damage, g_cooldown, g_explosion_range, g_effect_time, g_surv_effect_time
new maxplayers, bool:round_end, Float:current_time
new g_msgScreenShake, g_msgScreenFade, g_msgDamage
new g_msgDeathMsg, g_msgScoreAttrib, g_msgScoreInfo
new g_trailSpr, g_shokewaveSpr
new gMsgID

new energyball_num[33]
new check_step[33], bool:step_started[33], Float:step_check_time[33]
new bool:make_energyball[33], bool:have_energyball[33]
new bool:cooldown_started[33], Float:cooldown_over_time[33]
new bool:be_hited[33], Float:be_hit_check_time[33]
new bool:effect_started[33], Float:effect_over_time[33]
new Float:next_play_sound_time[33]
new bool:touched_energyball[33], Float:touch_energyball_time[33]
new g_ent_weaponmodel[33]
new Float:g_abilonecooldown = 15.0 // cooldown time
new g_witch_dmg_multi

#if defined WHEN_DAMAGE_MAKE_FAIL
new Float:get_attack_damage[33], Float:damage_check_time[33]
#endif

#if defined WHEN_DAMAGE_OVER_HEALTH_INFECT
new bool:is_infect_round
#endif

#if defined SUPPORT_BOT_TO_USE
new aim_target[33], Float:aim_check_over_time[33]
#endif

#if defined SUPPORT_CZBOT

new cvar_botquota
new bool:BotHasDebug = false
#endif

public plugin_init()
{
	register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR)
	
	g_shoot_times = register_cvar("zp_zclass_eb_shoottimes", "6")
	g_speed = register_cvar("zp_zclass_eb_speed", "1000")
	g_damage = register_cvar("zp_zclass_eb_damage", "100")
	g_cooldown = register_cvar("zp_zclass_eb_cooldown", "15.0")
	g_explosion_range = register_cvar("zp_zclass_eb_exploderange", "5.0")
	g_effect_time = register_cvar("zp_zclass_eb_effecttime", "5.0")
	g_surv_effect_time = register_cvar("zp_zclass_eb_surveffecttime", "0.1") 
	RegisterHam(Ham_TakeDamage, "player", "fw_TakeDamage_Post", 1)
	
	register_cvar("zp_give_hp_tesla", "100")
	register_cvar("zp_give_hp_tesla_freq", "3.0")
	
	g_witch_dmg_multi = register_cvar( "zp_witch_dmg_multi", "2.0" )
	
	register_dictionary( "zp_zclass_energy_ball.txt" )
	register_event("CurWeapon","handle_gun","be","1=1")
	register_forward(FM_CmdStart, "fw_CmdStart")
	register_forward(FM_PlayerPreThink, "fw_PlayerPreThink")
	register_forward(FM_Touch, "fw_Touch")
	register_forward(FM_StartFrame, "fw_StartFrame")
	RegisterHam( Ham_TakeDamage, "player", "fwww_TakeDamage" )
	RegisterHam( Ham_TakeDamage, "player", "fww_TakeDamage" )
	
	register_event("ResetHUD","NewRound","be")
	register_event("DeathMsg", "Death", "a")
	register_event("HLTV", "event_round_start", "a", "1=0", "2=0")
	register_logevent("logevent_round_end", 2, "1=Round_End")
	register_logevent("roundStart", 2, "1=Round_Start")
	RegisterHam(Ham_Spawn, "player", "player_spawn")

	gCvarDamageMultiplier = register_cvar( "zp_iron_dmg_multiplier", "0.60" )	// ( 1.0: Default Damage | 0.5: Half Damage ) Default: 0.75
	gCvarShouldPlaySound = register_cvar( "zp_iron_play_sound", "0" ) // ( 1: Play sound | 0: Don't play sound ) Default: 1
	
	#if defined WHEN_DAMAGE_MAKE_FAIL
	RegisterHam(Ham_TakeDamage, "player", "fw_TakeDamage")
	#endif
	
	maxplayers = get_maxplayers()
	g_msgScreenShake = get_user_msgid("ScreenShake")
	g_msgScreenFade = get_user_msgid("ScreenFade")
	g_msgDamage = get_user_msgid("Damage")
	g_msgDeathMsg = get_user_msgid("DeathMsg")
	g_msgScoreAttrib = get_user_msgid("ScoreAttrib")
	g_msgScoreInfo = get_user_msgid("ScoreInfo")
	
	gMsgID = get_user_msgid("StatusIcon")
	
	#if defined SUPPORT_CZBOT
	// CZBot support
	cvar_botquota = get_cvar_pointer("bot_quota")
	#endif
  }

public plugin_precache()
{
	precache_model(EnergyBall_P_Model)
	precache_model(EnergyBall_W_Model)
	precache_sound(EnergyBall_Make_Sound)
	precache_sound(EnergyBall_Shoot_Sound)
	precache_model(g_vgrenade)

	for (new i = 0; i < sizeof EnergyBall_Touch_Sound; i++)
		precache_sound(EnergyBall_Touch_Sound[i])
	
	precache_sound(EnergyBall_Hit_Pain_Sound)
	
	g_trailSpr = precache_model("sprites/zbeam4.spr")
	g_shokewaveSpr = precache_model( "sprites/shockwave.spr")

	precache_sound( sound_hit )
	
	g_zclass_energyball = zp_register_zombie_class(zclass_name, zclass_info, zclass_model, zclass_clawmodel, zclass_health, zclass_speed, zclass_gravity, zclass_knockback)
}
public fwww_TakeDamage( victim, inflictor, attacker, Float:damage )
{
	if( !is_valid_player( attacker ) || victim == attacker || !zp_get_user_zombie( victim ) || zp_get_user_zombie_class( victim ) != g_zclass_energyball || zp_get_user_nemesis( victim ) )
		return
		
	SetHamParamFloat( 4, damage * get_pcvar_float( gCvarDamageMultiplier ) )
	
	if( get_pcvar_num( gCvarShouldPlaySound ) == 1 )
	{
		emit_sound( victim, CHAN_STREAM, sound_hit, 1.0, ATTN_NORM, 0, PITCH_HIGH )
	}
}
public handle_gun(id)
{
	new weap = get_user_weapon(id)

	if(weap == CSW_HEGRENADE && zp_get_user_zombie_class(id) == g_zclass_energyball && zp_get_user_zombie(id) && !zp_get_user_nemesis(id))
	{

		entity_set_string(id, EV_SZ_viewmodel, g_vgrenade)	
	}
	if(weap == CSW_FLASHBANG && zp_get_user_zombie_class(id) == g_zclass_energyball && zp_get_user_zombie(id))
	{
		entity_set_string(id, EV_SZ_viewmodel, g_vgrenade)	
	}
	if(weap == CSW_SMOKEGRENADE && zp_get_user_zombie_class(id) == g_zclass_energyball && zp_get_user_zombie(id))
	{
		entity_set_string(id, EV_SZ_viewmodel, g_vgrenade)	
	}

	return PLUGIN_HANDLED
}

public zp_user_infected_post(id, infector)
{
	if (zp_get_user_zombie_class(infector) == g_zclass_energyball)
	{
		if ((energyball_num[infector]) <= get_pcvar_num(g_shoot_times))
		{
			ammo_hud(infector, 0)
			energyball_num[infector] += 1
			ammo_hud(infector, 1)
		}
	}
	if (zp_get_user_zombie_class(id) == g_zclass_energyball && !zp_get_user_nemesis(id))
	{
		ammo_hud(id,1)
		i_cooldown_time[id] = floatround(g_abilonecooldown)
		remove_task(id)
		reset_cvars(id)
		g_has_pain_shock_free[id] = true
	}

	set_task(get_cvar_float("zp_give_hp_tesla_freq"), "AddHP44", id, _, _, "b")
	set_pev(id, pev_body, random_num(0, 1))
}

public fw_TakeDamage_Post(id)
{
	if (!is_user_alive(id) || !zp_get_user_zombie(id))
		return HAM_IGNORED
		
	if (zp_get_user_zombie_class(id) != g_zclass_energyball)
		return HAM_IGNORED
		
	g_has_pain_shock_free[id] = true
		
	set_pdata_float(id, OFFSET_PAINSHOCK, 1.0, OFFSET_LINUX)
	
	return HAM_IGNORED
}
public roundStart()
{
	for (new i = 1; i <= maxplayers; i++)
	{
		i_cooldown_time[i] = floatround(g_abilonecooldown)
		remove_task(i)

	}
}

public AddHP44(id)
{
	if (!is_user_connected(id))
  		return PLUGIN_CONTINUE;

	if (zp_get_user_zombie(id) && !zp_is_survivor_round(  ) ) {
		if (zp_get_user_zombie_class(id) == g_zclass_energyball) {
			new cur_hp2 = get_user_health(id)
			new am_hp2 = get_cvar_num("zp_give_hp_tesla")
			new max_hp2 = zp_get_zombie_maxhealth(id)
	
			if (cur_hp2 < max_hp2) {
			set_user_health(id, cur_hp2 + am_hp2)
			} else {
				return PLUGIN_HANDLED
			}
		} else {
			remove_task(id)
		}
	} else {
		remove_task(id)
	}

	return PLUGIN_CONTINUE
}

public fww_TakeDamage( victim, inflictor, attacker, Float:damage, damagebits )
{
	if( IsPlayer( attacker ) && zp_get_user_zombie( attacker ) && zp_get_user_zombie_class( attacker ) == g_zclass_energyball && !zp_get_user_nemesis( attacker ) )
	{
		SetHamParamFloat( 4, damage * get_pcvar_float( g_witch_dmg_multi ) )
	}
}

public player_spawn(id)
{
	ammo_hud(id,0)
	reset_cvars(id)
}

public fw_CmdStart(id, uc_handle, seed)
{
	if (!is_user_alive(id) || !zp_get_user_zombie(id) || zp_get_user_zombie_class(id) != g_zclass_energyball)
		return FMRES_IGNORED;
	
	if (zp_get_user_nemesis(id))
		return FMRES_IGNORED;
		
	if (zp_is_survivor_round())
		return FMRES_IGNORED;
	
	#if defined FIRST_ZOMBIE_CANT_USE
	if (zp_get_user_first_zombie(id))
		return FMRES_IGNORED;
	#endif
	
	static weap_id
	weap_id = get_user_weapon(id)
	
	if (weap_id != CSW_KNIFE)
	{
		if (make_energyball[id] || have_energyball[id])
		{
			check_step[id] = 1
			step_started[id] = false
			make_energyball[id] = false
			have_energyball[id] = false
			set_user_weapon_attack_time(id, 0.0)
		}
		
		return FMRES_IGNORED;
	}
	
	if (get_pcvar_num(g_shoot_times) != 0 && energyball_num[id] <= 0)
		return FMRES_IGNORED;
	
	if (cooldown_started[id])
		return FMRES_IGNORED;
	
	static button, oldbutton
	button = get_uc(uc_handle, UC_Buttons)
	oldbutton = pev(id, pev_oldbuttons)
	
	#if defined SUPPORT_BOT_TO_USE
	if (is_user_bot(id))
	{
		static target, body
		get_user_aiming(id, target, body)
		if (check_target_valid(target))
		{
			aim_target[id] = target
			
			aim_check_over_time[id] = current_time + 20.0
		}
		else
		{
			aim_target[id] = 0
			
			if (current_time >= aim_check_over_time[id])
			{
				check_step[id] = 1
				step_started[id] = false
				
				if (make_energyball[id] || have_energyball[id])
				{
					make_energyball[id] = false
					have_energyball[id] = false
					set_user_weapon_attack_time(id, 0.0)
				}
			}
		}
		
		switch (check_step[id])
		{
			case 1:
			{
				if (!step_started[id])
				{

					if (aim_target[id])
					{
						step_started[id] = true
						step_check_time[id] = current_time + Hit_Attack2_Key_Time
					}
				}
				else
				{
					if (current_time >= step_check_time[id])
					{
						check_step[id] = 2
						step_started[id] = false
						make_energyball[id] = true
						set_user_weapon_attack_time(id, 0.5)
						SendWeaponAnim(id, 0)
					}
				}
			}
			case 2:
			{
				if (!step_started[id])
				{
					step_started[id] = true
					step_check_time[id] = current_time + Make_EnergyBall_Time
				}
				else
				{
					if (current_time >= step_check_time[id])
					{
						check_step[id] = 3
						step_started[id] = false
						make_energyball[id] = false
						have_energyball[id] = true
						set_user_weapon_attack_time(id, 0.5)
						SendWeaponAnim(id, 0)
					}
				}
			}
			case 3:
			{
				if (aim_target[id])
				{
					if (have_energyball[id])
					{
						check_step[id] = 1
						have_energyball[id] = false
						shoot_energyball(id)
						set_user_weapon_attack_time(id, 0.0)
					}
				}
			}
		}
		
		return FMRES_IGNORED;
	}
	#endif
	
	switch (check_step[id])
	{
		case 1:
		{
			if (button & IN_ATTACK)
			{
				check_step[id] = 1
				step_started[id] = false
			}
			else if (button & IN_ATTACK2)
			{
				if (!step_started[id])
				{
					if (!(oldbutton & IN_ATTACK2))
					{
						step_started[id] = true
						step_check_time[id] = current_time + Hit_Attack2_Key_Time
					}
				}
				else
				{
					if (current_time >= step_check_time[id])
					{
						if (get_pcvar_num(g_shoot_times) != 0)
							//client_print(id, print_chat, "[SERVER] x3 1%d ", energyball_num[id])
						
						check_step[id] = 2
						step_started[id] = false
						make_energyball[id] = true
						set_user_weapon_attack_time(id, 1.0)
						SendWeaponAnim(id, 0)
					}
				}
			}
			else
			{
				step_started[id] = false
			}
		}
		case 2:
		{
			if (button & IN_ATTACK)
			{
				check_step[id] = 1
				step_started[id] = false
				
				if (make_energyball[id])
				{
					client_print(id, print_center, "")
					make_energyball[id] = false
					set_user_weapon_attack_time(id, 0.0)
				}
			}
			else if (button & IN_ATTACK2)
			{
				client_print(id, print_center, "")
				
				if (!step_started[id])
				{
					step_started[id] = true
					step_check_time[id] = current_time + Make_EnergyBall_Time
				}
				else
				{
					if (current_time >= step_check_time[id])
					{
						check_step[id] = 3
						step_started[id] = false
						make_energyball[id] = false
						have_energyball[id] = true
						set_user_weapon_attack_time(id, 1.0)
						SendWeaponAnim(id, 0)
					}
				}
			}
			else
			{
				check_step[id] = 1
				step_started[id] = false
				
				if (make_energyball[id])
				{
					client_print(id, print_center, "")
					make_energyball[id] = false
					set_user_weapon_attack_time(id, 0.0)
				}
			}
		}
		case 3:
		{
			if (button & IN_ATTACK)
			{
				check_step[id] = 1
				
				if (have_energyball[id])
				{
					client_print(id, print_center, "")
					have_energyball[id] = false
					set_user_weapon_attack_time(id, 0.0)
				}
			}
			else if (button & IN_ATTACK2)
			{
				static dist
				dist = get_forward_view_dist(id)
				if (dist < Short_Dist_Cant_Shoot)
					client_print(id, print_chat, "")
				else
					client_print(id, print_chat, "")
			}
			else
			{
				if (have_energyball[id])
				{
					client_print(id, print_center, "")
					check_step[id] = 1
					have_energyball[id] = false
					shoot_energyball(id)
					set_user_weapon_attack_time(id, 0.0)
				}
			}
		}
	}
	
	return FMRES_HANDLED;
}

#if defined SUPPORT_BOT_TO_USE
check_target_valid(target)
{
	if (!(1 <= target <= maxplayers) || !is_user_alive(target) || zp_get_user_zombie(target))
		return 0;
	
	return 1;
}
#endif

set_user_weapon_attack_time(id, Float:next_attack_time)
{
	static weap_id
	weap_id = get_user_weapon(id)
	
	static weap_name[32]
	get_weaponname(weap_id, weap_name, charsmax(weap_name))
	
	static weap_ent
	weap_ent = fm_find_ent_by_owner(-1, weap_name, id)
	
	set_weapon_next_pri_attack(weap_ent, next_attack_time)
	set_weapon_next_sec_attack(weap_ent, next_attack_time)
	
	if (weap_id == CSW_XM1014 || weap_id == CSW_M3)
		set_weapon_idle_time(weap_ent, next_attack_time)
}

public fw_PlayerPreThink(id)
{
	if (!is_user_alive(id))
		return FMRES_IGNORED;
	
	if (zp_get_user_zombie(id))
	{
		if (zp_get_user_zombie_class(id) != g_zclass_energyball)
			return FMRES_IGNORED;
		
		if (zp_get_user_nemesis(id))
			return FMRES_IGNORED;
		
		#if defined FIRST_ZOMBIE_CANT_USE
		if (zp_get_user_first_zombie(id))
			return FMRES_IGNORED;
		#endif
		
		if (get_pcvar_num(g_shoot_times) != 0 && energyball_num[id] <= 0)
			return FMRES_IGNORED;
		
		if (make_energyball[id] || have_energyball[id])
		{
			freeze_user_attack(id)
		}
		
		if (cooldown_started[id])
		{
			if (current_time >= cooldown_over_time[id])
			{
				cooldown_started[id] = false
				ChatColor(id, "!g[ZM] !yСпособность восстановлена")
			}
		}
	}
	else
	{
		if (be_hited[id])
		{
			if (current_time >= be_hit_check_time[id])
			{
				be_hited[id] = false
				effect_started[id] = true
				
				if (zp_get_user_survivor(id))
					effect_over_time[id] = current_time + get_pcvar_float(g_surv_effect_time)
				else
					effect_over_time[id] = current_time + get_pcvar_float(g_effect_time)
			}
		}
		
		if (effect_started[id])
		{
			#if defined WHEN_HITED_CANT_SHOOT
			freeze_user_attack(id)
			#endif
			
			#if defined WHEN_HITED_CANT_MOVE
			if (is_user_on_ground(id))
			{
				set_pev(id, pev_velocity, Float:{0.0,0.0,0.0}) // stop motion
				set_pev(id, pev_maxspeed, 1.0) // prevent from moving
				set_pev(id, pev_gravity, 999999.9) // set really high

			}
			#endif
			fm_set_rendering(id, kRenderFxGlowShell, 255, 0, 255, kRenderNormal, 16)
			
			if (current_time >= effect_over_time[id])
			{
				#if defined WHEN_HITED_CANT_MOVE
				set_pev(id, pev_gravity, get_cvar_float("zp_human_gravity"))

				#endif
				fm_set_rendering(id, 0, 0, 0, 0, kRenderNormal, 25) 
				
				effect_started[id] = false
			}
		}
		
		if (touched_energyball[id])
		{
			if (current_time - touch_energyball_time[id] >= 0.2)
			{
				touched_energyball[id] = false
			}
		}
	}
	
	return FMRES_IGNORED;
}

freeze_user_attack(id)
{
	static weap_id
	weap_id = get_user_weapon(id)
	
	static weap_name[32]
	get_weaponname(weap_id, weap_name, charsmax(weap_name))
	
	static weap_ent
	weap_ent = fm_find_ent_by_owner(-1, weap_name, id)
	
	if (get_weapon_next_pri_attack(weap_ent) <= 0.1)
		set_weapon_next_pri_attack(weap_ent, 1.0)
	
	if (get_weapon_next_sec_attack(weap_ent) <= 0.1)
		set_weapon_next_sec_attack(weap_ent, 1.0)
	
	if (weap_id == CSW_XM1014 || weap_id == CSW_M3)
	{
		if (get_weapon_idle_time(weap_ent) <= 0.1)
			set_weapon_idle_time(weap_ent, 1.0)
	}
}

public fw_Touch(ptr, ptd)
{
	if (!pev_valid(ptr))
		return FMRES_IGNORED;
	
	static classname[32]
	pev(ptr, pev_classname, classname, 31)
	
	if (!equal(classname, "EnergyBall_Ent"))
		return FMRES_IGNORED;
	
	static owner
	owner = pev(ptr, pev_iuser1)
	
	static Float:ent_origin[3]
	pev(ptr, pev_origin, ent_origin)
	
	static sound_index 
	sound_index = random_num(0, sizeof EnergyBall_Touch_Sound -1)
	engfunc(EngFunc_EmitSound, ptr, CHAN_VOICE, EnergyBall_Touch_Sound[sound_index], VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
	
	static ent_speed
	ent_speed = pev(ptr, pev_iuser4) - EnergyBall_Deduct_Speed
	set_pev(ptr, pev_iuser4, ent_speed)
	
	pev(ptd, pev_classname, classname, 31)
	
	if (equal(classname, "EnergyBall_Ent"))
	{
		set_pev(ptr, pev_iuser2, 1)
	}
	else if ((1 <= ptd <= 32) && is_user_alive(ptd) && !touched_energyball[ptd])
	{
		#if !(defined HITED_ZOMBIE_KNOCKBACK)
		if (zp_get_user_zombie(ptd))
			return FMRES_IGNORED;
		#endif
		
		if (round_end)
			return FMRES_IGNORED;
		
		touched_energyball[ptd] = true
		touch_energyball_time[ptd] = current_time
		
		static Float:origin[3], Float:velocity1[3], Float:velocity2[3]
		pev(ptd, pev_origin, origin)
		pev(ptd, pev_velocity, velocity1)
		
		particle_burst_effect(origin)
		
		velocity2[0] = origin[0] - ent_origin[0]
		velocity2[1] = origin[1] - ent_origin[1]
		velocity2[2] = origin[2] - ent_origin[2]
		
		static Float:speed
		speed = vector_length(velocity2)
		
		speed = floatmax(float(ent_speed) - 800.0, 0.0) / (speed > 0.0 ? speed : 1.0)
		
		xs_vec_mul_scalar(velocity2, speed, velocity2)
		xs_vec_sub(velocity2, velocity1, velocity2)
		
		speed = vector_length(velocity2)
		if (speed > 800.0)
			xs_vec_mul_scalar(velocity2, (800.0 / speed), velocity2) 
		
		floatclamp(velocity2[2], -200.0, 800.0)
		
		set_pev(ptd, pev_velocity, velocity2)
		
		if (!zp_get_user_zombie(ptd))
		{
			if (fm_get_user_godmode(ptd) || get_user_godmode(ptd))
				return FMRES_IGNORED;
			
			PlaySound(ptd, EnergyBall_Hit_Pain_Sound)
			screen_shake(ptd, 6, 1, 5)
			screen_fade(ptd, 0.2, 220, 0, 0, 150)
			
			#if defined WHEN_HITED_DROP_WEAPON
			if (!zp_get_user_survivor(ptd))
			{
				static EnergyBall_fly_time
				EnergyBall_fly_time = pev(ptr, pev_iuser3)
				
				if (EnergyBall_fly_time <= 10)
					drop_current_weapon(ptd)
			}
			#endif
			
			static damage
			damage = get_pcvar_num(g_damage)
			
			if (zp_get_user_survivor(ptd))
				damage = floatround(float(damage) * Damage_Survivor_Multiplier)
			
			damage_human_user(owner, ptd, damage, (4.0 /5.0), DMG_BLAST, "EnergyBall")
		}
	}
	
	return FMRES_IGNORED;
}

damage_human_user(attacker, victim, damage, Float:damage_armor_rate, damage_type, weapon[])
{
	new health = get_user_health(victim)
	new armor = get_user_armor(victim)
	
	new damage_armor = floatround(float(damage) * damage_armor_rate)
	
	if (damage_armor > 0 && armor > 0)
	{
		if (armor > damage_armor)
		{
			damage -= damage_armor
			fm_set_user_armor(victim, armor - damage_armor)
		}
		else
		{
			damage -= armor
			fm_set_user_armor(victim, 0)
		}
	}
	
	if (damage > 0)
	{
		if (health > damage)
		{
			set_user_takedamage(victim, damage, damage_type)
			effect_started[victim] = false
			be_hited[victim] = true
			be_hit_check_time[victim] = current_time + 1.0 
		}
		else
		{
			new frags = get_user_frags(attacker)
			
			#if defined WHEN_DAMAGE_OVER_HEALTH_INFECT
			if (is_infect_round && !(zp_get_user_last_human(victim) || zp_get_user_survivor(victim)))
			{
				if (zp_infect_user(victim, 0))
				{
					new weapon_string[64]
					format(weapon_string, charsmax(weapon_string), "%s (Infect)", weapon)
					SendDeathMsg(attacker, victim, 1, weapon_string)
					cs_set_user_deaths(victim, get_user_deaths(victim) + 1)
				}
				else
				{
					set_msg_block(g_msgDeathMsg, BLOCK_SET)
					ExecuteHamB(Ham_Killed, victim, attacker, 0)
					set_msg_block(g_msgDeathMsg, BLOCK_NOT)
					SendDeathMsg(attacker, victim, 0, weapon)
				}
			}
			else
			{
			#endif
			
			set_msg_block(g_msgDeathMsg, BLOCK_SET)
			ExecuteHamB(Ham_Killed, victim, attacker, 0)
			set_msg_block(g_msgDeathMsg, BLOCK_NOT)
			SendDeathMsg(attacker, victim, 0, weapon)
			
			#if defined WHEN_DAMAGE_OVER_HEALTH_INFECT
			}
			#endif
			
			fm_set_user_frags(attacker, frags + 1)
			zp_set_user_ammo_packs(attacker, zp_get_user_ammo_packs(attacker) + 1)
			
			FixDeadAttrib(victim, (is_user_alive(victim) ? 0 : 1))
			Update_ScoreInfo(victim, get_user_frags(victim), get_user_deaths(victim))
			FixDeadAttrib(attacker, (is_user_alive(attacker) ? 0 : 1))
			Update_ScoreInfo(attacker, get_user_frags(attacker), get_user_deaths(attacker))
			
/*
			new k_name[32], v_name[32], k_authid[32], v_authid[32], k_team[10], v_team[10]
			get_user_name(attacker, k_name, charsmax(k_name))
			get_user_team(attacker, k_team, charsmax(k_team))
			get_user_authid(attacker, k_authid, charsmax(k_authid))
			get_user_name(victim, v_name, charsmax(v_name))
			get_user_team(victim, v_team, charsmax(v_team))
			get_user_authid(victim, v_authid, charsmax(v_authid))
			log_message("^"%s<%d><%s><%s>^" killed ^"%s<%d><%s><%s>^" with ^"%s^"", 
			k_name, get_user_userid(attacker), k_authid, k_team, 
	 		v_name, get_user_userid(victim), v_authid, v_team, weapon)
*/
		}
	}
}

public fw_StartFrame()
{
	current_time = get_gametime()
	
	static Float:next_check_time, id
	if (current_time < next_check_time)
		return FMRES_IGNORED;
	else
		next_check_time = current_time + 0.1
	
	#if defined HAVE_DYNAMIC_LIGHT_EFFECT
	static Float:origin[3]
	#endif
	
	for (id = 1; id <= maxplayers; id++)
	{
		if (!is_user_alive(id) || !zp_get_user_zombie(id) || zp_get_user_zombie_class(id) != g_zclass_energyball)
			continue;
		
		if (make_energyball[id])
		{
			#if defined HAVE_DYNAMIC_LIGHT_EFFECT
			pev(id, pev_origin, origin)
			
			create_dynamic_light(origin, 15, 127, 255, 212, 2)
			#endif
			
			if (current_time > next_play_sound_time[id])
			{
				engfunc(EngFunc_EmitSound, id, CHAN_VOICE, EnergyBall_Make_Sound, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
				next_play_sound_time[id] = current_time + 1.0
			}
		}
		else if (have_energyball[id])
		{
			#if defined HAVE_DYNAMIC_LIGHT_EFFECT
			pev(id, pev_origin, origin)
			
			create_dynamic_light(origin, 15, 244, 102, 255, 2)
			#endif
			
			fm_set_weaponmodel_ent(id, EnergyBall_P_Model)
			
			if (pev_valid(g_ent_weaponmodel[id]))
			{
				fm_set_rendering(g_ent_weaponmodel[id], kRenderFxGlowShell, 224, 102, 255, kRenderNormal, 255)
			}
		}
		
		if (!have_energyball[id])
		{
			fm_remove_weaponmodel_ent(id)
		}
	}
	
	return FMRES_IGNORED;
}

#if defined WHEN_DAMAGE_MAKE_FAIL
public fw_TakeDamage(victim, inflictor, attacker, Float:damage, damage_type)
{
	if (victim == attacker || !is_user_connected(attacker))
		return HAM_IGNORED;
	
	if (!zp_get_user_zombie(victim) || zp_get_user_zombie(attacker))
		return HAM_IGNORED;
	
	if (zp_get_user_zombie_class(victim) != g_zclass_energyball || zp_get_user_nemesis(victim))
		return HAM_IGNORED;
	
	
	if (!(damage_type & DMG_BULLET))
		return HAM_IGNORED;
	
	if (!make_energyball[victim] && !have_energyball[victim])
	{
		get_attack_damage[victim] = 0.0
		return HAM_IGNORED;
	}
	
	if (current_time > damage_check_time[victim])
	{
		get_attack_damage[victim] = 0.0
		damage_check_time[victim] = current_time + Damage_Check_Time_Range
	}
	
	get_attack_damage[victim] += damage
	
	if (get_attack_damage[victim] >= Get_Amount_Of_Damage)
	{
		get_attack_damage[victim] = 0.0
		damage_check_time[victim] = current_time + Damage_Check_Time_Range
		
		check_step[victim] = 1
		step_started[victim] = false
		make_energyball[victim] = false
		have_energyball[victim] = false
		//set_user_weapon_attack_time(id, 0.0)
	}
	
	return HAM_IGNORED;
}
#endif

public shoot_energyball(id)
{
	if (!is_user_alive(id) || !zp_get_user_zombie(id) || zp_get_user_zombie_class(id) != g_zclass_energyball)
		return;
	
	new dist = get_forward_view_dist(id)
	if (dist < Short_Dist_Cant_Shoot)	
		return;
	
	SendWeaponAnim(id, 7)
	
	fm_remove_weaponmodel_ent(id)
	
	new Float:origin[3], Float:vector[3]
	pev(id, pev_origin, origin)
	velocity_by_aim(id, 45, vector)
	xs_vec_add(origin, vector, origin)
	
	new Float:angles[3]
	pev(id, pev_angles, angles)
	
	new ent = create_entity_object2("EnergyBall_Ent", SOLID_BBOX, MOVETYPE_BOUNCEMISSILE, 1, EnergyBall_W_Model, Float:{ 20.0, 20.0, 20.0 }, angles, origin)
	if (ent == -1)	return;
	
	new Float:speed = vector_length(vector)
	speed = get_pcvar_float(g_speed) / (speed > 0.0 ? speed : 1.0)
	xs_vec_mul_scalar(vector, speed, vector)
	speed = vector_length(vector)
	set_pev(ent, pev_iuser4, floatround(speed))
	set_pev(ent, pev_iuser3, 0)
	set_pev(ent, pev_iuser2, 0) 
	set_pev(ent, pev_iuser1, id) 
	
	set_pev(ent, pev_velocity, vector)
	fm_set_rendering(ent, kRenderFxGlowShell, 224, 102, 255, kRenderNormal, 255)
	engfunc(EngFunc_EmitSound, id, CHAN_VOICE, EnergyBall_Shoot_Sound, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
	create_beam_follow(ent, 224, 102, 255, 200)
	
	new param[4]
	param[0] = ent
	param[1] = 100
	param[2] = 3
	param[3] = 0
	set_task(1.0, "energyball_fly", Task_ID_1, param, 4)
	
	if (get_pcvar_num(g_shoot_times) != 0)
	{
		ammo_hud(id,0)
		energyball_num[id]--
		ammo_hud(id,1)
		//~ new icon[9], temp
		//~ temp = get_msg_arg_string(2, icon, 8)
		//~ client_print(id, print_chat, "%d", temp)
		//~ if (szIcon == energyball_num[id] + 1) {
		//~ new tmp[9]
		//~ formatex(tmp, 8, "%s%d", icon, energyball_num[id])
		//~ client_print(id, print_chat, "%s", tmp)
		//~ set_msg_arg_string(2, tmp)
		//~ }
		//~ msg_energyball_num(id, 1, energyball_num[id])
		
		if (energyball_num[id] > 0)
			ChatColor(id,  "", energyball_num[id])
		else
			ChatColor(id, "!g[ZM] !yХуй пизда")
	}
	
	cooldown_started[id] = true
	cooldown_over_time[id] = current_time + get_pcvar_float(g_cooldown)
	i_cooldown_time[id] = floatround(g_abilonecooldown)
	set_task(1.0, "ShowHUD", id, _, _, "a",i_cooldown_time[id])
}

public energyball_fly(param[4])
{
	new ent = param[0]
	
	if (!pev_valid(ent))
		return;
	
	if (round_end)
	{
		if (pev_valid(ent))
		{
			//kill_beam(ent)
			engfunc(EngFunc_RemoveEntity, ent)
		}
		
		return;
	}
	
	kill_beam(ent)
	create_beam_follow(ent, 224, 102, 255, 200)
	
	new Float:velocity[3]
	pev(ent, pev_velocity, velocity)
	new Float:speed = vector_length(velocity)
	
	new Float:origin[3]
	pev(ent, pev_origin, origin)
	
	new EnergyBall_fly_time = pev(ent, pev_iuser3)
	set_pev(ent, pev_iuser3, EnergyBall_fly_time + 1)
	
	new touch_EnergyBall = pev(ent, pev_iuser2)
	
	if (is_ent_stuck(ent))
		param[3]++
	else
		param[3] = 0
	
	if (param[1] <= 0 || touch_EnergyBall || param[3] >= 5 || speed <= 20.0)
	{
		set_pev(ent, pev_velocity, { 0.0, 0.0, 0.0 })
		create_explo2(origin)
		create_blast_effect(origin, 224, 102, 255, 200, get_pcvar_float(g_explosion_range))
		
		if (!round_end)
			search_in_range_target(origin)
		
		if (pev_valid(ent))
			engfunc(EngFunc_RemoveEntity, ent)
		
		return;
	}
	
	if (param[2] <= 0)
	{
		new set_speed = pev(ent, pev_iuser4)
		speed = float(set_speed) / (speed > 0.0 ? speed : 1.0)
		xs_vec_mul_scalar(velocity, speed, velocity)
		set_pev(ent, pev_velocity, velocity)
		param[2] = 3
	}
	
	param[2]--
	param[1]--
	
	set_task(0.1, "energyball_fly", Task_ID_1, param, 4)
}

public search_in_range_target(Float:origin[3])
{
	new i, Float:target_origin[3], Float:dist
	for (i = 1; i <= maxplayers; i++)
	{
		if (!is_user_alive(i) || zp_get_user_zombie(i))
			continue;
		
		if (fm_get_user_godmode(i) || get_user_godmode(i))
			continue;
		
		pev(i, pev_origin, target_origin)
		dist = get_distance_f(origin, target_origin)
		if (dist > get_pcvar_float(g_explosion_range))
			continue;
		
		screen_fade(i, 0.2, 224, 102, 255, 150)
		screen_fade(i, 0.2, 122, 55, 139, 150)
		
		be_hited[i] = true
		be_hit_check_time[i] = current_time
	}
}

public zp_user_humanized_post(id)
{
	fm_remove_weaponmodel_ent(id)
	remove_task(id)
	reset_cvars(id)
	ammo_hud(id, 0)
}

#if defined WHEN_DAMAGE_OVER_HEALTH_INFECT
public zp_round_started(gamemode, id)
{
	is_infect_round = (gamemode == MODE_INFECTION || gamemode == MODE_MULTI)
}
#endif

public logevent_round_end()
{
	round_end = true
}

public client_connect(id)
{
	reset_cvars(id)
	ammo_hud(id,0)
}

public client_disconnect(id)
{
	fm_remove_weaponmodel_ent(id)
	reset_cvars(id)
	ammo_hud(id,0)
}

public NewRound(id)
{
	fm_remove_weaponmodel_ent(id)
	reset_cvars(id)
}

public Death()
{
	new id = read_data(2)
	if (!(1 <= id <= maxplayers))
		return;
	
	fm_remove_weaponmodel_ent(id)
	reset_cvars(id)
}

public event_round_start()
{

	round_end = false
	
	remove_energyball()
	
	#if defined WHEN_DAMAGE_OVER_HEALTH_INFECT
	is_infect_round = false
	#endif

	
}

public reset_cvars(id)
{
	energyball_num[id] = get_pcvar_num(g_shoot_times)
	check_step[id] = 1
	step_started[id] = false
	step_check_time[id] = 0.0
	make_energyball[id] = false
	have_energyball[id] = false
	cooldown_started[id] = false
	cooldown_over_time[id] = 0.0
	be_hited[id] = false
	be_hit_check_time[id] = 0.0
	effect_started[id] = false
	effect_over_time[id] = 0.0
	touched_energyball[id] = false
	touch_energyball_time[id] = 0.0
	g_ent_weaponmodel[id] = 0
}

public remove_energyball()
{
	new ent = fm_find_ent_by_class(-1, "EnergyBall_Ent")
	while(ent)
	{
		engfunc(EngFunc_RemoveEntity, ent)
		ent = fm_find_ent_by_class(ent, "EnergyBall_Ent")
	}
}

stock create_entity_object2(const classname[], solid, movetype, sequence, const model[], Float:size[3], Float:angles[3], Float:origin[3])
{
	// Create entity
	new ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
	if (!pev_valid(ent)) return -1;
	
	// Set entity status
	set_pev(ent, pev_classname, classname)
	set_pev(ent, pev_solid, solid)
	set_pev(ent, pev_movetype, movetype)
	set_pev(ent, pev_sequence, sequence)
	
	// Set entity size
	new Float:half_size[3], Float:mins[3], Float:maxs[3]
	half_size[0] = size[0] / 2.0
	half_size[1] = size[1] / 2.0
	half_size[2] = size[2] / 2.0
	mins[0] = 0.0 - half_size[0]
	mins[1] = 0.0 - half_size[1]
	mins[2] = 0.0 - half_size[2]
	maxs[0] = half_size[0]
	maxs[1] = half_size[1]
	maxs[2] = half_size[2]
	engfunc(EngFunc_SetSize, ent, mins, maxs)
	
	// Set entity angles
	set_pev(ent, pev_angles, angles)
	
	// Set entity model
	if (strlen(model) > 0)
		engfunc(EngFunc_SetModel, ent, model)
	
	// Set entity origin
	set_pev(ent, pev_origin, origin)
	
	return ent;
}

stock get_forward_view_dist(id)
{
	new iOrigin1[3], iOrigin2[3]
	get_user_origin(id, iOrigin1, 0)
	get_user_origin(id, iOrigin2, 3)
	new dist = get_distance(iOrigin1, iOrigin2)
	
	return dist;
}

stock fm_set_rendering(entity, fx = kRenderFxNone, r = 255, g = 255, b = 255, render = kRenderNormal, amount = 16)
{
	static Float:color[3]
	color[0] = float(r)
	color[1] = float(g)
	color[2] = float(b)
	
	set_pev(entity, pev_renderfx, fx)
	set_pev(entity, pev_rendercolor, color)
	set_pev(entity, pev_rendermode, render)
	set_pev(entity, pev_renderamt, float(amount))
}

stock fm_set_user_armor(index, armor)
{
	set_pev(index, pev_armorvalue, float(armor));
	
	return 1;
}

stock fm_set_user_health(index, health)
{
	health > 0 ? set_pev(index, pev_health, float(health)) : dllfunc(DLLFunc_ClientKill, index);
	
	return 1;
}

stock set_user_takedamage(index, damage, damage_type)
{
	new Float:origin[3], iOrigin[3]
	pev(index, pev_origin, origin)
	FVecIVec(origin, iOrigin)
	
	message_begin(MSG_ONE, g_msgDamage, _, index)
	write_byte(21) // damage save
	write_byte(20) // damage take
	write_long(damage_type) // damage type
	write_coord(iOrigin[0]) // position.x
	write_coord(iOrigin[1]) // position.y
	write_coord(iOrigin[2]) // position.z
	message_end()
	
	fm_set_user_health(index, max(get_user_health(index) - damage, 0))
}

stock fm_set_user_frags(index, frags)
{
	set_pev(index, pev_frags, float(frags));
	
	return 1;
}

stock is_user_on_ground(index)
{
	if (pev(index, pev_flags) & FL_ONGROUND)
		return true;
	
	return false;
}

stock is_ent_stuck(ent)
{
	static Float:originF[3]
	pev(ent, pev_origin, originF)
	
	engfunc(EngFunc_TraceHull, originF, originF, 0, HULL_HEAD, ent, 0)
	
	if (get_tr2(0, TR_StartSolid) || get_tr2(0, TR_AllSolid) || !get_tr2(0, TR_InOpen))
		return true;
	
	return false;
}

stock Float:get_weapon_next_pri_attack(entity)
{
	return get_pdata_float(entity, OFFSET_flNextPrimaryAttack, OFFSET_LINUX_WEAPONS)
}

stock set_weapon_next_pri_attack(entity, Float:time)
{
	set_pdata_float(entity, OFFSET_flNextPrimaryAttack, time, OFFSET_LINUX_WEAPONS)
}

stock Float:get_weapon_next_sec_attack(entity)
{
	return get_pdata_float(entity, OFFSET_flNextSecondaryAttack, OFFSET_LINUX_WEAPONS)
}

stock set_weapon_next_sec_attack(entity, Float:time)
{
	set_pdata_float(entity, OFFSET_flNextSecondaryAttack, time, OFFSET_LINUX_WEAPONS)
}

stock Float:get_weapon_idle_time(entity)
{
	return get_pdata_float(entity, OFFSET_flTimeWeaponIdle, OFFSET_LINUX_WEAPONS)
}

stock set_weapon_idle_time(entity, Float:time)
{
	set_pdata_float(entity, OFFSET_flTimeWeaponIdle, time, OFFSET_LINUX_WEAPONS)
}

stock fm_find_ent_by_owner(entity, const classname[], owner)
{
	while ((entity = engfunc(EngFunc_FindEntityByString, entity, "classname", classname)) && (pev(entity, pev_owner) != owner)) {}
	
	return entity;
}

stock fm_find_ent_by_class(index, const classname[])
{
	return engfunc(EngFunc_FindEntityByString, index, "classname", classname) 
}

#if defined WHEN_HITED_DROP_WEAPON
stock drop_current_weapon(id)
{
	static weapon_id, clip, ammo
	weapon_id = get_user_weapon(id, clip, ammo)
	
	if (((1<<weapon_id) & PRIMARY_WEAPONS_BIT_SUM) || ((1<<weapon_id) & SECONDARY_WEAPONS_BIT_SUM))
	{
		static weapon_name[32]
		get_weaponname(weapon_id, weapon_name, sizeof weapon_name - 1)
		engclient_cmd(id, "drop", weapon_name)
	}
}
#endif

stock PlaySound(index, const sound[])
{
	if (equal(sound[strlen(sound)-4], ".mp3"))
		client_cmd(index, "mp3 play ^"sound/%s^"", sound)
	else
		client_cmd(index, "spk ^"%s^"", sound)
}

stock SendWeaponAnim(id, iAnim)
{
	set_pev(id, pev_weaponanim, iAnim)
	
	message_begin(MSG_ONE_UNRELIABLE, SVC_WEAPONANIM, _, id)
	write_byte(iAnim)
	write_byte(pev(id, pev_body))
	message_end()
}

stock SendDeathMsg(attacker, victim, headshot, const weapon[]) // Send Death Message
{
	message_begin(MSG_BROADCAST, g_msgDeathMsg)
	write_byte(attacker) 
	write_byte(victim) 
	write_byte(headshot) 
	write_string(weapon) 
	message_end()
}

stock FixDeadAttrib(id, dead_flag = 0) // Fix Dead Attrib on scoreboard
{
	message_begin(MSG_BROADCAST, g_msgScoreAttrib)
	write_byte(id) 
	write_byte(dead_flag) 
	message_end()
}

stock Update_ScoreInfo(id, frags, deaths)
{
	// Update scoreboard with attacker's info
	message_begin(MSG_BROADCAST, g_msgScoreInfo)
	write_byte(id) 
	write_short(frags) 
	write_short(deaths) 
	write_short(0)
	write_short(get_user_team(id)) 
	message_end()
}

stock screen_shake(id, amplitude = 4, duration = 2, frequency = 10)
{
	message_begin(MSG_ONE_UNRELIABLE, g_msgScreenShake, _, id)
	write_short((1<<12)*amplitude)
	write_short((1<<12)*duration) 
	write_short((1<<12)*frequency) 
	message_end()
}

stock screen_fade(id, Float:time, red, green, blue, alpha)
{
	// Add a blue tint to their screen
	message_begin(MSG_ONE_UNRELIABLE, g_msgScreenFade, _, id)
	write_short((1<<12)*1) 
	write_short(floatround((1<<12)*time)) 
	write_short(0x0000)
	write_byte(red) 
	write_byte(green) 
	write_byte(blue) 
	write_byte(alpha) 
	message_end()
}

stock particle_burst_effect(const Float:originF[3])
{
	// Particle burst
	engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
	write_byte(TE_PARTICLEBURST) // TE id
	engfunc(EngFunc_WriteCoord, originF[0]) 
	engfunc(EngFunc_WriteCoord, originF[1]) 
	engfunc(EngFunc_WriteCoord, originF[2])
	write_short(50)
	write_byte(70)
	write_byte(3)
	message_end()
}

#if defined HAVE_DYNAMIC_LIGHT_EFFECT
stock create_dynamic_light(const Float:originF[3], radius, red, green, blue, life)
{
	// Dynamic light, effect world, minor entity effect
	engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
	write_byte(TE_DLIGHT) // TE id: 27
	engfunc(EngFunc_WriteCoord, originF[0])
	engfunc(EngFunc_WriteCoord, originF[1]) 
	engfunc(EngFunc_WriteCoord, originF[2]) 
	write_byte(radius) 
	write_byte(red) 
	write_byte(green)
	write_byte(blue)
	write_byte(life)
	write_byte(0)
	message_end()
}
#endif

stock create_beam_follow(entity, red, green, blue, brightness)
{
	//Entity add colored trail
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte(TE_BEAMFOLLOW) 
	write_short(entity) 
	write_short(g_trailSpr) 
	write_byte(1) 
	write_byte(10) 
	write_byte(red) 
	write_byte(green)
	write_byte(blue)
	write_byte(brightness)
	message_end()
}

stock create_explo2(const Float:originF[3])
{
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte(TE_EXPLOSION2) 
	engfunc(EngFunc_WriteCoord, originF[0]) 
	engfunc(EngFunc_WriteCoord, originF[1])
	engfunc(EngFunc_WriteCoord, originF[2]) 
	write_byte(1) // starting color
	write_byte(10) // num colors
	message_end()
}

stock create_blast_effect(const Float:originF[3], red, green, blue, brightness, Float:radius)
{
	// Light ring effect
	engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
	write_byte(TE_BEAMCYLINDER) 
	engfunc(EngFunc_WriteCoord, originF[0])
	engfunc(EngFunc_WriteCoord, originF[1]) 
	engfunc(EngFunc_WriteCoord, originF[2]) 
	engfunc(EngFunc_WriteCoord, originF[0]) 
	engfunc(EngFunc_WriteCoord, originF[1]) 
	engfunc(EngFunc_WriteCoord, originF[2] + radius) 
	write_short(g_shokewaveSpr) 
	write_byte(0)
	write_byte(0) 
	write_byte(4) 
	write_byte(60) 
	write_byte(0) 
	write_byte(red) 
	write_byte(green) 
	write_byte(blue)
	write_byte(brightness) 
	write_byte(0)
	message_end()
}

stock kill_beam(entity)
{
	// Kill all beams attached to entity
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte(TE_KILLBEAM) // TE id: 99
	write_short(entity)
	message_end()
}

stock fm_get_user_godmode(index)
{
	new Float:val;
	pev(index, pev_takedamage, val);
	
	return (val == DAMAGE_NO);
}

// Set Weapon Model on Entity
stock fm_set_weaponmodel_ent(id, const weapon_model[])
{
	// Set model on entity or make a new one if unexistant
	if (!pev_valid(g_ent_weaponmodel[id]))
	{
		g_ent_weaponmodel[id] = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
		if (!pev_valid(g_ent_weaponmodel[id])) return;
		
		set_pev(g_ent_weaponmodel[id], pev_classname, "weapon_model")
		set_pev(g_ent_weaponmodel[id], pev_movetype, MOVETYPE_FOLLOW)
		set_pev(g_ent_weaponmodel[id], pev_aiment, id)
		set_pev(g_ent_weaponmodel[id], pev_owner, id)
	}
	
	static model[100]
	
	if (equal(weapon_model, ""))
	{
		static weap_id, weap_name[32]
		weap_id = get_user_weapon(id)
		get_weaponname(weap_id, weap_name, sizeof weap_name - 1)
		formatex(model, sizeof model - 1, "models/p_%s.mdl", weap_name[7])
	}
	else
	{
		copy(model, sizeof model - 1, weapon_model)
	}
	
	engfunc(EngFunc_SetModel, g_ent_weaponmodel[id], model)
}

stock fm_remove_weaponmodel_ent(id)
{
	// Remove "weaponmodel" ent if present
	if (pev_valid(g_ent_weaponmodel[id]))
	{
		engfunc(EngFunc_RemoveEntity, g_ent_weaponmodel[id])
		g_ent_weaponmodel[id] = 0
	}
}

#if defined SUPPORT_CZBOT
public client_putinserver(id)
{
	if (!cvar_botquota || !is_user_bot(id) || BotHasDebug)
		return;
	
	new classname[32]
	pev(id, pev_classname, classname, 31)
	
	if (!equal(classname, "player"))
		set_task(0.1, "_Debug", id)
}
public _Debug(id)
{
	if (!get_pcvar_num(cvar_botquota) || !is_user_connected(id))
		return;
	
	BotHasDebug = true
	RegisterHamFromEntity(Ham_TakeDamage, id, "fw_TakeDamage")
}
#endif

ammo_hud(id, sw)
{

	if(is_user_bot(id)||!is_user_alive(id)||!is_user_connected(id)) 
        	return
        if ( zp_is_survivor_round ( ) ) return ;
	new s_sprite[33]
	format(s_sprite,32,"number_%d",energyball_num[id])
	if(sw)
	{
		message_begin( MSG_ONE, gMsgID, {0,0,0}, id )
		write_byte( ICON_SHOW ) // status
		write_string( s_sprite ) // sprite name
		write_byte( 255 ) // red
		write_byte( 186 ) // green
		write_byte( 0 ) // blue
		message_end()
	}
	else
	{
		message_begin( MSG_ONE, gMsgID, {0,0,0}, id )
		write_byte( ICON_HIDE ) // status
		write_string( s_sprite ) // sprite name
		write_byte( 255 ) // red
		write_byte( 186 ) // green
		write_byte( 0 ) // blue
		message_end()
	}
}

stock set_player_rendering(id, renderfx, red, green, blue, rendermode, renderamt, alive) {
	if (is_user_connected(id) && ((is_user_alive(id) && alive) || !alive)) {
		new Float:rendercolor[3]
		set_pev(id, pev_renderfx, renderfx)
		rendercolor[0] = float(red)
		rendercolor[1] = float(green)
		rendercolor[2] = float(blue)
		set_pev(id, pev_rendercolor, rendercolor)
		set_pev(id, pev_rendermode, rendermode)
		set_pev(id, pev_renderamt, float(renderamt))
	}
}

public zp_user_infected_pre(id) 
{
    if(!(get_user_flags(id) & ADMIN_KICK)) 
	{
        if (zp_get_user_next_class(id) == g_zclass_energyball) 
		{
            zp_set_user_zombie_class(id, 0)
            client_print(id, print_center, "Купи Админа, чтобы взять этот класс!")
            client_print(id, print_chat, "Купи Админа, чтобы взять этот класс!")
        }    
    }
}

stock ChatColor(const id, const input[], any:...)
{
	new count = 1, players[32]
	static msg[191]
	vformat(msg, 190, input, 3)
	
	replace_all(msg, 190, "!g", "^4") // Green Color
	replace_all(msg, 190, "!y", "^1") // Default Color
	replace_all(msg, 190, "!team", "^3") // Team Color
	replace_all(msg, 190, "!team2", "^0") // Team2 Color
	
	if (id) players[0] = id; else get_players(players, count, "ch")
	{
	for (new i = 0; i < count; i++)
	{
		if (is_user_connected(players[i]))
		{
			message_begin(MSG_ONE_UNRELIABLE, get_user_msgid("SayText"), _, players[i])
			write_byte(players[i]);
			write_string(msg);
			message_end();
		}
	}
}
}
cso_class_lilith.sma

Code: Select all

#include <amxmodx>
#include <fakemeta>
#include <fakemeta_util>
#include <hamsandwich>
#include <engine>
#include <fun>

// ZP NATIVE
#include <zombieplague>

#define PLUGIN	"[CSO] LILITH ZOMBIE (Z-NOID) || ZP CLASS"
#define VERSION	"1.0"
#define AUTHOR	"Asep Khairul Anam"
// Teleport Mark
#define TELEPORT_MARK_MODEL		"models/zombie_plague/teleport_zombie_mark.mdl"
#define TELEPORT_MARK_CLASSNAME		"lilith_mark_teleport"

// Teleport Portal
#define TELEPORT_PORTAL_MODEL		"sprites/zombie_plague/ef_teleportzombie.spr"
#define TELEPORT_PORTAL_CLASSNAME	"lilith_portal_teleport"

// Teleport Origin ++
#define TELEPORT_X 			25.0
#define TELEPORT_Z 			15.0

// Zombie Configuration (String)
#define ZOMBIE_NAME			"Лилит"
#define ZOMBIE_INFO			"\y|Телеп.| \r[Прем.]"
#define ZOMBIE_MODEL			"lilith_zombie"
#define ZOMBIE_CLAW_MDL			"v_knife_lilith.mdl"
#define ZOMBIE_BOMB_MDL			"models/zombie_plague/v_bomb_lilith_merah.mdl"

// Zombie Configuration (Value)
#define ZOMBIE_HEALTH			4500
#define ZOMBIE_SPEED			260
#define ZOMBIE_GRAVITY			0.8
#define ZOMBIE_KNOCKBACK		0.8

// Delay Skill Configuration
#define DELAY_SKILL_1			30
#define DELAY_SKILL_2			40

// Task
#define TASK_TELEPORT			10221
#define	TASK_DELAY			10222

new const Float:UnstuckVector[][] =
{
	{0.0, 0.0, 1.0}, {0.0, 0.0, -1.0}, {0.0, 1.0, 0.0}, {0.0, -1.0, 0.0}, {1.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, {-1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, -1.0}, {-1.0, -1.0, 1.0}, {1.0, -1.0, -1.0}, {-1.0, 1.0, -1.0}, {-1.0, -1.0, -1.0},
	{0.0, 0.0, 2.0}, {0.0, 0.0, -2.0}, {0.0, 2.0, 0.0}, {0.0, -2.0, 0.0}, {2.0, 0.0, 0.0}, {-2.0, 0.0, 0.0}, {-2.0, 2.0, 2.0}, {2.0, 2.0, 2.0}, {2.0, -2.0, 2.0}, {2.0, 2.0, -2.0}, {-2.0, -2.0, 2.0}, {2.0, -2.0, -2.0}, {-2.0, 2.0, -2.0}, {-2.0, -2.0, -2.0},
	{0.0, 0.0, 3.0}, {0.0, 0.0, -3.0}, {0.0, 3.0, 0.0}, {0.0, -3.0, 0.0}, {3.0, 0.0, 0.0}, {-3.0, 0.0, 0.0}, {-3.0, 3.0, 3.0}, {3.0, 3.0, 3.0}, {3.0, -3.0, 3.0}, {3.0, 3.0, -3.0}, {-3.0, -3.0, 3.0}, {3.0, -3.0, -3.0}, {-3.0, 3.0, -3.0}, {-3.0, -3.0, -3.0},
	{0.0, 0.0, 4.0}, {0.0, 0.0, -4.0}, {0.0, 4.0, 0.0}, {0.0, -4.0, 0.0}, {4.0, 0.0, 0.0}, {-4.0, 0.0, 0.0}, {-4.0, 4.0, 4.0}, {4.0, 4.0, 4.0}, {4.0, -4.0, 4.0}, {4.0, 4.0, -4.0}, {-4.0, -4.0, 4.0}, {4.0, -4.0, -4.0}, {-4.0, 4.0, -4.0}, {-4.0, -4.0, -4.0},
	{0.0, 0.0, 5.0}, {0.0, 0.0, -5.0}, {0.0, 5.0, 0.0}, {0.0, -5.0, 0.0}, {5.0, 0.0, 0.0}, {-5.0, 0.0, 0.0}, {-5.0, 5.0, 5.0}, {5.0, 5.0, 5.0}, {5.0, -5.0, 5.0}, {5.0, 5.0, -5.0}, {-5.0, -5.0, 5.0}, {5.0, -5.0, -5.0}, {-5.0, 5.0, -5.0}, {-5.0, -5.0, -5.0},
	{0.0, 0.0, 6.0}, {0.0, 0.0, -6.0}, {0.0, 6.0, 0.0}, {0.0, -6.0, 0.0}, {6.0, 0.0, 0.0}, {-6.0, 0.0, 0.0}, {-6.0, 6.0, 6.0}, {6.0, 6.0, 6.0}, {6.0, -6.0, 6.0}, {6.0, 6.0, -6.0}, {-6.0, -6.0, 6.0}, {6.0, -6.0, -6.0}, {-6.0, 6.0, -6.0}, {-6.0, -6.0, -6.0},
	{0.0, 0.0, 7.0}, {0.0, 0.0, -7.0}, {0.0, 7.0, 0.0}, {0.0, -7.0, 0.0}, {7.0, 0.0, 0.0}, {-7.0, 0.0, 0.0}, {-7.0, 7.0, 7.0}, {7.0, 7.0, 7.0}, {7.0, -7.0, 7.0}, {7.0, 7.0, -7.0}, {-7.0, -7.0, 7.0}, {7.0, -7.0, -7.0}, {-7.0, 7.0, -7.0}, {-7.0, -7.0, -7.0},
	{0.0, 0.0, 8.0}, {0.0, 0.0, -8.0}, {0.0, 8.0, 0.0}, {0.0, -8.0, 0.0}, {8.0, 0.0, 0.0}, {-8.0, 0.0, 0.0}, {-8.0, 8.0, 8.0}, {8.0, 8.0, 8.0}, {8.0, -8.0, 8.0}, {8.0, 8.0, -8.0}, {-8.0, -8.0, 8.0}, {8.0, -8.0, -8.0}, {-8.0, 8.0, -8.0}, {-8.0, -8.0, -8.0},
	{0.0, 0.0, 9.0}, {0.0, 0.0, -9.0}, {0.0, 9.0, 0.0}, {0.0, -9.0, 0.0}, {9.0, 0.0, 0.0}, {-9.0, 0.0, 0.0}, {-9.0, 9.0, 9.0}, {9.0, 9.0, 9.0}, {9.0, -9.0, 9.0}, {9.0, 9.0, -9.0}, {-9.0, -9.0, 9.0}, {9.0, -9.0, -9.0}, {-9.0, 9.0, -9.0}, {-9.0, -9.0, -9.0},
	{0.0, 0.0, 10.0}, {0.0, 0.0, -10.0}, {0.0, 10.0, 0.0}, {0.0, -10.0, 0.0}, {10.0, 0.0, 0.0}, {-10.0, 0.0, 0.0}, {-10.0, 10.0, 10.0}, {10.0, 10.0, 10.0}, {10.0, -10.0, 10.0}, {10.0, 10.0, -10.0}, {-10.0, -10.0, 10.0}, {10.0, -10.0, -10.0}, {-10.0, 10.0, -10.0}, {-10.0, -10.0, -10.0},
	{0.0, 0.0, 11.0}, {0.0, 0.0, -11.0}, {0.0, 11.0, 0.0}, {0.0, -11.0, 0.0}, {11.0, 0.0, 0.0}, {-11.0, 0.0, 0.0}, {-11.0, 11.0, 11.0}, {11.0, 11.0, 11.0}, {11.0, -11.0, 11.0}, {11.0, 11.0, -11.0}, {-11.0, -11.0, 11.0}, {11.0, -11.0, -11.0}, {-11.0, 11.0, -11.0}, {-11.0, -11.0, -11.0},
	{0.0, 0.0, 12.0}, {0.0, 0.0, -12.0}, {0.0, 12.0, 0.0}, {0.0, -12.0, 0.0}, {12.0, 0.0, 0.0}, {-12.0, 0.0, 0.0}, {-12.0, 12.0, 12.0}, {12.0, 12.0, 12.0}, {12.0, -12.0, 12.0}, {12.0, 12.0, -12.0}, {-12.0, -12.0, 12.0}, {12.0, -12.0, -12.0}, {-12.0, 12.0, -12.0}, {-12.0, -12.0, -12.0},
	{0.0, 0.0, 13.0}, {0.0, 0.0, -13.0}, {0.0, 13.0, 0.0}, {0.0, -13.0, 0.0}, {13.0, 0.0, 0.0}, {-13.0, 0.0, 0.0}, {-13.0, 13.0, 13.0}, {13.0, 13.0, 13.0}, {13.0, -13.0, 13.0}, {13.0, 13.0, -13.0}, {-13.0, -13.0, 13.0}, {13.0, -13.0, -13.0}, {-13.0, 13.0, -13.0}, {-13.0, -13.0, -13.0},
	{0.0, 0.0, 14.0}, {0.0, 0.0, -14.0}, {0.0, 14.0, 0.0}, {0.0, -14.0, 0.0}, {14.0, 0.0, 0.0}, {-14.0, 0.0, 0.0}, {-14.0, 14.0, 14.0}, {14.0, 14.0, 14.0}, {14.0, -14.0, 14.0}, {14.0, 14.0, -14.0}, {-14.0, -14.0, 14.0}, {14.0, -14.0, -14.0}, {-14.0, 14.0, -14.0}, {-14.0, -14.0, -14.0},
	{0.0, 0.0, 15.0}, {0.0, 0.0, -15.0}, {0.0, 15.0, 0.0}, {0.0, -15.0, 0.0}, {15.0, 0.0, 0.0}, {-15.0, 0.0, 0.0}, {-15.0, 15.0, 15.0}, {15.0, 15.0, 15.0}, {15.0, -15.0, 15.0}, {15.0, 15.0, -15.0}, {-15.0, -15.0, 15.0}, {15.0, -15.0, -15.0}, {-15.0, 15.0, -15.0}, {-15.0, -15.0, -15.0},
	{0.0, 0.0, 16.0}, {0.0, 0.0, -16.0}, {0.0, 16.0, 0.0}, {0.0, -16.0, 0.0}, {16.0, 0.0, 0.0}, {-16.0, 0.0, 0.0}, {-16.0, 16.0, 16.0}, {16.0, 16.0, 16.0}, {16.0, -16.0, 16.0}, {16.0, 16.0, -16.0}, {-16.0, -16.0, 16.0}, {16.0, -16.0, -16.0}, {-16.0, 16.0, -16.0}, {-16.0, -16.0, -16.0},
	{0.0, 0.0, 17.0}, {0.0, 0.0, -17.0}, {0.0, 17.0, 0.0}, {0.0, -17.0, 0.0}, {17.0, 0.0, 0.0}, {-17.0, 0.0, 0.0}, {-17.0, 17.0, 17.0}, {17.0, 17.0, 17.0}, {17.0, -17.0, 17.0}, {17.0, 17.0, -17.0}, {-17.0, -17.0, 17.0}, {17.0, -17.0, -17.0}, {-17.0, 17.0, -17.0}, {-17.0, -17.0, -17.0},
	{0.0, 0.0, 18.0}, {0.0, 0.0, -18.0}, {0.0, 18.0, 0.0}, {0.0, -18.0, 0.0}, {18.0, 0.0, 0.0}, {-18.0, 0.0, 0.0}, {-18.0, 18.0, 18.0}, {18.0, 18.0, 18.0}, {18.0, -18.0, 18.0}, {18.0, 18.0, -18.0}, {-18.0, -18.0, 18.0}, {18.0, -18.0, -18.0}, {-18.0, 18.0, -18.0}, {-18.0, -18.0, -18.0},
	{0.0, 0.0, 19.0}, {0.0, 0.0, -19.0}, {0.0, 19.0, 0.0}, {0.0, -19.0, 0.0}, {19.0, 0.0, 0.0}, {-19.0, 0.0, 0.0}, {-19.0, 19.0, 19.0}, {19.0, 19.0, 19.0}, {19.0, -19.0, 19.0}, {19.0, 19.0, -19.0}, {-19.0, -19.0, 19.0}, {19.0, -19.0, -19.0}, {-19.0, 19.0, -19.0}, {-19.0, -19.0, -19.0},
	{0.0, 0.0, 20.0}, {0.0, 0.0, -20.0}, {0.0, 20.0, 0.0}, {0.0, -20.0, 0.0}, {20.0, 0.0, 0.0}, {-20.0, 0.0, 0.0}, {-20.0, 20.0, 20.0}, {20.0, 20.0, 20.0}, {20.0, -20.0, 20.0}, {20.0, 20.0, -20.0}, {-20.0, -20.0, 20.0}, {20.0, -20.0, -20.0}, {-20.0, 20.0, -20.0}, {-20.0, -20.0, -20.0},
	{0.0, 0.0, 21.0}, {0.0, 0.0, -21.0}, {0.0, 21.0, 0.0}, {0.0, -21.0, 0.0}, {21.0, 0.0, 0.0}, {-21.0, 0.0, 0.0}, {-21.0, 21.0, 21.0}, {21.0, 21.0, 21.0}, {21.0, -21.0, 21.0}, {21.0, 21.0, -21.0}, {-21.0, -21.0, 21.0}, {21.0, -21.0, -21.0}, {-21.0, 21.0, -21.0}, {-21.0, -21.0, -21.0},
	{0.0, 0.0, 22.0}, {0.0, 0.0, -22.0}, {0.0, 22.0, 0.0}, {0.0, -22.0, 0.0}, {22.0, 0.0, 0.0}, {-22.0, 0.0, 0.0}, {-22.0, 22.0, 22.0}, {22.0, 22.0, 22.0}, {22.0, -22.0, 22.0}, {22.0, 22.0, -22.0}, {-22.0, -22.0, 22.0}, {22.0, -22.0, -22.0}, {-22.0, 22.0, -22.0}, {-22.0, -22.0, -22.0},
	{0.0, 0.0, 23.0}, {0.0, 0.0, -23.0}, {0.0, 23.0, 0.0}, {0.0, -23.0, 0.0}, {23.0, 0.0, 0.0}, {-23.0, 0.0, 0.0}, {-23.0, 23.0, 23.0}, {23.0, 23.0, 23.0}, {23.0, -23.0, 23.0}, {23.0, 23.0, -23.0}, {-23.0, -23.0, 23.0}, {23.0, -23.0, -23.0}, {-23.0, 23.0, -23.0}, {-23.0, -23.0, -23.0},
	{0.0, 0.0, 24.0}, {0.0, 0.0, -24.0}, {0.0, 24.0, 0.0}, {0.0, -24.0, 0.0}, {24.0, 0.0, 0.0}, {-24.0, 0.0, 0.0}, {-24.0, 24.0, 24.0}, {24.0, 24.0, 24.0}, {24.0, -24.0, 24.0}, {24.0, 24.0, -24.0}, {-24.0, -24.0, 24.0}, {24.0, -24.0, -24.0}, {-24.0, 24.0, -24.0}, {-24.0, -24.0, -24.0},
	{0.0, 0.0, 25.0}, {0.0, 0.0, -25.0}, {0.0, 25.0, 0.0}, {0.0, -25.0, 0.0}, {25.0, 0.0, 0.0}, {-25.0, 0.0, 0.0}, {-25.0, 25.0, 25.0}, {25.0, 25.0, 25.0}, {25.0, -25.0, 25.0}, {25.0, 25.0, -25.0}, {-25.0, -25.0, 25.0}, {25.0, -25.0, -25.0}, {-25.0, 25.0, -25.0}, {-25.0, -25.0, -25.0},
	{0.0, 0.0, 26.0}, {0.0, 0.0, -26.0}, {0.0, 26.0, 0.0}, {0.0, -26.0, 0.0}, {26.0, 0.0, 0.0}, {-26.0, 0.0, 0.0}, {-26.0, 26.0, 26.0}, {26.0, 26.0, 26.0}, {26.0, -26.0, 26.0}, {26.0, 26.0, -26.0}, {-26.0, -26.0, 26.0}, {26.0, -26.0, -26.0}, {-26.0, 26.0, -26.0}, {-26.0, -26.0, -26.0},
	{0.0, 0.0, 27.0}, {0.0, 0.0, -27.0}, {0.0, 27.0, 0.0}, {0.0, -27.0, 0.0}, {27.0, 0.0, 0.0}, {-27.0, 0.0, 0.0}, {-27.0, 27.0, 27.0}, {27.0, 27.0, 27.0}, {27.0, -27.0, 27.0}, {27.0, 27.0, -27.0}, {-27.0, -27.0, 27.0}, {27.0, -27.0, -27.0}, {-27.0, 27.0, -27.0}, {-27.0, -27.0, -27.0},
	{0.0, 0.0, 28.0}, {0.0, 0.0, -28.0}, {0.0, 28.0, 0.0}, {0.0, -28.0, 0.0}, {28.0, 0.0, 0.0}, {-28.0, 0.0, 0.0}, {-28.0, 28.0, 28.0}, {28.0, 28.0, 28.0}, {28.0, -28.0, 28.0}, {28.0, 28.0, -28.0}, {-28.0, -28.0, 28.0}, {28.0, -28.0, -28.0}, {-28.0, 28.0, -28.0}, {-28.0, -28.0, -28.0},
	{0.0, 0.0, 29.0}, {0.0, 0.0, -29.0}, {0.0, 29.0, 0.0}, {0.0, -29.0, 0.0}, {29.0, 0.0, 0.0}, {-29.0, 0.0, 0.0}, {-29.0, 29.0, 29.0}, {29.0, 29.0, 29.0}, {29.0, -29.0, 29.0}, {29.0, 29.0, -29.0}, {-29.0, -29.0, 29.0}, {29.0, -29.0, -29.0}, {-29.0, 29.0, -29.0}, {-29.0, -29.0, -29.0},
	{0.0, 0.0, 30.0}, {0.0, 0.0, -30.0}, {0.0, 30.0, 0.0}, {0.0, -30.0, 0.0}, {30.0, 0.0, 0.0}, {-30.0, 0.0, 0.0}, {-30.0, 30.0, 30.0}, {30.0, 30.0, 30.0}, {30.0, -30.0, 30.0}, {30.0, 30.0, -30.0}, {-30.0, -30.0, 30.0}, {30.0, -30.0, -30.0}, {-30.0, 30.0, -30.0}, {-30.0, -30.0, -30.0},
	{0.0, 0.0, 31.0}, {0.0, 0.0, -31.0}, {0.0, 31.0, 0.0}, {0.0, -31.0, 0.0}, {31.0, 0.0, 0.0}, {-31.0, 0.0, 0.0}, {-31.0, 31.0, 31.0}, {31.0, 31.0, 31.0}, {31.0, -31.0, 31.0}, {31.0, 31.0, -31.0}, {-31.0, -31.0, 31.0}, {31.0, -31.0, -31.0}, {-31.0, 31.0, -31.0}, {-31.0, -31.0, -31.0},
	{0.0, 0.0, 32.0}, {0.0, 0.0, -32.0}, {0.0, 32.0, 0.0}, {0.0, -32.0, 0.0}, {32.0, 0.0, 0.0}, {-32.0, 0.0, 0.0}, {-32.0, 32.0, 32.0}, {32.0, 32.0, 32.0}, {32.0, -32.0, 32.0}, {32.0, 32.0, -32.0}, {-32.0, -32.0, 32.0}, {32.0, -32.0, -32.0}, {-32.0, 32.0, -32.0}, {-32.0, -32.0, -32.0},
	{0.0, 0.0, 33.0}, {0.0, 0.0, -33.0}, {0.0, 33.0, 0.0}, {0.0, -33.0, 0.0}, {33.0, 0.0, 0.0}, {-33.0, 0.0, 0.0}, {-33.0, 33.0, 33.0}, {33.0, 33.0, 33.0}, {33.0, -33.0, 33.0}, {33.0, 33.0, -33.0}, {-33.0, -33.0, 33.0}, {33.0, -33.0, -33.0}, {-33.0, 33.0, -33.0}, {-33.0, -33.0, -33.0},
	{0.0, 0.0, 34.0}, {0.0, 0.0, -34.0}, {0.0, 34.0, 0.0}, {0.0, -34.0, 0.0}, {34.0, 0.0, 0.0}, {-34.0, 0.0, 0.0}, {-34.0, 34.0, 34.0}, {34.0, 34.0, 34.0}, {34.0, -34.0, 34.0}, {34.0, 34.0, -34.0}, {-34.0, -34.0, 34.0}, {34.0, -34.0, -34.0}, {-34.0, 34.0, -34.0}, {-34.0, -34.0, -34.0},
	{0.0, 0.0, 35.0}, {0.0, 0.0, -35.0}, {0.0, 35.0, 0.0}, {0.0, -35.0, 0.0}, {35.0, 0.0, 0.0}, {-35.0, 0.0, 0.0}, {-35.0, 35.0, 35.0}, {35.0, 35.0, 35.0}, {35.0, -35.0, 35.0}, {35.0, 35.0, -35.0}, {-35.0, -35.0, 35.0}, {35.0, -35.0, -35.0}, {-35.0, 35.0, -35.0}, {-35.0, -35.0, -35.0},
	{0.0, 0.0, 36.0}, {0.0, 0.0, -36.0}, {0.0, 36.0, 0.0}, {0.0, -36.0, 0.0}, {36.0, 0.0, 0.0}, {-36.0, 0.0, 0.0}, {-36.0, 36.0, 36.0}, {36.0, 36.0, 36.0}, {36.0, -36.0, 36.0}, {36.0, 36.0, -36.0}, {-36.0, -36.0, 36.0}, {36.0, -36.0, -36.0}, {-36.0, 36.0, -36.0}, {-36.0, -36.0, -36.0},
	{0.0, 0.0, 37.0}, {0.0, 0.0, -37.0}, {0.0, 37.0, 0.0}, {0.0, -37.0, 0.0}, {37.0, 0.0, 0.0}, {-37.0, 0.0, 0.0}, {-37.0, 37.0, 37.0}, {37.0, 37.0, 37.0}, {37.0, -37.0, 37.0}, {37.0, 37.0, -37.0}, {-37.0, -37.0, 37.0}, {37.0, -37.0, -37.0}, {-37.0, 37.0, -37.0}, {-37.0, -37.0, -37.0},
	{0.0, 0.0, 38.0}, {0.0, 0.0, -38.0}, {0.0, 38.0, 0.0}, {0.0, -38.0, 0.0}, {38.0, 0.0, 0.0}, {-38.0, 0.0, 0.0}, {-38.0, 38.0, 38.0}, {38.0, 38.0, 38.0}, {38.0, -38.0, 38.0}, {38.0, 38.0, -38.0}, {-38.0, -38.0, 38.0}, {38.0, -38.0, -38.0}, {-38.0, 38.0, -38.0}, {-38.0, -38.0, -38.0},
	{0.0, 0.0, 39.0}, {0.0, 0.0, -39.0}, {0.0, 39.0, 0.0}, {0.0, -39.0, 0.0}, {39.0, 0.0, 0.0}, {-39.0, 0.0, 0.0}, {-39.0, 39.0, 39.0}, {39.0, 39.0, 39.0}, {39.0, -39.0, 39.0}, {39.0, 39.0, -39.0}, {-39.0, -39.0, 39.0}, {39.0, -39.0, -39.0}, {-39.0, 39.0, -39.0}, {-39.0, -39.0, -39.0},
	{0.0, 0.0, 40.0}, {0.0, 0.0, -40.0}, {0.0, 40.0, 0.0}, {0.0, -40.0, 0.0}, {40.0, 0.0, 0.0}, {-40.0, 0.0, 0.0}, {-40.0, 40.0, 40.0}, {40.0, 40.0, 40.0}, {40.0, -40.0, 40.0}, {40.0, 40.0, -40.0}, {-40.0, -40.0, 40.0}, {40.0, -40.0, -40.0}, {-40.0, 40.0, -40.0}, {-40.0, -40.0, -40.0}
}

enum _:LILITH_SKILL
{
	SKILL_READY = 0,
	SKILL_USE,
	SKILL_DELAY,
}

enum _:LILITH_ANIMATION
{
	V_ANIM_SKILL_1	= 2,
	V_ANIM_SKILL_2	= 8,
	P_ANIM_SKILL_1	= 152,
	P_ANIM_SKILL_2	= 153
}

enum _:LILITH_SOUND
{
	SKILL_1 = 0,
	SKILL_2_IN,
	SKILL_2_OUT,
	PAIN_HURT,
	PAIN_GATE,
	PAIN_DEATH
}

enum _:LILITH_ENT
{
	ENT_MARK = 0,
	ENT_PORTAL1,
	ENT_PORTAL2
}

new const LilithSound[][] = 
{
	"zombie_plague/lilith/lilith_teleport_skill1.wav",
	"zombie_plague/lilith/lilith_teleport_skill2_in.wav",
	"zombie_plague/lilith/lilith_teleport_skill2_out.wav",
	"zombie_plague/lilith/lilith_pain_hurt.wav",
	"zombie_plague/lilith/lilith_pain_gate.wav",
	"zombie_plague/lilith/lilith_pain_death.wav"
}

new g_teleport_ent[33][3]
new class_lilith[33]
new g_skill1[33]
new g_skill2[33]
new sync_hud[2]
new index_lilith
new g_HamBot
new g_lilith

public plugin_init()
{
	// Register Plugins .....
	register_plugin(PLUGIN, VERSION, AUTHOR)
	
	// Forward Event
	register_event("DeathMsg", "Event_Death", "a")
	register_event("CurWeapon","Event_CurWeapon","be","1=1")
	register_event("HLTV", "Event_RoundStart", "a", "1=0", "2=0")
	
	// Forward Log Event
	register_logevent("Event_RoundEnd", 2, "1=Round_End")
	
	// Forward Fakemeta
	register_forward(FM_CmdStart , "Forward_CmdStart")
	
	// Forward Ham
	RegisterHam(Ham_TakeDamage, "player", "Forward_TakeDamage")
	
	// Forward Think Entity
	register_think(TELEPORT_MARK_CLASSNAME, "Forward_Mark_Think")
	register_think(TELEPORT_PORTAL_CLASSNAME, "Forward_Portal_Think")
	register_touch(TELEPORT_MARK_CLASSNAME, "player", "Forward_Mark_Touch")
	
	// Create Sync Hud
	sync_hud[0] = CreateHudSyncObj(12)
	sync_hud[1] = CreateHudSyncObj(13)
	g_lilith = zp_register_zombie_class(ZOMBIE_NAME, ZOMBIE_INFO, ZOMBIE_MODEL, ZOMBIE_CLAW_MDL, ZOMBIE_HEALTH, ZOMBIE_SPEED, ZOMBIE_GRAVITY, ZOMBIE_KNOCKBACK)
}

public zp_user_infected_pre(id) 
{
    if(!(get_user_flags(id) & ADMIN_SLAY)) 
	{
        if (zp_get_user_next_class(id) == g_lilith) 
		{
            zp_set_user_zombie_class(id, 0)
            client_print(id, print_center, "Купи Премиума, чтобы взять этот класс!")
            client_print(id, print_chat, "Купи Премиума, чтобы взять этот класс!")
        }    
    }
}

public plugin_precache()
{	
	for(new i = 0; i < sizeof(LilithSound); i++)
		precache_sound(LilithSound[i])
	
	new CLAW_MDL[101]
	formatex(CLAW_MDL, charsmax(CLAW_MDL), "models/zombie_plague/%s", ZOMBIE_CLAW_MDL)
	
	precache_model(CLAW_MDL)
	precache_model(ZOMBIE_BOMB_MDL)
	precache_viewmodel_sound(ZOMBIE_BOMB_MDL)
	
	precache_model(TELEPORT_MARK_MODEL)
	precache_model(TELEPORT_PORTAL_MODEL)
	
	precache_sound("common/null.wav")
	
	new player_models[101]
	formatex(player_models, charsmax(player_models), "models/player/%s/%s.mdl", ZOMBIE_MODEL, ZOMBIE_MODEL)
	index_lilith = precache_model(player_models)
}

public client_putinserver(id)
{
	if(!g_HamBot && is_user_bot(id))
	{
		g_HamBot = 1
		set_task(0.1, "Do_RegisterHam", id)
	}
}

public Do_RegisterHam(id)
{
	RegisterHamFromEntity(Ham_TakeDamage, id, "Forward_TakeDamage")
}

public Event_RoundEnd(id) lilith_reset_value(id)
public Event_RoundStart(id) lilith_reset_value(id)
public Event_Death()
{
	new id = read_data(2)
	if(zp_get_user_zombie(id) && class_lilith[id])
	{
		engfunc(EngFunc_EmitSound, id, CHAN_ITEM, LilithSound[PAIN_DEATH], 1.0, ATTN_NORM, 0, PITCH_NORM)
		lilith_reset_value(id)
	
	}
}

public Event_CurWeapon(id)
{
	if(!is_user_alive(id))
		return
	if(!zp_get_user_zombie(id) || !class_lilith[id])
		return
	
	if(g_skill1[id] != SKILL_USE) set_user_maxspeed(id, float(ZOMBIE_SPEED))
	else if(g_skill2[id] != SKILL_USE) set_user_maxspeed(id, float(ZOMBIE_SPEED))
	switch(read_data(2))
	{
		case CSW_KNIFE:
		{
			new CLAW_MDL[101]
			formatex(CLAW_MDL, charsmax(CLAW_MDL), "models/zombie_plague/%s", ZOMBIE_CLAW_MDL)
			
			set_pev(id, pev_viewmodel2, CLAW_MDL)
			set_pev(id, pev_weaponmodel2, "")
		}
		case CSW_SMOKEGRENADE: set_pev(id, pev_viewmodel2, ZOMBIE_BOMB_MDL)
		case CSW_HEGRENADE: set_pev(id, pev_viewmodel2, ZOMBIE_BOMB_MDL)
		case CSW_FLASHBANG: set_pev(id, pev_viewmodel2, ZOMBIE_BOMB_MDL)
	}
	
}

public Forward_TakeDamage(victim, inflictor, attacker, Float:damage, dmgtype)
{
	if(!is_user_alive(attacker) || zp_get_user_zombie(attacker))
		return
	if(!is_user_alive(victim) || !is_user_connected(victim))
		return
	if(!zp_get_user_zombie(victim) || !class_lilith[victim])
		return
		
	engfunc(EngFunc_EmitSound, victim, CHAN_ITEM, LilithSound[PAIN_HURT], 1.0, ATTN_NORM, 0, PITCH_NORM)
}

public show_lilith_hud(id)
{
	static Temp_Skill_1[128], Temp_Skill_2[128]
	static Red[2], Blue[2], Green[2]
	if(g_skill1[id] == SKILL_READY)
	{
		Red[0] = 0
		Green[0] = 255
		Blue[0] = 0
		
		formatex(Temp_Skill_1, sizeof(Temp_Skill_1), "[ E ] -> Create Portal (Ready)")
	}
	else if(g_skill1[id] == SKILL_USE)
	{
		Red[0] = 200
		Green[0] = 200
		Blue[0] = 0
		
		formatex(Temp_Skill_1, sizeof(Temp_Skill_1), "Creating Portal ....")
	}
	else if(g_skill1[id] == SKILL_DELAY)
	{
		Red[0] = 255
		Green[0] = 0
		Blue[0] = 0
		
		formatex(Temp_Skill_1, sizeof(Temp_Skill_1), "[ E ] -> Create Portal (Delayed)")
	}
	
	if(g_skill2[id] == SKILL_READY)
	{
		if(!pev_valid(g_teleport_ent[id][ENT_MARK]))
		{
			Red[1] = 255
			Green[1] = 0
			Blue[1] = 0
		}
		else
		{
			Red[1] = 0
			Green[1] = 255
			Blue[1] = 0
		}
		
		formatex(Temp_Skill_2, sizeof(Temp_Skill_2), "^n[ R ] -> Teleport (Ready)")
	}
	else if(g_skill2[id] == SKILL_USE)
	{
		Red[1] = 200
		Green[1] = 200
		Blue[1] = 0
		
		formatex(Temp_Skill_2, sizeof(Temp_Skill_2), "^nTeleporting .....")
	}
	else if(g_skill2[id] == SKILL_DELAY)
	{
		Red[1] = 255
		Green[1] = 0
		Blue[1] = 0
		
		formatex(Temp_Skill_2, sizeof(Temp_Skill_2), "^n[ R ] -> Teleport (Delayed)")
	}
	
	set_hudmessage(Red[0], Green[0], Blue[0], -1.0, -0.79, 0, 2.0, 10.0)
	ShowSyncHudMsg(id, sync_hud[0], Temp_Skill_1)
	
	set_hudmessage(Red[1], Green[1], Blue[1], -1.0, -0.76, 0, 2.0, 10.0)
	ShowSyncHudMsg(id, sync_hud[1], Temp_Skill_2)
}

public Forward_CmdStart(id, UC_Handle, seed)
{
	if(!is_user_alive(id))
		return
	if(!zp_get_user_zombie(id) || !class_lilith[id])
		return
	
	static Float:CurrentTime, Float:g_hud_delay[33]
	CurrentTime = get_gametime()
	
	if(CurrentTime - 1.0 > g_hud_delay[id])
	{
		show_lilith_hud(id)
		
		if(pev(id, pev_solid) == SOLID_NOT)
			set_pev(id, pev_solid, SOLID_BBOX)
		
		g_hud_delay[id] = CurrentTime
	}
	
	static PressedButton
	PressedButton = get_uc(UC_Handle, UC_Buttons)
	
	if(PressedButton & IN_RELOAD)
	{
		if(g_skill2[id] != SKILL_READY)
			return
		if(!pev_valid(g_teleport_ent[id][ENT_MARK]))
			return
			
		set_uc(UC_Handle, UC_Buttons, IN_ATTACK2)
		set_task(0.001, "action_teleport", id)
	}
	else if(PressedButton & IN_USE)
	{
		if(pev(id, pev_flags) & FL_DUCKING)
		{
			client_print(id, print_center, "You Can't Create Teleport Portal If You Ducking ...")
			return
		}
		
		if(g_skill1[id] != SKILL_READY)
			return
		
		set_uc(UC_Handle, UC_Buttons, IN_ATTACK2)
		set_task(0.001, "action_create_teleport_mark", id)
	}
	
	auto_unstuck(id)
}

public auto_unstuck(id)
{
	static Float:origin[3], Float:mins[3], hull, Float:vec[3], i
	
	pev(id, pev_origin, origin)
	hull = pev(id, pev_flags) & FL_DUCKING ? HULL_HEAD : HULL_HUMAN
	
	if(!is_hull_vacant(origin, hull, id))
	{
		pev(id, pev_mins, mins)
		vec[2] = origin[2]
		
		for (i = 0; i < sizeof UnstuckVector; ++i)
		{
			vec[0] = origin[0] - mins[0] * UnstuckVector[i][0]
			vec[1] = origin[1] - mins[1] * UnstuckVector[i][1]
			vec[2] = origin[2] - mins[2] * UnstuckVector[i][2]
			
			if(is_hull_vacant(vec, hull, id))
			{
				engfunc(EngFunc_SetOrigin, id, vec)
				set_pev(id,pev_velocity,{0.0,0.0,0.0})
			
				i = sizeof UnstuckVector
			}
		}
	}
}

public zp_user_infected_post(id)
{
	if(zp_get_user_zombie_class(id) == g_lilith)
	{
		class_lilith[id] = true
	
		show_lilith_hud(id)
		lilith_reset_var_skill(id)
		
		fm_strip_user_weapons(id)
		fm_give_item(id, "weapon_knife")
		
		set_pdata_int(id, 491, index_lilith, 5)
	}
}

public action_teleport(id)
{
	if(!is_user_alive(id))
		return
	if(!zp_get_user_zombie(id) || !class_lilith[id])
		return
	if(g_skill2[id] != SKILL_READY)
		return
	
	g_skill2[id] = SKILL_USE
	
	set_weapon_anim(id, V_ANIM_SKILL_2)
	set_pev(id, pev_sequence, P_ANIM_SKILL_2)
	set_pev(id, pev_framerate, 0.3)
		
	set_user_maxspeed(id, 0.1)
	set_user_gravity(id, 2.0)
	set_pdata_float(id, 83, 2.0, 5)
	
	new Float:fOrigin[3]
	pev(id, pev_origin, fOrigin)
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte(TE_DLIGHT)
	engfunc(EngFunc_WriteCoord, fOrigin[0])
	engfunc(EngFunc_WriteCoord, fOrigin[1])
	engfunc(EngFunc_WriteCoord, fOrigin[2])
	write_byte(20) // radius
	write_byte(200)    // r
	write_byte(200)  // g
	write_byte(255)   // b
	write_byte(40) // life in 10's
	write_byte(1)  // decay rate in 10's
	message_end() 
	
	new Float:OriginPlayer[3]
	get_position(id, 5.0, 0.0, 0.0, OriginPlayer)
	create_teleport_portal(g_teleport_ent[id][ENT_PORTAL1], id, SKILL_2_IN, OriginPlayer)
	
	if(pev_valid(g_teleport_ent[id][ENT_MARK]))
	{
		static Float:OriginTeleport[3]
		pev(g_teleport_ent[id][ENT_MARK], pev_origin, OriginTeleport)
		OriginTeleport[2] += 50.0
		create_teleport_portal(g_teleport_ent[id][ENT_PORTAL2], id, SKILL_2_OUT, OriginTeleport)
	}
	
	set_task(2.0, "do_teleport", id+TASK_TELEPORT)
}

public do_teleport(id)
{
	id -= TASK_TELEPORT
	if(!is_user_alive(id))
		return
	if(!zp_get_user_zombie(id) || !class_lilith[id])
	{
		remove_task(id+TASK_TELEPORT)
		return
	}
	
	if(!pev_valid(g_teleport_ent[id][ENT_MARK]))
		return
	if(g_skill2[id] != SKILL_USE)
		return
	
	client_cmd(id, "+duck")
	
	static Float:OriginTeleport[3]
	pev(g_teleport_ent[id][ENT_MARK], pev_origin, OriginTeleport)
	OriginTeleport[2] += 50.0
	set_pev(id, pev_origin, OriginTeleport)
	engfunc(EngFunc_EmitSound, g_teleport_ent[id][ENT_MARK], CHAN_ITEM, "common/null.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
	
	remove_entity(g_teleport_ent[id][ENT_MARK])
	g_teleport_ent[id][ENT_MARK] = 0
	
	set_user_maxspeed(id, float(ZOMBIE_SPEED))
	set_user_gravity(id, ZOMBIE_GRAVITY)
	set_pev(id, pev_framerate, 1.0)
	client_cmd(id, "-duck")
	
	g_skill2[id] = SKILL_DELAY
	set_task(float(DELAY_SKILL_2), "skill2_delay", id+TASK_DELAY)
}

public skill2_delay(id)
{
	id -= TASK_DELAY
	
	if(g_skill2[id] != SKILL_DELAY)
		return
	
	g_skill2[id] = SKILL_READY
}

public action_create_teleport_mark(id)
{
	if(!is_user_alive(id))
		return
	if(!zp_get_user_zombie(id) || !class_lilith[id])
		return
	if(g_skill1[id] != SKILL_READY)
		return
	
	g_skill1[id] = SKILL_USE
	
	set_weapon_anim(id, V_ANIM_SKILL_1)
	set_pev(id, pev_sequence, P_ANIM_SKILL_1)
	set_pev(id, pev_framerate, 0.5)
	
	set_user_maxspeed(id, 0.1)
	set_user_gravity(id, 2.0)
	
	new Float:fOrigin[3]
	pev(id, pev_origin, fOrigin)
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte(TE_DLIGHT)
	engfunc(EngFunc_WriteCoord, fOrigin[0])
	engfunc(EngFunc_WriteCoord, fOrigin[1])
	engfunc(EngFunc_WriteCoord, fOrigin[2])
	write_byte(20) // radius
	write_byte(200)    // r
	write_byte(200)  // g
	write_byte(255)   // b
	write_byte(40) // life in 10's
	write_byte(1)  // decay rate in 10's
	message_end() 
	
	engfunc(EngFunc_EmitSound, id, CHAN_ITEM, LilithSound[SKILL_1], 1.0, ATTN_NORM, 0, PITCH_NORM)
	set_pdata_float(id, 83, 1.0, 5)
	
	set_task(0.63, "create_teleport_mark", id+TASK_TELEPORT)
}

public create_teleport_mark(id)
{
	id -= TASK_TELEPORT
	
	if(!is_user_alive(id))
		return
	if(!zp_get_user_zombie(id) || !class_lilith[id])
	{
		remove_task(id+TASK_TELEPORT)
		return
	}
	
	if(g_skill1[id] != SKILL_USE)
		return
	
	if(pev_valid(g_teleport_ent[id][ENT_MARK]))
	{
		remove_entity(g_teleport_ent[id][ENT_MARK])
		g_teleport_ent[id][ENT_MARK] = 0
	}
	
	set_user_maxspeed(id, float(ZOMBIE_SPEED))
	set_user_gravity(id, ZOMBIE_GRAVITY)
	set_pev(id, pev_framerate, 1.0)
	
	static Float:fOrigin1[3], Float:fOrigin2[3]
	g_teleport_ent[id][ENT_MARK] = create_entity("env_sprite")
	
	set_pev(g_teleport_ent[id][ENT_MARK], pev_classname, TELEPORT_MARK_CLASSNAME)
	engfunc(EngFunc_SetModel, g_teleport_ent[id][ENT_MARK], TELEPORT_MARK_MODEL)
	
	pev(id, pev_origin, fOrigin1)
	set_pev(g_teleport_ent[id][ENT_MARK], pev_origin, fOrigin1)
	
	drop_to_floor(g_teleport_ent[id][ENT_MARK])
	
	pev(g_teleport_ent[id][ENT_MARK], pev_origin, fOrigin2)
	fOrigin2[0] += TELEPORT_X
	
	set_pev(g_teleport_ent[id][ENT_MARK], pev_origin, fOrigin2)
	
	set_pev(g_teleport_ent[id][ENT_MARK], pev_solid, SOLID_NOT)
	set_pev(g_teleport_ent[id][ENT_MARK], pev_movetype, MOVETYPE_NOCLIP)
	
	set_pev(g_teleport_ent[id][ENT_MARK], pev_animtime, get_gametime())
	set_pev(g_teleport_ent[id][ENT_MARK], pev_framerate, 1.0)
	set_pev(g_teleport_ent[id][ENT_MARK], pev_sequence, 0)
	set_pev(g_teleport_ent[id][ENT_MARK], pev_owner, id)
	
	set_pev(g_teleport_ent[id][ENT_MARK], pev_nextthink, get_gametime() + 2.0)
	
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte(TE_DLIGHT)
	engfunc(EngFunc_WriteCoord, fOrigin2[0])
	engfunc(EngFunc_WriteCoord, fOrigin2[1])
	engfunc(EngFunc_WriteCoord, fOrigin2[2])
	write_byte(10) // radius
	write_byte(200)    // r
	write_byte(200)  // g
	write_byte(255)   // b
	write_byte(40) // life in 10's
	write_byte(1)  // decay rate in 10's
	message_end() 
	
	engfunc(EngFunc_EmitSound, g_teleport_ent[id][ENT_MARK], CHAN_ITEM, LilithSound[PAIN_GATE], 1.0, ATTN_NORM, 0, PITCH_NORM)
	
	g_skill1[id] = SKILL_DELAY
	set_task(float(DELAY_SKILL_1), "skill1_delay", id+TASK_DELAY)
}

public skill1_delay(id)
{
	id -= TASK_DELAY
	
	if(g_skill1[id] != SKILL_DELAY)
		return
	
	g_skill1[id] = SKILL_READY
}

public create_teleport_portal(ent, owner, const Sound, Float:Origin[3])
{
	ent = create_entity("env_sprite")
	
	Origin[0] += TELEPORT_X
	Origin[2] += TELEPORT_Z
	
	set_pev(ent, pev_classname, TELEPORT_PORTAL_CLASSNAME)
	engfunc(EngFunc_SetModel, ent, TELEPORT_PORTAL_MODEL)
	
	set_pev(ent, pev_origin, Origin)
	
	set_pev(ent, pev_solid, SOLID_NOT)
	set_pev(ent, pev_movetype, MOVETYPE_NOCLIP)
	
	set_pev(ent, pev_rendermode, kRenderTransAdd)
	set_pev(ent, pev_renderamt, 150.0)
	set_pev(ent, pev_scale, 0.5)
	
	set_pev(ent, pev_frame, 0.0)
	set_pev(ent, pev_owner, owner)
	set_pev(ent, pev_fuser1, get_gametime() + 3.0)
	
	set_pev(ent, pev_nextthink, get_gametime() + 0.05)
	engfunc(EngFunc_EmitSound, ent, CHAN_ITEM, LilithSound[Sound], 1.0, ATTN_NORM, 0, PITCH_NORM)
}

public Forward_Portal_Think(ent)
{
	if(!pev_valid(ent))
		return
	
	static Float:fFrame, Float:Origin[3], owner
	owner = pev(ent, pev_owner)
	pev(ent, pev_frame, fFrame)
	pev(ent, pev_origin, Origin)

	if(ent == g_teleport_ent[owner][ENT_PORTAL2])
	{
		fFrame += 1.0
		if(fFrame > 15.0) fFrame = 0.0
	}
	else if(ent == g_teleport_ent[owner][ENT_PORTAL1])
	{
		fFrame -= 1.0
		if(fFrame == 0.0) fFrame = 15.0
	}
	
	set_pev(ent, pev_frame, fFrame)
	set_pev(ent, pev_nextthink, get_gametime() + 0.05)
	
	static Float:fTimeRemove
	pev(ent, pev_fuser1, fTimeRemove)
	if(get_gametime() >= pev(ent, pev_fuser1))
	{
		engfunc(EngFunc_RemoveEntity, ent)
		return
	}
}

public Forward_Mark_Think(ent)
{
	if(!pev_valid(ent))
		return
	
	static Float:Origin[3]
	pev(ent, pev_origin, Origin)
	
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte(TE_DLIGHT)
	engfunc(EngFunc_WriteCoord, Origin[0])
	engfunc(EngFunc_WriteCoord, Origin[1])
	engfunc(EngFunc_WriteCoord, Origin[2])
	write_byte(10) // radius
	write_byte(200)    // r
	write_byte(200)  // g
	write_byte(255)   // b
	write_byte(40) // life in 10's
	write_byte(1)  // decay rate in 10's
	message_end()
	
	engfunc(EngFunc_EmitSound, ent, CHAN_ITEM, LilithSound[PAIN_GATE], 1.0, ATTN_NORM, 0, PITCH_NORM)
	set_pev(ent, pev_nextthink, get_gametime() + 2.0)
}

public Forward_Mark_Touch(ent, id)
{
	if(!pev_valid(ent))
		return
	if(!is_user_alive(id))
		return
	
	if(pev(id, pev_solid) != SOLID_NOT)
		set_pev(id, pev_solid, SOLID_NOT)
}

public lilith_reset_value(id)
{
	class_lilith[id] = false
	lilith_reset_var_skill(id)
}

public lilith_reset_var_skill(id)
{
	remove_task(id+TASK_TELEPORT)
	
	if(pev_valid(g_teleport_ent[id][ENT_MARK]))
	{
		remove_entity(g_teleport_ent[id][ENT_MARK])
		g_teleport_ent[id][ENT_PORTAL2] = 0
	}
	
	if(pev_valid(g_teleport_ent[id][ENT_PORTAL1]))
	{
		remove_entity(g_teleport_ent[id][ENT_PORTAL1])
		g_teleport_ent[id][ENT_PORTAL2] = 0
	}
	
	if(pev_valid(g_teleport_ent[id][ENT_PORTAL2]))
	{
		remove_entity(g_teleport_ent[id][ENT_PORTAL2])
		g_teleport_ent[id][ENT_PORTAL2] = 0
	}
	
	g_skill1[id] = 0
	g_skill2[id] = 0
	g_teleport_ent[id][ENT_MARK] = 0
}

stock bool:is_hull_vacant(const Float:origin[3], hull,id)
{
	static tr
	engfunc(EngFunc_TraceHull, origin, origin, 0, hull, id, tr)
	if (!get_tr2(tr, TR_StartSolid) || !get_tr2(tr, TR_AllSolid))
		return true;
	
	return false;
}

stock get_position(id, Float:forw, Float:right, Float:up, Float:vStart[])
{
	new Float:vOrigin[3], Float:vAngle[3], Float:vForward[3], Float:vRight[3], Float:vUp[3]
	
	pev(id, pev_origin, vOrigin)
	pev(id, pev_view_ofs,vUp) //for player
	xs_vec_add(vOrigin,vUp,vOrigin)
	pev(id, pev_v_angle, vAngle) // if normal entity ,use pev_angles
	
	angle_vector(vAngle,ANGLEVECTOR_FORWARD,vForward) //or use EngFunc_AngleVectors
	angle_vector(vAngle,ANGLEVECTOR_RIGHT,vRight)
	angle_vector(vAngle,ANGLEVECTOR_UP,vUp)
	
	vStart[0] = vOrigin[0] + vForward[0] * forw + vRight[0] * right + vUp[0] * up
	vStart[1] = vOrigin[1] + vForward[1] * forw + vRight[1] * right + vUp[1] * up
	vStart[2] = vOrigin[2] + vForward[2] * forw + vRight[2] * right + vUp[2] * up
}

stock set_weapon_anim(id, anim)
{
	set_pev(id, pev_weaponanim, anim)
	message_begin(MSG_ONE_UNRELIABLE, SVC_WEAPONANIM, .player = id)
	write_byte(anim)
	write_byte(pev(id, pev_body))
	message_end()
}

stock precache_viewmodel_sound(const model[]) // I Get This From BTE
{
	new file, i, k
	if((file = fopen(model, "rt")))
	{
		new szsoundpath[64], NumSeq, SeqID, Event, NumEvents, EventID
		fseek(file, 164, SEEK_SET)
		fread(file, NumSeq, BLOCK_INT)
		fread(file, SeqID, BLOCK_INT)
		
		for(i = 0; i < NumSeq; i++)
		{
			fseek(file, SeqID + 48 + 176 * i, SEEK_SET)
			fread(file, NumEvents, BLOCK_INT)
			fread(file, EventID, BLOCK_INT)
			fseek(file, EventID + 176 * i, SEEK_SET)
			
			// The Output Is All Sound To Precache In ViewModels (GREAT :V)
			for(k = 0; k < NumEvents; k++)
			{
				fseek(file, EventID + 4 + 76 * k, SEEK_SET)
				fread(file, Event, BLOCK_INT)
				fseek(file, 4, SEEK_CUR)
				
				if(Event != 5004)
					continue
				
				fread_blocks(file, szsoundpath, 64, BLOCK_CHAR)
				
				if(strlen(szsoundpath))
				{
					strtolower(szsoundpath)
					engfunc(EngFunc_PrecacheSound, szsoundpath)
				}
			}
		}
	}
	fclose(file)
}
cso_class_revenant_boss.sma

Code: Select all

#include <amxmodx>
#include <engine>
#include <fakemeta>
#include <hamsandwich>
#include <zombieplague>
#include <cstrike>
#include <fun>
#include <xs>
#include <fakemeta_util>

#define PLUGIN "Revenant Boss [REMAKE]"
#define VERSION "3.0"
#define AUTHOR "inf"

new Povelitel

#define FireShpere_Classname "ZP_Povelitel_FireShpere"
#define FrostSphere_Classname "ZP_Povelitel_FrostSphere"

#define CDHudChannel 4

#define Model "revenant_gladmin"
#define Claw "v_knife_revenant_gladmin.mdl"
#define Shpere "models/revenant_fire/w_hiddentail.mdl"
#define Trail "sprites/arena/tok.spr"
#define Burn "sprites/flame.spr"

const Float:FireShpereExplodeRadius = 100.0
const Float:FireShpereExplodeDamage = 100.0
const Float:FireShpere_CD= 10.0
const Float:FireShpere_BurnTime = 3.0
const Float:BurnDamage = 25.0
const Float:BurnUpdate = 0.5

const Float:FrostSphereExplodeRadius = 100.0
const Float:FrostSphereExplodeDamage = 0.0
const Float:FrostSphere_CD= 10.0
const Float:FrostSphere_FreezeTime = 5.0


new bool:Can_Use_Ability[32],Selected_Ability[32],Float:Ability_CD[32],Float:UpdateHud[32]
new bool:in_frost[32],Float:FrostTime[32]
new bool:in_burn[32],Float:BurnTime[32],BurnOwner[32],Float:BurnUpdateDamage[32]

new Msg_ScreenShake,Msg_ScreenFade,TrailSpriteIndex,BurnSprite
new g_has_Povelitel[33]

public plugin_precache()
{
	precache_model(Shpere)
	TrailSpriteIndex=precache_model(Trail)
	BurnSprite=precache_model(Burn)
}

public plugin_init()
{
	register_plugin(PLUGIN, VERSION, AUTHOR)
	Msg_ScreenShake = get_user_msgid("ScreenShake")
	Msg_ScreenFade = get_user_msgid("ScreenFade")
	
	//Register Class
	#if !defined TestingTime
	Povelitel=zp_register_zombie_class("Повелитель","\y|G| \r[Гл.Админ]",Model,Claw,26000,320,0.6,1.0)
	#endif

	register_message(get_user_msgid("DeathMsg"), "message_DeathMsg")
	RegisterHam(Ham_Killed, "player", "fw_PlayerKilled")
	RegisterHam(Ham_Touch, "info_target", "Ham_Touch_Pre")

	register_clcmd("drop","use_ability")
}


//Cmd Drop
public use_ability(id)
{
	if(!is_user_connected(id))return
	if(!is_user_alive(id))return
	#if !defined TestingTime
	if(!zp_get_user_zombie(id))return
	if(zp_get_user_nemesis(id))return
	if(zp_get_user_zombie_class(id)!=Povelitel)return
	#endif
	if(!Can_Use_Ability[id-1])return
	new Float: gametime = get_gametime()
	switch(Selected_Ability[id-1])
	{
		case 0:throw_Shpere(id,1),Ability_CD[id-1]=gametime+FireShpere_CD,Can_Use_Ability[id-1]=false
		case 1:throw_Shpere(id,2),Ability_CD[id-1]=gametime+FrostSphere_CD,Can_Use_Ability[id-1]=false
	}	
}
//Ham
public Ham_Touch_Pre(ent,world)
{
	if(!pev_valid(ent))return HAM_IGNORED
	
	new Classname[32]
	pev(ent, pev_classname, Classname, sizeof(Classname))
	if(!equal(Classname, FireShpere_Classname)&&!equal(Classname, FrostSphere_Classname))return HAM_IGNORED
	
	new Float:Origin[3],id = pev(ent,pev_owner)
	
	pev(ent,pev_origin,Origin)
	new victim =-1,Float:Damage_Radius,Float:Damage,attacker
	switch(pev(ent,pev_iuser1))
	{
		case 1:Damage_Radius=FireShpereExplodeRadius,Damage=FireShpereExplodeDamage,Light(Origin,30,255,105,0,4),DrawRings(Origin,255,105,0)
		case 2:Damage_Radius=FrostSphereExplodeRadius,Damage=FrostSphereExplodeDamage,Light(Origin,30,0,105,255,4),DrawRings(Origin,0,55,255)
	}
	
	while((victim = engfunc(EngFunc_FindEntityInSphere, victim, Origin, Damage_Radius)) != 0) 
	{
		if(pev_valid(victim)&&pev(victim, pev_takedamage)!=DAMAGE_NO&&pev(victim, pev_solid)!=SOLID_NOT)
		{
			if(is_user_connected(victim))
			{
				#if defined TestingTime
				if(get_user_team(victim)!=get_user_team(id))
				#else
				if(!zp_get_user_zombie(victim))
				#endif
				{
					if(pev(victim,pev_armorvalue)<=0.0&&pev(victim,pev_health)<Damage)attacker=id;else attacker=0
					switch(pev(ent,pev_iuser1))
					{
						case 1:	ExecuteHamB(Ham_TakeDamage,victim, ent,attacker, Damage, DMG_BURN),ScreenFade(victim,6,1,{255,125,0},125,1),
							BurnTime[victim-1]=get_gametime()+FireShpere_BurnTime,in_burn[victim-1]=true,in_frost[victim-1]=false,BurnOwner[victim-1]=id
						case 2:	ExecuteHamB(Ham_TakeDamage,victim, ent,attacker, Damage, DMG_FREEZE),ScreenFade(victim,6,1,{0,0,255},125,1),
							FrostTime[victim-1]=get_gametime()+FrostSphere_FreezeTime,in_frost[victim-1]=true,in_burn[victim-1]=false,
							fm_set_rendering(victim, kRenderFxGlowShell, 0,105,255, kRenderNormal,15)
					}
					ScreenShake(victim, ((1<<12) * 3), ((2<<12) * 3))
				}
			}
			else ExecuteHamB(Ham_TakeDamage,victim, ent,id, Damage, DMG_BLAST)	//take damage entity
		}
	} 
	if(pev_valid(ent))engfunc(EngFunc_RemoveEntity, ent)
	return HAM_HANDLED
}

public message_DeathMsg(msg_id, msg_dest, id)
{
	static szTruncatedWeapon[33], iAttacker, iVictim
	
	get_msg_arg_string(4, szTruncatedWeapon, charsmax(szTruncatedWeapon))
	
	iAttacker = get_msg_arg_int(1)
	iVictim = get_msg_arg_int(2)
	
	if(!is_user_connected(iAttacker) || iAttacker == iVictim)
		return PLUGIN_CONTINUE
	
	if(equal(szTruncatedWeapon, "knife") && get_user_weapon(iAttacker) == CSW_KNIFE)
	{
		if(g_has_Povelitel[iAttacker])
			set_msg_arg_string(4, "knife")
	}
	return PLUGIN_CONTINUE
}

public remove_values(id)
{
	remove_task(id)
}

public zp_user_infected_pre(id) {
    if(!(get_user_flags(id) & ADMIN_SLAY)) {
        if (zp_get_user_next_class(id) == Povelitel) {
            zp_set_user_zombie_class(id, 0)
        }
    }
}
			
//ZP
#if !defined TestingTime
public zp_user_infected_post(id,infector,nemesis)
{
	if(!zp_get_user_nemesis(id))Can_Use_Ability[id-1]=true
}

public fw_PlayerKilled(id, attacker, shouldgib) 
{
	remove_values(id)
}

public zp_user_humanized_post(id)
{
	Can_Use_Ability[id-1]=false,in_frost[id-1]=false,in_burn[id-1]=false
	remove_values(id)
}
#endif
//Standart Forwards
public client_connect(id)
{
	Can_Use_Ability[id-1]=false,Selected_Ability[id-1]=0
	remove_values(id)
}

public client_PreThink(id)
{
	new Float:gametime = get_gametime()
	if(in_frost[id-1])
		#if defined TestingTime
		if(FrostTime[id-1]<gametime||!is_user_alive(id))
		#else
		if(FrostTime[id-1]<gametime||!is_user_alive(id)||zp_get_user_zombie(id))
		#endif
			fm_set_rendering(id),
			in_frost[id-1]=false
		else
			{set_pev(id,pev_velocity,{0.0,0.0,0.0});new Float:Origin[3];pev(id,pev_origin,Origin);Light(Origin,15,0,105,255,4);}
	if(in_burn[id-1])
		#if defined TestingTime
		if(BurnTime[id-1]<gametime||!is_user_alive(id))
		#else
		if(BurnTime[id-1]<gametime||!is_user_alive(id)||zp_get_user_zombie(id))
		#endif
			in_burn[id-1]=false
		else
			if(BurnUpdateDamage[id-1]<gametime)
			{
				if(pev(id,pev_armorvalue)<=0.0&&pev(id,pev_health)<BurnDamage)ExecuteHamB(Ham_TakeDamage,id, 0,BurnOwner[id-1], BurnDamage, DMG_BURN)
				else ExecuteHamB(Ham_TakeDamage,id, 0,0, BurnDamage, DMG_BURN)
				
				BurnUpdateDamage[id-1]=gametime+BurnUpdate
				
				new Float:Origin[3]
				pev(id,pev_origin,Origin)
				engfunc(EngFunc_MessageBegin, MSG_BROADCAST, SVC_TEMPENTITY, Origin, 0)
				write_byte(TE_SPRITE) // TE id
				engfunc(EngFunc_WriteCoord, Origin[0]+random_float(-5.0, 5.0)) // x
				engfunc(EngFunc_WriteCoord, Origin[1]+random_float(-5.0, 5.0)) // y
				engfunc(EngFunc_WriteCoord, Origin[2]+random_float(-10.0, 10.0)) // z
				write_short(BurnSprite) // sprite
				write_byte(random_num(5, 10)) // scale
				write_byte(200) // brightness
				message_end()
				Light(Origin,15,255,105,0,7)	
			}
	if(!is_user_alive(id))return
	#if !defined TestingTime
	if(!zp_get_user_zombie(id))return
	if(zp_get_user_nemesis(id))return
	if(zp_get_user_zombie_class(id)!=Povelitel)return
	#endif
	if(UpdateHud[id-1]<gametime)
	{
		new Text0[100], Text1[56],Text2[56]
		formatex(Text0, 99, "Нажми [E] Сменить Стихию^nНажми [G] Использовать^n^n")
		switch(Selected_Ability[id-1])
		{
			case 0:formatex(Text1, 55, "Стихия: Огонь^n")
			case 1:formatex(Text1, 55, "Стихия: Лед^n")
		}
		if(!Can_Use_Ability[id-1])
		{
			if(Ability_CD[id-1]-gametime>0.0)formatex(Text2, 55, "Жди: %..1f^n",Ability_CD[id-1]-gametime)
			else formatex(Text2, 55, "Стихия: Готово^n"),Can_Use_Ability[id-1]=true
		}
		set_hudmessage(255,255,255,0.02,0.2,0,0.1,1.0,0.0,0.0,CDHudChannel)
		show_hudmessage(id,"%s%s%s",Text0,Text1,Text2)
		UpdateHud[id-1]=gametime+0.1
	}
	//Select Ability
	if((pev(id,pev_button)&IN_USE)&&!(pev(id,pev_oldbuttons)&IN_USE))
	{
		switch(Selected_Ability[id-1])
		{
			case 0:Selected_Ability[id-1]=1
			case 1:Selected_Ability[id-1]=0
		}
	}
	//Use ability
	if(Can_Use_Ability[id-1])
	if (pev(id,pev_impulse)==100)
	{
		switch(Selected_Ability[id-1])
		{
			case 0:throw_Shpere(id,1),Ability_CD[id-1]=gametime+FireShpere_CD,Can_Use_Ability[id-1]=false
			case 1:throw_Shpere(id,2),Ability_CD[id-1]=gametime+FrostSphere_CD,Can_Use_Ability[id-1]=false
		}
		
	}
}
//Public func
public throw_Shpere(id,type)
{
	set_pdata_float(id, 83, 0.7, 5)
	UTIL_PlayWeaponAnimation(id,5)
	
	new Float:StartOrigin[3],Float:EndOrigin[3]
	get_position(id,30.0,0.0,5.0,StartOrigin)
	fm_get_aim_origin(id,EndOrigin)
	
	new ient = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
	engfunc(EngFunc_SetModel,ient, Shpere)
	engfunc(EngFunc_SetSize, ient, {-3.0,-3.0,-3.0}, {3.0,3.0,3.0})
	switch(type)
	{
		case 1:	set_pev(ient, pev_classname, FireShpere_Classname),
			fm_set_rendering(ient, kRenderFxGlowShell, 255,155,0, kRenderTransAlpha,25)
		case 2:	set_pev(ient, pev_classname, FrostSphere_Classname),
			fm_set_rendering(ient, kRenderFxGlowShell, 0,105,255, kRenderTransAlpha,25)
	}
	set_pev(ient, pev_movetype, MOVETYPE_FLY)
	set_pev(ient,pev_solid,SOLID_TRIGGER)
	set_pev(ient,pev_origin,StartOrigin)
	set_pev(ient,pev_owner,id)
	set_pev(ient, pev_nextthink, get_gametime() +0.01)		
	set_pev(ient,pev_iuser1,type)
	
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte(TE_BEAMFOLLOW)
	write_short(ient)
	write_short(TrailSpriteIndex)
	write_byte(15)
	write_byte(15)
	switch(type)
	{
		case 1:
		{
			write_byte(255)
			write_byte(155)
			write_byte(0)
		}
		case 2:
		{
			write_byte(0)
			write_byte(0)
			write_byte(255)
		}
	}
	write_byte(255)
	message_end()
	
	new Float:VECTOR[3],Float:VELOCITY[3]
	xs_vec_sub(EndOrigin, StartOrigin, VECTOR)
	xs_vec_normalize(VECTOR, VECTOR)
	xs_vec_mul_scalar(VECTOR, 1300.0, VELOCITY)
	set_pev(ient, pev_velocity, VELOCITY)
}
//Stocks
stock get_position(id,Float:forw, Float:right, Float:up, Float:vStart[])
{
	new Float:vOrigin[3], Float:vAngle[3], Float:vForward[3], Float:vRight[3], Float:vUp[3]
	pev(id, pev_v_angle, vAngle);pev(id, pev_origin, vOrigin);pev(id, pev_view_ofs,vUp)
	xs_vec_add(vOrigin,vUp,vOrigin)
	angle_vector(vAngle,ANGLEVECTOR_FORWARD,vForward)
	angle_vector(vAngle,ANGLEVECTOR_RIGHT,vRight)
	angle_vector(vAngle,ANGLEVECTOR_UP,vUp)
	vStart[0] = vOrigin[0] + vForward[0] * forw + vRight[0] * right + vUp[0] * up
	vStart[1] = vOrigin[1] + vForward[1] * forw + vRight[1] * right + vUp[1] * up
	vStart[2] = vOrigin[2] + vForward[2] * forw + vRight[2] * right + vUp[2] * up
}
stock DrawRings(Float:Origin[3],R,G,B)
{
	for(new i=0;i<4;i++)
	{
		message_begin( MSG_BROADCAST, SVC_TEMPENTITY );
		write_byte( TE_BEAMTORUS );
		engfunc(EngFunc_WriteCoord, Origin[0])
		engfunc(EngFunc_WriteCoord, Origin[1])
		engfunc(EngFunc_WriteCoord, Origin[2]+3.0*i)
		engfunc(EngFunc_WriteCoord, Origin[0])
		engfunc(EngFunc_WriteCoord, Origin[1])
		engfunc(EngFunc_WriteCoord, Origin[2]+100.0+10.0*i)
		write_short( TrailSpriteIndex ); // sprite
		write_byte( 0 ); // Starting frame
		write_byte( 0  ); // framerate * 0.1
		write_byte( 8-1*i ); // life * 0.1
		write_byte( 14 ); // width
		write_byte( 0 ); // noise
		write_byte( R ); // color r,g,b
		write_byte( G ); // color r,g,b
		write_byte( B); // color r,g,b
		write_byte( 255 ); // brightness
		write_byte( 0 ); // scroll speed
		message_end();  
	}	
}
stock Light(Float:Origin[3],RAD,R,G,B,Life)
{
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte(TE_DLIGHT)
	engfunc(EngFunc_WriteCoord, Origin[0])
	engfunc(EngFunc_WriteCoord, Origin[1])
	engfunc(EngFunc_WriteCoord, Origin[2])
	write_byte(RAD)	//Radius
	write_byte(R)	// r
	write_byte(G)	// g
	write_byte(B)	// b
	write_byte(Life)	//Life
	write_byte(10)
	message_end() 
}
stock ScreenFade(id, Timer, FadeTime, Colors[3], Alpha, type)
{
	if(id) if(!is_user_connected(id)) return

	if (Timer > 0xFFFF) Timer = 0xFFFF
	if (FadeTime <= 0) FadeTime = 4
	
	message_begin(id ? MSG_ONE_UNRELIABLE : MSG_BROADCAST,Msg_ScreenFade, _, id);
	write_short(Timer * 1 << 12)
	write_short(FadeTime * 1 << 12)
	switch (type) {
		case 1: write_short(0x0000)		// IN ( FFADE_IN )
		case 2: write_short(0x0001)		// OUT ( FFADE_OUT )
		case 3: write_short(0x0002)		// MODULATE ( FFADE_MODULATE )
		case 4: write_short(0x0004)		// STAYOUT ( FFADE_STAYOUT )
		default: write_short(0x0001)
	}
	write_byte(Colors[0])
	write_byte(Colors[1])
	write_byte(Colors[2])
	write_byte(Alpha)
	message_end()
}
stock ScreenShake(id, duration, frequency)
{	
	message_begin(id ? MSG_ONE_UNRELIABLE : MSG_ALL, Msg_ScreenShake, _, id ? id : 0);
	write_short(1<<14)
	write_short(duration)
	write_short(frequency)
	message_end();
}
stock UTIL_PlayWeaponAnimation(const Player, const Sequence)
{
	set_pev(Player, pev_weaponanim, Sequence)
	
	message_begin(MSG_ONE_UNRELIABLE, SVC_WEAPONANIM, .player = Player)
	write_byte(Sequence)
	write_byte(pev(Player, pev_body))
	message_end()
}
cso_class_revenant_fire.sma

Code: Select all

#include <amxmodx>
#include <engine>
#include <fakemeta>
#include <hamsandwich>
#include <zombieplague>
#include <cstrike>
#include <fun>
#include <xs>

new const ball_name[] = "dragon_ball"
new const ball_model[] = "models/revenant_fire/w_hiddentail.mdl"
new const ball_firespritemdl[] = "sprites/flame.spr"
new const ball_spriteexplodemdl[] = "sprites/revenant_fire/fire_explode.spr"

new const zclass_name[] = { "Ревенант Fire" } // name
new const zclass_info[] = { "\y|G| \r[VIP]" } // description
new const zclass_model[] = { "revenant" } // model
new const zclass_clawmodel[] = { "v_revenant.mdl" } // claw model
const zclass_health = 9000 // health
const zclass_speed = 320 // speed
const Float:zclass_gravity = 0.6 // gravity
const Float:zclass_knockback = 1.1 // knockback

#define OFFSET_MODELINDEX 491
#define OFFSET_LINUX 5 

new index, defaultindex

new sprFlame, sprSmoke

new g_zclassdragon
new cvar_dragondmg, cvar_dragondelay, cvar_dragonvelocity, cvar_dragonballhealth, cvar_dragonballradius, cvar_dragonballpower, cvar_burndmg, cvar_burntime, cvar_burn
new g_msgScreenShake, g_smoke, sTrail, ball_firesprite, ball_spriteexplode, g_explode[512], g_can[33], g_msgScoreInfo, g_roundend, bool:g_AlreadyBurn[33], Time[33]

public plugin_init()
{
	register_plugin("[ZP] Zombie Class: Dragon Zombie", "0.1", "=), LARS-BLOODLIKER")

	cvar_dragondelay = register_cvar("zp_classdragon_delay","10")
	cvar_dragondmg = register_cvar("zp_classdragonball_dmg","50.0")
	cvar_dragonvelocity = register_cvar("zp_classdragonball_velocity","1200")
	cvar_dragonballhealth = register_cvar("zp_classdragonball_health","1.0")
	cvar_dragonballradius = register_cvar("zp_classdragonball_radius","300.0")
	cvar_dragonballpower = register_cvar ( "zp_classdragonball_power", "800" )
	cvar_burn = register_cvar ( "zp_classdragonball_enable", "1" )
	cvar_burntime = register_cvar ( "zp_classdragonball_burntime", "5" )
	cvar_burndmg = register_cvar ( "zp_classdragonball_burndmg", "25" )

	register_touch(ball_name, "worldspawn",		"touchWorld")
	register_touch(ball_name, "func_wall",			"touchWorld")
	register_touch(ball_name, "func_door",			"touchWorld")
	register_touch(ball_name, "func_door_rotating", "touchWorld")
	register_touch(ball_name, "func_wall_toggle",	"touchWorld")
	register_touch(ball_name, "func_breakable",	"touchWorld")
	register_think(ball_name,"ball_think")

	register_clcmd("drop","dragon_cmd")
	register_event("HLTV", "event_round_start", "a", "1=0", "2=0")

	RegisterHam(Ham_Killed, "player", "fw_PlayerKilled")

	g_msgScoreInfo = get_user_msgid("ScoreInfo")
	g_msgScreenShake = get_user_msgid("ScreenShake")
}

public plugin_precache()
{
	precache_model(ball_model)
	g_smoke = precache_model("sprites/steam1.spr")
	sTrail = precache_model("sprites/arena/tok.spr")
	ball_firesprite = precache_model(ball_firespritemdl)
	ball_spriteexplode  = precache_model(ball_spriteexplodemdl)

	sprFlame = precache_model("sprites/flame.spr")
	sprSmoke = precache_model("sprites/black_smoke3.spr")

	g_zclassdragon = zp_register_zombie_class(zclass_name, zclass_info, zclass_model, zclass_clawmodel, zclass_health, zclass_speed, zclass_gravity, zclass_knockback)	

	index = precache_model("models/player/revenant/revenant.mdl")
    	defaultindex = precache_model("models/player.mdl")
}

public dragon_cmd( id )
{
	if(!is_user_alive(id) || !zp_get_user_zombie(id) || zp_get_user_zombie_class(id) != g_zclassdragon || zp_get_user_nemesis(id))
		return PLUGIN_CONTINUE

	if(g_can[id]) 
	{
		client_print(id,print_center,"Востановление через %d секунд",g_can[id])
		return PLUGIN_HANDLED
	}

	static Float:origin[3], Float:angles[3], Float:v_forward[3], Float:v_right[3], Float:v_up[3], Float:gun_position[3], Float:player_origin[3], Float:player_view_offset[3];
	static Float:OriginX[3]
	pev(id, pev_v_angle, angles)
	pev(id, pev_origin, OriginX)
	engfunc(EngFunc_MakeVectors, angles)

	global_get(glb_v_forward, v_forward)
	global_get(glb_v_right, v_right)
	global_get(glb_v_up, v_up)

	pev(id, pev_origin, player_origin)
	pev(id, pev_view_ofs, player_view_offset)
	xs_vec_add(player_origin, player_view_offset, gun_position)

	xs_vec_mul_scalar(v_forward, 13.0, v_forward)
	xs_vec_mul_scalar(v_right, 0.0, v_right)
	xs_vec_mul_scalar(v_up, 5.0, v_up)

	xs_vec_add(gun_position, v_forward, origin)
	xs_vec_add(origin, v_right, origin)
	xs_vec_add(origin, v_up, origin)

	new Float:StartOrigin[3]
			
	StartOrigin[0] = origin[0]
	StartOrigin[1] = origin[1]
	StartOrigin[2] = origin[2]

	new Float:fVelocity[3] , Float:flOrigin[3] , Float:flAngle[3]
	pev(id,pev_origin,flOrigin)
	pev(id,pev_angles,flAngle)

	new ball = create_entity("info_target")
	
	if(!ball) return PLUGIN_HANDLED

	g_explode[ball] = 0
	
	entity_set_string(ball, EV_SZ_classname, ball_name)
	
	entity_set_model(ball, ball_model)
	
	entity_set_origin(ball, StartOrigin)
	
	entity_set_vector(ball, EV_VEC_angles, flAngle)
	
	new Float:MinBox[3] = {-1.0, -1.0, -1.0}
	new Float:MaxBox[3] = {1.0, 1.0, 1.0}
	entity_set_vector(ball, EV_VEC_mins, MinBox)
	entity_set_vector(ball, EV_VEC_maxs, MaxBox)
	
	entity_set_int(ball, EV_INT_solid, SOLID_SLIDEBOX)
	
	entity_set_int(ball, EV_INT_movetype, MOVETYPE_TOSS)
	
	entity_set_edict(ball, EV_ENT_owner, id)
	
	entity_set_int(ball, EV_INT_effects, EF_BRIGHTLIGHT)
	
	VelocityByAim(id, get_pcvar_num(cvar_dragonvelocity), fVelocity)
	entity_set_vector(ball , EV_VEC_velocity, fVelocity)
	
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte(TE_BEAMFOLLOW) // Temporary entity ID
	write_short(ball) // Entity
	write_short(sTrail) // Sprite index
	write_byte(10) // Life
	write_byte(3) // Line width
	write_byte(255) // Red
	write_byte(150) // Green
	write_byte(20) // Blue
	write_byte(255) // Alpha
	message_end() 

	entity_set_int(id, EV_INT_sequence, 10)
	//UTIL_PlayPlayerAnimation(id,10)
	UTIL_PlayWeaponAnimation(id,8)

	g_can[id] = get_pcvar_num(cvar_dragondelay)
	set_task(1.0,"ability_zero",id)

	entity_set_float(ball, EV_FL_health , get_pcvar_float(cvar_dragonballhealth))

	entity_set_float(ball, EV_FL_nextthink, get_gametime() + 0.1) 
	
	return PLUGIN_HANDLED
}

public touchWorld(ball, world) 
{
	new Float:v[3]
	entity_get_vector(ball, EV_VEC_velocity, v)

	v[0] = (v[0] * 0.85)
	v[1] = (v[1] * 0.85)
	v[2] = (v[2] * 0.85)
	entity_set_vector(ball, EV_VEC_velocity, v)
	
	return PLUGIN_HANDLED
}

public event_round_start()
{
	new iEnt = FM_NULLENT
	while((iEnt = engfunc(EngFunc_FindEntityByString, iEnt, "classname", ball_name)) > 0)
	{
		engfunc(EngFunc_RemoveEntity,iEnt)
	}	
	for(new i;i<=32;i++)
	{
		remove_task(i)
		g_can[i] = 0
		Time[i] = 0 
		g_AlreadyBurn[i] = false
	}
	g_roundend = 0
}

public ball_think(ball)
{
	if(!is_valid_ent(ball))
		return

	new Float:oldangles[3],Float:angles[3]
	pev(ball,pev_angles,oldangles)
	angles[0] = oldangles[0] + random_float(20.0,100.0)
	angles[1] = oldangles[1] + random_float(10.0,80.0)
	angles[2] = oldangles[2] + random_float(10.0,80.0)
	set_pev(ball,pev_angles,angles)

	new Float:v[3]
	entity_get_vector(ball, EV_VEC_velocity, v)

	if(v[2] < 40.0 && v[1] < 40.0 && v[0] < 40.0) 
	{
		if(!g_explode[ball])
		{
			set_task(0.5,"firesprite_ball",ball)
			g_explode[ball] = 1
		}

		entity_set_float(ball, EV_FL_health, entity_get_float(ball,EV_FL_health) - 0.2) 

		if(entity_get_float(ball,EV_FL_health) <= 0.0) 
		{
			ball_explode(ball)
			remove_entity(ball)
			g_explode[ball] = 0
			return;
		}
	}
	entity_set_float(ball, EV_FL_nextthink, get_gametime() + 0.1) 
}

public firesprite_ball(ball)
{
	if(!is_valid_ent(ball))
		return

	new Float:flOrigin[3]
	pev(ball,pev_origin,flOrigin)

	engfunc ( EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, flOrigin, 0 )
	write_byte ( TE_SPRITE )
	engfunc ( EngFunc_WriteCoord, flOrigin [ 0 ] )
	engfunc ( EngFunc_WriteCoord, flOrigin [ 1 ] )
	engfunc ( EngFunc_WriteCoord, flOrigin [ 2 ] + 45.0 )
	write_short ( ball_firesprite )
	write_byte ( 5 )
	write_byte ( 185 )
	message_end ( )

	message_begin( MSG_BROADCAST, SVC_TEMPENTITY )
	write_byte( TE_SMOKE );
	engfunc ( EngFunc_WriteCoord, flOrigin [ 0 ] )
	engfunc ( EngFunc_WriteCoord, flOrigin [ 1 ] )
	engfunc ( EngFunc_WriteCoord, flOrigin [ 2 ] + 45.0 )
	write_short( g_smoke );
	write_byte( 10 );
	write_byte( 10 );
	message_end();

	if(entity_get_float(ball,EV_FL_health) >= 1.0) set_task(0.5,"firesprite_ball",ball)
}
public ball_explode ( Entity )
{
	if ( Entity < 0 )
		return
       
	static Float:flOrigin [ 3 ]
	pev ( Entity, pev_origin, flOrigin )
       
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte(TE_EXPLOSION) // Temporary entity ID
	engfunc(EngFunc_WriteCoord, flOrigin[0]) // engfunc because float
	engfunc(EngFunc_WriteCoord, flOrigin[1])
	engfunc(EngFunc_WriteCoord, flOrigin[2])
	write_short(ball_spriteexplode) // Sprite index
	write_byte(50) // Scale
	write_byte(15) // Framerate
	write_byte(0) // Flags
	message_end()
	
     	new iOwner = entity_get_edict ( Entity, EV_ENT_owner )
       
      	for ( new i = 1; i <= 32 ; i++ )
	{
		if ( !is_user_alive  ( i ) || zp_get_user_zombie( i ))
			continue
          
		new Float:flVictimOrigin [ 3 ]
		pev ( i, pev_origin, flVictimOrigin )
           
		new Float:flDistance = get_distance_f ( flOrigin, flVictimOrigin )   
           
		if ( flDistance <= get_pcvar_float(cvar_dragonballradius) )
		{
			static Float:flSpeed
			flSpeed = get_pcvar_float ( cvar_dragonballpower )
               
			static Float:flNewSpeed
			flNewSpeed = flSpeed * ( 1.0 - ( flDistance / get_pcvar_float(cvar_dragonballradius) ) )
               
			static Float:flVelocity [ 3 ]
			get_speed_vector ( flOrigin, flVictimOrigin, flNewSpeed, flVelocity )
               
			set_pev ( i, pev_velocity,flVelocity )

			message_begin(MSG_ONE, g_msgScreenShake, {0,0,0}, i)
			write_short(1<<14) // Amount
			write_short(1<<14) // Duration
			write_short(1<<14) // Frequency
			message_end()

			radius_damage_ab( flVictimOrigin, flOrigin , i , iOwner)

			if(!g_AlreadyBurn[ i ] && get_pcvar_num(cvar_burn ) == 1 ) 
			{
				// Burn / ON
				g_AlreadyBurn[ i ] = true
		
				// Set burn time
				Time[ i ] = get_pcvar_num(cvar_burntime)
		
				// Burn victim
				Burn( i )
			}
		}
	}
}       

public radius_damage_ab(Float:originF[3] , Float:flOrigin[3] , iVictim , iAttacker)
{
	if(g_roundend || !is_user_connected(iAttacker) || !is_user_connected(iVictim))
		return;

	new Float:dist = get_distance_f(originF, flOrigin);
	new Float:dmg = get_pcvar_float(cvar_dragondmg) - ( get_pcvar_float(cvar_dragondmg) / get_pcvar_float(cvar_dragonballradius) ) * dist;

	if(pev(iVictim,pev_health) - dmg <= 0) 
	{
		new headshot
		if(dist < 20.0) headshot = 1
		if(dist >= 20.0) headshot = 0
		message_begin( MSG_ALL, get_user_msgid("DeathMsg"),{0,0,0},0)
		write_byte(iAttacker)
		write_byte(iVictim)
		write_byte(headshot)
		write_string("dragon")
		message_end()

		user_silentkill(iVictim)

		set_pev(iAttacker, pev_frags, float(pev(iAttacker, pev_frags) + 1))
		zp_set_user_ammo_packs(iAttacker, zp_get_user_ammo_packs(iAttacker) + 1)
		fm_cs_set_user_deaths(iVictim, cs_get_user_deaths(iVictim) + 1)

		message_begin(MSG_BROADCAST, g_msgScoreInfo)
		write_byte(iAttacker) // id
		write_short(pev(iAttacker, pev_frags)) // frags
		write_short(cs_get_user_deaths(iAttacker)) // deaths
		write_short(0) // class?
		write_short(fm_cs_get_user_team(iAttacker)) // team
		message_end()
		
		message_begin(MSG_BROADCAST, g_msgScoreInfo)
		write_byte(iVictim) // id
		write_short(pev(iVictim, pev_frags)) // frags
		write_short(cs_get_user_deaths(iVictim)) // deaths
		write_short(0) // class?
		write_short(fm_cs_get_user_team(iVictim)) // team
		message_end()

	}else{
		if(dmg > 0) set_pev(iVictim , pev_health , pev(iVictim,pev_health) - dmg)
		if(dmg <= 0) set_pev(iVictim , pev_health , pev(iVictim,pev_health) + dmg)
	}
}

public remove_values(id)
{
	remove_task(id)
	g_can[id] = 0
}

public ability_zero(id) 
{
	g_can[id] -= 1
	if(!g_can[id]) client_print(id,print_center,"Способность активна!")
	if(g_can[id]) set_task(1.0,"ability_zero",id)
}

public Burn( victim )
{
	// Get user origin
	static Origin[ 3 ] ; get_user_origin( victim, Origin )
	
	// If burn time is over or victim are in water
	if( Time[ victim ] <= 0 || get_entity_flags( victim ) & FL_INWATER )
	{	
		// Show Smoke sprite	
		message_begin( MSG_PVS, SVC_TEMPENTITY, Origin )
		write_byte( TE_SMOKE ) // TE id
		write_coord( Origin[0] ) // x
		write_coord( Origin[1] ) // y
		write_coord( Origin[2]-50 ) // z
		write_short( sprSmoke ) // sprite
		write_byte( random_num(15, 20) ) // scale
		write_byte( random_num(10, 20) ) // framerate
		message_end( )
		
		// Delay to allow burn again
		set_task( float(get_pcvar_num(cvar_burntime)), "Stop", victim )
		
		// Exit
		return
	}
	else
	{		
		// Flame sprite	
		message_begin( MSG_PVS, SVC_TEMPENTITY, Origin )
		write_byte( TE_SPRITE ) // TE id
		write_coord( Origin[0]+random_num(-5, 5) ) // x
		write_coord( Origin[1]+random_num(-5, 5) ) // y
		write_coord( Origin[2]+random_num(-10, 10) ) // z
		write_short( sprFlame ) // sprite
		write_byte( random_num(5, 10) ) // scale
		write_byte( 200 ) // brightness
		message_end( )
			
		// Decrease Time
		Time[ victim ]--
		
		// Decrease life (random)
		if(get_user_health(victim) -  get_pcvar_num(cvar_burndmg) > 0) set_user_health( victim, get_user_health( victim ) -  get_pcvar_num(cvar_burndmg))
		
		// Stop fire if health <= min health.
		if( get_user_health( victim ) <=  get_pcvar_num(cvar_burndmg))
		{
			g_AlreadyBurn[ victim ] = false
			return
		}
		
		// Repeat
		set_task( 0.5, "Burn", victim )
	}
}

public Stop( victim )
	g_AlreadyBurn[ victim ] = false // Allow burn again

public zp_user_humanized_post(id) 
{
	fm_set_user_model_index(id, defaultindex)

	remove_values(id)
}
public fw_PlayerKilled(id, attacker, shouldgib) remove_values(id)
public client_connect(id)  remove_values(id)
public zp_round_ended() g_roundend = 1

public zp_user_infected_post(id)	
{
	if((zp_get_user_zombie_class(id) == g_zclassdragon) && (zp_get_user_zombie(id)))
	{
		fm_set_user_model_index(id, index)
	}
	Time[ id ] = 0 
	g_AlreadyBurn[ id ] = false
	remove_task(id)
}

public zp_user_infected_pre(id) 
{ 
    if(!(get_user_flags(id) & ADMIN_RESERVATION)) 
	{ 
        if(zp_get_user_next_class(id) == g_zclassdragon) 
		{ 
            zp_set_user_zombie_class(id, 0) 
        }     
    }	 
} 

stock UTIL_PlayWeaponAnimation(const Player, const Sequence)
{
	set_pev(Player, pev_weaponanim, Sequence)
	
	message_begin(MSG_ONE_UNRELIABLE, SVC_WEAPONANIM, .player = Player)
	write_byte(Sequence)
	write_byte(pev(Player, pev_body))
	message_end()
}

stock UTIL_PlayPlayerAnimation(const id, const Sequence , Float:frame = 1.0 , Float:framerate = 1.0)
{
	entity_set_int(id, EV_INT_sequence, Sequence)
	entity_set_int(id, EV_INT_gaitsequence, 1)
	entity_set_float(id, EV_FL_frame, frame)
	entity_set_float(id, EV_FL_framerate, framerate)
}

stock get_speed_vector(const Float:origin1[3],const Float:origin2[3],Float:speed, Float:new_velocity[3])
{
	new_velocity[0] = origin2[0] - origin1[0]
	new_velocity[1] = origin2[1] - origin1[1]
	new_velocity[2] = origin2[2] - origin1[2]
	new Float:num = floatsqroot(speed*speed / (new_velocity[0]*new_velocity[0] + new_velocity[1]*new_velocity[1] + new_velocity[2]*new_velocity[2]))
	new_velocity[0] *= num
	new_velocity[1] *= num
	new_velocity[2] *= num
       
	return 1;
} 

stock fm_cs_set_user_deaths(id, value)
{
	set_pdata_int(id, 444, value, 5)
}

stock fm_cs_get_user_team(id)
{
	return get_pdata_int(id, 114, 5);
}

stock fm_set_user_model_index(id, value)
{
    set_pdata_int(id, OFFSET_MODELINDEX, value, OFFSET_LINUX)
}  
cso_class_siren.sma

Code: Select all

#pragma tabsize 0
#include <amxmodx>
#include <engine>
#include <fakemeta>
#include <fun>
#include <xs>
#include <hamsandwich>
#include <zombieplague>

/*================================================================================
 [Customizations]
=================================================================================*/

// Zombie Attributes
new const zclass_name[] = "Сирена" // name
new const zclass_info[] = "\rКрик \y|E|" // description
new const zclass_model[] = "zombie_siners" // model
new const zclass_clawmodel[] = "v_knife_siners.mdl" // claw model
new const zclass_ring_sprite[] = "sprites/shockwave.spr" // ring sprite
new const zclass_screamsounds[][] = { "zombie_plague/siren_scream.wav" } // scream sound

// Scream ring color		R	G	B
new zclass_ring_colors[3] = {	255,	0,	0	}

const zclass_health = 5500 // health
const zclass_speed = 235 // speed

const Float:zclass_gravity = 0.6 // gravity
const Float:zclass_knockback = 2.0 // knockback

/*================================================================================
 Customization ends here! Yes, that's it. Editing anything beyond
 here is not officially supported. Proceed at your own risk...
=================================================================================*/

// Variables
new g_iSirenZID, g_iMaxPlayers, g_msgSayText, g_msgScreenFade, g_msgScreenShake,
g_msgBarTime, g_sprRing

// Arrays
new g_iPlayerTaskTimes[33]

// Cvar pointers
new cvar_screammode, cvar_duration, cvar_screamdmg, cvar_startime, cvar_reloadtime,
cvar_radius, cvar_damagemode, cvar_slowdown

// Cached cvars
new g_iCvar_ScreamMode, g_iCvar_ScreamDuration, g_iCvar_ScreamDmg, 
g_iCvar_ScreamStartTime, Float:g_flCvar_ReloadTime, Float:g_flCvar_Radius,
g_iCvar_DamageMode, Float:g_flCvar_ScreamSlowdown

// Bools
new bool:g_bIsConnected[33], bool:g_bIsAlive[33], bool:g_bInScreamProcess[33], 
bool:g_bCanDoScreams[33], bool:g_bKilledByScream[33], bool:g_bDoingScream[33], 
bool:g_bRoundEnding

// Some constants
const FFADE_IN = 		0x0000
const GIB_NEVER =		0
const UNIT_SECOND = 		(1<<12)
const TASK_SCREAM =		37729
const TASK_RELOAD =		55598
const TASK_SCREAMDMG =		48289
const NADE_TYPE_INFECTION = 	1111

// Plug info.
#define PLUG_VERSION "0.2"
#define PLUG_AUTH "meTaLiCroSS"

// Macros
#define zp_get_grenade_type(%1)		(entity_get_int(%1, EV_INT_flTimeStepSound))
#define is_user_valid_alive(%1) 	(1 <= %1 <= g_iMaxPlayers && g_bIsAlive[%1])
#define is_user_valid_connected(%1) 	(1 <= %1 <= g_iMaxPlayers && g_bIsConnected[%1])

/*================================================================================
 [Init, CFG and Precache]
=================================================================================*/

public plugin_init()
{
	// Plugin Info
	register_plugin("[ZP] Zombie Class: KF Siren Zombie", PLUG_VERSION, PLUG_AUTH)
		
	// Main events
	register_event("HLTV", "event_RoundStart", "a", "1=0", "2=0")
	
	// Main messages
	register_message(get_user_msgid("DeathMsg"), "message_DeathMsg")
	
	// Fakemeta Forwards
	register_forward(FM_CmdStart, "fw_CmdStart")
	
	// Hamsandwich Forward
	RegisterHam(Ham_Killed, "player", "fw_PlayerKilled")
	RegisterHam(Ham_Spawn, "player", "fw_PlayerSpawn_Post", 1)
	
	// Cvars
	cvar_screammode = register_cvar("zp_siren_mode", "0")
	cvar_duration = register_cvar("zp_siren_scream_duration", "3")
	cvar_screamdmg = register_cvar("zp_siren_scream_damage", "2")
	cvar_startime = register_cvar("zp_siren_scream_start_time", "1")
	cvar_reloadtime = register_cvar("zp_siren_scream_reload_time", "30.0")
	cvar_radius = register_cvar("zp_siren_scream_radius", "250.0")
	cvar_damagemode = register_cvar("zp_siren_damage_mode", "0")
	cvar_slowdown = register_cvar("zp_siren_damage_slowdown", "0.5")
	
	static szCvar[30]
	formatex(szCvar, charsmax(szCvar), "v%s by %s", PLUG_VERSION, PLUG_AUTH)
	register_cvar("zp_zclass_siren", szCvar, FCVAR_SERVER|FCVAR_SPONLY) 
	
	// Vars
	g_iMaxPlayers = get_maxplayers()
	g_msgBarTime = get_user_msgid("BarTime")
	g_msgSayText = get_user_msgid("SayText")
	g_msgScreenFade = get_user_msgid("ScreenFade")
	g_msgScreenShake = get_user_msgid("ScreenShake")
}

public plugin_cfg()
{
	// Cache some cvars
	cache_cvars()
}

public plugin_precache()
{
	// Register the new class and store ID for reference
	g_iSirenZID = zp_register_zombie_class(zclass_name, zclass_info, zclass_model, zclass_clawmodel, zclass_health, zclass_speed, zclass_gravity, zclass_knockback)	
	
	// Ring sprite
	g_sprRing = precache_model(zclass_ring_sprite)
	
	// Sounds
	static i
	for(i = 0; i < sizeof zclass_screamsounds; i++)
		precache_sound(zclass_screamsounds[i])
}

/*================================================================================
 [Main Events/Messages]
=================================================================================*/

public event_RoundStart()
{
	// Caching cvars
	cache_cvars()
	
	// Reset round end bar
	g_bRoundEnding = false
}

public message_DeathMsg(msg_id, msg_dest, id)
{
	static iAttacker, iVictim
	
	// Get attacker and victim
	iAttacker = get_msg_arg_int(1)
	iVictim = get_msg_arg_int(2)
	
	// Non-player attacker or self kill
	if(!is_user_connected(iAttacker) || iAttacker == iVictim)
		return PLUGIN_CONTINUE
		
	// Killed by siren scream
	if(g_bKilledByScream[iVictim])
		set_msg_arg_string(4, "siren scream")
		
	return PLUGIN_CONTINUE
}

/*================================================================================
 [Main Forwards]
=================================================================================*/

public client_putinserver(id)
{
	// Updating bool
	g_bIsConnected[id] = true
}

public client_disconnect(id)
{
	// Updating bool
	g_bIsAlive[id] = false
	g_bIsConnected[id] = false
}

public fw_PlayerSpawn_Post(id)
{
	// Not alive...
	if(!is_user_alive(id))
		return HAM_IGNORED
		
	// Player is alive
	g_bIsAlive[id] = true
	
	// Reset player vars and tasks
	stop_scream_task(id)
	
	g_bCanDoScreams[id] = false
	g_bDoingScream[id] = false
	g_iPlayerTaskTimes[id] = 0
	
	remove_task(id+TASK_RELOAD)
	remove_task(id+TASK_SCREAMDMG)
	
	return HAM_IGNORED
}

public fw_PlayerKilled(victim, attacker, shouldgib)
{
	// Player victim
	if(is_user_valid_connected(victim))
	{
		// Victim is not alive
		g_bIsAlive[victim] = false
		
		// Reset player vars and tasks
		stop_scream_task(victim)
		
		g_bCanDoScreams[victim] = false
		g_bDoingScream[victim] = false
		g_iPlayerTaskTimes[victim] = 0
		
		remove_task(victim+TASK_RELOAD)
		remove_task(victim+TASK_SCREAMDMG)
		
		return HAM_HANDLED
	}
	
	return HAM_IGNORED
}

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;
		
	// Invalid class id
	if(zp_get_user_zombie_class(id) != g_iSirenZID)
		return FMRES_IGNORED;
		
	// 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_bCanDoScreams[id] && !g_bDoingScream[id] && !g_bRoundEnding)
		{
			// A bar appears in his screen
			message_begin(MSG_ONE, g_msgBarTime, _, id)
			write_byte(g_iCvar_ScreamStartTime) // time
			write_byte(0) // unknown
			message_end()
			
			// Update bool
			g_bInScreamProcess[id] = true
			
			// Next scream time
			set_task(g_iCvar_ScreamStartTime + 0.2, "task_do_scream", id+TASK_SCREAM)
			
			return FMRES_HANDLED
		}
	}
	else
	{
		// Last used button it's +use
		if(iInUseOldButton && g_bInScreamProcess[id])
		{
			// Stop scream main task
			stop_scream_task(id)
			
			return FMRES_HANDLED
		}
	}
	
	return FMRES_IGNORED
}

/*================================================================================
 [Tasks]
=================================================================================*/

public task_do_scream(id)
{
	// Normalize task
	id -= TASK_SCREAM
	
	// Do scream sound
	emit_sound(id, CHAN_STREAM, zclass_screamsounds[random_num(0, sizeof zclass_screamsounds - 1)], 1.0, ATTN_NORM, 0, PITCH_NORM)
	
	// Block screams
	g_bCanDoScreams[id] = false
	
	// Reload task
	set_task(g_flCvar_ReloadTime, "task_reload_scream", id+TASK_RELOAD)
	
	// Now it's doing an scream
	g_bDoingScream[id] = true
	
	// Get his origin coords
	static iOrigin[3]
	get_user_origin(id, iOrigin)
	
	// Do a good effect, life the original Killing Floor.
	message_begin(MSG_PVS, SVC_TEMPENTITY, iOrigin) 
	write_byte(TE_LAVASPLASH)
	write_coord(iOrigin[0]) 
	write_coord(iOrigin[1]) 
	write_coord(iOrigin[2]) 
	message_end()
	
	// Scream damage task
	set_task(0.1, "task_scream_process", id+TASK_SCREAMDMG, _, _, "b")
}

public task_reload_scream(id)
{
	// Normalize taks
	id -= TASK_RELOAD
	
	// Can do screams again
	g_bCanDoScreams[id] = true
	
	// Message
	client_printcolor(id, "/g[ZP]/y Ready, you can do /gScreams/y again")
	client_printcolor(id, "/g[ZP]/y Remember, press the /g^"+use^"/y Button to do an /gScreams/y")
}

public task_scream_process(id)
{
	// Normalize task
	id -= TASK_SCREAMDMG
	
	// Time exceed
	if(g_iPlayerTaskTimes[id] >= (g_iCvar_ScreamDuration*10) || g_bRoundEnding)
	{
		// Remove player task
		remove_task(id+TASK_SCREAMDMG)
		
		// Reset task times count
		g_iPlayerTaskTimes[id] = 0
		
		// Update bool
		g_bDoingScream[id] = false
		
		return;
	}
	
	// Update player task time
	g_iPlayerTaskTimes[id]++
	
	// Get player origin
	static Float:flOrigin[3]
	entity_get_vector(id, EV_VEC_origin, flOrigin)
	
	// Collisions
	static iVictim
	iVictim = -1
	
	// Vector var
	static Float:flVictimOrigin[3]
	
	// A ring effect
	engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, flOrigin, 0)
	write_byte(TE_BEAMCYLINDER) // TE id
	engfunc(EngFunc_WriteCoord, flOrigin[0]) // x
	engfunc(EngFunc_WriteCoord, flOrigin[1]) // y
	engfunc(EngFunc_WriteCoord, flOrigin[2]) // z
	engfunc(EngFunc_WriteCoord, flOrigin[0]) // x axis
	engfunc(EngFunc_WriteCoord, flOrigin[1]) // y axis
	engfunc(EngFunc_WriteCoord, flOrigin[2] + g_flCvar_Radius) // z axis
	write_short(g_sprRing) // sprite
	write_byte(0) // startframe
	write_byte(0) // framerate
	write_byte(10) // life
	write_byte(25) // width
	write_byte(0) // noise
	write_byte(zclass_ring_colors[0]) // red
	write_byte(zclass_ring_colors[1]) // green
	write_byte(zclass_ring_colors[2]) // blue
	write_byte(200) // brightness
	write_byte(0) // speed
	message_end()
	
	// Screen effects for him self
	screen_effects(id)
	
	// Do scream effects
	while((iVictim = find_ent_in_sphere(iVictim, flOrigin, g_flCvar_Radius)) != 0)
	{
		// Non-player entity
		if(!is_user_valid_connected(iVictim))
		{
			// Validation check
			if(is_valid_ent(iVictim))
			{
				// Get entity classname
				static szClassname[33]
				entity_get_string(iVictim, EV_SZ_classname, szClassname, charsmax(szClassname))
				
				// It's a grenade, and isn't an Infection Bomb
				if(equal(szClassname, "grenade") && zp_get_grenade_type(iVictim) != NADE_TYPE_INFECTION)
				{
					// Get grenade origin
					entity_get_vector(iVictim, EV_VEC_origin, flVictimOrigin)
					
					// Do a good effect
					engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, flVictimOrigin, 0)
					write_byte(TE_PARTICLEBURST) // TE id
					engfunc(EngFunc_WriteCoord, flVictimOrigin[0]) // x
					engfunc(EngFunc_WriteCoord, flVictimOrigin[1]) // y
					engfunc(EngFunc_WriteCoord, flVictimOrigin[2]) // z
					write_short(45) // radius
					write_byte(108) // particle color
					write_byte(10) // duration * 10 will be randomized a bit
					message_end()
					
					// Remove it
					remove_entity(iVictim)
				}
				// If i don't check his solid type, it's used all the time.
				else if(equal(szClassname, "func_breakable") && entity_get_int(iVictim, EV_INT_solid) != SOLID_NOT)
				{
					// Destroy entity if he can
					force_use(id, iVictim)
				}
			}
			
			continue;
		}
			
		// Not alive, zombie or with Godmode
		if(!g_bIsAlive[iVictim] || zp_get_user_zombie(iVictim) || get_user_godmode(iVictim))
			continue;
			
		// Screen effects for victims
		screen_effects(iVictim)
			
		// Get scream mode
		switch(g_iCvar_ScreamMode)
		{
			// Do damage
			case 0:
			{
				// Scream slowdown, first should be enabled
				if(g_flCvar_ScreamSlowdown > 0.0)
				{
					// Get his current velocity vector
					static Float:flVelocity[3]
					get_user_velocity(iVictim, flVelocity)
					
					// Multiply his velocity by a number
					xs_vec_mul_scalar(flVelocity, g_flCvar_ScreamSlowdown, flVelocity)
					
					// Set his new velocity vector
					set_user_velocity(iVictim, flVelocity)	
				}
				
				// Get damage result
				static iNewHealth
				iNewHealth = max(0, get_user_health(iVictim) - g_iCvar_ScreamDmg)
				
				// Does not has health
				if(!iNewHealth)
				{
					// Be infected when it's going to die
					if(g_iCvar_DamageMode /* == 1*/)
					{
						// Returns 1 on sucess...
						if(zp_infect_user(iVictim, id, 0, 1))
							continue
					}
	
					// Kill it
					scream_kill(iVictim, id)
					
					continue
				}
				
				// Do fake damage
				set_user_health(iVictim, iNewHealth)
			}
			
			// Instantly Infect
			case 1:
			{
				// Can be infected?
				if(!zp_infect_user(iVictim, id, 0, 1))
				{
					// Kill it
					scream_kill(iVictim, id)
				}
			}
			
			// Instantly Kill
			case 2:
			{
				// Kill it
				scream_kill(iVictim, id)
			}
		}
			
	}
}

/*================================================================================
 [Zombie Plague Forwards]
=================================================================================*/

public zp_user_infected_post(id, infector)
{
	// It's the selected zombie class
	if(zp_get_user_zombie_class(id) == g_iSirenZID && !zp_get_user_nemesis(id))
	{
		// Array
		g_bCanDoScreams[id] = true
		
		// Message
		client_printcolor(id, "/g[ZP]/y You can do /gScreams/y pressing the /g^"+use^"/y Button")
	}
}

public zp_user_humanized_post(id)
{
	// Reset player vars and tasks
	stop_scream_task(id)
	
	g_bCanDoScreams[id] = false
	g_bDoingScream[id] = false
	g_iPlayerTaskTimes[id] = 0
	
	remove_task(id+TASK_RELOAD)
	remove_task(id+TASK_SCREAMDMG)
}

public zp_round_ended(winteam)
{
	// Update bool
	g_bRoundEnding = true
	
	// Make a loop
	static id
	for(id = 1; id <= g_iMaxPlayers; id++)
	{
		// Valid connected
		if(is_user_valid_connected(id))
		{
			// Remove mainly tasks
			stop_scream_task(id)
			remove_task(id+TASK_RELOAD)
		}
	}
}

/*================================================================================
 [Internal Functions]
=================================================================================*/

stop_scream_task(id)
{
	// Remove the task
	if(task_exists(id+TASK_SCREAM)) 
	{
		remove_task(id+TASK_SCREAM)
	
		// Remove screen's bar
		message_begin(MSG_ONE, g_msgBarTime, _, id)
		write_byte(0) // time
		write_byte(0) // unknown
		message_end()
		
		// Update bool
		g_bInScreamProcess[id] = false
	}
}

screen_effects(id)
{
	// Screen Fade
	message_begin(MSG_ONE_UNRELIABLE, g_msgScreenFade, _, id)
	write_short(UNIT_SECOND*1) // duration
	write_short(UNIT_SECOND*1) // hold time
	write_short(FFADE_IN) // fade type
	write_byte(200) // r
	write_byte(0) // g
	write_byte(0) // b
	write_byte(125) // alpha
	message_end()
	
	// Screen Shake
	message_begin(MSG_ONE_UNRELIABLE, g_msgScreenShake, _, id)
	write_short(UNIT_SECOND*5) // amplitude
	write_short(UNIT_SECOND*1) // duration
	write_short(UNIT_SECOND*5) // frequency
	message_end()
}

cache_cvars()
{
	g_iCvar_ScreamMode = get_pcvar_num(cvar_screammode)
	g_iCvar_ScreamDuration = get_pcvar_num(cvar_duration)
	g_iCvar_ScreamDmg = get_pcvar_num(cvar_screamdmg)
	g_iCvar_ScreamStartTime = get_pcvar_num(cvar_startime)
	g_iCvar_DamageMode = get_pcvar_num(cvar_damagemode)
	g_flCvar_ReloadTime = floatmax(g_iCvar_ScreamDuration+0.0, get_pcvar_float(cvar_reloadtime))
	g_flCvar_Radius = get_pcvar_float(cvar_radius)
	g_flCvar_ScreamSlowdown = get_pcvar_float(cvar_slowdown)
}

scream_kill(victim, attacker)
{
	// To use later in DeathMsg event
	g_bKilledByScream[victim] = true
	
	// Do kill
	ExecuteHamB(Ham_Killed, victim, attacker, GIB_NEVER)
	
	// We don't need this
	g_bKilledByScream[victim] = false
}

/*================================================================================
 [Stocks]
=================================================================================*/

stock client_printcolor(id, const input[], any:...)
{
	static iPlayersNum[32], iCount; iCount = 1
	static szMsg[191]
	
	vformat(szMsg, charsmax(szMsg), input, 3)
	
	replace_all(szMsg, 190, "/g", "^4") // green txt
	replace_all(szMsg, 190, "/y", "^1") // orange txt
	replace_all(szMsg, 190, "/ctr", "^3") // team txt
	replace_all(szMsg, 190, "/w", "^0") // team txt
	
	if(id) iPlayersNum[0] = id
	else get_players(iPlayersNum, iCount, "ch")
		
	for (new i = 0; i < iCount; i++)
	{
		if (g_bIsConnected[iPlayersNum[i]])
		{
			message_begin(MSG_ONE_UNRELIABLE, g_msgSayText, _, iPlayersNum[i])
			write_byte(iPlayersNum[i])
			write_string(szMsg)
			message_end()
		}
	}
}
cso_class_stamper.sma

Code: Select all

#include <amxmodx>
#include <fakemeta>
#include <fakemeta_util>
#include <hamsandwich> 
#include <zombieplague> 
#include <xs> 

#define PLUGIN "Undertaker"
#define VERSION "1.0"
#define AUTHOR "DSHGFHDS"

#define SKILLMODEL "models/zombie_plague/zombiepile.mdl"
#define SKILLNAME "zombiecoffin"
#define SKILL_COFFIN 15214
#define TASK_COOLDAWN 1234
#define TASK_SKILLUSEING 2345
#define TASK_SKILLOVER 3456
#define TASK_ENTTHINK 4567
#define TASK_SPEEDTIME 5678

new const WEAPON_CLASSNAME[][] = { "", "weapon_p228", "", "weapon_scout", "weapon_hegrenade", "weapon_xm1014", "weapon_c4", "weapon_mac10",
	"weapon_aug", "weapon_smokegrenade", "weapon_elite", "weapon_fiveseven", "weapon_ump45", "weapon_sg550",
	"weapon_galil", "weapon_famas", "weapon_usp", "weapon_glock18", "weapon_awp", "weapon_mp5navy", "weapon_m249",
	"weapon_m3", "weapon_m4a1", "weapon_tmp", "weapon_g3sg1", "weapon_flashbang", "weapon_deagle", "weapon_sg552",
"weapon_ak47", "weapon_knife", "weapon_p90" }

new const zclass_name[] = { "Стампер" }
new const zclass_info[] = { "\rГроб \y|G|" }
new const zclass_model[] = { "zombie_stamper" }
new const zclass_clawmodel[] = { "v_zm_undertaker.mdl" }
new const zclass_hemodel[] = { "models/zombie_plague/v_he_undertaker.mdl" }
new const zclass_health = 5400
new const zclass_speed = 260
new const Float:zclass_gravity = 0.8
new const Float:zclass_knockback = 1.5
new const setcoffinsound[] = "zombie_plague/zombi_stamper_iron_maiden_stamping.wav"
new const coffinexsound[] = "zombie_plague/zombi_stamper_iron_maiden_explosion.wav"
new g_zclass_undertaker, g_shokewaveSpr, humanspr, zm_zombiebomb
new skillcooldawn[33], skilluseing[33], setmaxspeed[33], sprremove[33], knifehit[33], removesdamage[33], removeknock[33]
new cvar_skillcooldawntime, cvar_skillhealth, cvar_coffintime, cvar_exrange, cvar_exknock, cvar_speedtime, cvar_maxspeed, cvar_bot_use_skill, cvar_exdamage, cvar_exhit
enum 
{
anim_idle,
anim_slash1,
anim_skill,
anim_daw,
anim_stab,
anim_stab_miss,
anim_midslash1,
anim_midslash2,
}
const DMG_HEGRENADE = (1<<24)
public plugin_init() 
{
        register_forward(FM_EmitSound, "fw_EmitSound")
	register_plugin(PLUGIN, VERSION, AUTHOR)
	register_clcmd("drop","makecoffin")
	register_event("CurWeapon", "Event_CurWeapon", "be", "1=1")
	RegisterHam(Ham_Killed, "player", "player_death",1)
	for (new i = 0; i < sizeof WEAPON_CLASSNAME; i++)
	{
	if (strlen(WEAPON_CLASSNAME[i]) <= 0)
	continue; 
	RegisterHam(Ham_Item_Deploy, WEAPON_CLASSNAME[i], "fwItemDeploy_Post", 1)
	}
	RegisterHam(Ham_Weapon_SecondaryAttack, "weapon_knife", "fw_Weapon_SecondaryAttack")
	RegisterHam(Ham_Weapon_SecondaryAttack, "weapon_knife", "fw_Weapon_SecondaryAttack_Post", 1)
	RegisterHam(Ham_TakeDamage, "info_target", "fw_TakeDamage")
	RegisterHam(Ham_TakeDamage, "player", "fw_TakeDamageplayer")
	RegisterHam(Ham_TraceAttack, "info_target", "fw_TraceAttack")
	RegisterHam(Ham_TraceAttack, "player", "fw_TraceAttackplayer")
	register_forward(FM_CmdStart, "forward_CmdStart", 1)
	register_forward(FM_PlayerPreThink, "fw_PlayerPreThink")
	register_forward(FM_PlayerPostThink, "fw_PlayerPostThink" , 1)
	register_forward(FM_UpdateClientData, "UpdateClientData_Post", 1) 
	cvar_skillcooldawntime = register_cvar("zp_undertaker_cooldawn","8.0") //技能冷却时间
	cvar_skillhealth = register_cvar("zp_undertaker_skillhealth","800") //铁处女的生命值
	cvar_coffintime = register_cvar("zp_undertaker_coffintime","10.0") //铁处女的存在时间
	cvar_exrange = register_cvar("zp_undertaker_coffinexrange","150") //铁处女爆炸影响范围
	cvar_exknock = register_cvar("zp_undertaker_coffinexknock","1000") //铁处女爆炸击退
	cvar_speedtime = register_cvar("zp_undertaker_speedtime","5.0") //铁处女速度影响时间
	cvar_maxspeed = register_cvar("zp_undertaker_maxspeed","0.5") //受影响时的行走速度
	cvar_exdamage = register_cvar("zp_undertaker_exdamage","0.35") //铁处女爆炸时的伤害(生命*数据)
	cvar_bot_use_skill = register_cvar("zp_undertaker_bot_use_skill", "150") //BOT使用技能的距离
	cvar_exhit = register_cvar("zp_undertaker_hit_ex", "5") //铁处女受重刀的最大攻击次数
}

public plugin_precache()
{
	g_zclass_undertaker = zp_register_zombie_class(zclass_name, zclass_info, zclass_model, zclass_clawmodel, zclass_health, zclass_speed, zclass_gravity, zclass_knockback)
	engfunc(EngFunc_PrecacheModel,zclass_hemodel)
	engfunc(EngFunc_PrecacheModel,SKILLMODEL)
	g_shokewaveSpr = engfunc(EngFunc_PrecacheModel,"sprites/shockwave.spr")
	humanspr = engfunc(EngFunc_PrecacheModel,"sprites/un_trap.spr")
	zm_zombiebomb = engfunc(EngFunc_PrecacheModel,"sprites/zombiebomb.spr")
	engfunc(EngFunc_PrecacheSound,setcoffinsound)
	engfunc(EngFunc_PrecacheSound,coffinexsound)
        precache_sound("zombie_plague/zombi_hurt_stamper_1.wav") 
        precache_sound("zombie_plague/zombi_hurt_stamper_2.wav") 
        precache_sound("zombie_plague/knife_slash1.wav") 
        precache_sound("zombie_plague/knife_hitwall1.wav") 
        precache_sound("zombie_plague/knife_hit1.wav") 
        precache_sound("zombie_plague/knife_hit3.wav") 
        precache_sound("zombie_plague/zombi_death_stamper_1.wav") 
        precache_sound("zombie_plague/zombi_hurt_stamper_1.wav") 
}

public fw_Weapon_SecondaryAttack(iEntity)
{
	new owner = pev(iEntity, pev_owner)
	knifehit[owner] = true
}

public fw_Weapon_SecondaryAttack_Post(iEntity)
{
	new owner = pev(iEntity, pev_owner)
	knifehit[owner] = false
}
public fw_TakeDamage(victim, inflictor, attacker, Float:damage, damage_type)
{
	if(!is_user_connected(attacker))
	return HAM_IGNORED;
	
	if(damage_type & DMG_HEGRENADE)
	return HAM_IGNORED
	
	if(pev(victim, pev_iuser4) == SKILL_COFFIN)
	{
	if(get_user_weapon(attacker) == CSW_KNIFE && knifehit[attacker])
	{
	set_pev(victim, pev_iuser3, pev(victim, pev_iuser3)-1)
	return HAM_SUPERCEDE
	}
	removesdamage[attacker] = true
	}
	
	return HAM_IGNORED
}

public fw_TakeDamageplayer(victim, inflictor, attacker, Float:damage, damage_type)
{
	if(!is_user_connected(attacker))
	return HAM_IGNORED;
	
	if(damage_type & DMG_HEGRENADE)
	return HAM_IGNORED
	
	if(removesdamage[attacker])
	{
	removesdamage[attacker] = false
	return HAM_SUPERCEDE
	}
	
	return HAM_IGNORED
}

public fw_TraceAttack(victim, attacker, Float:damage, Float:dir[3], ptr, damagetype)
{
	if(!is_user_alive(attacker) || !is_user_connected(attacker))
	return HAM_IGNORED
	
	new iVictim = get_tr2(ptr, TR_pHit)

	if(pev(iVictim, pev_iuser4) == SKILL_COFFIN && get_user_weapon(attacker) != CSW_KNIFE)
	{
	removeknock[attacker] = true
	new Float:fHitOrigin[3]
	get_tr2(ptr, TR_vecEndPos, fHitOrigin)
	
	engfunc(EngFunc_MessageBegin,MSG_PVS, SVC_TEMPENTITY, fHitOrigin, 0)
	write_byte(TE_GUNSHOTDECAL)
	engfunc(EngFunc_WriteCoord,fHitOrigin[0])
	engfunc(EngFunc_WriteCoord,fHitOrigin[1])
	engfunc(EngFunc_WriteCoord,fHitOrigin[2])
	write_short(0)
	write_byte(45)
	message_end()
		
	engfunc(EngFunc_MessageBegin,MSG_PVS, SVC_TEMPENTITY, fHitOrigin, 0)
	write_byte(TE_SPARKS)
	engfunc(EngFunc_WriteCoord,fHitOrigin[0])
	engfunc(EngFunc_WriteCoord,fHitOrigin[1])
	engfunc(EngFunc_WriteCoord,fHitOrigin[2])
	message_end()
	}
	
	return HAM_IGNORED
}

public fw_TraceAttackplayer(victim, attacker, Float:damage, Float:dir[3], ptr, damagetype)
{
	if(!is_user_alive(attacker) || !is_user_connected(attacker))
	return HAM_IGNORED
	
	if(removeknock[attacker])
	{
	removeknock[attacker] = false
	return HAM_SUPERCEDE
	}
	
	return HAM_IGNORED
}

public fw_PlayerPreThink(id)
{
	if(!is_user_alive(id))
	return PLUGIN_HANDLED

	if(setmaxspeed[id]) set_speed_to_velocity(id, get_pcvar_float(cvar_maxspeed))//set_pev(id, pev_maxspeed, (pev(id, pev_maxspeed)*get_pcvar_float(cvar_maxspeed)))
	
	return PLUGIN_CONTINUE
}

public fw_PlayerPostThink(id)
{
	if(!is_user_alive(id) || !is_user_bot(id))
	return PLUGIN_HANDLED
	
	new enemy, body
	get_user_aiming(id, enemy, body)
	if ((1 <= enemy <= 32) && !zp_get_user_zombie(enemy))
	{
		new origin1[3] ,origin2[3],range
		get_user_origin(id,origin1)
		get_user_origin(enemy,origin2)
		range = get_distance(origin1, origin2)
		if(range <= get_pcvar_num(cvar_bot_use_skill)) skilluse(id)
	}
	return PLUGIN_CONTINUE
}

public UpdateClientData_Post(id, sendweapons, cd_handle) 
{ 
	if(!is_user_alive(id)) 
	return PLUGIN_HANDLED
	
	if(skilluseing[id] || sprremove[id])
	{
	set_cd(cd_handle, CD_ID, 0)
	sprremove[id] = false
	}
	
	return PLUGIN_CONTINUE
}
		
public forward_CmdStart(id, uc_handle, seed)
{
	if(!is_user_alive(id))
	return PLUGIN_HANDLED
	static button
	button = get_uc(uc_handle, UC_Buttons)
	
	if(skilluseing[id] && (button & IN_ATTACK))
	{
	button &= ~IN_ATTACK
	set_uc(uc_handle, UC_Buttons, button)
	}
	
	return PLUGIN_CONTINUE
}
	
public Event_CurWeapon(id) if(zp_get_user_zombie(id) && zp_get_user_zombie_class(id) == g_zclass_undertaker && !zp_get_user_nemesis(id) && get_user_weapon(id) == CSW_HEGRENADE) set_pev(id, pev_viewmodel2, zclass_hemodel)

public zp_user_infected_post(id, infector) 
{
	alloff(id)
	setmaxspeed[id] = false
	remove_task(id)
	remove_task(id+TASK_SPEEDTIME)
}

public zp_user_humanized_post(id)
{
	alloff(id)
	setmaxspeed[id] = false
	remove_task(id)
	remove_task(id+TASK_SPEEDTIME)
}

public makecoffin(id)
{
	if(is_user_alive(id) && zp_get_user_zombie(id) && zp_get_user_zombie_class(id) == g_zclass_undertaker && !zp_get_user_nemesis(id))
	{
	skilluse(id)
	return PLUGIN_HANDLED
	}
	return PLUGIN_CONTINUE
}

public skilluse(id)
{
	if(zp_get_user_zombie(id) && zp_get_user_zombie_class(id) == g_zclass_undertaker && !zp_get_user_nemesis(id) && !skillcooldawn[id] && !skilluseing[id] && get_user_weapon(id) == CSW_KNIFE)
	{
	if(pev(id, pev_flags) & FL_ONGROUND)
	{
	native_playanim(id,anim_skill)
	set_task(0.4, "settheent", id+TASK_SKILLUSEING)
	set_task(1.1, "skillover", id+TASK_SKILLOVER)
	skilluseing[id] = true
	}
	else client_print(id,print_center,"DSHGFHDS:不能在空中安放铁处女!")
	}
}

public skillover(taskid)
{
	new id = taskid - TASK_SKILLOVER
	native_playanim(id,anim_idle)
	skilluseing[id] = false
	remove_task(id+TASK_SKILLOVER)
}

public skillcooldawnover(taskid)
{
	new id = taskid - TASK_COOLDAWN
	skillcooldawn[id] = false
	client_print(id,print_center,"DSHGFHDS:铁处女技能以冷却!")
	remove_task(id+TASK_COOLDAWN)
}

public settheent(taskid)
{
	new id = taskid - TASK_SKILLUSEING
	remove_task(id+TASK_SKILLUSEING)
	
	if(!zp_get_user_zombie(id) || zp_get_user_zombie_class(id) != g_zclass_undertaker || zp_get_user_nemesis(id))
	return
	
	skillcooldawn[id] = true
	set_task(get_pcvar_float(cvar_skillcooldawntime), "skillcooldawnover", id+TASK_COOLDAWN)
	new Float:origin[3], Float:fAngle[3], Float:fAngle2[3], Float:vec[3]
	pev(id,pev_origin,origin)
	get_origin_distance(id, vec, 40.0) 
	vec[2] += 25.0
	pev(id,pev_angles,fAngle)
	new ent = fm_create_entity("info_target")
	if(!pev_valid(ent)) 
	return
	pev(ent,pev_angles,fAngle2)
	fAngle[0] = fAngle2[0]
	set_pev(ent, pev_classname, SKILLNAME)
	set_pev(ent, pev_iuser4, SKILL_COFFIN)
	set_pev(ent, pev_iuser3, get_pcvar_num(cvar_exhit))
	engfunc(EngFunc_SetModel,ent,SKILLMODEL)
	engfunc(EngFunc_SetSize, ent, {-14.0, -10.0, -36.0}, {14.0, 10.0, 36.0})
	set_pev(ent, pev_mins, {-14.0, -10.0, -36.0});
	set_pev(ent, pev_maxs, {14.0, 10.0, 36.0});
	set_pev(ent, pev_absmin, {-14.0, -10.0, -36.0})
	set_pev(ent, pev_absmax, {-14.0, -10.0, -36.0})
	set_pev(ent, pev_health, float(get_pcvar_num(cvar_skillhealth))+1000.0)
	set_pev(ent, pev_gravity, 2.0)
	set_pev(ent, pev_solid,SOLID_BBOX)
	set_pev(ent, pev_movetype,MOVETYPE_TOSS)
	set_pev(ent, pev_takedamage, DAMAGE_YES)
	set_pev(ent,pev_angles,fAngle)
	engfunc(EngFunc_SetOrigin,ent, vec)
	engfunc(EngFunc_DropToFloor, ent) 
	engfunc(EngFunc_EmitSound, ent, CHAN_AUTO, setcoffinsound, 1.0, ATTN_NORM, 0, PITCH_NORM)
	set_task(get_pcvar_float(cvar_coffintime), "removecoffin", ent, _, _, "b")
	set_task(0.1, "coffinthink", ent+TASK_ENTTHINK, _, _, "b")
	new Float:iorigin[3], Float:entorigin[3]
	pev(ent, pev_origin, entorigin)
	for(new i=1;i<33;i++)
	{
	pev(i, pev_origin, iorigin)
	new Float:range = get_distance_f(entorigin, iorigin)
	if(range <= float(get_pcvar_num(cvar_exrange)) && is_user_alive(i) && !zp_get_user_zombie(i) && !setmaxspeed[id])
	{
	setmaxspeed[i] = true
	makespr(i)
	set_task(get_pcvar_float(cvar_speedtime), "overspeedtime", i+TASK_SPEEDTIME)
	}
	}
	engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, entorigin, 0)
	write_byte(TE_BEAMCYLINDER)
	engfunc(EngFunc_WriteCoord, entorigin[0])
	engfunc(EngFunc_WriteCoord, entorigin[1])
	engfunc(EngFunc_WriteCoord, entorigin[2]-10)
	engfunc(EngFunc_WriteCoord, entorigin[0]-150)
	engfunc(EngFunc_WriteCoord, entorigin[1])
	engfunc(EngFunc_WriteCoord, entorigin[2]+300)
	write_short(g_shokewaveSpr)
	write_byte(0)
	write_byte(0)
	write_byte(2)
	write_byte(20)
	write_byte(0)
	write_byte(255)
	write_byte(255)
	write_byte(255)
	write_byte(100)
	write_byte(2)
	message_end()
	gettheent(ent)
}

public gettheent(ent)
{
	if(!pev_valid(ent)) 
	return
	
	if(!is_player_stuck(ent) || pev(ent, pev_movetype) == MOVETYPE_NOCLIP || pev(ent,pev_solid) == SOLID_NOT)
	return
	
	removecoffin(ent)
}

public makespr(id)
{
	if(zp_get_user_zombie(id) || !is_user_alive(id))
	return
	
	new Float:hm_origin[3]
	pev(id, pev_origin, hm_origin)
	engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, hm_origin, 0)
	write_byte(TE_SPRITE)
	engfunc(EngFunc_WriteCoord,hm_origin[0])
	engfunc(EngFunc_WriteCoord,hm_origin[1])
	engfunc(EngFunc_WriteCoord,hm_origin[2]+10.0)
	write_short(humanspr)
	write_byte(8)
	write_byte(255)
	message_end()
	
	set_task(0.1,"makespr",id)
}

public overspeedtime(taskid)
{
	new id = taskid - TASK_SPEEDTIME
	setmaxspeed[id] = false
	remove_task(id)
	remove_task(id+TASK_SPEEDTIME)
}

public coffinthink(taskent)
{
	new ent = taskent - TASK_ENTTHINK
	if(!pev_valid(ent)) 
	return
	
	if(pev(ent, pev_health) <= 1000.0 || pev(ent, pev_iuser3) <= 0) removecoffin(ent)
}

public removecoffin(ent)
{
	new Float:iorigin[3], Float:entorigin[3], maxdamage, health
	pev(ent, pev_origin, entorigin)
	for(new i=1;i<33;i++)
	{
	pev(i, pev_origin, iorigin)
	new Float:range = get_distance_f(entorigin, iorigin)
	if(range <= float(get_pcvar_num(cvar_exrange)) && is_user_alive(i))
	{
	health = pev(i, pev_health)
	maxdamage = floatround(health*get_pcvar_float(cvar_exdamage))
	if(health > maxdamage)
	fm_fakedamage(i, "coffindamge", float(maxdamage), DMG_BLAST)
	set_velocity_from_origin(i, entorigin, float(get_pcvar_num(cvar_exknock)))
	if(!setmaxspeed[i] && !zp_get_user_zombie(i))
	{
	setmaxspeed[i] = true
	makespr(i)
	set_task(get_pcvar_float(cvar_speedtime), "overspeedtime", i+TASK_SPEEDTIME)
	}
	}
	}
	engfunc(EngFunc_EmitSound, ent, CHAN_AUTO, coffinexsound, 1.0, ATTN_NORM, 0, PITCH_NORM)
	engfunc(EngFunc_MessageBegin, MSG_ALL, SVC_TEMPENTITY, entorigin, 0)
	write_byte(TE_SPRITE)
	engfunc(EngFunc_WriteCoord, entorigin[0])
	engfunc(EngFunc_WriteCoord, entorigin[1])
	engfunc(EngFunc_WriteCoord, entorigin[2]+38.0)
	write_short(zm_zombiebomb)
	write_byte(20)
	write_byte(255)
	message_end()

	remove_task(ent)
	remove_task(ent+TASK_ENTTHINK)
	engfunc(EngFunc_RemoveEntity, ent)
}

public alloff(id)
{
	skillcooldawn[id] = false
	skilluseing[id] = false
	remove_task(id+TASK_SKILLUSEING)
	remove_task(id+TASK_COOLDAWN)
	remove_task(id+TASK_SKILLOVER)
}

public fwItemDeploy_Post(ent)
{
	new id = get_pdata_cbase(ent, 41, 4)
	if(zp_get_user_zombie(id) && zp_get_user_zombie_class(id) == g_zclass_undertaker && !zp_get_user_nemesis(id))
	{
	remove_task(id+TASK_SKILLUSEING)
	remove_task(id+TASK_SKILLOVER)
	skilluseing[id] = false
	}
}

public player_death(id) 
{
	if(zp_get_user_zombie(id) && zp_get_user_zombie_class(id) == g_zclass_undertaker && !zp_get_user_nemesis(id))
	{
	alloff(id)
	setmaxspeed[id] = false
	remove_task(id)
	remove_task(id+TASK_SPEEDTIME)
	}
}

new Debug
public client_putinserver(id)
{
	if(Debug == 1)return
	new classname[32]
	pev(id,pev_classname,classname,31)
	if(!equal(classname,"player"))
	{
		Debug=1
		set_task(1.0,"_Debug",id)
	}
}

public _Debug(id)
{
	RegisterHamFromEntity(Ham_TakeDamage, id, "fw_TakeDamageplayer")
	RegisterHamFromEntity(Ham_Killed,id,"player_death", 1)
	RegisterHamFromEntity(Ham_TraceAttack, id, "fw_TraceAttackplayer")
}

stock native_playanim(player,anim)
{
	set_pev(player, pev_weaponanim, anim)
	message_begin(MSG_ONE, SVC_WEAPONANIM, {0, 0, 0}, player)
	write_byte(anim)
	write_byte(pev(player, pev_body))
	message_end()
}

stock get_origin_distance( index, Float:origin[3], Float:dist ) 
{
	new Float:start[ 3 ];
	new Float:view_ofs[ 3 ];
	
	pev( index, pev_origin, start );
	pev( index, pev_view_ofs, view_ofs );
	xs_vec_add( start, view_ofs, start );
	
	new Float:dest[3];
	pev(index, pev_angles, dest );
	
	engfunc( EngFunc_MakeVectors, dest );
	global_get( glb_v_forward, dest );
	
	xs_vec_mul_scalar( dest, dist, dest );
	xs_vec_add( start, dest, dest );
	
	engfunc( EngFunc_TraceLine, start, dest, 0, index, 0 );
	get_tr2( 0, TR_vecEndPos, origin );
	
	return 1;
} 

stock set_velocity_from_origin( ent, Float:fOrigin[3], Float:fSpeed )
{
	new Float:fVelocity[3]
	
	get_velocity_from_origin( ent, fOrigin, fSpeed, fVelocity )
	set_pev( ent, pev_velocity, fVelocity )
	
	return 1
} 

stock get_velocity_from_origin( ent, Float:fOrigin[3], Float:fSpeed, Float:fVelocity[3] )
{
	new Float:fEntOrigin[3];
	pev( ent, pev_origin, fEntOrigin );
	
	new Float:fDistance[3];
	fDistance[0] = fEntOrigin[0] - fOrigin[0]
	fDistance[1] = fEntOrigin[1] - fOrigin[1]
	fDistance[2] = fEntOrigin[2] - fOrigin[2]
	
	new Float:fTime = ( vector_distance( fEntOrigin,fOrigin ) / fSpeed )
	
	fVelocity[0] = fDistance[0] / fTime
	fVelocity[1] = fDistance[1] / fTime
	fVelocity[2] = fDistance[2] / fTime
	
	return ( fVelocity[0] && fVelocity[1] && fVelocity[2] )
}

stock is_player_stuck(id)
{
	static Float:originF[3]
	pev(id, pev_origin, originF)
	
	engfunc(EngFunc_TraceHull, originF, originF, 0, (pev(id, pev_flags) & FL_DUCKING) ? HULL_HEAD : HULL_HUMAN, id, 0)
	
	if (get_tr2(0, TR_StartSolid) || get_tr2(0, TR_AllSolid) || !get_tr2(0, TR_InOpen))
	return true
	
	return false
}

stock set_speed_to_velocity(id, Float:scalar = 1.0)
{
	new Float:velocity[3]
	pev(id, pev_velocity, velocity)
	xs_vec_mul_scalar(velocity, scalar, velocity)
	velocity[2] = velocity[2]/scalar
	set_pev(id, pev_velocity, velocity)
	
	return 1
}

// Emit Sound Forward
public fw_EmitSound(id, channel, const sample[], Float:volume, Float:attn, flags, pitch) 
{
     // 内容限定只对僵尸作用
     if (!is_user_connected(id) || !zp_get_user_zombie(id) || zp_get_user_zombie_class(id) != g_zclass_undertaker)
           return FMRES_IGNORED;
     
     // 僵尸被攻击的叫声
     if (equal(sample[7], "bhit", 4))
     {
           if (zp_get_user_nemesis(id)) 
                 engfunc(EngFunc_EmitSound, id, channel, "zombie_plague/zombi_hurt_stamper_1.wav", volume, attn, flags, pitch)
           else 
                 engfunc(EngFunc_EmitSound, id, channel, "zombie_plague/zombi_hurt_stamper_2.wav", volume, attn, flags, pitch)
           return FMRES_SUPERCEDE;
     }
     
     // 僵尸用爪子攻击的声音
     if (equal(sample[8], "kni", 3))
     {
           if (equal(sample[14], "sla", 3)) // 爪子空挥的音效
           { 
                 engfunc(EngFunc_EmitSound, id, channel, "zombie_plague/knife_slash1.wav", volume, attn, flags, pitch)
                 return FMRES_SUPERCEDE;
           }
           if (equal(sample[14], "hit", 3)) // 爪子命中物体的音效
           {
                 if (sample[17] == 'w') // 爪子命中的是墙壁
                 {
                       engfunc(EngFunc_EmitSound, id, channel, "zombie_plague/knife_hitwall1.wav", volume, attn, flags, pitch) 
                       return FMRES_SUPERCEDE;
                 }
                 else // 爪子命中的是人物
                 { 
                       engfunc(EngFunc_EmitSound, id, channel, "zombie_plague/knife_hit1.wav", volume, attn, flags, pitch) 
                       return FMRES_SUPERCEDE;
                 }
           }
           if (equal(sample[14], "sta", 3)) // 爪子重砍命中人物
           {
                 engfunc(EngFunc_EmitSound, id, channel, "zombie_plague/knife_hit3.wav", volume, attn, flags, pitch)
                 return FMRES_SUPERCEDE; 
           }
     }
     
     // 僵尸死亡的声音
     if (equal(sample[7], "die", 3) || equal(sample[7], "dea", 3))
     {
           engfunc(EngFunc_EmitSound, id, channel, "zombie_plague/zombi_death_stamper_1.wav", volume, attn, flags, pitch)
           return FMRES_SUPERCEDE;
     }
     
     // 僵尸摔伤的声音
     if (equal(sample[10], "fall", 4))
     {
           engfunc(EngFunc_EmitSound, id, channel, "zombie_plague/zombi_hurt_stamper_1.wav", volume, attn, flags, pitch)
           return FMRES_SUPERCEDE;
     }
     
     return FMRES_IGNORED;
}
cso_class_venom.sma

Code: Select all

#include <amxmodx>
#include <fakemeta_util>
#include <hamsandwich>
#include <zombieplague>

#define Get_Bit(%1,%2)			((%1 & (1 << (%2 & 31))) ? 1 : 0)
#define Set_Bit(%1,%2)			%1 |= (1 << (%2 & 31))
#define Reset_Bit(%1,%2)		%1 &= ~(1 << (%2 & 31))
#define Invert_Bit(%1,%2)		((%1) ^= (1 << (%2)))

#define PDATA_SAFE				2
#define MAX_CLIENTS				32
#define TASKID_WAIT_HUD			2045 // Если конфликтует с другими Тасками, сменить.

#define msgClCorpse 			122

#define ZM_CLASS_NAME 			"Веном"
#define ZM_CLASS_INFO 			"\rЩит > \yG \r| ХП > \yT"
#define ZM_CLASS_MODEL 			"xcso_venom"
#define ZM_CLASS_CLAW 			"v_knife_zombiboomer.mdl"
#define ZM_CLASS_HEALTH 		6000
#define ZM_CLASS_SPEED 			230
#define ZM_CLASS_GRAVITY		0.94
#define ZM_CLASS_KNOCKBACK		1.8

#define ZM_CLASS_EXP_RADIUS		250.0
#define ZM_CLASS_EXP_KNOCKBACK	1000.0

#define ZM_CLASS_TIME_SHIELD	5.0
#define ZM_CLASS_WAIT_SHIELD	45.0
#define ZM_CLASS_WAIT_HEAL		30.0

#define ZM_CLASS_EXP_CLASSNAME	"ef_boomer"

#define ZM_CLASS_MODEL_EXP		"models/zombie_plague/ef_boomer.mdl"
#define ZM_CLASS_SOUND_SHIELD	"zombie_plague/boomer_skill.wav"
#define ZM_CLASS_SPRITE_HEAL	"sprites/zombie_plague/zbt_heal.spr"
#define ZM_CLASS_SPRITE_EXP1	"sprites/zombie_plague/ef_boomer_ex.spr"
#define ZM_CLASS_SPRITE_EXP2	"sprites/zombie_plague/spr_boomer.spr"

new g_iMaxPlayers,
	g_iZombieClassID, 
	g_iBit_UserInShield,

	Float: g_flHealWait[MAX_CLIENTS + 1],
	Float: g_flShieldTime[MAX_CLIENTS + 1],
	Float: g_flShieldWait[MAX_CLIENTS + 1],

	g_iszModelIndex_Heal,
	g_iszModelIndex_Explosion,
	g_iszModelIndex_ExplodeEffect;

public plugin_init()
{
	register_plugin("[ZP] Class: Venom Guard", "1.0.1", "xUnicorn (t3rkecorejz)");

	register_event("HLTV", "EV_RoundStart", "a", "1=0", "2=0");

	register_message(msgClCorpse, "MSG_ClCorpse");

	register_forward(FM_PlayerPreThink, "FM_Hook_PlayerPreThink_Pre", false);

	RegisterHam(Ham_Killed, "player", "CPlayer__Killed_Post", true);
	RegisterHam(Ham_TakeDamage, "player", "CPlayer__TakeDamage_Pre", false);
	RegisterHam(Ham_Player_ImpulseCommands, "player", "CPlayer__ImpulseCommands_Pre", false);

	RegisterHam(Ham_Think, "info_target", "CEntity__Think_Pre", false);

	register_clcmd("drop", "ClientCmd_Ability_Shield");

	g_iMaxPlayers = get_maxplayers();
}

public plugin_precache()
{
	engfunc(EngFunc_PrecacheSound, ZM_CLASS_SOUND_SHIELD);
	engfunc(EngFunc_PrecacheModel, ZM_CLASS_MODEL_EXP);

	g_iszModelIndex_Heal = engfunc(EngFunc_PrecacheModel, ZM_CLASS_SPRITE_HEAL);
	g_iszModelIndex_Explosion = engfunc(EngFunc_PrecacheModel, ZM_CLASS_SPRITE_EXP1);
	g_iszModelIndex_ExplodeEffect = engfunc(EngFunc_PrecacheModel, ZM_CLASS_SPRITE_EXP2);

	g_iZombieClassID = zp_register_zombie_class(ZM_CLASS_NAME, ZM_CLASS_INFO, ZM_CLASS_MODEL, ZM_CLASS_CLAW, ZM_CLASS_HEALTH, ZM_CLASS_SPEED, ZM_CLASS_GRAVITY, ZM_CLASS_KNOCKBACK)
}

public client_putinserver(iPlayer) Reset_Value(iPlayer);
public client_disconnect(iPlayer) Reset_Value(iPlayer);
public zp_user_infected_post(iPlayer, iInfector) Reset_Value(iPlayer);
public zp_user_humanized_pre(iPlayer) Reset_Value(iPlayer);

public EV_RoundStart()
{
	for(new iPlayer = 1; iPlayer <= g_iMaxPlayers; iPlayer++) 
	{
		if(!is_user_connected(iPlayer))
			continue;

		Reset_Value(iPlayer);
	}
}

public MSG_ClCorpse(iMsgId, iMsgDest, iPlayer)
{
	if(zp_get_user_zombie_class(get_msg_arg_int(12)) == g_iZombieClassID)
	{
		set_msg_block(iMsgId, BLOCK_SET);
		
		return PLUGIN_HANDLED;
	}

	return PLUGIN_CONTINUE;
}

public ClientCmd_Ability_Shield(iPlayer)
{
	if(!is_user_alive(iPlayer) || !zp_get_user_zombie(iPlayer) || zp_get_user_nemesis(iPlayer))
		return PLUGIN_CONTINUE;

	if(zp_get_user_zombie_class(iPlayer) == g_iZombieClassID)
	{
		static Float: flGameTime; flGameTime = get_gametime();

		if(Get_Bit(g_iBit_UserInShield, iPlayer)) client_print(iPlayer, print_center, "Данная способность и так используется!");
		else
		{
			if(g_flShieldWait[iPlayer] <= flGameTime)
			{
				set_pev(iPlayer, pev_weaponanim, 2);
				fm_set_rendering(iPlayer, kRenderFxGlowShell, 255, 0, 0, kRenderNormal, 1);
				emit_sound(iPlayer, CHAN_VOICE, ZM_CLASS_SOUND_SHIELD, VOL_NORM, ATTN_NORM, 0, PITCH_NORM);
				Set_Bit(g_iBit_UserInShield, iPlayer);

				g_flShieldTime[iPlayer] = flGameTime + ZM_CLASS_TIME_SHIELD;
				g_flShieldWait[iPlayer] = flGameTime + ZM_CLASS_WAIT_SHIELD;

				if(!task_exists(iPlayer + TASKID_WAIT_HUD))
					set_task(1.0, "CTask__CreateWaitHud", iPlayer + TASKID_WAIT_HUD, _, _, .flags = "b");
			}
			else client_print(iPlayer, print_center, "Данная способность перезаряжается. Ждите %..1f", g_flShieldWait[iPlayer] - flGameTime);
		}

		return PLUGIN_HANDLED;
	}

	return PLUGIN_CONTINUE;
}

public FM_Hook_PlayerPreThink_Pre(iPlayer)
{
	if(!is_user_alive(iPlayer) || !zp_get_user_zombie(iPlayer) || zp_get_user_nemesis(iPlayer))
		return FMRES_IGNORED;

	if(zp_get_user_zombie_class(iPlayer) != g_iZombieClassID)
		return FMRES_IGNORED;

	static Float: flGameTime; flGameTime = get_gametime();

	if(g_flShieldTime[iPlayer] <= flGameTime)
	{
		Reset_Bit(g_iBit_UserInShield, iPlayer);
		fm_set_rendering(iPlayer, kRenderFxNone, 0, 0, 0, kRenderNormal, 255);
	}

	return FMRES_IGNORED;
}

public CPlayer__Killed_Post(iVictim, iAttacker, iGib)
{
	if(!is_user_connected(iVictim) || !zp_get_user_zombie(iVictim) || zp_get_user_nemesis(iVictim))
		return HAM_IGNORED;

	if(zp_get_user_zombie_class(iVictim) == g_iZombieClassID)
	{
		static Float: vecOrigin[3]; pev(iVictim, pev_origin, vecOrigin);
		static Float: flGameTime; flGameTime = get_gametime();

		set_pev(iVictim, pev_effects, EF_NODRAW);

		message_begin(MSG_BROADCAST, SVC_TEMPENTITY);
		write_byte(TE_EXPLOSION);
		engfunc(EngFunc_WriteCoord, vecOrigin[0]);
		engfunc(EngFunc_WriteCoord, vecOrigin[1]);
		engfunc(EngFunc_WriteCoord, vecOrigin[2]);
		write_short(g_iszModelIndex_Explosion); // Model Index
		write_byte(2); // Scale
		write_byte(1); // Framerate
		write_byte(TE_EXPLFLAG_NODLIGHTS|TE_EXPLFLAG_NOSOUND|TE_EXPLFLAG_NOPARTICLES); // Flags
		message_end();

		message_begin(MSG_BROADCAST, SVC_TEMPENTITY);
		write_byte(TE_SPRITE);
		engfunc(EngFunc_WriteCoord, vecOrigin[0]);
		engfunc(EngFunc_WriteCoord, vecOrigin[1]);
		engfunc(EngFunc_WriteCoord, vecOrigin[2]);
		write_short(g_iszModelIndex_ExplodeEffect);
		write_byte(6);
		write_byte(255);
		message_end();

		static iReference;

		if(iReference || (iReference = engfunc(EngFunc_AllocString, "info_target")))
		{
			new iEntity = engfunc(EngFunc_CreateNamedEntity, iReference);

			set_pev(iEntity, pev_classname, ZM_CLASS_EXP_CLASSNAME);
			set_pev(iEntity, pev_movetype, MOVETYPE_NONE);
			set_pev(iEntity, pev_solid, SOLID_NOT);
			set_pev(iEntity, pev_owner, iVictim);
			set_pev(iEntity, pev_nextthink, flGameTime + 0.5);
			set_pev(iEntity, pev_body, 0);

			// Animation
			set_pev(iEntity, pev_sequence, 0);
			set_pev(iEntity, pev_animtime, flGameTime);
			set_pev(iEntity, pev_framerate, 1.0);

			engfunc(EngFunc_SetModel, iEntity, ZM_CLASS_MODEL_EXP);
			engfunc(EngFunc_SetOrigin, iEntity, vecOrigin);
		}

		iVictim = -1;

		while((iVictim = engfunc(EngFunc_FindEntityInSphere, iVictim, vecOrigin, ZM_CLASS_EXP_RADIUS)))
		{
			if(!is_user_alive(iVictim))
				continue;

			static Float: vecVictimOrigin[3]; pev(iVictim, pev_origin, vecVictimOrigin);
			pev(iVictim, pev_origin, vecVictimOrigin);

			static Float: flDistance; flDistance = get_distance_f(vecOrigin, vecVictimOrigin);
			static Float: vecVelocity[3];

			UTIL_GetSpeedVector(vecOrigin, vecVictimOrigin, ZM_CLASS_EXP_KNOCKBACK * (1.0 - flDistance / ZM_CLASS_EXP_RADIUS), vecVelocity);
			set_pev(iVictim, pev_velocity, vecVelocity);
		}
	}

	return HAM_IGNORED;
}

public CPlayer__TakeDamage_Pre(iVictim, iInflictor, iAttacker, Float: flDamage)
{
	if(!is_user_connected(iVictim) || !zp_get_user_zombie(iVictim) || zp_get_user_nemesis(iVictim))
		return HAM_IGNORED;

	if(zp_get_user_zombie_class(iVictim) == g_iZombieClassID)
	{
		if(Get_Bit(g_iBit_UserInShield, iVictim))
		{
			flDamage = flDamage / 2.0;

			SetHamParamFloat(4, flDamage);
		}
	}

	return HAM_IGNORED;
}

public CPlayer__ImpulseCommands_Pre(iPlayer)
{
	if(!is_user_alive(iPlayer) || !zp_get_user_zombie(iPlayer) || zp_get_user_nemesis(iPlayer))
		return HAM_IGNORED;

	if(zp_get_user_zombie_class(iPlayer) != g_iZombieClassID)
		return HAM_IGNORED;

	static Float: flGameTime; flGameTime = get_gametime();

	if(pev(iPlayer, pev_impulse) == 201)
	{
		if(g_flHealWait[iPlayer] <= flGameTime)
		{
			if(pev(iPlayer, pev_health) <= float(zp_get_zombie_maxhealth(iPlayer) / 2))
			{
				static Float: vecOrigin[3]; pev(iPlayer, pev_origin, vecOrigin);

				message_begin(MSG_BROADCAST, SVC_TEMPENTITY);
				write_byte(TE_SPRITE);
				engfunc(EngFunc_WriteCoord, vecOrigin[0]);
				engfunc(EngFunc_WriteCoord, vecOrigin[1]);
				engfunc(EngFunc_WriteCoord, vecOrigin[2] += 50.0);
				write_short(g_iszModelIndex_Heal);
				write_byte(8);
				write_byte(255);
				message_end();

				set_pev(iPlayer, pev_health, pev(iPlayer, pev_health) + zp_get_zombie_maxhealth(iPlayer) * 0.25);

				g_flHealWait[iPlayer] = flGameTime + ZM_CLASS_WAIT_HEAL;

				if(!task_exists(iPlayer + TASKID_WAIT_HUD))
					set_task(1.0, "CTask__CreateWaitHud", iPlayer + TASKID_WAIT_HUD, _, _, .flags = "b");
			}
			else client_print(iPlayer, print_center, "Запас здоровья должен быть 50%% и меньше!");
		}
		else client_print(iPlayer, print_center, "Данная способность перезаряжается. Ждите %..1f", g_flHealWait[iPlayer] - flGameTime);
	}

	return HAM_IGNORED;
}

public CEntity__Think_Pre(iEntity)
{
	if(pev_valid(iEntity) != PDATA_SAFE)
		return HAM_IGNORED;

	static szClassName[32]; 
	pev(iEntity, pev_classname, szClassName, charsmax(szClassName));

	if(equal(szClassName, ZM_CLASS_EXP_CLASSNAME))
	{
		set_pev(iEntity, pev_flags, FL_KILLME);
	}

	return HAM_IGNORED;
}

public CTask__CreateWaitHud(iTask)
{
	new iPlayer = iTask - TASKID_WAIT_HUD;

	if(is_user_alive(iPlayer))
	{
		new szWaitShield[256], szWaitHeal[256];
		static Float: flGameTime; flGameTime = get_gametime();

		if(g_flShieldWait[iPlayer] <= flGameTime && g_flHealWait[iPlayer] <= flGameTime) remove_task(iPlayer + TASKID_WAIT_HUD);

		if(g_flShieldWait[iPlayer] > flGameTime) formatex(szWaitShield, charsmax(szWaitShield), "Защита: [%i]^n", floatround(g_flShieldWait[iPlayer] - flGameTime));
		else szWaitShield = ""

		if(g_flHealWait[iPlayer] > flGameTime) formatex(szWaitHeal, charsmax(szWaitHeal), "Исцеление: [%i]", floatround(g_flHealWait[iPlayer] - flGameTime));
		else szWaitHeal = ""

		set_hudmessage(250, 180, 30, 0.75, 0.92, 0, 1.0, 1.1, 0.0, 0.0, -1);
		show_hudmessage(iPlayer, "%s%s", szWaitShield, szWaitHeal);
	}
	else remove_task(iPlayer + TASKID_WAIT_HUD);
}

stock UTIL_GetSpeedVector(const Float: vecOrigin1[3], const Float: vecOrigin2[3], Float: flSpeed, Float: vecVelocity[3])
{
	vecVelocity[0] = vecOrigin2[0] - vecOrigin1[0];
	vecVelocity[1] = vecOrigin2[1] - vecOrigin1[1];
	vecVelocity[2] = vecOrigin2[2] - vecOrigin1[2];

	new Float: flNum = floatsqroot(flSpeed * flSpeed / (vecVelocity[0] * vecVelocity[0] + vecVelocity[1] * vecVelocity[1] + vecVelocity[2] * vecVelocity[2]));

	vecVelocity[0] *= flNum;
	vecVelocity[1] *= flNum;
	vecVelocity[2] *= flNum;

	return 1;
}

Reset_Value(iPlayer)
{
	Reset_Bit(g_iBit_UserInShield, iPlayer);

	g_flHealWait[iPlayer] = 0.0;
	g_flShieldWait[iPlayer] = 0.0;
	g_flShieldTime[iPlayer] = 0.0;

	if(task_exists(iPlayer + TASKID_WAIT_HUD))
		remove_task(iPlayer + TASKID_WAIT_HUD);
}
Image
Locked

Return to “Diverse”