// SCORPION! - from the Mortal Kombat series, known for his spear move and saying "Get Over Here" 

//----------------------------------------------------------------------------------------------
// Scorpion - This is about a 80% code change from the original one
// + alot of extra added code to make this workable lol.
//
// Rewritten by DuPeR aka yang
//
// Big THANKS TO VITTU FOR MAKING THE UPPERCUT TO WORK/OPTIMIZING USELESS CODES, BIG FUCKING SEXY THANKS :D
// Also BIG thanx to the makers of super hero Batgirl for the cheapreel code and basic script core (sharky/JTP10181)
// This was originally done by Revengist but his apperantly didn't work. Which is why I remade it.
//
//----------------------------------------------------------------------------------------------

/* CVARS - copy and paste to shconfig.cfg

//Scorpion
scorpion_level 9
scorpion_maxhooks 30		//Max ammout of spears/hooks allowed, -1 is an unlimited ammount (Default 30)
scorpion_reelspeed 1000		//How fast hook line reels speared users in (Default 1000)
scorpion_dragmates 0		//Drag teammates, 0-no 1-yes
scorpion_knifefight 0		//Knife only with enemies you speared til death, 0-no 1-yes (Default 0)
scorpion_mode 1			//0-no xtra mode/dmg, 1-uppercut dmg, 2-line dmg and stun, 3-both 1 and 2 (Default 1)
//If scorpion_mode 1 or 3, this gets used:
scorpion_uppercutdmg 20		//Amount of Damage for uppercut performed when speared user is touched (Default 20)
//If scorpion_mode 2 or 3, these get used:
scorpion_speardmg 20		//Amount of Damage done when user is speared (Default 20)
scorpion_stuntime 2			//Seconds of stun when user is speared (Default 2)

*/

//----------------------------------------------------------------------------------------------
/*

Version History:

2.0    - PSX2 Version of Scorpion born.

2.01   - Fixed Emp's hold down button bug.

2.1    - Added allow drag teammates. 
				 Minor bug fix/optimization.

2.15   - Fixed code to reflect standards of sh making.
				 Added correct credits on top of script.
				 Added small distortion to line.
				 Cleaned up small codes.

2.2   - vittu - 12/9/2005
				Code cleaned up and reworked
				Fixed blood splash look and added second one for spear damage
				Changed so speared user is let go if touched
				Changed so both damage modes can be used
				Added amx support
				Added Knife Fight mode, forced knife fights til user/s in fight die
				Added sounds for uppercut and spear hit

2.3   - vittu - 5/31/2006
				Fixed small issue where pToucher should have been pTouched, however
					recoded that part anyway to a simpler form.
				Also fixed misnamed cvar so spear damage works now, not sure why
					no one noticed.
2.4   - vittu - 7/6/2007
				Fixed uppercut from being called on non-alive/non-connected players.
				Will fully convert to amxmodx on next update.
*/
//----------------------------------------------------------------------------------------------

#include <amxmod>
#include <Vexd_Utilities>
#include <superheromod>

// GLOBAL VARIABLES
new g_heroName[]="Scorpion"
new bool:g_hasScorpionPower[SH_MAXSLOTS+1]
new bool:g_knifeFight[SH_MAXSLOTS+1][SH_MAXSLOTS+1]
new bool:g_inKnifeFight[SH_MAXSLOTS+1]
new g_hooked[SH_MAXSLOTS+1]
new g_hooksLeft[SH_MAXSLOTS+1]
new g_lastWeapon[SH_MAXSLOTS+1]
new g_spriteLine, g_spriteBlood, g_spriteBldSpray
//----------------------------------------------------------------------------------------------
public plugin_init()
{
	// Plugin Info
	register_plugin("SUPERHERO Scorpion", "2.3", "ReVeNgIsT/yang/vittu")

	// DO NOT EDIT THIS FILE TO CHANGE CVARS, USE THE SHCONFIG.CFG
	register_cvar("scorpion_level", "9")
	register_cvar("scorpion_maxhooks", "30")
	register_cvar("scorpion_reelspeed", "1000")
	register_cvar("scorpion_dragmates", "0")
	register_cvar("scorpion_knifefight", "0")
	register_cvar("scorpion_mode", "1")
	register_cvar("scorpion_uppercutdmg", "20")
	register_cvar("scorpion_speardmg", "20")
	register_cvar("scorpion_stuntime", "2")

	// FIRE THE EVENT TO CREATE THIS SUPERHERO!
	shCreateHero(g_heroName, "Get Over Here!", "Hold +power key to Harpoon and Drag opponents to you.", true, "scorpion_level")

	// REGISTER EVENTS THIS HERO WILL RESPOND TO! (AND SERVER COMMANDS)
	// INIT
	register_srvcmd("scorpion_init", "scorpion_init")
	shRegHeroInit(g_heroName, "scorpion_init")

	// KEY UP
	register_srvcmd("scorpion_ku", "scorpion_ku")
	shRegKeyUp(g_heroName, "scorpion_ku")

	// KEY DOWN
	register_srvcmd("scorpion_kd", "scorpion_kd")
	shRegKeyDown(g_heroName, "scorpion_kd")

	// NEW SPAWN
	register_event("ResetHUD", "newSpawn", "b")

	// DEATH
	register_event("DeathMsg", "scorpion_death", "a")

	// WEAPON CHANGE
	register_event("CurWeapon", "changeWeapon", "be", "1=1")
}
//----------------------------------------------------------------------------------------------
public plugin_precache()
{
	precache_sound("shmod/scorpion_getoverhere.wav")
	precache_sound("player/headshot3.wav")
	precache_sound("weapons/xbow_hitbod1.wav")
	g_spriteLine = precache_model("sprites/zbeam4.spr")
	g_spriteBlood = precache_model("sprites/blood.spr")
	g_spriteBldSpray = precache_model("sprites/bloodspray.spr")
}
//----------------------------------------------------------------------------------------------
public scorpion_init()
{
	// First Argument is an id
	new temp[6]
	read_argv(1,temp,5)
	new id = str_to_num(temp)

	// 2nd Argument is 0 or 1 depending on whether the id has the hero
	read_argv(2,temp,5)
	new hasPowers = str_to_num(temp)

	g_hasScorpionPower[id] = (hasPowers != 0)

	if ( g_hooked[id] ) scorpion_hookOff(id)
}
//----------------------------------------------------------------------------------------------
public newSpawn(id)
{
	g_hooksLeft[id] = get_cvar_num("scorpion_maxhooks")

	if ( g_hooked[id] ) scorpion_hookOff(id)

	// Should only get run if no one dies (ie. map objective was completed)
	if ( g_inKnifeFight[id] ) {
		g_inKnifeFight[id] = false
		for (new i = 1; i <= SH_MAXSLOTS; i++) {
			// check id for any knife fights to turn off
			if ( g_knifeFight[id][i] ) {
				g_knifeFight[id][i] = false
			}
			if ( g_knifeFight[i][id] ) {
				g_knifeFight[i][id] = false
			}
		}
	}
}
//----------------------------------------------------------------------------------------------
public scorpion_kd()
{
	// First Argument is an id
	new temp[6]
	read_argv(1,temp,5)
	new id = str_to_num(temp)

	if ( !is_user_alive(id) || !g_hasScorpionPower[id] || !hasRoundStarted() || !shModActive() ) return

	scorpion_hookOn(id)
}
//----------------------------------------------------------------------------------------------
public scorpion_ku()
{
	// First Argument is an id
	new temp[6]
	read_argv(1,temp,5)
	new id = str_to_num(temp)

	scorpion_hookOff(id)
}
//----------------------------------------------------------------------------------------------
public scorpion_hookOn(id)
{
	if ( !is_user_alive(id) ) return

	if ( g_hooksLeft[id] == 0 ) {
		playSoundDenySelect(id)
		return
	}

	if ( g_hooksLeft[id] > 0 ) g_hooksLeft[id]--

	if ( g_hooksLeft[id] >= 0 && g_hooksLeft[id] < 5 ) {
		client_print(id, print_center, "You have %d Scorpion Spear%s left", g_hooksLeft[id], (g_hooksLeft[id] == 1) ? "" : "s")
	}

	new hooktarget, body


	get_user_aiming(id, hooktarget, body)

	if ( is_user_alive(hooktarget) ) {
		new mode = get_cvar_num("scorpion_mode")

		if ( get_user_team(hooktarget) != get_user_team(id) ) {
			g_hooked[id] = hooktarget
			emit_sound(hooktarget, CHAN_BODY, "weapons/xbow_hitbod1.wav", 0.6, ATTN_NORM, 0, PITCH_HIGH)

			if ( mode >= 2 ) {
				if ( !get_user_godmode(hooktarget) ) blood_spurt(hooktarget, id)
				shExtraDamage(hooktarget, id, get_cvar_num("scorpion_speardmg"), "Scorpion Spear")
				shStun(hooktarget, get_cvar_num("scorpion_stuntime"))
				set_user_maxspeed(hooktarget, 100.0)
			}

			//Knife fight only with enemies
			if ( get_cvar_num("scorpion_knifefight") && !g_knifeFight[id][hooktarget] ) {
				g_knifeFight[id][hooktarget] = true
				scorpion_fight_on(id, hooktarget)
				scorpion_fight_on(hooktarget, id)
			}
		}
		else if ( get_cvar_num("scorpion_dragmates") == 1 ) {
			g_hooked[id] = hooktarget
			emit_sound(hooktarget, CHAN_BODY, "weapons/xbow_hitbod1.wav", 0.6, ATTN_NORM, 0, PITCH_HIGH)

			new ffOn = get_cvar_num("mp_friendlyfire")
			if ( ffOn && mode >= 2 ) {
				if ( !get_user_godmode(hooktarget) ) blood_spurt(hooktarget, id)
				shExtraDamage(hooktarget, id, get_cvar_num("scorpion_speardmg"), "Scorpion Spear")
				shStun(hooktarget, get_cvar_num("scorpion_stuntime"))
				set_user_maxspeed(hooktarget, 100.0)
			}
		}
		else {
			g_hooked[id] = SH_MAXSLOTS+1
			hook_notarget(id)
			return
		}

		emit_sound(id, CHAN_VOICE, "shmod/scorpion_getoverhere.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)

		new parm[2]
		parm[0] = id
		parm[1] = hooktarget
		set_task(0.1, "scorpion_reelin", id, parm, 2, "b")

		hook_target(parm)
	}
	else {
		g_hooked[id] = SH_MAXSLOTS+1
		hook_notarget(id)
	}
}
//----------------------------------------------------------------------------------------------
public scorpion_reelin(parm[])
{
	// Drags player to you
	new id = parm[0]
	new victim = parm[1]

	if ( !g_hooked[id] ) return

	if ( !is_user_alive(victim) ) {
		scorpion_hookOff(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 / get_cvar_float("scorpion_reelspeed")

		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
	}

	Entvars_Set_Vector(victim, EV_VEC_velocity, fl_Velocity)
}
//----------------------------------------------------------------------------------------------
public scorpion_hookOff(id)
{
	g_hooked[id] = 0

	hook_remove(id)

	remove_task(id)
}
//----------------------------------------------------------------------------------------------
#if defined AMX_NEW
public entity_touch(entity1, entity2) {
	new pToucher = entity1
	new pTouched = entity2
#else
public vexd_pfntouch(pToucher, pTouched) {
#endif

	if ( !is_user_alive(pToucher) || !is_user_alive(pTouched) ) return

	if ( g_hasScorpionPower[pTouched] && g_hooked[pTouched] == pToucher ) {

		scorpion_hookOff(pTouched)

		new mode = get_cvar_num("scorpion_mode")
		if ( mode != 2 ) {

			new ffOn = get_cvar_num("mp_friendlyfire")
			if ( ffOn || get_user_team(pToucher) != get_user_team(pTouched) ) {

				new parm[2]
				parm[0] = pTouched
				parm[1] = pToucher
				set_task(0.1, "uppercut", pTouched+100, parm, 2)
			}
		}
	}
}
//----------------------------------------------------------------------------------------------
public uppercut(parm[])
{
	new vic = parm[1]
	if ( !is_user_alive(vic) ) return

	new id = parm[0]
	new Origin[3], vicOrigin[3]

	get_user_origin(id, Origin)
	get_user_origin(vic, vicOrigin)

	emit_sound(vic, CHAN_BODY, "player/headshot3.wav", 1.0, ATTN_NORM, 0, PITCH_LOW)
	if ( !get_user_godmode(vic) ) blood_spray(vic, vicOrigin)

	new Float:fl_Time = get_distance(vicOrigin, Origin) / 300.0

	new Float:fl_vicVelocity[3]
	fl_vicVelocity[0] = (vicOrigin[0] - Origin[0]) / fl_Time
	fl_vicVelocity[1] = (vicOrigin[1] - Origin[1]) / fl_Time
	fl_vicVelocity[2] = 450.0

	Entvars_Set_Vector(vic, EV_VEC_velocity, fl_vicVelocity)

	shExtraDamage(vic, id, get_cvar_num("scorpion_uppercutdmg"), "Scorpion Uppercut")
}
//----------------------------------------------------------------------------------------------
public scorpion_fight_on(id, enemy)
{
	new enemy_name[32]
	get_user_name(enemy, enemy_name, 31)
	client_print(id, print_chat, "[SH](Scorpion) Mortal Kombat! Knife til death with %s", enemy_name)
	client_print(id, print_center, "FIGHT!")

	if ( g_inKnifeFight[id] ) return

	sh_setScreenFlash(id, 255, 255, 25, 10, 45)

	// Remember this weapon...
	new clip, ammo, weaponID = get_user_weapon(id, clip, ammo)
	g_lastWeapon[id] = weaponID

	// switch to knife
	if ( g_lastWeapon[id] != CSW_KNIFE ) engclient_cmd(id, "weapon_knife")

	g_inKnifeFight[id] = true
}
//----------------------------------------------------------------------------------------------
public scorpion_fight_off(id)
{
	g_inKnifeFight[id] = false

	for (new i = 1; i <= SH_MAXSLOTS; i++) {
		// check id for any knife fights to turn off
		new bool:fight_found = false
		if ( g_knifeFight[id][i] ) {
			g_knifeFight[id][i] = false
			fight_found = true
		}
		if ( g_knifeFight[i][id] ) {
			g_knifeFight[i][id] = false
			fight_found = true
		}
		if ( fight_found ) {
			// check if i is in any other knife fights
			new bool:other_fight = false
			for (new j = 1; j <= SH_MAXSLOTS; j++) {
				if ( g_knifeFight[j][i] || g_knifeFight[i][j] ) {
					other_fight = true
					break
				}
			}
			if ( !other_fight ) {
				g_inKnifeFight[i] = false
				new i_name[32]
				get_user_name(i, i_name, 31)
				client_print(i, print_center, "%s WINS", i_name)
				if ( is_user_connected(id) ) client_print(id, print_center, "%s WINS", i_name)
				sh_setScreenFlash(i, 255, 255, 25, 10, 45)
				// Switch back to previous weapon...
				if ( g_lastWeapon[i] != CSW_KNIFE ) shSwitchWeaponID(i, g_lastWeapon[i])
			}
		}
	}
}
//----------------------------------------------------------------------------------------------
public changeWeapon(id)
{
	if ( !shModActive() || !g_inKnifeFight[id] || !get_cvar_num("scorpion_knifefight") ) return

	new wpnid = read_data(2)

	if ( wpnid == CSW_KNIFE ) return

	client_cmd(id, "weapon_knife")
}
//----------------------------------------------------------------------------------------------
public scorpion_death()
{
	new id = read_data(2)

	if ( g_hooked[id] ) scorpion_hookOff(id)

	if ( g_inKnifeFight[id] ) scorpion_fight_off(id)
}
//----------------------------------------------------------------------------------------------
public client_disconnect(id)
{
	// stupid check but lets see
	if ( id <= 0 || id > SH_MAXSLOTS ) return

	if ( g_hooked[id] ) scorpion_hookOff(id)

	if ( g_inKnifeFight[id] ) scorpion_fight_off(id)
}
//----------------------------------------------------------------------------------------------
public hook_target(parm[])
{
	new id = parm[0]
	new hooktarget = parm[1]

	// Create a beam between two entities
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte(8)				// TE_BEAMENTS
	write_short(id)
	write_short(hooktarget)
	write_short(g_spriteLine)	// sprite index
	write_byte(0)		// start frame
	write_byte(0)		// framerate
	write_byte(200)	// life
	write_byte(6)		// width
	write_byte(1)		// noise
	write_byte(255)	// r, g, b
	write_byte(255)	// r, g, b
	write_byte(25)		// r, g, b
	write_byte(255)	// brightness
	write_byte(10)		// speed
	message_end()
}
//----------------------------------------------------------------------------------------------
public hook_notarget(id)
{
	new endorigin[3]

	// Set beam to users aim
	get_user_origin(id, endorigin, 3)

	// Beam effect between point and entity
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte(1)				// TE_BEAMENTPOINT
	write_short(id)
	write_coord(endorigin[0])
	write_coord(endorigin[1])
	write_coord(endorigin[2])
	write_short(g_spriteLine)	// sprite index
	write_byte(0)		// start frame
	write_byte(0)		// framerate
	write_byte(200)	// life
	write_byte(6)		// width
	write_byte(1)		// noise
	write_byte(255)	// r, g, b
	write_byte(255)	// r, g, b
	write_byte(25)		// r, g, b
	write_byte(100)	// brightness
	write_byte(0)		// speed
	message_end()
}
//----------------------------------------------------------------------------------------------
public hook_remove(id)
{
	// Remove the beam aka hook
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte(99)		//TE_KILLBEAM
	write_short(id)	//entity
	message_end()
}
//----------------------------------------------------------------------------------------------
public blood_spurt(vic, id)
{
	new vicOrigin[3], idOrigin[3]
	get_user_origin(id, idOrigin)
	get_user_origin(vic, vicOrigin)

	new invTime = 300 / ( get_distance(vicOrigin, idOrigin) ? get_distance(vicOrigin, idOrigin) : 1 )

	new rX = (vicOrigin[0] - idOrigin[0])*invTime
	new rY = (vicOrigin[1] - idOrigin[1])*invTime
	new rZ = (vicOrigin[2] - idOrigin[2])*invTime

	// Stream of blood
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte(101)			// TE_BLOODSTREAM
	write_coord(vicOrigin[0])	// start position
	write_coord(vicOrigin[1])
	write_coord(vicOrigin[2])
	write_coord(rX) 	// spray vector
	write_coord(rY)
	write_coord(rZ)
	write_byte(70) 	// color RED = 248 YELLOW = 196 
	write_byte(random_num(100, 200)) // speed
	message_end()
}
//----------------------------------------------------------------------------------------------
public blood_spray(vic, vicOrigin[3])
{
	new x, y
	for(new i = 0; i < 2; i++) {
		x = random_num(-10, 10)
		y = random_num(-10, 10)
		for(new j = 0; j < 2; j++) {
			// Blood spray
			message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
			write_byte(115)				// TE_BLOODSPRITE
			write_coord(vicOrigin[0]+(x*j))	// position
			write_coord(vicOrigin[1]+(y*j))
			write_coord(vicOrigin[2]+21)
			write_short(g_spriteBldSpray)	// sprite1 index
			write_short(g_spriteBlood)	// sprite2 index
			write_byte(248) 			// color RED = 248 YELLOW = 196
			write_byte(10) 			// scale
			message_end()
		}
	}
}
//----------------------------------------------------------------------------------------------