/*

	Bot menu made by Rick

	TODO : Make localized strings?

*/

#include "hud.h"
#include "cl_util.h"
#include "parsemsg.h"
#include "const.h"
#include "entity_state.h"
#include "cl_entity.h"
#include "vgui_TeamFortressViewport.h"
#include "vgui_botmenu.h"
#include<vgui_helpers.h>
#include<vgui_listbox.h>
#include<vgui_textentry.h>
#include<vgui_focuschangesignal.h>

DECLARE_MESSAGE(m_BotVGUI, BotVGUI);

bot_info_s gBotInfo[32]; // Array containing bot info
char gszDefaultPerso[32]; // The default personality for the bots
bool gbIsDBMode = false;

// menu texts
char *sBotMenuNames[]=
{
	"Add Custom Bots",
	"Add Super Bots",
	"Manage Bots",
	"Advanced Options",
	"Kick Last Bot",
	"Show Bot Help"
};

char *sAddBotSkillMenuNames[] =
{
	"Best",
	"Good",
	"Medium",
	"Weak",
	"Bad",
	"Default",
	"Random"
};

char *sAddBotTeamMenuNames[] =
{
	"Good",
	"Evil",
	"Random"
};

char *sAddBotClassMenuNames[] =
{
	"Buu",
	"Goku",
	"Gohan",
	"Krillin",
	"Frieza",
	"Piccolo",
	"Trunks",
	"Vegeta",
	"Cell",
	"Random"
};

char *sAddBotDBTypeMenuNames[] =
{
	"Defender",
	"Collecter",
	"Attacker",
	"Auto Assign"
};

char *sSBotMenuNames[] =
{
	"Super Bot",
	"Mega Bot",
	"Ultimate Bot",
	"Random"
};

char *sAdvancedBotMenuNames[] =
{
	"Change Bot Skill",
	"Bot Agressiveness",
	"Bot Chat Settings",
	"Other Bot Settings",
	"Restore Bot Personalities"
};

char *sBotSkillMenuNames[] =
{
	"Best",
	"Good",
	"Medium",
	"Weak",
	"Bad",
	"Default"
};

char *sBotTeamMenuNames[] =
{
	"Good",
	"Evil"
};

char *sBotClassMenuNames[] =
{
	"Buu",
	"Goku",
	"Gohan",
	"Krillin",
	"Frieza",
	"Piccolo",
	"Trunks",
	"Vegeta",
	"Cell"
};

char *sBotDBTypeMenuNames[] =
{
	"Defender",
	"Collecter",
	"Attacker"
};

char *sBotAggressionLevelMenuNames[] =
{
	"Aggressive",
	"Normal",
	"Defensive"
};

char *sBotChatSettingsMenuNames[] =
{
	"Normal Chat Percent",
	"Chat Taunt Percent",
	"Chat Whine Percent",
	"Chat Swap Percent",
	"Chat Lower Percent",
	"Chat Drop Percent",
	"Chat Tag Percent"
};

char *sBotPercentageMenuNames[] =
{
	"Melee Percent",
	"Teleport Percent",
	"Swoop Percent",
	"Fly Percent",
	"Block Percent",
	"Melee Throw Percent",
	"Simple Melee Percent",
	"Super Bot Laser Percent"
};

char *sKickBotsMenuNames[] =
{
	"Bots On Good Team",
	"Bots On Evil Team",
	"All Bots"
};

char *sBotSkillMenuCommands[] =
{
	"botskill 1",
	"botskill 2",
	"botskill 3",
	"botskill 4",
	"botskill 5",
	"botskill 2"
};

char *sBotAggressionLevelMenuCommands[] =
{
	"bot_aggression_level aggressive",
	"bot_aggression_level normal",
	"bot_aggression_level defensive"
};

char *sKickBotsMenuCommands[] =
{
	"botkickallgood",
	"botkickallevil",
	"botkickall"
};

char *sBotSettingsMenuCommands[] =
{
	"bot_melee_percent",
	"bot_teleport_percent",
	"bot_swoop_percent",
	"bot_fly_percent",
	"bot_block_percent",
	"bot_meleethrow_percent",
	"bot_simplemelee_percent",
	"sbot_laser_percent"
};

char *sBotChatSettingsMenuCommands[] =
{
	"bot_chat_percent",
	"bot_whine_percent",
	"bot_taunt_percent",
	"bot_chat_swap_percent",
	"bot_chat_lower_percent",
	"bot_chat_drop_percent",
	"bot_chat_tag_percent"
};


struct AdvancedBotOptionsMenuItem
{
	const char *szCVAR;
	const char *szName;
};

AdvancedBotOptionsMenuItem AdvancedBotOptionsMenuItems[] =
{
	{"sv_botsshoot", "Bots Shoot"},
	{"sv_botssearchenemies", "Bots Search Enemies"},
	{"sv_observebots", "Observer Mode"},
	{"sv_idlebots", "Bots are Idle"},
	{"sv_botsusediscs", "Bots Use Discs"},
	{"sv_botsmove", "Bots Move"},
	{"sv_botschat", "Bots Chat"},
	{"sv_botsbalanceteams", "Bots Balance Teams"}
};

// Bot Setting Listbox

void CBotSettingListBox::CListBoxLabel::paintBackground()
{
	Color oldBg;
	getBgColor(oldBg);

	if (m_pOwner->m_pSelectedRow && (m_pOwner->m_pSelectedRow->iRow == m_iRow))
	{
		setBgColor(134, 91, 19, 0);
	}

	Label::paintBackground();

	setBgColor(oldBg);
}
		
void CBotSettingListBox::CListBoxLabel::paint()
{
	Color oldFg;
	getFgColor(oldFg);

	if (m_pOwner->m_pSelectedRow && (m_pOwner->m_pSelectedRow->iRow == m_iRow))
	{
		setFgColor(255, 255, 255, 0);
	}

	Label::paint();
	
	setFgColor(oldFg[0], oldFg[1], oldFg[2], oldFg[3]);
}

CBotSettingListBox::CBotSettingListBox()  : m_pOwner(NULL), m_iRows(0), m_pMouseRow(NULL),
											m_pSelectedRow(NULL), m_iWidth(0),
											m_pCurrentHighlightLabel(NULL),
											m_pFirstSettingEntry(NULL), m_pLastSettingEntry(NULL)
{
	m_SettingList.setBgColor(0,0,0,255);
	m_SettingList.setBorder( new LineBorder( Color(200, 200, 200, 150) ) );
	// set scrollbar range
	m_SettingList.SetScrollRange(0);
}

CBotSettingListBox::CBotSettingListBox(int x, int y, int wide, int tall, Panel *pOwner) : m_pOwner(pOwner), m_iRows(0), m_iWidth(wide)
{
	m_pCurrentHighlightLabel = NULL;

	m_pFirstSettingEntry = m_pLastSettingEntry = NULL;

	m_SettingList.setBounds(x, y, wide, tall);
	m_SettingList.setBgColor(0,0,0,255);
	m_SettingList.setParent(m_pOwner);
	m_SettingList.setBorder( new LineBorder( Color(200, 200, 200, 150) ) );

	m_pMouseRow = m_pSelectedRow = NULL;

	// set scrollbar range
	m_SettingList.SetScrollRange(m_iRows);
}

void CBotSettingListBox::mousePressed(MouseCode code, Panel* panel)
{
	if(gHUD.m_iIntermission)
		return;

	if (m_pMouseRow)
	{
		m_pSelectedRow = m_pMouseRow;
	}
}

void CBotSettingListBox::cursorMoved(int x, int y, Panel *panel)
{
	if (!m_pFirstSettingEntry)
		return;

	setting_entry_s *pNode = m_pFirstSettingEntry;
	// look for which cell the mouse is currently over
	while(pNode)
	{
		if (pNode->SettingGrid.isWithin(x, y))
		{
			MouseOverCell(pNode);
			return;
		}
		pNode = pNode->next;
	}
}

void CBotSettingListBox::MouseOverCell(setting_entry_s *pEntry)
{
	CListBoxLabel *label = &pEntry->SettingLabel;

	// clear the previously highlighted label
	if (m_pCurrentHighlightLabel != label)
	{
		m_pCurrentHighlightLabel = NULL;
		m_pMouseRow = NULL;
	}

	if (!label)
		return;

	// setup the new highlight
	m_pCurrentHighlightLabel = label;
	m_pMouseRow = pEntry;
}

void CBotSettingListBox::Update()
{
	if (m_pSelectedRow && (m_pSelectedRow->iRow >= m_iRows))
		m_pSelectedRow = NULL;

	// update highlight position
	int x, y;
	m_pOwner->getApp()->getCursorPos(x, y);
	cursorMoved(x, y, m_pOwner);
}

void CBotSettingListBox::AddEntry(const char *szText)
{
	int rowheight = 20;
	if (ScreenHeight >= 480)
		rowheight = YRES(rowheight);
	
	setting_entry_s *pEntry = new setting_entry_s;

	pEntry->szListText = szText;
	pEntry->SettingGrid.SetDimensions(1, 1);

	pEntry->SettingLabel.setContentFitted(false);
	pEntry->SettingLabel.addInputSignal(this);
	pEntry->SettingLabel.SetRow(m_iRows);
	pEntry->SettingLabel.SetOwner(this);
	pEntry->SettingLabel.setBgColor(0, 0, 0, 255);
	pEntry->SettingLabel.setFgColor(200, 200, 200, 150);
	pEntry->SettingLabel.setSize(pEntry->SettingLabel.getWide(), rowheight);
	pEntry->SettingLabel.setContentAlignment( vgui::Label::a_center );
	pEntry->SettingLabel.setText(szText);

	pEntry->SettingGrid.SetEntry(0, 0, &pEntry->SettingLabel);

	pEntry->SettingGrid.setBgColor(0,0,0,255);
	pEntry->SettingGrid.SetSpacing(0, 0);
	pEntry->SettingGrid.SetColumnWidth(0, m_iWidth);
	pEntry->SettingGrid.AutoSetRowHeights();
	pEntry->SettingGrid.setSize(PanelWidth(&pEntry->SettingGrid), rowheight);
	pEntry->SettingGrid.RepositionContents();

	pEntry->iRow = m_iRows;

	m_SettingList.AddItem(&pEntry->SettingGrid);

	if (!m_pFirstSettingEntry)
	{
		m_pFirstSettingEntry = m_pLastSettingEntry = pEntry;
	}
	else
	{
		m_pLastSettingEntry->next = pEntry;
		m_pLastSettingEntry = m_pLastSettingEntry->next;
	}

	pEntry = m_pFirstSettingEntry;
	while(pEntry)
	{
		CGrid *pGridRow = &pEntry->SettingGrid;

		pGridRow->AutoSetRowHeights();
		//pGridRow->setSize(PanelWidth(pGridRow), pGridRow->CalcDrawHeight());
		pGridRow->setSize(PanelWidth(pGridRow), rowheight);
		pGridRow->RepositionContents();

		pEntry = pEntry->next;
	}

	// hack, for the thing to resize
	int x, y;
	m_SettingList.getSize(x, y);
	m_SettingList.setSize(x, y);

	m_iRows++;

	// set scrollbar range
	m_SettingList.SetScrollRange(m_iRows);
}

const char *CBotSettingListBox::GetRandomSelection()
{
	int iRow = gEngfuncs.pfnRandomFloat(0, m_iRows-1);

	setting_entry_s *pNode = m_pFirstSettingEntry;
	while(pNode)
	{
		if (pNode->iRow == iRow)
			return pNode->szListText;
		pNode = pNode->next;
	}
	return NULL;
}

void CBotSettingListBox::ClearAll()
{
	while(m_pFirstSettingEntry)
	{
		setting_entry_s *pEntry = m_pFirstSettingEntry;
		m_pFirstSettingEntry = m_pFirstSettingEntry->next;
		delete pEntry;
	}
	m_pFirstSettingEntry = NULL;
}

void CBotSettingListBox::SetCurrentSelection(int Sel)
{
	setting_entry_s *pEntry = m_pFirstSettingEntry;
	while(pEntry)
	{
		if (pEntry->iRow == Sel)
		{
			m_pSelectedRow = pEntry;
			m_SettingList.SetScrollVal(Sel);
			break;
		}
		pEntry = pEntry->next;
	}
}

void CBotSettingListBox::SetCurrentSelection(const char *szName)
{
	setting_entry_s *pEntry = m_pFirstSettingEntry;
	while(pEntry)
	{
		if (!strcmp(pEntry->szListText, szName))
		{
			m_pSelectedRow = pEntry;
			m_SettingList.SetScrollVal(pEntry->iRow);
			break;
		}
		pEntry = pEntry->next;
	}
}

CBotSettingListBox::~CBotSettingListBox()
{
	while(m_pFirstSettingEntry)
	{
		setting_entry_s *pEntry = m_pFirstSettingEntry;
		m_pFirstSettingEntry = m_pFirstSettingEntry->next;
		delete pEntry;
	}
	m_pFirstSettingEntry = NULL;
}

// Bot Setting Listbox end

// Bot text entry

bool CBotTextEntry::CanAddChar()
{
	if ((_parent) && (_parent->isVisible() == false))
		return false; // dont insert the char when not active

	if ((m_iMaxChars > -1) && (_lineDar.getCount() >= m_iMaxChars))
		return false;

//	if (!m_bActive)
//		return false;

	return true;
}

void CBotTextEntry::doInsertChar(char ch)
{
	if (CanAddChar())
		TextEntry::doInsertChar(ch);
}

// Bot text entry end

// Base Bot Menu
void CBaseBotMenu::MakeExitButton(int x, int y, int wide, int tall)
{
	m_pExitButton = new CommandButton( "Exit", x, y, wide, tall);
	m_pExitButton->setContentAlignment(vgui::Label::a_center);
	m_pExitButton->setParent( m_pPanel );
	m_pExitButton->addActionSignal( new CCloseAllMenus );
}

void CBaseBotMenu::MakeBackToMainButton(int x, int y, int wide, int tall)
{
	m_pGoBackButton = new CommandButton( "<< Previous Menu", x, y, wide, tall);
	m_pGoBackButton->setContentAlignment(vgui::Label::a_center);
	m_pGoBackButton->setParent( m_pPanel );
	m_pGoBackButton->addActionSignal( new CGoToPrevMenuHandler(this) );
}

void CBaseBotMenu::MakeCancelButton(int x, int y, int wide, int tall)
{
	CommandButton *pButton = new CommandButton( "Cancel", x, y, wide, tall);
	pButton->setContentAlignment(vgui::Label::a_center);
	pButton->setParent( m_pPanel );
	pButton->addActionSignal( new CGoToPrevMenuHandler(this) );
}

void CBaseBotMenu::MakeBackAndExitButtons(int y, int PanelWidth)
{
	// Calculate starting x for 'Back To Main Menu' button
	int x = (PanelWidth - ((2 * BACKEXIT_BUTTONS_WIDTH) + (2 * BUTTON_WIDTH_SPACE))) / 2;
	MakeBackToMainButton(x, y, BACKEXIT_BUTTONS_WIDTH, BUTTON_HEIGHT);

	// Calculate x for Exit button
	x += (BACKEXIT_BUTTONS_WIDTH + (2 * BUTTON_WIDTH_SPACE));
	MakeExitButton(x, y, BACKEXIT_BUTTONS_WIDTH, BUTTON_HEIGHT);
}

void CBaseBotMenu::MakeIncreaseButton(int x, int y, int *pVar, int iDefault, int Min, int Max, Label *pLabel, const char *szHeadText, char **szValTexts, bool bTeamOnly)
{
	CommandButton *pButton;

	if (bTeamOnly)
		pButton = new CBotTeamButton("+", x, y, INCDECBUTTON_WIDTH, INCDECBUTTON_HEIGHT);
	else
		pButton = new CommandButton("+", x, y, INCDECBUTTON_WIDTH, INCDECBUTTON_HEIGHT);

	pButton->setContentAlignment(vgui::Label::a_center);
	pButton->setParent( m_pPanel );
	pButton->addActionSignal( new CIncreaseIntMenuHandler(pVar, iDefault, Min, Max, pLabel, szHeadText, szValTexts) );	
}

void CBaseBotMenu::MakeDecreaseButton(int x, int y, int *pVar, int iDefault, int Min, int Max, Label *pLabel, const char *szHeadText, char **szValTexts, bool bTeamOnly)
{
	CommandButton *pButton;

	if (bTeamOnly)
		pButton = new CBotTeamButton("-", x, y, INCDECBUTTON_WIDTH, INCDECBUTTON_HEIGHT);
	else
		pButton = new CommandButton("-", x, y, INCDECBUTTON_WIDTH, INCDECBUTTON_HEIGHT);

	pButton->setContentAlignment(vgui::Label::a_center);
	pButton->setParent( m_pPanel );
	pButton->addActionSignal( new CDecreaseIntMenuHandler(pVar, iDefault, Min, Max, pLabel, szHeadText, szValTexts) );	
}

Label *CBaseBotMenu::MakeTitle(const char *szText, int x, int y, int wide, int tall)
{
	Label *pLabel = new Label( "", x, y, wide, tall);
	pLabel->setParent( m_pPanel );
	pLabel->setBgColor( 200, 0, 0, 150 );
	pLabel->setFgColor( 200, 200, 200, 150 );
	pLabel->setContentAlignment( vgui::Label::a_center );
	pLabel->setText( szText );
	return pLabel;
}

Label *CBaseBotMenu::MakeLabel(const char *szText, int x, int y, int wide, int tall,
							   vgui::Label::Alignment Al, int r, int g, int b, int a)
{
	Label *pLabel = new Label( "", x, y, wide, tall);
	pLabel->setParent( m_pPanel );
	pLabel->setBgColor( 0, 0, 0, 255 );
	pLabel->setFgColor( r, g, b, a );
	pLabel->setContentAlignment( Al );
	pLabel->setText( szText );
	return pLabel;
}

Label *CBaseBotMenu::MakeIncDecLabel(const char *szText, int x, int y)
{
	Label *pLabel = new Label( "", x, y, INCDECLABEL_WIDTH, INCDECLABEL_HEIGHT);
	pLabel->setParent( m_pPanel );
	pLabel->setBgColor( 0, 0, 0, 255 );
	pLabel->setFgColor( 200, 200, 200, 150 );
	pLabel->setContentAlignment( vgui::Label::a_west );
	pLabel->setText( szText );
	return pLabel;
}

void CBaseBotMenu::MakeSettingScrollBar(int x, int y, Label *&pLabel, ScrollBar2 *&pScrollBar,
										const char *szTitle, const char *szCommand)
{
	// Make label above scrollbar
	Label *pTempLabel = new Label( "", x, y, BOTSLIDER_WIDTH, YRES(20));
	pTempLabel->setParent( m_pPanel );
	pTempLabel->setBgColor( 0, 0, 0, 255 );
	pTempLabel->setFgColor( 255, 255, 0, 150 );
	pTempLabel->setContentAlignment( vgui::Label::a_center );
	pTempLabel->setText( szTitle );

	y += YRES(20);

	// Make the scrollbar
    pScrollBar = new ScrollBar2(0,0,0,0,false);
	Slider2 *pSlider = new Slider2(0,0,10,10,false);

	pSlider->setRangeWindow(10);
	pSlider->setRangeWindowEnabled(true);
	
	pScrollBar->setPos(x, y);
	pScrollBar->setSize(BOTSLIDER_WIDTH, BOTSLIDER_HEIGHT);
	pScrollBar->setSlider(pSlider);
	pScrollBar->setParent(this);
	pScrollBar->setRange(0, 100);
	pScrollBar->setFgColor(200, 200 ,200, 150);
	pScrollBar->setBgColor(0, 0, 0, 255);
	pScrollBar->setButtonPressedScrollValue(5);

	y += YRES(10);

	// Make a label that will tell what the current value of the scrollbar is
	pLabel = new Label( "", x + (BOTSLIDER_WIDTH/2), y, BOTSLIDER_WIDTH, YRES(20));
	pLabel->setParent( m_pPanel );
	pLabel->setBgColor( 0, 0, 0, 255 );
	pLabel->setFgColor( 200, 200, 200, 150 );
	pLabel->setContentAlignment( vgui::Label::a_west );
	pLabel->setText( "0" );

	// Make an apply button, when pressed the button will execute szCommand with the scrollvalue
	// as a parameter
	x += BOTSLIDER_WIDTH + XRES(10);
	y -= YRES(18);
	CommandButton *pButton = new CommandButton("Apply", x, y, APPLYBUTTON_WIDTH, BUTTON_HEIGHT);
	pButton->addActionSignal( new CBotSettingApplyButtonHandler( szCommand, pScrollBar ));
	pButton->setContentAlignment(vgui::Label::a_center);
	pButton->setParent( m_pPanel );
}

void CBaseBotMenu::paintBackground()
{
	drawSetColor(Scheme::sc_primary3);
	drawFilledRect(0,0,_size[0],_size[1]);
}

// Base botmenu end


// Main bot menu
CBotMenuPanel::CBotMenuPanel(void) : CBaseBotMenu(false, MAINBOTMENU_HEIGHT)
{	
	int iButtonHeight = BUTTON_HEIGHT;
	int iButtonWidth = BOTMENU_WIDTH - BUTTON_WIDTH_SPACE * 2 - 2;
	int iButtonx = BUTTON_WIDTH_SPACE;
	
	m_pPanel = new CTransparentPanel( PANEL_TRANS, 0, 0, BOTMENU_WIDTH, MAINBOTMENU_HEIGHT);
	m_pPanel->setParent( this );
	m_pPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
	
	MakeTitle("ESF Bot Menu", 0, 0, BOTMENU_WIDTH-2, iButtonHeight);

	// Create Sub Menus
	m_pSubMenus[0] = new CAddBotMenuPanel;
	m_pSubMenus[1] = new CAddSuperBotMenuPanel;
	m_pSubMenus[2] = new CBotManager;//new CKickBotsMenuPanel;
	m_pSubMenus[3] = new CAdvancedBotOptionsMenuPanel;

	int iButtony = 0;
	for (int n=0; n<MAINBOTMENU_BUTTONS;n++)
	{	
		iButtony += iButtonHeight + BUTTON_HEIGHT_SPACE;

		switch (n)
		{
		case 0: // Add customized bot
			m_pBotButton[n] = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString(sBotMenuNames[n]), iButtonx, iButtony, iButtonWidth, iButtonHeight);
			m_pBotButton[n]->addActionSignal( new CBotMenuHandler(this, m_pSubMenus[0]) );
			break;
		case 1: // Super bot menu
			m_pBotButton[n] = new CBotTeamButton( gHUD.m_TextMessage.BufferedLocaliseTextString(sBotMenuNames[n]), iButtonx, iButtony, iButtonWidth, iButtonHeight);
			m_pBotButton[n]->addActionSignal( new CBotMenuHandler(this, m_pSubMenus[1]) );
			break;
		case 2: // Manage bots menu
			m_pBotButton[n] = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString(sBotMenuNames[n]), iButtonx, iButtony, iButtonWidth, iButtonHeight);
			m_pBotButton[n]->addActionSignal( new CBotMenuHandler(this, m_pSubMenus[2]) );
			break;
		case 3: // Advanced menu
			m_pBotButton[n] = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString(sBotMenuNames[n]), iButtonx, iButtony, iButtonWidth, iButtonHeight);
			m_pBotButton[n]->addActionSignal( new CBotMenuHandler(this, m_pSubMenus[3]) );
			break;
		case 4: // kick last bot
			m_pBotButton[n] = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString(sBotMenuNames[n]), iButtonx, iButtony, iButtonWidth, iButtonHeight);
			m_pBotButton[n]->addActionSignal( new CExecuteBotCommandMenuHandler("botkicklast") );
			break;
		case 5: // show bot help
			m_pBotButton[n] = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString(sBotMenuNames[n]), iButtonx, iButtony, iButtonWidth, iButtonHeight);
			m_pBotButton[n]->addActionSignal( new CExecuteBotCommandMenuHandler("bot_help") );
			break;
		}

		m_pBotButton[n]->setContentAlignment(vgui::Label::a_center);
		m_pBotButton[n]->setParent( m_pPanel );
	}
	
	iButtony += (iButtonHeight * 2) + BUTTON_HEIGHT_SPACE;
	MakeExitButton(iButtonx, iButtony, iButtonWidth, iButtonHeight);
}

void CBotMenuPanel::DeInit()
{
	for(short s=0;s<MAINBOTMENU_SUBMENUS;s++)
		m_pSubMenus[s]->DeInit();
}

// Add a customized bot menu
CAddBotMenuPanel :: CAddBotMenuPanel() : CBaseBotMenu(false, ADDBOTMENU_WIDTH, ADDBOTMENU_HEIGHT),
										 m_iBotCount(1)
{	int iButtonHeight = BUTTON_HEIGHT;
	int iButtonWidth = XRES(120);
	int iButtonx = BUTTON_WIDTH_SPACE + XRES(20);
	
	m_pPanel = new CTransparentPanel( PANEL_TRANS, 0, 0, ADDBOTMENU_WIDTH, ADDBOTMENU_HEIGHT);
	m_pPanel->setParent( this );
	m_pPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
	
	MakeTitle("Add Custom Bots", 0, 0, ADDBOTMENU_WIDTH-2, iButtonHeight);

	int wide = XRES(90), height = YRES(85), i;
	
	// Create skill select listbox
	int x = XRES(10), y = YRES(30);
	MakeLabel("Bot Skill", x, y, wide, YRES(20), vgui::Label::a_center);
	m_SkillListBox.setBounds(x, y + YRES(25), wide, height);
	m_SkillListBox.setParent(this);
	for(i=0;i<7;i++)
		m_SkillListBox.AddEntry(sAddBotSkillMenuNames[i]);
	m_SkillListBox.SetCurrentSelection(5);

	// Create class select listbox
	x += wide + XRES(30);
	MakeLabel("Bot Class", x, y, wide, YRES(20), vgui::Label::a_center);
	m_ClassListBox.setBounds(x, y + YRES(25), wide, height);
	m_ClassListBox.setParent(this);
	for(i=0;i<10;i++)
		m_ClassListBox.AddEntry(sAddBotClassMenuNames[i]);
	m_ClassListBox.SetCurrentSelection(9);

	// Create team select listbox
	x += wide + XRES(30);
	m_pTeamLabel = MakeLabel("Bot Team", x, y, wide, YRES(20), vgui::Label::a_center);
	m_TeamListBox.setBounds(x, y + YRES(25), wide, height);
	m_TeamListBox.setParent(this);
	for(i=0;i<3;i++)
		m_TeamListBox.AddEntry(sAddBotTeamMenuNames[i]);
	m_TeamListBox.SetCurrentSelection(2);

	// Create db type select listbox
	x += wide + XRES(30);
	m_pDBTypeLabel = MakeLabel("Bot DB Role", x, y, wide, YRES(20), vgui::Label::a_center);
	m_DBTypeListBox.setBounds(x, y + YRES(25), wide, height);
	m_DBTypeListBox.setParent(this);
	for(i=0;i<4;i++)
		m_DBTypeListBox.AddEntry(sAddBotDBTypeMenuNames[i]);
	m_DBTypeListBox.SetCurrentSelection(3);

	// Create name text field
	x = XRES(10);
	y += height + YRES(50);
	MakeLabel("Bot Name", x, y, XRES(80));
	MakeLabel("(Leave blank for random)", x, y + YRES(20), XRES(150));
	y += YRES(40);
	m_pBotTextEntry = new CBotTextEntry("",x,y + YRES(5), XRES(325), YRES(15));
	m_pBotTextEntry->setParent(this);
	m_pBotTextEntry->setBgColor(0, 0, 0, 255);
	m_pBotTextEntry->setFgColor(100, 100, 100, 150);
	m_pBotTextEntry->SetMaxChars(32);

	// Create num bots counter
	x += XRES(350);
	Label *pLabel = MakeIncDecLabel( "Bot Count : 1", x, y);
	x += XRES(100);
	MakeIncreaseButton(x, y, &m_iBotCount, 1, 1, 31, pLabel, "Bot Count :");
	MakeDecreaseButton(x, y + iButtonHeight + BUTTON_HEIGHT_SPACE, &m_iBotCount, 1, 1, 31, pLabel, "Bot Count :");

	// Create perso select listbox
	x = XRES(10);
	y += YRES(30);
	wide = XRES(325);
	MakeLabel("Bot Personality", x, y, wide, YRES(20), vgui::Label::a_center);
	y += YRES(25);
	m_PersoListBox.setBounds(x, y, wide, height);
	m_PersoListBox.setParent(this);
	m_PersoListBox.AddEntry("Random Personality");
	m_PersoListBox.SetCurrentSelection(0);

	x = ADDBOTMENU_WIDTH - (iButtonWidth + BUTTON_WIDTH_SPACE);
	CommandButton *pButton = new CommandButton( "Add Bot(s)", x, y, iButtonWidth, iButtonHeight);
	pButton->setContentAlignment(vgui::Label::a_center);
	pButton->setParent( m_pPanel );
	pButton->addActionSignal( new CAddBotMenuHandler(this) );

	y += iButtonHeight + BUTTON_HEIGHT_SPACE;
	MakeBackToMainButton(x, y, iButtonWidth, iButtonHeight);
	y += iButtonHeight + BUTTON_HEIGHT_SPACE;
	MakeExitButton(x, y, iButtonWidth, iButtonHeight);
}

void CAddBotMenuPanel::DeInit()
{
	m_SkillListBox.ClearAll();
	m_ClassListBox.ClearAll();
	m_TeamListBox.ClearAll();
	m_DBTypeListBox.ClearAll();
	m_PersoListBox.ClearAll();
}

void CAddBotMenuPanel::paintBackground()
{
	CBaseBotMenu::paintBackground();
	m_SkillListBox.Update();
	m_TeamListBox.Update();
	m_ClassListBox.Update();
	m_DBTypeListBox.Update();
	m_PersoListBox.Update();
}

void CAddBotMenuPanel::Open()
{
	m_TeamListBox.SetVisible((gHUD.m_Teamplay != 0));
	m_pTeamLabel->setVisible((gHUD.m_Teamplay != 0));
	m_DBTypeListBox.SetVisible(gbIsDBMode);
	m_pDBTypeLabel->setVisible(gbIsDBMode);

	CBotSettingListBox::setting_entry_s *pListBoxEntry = m_PersoListBox.m_pFirstSettingEntry;

	// Check if we have to add the default personality
	if (gszDefaultPerso[0])
	{
		bool IsIn = false;
		while(pListBoxEntry)
		{
			if (!strcmp(pListBoxEntry->szListText, "Default Personality"))
			{
				IsIn = true;
				break;
			}
			pListBoxEntry = pListBoxEntry->next;
		}

		if (!IsIn)
			m_PersoListBox.AddEntry("Default Personality");
	}

	// Check if we have to add new personalities
	CBotVGUI::bot_perso_list_s *pPersoEntry = gHUD.m_BotVGUI.m_pBotPersonalityNames;
	while(pPersoEntry)
	{
		pListBoxEntry = m_PersoListBox.m_pFirstSettingEntry;
		bool IsIn = false;

		while(pListBoxEntry)
		{
			if (!strcmp(pPersoEntry->szBotPersoName, pListBoxEntry->szListText))
			{
				IsIn = true;
				break;
			}
			pListBoxEntry = pListBoxEntry->next;
		}

		if (!IsIn)
			m_PersoListBox.AddEntry(pPersoEntry->szBotPersoName);

		pPersoEntry = pPersoEntry->next;
	}

	CBaseBotMenu::Open();
}

// add bot menu end

// Add a super bot menu
CAddSuperBotMenuPanel :: CAddSuperBotMenuPanel() : CBaseBotMenu(false, ADDSBOTMENU_WIDTH, ADDSBOTMENU_HEIGHT),
										           m_iSBotCount(1)
{	int iButtonHeight = BUTTON_HEIGHT;
	int iButtonWidth = XRES(120);
	int iButtonx = BUTTON_WIDTH_SPACE + XRES(20);
	
	m_pPanel = new CTransparentPanel( PANEL_TRANS, 0, 0, ADDSBOTMENU_WIDTH, ADDSBOTMENU_HEIGHT);
	m_pPanel->setParent( this );
	m_pPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
	
	MakeTitle("Add Super Bots", 0, 0, ADDSBOTMENU_WIDTH-2, iButtonHeight);

	int wide = XRES(100), height = YRES(85), i;
	
	// Create super bot type select listbox
	int x = XRES(10), y = YRES(30);
	MakeLabel("Super Bot Type", x, y, wide, YRES(20), vgui::Label::a_center);
	m_SBotTypeListBox.setBounds(x, y + YRES(25), wide, height);
	m_SBotTypeListBox.setParent(this);
	for(i=0;i<4;i++)
		m_SBotTypeListBox.AddEntry(sSBotMenuNames[i]);
	m_SBotTypeListBox.SetCurrentSelection(0);

	// Create class select listbox
	x += wide + XRES(40);
	MakeLabel("Bot Class", x, y, wide, YRES(20), vgui::Label::a_center);
	m_ClassListBox.setBounds(x, y + YRES(25), wide, height);
	m_ClassListBox.setParent(this);
	for(i=0;i<10;i++)
		m_ClassListBox.AddEntry(sAddBotClassMenuNames[i]);
	m_ClassListBox.SetCurrentSelection(9);

	// Create class select listbox
	x += wide + XRES(40);
	m_pDBRoleLabel = MakeLabel("Bot DB Type", x, y, wide, YRES(20), vgui::Label::a_center);
	m_DBRoleListBox.setBounds(x, y + YRES(25), wide, height);
	m_DBRoleListBox.setParent(this);
	for(i=0;i<4;i++)
		m_DBRoleListBox.AddEntry(sAddBotDBTypeMenuNames[i]);
	m_DBRoleListBox.SetCurrentSelection(3);

	// Create name text field
	x = XRES(10);
	y += height + YRES(50);
	MakeLabel("Bot Name", x, y, XRES(80));
	MakeLabel("(Leave blank for random)", x, y + YRES(20), XRES(150));
	y += YRES(40);
	m_pBotTextEntry = new CBotTextEntry("",x,y + YRES(5), XRES(300), YRES(15));
	m_pBotTextEntry->setParent(this);
	m_pBotTextEntry->setBgColor(0, 0, 0, 255);
	m_pBotTextEntry->setFgColor(100, 100, 100, 150);
	m_pBotTextEntry->SetMaxChars(26);

	// Create bot counter
	x += XRES(320);
	Label *pLabel = MakeIncDecLabel( "Bot Count : 1", x, y);
	x += XRES(100);
	MakeIncreaseButton(x, y, &m_iSBotCount, 1, 1, 31, pLabel, "Bot Count :");
	MakeDecreaseButton(x, y + iButtonHeight + BUTTON_HEIGHT_SPACE, &m_iSBotCount, 1, 1, 31, pLabel, "Bot Count :");

	// Create perso select listbox
	x = XRES(10);
	y += YRES(50);
	wide = XRES(325);
	MakeLabel("Bot Personality", x, y, wide, YRES(20), vgui::Label::a_center);
	y += YRES(25);
	m_PersoListBox.setBounds(x, y, wide, height);
	m_PersoListBox.setParent(this);

	x = ADDSBOTMENU_WIDTH - (iButtonWidth + BUTTON_WIDTH_SPACE);
	CommandButton *pButton = new CommandButton( "Add Super Bot(s)", x, y, iButtonWidth, iButtonHeight);
	pButton->setContentAlignment(vgui::Label::a_center);
	pButton->setParent( m_pPanel );
	pButton->addActionSignal( new CAddSuperBotMenuHandler(this) );
	y += iButtonHeight + BUTTON_HEIGHT_SPACE;
	MakeBackToMainButton(x, y, iButtonWidth, iButtonHeight);
	y += iButtonHeight + BUTTON_HEIGHT_SPACE;
	MakeExitButton(x, y, iButtonWidth, iButtonHeight);
}

void CAddSuperBotMenuPanel::DeInit()
{
	m_SBotTypeListBox.ClearAll();
	m_ClassListBox.ClearAll();
	m_PersoListBox.ClearAll();
	m_DBRoleListBox.ClearAll();
}

void CAddSuperBotMenuPanel::paintBackground()
{
	CBaseBotMenu::paintBackground();
	m_SBotTypeListBox.Update();
	m_ClassListBox.Update();
	m_PersoListBox.Update();
	m_DBRoleListBox.Update();
}

void CAddSuperBotMenuPanel::Open()
{
	m_DBRoleListBox.SetVisible(gbIsDBMode);
	m_pDBRoleLabel->setVisible(gbIsDBMode);

	CBotSettingListBox::setting_entry_s *pListBoxEntry = m_PersoListBox.m_pFirstSettingEntry;
	// Check if we have to add the default personality
	if (gszDefaultPerso[0])
	{
		bool IsIn = false;
		while(pListBoxEntry)
		{
			if (!strcmp(pListBoxEntry->szListText, "Default Personality"))
			{
				IsIn = true;
				break;
			}
			pListBoxEntry = pListBoxEntry->next;
		}

		if (!IsIn)
			m_PersoListBox.AddEntry("Default Personality");
	}

	// Check if we have to add new personalities
	CBotVGUI::bot_perso_list_s *pPersoEntry = gHUD.m_BotVGUI.m_pBotPersonalityNames;
	while(pPersoEntry)
	{
		pListBoxEntry = m_PersoListBox.m_pFirstSettingEntry;
		bool IsIn = false;

		while(pListBoxEntry)
		{
			if (!strcmp(pPersoEntry->szBotPersoName, pListBoxEntry->szListText))
			{
				IsIn = true;
				break;
			}
			pListBoxEntry = pListBoxEntry->next;
		}

		if (!IsIn)
			m_PersoListBox.AddEntry(pPersoEntry->szBotPersoName);

		pPersoEntry = pPersoEntry->next;
	}

	CBaseBotMenu::Open();
}

// end add Super Bot menu

// Advanced menus

//main advanced menu panel
CAdvancedBotOptionsMenuPanel::CAdvancedBotOptionsMenuPanel() : CBaseBotMenu(false, ADVANCEDOPTIONSBOTMENU_WIDTH, ADVANCEDOPTIONSBOTMENU_HEIGHT)
{	int iButtonHeight = BUTTON_HEIGHT;
	int iButtonWidth = XRES(200);
	int iButtonx = BUTTON_WIDTH_SPACE;
	
	m_pPanel = new CTransparentPanel( PANEL_TRANS, 0, 0, ADVANCEDOPTIONSBOTMENU_WIDTH, ADVANCEDOPTIONSBOTMENU_HEIGHT);
	m_pPanel->setParent( this );
	m_pPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
	
	MakeTitle("Advanced Bot Options", 0, 0, ADVANCEDOPTIONSBOTMENU_WIDTH-2, iButtonHeight);

	int iButtony = 0;
	int n;
	for (n=0; n < ADVANCEDBOTMENU_CHECKBUTTONS;n++)
	{	
		iButtony += iButtonHeight + BUTTON_HEIGHT_SPACE;

		AddCheckBox(iButtonx, iButtony, AdvancedBotOptionsMenuItems[n].szName,
					AdvancedBotOptionsMenuItems[n].szCVAR);
	}

	iButtonx += XRES(170);
	iButtony = 0;
	CommandButton *pButton;
	for (n=0; n<ADVANCEDBOTMENU_BUTTONS; n++)
	{
		iButtony += iButtonHeight + BUTTON_HEIGHT_SPACE;

		switch(n)
		{
		case 0: // Change Bot Skill
			pButton = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString(sAdvancedBotMenuNames[n]), iButtonx, iButtony, iButtonWidth, iButtonHeight);
			m_pSubMenus[0] = new CBotSkillMenuPanel;
			pButton->addActionSignal( new CBotMenuHandler(this, m_pSubMenus[0]) );	
			break;
		case 1: // Change Bot Aggression Level
			pButton = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString(sAdvancedBotMenuNames[n]), iButtonx, iButtony, iButtonWidth, iButtonHeight);
			m_pSubMenus[1] = new CBotAggressionLevelMenuPanel;
			pButton->addActionSignal( new CBotMenuHandler(this, m_pSubMenus[1]) );	
			break;
		case 2: // Change Bot Chat Settings
			pButton = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString(sAdvancedBotMenuNames[n]), iButtonx, iButtony, iButtonWidth, iButtonHeight);
			m_pSubMenus[2] = new CBotChatSettingsMenuPanel;
			pButton->addActionSignal( new CBotMenuHandler(this, m_pSubMenus[2]) );	
			break;
		case 3: // Change other Bot Settinggs
			pButton = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString(sAdvancedBotMenuNames[n]), iButtonx, iButtony, iButtonWidth, iButtonHeight);
			m_pSubMenus[3] = new CBotSettingsMenuPanel;
			pButton->addActionSignal( new CBotMenuHandler(this, m_pSubMenus[3]) );	
			break;
		case 4: // Restore bot personalities
			pButton = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString(sAdvancedBotMenuNames[n]), iButtonx, iButtony, iButtonWidth, iButtonHeight);
			pButton->addActionSignal( new CMenuHandler_StringCommand("restorebotpersonalities") );
			break;
		default:
			break;
		}

		pButton->setContentAlignment(vgui::Label::a_center);
		pButton->setParent( m_pPanel );
	}

	iButtony += (iButtonHeight * 2) + BUTTON_HEIGHT_SPACE;
	MakeBackToMainButton(iButtonx, iButtony, iButtonWidth, iButtonHeight);

	iButtony += iButtonHeight + BUTTON_HEIGHT_SPACE;
	MakeExitButton(iButtonx, iButtony, iButtonWidth, iButtonHeight);
}

void CAdvancedBotOptionsMenuPanel::DeInit()
{
	for (int i=0;i<ADVANCEDBOTOPTIONSMENU_SUBMENUS;i++)
		delete m_pSubMenus[i];
}

void CAdvancedBotOptionsMenuPanel::AddCheckBox(int x, int y, const char *szTitle, const char *szCVAR)
{
	CBotBoolCheckBox *pCheckBox = new CBotBoolCheckBox;
	pCheckBox->setParent(this);
	pCheckBox->SetImages("gfx/vgui/checked.tga", "gfx/vgui/unchecked.tga");
	pCheckBox->SetText(szTitle);
	pCheckBox->SetTextColor(200, 200, 200, 150);
	pCheckBox->setPos(x, y);
	pCheckBox->SetCheckboxLeft(false);
	pCheckBox->SetChecked((CVAR_GET_FLOAT(szCVAR) != 0.0f));
	pCheckBox->SetHandler(NULL); // CBotBoolCheckBox doesnt use this
	pCheckBox->SetCVAR(szCVAR);
}

CBotSkillMenuPanel :: CBotSkillMenuPanel() : CBaseBotMenu(false, BOTSKILLMENU_HEIGHT)
{	int iButtonHeight = BUTTON_HEIGHT;
	int iButtonWidth = BOTMENU_WIDTH - BUTTON_WIDTH_SPACE * 2 - 2;
	int iButtonx = BUTTON_WIDTH_SPACE;
	
	m_pPanel = new CTransparentPanel( PANEL_TRANS, 0, 0, BOTMENU_WIDTH, BOTSKILLMENU_HEIGHT);
	m_pPanel->setParent( this );
	m_pPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
	
	MakeTitle("Change Bot Skill", 0, 0, BOTMENU_WIDTH-2, iButtonHeight);

	int iButtony = 0;
	for (int n=0; n < BOTSKILLMENU_BUTTONS;n++)
	{	
		iButtony += iButtonHeight + BUTTON_HEIGHT_SPACE;

		m_pBotButton[n] = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString(sBotSkillMenuNames[n]), iButtonx, iButtony, iButtonWidth, iButtonHeight);
		m_pBotButton[n]->setContentAlignment(vgui::Label::a_center);
		m_pBotButton[n]->setParent( m_pPanel );
		m_pBotButton[n]->addActionSignal( new CExecuteBotCommandMenuHandler(sBotSkillMenuCommands[n]) );	
	}

	iButtony += (iButtonHeight * 2) + BUTTON_HEIGHT_SPACE;
	MakeBackToMainButton(iButtonx, iButtony, iButtonWidth, iButtonHeight);

	iButtony += (iButtonHeight * 2) + BUTTON_HEIGHT_SPACE;
	MakeExitButton(iButtonx, iButtony, iButtonWidth, iButtonHeight);
}

CBotAggressionLevelMenuPanel :: CBotAggressionLevelMenuPanel() : CBaseBotMenu(false, BOTAGGRESSIONLEVELMENU_HEIGHT)
{	int iButtonHeight = BUTTON_HEIGHT;
	int iButtonWidth = BOTMENU_WIDTH - BUTTON_WIDTH_SPACE * 2 - 2;
	int iButtonx = BUTTON_WIDTH_SPACE;
	
	m_pPanel = new CTransparentPanel( PANEL_TRANS, 0, 0, BOTMENU_WIDTH, BOTAGGRESSIONLEVELMENU_HEIGHT);
	m_pPanel->setParent( this );
	m_pPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
	
	MakeTitle("Change Bot Agressiveness", 0, 0, BOTMENU_WIDTH-2, iButtonHeight);

	int iButtony = 0;
	for (int n=0; n < BOTAGGRESSIONLEVELMENU_BUTTONS;n++)
	{	
		iButtony += iButtonHeight + BUTTON_HEIGHT_SPACE;

		m_pBotButton[n] = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString(sBotAggressionLevelMenuNames[n]), iButtonx, iButtony, iButtonWidth, iButtonHeight);
		m_pBotButton[n]->setContentAlignment(vgui::Label::a_center);
		m_pBotButton[n]->setParent( m_pPanel );
		m_pBotButton[n]->addActionSignal( new CExecuteBotCommandMenuHandler(sBotAggressionLevelMenuCommands[n]) );	
	}

	iButtony += (iButtonHeight * 2) + BUTTON_HEIGHT_SPACE;
	MakeBackToMainButton(iButtonx, iButtony, iButtonWidth, iButtonHeight);

	iButtony += (iButtonHeight * 2) + BUTTON_HEIGHT_SPACE;
	MakeExitButton(iButtonx, iButtony, iButtonWidth, iButtonHeight);
}

CBotSettingsMenuPanel :: CBotSettingsMenuPanel() : CBaseBotMenu(false, BOTSETTINGSMENU_WIDTH, BOTSETTINGSMENU_HEIGHT)
{	int iButtonHeight = BUTTON_HEIGHT;
	int iButtonWidth = XRES(125);
	int iButtonx = BUTTON_WIDTH_SPACE;
	
	m_pPanel = new CTransparentPanel( PANEL_TRANS, 0, 0, BOTSETTINGSMENU_WIDTH, BOTSETTINGSMENU_HEIGHT);
	m_pPanel->setParent( this );
	m_pPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
	
	MakeTitle("Other Bot Settings Menu", 0, 0, BOTSETTINGSMENU_WIDTH-2, iButtonHeight);

	int iButtony = 0, n;
	iButtony = BUTTON_HEIGHT_SPACE + YRES(20);

	// First column
	iButtonx = BUTTON_WIDTH_SPACE;
	for (n=0;n<ceil(float(BOTSETTINGSMENU_SCROLLBARS)/2.0f);n++)
	{
		MakeSettingScrollBar(iButtonx, iButtony, m_pScrollLabels[n], m_pScrollBars[n],
							 sBotPercentageMenuNames[n], sBotSettingsMenuCommands[n]);
		iButtony += YRES(75);
	}

	// Second column
	iButtonx += XRES(250);//180);
	iButtony = BUTTON_HEIGHT_SPACE + YRES(20);
	for (n=ceil(float(BOTSETTINGSMENU_SCROLLBARS)/2.0f);n<BOTSETTINGSMENU_SCROLLBARS;n++)
	{
		MakeSettingScrollBar(iButtonx, iButtony, m_pScrollLabels[n], m_pScrollBars[n],
							 sBotPercentageMenuNames[n], sBotSettingsMenuCommands[n]);
		iButtony += YRES(75);
	}

	//iButtonx = (BOTSETTINGSMENU_WIDTH - iButtonWidth) / 2;
/*		
	CommandButton *pButton = new CommandButton( "OK", iButtonx, iButtony, iButtonWidth, iButtonHeight);
	pButton->setContentAlignment(vgui::Label::a_center);
	pButton->setParent( m_pPanel );
	pButton->addActionSignal( new CApplyMenuHandler(this));

	iButtony += (iButtonHeight * 2) + BUTTON_HEIGHT_SPACE;
	MakeCancelButton(iButtonx, iButtony, iButtonWidth, iButtonHeight);
*/
	iButtony += YRES(20);
	MakeBackAndExitButtons(iButtony, BOTSETTINGSMENU_WIDTH); 
}

void CBotSettingsMenuPanel::paintBackground()
{
	CBaseBotMenu::paintBackground();
	char szValue[24];

	// Update all values of the scrollbars
	for (int n=0;n<BOTSETTINGSMENU_SCROLLBARS;n++)
	{
		sprintf(szValue, "%d", m_pScrollBars[n]->getValue());
		m_pScrollLabels[n]->setText(szValue);
	}
}

// end advanced menus

// Bot chat settings menu panel
CBotChatSettingsMenuPanel :: CBotChatSettingsMenuPanel() : CBaseBotMenu(false, BOTCHATSETTINGSMENU_WIDTH, BOTCHATSETTINGSMENU_HEIGHT)
{	int iButtonHeight = BUTTON_HEIGHT;
	int iButtonWidth = XRES(125);
	int iButtonx = BUTTON_WIDTH_SPACE;
	
	m_pPanel = new CTransparentPanel( PANEL_TRANS, 0, 0, BOTCHATSETTINGSMENU_WIDTH, BOTCHATSETTINGSMENU_HEIGHT);
	m_pPanel->setParent( this );
	m_pPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
	
	MakeTitle("Bot Chat Settings Menu", 0, 0, BOTCHATSETTINGSMENU_WIDTH-2, iButtonHeight);

	int iButtony = 0, n;
	iButtony = BUTTON_HEIGHT_SPACE + YRES(20);

	// First column
	iButtonx = BUTTON_WIDTH_SPACE;
	for (n=0;n<ceil(float(BOTCHATSETTINGSMENU_SCROLLBARS)/2.0f);n++)
	{
		MakeSettingScrollBar(iButtonx, iButtony, m_pScrollLabels[n], m_pScrollBars[n],
							 sBotChatSettingsMenuNames[n], sBotChatSettingsMenuCommands[n]);
		iButtony += YRES(75);
	}

	// Second column
	iButtonx += XRES(250);//180);
	iButtony = BUTTON_HEIGHT_SPACE + YRES(20);
	for (n=ceil(float(BOTSETTINGSMENU_SCROLLBARS)/2.0f);n<BOTCHATSETTINGSMENU_SCROLLBARS;n++)
	{
		MakeSettingScrollBar(iButtonx, iButtony, m_pScrollLabels[n], m_pScrollBars[n],
							 sBotChatSettingsMenuNames[n], sBotChatSettingsMenuCommands[n]);
		iButtony += YRES(75);
	}

	iButtony += YRES(75);
	MakeBackAndExitButtons(iButtony, BOTCHATSETTINGSMENU_WIDTH); 
}

void CBotChatSettingsMenuPanel::paintBackground()
{
	CBaseBotMenu::paintBackground();
	char szValue[24];

	// Update all values of the scrollbars
	for (int n=0;n<BOTCHATSETTINGSMENU_SCROLLBARS;n++)
	{
		sprintf(szValue, "%d", m_pScrollBars[n]->getValue());
		m_pScrollLabels[n]->setText(szValue);
	}
}

// end bot chattings menu panel

void CBotBoolCheckBox::ChangeCVAR()
{
	cvar_t *pCVAR = gEngfuncs.pfnGetCvarPointer(m_szCVAR);
	if (pCVAR)
		pCVAR->value = float(m_bChecked);
}


// Bot manager

void CBotManager::CBotManagerLabel::paintBackground()
{
	Color oldBg;
	getBgColor(oldBg);

	if (m_pOwner->m_iSelectedRow == m_iRow)
	{
		setBgColor(134, 91, 19, 0);
	}

	Label::paintBackground();

	setBgColor(oldBg);
}
		
void CBotManager::CBotManagerLabel::paint()
{
	Color oldFg;
	getFgColor(oldFg);

	if (m_pOwner->m_iSelectedRow == m_iRow)
	{
		setFgColor(255, 255, 255, 0);
	}

	Label::paint();
	
	setFgColor(oldFg[0], oldFg[1], oldFg[2], oldFg[3]);
}


CBotManager::CBotManager() : CBaseBotMenu(false, BOTMANAGERMENU_WIDTH, BOTMANAGERMENU_HEIGHT)
{
	m_pCurrentHighlightLabel = NULL;

	m_pPanel = new CTransparentPanel( PANEL_TRANS, 0, 0, BOTMANAGERMENU_WIDTH, BOTMANAGERMENU_HEIGHT);
	m_pPanel->setParent( this );
	m_pPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
	
	MakeTitle("Manage Bots", 0, 0, BOTMANAGERMENU_WIDTH-2, BUTTON_HEIGHT);

	m_PlayerList.setBounds(XRES(10), YRES(35), BOTMANAGERLIST_WIDTH, YRES(270));
	m_PlayerList.setBgColor(0,0,0,255);
	m_PlayerList.setParent(m_pPanel);
	m_PlayerList.setBorder( new LineBorder( Color(200, 200, 200, 150) ) );

	for(int row=0; row < 32; row++)
	{
		CGrid *pGridRow = &m_PlayerGrids[row];
		//m_PlayerEntries[row] = new CBotManagerLabel(this, row);

		pGridRow->SetDimensions(1, 1);
		
		m_PlayerEntries[row].setContentFitted(false);
//		m_PlayerEntries[row].setRow(row);
		m_PlayerEntries[row].addInputSignal(this);
		m_PlayerEntries[row].SetRow(row);
		m_PlayerEntries[row].SetOwner(this);

		pGridRow->SetEntry(0, 0, &m_PlayerEntries[row]);

		pGridRow->setBgColor(0,0,0,255);
		pGridRow->SetSpacing(0, 0);
		pGridRow->SetColumnWidth(0, BOTMANAGERLIST_WIDTH-XRES(10));
		pGridRow->AutoSetRowHeights();
		pGridRow->setSize(PanelWidth(pGridRow), pGridRow->CalcDrawHeight());
		pGridRow->RepositionContents();

		m_PlayerList.AddItem(pGridRow);
	}

	m_iRows = 0;
	m_iMouseRow = -1;

	int iButtonWidth = XRES(120);
	int iButtonx = BOTMANAGERMENU_WIDTH - (iButtonWidth + BUTTON_WIDTH_SPACE);
	int iButtony = YRES(135);

	MakeEditBotButton(iButtonx, iButtony, iButtonWidth, BUTTON_HEIGHT);
	iButtony += BUTTON_HEIGHT + BUTTON_HEIGHT_SPACE;
	MakeKillBotButton(iButtonx, iButtony, iButtonWidth, BUTTON_HEIGHT);
	iButtony += BUTTON_HEIGHT + BUTTON_HEIGHT_SPACE;
	MakeKickBotButton(iButtonx, iButtony, iButtonWidth, BUTTON_HEIGHT);
	iButtony += (BUTTON_HEIGHT + BUTTON_HEIGHT_SPACE) * 3;
	MakeBackToMainButton(iButtonx, iButtony, iButtonWidth, BUTTON_HEIGHT);
	iButtony += BUTTON_HEIGHT + BUTTON_HEIGHT_SPACE;
	MakeExitButton(iButtonx, iButtony, iButtonWidth, BUTTON_HEIGHT);

	m_pEditBotPanel = new CEditBotPanel;
}

void CBotManager::MakeKillBotButton(int x, int y, int wide, int tall)
{
	CommandButton *pButton = new CommandButton( "Kill Bot", x, y, wide, tall);
	pButton->setContentAlignment(vgui::Label::a_center);
	pButton->setParent( m_pPanel );
	pButton->addActionSignal( new CKillBotHandler(this) );
}

void CBotManager::MakeKickBotButton(int x, int y, int wide, int tall)
{
	CommandButton *pButton = new CommandButton( "Kick Bot", x, y, wide, tall);
	pButton->setContentAlignment(vgui::Label::a_center);
	pButton->setParent( m_pPanel );
	pButton->addActionSignal( new CKickBotHandler(this) );
}

void CBotManager::MakeEditBotButton(int x, int y, int wide, int tall)
{
	CommandButton *pButton = new CommandButton( "Edit Bot", x, y, wide, tall);
	pButton->setContentAlignment(vgui::Label::a_center);
	pButton->setParent( m_pPanel );
	pButton->addActionSignal( new CEditBotButtonHandler(this) );
}

void CBotManager::Update()
{
	m_iRows = 0;
	gViewPort->GetAllPlayersInfo();
	
	for(int i=0;i<32;i++)
		m_iPlayers[i] = 0;

	GetPlayers();

	// set scrollbar range
	m_PlayerList.SetScrollRange(m_iRows);

	FillGrid();
}

void CBotManager::FillGrid()
{
	if (m_iSelectedRow >= m_iRows)
		m_iSelectedRow = -1;

	int x, y;
	m_pPanel->getApp()->getCursorPos(x, y);
	cursorMoved(x, y, this);
	
	int row=0;
	for(row=0; row < 32; row++)
	{
		CGrid *pGridRow = &m_PlayerGrids[row];
		pGridRow->SetRowUnderline(0, false, 0, 0, 0, 0, 0);

		if(row >= m_iRows)
		{
			m_PlayerEntries[row].setVisible(false);
			continue;
		}

		CBotManagerLabel *pLabel = &m_PlayerEntries[row];

		pLabel->setVisible(true);
//		pLabel->setText2("");
		pLabel->setImage(NULL);
//		pLabel->setFont(sfont);
//		pLabel->setTextOffset(0, 0);
			
		int rowheight = 13;
		if (ScreenHeight > 480)
		{
			rowheight = YRES(rowheight);
		}

		pLabel->setSize(pLabel->getWide(), rowheight);
		pLabel->setBgColor(0, 0, 0, 255);
			
		pLabel->setFgColor(200, 200, 200, 150);

		rowheight = 20;
		if (ScreenHeight >= 480)
		{
			rowheight = YRES(rowheight);
		}
		pLabel->setSize(pLabel->getWide(), rowheight);

		pLabel->setContentAlignment( vgui::Label::a_center );

		pLabel->setText(g_PlayerInfoList[m_iPlayers[row]].name);
	}

	for(row=0; row < 32; row++)
	{
		CGrid *pGridRow = &m_PlayerGrids[row];

		pGridRow->AutoSetRowHeights();
		pGridRow->setSize(PanelWidth(pGridRow), pGridRow->CalcDrawHeight());
		pGridRow->RepositionContents();
	}

	// hack, for the thing to resize
	m_PlayerList.getSize(x, y);
	m_PlayerList.setSize(x, y);
}

void CBotManager::mousePressed(MouseCode code, Panel* panel)
{
	if(gHUD.m_iIntermission)
		return;

	if (m_iMouseRow >= 0)
	{
		m_iSelectedRow = m_iMouseRow;
	}
}

void CBotManager::cursorMoved(int x, int y, Panel *panel)
{
	// look for which cell the mouse is currently over
	for (int i = 0; i < 32; i++)
	{
		int row, col;
		if (m_PlayerGrids[i].getCellAtPoint(x, y, row, col))
		{
			MouseOverCell(i);
			return;
		}
	}
}

void CBotManager::MouseOverCell(int row)
{
	CBotManagerLabel *label = &m_PlayerEntries[row];

	// clear the previously highlighted label
	if (m_pCurrentHighlightLabel != label)
	{
		m_pCurrentHighlightLabel = NULL;
		m_iMouseRow = -1;
	}

	if ((!label) || (!m_iPlayers[row]))
		return;

	// don't act on disconnected players or ourselves
	hud_player_info_t *pl_info = &g_PlayerInfoList[ m_iPlayers[row] ];
	if (!pl_info->name || !pl_info->name[0])
		return;

	// setup the new highlight
	m_pCurrentHighlightLabel = label;
	m_iMouseRow = row;
}

void CBotManager::GetPlayers()
{
	for ( int i = 1; i < 32; i++ )
	{
		if ((g_PlayerInfoList[i].name) && (!g_PlayerInfoList[i].thisplayer))
		{
			if (GetBotIndex(i) != -1) // Is it a bot?
			{
				cl_entity_t *ent = gEngfuncs.GetEntityByIndex( i );
				if (ent)
				{
					m_iPlayers[m_iRows] = i;
					m_iRows++;
				}
			}
		}
	}
}

CBotManager::CEditBotPanel::CEditBotPanel() : CBaseBotMenu(false, EDITBOTMENU_WIDTH, EDITBOTMENU_HEIGHT)
{
	m_szBotName[0] = 0;

	short BotIndex = -1, i;

	m_pPanel = new CTransparentPanel( PANEL_TRANS, 0, 0, EDITBOTMENU_WIDTH, EDITBOTMENU_HEIGHT);
	m_pPanel->setParent( this );
	m_pPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
	
	m_pTitleLabel = MakeTitle(" ", 0, 0, EDITBOTMENU_WIDTH-2, BUTTON_HEIGHT);

	int wide = XRES(80), height = YRES(85);
	
	// Create skill select listbox
	int x = XRES(10), y = YRES(30);
	MakeLabel("Bot Skill", x, y, wide, YRES(20), vgui::Label::a_center);
	m_SkillListBox.setBounds(x, y + YRES(25), wide, height);
	m_SkillListBox.setParent(this);
	for(i=0;i<6;i++)
		m_SkillListBox.AddEntry(sBotSkillMenuNames[i]);

	// Create class select listbox
	x += wide + XRES(40);
	MakeLabel("Bot Class", x, y, wide, YRES(20), vgui::Label::a_center);
	m_ClassListBox.setBounds(x, y + YRES(25), wide, height);
	m_ClassListBox.setParent(this);
	for(i=0;i<9;i++)
		m_ClassListBox.AddEntry(sBotClassMenuNames[i]);

	// Create team select listbox
	x += wide + XRES(40);
	m_pTeamLabel = MakeLabel("Bot Team", x, y, wide, YRES(20), vgui::Label::a_center);
	m_TeamListBox.setBounds(x, y + YRES(25), wide, height);
	m_TeamListBox.setParent(this);
	for(i=0;i<2;i++)
		m_TeamListBox.AddEntry(sBotTeamMenuNames[i]);

	// Create db role select listbox
	x += wide + XRES(40);
	m_pDBRoleLabel = MakeLabel("Bot DB Role", x, y, wide, YRES(20), vgui::Label::a_center);
	m_DBRoleListBox.setBounds(x, y + YRES(25), wide, height);
	m_DBRoleListBox.setParent(this);
	for(i=0;i<3;i++)
		m_DBRoleListBox.AddEntry(sBotDBTypeMenuNames[i]);

	// Create bot name text box
	x = XRES(10);
	y += height + YRES(50);
	MakeLabel("Bot Name", x, y, XRES(60));
	y += XRES(20);
	m_pBotTextEntry = new CBotTextEntry("",x,y,XRES(325),YRES(15));
	m_pBotTextEntry->setParent(this);
	m_pBotTextEntry->addActionSignal(new CBotNameHandler(this));
	m_pBotTextEntry->SetMaxChars(32);

	x = XRES(10);
	y += YRES(30);
	wide = YRES(325);
	MakeLabel("Bot Personality", x, y, wide, YRES(20), vgui::Label::a_center);
	y += YRES(25);
	m_PersoListBox.setBounds(x, y, wide, height);
	m_PersoListBox.setParent(this);

	wide = XRES(120);
	//y += height + YRES(30);
	height = BUTTON_HEIGHT;
	//x = (EDITBOTMENU_WIDTH - (3 * (wide + BUTTON_WIDTH_SPACE))) / 2;
//	y += YRES(35);
	x = EDITBOTMENU_WIDTH - (wide + BUTTON_WIDTH_SPACE);
	MakeEditButton(x, y, wide, height);
	//x += wide + BUTTON_WIDTH_SPACE;
	y += height + BUTTON_HEIGHT_SPACE;
	MakeBackToMainButton(x, y, wide, height);
	//x += wide + BUTTON_WIDTH_SPACE;
	y += height + BUTTON_HEIGHT_SPACE;
	MakeExitButton(x, y, wide, height);
}

void CBotManager::CEditBotPanel::DeInit()
{
	m_SkillListBox.ClearAll();
	m_TeamListBox.ClearAll();
	m_ClassListBox.ClearAll();
	m_DBRoleListBox.ClearAll();
	m_PersoListBox.ClearAll();
}

void CBotManager::CEditBotPanel::MakeEditButton(int x, int y, int wide, int tall)
{
	CommandButton *pButton = new CommandButton( "Edit Bot", x, y, wide, tall);
	pButton->setContentAlignment(vgui::Label::a_center);
	pButton->setParent( m_pPanel );
	pButton->addActionSignal( new CEditButtonHandler(this) );
}

void CBotManager::CEditBotPanel::paintBackground()
{
	CBaseBotMenu::paintBackground();
	m_SkillListBox.Update();
	m_TeamListBox.Update();
	m_ClassListBox.Update();
	m_DBRoleListBox.Update();
	m_PersoListBox.Update();
}

void CBotManager::CEditBotPanel::Open()
{
	m_TeamListBox.SetVisible((gHUD.m_Teamplay != 0));
	m_pTeamLabel->setVisible((gHUD.m_Teamplay != 0));
	m_DBRoleListBox.SetVisible(gbIsDBMode);
	m_pDBRoleLabel->setVisible(gbIsDBMode);

	char szTitle[64];
	sprintf(szTitle, "Editing bot \"%s\"", m_szBotName);
	m_pTitleLabel->setText(szTitle);

	short BotIndex = -1, i;

	// Search the bot ent index
	for (i=1;i<=32;i++)
	{
		if (!strcmp(g_PlayerInfoList[i].name, m_szBotName))
		{
			BotIndex = i;
			break;
		}
	}

	bot_info_s *pBot = GetBotPointer(BotIndex);

	short Skill = -1;

	if (pBot)
		Skill = pBot->sSkill;

	if (Skill > 0)
		m_SkillListBox.SetCurrentSelection(Skill - 1);

	short Class = -1;

	if (BotIndex != -1)
		Class = g_PlayerExtraInfo[BotIndex].playerclass;

	if ((Class >= 1) || (Class <= 9))
		m_ClassListBox.SetCurrentSelection(Class - 1);

	short Team = -1;

	if (gHUD.m_Teamplay)
	{
		if (BotIndex != -1)
			Team = g_PlayerExtraInfo[BotIndex].teamnumber;
	}

	if ((Team == 1) || (Team == 2))
		m_TeamListBox.SetCurrentSelection(Team - 1);

	if ((gbIsDBMode) && (pBot))
		m_DBRoleListBox.SetCurrentSelection(pBot->sDBRole - 1);

	// Check if we have to add new personalities
	CBotVGUI::bot_perso_list_s *pPersoEntry = gHUD.m_BotVGUI.m_pBotPersonalityNames;
	while(pPersoEntry)
	{
		CBotSettingListBox::setting_entry_s *pListBoxEntry = m_PersoListBox.m_pFirstSettingEntry;
		bool IsIn = false;

		while(pListBoxEntry)
		{
			if (!strcmp(pPersoEntry->szBotPersoName, pListBoxEntry->szListText))
			{
				IsIn = true;
				break;
			}
			pListBoxEntry = pListBoxEntry->next;
		}

		if (!IsIn)
			m_PersoListBox.AddEntry(pPersoEntry->szBotPersoName);

		pPersoEntry = pPersoEntry->next;
	}

	char *szPerso = NULL;
	if (pBot)
		szPerso = pBot->szPersonality;

	if ((szPerso) && (*szPerso))
		m_PersoListBox.SetCurrentSelection(szPerso);

	m_pBotTextEntry->setText(m_szBotName, strlen(m_szBotName));

	CBaseBotMenu::Open();
}

// Bot manager end

int CBotVGUI::Init()
{	
	HOOK_MESSAGE(BotVGUI);

	gHUD.AddHudElem(this);
	m_iFlags |= HUD_ACTIVE;

	m_pBotPersonalityNames = m_pLastPersoNameEntry = NULL;

	memset(gBotInfo, 0, sizeof(gBotInfo));
	gszDefaultPerso[0] = 0;

	return 1;
}

int CBotVGUI::MsgFunc_BotVGUI(const char *pszName, int iSize, void *pbuf)
{
	BEGIN_READ( pbuf, iSize );
	BotVGUIMsgTypes type = BotVGUIMsgTypes(READ_BYTE());

	switch (type)
	{
	case BOTVGUI_ADDPERSO:
	{
		char *szBotPerso = new char[33];
		strcpy(szBotPerso, READ_STRING());

		if (!m_pBotPersonalityNames)
		{
			m_pBotPersonalityNames = new bot_perso_list_s(szBotPerso);
			m_pLastPersoNameEntry = m_pBotPersonalityNames;
		}
		else
		{
			m_pLastPersoNameEntry->next = new bot_perso_list_s(szBotPerso);
			m_pLastPersoNameEntry = m_pLastPersoNameEntry->next;
		}

		break;
	}
	case BOTVGUI_DEFAULTPERSO:
		strcpy(gszDefaultPerso, READ_STRING());
		break;
	case BOTVGUI_BOTSKILL:
	{
		short BotEntIndex = READ_BYTE();
		short BotSkill = READ_BYTE();

		bot_info_s *pBot = GetBotPointer(BotEntIndex);
		if (!pBot)
			pBot = GetFirstFreeBotSlot();

		if (!pBot)
			break;
		else
			pBot->sEntIndex = BotEntIndex;

		pBot->sSkill = BotSkill;
		break;
	}
	case BOTVGUI_BOTPERSO:
	{
		short BotEntIndex = READ_BYTE();

		bot_info_s *pBot = GetBotPointer(BotEntIndex);
		if (!pBot)
			pBot = GetFirstFreeBotSlot();

		if (!pBot)
			break;
		else
			pBot->sEntIndex = BotEntIndex;

		strcpy(pBot->szPersonality, READ_STRING());
		break;
	}
	case BOTVGUI_BOTDBROLE:
	{
		short BotEntIndex = READ_BYTE();

		bot_info_s *pBot = GetBotPointer(BotEntIndex);
		if (!pBot)
			pBot = GetFirstFreeBotSlot();

		if (!pBot)
			break;
		else
			pBot->sEntIndex = BotEntIndex;

		pBot->sDBRole = READ_BYTE();
		break;
	}
	case BOTVGUI_DBMODE:
		gbIsDBMode = (READ_BYTE() != 0);
		break;
	default:
		break;
	}

	return 1;
}

CBotVGUI::~CBotVGUI()
{
	DeInitBotMenus();

	if (m_pBotPersonalityNames)
	{
		bot_perso_list_s *pTemp = NULL;

		while(m_pBotPersonalityNames)
		{
			pTemp = m_pBotPersonalityNames;
			
			m_pBotPersonalityNames = m_pBotPersonalityNames->next;
			delete[] pTemp->szBotPersoName;
			delete (pTemp);
		}
	}
}

// Bot utility functions

short GetBotIndex(int iEntIndex)
{
	for(int i=0;i<32;i++)
	{
		if (gBotInfo[i].sEntIndex == iEntIndex)
			return i;
	}

	return -1;
}

bot_info_s *GetBotPointer(int iEntIndex)
{
	for(int i=0;i<32;i++)
	{
		if (gBotInfo[i].sEntIndex == iEntIndex)
			return &gBotInfo[i];
	}

	return NULL;
}

bot_info_s *GetFirstFreeBotSlot()
{
	for(int i=0;i<32;i++)
	{
		if (gBotInfo[i].sEntIndex < 1)
			return &gBotInfo[i];
	}

	return NULL;
}