// AFTERBURN! - ?

/* CVARS - copy and paste to shconfig.cfg

//AfterBurn
afterburn_level 7
afterburn_cooldown 6.0	//# of seconds before Afterburn can use flame thrower again
afterburn_numburns 1	//How many times to burn the victim
afterburn_burndmg 5		//How much damage each burn does

*/

/*
* v1.2 - vittu - 6/14/05
*      - Minor code cleanup.
*      - Fixed a possible issue if sqroot retuns a 0.
*
* v1.1 - vittu - 3/23/05
*      - Clean up code.
*      - Fixed cooldown so it actually works, it was not being used before.
*      - Added check against Spectator use.
*
* Ripped from Human Torch, BASED ON FlameThrower by Ludwig.
* (takes 5.5 secs until damage can be caused again)
*/

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

// GLOBAL VARIABLES
new gHeroName[]="AfterBurn"
new bool:gHasAfterBurnPower[SH_MAXSLOTS+1]
new gIsBurning[SH_MAXSLOTS+1]
new gSpriteSmoke, gSpriteFire, gSpriteBurning
//----------------------------------------------------------------------------------------------
public plugin_init()
{
	// Plugin Info
	register_plugin("SUPERHERO AfterBurn", "1.2", "[FTW]-S.W.A.T")

	// DO NOT EDIT THIS FILE TO CHANGE CVARS, USE THE SHCONFIG.CFG
	register_cvar("afterburn_level", "7")
	register_cvar("afterburn_cooldown", "6.0")
	register_cvar("afterburn_numburns", "1")
	register_cvar("afterburn_burndmg", "5")

	// FIRE THE EVENT TO CREATE THIS SUPERHERO!
	shCreateHero(gHeroName, "Flames From Beyond", "Shoot flames while your dead, from your dead body or while in dead spectate mode.", true, "afterburn_level")

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

	// KEY DOWN
	register_srvcmd("afterburn_kd", "afterburn_kd")
	shRegKeyDown(gHeroName, "afterburn_kd")

	register_event("ResetHUD", "newSpawn", "b")
}
//----------------------------------------------------------------------------------------------
public plugin_precache()
{
	gSpriteSmoke = precache_model("sprites/steam1.spr")
	gSpriteFire = precache_model("sprites/explode1.spr")
	gSpriteBurning = precache_model("sprites/xfire.spr")
	precache_sound("ambience/burning1.wav")
	precache_sound("ambience/flameburst1.wav")
	precache_sound("scientist/c1a0_sci_catscream.wav")
	precache_sound("vox/_period.wav")
}
//----------------------------------------------------------------------------------------------
public afterburn_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)

	gHasAfterBurnPower[id] = (hasPowers != 0)
}
//----------------------------------------------------------------------------------------------
public newSpawn(id)
{
	gIsBurning[id] = 0

	stopFireSound(id)

	if ( gHasAfterBurnPower[id] ) {
		gPlayerUltimateUsed[id] = false
	}
}
//----------------------------------------------------------------------------------------------
// Ludwigs flame thrower
public afterburn_kd()
{
	if ( !hasRoundStarted() ) return

	// First Argument is an id
	new temp[6]
	read_argv(1,temp,5)
	new id = str_to_num(temp)

	// This is the original only change from human torch,
	// this makes sure you are dead to use the power... wow what a rip.
	if ( is_user_alive(id) || !gHasAfterBurnPower[id] ) return
	// Check to make sure they are on a Team
	if ( get_user_team(id) < 1 || get_user_team(id) > 2 ) return

	if ( Entvars_Get_Int( id, EV_INT_waterlevel ) == 3 ) {
		client_print(id,print_chat,"[SH] You cannot use the Flame Thrower while underwater")
		playSoundDenySelect(id)
		return
	}

	if ( gPlayerUltimateUsed[id] ) {
		playSoundDenySelect(id)
		return
	}

	emit_sound(id, CHAN_WEAPON, "ambience/flameburst1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
	new vec[3]
	new aimvec[3]
	new velocityvec[3]
	new length
	new speed = 10
	get_user_origin(id,vec)
	get_user_origin(id,aimvec,2)
	new dist = get_distance(vec,aimvec)

	new speed1 = 160
	new speed2 = 350
	new radius = 105

	if (dist < 50) {
		radius = 0
		speed = 5
	}
	else if (dist < 150) {
		speed1 = speed2 = 1
		speed = 5
		radius = 50
	}
	else if (dist < 200) {
		speed1 = speed2 = 1
		speed = 5
		radius = 90
	}
	else if (dist < 250) {
		speed1 = speed2 = 90
		speed = 6
		radius = 90
	}
	else if (dist < 300) {
		speed1 = speed2 = 140
		speed = 7
	}
	else if (dist < 350) {
		speed1 = speed2 = 190
		speed = 7
	}
	else if (dist < 400) {
		speed1 = 150
		speed2 = 240
		speed = 8
	}
	else if (dist < 450) {
		speed1 = 150
		speed2 = 290
		speed = 8
	}
	else if (dist < 500) {
		speed1 = 180
		speed2 = 340
		speed = 9
	}

	velocityvec[0] = aimvec[0] - vec[0]
	velocityvec[1] = aimvec[1] - vec[1]
	velocityvec[2] = aimvec[2] - vec[2]
	length = sqrt(velocityvec[0]*velocityvec[0] + velocityvec[1]*velocityvec[1] + velocityvec[2]*velocityvec[2])
	if (!length) length = 1
	velocityvec[0] = velocityvec[0]*speed / length
	velocityvec[1] = velocityvec[1]*speed / length
	velocityvec[2] = velocityvec[2]*speed / length

	new args[6]
	args[0] = vec[0]
	args[1] = vec[1]
	args[2] = vec[2]
	args[3] = velocityvec[0]
	args[4] = velocityvec[1]
	args[5] = velocityvec[2]
	set_task(0.1, "te_spray", 0, args, 6, "a", 2)
	check_burnzone(id, vec, aimvec, speed1, speed2, radius)

	if (get_cvar_float("afterburn_cooldown") > 0.0) ultimateTimer(id, get_cvar_float("afterburn_cooldown"))
}
//----------------------------------------------------------------------------------------------
public te_spray(args[])
{
	//TE_SPRAY
	message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
	write_byte(120)		// Throws a shower of sprites or models
	write_coord(args[0])	// start pos
	write_coord(args[1])
	write_coord(args[2])
	write_coord(args[3])	// velocity
	write_coord(args[4])
	write_coord(args[5])
	write_short(gSpriteFire)	// spr
	write_byte(8)		// count
	write_byte(70)		// speed
	write_byte(100)	// (noise)
	write_byte(5)		// (rendermode)
	message_end()
}
//----------------------------------------------------------------------------------------------
check_burnzone(id, vec[], aimvec[], speed1, speed2, radius)
{
	new tbody, tid
	get_user_aiming(id, tid, tbody, 550)

	if (tid <= 0 || tid > SH_MAXSLOTS) return

	if ( get_cvar_num("mp_friendlyfire") == 1 ) {
		burn_victim(tid, id)
	}
	else if ( get_user_team(id) != get_user_team(tid) ) {
		burn_victim(tid, id)
	}

	new burnvec1[3],burnvec2[3],length1

	burnvec1[0] = aimvec[0]-vec[0]
	burnvec1[1] = aimvec[1]-vec[1]
	burnvec1[2] = aimvec[2]-vec[2]

	length1 = sqrt(burnvec1[0]*burnvec1[0] + burnvec1[1]*burnvec1[1] + burnvec1[2]*burnvec1[2])
	if (!length1) length1 = 1
	burnvec2[0] = burnvec1[0]*speed2 / length1
	burnvec2[1] = burnvec1[1]*speed2 / length1
	burnvec2[2] = burnvec1[2]*speed2 / length1
	burnvec1[0] = burnvec1[0]*speed1 / length1
	burnvec1[1] = burnvec1[1]*speed1 / length1
	burnvec1[2] = burnvec1[2]*speed1 / length1
	burnvec1[0] += vec[0]
	burnvec1[1] += vec[1]
	burnvec1[2] += vec[2]
	burnvec2[0] += vec[0]
	burnvec2[1] += vec[1]
	burnvec2[2] += vec[2]

	new origin[3]
	for (new i = 1; i <= SH_MAXSLOTS; i++){
		if ( is_user_alive(i) && i != id && ( get_cvar_num("mp_friendly_fire") || get_user_team(id) != get_user_team(i) ) ) {
			get_user_origin(i, origin)
			if ( get_distance(origin, burnvec1) < radius ) {
				burn_victim(i, id)
			}
			else if ( get_distance(origin, burnvec2) < radius ) {
				burn_victim(i, id)
			}
		}
	}
}
//----------------------------------------------------------------------------------------------
public burn_victim(id, killer)
{
	if ( Entvars_Get_Int( id, EV_INT_waterlevel ) == 3 ) return
	if ( gIsBurning[id] ) return

	gIsBurning[id] = 1

	emit_sound(id, CHAN_ITEM, "ambience/burning1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)

	new args[3]
	args[0] = id
	args[1] = killer
	set_task(0.3, "on_fire", 451, args, 3, "a", get_cvar_num("afterburn_numburns"))
	set_task(0.7, "fire_scream", 0, args, 3)
	set_task(5.5, "stopFireSound", id)
}
//----------------------------------------------------------------------------------------------
public on_fire(args[])
{
	new id = args[0]
	new killer = args[1]

	if( !is_user_connected(id) || !is_user_alive(id) ) {
		gIsBurning[id] = 0
		return
	}
	if( Entvars_Get_Int( id, EV_INT_waterlevel ) == 3 ) {
		gIsBurning[id] = 0
		return
	}
	if (!gIsBurning[id]) return

	new rx, ry, rz, forigin[3]
	rx = random_num(-30, 30)
	ry = random_num(-30, 30)
	rz = random_num(-30, 30)
	get_user_origin(id, forigin)

	//TE_SPRITE - additive sprite, plays 1 cycle
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte(17)
	write_coord(forigin[0]+rx)	// coord, coord, coord (position)
	write_coord(forigin[1]+ry)
	write_coord(forigin[2]+10+rz)
	write_short(gSpriteBurning)	// short (sprite index)
	write_byte(30)				// byte (scale in 0.1's)
	write_byte(200)			// byte (brightness)
	message_end()

	//Smoke
	message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
	write_byte(5)
	write_coord(forigin[0]+(rx*2))	// coord, coord, coord (position)
	write_coord(forigin[1]+(ry*2))
	write_coord(forigin[2]+100+(rz*2))
	write_short(gSpriteSmoke)	// short (sprite index)
	write_byte(60)				// byte (scale in 0.1's)
	write_byte(15)				// byte (framerate)
	message_end()

	new health = get_user_health(id)
	new damage = get_cvar_num("afterburn_burndmg")

	//Prevents the shExtraDamage from saying you attacked a teammate for every cycle of the loop
	if(health - damage  <= 0) {
		shExtraDamage(id, killer, damage, "AfterBurn")
	}
	else {
		set_user_health(id, health - damage)

		//let them know who is hurting them with a flame
		new attackerName[32]
		get_user_name(killer, attackerName, 31)
		client_print(id, print_chat, "[SH](AfterBurn) %s is burning you from beyond the grave", attackerName)
	}
}
//----------------------------------------------------------------------------------------------
public fire_scream(args[])
{
	emit_sound(args[0], CHAN_AUTO, "scientist/c1a0_sci_catscream.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
}
//----------------------------------------------------------------------------------------------
public stopFireSound(id)
{
	new sndStop = (1<<5)
	gIsBurning[id] = 0
	emit_sound(id, CHAN_ITEM, "ambience/burning1.wav", 1.0, ATTN_NORM, sndStop, PITCH_NORM)
}
//----------------------------------------------------------------------------------------------
public client_connect(id)
{
	gHasAfterBurnPower[id] = false
}
//----------------------------------------------------------------------------------------------