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

#define CUSTOM_MODELS  1
#define MAX_KNIFE_SNDS 9

#if (CUSTOM_MODELS)
	new MODEL_PLAYER[] 	= "models/p_crowbar.mdl"
#endif

#define PLUGIN	"Knife Knockback"
#define VERSION	"2.0"
#define AUTHOR	"CHyC"

new zp_knife_sound;

new cvar_knife , cvar_knock , cvar_jump , cvar_sound , cvar_survivor;

public plugin_init()
{
	register_plugin(PLUGIN , VERSION , AUTHOR);
	register_cvar("zp_knife", VERSION, FCVAR_SERVER);
	register_event("Damage" , "event_Damage" , "b" , "2>0");
	register_event( "CurWeapon", "Event_CurWeapon", "be", "1=1" );
	register_event("HLTV", "event_round_start", "a");
	register_forward(FM_EmitSound, "fw_EmitSound");

	cvar_knife         = register_cvar("zp_knife_knock" , "1");
	cvar_knock	   = register_cvar("zp_knife_power" , "10");
	cvar_jump          = register_cvar("zp_knife_jump", "300.0");
        cvar_sound         = register_cvar("zp_knife_sound" , "1");
        cvar_survivor      = register_cvar("zp_knife_survivor" , "1");
}

public event_round_start()
{
	if (get_pcvar_num(cvar_sound) == 1)
		zp_knife_sound = true;
	else
		zp_knife_sound = false;
}

public event_Damage(id)
{
	if(!get_pcvar_num(cvar_knife))
		return PLUGIN_CONTINUE;

	if(!is_user_alive(id))
		return PLUGIN_CONTINUE;

	if(zp_is_survivor_round() && get_pcvar_num(cvar_survivor) == 0)
		return PLUGIN_CONTINUE;

	new weapon , attacker = get_user_attacker(id , weapon);

	if(!is_user_alive(attacker))
		return PLUGIN_CONTINUE;

	if(weapon == CSW_KNIFE)
	{
		new Float:vec[3];
		new Float:oldvelo[3];
		get_user_velocity(id, oldvelo);
		create_velocity_vector(id , attacker , vec);
		vec[0] += oldvelo[0];
		vec[1] += oldvelo[1];
		set_user_velocity(id , vec);
	}

	return PLUGIN_CONTINUE;
}

public Event_CurWeapon( id )
{
	if (!is_user_connected(id) || !is_user_alive(id) || zp_get_user_zombie(id))
		return PLUGIN_CONTINUE
	
	new WeaponID = read_data(2)
	if (WeaponID != CSW_KNIFE)
		return  PLUGIN_CONTINUE
	
	#if (CUSTOM_MODELS)
		entity_set_string(id, EV_SZ_weaponmodel, MODEL_PLAYER)
	#endif
	
	return PLUGIN_CONTINUE;
} 

stock create_velocity_vector(victim,attacker,Float:velocity[3])
{
	if(!zp_get_user_zombie(victim) || !is_user_alive(attacker))
		return 0;

	new Float:vicorigin[3];
	new Float:attorigin[3];
	entity_get_vector(victim   , EV_VEC_origin , vicorigin);
	entity_get_vector(attacker , EV_VEC_origin , attorigin);

	new Float:origin2[3]
	origin2[0] = vicorigin[0] - attorigin[0];
	origin2[1] = vicorigin[1] - attorigin[1];

	new Float:largestnum = 0.0;

	if(floatabs(origin2[0])>largestnum) largestnum = floatabs(origin2[0]);
	if(floatabs(origin2[1])>largestnum) largestnum = floatabs(origin2[1]);

	origin2[0] /= largestnum;
	origin2[1] /= largestnum;

	velocity[0] = ( origin2[0] * (get_pcvar_float(cvar_knock) * 3000) ) / get_entity_distance(victim , attacker);
	velocity[1] = ( origin2[1] * (get_pcvar_float(cvar_knock) * 3000) ) / get_entity_distance(victim , attacker);
	if(velocity[0] <= 20.0 || velocity[1] <= 20.0)
		velocity[2] = random_float(200.0 , 275.0);

	return 1;
}

new knife_sounds_o[MAX_KNIFE_SNDS][] =
{
             "weapons/knife_deploy1.wav",
             "weapons/knife_hit1.wav",
             "weapons/knife_hit2.wav",
             "weapons/knife_hit3.wav",
             "weapons/knife_hit4.wav",
             "weapons/knife_hitwall1.wav",
             "weapons/knife_slash1.wav",
             "weapons/knife_slash2.wav",
             "weapons/knife_stab.wav"
}

new knife_sounds_r[MAX_KNIFE_SNDS][] =
{
             "zombie_plague/knife_deploy1.wav",
             "zombie_plague/knife_hit1.wav",
             "zombie_plague/knife_hit2.wav",
             "zombie_plague/knife_hit3.wav",
             "zombie_plague/knife_hit4.wav",
             "zombie_plague/knife_hitwall1.wav",
             "zombie_plague/knife_slash1.wav",
             "zombie_plague/knife_slash2.wav",
             "zombie_plague/knife_stab.wav"
}

public plugin_precache()
{
          for(new i = 0; i < MAX_KNIFE_SNDS; i++)
                precache_sound(knife_sounds_r[i]);

	#if (CUSTOM_MODELS)
		precache_model(MODEL_PLAYER)
	#endif
}

public EmitSound(entity, channel, const sound[])
{
       if(pev_valid(entity) && is_user_alive(entity))
      {
             for(new i = 0; i < MAX_KNIFE_SNDS; i++)
               {
                   if(equal(sound , knife_sounds_o[i]))
               {
             if (zp_knife_sound) emit_sound(entity, channel, knife_sounds_r[i], 1.0, ATTN_NORM, 0, PITCH_NORM);
             return FMRES_SUPERCEDE;
      }
   }
}
   return FMRES_IGNORED;
}

public client_PreThink(id)
{
	if (!is_user_connected(id) || !is_user_alive(id) || zp_get_user_zombie(id))
		return PLUGIN_CONTINUE

	new temp[2], weapon = get_user_weapon(id, temp[0], temp[1])
	if (weapon != CSW_KNIFE)
		return PLUGIN_CONTINUE
		
	if ((get_user_button(id) & IN_JUMP) && !(get_user_oldbutton(id) & IN_JUMP))
	{
		new flags = entity_get_int(id, EV_INT_flags)
		new waterlvl = entity_get_int(id, EV_INT_waterlevel)
		
		if (!(flags & FL_ONGROUND))
			return PLUGIN_CONTINUE
		if (flags & FL_WATERJUMP)
			return PLUGIN_CONTINUE
		if (waterlvl > 1)
			return PLUGIN_CONTINUE
				
		new Float:fVelocity[3]
		entity_get_vector(id, EV_VEC_velocity, fVelocity)
		fVelocity[2] += get_pcvar_num(cvar_jump)
		
		entity_set_vector(id, EV_VEC_velocity, fVelocity)
		entity_set_int(id, EV_INT_gaitsequence, 6)
	}
	return PLUGIN_CONTINUE;
}  

