#pragma tabsize			0
//#pragma semicolon		1

#define	PLUGIN_NAME		"Warcraft 3 Frozen Throne"
#define PLUGIN_AUTHOR	"WISHEXEC, Geesu, Avanderik & YamiKaitou"
#define	PLUGIN_VERSION	"RC15 2018"

#include <amxmodx>
#include <amxmisc>
#include <engine>
#include <fun>
#include <fakemeta>
#include <cstrike>
#include <sqlx>
#include <hamsandwich>
#include <dhudmessage>
#include <Vexd_Utilities>
#include <xs>

// Header files that contain function declarations and variables
#include "war3ft/constants.inl"
#include "war3ft/db/db_common.h"
#include "war3ft/db/db_mysqlx.h"
#include "war3ft/db/db_sqlite.h"
#include "war3ft/items.h"
#include "war3ft/XP.h"
#include "war3ft/war3ft.h"
#include "war3ft/cstrike.h"
#include "war3ft/menus.h"
#include "war3ft/shared.h"
#include "war3ft/ultimates.h"
#include "war3ft/loot.h"

// Source Code
#include "war3ft/cvar.inl"

#include "war3ft/race_undead.inl"           // Undead    		- 1
#include "war3ft/race_human.inl"			// Human 			- 2
#include "war3ft/race_orc.inl"				// Orc				- 3
#include "war3ft/race_elf.inl"				// Night Elf		- 4
#include "war3ft/race_blood.inl"			// Blood Elf		- 5
#include "war3ft/race_shadow.inl"			// Troll			- 6
#include "war3ft/race_warden.inl"           // Specter          - 7
#include "war3ft/race_crypt.inl"			// Nerubian     	- 8
#include "war3ft/race_crystal.inl"			// Crystal Maiden   - 9
#include "war3ft/race_druid.inl"			// Druid   			- 10


#include "war3ft/race_chameleon.inl"		// Chameleon		- X

#include "war3ft/forwards.inl"
#include "war3ft/effects.inl"
#include "war3ft/XP.inl"
#include "war3ft/db/db_mysqlx.inl"
#include "war3ft/db/db_sqlite.inl"
#include "war3ft/db/db_common.inl"
#include "war3ft/war3ft.inl"
#include "war3ft/events.inl"
#include "war3ft/clientCommands.inl"
#include "war3ft/items.inl"
#include "war3ft/stocks.inl"
#include "war3ft/shared.inl"
#include "war3ft/menus.inl"
#include "war3ft/admin.inl"
#include "war3ft/ultimates.inl"
#include "war3ft/util.inl"
#include "war3ft/skill_manager.inl"
#include "war3ft/loot.inl"
#include "war3ft/gold.inl"
#include "war3ft/levelbank.inl"

#include "war3ft/grenades.inl"

#include "war3ft/cstrike.inl"


public plugin_init()
{
	register_plugin( PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR );
	
	WC3_DetermineGame();
	
	// Plugin initialization procedures
	WC3_Init();

	gmsgDeathMsg		= get_user_msgid( "DeathMsg"	);
	gmsgScreenFade		= get_user_msgid( "ScreenFade"	);
	gmsgScreenShake		= get_user_msgid( "ScreenShake"	);
	gmsgScoreInfo		= get_user_msgid( "ScoreInfo"	);
	
	register_clcmd("chooseteam", "ChooseTeam");
	
	set_task(INFO_FREQ, "ShowInfoMessage", _,_,_,"b");
	
	
	set_task(CONVERTOR_THINK_FREQ, "Convertor_Think", _,_,_,"b");
	
	//set_task( 1.0, "_ULT_Delay", TASK_UDELAY, "", 0, "b" );
	

	register_concmd( "playerskills"		, "CMD_Handler"		, -1 );

	register_clcmd( "account"			, "CMD_Handler"		, -1 );
	register_clcmd( "war3menu"			, "CMD_Handler"		, -1 );
	register_clcmd( "changerace"		, "CMD_Handler"		, -1 );
	register_clcmd( "selectskill"		, "CMD_Handler"		, -1 );
	register_clcmd( "skillsinfo"		, "CMD_Handler"		, -1 );
	register_clcmd( "resetskills"		, "CMD_Handler"		, -1 );
	register_clcmd( "resetxp"			, "CMD_Handler"		, -1 );
	register_clcmd( "itemsinfo"			, "CMD_Handler"		, -1 );
	register_clcmd( "level"				, "CMD_Handler"		, -1 );
	register_clcmd( "war3help"			, "CMD_Handler"		, -1 );
	register_clcmd( "ultimate"			, "cmd_Ultimate"	, -1 );
	
	register_clcmd( "exchange"			, "CMD_Handler"		, -1 );
	register_clcmd( "gold"				, "CMD_Handler"		, -1 );
	register_clcmd( "levelbank"			, "CMD_Handler"		, -1 );
	register_clcmd( "trade"				, "CMD_Handler"		, -1 );
	
	
	register_clcmd( "shopmenu"			, "CMD_Handler"		, -1 );
	register_clcmd( "shop"				, "CMD_Handler"		, -1 );
	
	register_clcmd( "ability"			, "CMD_Handler"		, -1 );
	
	register_clcmd( "ankh"				, "CMD_Handler"		, -1 );
	register_clcmd( "amulet"			, "CMD_Handler"		, -1 );
	register_clcmd( "boots"				, "CMD_Handler"		, -1 );
	
	register_clcmd( "claw"				, "CMD_Handler"		, -1 );
	register_clcmd( "claws"				, "CMD_Handler"		, -1 );
	
	register_clcmd( "cloak"				, "CMD_Handler"		, -1 );
	register_clcmd( "chameleon"			, "CMD_Handler"		, -1 );
	register_clcmd( "frost"				, "CMD_Handler"		, -1 );
	register_clcmd( "mine"				, "CMD_Handler"		, -1 );
	
	
	register_clcmd( "gloves"			, "CMD_Handler"		, -1 );
	register_clcmd( "glove"				, "CMD_Handler"		, -1 );
	
	register_clcmd( "health"			, "CMD_Handler"		, -1 );
	register_clcmd( "helm"				, "CMD_Handler"		, -1 );
	register_clcmd( "mask"				, "CMD_Handler"		, -1 );
	register_clcmd( "mole"				, "CMD_Handler"		, -1 );
	
	register_clcmd( "gem"				, "CMD_Handler"		, -1 );
	register_clcmd( "protectant"		, "CMD_Handler"		, -1 );
	
	register_clcmd( "necklace"			, "CMD_Handler"		, -1 );
	register_clcmd( "neck"				, "CMD_Handler"		, -1 );
	register_clcmd( "wand"				, "CMD_Handler"		, -1 );
	
	register_clcmd( "ring"				, "CMD_Handler"		, -1 );
	register_clcmd( "rings"				, "CMD_Handler"		, -1 );
	
	register_clcmd( "sock"				, "CMD_Handler"		, -1 );
	register_clcmd( "socks"				, "CMD_Handler"		, -1 );
	
	register_clcmd( "scroll"			, "CMD_Handler"		, -1 );
	register_clcmd( "tome"				, "CMD_Handler"		, -1 );
	
	
	
	register_clcmd( "say"				, "cmd_Say"			, -1 );
	register_clcmd( "say_team"			, "cmd_Say"			, -1 );
	
	
	
	// Those are usefull 
	register_clcmd( "fullupdate"		, "cmd_fullupdate"	, -1 );
	register_clcmd( "drop"				, "on_Drop"			, -1 );
	register_clcmd( "jointeam"			, "cmd_Jointeam"	, -1 );

	// Admin Commands
	//register_concmd( "wc3_givexp"		, "ADMIN_Handler"		, -1 , " -- Gives XP to players"				);
	//register_concmd( "wc3_setlevel"	    , "ADMIN_Handler"		, -1 , " -- Sets a player's level"			);
	register_concmd( "wc3_giveitem"		, "ADMIN_Handler"		, -1 , " -- Gives an item to a player"			);


	// Depreciated Admin Commands
	register_concmd("amx_givexp"		, "ADMIN_Handler"		, -1 , " -- Gives XP to players"				);
	register_concmd("amx_givegold"		, "GiveGold", ADMIN_CVAR, "Name/@All -> Amount"							);
	register_concmd("amx_resetgold"		, "ResetGold", ADMIN_CVAR, "Name/@All -> Amount"						);
	
	


	// Server Admin Commands (used by external plugins)
	register_srvcmd( "amx_takexp"		, "ADMIN_ServerHandler"	);
	register_srvcmd( "changexp"			, "ADMIN_ServerHandler"	);

	// Register forwards (from fakemeta)
	register_forward( FM_TraceLine		, "TRIGGER_TraceLine"	);
	register_forward( FM_Touch		, "FM_Player_Touch"			);
	
	register_think("lasermine","Lasermine_Think")

	

	
	register_event( "DeathMsg"			, "on_DeathMsg"		, "a"								);
	register_event( "CurWeapon"			, "on_CurWeapon"	, "be"	, "1=1"						);
	register_event( "HideWeapon"		, "on_CurWeapon"	, "b"								);
//	register_event( "ResetHUD"			, "on_ResetHud"		, "b"								);
	register_event( "TextMsg"			, "on_GameRestart"	, "a"	, "2&#Game_will_restart_in" );
	register_event( "HLTV"				, "EVENT_NewRound"	, "a"	, "1=0"	,			"2=0"	);
	
	

	RegisterHam( Ham_TakeDamage, "player", "EVENT_TakeDamage" );
	RegisterHam( Ham_Spawn, "player", "EVENT_Spawn", 1);
	
	
	register_forward(FM_SetModel, "FW_SetModel_Nades");
	register_forward(FM_Touch, "FW_Touch_Nades");
	RegisterHam(Ham_Item_Deploy, "weapon_hegrenade", "FW_Item_Deploy_HE", 1)
	RegisterHam(Ham_Item_Deploy, "weapon_smokegrenade", "FW_Item_Deploy_SM", 1)
	//RegisterHam(Ham_Item_Deploy, "weapon_flashbang", "FW_Item_Deploy_FB", 1)
	
	//register_forward( FM_PlayerPreThink, "FW_RadarThink", false );
	register_forward( FM_PlayerPreThink, "fwdPlayerPreThink" ); 
	
	
	g_iMsgIdHostageK = get_user_msgid( "HostageK" );
	g_iMsgIdHostagePos = get_user_msgid( "HostagePos" );
	g_iMaxPlayers = get_maxplayers( );

	
	

	// Game Specific Initialization
	if ( g_MOD == GAME_CSTRIKE || g_MOD == GAME_CZERO )
	{
		gmsgBarTime			= get_user_msgid( "BarTime"		);
		gmsgStatusText		= get_user_msgid( "StatusText"	);
		gmsgStatusIcon		= get_user_msgid( "StatusIcon"	);

		register_logevent( "on_PlayerAction"		, 3		, "1=triggered"								);
		register_logevent( "on_FreezeTimeComplete"	, 2		, "0=World triggered"	, "1=Round_Start"	);
		register_logevent( "on_EndRound"			, 2		, "0=World triggered"	, "1=Round_End"		);

		

		register_event( "SendAudio"		, "on_TerroristWin"		, "a"	, "2=%!MRAD_terwin"					);
		register_event( "SendAudio"		, "on_CTWin"			, "a"	, "2=%!MRAD_ctwin"					);
		register_event( "ArmorType"		, "on_ArmorType"		, "be"										);
		register_event( "Battery"		, "on_Battery"			, "be"										);
		register_event( "WeapPickup"	, "on_WeapPickup"		, "b"										); 
		register_event( "StatusValue"	, "on_ShowStatus"		, "be"	, "1=2"		,"2!0"					);
		register_event( "StatusValue"	, "on_HideStatus"		, "be"	, "1=1"		,"2=0"					);
		register_event( "SetFOV"		, "on_Zoom"				, "be"										);
		register_event( "BarTime"		, "on_BombPlanting"		, "be"	, "1=3"								);
		register_event( "BarTime"		, "on_BombStopPlanting"	, "b"	, "1=0"								);
		
		
		
		
		
		
		
		

		// Old Style
		register_menucmd( register_menuid( "BuyItem" )	, (1<<3)	, "cmd_hegren"	);

		// VGUI
		register_menucmd( -34	, (1<<3)	, "cmd_hegren"	);

		// Steam
		register_clcmd( "hegren"	, "cmd_hegren"	);
		
		// Old style menu (now its jointeam client command)
		register_menucmd( register_menuid( "Team_Select" , 1 )	, (1<<0)|(1<<1)|(1<<4)	, "cmd_Teamselect" );
		
		//register_menu("ChangeRace", 1023, "_MENU_ChangeRace")
	   register_menu("ChangeRace", 32767, "_MENU_ChangeRace")

		register_event("TextMsg", "on_GameRestart", "a", "2&#Game_C")
		
	}
	
	// Format files 
	new DataDir[64]
	get_datadir(DataDir, 63)
	
	format(GoldFile, 127, "%s/Gold.dat", DataDir)
	format(PolymorphFile, 127, "%s/Polymorph.dat", DataDir)
	format(LevelBankFile, 127, "%s/LevelBank.dat", DataDir)
	
	
	
	
	

}

public plugin_natives() 
{
	register_native("set_user_gold", "set_user_gold", 1);
	register_native("get_user_gold", "get_user_gold", 1);
	
	register_native("set_user_levelbank", "set_user_levelbank", 1);
	register_native("get_user_levelbank", "get_user_levelbank", 1);
}





public plugin_end()
{
	new szCurMap[32];
	get_mapname( szCurMap, 31 );
	WC3_Log( false, "** Map '%s' ended", szCurMap );

	if ( !WC3_Check() )
	{
		return;
	}

	if ( !get_pcvar_num( CVAR_wc3_save_xp ) )
	{
		return;
	}
	
	FWD_Destroy();
	DB_SaveAll( false );
	DB_Prune();
	DB_Close();


	return;
}

public plugin_precache()
{
	WC3_Precache();
	g_supplybox_icon_id = engfunc(EngFunc_PrecacheModel, supplybox_icon_spr)
}

public client_putinserver( id )
{	

	LoadPolymorph(id);


	LoadGold(id);
	
	LoadLevelBank(id);
	
	g_bExchange[id] = true;
	
	
	bChooseTeamOverrideActive[id] = true;
	

	// Get the user's ID!
	DB_FetchUniqueID( id );

	p_data_b[id][PB_ISCONNECTED] = true;
	
	
	return;
}



public client_connect( id )
{

	IsUserConnected[  id ] = true;

	PrintMessageInfo(id);

	// Initialize this player
	WC3_PlayerInit( id );
	

	client_cmd( id, "hud_centerid 0" );


	p_data[id][P_RESPAWNBY]				= 0;
	p_data[id][P_SPECMODE]				= 0;

	p_data_b[id][PB_ISBURNING]			= false;
	p_data_b[id][PB_JUSTJOINED]			= true;
	p_data_b[id][PB_CAN_RENDER]			= true;
	p_data_b[id][PB_HAS_SPAWNED]		= false;
	p_data_b[id][PB_SKINSWITCHED]		= false;

	// User should have no items on connect...
	g_iShopMenuItems[id][0] = -1;
	g_iShopMenuItems[id][1] = -1;

	// Automatically set their XP if it's enabled
	if ( get_pcvar_num( CVAR_wc3_xp_auto_average ) && !get_pcvar_num( CVAR_wc3_save_xp ) )
	{
		new iTotalXP;
		new iNum, i;
		for( i = 1; i <= MAXPLAYERS; i++ )
		{
			if ( p_data[i][P_XP] > 0 )
			{
				iNum++;
				iTotalXP += p_data[i][P_XP];
			}
		}
		if ( iNum > 0 && iTotalXP > 0 )
		{
			p_data[id][P_XP] = iTotalXP/iNum;
		}
	}

	if ( g_MOD == GAME_CSTRIKE || g_MOD == GAME_CZERO )
	{
		p_data[id][P_HECOUNT]		= 0;
		p_data[id][P_FLASHCOUNT]	= 0;
	}
	
	
	return;
}

public client_disconnect( id )
{

	PrintMessageInfo(id);
	
	IsUserConnected[ id ] = false;
	

	// Update the user's timestamps for each race if we're saving XP
	DB_UpdateTimestamp( id );

	

	p_data[id][P_SPECMODE]			= 0;
	p_data_b[id][PB_ISBURNING]		= false;
	p_data_b[id][PB_DIEDLASTROUND]	= false;
	p_data_b[id][PB_JUSTJOINED]		= false;
	p_data_b[id][PB_ISCONNECTED]	= false;
	bIgnoreArmorSet[id]				= false;
	
	// Reset xp assist
	for ( new i = 0; i < MAXPLAYERS; i++ )
	{
		g_iDamageDealt[id][i] = 0;
	}

	// Save the user's XP if we have XP to save
	if ( get_pcvar_num( CVAR_wc3_save_xp ) && !is_user_bot(id) && p_data[id][P_RACE] && p_data[id][P_XP] )
	{
		DB_SaveXP( id, true );
	}

}

public client_PreThink( id )
{
	

	if ( p_data_b[id][PB_ISCONNECTED] )
	{
		if ( is_user_alive( id ) )
		{
			
			new temp[2], weapon = get_user_weapon(id, temp[0], temp[1])
			if(weapon != CSW_C4 && ITEM_Has( id, ITEM_MINE ) > ITEM_NONE)
			{
				if(get_user_button(id) & IN_USE)
				{
					if((Delay[id] + 1.3) < get_gametime())
					{

						Create_Mine(id)
	
						Delay[id] = get_gametime()
					}
				}
			}
			
			

			
			if(currentFrame[id] >= FRAME) 
			{
				client_cmd(id,"cl_minmodels 0");
				currentFrame[id] = 0;
			}
			
			currentFrame[id]++;
	
			
				// This is used so we can't hear the undead's footsteps at level 3
				if ( SM_GetSkillLevel( id, SKILL_UNHOLYAURA ) > 0 && !p_data_b[id][PB_STUNNED] && !p_data_b[id][PB_SLOWED] )
				{
					new Float:vel[3];
					entity_get_vector( id, EV_VEC_velocity, vel );

					// When this is true, the user is walking...  lets hope :P
					if ( vector_length( vel ) < 180.0 )
					{
						entity_set_int( id, EV_INT_flTimeStepSound, 999 );
					}

					// Otherwise if we just set it on the previous tick we need to set it back
					else if ( entity_get_int(id, EV_INT_flTimeStepSound) > 500 )
					{
						entity_set_int( id, EV_INT_flTimeStepSound, 200 );
					}
				}


			

			// Amulet of the Cat
			if ( ITEM_Has( id, ITEM_AMULET ) > ITEM_NONE )
			{
				entity_set_int( id, EV_INT_flTimeStepSound, 999 );
			}
		}
		
		// User is dead
		else
		{

			// Check to see if spectated player has changed
			new iTarget = entity_get_int( id, EV_INT_iuser2 );
			
			new Float:fTime = halflife_time();

			// Then we are looking at a new player or the last hud message has disappeared
			if ( g_iSpectatingID[id] != iTarget || g_fLastSpecDisplay[id] <= fTime )
			{

				// We have a valid target!!
				if ( SHARED_ValidPlayer( iTarget ) && iTarget != id )
				{
					WC3_ShowSpecInfo( id, iTarget );

					g_fLastSpecDisplay[id] = fTime + SPEC_HOLDTIME;
				}

				g_iSpectatingID[id] = iTarget;
			}
		}
	}

	return;
}

public client_PostThink(id)
{


	if (!is_user_alive(id))
		return
		
	static iSkillLevel;
	iSkillLevel = SM_GetSkillLevel( id, SKILL_CYCLONE ); 
	
	if (!iSkillLevel)
		return
		
	if(g_icon_delay[id] + WALL_ICON_DELAY > get_gametime())
		return
		
	g_icon_delay[id] = get_gametime()
	
	
	for( new iPlayer = 1; iPlayer <= g_iMaxPlayers; iPlayer++ )
			{
				if( cs_get_user_team(id) != cs_get_user_team(iPlayer) && is_user_alive( iPlayer ) && get_user_health(iPlayer) <= p_cyclone[iSkillLevel-1] && is_user_connected(id) && is_user_connected(iPlayer) )
				{
					create_icon_origin(id, iPlayer, g_supplybox_icon_id)		
				}
			}
			

}


public fwdPlayerPreThink( id ) 
{
	
	if( IsUserConnected[ id ] )
	{

		GameTime[ id ] = get_gametime( );
				
		if( FramesPer[ id ] >= GameTime[ id ] )
			Fps[ id ] += 1;
		
		else 
		{
			FramesPer[ id ]	+= 1;
			CurFps[ id ]	= Fps[ id ];
			Fps[ id ]	= 0;
		}
			
	}
	
	return FMRES_IGNORED;
}
