Index: ps/trunk/binaries/data/mods/public/gui/common/gamedescription.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/common/gamedescription.js
+++ ps/trunk/binaries/data/mods/public/gui/common/gamedescription.js
@@ -449,13 +449,9 @@
/**
* Sets the win/defeat icon to indicate current player's state.
- * @param {string} state - The current in-game state of the player.
- * @param {string} imageID - The name of the XML image object to update.
*/
-function setOutcomeIcon(state, imageID)
+function setOutcomeIcon(state, image)
{
- let image = Engine.GetGUIObjectByName(imageID);
-
if (state == "won")
{
image.sprite = "stretched:session/icons/victory.png";
Index: ps/trunk/binaries/data/mods/public/gui/session/diplomacy/DiplomacyDialog.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/diplomacy/DiplomacyDialog.js
+++ ps/trunk/binaries/data/mods/public/gui/session/diplomacy/DiplomacyDialog.js
@@ -0,0 +1,89 @@
+/**
+ * This class is concerned with opening, closing and resizing the diplomacy dialog and
+ * relaying events to the classes that update individual elements of the dialog.
+ */
+class DiplomacyDialog
+{
+ constructor(diplomacyColors)
+ {
+ this.diplomacyDialogCeasefireCounter = new DiplomacyDialogCeasefireCounter();
+ this.diplomacyDialogColorsButton = new DiplomacyDialogColorsButton(diplomacyColors);
+ this.diplomacyDialogPlayerControlManager = undefined;
+
+ this.diplomacyDialogPanel = Engine.GetGUIObjectByName("diplomacyDialogPanel");
+ Engine.GetGUIObjectByName("diplomacyClose").onPress = this.close.bind(this);
+ }
+
+ onPlayerInit()
+ {
+ this.diplomacyDialogPlayerControlManager = new DiplomacyDialogPlayerControlManager();
+ this.resize();
+ }
+
+ onSpyResponse(notification, player)
+ {
+ this.diplomacyDialogPlayerControlManager.onSpyResponse(notification, player);
+ }
+
+ update()
+ {
+ if (!this.isOpen())
+ return;
+
+ if (g_ViewedPlayer >= 1)
+ this.updatePanels();
+ else
+ this.close();
+ }
+
+ updatePanels()
+ {
+ this.diplomacyDialogCeasefireCounter.update();
+ this.diplomacyDialogColorsButton.update();
+ this.diplomacyDialogPlayerControlManager.update();
+ }
+
+ open()
+ {
+ closeOpenDialogs();
+
+ if (g_ViewedPlayer < 1)
+ return;
+
+ this.updatePanels();
+ this.diplomacyDialogPanel.hidden = false;
+ }
+
+ close()
+ {
+ this.diplomacyDialogPanel.hidden = true;
+ }
+
+ isOpen()
+ {
+ return !this.diplomacyDialogPanel.hidden;
+ }
+
+ toggle()
+ {
+ let open = this.isOpen();
+
+ closeOpenDialogs();
+
+ if (!open)
+ this.open();
+ }
+
+ resize()
+ {
+ let widthOffset = DiplomacyDialogPlayerControl.prototype.TributeButtonManager.getWidthOffset() / 2;
+ let heightOffset = DiplomacyDialogPlayerControl.prototype.DiplomacyPlayerText.getHeightOffset() / 2;
+
+ let size = this.diplomacyDialogPanel.size;
+ size.left -= widthOffset;
+ size.right += widthOffset;
+ size.top -= heightOffset;
+ size.bottom += heightOffset;
+ this.diplomacyDialogPanel.size = size;
+ }
+}
Index: ps/trunk/binaries/data/mods/public/gui/session/diplomacy/DiplomacyDialog.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/diplomacy/DiplomacyDialog.xml
+++ ps/trunk/binaries/data/mods/public/gui/session/diplomacy/DiplomacyDialog.xml
@@ -0,0 +1,92 @@
+
+
+
Index: ps/trunk/binaries/data/mods/public/gui/session/diplomacy/DiplomacyDialogCeasefireCounter.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/diplomacy/DiplomacyDialogCeasefireCounter.js
+++ ps/trunk/binaries/data/mods/public/gui/session/diplomacy/DiplomacyDialogCeasefireCounter.js
@@ -0,0 +1,27 @@
+/**
+ * This class updates the ceasefire counter in the diplomacy dialog.
+ */
+class DiplomacyDialogCeasefireCounter
+{
+ constructor()
+ {
+ this.diplomacyCeasefireCounter = Engine.GetGUIObjectByName("diplomacyCeasefireCounter");
+ }
+
+ update()
+ {
+ let active = GetSimState().ceasefireActive;
+
+ this.diplomacyCeasefireCounter.hidden = !active;
+ if (!active)
+ return;
+
+ this.diplomacyCeasefireCounter.caption =
+ sprintf(translateWithContext("ceasefire", this.Caption), {
+ "time": timeToString(GetSimState().ceasefireTimeRemaining)
+ });
+ }
+}
+
+DiplomacyDialogCeasefireCounter.prototype.Caption =
+ markForTranslationWithContext("ceasefire", "Remaining ceasefire time: %(time)s.");
Index: ps/trunk/binaries/data/mods/public/gui/session/diplomacy/DiplomacyDialogColorsButton.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/diplomacy/DiplomacyDialogColorsButton.js
+++ ps/trunk/binaries/data/mods/public/gui/session/diplomacy/DiplomacyDialogColorsButton.js
@@ -0,0 +1,31 @@
+/**
+ * This class updates the diplomacy colors button within the diplomacy dialog.
+ */
+class DiplomacyDialogColorsButton
+{
+ constructor(diplomacyColors)
+ {
+ this.diplomacyColors = diplomacyColors;
+
+ this.diplomacyColorsWindowButton = Engine.GetGUIObjectByName("diplomacyColorsWindowButton");
+ this.diplomacyColorsWindowButtonIcon = Engine.GetGUIObjectByName("diplomacyColorsWindowButtonIcon");
+ this.diplomacyColorsWindowButton.onPress = diplomacyColors.toggle.bind(diplomacyColors);
+ }
+
+ update()
+ {
+ this.diplomacyColorsWindowButton.tooltip =
+ colorizeHotkey("%(hotkey)s" + " ", "session.diplomacycolors") +
+ translate(this.Tooltip);
+
+ this.diplomacyColorsWindowButtonIcon.sprite =
+ "stretched:" +
+ (this.diplomacyColors.isEnabled() ? this.SpriteEnabled : this.SpriteDisabled);
+ }
+}
+
+DiplomacyDialogColorsButton.prototype.Tooltip = markForTranslation("Toggle Diplomacy Colors");
+
+DiplomacyDialogColorsButton.prototype.SpriteEnabled = "session/icons/diplomacy-on.png";
+
+DiplomacyDialogColorsButton.prototype.SpriteDisabled = "session/icons/diplomacy.png";
Index: ps/trunk/binaries/data/mods/public/gui/session/diplomacy/DiplomacyPlayerControl.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/diplomacy/DiplomacyPlayerControl.js
+++ ps/trunk/binaries/data/mods/public/gui/session/diplomacy/DiplomacyPlayerControl.js
@@ -0,0 +1,51 @@
+/**
+ * The prototype of this class is extended by subclasses in according files.
+ */
+class DiplomacyDialogPlayerControl
+{
+}
+
+class DiplomacyDialogPlayerControlManager
+{
+ constructor()
+ {
+ this.controls = {};
+ for (let name in DiplomacyDialogPlayerControl.prototype)
+ {
+ this.controls[name] = [];
+
+ // Exclude gaia
+ for (let playerID = 1; playerID < g_Players.length; ++playerID)
+ this.controls[name][playerID] = new DiplomacyDialogPlayerControl.prototype[name](playerID);
+ }
+ }
+
+ isInactive(playerID)
+ {
+ return playerID == g_ViewedPlayer ||
+ isPlayerObserver(g_ViewedPlayer) ||
+ isPlayerObserver(playerID);
+ }
+
+ update()
+ {
+ for (let playerID = 1; playerID < g_Players.length; ++playerID)
+ {
+ let isInactive = this.isInactive(playerID);
+ for (let name in this.controls)
+ this.controls[name][playerID].update(isInactive);
+ }
+ }
+
+ onSpyResponse(notification, player)
+ {
+ for (let name in this.controls)
+ for (let playerID = 1; playerID < g_Players.length; ++playerID)
+ {
+ if (!this.controls[name][playerID].onSpyResponse)
+ break;
+
+ this.controls[name][playerID].onSpyResponse(notification, player);
+ }
+ }
+}
Index: ps/trunk/binaries/data/mods/public/gui/session/diplomacy/playercontrols/AttackRequestButton.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/diplomacy/playercontrols/AttackRequestButton.js
+++ ps/trunk/binaries/data/mods/public/gui/session/diplomacy/playercontrols/AttackRequestButton.js
@@ -0,0 +1,38 @@
+/**
+ * This class updates the attack request button per player within the diplomacy dialog.
+ * If an attack request is sent to Petra, the AI may respond with an attack or decline.
+ */
+DiplomacyDialogPlayerControl.prototype.AttackRequestButton = class
+{
+ constructor(playerID)
+ {
+ this.button = Engine.GetGUIObjectByName("diplomacyAttackRequest[" + (playerID - 1) + "]");
+ this.button.tooltip = translate(this.Tooltip);
+ this.button.onPress = this.onPress.bind(this);
+
+ this.playerID = playerID;
+ }
+
+ update(playerInactive)
+ {
+ this.button.enabled = controlsPlayer(g_ViewedPlayer);
+ this.button.hidden =
+ playerInactive ||
+ GetSimState().ceasefireActive ||
+ !g_Players[g_ViewedPlayer].isEnemy[this.playerID] ||
+ g_Players[g_ViewedPlayer].isMutualAlly.every(
+ (isMutualAlly, playerID) => !isMutualAlly || playerID == g_ViewedPlayer);
+ }
+
+ onPress()
+ {
+ Engine.PostNetworkCommand({
+ "type": "attack-request",
+ "source": g_ViewedPlayer,
+ "player": this.playerID
+ });
+ }
+};
+
+DiplomacyDialogPlayerControl.prototype.AttackRequestButton.prototype.Tooltip =
+ markForTranslation("Request your allies to attack this enemy");
Index: ps/trunk/binaries/data/mods/public/gui/session/diplomacy/playercontrols/DiplomacyPlayerText.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/diplomacy/playercontrols/DiplomacyPlayerText.js
+++ ps/trunk/binaries/data/mods/public/gui/session/diplomacy/playercontrols/DiplomacyPlayerText.js
@@ -0,0 +1,80 @@
+/**
+ * This class is concerned with updating the labels and icons in the diplomacy dialog that don't provide player interaction.
+ */
+DiplomacyDialogPlayerControl.prototype.DiplomacyPlayerText = class
+{
+ constructor(playerID)
+ {
+ this.playerID = playerID;
+
+ let id = "[" + (playerID - 1) + "]";
+
+ this.diplomacyPlayer = Engine.GetGUIObjectByName("diplomacyPlayer" + id);
+ this.diplomacyPlayerCiv = Engine.GetGUIObjectByName("diplomacyPlayerCiv" + id);
+ this.diplomacyPlayerName = Engine.GetGUIObjectByName("diplomacyPlayerName" + id);
+ this.diplomacyPlayerTeam = Engine.GetGUIObjectByName("diplomacyPlayerTeam" + id);
+ this.diplomacyPlayerTheirs = Engine.GetGUIObjectByName("diplomacyPlayerTheirs" + id);
+ this.diplomacyPlayerOutcome = Engine.GetGUIObjectByName("diplomacyPlayerOutcome" + id);
+
+ this.init();
+ }
+
+ init()
+ {
+ this.diplomacyPlayerCiv.caption = g_CivData[g_Players[this.playerID].civ].Name;
+ this.diplomacyPlayerName.tooltip = translateAISettings(g_GameAttributes.settings.PlayerData[this.playerID]);
+
+ // Apply offset
+ let rowSize = DiplomacyDialogPlayerControl.prototype.DiplomacyPlayerText.getRowHeight();
+ let size = this.diplomacyPlayer.size;
+ size.top = rowSize * (this.playerID - 1);
+ size.bottom = rowSize * this.playerID;
+ this.diplomacyPlayer.size = size;
+ this.diplomacyPlayer.hidden = false;
+ }
+
+ update()
+ {
+ setOutcomeIcon(g_Players[this.playerID].state, this.diplomacyPlayerOutcome);
+
+ this.diplomacyPlayer.sprite = "color:" + g_DiplomacyColors.getPlayerColor(this.playerID, 32);
+
+ this.diplomacyPlayerName.caption = colorizePlayernameByID(this.playerID);
+
+ this.diplomacyPlayerTeam.caption =
+ g_Players[this.playerID].team >= 0 ?
+ g_Players[this.playerID].team + 1 :
+ translateWithContext("team", this.NoTeam);
+
+ this.diplomacyPlayerTheirs.caption =
+ this.playerID == g_ViewedPlayer ? "" :
+ g_Players[this.playerID].isAlly[g_ViewedPlayer] ?
+ translate(this.Ally) :
+ g_Players[this.playerID].isNeutral[g_ViewedPlayer] ?
+ translate(this.Neutral) :
+ translate(this.Enemy);
+ }
+};
+
+DiplomacyDialogPlayerControl.prototype.DiplomacyPlayerText.getRowHeight = function()
+{
+ let diplomacyPlayer = Engine.GetGUIObjectByName("diplomacyPlayer[0]").size;
+ return diplomacyPlayer.bottom - diplomacyPlayer.top;
+};
+
+DiplomacyDialogPlayerControl.prototype.DiplomacyPlayerText.getHeightOffset = function()
+{
+ return (g_Players.length - 1) * DiplomacyDialogPlayerControl.prototype.DiplomacyPlayerText.getRowHeight();
+};
+
+DiplomacyDialogPlayerControl.prototype.DiplomacyPlayerText.prototype.NoTeam =
+ markForTranslationWithContext("team", "None");
+
+DiplomacyDialogPlayerControl.prototype.DiplomacyPlayerText.prototype.Ally =
+ markForTranslation("Ally");
+
+DiplomacyDialogPlayerControl.prototype.DiplomacyPlayerText.prototype.Neutral =
+ markForTranslation("Neutral");
+
+DiplomacyDialogPlayerControl.prototype.DiplomacyPlayerText.prototype.Enemy =
+ markForTranslation("Enemy");
Index: ps/trunk/binaries/data/mods/public/gui/session/diplomacy/playercontrols/SpyRequestButton.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/diplomacy/playercontrols/SpyRequestButton.js
+++ ps/trunk/binaries/data/mods/public/gui/session/diplomacy/playercontrols/SpyRequestButton.js
@@ -0,0 +1,142 @@
+/**
+ * This class is concerned with providing the spy request button that once pressed will
+ * attempt to bribe a unit of the selected enemy for temporary vision sharing against resources.
+ */
+DiplomacyDialogPlayerControl.prototype.SpyRequestButton = class
+{
+ constructor(playerID)
+ {
+ this.playerID = playerID;
+
+ // Players who requested a spy against this playerID.
+ this.spyRequests = new Set();
+
+ let id = "[" + (playerID - 1) + "]";
+ this.diplomacySpyRequest = Engine.GetGUIObjectByName("diplomacySpyRequest" + id);
+ this.diplomacySpyRequestImage = Engine.GetGUIObjectByName("diplomacySpyRequestImage" + id);
+
+ this.diplomacySpyRequest.onPress = this.onPress.bind(this);
+ }
+
+ onPress()
+ {
+ Engine.PostNetworkCommand({
+ "type": "spy-request",
+ "source": g_ViewedPlayer,
+ "player": this.playerID
+ });
+ this.spyRequests.add(g_ViewedPlayer);
+ this.update(false);
+ }
+
+ /**
+ * Called from GUIInterface notification.
+ * @param player is the one who requested a spy.
+ * @param notification.target is the player who shall be spied upon.
+ */
+ onSpyResponse(notification, player, playerInactive)
+ {
+ // Update the state if the response was against the current row (target player)
+ if (notification.target == this.playerID)
+ {
+ this.spyRequests.delete(player);
+
+ // Update UI if the currently viewed player sent the request
+ if (player == g_ViewedPlayer)
+ this.update(false);
+ }
+ }
+
+ update(playerInactive)
+ {
+ let template = GetTemplateData(this.TemplateName);
+
+ let hidden =
+ playerInactive ||
+ !template ||
+ !!GetSimState().players[g_ViewedPlayer].disabledTemplates[this.TemplateName] ||
+ g_Players[this.playerID].isMutualAlly[g_ViewedPlayer] &&
+ !GetSimState().players[g_ViewedPlayer].hasSharedLos;
+
+ this.diplomacySpyRequest.hidden = hidden;
+
+ if (hidden)
+ return;
+
+ let tooltip = translate(this.Tooltip);
+
+ if (template.requiredTechnology &&
+ !Engine.GuiInterfaceCall("IsTechnologyResearched", {
+ "tech": template.requiredTechnology,
+ "player": g_ViewedPlayer
+ }))
+ {
+ tooltip += "\n" + getRequiredTechnologyTooltip(
+ false,
+ template.requiredTechnology,
+ GetSimState().players[g_ViewedPlayer].civ);
+
+ this.diplomacySpyRequest.enabled = false;
+ this.diplomacySpyRequest.tooltip = tooltip;
+ this.diplomacySpyRequestImage.sprite = this.SpriteModifierDisabled + this.Sprite;
+ return;
+ }
+
+ if (template.cost)
+ {
+ let modifiedTemplate = clone(template);
+
+ for (let res in template.cost)
+ modifiedTemplate.cost[res] =
+ Math.floor(GetSimState().players[this.playerID].spyCostMultiplier * template.cost[res]);
+
+ tooltip += "\n" + getEntityCostTooltip(modifiedTemplate);
+
+ let neededResources = Engine.GuiInterfaceCall("GetNeededResources", {
+ "cost": modifiedTemplate.cost,
+ "player": g_ViewedPlayer
+ });
+
+ if (neededResources)
+ {
+ tooltip += "\n" + getNeededResourcesTooltip(neededResources);
+ this.diplomacySpyRequest.enabled = false;
+ this.diplomacySpyRequest.tooltip = tooltip;
+ this.diplomacySpyRequestImage.sprite =
+ resourcesToAlphaMask(neededResources) + ":" + this.Sprite;
+ return;
+ }
+
+ let costRatio = Engine.GetTemplate(this.TemplateName).VisionSharing.FailureCostRatio;
+ if (costRatio)
+ {
+ for (let res in modifiedTemplate.cost)
+ modifiedTemplate.cost[res] = Math.floor(costRatio * modifiedTemplate.cost[res]);
+
+ tooltip +=
+ "\n" + translate(this.TooltipFailed) +
+ "\n" + getEntityCostTooltip(modifiedTemplate);
+ }
+ }
+
+ let enabled = !this.spyRequests.has(g_ViewedPlayer);
+ this.diplomacySpyRequest.enabled = enabled && controlsPlayer(g_ViewedPlayer);
+ this.diplomacySpyRequest.tooltip = tooltip;
+ this.diplomacySpyRequestImage.sprite = (enabled ? "" : this.SpriteModifierDisabled) + this.Sprite;
+ }
+};
+
+DiplomacyDialogPlayerControl.prototype.SpyRequestButton.prototype.TemplateName =
+ "special/spy";
+
+DiplomacyDialogPlayerControl.prototype.SpyRequestButton.prototype.Sprite =
+ "stretched:" + "session/icons/bribes.png";
+
+DiplomacyDialogPlayerControl.prototype.SpyRequestButton.prototype.SpriteModifierDisabled =
+ "color:0 0 0 127:grayscale:";
+
+DiplomacyDialogPlayerControl.prototype.SpyRequestButton.prototype.Tooltip =
+ markForTranslation("Bribe a random unit from this player and share its vision during a limited period.");
+
+DiplomacyDialogPlayerControl.prototype.SpyRequestButton.prototype.TooltipFailed =
+ markForTranslation("A failed bribe will cost you:");
Index: ps/trunk/binaries/data/mods/public/gui/session/diplomacy/playercontrols/StanceButton.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/diplomacy/playercontrols/StanceButton.js
+++ ps/trunk/binaries/data/mods/public/gui/session/diplomacy/playercontrols/StanceButton.js
@@ -0,0 +1,60 @@
+/**
+ * This class provides one button per diplomatic stance for a given player.
+ */
+DiplomacyDialogPlayerControl.prototype.StanceButtonManager = class
+{
+ constructor(playerID)
+ {
+ this.buttons = this.Stances.map(stance =>
+ new this.StanceButton(playerID, stance));
+ }
+
+ update(playerInactive)
+ {
+ let hidden = playerInactive || GetSimState().ceasefireActive || g_Players[g_ViewedPlayer].teamsLocked;
+
+ for (let button of this.buttons)
+ button.update(hidden);
+ }
+};
+
+DiplomacyDialogPlayerControl.prototype.StanceButtonManager.prototype.Stances = ["Ally", "Neutral", "Enemy"];
+
+/**
+ * This class manages a button that if pressed, will change the diplomatic stance to the given player to the given stance.
+ */
+DiplomacyDialogPlayerControl.prototype.StanceButtonManager.prototype.StanceButton = class
+{
+ constructor(playerID, stance)
+ {
+ this.playerID = playerID;
+ this.stance = stance;
+ this.button = Engine.GetGUIObjectByName("diplomacyPlayer" + stance + "[" + (playerID - 1) + "]");
+ this.button.onPress = this.onPress.bind(this);
+ }
+
+ update(hidden)
+ {
+ this.button.hidden = hidden;
+ if (hidden)
+ return;
+
+ let isCurrentStance = g_Players[g_ViewedPlayer]["is" + this.stance][this.playerID];
+ this.button.enabled = !isCurrentStance && controlsPlayer(g_ViewedPlayer);
+ this.button.caption = isCurrentStance ?
+ translateWithContext("diplomatic stance selection", this.StanceSelection) :
+ "";
+ }
+
+ onPress()
+ {
+ Engine.PostNetworkCommand({
+ "type": "diplomacy",
+ "player": this.playerID,
+ "to": this.stance.toLowerCase()
+ });
+ }
+};
+
+DiplomacyDialogPlayerControl.prototype.StanceButtonManager.prototype.StanceButton.prototype.StanceSelection =
+ markForTranslationWithContext("diplomatic stance selection", "x");
Index: ps/trunk/binaries/data/mods/public/gui/session/diplomacy/playercontrols/TributeButton.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/diplomacy/playercontrols/TributeButton.js
+++ ps/trunk/binaries/data/mods/public/gui/session/diplomacy/playercontrols/TributeButton.js
@@ -0,0 +1,119 @@
+/**
+ * This class creates and handles a tribute button for the given player for every tributable resource.
+ */
+DiplomacyDialogPlayerControl.prototype.TributeButtonManager = class
+{
+ constructor(playerID)
+ {
+ let resCodes = g_ResourceData.GetTributableCodes();
+ let buttonCount = Engine.GetGUIObjectByName("diplomacyPlayer[0]_tribute").children.length;
+
+ Engine.GetGUIObjectByName("diplomacyHeaderTribute").hidden = !resCodes.length;
+
+ if (resCodes.length > buttonCount)
+ warn("There are " + resCodes.length + " tributable resources, but only " + buttonCount + " buttons!");
+
+ this.buttons = [];
+
+ for (let i = 0; i < Math.min(resCodes.length, buttonCount); ++i)
+ this.buttons[i] = new this.TributeButton(playerID, resCodes[i], i);
+ }
+
+ update(playerInactive)
+ {
+ for (let button of this.buttons)
+ button.update(playerInactive);
+ }
+};
+
+DiplomacyDialogPlayerControl.prototype.TributeButtonManager.getWidthOffset = function()
+{
+ let tributeButtonSize = Engine.GetGUIObjectByName("diplomacyPlayer[0]_tribute[0]").size;
+ return g_ResourceData.GetTributableCodes().length * (tributeButtonSize.right - tributeButtonSize.left);
+};
+
+/**
+ * This class manages one tribute button for one tributable resource for one receiving player.
+ * Players may tribute mass amounts of resources by clicking multiple times on the button while holding a hotkey.
+ */
+DiplomacyDialogPlayerControl.prototype.TributeButtonManager.prototype.TributeButton = class
+{
+ constructor(playerID, resCode, resIndex)
+ {
+ this.playerID = playerID;
+ this.resCode = resCode;
+ this.amount = undefined;
+
+ let name = "diplomacyPlayer[" + (playerID - 1) + "]_tribute[" + resIndex + "]";
+
+ this.button = Engine.GetGUIObjectByName(name);
+ this.button.onPress = this.onPress.bind(this);
+ setPanelObjectPosition(this.button, resIndex, resIndex + 1, 0);
+
+ Engine.GetGUIObjectByName(name + "_hotkey").onRelease = this.onMassTributeRelease.bind(this);
+ Engine.GetGUIObjectByName(name + "_image").sprite = "stretched:" + this.ResourceIconPath + resCode + ".png";
+
+ this.setAmount(this.DefaultAmount);
+ }
+
+ update(playerInactive)
+ {
+ this.button.hidden = playerInactive;
+
+ if (!this.button.hidden)
+ this.button.enabled = controlsPlayer(g_ViewedPlayer);
+ }
+
+ onPress()
+ {
+ if (Engine.HotkeyIsPressed("session.masstribute"))
+ this.setAmount(this.nextAmount());
+ else
+ this.performTribute();
+ }
+
+ onMassTributeRelease()
+ {
+ if (this.amount >= this.MassAmount)
+ this.performTribute();
+ }
+
+ setAmount(amount)
+ {
+ this.amount = amount;
+ this.button.tooltip = sprintf(
+ translate(this.Tooltip), {
+ "resourceAmount": this.amount,
+ "greaterAmount": this.nextAmount(),
+ "resourceType": resourceNameWithinSentence(this.resCode),
+ "playerName": colorizePlayernameByID(this.playerID),
+ });
+ }
+
+ nextAmount()
+ {
+ return this.MassAmount * (Math.floor(this.amount / this.MassAmount) + 1);
+ }
+
+ performTribute()
+ {
+ Engine.PostNetworkCommand({
+ "type": "tribute",
+ "player": this.playerID,
+ "amounts": {
+ [this.resCode]: this.amount
+ }
+ });
+ this.setAmount(this.DefaultAmount);
+ }
+};
+
+DiplomacyDialogPlayerControl.prototype.TributeButtonManager.prototype.TributeButton.prototype.Tooltip =
+ markForTranslation("Tribute %(resourceAmount)s %(resourceType)s to %(playerName)s. Shift-click to tribute %(greaterAmount)s.");
+
+DiplomacyDialogPlayerControl.prototype.TributeButtonManager.prototype.TributeButton.prototype.ResourceIconPath =
+ "session/icons/resources/";
+
+DiplomacyDialogPlayerControl.prototype.TributeButtonManager.prototype.TributeButton.prototype.DefaultAmount = 100;
+
+DiplomacyDialogPlayerControl.prototype.TributeButtonManager.prototype.TributeButton.prototype.MassAmount = 500;
Index: ps/trunk/binaries/data/mods/public/gui/session/diplomacy_window.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/diplomacy_window.xml
+++ ps/trunk/binaries/data/mods/public/gui/session/diplomacy_window.xml
@@ -1,93 +0,0 @@
-
-
-
-
- Diplomacy
-
-
-
-
- Name
-
-
- Civilization
-
-
- Team
-
-
- Theirs
-
-
- A
- Ally
-
-
- N
- Neutral
-
-
- E
- Enemy
-
-
- Tribute
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- updateDiplomacyColorsButton();
-
-
- Toggle Diplomacy Colors
-
-
-
-
- Close
- closeDiplomacy();
-
-
Index: ps/trunk/binaries/data/mods/public/gui/session/input.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/input.js
+++ ps/trunk/binaries/data/mods/public/gui/session/input.js
@@ -29,9 +29,8 @@
const INPUT_PRESELECTEDACTION = 7;
const INPUT_BUILDING_WALL_CLICK = 8;
const INPUT_BUILDING_WALL_PATHING = 9;
-const INPUT_MASSTRIBUTING = 10;
-const INPUT_UNIT_POSITION_START = 11;
-const INPUT_UNIT_POSITION = 12;
+const INPUT_UNIT_POSITION_START = 10;
+const INPUT_UNIT_POSITION = 11;
var inputState = INPUT_NORMAL;
@@ -767,14 +766,6 @@
}
break;
- case INPUT_MASSTRIBUTING:
- if (ev.type == "hotkeyup" && ev.hotkey == "session.masstribute")
- {
- g_FlushTributing();
- inputState = INPUT_NORMAL;
- }
- break;
-
case INPUT_BATCHTRAINING:
if (ev.type == "hotkeyup" && ev.hotkey == "session.batchtrain")
{
@@ -1219,21 +1210,6 @@
return true;
}
-function handleMinimapEvent(target)
-{
- // Partly duplicated from handleInputAfterGui(), but with the input being
- // world coordinates instead of screen coordinates.
-
- if (inputState != INPUT_NORMAL)
- return false;
-
- let action = determineAction(undefined, undefined, true);
- if (!action)
- return false;
-
- return handleUnitAction(target, action);
-}
-
function handleUnitAction(target, action)
{
if (!g_UnitActions[action.type] || !g_UnitActions[action.type].execute)
Index: ps/trunk/binaries/data/mods/public/gui/session/menu.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/menu.js
+++ ps/trunk/binaries/data/mods/public/gui/session/menu.js
@@ -56,30 +56,20 @@
var g_IsMenuOpen = false;
-var g_IsDiplomacyOpen = false;
var g_IsTradeOpen = false;
var g_IsObjectivesOpen = false;
/**
- * Used to disable a specific bribe button for the time we are waiting for the result of the bribe after it was clicked.
- * It contains an array per viewedPlayer. This array is a list of the players that were bribed.
- */
-var g_BribeButtonsWaiting = {};
-
-/**
* Remember last viewed summary panel and charts.
*/
var g_SummarySelectedData;
-// Redefined every time someone makes a tribute (so we can save some data in a closure). Called in input.js handleInputBeforeGui.
-var g_FlushTributing = function() {};
-
function initMenu()
{
Engine.GetGUIObjectByName("menu").size = "100%-164 " + MENU_TOP + " 100% " + MENU_BOTTOM;
// TODO: Atlas should pass g_GameAttributes.settings
- for (let button of ["menuExitButton", "summaryButton", "objectivesButton", "diplomacyButton"])
+ for (let button of ["menuExitButton", "summaryButton", "objectivesButton"])
Engine.GetGUIObjectByName(button).enabled = !Engine.IsAtlasRunning();
}
@@ -247,291 +237,6 @@
});
}
-function resizeDiplomacyDialog()
-{
- let dialog = Engine.GetGUIObjectByName("diplomacyDialogPanel");
- let size = dialog.size;
-
- let resTribCodesLength = g_ResourceData.GetTributableCodes().length;
- if (resTribCodesLength)
- {
- let tribSize = Engine.GetGUIObjectByName("diplomacyPlayer[0]_tribute[0]").size;
- let widthOffset = resTribCodesLength * (tribSize.right - tribSize.left) / 2;
- size.left -= widthOffset;
- size.right += widthOffset;
- }
- else
- Engine.GetGUIObjectByName("diplomacyHeaderTribute").hidden = true;
-
- let firstRow = Engine.GetGUIObjectByName("diplomacyPlayer[0]").size;
- let heightOffset = (g_Players.length - 1) * (firstRow.bottom - firstRow.top) / 2;
- size.top -= heightOffset;
- size.bottom += heightOffset;
-
- dialog.size = size;
-}
-
-function openDiplomacy()
-{
- closeOpenDialogs();
-
- if (g_ViewedPlayer < 1)
- return;
-
- g_IsDiplomacyOpen = true;
-
- updateDiplomacy(true);
-
- Engine.GetGUIObjectByName("diplomacyDialogPanel").hidden = false;
-}
-
-function closeDiplomacy()
-{
- g_IsDiplomacyOpen = false;
- Engine.GetGUIObjectByName("diplomacyDialogPanel").hidden = true;
-}
-
-function toggleDiplomacy()
-{
- let open = g_IsDiplomacyOpen;
- closeOpenDialogs();
-
- if (!open)
- openDiplomacy();
-}
-
-function updateDiplomacy(opening = false)
-{
- if (g_ViewedPlayer < 1 || !g_IsDiplomacyOpen)
- return;
-
- let simState = GetSimState();
- let isCeasefireActive = simState.ceasefireActive;
- let hasSharedLos = GetSimState().players[g_ViewedPlayer].hasSharedLos;
-
- // Get offset for one line
- let onesize = Engine.GetGUIObjectByName("diplomacyPlayer[0]").size;
- let rowsize = onesize.bottom - onesize.top;
-
- // We don't include gaia
- for (let i = 1; i < g_Players.length; ++i)
- {
- let myself = i == g_ViewedPlayer;
- let playerInactive = isPlayerObserver(g_ViewedPlayer) || isPlayerObserver(i);
- let hasAllies = g_Players.filter(player => player.isMutualAlly[g_ViewedPlayer]).length > 1;
-
- diplomacySetupTexts(i, rowsize);
- diplomacyFormatStanceButtons(i, myself || playerInactive || isCeasefireActive || g_Players[g_ViewedPlayer].teamsLocked);
- // Tribute buttons do not need to be updated onTick, and should not because of massTributing
- if (opening)
- diplomacyFormatTributeButtons(i, myself || playerInactive);
- diplomacyFormatAttackRequestButton(i, myself || playerInactive || isCeasefireActive || !hasAllies || !g_Players[i].isEnemy[g_ViewedPlayer]);
- diplomacyFormatSpyRequestButton(i, myself || playerInactive || g_Players[i].isMutualAlly[g_ViewedPlayer] && hasSharedLos);
- }
-
- let diplomacyCeasefireCounter = Engine.GetGUIObjectByName("diplomacyCeasefireCounter");
- diplomacyCeasefireCounter.caption = sprintf(
- translateWithContext("ceasefire", "Remaining ceasefire time: %(time)s."),
- { "time": timeToString(simState.ceasefireTimeRemaining) }
- );
- diplomacyCeasefireCounter.hidden = !isCeasefireActive;
-}
-
-function diplomacySetupTexts(i, rowsize)
-{
- // Apply offset
- let row = Engine.GetGUIObjectByName("diplomacyPlayer[" + (i - 1) + "]");
- let size = row.size;
- size.top = rowsize * (i - 1);
- size.bottom = rowsize * i;
- row.size = size;
- row.hidden = false;
-
- row.sprite = "color:" + rgbToGuiColor(g_DisplayedPlayerColors[i], 32);
-
- setOutcomeIcon(g_Players[i].state, "diplomacyPlayerOutcome[" + (i - 1) + "]");
-
- let diplomacyPlayerName = Engine.GetGUIObjectByName("diplomacyPlayerName[" + (i - 1) + "]");
- diplomacyPlayerName.caption = colorizePlayernameByID(i);
- diplomacyPlayerName.tooltip = translateAISettings(g_GameAttributes.settings.PlayerData[i]);
-
- Engine.GetGUIObjectByName("diplomacyPlayerCiv[" + (i - 1) + "]").caption = g_CivData[g_Players[i].civ].Name;
-
- Engine.GetGUIObjectByName("diplomacyPlayerTeam[" + (i - 1) + "]").caption =
- g_Players[i].team < 0 ? translateWithContext("team", "None") : g_Players[i].team + 1;
-
- Engine.GetGUIObjectByName("diplomacyPlayerTheirs[" + (i - 1) + "]").caption =
- i == g_ViewedPlayer ? "" :
- g_Players[i].isAlly[g_ViewedPlayer] ?
- translate("Ally") :
- g_Players[i].isNeutral[g_ViewedPlayer] ? translate("Neutral") : translate("Enemy");
-}
-
-function diplomacyFormatStanceButtons(i, hidden)
-{
- for (let stance of ["Ally", "Neutral", "Enemy"])
- {
- let button = Engine.GetGUIObjectByName("diplomacyPlayer" + stance + "[" + (i - 1) + "]");
- button.hidden = hidden;
- if (hidden)
- continue;
-
- let isCurrentStance = g_Players[g_ViewedPlayer]["is" + stance][i];
- button.caption = isCurrentStance ? translate("x") : "";
- button.enabled = controlsPlayer(g_ViewedPlayer) && !isCurrentStance;
-
- button.onPress = (function(player, stance) { return function() {
- Engine.PostNetworkCommand({
- "type": "diplomacy",
- "player": i,
- "to": stance.toLowerCase()
- });
- }; })(i, stance);
- }
-}
-
-function diplomacyFormatTributeButtons(i, hidden)
-{
- let resTribCodes = g_ResourceData.GetTributableCodes();
- let r = 0;
- for (let resCode of resTribCodes)
- {
- let button = Engine.GetGUIObjectByName("diplomacyPlayer[" + (i - 1) + "]_tribute[" + r + "]");
- if (!button)
- {
- warn("Current GUI limits prevent displaying more than " + r + " tribute buttons!");
- break;
- }
-
- Engine.GetGUIObjectByName("diplomacyPlayer[" + (i - 1) + "]_tribute[" + r + "]_image").sprite = "stretched:session/icons/resources/" + resCode + ".png";
- button.hidden = hidden;
- setPanelObjectPosition(button, r, r + 1, 0);
- ++r;
- if (hidden)
- continue;
-
- button.enabled = controlsPlayer(g_ViewedPlayer);
- button.tooltip = formatTributeTooltip(i, resCode, 100);
- button.onPress = (function(i, resCode, button) {
- // Shift+click to send 500, shift+click+click to send 1000, etc.
- // See INPUT_MASSTRIBUTING in input.js
- let multiplier = 1;
- return function() {
- let isMassTributePressed = Engine.HotkeyIsPressed("session.masstribute");
- if (isMassTributePressed)
- {
- inputState = INPUT_MASSTRIBUTING;
- multiplier += multiplier == 1 ? 4 : 5;
- }
-
- let amounts = {};
- for (let res of resTribCodes)
- amounts[res] = 0;
- amounts[resCode] = 100 * multiplier;
-
- button.tooltip = formatTributeTooltip(i, resCode, amounts[resCode]);
-
- // This is in a closure so that we have access to `player`, `amounts`, and `multiplier` without some
- // evil global variable hackery.
- g_FlushTributing = function() {
- Engine.PostNetworkCommand({ "type": "tribute", "player": i, "amounts": amounts });
- multiplier = 1;
- button.tooltip = formatTributeTooltip(i, resCode, 100);
- };
-
- if (!isMassTributePressed)
- g_FlushTributing();
- };
- })(i, resCode, button);
- }
-}
-
-function diplomacyFormatAttackRequestButton(i, hidden)
-{
- let button = Engine.GetGUIObjectByName("diplomacyAttackRequest[" + (i - 1) + "]");
- button.hidden = hidden;
- if (hidden)
- return;
-
- button.enabled = controlsPlayer(g_ViewedPlayer);
- button.tooltip = translate("Request your allies to attack this enemy");
- button.onPress = (function(i) { return function() {
- Engine.PostNetworkCommand({ "type": "attack-request", "source": g_ViewedPlayer, "player": i });
- }; })(i);
-}
-
-function diplomacyFormatSpyRequestButton(i, hidden)
-{
- let button = Engine.GetGUIObjectByName("diplomacySpyRequest[" + (i - 1) + "]");
- let template = GetTemplateData("special/spy");
- button.hidden = hidden || !template || !!GetSimState().players[g_ViewedPlayer].disabledTemplates["special/spy"];
- if (button.hidden)
- return;
-
- button.enabled = controlsPlayer(g_ViewedPlayer) &&
- !(g_BribeButtonsWaiting[g_ViewedPlayer] && g_BribeButtonsWaiting[g_ViewedPlayer].indexOf(i) != -1);
- let modifier = "";
- let tooltips = [translate("Bribe a random unit from this player and share its vision during a limited period.")];
- if (!button.enabled)
- modifier = "color:0 0 0 127:grayscale:";
- else
- {
- if (template.requiredTechnology)
- {
- let technologyEnabled = Engine.GuiInterfaceCall("IsTechnologyResearched", {
- "tech": template.requiredTechnology,
- "player": g_ViewedPlayer
- });
- if (!technologyEnabled)
- {
- modifier = "color:0 0 0 127:grayscale:";
- button.enabled = false;
- tooltips.push(getRequiredTechnologyTooltip(technologyEnabled, template.requiredTechnology, GetSimState().players[g_ViewedPlayer].civ));
- }
- }
-
- if (template.cost)
- {
- let modifiedTemplate = clone(template);
- for (let res in template.cost)
- modifiedTemplate.cost[res] = Math.floor(GetSimState().players[i].spyCostMultiplier * template.cost[res]);
- tooltips.push(getEntityCostTooltip(modifiedTemplate));
- let neededResources = Engine.GuiInterfaceCall("GetNeededResources", {
- "cost": modifiedTemplate.cost,
- "player": g_ViewedPlayer
- });
- let costRatio = Engine.GetTemplate("special/spy").VisionSharing.FailureCostRatio;
- if (costRatio > 0)
- {
- tooltips.push(translate("A failed bribe will cost you:"));
- for (let res in modifiedTemplate.cost)
- modifiedTemplate.cost[res] = Math.floor(costRatio * modifiedTemplate.cost[res]);
- tooltips.push(getEntityCostTooltip(modifiedTemplate));
- }
-
- if (neededResources)
- {
- if (button.enabled)
- modifier = resourcesToAlphaMask(neededResources) + ":";
- button.enabled = false;
- tooltips.push(getNeededResourcesTooltip(neededResources));
- }
- }
- }
- let icon = Engine.GetGUIObjectByName("diplomacySpyRequestImage[" + (i - 1) + "]");
- icon.sprite = modifier + "stretched:session/icons/bribes.png";
- button.tooltip = tooltips.filter(tip => tip).join("\n");
- button.onPress = (function(i, button) { return function() {
- Engine.PostNetworkCommand({ "type": "spy-request", "source": g_ViewedPlayer, "player": i });
- if (!g_BribeButtonsWaiting[g_ViewedPlayer])
- g_BribeButtonsWaiting[g_ViewedPlayer] = [];
- // Don't push i twice
- if (g_BribeButtonsWaiting[g_ViewedPlayer].indexOf(i) == -1)
- g_BribeButtonsWaiting[g_ViewedPlayer].push(i);
- diplomacyFormatSpyRequestButton(i, false);
- }; })(i, button);
-}
-
function resizeTradeDialog()
{
let dialog = Engine.GetGUIObjectByName("tradeDialogPanel");
@@ -1158,19 +863,9 @@
function closeOpenDialogs()
{
closeMenu();
- closeDiplomacy();
closeTrade();
closeObjectives();
g_Chat.closePage();
-}
-
-function formatTributeTooltip(playerID, resourceCode, amount)
-{
- return sprintf(translate("Tribute %(resourceAmount)s %(resourceType)s to %(playerName)s. Shift-click to tribute %(greaterAmount)s."), {
- "resourceAmount": amount,
- "resourceType": resourceNameWithinSentence(resourceCode),
- "playerName": colorizePlayernameByID(playerID),
- "greaterAmount": amount < 500 ? 500 : amount + 500
- });
+ g_DiplomacyDialog.close();
}
Index: ps/trunk/binaries/data/mods/public/gui/session/messages.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/messages.js
+++ ps/trunk/binaries/data/mods/public/gui/session/messages.js
@@ -134,8 +134,7 @@
"diplomacy": function(notification, player)
{
updatePlayerData();
- if (g_DiplomacyColorsToggle)
- updateDisplayedPlayerColors();
+ g_DiplomacyColors.onDiplomacyChange();
addChatMessage({
"type": "diplomacy",
@@ -147,8 +146,7 @@
"ceasefire-ended": function(notification, player)
{
updatePlayerData();
- if (g_DiplomacyColorsToggle)
- updateDisplayedPlayerColors();
+ g_DiplomacyColors.OnCeasefireEnded();
},
"tutorial": function(notification, player)
{
@@ -176,12 +174,11 @@
},
"spy-response": function(notification, player)
{
- if (g_BribeButtonsWaiting[player])
- g_BribeButtonsWaiting[player] = g_BribeButtonsWaiting[player].filter(p => p != notification.target);
+ g_DiplomacyDialog.onSpyResponse(notification, player);
if (notification.entity && g_ViewedPlayer == player)
{
- closeDiplomacy();
+ g_DiplomacyDialog.close();
setCameraFollow(notification.entity);
}
},
@@ -622,7 +619,7 @@
function colorizePlayernameHelper(username, playerID)
{
- let playerColor = playerID > -1 ? rgbToGuiColor(g_DisplayedPlayerColors[playerID]) : "white";
+ let playerColor = playerID > -1 ? g_DiplomacyColors.getPlayerColor(playerID) : "white";
return coloredText(username || translate("Unknown Player"), playerColor);
}
Index: ps/trunk/binaries/data/mods/public/gui/session/minimap/MiniMap.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/minimap/MiniMap.js
+++ ps/trunk/binaries/data/mods/public/gui/session/minimap/MiniMap.js
@@ -0,0 +1,26 @@
+/**
+ * This class is concerned with handling events occurring when the interacts with the minimap,
+ * except for changing the camera position on leftclick.
+ */
+class Minimap
+{
+ constructor()
+ {
+ Engine.GetGUIObjectByName("minimap").onWorldClick = this.onWorldClick.bind(this);
+ }
+
+ onWorldClick(target)
+ {
+ if (!controlsPlayer(g_ViewedPlayer))
+ return;
+
+ // Partly duplicated from handleInputAfterGui(), but with the input being
+ // world coordinates instead of screen coordinates.
+
+ if (inputState != INPUT_NORMAL)
+ return false;
+
+ let action = determineAction(undefined, undefined, true);
+ return action && handleUnitAction(target, action);
+ }
+}
Index: ps/trunk/binaries/data/mods/public/gui/session/minimap/MiniMap.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/minimap/MiniMap.xml
+++ ps/trunk/binaries/data/mods/public/gui/session/minimap/MiniMap.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: ps/trunk/binaries/data/mods/public/gui/session/minimap/MiniMapDiplomacyColorsButton.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/minimap/MiniMapDiplomacyColorsButton.js
+++ ps/trunk/binaries/data/mods/public/gui/session/minimap/MiniMapDiplomacyColorsButton.js
@@ -0,0 +1,36 @@
+/**
+ * The purpose of this class is to exclusively manage the diplomacy colors button within the minimap.
+ */
+class MiniMapDiplomacyColorsButton
+{
+ constructor(diplomacyColors)
+ {
+ this.diplomacyColorsButton = Engine.GetGUIObjectByName("diplomacyColorsButton");
+ this.diplomacyColorsButton.onPress = diplomacyColors.toggle.bind(diplomacyColors);
+
+ this.diplomacyColors = diplomacyColors;
+ }
+
+ update()
+ {
+ this.diplomacyColorsButton.tooltip =
+ colorizeHotkey("%(hotkey)s" + " ", "session.diplomacycolors") +
+ translate(this.Tooltip);
+
+ this.diplomacyColorsButton.sprite =
+ "stretched:" +
+ (this.diplomacyColors.isEnabled() ? this.SpriteEnabled : this.SpriteDisabled);
+
+ this.diplomacyColorsButton.sprite_over =
+ "stretched:" +
+ (this.diplomacyColors.isEnabled() ? this.SpriteEnabledOver : this.SpriteDisabledOver);
+ }
+}
+
+MiniMapDiplomacyColorsButton.prototype.Tooltip = markForTranslation("Toggle Diplomacy Colors");
+
+MiniMapDiplomacyColorsButton.prototype.SpriteEnabled = "session/minimap-diplomacy-on.png";
+MiniMapDiplomacyColorsButton.prototype.SpriteDisabled = "session/minimap-diplomacy-off.png";
+
+MiniMapDiplomacyColorsButton.prototype.SpriteEnabledOver = "session/minimap-diplomacy-on-highlight.png";
+MiniMapDiplomacyColorsButton.prototype.SpriteDisabledOver = "session/minimap-diplomacy-off-highlight.png";
Index: ps/trunk/binaries/data/mods/public/gui/session/minimap/MiniMapIdleWorkerButton.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/minimap/MiniMapIdleWorkerButton.js
+++ ps/trunk/binaries/data/mods/public/gui/session/minimap/MiniMapIdleWorkerButton.js
@@ -0,0 +1,32 @@
+/**
+ * If the button that this class manages is pressed, an idle unit having one of the given classes is selected.
+ */
+class MiniMapIdleWorkerButton
+{
+ constructor(idleClasses)
+ {
+ this.idleWorkerButton = Engine.GetGUIObjectByName("idleWorkerButton");
+ this.idleWorkerButton.onPress = this.onPress.bind(this);
+ this.idleClasses = idleClasses;
+ }
+
+ update()
+ {
+ this.idleWorkerButton.tooltip =
+ colorizeHotkey("%(hotkey)s" + " ", "selection.idleworker") +
+ translate(this.Tooltip);
+
+ this.idleWorkerButton.enabled = Engine.GuiInterfaceCall("HasIdleUnits", {
+ "viewedPlayer": g_ViewedPlayer,
+ "idleClasses": this.idleClasses,
+ "excludeUnits": []
+ });
+ }
+
+ onPress()
+ {
+ findIdleUnit(this.idleClasses);
+ }
+}
+
+MiniMapIdleWorkerButton.prototype.Tooltip = markForTranslation("Find idle worker");
Index: ps/trunk/binaries/data/mods/public/gui/session/minimap/MiniMapPanel.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/minimap/MiniMapPanel.js
+++ ps/trunk/binaries/data/mods/public/gui/session/minimap/MiniMapPanel.js
@@ -0,0 +1,18 @@
+/**
+ * This class is concerned with managing the different elements of the minimap panel.
+ */
+class MiniMapPanel
+{
+ constructor(diplomacyColors, idleWorkerClasses)
+ {
+ this.diplomacyColorsButton = new MiniMapDiplomacyColorsButton(diplomacyColors);
+ this.idleWorkerButton = new MiniMapIdleWorkerButton(idleWorkerClasses);
+ this.minimap = new Minimap();
+ }
+
+ update()
+ {
+ this.diplomacyColorsButton.update();
+ this.idleWorkerButton.update();
+ }
+}
Index: ps/trunk/binaries/data/mods/public/gui/session/minimap_panel.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/minimap_panel.xml
+++ ps/trunk/binaries/data/mods/public/gui/session/minimap_panel.xml
@@ -1,45 +0,0 @@
-
-
-
-
- handleMinimapEvent(arguments[0]);
-
-
-
-
-
- findIdleUnit(g_WorkerTypes);
-
-
-
-
- updateDiplomacyColorsButton();
-
-
Index: ps/trunk/binaries/data/mods/public/gui/session/selection_details.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/selection_details.js
+++ ps/trunk/binaries/data/mods/public/gui/session/selection_details.js
@@ -72,7 +72,6 @@
let civEmblem = g_CivData[playerState.civ].Emblem;
let playerName = playerState.name;
- let playerColor = rgbToGuiColor(g_DisplayedPlayerColors[entState.player], 128);
// Indicate disconnected players by prefixing their name
if (g_Players[entState.player].offline)
@@ -158,7 +157,7 @@
let size = 100 * Math.max(0, Math.min(1, entState.capturePoints[playerID] / entState.maxCapturePoints));
sizeObj.rright = startSize + size;
unitCaptureBar.size = sizeObj;
- unitCaptureBar.sprite = "color:" + rgbToGuiColor(g_DisplayedPlayerColors[playerID], 128);
+ unitCaptureBar.sprite = "color:" + g_DiplomacyColors.getPlayerColor(playerID, 128);
unitCaptureBar.hidden = false;
return startSize + size;
};
@@ -286,7 +285,10 @@
Engine.GetGUIObjectByName("specific").caption = specificName;
Engine.GetGUIObjectByName("player").caption = playerName;
- Engine.GetGUIObjectByName("playerColorBackground").sprite = "color:" + playerColor;
+
+ Engine.GetGUIObjectByName("playerColorBackground").sprite =
+ "color:" + g_DiplomacyColors.getPlayerColor(entState.player, 128);
+
Engine.GetGUIObjectByName("generic").caption = genericName == specificName ? "" :
sprintf(translate("(%(genericName)s)"), {
"genericName": genericName
@@ -401,7 +403,7 @@
let size = 100 * Math.max(0, Math.min(1, capturePoints[pID] / maxCapturePoints));
sizeObj.rbottom = startSize + size;
unitCaptureBar.size = sizeObj;
- unitCaptureBar.sprite = "color:" + rgbToGuiColor(g_DisplayedPlayerColors[pID], 128);
+ unitCaptureBar.sprite = "color:" + g_DiplomacyColors.getPlayerColor(pID, 128);
unitCaptureBar.hidden = false;
return startSize + size;
};
Index: ps/trunk/binaries/data/mods/public/gui/session/selection_panels.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/selection_panels.js
+++ ps/trunk/binaries/data/mods/public/gui/session/selection_panels.js
@@ -382,7 +382,7 @@
"playername": g_Players[entState.player].name
});
- data.guiSelection.sprite = getPlayerHighlightColor(entState.player);
+ data.guiSelection.sprite = "color:" + g_DiplomacyColors.getPlayerColor(entState.player, 160);
data.button.sprite_disabled = data.button.sprite;
// Selection panel buttons only appear disabled if they
@@ -873,7 +873,7 @@
});
data.button.tooltip = tooltip;
- data.guiSelection.sprite = getPlayerHighlightColor(unitOwner);
+ data.guiSelection.sprite = "color:" + g_DiplomacyColors.getPlayerColor(unitOwner, 160);
data.guiSelection.hidden = !g_IsObserver;
data.countDisplay.caption = data.item.ents.length || "";
Index: ps/trunk/binaries/data/mods/public/gui/session/selection_panels_helpers.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/selection_panels_helpers.js
+++ ps/trunk/binaries/data/mods/public/gui/session/selection_panels_helpers.js
@@ -31,11 +31,6 @@
return false;
}
-function getPlayerHighlightColor(player)
-{
- return "color:" + rgbToGuiColor(g_DisplayedPlayerColors[player], 160);
-}
-
/**
* Returns a "color:255 0 0 Alpha" string based on how many resources are needed.
*/
Index: ps/trunk/binaries/data/mods/public/gui/session/session.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/session.js
+++ ps/trunk/binaries/data/mods/public/gui/session/session.js
@@ -11,21 +11,14 @@
const g_VictoryConditions = g_Settings && g_Settings.VictoryConditions;
var g_Chat;
+var g_DiplomacyButton;
+var g_DiplomacyColors;
+var g_DiplomacyDialog;
+var g_MiniMapPanel;
var g_GameSpeeds;
/**
- * Whether to display diplomacy colors (where players see self/ally/neutral/enemy each in different colors and
- * observers see each team in a different color) or regular player colors.
- */
-var g_DiplomacyColorsToggle = false;
-
-/**
- * The array of displayed player colors (either the diplomacy color or regular color for each player).
- */
-var g_DisplayedPlayerColors;
-
-/**
* Colors to flash when pop limit reached.
*/
var g_DefaultPopulationColor = "white";
@@ -272,8 +265,12 @@
restoreSavedGameData(initData.savedGUIData);
}
- g_DeveloperOverlay = new DeveloperOverlay();
g_Chat = new Chat();
+ g_DeveloperOverlay = new DeveloperOverlay();
+ g_DiplomacyColors = new DiplomacyColors();
+ g_DiplomacyDialog = new DiplomacyDialog(g_DiplomacyColors);
+ g_DiplomacyButton = new DiplomacyButton(g_DiplomacyDialog);
+ g_MiniMapPanel = new MiniMapPanel(g_DiplomacyColors, g_WorkerTypes);
LoadModificationTemplates();
updatePlayerData();
@@ -296,13 +293,14 @@
{
initMenu();
updateGameSpeedControl();
- resizeDiplomacyDialog();
resizeTradeDialog();
initBarterButtons();
initPanelEntities();
+ g_DiplomacyColors.onPlayerInit();
initViewedPlayerDropdown();
Engine.SetBoundingBoxDebugOverlay(false);
updateEnabledRangeOverlayTypes();
+ g_DiplomacyDialog.onPlayerInit();
}
function updatePlayerData()
@@ -353,69 +351,13 @@
g_Players = playerData;
}
-function updateDiplomacyColorsButton()
-{
- g_DiplomacyColorsToggle = !g_DiplomacyColorsToggle;
-
- let diplomacyColorsButton = Engine.GetGUIObjectByName("diplomacyColorsButton");
-
- diplomacyColorsButton.sprite = g_DiplomacyColorsToggle ?
- "stretched:session/minimap-diplomacy-on.png" :
- "stretched:session/minimap-diplomacy-off.png";
-
- diplomacyColorsButton.sprite_over = g_DiplomacyColorsToggle ?
- "stretched:session/minimap-diplomacy-on-highlight.png" :
- "stretched:session/minimap-diplomacy-off-highlight.png";
-
- Engine.GetGUIObjectByName("diplomacyColorsWindowButtonIcon").sprite = g_DiplomacyColorsToggle ?
- "stretched:session/icons/diplomacy-on.png" :
- "stretched:session/icons/diplomacy.png";
-
- updateDisplayedPlayerColors();
-}
-
/**
- * Updates the displayed colors of players in the simulation and GUI.
+ * Called when the user changed the diplomacy colors in the options.
+ * TODO: Remove this proxy and make the options page agnostic of the session page.
*/
function updateDisplayedPlayerColors()
{
- if (g_DiplomacyColorsToggle)
- {
- let getDiplomacyColor = stance =>
- guiToRgbColor(Engine.ConfigDB_GetValue("user", "gui.session.diplomacycolors." + stance)) ||
- guiToRgbColor(Engine.ConfigDB_GetValue("default", "gui.session.diplomacycolors." + stance));
-
- let teamRepresentatives = {};
- for (let i = 1; i < g_Players.length; ++i)
- if (g_ViewedPlayer <= 0)
- {
- // Observers and gaia see team colors
- let team = g_Players[i].team;
- g_DisplayedPlayerColors[i] = g_Players[teamRepresentatives[team] || i].color;
- if (team != -1 && !teamRepresentatives[team])
- teamRepresentatives[team] = i;
- }
- else
- // Players see colors depending on diplomacy
- g_DisplayedPlayerColors[i] =
- g_ViewedPlayer == i ? getDiplomacyColor("self") :
- g_Players[g_ViewedPlayer].isAlly[i] ? getDiplomacyColor("ally") :
- g_Players[g_ViewedPlayer].isNeutral[i] ? getDiplomacyColor("neutral") :
- getDiplomacyColor("enemy");
-
- g_DisplayedPlayerColors[0] = g_Players[0].color;
- }
- else
- g_DisplayedPlayerColors = g_Players.map(player => player.color);
-
- Engine.GuiInterfaceCall("UpdateDisplayedPlayerColors", {
- "displayedPlayerColors": g_DisplayedPlayerColors,
- "displayDiplomacyColors": g_DiplomacyColorsToggle,
- "showAllStatusBars": g_ShowAllStatusBars,
- "selected": g_Selection.toList()
- });
-
- updateGUIObjects();
+ g_DiplomacyColors.updateDisplayedPlayerColors();
}
/**
@@ -423,22 +365,6 @@
*/
function updateHotkeyTooltips()
{
- Engine.GetGUIObjectByName("idleWorkerButton").tooltip =
- colorizeHotkey("%(hotkey)s" + " ", "selection.idleworker") +
- translate("Find idle worker");
-
- Engine.GetGUIObjectByName("diplomacyColorsButton").tooltip =
- colorizeHotkey("%(hotkey)s" + " ", "session.diplomacycolors") +
- translate("Toggle Diplomacy Colors");
-
- Engine.GetGUIObjectByName("diplomacyColorsWindowButton").tooltip =
- colorizeHotkey("%(hotkey)s" + " ", "session.diplomacycolors") +
- translate("Toggle Diplomacy Colors");
-
- Engine.GetGUIObjectByName("diplomacyButton").tooltip =
- colorizeHotkey("%(hotkey)s" + " ", "session.gui.diplomacy.toggle") +
- translate("Diplomacy");
-
Engine.GetGUIObjectByName("tradeButton").tooltip =
colorizeHotkey("%(hotkey)s" + " ", "session.gui.barter.toggle") +
translate("Barter & Trade");
@@ -506,7 +432,6 @@
function initViewedPlayerDropdown()
{
- g_DisplayedPlayerColors = g_Players.map(player => player.color);
updateViewedPlayerDropdown();
// Select "observer" in the view player dropdown when rejoining as a defeated player
@@ -551,7 +476,7 @@
}
Engine.SetViewedPlayer(g_ViewedPlayer);
- updateDisplayedPlayerColors();
+ g_DiplomacyColors.updateDisplayedPlayerColors();
updateTopPanel();
g_Chat.onUpdatePlayers();
updateHotkeyTooltips();
@@ -561,8 +486,7 @@
Engine.GuiInterfaceCall("ResetTemplateModified");
onSimulationUpdate();
- if (g_IsDiplomacyOpen)
- openDiplomacy();
+ g_DiplomacyDialog.update();
if (g_IsTradeOpen)
openTrade();
@@ -687,7 +611,8 @@
resPop.size = resPopSize;
Engine.GetGUIObjectByName("population").hidden = !isPlayer;
- Engine.GetGUIObjectByName("diplomacyButton").hidden = !isPlayer;
+ g_DiplomacyButton.update();
+
Engine.GetGUIObjectByName("tradeButton").hidden = !isPlayer ||
(!g_ResourceData.GetTradableCodes().length && !g_ResourceData.GetBarterableCodes().length);
Engine.GetGUIObjectByName("observerText").hidden = isPlayer;
@@ -846,15 +771,6 @@
Engine.SetSimRate(speed);
}
-function updateIdleWorkerButton()
-{
- Engine.GetGUIObjectByName("idleWorkerButton").enabled = Engine.GuiInterfaceCall("HasIdleUnits", {
- "viewedPlayer": g_ViewedPlayer,
- "idleClasses": g_WorkerTypes,
- "excludeUnits": []
- });
-}
-
function onSimulationUpdate()
{
// Templates change depending on technologies and auras, so they have to be reloaded after such a change.
@@ -946,7 +862,6 @@
updateSelectionDetails();
updateBuildingPlacementPreview();
updateTimeNotifications();
- updateIdleWorkerButton();
if (g_IsTradeOpen)
{
@@ -969,8 +884,9 @@
}
updateViewedPlayerDropdown();
- updateDiplomacy();
g_DeveloperOverlay.update();
+ g_DiplomacyDialog.update();
+ g_MiniMapPanel.update();
}
function saveResPopTooltipSort()
Index: ps/trunk/binaries/data/mods/public/gui/session/session.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/session.xml
+++ ps/trunk/binaries/data/mods/public/gui/session/session.xml
@@ -5,6 +5,10 @@
+
+
+
+
@@ -97,8 +101,8 @@
+
-
@@ -120,7 +124,7 @@
-
+
-
- toggleDiplomacy();
-
Index: ps/trunk/binaries/data/mods/public/gui/summary/summary.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/summary/summary.js
+++ ps/trunk/binaries/data/mods/public/gui/summary/summary.js
@@ -418,7 +418,7 @@
boxSize.right = rowPlayerObjectWidth;
rowPlayerObject.size = boxSize;
- setOutcomeIcon(playerState.state, playerOutcome);
+ setOutcomeIcon(playerState.state, Engine.GetGUIObjectByName(playerOutcome));
playerNameColumn = Engine.GetGUIObjectByName(playerNameColumn);
playerNameColumn.caption = g_GameData.sim.playerStates[i + 1].name;