------------------------------------------- -*- [ZP] Extra Item: Knife Blink 1.2 -*- -------------------------------------------
~~~~~~~~~~~~~~~ - Description - ~~~~~~~~~~~~~~~
This item/upgrade gives zombies the possibility to move rapidly towards a human over a short distance, when aiming at him and holding down the attack button.
new Float:g_fSpeed = 1000.0; new Float:g_fDelay = 1.0;
new g_iMaxPlayers; new g_iEnemy[33]; new g_iInBlink[33]; new Float:g_fLastSlash[33]; new g_iCanceled[33]; new g_iSlash[33]; new g_iBlinks[33]; new g_itemid_blink;
public plugin_init(){
register_plugin("[ZP] Extra Item: Knife Blink", "1.2", "pharse");
Sorry for hijacking this thread, but can anybody add limit for single player on original zp508 fire, frost and flare grenade? I tried but failed so hard
// Models
new g_model_grenade_fire[MODEL_MAX_LENGTH] = "models/zombie_plague/v_grenade_fire.mdl"
// Sprites
new g_sprite_grenade_trail[SPRITE_MAX_LENGTH] = "sprites/laserbeam.spr"
new g_sprite_grenade_ring[SPRITE_MAX_LENGTH] = "sprites/shockwave.spr"
new g_sprite_grenade_fire[SPRITE_MAX_LENGTH] = "sprites/flame.spr"
new g_sprite_grenade_smoke[SPRITE_MAX_LENGTH] = "sprites/black_smoke3.spr"
new Array:g_sound_grenade_fire_explode
new Array:g_sound_grenade_fire_player
// Explosion radius for custom grenades
const Float:NADE_EXPLOSION_RADIUS = 240.0
// HACK: pev_ field used to store custom nade types and their values
const PEV_NADE_TYPE = pev_flTimeStepSound
const NADE_TYPE_NAPALM = 2222
// Load from external file
amx_load_setting_string_arr(ZP_SETTINGS_FILE, "Sounds", "GRENADE FIRE EXPLODE", g_sound_grenade_fire_explode)
amx_load_setting_string_arr(ZP_SETTINGS_FILE, "Sounds", "GRENADE FIRE PLAYER", g_sound_grenade_fire_player)
// If we couldn't load custom sounds from file, use and save default ones
new index
if (ArraySize(g_sound_grenade_fire_explode) == 0)
{
for (index = 0; index < sizeof sound_grenade_fire_explode; index++)
ArrayPushString(g_sound_grenade_fire_explode, sound_grenade_fire_explode[index])
// Save to external file
amx_save_setting_string_arr(ZP_SETTINGS_FILE, "Sounds", "GRENADE FIRE EXPLODE", g_sound_grenade_fire_explode)
}
if (ArraySize(g_sound_grenade_fire_player) == 0)
{
for (index = 0; index < sizeof sound_grenade_fire_player; index++)
ArrayPushString(g_sound_grenade_fire_player, sound_grenade_fire_player[index])
// Save to external file
amx_save_setting_string_arr(ZP_SETTINGS_FILE, "Sounds", "GRENADE FIRE PLAYER", g_sound_grenade_fire_player)
}
// Load from external file, save if not found
if (!amx_load_setting_string(ZP_SETTINGS_FILE, "Weapon Models", "GRENADE FIRE", g_model_grenade_fire, charsmax(g_model_grenade_fire)))
amx_save_setting_string(ZP_SETTINGS_FILE, "Weapon Models", "GRENADE FIRE", g_model_grenade_fire)
if (!amx_load_setting_string(ZP_SETTINGS_FILE, "Grenade Sprites", "TRAIL", g_sprite_grenade_trail, charsmax(g_sprite_grenade_trail)))
amx_save_setting_string(ZP_SETTINGS_FILE, "Grenade Sprites", "TRAIL", g_sprite_grenade_trail)
if (!amx_load_setting_string(ZP_SETTINGS_FILE, "Grenade Sprites", "RING", g_sprite_grenade_ring, charsmax(g_sprite_grenade_ring)))
amx_save_setting_string(ZP_SETTINGS_FILE, "Grenade Sprites", "RING", g_sprite_grenade_ring)
if (!amx_load_setting_string(ZP_SETTINGS_FILE, "Grenade Sprites", "FIRE", g_sprite_grenade_fire, charsmax(g_sprite_grenade_fire)))
amx_save_setting_string(ZP_SETTINGS_FILE, "Grenade Sprites", "FIRE", g_sprite_grenade_fire)
if (!amx_load_setting_string(ZP_SETTINGS_FILE, "Grenade Sprites", "SMOKE", g_sprite_grenade_smoke, charsmax(g_sprite_grenade_smoke)))
amx_save_setting_string(ZP_SETTINGS_FILE, "Grenade Sprites", "SMOKE", g_sprite_grenade_smoke)
// Precache sounds
new sound[SOUND_MAX_LENGTH]
for (index = 0; index < ArraySize(g_sound_grenade_fire_explode); index++)
{
ArrayGetString(g_sound_grenade_fire_explode, index, sound, charsmax(sound))
precache_sound(sound)
}
for (index = 0; index < ArraySize(g_sound_grenade_fire_player); index++)
{
ArrayGetString(g_sound_grenade_fire_player, index, sound, charsmax(sound))
precache_sound(sound)
}
// Forward Set Model
public fw_SetModel(entity, const model[])
{
// We don't care
if (strlen(model) < 8)
return;
// Narrow down our matches a bit
if (model[7] != 'w' || model[8] != '_')
return;
// Get damage time of grenade
static Float:dmgtime
pev(entity, pev_dmgtime, dmgtime)
// Grenade not yet thrown
if (dmgtime == 0.0)
return;
// Grenade's owner is zombie?
if (zp_core_is_zombie(pev(entity, pev_owner)))
return;
// HE Grenade
if (model[9] == 'h' && model[10] == 'e')
{
// Give it a glow
fm_set_rendering(entity, kRenderFxGlowShell, 200, 0, 0, kRenderNormal, 16)
// And a colored trail
message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
write_byte(TE_BEAMFOLLOW) // TE id
write_short(entity) // entity
write_short(g_trailSpr) // sprite
write_byte(10) // life
write_byte(10) // width
write_byte(200) // r
write_byte(0) // g
write_byte(0) // b
write_byte(200) // brightness
message_end()
// Set grenade type on the thrown grenade entity
set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_NAPALM)
}
}
// Ham Grenade Think Forward
public fw_ThinkGrenade(entity)
{
// Invalid entity
if (!pev_valid(entity)) return HAM_IGNORED;
// Get damage time of grenade
static Float:dmgtime
pev(entity, pev_dmgtime, dmgtime)
// Check if it's time to go off
if (dmgtime > get_gametime())
return HAM_IGNORED;
// Not a napalm grenade
if (pev(entity, PEV_NADE_TYPE) != NADE_TYPE_NAPALM)
return HAM_IGNORED;
fire_explode(entity);
// Keep the original explosion?
if (get_pcvar_num(cvar_grenade_fire_explosion))
{
set_pev(entity, PEV_NADE_TYPE, 0)
return HAM_IGNORED;
}
// Get rid of the grenade
engfunc(EngFunc_RemoveEntity, entity)
return HAM_SUPERCEDE;
}
// Fire Grenade Explosion
fire_explode(ent)
{
// Get origin
static Float:origin[3]
pev(ent, pev_origin, origin)
// Override original HE grenade explosion?
if (!get_pcvar_num(cvar_grenade_fire_explosion))
{
// Make the explosion
create_blast2(origin)
while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, origin, NADE_EXPLOSION_RADIUS)) != 0)
{
// Only effect alive zombies
if (!is_user_alive(victim) || !zp_core_is_zombie(victim))
continue;
set_on_fire(victim)
}
}
set_on_fire(victim)
{
// Allow other plugins to decide whether player should be burned or not
ExecuteForward(g_Forwards[FW_USER_BURN_PRE], g_ForwardResult, victim)
if (g_ForwardResult >= PLUGIN_HANDLED)
return false;
// Heat icon?
if (get_pcvar_num(cvar_grenade_fire_hudicon))
{
message_begin(MSG_ONE_UNRELIABLE, g_MsgDamage, _, victim)
write_byte(0) // damage save
write_byte(0) // damage take
write_long(DMG_BURN) // damage type
write_coord(0) // x
write_coord(0) // y
write_coord(0) // z
message_end()
}
// Reduced duration for Nemesis
if (LibraryExists(LIBRARY_NEMESIS, LibType_Library) && zp_class_nemesis_get(victim))
{
// fire duration (nemesis)
g_BurningDuration[victim] += get_pcvar_num(cvar_grenade_fire_duration)
}
else
{
// fire duration (zombie)
g_BurningDuration[victim] += get_pcvar_num(cvar_grenade_fire_duration) * 5
}
// Set burning task on victim
remove_task(victim+TASK_BURN)
set_task(0.2, "burning_flame", victim+TASK_BURN, _, _, "b")
return true;
}
// Burning Flames
public burning_flame(taskid)
{
// Get player origin and flags
static origin[3]
get_user_origin(ID_BURN, origin)
new flags = pev(ID_BURN, pev_flags)
// In water or burning stopped
if ((flags & FL_INWATER) || g_BurningDuration[ID_BURN] < 1)
{
// 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(g_smokeSpr) // sprite
write_byte(random_num(15, 20)) // scale
write_byte(random_num(10, 20)) // framerate
message_end()
// Task not needed anymore
remove_task(taskid)
return;
}
// Nemesis Class loaded?
if (!LibraryExists(LIBRARY_NEMESIS, LibType_Library) || !zp_class_nemesis_get(ID_BURN))
{
// Randomly play burning zombie scream sounds
if (random_num(1, 20) == 1)
{
static sound[SOUND_MAX_LENGTH]
ArrayGetString(g_sound_grenade_fire_player, random_num(0, ArraySize(g_sound_grenade_fire_player) - 1), sound, charsmax(sound))
emit_sound(ID_BURN, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
}
// Fire slow down
if ((flags & FL_ONGROUND) && get_pcvar_float(cvar_grenade_fire_slowdown) > 0.0)
{
static Float:velocity[3]
pev(ID_BURN, pev_velocity, velocity)
xs_vec_mul_scalar(velocity, get_pcvar_float(cvar_grenade_fire_slowdown), velocity)
set_pev(ID_BURN, pev_velocity, velocity)
}
}
// Get player's health
new health = get_user_health(ID_BURN)
// Take damage from the fire
if (health - floatround(get_pcvar_float(cvar_grenade_fire_damage), floatround_ceil) > 0)
set_user_health(ID_BURN, health - floatround(get_pcvar_float(cvar_grenade_fire_damage), floatround_ceil))
// 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(g_flameSpr) // sprite
write_byte(random_num(5, 10)) // scale
write_byte(200) // brightness
message_end()
// Models
new g_model_grenade_frost[MODEL_MAX_LENGTH] = "models/zombie_plague/v_grenade_frost.mdl"
// Sprites
new g_sprite_grenade_trail[SPRITE_MAX_LENGTH] = "sprites/laserbeam.spr"
new g_sprite_grenade_ring[SPRITE_MAX_LENGTH] = "sprites/shockwave.spr"
new g_sprite_grenade_glass[SPRITE_MAX_LENGTH] = "models/glassgibs.mdl"
new Array:g_sound_grenade_frost_explode
new Array:g_sound_grenade_frost_player
new Array:g_sound_grenade_frost_break
// Custom Forwards
enum _:TOTAL_FORWARDS
{
FW_USER_FREEZE_PRE = 0,
FW_USER_UNFROZEN
}
new g_Forwards[TOTAL_FORWARDS]
new g_ForwardResult
new g_IsFrozen
new Float:g_FrozenGravity[MAXPLAYERS+1]
new g_FrozenRenderingFx[MAXPLAYERS+1]
new Float:g_FrozenRenderingColor[MAXPLAYERS+1][3]
new g_FrozenRenderingRender[MAXPLAYERS+1]
new Float:g_FrozenRenderingAmount[MAXPLAYERS+1]
new g_MsgDamage, g_MsgScreenFade
new g_trailSpr, g_exploSpr, g_glassSpr
new cvar_grenade_frost_duration, cvar_grenade_frost_hudicon
public plugin_init()
{
register_plugin("[ZP] Grenade: Frost", ZP_VERSION_STRING, "ZP Dev Team")
// If we couldn't load custom sounds from file, use and save default ones
new index
if (ArraySize(g_sound_grenade_frost_explode) == 0)
{
for (index = 0; index < sizeof sound_grenade_frost_explode; index++)
ArrayPushString(g_sound_grenade_frost_explode, sound_grenade_frost_explode[index])
// Save to external file
amx_save_setting_string_arr(ZP_SETTINGS_FILE, "Sounds", "GRENADE FROST EXPLODE", g_sound_grenade_frost_explode)
}
if (ArraySize(g_sound_grenade_frost_player) == 0)
{
for (index = 0; index < sizeof sound_grenade_frost_player; index++)
ArrayPushString(g_sound_grenade_frost_player, sound_grenade_frost_player[index])
// Save to external file
amx_save_setting_string_arr(ZP_SETTINGS_FILE, "Sounds", "GRENADE FROST PLAYER", g_sound_grenade_frost_player)
}
if (ArraySize(g_sound_grenade_frost_break) == 0)
{
for (index = 0; index < sizeof sound_grenade_frost_break; index++)
ArrayPushString(g_sound_grenade_frost_break, sound_grenade_frost_break[index])
// Save to external file
amx_save_setting_string_arr(ZP_SETTINGS_FILE, "Sounds", "GRENADE FROST BREAK", g_sound_grenade_frost_break)
}
// Load from external file, save if not found
if (!amx_load_setting_string(ZP_SETTINGS_FILE, "Weapon Models", "GRENADE FROST", g_model_grenade_frost, charsmax(g_model_grenade_frost)))
amx_save_setting_string(ZP_SETTINGS_FILE, "Weapon Models", "GRENADE FROST", g_model_grenade_frost)
if (!amx_load_setting_string(ZP_SETTINGS_FILE, "Grenade Sprites", "TRAIL", g_sprite_grenade_trail, charsmax(g_sprite_grenade_trail)))
amx_save_setting_string(ZP_SETTINGS_FILE, "Grenade Sprites", "TRAIL", g_sprite_grenade_trail)
if (!amx_load_setting_string(ZP_SETTINGS_FILE, "Grenade Sprites", "RING", g_sprite_grenade_ring, charsmax(g_sprite_grenade_ring)))
amx_save_setting_string(ZP_SETTINGS_FILE, "Grenade Sprites", "RING", g_sprite_grenade_ring)
if (!amx_load_setting_string(ZP_SETTINGS_FILE, "Grenade Sprites", "GLASS", g_sprite_grenade_glass, charsmax(g_sprite_grenade_glass)))
amx_save_setting_string(ZP_SETTINGS_FILE, "Grenade Sprites", "GLASS", g_sprite_grenade_glass)
// Precache sounds
new sound[SOUND_MAX_LENGTH]
for (index = 0; index < ArraySize(g_sound_grenade_frost_explode); index++)
{
ArrayGetString(g_sound_grenade_frost_explode, index, sound, charsmax(sound))
precache_sound(sound)
}
for (index = 0; index < ArraySize(g_sound_grenade_frost_player); index++)
{
ArrayGetString(g_sound_grenade_frost_player, index, sound, charsmax(sound))
precache_sound(sound)
}
for (index = 0; index < ArraySize(g_sound_grenade_frost_break); index++)
{
ArrayGetString(g_sound_grenade_frost_break, index, sound, charsmax(sound))
precache_sound(sound)
}
public zp_fw_core_cure_post(id, attacker)
{
// Set custom grenade model
cs_set_player_view_model(id, CSW_FLASHBANG, g_model_grenade_frost)
// If frozen, remove freeze after player is cured
if (flag_get(g_IsFrozen, id))
{
// Update gravity and rendering values first
ApplyFrozenGravity(id)
ApplyFrozenRendering(id)
// Remove freeze right away and stop the task
remove_freeze(id+TASK_FROST_REMOVE)
remove_task(id+TASK_FROST_REMOVE)
}
}
public zp_fw_core_infect(id, attacker)
{
// Remove custom grenade model
cs_reset_player_view_model(id, CSW_FLASHBANG)
}
public zp_fw_core_infect_post(id, attacker)
{
// If frozen, update gravity and rendering
if (flag_get(g_IsFrozen, id))
{
ApplyFrozenGravity(id)
ApplyFrozenRendering(id)
}
}
public client_disconnect(id)
{
flag_unset(g_IsFrozen, id)
remove_task(id+TASK_FROST_REMOVE)
}
public fw_ResetMaxSpeed_Post(id)
{
// Dead or not frozen
if (!is_user_alive(id) || !flag_get(g_IsFrozen, id))
return;
// Prevent from moving
set_user_maxspeed(id, 1.0)
}
// Ham Trace Attack Forward
public fw_TraceAttack(victim, attacker)
{
// Non-player damage or self damage
if (victim == attacker || !is_user_alive(attacker))
return HAM_IGNORED;
// Block damage while frozen, as it makes killing zombies too easy
if (flag_get(g_IsFrozen, victim))
return HAM_SUPERCEDE;
return HAM_IGNORED;
}
// Ham Take Damage Forward (needed to block explosion damage too)
public fw_TakeDamage(victim, inflictor, attacker, Float:damage, damage_type)
{
// Non-player damage or self damage
if (victim == attacker || !is_user_alive(attacker))
return HAM_IGNORED;
// Block damage while frozen, as it makes killing zombies too easy
if (flag_get(g_IsFrozen, victim))
return HAM_SUPERCEDE;
return HAM_IGNORED;
}
// Ham Player Killed Forward
public fw_PlayerKilled(victim, attacker, shouldgib)
{
// Frozen player being killed (usually caused by a 3rd party plugin, e.g. lasermines)
if (flag_get(g_IsFrozen, victim))
{
// Remove freeze right away and stop the task
remove_freeze(victim+TASK_FROST_REMOVE)
remove_task(victim+TASK_FROST_REMOVE)
}
}
// Forward Player PreThink
public fw_PlayerPreThink(id)
{
// Not alive or not frozen
if (!is_user_alive(id) || !flag_get(g_IsFrozen, id))
return;
// Forward Set Model
public fw_SetModel(entity, const model[])
{
// We don't care
if (strlen(model) < 8)
return;
// Narrow down our matches a bit
if (model[7] != 'w' || model[8] != '_')
return;
// Get damage time of grenade
static Float:dmgtime
pev(entity, pev_dmgtime, dmgtime)
// Grenade not yet thrown
if (dmgtime == 0.0)
return;
// Grenade's owner is zombie?
if (zp_core_is_zombie(pev(entity, pev_owner)))
return;
// Flashbang
if (model[9] == 'f' && model[10] == 'l')
{
// Give it a glow
fm_set_rendering(entity, kRenderFxGlowShell, 0, 100, 200, kRenderNormal, 16);
// And a colored trail
message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
write_byte(TE_BEAMFOLLOW) // TE id
write_short(entity) // entity
write_short(g_trailSpr) // sprite
write_byte(10) // life
write_byte(10) // width
write_byte(0) // r
write_byte(100) // g
write_byte(200) // b
write_byte(200) // brightness
message_end()
// Set grenade type on the thrown grenade entity
set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_FROST)
}
}
// Ham Grenade Think Forward
public fw_ThinkGrenade(entity)
{
// Invalid entity
if (!pev_valid(entity)) return HAM_IGNORED;
// Get damage time of grenade
static Float:dmgtime
pev(entity, pev_dmgtime, dmgtime)
// Check if it's time to go off
if (dmgtime > get_gametime())
return HAM_IGNORED;
// Check if it's one of our custom nades
switch (pev(entity, PEV_NADE_TYPE))
{
case NADE_TYPE_FROST: // Frost Grenade
{
frost_explode(entity)
return HAM_SUPERCEDE;
}
}
while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, origin, NADE_EXPLOSION_RADIUS)) != 0)
{
// Only effect alive zombies
if (!is_user_alive(victim) || !zp_core_is_zombie(victim))
continue;
set_freeze(victim)
}
// Get rid of the grenade
engfunc(EngFunc_RemoveEntity, ent)
}
set_freeze(victim)
{
// Already frozen
if (flag_get(g_IsFrozen, victim))
return false;
// Allow other plugins to decide whether player should be frozen or not
ExecuteForward(g_Forwards[FW_USER_FREEZE_PRE], g_ForwardResult, victim)
if (g_ForwardResult >= PLUGIN_HANDLED)
{
// Get player's origin
static origin2[3]
get_user_origin(victim, origin2)
// Glass shatter
message_begin(MSG_PVS, SVC_TEMPENTITY, origin2)
write_byte(TE_BREAKMODEL) // TE id
write_coord(origin2[0]) // x
write_coord(origin2[1]) // y
write_coord(origin2[2]+24) // z
write_coord(16) // size x
write_coord(16) // size y
write_coord(16) // size z
write_coord(random_num(-50, 50)) // velocity x
write_coord(random_num(-50, 50)) // velocity y
write_coord(25) // velocity z
write_byte(10) // random velocity
write_short(g_glassSpr) // model
write_byte(10) // count
write_byte(25) // life
write_byte(BREAK_GLASS) // flags
message_end()
return false;
}
// Freeze icon?
if (get_pcvar_num(cvar_grenade_frost_hudicon))
{
message_begin(MSG_ONE_UNRELIABLE, g_MsgDamage, _, victim)
write_byte(0) // damage save
write_byte(0) // damage take
write_long(DMG_DROWN) // damage type - DMG_FREEZE
write_coord(0) // x
write_coord(0) // y
write_coord(0) // z
message_end()
}
// Add a blue tint to their screen
message_begin(MSG_ONE, g_MsgScreenFade, _, victim)
write_short(0) // duration
write_short(0) // hold time
write_short(FFADE_STAYOUT) // fade type
write_byte(0) // red
write_byte(50) // green
write_byte(200) // blue
write_byte(100) // alpha
message_end()
// Update player entity rendering
ApplyFrozenRendering(victim)
// Set a task to remove the freeze
set_task(get_pcvar_float(cvar_grenade_frost_duration), "remove_freeze", victim+TASK_FROST_REMOVE)
return true;
}
ApplyFrozenGravity(id)
{
// Get current gravity
new Float:gravity = get_user_gravity(id)
// Already set, no worries...
if (gravity == GRAVITY_HIGH || gravity == GRAVITY_NONE)
return;
// Save player's old gravity
g_FrozenGravity[id] = gravity
// Prevent from jumping
if (pev(id, pev_flags) & FL_ONGROUND)
set_user_gravity(id, GRAVITY_HIGH) // set really high
else
set_user_gravity(id, GRAVITY_NONE) // no gravity
}
ApplyFrozenRendering(id)
{
// Get current rendering
new rendering_fx = pev(id, pev_renderfx)
new Float:rendering_color[3]
pev(id, pev_rendercolor, rendering_color)
new rendering_render = pev(id, pev_rendermode)
new Float:rendering_amount
pev(id, pev_renderamt, rendering_amount)
// Gradually remove screen's blue tint
message_begin(MSG_ONE, g_MsgScreenFade, _, ID_FROST_REMOVE)
write_short(UNIT_SECOND) // duration
write_short(0) // hold time
write_short(FFADE_IN) // fade type
write_byte(0) // red
write_byte(50) // green
write_byte(200) // blue
write_byte(100) // alpha
message_end()
// Get player's origin
static origin[3]
get_user_origin(ID_FROST_REMOVE, origin)
// Glass shatter
message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
write_byte(TE_BREAKMODEL) // TE id
write_coord(origin[0]) // x
write_coord(origin[1]) // y
write_coord(origin[2]+24) // z
write_coord(16) // size x
write_coord(16) // size y
write_coord(16) // size z
write_coord(random_num(-50, 50)) // velocity x
write_coord(random_num(-50, 50)) // velocity y
write_coord(25) // velocity z
write_byte(10) // random velocity
write_short(g_glassSpr) // model
write_byte(10) // count
write_byte(25) // life
write_byte(BREAK_GLASS) // flags
message_end()
// Models
new g_model_grenade_flare[MODEL_MAX_LENGTH] = "models/zombie_plague/v_grenade_flare.mdl"
// Sprites
new g_sprite_grenade_trail[SPRITE_MAX_LENGTH] = "sprites/laserbeam.spr"
new Array:g_sound_grenade_flare_explode
// HACK: pev_ field used to store custom nade types and their values
const PEV_NADE_TYPE = pev_flTimeStepSound
const NADE_TYPE_FLARE = 4444
const PEV_FLARE_COLOR = pev_punchangle
const PEV_FLARE_DURATION = pev_flSwimTime
new g_trailSpr
new cvar_grenade_flare_duration, cvar_grenade_flare_radius, cvar_grenade_flare_color
public plugin_init()
{
register_plugin("[ZP] Grenade: Flare", ZP_VERSION_STRING, "ZP Dev Team")
public plugin_precache()
{
// Initialize arrays
g_sound_grenade_flare_explode = ArrayCreate(SOUND_MAX_LENGTH, 1)
// Load from external file
amx_load_setting_string_arr(ZP_SETTINGS_FILE, "Sounds", "GRENADE FLARE", g_sound_grenade_flare_explode)
// If we couldn't load custom sounds from file, use and save default ones
new index
if (ArraySize(g_sound_grenade_flare_explode) == 0)
{
for (index = 0; index < sizeof sound_grenade_flare_explode; index++)
ArrayPushString(g_sound_grenade_flare_explode, sound_grenade_flare_explode[index])
// Save to external file
amx_save_setting_string_arr(ZP_SETTINGS_FILE, "Sounds", "GRENADE FLARE", g_sound_grenade_flare_explode)
}
// Load from external file, save if not found
if (!amx_load_setting_string(ZP_SETTINGS_FILE, "Weapon Models", "GRENADE FLARE", g_model_grenade_flare, charsmax(g_model_grenade_flare)))
amx_save_setting_string(ZP_SETTINGS_FILE, "Weapon Models", "GRENADE FLARE", g_model_grenade_flare)
if (!amx_load_setting_string(ZP_SETTINGS_FILE, "Grenade Sprites", "TRAIL", g_sprite_grenade_trail, charsmax(g_sprite_grenade_trail)))
amx_save_setting_string(ZP_SETTINGS_FILE, "Grenade Sprites", "TRAIL", g_sprite_grenade_trail)
public zp_fw_core_cure_post(id, attacker)
{
// Set custom grenade model
cs_set_player_view_model(id, CSW_SMOKEGRENADE, g_model_grenade_flare)
}
public zp_fw_core_infect(id, attacker)
{
// Remove custom grenade model
cs_reset_player_view_model(id, CSW_SMOKEGRENADE)
}
// Forward Set Model
public fw_SetModel(entity, const model[])
{
// We don't care
if (strlen(model) < 8)
return;
// Narrow down our matches a bit
if (model[7] != 'w' || model[8] != '_')
return;
// Get damage time of grenade
static Float:dmgtime
pev(entity, pev_dmgtime, dmgtime)
// Grenade not yet thrown
if (dmgtime == 0.0)
return;
// Grenade's owner is zombie?
if (zp_core_is_zombie(pev(entity, pev_owner)))
return;
// Smoke Grenade
if (model[9] == 's' && model[10] == 'm')
{
// Build flare's color
static rgb[3]
switch (get_pcvar_num(cvar_grenade_flare_color))
{
case 0: // white
{
rgb[0] = 255 // r
rgb[1] = 255 // g
rgb[2] = 255 // b
}
case 1: // red
{
rgb[0] = random_num(50,255) // r
rgb[1] = 0 // g
rgb[2] = 0 // b
}
case 2: // green
{
rgb[0] = 0 // r
rgb[1] = random_num(50,255) // g
rgb[2] = 0 // b
}
case 3: // blue
{
rgb[0] = 0 // r
rgb[1] = 0 // g
rgb[2] = random_num(50,255) // b
}
case 4: // random (all colors)
{
rgb[0] = random_num(50,200) // r
rgb[1] = random_num(50,200) // g
rgb[2] = random_num(50,200) // b
}
case 5: // random (r,g,b)
{
switch (random_num(1, 3))
{
case 1: // red
{
rgb[0] = random_num(50,255) // r
rgb[1] = 0 // g
rgb[2] = 0 // b
}
case 2: // green
{
rgb[0] = 0 // r
rgb[1] = random_num(50,255) // g
rgb[2] = 0 // b
}
case 3: // blue
{
rgb[0] = 0 // r
rgb[1] = 0 // g
rgb[2] = random_num(50,255) // b
}
}
}
}
// Give it a glow
fm_set_rendering(entity, kRenderFxGlowShell, rgb[0], rgb[1], rgb[2], kRenderNormal, 16);
// And a colored trail
message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
write_byte(TE_BEAMFOLLOW) // TE id
write_short(entity) // entity
write_short(g_trailSpr) // sprite
write_byte(10) // life
write_byte(10) // width
write_byte(rgb[0]) // r
write_byte(rgb[1]) // g
write_byte(rgb[2]) // b
write_byte(200) // brightness
message_end()
// Set grenade type on the thrown grenade entity
set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_FLARE)
// Set flare color on the thrown grenade entity
set_pev(entity, PEV_FLARE_COLOR, rgb)
}
}
// Ham Grenade Think Forward
public fw_ThinkGrenade(entity)
{
// Invalid entity
if (!pev_valid(entity)) return HAM_IGNORED;
// Get damage time of grenade
static Float:dmgtime
pev(entity, pev_dmgtime, dmgtime)
new Float:current_time = get_gametime()
// Check if it's time to go off
if (dmgtime > current_time)
return HAM_IGNORED;
// Check if it's one of our custom nades
switch (pev(entity, PEV_NADE_TYPE))
{
case NADE_TYPE_FLARE: // Flare
{
// Get its duration
new duration = pev(entity, PEV_FLARE_DURATION)
// Already went off, do lighting loop for the duration of PEV_FLARE_DURATION
if (duration > 0)
{
// Check whether this is the last loop
if (duration == 1)
{
// Get rid of the flare entity
engfunc(EngFunc_RemoveEntity, entity)
return HAM_SUPERCEDE;
}
// Light it up!
flare_lighting(entity, duration)
// Set time for next loop
set_pev(entity, PEV_FLARE_DURATION, --duration)
set_pev(entity, pev_dmgtime, current_time + 2.0)
}
// Light up when it's stopped on ground
else if ((pev(entity, pev_flags) & FL_ONGROUND) && fm_get_speed(entity) < 10)
{
// Flare sound
static sound[SOUND_MAX_LENGTH]
ArrayGetString(g_sound_grenade_flare_explode, random_num(0, ArraySize(g_sound_grenade_flare_explode) - 1), sound, charsmax(sound))
emit_sound(entity, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
// Set duration and start lightning loop on next think
set_pev(entity, PEV_FLARE_DURATION, 1 + get_pcvar_num(cvar_grenade_flare_duration)/2)
set_pev(entity, pev_dmgtime, current_time + 0.1)
}
else
{
// Delay explosion until we hit ground
set_pev(entity, pev_dmgtime, current_time + 0.5)
}
}
}
return HAM_IGNORED;
}
// Flare Lighting Effects
flare_lighting(entity, duration)
{
// Get origin and color
static Float:origin[3], color[3]
pev(entity, pev_origin, origin)
pev(entity, PEV_FLARE_COLOR, color)
// Lighting
engfunc(EngFunc_MessageBegin, MSG_PAS, SVC_TEMPENTITY, origin, 0)
write_byte(TE_DLIGHT) // TE id
engfunc(EngFunc_WriteCoord, origin[0]) // x
engfunc(EngFunc_WriteCoord, origin[1]) // y
engfunc(EngFunc_WriteCoord, origin[2]) // z
write_byte(get_pcvar_num(cvar_grenade_flare_radius)) // radius
write_byte(color[0]) // r
write_byte(color[1]) // g
write_byte(color[2]) // b
write_byte(21) //life
write_byte((duration < 2) ? 3 : 0) //decay rate
message_end()
// Sparks
engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, origin, 0)
write_byte(TE_SPARKS) // TE id
engfunc(EngFunc_WriteCoord, origin[0]) // x
engfunc(EngFunc_WriteCoord, origin[1]) // y
engfunc(EngFunc_WriteCoord, origin[2]) // z
message_end()
}
// 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)