about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/game/client/components/countryflags.cpp2
-rw-r--r--src/game/client/components/menus.cpp11
-rw-r--r--src/game/client/components/menus.h8
-rw-r--r--src/game/client/components/menus_demo.cpp4
-rw-r--r--src/game/client/components/menus_settings.cpp500
-rw-r--r--src/game/client/components/skins.cpp2
6 files changed, 316 insertions, 211 deletions
diff --git a/src/game/client/components/countryflags.cpp b/src/game/client/components/countryflags.cpp
index fd6e31d1..3a56d43a 100644
--- a/src/game/client/components/countryflags.cpp
+++ b/src/game/client/components/countryflags.cpp
@@ -91,7 +91,7 @@ int CCountryFlags::Num() const
 
 const CCountryFlags::CCountryFlag *CCountryFlags::Get(int Index) const
 {
-	return &m_aCountryFlags[Index%m_aCountryFlags.size()];
+	return &m_aCountryFlags[max(0, Index%m_aCountryFlags.size())];
 }
 
 int CCountryFlags::Find(int CountryCode) const
diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp
index 068d7451..5a48ab9d 100644
--- a/src/game/client/components/menus.cpp
+++ b/src/game/client/components/menus.cpp
@@ -112,6 +112,17 @@ int CMenus::DoButton_MenuTab(const void *pID, const char *pText, int Checked, co
 	return UI()->DoButtonLogic(pID, pText, Checked, pRect);
 }
 
+int CMenus::DoButton_PageMenu(const void *pID, const char *pText, int Checked, bool Active, const CUIRect *pRect, int Corners)
+{
+	if(Active)
+		RenderTools()->DrawUIRect(pRect, vec4(1,1,1,0.5f)*ButtonColorMul(pID), Corners, 10.0f);
+	else
+		RenderTools()->DrawUIRect(pRect, ms_ColorTabbarInactive, Corners, 10.0f);
+	UI()->DoLabel(pRect, pText, pRect->h*ms_FontmodHeight, 0);
+	
+	return UI()->DoButtonLogic(pID, pText, Checked, pRect);
+}
+
 int CMenus::DoButton_GridHeader(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
 //void CMenus::ui_draw_grid_header(const void *id, const char *text, int checked, const CUIRect *r, const void *extra)
 {
diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h
index 0ad63669..e8236f59 100644
--- a/src/game/client/components/menus.h
+++ b/src/game/client/components/menus.h
@@ -40,6 +40,7 @@ class CMenus : public CComponent
 	int DoButton_DemoPlayer_Sprite(const void *pID, int SpriteId, int Checked, const CUIRect *pRect);
 	int DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
 	int DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners);
+	int DoButton_PageMenu(const void *pID, const char *pText, int Checked, bool Active, const CUIRect *pRect, int Corners);
 
 	int DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect);
 	int DoButton_CheckBox(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
@@ -80,9 +81,9 @@ class CMenus : public CComponent
 		CUIRect m_HitRect;
 	};
 	
-	void UiDoListboxStart(void *pID, const CUIRect *pRect, float RowHeight, const char *pTitle, const char *pBottomText, int NumItems,
+	void UiDoListboxStart(const void *pID, const CUIRect *pRect, float RowHeight, const char *pTitle, const char *pBottomText, int NumItems,
 						  int ItemsPerRow, int SelectedIndex, float ScrollValue);
-	CListboxItem UiDoListboxNextItem(void *pID, bool Selected = false);
+	CListboxItem UiDoListboxNextItem(const void *pID, bool Selected = false);
 	CListboxItem UiDoListboxNextRow();
 	int UiDoListboxEnd(float *pScrollValue, bool *pItemActivated);
 	
@@ -153,6 +154,7 @@ class CMenus : public CComponent
 	bool m_NeedRestartGraphics;
 	bool m_NeedRestartSound;
 	bool m_NeedSendinfo;
+	int m_SettingPlayerPage;
 	
 	//
 	bool m_EscapePressed;
@@ -225,6 +227,8 @@ class CMenus : public CComponent
 	
 	// found in menus_settings.cpp
 	void RenderLanguageSelection(CUIRect MainView);
+	void RenderSPPage0(CUIRect MainView);
+	void RenderSPPage1(CUIRect MainView);
 	void RenderSettingsGeneral(CUIRect MainView);
 	void RenderSettingsPlayer(CUIRect MainView);
 	void RenderSettingsControls(CUIRect MainView);
diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp
index 011b1e5e..c4bfb0e0 100644
--- a/src/game/client/components/menus_demo.cpp
+++ b/src/game/client/components/menus_demo.cpp
@@ -235,7 +235,7 @@ static int gs_ListBoxItemsPerRow;
 static float gs_ListBoxScrollValue;
 static bool gs_ListBoxItemActivated;
 
-void CMenus::UiDoListboxStart(void *pID, const CUIRect *pRect, float RowHeight, const char *pTitle, const char *pBottomText, int NumItems,
+void CMenus::UiDoListboxStart(const void *pID, const CUIRect *pRect, float RowHeight, const char *pTitle, const char *pBottomText, int NumItems,
 								int ItemsPerRow, int SelectedIndex, float ScrollValue)
 {
 	CUIRect Scroll, Row;
@@ -340,7 +340,7 @@ CMenus::CListboxItem CMenus::UiDoListboxNextRow()
 	return Item;
 }
 
-CMenus::CListboxItem CMenus::UiDoListboxNextItem(void *pId, bool Selected)
+CMenus::CListboxItem CMenus::UiDoListboxNextItem(const void *pId, bool Selected)
 {
 	int ThisItemIndex = gs_ListBoxItemIndex;
 	if(Selected)
diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp
index 4bdf0fd3..5fc90459 100644
--- a/src/game/client/components/menus_settings.cpp
+++ b/src/game/client/components/menus_settings.cpp
@@ -20,6 +20,7 @@
 #include <game/localization.h>
 
 #include "binds.h"
+#include "countryflags.h"
 #include "menus.h"
 #include "skins.h"
 
@@ -49,247 +50,334 @@ bool CMenusKeyBinder::OnInput(IInput::CEvent Event)
 
 void CMenus::RenderSettingsPlayer(CUIRect MainView)
 {
-	CUIRect Button;
-	CUIRect LeftView, RightView;
+	// page menu
+	CUIRect PageMenu, Button;
+	MainView.HSplitBottom(50.0f, &MainView, &PageMenu);
+	PageMenu.HSplitTop(10.0f, 0, &PageMenu);
+	RenderTools()->DrawUIRect(&PageMenu, vec4(1.0f, 1.0f, 1.0f,0.25f), CUI::CORNER_ALL, 10.0f);
+	PageMenu.Margin(10.0f, &PageMenu);
+
+	PageMenu.VSplitLeft(50.0f, 0, &PageMenu);
+	PageMenu.VSplitLeft(120.0f, &Button, &PageMenu);
+	static int s_PrevButton = 0;
+	if(DoButton_PageMenu(&s_PrevButton, Localize("Prev"), 0, m_SettingPlayerPage>0, &Button, CUI::CORNER_L))
+	{
+		if(m_SettingPlayerPage > 0)
+			--m_SettingPlayerPage;
+	}
+	
+	PageMenu.VSplitRight(50.0f, &PageMenu, 0);
+	PageMenu.VSplitRight(120.0f, &PageMenu, &Button);
+	static int s_NextButton = 0;
+	if(DoButton_PageMenu(&s_NextButton, Localize("Next"), 0, m_SettingPlayerPage<1, &Button, CUI::CORNER_R))
+	{
+		if(m_SettingPlayerPage < 1)
+			++m_SettingPlayerPage;
+	}
+	
+	RenderTools()->DrawUIRect(&PageMenu, vec4(1.0f, 1.0f, 1.0f, 0.5f), 0, 10.0f);
+	char aBuf[64];
+	str_format(aBuf, sizeof(aBuf), Localize("Page %d of %d"), m_SettingPlayerPage+1, 2);
+	UI()->DoLabelScaled(&PageMenu, aBuf, PageMenu.h*ms_FontmodHeight, 0);
 
-	MainView.VSplitMid(&LeftView, &RightView);
-    LeftView.HSplitTop(20.0f, &Button, &LeftView);
+	// actual settings player page
+	RenderTools()->DrawUIRect(&MainView, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, 10.0f);
+	MainView.Margin(10.0f, &MainView);
+	if(m_SettingPlayerPage == 0)
+		RenderSPPage0(MainView);
+	else if(m_SettingPlayerPage == 1)
+		RenderSPPage1(MainView);
+}
 
-	// render settings
-	{
-		char aBuf[128];
+void CMenus::RenderSPPage0(CUIRect MainView)
+{
+	// settings player page 0
+	CUIRect Button, Label;
+	MainView.HSplitTop(10.0f, 0, &MainView);
 
-		LeftView.HSplitTop(20.0f, &Button, &LeftView);
-		str_format(aBuf, sizeof(aBuf), "%s:", Localize("Name"));
-		UI()->DoLabel(&Button, aBuf, 14.0, -1);
-		Button.VSplitLeft(80.0f, 0, &Button);
-		Button.VSplitLeft(180.0f, &Button, 0);
-		static float Offset = 0.0f;
-		if(DoEditBox(g_Config.m_PlayerName, &Button, g_Config.m_PlayerName, sizeof(g_Config.m_PlayerName), 14.0f, &Offset))
-			m_NeedSendinfo = true;
+	// player name
+	MainView.HSplitTop(20.0f, &Button, &MainView);
+	Button.VSplitLeft(80.0f, &Label, &Button);
+	Button.VSplitLeft(150.0f, &Button, 0);
+	char aBuf[128];
+	str_format(aBuf, sizeof(aBuf), "%s:", Localize("Name"));
+	UI()->DoLabelScaled(&Label, aBuf, 14.0, -1);
+	static float s_OffsetName = 0.0f;
+	if(DoEditBox(g_Config.m_PlayerName, &Button, g_Config.m_PlayerName, sizeof(g_Config.m_PlayerName), 14.0f, &s_OffsetName))
+		m_NeedSendinfo = true;
+
+	// player clan
+	MainView.HSplitTop(5.0f, 0, &MainView);
+	MainView.HSplitTop(20.0f, &Button, &MainView);
+	Button.VSplitLeft(80.0f, &Label, &Button);
+	Button.VSplitLeft(150.0f, &Button, 0);
+	str_format(aBuf, sizeof(aBuf), "%s:", Localize("Clan"));
+	UI()->DoLabelScaled(&Label, aBuf, 14.0, -1);
+	static float s_OffsetClan = 0.0f;
+	if(DoEditBox(g_Config.m_PlayerClan, &Button, g_Config.m_PlayerClan, sizeof(g_Config.m_PlayerClan), 14.0f, &s_OffsetClan))
+		m_NeedSendinfo = true;
+
+	// country flag selector
+	MainView.HSplitTop(20.0f, 0, &MainView);
+	MainView.HSplitTop(200.0f, &Button, &MainView);
+	static float s_ScrollValue = 0.0f;
+	int OldSelected = -1;
+	UiDoListboxStart(&s_ScrollValue, &Button, 50.0f, Localize("Country flags"), "", m_pClient->m_pCountryFlags->Num(), 6, OldSelected, s_ScrollValue);
 
-		// extra spacing
-		LeftView.HSplitTop(10.0f, 0, &LeftView);
+	for(int i = 0; i < m_pClient->m_pCountryFlags->Num(); ++i)
+	{
+		const CCountryFlags::CCountryFlag *pEntry = m_pClient->m_pCountryFlags->Get(i);
+		if(pEntry == 0)
+			continue;
 
-		static int s_DynamicCameraButton = 0;
-		LeftView.HSplitTop(20.0f, &Button, &LeftView);
-		if(DoButton_CheckBox(&s_DynamicCameraButton, Localize("Dynamic Camera"), g_Config.m_ClMouseDeadzone != 0, &Button))
-		{
+		if(pEntry->m_CountryCode == g_Config.m_PlayerCountry)
+			OldSelected = i;
 
-			if(g_Config.m_ClMouseDeadzone)
-			{
-				g_Config.m_ClMouseFollowfactor = 0;
-				g_Config.m_ClMouseMaxDistance = 400;
-				g_Config.m_ClMouseDeadzone = 0;
-			}
-			else
-			{
-				g_Config.m_ClMouseFollowfactor = 60;
-				g_Config.m_ClMouseMaxDistance = 1000;
-				g_Config.m_ClMouseDeadzone = 300;
-			}
+		CListboxItem Item = UiDoListboxNextItem(&pEntry->m_CountryCode, OldSelected == i);
+		if(Item.m_Visible)
+		{
+			Item.m_Rect.Margin(10.0f, &Item.m_Rect);
+			float OldWidth = Item.m_Rect.w;
+			Item.m_Rect.w = 96.0f*Item.m_Rect.h/64.0f;
+			Item.m_Rect.x += (OldWidth-Item.m_Rect.w)/ 2.0f;
+			Graphics()->TextureSet(pEntry->m_Texture);
+			Graphics()->QuadsBegin();
+			Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
+			IGraphics::CQuadItem QuadItem(Item.m_Rect.x, Item.m_Rect.y, Item.m_Rect.w, Item.m_Rect.h);
+			Graphics()->QuadsDrawTL(&QuadItem, 1);
+			Graphics()->QuadsEnd();
 		}
+	}
 
-		LeftView.HSplitTop(20.0f, &Button, &LeftView);
-		if(DoButton_CheckBox(&g_Config.m_ClAutoswitchWeapons, Localize("Switch weapon on pickup"), g_Config.m_ClAutoswitchWeapons, &Button))
-			g_Config.m_ClAutoswitchWeapons ^= 1;
-
-		LeftView.HSplitTop(20.0f, &Button, &LeftView);
-		if(DoButton_CheckBox(&g_Config.m_ClNameplates, Localize("Show name plates"), g_Config.m_ClNameplates, &Button))
-			g_Config.m_ClNameplates ^= 1;
+	const int NewSelected = UiDoListboxEnd(&s_ScrollValue, 0);
+	if(OldSelected != NewSelected)
+	{
+		g_Config.m_PlayerCountry = m_pClient->m_pCountryFlags->Get(NewSelected)->m_CountryCode;
+		m_NeedSendinfo = true;
+	}
 
-		LeftView.HSplitTop(20.0f, &Button, &LeftView);
-		if(g_Config.m_ClNameplates)
+	// dynamic camera
+	MainView.HSplitTop(20.0f, 0, &MainView);
+	MainView.HSplitTop(20.0f, &Button, &MainView);
+	Button.VSplitLeft(230.0f, &Button, 0);
+	static int s_DynamicCameraButton = 0;
+	if(DoButton_CheckBox(&s_DynamicCameraButton, Localize("Dynamic Camera"), g_Config.m_ClMouseDeadzone != 0, &Button))
+	{
+		if(g_Config.m_ClMouseDeadzone)
 		{
-			Button.VSplitLeft(15.0f, 0, &Button);
-			if(DoButton_CheckBox(&g_Config.m_ClNameplatesAlways, Localize("Always show name plates"), g_Config.m_ClNameplatesAlways, &Button))
-				g_Config.m_ClNameplatesAlways ^= 1;
-		
-			// draw nameplates size slider
-			CUIRect Label;
-			LeftView.HSplitTop(20.0f, &Button, &LeftView);
-			Button.VSplitLeft(15.0f, 0, &Button);
-			Button.VSplitRight(10.0f, &Button, 0);
-			Button.VSplitLeft(140.0f, &Label, &Button);
-			Button.HMargin(2.0f, &Button);
-			UI()->DoLabel(&Label, Localize("Name plates size"), 13.0f, -1);
-			g_Config.m_ClNameplatesSize = (int)(DoScrollbarH(&g_Config.m_ClNameplatesSize, &Button, g_Config.m_ClNameplatesSize/100.0f)*100.0f+0.1f);
+			g_Config.m_ClMouseFollowfactor = 0;
+			g_Config.m_ClMouseMaxDistance = 400;
+			g_Config.m_ClMouseDeadzone = 0;
 		}
 		else
-			LeftView.HSplitTop(20.0f, &Button, &LeftView);
-
-        {
-            const CSkins::CSkin *pOwnSkin = m_pClient->m_pSkins->Get(max(0, m_pClient->m_pSkins->Find(g_Config.m_PlayerSkin)));
-
-            CTeeRenderInfo OwnSkinInfo;
-            OwnSkinInfo.m_Texture = pOwnSkin->m_OrgTexture;
-            OwnSkinInfo.m_ColorBody = vec4(1, 1, 1, 1);
-            OwnSkinInfo.m_ColorFeet = vec4(1, 1, 1, 1);
-
-            if(g_Config.m_PlayerUseCustomColor)
-            {
-                OwnSkinInfo.m_ColorBody = m_pClient->m_pSkins->GetColorV4(g_Config.m_PlayerColorBody);
-                OwnSkinInfo.m_ColorFeet = m_pClient->m_pSkins->GetColorV4(g_Config.m_PlayerColorFeet);
-                OwnSkinInfo.m_Texture = pOwnSkin->m_ColorTexture;
-            }
+		{
+			g_Config.m_ClMouseFollowfactor = 60;
+			g_Config.m_ClMouseMaxDistance = 1000;
+			g_Config.m_ClMouseDeadzone = 300;
+		}
+	}
 
-            OwnSkinInfo.m_Size = 50.0f*UI()->Scale();
+	// weapon pickup
+	MainView.HSplitTop(5.0f, 0, &MainView);
+	MainView.HSplitTop(20.0f, &Button, &MainView);
+	Button.VSplitLeft(230.0f, &Button, 0);
+	if(DoButton_CheckBox(&g_Config.m_ClAutoswitchWeapons, Localize("Switch weapon on pickup"), g_Config.m_ClAutoswitchWeapons, &Button))
+		g_Config.m_ClAutoswitchWeapons ^= 1;
 
-            LeftView.HSplitTop(20.0f, &Button, &LeftView);
-            LeftView.HSplitTop(20.0f, &Button, &LeftView);
+	// name plates
+	MainView.HSplitTop(5.0f, 0, &MainView);
+	MainView.HSplitTop(20.0f, &Button, &MainView);
+	Button.VSplitLeft(230.0f, &Button, 0);
+	if(DoButton_CheckBox(&g_Config.m_ClNameplates, Localize("Show name plates"), g_Config.m_ClNameplates, &Button))
+		g_Config.m_ClNameplates ^= 1;
 
-            str_format(aBuf, sizeof(aBuf), "%s:", Localize("Your skin"));
-            UI()->DoLabelScaled(&Button, aBuf, 14.0f, -1);
+	if(g_Config.m_ClNameplates)
+	{
+		MainView.HSplitTop(2.5f, 0, &MainView);
+		MainView.VSplitLeft(30.0f, 0, &MainView);
+		MainView.VSplitLeft(200.0f, &MainView, 0);
+		MainView.HSplitTop(20.0f, &Button, &MainView);
+		if(DoButton_CheckBox(&g_Config.m_ClNameplatesAlways, Localize("Always show name plates"), g_Config.m_ClNameplatesAlways, &Button))
+			g_Config.m_ClNameplatesAlways ^= 1;
+		
+		MainView.HSplitTop(2.5f, 0, &MainView);
+		MainView.HSplitTop(20.0f, &Label, &MainView);
+		MainView.HSplitTop(20.0f, &Button, &MainView);
+		str_format(aBuf, sizeof(aBuf), "%s: %i", Localize("Name plates size"), g_Config.m_ClNameplatesSize);
+		UI()->DoLabelScaled(&Label, aBuf, 13.0f, -1);
+		Button.HMargin(2.0f, &Button);
+		g_Config.m_ClNameplatesSize = (int)(DoScrollbarH(&g_Config.m_ClNameplatesSize, &Button, g_Config.m_ClNameplatesSize/100.0f)*100.0f+0.1f);
+	}
+}
 
-            CUIRect SkinRect;
-            LeftView.VSplitLeft(LeftView.w/1.2f/UI()->Scale(), &SkinRect, 0);
-            SkinRect.HSplitTop(50.0f, &SkinRect, 0);
-            RenderTools()->DrawUIRect(&SkinRect, vec4(1, 1, 1, 0.25f), CUI::CORNER_ALL, 10.0f);
+void CMenus::RenderSPPage1(CUIRect MainView)
+{
+	// settings player page 1
+	CUIRect Button, Label;
+	MainView.HSplitTop(10.0f, 0, &MainView);
 
-            Button.VSplitLeft(30.0f, 0, &Button);
-            Button.HSplitTop(50.0f, 0, &Button);
-            RenderTools()->RenderTee(CAnimState::GetIdle(), &OwnSkinInfo, 0, vec2(1, 0), vec2(Button.x, Button.y));
+	// skin info
+	const CSkins::CSkin *pOwnSkin = m_pClient->m_pSkins->Get(m_pClient->m_pSkins->Find(g_Config.m_PlayerSkin));	
+	CTeeRenderInfo OwnSkinInfo;
+	if(g_Config.m_PlayerUseCustomColor)
+	{
+		OwnSkinInfo.m_Texture = pOwnSkin->m_ColorTexture;
+		OwnSkinInfo.m_ColorBody = m_pClient->m_pSkins->GetColorV4(g_Config.m_PlayerColorBody);
+		OwnSkinInfo.m_ColorFeet = m_pClient->m_pSkins->GetColorV4(g_Config.m_PlayerColorFeet);
+	}
+	else
+	{
+		OwnSkinInfo.m_Texture = pOwnSkin->m_OrgTexture;
+		OwnSkinInfo.m_ColorBody = vec4(1.0f, 1.0f, 1.0f, 1.0f);
+		OwnSkinInfo.m_ColorFeet = vec4(1.0f, 1.0f, 1.0f, 1.0f);
+	}
+	OwnSkinInfo.m_Size = 50.0f*UI()->Scale();
 
-            LeftView.HSplitTop(20.0f, &Button, &LeftView);
-            Button.HSplitTop(15.0f, 0, &Button);
-            Button.VSplitLeft(100.0f, 0, &Button);
+	MainView.HSplitTop(20.0f, &Label, &MainView);
+	Label.VSplitLeft(230.0f, &Label, 0);
+	char aBuf[128];
+	str_format(aBuf, sizeof(aBuf), "%s:", Localize("Your skin"));
+	UI()->DoLabelScaled(&Label, aBuf, 14.0f, -1);
+
+	MainView.HSplitTop(50.0f, &Label, &MainView);
+	Label.VSplitLeft(230.0f, &Label, 0);
+	RenderTools()->DrawUIRect(&Label, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, 10.0f);
+	RenderTools()->RenderTee(CAnimState::GetIdle(), &OwnSkinInfo, 0, vec2(1, 0), vec2(Label.x+30.0f, Label.y+28.0f));
+	Label.HSplitTop(15.0f, 0, &Label);;
+	Label.VSplitLeft(70.0f, 0, &Label);
+	UI()->DoLabelScaled(&Label,  g_Config.m_PlayerSkin, 14.0f, -1, 150.0f);
+
+	// custom colour selector
+	MainView.HSplitTop(20.0f, 0, &MainView);
+	MainView.HSplitTop(20.0f, &Button, &MainView);
+	Button.VSplitLeft(230.0f, &Button, 0);
+	if(DoButton_CheckBox(&g_Config.m_PlayerColorBody, Localize("Custom colors"), g_Config.m_PlayerUseCustomColor, &Button))
+	{
+		g_Config.m_PlayerUseCustomColor = g_Config.m_PlayerUseCustomColor?0:1;
+		m_NeedSendinfo = true;
+	}
 
-            str_format(aBuf, sizeof(aBuf), "%s", g_Config.m_PlayerSkin);
-			CTextCursor Cursor;
-			TextRender()->SetCursor(&Cursor, Button.x, Button.y, 14.0f*UI()->Scale(), TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
-			Cursor.m_LineWidth = SkinRect.w-(Button.x-SkinRect.x)-5.0f;
-			TextRender()->TextEx(&Cursor, aBuf, -1);
-        }
+	MainView.HSplitTop(5.0f, 0, &MainView);
+	MainView.HSplitTop(82.5f, &Label, &MainView);
+	if(g_Config.m_PlayerUseCustomColor)
+	{
+		CUIRect aRects[2];
+		Label.VSplitMid(&aRects[0], &aRects[1]);
+		aRects[0].VSplitRight(10.0f, &aRects[0], 0);
+		aRects[1].VSplitLeft(10.0f, 0, &aRects[1]);
+
+		int *paColors[2];
+		paColors[0] = &g_Config.m_PlayerColorBody;
+		paColors[1] = &g_Config.m_PlayerColorFeet;
+
+		const char *paParts[] = {
+			Localize("Body"),
+			Localize("Feet")};
+		const char *paLabels[] = {
+			Localize("Hue"),
+			Localize("Sat."),
+			Localize("Lht.")};
+		static int s_aColorSlider[2][3] = {{0}};
+
+		for(int i = 0; i < 2; i++)
+		{
+			aRects[i].HSplitTop(20.0f, &Label, &aRects[i]);
+			UI()->DoLabelScaled(&Label, paParts[i], 14.0f, -1);
+			aRects[i].VSplitLeft(20.0f, 0, &aRects[i]);
+			aRects[i].HSplitTop(2.5f, 0, &aRects[i]);
+
+			int PrevColor = *paColors[i];
+			int Color = 0;
+			for(int s = 0; s < 3; s++)
+			{
+				aRects[i].HSplitTop(20.0f, &Label, &aRects[i]);
+				Label.VSplitLeft(50.0f, &Label, &Button);
+				Button.HMargin(2.0f, &Button);
+
+				float k = ((PrevColor>>((2-s)*8))&0xff)  / 255.0f;
+				k = DoScrollbarH(&s_aColorSlider[i][s], &Button, k);
+				Color <<= 8;
+				Color += clamp((int)(k*255), 0, 255);
+				UI()->DoLabelScaled(&Label, paLabels[s], 14.0f, -1);
+			}
 
-		RightView.HSplitTop(20.0f, &Button, &RightView);
-		RightView.HSplitTop(20.0f, &Button, &RightView);
+			if(PrevColor != Color)
+				m_NeedSendinfo = true;
 
-		if(DoButton_CheckBox(&g_Config.m_PlayerColorBody, Localize("Custom colors"), g_Config.m_PlayerUseCustomColor, &Button))
-		{
-			g_Config.m_PlayerUseCustomColor = g_Config.m_PlayerUseCustomColor?0:1;
-			m_NeedSendinfo = true;
+			*paColors[i] = Color;
 		}
+	}
 
-		if(g_Config.m_PlayerUseCustomColor)
+	// skin selector
+	MainView.HSplitTop(20.0f, 0, &MainView);
+	static bool s_InitSkinlist = true;
+	static sorted_array<const CSkins::CSkin *> s_paSkinList;
+	static float s_ScrollValue = 0.0f;
+	if(s_InitSkinlist)
+	{
+		s_paSkinList.clear();
+		for(int i = 0; i < m_pClient->m_pSkins->Num(); ++i)
 		{
-			int *paColors[2];
-			paColors[0] = &g_Config.m_PlayerColorBody;
-			paColors[1] = &g_Config.m_PlayerColorFeet;
-
-			const char *paParts[] = {
-				Localize("Body"),
-				Localize("Feet")};
-			const char *paLabels[] = {
-				Localize("Hue"),
-				Localize("Sat."),
-				Localize("Lht.")};
-			static int s_aColorSlider[2][3] = {{0}};
-			//static float v[2][3] = {{0, 0.5f, 0.25f}, {0, 0.5f, 0.25f}};
-
-			for(int i = 0; i < 2; i++)
-			{
-				CUIRect Text;
-				RightView.HSplitTop(20.0f, &Text, &RightView);
-				Text.VSplitLeft(15.0f, 0, &Text);
-				UI()->DoLabelScaled(&Text, paParts[i], 14.0f, -1);
-
-				int PrevColor = *paColors[i];
-				int Color = 0;
-				for(int s = 0; s < 3; s++)
-				{
-					CUIRect Text;
-					RightView.HSplitTop(19.0f, &Button, &RightView);
-					Button.VSplitLeft(30.0f, 0, &Button);
-					Button.VSplitLeft(70.0f, &Text, &Button);
-					Button.VSplitRight(5.0f, &Button, 0);
-					Button.HSplitTop(4.0f, 0, &Button);
-
-					float k = ((PrevColor>>((2-s)*8))&0xff)  / 255.0f;
-					k = DoScrollbarH(&s_aColorSlider[i][s], &Button, k);
-					Color <<= 8;
-					Color += clamp((int)(k*255), 0, 255);
-					UI()->DoLabelScaled(&Text, paLabels[s], 15.0f, -1);
-
-				}
-
-				if(*paColors[i] != Color)
-					m_NeedSendinfo = true;
-
-				*paColors[i] = Color;
-				RightView.HSplitTop(5.0f, 0, &RightView);
-			}
+			const CSkins::CSkin *s = m_pClient->m_pSkins->Get(i);
+			// no special skins
+			if(s->m_aName[0] == 'x' && s->m_aName[1] == '_')
+				continue;
+			s_paSkinList.add(s);
 		}
+		s_InitSkinlist = false;
+	}
 
-        MainView.HSplitTop(MainView.h/2, 0, &MainView);
+	int OldSelected = -1;
+	UiDoListboxStart(&s_InitSkinlist, &MainView, 50.0f, Localize("Skins"), "", s_paSkinList.size(), 4, OldSelected, s_ScrollValue);
 
-		// render skinselector
-		static bool s_InitSkinlist = true;
-		static sorted_array<const CSkins::CSkin *> s_paSkinList;
-		static float s_ScrollValue = 0;
-		if(s_InitSkinlist)
-		{
-			s_paSkinList.clear();
-			for(int i = 0; i < m_pClient->m_pSkins->Num(); ++i)
-			{
-				const CSkins::CSkin *s = m_pClient->m_pSkins->Get(i);
-				// no special skins
-				if(s->m_aName[0] == 'x' && s->m_aName[1] == '_')
-					continue;
-				s_paSkinList.add(s);
-			}
-			s_InitSkinlist = false;
-		}
+	for(int i = 0; i < s_paSkinList.size(); ++i)
+	{
+		const CSkins::CSkin *s = s_paSkinList[i];
+		if(s == 0)
+			continue;
 
-		int OldSelected = -1;
-		UiDoListboxStart(&s_InitSkinlist, &MainView, 50.0f, Localize("Skins"), "", s_paSkinList.size(), 4, OldSelected, s_ScrollValue);
+		if(str_comp(s->m_aName, g_Config.m_PlayerSkin) == 0)
+			OldSelected = i;
 
-		for(int i = 0; i < s_paSkinList.size(); ++i)
+		CListboxItem Item = UiDoListboxNextItem(&s_paSkinList[i], OldSelected == i);
+		if(Item.m_Visible)
 		{
-			const CSkins::CSkin *s = s_paSkinList[i];
-			if(s == 0)
-				continue;
+			CTeeRenderInfo Info;
+			if(g_Config.m_PlayerUseCustomColor)
+			{
+				Info.m_Texture = s->m_ColorTexture;
+				Info.m_ColorBody = m_pClient->m_pSkins->GetColorV4(g_Config.m_PlayerColorBody);
+				Info.m_ColorFeet = m_pClient->m_pSkins->GetColorV4(g_Config.m_PlayerColorFeet);
+			}
+			else
+			{
+				Info.m_Texture = s->m_OrgTexture;
+				Info.m_ColorBody = vec4(1.0f, 1.0f, 1.0f, 1.0f);
+				Info.m_ColorFeet = vec4(1.0f, 1.0f, 1.0f, 1.0f);
+			}
 
-			if(str_comp(s->m_aName, g_Config.m_PlayerSkin) == 0)
-				OldSelected = i;
+			Info.m_Size = UI()->Scale()*50.0f;
+			Item.m_Rect.HSplitTop(5.0f, 0, &Item.m_Rect); // some margin from the top
+			RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, 0, vec2(1.0f, 0.0f), vec2(Item.m_Rect.x+Item.m_Rect.w/2, Item.m_Rect.y+Item.m_Rect.h/2));
 
-			CListboxItem Item = UiDoListboxNextItem(&s_paSkinList[i], OldSelected == i);
-			if(Item.m_Visible)
+			if(g_Config.m_Debug)
 			{
-				CTeeRenderInfo Info;
-				Info.m_Texture = s->m_OrgTexture;
-				Info.m_ColorBody = vec4(1, 1, 1, 1);
-				Info.m_ColorFeet = vec4(1, 1, 1, 1);
-
-				if(g_Config.m_PlayerUseCustomColor)
-				{
-					Info.m_ColorBody = m_pClient->m_pSkins->GetColorV4(g_Config.m_PlayerColorBody);
-					Info.m_ColorFeet = m_pClient->m_pSkins->GetColorV4(g_Config.m_PlayerColorFeet);
-					Info.m_Texture = s->m_ColorTexture;
-				}
-
-				Info.m_Size = UI()->Scale()*50.0f;
-				Item.m_Rect.HSplitTop(5.0f, 0, &Item.m_Rect); // some margin from the top
-				RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, 0, vec2(1, 0), vec2(Item.m_Rect.x+Item.m_Rect.w/2, Item.m_Rect.y+Item.m_Rect.h/2));
-
-				if(g_Config.m_Debug)
-				{
-					vec3 BloodColor = g_Config.m_PlayerUseCustomColor ? m_pClient->m_pSkins->GetColorV3(g_Config.m_PlayerColorBody) : s->m_BloodColor;
-					Graphics()->TextureSet(-1);
-					Graphics()->QuadsBegin();
-					Graphics()->SetColor(BloodColor.r, BloodColor.g, BloodColor.b, 1.0f);
-					IGraphics::CQuadItem QuadItem(Item.m_Rect.x, Item.m_Rect.y, 12, 12);
-					Graphics()->QuadsDrawTL(&QuadItem, 1);
-					Graphics()->QuadsEnd();
-				}
+				vec3 BloodColor = g_Config.m_PlayerUseCustomColor ? m_pClient->m_pSkins->GetColorV3(g_Config.m_PlayerColorBody) : s->m_BloodColor;
+				Graphics()->TextureSet(-1);
+				Graphics()->QuadsBegin();
+				Graphics()->SetColor(BloodColor.r, BloodColor.g, BloodColor.b, 1.0f);
+				IGraphics::CQuadItem QuadItem(Item.m_Rect.x, Item.m_Rect.y, 12.0f, 12.0f);
+				Graphics()->QuadsDrawTL(&QuadItem, 1);
+				Graphics()->QuadsEnd();
 			}
 		}
+	}
 
-		const int NewSelected = UiDoListboxEnd(&s_ScrollValue, 0);
-		if(OldSelected != NewSelected)
-		{
-			mem_copy(g_Config.m_PlayerSkin, s_paSkinList[NewSelected]->m_aName, sizeof(g_Config.m_PlayerSkin));
-			m_NeedSendinfo = true;
-		}
+	const int NewSelected = UiDoListboxEnd(&s_ScrollValue, 0);
+	if(OldSelected != NewSelected)
+	{
+		mem_copy(g_Config.m_PlayerSkin, s_paSkinList[NewSelected]->m_aName, sizeof(g_Config.m_PlayerSkin));
+		m_NeedSendinfo = true;
 	}
 }
 
@@ -791,6 +879,7 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView)
 		else
 			str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Max demos"), Localize("no limit"));
 		UI()->DoLabelScaled(&Label, aBuf, 13.0f, -1);
+		Button.HMargin(2.0f, &Button);
 		g_Config.m_ClAutoDemoMax = static_cast<int>(DoScrollbarH(&g_Config.m_ClAutoDemoMax, &Button, g_Config.m_ClAutoDemoMax/1000.0f)*1000.0f+0.1f);
 
 		Right.HSplitTop(10.0f, 0, &Right);
@@ -802,6 +891,7 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView)
 		else
 			str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Max Screenshots"), Localize("no limit"));
 		UI()->DoLabelScaled(&Label, aBuf, 13.0f, -1);
+		Button.HMargin(2.0f, &Button);
 		g_Config.m_ClAutoScreenshotMax = static_cast<int>(DoScrollbarH(&g_Config.m_ClAutoScreenshotMax, &Button, g_Config.m_ClAutoScreenshotMax/1000.0f)*1000.0f+0.1f);
 	}
 
diff --git a/src/game/client/components/skins.cpp b/src/game/client/components/skins.cpp
index 6c845bb4..d8550da4 100644
--- a/src/game/client/components/skins.cpp
+++ b/src/game/client/components/skins.cpp
@@ -135,7 +135,7 @@ int CSkins::Num()
 
 const CSkins::CSkin *CSkins::Get(int Index)
 {
-	return &m_aSkins[Index%m_aSkins.size()];
+	return &m_aSkins[max(0, Index%m_aSkins.size())];
 }
 
 int CSkins::Find(const char *pName)