Index: binaries/data/mods/public/gui/common/functions_utility.js
===================================================================
--- binaries/data/mods/public/gui/common/functions_utility.js	(revision 16105)
+++ binaries/data/mods/public/gui/common/functions_utility.js	(working copy)
@@ -240,3 +240,44 @@
 	// Limit the length to 20 characters
 	return sanitizedName.substr(0,20);
 }
+
+function tryAutoComplete(text, autoCompleteList)
+{
+	if (text.length == 0)
+		return text;
+
+	var wordSplit = text.split(/\s+/g);
+
+	if (!wordSplit.length)
+		return text;
+
+	var lastWord = wordSplit.pop();
+	for (var wordAutoCompletion of autoCompleteList)
+	{
+		if (wordAutoCompletion.toLowerCase().indexOf(lastWord.toLowerCase()) == 0)
+		{
+			text = wordSplit.join(" ")
+			if (text.length > 0)
+				text += " ";
+
+			text += wordAutoCompletion;
+			break;
+		}
+	}
+	return text;
+}
+
+//listPlayer parameter must be an array and every object with name property
+function autoCompleteNick(guiName, listPlayer)
+{
+	var input = Engine.GetGUIObjectByName(guiName);
+	var text = escapeText(input.caption);
+	if (!text.length)
+		return;
+
+	var autoCompleteList = [];
+	for (var player of listPlayer)
+		autoCompleteList.push(player.name);
+
+	input.caption = tryAutoComplete(text, autoCompleteList);
+}
\ No newline at end of file
Index: binaries/data/mods/public/gui/lobby/lobby.js
===================================================================
--- binaries/data/mods/public/gui/lobby/lobby.js	(revision 16105)
+++ binaries/data/mods/public/gui/lobby/lobby.js	(working copy)
@@ -749,35 +749,6 @@
 	}
 }
 
-function completeNick()
-{
-	var input = Engine.GetGUIObjectByName("chatInput");
-	var text = escapeText(input.caption);
-	if (text.length)
-	{
-		var matched = false;
-		for each (var playerObj in Engine.GetPlayerList())
-		{
-			var player = playerObj.name;
-			var breaks = text.match(/(\s+)/g) || [];
-			text.split(/\s+/g).reduceRight(function (wordsSoFar, word, index)
-			{
-				if (matched)
-					return null;
-				var matchCandidate = word + (breaks[index - 1] || "") + wordsSoFar;
-				if (player.toUpperCase().indexOf(matchCandidate.toUpperCase().trim()) == 0)
-				{
-					input.caption = text.replace(matchCandidate.trim(), player);
-					matched = true;
-				}
-				return matchCandidate;
-			}, "");
-		if (matched)
-			break;
-		}
-	}
-}
-
 function isValidNick(nick)
 {
 	var prohibitedNicks = ["system"];
Index: binaries/data/mods/public/gui/lobby/lobby.xml
===================================================================
--- binaries/data/mods/public/gui/lobby/lobby.xml	(revision 16105)
+++ binaries/data/mods/public/gui/lobby/lobby.xml	(working copy)
@@ -231,7 +231,7 @@
 				<object name="chatText" size="0 0 100% 94%" type="text" style="ChatPanel" font="sans-13"/>
 				<object name="chatInput" size="0 94% 100% 100%" type="input" style="ModernInput" font="sans-13">
 					<action on="Press">submitChatInput();</action>
-					<action on="Tab">completeNick();</action>
+					<action on="Tab">autoCompleteNick("chatInput", Engine.GetPlayerList());</action>
 				</object>
 			</object>
 		</object>
Index: binaries/data/mods/public/gui/session/messages.js
===================================================================
--- binaries/data/mods/public/gui/session/messages.js	(revision 16105)
+++ binaries/data/mods/public/gui/session/messages.js	(working copy)
@@ -612,6 +612,16 @@
 			msg.hide = true;
 		recurse = true;
 		break;
+	case "/allies":
+		var player = g_Players[Engine.GetPlayerID()];
+
+		if (player && player.isAlly[sender])
+			msg.context = translate("Ally");
+		else
+			msg.hide = true;
+
+		recurse = true;
+		break;
 	case "/enemy":
 		// Check if we are in a team.
 		if (g_Players[Engine.GetPlayerID()] && g_Players[Engine.GetPlayerID()].team != -1)
Index: binaries/data/mods/public/gui/session/session.xml
===================================================================
--- binaries/data/mods/public/gui/session/session.xml	(revision 16105)
+++ binaries/data/mods/public/gui/session/session.xml	(working copy)
@@ -195,6 +195,7 @@
 	<object name="chatDialogPanel" size="50%-180 50%-48 50%+180 50%+36" type="image" hidden="true" sprite="genericPanel">
 		<object name="chatInput" size="16 12 100%-16 36" type="input" style="ModernInput" max_length="80">
 			<action on="Press">submitChatInput();</action>
+			<action on="Tab">autoCompleteNick("chatInput", g_Players);</action>
 		</object>
 
 		<object size="16 100%-40 30%+16 100%-12" type="button" style="StoneButton">
Index: source/gui/CInput.cpp
===================================================================
--- source/gui/CInput.cpp	(revision 16105)
+++ source/gui/CInput.cpp	(working copy)
@@ -841,6 +841,13 @@
 			GetScrollBar(0).SetScrollBarStyle(scrollbar_style);
 		}
 
+		if (Message.value == CStr("caption") && m_iBufferPos > 0)
+		{
+				CStrW caption;
+				GUI<CStrW>::GetSetting(this, "caption", caption);
+				m_iBufferPos = m_iBufferPos_Tail = (int)caption.size();
+		}
+
 		if (Message.value == CStr("size") || 
 			Message.value == CStr("z") ||
 			Message.value == CStr("font") || 