diff --git a/binaries/data/config/default.cfg b/binaries/data/config/default.cfg index 29b22b062e..e512bf322d 100644 --- a/binaries/data/config/default.cfg +++ b/binaries/data/config/default.cfg @@ -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. diff --git a/binaries/data/mods/public/gui/gamesetup/gamesetup.js b/binaries/data/mods/public/gui/gamesetup/gamesetup.js index 588251c7ff..c3540598bf 100644 --- a/binaries/data/mods/public/gui/gamesetup/gamesetup.js +++ b/binaries/data/mods/public/gui/gamesetup/gamesetup.js @@ -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": diff --git a/binaries/data/mods/public/gui/loading/loading.js b/binaries/data/mods/public/gui/loading/loading.js index adf88b4e67..752f6b60e1 100644 --- a/binaries/data/mods/public/gui/loading/loading.js +++ b/binaries/data/mods/public/gui/loading/loading.js @@ -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"); diff --git a/binaries/data/mods/public/gui/session_new/menu.js b/binaries/data/mods/public/gui/session_new/menu.js index 8edc60dd59..96842808b6 100644 --- a/binaries/data/mods/public/gui/session_new/menu.js +++ b/binaries/data/mods/public/gui/session_new/menu.js @@ -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 } \ No newline at end of file diff --git a/binaries/data/mods/public/gui/session_new/selection_details.js b/binaries/data/mods/public/gui/session_new/selection_details.js index b5ae69eb14..69b5ac1e7d 100644 --- a/binaries/data/mods/public/gui/session_new/selection_details.js +++ b/binaries/data/mods/public/gui/session_new/selection_details.js @@ -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; diff --git a/binaries/data/mods/public/gui/session_new/session.js b/binaries/data/mods/public/gui/session_new/session.js index a4947906ae..5fc91f6c9f 100644 --- a/binaries/data/mods/public/gui/session_new/session.js +++ b/binaries/data/mods/public/gui/session_new/session.js @@ -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; diff --git a/binaries/data/mods/public/gui/session_new/session.xml b/binaries/data/mods/public/gui/session_new/session.xml index 3fee4406ed..9d115244f8 100644 --- a/binaries/data/mods/public/gui/session_new/session.xml +++ b/binaries/data/mods/public/gui/session_new/session.xml @@ -51,9 +51,14 @@ ]]> + + + toggleChatWindow(); + + - performCommand(g_Selection.toList()[0], "delete") + performCommand(g_Selection.toList()[0], "delete"); @@ -119,6 +124,27 @@ togglePause(); + + + + + + + + + + + + @@ -127,7 +153,7 @@ type="image" size="50%-180 50%-200 50%+180 50%+50" hidden="true" - z="50" + z="30" > Settings @@ -178,10 +204,11 @@