about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--data/languages/dutch.txt204
-rw-r--r--data/languages/german.txt4
-rw-r--r--datasrc/content.py4
-rw-r--r--src/base/system.c19
-rw-r--r--src/engine/client/client.cpp13
-rw-r--r--src/engine/client/graphics.cpp4
-rw-r--r--src/engine/client/text.cpp2
-rw-r--r--src/engine/console.h4
-rw-r--r--src/engine/server/register.cpp17
-rw-r--r--src/engine/server/server.cpp17
-rw-r--r--src/engine/shared/console.cpp25
-rw-r--r--src/engine/shared/console.h7
-rw-r--r--src/engine/shared/demorec.cpp2
-rw-r--r--src/engine/shared/ringbuffer.cpp2
-rw-r--r--src/engine/shared/storage.cpp3
-rw-r--r--src/game/client/components/console.cpp85
-rw-r--r--src/game/client/components/console.h8
-rw-r--r--src/game/client/components/hud.cpp77
-rw-r--r--src/game/client/components/items.cpp2
-rw-r--r--src/game/client/components/maplayers.cpp2
-rw-r--r--src/game/client/components/menus.h1
-rw-r--r--src/game/client/components/menus_browser.cpp12
-rw-r--r--src/game/client/components/menus_demo.cpp36
-rw-r--r--src/game/client/components/players.cpp2
-rw-r--r--src/game/editor/ed_editor.cpp141
-rw-r--r--src/game/editor/ed_popups.cpp5
-rw-r--r--src/game/server/entities/character.cpp16
-rw-r--r--src/game/server/gamecontroller.cpp3
28 files changed, 458 insertions, 259 deletions
diff --git a/data/languages/dutch.txt b/data/languages/dutch.txt
index 6804423b..bb1f7480 100644
--- a/data/languages/dutch.txt
+++ b/data/languages/dutch.txt
@@ -75,7 +75,7 @@ Demos
 == Demos
 
 Disconnect
-== Verbinding verbreken
+== Stoppen
 
 Disconnected
 == Verbinding verbroken
@@ -282,7 +282,7 @@ Players
 == Spelers
 
 Please balance teams!
-== Balanceer teams
+== Breng teams in balans!
 
 Prev. weapon
 == Vorig wapen
@@ -405,7 +405,7 @@ Teeworlds %s is out! Download it at www.teeworlds.com!
 == Teeworld %s is uit! Download het op www.teeworlds.com!
 
 Texture Compression
-== Tekst verkleinen
+== Structuur verkleinen
 
 The server is running a non-standard tuning on a pure game type.
 == The server draait geen standaard spel type.
@@ -461,310 +461,310 @@ Your skin
 ##### needs translation ####
 
 Open map
-== Open map
+== Open kaart
 
 Open
 == Open
 
 Save map
-== Save map
+== Sla kaart op
 
 Save
-== Save
+== Opslaan
 
 HD
-== HD
+== Det.
 
 [ctrl+h] Toggle High Detail
-== [ctrl+h] Toggle High Detail
+== [ctrl+h] Activeer Details
 
 Anim
-== Anim
+== Anim.
 
 [ctrl+m] Toggle animation
-== [ctrl+m] Toggle animation
+== [ctrl+m] Activeer animaties
 
 Proof
-== Proof
+== Test
 
 [ctrl+p] Toggles proof borders. These borders represent what a player maximum can see.
-== [ctrl+p] Toggles proof borders. These borders represent what a player maximum can see.
+== [ctrl+p] Test grenzen. Deze grenzen laten zien wat een speler maximaal kan zien.
 
 ZO
 == ZO
 
 [NumPad-] Zoom out
-== [NumPad-] Zoom out
+== [NumPad-] Uitzoomen
 
 [NumPad*] Zoom to normal and remove editor offset
-== [NumPad*] Zoom to normal and remove editor offset
+== [NumPad*] Zoom naar normaal en verwijder toevoegingen van de editor 
 
 ZI
 == ZI
 
 [NumPad+] Zoom in
-== [NumPad+] Zoom in
+== [NumPad+] Inzoomen
 
 Increase animation speed
-== Increase animation speed
+== Vergroot animatie snelheid
 
 Normal animation speed
-== Normal animation speed
+== Normale animatie snelheid
 
 Decrease animation speed
-== Decrease animation speed
+== Verklein animatie snelheid
 
 [N] Flip brush horizontal
-== [N] Flip brush horizontal
+== [N] Draai kwast horizontaal
 
 [M] Flip brush vertical
-== [M] Flip brush vertical
+== [M] Draai kwast verticaal
 
 CCW
 == CCW
 
 [R] Rotates the brush counter clockwise
-== [R] Rotates the brush counter clockwise
+== [R] Draai de kwast tegen de klok in
 
 CW
 == CW
 
 [T] Rotates the brush clockwise
-== [T] Rotates the brush clockwise
+== [T] Draai de kwast met de klok mee
 
 Add Quad
-== Add Quad
+== Voeg Quad toe
 
 Adds a new quad
-== Adds a new quad
+== Voegt een nieuwe Quad toe
 
 Border
-== Border
+== Grens
 
 Left mouse button to move. Hold shift to move pivot. Hold ctrl to rotate.
-== Left mouse button to move. Hold shift to move pivot. Hold ctrl to rotate.
+== Linkermuisknop om te bewegen. Druk shift in om te roteren. Druk ctrl om te draaien.
 
 Left mouse button to move. Hold shift to move the texture.
-== Left mouse button to move. Hold shift to move the texture.
+== Linkermuisknop om te bewegen. Druk shift in om de textuur te bewegen
 
 Use left mouse button to drag and create a brush.
-== Use left mouse button to drag and create a brush.
+== Gebruik de linkermuisknop om de kwast te maken en te slepen.
 
 Use left mouse button to paint with the brush. Right button clears the brush.
-== Use left mouse button to paint with the brush. Right button clears the brush.
+== Gebruik de linkermuisknop om de kwast te gebruiken. Rechtermuisknop maakt de kwast schoon. 
 
 Decrease
-== Decrease
+== Verkleinen
 
 Increase
-== Increase
+== Vergroten
 
 None
-== None
+== Geen
 
 Toggle group visibility
-== Toggle group visibility
+== Acitveer groepszichtbaarheid
 
 Select group. Right click for properties.
-== Select group. Right click for properties.
+== Kies een groep. Rechtermuisknop voor eigenschappen.
 
 Add group
-== Add group
+== Voeg groep toe
 
 Adds a new group
-== Adds a new group
+== Voegt een nieuwe groep toe
 
 Embed
-== Embed
+== Insluiten
 
 Embeds the image into the map file.
-== Embeds the image into the map file.
+== Sluit een afbeelding in in het bestand van de kaart
 
 Make external
-== Make external
+== Maak extern
 
 Removes the image from the map file.
-== Removes the image from the map file.
+== Verwijderd de afbeelding uit de kaart.
 
 Replace
-== Replace
+== Vervang
 
 Replaces the image with a new one
-== Replaces the image with a new one
+== Vervangt de afbeelding met een nieuwe
 
 Replace Image
-== Replace Image
+== Vervang afbeelding
 
 Remove
-== Remove
+== Verwijder
 
 Removes the image from the map
-== Removes the image from the map
+== Verwijderd de afbeelding uit de kaart
 
 Embedded
-== Embedded
+== Ingesloten
 
 External
-== External
+== Extern
 
 Select image
-== Select image
+== Selecteer afbeelding
 
 Load a new image to use in the map
-== Load a new image to use in the map
+== Laad een nieuwe afbeelding om te gebruiken in de kaart
 
 Add Image
-== Add Image
+== Voeg afbeelding toe
 
 Add
-== Add
+== Voeg toe
 
 Filename:
-== Filename:
+== Bestandsnaam:
 
 Cancel
-== Cancel
+== Annuleren
 
 Layers
-== Layers
+== Lagen
 
 Images
-== Images
+== Afbeeldingen
 
 Switch between images and layers managment.
-== Switch between images and layers managment.
+== Wissel tussen afbeeldinglaag en beheerlaag.
 
 Envelopes
 == Envelopes
 
 Toggles the envelope editor.
-== Toggles the envelope editor.
+== Activeer de envelope editor.
 
 %s Right click for context menu.
-== %s Right click for context menu.
+== %s Rechtermuisknop voor context menu.
 
 Color+
-== Color+
+== Kleur+
 
 Creates a new color envelope
-== Creates a new color envelope
+== Maakt een nieuwe kleur envelope
 
 Pos.+
 == Pos.+
 
 Creates a new pos envelope
-== Creates a new pos envelope
+== Maakt een nieuwe pos envelope
 
 Previous Envelope
-== Previous Envelope
+== Vorige envelope
 
 Next Envelope
-== Next Envelope
+== Volgende envelope
 
 Name:
-== Name:
+== Naam:
 
 Press right mouse button to create a new point
-== Press right mouse button to create a new point
+== Rechtermuisknop om een nieuw punt te maken
 
 Switch curve type
-== Switch curve type
+== Wissel bocht type
 
 Left mouse to drag. Hold shift to alter time point aswell. Right click to delete.
-== Left mouse to drag. Hold shift to alter time point aswell. Right click to delete.
+== Linkermuisknop om te slepen. Druk shift in om het punt te veranderen. Rechtermuisknop om te verwijderen.
 
 New
-== New
+== Nieuw
 
 Creates a new map
-== Creates a new map
+== Maakt een nieuwe kaart.
 
 Opens a map for editing
-== Opens a map for editing
+== Opent een kaart om te bewerken
 
 Append
-== Append
+== Toevoegen
 
 Opens a map and adds everything from that map to the current one
-== Opens a map and adds everything from that map to the current one
+== Opent een kaart en voegt alles van die kaart toe aan de huidige
 
 Append map
-== Append map
+== Voeg kaart toe
 
 Saves the current map
-== Saves the current map
+== Sla huidige kaart op
 
 Save As
-== Save As
+== Opslaan als
 
 Saves the current map under a new name
-== Saves the current map under a new name
+== Sla de huidige kaart op onder een nieuwe naam
 
 Exits from the editor
-== Exits from the editor
+== Verlaat de editor
 
 Clear collision
-== Clear collision
+== Verwijder botsingen
 
 Removes collision from this layer
-== Removes collision from this layer
+== Verwijderd botsingen in deze laag
 
 Make collision
-== Make collision
+== Maak botsing
 
 Constructs collision from this layer
-== Constructs collision from this layer
+== Maakt botsing van deze laag
 
 Width
-== Width
+== Breedte
 
 Height
-== Height
+== Hoogte
 
 Image
-== Image
+== Afbeelding
 
 Delete group
-== Delete group
+== Verwijder groep
 
 Add quads layer
-== Add quads layer
+== Voeg quads laag toe
 
 Creates a new quad layer
-== Creates a new quad layer
+== Maakt een nieuwe quads laag
 
 Add tile layer
-== Add tile layer
+== Voeg tegel laag toe
 
 Creates a new tile layer
-== Creates a new tile layer
+== Maakt een nieuwe tegel laag
 
 Delete layer
-== Delete Layer
+== Verwijder laag
 
 Deletes the layer
-== Deletes the layer
+== Verwijdert de laag
 
 Group
-== Group
+== Groep
 
 Order
-== Order
+== Volgorde
 
 Detail
 == Detail
 
 Delete
-== Delete
+== Verwijder
 
 Deletes the current quad
-== Deletes the current quad
+== Verwijdert de huidige quad
 
 Square
-== Square
+== Vereffenen
 
 Squares the current quad
-== Squares the current quad
+== Vereffenen de huidige quad
 
 Pos. Env
 == Pos. Env
@@ -773,18 +773,18 @@ Pos. TO
 == Pos. TO
 
 Color Env
-== Color Env
+== Kleur Env
 
 Color TO
-== Color TO
+== Kleur TO
 
 Select layer. Right click for properties.
-== Select layer. Right click for properties.
+== Selecteer laag. Rechtermuisknop voor eigenschappen.
 
 Toggle layer visibility
-== Toggle layer visibility
+== Activeer zichtbaarheid laag
 
 File
-== File
+== Bestand
 
 ##### old translations ####
diff --git a/data/languages/german.txt b/data/languages/german.txt
index 8bea5723..81fca269 100644
--- a/data/languages/german.txt
+++ b/data/languages/german.txt
@@ -260,7 +260,7 @@ Pistol
 == Pistole
 
 Play
-== Spielen
+== Abspielen
 
 Player
 == Spieler
@@ -455,7 +455,7 @@ Sudden Death
 == Noch %ds
 
 error loading demo
-== Fehler beim Laden der Demo, die Datei ist nicht gültig.
+== Fehler beim Laden der Demo, die Datei ist ungültig.
 
 Error
 == Fehlgeschlagen
diff --git a/datasrc/content.py b/datasrc/content.py
index 2c353f24..e510a19f 100644
--- a/datasrc/content.py
+++ b/datasrc/content.py
@@ -305,7 +305,7 @@ container.sprites.Add(Sprite("weapon_hammer_body", set_game, 2,1,4,3))
 container.sprites.Add(Sprite("weapon_hammer_cursor", set_game, 0,0,2,2))
 container.sprites.Add(Sprite("weapon_hammer_proj", set_game, 0,0,0,0))
 
-container.sprites.Add(Sprite("weapon_ninja_body", set_game, 2,10,7,2))
+container.sprites.Add(Sprite("weapon_ninja_body", set_game, 2,10,8,2))
 container.sprites.Add(Sprite("weapon_ninja_cursor", set_game, 0,10,2,2))
 container.sprites.Add(Sprite("weapon_ninja_proj", set_game, 0,0,0,0))
 
@@ -323,7 +323,7 @@ container.sprites.Add(Sprite("weapon_ninja_muzzle3", set_game, 25,8,7,4))
 container.sprites.Add(Sprite("pickup_health", set_game, 10,2,2,2))
 container.sprites.Add(Sprite("pickup_armor", set_game, 12,2,2,2))
 container.sprites.Add(Sprite("pickup_weapon", set_game, 3,0,6,2))
-container.sprites.Add(Sprite("pickup_ninja", set_game, 3,10,7,2))
+container.sprites.Add(Sprite("pickup_ninja", set_game, 2,10,8,2))
 
 container.sprites.Add(Sprite("flag_blue", set_game, 12,8,4,8))
 container.sprites.Add(Sprite("flag_red", set_game, 16,8,4,8))
diff --git a/src/base/system.c b/src/base/system.c
index a1a1b33e..457b761a 100644
--- a/src/base/system.c
+++ b/src/base/system.c
@@ -262,7 +262,23 @@ int mem_check_imp()
 IOHANDLE io_open(const char *filename, int flags)
 {
 	if(flags == IOFLAG_READ)
+	{
+	#if defined(CONF_FAMILY_WINDOWS)
+		// check for filename case sensitive
+		WIN32_FIND_DATA finddata;
+		HANDLE handle;
+		int length;
+		
+		length = str_length(filename);
+		if(!filename || !length || filename[length-1] == '\\')
+			return 0x0;
+		handle = FindFirstFile(filename, &finddata);
+		if(handle == INVALID_HANDLE_VALUE || str_comp(filename+length-str_length(finddata.cFileName), finddata.cFileName))
+			return 0x0;
+		FindClose(handle);
+	#endif
 		return (IOHANDLE)fopen(filename, "rb");
+	}
 	if(flags == IOFLAG_WRITE)
 		return (IOHANDLE)fopen(filename, "wb");
 	return 0x0;
@@ -863,7 +879,8 @@ int fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, void *user)
 	/* add all the entries */
 	do
 	{
-		cb(finddata.cFileName, 0, user);
+		if(finddata.cFileName[0] != '.')
+			cb(finddata.cFileName, 0, user);
 	} while (FindNextFileA(handle, &finddata));
 
 	FindClose(handle);
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp
index 613a8137..eae5ef3a 100644
--- a/src/engine/client/client.cpp
+++ b/src/engine/client/client.cpp
@@ -1123,6 +1123,7 @@ void CClient::ProcessPacket(CNetChunk *pPacket)
 						int DeltaSize;
 						unsigned char aTmpBuffer2[CSnapshot::MAX_SIZE];
 						unsigned char aTmpBuffer3[CSnapshot::MAX_SIZE];
+						CSnapshot *pTmpBuffer3 = (CSnapshot*)aTmpBuffer3;	// Fix compiler warning for strict-aliasing
 						int SnapSize;
 
 						CompleteSize = (NumParts-1) * MAX_SNAPSHOT_PACKSIZE + PartSize;
@@ -1169,19 +1170,19 @@ void CClient::ProcessPacket(CNetChunk *pPacket)
 
 						// unpack delta
 						PurgeTick = DeltaTick;
-						SnapSize = m_SnapshotDelta.UnpackDelta(pDeltaShot, (CSnapshot*)aTmpBuffer3, pDeltaData, DeltaSize);
+						SnapSize = m_SnapshotDelta.UnpackDelta(pDeltaShot, pTmpBuffer3, pDeltaData, DeltaSize);
 						if(SnapSize < 0)
 						{
 							dbg_msg("client", "delta unpack failed!");
 							return;
 						}
 
-						if(Msg != NETMSG_SNAPEMPTY && ((CSnapshot*)aTmpBuffer3)->Crc() != Crc)
+						if(Msg != NETMSG_SNAPEMPTY && pTmpBuffer3->Crc() != Crc)
 						{
 							if(g_Config.m_Debug)
 							{
 								dbg_msg("client", "snapshot crc error #%d - tick=%d wantedcrc=%d gotcrc=%d compressed_size=%d delta_tick=%d",
-									m_SnapCrcErrors, GameTick, Crc, ((CSnapshot*)aTmpBuffer3)->Crc(), CompleteSize, DeltaTick);
+									m_SnapCrcErrors, GameTick, Crc, pTmpBuffer3->Crc(), CompleteSize, DeltaTick);
 							}
 
 							m_SnapCrcErrors++;
@@ -1209,13 +1210,13 @@ void CClient::ProcessPacket(CNetChunk *pPacket)
 						m_SnapshotStorage.PurgeUntil(PurgeTick);
 
 						// add new
-						m_SnapshotStorage.Add(GameTick, time_get(), SnapSize, (CSnapshot*)aTmpBuffer3, 1);
+						m_SnapshotStorage.Add(GameTick, time_get(), SnapSize, pTmpBuffer3, 1);
 
 						// add snapshot to demo
 						if(m_DemoRecorder.IsRecording())
 						{
 							// write snapshot
-							m_DemoRecorder.RecordSnapshot(GameTick, aTmpBuffer3, SnapSize);
+							m_DemoRecorder.RecordSnapshot(GameTick, pTmpBuffer3, SnapSize);
 						}
 
 						// apply snapshot, cycle pointers
@@ -1963,7 +1964,7 @@ int main(int argc, const char **argv) // ignore_convention
 	m_Client.RegisterInterfaces();
 
 	// create the components
-	IConsole *pConsole = CreateConsole();
+	IConsole *pConsole = CreateConsole(CFGFLAG_CLIENT);
 	IStorage *pStorage = CreateStorage("Teeworlds", argv[0]); // ignore_convention
 	IConfig *pConfig = CreateConfig();
 	IEngineGraphics *pEngineGraphics = CreateEngineGraphics();
diff --git a/src/engine/client/graphics.cpp b/src/engine/client/graphics.cpp
index e2f4ae4c..bf3f42ea 100644
--- a/src/engine/client/graphics.cpp
+++ b/src/engine/client/graphics.cpp
@@ -422,7 +422,11 @@ void CGraphics_OpenGL::ScreenshotDirect(const char *pFilename)
 	int h = m_ScreenHeight;
 	unsigned char *pPixelData = (unsigned char *)mem_alloc(w*(h+1)*3, 1);
 	unsigned char *pTempRow = pPixelData+w*h*3;
+	GLint Alignment;
+	glGetIntegerv(GL_PACK_ALIGNMENT, &Alignment);
+	glPixelStorei(GL_PACK_ALIGNMENT, 1);
 	glReadPixels(0,0, w, h, GL_RGB, GL_UNSIGNED_BYTE, pPixelData);
+	glPixelStorei(GL_PACK_ALIGNMENT, Alignment);
 	
 	// flip the pixel because opengl works from bottom left corner
 	for(y = 0; y < h/2; y++)
diff --git a/src/engine/client/text.cpp b/src/engine/client/text.cpp
index 57e1b43b..8fa8efee 100644
--- a/src/engine/client/text.cpp
+++ b/src/engine/client/text.cpp
@@ -681,7 +681,7 @@ public:
 						Advance = pChr->m_AdvanceX + Kerning(pFont, Character, Nextcharacter)/Size;
 					}
 									
-					if(pCursor->m_Flags&TEXTFLAG_STOP_AT_END && DrawX+Advance*Size-pCursor->m_StartX > pCursor->m_LineWidth)
+					if(pCursor->m_Flags&TEXTFLAG_STOP_AT_END && DrawX+(Advance+pChr->m_Width)*Size-pCursor->m_StartX > pCursor->m_LineWidth)
 					{
 						// we hit the end of the line, no more to render or count
 						pCurrent = pEnd;
diff --git a/src/engine/console.h b/src/engine/console.h
index 74d789e9..34fa4272 100644
--- a/src/engine/console.h
+++ b/src/engine/console.h
@@ -37,7 +37,7 @@ public:
 	typedef void (*FCommandCallback)(IResult *pResult, void *pUserData);
 	typedef void (*FChainCommandCallback)(IResult *pResult, void *pUserData, FCommandCallback pfnCallback, void *pCallbackUserData);
 
-	virtual CCommandInfo *GetCommandInfo(const char *pName) = 0;
+	virtual CCommandInfo *GetCommandInfo(const char *pName, int FlagMask) = 0;
 	virtual void PossibleCommands(const char *pStr, int FlagMask, FPossibleCallback pfnCallback, void *pUser) = 0;
 	virtual void ParseArguments(int NumArgs, const char **ppArguments) = 0;
 
@@ -53,6 +53,6 @@ public:
 	virtual void Print(const char *pStr) = 0;
 };
 
-extern IConsole *CreateConsole();
+extern IConsole *CreateConsole(int FlagMask);
 
 #endif // FILE_ENGINE_CONSOLE_H
diff --git a/src/engine/server/register.cpp b/src/engine/server/register.cpp
index 959b9288..5e49f499 100644
--- a/src/engine/server/register.cpp
+++ b/src/engine/server/register.cpp
@@ -231,6 +231,23 @@ void CRegister::RegisterUpdate()
 
 int CRegister::RegisterProcessPacket(CNetChunk *pPacket)
 {
+	// check for masterserver address
+	bool Valid = false;
+	NETADDR Addr1 = pPacket->m_Address;
+	Addr1.port = 0;
+	for(int i = 0; i < IMasterServer::MAX_MASTERSERVERS; i++)
+	{
+		NETADDR Addr2 = m_aMasterserverInfo[i].m_Addr;
+		Addr2.port = 0;
+		if(net_addr_comp(&Addr1, &Addr2) == 0)
+		{
+			Valid = true;
+			break;
+		}
+	}
+	if(!Valid)
+		return 0;
+			
 	if(pPacket->m_DataSize == sizeof(SERVERBROWSE_FWCHECK) &&
 		mem_comp(pPacket->m_pData, SERVERBROWSE_FWCHECK, sizeof(SERVERBROWSE_FWCHECK)) == 0)
 	{
diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp
index 620599c8..c45b2dd4 100644
--- a/src/engine/server/server.cpp
+++ b/src/engine/server/server.cpp
@@ -427,6 +427,7 @@ void CServer::DoSnapshot()
 			
 		{
 			char aData[CSnapshot::MAX_SIZE];
+			CSnapshot *pData = (CSnapshot*)aData;	// Fix compiler warning for strict-aliasing
 			char aDeltaData[CSnapshot::MAX_SIZE];
 			char aCompData[CSnapshot::MAX_SIZE];
 			int SnapshotSize;
@@ -442,15 +443,15 @@ void CServer::DoSnapshot()
 			GameServer()->OnSnap(i);
 
 			// finish snapshot
-			SnapshotSize = m_SnapshotBuilder.Finish(aData);
-			Crc = ((CSnapshot*)aData)->Crc();
+			SnapshotSize = m_SnapshotBuilder.Finish(pData);
+			Crc = pData->Crc();
 
 			// remove old snapshos
 			// keep 3 seconds worth of snapshots
 			m_aClients[i].m_Snapshots.PurgeUntil(m_CurrentGameTick-SERVER_TICK_SPEED*3);
 			
 			// save it the snapshot
-			m_aClients[i].m_Snapshots.Add(m_CurrentGameTick, time_get(), SnapshotSize, aData, 0);
+			m_aClients[i].m_Snapshots.Add(m_CurrentGameTick, time_get(), SnapshotSize, pData, 0);
 			
 			// find snapshot that we can preform delta against
 			EmptySnap.Clear();
@@ -468,7 +469,7 @@ void CServer::DoSnapshot()
 			}
 			
 			// create delta
-			DeltaSize = m_SnapshotDelta.CreateDelta(pDeltashot, (CSnapshot*)aData, aDeltaData);
+			DeltaSize = m_SnapshotDelta.CreateDelta(pDeltashot, pData, aDeltaData);
 			
 			if(DeltaSize)
 			{
@@ -554,9 +555,9 @@ void CServer::SendMap(int ClientId)
 {
 	//get the name of the map without his path
 	char * pMapShortName = &g_Config.m_SvMap[0];
-	for(int i = 0; i < 128; i++)
+	for(int i = 0; i < str_length(g_Config.m_SvMap)-1; i++)
 	{
-		if(g_Config.m_SvMap[i] == '/' || g_Config.m_SvMap[i] == '\\' && i+1 < 128)
+		if(g_Config.m_SvMap[i] == '/' || g_Config.m_SvMap[i] == '\\')
 			pMapShortName = &g_Config.m_SvMap[i+1];
 	}
 	
@@ -1066,7 +1067,7 @@ int CServer::Run()
 					
 					for(int c = 0; c < MAX_CLIENTS; c++)
 					{
-						if(m_aClients[c].m_State == CClient::STATE_EMPTY)
+						if(m_aClients[c].m_State <= CClient::STATE_AUTH)
 							continue;
 						
 						SendMap(c);
@@ -1390,7 +1391,7 @@ int main(int argc, const char **argv) // ignore_convention
 	// create the components
 	IEngineMap *pEngineMap = CreateEngineMap();
 	IGameServer *pGameServer = CreateGameServer();
-	IConsole *pConsole = CreateConsole();
+	IConsole *pConsole = CreateConsole(CFGFLAG_SERVER);
 	IEngineMasterServer *pEngineMasterServer = CreateEngineMasterServer();
 	IStorage *pStorage = CreateStorage("Teeworlds", argv[0]); // ignore_convention
 	IConfig *pConfig = CreateConfig();
diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp
index eacf9b78..b7850bea 100644
--- a/src/engine/shared/console.cpp
+++ b/src/engine/shared/console.cpp
@@ -210,7 +210,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr)
 		if(ParseStart(&Result, pStr, (pEnd-pStr) + 1) != 0)
 			return;
 
-		CCommand *pCommand = FindCommand(Result.m_pCommand);
+		CCommand *pCommand = FindCommand(Result.m_pCommand, m_FlagMask);
 
 		if(pCommand)
 		{
@@ -234,7 +234,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr)
 					pCommand->m_pfnCallback(&Result, pCommand->m_pUserData);
 			}
 		}
-		else
+		else if(Stroke)
 		{
 			char aBuf[256];
 			str_format(aBuf, sizeof(aBuf), "No such command: %s.", Result.m_pCommand);
@@ -258,14 +258,16 @@ void CConsole::PossibleCommands(const char *pStr, int FlagMask, FPossibleCallbac
 	}	
 }
 
-// TODO: this should regard the commands flag
-CConsole::CCommand *CConsole::FindCommand(const char *pName)
+CConsole::CCommand *CConsole::FindCommand(const char *pName, int FlagMask)
 {
 	CCommand *pCommand;
 	for (pCommand = m_pFirstCommand; pCommand; pCommand = pCommand->m_pNext)
 	{
-		if(str_comp_nocase(pCommand->m_pName, pName) == 0)
-			return pCommand;
+		if(pCommand->m_Flags&FlagMask)
+		{
+			if(str_comp_nocase(pCommand->m_pName, pName) == 0)
+				return pCommand;
+		}
 	}	
 	
 	return 0x0;
@@ -385,8 +387,9 @@ static void StrVariableCommand(IConsole::IResult *pResult, void *pUserData)
 	}
 }
 
-CConsole::CConsole()
+CConsole::CConsole(int FlagMask)
 {
+	m_FlagMask = FlagMask;
 	m_pFirstCommand = 0;
 	m_pFirstExec = 0;
 	m_pPrintCallbackUserdata = 0;
@@ -459,7 +462,7 @@ void CConsole::Con_Chain(IResult *pResult, void *pUserData)
 
 void CConsole::Chain(const char *pName, FChainCommandCallback pfnChainFunc, void *pUser)
 {
-	CCommand *pCommand = FindCommand(pName);
+	CCommand *pCommand = FindCommand(pName, m_FlagMask);
 	
 	if(!pCommand)
 	{
@@ -481,10 +484,10 @@ void CConsole::Chain(const char *pName, FChainCommandCallback pfnChainFunc, void
 }
 
 
-IConsole::CCommandInfo *CConsole::GetCommandInfo(const char *pName)
+IConsole::CCommandInfo *CConsole::GetCommandInfo(const char *pName, int FlagMask)
 {
-	return FindCommand(pName);
+	return FindCommand(pName, FlagMask);
 }
 
 
-extern IConsole *CreateConsole() { return new CConsole(); }
+extern IConsole *CreateConsole(int FlagMask) { return new CConsole(FlagMask); }
diff --git a/src/engine/shared/console.h b/src/engine/shared/console.h
index 93d23547..9064fa86 100644
--- a/src/engine/shared/console.h
+++ b/src/engine/shared/console.h
@@ -24,6 +24,7 @@ class CConsole : public IConsole
 		void *m_pUserData;
 	};	
 	
+	int m_FlagMask;
 	CCommand *m_pFirstCommand;
 
 	class CExecFile
@@ -74,12 +75,12 @@ class CConsole : public IConsole
 	int ParseStart(CResult *pResult, const char *pString, int Length);
 	int ParseArgs(CResult *pResult, const char *pFormat);
 
-	CCommand *FindCommand(const char *pName);
+	CCommand *FindCommand(const char *pName, int FlagMask);
 
 public:
-	CConsole();
+	CConsole(int FlagMask);
 
-	virtual CCommandInfo *GetCommandInfo(const char *pName);
+	virtual CCommandInfo *GetCommandInfo(const char *pName, int FlagMask);
 	virtual void PossibleCommands(const char *pStr, int FlagMask, FPossibleCallback pfnCallback, void *pUser) ;
 
 	virtual void ParseArguments(int NumArgs, const char **ppArguments);
diff --git a/src/engine/shared/demorec.cpp b/src/engine/shared/demorec.cpp
index 48b06e9a..6c2ba07d 100644
--- a/src/engine/shared/demorec.cpp
+++ b/src/engine/shared/demorec.cpp
@@ -335,7 +335,7 @@ void CDemoPlayer::DoTick()
 	static char aDecompressed[CSnapshot::MAX_SIZE];
 	static char aData[CSnapshot::MAX_SIZE];
 	int ChunkType, ChunkTick, ChunkSize;
-	int DataSize;
+	int DataSize = 0;
 	int GotSnapshot = 0;
 
 	// update ticks
diff --git a/src/engine/shared/ringbuffer.cpp b/src/engine/shared/ringbuffer.cpp
index 45a845ee..b84db5a3 100644
--- a/src/engine/shared/ringbuffer.cpp
+++ b/src/engine/shared/ringbuffer.cpp
@@ -98,7 +98,7 @@ void *CRingBufferBase::Allocate(int Size)
 	// okey, we have our block
 	
 	// split the block if needed
-	if(pBlock->m_Size > WantedSize+sizeof(CItem))
+	if(pBlock->m_Size > WantedSize+(int)sizeof(CItem))
 	{
 		CItem *pNewItem = (CItem *)((char *)pBlock + WantedSize);
 		pNewItem->m_pPrev = pBlock;
diff --git a/src/engine/shared/storage.cpp b/src/engine/shared/storage.cpp
index 491795ad..1d0e2f78 100644
--- a/src/engine/shared/storage.cpp
+++ b/src/engine/shared/storage.cpp
@@ -30,6 +30,9 @@ public:
 			str_format(aPath, sizeof(aPath), "%s/maps", m_aApplicationSavePath);
 			fs_makedir(aPath);
 
+			str_format(aPath, sizeof(aPath), "%s/dumps", m_aApplicationSavePath);
+			fs_makedir(aPath);
+
 			str_format(aPath, sizeof(aPath), "%s/downloadedmaps", m_aApplicationSavePath);
 			fs_makedir(aPath);
 
diff --git a/src/game/client/components/console.cpp b/src/game/client/components/console.cpp
index b323ab48..cb8c31ce 100644
--- a/src/game/client/components/console.cpp
+++ b/src/game/client/components/console.cpp
@@ -1,5 +1,6 @@
 //#include "gc_console.h"
 #include <math.h>
+#include <time.h>
 
 #include <game/generated/client_data.h>
 
@@ -9,6 +10,7 @@
 #include <engine/shared/config.h>
 #include <engine/graphics.h>
 #include <engine/textrender.h>
+#include <engine/storage.h>
 #include <engine/keys.h>
 #include <engine/console.h>
 
@@ -51,6 +53,7 @@ CGameConsole::CInstance::CInstance(int Type)
 
 	m_aCompletionBuffer[0] = 0;
 	m_CompletionChosen = -1;
+	m_CompletionRenderOffset = 0.0f;
 	
 	m_pCommand = 0x0;
 }
@@ -60,6 +63,12 @@ void CGameConsole::CInstance::Init(CGameConsole *pGameConsole)
 	m_pGameConsole = pGameConsole;
 };
 
+void CGameConsole::CInstance::ClearBacklog()
+{
+	m_Backlog.Init();
+	m_BacklogActPage = 0;
+}
+
 void CGameConsole::CInstance::ExecuteLine(const char *pLine)
 {
 	if(m_Type == 0)
@@ -180,11 +189,11 @@ void CGameConsole::CInstance::OnInput(IInput::CEvent Event)
 			char aBuf[64] = {0};
 			const char *pSrc = GetString();
 			int i = 0;
-			for(; i < (int)sizeof(aBuf) && *pSrc && *pSrc != ' '  && *pSrc != ' '; i++, pSrc++)
+			for(; i < (int)sizeof(aBuf)-1 && *pSrc && *pSrc != ' '; i++, pSrc++)
 				aBuf[i] = *pSrc;
 			aBuf[i] = 0;
 			
-			m_pCommand = m_pGameConsole->m_pConsole->GetCommandInfo(aBuf);
+			m_pCommand = m_pGameConsole->m_pConsole->GetCommandInfo(aBuf, m_CompletionFlagmask);
 		}
 	}
 }
@@ -241,6 +250,8 @@ struct CRenderInfo
 	const char *m_pCurrentCmd;
 	int m_WantedCompletion;
 	int m_EnumCount;
+	float m_Offset;
+	float m_Width;
 };
 
 void CGameConsole::PossibleCommandsRenderCallback(const char *pStr, void *pUser)
@@ -256,6 +267,12 @@ void CGameConsole::PossibleCommandsRenderCallback(const char *pStr, void *pUser)
 			pInfo->m_pSelf->RenderTools()->DrawRoundRect(pInfo->m_Cursor.m_X-3, pInfo->m_Cursor.m_Y, tw+5, pInfo->m_Cursor.m_FontSize+4, pInfo->m_Cursor.m_FontSize/3);
 		pInfo->m_pSelf->Graphics()->QuadsEnd();
 		
+		// scroll when out of sight
+		if(pInfo->m_Cursor.m_X < 3.0f)
+			pInfo->m_Offset = 0.0f;
+		else if(pInfo->m_Cursor.m_X+tw > pInfo->m_Width)
+			pInfo->m_Offset -= pInfo->m_Width/2;
+
 		pInfo->m_pSelf->TextRender()->TextColor(0.05f, 0.05f, 0.05f,1);
 		pInfo->m_pSelf->TextRender()->TextEx(&pInfo->m_Cursor, pStr, -1);
 	}
@@ -386,8 +403,10 @@ void CGameConsole::OnRender()
 		Info.m_pSelf = this;
 		Info.m_WantedCompletion = pConsole->m_CompletionChosen;
 		Info.m_EnumCount = 0;
+		Info.m_Offset = pConsole->m_CompletionRenderOffset;
+		Info.m_Width = Screen.w;
 		Info.m_pCurrentCmd = pConsole->m_aCompletionBuffer;
-		TextRender()->SetCursor(&Info.m_Cursor, x, y+12.0f, FontSize, TEXTFLAG_RENDER);
+		TextRender()->SetCursor(&Info.m_Cursor, x+Info.m_Offset, y+12.0f, FontSize, TEXTFLAG_RENDER);
 
 		const char *pPrompt = "> ";
 		if(m_ConsoleType)
@@ -438,6 +457,7 @@ void CGameConsole::OnRender()
 			if(pConsole->m_Input.GetString()[0] != 0)
 			{
 				m_pConsole->PossibleCommands(pConsole->m_aCompletionBuffer, pConsole->m_CompletionFlagmask, PossibleCommandsRenderCallback, &Info);
+				pConsole->m_CompletionRenderOffset = Info.m_Offset;
 				
 				if(Info.m_EnumCount <= 0)
 				{
@@ -552,6 +572,41 @@ void CGameConsole::Toggle(int Type)
 	m_ConsoleType = Type;
 }
 
+void CGameConsole::Dump(int Type)
+{
+	CInstance *pConsole = Type == 1 ? &m_RemoteConsole : &m_LocalConsole;
+	char aFilename[128];
+	time_t Time;
+	char aDate[20];
+
+	time(&Time);
+	tm* TimeInfo = localtime(&Time);
+	strftime(aDate, sizeof(aDate), "%Y-%m-%d_%I-%M", TimeInfo);
+
+	for(int i = 0; i < 10; i++)
+	{
+		IOHANDLE io;
+		str_format(aFilename, sizeof(aFilename), "dumps/%s_dump%s-%05d.txt", Type==1?"remote_console":"local_console", aDate, i);
+		io = Storage()->OpenFile(aFilename, IOFLAG_WRITE);
+		if(io)
+		{
+			#if defined(CONF_FAMILY_WINDOWS)
+				static const char Newline[] = "\r\n";
+			#else
+				static const char Newline[] = "\n";
+			#endif
+
+			for(char *pEntry = pConsole->m_Backlog.First(); pEntry; pEntry = pConsole->m_Backlog.Next(pEntry))
+			{
+				io_write(io, pEntry, str_length(pEntry));
+				io_write(io, Newline, sizeof(Newline)-1);
+			}
+			io_close(io);
+			break;
+		}
+	}
+}
+
 void CGameConsole::ConToggleLocalConsole(IConsole::IResult *pResult, void *pUserData)
 {
 	((CGameConsole *)pUserData)->Toggle(0);
@@ -562,6 +617,26 @@ void CGameConsole::ConToggleRemoteConsole(IConsole::IResult *pResult, void *pUse
 	((CGameConsole *)pUserData)->Toggle(1);
 }
 
+void CGameConsole::ConClearLocalConsole(IConsole::IResult *pResult, void *pUserData)
+{
+	((CGameConsole *)pUserData)->m_LocalConsole.ClearBacklog();
+}
+
+void CGameConsole::ConClearRemoteConsole(IConsole::IResult *pResult, void *pUserData)
+{
+	((CGameConsole *)pUserData)->m_RemoteConsole.ClearBacklog();
+}
+
+void CGameConsole::ConDumpLocalConsole(IConsole::IResult *pResult, void *pUserData)
+{
+	((CGameConsole *)pUserData)->Dump(0);
+}
+
+void CGameConsole::ConDumpRemoteConsole(IConsole::IResult *pResult, void *pUserData)
+{
+	((CGameConsole *)pUserData)->Dump(1);
+}
+
 void CGameConsole::ClientConsolePrintCallback(const char *pStr, void *pUserData)
 {
 	((CGameConsole *)pUserData)->m_LocalConsole.PrintLine(pStr);
@@ -588,6 +663,10 @@ void CGameConsole::OnConsoleInit()
 	
 	Console()->Register("toggle_local_console", "", CFGFLAG_CLIENT, ConToggleLocalConsole, this, "Toggle local console");
 	Console()->Register("toggle_remote_console", "", CFGFLAG_CLIENT, ConToggleRemoteConsole, this, "Toggle remote console");
+	Console()->Register("clear_local_console", "", CFGFLAG_CLIENT, ConClearLocalConsole, this, "Clear local console");
+	Console()->Register("clear_remote_console", "", CFGFLAG_CLIENT, ConClearRemoteConsole, this, "Clear remote console");
+	Console()->Register("dump_local_console", "", CFGFLAG_CLIENT, ConDumpLocalConsole, this, "Dump local console");
+	Console()->Register("dump_remote_console", "", CFGFLAG_CLIENT, ConDumpRemoteConsole, this, "Dump remote console");
 }
 
 /*
diff --git a/src/game/client/components/console.h b/src/game/client/components/console.h
index d146307f..a4d22790 100644
--- a/src/game/client/components/console.h
+++ b/src/game/client/components/console.h
@@ -24,12 +24,15 @@ class CGameConsole : public CComponent
 		char m_aCompletionBuffer[128];
 		int m_CompletionChosen;
 		int m_CompletionFlagmask;
+		float m_CompletionRenderOffset;
 		
 		IConsole::CCommandInfo *m_pCommand;
 
 		CInstance(int t);
 		void Init(CGameConsole *pGameConsole);
 
+		void ClearBacklog();
+
 		void ExecuteLine(const char *pLine);
 		
 		void OnInput(IInput::CEvent Event);
@@ -53,11 +56,16 @@ class CGameConsole : public CComponent
 	float m_StateChangeDuration;
 
 	void Toggle(int Type);
+	void Dump(int Type);
 
 	static void PossibleCommandsRenderCallback(const char *pStr, void *pUser);
 	static void ClientConsolePrintCallback(const char *pStr, void *pUserData);
 	static void ConToggleLocalConsole(IConsole::IResult *pResult, void *pUserData);
 	static void ConToggleRemoteConsole(IConsole::IResult *pResult, void *pUserData);
+	static void ConClearLocalConsole(IConsole::IResult *pResult, void *pUserData);
+	static void ConClearRemoteConsole(IConsole::IResult *pResult, void *pUserData);
+	static void ConDumpLocalConsole(IConsole::IResult *pResult, void *pUserData);
+	static void ConDumpRemoteConsole(IConsole::IResult *pResult, void *pUserData);
 	
 public:
 	CGameConsole();
diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp
index a3ae5a4d..73dfef53 100644
--- a/src/game/client/components/hud.cpp
+++ b/src/game/client/components/hud.cpp
@@ -71,57 +71,58 @@ void CHud::RenderScoreHud()
 	// render small score hud
 	if(!(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver) && (GameFlags&GAMEFLAG_TEAMS))
 	{
+		char aScoreTeam[2][32];
+		str_format(aScoreTeam[0], sizeof(aScoreTeam)/2, "%d", m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed);
+		str_format(aScoreTeam[1], sizeof(aScoreTeam)/2, "%d", m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue);
+		float aScoreTeamWidth[2] = {TextRender()->TextWidth(0, 14.0f, aScoreTeam[0], -1), TextRender()->TextWidth(0, 14.0f, aScoreTeam[1], -1)};
+		float ScoreWidthMax = max(max(aScoreTeamWidth[0], aScoreTeamWidth[1]), TextRender()->TextWidth(0, 14.0f, "100", -1));
+		float Split = 3.0f;
+		float ImageSize = GameFlags&GAMEFLAG_FLAGS ? 16.0f : Split;
+		
 		for(int t = 0; t < 2; t++)
 		{
+			// draw box
 			Graphics()->BlendNormal();
 			Graphics()->TextureSet(-1);
 			Graphics()->QuadsBegin();
 			if(t == 0)
-				Graphics()->SetColor(1,0,0,0.25f);
+				Graphics()->SetColor(1.0f, 0.0f, 0.0f, 0.25f);
 			else
-				Graphics()->SetColor(0,0,1,0.25f);
-			RenderTools()->DrawRoundRect(Whole-45, 300-40-15+t*20, 50, 18, 5.0f);
+				Graphics()->SetColor(0.0f, 0.0f, 1.0f, 0.25f);
+			RenderTools()->DrawRoundRectExt(Whole-ScoreWidthMax-ImageSize-2*Split, 245.0f+t*20, ScoreWidthMax+ImageSize+2*Split, 18.0f, 5.0f, CUI::CORNER_L);
 			Graphics()->QuadsEnd();
 
-			char Buf[32];
-			str_format(Buf, sizeof(Buf), "%d", t?m_pClient->m_Snap.m_pGameobj->m_TeamscoreBlue : m_pClient->m_Snap.m_pGameobj->m_TeamscoreRed);
-			float w = TextRender()->TextWidth(0, 14, Buf, -1);
-			
-			if(GameFlags&GAMEFLAG_FLAGS)
+			// draw score
+			TextRender()->Text(0, Whole-ScoreWidthMax+(ScoreWidthMax-aScoreTeamWidth[t])/2-Split, 245.0f+t*20, 14.0f, aScoreTeam[t], -1);
+
+			if(GameFlags&GAMEFLAG_FLAGS && m_pClient->m_Snap.m_paFlags[t])
 			{
-				TextRender()->Text(0, Whole-20-w/2+5, 300-40-15+t*20, 14, Buf, -1);
-				if(m_pClient->m_Snap.m_paFlags[t])
+				if(m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy == -2 || (m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy == -1 && ((Client()->GameTick()/10)&1)))
 				{
-					if(m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy == -2 || (m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy == -1 && ((Client()->GameTick()/10)&1)))
-					{
-						Graphics()->BlendNormal();
-						Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
-						Graphics()->QuadsBegin();
-
-						if(t == 0) RenderTools()->SelectSprite(SPRITE_FLAG_RED);
-						else RenderTools()->SelectSprite(SPRITE_FLAG_BLUE);
-						
-						float Size = 16;					
-						IGraphics::CQuadItem QuadItem(Whole-40+2, 300-40-15+t*20+1, Size/2, Size);
-						Graphics()->QuadsDrawTL(&QuadItem, 1);
-						Graphics()->QuadsEnd();
-					}
-					else if(m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy >= 0)
-					{
-						int Id = m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy%MAX_CLIENTS;
-						const char *pName = m_pClient->m_aClients[Id].m_aName;
-						float w = TextRender()->TextWidth(0, 10, pName, -1);
-						TextRender()->Text(0, Whole-40-7-w, 300-40-15+t*20+2, 10, pName, -1);
-						CTeeRenderInfo Info = m_pClient->m_aClients[Id].m_RenderInfo;
-						Info.m_Size = 18.0f;
-						
-						RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0),
-							vec2(Whole-40+5, 300-40-15+9+t*20+1));
-					}
+					// draw flag
+					Graphics()->BlendNormal();
+					Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
+					Graphics()->QuadsBegin();
+					RenderTools()->SelectSprite(t==0?SPRITE_FLAG_RED:SPRITE_FLAG_BLUE);
+					IGraphics::CQuadItem QuadItem(Whole-ScoreWidthMax-ImageSize, 246.0f+t*20, ImageSize/2, ImageSize);
+					Graphics()->QuadsDrawTL(&QuadItem, 1);
+					Graphics()->QuadsEnd();
+				}
+				else if(m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy >= 0)
+				{
+					// draw name of the flag holder
+					int Id = m_pClient->m_Snap.m_paFlags[t]->m_CarriedBy%MAX_CLIENTS;
+					const char *pName = m_pClient->m_aClients[Id].m_aName;
+					float w = TextRender()->TextWidth(0, 10.0f, pName, -1);
+					TextRender()->Text(0, Whole-ScoreWidthMax-ImageSize-3*Split-w, 247.0f+t*20, 10.0f, pName, -1);
+
+					// draw tee of the flag holder
+					CTeeRenderInfo Info = m_pClient->m_aClients[Id].m_RenderInfo;
+					Info.m_Size = 18.0f;
+					RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0),
+						vec2(Whole-ScoreWidthMax-Info.m_Size/2-Split, 246.0f+Info.m_Size/2+t*20));
 				}
 			}
-			else
-				TextRender()->Text(0, Whole-20-w/2, 300-40-15+t*20, 14, Buf, -1);
 		}
 	}
 }
diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp
index 70479e53..b29bee99 100644
--- a/src/game/client/components/items.cpp
+++ b/src/game/client/components/items.cpp
@@ -104,7 +104,7 @@ void CItems::RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCu
 		{
 			m_pClient->m_pEffects->PowerupShine(Pos, vec2(96,18));
 			Size *= 2.0f;
-			Pos.x += 10.0f;
+			Pos.x -= 10.0f;
 		}
 	}
 
diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp
index 202ea2da..62b32a1f 100644
--- a/src/game/client/components/maplayers.cpp
+++ b/src/game/client/components/maplayers.cpp
@@ -42,7 +42,7 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void
 	pChannels[2] = 0;
 	pChannels[3] = 0;
 
-	CEnvPoint *pPoints;
+	CEnvPoint *pPoints = 0;
 
 	{
 		int Start, Num;
diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h
index 229fce80..9ea9c6ef 100644
--- a/src/game/client/components/menus.h
+++ b/src/game/client/components/menus.h
@@ -165,7 +165,6 @@ class CMenus : public CComponent
 	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
diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp
index 9b816f15..32243a2a 100644
--- a/src/game/client/components/menus_browser.cpp
+++ b/src/game/client/components/menus_browser.cpp
@@ -309,7 +309,12 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
 					TextRender()->TextEx(&Cursor, pItem->m_aName, -1);
 			}
 			else if(Id == COL_MAP)
-				UI()->DoLabel(&Button, pItem->m_aMap, 12.0f, -1);
+			{
+				CTextCursor Cursor;
+				TextRender()->SetCursor(&Cursor, Button.x, Button.y, 12.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
+				Cursor.m_LineWidth = Button.w;
+				TextRender()->TextEx(&Cursor, pItem->m_aMap, -1);
+			}
 			else if(Id == COL_PLAYERS)
 			{
 				str_format(aTemp, sizeof(aTemp), "%i/%i", pItem->m_NumPlayers, pItem->m_MaxPlayers);
@@ -332,7 +337,10 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
 			}
 			else if(Id == COL_GAMETYPE)
 			{
-				UI()->DoLabel(&Button, pItem->m_aGameType, 12.0f, 0);
+				CTextCursor Cursor;
+				TextRender()->SetCursor(&Cursor, Button.x, Button.y, 12.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
+				Cursor.m_LineWidth = Button.w;
+				TextRender()->TextEx(&Cursor, pItem->m_aGameType, -1);
 			}
 
 		}
diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp
index ec1ead8e..f8cf8e4f 100644
--- a/src/game/client/components/menus_demo.cpp
+++ b/src/game/client/components/menus_demo.cpp
@@ -1,5 +1,4 @@
 
-#include <string.h>
 #include <base/math.h>
 
 
@@ -380,9 +379,9 @@ struct FETCH_CALLBACKINFO
 
 void CMenus::DemolistFetchCallback(const char *pName, int IsDir, void *pUser)
 {
-	if(IsDir || pName[0] == '.')
+	if(pName[0] == '.')
 		return;
-			
+	
 	FETCH_CALLBACKINFO *pInfo = (FETCH_CALLBACKINFO *)pUser;
 	
 	CDemoItem Item;
@@ -391,17 +390,12 @@ 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
+	if(str_comp_num(m_aCurrentDemoFolder, "demos", 256)) //add parent folder
 	{
 		CDemoItem Item;
 		str_copy(Item.m_aName, "..", sizeof(Item.m_aName));
@@ -413,7 +407,7 @@ void CMenus::DemolistPopulate()
 	char aBuf[512];
 	str_format(aBuf, sizeof(aBuf), "%s/%s", Client()->UserDirectory(), m_aCurrentDemoFolder);
 	
-	FETCH_CALLBACKINFO Info = {this, aBuf, 0};
+	FETCH_CALLBACKINFO Info = {this, aBuf, m_aCurrentDemoFolder[6]}; //skip "demos/"
 	fs_listdir(aBuf, DemolistFetchCallback, &Info);
 	Info.m_pPrefix = m_aCurrentDemoFolder;
 	fs_listdir(m_aCurrentDemoFolder, DemolistFetchCallback, &Info);
@@ -457,10 +451,10 @@ void CMenus::RenderDemoList(CUIRect MainView)
 	
 	
 	bool IsDir = false;
-	if(!strncmp(m_lDemos[s_SelectedItem].m_aName, "..", 256)) //parent folder
+	if(!str_comp_num(m_lDemos[s_SelectedItem].m_aName, "..", 256)) //parent folder
+		IsDir = true;
+	else if(fs_is_dir(m_lDemos[s_SelectedItem].m_aFilename))
 		IsDir = true;
-	else
-		fs_listdir(m_lDemos[s_SelectedItem].m_aFilename, IsDirCallback, &IsDir);
 	
 	
 	static int s_RefreshButton = 0;
@@ -470,17 +464,17 @@ void CMenus::RenderDemoList(CUIRect MainView)
 	}
 	
 	static int s_PlayButton = 0;
-	char aTitleButton[8];
+	char aTitleButton[10];
 	if(IsDir)
-		str_copy(aTitleButton, "Open", sizeof(aTitleButton));
+		str_copy(aTitleButton, Localize("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)
+		str_copy(aTitleButton, Localize("Play"), sizeof(aTitleButton));
+	
+	if(DoButton_Menu(&s_PlayButton, aTitleButton, 0, &PlayRect) || Activated)
 	{		
 		if(s_SelectedItem >= 0 && s_SelectedItem < m_lDemos.size())
 		{
-			if(!strncmp(m_lDemos[s_SelectedItem].m_aName, "..", 256))
+			if(!str_comp_num(m_lDemos[s_SelectedItem].m_aName, "..", 256))
 			{
 				DemoSetParentDirectory();
 				DemolistPopulate();
@@ -496,7 +490,7 @@ void CMenus::RenderDemoList(CUIRect MainView)
 			{
 				const char *pError = Client()->DemoPlayer_Play(m_lDemos[s_SelectedItem].m_aFilename);
 				if(pError)
-					PopupMessage(Localize("Error"), pError, Localize("Ok"));
+					PopupMessage(Localize("Error"), Localize(pError), Localize("Ok"));
 			}
 		}
 	}
@@ -519,6 +513,6 @@ void CMenus::DemoSetParentDirectory()
 	for(i = 0; i < 256; i++)
 	{
 		if(i >= Stop)
-			m_aCurrentDemoFolder[i] = NULL;
+			m_aCurrentDemoFolder[i] = 0;
 	}
 }
diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp
index 8ad7b0cb..ad7b3bcd 100644
--- a/src/game/client/components/players.cpp
+++ b/src/game/client/components/players.cpp
@@ -319,7 +319,7 @@ void CPlayers::RenderPlayer(
 	bool WantOtherDir = (Player.m_Direction == -1 && Vel.x > 0) || (Player.m_Direction == 1 && Vel.x < 0);
 
 	// evaluate animation
-	float WalkTime = fmod(Position.x, 100.0f)/100.0f;
+	float WalkTime = fmod(absolute(Position.x), 100.0f)/100.0f;
 	CAnimState State;
 	State.Set(&g_pData->m_aAnimations[ANIM_BASE], 0);
 
diff --git a/src/game/editor/ed_editor.cpp b/src/game/editor/ed_editor.cpp
index 63963dc2..da97ed61 100644
--- a/src/game/editor/ed_editor.cpp
+++ b/src/game/editor/ed_editor.cpp
@@ -573,7 +573,21 @@ static void CallbackAppendMap(const char *pFileName, void *pUser)
 	else
 		pEditor->SortImages();
 }
-static void CallbackSaveMap(const char *pFileName, void *pUser){ if(((CEditor*)pUser)->Save(pFileName)) str_copy(((CEditor*)pUser)->m_aFileName, pFileName, 512); }
+static void CallbackSaveMap(const char *pFileName, void *pUser)
+{
+	char aBuf[1024];
+	const int Length = str_length(pFileName);
+	// add map extension
+	if(Length <= 4 || pFileName[Length-4] != '.' || str_comp_nocase(pFileName+Length-3, "map"))
+	{
+		str_format(aBuf, sizeof(aBuf), "%s.map", pFileName);
+		pFileName = aBuf;
+	}
+
+	CEditor *pEditor = static_cast<CEditor*>(pUser);
+	if(pEditor->Save(pFileName))
+		str_copy(pEditor->m_aFileName, pFileName, sizeof(pEditor->m_aFileName));
+}
 
 void CEditor::DoToolbar(CUIRect ToolBar)
 {
@@ -593,7 +607,7 @@ void CEditor::DoToolbar(CUIRect ToolBar)
 	if(Input()->KeyDown('s') && (Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL)))
 	{
 		if(m_aFileName[0])	
-			Save(m_aFileName);
+			CallbackSaveMap(m_aFileName, this);
 		else
 			InvokeFileDialog(IStorage::TYPE_SAVE, Localize("Save map"), Localize("Save"), "maps/", "", CallbackSaveMap, this);
 	}
@@ -773,6 +787,17 @@ void CEditor::DoToolbar(CUIRect ToolBar)
                 DoMapBorder();
 		}
 	}
+
+	TB_Bottom.VSplitLeft(5.0f, 0, &TB_Bottom);
+
+	// refocus button
+	TB_Bottom.VSplitLeft(50.0f, &Button, &TB_Bottom);
+	static int s_RefocusButton = 0;
+	if(DoButton_Editor(&s_RefocusButton, Localize("Refocus"), m_WorldOffsetX&&m_WorldOffsetY?0:-1, &Button, 0, Localize("[HOME] Restore map focus")) || Input()->KeyDown(KEY_HOME))
+	{
+		m_WorldOffsetX = 0;
+		m_WorldOffsetY = 0;
+	}
 }
 
 static void Rotate(CPoint *pCenter, CPoint *pPoint, float Rotation)
@@ -1317,24 +1342,26 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar)
 					}
 
 					CLayerGroup *g = GetSelectedGroup();
-					m_Brush.m_OffsetX += g->m_OffsetX;
-					m_Brush.m_OffsetY += g->m_OffsetY;
-					m_Brush.m_ParallaxX = g->m_ParallaxX;
-					m_Brush.m_ParallaxY = g->m_ParallaxY;
-					m_Brush.Render();
-					float w, h;
-					m_Brush.GetSize(&w, &h);
-
-					IGraphics::CLineItem Array[4] = {
-						IGraphics::CLineItem(0, 0, w, 0),
-						IGraphics::CLineItem(w, 0, w, h),
-						IGraphics::CLineItem(w, h, 0, h),
-						IGraphics::CLineItem(0, h, 0, 0)};
-					Graphics()->TextureSet(-1);
-					Graphics()->LinesBegin();
-					Graphics()->LinesDraw(Array, 4);
-					Graphics()->LinesEnd();
-
+					if(g)
+					{
+						m_Brush.m_OffsetX += g->m_OffsetX;
+						m_Brush.m_OffsetY += g->m_OffsetY;
+						m_Brush.m_ParallaxX = g->m_ParallaxX;
+						m_Brush.m_ParallaxY = g->m_ParallaxY;
+						m_Brush.Render();
+						float w, h;
+						m_Brush.GetSize(&w, &h);
+
+						IGraphics::CLineItem Array[4] = {
+							IGraphics::CLineItem(0, 0, w, 0),
+							IGraphics::CLineItem(w, 0, w, h),
+							IGraphics::CLineItem(w, h, 0, h),
+							IGraphics::CLineItem(0, h, 0, 0)};
+						Graphics()->TextureSet(-1);
+						Graphics()->LinesBegin();
+						Graphics()->LinesDraw(Array, 4);
+						Graphics()->LinesEnd();
+					}
 				}
 			}
 		}
@@ -1393,6 +1420,15 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar)
 			}
 		}
 	}
+	else if(UI()->ActiveItem() == s_pEditorId)
+	{
+		// release mouse
+		if(!UI()->MouseButton(0))
+		{
+			s_Operation = OP_NONE;
+			UI()->SetActiveItem(0);
+		}
+	}
 
 	if(GetSelectedGroup() && GetSelectedGroup()->m_UseClipping)
 	{
@@ -1655,19 +1691,6 @@ void CEditor::RenderLayers(CUIRect ToolBox, CUIRect ToolBar, CUIRect View)
 		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);
@@ -1953,19 +1976,6 @@ void CEditor::RenderImages(CUIRect ToolBox, CUIRect ToolBar, CUIRect View)
 		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);
@@ -2670,7 +2680,7 @@ int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View)
 	if(pEditor->DoButton_MenuItem(&s_SaveButton, Localize("Save"), 0, &Slot, 0, Localize("Saves the current map")))
 	{
 		if(pEditor->m_aFileName[0])	
-			pEditor->Save(pEditor->m_aFileName);
+			CallbackSaveMap(pEditor->m_aFileName, pEditor);
 		else
 			pEditor->InvokeFileDialog(IStorage::TYPE_SAVE, Localize("Save Map"), Localize("Save"), "maps/", "", CallbackSaveMap, pEditor);
 		return 1;
@@ -2865,6 +2875,19 @@ void CEditor::Reset(bool CreateDefault)
 	m_SelectedPoints = 0;
 	m_SelectedEnvelope = 0;
 	m_SelectedImage = 0;
+	
+	m_WorldOffsetX = 0;
+	m_WorldOffsetY = 0;
+	m_EditorOffsetX = 0.0f;
+	m_EditorOffsetY = 0.0f;
+	
+	m_WorldZoom = 1.0f;
+	m_ZoomLevel = 200;
+
+	m_MouseDeltaX = 0;
+	m_MouseDeltaY = 0;
+	m_MouseDeltaWx = 0;
+	m_MouseDeltaWy = 0;
 }
 
 void CEditorMap::MakeGameLayer(CLayer *pLayer)
@@ -2895,6 +2918,28 @@ void CEditorMap::Clean()
 
 void CEditorMap::CreateDefault(int EntitiesTexture)
 {
+	// add background
+	CLayerGroup *pGroup = NewGroup();
+	pGroup->m_ParallaxX = 0;
+	pGroup->m_ParallaxY = 0;
+	CLayerQuads *pLayer = new CLayerQuads;
+	pLayer->m_pEditor = m_pEditor;
+	CQuad *pQuad = pLayer->NewQuad();
+	const int Width = 800000;
+	const int Height = 600000;
+	pQuad->m_aPoints[0].x = pQuad->m_aPoints[2].x = -Width;
+	pQuad->m_aPoints[1].x = pQuad->m_aPoints[3].x = Width;
+	pQuad->m_aPoints[0].y = pQuad->m_aPoints[1].y = -Height;
+	pQuad->m_aPoints[2].y = pQuad->m_aPoints[3].y = Height;
+	pQuad->m_aColors[0].r = pQuad->m_aColors[1].r = 94;
+	pQuad->m_aColors[0].g = pQuad->m_aColors[1].g = 132;
+	pQuad->m_aColors[0].b = pQuad->m_aColors[1].b = 174;
+	pQuad->m_aColors[2].r = pQuad->m_aColors[3].r = 204;
+	pQuad->m_aColors[2].g = pQuad->m_aColors[3].g = 232;
+	pQuad->m_aColors[2].b = pQuad->m_aColors[3].b = 255;
+	pGroup->AddLayer(pLayer);
+
+	// add game layer
 	MakeGameGroup(NewGroup());
 	MakeGameLayer(new CLayerGame(50, 50));
 	m_pGameGroup->AddLayer(m_pGameLayer);
@@ -2938,7 +2983,7 @@ void CEditor::DoMapBorder()
             pT->m_pTiles[i].m_Index = 1;
     }
     
-    for(int i = ((pT->m_Width-2)*pT->m_Height); i < pT->m_Width*pT->m_Height; ++i)
+    for(int i = (pT->m_Width*(pT->m_Height-2)); i < pT->m_Width*pT->m_Height; ++i)
         pT->m_pTiles[i].m_Index = 1;
 }
 
diff --git a/src/game/editor/ed_popups.cpp b/src/game/editor/ed_popups.cpp
index 5e833ba6..001a7249 100644
--- a/src/game/editor/ed_popups.cpp
+++ b/src/game/editor/ed_popups.cpp
@@ -20,6 +20,10 @@ static int g_UiNumPopups = 0;
 void CEditor::UiInvokePopupMenu(void *Id, int Flags, float x, float y, float w, float h, int (*pfnFunc)(CEditor *pEditor, CUIRect Rect), void *pExtra)
 {
 	dbg_msg("", "invoked");
+	if(x + w > UI()->Screen()->w)
+		x -= w;
+	if(y + h > UI()->Screen()->h)
+		y -= h;
 	s_UiPopups[g_UiNumPopups].m_pId = Id;
 	s_UiPopups[g_UiNumPopups].m_IsMenu = Flags;
 	s_UiPopups[g_UiNumPopups].m_Rect.x = x;
@@ -84,6 +88,7 @@ int CEditor::PopupGroup(CEditor *pEditor, CUIRect View)
 		pEditor->DoButton_Editor(&s_DeleteButton, Localize("Delete group"), 0, &Button, 0, Localize("Delete group")))
 	{
 		pEditor->m_Map.DeleteGroup(pEditor->m_SelectedGroup);
+		pEditor->m_SelectedGroup = max(0, pEditor->m_SelectedGroup-1);
 		return 1;
 	}
 
diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp
index 77d8f462..81d1f85b 100644
--- a/src/game/server/entities/character.cpp
+++ b/src/game/server/entities/character.cpp
@@ -585,14 +585,26 @@ void CCharacter::TickDefered()
 	
 	if(!StuckBefore && (StuckAfterMove || StuckAfterQuant))
 	{
+		// Hackish solution to get rid of strict-aliasing warning
+		union
+		{
+			float f;
+			unsigned u;
+		}StartPosX, StartPosY, StartVelX, StartVelY;
+
+		StartPosX.f = StartPos.x;
+		StartPosY.f = StartPos.y;
+		StartVelX.f = StartVel.x;
+		StartVelY.f = StartVel.y;
+
 		dbg_msg("char_core", "STUCK!!! %d %d %d %f %f %f %f %x %x %x %x", 
 			StuckBefore,
 			StuckAfterMove,
 			StuckAfterQuant,
 			StartPos.x, StartPos.y,
 			StartVel.x, StartVel.y,
-			*((unsigned *)&StartPos.x), *((unsigned *)&StartPos.y),
-			*((unsigned *)&StartVel.x), *((unsigned *)&StartVel.y));
+			StartPosX.u, StartPosY.u,
+			StartVelX.u, StartVelY.u);
 	}
 
 	int Events = m_Core.m_TriggeredEvents;
diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp
index 5b7051d3..07f8bf86 100644
--- a/src/game/server/gamecontroller.cpp
+++ b/src/game/server/gamecontroller.cpp
@@ -286,6 +286,7 @@ void IGameController::PostReset()
 			GameServer()->m_apPlayers[i]->Respawn();
 			GameServer()->m_apPlayers[i]->m_Score = 0;
 			GameServer()->m_apPlayers[i]->m_ScoreStartTick = Server()->Tick();
+			GameServer()->m_apPlayers[i]->m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2;
 		}
 	}
 }
@@ -540,7 +541,7 @@ int IGameController::GetAutoTeam(int Notthisid)
 
 bool IGameController::CanJoinTeam(int Team, int Notthisid)
 {
-	if(Team == -1)
+	if(Team == -1 || (GameServer()->m_apPlayers[Notthisid] && GameServer()->m_apPlayers[Notthisid]->GetTeam() != -1))
 		return true;
 
 	int aNumplayers[2] = {0,0};