// POISON IVY! - from Batman. Poison Ivy is immune to all forms of poison and her body manufactures poisons at will.

/* CVARS - copy and paste to shconfig.cfg

//Poison Ivy
poisonivy_level 0
poisonivy_damage 1		//Damage per second from infection
poisonivy_cooldown 0.0	//Seconds before you can infect another player
poisonivy_xpbased 0		//Do they cause more damage each xp level, 0=no 1=yes (def=0)
poisonivy_dpl 1		//Amount of additonal damage per level
poisonivy_maxdpl 0		//Maximum possible damage amount if xpbased (0=no max set)
poisonivy_self 1		//Can users with Poison Ivy be infected, 0=no 1=yes

*/

/*
* v1.5 - vittu - 7/3/05
*      - Fixed crash to AMX caused by the previous update, since
*          AMX can't register a MSG_ONE_UNRELIABLE message.
*
* v1.4 - vittu - 6/27/05
*      - Minor update for FF servers, prevents the shExtraDamage
*          from saying you attacked a teammate for every cycle.
*
* v1.3 - vittu - 6/22/05
*      - Minor code clean up.
*
* v1.2 - vittu - 4/7/05
*      - Removed some useless code and cleaned up.
*      - Added poison HUD icon and a sound to when a user gets poisoned.
*      - Added cooldown cvar and XP based damage possiblity thru cvar.
*      - Added cvar option for not poisoning users with Poison Ivy,
*         since the charater is immune to all poisons.
*
*    Hero orginally created by AssKicR
*/

#include <amxmod>
#include <superheromod>

// GLOBAL VARIABLES
new gHeroName[]="Poison Ivy"
new bool:gHasPoisonIvyPower[SH_MAXSLOTS+1]
new bool:gIsPoisoned[SH_MAXSLOTS+1][SH_MAXSLOTS+1]
new gPoisonDamage[SH_MAXSLOTS+1]
new gPlayerLevels[SH_MAXSLOTS+1]
new gmsgDamage, gmsgIcon
//----------------------------------------------------------------------------------------------
public plugin_init()
{
	// Plugin Info
	register_plugin("SUPERHERO Poison Ivy", "1.5", "AssKicR / vittu")

	// DO NOT EDIT THIS FILE TO CHANGE CVARS, USE THE SHCONFIG.CFG
	register_cvar("poisonivy_level", "0")
	register_cvar("poisonivy_damage", "1")
	register_cvar("poisonivy_cooldown", "0.0")
	register_cvar("poisonivy_xpbased", "0")
	register_cvar("poisonivy_dpl", "1")
	register_cvar("poisonivy_maxdpl", "0")
	register_cvar("poisonivy_self", "0")

	// FIRE THE EVENT TO CREATE THIS SUPERHERO!
	shCreateHero(gHeroName, "Infect Poison", "Infect the enemy with your Poisoned Bullets or Poisoned Knife", false, "poisonivy_level")

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

	// EVENTS
	register_event("ResetHUD", "newSpawn", "b")
	register_event("Damage", "poisonivy_damage", "b", "2!0")
	register_event("DeathMsg", "poisonivy_death", "a")

	// LOOP
	set_task(1.0, "poisonivy_loop", 0, "", 0, "b")

	// LEVELS
	register_srvcmd("poisonivy_levels", "poisonivy_levels")
	shRegLevels(gHeroName, "poisonivy_levels")

	gmsgDamage = get_user_msgid("Damage")
	gmsgIcon = get_user_msgid("StatusIcon")
}
//----------------------------------------------------------------------------------------------
public plugin_precache()
{
	precache_sound("hornet/ag_hornethit1.wav")
}
//----------------------------------------------------------------------------------------------
public poisonivy_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)

	// This gets run if they had the power but don't anymore
	if ( !hasPowers && gHasPoisonIvyPower[id] && is_user_connected(id) ) {
		remove_poison(id)
	}

	// Sets this variable to the current status
	gHasPoisonIvyPower[id] = (hasPowers != 0)
}
//----------------------------------------------------------------------------------------------
public poisonivy_levels()
{
	new id[5]
	new lev[5]

	read_argv(1,id,4)
	read_argv(2,lev,4)

	gPlayerLevels[str_to_num(id)] = str_to_num(lev)
}
//----------------------------------------------------------------------------------------------
public newSpawn(id)
{
	if ( is_user_alive(id) && shModActive() ) {

		reset_poisoned(id)

		if( gHasPoisonIvyPower[id] ) {

			gPlayerUltimateUsed[id] = false

			// Set damage amount per user
			if ( get_cvar_num("poisonivy_xpbased") ) {

				new poison = ( (gPlayerLevels[id] - get_cvar_num("poisonivy_level")) * get_cvar_num("poisonivy_dpl") + get_cvar_num("poisonivy_damage") )

				// Set max possible damage if one is set
				if ( get_cvar_num("poisonivy_maxdpl") > 0 ) {
					if ( poison > get_cvar_num("poisonivy_maxdpl") ) {
						poison = get_cvar_num("poisonivy_maxdpl")
					}
				}

				// Stupid checks
				if (poison > 0) {
					gPoisonDamage[id] = poison
				}
				else if (poison == 0) {
					gPoisonDamage[id] = get_cvar_num("poisonivy_damage")
				}
				else {
					gPoisonDamage[id] = 0
				}
			}
			else {
				gPoisonDamage[id] = get_cvar_num("poisonivy_damage")
			}
		}
	}
}
//----------------------------------------------------------------------------------------------
public poisonivy_damage(id)
{
	if ( !shModActive() || !is_user_alive(id) ) return

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

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

	// If already poisoned no need to set it twice
	if( gIsPoisoned[id][attacker] ) return

	// Can users with Poison Ivy be poisoned
	if ( !get_cvar_num("poisonivy_self") ) {
		if ( gHasPoisonIvyPower[id] ) return
	}

	if ( gHasPoisonIvyPower[attacker] && weapon != CSW_HEGRENADE && is_user_alive(id) && !gPlayerUltimateUsed[attacker] && id != attacker ) {
		// Set a poisoned player
		emit_sound(id, CHAN_STATIC, "hornet/ag_hornethit1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
		gIsPoisoned[id][attacker] = true

		// Set a cooldown if there is one until user can poison another player
		if (get_cvar_float("poisonivy_cooldown") > 0.0) ultimateTimer(attacker, get_cvar_float("poisonivy_cooldown"))
	}
}
//----------------------------------------------------------------------------------------------
public poisonivy_loop()
{
	if ( !shModActive() ) return

	for ( new attacker = 1; attacker <= SH_MAXSLOTS; attacker++ ) {
		if ( !gHasPoisonIvyPower[attacker] || !is_user_connected(attacker) ) continue

		for ( new id = 1; id <= SH_MAXSLOTS; id++ ) {
			if ( gIsPoisoned[id][attacker] && is_user_alive(id) ) {

				new health = get_user_health(id)
				new damage = gPoisonDamage[attacker]

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

				new origin[3]
				get_user_origin(id, origin)

				// Poison HUD Icon
				message_begin(MSG_ONE, gmsgIcon, {0,0,0}, id)
				write_byte(1)				// status (0=hide, 1=show, 2=flash)
				write_string("dmg_poison")	// sprite name
				write_byte(0)		// red
				write_byte(125)	// green
				write_byte(0)		// blue
				message_end()

				// Remove poison icon
				set_task(0.3, "remove_poisonicon", id)

				// Show damage, damage origin is self
				message_begin(MSG_ONE, gmsgDamage, {0,0,0}, id)
				write_byte(30)			// dmg_save
				write_byte(30)			// dmg_take
				write_long((1 << 16))	// visibleDamageBits
				write_coord(origin[0])	// damageOrigin.x
				write_coord(origin[1])	// damageOrigin.y
				write_coord(origin[2])	// damageOrigin.z
				message_end()
			}
		}
	}
}
//----------------------------------------------------------------------------------------------
public client_connect(id)
{
	reset_poisoned(id)
}
//----------------------------------------------------------------------------------------------
public client_disconnect(id)
{
	remove_poison(id)

	reset_poisoned(id)
}
//----------------------------------------------------------------------------------------------
public poisonivy_death()
{
	new id = read_data(2)

	reset_poisoned(id)
}
//----------------------------------------------------------------------------------------------
public reset_poisoned(victim)
{
	// Resets poison status on victim if poisoned by any posion ivy's
	for ( new attacker = 1; attacker <= SH_MAXSLOTS; attacker++ ) {
		if ( gIsPoisoned[victim][attacker] ) {
			gIsPoisoned[victim][attacker] = false
		}
	}
}
//----------------------------------------------------------------------------------------------
public remove_poison(attacker)
{
	new players[SH_MAXSLOTS], pnum, victim
	get_players(players, pnum, "a")

	// Removes poison on alive players that the attacker poisoned
	for (new i = 0; i < pnum; i++) {
		victim = players[i]
		if ( gIsPoisoned[victim][attacker] ) {
			gIsPoisoned[victim][attacker] = false
		}
	}
}
//----------------------------------------------------------------------------------------------
public remove_poisonicon(id)
{
	if ( !is_user_connected(id) ) return

	// Poison HUD Icon, reset to none
	message_begin(MSG_ONE, gmsgIcon, {0,0,0}, id)
	write_byte(0)				// status (0=hide, 1=show, 2=flash)
	write_string("dmg_poison")	// sprite name
	write_byte(0)		// red
	write_byte(0)		// green
	write_byte(0)		// blue
	message_end()
}
//----------------------------------------------------------------------------------------------