1
0
forked from 0ad/0ad

Added Multi-player chat in menu and hotkey (return key)

Made player names match custom names in multi-player

The chat window will still need some more aesthetic work

This was SVN commit r7909.
This commit is contained in:
WhiteTreePaladin 2010-08-11 22:16:16 +00:00
parent 54d9224918
commit 4cfca1625d
8 changed files with 242 additions and 32 deletions

View File

@ -190,6 +190,13 @@ hotkey.menu.toggle = "F10" ; Toggle in-game menu.
hotkey.menu.resign = "Alt+X" ; End current game session and return to main menu.
; > HOTKEYS ONLY
hotkey.chat = Return ; Toggles chat window
hotkey.onlinehelp = "F1" ; Enable/disable online manual entry for current selection.
hotkey.music.toggle = "M" ; Enable/disable music.
hotkey.audio.toggle = "Ctrl+A" ; Enable/disable sound.

View File

@ -14,7 +14,7 @@ var g_IsInGuiUpdate;
var g_PlayerAssignments = {};
// Default game setup attributes
var g_GameAttributes = { "map": "" };
var g_GameAttributes = { "map": ""};
// Number of players for currently selected map
var g_MaxPlayers = 8;
@ -132,7 +132,7 @@ function handleNetMessage(message)
break;
case "start":
Engine.SwitchGuiPage("page_loading.xml", { "attribs": g_GameAttributes });
Engine.SwitchGuiPage("page_loading.xml", { "attribs": g_GameAttributes, "isNetworked" : g_IsNetworked, "playerAssignments": g_PlayerAssignments});
break;
case "chat":

View File

@ -1,9 +1,20 @@
var g_Data;
function init(data)
{
var mapName = "map";
if (data && data.attribs)
mapName = data.attribs.map;
if (data)
g_Data = data;
// Set to "hourglass" cursor.
setCursor("cursor-wait");
@ -45,7 +56,7 @@ function reallyStartGame()
// to start the game (i.e. loading progress has reached 100%).
// Switch GUI from loading screen to game session.
Engine.SwitchGuiPage("page_session_new.xml");
Engine.SwitchGuiPage("page_session_new.xml", g_Data);
// Restore default cursor.
setCursor ("arrow-default");

View File

@ -38,4 +38,19 @@ function toggleMenu()
getGUIObjectByName("menu").hidden = false; // View menu
else
getGUIObjectByName("menu").hidden = true; // Hide menu
}
function toggleChatWindow()
{
if (getGUIObjectByName("chatWindow").hidden)
{
getGUIObjectByName("chatInput").focus();
getGUIObjectByName("chatWindow").hidden = false; // View chat
}
else
{
getGUIObjectByName("chatWindow").hidden = true; // Hide chat
}
getGUIObjectByName("menu").hidden = true; // Hide menu
}

View File

@ -29,21 +29,14 @@ function layoutSelectionSingle(entState)
}
// Fills out information that most entities have
function displayGeneralInfo(playerState, entState, template)
function displayGeneralInfo(entState, template)
{
var civName = toTitleCase(playerState.civ);
var color = playerState.color;
var playerColor = color["r"]*255 + " " + color["g"]*255 + " " + color["b"]*255 + " " + color["a"]*255;
var civName = toTitleCase(g_Players[entState.player].civ);
var playerColor = g_Players[entState.player].color.r + " " + g_Players[entState.player].color.g + " " +
g_Players[entState.player].color.b+ " " + g_Players[entState.player].color.a;
var iconTooltip = "";
// Rank Icon
// var rankId = getRankCellId(entState);
// getGUIObjectByName("sdRankIcon").cell_id = rankId;
// Rank Title
// var rankText = getRankTitle(getRankCellId(entState.template));
// rankText = (rankText? rankText : "");
// Specific Name
var name = template.name.specific + getRankTitle(getRankCellId(entState.template));
getGUIObjectByName("sdSpecific").caption = name;
@ -56,7 +49,7 @@ function displayGeneralInfo(playerState, entState, template)
getGUIObjectByName("sdSpecific").tooltip = "";
// Player Name
getGUIObjectByName("sdPlayer").caption = playerState.name;
getGUIObjectByName("sdPlayer").caption = g_Players[entState.player].name;
getGUIObjectByName("sdPlayer").tooltip = getFormalCivName(civName);
getGUIObjectByName("sdPlayer").textcolor = playerColor;
@ -130,7 +123,7 @@ function displayGeneralInfo(playerState, entState, template)
}
// Updates middle entity Selection Details Panel
function updateSelectionDetails(simState)
function updateSelectionDetails()
{
var detailsPanel = getGUIObjectByName("selectionDetails");
var commandsPanel = getGUIObjectByName("unitCommands");
@ -152,10 +145,6 @@ function updateSelectionDetails(simState)
if (!entState)
return;
var playerState = simState.players[entState.player];
if (!playerState)
return;
// Choose the highest ranked version of the primary selection
// Different selection details are shown based on whether multiple units or a single unit is selected
if (selection.length > 1)
@ -166,7 +155,7 @@ function updateSelectionDetails(simState)
var template = Engine.GuiInterfaceCall("GetTemplateData", entState.template);
// Fill out general info and display it
displayGeneralInfo(playerState, entState, template); // must come after layout functions
displayGeneralInfo(entState, template); // must come after layout functions
// Show Panels
detailsPanel.hidden = false;

View File

@ -2,7 +2,6 @@ const GEOLOGY = "geology";
const FLORA = "flora";
const FAUNA = "fauna";
const SPECIAL = "special";
const CAMP = "camp";
const GAIA = "Gaia"
const CART = "Cart";
@ -19,6 +18,17 @@ const CELTS = "Celts";
const PERSIANS = "Persians";
const IBERIANS = "Iberians";
// Chat data
const maxNumChatLines = 30;
var g_ChatMessages = [];
var g_ChatTimers = [];
// Network Mode
var g_IsNetworked = false;
// Cache the basic player data (name, civ, color)
var g_Players = [];
// Cache dev-mode settings that are frequently or widely used
var g_DevSettings = {
controlAll: false
@ -36,9 +46,55 @@ function init(initData, hotloadData)
startMusic();
}
if (initData)
{
g_IsNetworked = initData.isNetworked; // Set network mode
g_Players = getPlayerData(initData.playerAssignments); // Cache the player data
}
onSimulationUpdate();
}
// Get the basic player data
function getPlayerData(playerAssignments)
{
var players = [];
var simState = Engine.GuiInterfaceCall("GetSimulationState");
if (!simState)
return players;
for (var i = 0; i < simState.players.length; i++)
{
var playerState = simState.players[i];
if (!playerState)
continue;
var name = playerState.name;
var civ = playerState.civ;
var color = {"r": 255, "g": 255, "b": 255, "a": 255};
color.r = playerState.color["r"]*255;
color.g = playerState.color["g"]*255;
color.b = playerState.color["b"]*255;
color.a = playerState.color["a"]*255;
var player = {"name": name, "civ": civ, "color": color};
players.push(player);
}
var i = 1;
if (playerAssignments)
{
for each (var playerAssignment in playerAssignments)
{
players[i].name = playerAssignment.name;
i++;
}
}
return players;
}
function leaveGame()
{
stopMusic();
@ -75,16 +131,97 @@ function handleNetMessage(message)
obj.hidden = false;
// TODO: we need to give players some way to exit
break;
default:
error("Unrecognised netstatus type "+message.status);
break;
}
break;
case "chat":
addChatMessage({ "type": "message", "username": message.username, "text": message.text });
break;
default:
error("Unrecognised net message type "+message.type);
}
}
function submitChatInput()
{
toggleChatWindow();
var input = getGUIObjectByName("chatInput");
var text = input.caption;
if (text.length)
{
if (g_IsNetworked)
Engine.SendNetworkChat(text);
else
getGUIObjectByName("chatText").caption = "Chat is not currently supported in single player mode.";
input.caption = "";
}
}
function addChatMessage(msg)
{
// TODO: we ought to escape all values before displaying them,
// to prevent people inserting colours and newlines etc
var playerColor;
for (var i = 0; i < g_Players.length; i++)
{
if (msg.username == g_Players[i].name)
{
playerColor = g_Players[i].color.r + " " + g_Players[i].color.g + " " + g_Players[i].color.b;
break
}
}
var formatted;
switch (msg.type)
{
case "connect":
formatted = '<[color="' + playerColor + '"]' + msg.username + '[/color]> [color="64 64 64"]has joined[/color]';
break;
case "disconnect":
formatted = '<[color="' + playerColor + '"]' + msg.username + '[/color]> [color="64 64 64"]has left[/color]';
break;
case "message":
formatted = '<[color="' + playerColor + '"]' + msg.username + '[/color]> ' + msg.text;
break;
default:
error("Invalid chat message '" + uneval(msg) + "'");
return;
}
var timerExpiredFunction = function () { removeOldChatMessages(); }
g_ChatMessages.push(formatted);
g_ChatTimers.push(setTimeout(timerExpiredFunction, 30000));
if (g_ChatMessages.length > maxNumChatLines)
{
clearTimeout(g_ChatTimers[0]);
g_ChatTimers.shift();
g_ChatMessages.shift();
}
getGUIObjectByName("chatText").caption = g_ChatMessages.join("\n");
}
function removeOldChatMessages()
{
clearTimeout(g_ChatTimers[0]);
g_ChatTimers.shift();
g_ChatMessages.shift();
getGUIObjectByName("chatText").caption = g_ChatMessages.join("\n");
}
function onTick()
{
while (true)
@ -125,7 +262,11 @@ function onSimulationUpdate()
updateDebug(simState);
updatePlayerDisplay(simState);
updateSelectionDetails(simState);
updateSelectionDetails();
if (g_ChatTimers.length)
console.write(g_ChatTimers[0]);
}
function updateDebug(simState)
@ -161,7 +302,6 @@ function updateDebug(simState)
function updatePlayerDisplay(simState)
{
var playerState = simState.players[Engine.GetPlayerID()];
if (!playerState)
return;

View File

@ -51,9 +51,14 @@
]]></action>
</object>
<!-- Depending on the current state, it either opens message window or closes message window / posts message -->
<object hotkey="chat">
<action on="Press">toggleChatWindow();</action>
</object>
<!-- Delete button Hotkey (For some reason it won't work when the console is visible -->
<object hotkey="killUnit">
<action on="Press">performCommand(g_Selection.toList()[0], "delete")</action>
<action on="Press">performCommand(g_Selection.toList()[0], "delete");</action>
</object>
<!-- ================================ ================================ -->
@ -119,6 +124,27 @@
<action on="Press">togglePause();</action>
</object>
<!-- ================================ ================================ -->
<!-- Chat -->
<!-- ================================ ================================ -->
<!-- Chat panel -->
<object name="chatPanel" size="0 50 512 100%-200" type="image" ghost="true">
<object name="chatText" size="3 1 100%-1 100%-25" type="text" style="chatPanel" ghost="true"/>
</object>
<!-- Chat window -->
<object name="chatWindow" size="50%-200 50%-13 50%+200 50%+13" type="image" sprite="wheatIndentFillLight" hidden="true" z="10">
<object name="chatInput" size="2 100%-23 100%-66 100%-3" type="input" style="wheatInput" max_length="40">
<action on="Press">submitChatInput();</action>
</object>
<object size="100%-65 100%-25 100%-1 100%" type="button" style="wheatButton">
Send
<action on="Press">submitChatInput();</action>
</object>
</object>
<!-- ================================ ================================ -->
<!-- Settings Window -->
<!-- ================================ ================================ -->
@ -127,7 +153,7 @@
type="image"
size="50%-180 50%-200 50%+180 50%+50"
hidden="true"
z="50"
z="30"
>
<object name="settingsTitleBar" style="wheatWindowTitleBar" type="text">Settings</object>
@ -178,10 +204,11 @@
<!-- Menu Details -->
<!-- ================================ ================================ -->
<object name="menu"
size="0 0 114 128"
size="0 0 114 160"
type="image"
sprite="menuBackground"
hidden="true"
z="20"
>
<!-- Settings button -->
<object type="button"
@ -194,14 +221,25 @@
<action on="Press">toggleSettingsWindow();</action>
</object>
<!-- Chat button -->
<object type="button"
name="chatButton"
style="wheatButtonFancy"
size="0 64 114 96"
tooltip_style="snToolTip"
>
<object size="0 0 100% 100%" type="text" style="centeredText" name="chatButtonText" ghost="true">Chat</object>
<action on="Press">toggleChatWindow();</action>
</object>
<!-- Pause Button -->
<object type="button"
style="wheatButtonFancy"
name="pauseButton"
size="0 64 114 96"
size="0 96 114 128"
tooltip_style="snToolTip"
>
<object size="0 0 100% 100%" type="text" ghost="true" style="centeredText">Pause Game</object>
<object size="0 0 100% 100%" type="text" ghost="true" style="centeredText">Pause</object>
<action on="Press">togglePause();</action>
</object>
@ -209,10 +247,10 @@
<object type="button"
name="exitButton"
style="wheatButtonFancy"
size="0 96 114 128"
size="0 128 114 160"
tooltip_style="snToolTip"
>
<object size="0 0 100% 100%" type="text" style="centeredText" name="exitButtonText" ghost="true" font="serif-14">Quit Game</object>
<object size="0 0 100% 100%" type="text" style="centeredText" name="exitButtonText" ghost="true" font="serif-14">Quit</object>
<action on="Press">
toggleMenu();
<![CDATA[messageBox(400, 200, "Do you really want to quit?", "Confirmation", 0, ["Yes", "No!"], [leaveGame, null]);]]>
@ -226,6 +264,7 @@
style="wheatButtonFancy"
size="0 0 114 32"
tooltip_style="snToolTip"
z="30"
>
<object size="0 0 100% 100%" type="text" style="largeBoldCenteredText" name="menuButtonText" ghost="true">Menu</object>
<action on="Press">toggleMenu();</action>

View File

@ -146,4 +146,13 @@
sprite="netStatusBackground"
/>
<style name="chatPanel"
buffer_zone="5"
font="serif-bold-13"
textcolor="white"
textcolor_selected="white"
text_align="left"
text_valign="top"
/>
</styles>