#include <amxmodx>
#include <colorchat>
#include <fakemeta>
#include <hamsandwich>
#include <engine>
#include <cs_maxspeed_api>
#include <zp50_core>
#include <zp50_class_nemesis>
#include <zp50_class_survivor>
new g_bitAlivePlayers, g_bitUserAllowed
#define MarkUserAlive(%0) g_bitAlivePlayers |= (1 << (%0 & 31))
#define ClearUserAlive(%0) g_bitAlivePlayers &= ~(1 << (%0 & 31))
#define IsUserAlive(%0) g_bitAlivePlayers & (1 << (%0 & 31))
#define MarkUserAllow(%0) g_bitUserAllowed |= (1 << (%0 & 31))
#define ClearUserAllow(%0) g_bitUserAllowed &= ~(1 << (%0 & 31))
#define IsUserAllow(%0) g_bitUserAllowed & (1 << (%0 & 31))
#define PLUGIN "[ZP] Class: Smoker"
#define VERSION "1.2"
#define AUTHOR "Lambda"
#define TASK_REMOVE_SPEED 1322
new g_zclass_smoker, g_Line, stunTime, breakDamage
new g_sndMiss[] = "zombie_plague/eqtonguemiss.wav"
new g_sndDrag[] = "zombie_plague/eqtonguehit.wav"
new g_hooked[33], g_ovr_dmg[33]
new Float:g_lastHook[33]
new const zclass_name[] = { "VIP Smoker" }
new const zclass_info[] = { "Grab Players [R]" }
new const zclass_model[][] = { "eqsmoker" }
new const zclass_clawmodel[][] = { "models/zombie_plague/v_smoker_hands.mdl" }
const zclass_health = 2300
const Float:zclass_speed = 270.0
const Float:zclass_gravity = 0.75
const Float:zclass_knockback = 1.0
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
RegisterHam(Ham_Spawn, "player", "fwd_Ham_Spawn_post", 1);
register_event("DeathMsg", "smoker_death", "a")
register_forward(FM_CmdStart, "fwd_CmdStart")
register_forward(FM_ClientDisconnect, "fw_ClientDisconnect_Post", 1)
RegisterHam(Ham_TakeDamage, "player", "fw_TakeDamage")
stunTime = register_cvar("zp_smoker_stun", "2.0")
breakDamage = register_cvar("zp_smoker_break", "100")
}
public plugin_precache()
{
g_zclass_smoker = zp_class_zombie_register(zclass_name, zclass_info, zclass_health, zclass_speed, zclass_gravity)
new index
zp_class_zombie_register_kb(g_zclass_smoker, zclass_knockback)
for (index = 0; index < sizeof zclass_model; index++)
zp_class_zombie_register_model(g_zclass_smoker, zclass_model[index])
for (index = 0; index < sizeof zclass_clawmodel; index++)
zp_class_zombie_register_claw(g_zclass_smoker, zclass_clawmodel[index])
precache_sound(g_sndDrag)
precache_sound(g_sndMiss)
g_Line = precache_model("sprites/zbeam4.spr")
}
public zp_fw_core_spawn_post(id)
{
if(is_user_alive(id))
MarkUserAlive(id)
}
public client_putinserver(id)
{
ClearUserAlive(id)
ClearUserAllow(id)
}
public client_disconnect(id)
{
ClearUserAlive(id)
if (g_hooked[id])
drag_end(id)
}
public fw_ClientDisconnect_Post(id)
ClearUserAllow(id)
public smoker_death()
{
new id = read_data(2)
ClearUserAlive(id)
beam_remove(id)
if (g_hooked[id])
drag_end(id)
}
public zp_fw_core_cure_post(id)
ClearUserAllow(id)
public zp_fw_core_infect_post(id)
{
if(zp_class_zombie_get_current(id) != g_zclass_smoker || zp_class_nemesis_get(id))
ClearUserAllow(id)
else
{
MarkUserAllow(id)
g_lastHook[id] = 0.0
ColorChat(id, GREEN, "^1[^4Smoker^1] Press^4 R^1 to use your skills.")
}
}
public fwd_CmdStart(id, handle)
{
if (~IsUserAlive(id) || ~IsUserAllow(id))
return
static button, oldbutton
button = get_user_button(id)
oldbutton = get_user_oldbutton(id)
if (!(oldbutton & IN_RELOAD) && (button & IN_RELOAD))
drag_start(id)
if ((oldbutton & IN_RELOAD) && !(button & IN_RELOAD))
drag_end(id)
}
public fwd_Ham_Spawn_post(id)
{
if (IsUserAlive(id))
{
if (g_hooked[id])
drag_end(id)
}
return HAM_IGNORED;
}
public drag_start(id)
{
if (~IsUserAllow(id))
return
static Float:cdown
cdown = 50.0
if (get_gametime() - g_lastHook[id] < cdown)
{
ColorChat(id, GREEN, "^1[^4ZP^1] You must wait ^4%.f0^1s", cdown - (get_gametime() - g_lastHook[id]))
return
}
else
{
g_lastHook[id] = get_gametime()
new hooktarget, body
get_user_aiming(id, hooktarget, body)
if (IsUserAlive(hooktarget))
{
if (!zp_core_is_zombie(hooktarget))
{
if (zp_class_survivor_get(hooktarget))
{
ColorChat(id, GREEN, "^1[^4ZP^1] You can't use this on a Survivor!")
return
}
g_hooked[id] = hooktarget
emit_sound(hooktarget, CHAN_BODY, g_sndDrag, 1.0, ATTN_NORM, 0, PITCH_HIGH)
}
else
{
ColorChat(id, GREEN, "^1[^4ZP^1] You can't grab your teammates.")
return
}
new parm[2]
parm[0] = id
parm[1] = hooktarget
cs_set_player_maxspeed_auto(id, 0.01)
cs_set_player_maxspeed_auto(hooktarget, 0.01)
set_task(0.1, "smoker_reelin", id, parm, 2, "b")
if(get_pcvar_float(stunTime) > 0.0)
set_task(get_pcvar_float(stunTime), "RemoveSpeed", hooktarget+TASK_REMOVE_SPEED)
harpoon_target(parm)
g_ovr_dmg[id] = 0
}
else
{
g_hooked[id] = 33
noTarget(id)
emit_sound(hooktarget, CHAN_BODY, g_sndMiss, 1.0, ATTN_NORM, 0, PITCH_HIGH)
}
}
}
public RemoveSpeed(hooktarget)
{
hooktarget -= TASK_REMOVE_SPEED
if (IsUserAlive(hooktarget))
cs_set_player_maxspeed_auto(hooktarget, 1.0)
}
public smoker_reelin(parm[])
{
new id = parm[0]
new victim = parm[1]
if (!g_hooked[id] || ~IsUserAlive(victim))
{
drag_end(id)
return
}
new Float:fl_Velocity[3]
new idOrigin[3], vicOrigin[3]
get_user_origin(victim, vicOrigin)
get_user_origin(id, idOrigin)
new distance = get_distance(idOrigin, vicOrigin)
if (distance > 5)
{
new Float:fl_Time = distance / 180.0
fl_Velocity[0] = (idOrigin[0] - vicOrigin[0]) / fl_Time
fl_Velocity[1] = (idOrigin[1] - vicOrigin[1]) / fl_Time
fl_Velocity[2] = (idOrigin[2] - vicOrigin[2]) / fl_Time
}
else
{
fl_Velocity[0] = 0.0
fl_Velocity[1] = 0.0
fl_Velocity[2] = 0.0
drag_end(id)
}
entity_set_vector(victim, EV_VEC_velocity, fl_Velocity)
}
public drag_end(id)
{
g_hooked[id] = 0
beam_remove(id)
cs_set_player_maxspeed_auto(id, 1.0)
remove_task(id)
}
public fw_TakeDamage(victim, inflictor, attacker, Float:damage)
{
if (~IsUserAlive(attacker) || ~IsUserAllow(victim))
return HAM_IGNORED
g_ovr_dmg[victim] += floatround(damage)
if (g_ovr_dmg[victim] >= get_pcvar_num(breakDamage))
{
g_ovr_dmg[victim] = 0
drag_end(victim)
}
return HAM_IGNORED
}
public harpoon_target(parm[])
{
new id = parm[0]
new hooktarget = parm[1]
message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
write_byte(8) // TE_BEAMENTS
write_short(id)
write_short(hooktarget)
write_short(g_Line) // sprite index
write_byte(0) // start frame
write_byte(0) // framerate
write_byte(200) // life
write_byte(8) // width
write_byte(1) // noise
write_byte(155) // r
write_byte(155) // g
write_byte(55) // b
write_byte(90) // brightness
write_byte(10) // speed
message_end()
}
public noTarget(id)
{
new endorigin[3]
get_user_origin(id, endorigin, 3)
message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
write_byte( TE_BEAMENTPOINT ); // TE_BEAMENTPOINT
write_short(id)
write_coord(endorigin[0])
write_coord(endorigin[1])
write_coord(endorigin[2])
write_short(g_Line) // sprite index
write_byte(0) // start frame
write_byte(0) // framerate
write_byte(200) // life
write_byte(8) // width
write_byte(1) // noise
write_byte(155) // r
write_byte(155) // g
write_byte(55) // b
write_byte(75) // brightness
write_byte(0) // speed
message_end()
}
public beam_remove(id)
{
message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
write_byte(99) //TE_KILLBEAM
write_short(id) //entity
message_end()
}