Spoiler :
/*
----------------------------
Description
----------------------------
A Zombie Class for Zombie Plague Mod( L4D Witch )
What can this do?
* Idle mode( No moving, jumping, ducking ), only when crying.
* Crying( Random L4D Sounds ) when not attacked
* Angry( Random L4D Sounds ) when startled by radius/attacked.
* Pain Shock Free( Can be disabled by changing the CVar )
* Red Aura( Only when crying )
----------------------------
Update Logs
----------------------------
v1.0 - Intial Release
v1.1 - Engine not needed anymore
v1.2 - Optimized code( No need for damage event anymore )
- Now works flawlessly with napalm and frost nades
- Fix zombie scream twice
- Fix pain shock free not given to witch
- Removed define for zombie health( Automatically check for zombie's health )
v1.3 - Added damage multiplier
v1.4 - Fix radius affecting through walls
v1.5 - Removed Pain Shock( Buggy, only works sometimes )
- FakeMeta ---> Engine
v1.5a - Removed some useless checks
----------------------------
Suggestions & Bug reporting
----------------------------
1. PM( Private Message ) me( Recommended, I online very often. )
----------------------------
Credits
----------------------------
007 -> Idea, main plug-in, fixed radius , damage multiplier, L4D Sounds( Rip from L4D Folder )
Merc3y. -> Some console error fixes and minor bug fixes
Zombie Plague Core -> Witch aura
----------------------------
*/
#include < amxmodx >
#include < engine >
#include < hamsandwich >
#include < fun >
#include < zombieplague >
#define IsPlayer(%1) (1 <= %1 <= gMaxPlayers)
new const zclass_name[ ] = "L4D Witch"
new const zclass_info[ ] = ""
new const zclass_model[ ] = "zombie_source"
new const zclass_clawmodel[ ] = "v_knife_zombie.mdl"
const zclass_health = 500
const zclass_speed = 1
const Float:zclass_gravity = 0.875
const Float:zclass_knockback = 0.0
// Random Cry & Angry sounds( Rip from L4D Folder )
new Cry[ 3 ][ ] =
{
"zombie_plague/female_cry_1.wav",
"zombie_plague/female_cry_2.wav",
"zombie_plague/female_cry_3.wav"
}
new Angry[ 2 ][ ] =
{
"zombie_plague/female_ls_d_madscream01.wav",
"zombie_plague/female_ls_d_madscream02.wav"
}
new g_zclass_witch,
g_witch_radius,
g_witch_maxspeed,
g_witch_dmg_multi,
g_witch_move_time,
g_witch_red_aura_radius,
g_witch_red_aura_amt,
gMaxPlayers
new bool: g_b_isCrying[ 33 ],
bool: g_b_isAngry[ 33 ],
bool: g_b_Radius[ 33 ]
public plugin_init( )
{
register_plugin( "[ZP] ZClass: L4D Witch", "1.5a", "007" )
RegisterHam( Ham_TakeDamage, "player", "fw_TakeDamage" )
RegisterHam( Ham_Player_PreThink, "player", "fw_PlayerPreThink" )
// CVars
g_witch_radius = register_cvar( "zp_witch_radius", "300" ) // If a player( Only human or survivor ) is within the radius, Witch will be startled
g_witch_maxspeed = register_cvar( "zp_witch_maxspeed", "400.0" ) // Amount of max speed should be set if startled
g_witch_dmg_multi = register_cvar( "zp_witch_dmg_multi", "3.0" ) // Amount of damage witch should deal( 1.0: Normal Damage | 2.0: 2X Dmg | 3.0: Default )
g_witch_move_time = register_cvar( "zp_witch_move_time", "30.0" ) // Amount of time after not attacked, then witch can move
g_witch_red_aura_radius = register_cvar( "zp_witch_red_aura_radius", "10" ) // Red aura radius
g_witch_red_aura_amt = register_cvar( "zp_witch_red_aura_amt", "180" ) // Amount of red aura( 0: Black | 255: White | 180: Default( Red ) )
gMaxPlayers = get_maxplayers( )
}
public plugin_precache( )
{
g_zclass_witch = zp_register_zombie_class( zclass_name, zclass_info, zclass_model, zclass_clawmodel, zclass_health, zclass_speed, zclass_gravity, zclass_knockback )
for( new i = 0;i < sizeof Cry;i++ )
precache_sound( Cry[ i ] )
for( new i = 0;i < sizeof Angry;i++)
precache_sound( Angry[ i ] )
}
public zp_user_infected_post( id, infector )
{
if( zp_get_user_zombie_class( id ) == g_zclass_witch && !zp_get_user_nemesis( id ) )
{
client_print( id, print_chat, "[ZP] You are now in idle mode." )
g_b_isCrying[ id ] = true
g_b_isAngry[ id ] = false
g_b_Radius[ id ] = true
set_task( 8.0, "Witch_Cry", id, _, _, "b" )
set_task( get_pcvar_float( g_witch_move_time ), "Witch_Move", id )
}
}
public zp_user_unfrozen( id )
{
if( g_b_isCrying[ id ] && !g_b_isAngry[ id ] )
{
g_b_isCrying[ id ] = false
g_b_isAngry[ id ] = true
emit_sound( id, CHAN_STREAM, Angry[ random_num( 0, sizeof Angry - 1 ) ], 1.0, ATTN_NORM, 0, PITCH_HIGH )
}
}
public fw_PlayerPreThink( id )
{
if( !is_user_alive( id ) || !zp_get_user_zombie( id ) || zp_get_user_zombie_class( id ) != g_zclass_witch || zp_get_user_nemesis( id ) )
return
if( g_b_isCrying[ id ] && !g_b_isAngry[ id ] )
{
// Stop Max Speed & Velocity
set_user_maxspeed( id, 1.0 )
set_user_velocity( id, Float:{ 0.0, 0.0, 0.0 } )
// Block Jump and Duck( When crying ) to prevent gravity bug
entity_set_int( id, EV_INT_oldbuttons, entity_get_int( id, EV_INT_oldbuttons ) | IN_JUMP | IN_DUCK )
// Aura
static origin[ 3 ]
get_user_origin( id, origin )
message_begin( MSG_PVS, SVC_TEMPENTITY, origin )
write_byte( TE_DLIGHT )
write_coord( origin[0] )
write_coord( origin[1] )
write_coord( origin[2] )
write_byte( get_pcvar_num( g_witch_red_aura_radius ) )
write_byte( get_pcvar_num( g_witch_red_aura_amt ) )
write_byte( 0 )
write_byte( 0 )
write_byte( 1 )
write_byte( 0 )
message_end( )
}
else if( !g_b_isCrying[ id ] && g_b_isAngry[ id ] )
{
set_user_maxspeed( id, get_pcvar_float( g_witch_maxspeed ) )
}
if( get_user_health( id ) < zclass_health && g_b_isCrying[ id ] && !g_b_isAngry[ id ] )
{
g_b_isCrying[ id ] = false
g_b_isAngry[ id ] = true
emit_sound( id, CHAN_STREAM, Angry[ random_num( 0, sizeof Angry - 1 ) ], 1.0, ATTN_NORM, 0, PITCH_HIGH )
}
else if( zp_get_user_first_zombie( id ) && get_user_health( id ) < zp_get_zombie_maxhealth( id ) && g_b_isCrying[ id ] && !g_b_isAngry[ id ] )
{
g_b_isCrying[ id ] = false
g_b_isAngry[ id ] = true
emit_sound( id, CHAN_STREAM, Angry[ random_num( 0, sizeof Angry - 1 ) ], 1.0, ATTN_NORM, 0, PITCH_HIGH )
}
if( g_b_Radius[ id ] && g_b_isCrying[ id ] )
{
for( new i = 1; i <= gMaxPlayers; i++ )
{
if( is_user_alive( i ) && !zp_get_user_zombie( i ) || is_user_alive( i ) && zp_get_user_survivor( i ) )
{
new Distance; Distance = get_entity_distance( i, id )
if( Distance <= get_pcvar_num( g_witch_radius ) && is_visible( id, i ) )
{
g_b_isCrying[ id ] = false
g_b_isAngry[ id ] = true
g_b_Radius[ id ] = false
emit_sound( id, CHAN_STREAM, Angry[ random_num( 0, sizeof Angry - 1 ) ], 1.0, ATTN_NORM, 0, PITCH_HIGH )
}
}
}
}
}
public Witch_Cry( id )
{
if( is_user_alive( id ) && zp_get_user_zombie( id ) && zp_get_user_zombie_class( id ) == g_zclass_witch && !zp_get_user_nemesis( id ) && g_b_isCrying[ id ] && !g_b_isAngry[ id ] )
{
emit_sound( id, CHAN_STREAM, Cry[ random_num( 0, sizeof Cry - 1 ) ], 1.0, ATTN_NORM, 0, PITCH_HIGH )
}
}
public fw_TakeDamage( victim, inflictor, attacker, Float:damage, damagebits )
{
if( IsPlayer( attacker ) && zp_get_user_zombie( attacker ) && zp_get_user_zombie_class( attacker ) == g_zclass_witch && !zp_get_user_nemesis( attacker ) )
{
SetHamParamFloat( 4, damage * get_pcvar_float( g_witch_dmg_multi ) )
}
}
public Witch_Move( id )
{
if( g_b_isCrying[ id ] && !g_b_isAngry[ id ] )
{
g_b_isCrying[ id ] = false
g_b_isAngry[ id ] = true
emit_sound( id, CHAN_STREAM, Angry[ random_num( 0, sizeof Angry - 1 ) ], 1.0, ATTN_NORM, 0, PITCH_HIGH )
}
}