Index: binaries/data/mods/public/gui/session/input.js
===================================================================
--- binaries/data/mods/public/gui/session/input.js
+++ binaries/data/mods/public/gui/session/input.js
@@ -1654,6 +1654,23 @@
lastIdleClasses = [];
}
+function updateColors()
+{
+ // Recolor units, selection, and the minimap.
+ Engine.GuiInterfaceCall("UpdateColors", g_DiplomacyColors);
+
+ // Recolor panels, windows, and status bars.
+ onSimulationUpdate();
+ updatePlayerData();
+ recalculateStatusBarDisplay();
+
+ // Recolor the player selection dropdown.
+ let playerNames = [translate("Observer")];
+ for (let player in g_Players)
+ playerNames.push(colorizePlayernameHelper("■", player) + " " + g_Players[player].name);
+ Engine.GetGUIObjectByName("viewPlayer").list = playerNames;
+}
+
function findIdleUnit(classes)
{
var append = Engine.HotkeyIsPressed("selection.add");
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
@@ -336,6 +336,9 @@
},
"diplomacy": function(notification, player)
{
+ if (g_DiplomacyColors)
+ updateColors();
+
addChatMessage({
"type": "diplomacy",
"sourcePlayer": player,
Index: binaries/data/mods/public/gui/session/minimap_panel.xml
===================================================================
--- binaries/data/mods/public/gui/session/minimap_panel.xml
+++ binaries/data/mods/public/gui/session/minimap_panel.xml
@@ -19,6 +19,20 @@
if (g_HasIdleWorker) Engine.GetGUIObjectByName("idleOverlay").sprite = "stretched:session/minimap-idle-highlight.png";
+
+
-
+
+
Index: binaries/data/mods/public/gui/session/session.js
===================================================================
--- binaries/data/mods/public/gui/session/session.js
+++ binaries/data/mods/public/gui/session/session.js
@@ -186,6 +186,12 @@
* Unit classes to be checked for the military-only-selection modifier and for the idle-warrior-hotkey.
*/
var g_MilitaryTypes = ["Melee", "Ranged"];
+
+/**
+ * True if we should use diplomacy colors (ally/neutral/enemy as a player, teams as an observer).
+ */
+var g_DiplomacyColors = false;
+
/**
* Cache the idle worker status.
*/
@@ -334,6 +340,7 @@
g_Selection.selected = hotloadData.selection;
initChatWindow();
+ updateColors();
sendLobbyPlayerlistUpdate();
onSimulationUpdate();
@@ -508,6 +515,9 @@
}
Engine.SetViewedPlayer(g_ViewedPlayer);
+ if (g_DiplomacyColors)
+ updateColors();
+
updateTopPanel();
updateChatAddressees();
updateHotkeyTooltips();
Index: binaries/data/mods/public/simulation/components/GuiInterface.js
===================================================================
--- binaries/data/mods/public/simulation/components/GuiInterface.js
+++ binaries/data/mods/public/simulation/components/GuiInterface.js
@@ -3,6 +3,13 @@
GuiInterface.prototype.Schema =
"";
+/**
+ * Store diplomacy colors (ally/neutral/enemy as a player, teams as an observer).
+ */
+var g_DiplomacyColors = Engine.ReadJSONFile("settings/diplomacy_colors.json");
+if (!g_DiplomacyColors)
+ throw("GuiInterface.js: Error reading diplomacy_colors.json");
+
GuiInterface.prototype.Serialize = function()
{
// This component isn't network-synchronised for the biggest part
@@ -1757,6 +1764,55 @@
return reduced;
};
+GuiInterface.prototype.UpdateColors = function(player, diplomacyColors)
+{
+ let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
+ let cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
+ let numPlayers = cmpPlayerManager.GetNumPlayers();
+
+ let cmpPlayer = QueryPlayerIDInterface(player, IID_Player);
+ if (!cmpPlayer)
+ return;
+
+ let teamColors = {};
+ for (let i = 1; i < numPlayers; ++i)
+ {
+ let cmpPlayer2 = QueryPlayerIDInterface(i, IID_Player);
+ if (!cmpPlayer2)
+ continue;
+
+ if (!diplomacyColors)
+ cmpPlayer2.ResetDiplomacyColor();
+ else if (player == -1)
+ {
+ // Observers see team colors.
+ let team = cmpPlayer2.GetTeam();
+ if (teamColors[team])
+ cmpPlayer2.SetDiplomacyColor(...g_DiplomacyColors[teamColors[team]]);
+ else
+ cmpPlayer2.SetDiplomacyColor(...g_DiplomacyColors[i]);
+ if (team != -1 && !teamColors[team])
+ teamColors[team] = i;
+ }
+ else if (player == i)
+ cmpPlayer2.SetDiplomacyColor(...g_DiplomacyColors.Self);
+ else if (cmpPlayer.IsAlly(i))
+ cmpPlayer2.SetDiplomacyColor(...g_DiplomacyColors.Ally);
+ else if (cmpPlayer.IsEnemy(i))
+ cmpPlayer2.SetDiplomacyColor(...g_DiplomacyColors.Enemy);
+ else
+ cmpPlayer2.SetDiplomacyColor(...g_DiplomacyColors.Neutral);
+
+ let entities = cmpRangeManager.GetEntitiesByPlayer(i);
+ for (let entity of entities)
+ Engine.PostMessage(entity, MT_ColorChanged, {
+ "entity": entity,
+ "from": i,
+ "to": i
+ });
+ }
+}
+
/**
* Discover if the player has idle units.
*
@@ -1996,6 +2052,7 @@
"GetFoundationSnapData": 1,
"PlaySound": 1,
"FindIdleUnits": 1,
+ "UpdateColors": 1,
"HasIdleUnits": 1,
"GetTradingRouteGain": 1,
"GetTradingDetails": 1,
Index: binaries/data/mods/public/simulation/components/Player.js
===================================================================
--- binaries/data/mods/public/simulation/components/Player.js
+++ binaries/data/mods/public/simulation/components/Player.js
@@ -22,6 +22,20 @@
"";
/**
+ * Don't serialise this.diplomacyColor since it's modified by the GUI
+ */
+Player.prototype.Serialize = function()
+{
+ var ret = {};
+ for (var i in this)
+ if (this.hasOwnProperty(i))
+ ret[i] = this[i];
+
+ delete ret.diplomacyColor;
+ return ret;
+};
+
+/**
* Which units will be shown with special icons at the top.
*/
var panelEntityClasses = "Hero Relic";
@@ -32,6 +46,7 @@
this.name = undefined; // define defaults elsewhere (supporting other languages)
this.civ = undefined;
this.color = { "r": 0.0, "g": 0.0, "b": 0.0, "a": 1.0 };
+ this.diplomacyColor = undefined;
this.popUsed = 0; // population of units owned or trained by this player
this.popBonuses = 0; // sum of population bonuses of player's entities
this.maxPop = 300; // maximum population
@@ -123,9 +138,19 @@
this.color = { "r": r/255.0, "g": g/255.0, "b": b/255.0, "a": 1.0 };
};
+Player.prototype.SetDiplomacyColor = function(r, g, b)
+{
+ this.diplomacyColor = { "r": r/255.0, "g": g/255.0, "b": b/255.0, "a": 1.0 };
+};
+
+Player.prototype.ResetDiplomacyColor = function()
+{
+ this.diplomacyColor = undefined;
+};
+
Player.prototype.GetColor = function()
{
- return this.color;
+ return this.diplomacyColor ? this.diplomacyColor : this.color;
};
// Try reserving num population slots. Returns 0 on success or number of missing slots otherwise.
Index: binaries/data/mods/public/simulation/components/StatusBars.js
===================================================================
--- binaries/data/mods/public/simulation/components/StatusBars.js
+++ binaries/data/mods/public/simulation/components/StatusBars.js
@@ -101,6 +101,12 @@
this.RegenerateSprites();
};
+StatusBars.prototype.OnColorChanged = function(msg)
+{
+ if (this.enabled)
+ this.RegenerateSprites();
+};
+
StatusBars.prototype.RegenerateSprites = function()
{
let cmpOverlayRenderer = Engine.QueryInterface(this.entity, IID_OverlayRenderer);
Index: binaries/data/mods/public/simulation/data/settings/diplomacy_colors.json
===================================================================
--- binaries/data/mods/public/simulation/data/settings/diplomacy_colors.json
+++ binaries/data/mods/public/simulation/data/settings/diplomacy_colors.json
@@ -0,0 +1,15 @@
+{
+ "0": [255, 255, 255],
+ "1": [0, 0, 255],
+ "2": [255, 0, 0],
+ "3": [0, 255, 0],
+ "4": [255, 255, 0],
+ "5": [0, 255, 255],
+ "6": [255, 0, 255],
+ "7": [255, 128, 0],
+ "8": [25, 25, 25],
+ "Self": [0, 0, 255],
+ "Ally": [0, 255, 0],
+ "Neutral": [255, 255, 0],
+ "Enemy": [255, 0, 0]
+}
Index: source/simulation2/MessageTypes.h
===================================================================
--- source/simulation2/MessageTypes.h
+++ source/simulation2/MessageTypes.h
@@ -243,6 +243,21 @@
entity_id_t entity;
};
+class CMessageColorChanged : public CMessage
+{
+public:
+ DEFAULT_MESSAGE_IMPL(ColorChanged)
+
+ CMessageColorChanged(entity_id_t entity, player_id_t from, player_id_t to) :
+ entity(entity), from(from), to(to)
+ {
+ }
+
+ entity_id_t entity;
+ player_id_t from;
+ player_id_t to;
+};
+
class CMessageOwnershipChanged : public CMessage
{
public:
Index: source/simulation2/TypeList.h
===================================================================
--- source/simulation2/TypeList.h
+++ source/simulation2/TypeList.h
@@ -41,6 +41,7 @@
MESSAGE(Deserialized) // non-deterministic (use with caution)
MESSAGE(Create)
MESSAGE(Destroy)
+MESSAGE(ColorChanged)
MESSAGE(OwnershipChanged)
MESSAGE(PositionChanged)
MESSAGE(InterpolatedPositionChanged)
Index: source/simulation2/components/CCmpMinimap.cpp
===================================================================
--- source/simulation2/components/CCmpMinimap.cpp
+++ source/simulation2/components/CCmpMinimap.cpp
@@ -33,6 +33,7 @@
static void ClassInit(CComponentManager& componentManager)
{
componentManager.SubscribeToMessageType(MT_PositionChanged);
+ componentManager.SubscribeToMessageType(MT_ColorChanged);
componentManager.SubscribeToMessageType(MT_OwnershipChanged);
componentManager.SubscribeToMessageType(MT_MinimapPing);
}
@@ -117,13 +118,6 @@
template
void SerializeCommon(S& serialize)
{
- if (m_UsePlayerColor)
- {
- serialize.NumberU8_Unbounded("r", m_R);
- serialize.NumberU8_Unbounded("g", m_G);
- serialize.NumberU8_Unbounded("b", m_B);
- }
-
serialize.Bool("active", m_Active);
if (m_Active)
@@ -166,6 +160,7 @@
break;
}
+ case MT_ColorChanged:
case MT_OwnershipChanged:
{
if (!m_UsePlayerColor)
Index: source/simulation2/components/CCmpSelectable.cpp
===================================================================
--- source/simulation2/components/CCmpSelectable.cpp
+++ source/simulation2/components/CCmpSelectable.cpp
@@ -54,6 +54,7 @@
public:
static void ClassInit(CComponentManager& componentManager)
{
+ componentManager.SubscribeToMessageType(MT_ColorChanged);
componentManager.SubscribeToMessageType(MT_OwnershipChanged);
componentManager.SubscribeToMessageType(MT_PositionChanged);
componentManager.SubscribeToMessageType(MT_TerrainChanged);
@@ -354,6 +355,7 @@
break;
}
+ case MT_ColorChanged:
case MT_OwnershipChanged:
{
const CMessageOwnershipChanged& msgData = static_cast (msg);
Index: source/simulation2/components/CCmpTerritoryManager.cpp
===================================================================
--- source/simulation2/components/CCmpTerritoryManager.cpp
+++ source/simulation2/components/CCmpTerritoryManager.cpp
@@ -59,6 +59,7 @@
public:
static void ClassInit(CComponentManager& componentManager)
{
+ componentManager.SubscribeGloballyToMessageType(MT_ColorChanged);
componentManager.SubscribeGloballyToMessageType(MT_OwnershipChanged);
componentManager.SubscribeGloballyToMessageType(MT_PositionChanged);
componentManager.SubscribeGloballyToMessageType(MT_ValueModification);
@@ -166,6 +167,19 @@
{
switch (msg.GetType())
{
+ case MT_ColorChanged:
+ {
+ const CMessageOwnershipChanged& msgData = static_cast (msg);
+ CmpPtr cmpTerritoryInfluence(GetSimContext(), msgData.entity);
+ if (cmpTerritoryInfluence)
+ {
+ SAFE_DELETE(m_Territories);
+ ++m_DirtyID;
+ m_BoundaryLinesDirty = true;
+// m_TriggerEvent = true; // Same as case MT_OwnershipChanged, except for this line
+ }
+ break;
+ }
case MT_OwnershipChanged:
{
const CMessageOwnershipChanged& msgData = static_cast (msg);
Index: source/simulation2/scripting/MessageTypeConversions.cpp
===================================================================
--- source/simulation2/scripting/MessageTypeConversions.cpp
+++ source/simulation2/scripting/MessageTypeConversions.cpp
@@ -190,6 +190,26 @@
////////////////////////////////
+JS::Value CMessageColorChanged::ToJSVal(ScriptInterface& scriptInterface) const
+{
+ TOJSVAL_SETUP();
+ SET_MSG_PROPERTY(entity);
+ SET_MSG_PROPERTY(from);
+ SET_MSG_PROPERTY(to);
+ return JS::ObjectValue(*obj);
+}
+
+CMessage* CMessageColorChanged::FromJSVal(ScriptInterface& scriptInterface, JS::HandleValue val)
+{
+ FROMJSVAL_SETUP();
+ GET_MSG_PROPERTY(entity_id_t, entity);
+ GET_MSG_PROPERTY(player_id_t, from);
+ GET_MSG_PROPERTY(player_id_t, to);
+ return new CMessageColorChanged(entity, from, to);
+}
+
+////////////////////////////////
+
JS::Value CMessageOwnershipChanged::ToJSVal(ScriptInterface& scriptInterface) const
{
TOJSVAL_SETUP();