From a1796ed71f0cfbcb052faa47e8642af7ff8fb3cb Mon Sep 17 00:00:00 2001 From: Vantha Date: Thu, 14 Nov 2024 10:26:09 +0100 Subject: [PATCH] Enable observers to see and send flares This patch gives observers the possibility to see and send flares. Players keep their color after resigning and "true" observers flare in white. Observers render all flares; the ones sent by any player or observer. Player continue to only see their allies' flares. The flare notification option is converted into a dropdown. -> adding the possibility to only receive them as observer. --- binaries/data/config/default.cfg | 2 +- .../cursors/action-observer-flare.png | 3 ++ ...on-flare.txt => action-observer-flare.txt} | 0 ...tion-flare.png => action-player-flare.png} | 0 .../textures/cursors/action-player-flare.txt | 1 + .../ui/session/minimap-flare-disabled.png | 3 -- .../minimap-observer-flare-highlight.png | 3 ++ .../ui/session/minimap-observer-flare.png | 3 ++ ...png => minimap-player-flare-highlight.png} | 0 ...map-flare.png => minimap-player-flare.png} | 0 .../data/mods/public/gui/options/options.json | 11 ++++-- .../chat/ChatMessageFormatSimulation.js | 14 ++++++-- .../data/mods/public/gui/session/input.js | 12 ++++--- .../data/mods/public/gui/session/messages.js | 34 ++++++++++--------- .../public/gui/session/minimap/MiniMap.js | 8 +++-- .../public/gui/session/minimap/MiniMap.xml | 3 -- .../gui/session/minimap/MiniMapFlareButton.js | 29 +++++++++++----- .../mods/public/gui/session/unit_actions.js | 3 +- .../public/simulation/helpers/Commands.js | 11 ++++++ 19 files changed, 97 insertions(+), 43 deletions(-) create mode 100644 binaries/data/mods/public/art/textures/cursors/action-observer-flare.png rename binaries/data/mods/public/art/textures/cursors/{action-flare.txt => action-observer-flare.txt} (100%) rename binaries/data/mods/public/art/textures/cursors/{action-flare.png => action-player-flare.png} (100%) create mode 100644 binaries/data/mods/public/art/textures/cursors/action-player-flare.txt delete mode 100644 binaries/data/mods/public/art/textures/ui/session/minimap-flare-disabled.png create mode 100644 binaries/data/mods/public/art/textures/ui/session/minimap-observer-flare-highlight.png create mode 100644 binaries/data/mods/public/art/textures/ui/session/minimap-observer-flare.png rename binaries/data/mods/public/art/textures/ui/session/{minimap-flare-highlight.png => minimap-player-flare-highlight.png} (100%) rename binaries/data/mods/public/art/textures/ui/session/{minimap-flare.png => minimap-player-flare.png} (100%) diff --git a/binaries/data/config/default.cfg b/binaries/data/config/default.cfg index 8106beb054..36ebb04e66 100644 --- a/binaries/data/config/default.cfg +++ b/binaries/data/config/default.cfg @@ -477,7 +477,7 @@ pingduration = 50.0 ; The duration for which an entity will be pin attack = true ; Show a chat notification if you are attacked by another player tribute = true ; Show a chat notification if an ally tributes resources to another team member if teams are locked, and all tributes in observer mode barter = true ; Show a chat notification to observers when a player bartered resources -flare = true ; Show a chat notification when a you or an ally sends a flare +flare = always ; Show a chat notification when a player sends a flare. Possible values: never, observer, always. phase = completed ; Show a chat notification if you or an ally have started, aborted or completed a new phase, and phases of all players in observer mode. Possible values: none, completed, all. [gui.splashscreen] diff --git a/binaries/data/mods/public/art/textures/cursors/action-observer-flare.png b/binaries/data/mods/public/art/textures/cursors/action-observer-flare.png new file mode 100644 index 0000000000..95f725dae6 --- /dev/null +++ b/binaries/data/mods/public/art/textures/cursors/action-observer-flare.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11022a8511dfb6779248ae55590973942e6469681f78f78a8e27a9a01c6aed5d +size 1653 diff --git a/binaries/data/mods/public/art/textures/cursors/action-flare.txt b/binaries/data/mods/public/art/textures/cursors/action-observer-flare.txt similarity index 100% rename from binaries/data/mods/public/art/textures/cursors/action-flare.txt rename to binaries/data/mods/public/art/textures/cursors/action-observer-flare.txt diff --git a/binaries/data/mods/public/art/textures/cursors/action-flare.png b/binaries/data/mods/public/art/textures/cursors/action-player-flare.png similarity index 100% rename from binaries/data/mods/public/art/textures/cursors/action-flare.png rename to binaries/data/mods/public/art/textures/cursors/action-player-flare.png diff --git a/binaries/data/mods/public/art/textures/cursors/action-player-flare.txt b/binaries/data/mods/public/art/textures/cursors/action-player-flare.txt new file mode 100644 index 0000000000..2fb73a07ec --- /dev/null +++ b/binaries/data/mods/public/art/textures/cursors/action-player-flare.txt @@ -0,0 +1 @@ +1 1 diff --git a/binaries/data/mods/public/art/textures/ui/session/minimap-flare-disabled.png b/binaries/data/mods/public/art/textures/ui/session/minimap-flare-disabled.png deleted file mode 100644 index 2762b4d945..0000000000 --- a/binaries/data/mods/public/art/textures/ui/session/minimap-flare-disabled.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:41432cec030750dc8ba0fd3a1ff496c50a5731e78f6c12164d97fd991b37ae63 -size 13267 diff --git a/binaries/data/mods/public/art/textures/ui/session/minimap-observer-flare-highlight.png b/binaries/data/mods/public/art/textures/ui/session/minimap-observer-flare-highlight.png new file mode 100644 index 0000000000..ec71983ccf --- /dev/null +++ b/binaries/data/mods/public/art/textures/ui/session/minimap-observer-flare-highlight.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f2680500fd122178db80b378e19821eb30baf639edc46eacc3d23c97b19481c +size 6214 diff --git a/binaries/data/mods/public/art/textures/ui/session/minimap-observer-flare.png b/binaries/data/mods/public/art/textures/ui/session/minimap-observer-flare.png new file mode 100644 index 0000000000..753652d3da --- /dev/null +++ b/binaries/data/mods/public/art/textures/ui/session/minimap-observer-flare.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85d985e5b208f4947fe2bf580a5f181990892620c50f1dd356655d879a94aea4 +size 5356 diff --git a/binaries/data/mods/public/art/textures/ui/session/minimap-flare-highlight.png b/binaries/data/mods/public/art/textures/ui/session/minimap-player-flare-highlight.png similarity index 100% rename from binaries/data/mods/public/art/textures/ui/session/minimap-flare-highlight.png rename to binaries/data/mods/public/art/textures/ui/session/minimap-player-flare-highlight.png diff --git a/binaries/data/mods/public/art/textures/ui/session/minimap-flare.png b/binaries/data/mods/public/art/textures/ui/session/minimap-player-flare.png similarity index 100% rename from binaries/data/mods/public/art/textures/ui/session/minimap-flare.png rename to binaries/data/mods/public/art/textures/ui/session/minimap-player-flare.png diff --git a/binaries/data/mods/public/gui/options/options.json b/binaries/data/mods/public/gui/options/options.json index 70a0299281..5b4af2326c 100644 --- a/binaries/data/mods/public/gui/options/options.json +++ b/binaries/data/mods/public/gui/options/options.json @@ -595,10 +595,15 @@ "config": "gui.session.notifications.barter" }, { - "type": "boolean", + "type": "dropdown", "label": "Chat notification flare", - "tooltip": "Show a chat notification when you or an ally sends a flare.", - "config": "gui.session.notifications.flare" + "tooltip": "Show a chat notification when a player sends a flare.", + "config": "gui.session.notifications.flare", + "list": [ + { "value": "never", "label": "Never", "tooltip": "Disable flare chat notifications."}, + { "value": "observer", "label": "Only as observer", "tooltip": "Only show flare chat notifications when you are observer."}, + { "value": "always", "label": "Always", "tooltip": "Always show flare chat notifications – as player and as observer."} + ] }, { "type": "dropdown", diff --git a/binaries/data/mods/public/gui/session/chat/ChatMessageFormatSimulation.js b/binaries/data/mods/public/gui/session/chat/ChatMessageFormatSimulation.js index 7cd3a15731..a801a329a7 100644 --- a/binaries/data/mods/public/gui/session/chat/ChatMessageFormatSimulation.js +++ b/binaries/data/mods/public/gui/session/chat/ChatMessageFormatSimulation.js @@ -177,12 +177,22 @@ ChatMessageFormatSimulation.tribute = class ChatMessageFormatSimulation.flare = class { - // We don't need to check whether the player is supposed to see the flare as this function is only ever called in that case + // We don't need to check whether the player is supposed to see the flare as this function is only ever called in that case. parse(msg) { - if (Engine.ConfigDB_GetValue("user", "gui.session.notifications.flare") != "true") + switch (Engine.ConfigDB_GetValue("user", "gui.session.notifications.flare")) + { + case "never": return ""; + case "observer": + if (!g_IsObserver) + return ""; + + default: + break; + } + return { "text": sprintf(translate("%(icon)s%(player)s has sent a flare."), { "icon": "[icon=\"icon_focusflare\" displace=\"0 1\"]", diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js index 2710979f3e..ef50a0c667 100644 --- a/binaries/data/mods/public/gui/session/input.js +++ b/binaries/data/mods/public/gui/session/input.js @@ -101,9 +101,13 @@ function updateCursorAndTooltip() let cursorSet = false; let tooltipSet = false; let informationTooltip = Engine.GetGUIObjectByName("informationTooltip"); - if (inputState == INPUT_FLARE || inputState == INPUT_NORMAL && Engine.HotkeyIsPressed("session.flare") && !g_IsObserver) + if (inputState == INPUT_FLARE || inputState == INPUT_NORMAL && Engine.HotkeyIsPressed("session.flare")) { - Engine.SetCursor("action-flare"); + Engine.SetCursor( + g_IsObserver ? + "action-observer-flare" : + "action-player-flare" + ); cursorSet = true; } else if (!mouseIsOverObject && (inputState == INPUT_NORMAL || inputState == INPUT_PRESELECTEDACTION) || g_MiniMapPanel.isMouseOverMiniMap()) @@ -825,7 +829,7 @@ function handleInputAfterGui(ev) return false; case "mousebuttondown": - if (Engine.HotkeyIsPressed("session.flare") && controlsPlayer(g_ViewedPlayer)) + if (Engine.HotkeyIsPressed("session.flare")) { triggerFlareAction(Engine.GetTerrainAtScreenPoint(ev.x, ev.y)); return true; @@ -1134,7 +1138,7 @@ function handleInputAfterGui(ev) case INPUT_FLARE: if (ev.type == "mousebuttondown") { - if (ev.button == SDL_BUTTON_LEFT && controlsPlayer(g_ViewedPlayer)) + if (ev.button == SDL_BUTTON_LEFT) { triggerFlareAction(Engine.GetTerrainAtScreenPoint(ev.x, ev.y)); inputState = INPUT_NORMAL; diff --git a/binaries/data/mods/public/gui/session/messages.js b/binaries/data/mods/public/gui/session/messages.js index 63100b58f4..7f688c5347 100644 --- a/binaries/data/mods/public/gui/session/messages.js +++ b/binaries/data/mods/public/gui/session/messages.js @@ -290,24 +290,26 @@ var g_NotificationsTypes = }, "map-flare": function(notification, player) { - // Don't display for the player that did the flare because they will see it immediately - if (player != Engine.GetPlayerID() && g_Players[player].isMutualAlly[Engine.GetPlayerID()]) - { - let now = Date.now(); - if (g_FlareRateLimitLastTimes.length) - { - g_FlareRateLimitLastTimes = g_FlareRateLimitLastTimes.filter(t => now - t < g_FlareRateLimitScope * 1000); - if (g_FlareRateLimitLastTimes.length >= g_FlareRateLimitMaximumFlares) - { - warn("Received too many flares. Dropping a flare request by '" + g_Players[player].name + "'."); - return; - } - } - g_FlareRateLimitLastTimes.push(now); + const shouldSeeFlare = g_IsObserver || g_Players[player]?.isMutualAlly[Engine.GetPlayerID()]; - displayFlare(notification.position, notification.guid); - Engine.PlayUISound(g_FlareSound, false); + // Don't display for the player that did the flare because they will see it immediately. + if (!shouldSeeFlare || notification.guid == Engine.GetPlayerGUID()) + return; + + let now = Date.now(); + if (g_FlareRateLimitLastTimes.length) + { + g_FlareRateLimitLastTimes = g_FlareRateLimitLastTimes.filter(t => now - t < g_FlareRateLimitScope * 1000); + if (g_FlareRateLimitLastTimes.length >= g_FlareRateLimitMaximumFlares) + { + warn("Received too many flares. Dropping a flare request by '" + g_Players[player].name + "'."); + return; + } } + g_FlareRateLimitLastTimes.push(now); + + displayFlare(notification.position, notification.guid); + Engine.PlayUISound(g_FlareSound, false); } }; diff --git a/binaries/data/mods/public/gui/session/minimap/MiniMap.js b/binaries/data/mods/public/gui/session/minimap/MiniMap.js index 3dc47c84d0..4b88643a85 100644 --- a/binaries/data/mods/public/gui/session/minimap/MiniMap.js +++ b/binaries/data/mods/public/gui/session/minimap/MiniMap.js @@ -28,7 +28,7 @@ class MiniMap { // Partly duplicated from handleInputAfterGui(), but with the input being // world coordinates instead of screen coordinates. - if (inputState == INPUT_NORMAL && controlsPlayer(g_ViewedPlayer) && Engine.HotkeyIsPressed("session.flare")) + if (inputState == INPUT_NORMAL && Engine.HotkeyIsPressed("session.flare")) { triggerFlareAction(target); return true; @@ -97,6 +97,10 @@ class MiniMap flare(target, playerID) { - return this.miniMap.flare({ "x": target.x, "y": target.z }, g_DiplomacyColors.getPlayerColor(playerID)); + return this.miniMap.flare( + { "x": target.x, "y": target.z }, + // Observers flare in white. + g_DiplomacyColors.getPlayerColor(playerID == -1 ? 0 : playerID) + ); } } diff --git a/binaries/data/mods/public/gui/session/minimap/MiniMap.xml b/binaries/data/mods/public/gui/session/minimap/MiniMap.xml index 74cf99fbf4..2b6cefa89e 100644 --- a/binaries/data/mods/public/gui/session/minimap/MiniMap.xml +++ b/binaries/data/mods/public/gui/session/minimap/MiniMap.xml @@ -57,9 +57,6 @@ size="2 4 117 119" tooltip_style="sessionToolTip" hotkey="session.flareactivate" - sprite="stretched:session/minimap-flare.png" - sprite_over="stretched:session/minimap-flare-highlight.png" - sprite_disabled="stretched:session/minimap-flare-disabled.png" mouse_event_mask="texture:session/minimap-flare.png" /> diff --git a/binaries/data/mods/public/gui/session/minimap/MiniMapFlareButton.js b/binaries/data/mods/public/gui/session/minimap/MiniMapFlareButton.js index 1130a8a1c6..e91f45bae8 100644 --- a/binaries/data/mods/public/gui/session/minimap/MiniMapFlareButton.js +++ b/binaries/data/mods/public/gui/session/minimap/MiniMapFlareButton.js @@ -1,5 +1,5 @@ /** - * If the button that this class manages is pressed, an idle unit having one of the given classes is selected. + * If the button that this class manages is pressed, the input state is switched to 'flare', letting the player send a flare by left-clicking on the map. */ class MiniMapFlareButton { @@ -13,23 +13,36 @@ class MiniMapFlareButton rebuild() { - this.flareButton.enabled = !g_IsObserver; + if (g_IsObserver) + { + this.flareButton.sprite = "stretched:session/minimap-observer-flare.png"; + this.flareButton.sprite_over = "stretched:session/minimap-observer-flare-highlight.png"; + } + else + { + this.flareButton.sprite = "stretched:session/minimap-player-flare.png"; + this.flareButton.sprite_over = "stretched:session/minimap-player-flare-highlight.png"; + } + this.updateTooltip(); } onHotkeyChange() { - this.flareButton.tooltip = - colorizeHotkey("%(hotkey)s" + " ", "session.flare") + - translate(this.Tooltip); + this.colorizedHotkey = colorizeHotkey("%(hotkey)s" + " ", "session.flare"); + this.updateTooltip(); + } + + updateTooltip() + { + this.flareButton.tooltip = this.colorizedHotkey + (g_IsObserver ? this.ObserverTooltip : this.PlayerTooltip); } onPress() { - if (g_IsObserver) - return; if (inputState == INPUT_NORMAL) inputState = INPUT_FLARE; } } -MiniMapFlareButton.prototype.Tooltip = markForTranslation("Send a flare to your allies"); +MiniMapFlareButton.prototype.PlayerTooltip = markForTranslation("Send a flare to your allies."); +MiniMapFlareButton.prototype.ObserverTooltip = markForTranslation("Send a flare to other observers."); diff --git a/binaries/data/mods/public/gui/session/unit_actions.js b/binaries/data/mods/public/gui/session/unit_actions.js index 316b7115ea..62673e1198 100644 --- a/binaries/data/mods/public/gui/session/unit_actions.js +++ b/binaries/data/mods/public/gui/session/unit_actions.js @@ -1944,7 +1944,8 @@ function displayFlare(position, playerGUID) "template": g_TargetMarker.map_flare, "x": position.x, "z": position.z, - "owner": playerID + // Set the owner to gaia if the flare was sent by an observer (to make the target marker white). + "owner": playerID != -1 ? playerID : 0 }); g_MiniMapPanel.flare(position, playerID); addChatMessage({ diff --git a/binaries/data/mods/public/simulation/helpers/Commands.js b/binaries/data/mods/public/simulation/helpers/Commands.js index 8498388f0d..8e301bb145 100644 --- a/binaries/data/mods/public/simulation/helpers/Commands.js +++ b/binaries/data/mods/public/simulation/helpers/Commands.js @@ -4,6 +4,13 @@ var g_DebugCommands = false; function ProcessCommand(player, cmd) { + if (player == -1) + { + if (g_ObserverCommands[cmd.type]) + g_ObserverCommands[cmd.type](player, cmd, {}); + return; + } + let cmpPlayer = QueryPlayerIDInterface(player); if (!cmpPlayer) return; @@ -908,6 +915,10 @@ var g_Commands = { }; +var g_ObserverCommands = { + "map-flare": g_Commands["map-flare"] +}; + /** * Sends a GUI notification about unit(s) that failed to ungarrison. */