/*
*   Health Display (health-display.sma)
*   Copyright (C) 2007 Exolent
*
*   This program is free software; you can redistribute it and/or
*   modify it under the terms of the GNU General Public License
*   as published by the Free Software Foundation; either version 2
*   of the License, or (at your option) any later version.
*
*   This program is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU General Public License for more details.
*
*   You should have received a copy of the GNU General Public License
*   along with this program; if not, write to the Free Software
*   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
*   In addition, as a special exception, the author gives permission to
*   link the code of this program with the Half-Life Game Engine ("HL
*   Engine") and Modified Game Libraries ("MODs") developed by Valve,
*   L.L.C ("Valve"). You must obey the GNU General Public License in all
*   respects for all of the code used other than the HL Engine and MODs
*   from Valve. If you modify this file, you may extend this exception
*   to your version of the file, but you are not obligated to do so. If
*   you do not wish to do so, delete this exception statement from your
*   version.
*   
*   
*   -------------------------------------------------------------------------
*   -------------------------------------------------------------------------
*   -------------------------------------------------------------------------
*   
*   
*   Introduction:
*   =================
*     This is my very first plugin.
*     It is mainly meant for surf and kz maps in Counter-Strike 1.6.
*     If it works in any other game, be my guest, but I do not recommend it.
*     It has only been tested in Counter-Strike 1.6.
*     In my experience, in servers that are on surf/kz maps, (not all the time) people will go into health givers to receive hp.
*     Other times, they either decide not to go into one or can't since one doesn't exist.
*     Anyway, they might lose hp throughout the map, and have a low hp.
*     That is when they will ask admins to give them hp.
*     Only because they will be near the end or middle of the map.
*     Admins will ignore them if a health giver is present at the beginning (most of the time).
*   
*   
*   Function:
*   =============
*     This plugin displays the player's actual health above the timer in the hud.
*     The health is only displayed for 12 seconds or whatever the cvar is set to.
*     Also, it is displayed each time the player's health increases or decreases.
*     And, the player can type /health, /myhp, or any message that include health or hp.
*   
*   
*   Changelog:
*   ==============
*     Version 1.0
*     -- Initial Release
*     
*     Version 2.0
*     -- Fixed multiple reminder bug
*     -- Doubled hud message for more brightness and saturation
*     
*     Version 3.0
*     -- Added log_amx for admin commands
*     -- Second attempt for remind bug fix
*     -- Fixed double health display on spawn
*     
*     Version 4.0
*     -- Fixed death health displaying "Health: 1" when /health is typed
*     -- Registered only /health to prevent stats plugin(s) interference
*     -- Made code more efficient
*     -- Registered ResetHUD
*     
*     Version 5.0
*     -- Plugin revised by arkshine
*     -- French language added
*     
*     Version 6.0
*     -- Spanish language added
*     -- German language added
*     
*     Version 7.0
*     -- Merged original idea with arkshine's help
*     -- Added more customization
*    
*     Version 8.0
*     -- Fixed multiple bugs
*     -- Optimized code
*    
*     Version 9.0
*     -- Added print out effect
*     -- Added config option
*    
*     Version 10.0
*     -- Fixed a few bugs
*     
*     Version 10.1
*     -- Fixed a minor bug
*     
*     Version 10.2
*     -- Changed name from 'Health Shower' to 'Health Display' due to any available confusion.
*     -- Rearranged set_color() fuction to be working properly.
*        This way, you can change the custom color via amx_cvar.
*        If I hadn't rearranged it, the only purpose was an admin command and the cvar would be useless.
*   
*   
*   Client Commands:
*   ====================
*     /health, /myhp, or any message to do with health or hp
*   
*   
*   Cvars:
*   ==========
*     health_on (1 for on. 0 for off)
*     health_time (time in seconds health is displayed)
*     health_color (0 for white; 1 for custom color; 2 for random color)
*     health_remind (interval in seconds between each reminder)
*     health_effects (2 for print out. 1 for flickering health show. 0 for no effects)
*     health_custom (RRR GGG BBB (color for custom hud color))
*   
*   
*   Admin Commands:
*   ===================
*     amx_healthon (1 turns on health show; 0 turns it off)
*     amx_healthcustom (RRR GGG BBB format for health show color)
*     amx_healthcolor (0 for white; 1 for custom color; 2 for random)
*     amx_healtheffects (2 for print out. 1 for flickering health show. 0 for no effects)
*   
*   
*   Cvar Presets:
*   =================
*     health_on 1
*     health_time 12
*     health_color 1
*     health_remind 90
*     health_effects 1
*     health_custom 255 255 0
*   
*   
*   Module Required:
*   ====================
*     fun
*   
*   
*   Credits:
*   ============
*     Emp` for helping me improve my coding skills.
*     arkshine for revising my code, adding french, and encouraging me to add other languages.
*/

// -------------------------------------------------------------------------------------------------
// -- CUSTOMIZALBE OPTIONS -------------------------------------------------------------------------
// -- TO USE CHANGED OPTIONS, SAVE AND RECOMPILE ---------------------------------------------------
// -------------------------------------------------------------------------------------------------

#define ACCESS_LEVEL ADMIN_LEVEL_A	// -- Access level for admin commands
#define HUD_CHANNEL 3			// -- Hud channel for health display
#define MAX_PLAYERS 32			// -- Max player slots
#define USE_CONFIG 1			// -- 1 to use config file. 0 to not

// -------------------------------------------------------------------------------------------------
// -- END CUSTOMIZABLE OPTIONS ---------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------

#include <amxmodx>
#include <amxmisc>
#include <fun>

#define PLUGIN "Health Display"
#define VERSION "10.2"
#define AUTHOR "Exolent"

new g_health, g_time, g_remind				// -- pCvars
new g_custom, g_color, g_effects 			// -- pCvars
new aR, aG, aB						// -- Defined Custom Colors
new szColor[16], szR, szG, szB				// -- Color finders
new bool:g_event_restart[MAX_PLAYERS + 1]		// -- Indication of round restart
#if USE_CONFIG == 1
new const health_site[] = "http://forums.alliedmods.net/showthread.php?t=54091"
#endif
new g_logmessage[4][] = 					// -- Log messages (english)
{
	"Admin %s ( %s ) has turned %s health display.",
	"Admin %s ( %s ) has set health custom color to %i %i %i.",
	"Admin %s ( %s ) has set health color to %s",
	"Admin %s ( %s ) has set health effects to %s"
}
new g_logoptions[8][] = 
{
	"white",
	"custom",
	"random",
	"none",
	"flicker",
	"print",
	"off",
	"on"
}
public plugin_init()
{
	// -- Plugin Info
	// -------------------------
	register_plugin(PLUGIN, VERSION, AUTHOR)
	register_cvar( "health-display", VERSION, FCVAR_SERVER | FCVAR_EXTDLL | FCVAR_SPONLY )
	
	// -- Languages
	// -------------------------
	register_dictionary("common.txt")
	register_dictionary("health-display.txt")
	
	// -- Client Commands
	// -------------------------
	register_clcmd("say /myhp", "prehealthshow")
	register_clcmd("say /health","prehealthshow")
	register_clcmd("say_team /myhp", "prehealthshow")
	register_clcmd("say_team /health","prehealthshow")
	
	// -- Admin Commands
	// -------------------------
	register_concmd("amx_healthon","sethealthshow",ACCESS_LEVEL,"<1|0> Turns On/Off Health Showing")
	register_concmd("amx_healthcustom","sethealthcustom",ACCESS_LEVEL,"<RRR GGG BBB> Sets RGB color for health shower")
	register_concmd("amx_healthcolor","sethealthcolor",ACCESS_LEVEL,"<0|1|2> 0 Sets health to white. 1 Sets to custom color. 2 Sets to random")
	register_concmd("amx_healtheffects","sethealtheffects",ACCESS_LEVEL,"<1|0> 1 Sets health to white. 0 Sets back to custom color")
	
	// -- Events
	// -------------------------
	register_event("Health","event_health","be")		// -- Catches player's health change
	register_event("DeathMsg","stop_health","bd")		// -- Caught to destroy health displayment
	
	// -- pCvars
	// -------------------------
	g_time = register_cvar("health_time","12")		// -- Time health is displayed
	g_color = register_cvar("health_color","1")		// -- 0 for white, 1 for custom, 2 for random
	g_remind = register_cvar("health_remind","90")		// -- Interval between each reminder
	g_health = register_cvar("health_on","1")		// -- 1 for health showing on. 0 for off
	g_effects = register_cvar("health_effects","1")		// -- 2 for print out. 1 for flickering. 0 for none
	g_custom = register_cvar("health_custom","255 255 0")	// -- Color for hud message
}

public plugin_cfg()
{
	#if USE_CONFIG == 1
	check_file()
	#endif
	set_color()
}

#if USE_CONFIG == 1
check_file()
{
	// -- 'cstrike/addons/amxmodx/configs' folder
	new configsdir[64]
	get_configsdir(configsdir,63)
	
	// -- Health Config File + Location
	new healthcfg[128]
	format(healthcfg,127,"%s/health-display.cfg",configsdir)
	
	// -- Check if file is in folder
	if(!file_exists(healthcfg))
	{
		server_print("Not all files for '%s' are present.", PLUGIN )
		server_print("Please be sure to pick up the health-display.rar at:")
		server_print(health_site)
	}
	else
		server_cmd("exec %s",healthcfg)
}
#endif

set_color()
{
	// -- Get the health color
	new nColor[16]
	get_pcvar_string(g_custom,nColor,15)
	
	// -- Separate to RGB format
	static nR[4], nG[4], nB[4]
	parse(nColor,nR,3,nG,3,nB,3)
	
	// -- Translate the cvar to numbers
	// -- Temporary color holders
	new tR = str_to_num(nR)
	new tG = str_to_num(nG)
	new tB = str_to_num(nB)
	
	// -- Indicator for wrong color number
	new wrongcolor
	
	// -- Check if the color is out of RGB bounds
	if(tR>255||tR<0)
	{
		wrongcolor = 1
	}
	if(tG>255||tG<0)
	{
		wrongcolor = 1
	}
	if(tB>255||tB<0)
	{
		wrongcolor = 1
	}
	
	// -- If the color is out of RGB bounds, set to yellow as default
	if(wrongcolor)
	{
		tR = 255
		tG = 255
		tB = 0
	}
	
	// -- Set colors
	aR = tR
	aG = tG
	aB = tB
}

public stop_health()
{
	if(get_pcvar_num(g_health)!=1)
		return;
	// -- Get player's id
	new id = read_data(2)
	
	// -- Replace health message with a blank one
	destroy_health(id)
}

public client_putinserver(id)
{
	if(!is_user_connected(id))
		return;
	
	// -- Show Reminder 1st Time
	client_print(id,print_chat,"%L",id,"HEALTH_ADS_MSG")
	
	// -- Start Repeat Reminder
	set_task(float(get_pcvar_num(g_remind)),"healthremind",id,_,_,"b")
}

public healthremind(id)
{
	client_print(id,print_chat,"%L",id,"HEALTH_ADS_MSG")
}

public client_connect(id)
{
	g_event_restart[id] = false
}

public client_disconnect(id)
{
	// -- If reminder was active, remove it
	if(task_exists(id))
		remove_task(id)
	g_event_restart[id] = false
}

public prehealthshow(id)
{
	// -- If health showing isnt on, tell the player
	if(get_pcvar_num(g_health)!=1)
		client_print(id,print_chat,"%L",id,"HEALTH_CURRENT_STATUS")
		
	// -- If the player isnt alive, remind the player
	else if(!is_user_alive(id))
		client_print(id,print_chat,"%L",id,"HEALTH_ALIVE")
	
	// -- If all else fails, show the health
	else
		event_health(id)
	
	return PLUGIN_HANDLED;
}

public event_health(id)
{
	// -- If health showing isnt on or alive, dont show
	if(get_pcvar_num(g_health)!=1 || !is_user_alive(id))
		return;
	
	// -- Get the user's health
	new health = get_user_health(id)
	
	// -- Format health message
	static healthmsg[191]
	format(healthmsg,190,"%L",id,"HEALTH_HUD",health)
	
	// -- Get the colors according to cvars
	new cR, cG, cB
	set_color()
	switch(get_pcvar_num(g_color))
	{
		case 0: // -- White
		{
			cR = 255
			cG = 255
			cB = 255
		}
		case 1: // -- Custom
		{
			cR = aR
			cG = aG
			cB = aB
		}
		case 2: // -- Random
		{
			cR = random(255)
			cG = random(255)
			cB = random(255)
		}
	}
	
	// -- Set the colors for the hud message and show
	set_hudmessage(cR, cG, cB, -1.0, 0.9, get_pcvar_num(g_effects), float(get_pcvar_num(g_time)), float(get_pcvar_num(g_time)), 0.1, 0.2, HUD_CHANNEL)
	show_hudmessage(id,healthmsg)
}

public destroy_health(id)
{
	// -- Show a blank hud message
	set_hudmessage(0,0,0,-1.0,0.9,0,0.1,0.2,0.1,0.2,HUD_CHANNEL)
	show_hudmessage(id,"")
}

public sethealthshow(id,level,cid)
{
	// -- Check if the player is an admin
	if(!cmd_access(id,level,cid,2))
		return PLUGIN_HANDLED;
	
	// -- Get the arguments of the command
	new arg[32]
	read_argv(1,arg,31)
	
	// -- Get the admin's info
	new adminname[32], adminauth[32]
	get_user_name(id,adminname,31)
	get_user_authid(id,adminauth,31)
	
	// -- Get the number
	new hOn = str_to_num(arg)
	if( hOn > 1 || hOn < 0 )
		hOn = 0
	
	// -- Check if the cvar is already set
	if(get_pcvar_num(g_health) == hOn)
	{
		console_print(id,"%L",id,"HEALTH_ALREADY",id,hOn?"ON":"OFF")
		return PLUGIN_HANDLED;
	}
	
	// -- Set the cvar
	set_pcvar_num(g_health,hOn)
	
	// -- Action for all players
	new players[32], pnum
	get_players( players, pnum, "ac" )
	for(new i=0;i<pnum;i++)
	{
		switch(hOn)
		{
			case 1: event_health(players[i]) // -- If health showing was turned on
			case 0: destroy_health(players[i]) // -- // -- If health showing was turned off
		}
	}
	// -- Inform the players
	client_print(0,print_chat,"%L",LANG_PLAYER,"HEALTH_NEW_STATUS",LANG_PLAYER,hOn?"ON":"OFF")
	
	// -- Log the command
	log_amx(g_logmessage[0],adminname,adminauth,g_logoptions[hOn + 7])
	return PLUGIN_HANDLED;
}

public sethealthcustom(id,level,cid)
{
	// -- Check if player is an admin
	if(!cmd_access(id,level,cid,4))
		return PLUGIN_HANDLED;
	
	// -- Get the string
	read_args(szColor,15)
	remove_quotes(szColor)
	
	// -- Separate string to individual RGB numbers
	static tR[4], tG[4], tB[4]
	parse(szColor,tR,3,tG,3,tB,3)
	szR = str_to_num(tR)
	szG = str_to_num(tG)
	szB = str_to_num(tB)
	
	// -- Out of bounds indicator
	new wrongcolor = 0
	
	// -- Check if specified color is uot of RGB bounds
	if(szR>255 || szR<0)
		wrongcolor = 1
	
	if(szG>255 || szG<0)
		wrongcolor = 2
	
	if(szB>255 || szB<0)
		wrongcolor = 3
	
	
	// -- If the color was out of bounds
	if(wrongcolor>0)
	{
		// -- Print usage of command
		console_print(id,"%L",id,"HEALTH_IE_MAIN")
		switch(wrongcolor)
		{
			// -- Print example of each color
			case 1: console_print(id,"%L",id,"HEALTH_IE_RED")
			case 2: console_print(id,"%L",id,"HEALTH_IE_GREEN")
			case 3: console_print(id,"%L",id,"HEALTH_IE_BLUE")
		}
		return PLUGIN_HANDLED;
	}
	
	// -- Set the health color
	set_cvar_string("health_custom",szColor)
	
	// -- Get the admin's info
	new adminname[32], adminauth[32]
	get_user_name(id,adminname,31)
	get_user_authid(id,adminname,31)
	
	// -- Log the admin's command
	log_amx(g_logmessage[1],adminname,adminauth,aR,aG,aB)
	return PLUGIN_HANDLED;
}

public sethealthcolor(id,level,cid)
{
	// -- Check if the player is an admin
	if(!cmd_access(id,level,cid,2))
		return PLUGIN_HANDLED;
	
	// -- Get the cvar desired
	new arg[32]
	read_argv(1,arg,31)
	
	// -- Get the admin's info
	new adminname[32], adminauth[32]
	get_user_name(id,adminname,31)
	get_user_authid(id,adminauth,31)
	
	// -- Get the custom color
	new cColor = str_to_num(arg)
	if( cColor > 2 || cColor < 0 )
		cColor = 0
	
	// -- Set the color and log command
	set_pcvar_num(g_color,cColor)
	log_amx(g_logmessage[2],adminname,adminauth,g_logoptions[cColor])
	return PLUGIN_HANDLED;
}

public sethealtheffects(id,level,cid)
{
	// -- Check if the player is an admin
	if(!cmd_access(id,level,cid,2))
		return PLUGIN_HANDLED;
	
	// -- Get the effects number desired
	new arg[32]
	read_argv(1,arg,31)
	
	// -- Get the adimn's info
	new adminname[32], adminauth[32]
	get_user_name(id,adminname,31)
	get_user_authid(id,adminauth,31)
	
	// -- Get the effect
	new hEffect = str_to_num(arg)
	if( hEffect > 2 || hEffect < 0 )
		hEffect = 0
	
	set_pcvar_num(g_effects,hEffect)
	log_amx(g_logmessage[3],adminname,adminauth,g_logoptions[hEffect + 3])
	return PLUGIN_HANDLED;
}
