about summary refs log tree commit diff
path: root/src/game
diff options
context:
space:
mode:
authorFujnky <larsfunke1996@gmail.com>2010-06-07 16:00:01 +0200
committerFujnky <larsfunke1996@gmail.com>2010-06-07 16:00:01 +0200
commit7cc7c8f84eba9d9c103e6cc393da9c0fab41cf16 (patch)
tree4a308559ece64a7c90328432fd3956021ffb2e3d /src/game
parent34bd0a09b7b57fb83f7cc44ea880387538102bf4 (diff)
parent04b6abae93c809efeeb4f6b2e9d8eb80a48b1686 (diff)
downloadzcatch-7cc7c8f84eba9d9c103e6cc393da9c0fab41cf16.tar.gz
zcatch-7cc7c8f84eba9d9c103e6cc393da9c0fab41cf16.zip
Merged with master
Diffstat (limited to 'src/game')
-rw-r--r--src/game/client/components/console.cpp14
-rw-r--r--src/game/client/components/console.h3
-rw-r--r--src/game/client/components/killmessages.cpp36
-rw-r--r--src/game/client/components/killmessages.h10
-rw-r--r--src/game/client/components/menus.cpp2
-rw-r--r--src/game/client/components/menus.h7
-rw-r--r--src/game/client/components/menus_demo.cpp82
-rw-r--r--src/game/editor/ed_editor.cpp222
-rw-r--r--src/game/editor/ed_editor.h1
-rw-r--r--src/game/server/entities/character.h2
-rw-r--r--src/game/server/gamecontroller.cpp2
-rw-r--r--src/game/server/player.cpp4
12 files changed, 325 insertions, 60 deletions
diff --git a/src/game/client/components/console.cpp b/src/game/client/components/console.cpp
index 742b6b2d..b323ab48 100644
--- a/src/game/client/components/console.cpp
+++ b/src/game/client/components/console.cpp
@@ -34,9 +34,8 @@ enum
 	CONSOLE_CLOSING,
 };
 
-CGameConsole::CInstance::CInstance(CGameConsole *pGameConsole, int Type)
+CGameConsole::CInstance::CInstance(int Type)
 {
-	m_pGameConsole = pGameConsole;
 	// init ringbuffers
 	//history = ringbuf_init(history_data, sizeof(history_data), RINGBUF_FLAG_RECYCLE);
 	//backlog = ringbuf_init(backlog_data, sizeof(backlog_data), RINGBUF_FLAG_RECYCLE);
@@ -56,6 +55,11 @@ CGameConsole::CInstance::CInstance(CGameConsole *pGameConsole, int Type)
 	m_pCommand = 0x0;
 }
 
+void CGameConsole::CInstance::Init(CGameConsole *pGameConsole)
+{
+	m_pGameConsole = pGameConsole;
+};
+
 void CGameConsole::CInstance::ExecuteLine(const char *pLine)
 {
 	if(m_Type == 0)
@@ -198,7 +202,7 @@ void CGameConsole::CInstance::PrintLine(const char *pLine)
 }
 
 CGameConsole::CGameConsole()
-: m_LocalConsole(this, 0), m_RemoteConsole(this, 1)
+: m_LocalConsole(0), m_RemoteConsole(1)
 {
 	m_ConsoleType = 0;
 	m_ConsoleState = CONSOLE_CLOSED;
@@ -573,6 +577,10 @@ void CGameConsole::PrintLine(int Type, const char *pLine)
 
 void CGameConsole::OnConsoleInit()
 {
+	// init console instances
+	m_LocalConsole.Init(this);
+	m_RemoteConsole.Init(this);
+
 	m_pConsole = Kernel()->RequestInterface<IConsole>();
 	
 	//
diff --git a/src/game/client/components/console.h b/src/game/client/components/console.h
index b88c6349..d146307f 100644
--- a/src/game/client/components/console.h
+++ b/src/game/client/components/console.h
@@ -27,7 +27,8 @@ class CGameConsole : public CComponent
 		
 		IConsole::CCommandInfo *m_pCommand;
 
-		CInstance(CGameConsole *pGameConsole, int t);
+		CInstance(int t);
+		void Init(CGameConsole *pGameConsole);
 
 		void ExecuteLine(const char *pLine);
 		
diff --git a/src/game/client/components/killmessages.cpp b/src/game/client/components/killmessages.cpp
index d18dd965..a3dc3b9c 100644
--- a/src/game/client/components/killmessages.cpp
+++ b/src/game/client/components/killmessages.cpp
@@ -22,8 +22,14 @@ void CKillMessages::OnMessage(int MsgType, void *pRawMsg)
 		
 		// unpack messages
 		CKillMsg Kill;
-		Kill.m_Killer = pMsg->m_Killer;
-		Kill.m_Victim = pMsg->m_Victim;
+		Kill.m_VictimID = pMsg->m_Victim;
+		Kill.m_VictimTeam = m_pClient->m_aClients[Kill.m_VictimID].m_Team;
+		str_copy(Kill.m_aVictimName, m_pClient->m_aClients[Kill.m_VictimID].m_aName, sizeof(Kill.m_aVictimName));
+		Kill.m_VictimRenderInfo = m_pClient->m_aClients[Kill.m_VictimID].m_RenderInfo;
+		Kill.m_KillerID = pMsg->m_Killer;
+		Kill.m_KillerTeam = m_pClient->m_aClients[Kill.m_KillerID].m_Team;
+		str_copy(Kill.m_aKillerName, m_pClient->m_aClients[Kill.m_KillerID].m_aName, sizeof(Kill.m_aKillerName));
+		Kill.m_KillerRenderInfo = m_pClient->m_aClients[Kill.m_KillerID].m_RenderInfo;
 		Kill.m_Weapon = pMsg->m_Weapon;
 		Kill.m_ModeSpecial = pMsg->m_ModeSpecial;
 		Kill.m_Tick = Client()->GameTick();
@@ -51,14 +57,14 @@ void CKillMessages::OnRender()
 			continue;
 
 		float FontSize = 36.0f;
-		float KillerNameW = TextRender()->TextWidth(0, FontSize, m_pClient->m_aClients[m_aKillmsgs[r].m_Killer].m_aName, -1);
-		float VictimNameW = TextRender()->TextWidth(0, FontSize, m_pClient->m_aClients[m_aKillmsgs[r].m_Victim].m_aName, -1);
+		float KillerNameW = TextRender()->TextWidth(0, FontSize, m_aKillmsgs[r].m_aKillerName, -1);
+		float VictimNameW = TextRender()->TextWidth(0, FontSize, m_aKillmsgs[r].m_aVictimName, -1);
 
 		float x = StartX;
 
 		// render victim name
 		x -= VictimNameW;
-		TextRender()->Text(0, x, y, FontSize, m_pClient->m_aClients[m_aKillmsgs[r].m_Victim].m_aName, -1);
+		TextRender()->Text(0, x, y, FontSize, m_aKillmsgs[r].m_aVictimName, -1);
 
 		// render victim tee
 		x -= 24.0f;
@@ -71,8 +77,10 @@ void CKillMessages::OnRender()
 				Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
 				Graphics()->QuadsBegin();
 
-				if(m_pClient->m_aClients[m_aKillmsgs[r].m_Victim].m_Team == 0) RenderTools()->SelectSprite(SPRITE_FLAG_BLUE);
-				else RenderTools()->SelectSprite(SPRITE_FLAG_RED);
+				if(m_aKillmsgs[r].m_VictimTeam == 0)
+					RenderTools()->SelectSprite(SPRITE_FLAG_BLUE);
+				else
+					RenderTools()->SelectSprite(SPRITE_FLAG_RED);
 				
 				float Size = 56.0f;
 				IGraphics::CQuadItem QuadItem(x, y-16, Size/2, Size);
@@ -81,7 +89,7 @@ void CKillMessages::OnRender()
 			}
 		}
 		
-		RenderTools()->RenderTee(CAnimState::GetIdle(), &m_pClient->m_aClients[m_aKillmsgs[r].m_Victim].m_RenderInfo, EMOTE_PAIN, vec2(-1,0), vec2(x, y+28));
+		RenderTools()->RenderTee(CAnimState::GetIdle(), &m_aKillmsgs[r].m_VictimRenderInfo, EMOTE_PAIN, vec2(-1,0), vec2(x, y+28));
 		x -= 32.0f;
 		
 		// render weapon
@@ -96,7 +104,7 @@ void CKillMessages::OnRender()
 		}
 		x -= 52.0f;
 
-		if(m_aKillmsgs[r].m_Victim != m_aKillmsgs[r].m_Killer)
+		if(m_aKillmsgs[r].m_VictimID != m_aKillmsgs[r].m_KillerID)
 		{
 			if(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_FLAGS)
 			{
@@ -106,8 +114,10 @@ void CKillMessages::OnRender()
 					Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
 					Graphics()->QuadsBegin();
 
-					if(m_pClient->m_aClients[m_aKillmsgs[r].m_Killer].m_Team == 0) RenderTools()->SelectSprite(SPRITE_FLAG_BLUE, SPRITE_FLAG_FLIP_X);
-					else RenderTools()->SelectSprite(SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X);
+					if(m_aKillmsgs[r].m_KillerTeam == 0)
+						RenderTools()->SelectSprite(SPRITE_FLAG_BLUE, SPRITE_FLAG_FLIP_X);
+					else
+						RenderTools()->SelectSprite(SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X);
 					
 					float Size = 56.0f;
 					IGraphics::CQuadItem QuadItem(x-56, y-16, Size/2, Size);
@@ -118,12 +128,12 @@ void CKillMessages::OnRender()
 			
 			// render killer tee
 			x -= 24.0f;
-			RenderTools()->RenderTee(CAnimState::GetIdle(), &m_pClient->m_aClients[m_aKillmsgs[r].m_Killer].m_RenderInfo, EMOTE_ANGRY, vec2(1,0), vec2(x, y+28));
+			RenderTools()->RenderTee(CAnimState::GetIdle(), &m_aKillmsgs[r].m_KillerRenderInfo, EMOTE_ANGRY, vec2(1,0), vec2(x, y+28));
 			x -= 32.0f;
 
 			// render killer name
 			x -= KillerNameW;
-			TextRender()->Text(0, x, y, FontSize, m_pClient->m_aClients[m_aKillmsgs[r].m_Killer].m_aName, -1);
+			TextRender()->Text(0, x, y, FontSize, m_aKillmsgs[r].m_aKillerName, -1);
 		}
 
 		y += 44;
diff --git a/src/game/client/components/killmessages.h b/src/game/client/components/killmessages.h
index 720b10ae..b4954e22 100644
--- a/src/game/client/components/killmessages.h
+++ b/src/game/client/components/killmessages.h
@@ -9,8 +9,14 @@ public:
 	struct CKillMsg
 	{
 		int m_Weapon;
-		int m_Victim;
-		int m_Killer;
+		int m_VictimID;
+		int m_VictimTeam;
+		char m_aVictimName[64];
+		CTeeRenderInfo m_VictimRenderInfo;
+		int m_KillerID;
+		int m_KillerTeam;
+		char m_aKillerName[64];
+		CTeeRenderInfo m_KillerRenderInfo;
 		int m_ModeSpecial; // for CTF, if the guy is carrying a flag for example
 		int m_Tick;
 	};
diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp
index fc919409..76943620 100644
--- a/src/game/client/components/menus.cpp
+++ b/src/game/client/components/menus.cpp
@@ -94,6 +94,8 @@ CMenus::CMenus()
 	m_NumInputEvents = 0;
 	
 	m_LastInput = time_get();
+	
+	str_copy(m_aCurrentDemoFolder, "demos", sizeof(m_aCurrentDemoFolder));
 }
 
 vec4 CMenus::ButtonColorMul(const void *pID)
diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h
index c09e6e96..229fce80 100644
--- a/src/game/client/components/menus.h
+++ b/src/game/client/components/menus.h
@@ -160,11 +160,14 @@ class CMenus : public CComponent
 	};
 	
 	sorted_array<CDemoItem> m_lDemos;
-		
+	char m_aCurrentDemoFolder[256];
+	
 	void DemolistPopulate();
 	static void DemolistCountCallback(const char *pName, int IsDir, void *pUser);
 	static void DemolistFetchCallback(const char *pName, int IsDir, void *pUser);
-
+	static void IsDirCallback(const char *pName, int IsDir, void *pUser);
+	void DemoSetParentDirectory();
+	
 	// found in menus.cpp
 	int Render();
 	//void render_background();
diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp
index f3a6bc88..ec1ead8e 100644
--- a/src/game/client/components/menus_demo.cpp
+++ b/src/game/client/components/menus_demo.cpp
@@ -1,4 +1,5 @@
 
+#include <string.h>
 #include <base/math.h>
 
 
@@ -390,17 +391,32 @@ void CMenus::DemolistFetchCallback(const char *pName, int IsDir, void *pUser)
 	pInfo->m_pSelf->m_lDemos.add(Item);
 }
 
+void CMenus::IsDirCallback(const char *pName, int IsDir, void *pUser)
+{
+	*((bool *)pUser) = true;
+}
+
 void CMenus::DemolistPopulate()
 {
 	m_lDemos.clear();
 	
+	
+	if(strncmp(m_aCurrentDemoFolder, "demos", 256)) //add parent folder
+	{
+		CDemoItem Item;
+		str_copy(Item.m_aName, "..", sizeof(Item.m_aName));
+		str_copy(Item.m_aFilename, "..", sizeof(Item.m_aFilename));
+		m_lDemos.add(Item);
+	}
+	
+	
 	char aBuf[512];
-	str_format(aBuf, sizeof(aBuf), "%s/demos", Client()->UserDirectory());
-
+	str_format(aBuf, sizeof(aBuf), "%s/%s", Client()->UserDirectory(), m_aCurrentDemoFolder);
+	
 	FETCH_CALLBACKINFO Info = {this, aBuf, 0};
 	fs_listdir(aBuf, DemolistFetchCallback, &Info);
-	Info.m_pPrefix = "demos";
-	fs_listdir("demos", DemolistFetchCallback, &Info);
+	Info.m_pPrefix = m_aCurrentDemoFolder;
+	fs_listdir(m_aCurrentDemoFolder, DemolistFetchCallback, &Info);
 }
 
 
@@ -439,22 +455,70 @@ void CMenus::RenderDemoList(CUIRect MainView)
 	RefreshRect.VSplitRight(130.0f, &RefreshRect, &PlayRect);
 	PlayRect.VSplitRight(120.0f, 0x0, &PlayRect);
 	
+	
+	bool IsDir = false;
+	if(!strncmp(m_lDemos[s_SelectedItem].m_aName, "..", 256)) //parent folder
+		IsDir = true;
+	else
+		fs_listdir(m_lDemos[s_SelectedItem].m_aFilename, IsDirCallback, &IsDir);
+	
+	
 	static int s_RefreshButton = 0;
 	if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &RefreshRect))
 	{
 		DemolistPopulate();
 	}
-		
+	
 	static int s_PlayButton = 0;
-	if(DoButton_Menu(&s_PlayButton, Localize("Play"), 0, &PlayRect) || Activated)
+	char aTitleButton[8];
+	if(IsDir)
+		str_copy(aTitleButton, "Open", sizeof(aTitleButton));
+	else
+		str_copy(aTitleButton, "Play", sizeof(aTitleButton));
+	// /!\ TODO: Add "Open" in Localization /!\ 
+	if(DoButton_Menu(&s_PlayButton, Localize(aTitleButton), 0, &PlayRect) || Activated)
 	{		
 		if(s_SelectedItem >= 0 && s_SelectedItem < m_lDemos.size())
 		{
-			const char *pError = Client()->DemoPlayer_Play(m_lDemos[s_SelectedItem].m_aFilename);
-			if(pError)
-				PopupMessage(Localize("Error"), Localize(pError), Localize("Ok"));
+			if(!strncmp(m_lDemos[s_SelectedItem].m_aName, "..", 256))
+			{
+				DemoSetParentDirectory();
+				DemolistPopulate();
+				s_SelectedItem = 0;
+			}
+			else if(IsDir)
+			{
+				str_format(m_aCurrentDemoFolder, sizeof(m_aCurrentDemoFolder), "%s/%s", m_aCurrentDemoFolder, m_lDemos[s_SelectedItem].m_aName);
+				DemolistPopulate();
+				s_SelectedItem = 0;
+			}
+			else
+			{
+				const char *pError = Client()->DemoPlayer_Play(m_lDemos[s_SelectedItem].m_aFilename);
+				if(pError)
+					PopupMessage(Localize("Error"), pError, Localize("Ok"));
+			}
 		}
 	}
 	
 }
 
+
+
+void CMenus::DemoSetParentDirectory()
+{
+	int Stop = 0;
+	int i;
+	for(i = 0; i < 256; i++)
+	{
+		if(m_aCurrentDemoFolder[i] == '/')
+			Stop = i;
+	}
+	
+	//keeps chars which are before the last '/' and remove chars which are after
+	for(i = 0; i < 256; i++)
+	{
+		if(i >= Stop)
+			m_aCurrentDemoFolder[i] = NULL;
+	}
+}
diff --git a/src/game/editor/ed_editor.cpp b/src/game/editor/ed_editor.cpp
index 409890a0..92939bb4 100644
--- a/src/game/editor/ed_editor.cpp
+++ b/src/game/editor/ed_editor.cpp
@@ -556,8 +556,23 @@ CQuad *CEditor::GetSelectedQuad()
 	return 0;
 }
 
-static void CallbackOpenMap(const char *pFileName, void *pUser) { if(((CEditor*)pUser)->Load(pFileName)) str_copy(((CEditor*)pUser)->m_aFileName, pFileName, 512); }
-static void CallbackAppendMap(const char *pFileName, void *pUser) { if(((CEditor*)pUser)->Append(pFileName)) ((CEditor*)pUser)->m_aFileName[0] = 0; }
+static void CallbackOpenMap(const char *pFileName, void *pUser)
+{
+	CEditor *pEditor = (CEditor*)pUser;
+	if(pEditor->Load(pFileName))
+	{
+		str_copy(pEditor->m_aFileName, pFileName, 512);
+		pEditor->SortImages();
+	}
+}
+static void CallbackAppendMap(const char *pFileName, void *pUser)
+{
+	CEditor *pEditor = (CEditor*)pUser;
+	if(pEditor->Append(pFileName))
+		pEditor->m_aFileName[0] = 0;
+	else
+		pEditor->SortImages();
+}
 static void CallbackSaveMap(const char *pFileName, void *pUser){ if(((CEditor*)pUser)->Save(pFileName)) str_copy(((CEditor*)pUser)->m_aFileName, pFileName, 512); }
 
 void CEditor::DoToolbar(CUIRect ToolBar)
@@ -1623,32 +1638,88 @@ void CEditor::RenderLayers(CUIRect ToolBox, CUIRect ToolBar, CUIRect View)
 	if(ValidGroup && m_SelectedLayer >= 0 && m_SelectedLayer < m_Map.m_lGroups[m_SelectedGroup]->m_lLayers.size())
 		ValidLayer = 1;
 
+	int Num = (int)(View.h/16.0f);
+	static int s_ScrollBar = 0;
+	static float s_ScrollValue = 0;
+
+	int LayerNum = 0;
+	for(int g = 0; g < m_Map.m_lGroups.size(); g++)
+		LayerNum += m_Map.m_lGroups[g]->m_lLayers.size() + 1;
+
+	int ScrollNum = LayerNum-Num+10;
+
+	if(LayerNum > Num)	// Do we even need a scrollbar?
+	{
+		CUIRect Scroll;
+		LayersBox.VSplitRight(15.0f, &LayersBox, &Scroll);
+		LayersBox.VSplitRight(3.0f, &LayersBox, 0);	// extra spacing
+		Scroll.HMargin(5.0f, &Scroll);
+		s_ScrollValue = UiDoScrollbarV(&s_ScrollBar, &Scroll, s_ScrollValue);
+
+		if(ScrollNum > 0)
+		{
+			if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP))
+				s_ScrollValue -= 3.0f/ScrollNum;
+			if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN))
+				s_ScrollValue += 3.0f/ScrollNum;
+
+			if(s_ScrollValue < 0) s_ScrollValue = 0;
+			if(s_ScrollValue > 1) s_ScrollValue = 1;
+		}
+		else
+			ScrollNum = 0;
+	}
+
+	int LayerStartAt = (int)(ScrollNum*s_ScrollValue);
+	if(LayerStartAt < 0)
+		LayerStartAt = 0;
+
+	int LayerStopAt = LayerStartAt+Num;
+	int LayerCur = 0;
+
 	// render layers
 	{
 		for(int g = 0; g < m_Map.m_lGroups.size(); g++)
 		{
+			if(LayerCur > LayerStopAt)
+				break;
+			else if(LayerCur + m_Map.m_lGroups[g]->m_lLayers.size() + 1 < LayerStartAt)
+			{
+				LayerCur += m_Map.m_lGroups[g]->m_lLayers.size() + 1;
+				continue;
+			}
+
 			CUIRect VisibleToggle;
-			LayersBox.HSplitTop(12.0f, &Slot, &LayersBox);
-			Slot.VSplitLeft(12, &VisibleToggle, &Slot);
-			if(DoButton_Ex(&m_Map.m_lGroups[g]->m_Visible, m_Map.m_lGroups[g]->m_Visible?"V":"H", 0, &VisibleToggle, 0, Localize("Toggle group visibility"), CUI::CORNER_L))
-				m_Map.m_lGroups[g]->m_Visible = !m_Map.m_lGroups[g]->m_Visible;
-
-			str_format(aBuf, sizeof(aBuf),"#%d %s", g, m_Map.m_lGroups[g]->m_pName);
-			if(int Result = DoButton_Ex(&m_Map.m_lGroups[g], aBuf, g==m_SelectedGroup, &Slot,
-				BUTTON_CONTEXT, Localize("Select group. Right click for properties."), CUI::CORNER_R))
+			if(LayerCur >= LayerStartAt)
 			{
-				m_SelectedGroup = g;
-				m_SelectedLayer = 0;
+				LayersBox.HSplitTop(12.0f, &Slot, &LayersBox);
+				Slot.VSplitLeft(12, &VisibleToggle, &Slot);
+				if(DoButton_Ex(&m_Map.m_lGroups[g]->m_Visible, m_Map.m_lGroups[g]->m_Visible?"V":"H", 0, &VisibleToggle, 0, "Toggle group visibility", CUI::CORNER_L))
+					m_Map.m_lGroups[g]->m_Visible = !m_Map.m_lGroups[g]->m_Visible;
 
-				static int s_GroupPopupId = 0;
-				if(Result == 2)
-					UiInvokePopupMenu(&s_GroupPopupId, 0, UI()->MouseX(), UI()->MouseY(), 120, 200, PopupGroup);
-			}
+				str_format(aBuf, sizeof(aBuf),"#%d %s", g, m_Map.m_lGroups[g]->m_pName);
+				if(int Result = DoButton_Ex(&m_Map.m_lGroups[g], aBuf, g==m_SelectedGroup, &Slot,
+					BUTTON_CONTEXT, "Select group. Right click for properties.", CUI::CORNER_R))
+				{
+					m_SelectedGroup = g;
+					m_SelectedLayer = 0;
 
-			LayersBox.HSplitTop(2.0f, &Slot, &LayersBox);
+					static int s_GroupPopupId = 0;
+					if(Result == 2)
+						UiInvokePopupMenu(&s_GroupPopupId, 0, UI()->MouseX(), UI()->MouseY(), 120, 200, PopupGroup);
+				}
+				LayersBox.HSplitTop(2.0f, &Slot, &LayersBox);
+			}
+			LayerCur++;
 
 			for(int i = 0; i < m_Map.m_lGroups[g]->m_lLayers.size(); i++)
 			{
+				if(LayerCur < LayerStartAt || LayerCur > LayerStopAt)
+				{
+					LayerCur++;
+					continue;
+				}
+
 				//visible
 				LayersBox.HSplitTop(12.0f, &Slot, &LayersBox);
 				Slot.VSplitLeft(12.0f, 0, &Button);
@@ -1668,14 +1739,14 @@ void CEditor::RenderLayers(CUIRect ToolBox, CUIRect ToolBar, CUIRect View)
 						UiInvokePopupMenu(&s_LayerPopupId, 0, UI()->MouseX(), UI()->MouseY(), 120, 150, PopupLayer);
 				}
 
-
+				LayerCur++;
 				LayersBox.HSplitTop(2.0f, &Slot, &LayersBox);
 			}
 			LayersBox.HSplitTop(5.0f, &Slot, &LayersBox);
 		}
 	}
 
-
+	if(LayerCur <= LayerStopAt)
 	{
 		LayersBox.HSplitTop(12.0f, &Slot, &LayersBox);
 
@@ -1687,7 +1758,7 @@ void CEditor::RenderLayers(CUIRect ToolBox, CUIRect ToolBar, CUIRect View)
 		}
 	}
 
-	LayersBox.HSplitTop(5.0f, &Slot, &LayersBox);
+	//LayersBox.HSplitTop(5.0f, &Slot, &LayersBox);
 
 }
 
@@ -1735,6 +1806,7 @@ void CEditor::ReplaceImage(const char *pFileName, void *pUser)
 	*pImg = ImgInfo;
 	ExtractName(pFileName, pImg->m_aName);
 	pImg->m_TexId = pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0);
+	pEditor->SortImages();
 }
 
 void CEditor::AddImage(const char *pFileName, void *pUser)
@@ -1757,6 +1829,7 @@ void CEditor::AddImage(const char *pFileName, void *pUser)
 	}
 
 	pEditor->m_Map.m_lImages.add(pImg);
+	pEditor->SortImages();
 }
 
 
@@ -1819,17 +1892,105 @@ int CEditor::PopupImage(CEditor *pEditor, CUIRect View)
 	return 0;
 }
 
+static int CompareImageName(const void *pObject1, const void *pObject2)
+{
+	CEditorImage *pImage1 = *(CEditorImage**)pObject1;
+	CEditorImage *pImage2 = *(CEditorImage**)pObject2;
+
+	return str_comp(pImage1->m_aName, pImage2->m_aName);
+}
+
+static int *gs_pSortedIndex = 0;
+static void ModifySortedIndex(int *pIndex)
+{
+	if(*pIndex > -1)
+		*pIndex = gs_pSortedIndex[*pIndex];
+}
+
+void CEditor::SortImages()
+{
+	bool Sorted = true;
+	for(int i = 1; i < m_Map.m_lImages.size(); i++)
+		if( str_comp(m_Map.m_lImages[i]->m_aName, m_Map.m_lImages[i-1]->m_aName) < 0 )
+		{
+			Sorted = false;
+			break;
+		}
+
+	if(!Sorted)
+	{
+		array<CEditorImage*> lTemp = array<CEditorImage*>(m_Map.m_lImages);
+		gs_pSortedIndex = new int[lTemp.size()];
+
+		qsort(m_Map.m_lImages.base_ptr(), m_Map.m_lImages.size(), sizeof(CEditorImage*), CompareImageName);
+
+		for(int OldIndex = 0; OldIndex < lTemp.size(); OldIndex++)
+			for(int NewIndex = 0; NewIndex < m_Map.m_lImages.size(); NewIndex++)
+				if(lTemp[OldIndex] == m_Map.m_lImages[NewIndex])
+					gs_pSortedIndex[OldIndex] = NewIndex;
+
+		m_Map.ModifyImageIndex(ModifySortedIndex);
+
+		delete [] gs_pSortedIndex;
+		gs_pSortedIndex = 0;
+	}
+}
+	
 
 void CEditor::RenderImages(CUIRect ToolBox, CUIRect ToolBar, CUIRect View)
 {
+	int Num = (int)(View.h/15.0f);
+	static int s_ScrollBar = 0;
+	static float s_ScrollValue = 0;
+
+	int ImageNum = m_Map.m_lImages.size();
+	int ScrollNum = ImageNum-Num+10;
+
+	if(ImageNum > Num)	// Do we even need a scrollbar?
+	{
+		CUIRect Scroll;
+		ToolBox.VSplitRight(15.0f, &ToolBox, &Scroll);
+		ToolBox.VSplitRight(3.0f, &ToolBox, 0);	// extra spacing
+		Scroll.HMargin(5.0f, &Scroll);
+		s_ScrollValue = UiDoScrollbarV(&s_ScrollBar, &Scroll, s_ScrollValue);
+
+		if(ScrollNum > 0)
+		{
+			if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP))
+				s_ScrollValue -= 3.0f/ScrollNum;
+			if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN))
+				s_ScrollValue += 3.0f/ScrollNum;
+
+			if(s_ScrollValue < 0) s_ScrollValue = 0;
+			if(s_ScrollValue > 1) s_ScrollValue = 1;
+		}
+		else
+			ScrollNum = 0;
+	}
+
+	int ImageStartAt = (int)(ScrollNum*s_ScrollValue);
+	if(ImageStartAt < 0)
+		ImageStartAt = 0;
+
+	int ImageStopAt = ImageStartAt+Num;
+	int ImageCur = 0;
+
 	for(int e = 0; e < 2; e++) // two passes, first embedded, then external
 	{
 		CUIRect Slot;
-		ToolBox.HSplitTop(15.0f, &Slot, &ToolBox);
-		if(e == 0)
-			UI()->DoLabel(&Slot, Localize("Embedded"), 12.0f, 0);
-		else
-			UI()->DoLabel(&Slot, Localize("External"), 12.0f, 0);
+
+		if(ImageCur > ImageStopAt)
+			break;
+		else if(ImageCur >= ImageStartAt)
+		{
+
+			ToolBox.HSplitTop(15.0f, &Slot, &ToolBox);
+			if(e == 0)
+				UI()->DoLabel(&Slot, Localize(""Embedded"), 12.0f, 0);
+			else
+				UI()->DoLabel(&Slot, Localize(""External"), 12.0f, 0);
+		}
+		ImageCur++;
 
 		for(int i = 0; i < m_Map.m_lImages.size(); i++)
 		{
@@ -1839,6 +2000,15 @@ void CEditor::RenderImages(CUIRect ToolBox, CUIRect ToolBar, CUIRect View)
 				continue;
 			}
 
+			if(ImageCur > ImageStopAt)
+				break;
+			else if(ImageCur < ImageStartAt)
+			{
+				ImageCur++;
+				continue;
+			}
+			ImageCur++;
+
 			char aBuf[128];
 			str_copy(aBuf, m_Map.m_lImages[i]->m_aName, sizeof(aBuf));
 			ToolBox.HSplitTop(12.0f, &Slot, &ToolBox);
@@ -2566,7 +2736,7 @@ void CEditor::Render()
 
 		View.HSplitTop(16.0f, &MenuBar, &View);
 		View.HSplitTop(53.0f, &ToolBar, &View);
-		View.VSplitLeft(80.0f, &ToolBox, &View);
+		View.VSplitLeft(100.0f, &ToolBox, &View);
 		View.HSplitBottom(16.0f, &View, &StatusBar);
 
 		if(m_ShowEnvelopeEditor)
diff --git a/src/game/editor/ed_editor.h b/src/game/editor/ed_editor.h
index d027c162..a7d742a8 100644
--- a/src/game/editor/ed_editor.h
+++ b/src/game/editor/ed_editor.h
@@ -608,6 +608,7 @@ public:
 	void RenderFileDialog();
 
 	void AddFileDialogEntry(const char *pName, CUIRect *pView);
+	void SortImages();
 };
 
 // make sure to inline this function
diff --git a/src/game/server/entities/character.h b/src/game/server/entities/character.h
index a1add982..bea0c002 100644
--- a/src/game/server/entities/character.h
+++ b/src/game/server/entities/character.h
@@ -57,7 +57,7 @@ public:
 	
 	void SetEmote(int Emote, int Tick);
 	
-	const bool IsAlive() { return m_Alive; }
+	bool IsAlive() const { return m_Alive; }
 	class CPlayer *GetPlayer() { return m_pPlayer; }
 	
 private:
diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp
index 519a28ae..66d84519 100644
--- a/src/game/server/gamecontroller.cpp
+++ b/src/game/server/gamecontroller.cpp
@@ -308,7 +308,7 @@ void IGameController::OnPlayerInfoChange(class CPlayer *pP)
 int IGameController::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon)
 {
 	// do scoreing
-	if(!pKiller)
+	if(!pKiller || Weapon == WEAPON_GAME)
 		return 0;
 	if(pKiller == pVictim->GetPlayer())
 		pVictim->GetPlayer()->m_Score--; // suicide
diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp
index 8e58b7c1..c295b5d5 100644
--- a/src/game/server/player.cpp
+++ b/src/game/server/player.cpp
@@ -156,9 +156,9 @@ void CPlayer::SetTeam(int Team)
 	GameServer()->SendChat(-1, CGameContext::CHAT_ALL, Buf); 
 	
 	KillCharacter();
+
 	m_Team = Team;
-	m_Score = 0;
-	m_ScoreStartTick = Server()->Tick();
+	//m_ScoreStartTick = Server()->Tick();
 	// we got to wait 0.5 secs before respawning
 	m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2;
 	dbg_msg("game", "team_join player='%d:%s' m_Team=%d", m_ClientID, Server()->ClientName(m_ClientID), m_Team);