// CATWOMAN! - from Batman of DC Comics.

/*	Credits - 
		Captain America helped loads with random number and such, too lazy to rewrite the code, so i just used cap ame's
		Credits go to {HOJ} Batman and JTP10181 of course
		Credits also to WC3FT mod for mole code
		Yang helped also ^_^
		Vittu helped mucho also =D He helped with tons and tons and tons =D

	Versions - 
		v2.6 - Cleaned up some code - vittu
		v2.5 - added type cvar and cleaned code more
		v2.1 - fixed the bug where it would only work for a short period of time
		v2.0 - converted to module
		v1.5 - changed includes to how jtp specified, changed the catwoman_change cvar and made it "better" i guess
		v1.1 - cleaned up code a little
		v1.0 - released
*/

/* CVARS - copy and paste to shconfig.cfg

//Catwoman
catwoman_level 1
catwoman_seconds 0.5		//Seconds after round starts that she sneaks to other base
catwoman_change 10.0		//Look like the enemy when you sneak? 0 dont look like enemy. 1.0 look like enemy for entire round. 2.0 and above is the time you look like the enemy.
catwoman_mode 2			//Mode of sneaking-
							//	1. It multiplies pctperlev cvar times current level and if it is higher than a random number, you sneak
							//	2. Works like my abomination, takes maxrounds and subtracts your level from it.
							//		This number is how many rounds you have to wait until you can sneak.
							//		It won't go under the minrounds.
//Catwoman - mode 1
catwoman_pctperlev 0.01		//Percent chance per level of sneaking
//Catwoman - mode 2
catwoman_maxrounds 20		//Max rounds to wait (minus your level) until you can sneak
catwoman_minrounds 5		//Min rounds to wait until you can sneak, no matter your level, it wont go under this

*/

#include <amxmodx>
#include <cstrike>
#include <engine>
#include <superheromod>
//ok happy now jtp? lol

// GLOBAL VARIABLES
new gHeroName[]="Catwoman"
new bool:gHasCatWomanPowers[SH_MAXSLOTS+1]
new bool:gCatWomanmns[SH_MAXSLOTS+1] = true //im using mns = message not shown, im doing this because of the double respawn
new bool:gCatWomanSneak[SH_MAXSLOTS+1]
new bool:spawnPointsused[2][SH_MAXSLOTS+1]
new gPlayerLevels[SH_MAXSLOTS+1]
new catround[SH_MAXSLOTS+1]
new spawnEntString[2][] = {"info_player_deathmatch", "info_player_start"}
new CTSkins[4][10] = {"sas", "gsg9", "urban", "gign"}
new TSkins[4][10] = {"arctic", "leet", "guerilla", "terror"}
//----------------------------------------------------------------------------------------------
public plugin_init()
{
	// Plugin Info
	register_plugin("SUPERHERO Catwoman", "2.6", "Emp`")

	// DO NOT EDIT THIS FILE TO CHANGE CVARS, USE THE SHCONFIG.CFG
	register_cvar("catwoman_level", "1")
	register_cvar("catwoman_seconds", "0.5")
	register_cvar("catwoman_change", "10.0")
	register_cvar("catwoman_mode", "2")
	register_cvar("catwoman_pctperlev", "0.01")
	register_cvar("catwoman_maxrounds", "20")
	register_cvar("catwoman_minrounds", "5")

	// FIRE THE EVENT TO CREATE THIS SUPERHERO!
	shCreateHero(gHeroName, "Sneak Into Enemies Base", "Chance Of Sneaking Into Enemies Base", false, "catwoman_level")

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

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

	// LEVELS
	register_srvcmd("catwoman_levels", "catwoman_levels")
	shRegLevels(gHeroName,"catwoman_levels")
}
//----------------------------------------------------------------------------------------------
public catwoman_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)

	gHasCatWomanPowers[id] = (hasPowers!=0)
}
//----------------------------------------------------------------------------------------------
public catwoman_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 ( gHasCatWomanPowers[id] && is_user_alive(id) && shModActive() )
	{
		if ( get_cvar_float("catwoman_change") > 0.0 )
			cs_reset_user_model(id)

		if ( get_cvar_num("catwoman_mode") == 1 )
		{
			new randNum = random_num(0, 100)
			new level = floatround(gPlayerLevels[id] * get_cvar_float("catwoman_pctperlev") * 100)
			if ( level > randNum )
				gCatWomanSneak[id] = true
		}
		else
		{
			// If spawned during round don't check or add to catround
			// This function should be changed to actual rounds, this is only a bandaid
			if ( hasRoundStarted() )
				return

			new sneakLevel, max = get_cvar_num("catwoman_maxrounds"), min = get_cvar_num("catwoman_minrounds")

			if ( max - gPlayerLevels[id] < min )
				sneakLevel = min
			else
				sneakLevel = max - gPlayerLevels[id]

			catround[id] += 1
			if ( catround[id] >= sneakLevel )
			{
				gCatWomanSneak[id] = true
				catround[id] = 0
			}
		}

		if ( gCatWomanmns[id] && gCatWomanSneak[id] )
		{
			gCatWomanmns[id] = false

			new CsTeams:idTeam = cs_get_user_team(id)
			new spawnType
			switch(idTeam)
			{
				case CS_TEAM_CT:
					spawnType = 0
				case CS_TEAM_T:
					spawnType = 1
			}

			// Make all spawn points possible again
			for(new i = 0 ; i <= SH_MAXSLOTS ; i++)
			{
				spawnPointsused[spawnType][i] = false
			}

			set_task(get_cvar_float("catwoman_seconds"), "catwoman_sneak", id)
		}
	}
}
//----------------------------------------------------------------------------------------------
public catwoman_sneak(id)
{
	if ( !shModActive() || !is_user_alive(id) || !gHasCatWomanPowers[id] )
		return

	new entSpawn
	new Float:spawnAngle[3]
	new Float:spawnOrigin[3]
	new Float:changetime = get_cvar_float("catwoman_change")
	new CsTeams:idTeam = cs_get_user_team(id)

	// Find a free spawn point and return the spawns ent id, it's origin, and angle
	switch(idTeam)
	{
		case CS_TEAM_CT:
			entSpawn = find_free_spawn(0, spawnOrigin, spawnAngle)
		case CS_TEAM_T:
			entSpawn = find_free_spawn(1, spawnOrigin, spawnAngle)
		default:
			entSpawn = 0
	}

	if ( !entSpawn )
	{
		// Didn't find a free spawn spot. Quit...
		client_print(id, print_chat, "[SH](%s) No opening to sneak through.", gHeroName)
		return
	}

	// Change clothes?
	if ( changetime > 0.0 )
	{
		new newSkin[32]
		new num = random_num(0, 3)

		switch(idTeam)
		{
			case CS_TEAM_CT:
				copy(newSkin, 31, TSkins[num])
			case CS_TEAM_T:
				copy(newSkin, 31, CTSkins[num])
		}

		cs_set_user_model(id, newSkin)

		if ( changetime > 1.0 )
			set_task(changetime, "catwoman_changeback", id)
	}

	// Move to an enemy spawn and set spawn angle
	entity_set_vector(id, EV_VEC_origin, spawnOrigin)
	entity_set_int(id, EV_INT_fixangle, 1)
	entity_set_vector(id, EV_VEC_angles, spawnAngle)

	client_print(id, print_chat, "[SH](%s) You snuck into the enemy base.", gHeroName)

	sh_screenShake(id, 14, 14, 14)

	gCatWomanmns[id] = true
	gCatWomanSneak[id] = false
}
//----------------------------------------------------------------------------------------------
/* Based on WC3FT mole code, which was used from JGHG I Spy */
/* This could be rewritten a bit, to be made easier. JGHG didn't like this method either */
//----------------------------------------------------------------------------------------------
find_free_spawn(spawnType, Float:spawnOrigin[3], Float:spawnAngle[3])
{
	new spawnEntId[2][SH_MAXSLOTS+1]
	new ent = -1, spawnsFound = 0

	/* Find all of the spawn points */
	do
	{
		ent = find_ent_by_class(ent, spawnEntString[spawnType])

		if ( ent != 0 )
		{
			spawnEntId[spawnType][spawnsFound] = ent
			spawnsFound++
		}
	}
	while (ent && spawnsFound <= SH_MAXSLOTS)

	new Float:vicinity = 96.0		//(32x32x96) player dimensions, 96 height?
	new playersInVicinity
	new entList[1]

	/* Loop through all the spawn points */
	for( new i = 0; i < spawnsFound; i++ )
	{
		if ( spawnEntId[spawnType][i] != 0 && !spawnPointsused[spawnType][i] )
		{
			/* zero out vector */
			spawnOrigin[0] = 0.0
			spawnOrigin[1] = 0.0
			spawnOrigin[2] = 0.0

			/* Get the origin of the spawn point */
			entity_get_vector(spawnEntId[spawnType][i], EV_VEC_origin, spawnOrigin)

			/* Determine if a player is in the vicinity of spawnOrigin */
			playersInVicinity = find_sphere_class(0, "player", vicinity, entList, 1, spawnOrigin)

			/* If not, we want to transport the player here */
			if ( !playersInVicinity )
			{
				entity_get_vector(spawnEntId[spawnType][i], EV_VEC_angles, spawnAngle)
				spawnPointsused[spawnType][i] = true
				return spawnEntId[spawnType][i]
			}
		}
	}

	return 0
}
//----------------------------------------------------------------------------------------------
public catwoman_changeback(id)
{
	if ( !is_user_alive(id) )
		return

	cs_reset_user_model(id)

	client_print(id, print_chat, "[SH](%s) You have taken off your sneaking outfit.", gHeroName)
}
//----------------------------------------------------------------------------------------------
public client_connect(id)
{
	gHasCatWomanPowers[id] = false
	gCatWomanmns[id] = true
	gCatWomanSneak[id] = false
	catround[id] = 0
}
//----------------------------------------------------------------------------------------------