forked from mirrors/0ad
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.
This commit is contained in:
@@ -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
|
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
|
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
|
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.
|
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]
|
[gui.splashscreen]
|
||||||
|
|||||||
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
1 1
|
||||||
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
@@ -595,10 +595,15 @@
|
|||||||
"config": "gui.session.notifications.barter"
|
"config": "gui.session.notifications.barter"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "boolean",
|
"type": "dropdown",
|
||||||
"label": "Chat notification flare",
|
"label": "Chat notification flare",
|
||||||
"tooltip": "Show a chat notification when you or an ally sends a flare.",
|
"tooltip": "Show a chat notification when a player sends a flare.",
|
||||||
"config": "gui.session.notifications.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",
|
"type": "dropdown",
|
||||||
|
|||||||
@@ -177,12 +177,22 @@ ChatMessageFormatSimulation.tribute = class
|
|||||||
|
|
||||||
ChatMessageFormatSimulation.flare = 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)
|
parse(msg)
|
||||||
{
|
{
|
||||||
if (Engine.ConfigDB_GetValue("user", "gui.session.notifications.flare") != "true")
|
switch (Engine.ConfigDB_GetValue("user", "gui.session.notifications.flare"))
|
||||||
|
{
|
||||||
|
case "never":
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
|
case "observer":
|
||||||
|
if (!g_IsObserver)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"text": sprintf(translate("%(icon)s%(player)s has sent a flare."), {
|
"text": sprintf(translate("%(icon)s%(player)s has sent a flare."), {
|
||||||
"icon": "[icon=\"icon_focusflare\" displace=\"0 1\"]",
|
"icon": "[icon=\"icon_focusflare\" displace=\"0 1\"]",
|
||||||
|
|||||||
@@ -101,9 +101,13 @@ function updateCursorAndTooltip()
|
|||||||
let cursorSet = false;
|
let cursorSet = false;
|
||||||
let tooltipSet = false;
|
let tooltipSet = false;
|
||||||
let informationTooltip = Engine.GetGUIObjectByName("informationTooltip");
|
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;
|
cursorSet = true;
|
||||||
}
|
}
|
||||||
else if (!mouseIsOverObject && (inputState == INPUT_NORMAL || inputState == INPUT_PRESELECTEDACTION) || g_MiniMapPanel.isMouseOverMiniMap())
|
else if (!mouseIsOverObject && (inputState == INPUT_NORMAL || inputState == INPUT_PRESELECTEDACTION) || g_MiniMapPanel.isMouseOverMiniMap())
|
||||||
@@ -825,7 +829,7 @@ function handleInputAfterGui(ev)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
case "mousebuttondown":
|
case "mousebuttondown":
|
||||||
if (Engine.HotkeyIsPressed("session.flare") && controlsPlayer(g_ViewedPlayer))
|
if (Engine.HotkeyIsPressed("session.flare"))
|
||||||
{
|
{
|
||||||
triggerFlareAction(Engine.GetTerrainAtScreenPoint(ev.x, ev.y));
|
triggerFlareAction(Engine.GetTerrainAtScreenPoint(ev.x, ev.y));
|
||||||
return true;
|
return true;
|
||||||
@@ -1134,7 +1138,7 @@ function handleInputAfterGui(ev)
|
|||||||
case INPUT_FLARE:
|
case INPUT_FLARE:
|
||||||
if (ev.type == "mousebuttondown")
|
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));
|
triggerFlareAction(Engine.GetTerrainAtScreenPoint(ev.x, ev.y));
|
||||||
inputState = INPUT_NORMAL;
|
inputState = INPUT_NORMAL;
|
||||||
|
|||||||
@@ -290,24 +290,26 @@ var g_NotificationsTypes =
|
|||||||
},
|
},
|
||||||
"map-flare": function(notification, player)
|
"map-flare": function(notification, player)
|
||||||
{
|
{
|
||||||
// Don't display for the player that did the flare because they will see it immediately
|
const shouldSeeFlare = g_IsObserver || g_Players[player]?.isMutualAlly[Engine.GetPlayerID()];
|
||||||
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);
|
|
||||||
|
|
||||||
displayFlare(notification.position, notification.guid);
|
// Don't display for the player that did the flare because they will see it immediately.
|
||||||
Engine.PlayUISound(g_FlareSound, false);
|
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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class MiniMap
|
|||||||
{
|
{
|
||||||
// Partly duplicated from handleInputAfterGui(), but with the input being
|
// Partly duplicated from handleInputAfterGui(), but with the input being
|
||||||
// world coordinates instead of screen coordinates.
|
// 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);
|
triggerFlareAction(target);
|
||||||
return true;
|
return true;
|
||||||
@@ -97,6 +97,10 @@ class MiniMap
|
|||||||
|
|
||||||
flare(target, playerID)
|
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)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,9 +57,6 @@
|
|||||||
size="2 4 117 119"
|
size="2 4 117 119"
|
||||||
tooltip_style="sessionToolTip"
|
tooltip_style="sessionToolTip"
|
||||||
hotkey="session.flareactivate"
|
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"
|
mouse_event_mask="texture:session/minimap-flare.png"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
class MiniMapFlareButton
|
||||||
{
|
{
|
||||||
@@ -13,23 +13,36 @@ class MiniMapFlareButton
|
|||||||
|
|
||||||
rebuild()
|
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()
|
onHotkeyChange()
|
||||||
{
|
{
|
||||||
this.flareButton.tooltip =
|
this.colorizedHotkey = colorizeHotkey("%(hotkey)s" + " ", "session.flare");
|
||||||
colorizeHotkey("%(hotkey)s" + " ", "session.flare") +
|
this.updateTooltip();
|
||||||
translate(this.Tooltip);
|
}
|
||||||
|
|
||||||
|
updateTooltip()
|
||||||
|
{
|
||||||
|
this.flareButton.tooltip = this.colorizedHotkey + (g_IsObserver ? this.ObserverTooltip : this.PlayerTooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
onPress()
|
onPress()
|
||||||
{
|
{
|
||||||
if (g_IsObserver)
|
|
||||||
return;
|
|
||||||
if (inputState == INPUT_NORMAL)
|
if (inputState == INPUT_NORMAL)
|
||||||
inputState = INPUT_FLARE;
|
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.");
|
||||||
|
|||||||
@@ -1944,7 +1944,8 @@ function displayFlare(position, playerGUID)
|
|||||||
"template": g_TargetMarker.map_flare,
|
"template": g_TargetMarker.map_flare,
|
||||||
"x": position.x,
|
"x": position.x,
|
||||||
"z": position.z,
|
"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);
|
g_MiniMapPanel.flare(position, playerID);
|
||||||
addChatMessage({
|
addChatMessage({
|
||||||
|
|||||||
@@ -4,6 +4,13 @@ var g_DebugCommands = false;
|
|||||||
|
|
||||||
function ProcessCommand(player, cmd)
|
function ProcessCommand(player, cmd)
|
||||||
{
|
{
|
||||||
|
if (player == -1)
|
||||||
|
{
|
||||||
|
if (g_ObserverCommands[cmd.type])
|
||||||
|
g_ObserverCommands[cmd.type](player, cmd, {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let cmpPlayer = QueryPlayerIDInterface(player);
|
let cmpPlayer = QueryPlayerIDInterface(player);
|
||||||
if (!cmpPlayer)
|
if (!cmpPlayer)
|
||||||
return;
|
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.
|
* Sends a GUI notification about unit(s) that failed to ungarrison.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user