#include "gen_bot_header.h"
#include "monsters.h"
#include "teamplay_gamerules.h"
#include "talkmonster.h"
#include "buddy_aura.h"
#include "buddy.h"

#ifdef _DEBUG
bool DisplayBotStuff = false;
#endif

//harSens: Linux compile fix
extern CLeftOutput lcout;

extern int gmsgVGUIMenu;

// ==================================================================
// Code of CBotManager - Begin
// ==================================================================

bool CBotManager::HandleBotCommands(edict_t *pEntity)
{
	// For now: no client-side commands and no ded server commands because they
	// are handled differently.
	if (IS_DEDICATED_SERVER())
		return false; // No ded server commands here

	// Check if this is the host
	CBasePlayer *pHost = GetHost();
	if ((pHost) && (pHost->edict() != pEntity))
		return false;

	HandleNonDedBotCommands();

	if (!m_bFoundBotCommand)
		HandleNormalBotCommands();

#ifdef _DEBUG
	if (!m_bFoundBotCommand)
		HandleBotDebugCommands();
#endif

	if (m_bFoundBotCommand)
	{
		m_bFoundBotCommand = false;
		return true;
	}

	return false;
}

void CBotManager::HandleNonDedBotCommands()
{
	CBasePlayer *pHost = GetHost();
	if (!pHost || IsNull(pHost))
		return;

	// Make some shortcuts...
	const char *pcmd = CMD_ARGV(0);
	const char *arg1 = CMD_ARGV(1);
	const char *arg2 = CMD_ARGV(2);
	const char *arg3 = CMD_ARGV(3);
	const char *arg4 = CMD_ARGV(4);
	const char *arg5 = CMD_ARGV(5);

	m_bFoundBotCommand = true;

	if (FStrEq(pcmd, "killbotinfront"))
	{
		UTIL_MakeVectors(pHost->pev->v_angle);
		Vector v_src = pHost->pev->origin;
		Vector v_end = v_src + gpGlobals->v_forward * 10000;
		TraceResult tr;

		UTIL_TraceHull(v_src, v_end, dont_ignore_monsters, human_hull,
					   pHost->pev->pContainingEntity, &tr);

		// Did the traceline hit something ?
		if (IsNull(tr.pHit) == false)
		{
			// Is it a bot ?
			if ((tr.pHit->v.flags & FL_CLIENT) && (tr.pHit->v.flags & FL_FAKECLIENT))
			{
				ClientKill(tr.pHit); // kill the bot
			}
		}
	}
	else if (FStrEq(pcmd, "waypoint"))
	{
		if (FStrEq(arg1, "on"))
		{
            WaypointClass.SetWaypointsVisible(true);
            cout << "waypoints are ON\n";
		}
        else if (FStrEq(arg1, "off"))
        {
            WaypointClass.SetWaypointsVisible(false);
            cout << "waypoints are OFF\n";
		}
        else if (FStrEq(arg1, "add"))
        {
			WaypointClass.SetWaypointsVisible(true);
            WaypointClass.AddWaypoint(pHost);
		}
        else if (FStrEq(arg1, "delete"))
        {
			WaypointClass.SetWaypointsVisible(true);
            WaypointClass.DeleteWaypoint(pHost);
		}
        else if (FStrEq(arg1, "save"))
		{
            WaypointClass.SaveWaypoints();

            cout << "waypoints saved\n";
		}
		else if (FStrEq(arg1, "load"))
        {
            if (WaypointClass.LoadWaypoints())
				cout << "waypoints loaded\n";
			else
				cout << "Error loading waypoints for this map\n";
		}
        else
		{
            if (WaypointClass.WaypointsAreVisible())
				cout << "waypoints are ON\n";
            else
				cout << "waypoints are OFF\n";
		}
	}
    else if (FStrEq(pcmd, "autowaypoint"))
    {
		if (FStrEq(arg1, "on"))
		{
			WaypointClass.SetWaypointsVisible(true); // turn this on just in case
			WaypointClass.SetAutoWaypoint(true);
			cout << "autowaypoint is ON\n";
		}
        else if (FStrEq(arg1, "off"))
		{
			WaypointClass.SetAutoWaypoint(false);
			cout << "autowaypoint is OFF\n";
		}
	}
    else if (FStrEq(pcmd, "pathwaypoint"))
	{
		if (FStrEq(arg1, "on"))
		{
            WaypointClass.SetPathsVisible(true);
            WaypointClass.SetWaypointsVisible(true); // turn this on just in case
            cout << "pathwaypoint is ON\n";
		}
        else if (FStrEq(arg1, "off"))
        {
            WaypointClass.SetPathsVisible(false);
            cout << "pathwaypoint is OFF\n";
		}
		else if (FStrEq(arg1, "create1"))
		{
            WaypointClass.ManuallyCreatePath(pHost, 1, false);
		}
        else if (FStrEq(arg1, "create2"))
		{
            WaypointClass.ManuallyCreatePath(pHost, 2, false);
		}
		else if (FStrEq(arg1, "create2way1"))
		{
			WaypointClass.ManuallyCreatePath(pHost, 1, true);
		}
		else if (FStrEq(arg1, "create2way2"))
		{
			WaypointClass.ManuallyCreatePath(pHost, 2, true);
		}
        else if (FStrEq(arg1, "remove1"))
        {
            WaypointClass.ManuallyDeletePath(pHost, 1, false);
		}
        else if (FStrEq(arg1, "remove2"))
        {
            WaypointClass.ManuallyDeletePath(pHost, 2, false);
		}
		else if (FStrEq(arg1, "remove2way1"))
		{
			WaypointClass.ManuallyDeletePath(pHost, 1, true);
		}
		else if (FStrEq(arg1, "remove2way2"))
		{
			WaypointClass.ManuallyDeletePath(pHost, 2, true);
		}
	}
	else if (FStrEq(pcmd, "dbgatherspot"))
	{
		if (!m_bDBMode)
		{
			cout << "Error: Cannot use dragonball commands when CPTDB mode is off!\n";
			return;
		}

		if (FStrEq(arg1, "on"))
		{
			cout << "DB gather spots are being drawed\n";
			BotDBManager.DrawDBSpots(true);
		}
		else if (FStrEq(arg1, "off"))
		{
			cout << "DB gather spots are not being drawed\n";
			BotDBManager.DrawDBSpots(false);
		}
		else if (FStrEq(arg1, "add"))
		{
			cout << "Adding dragonball gather spot...\n";
			BotDBManager.PlaceNewDBGatherSpot();
		}
		else if (FStrEq(arg1, "delete"))
		{
			cout << "Deleting dragonball gather spot...\n";
			BotDBManager.DeleteDBGatherSpot();
		}
		else if (FStrEq(arg1, "save"))
		{
			BotDBManager.SaveCustomGatherDBSpots();
		}
		else if (FStrEq(arg1, "load"))
		{
			BotDBManager.LoadCustomGatherDBSpots();
		}
		else if (FStrEq(arg1, "clear"))
		{
			BotDBManager.ClearAllDBSpots();
		}
		else
		{
			// ... TODO, print correct usage?
		}
	}
	else
		m_bFoundBotCommand = false;
}

// Can't make this a botmanager member function because its bound with AddServerCommand
void HandleNormalBotCommands()
{
	// Plus 1 if dedicated server, because the first arg will contain 'esf_bot'
	byte AddVal = (IS_DEDICATED_SERVER()) ? 1 : 0;
	const char *pcmd = CMD_ARGV(0 + AddVal);
	const char *arg1 = CMD_ARGV(1 + AddVal);
	const char *arg2 = CMD_ARGV(2 + AddVal);
	const char *arg3 = CMD_ARGV(3 + AddVal);
	const char *arg4 = CMD_ARGV(4 + AddVal);
	const char *arg5 = CMD_ARGV(5 + AddVal);
	const char *arg6 = CMD_ARGV(6 + AddVal);
	const char *arg7 = CMD_ARGV(7 + AddVal);

	BotManager.m_bFoundBotCommand = true;

	if (FStrEq(pcmd, "addbot"))
	{
		short Team = -1, Class = -1, Skill = -1, Count = -1;
		const char *szPerso = ((arg5) && (*arg5) && (arg5[0] != '*')) ? arg5 : "";
		const char *szName = ((arg3) && (*arg3) && (arg3[0] != '*')) ? arg3 : "";
		EBotDBType BotDBType = DB_UNASSIGNED;

		if ((arg1) && (*arg1) && (arg1[0] != '*'))
			Team = (g_teamplay) ? atoi(arg1) : -1;
		if ((arg2) && (*arg2) && (arg2[0] != '*'))
			Class = atoi(arg2);
		if ((arg4) && (*arg4) && (arg4[0] != '*'))
			Skill = atoi(arg4);
		if ((arg6) && (*arg6) && (arg6[0] != '*'))
			Count = atoi(arg6);

		if ((arg7) && (*arg7))
		{
			int DBType = atoi(arg7);
			if ((DBType >= 1) && (DBType <= 3))
				BotDBType = EBotDBType(DBType-1);
		}

		if (Count < 2)
			BotManager.CreateBot(Team, Class, szName, Skill, szPerso, BotDBType);
		else
			BotManager.BotFill(Count, Team, Class, Skill, szPerso, BotDBType);
	}
	else if (FStrEq(pcmd, "addsbot"))
	{
		if (!g_teamplay)
		{
			cout << "Cannot create Super Bots in free fight!\n";
			BotManager.m_bFoundBotCommand = false;
			return;
		}

		short Class = -1, Perso = -1, Type = -1, Count = -1;
		const char *szPerso = ((arg3) && (*arg3) && (arg3[0] != '*')) ? arg3 : "";
		const char *szName = ((arg6) && (*arg6) && (arg6[0] != '*')) ? arg6 : "";
		EBotDBType BotDBType = DB_UNASSIGNED;

		if ((arg1) && (*arg1) && (arg1[0] != '*'))
			Type = atoi(arg1);
		if ((arg2) && (*arg2) && (arg2[0] != '*'))
			Class = atoi(arg2);
		if ((arg5) && (*arg5) && (arg5[0] != '*'))
			Count = atoi(arg5);

		if ((arg4) && (*arg4))
		{
			int DBType = atoi(arg5);
			if ((DBType >= 1) && (DBType <= 3))
				BotDBType = EBotDBType(DBType-1);
		}

		if (Count < 2)
			BotManager.CreateSuperBot(Class, szName, szPerso, Type, BotDBType);
		else
			BotManager.SBotFill(Count, Class, szPerso, Type, BotDBType);
	}
/*
	else if (FStrEq(pcmd, "idlebots"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangeBotBoolSetting(BotManager.m_bBotsAreIdle, (atoi(arg1) != 0),
											"idlebots");
		}
	}
	else if (FStrEq(pcmd, "botsmove"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangeBotBoolSetting(BotManager.m_bBotsMove, (atoi(arg1) != 0),
											"botsmove");
		}
	}
	else if (FStrEq(pcmd, "botsusediscs"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangeBotBoolSetting(BotManager.m_bBotsUseDiscs, (atoi(arg1) != 0),
											"botsusediscs");
		}
	}
	else if (FStrEq(pcmd, "shouldbotschat"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangeBotBoolSetting(BotManager.m_bShouldBotsChat, (atoi(arg1) != 0),
											"shouldbotschat");
		}
	}
	else if (FStrEq(pcmd, "bot_balanceteams"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangeBotBoolSetting(BotManager.m_bBalanceTeams, (atoi(arg1) != 0),
											"bot_balanceteams");
		}
	}
	else if (FStrEq(pcmd, "observer"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangeBotBoolSetting(BotManager.m_bObserverMode, (atoi(arg1) != 0),
											"observer");
		}
	}
	else if (FStrEq(pcmd, "botsshoot"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangeBotBoolSetting(BotManager.m_bBotsShoot, (atoi(arg1) != 0),
											"botsshoot");
		}
	}
	else if (FStrEq(pcmd, "botssearchenemies"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangeBotBoolSetting(BotManager.m_bBotsSearchEnemies, (atoi(arg1) != 0),
											"botssearchenemies");
		}
	}
*/
	else if (FStrEq(pcmd, "bot_aggression_level"))
	{
		if ((arg1) && (*arg1))
		{
			EAggressionLevel AggrLevel;

			if (FStrEq(arg1,"defensive"))
				AggrLevel = Defensive;
			else if (FStrEq(arg1,"normal"))
				AggrLevel = Normal;
			else if (FStrEq(arg1,"aggressive"))
				AggrLevel = Aggressive;
			else
			{
				cout << "Invalid aggression level\n";
				return;				  
			}
			
			BotManager.ChangeAggressionLevel(AggrLevel);
		}
	}
	else if (FStrEq(pcmd, "botskill"))
	{
		if ((arg1) && (*arg1))
		{
			if ((arg2) && (*arg2))
			{
				CBasePlayer *pPlayer = FindPlayerByName(arg1);

				if (!UTIL_IsValidPlayer(pPlayer))
				{
					cout << "Error, invalid bot\n";
					return;
				}

				short Skill = atoi(arg2);
				if ((Skill < 1) || (Skill > 5))
				{
					cout << "Error: Invalid skill, range: 1(best) - 5(worst)\n";
					return;
				}

				// Is this player a bot?
				if (UTIL_IsBot(pPlayer))
				{
					CBot *pBot = UTIL_GetBotPointer(pPlayer);

					if (pBot->IsSuperBot())
						cout << "Error: can't change skill of a superbot\n";
					else
						pBot->SetSkill(Skill);
				}
			}
			else
				BotManager.ChangeBotSkill(atoi(arg1));
		}
	}
	else if (FStrEq(pcmd, "bot_chat_percent"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangePersoPercentSetting(&bot_personality_s::chat_percent, atoi(arg1),
												 "chat_percent");
		}
	}
	else if (FStrEq(pcmd, "bot_taunt_percent"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangePersoPercentSetting(&bot_personality_s::taunt_percent, atoi(arg1),
												 "taunt_percent");
		}
	}
	else if (FStrEq(pcmd, "bot_whine_percent"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangePersoPercentSetting(&bot_personality_s::whine_percent, atoi(arg1),
												 "whine_percent");
		}
	}
	else if (FStrEq(pcmd, "bot_chat_tag_percent"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangePersoPercentSetting(&bot_personality_s::chat_tag_percent, atoi(arg1),
												 "chat_tag_percent");
		}
	}
	else if (FStrEq(pcmd, "bot_chat_drop_percent"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangePersoPercentSetting(&bot_personality_s::chat_drop_percent, atoi(arg1),
												 "chat_drop_percent");
		}
	}
	else if (FStrEq(pcmd, "bot_chat_swap_percent"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangePersoPercentSetting(&bot_personality_s::chat_swap_percent, atoi(arg1),
												 "chat_swap_percent");
		}
	}
	else if (FStrEq(pcmd, "bot_chat_lower_percent"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangePersoPercentSetting(&bot_personality_s::chat_lower_percent, atoi(arg1),
												 "chat_lower_percent");
		}
	}
	else if (FStrEq(pcmd, "bot_melee_percent"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangePersoPercentSetting(&bot_personality_s::melee_percent, atoi(arg1),
												 "melee_percent");
		}
	}
	else if (FStrEq(pcmd, "bot_meleethrow_percent"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangePersoPercentSetting(&bot_personality_s::meleethrow_percent, atoi(arg1),
												 "meleethrow_percent");
		}
	}
	else if (FStrEq(pcmd, "bot_simplemelee_percent"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangePersoPercentSetting(&bot_personality_s::simplemelee_percent, atoi(arg1),
												 "simplemelee_percent");
		}
	}
	else if (FStrEq(pcmd, "bot_teleport_percent"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangePersoPercentSetting(&bot_personality_s::teleport_percent, atoi(arg1),
												 "teleport_percent");
		}
	}
	else if (FStrEq(pcmd, "bot_swoop_percent"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangePersoPercentSetting(&bot_personality_s::swoop_percent, atoi(arg1),
												 "swoop_percent");
		}
	}
	else if (FStrEq(pcmd, "bot_block_percent"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangePersoPercentSetting(&bot_personality_s::block_percent, atoi(arg1),
												 "block_percent");
		}
	}
	else if (FStrEq(pcmd, "bot_fly_percent"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangeBotFlyPercent(atoi(arg1));
		}
	}
	else if (FStrEq(pcmd, "sbot_laser_percent"))
	{
		if ((arg1) && (*arg1))
		{
			BotManager.ChangeSBotLaserPercent(atoi(arg1));
		}
	}
	else if (FStrEq(pcmd, "restorebotpersonalities"))
		BotManager.CreateBotPersonalities();
	else if (FStrEq(pcmd, "min_bots"))
	{
		if ((arg1) && (*arg1))
			BotManager.SetMinBots(atoi(arg1));
	}
	else if (FStrEq(pcmd, "max_bots"))
	{
		if ((arg1) && (*arg1))
			BotManager.SetMaxBots(atoi(arg1));
	}
	else if (FStrEq(pcmd, "killbot"))
	{
		if ((arg1) && (*arg1))
		{
			CBasePlayer *pPlayer = FindPlayerByName(arg1);

			if (!UTIL_IsValidPlayer(pPlayer))
			{
				cout << "Error, invalid bot\n";
				return;
			}

			// Is this player a bot?
			if (UTIL_IsBot(pPlayer))
				ClientKill(pPlayer->edict());
		}
	}
	else if (FStrEq(pcmd, "botteam"))
	{
		if ((arg1) && (*arg1))
		{
			if (!g_teamplay)
			{
				cout << "Error, no teamplay\n";
				return;
			}

			CBasePlayer *pPlayer = FindPlayerByName(arg1);

			if (!UTIL_IsValidPlayer(pPlayer, false, false))
			{
				cout << "Error, invalid bot\n";
				return;
			}

			if ((arg2) && (*arg2))
			{
				short Team;
				if (FStrEq(arg2, "good"))
					Team = 1;
				else if (FStrEq(arg2, "evil"))
					Team = 2;
				else
				{
					cout << "Error, invalid team\n";
					return;
				}

				// Is this player a bot?
				if (UTIL_IsBot(pPlayer))
				{
					CBot *pBot = UTIL_GetBotPointer(pPlayer);
					pBot->m_sBotTeam = Team;
					g_pGameRules->ClientCommand(pBot, "jointeam");
				}
			}
			else
			{
				cout << "Team of " << STRING(pPlayer->pev->netname) << " : " <<
					    pPlayer->m_szTeamName << "\n";
			}
		}
	}
	else if (FStrEq(pcmd, "botclass"))
	{
		if ((arg1) && (*arg1) && (arg2) && (*arg2))
		{
			CBasePlayer *pPlayer = FindPlayerByName(arg1);

			if (!UTIL_IsValidPlayer(pPlayer, false, false))
			{
				cout << "Error, invalid bot\n";
				return;
			}

			// Is this player a bot?
			if (UTIL_IsBot(pPlayer))
			{
				CBot *pBot = UTIL_GetBotPointer(pPlayer);
				pBot->ChangeClass(arg2);
			}
		}
	}
	else if (FStrEq(pcmd, "botperso"))
	{
		if ((arg1) && (*arg1) && (arg2) && (*arg2))
		{
			CBasePlayer *pPlayer = FindPlayerByName(arg1);

			if (!UTIL_IsValidPlayer(pPlayer, false, false))
			{
				cout << "Error, invalid bot\n";
				return;
			}

			bot_personality_s *pPerso = BotManager.FindPersoByName(arg2);
			
			if (!pPerso)
			{
				cout << "Error: couldn't find personality \"" << arg2 << "\"\n";
				return;
			}

			// Is this player a bot?
			if (UTIL_IsBot(pPlayer))
			{
				CBot *pBot = UTIL_GetBotPointer(pPlayer);
				pBot->SetPerso(pPerso);
			}
		}
	}
	else if (FStrEq(pcmd, "botdbrole"))
	{
		if ((arg1) && (*arg1) && (arg2) && (*arg2))
		{
			CBasePlayer *pPlayer = FindPlayerByName(arg1);

			if (!UTIL_IsValidPlayer(pPlayer, false, false))
			{
				cout << "Error, invalid bot\n";
				return;
			}

			int iDBRole = atoi(arg2);
			if ((iDBRole >= 1) && (iDBRole <= 3))
			{
				// Is this player a bot?
				if (UTIL_IsBot(pPlayer))
				{
					CBot *pBot = UTIL_GetBotPointer(pPlayer);
					pBot->SetDBRole(EBotDBType(iDBRole-1));
				}
			}
		}
	}
	else if (FStrEq(pcmd, "botname"))
	{
		if ((arg1) && (*arg1) && (arg2) && (*arg2))
		{
			CBasePlayer *pPlayer = FindPlayerByName(arg1);

			if (!UTIL_IsValidPlayer(pPlayer, false, false))
			{
				cout << "Error, invalid bot\n";
				return;
			}

			// Is this player a bot?
			if (UTIL_IsBot(pPlayer))
			{
				char szNewName[33];
				strncpy(szNewName, arg2, 32);
				szNewName[32] = 0;

				char *infobuffer;
			    int clientIndex;
				infobuffer = g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() );
			    clientIndex = ENTINDEX( pPlayer->edict() ); 
				g_engfuncs.pfnSetClientKeyValue( clientIndex, infobuffer, "name", szNewName );
			}
		}
	}
	else if (FStrEq(pcmd, "botkicklast"))
		BotManager.KickLastBot(true);
	else if (FStrEq(pcmd, "botkickall"))
		BotManager.KickBots(-1); // -1 means 'kick all'
	else if (FStrEq(pcmd, "botkickallgood"))
		BotManager.KickBots(GOOD_TEAM);
	else if (FStrEq(pcmd, "botkickallevil"))
		BotManager.KickBots(EVIL_TEAM);
	else if (FStrEq(pcmd, "bot_menu"))
	{
		if (IS_DEDICATED_SERVER())
			NMenu::ExecuteMenuCommand(-1);
		else if (UTIL_IsValidPlayer(BotManager.GetHost(), false, false))
		{
			MESSAGE_BEGIN(MSG_ONE, gmsgVGUIMenu, NULL, BotManager.GetHost()->edict());
				WRITE_BYTE( 34 );			//show bot menu
			MESSAGE_END();
		}
	}
	else if (FStrEq(pcmd, "menuselect"))
	{
		if ((arg1 != NULL) && (*arg1 != 0))
			NMenu::ExecuteMenuCommand(atoi(arg1));
	}
	else if (FStrEq(pcmd, "flood"))
	{
		if ((arg1) && (*arg1))
		{
			if (FStrEq(arg1, "start"))
				WaypointFlooder.StartFlood();
			else if (FStrEq(arg1, "count"))
				cout << "Flood WP Count : " << WaypointFlooder.m_iFloodWPCount << "\n";
			else if (FStrEq(arg1, "connectioncount"))
			{
				if ((arg2) && (*arg2))
				{
					short Count = atoi(arg2);

					cout << "Nodes with " << Count << " connections: " <<
							WaypointFlooder.GetNodeCountWithnConnections(Count) << "\n";
				}
			}
			else if (FStrEq(arg1, "checkconnections"))
			{
				if (WaypointFlooder.ConnectionsAreValid())
					cout << "All connections are valid\n";
				else
					cout << "Some connection are NOT valid\n";
			}
		}
	}
	else // No bot command found
		BotManager.m_bFoundBotCommand = false;

	return;
}

void CBotManager::HandleBotDebugCommands()
{
	if (IS_DEDICATED_SERVER()) // Shouldn't be here in ded servers
	{
		m_bFoundBotCommand = false;
		return;
	}

#ifndef _DEBUG
	return; // No debug commands if not in debug mode...
#endif

	// Make some shortcuts...
	const char *pcmd = CMD_ARGV(0);
	const char *arg1 = CMD_ARGV(1);
	const char *arg2 = CMD_ARGV(2);
	const char *arg3 = CMD_ARGV(3);
	const char *arg4 = CMD_ARGV(4);
	const char *arg5 = CMD_ARGV(5);
	CBasePlayer *pHost = GetHost();

	if (IsNull(pHost))
		return;

	m_bFoundBotCommand = true;

	if (FStrEq(pcmd, "bot_tele"))
	{
		// Name specified?
		if ((arg1) && (*arg1))
		{
			CBasePlayer *pPlayer = FindPlayerByName(arg1);

			// Found a player with this name?
			if (pPlayer)
			{
				// Teleport him infront of us
				TelePortPlayerToPlayer(pHost->edict(), pPlayer->edict());
			}
		}
		else // else just take the first bot
		{
			CBasePlayer *pPlayer;
			short s;
			for (s=1;s<=gpGlobals->maxClients;s++)
			{
				pPlayer = (CBasePlayer *)UTIL_PlayerByIndex(s);
				if (UTIL_IsValidPlayer(pPlayer) && UTIL_IsBot(pPlayer))
				{
					TelePortPlayerToPlayer(pHost->edict(), pPlayer->edict());
					break;
				}
			}
		}
	}
#ifdef _DEBUG
	else if (FStrEq(pcmd, "displaybotstuff"))
	{
		DisplayBotStuff ^= 1;			  
		cout << "DisplayBotStuff is now: " << DisplayBotStuff << "\n";
	}
	else if (FStrEq(pcmd, "sbotdrainlaser"))
	{
		cout << "ALL superbots will use pl/ki drain laser\n";
		CreateTaskForEveryBot(TaskDrainEnts);
	}
	else if (FStrEq(pcmd, "sbothealthlaser"))
	{
		cout << "ALL superbots will use health drain laser\n";
		CreateTaskForEveryBot(TaskAbsorbHealth);
	}
	else if (FStrEq(pcmd, "botbeamjump"))
	{
		cout << "ALL bots will use beamjump\n";
		CreateTaskForEveryBot(TaskBeamJump);
	}
	else if (FStrEq(pcmd, "botkametorp"))
	{
		cout << "ALL bots will make kame torps\n";
		CreateTaskForEveryBot(TaskKameTorp);
	}
	else if (FStrEq(pcmd, "botswoop"))
	{
		EComboType CT = COMBO_TYPE_UP_SWOOP;
		if (arg1 && *arg1)
			CT = EComboType(atoi(arg1));

		CreateComboForEveryBot(CT);
	}
	else if (FStrEq(pcmd, "botchargegballswoop"))
	{
		cout << "ALL bots will make the charge gen ball combo\n";
		CreateComboForEveryBot(COMBO_TYPE_CHARGE_GBALL_SWOOP);
	}
	else if (FStrEq(pcmd, "testthrow"))
	{
		extern Vector GatherDBPosForTeamGood;
		Vector v_throw = DebugVecCheckThrow(pHost->pev, pHost->pev->origin, GatherDBPosForTeamGood, 0.5f, 1.0f);

		if (v_throw == g_vecZero)
			cout << "Zero vec\n";
		else
			UTIL_DrawBeam(pHost, pHost->pev->origin, pHost->pev->origin + v_throw * 64, 10, 1, 255, 0, 0, 250, 10, 20);
	}
	else if (FStrEq(pcmd, "setgoal"))
	{
		m_vBotGoal = pHost->pev->origin;
		CreateTaskForEveryBot(TaskHeadToGoal);
	}
	else if (FStrEq(pcmd, "drawbotgoals"))
		m_bDrawWaypointGoals = !m_bDrawWaypointGoals;
#endif
	else if (FStrEq(pcmd, "printent"))
	{
		if ((arg1) && (*arg1))
			UTIL_PrintEntity(INDEXENT(atoi(arg1)));
	}
	else if (FStrEq(pcmd, "logchatlists"))
		ChatClass.LogChatLists();
	else if (FStrEq(pcmd, "logoldchats"))
		ChatClass.LogPrevMessages();
	else if (FStrEq(pcmd, "printchatlists"))
		ChatClass.PrintChatSentences();
	else if (FStrEq(pcmd, "hpcheat"))
		BotManager.m_bHPCheat ^= 1;
	else if (FStrEq(pcmd, "dumpoldbots"))
	{
		cout << "Dumping old bots...\n";
		/*modified by harSens
		TLinkedList<kicked_bot_s*>::node_s *pNode = m_pKickedBots->GetFirst();
		*/
		node_s<kicked_bot_s*> *pNode = m_pKickedBots->GetFirst();
		while (pNode)
		{
			cout << pNode->Entry->szBotName << "\n";
			pNode = pNode->next;
		}
	}
	else if (FStrEq(pcmd, "getlastattack"))
	{
		CBaseEntity *pLastAttack = UTIL_GetLastAttackFromPlayer(pHost);
		if (pLastAttack)
			cout << "Your last attack : " << STRING(pLastAttack->pev->classname) << "\n";
		else
			cout << "Couldn't find attack\n";
	}
	else if (FStrEq(pcmd, "dumppersonalities"))
	{
		/*modified by harSens
		TLinkedList<bot_personality_s*>::node_s *pNode = m_BotPersonalities.GetFirst();
		*/
		node_s<bot_personality_s*> *pNode = m_BotPersonalities.GetFirst();
		for(;pNode;pNode=pNode->next)
			cout << pNode->Entry->perso_name << "\n";
	}
	else if (FStrEq(pcmd, "searchents"))
	{
		CBaseEntity *pEnt = NULL;
	
		if ((arg1) && (*arg1))
		{
			while ((pEnt = UTIL_FindEntityByClassname(pEnt, arg1)) != NULL)
			{
				cout << "Ent: " << STRING(pEnt->pev->classname) << "\n";
				UTIL_DrawBeam(GetHost(), GetHost()->pev->origin, pEnt->pev->origin, 10, 1, 255, 0,
							  0, 250, 10);
			}
		}
		else
		{
			while ((pEnt = UTIL_FindEntityInSphere(pEnt, pHost->pev->origin, 500.0f)) != NULL)
			{
				if (IsNull(pEnt))
					continue;

				cout << "Ent: " << STRING(pEnt->pev->classname) << "\n";
			}
		}
	}
	else if (FStrEq(pcmd, "dbspot"))
	{
		extern Vector GatherDBPosForTeamGood;
		extern Vector GatherDBPosForTeamEvil;

		UTIL_DrawBeam(pHost, pHost->pev->origin, GatherDBPosForTeamGood,
		              10, 10, 0, 0, 255, 250, 5);

		UTIL_DrawBeam(pHost, pHost->pev->origin, GatherDBPosForTeamEvil,
		              10, 10, 255, 0, 0, 250, 5);
	}
	else if (FStrEq(pcmd, "createdbspots"))
		BotDBManager.AssignDBGatherSpots();
	else if (FStrEq(pcmd, "dumpdbspots"))
	{
		extern db_spot_s GatherSpotsForTeamGood[MAX_CUSTOM_DB_GATHER_SPOTS];
		extern db_spot_s GatherSpotsForTeamEvil[MAX_CUSTOM_DB_GATHER_SPOTS];
		
		cout << "Team good :\n";
		int i;
		for(i=0;i<MAX_CUSTOM_DB_GATHER_SPOTS;i++)
			cout << i << "is " << ((GatherSpotsForTeamGood[i].Deleted) ? "deleted" : "in use") << "\n";

		cout << "\nTeam evil :\n";
		for(i=0;i<MAX_CUSTOM_DB_GATHER_SPOTS;i++)
			cout << i << "is " << ((GatherSpotsForTeamEvil[i].Deleted) ? "deleted" : "in use") << "\n";
	}
	else if (FStrEq(pcmd, "dumpunreachablegoals"))
	{
		if (arg1 && *arg1)
		{
			CBasePlayer *pPlayer = FindPlayerByName(arg1);
			if (UTIL_IsValidPlayer(pPlayer) && UTIL_IsBot(pPlayer))
			{
				CBot *pBot = UTIL_GetBotPointer(pPlayer);
				/*modified by harSens
				TLinkedList<unreachable_node_s>::node_s *pNode = pBot->m_UnreachableNodes.GetFirst();
				*/
				node_s<unreachable_node_s> *pNode = pBot->m_UnreachableNodes.GetFirst();
				while(pNode)
				{
					cout << "Time remaining : " << ((pNode->Entry.flUnreachableTime + 50.0f) - gpGlobals->time) << "\n";
					UTIL_DrawBeam(pHost, pHost->pev->origin, pNode->Entry.pNode->v_origin, 10, 2,
								  255, 0, 0, 250, 10, 50); 
					pNode = pNode->next;
				}
			}
		}
	}
	else if (FStrEq(pcmd, "triggerbotents"))
	{
		CBaseEntity *pEnt = NULL;
		while((pEnt = UTIL_FindEntityByClassname(pEnt, "info_bot")))
			pEnt->Use(NULL, NULL, USE_TOGGLE, 1.0f);
	}
	else if (FStrEq(pcmd, "dumpbotteaminfo"))
	{
		if (arg1 && *arg1)
		{
			CBasePlayer *pPlayer = FindPlayerByName(arg1);
			if (pPlayer && UTIL_IsBot(pPlayer))
			{
				CBot *pBot = UTIL_GetBotPointer(pPlayer);
				cout << "Team Nr: " << pBot->pev->team << "\n";
				cout << "Team Name: " << pBot->m_szTeamName << "\n";
				cout << "IsSpec: " << pBot->IsSpectator() << "\n";
				cout << "Is observer: " << pBot->m_fObserverFlag << "\n";
			}
		}
	}
	else if (FStrEq(pcmd, "dumbcrashtest"))
	{
		// Test the debugger.....
		int *p = NULL;
		*p = 5;
	}
	else if (FStrEq(pcmd, "spawnmonster"))
	{
		ALERT(at_console,"Creating buddy...\n");
        UTIL_MakeVectors(Vector(0,pHost->pev->v_angle.y,0));
		pHost->Create("player_buddy", pHost->pev->origin + gpGlobals->v_forward * 128 + gpGlobals->v_up * 28, pHost->pev->angles, pHost->edict());
    }
	else if (FStrEq(pcmd, "telemonster"))
	{
		CBaseEntity *pMonster = NULL;
		while((pMonster = UTIL_FindEntityByClassname(pMonster, "player_buddy")) != NULL)
			TelePortPlayerToPlayer(pHost->edict(), pMonster->edict());
	}
	else if (FStrEq(pcmd, "monstertele"))
	{
		CBaseEntity *pEnt = NULL;
		CBuddy *pBuddy = NULL;
		while((pEnt = UTIL_FindEntityByClassname(pEnt, "player_buddy")) != NULL)
		{
			pBuddy = (CBuddy *)pEnt;
			pBuddy->Teleport();
		}
	}
	else if (FStrEq(pcmd, "+monsterpowerup"))
	{
		CBaseEntity *pEnt = NULL;
		CBuddy *pBuddy = NULL;
		while((pEnt = UTIL_FindEntityByClassname(pEnt, "player_buddy")) != NULL)
		{
			pBuddy = (CBuddy *)pEnt;
			pBuddy->StartPowerUp();
		}
	}
	else if (FStrEq(pcmd, "-monsterpowerup"))
	{
		CBaseEntity *pEnt = NULL;
		CBuddy *pBuddy = NULL;
		while((pEnt = UTIL_FindEntityByClassname(pEnt, "player_buddy")) != NULL)
		{
			pBuddy = (CBuddy *)pEnt;
			pBuddy->StopPowerUp();
		}
	}
	else if (FStrEq(pcmd, "getbuddies"))
	{
		CBaseEntity *pEnt = NULL;
		while((pEnt = UTIL_FindEntityByClassname(pEnt, "player_buddy")) != NULL)
		{
			UTIL_DrawBeam(pHost, pHost->pev->origin, pEnt->pev->origin, 10, 1, 255, 255, 255,
						  250, 10);
		}
	}
	else if (FStrEq(pcmd, "botsmakebuddy"))
	{
		CBasePlayer *pPlayer;
		for(int i=1;i<=gpGlobals->maxClients;i++)
		{
			pPlayer = (CBasePlayer *)UTIL_PlayerByIndex(i);
			if (!UTIL_IsValidPlayer(pPlayer) || !UTIL_IsBot(pPlayer))
				continue;

	        UTIL_MakeVectors(Vector(0,pPlayer->pev->v_angle.y,0));
			pPlayer->Create("player_buddy", pPlayer->pev->origin + gpGlobals->v_forward * 128 + gpGlobals->v_up * 28, pPlayer->pev->angles, pPlayer->edict());
		}
	}
	else if (FStrEq(pcmd, "testvec"))
	{
		UTIL_MakeVectors(pHost->pev->angles);
		Vector v_test = pHost->pev->origin + gpGlobals->v_forward * 500.0f;
		cout << "Normal : x : " << v_test.x << " y : " << v_test.y << " z : " << v_test.z << "\n";
		v_test = v_test.Normalize();
		cout << "Normalize 1 : x : " << v_test.x << " y : " << v_test.y << " z : " << v_test.z << "\n";
		v_test = v_test.Normalize();
		cout << "Normalize 2 : x : " << v_test.x << " y : " << v_test.y << " z : " << v_test.z << "\n";
		v_test = v_test.Normalize();
		cout << "Normalize 3 : x : " << v_test.x << " y : " << v_test.y << " z : " << v_test.z << "\n";
	}
	else
		m_bFoundBotCommand = false;
}

// ==================================================================
// Code of CBotManager - End
// ==================================================================