Index: binaries/data/mods/public/gui/session/messages.js =================================================================== --- binaries/data/mods/public/gui/session/messages.js +++ binaries/data/mods/public/gui/session/messages.js @@ -9,11 +9,6 @@ var g_ChatTimeout = 30; /** - * Maximum number of lines to display simultaneously. - */ -var g_ChatLines = 20; - -/** * The currently displayed strings, limited by the given timeframe and limit above. */ var g_ChatMessages = []; @@ -98,42 +93,55 @@ }; var g_FormatChatMessage = { - "system": msg => msg.text, - "connect": msg => - sprintf( - g_PlayerAssignments[msg.guid].player != -1 ? - // Translation: A player that left the game joins again - translate("%(player)s is starting to rejoin the game.") : - // Translation: A player joins the game for the first time - translate("%(player)s is starting to join the game."), - { "player": colorizePlayernameByGUID(msg.guid) } - ), - "disconnect": msg => - sprintf(translate("%(player)s has left the game."), { - "player": colorizePlayernameByGUID(msg.guid) - }), - "rejoined": msg => - sprintf( - g_PlayerAssignments[msg.guid].player != -1 ? - // Translation: A player that left the game joins again - translate("%(player)s has rejoined the game.") : - // Translation: A player joins the game for the first time - translate("%(player)s has joined the game."), - { "player": colorizePlayernameByGUID(msg.guid) } - ), - "kicked": msg => - sprintf( - msg.banned ? - translate("%(username)s has been banned") : - translate("%(username)s has been kicked"), - { - "username": colorizePlayernameHelper( - msg.username, - g_Players.findIndex(p => p.name == msg.username) - ) - } - ), - "clientlist": msg => getUsernameList(), + "system": msg => { + return { "text": msg.text }; + }, + "connect": msg => { + return { + "text": sprintf( + g_PlayerAssignments[msg.guid].player != -1 ? + // Translation: A player that left the game joins again + translate("%(player)s is starting to rejoin the game.") : + // Translation: A player joins the game for the first time + translate("%(player)s is starting to join the game."), + { "player": colorizePlayernameByGUID(msg.guid) } + )}; + }, + "disconnect": msg => { + return { + "text": sprintf(translate("%(player)s has left the game."), { + "player": colorizePlayernameByGUID(msg.guid) + })}; + }, + "rejoined": msg => { + return { + "text": sprintf( + g_PlayerAssignments[msg.guid].player != -1 ? + // Translation: A player that left the game joins again + translate("%(player)s has rejoined the game.") : + // Translation: A player joins the game for the first time + translate("%(player)s has joined the game."), + { "player": colorizePlayernameByGUID(msg.guid) } + )}; + }, + "kicked": msg => { + return { + "text": sprintf( + msg.banned ? + translate("%(username)s has been banned") : + translate("%(username)s has been kicked"), + { + "username": colorizePlayernameHelper( + msg.username, + g_Players.findIndex(p => p.name == msg.username) + ) + } + ) + }; + }, + "clientlist": msg => ({ + "text": getUsernameList() + }), "message": msg => formatChatCommand(msg), "defeat-victory": msg => formatDefeatVictoryMessage(msg.message, msg.players), "diplomacy": msg => formatDiplomacyMessage(msg), @@ -401,10 +409,13 @@ if (Engine.ConfigDB_GetValue("user", "gui.session.notifications.attack") !== "true") return; + let entState = GetEntityState(notification.target); addChatMessage({ "type": "attack", "player": player, "attacker": notification.attacker, + "target": notification.target, + "position": entState && entState.position, "targetIsDomesticAnimal": notification.targetIsDomesticAnimal }); }, @@ -901,6 +912,41 @@ submitChatDirectly(text); } +function showChatMessages() +{ + for (let i = 0; i < Engine.GetGUIObjectByName("chatPanel").children.length; ++i) + { + let chatLine = Engine.GetGUIObjectByName("chatLine[" + i + "]"); + if (g_ChatMessages[i] && g_ChatMessages[i].text) + { + // First scale line width to maximum size. + let lineSize = chatLine.size; + let height = lineSize.bottom - lineSize.top; + lineSize.top = i * height; + lineSize.bottom = lineSize.top + height; + lineSize.rright = 100; + chatLine.size = lineSize; + + chatLine.caption = g_ChatMessages[i].text; + + // Now read the actual text width and scale the line width accordingly. + lineSize.rright = 0; + lineSize.right = lineSize.left + chatLine.getTextSize().width; + chatLine.size = lineSize; + + if (g_ChatMessages[i].target) + chatLine.onPress = ((entityId, position) => function() { + if (GetEntityState(entityId)) + setCameraFollow(entityId); + else + Engine.SetCameraTarget(position.x, position.y, position.z); + })(g_ChatMessages[i].target, g_ChatMessages[i].position); + } + chatLine.hidden = !g_ChatMessages[i] || !g_ChatMessages[i].text; + chatLine.ghost = !g_ChatMessages[i] || !g_ChatMessages[i].target; + } +} + /** * Displays the prepared chatmessage. * @@ -912,21 +958,21 @@ return; let formatted = g_FormatChatMessage[msg.type](msg); - if (!formatted) + if (!formatted || !formatted.text) return; // Update chat overlay g_ChatMessages.push(formatted); g_ChatTimers.push(setTimeout(removeOldChatMessage, g_ChatTimeout * 1000)); - if (g_ChatMessages.length > g_ChatLines) + if (g_ChatMessages.length > Engine.GetGUIObjectByName("chatPanel").children.length) removeOldChatMessage(); else - Engine.GetGUIObjectByName("chatText").caption = g_ChatMessages.join("\n"); + showChatMessages(); // Save to chat history let historical = { - "txt": formatted, + "txt": formatted.text, "timePrefix": sprintf(translate("\\[%(time)s]"), { "time": Engine.FormatMillisecondsIntoDateStringLocal(Date.now(), translate("HH:mm")) }), @@ -950,7 +996,7 @@ clearTimeout(g_ChatTimers[0]); g_ChatTimers.shift(); g_ChatMessages.shift(); - Engine.GetGUIObjectByName("chatText").caption = g_ChatMessages.join("\n"); + showChatMessages(); } /** @@ -988,18 +1034,20 @@ function formatDefeatVictoryMessage(message, players) { if (!message.pluralMessage) - return sprintf(translate(message), { - "player": colorizePlayernameByID(players[0]) - }); + return { + "text": sprintf(translate(message), { + "player": colorizePlayernameByID(players[0]) + })}; let mPlayers = players.map(playerID => colorizePlayernameByID(playerID)); let lastPlayer = mPlayers.pop(); - return sprintf(translatePlural(message.message, message.pluralMessage, message.pluralCount), { - // Translation: This comma is used for separating first to penultimate elements in an enumeration. - "players": mPlayers.join(translate(", ")), - "lastPlayer": lastPlayer - }); + return { + "text": sprintf(translatePlural(message.message, message.pluralMessage, message.pluralCount), { + // Translation: This comma is used for separating first to penultimate elements in an enumeration. + "players": mPlayers.join(translate(", ")), + "lastPlayer": lastPlayer + })}; } function formatDiplomacyMessage(msg) @@ -1015,10 +1063,11 @@ else return ""; - return sprintf(g_DiplomacyMessages[messageType][msg.status], { - "player": colorizePlayernameByID(messageType == "active" ? msg.targetPlayer : msg.sourcePlayer), - "player2": colorizePlayernameByID(messageType == "active" ? msg.sourcePlayer : msg.targetPlayer) - }); + return { + "text": sprintf(g_DiplomacyMessages[messageType][msg.status], { + "player": colorizePlayernameByID(messageType == "active" ? msg.targetPlayer : msg.sourcePlayer), + "player2": colorizePlayernameByID(messageType == "active" ? msg.sourcePlayer : msg.targetPlayer) + })}; } /** @@ -1038,11 +1087,12 @@ g_Players[msg.targetPlayer].isMutualAlly[Engine.GetPlayerID()])) message = translate("%(player)s has sent %(player2)s %(amounts)s."); - return sprintf(message, { - "player": colorizePlayernameByID(msg.sourcePlayer), - "player2": colorizePlayernameByID(msg.targetPlayer), - "amounts": getLocalizedResourceAmounts(msg.amounts) - }); + return { + "text": sprintf(message, { + "player": colorizePlayernameByID(msg.sourcePlayer), + "player2": colorizePlayernameByID(msg.targetPlayer), + "amounts": getLocalizedResourceAmounts(msg.amounts) + })}; } function formatBarterMessage(msg) @@ -1056,11 +1106,12 @@ let amountsBought = {}; amountsBought[msg.resourceBought] = msg.amountsBought; - return sprintf(translate("%(player)s bartered %(amountsBought)s for %(amountsSold)s."), { - "player": colorizePlayernameByID(msg.player), - "amountsBought": getLocalizedResourceAmounts(amountsBought), - "amountsSold": getLocalizedResourceAmounts(amountsSold) - }); + return { + "text": sprintf(translate("%(player)s bartered %(amountsBought)s for %(amountsSold)s."), { + "player": colorizePlayernameByID(msg.player), + "amountsBought": getLocalizedResourceAmounts(amountsBought), + "amountsSold": getLocalizedResourceAmounts(amountsSold) + })}; } function formatAttackMessage(msg) @@ -1072,9 +1123,11 @@ translate("Your livestock has been attacked by %(attacker)s!") : translate("You have been attacked by %(attacker)s!"); - return sprintf(message, { - "attacker": colorizePlayernameByID(msg.attacker) - }); + return { + "target": msg.target, + "position": msg.position, + "text": sprintf(message, { "attacker": colorizePlayernameByID(msg.attacker) }) + }; } function formatPhaseMessage(msg) @@ -1094,10 +1147,11 @@ if (msg.phaseState == "completed") message = translate("%(player)s has reached the %(phaseName)s."); - return sprintf(message, { - "player": colorizePlayernameByID(msg.player), - "phaseName": getEntityNames(GetTechnologyData(msg.phaseName, g_Players[msg.player].civ)) - }); + return { + "text": sprintf(message, { + "player": colorizePlayernameByID(msg.player), + "phaseName": getEntityNames(GetTechnologyData(msg.phaseName, g_Players[msg.player].civ)) + })}; } function formatChatCommand(msg) @@ -1140,12 +1194,13 @@ // GUID for players, playerID for AIs let coloredUsername = msg.guid != -1 ? colorizePlayernameByGUID(msg.guid) : colorizePlayernameByID(msg.player); - return sprintf(g_ChatCommands[isMe ? "me" : "regular"][msg.context ? "context" : "no-context"], { - "message": msg.text, - "context": msg.context || undefined, - "user": coloredUsername, - "userTag": sprintf(translate("<%(user)s>"), { "user": coloredUsername }) - }); + return { + "text": sprintf(g_ChatCommands[isMe ? "me" : "regular"][msg.context ? "context" : "no-context"], { + "message": msg.text, + "context": msg.context || undefined, + "user": coloredUsername, + "userTag": sprintf(translate("<%(user)s>"), { "user": coloredUsername }) + })}; } /** Index: binaries/data/mods/public/gui/session/session.xml =================================================================== --- binaries/data/mods/public/gui/session/session.xml +++ binaries/data/mods/public/gui/session/session.xml @@ -78,8 +78,10 @@ - - + + +