Index: binaries/data/config/default.cfg =================================================================== --- binaries/data/config/default.cfg +++ binaries/data/config/default.cfg @@ -367,6 +367,10 @@ 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 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. +technologies_observer = all ; Show a chat notification in observermode if a player researchs a technology. + +[gui.session.notifications.technology] +phase_village = none ; Supress notifications of technologies instantly researched [gui.splashscreen] enable = true ; Enable/disable the splashscreen Index: binaries/data/mods/public/gui/options/options.json =================================================================== --- binaries/data/mods/public/gui/options/options.json +++ binaries/data/mods/public/gui/options/options.json @@ -447,6 +447,17 @@ { "value": "completed", "label": "Completed" }, { "value": "all", "label": "All displayed" } ] + }, + { + "type": "dropdown", + "label": "Observer Technologies", + "tooltip": "Show a chat notification in observermode if a player researchs a technology.", + "config": "gui.session.notifications.technologies_observer", + "list": [ + { "value": "none", "label": "Disable" }, + { "value": "completed", "label": "Completed" }, + { "value": "all", "label": "All displayed" } + ] } ] } 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 @@ -130,7 +130,7 @@ "tribute": msg => formatTributeMessage(msg), "barter": msg => formatBarterMessage(msg), "attack": msg => formatAttackMessage(msg), - "phase": msg => formatPhaseMessage(msg) + "technology": msg => formatTechnologyMessage(msg) }; /** @@ -393,13 +393,13 @@ "targetIsDomesticAnimal": notification.targetIsDomesticAnimal }); }, - "phase": function(notification, player) + "technology": function(notification, player) { addChatMessage({ - "type": "phase", + "type": "technology", "player": player, - "phaseName": notification.phaseName, - "phaseState": notification.phaseState + "name": notification.name, + "state": notification.state }); }, "dialog": function(notification, player) @@ -1051,26 +1051,46 @@ }); } -function formatPhaseMessage(msg) +function formatTechnologyMessage(msg) { - let notifyPhase = Engine.ConfigDB_GetValue("user", "gui.session.notifications.phase"); - if (notifyPhase == "none" || msg.player != g_ViewedPlayer && !g_IsObserver && !g_Players[msg.player].isMutualAlly[g_ViewedPlayer]) + let isPhase = msg.name.startsWith("phase_"); + + // Allow the user to suppress for example instantly researched phases + let notify = + Engine.ConfigDB_GetValue("user", "gui.session.notifications.technology." + msg.name) || + (isPhase ? + Engine.ConfigDB_GetValue("user", "gui.session.notifications.phase") : + g_IsObserver && Engine.ConfigDB_GetValue("user", "gui.session.notifications.technologies_observer")); + + if (!notify || notify == "none" || msg.player != g_ViewedPlayer && !g_IsObserver && !g_Players[msg.player].isMutualAlly[g_ViewedPlayer]) return ""; let message = ""; - if (notifyPhase == "all") + if (notify == "all") { - if (msg.phaseState == "started") - message = translate("%(player)s is advancing to the %(phaseName)s."); - else if (msg.phaseState == "aborted") - message = translate("The %(phaseName)s of %(player)s has been aborted."); + if (msg.state == "started") + { + message = isPhase ? + translate("%(player)s is advancing to the %(phaseName)s.") : + translate("%(player)s starts to research the %(technologyName)s."); + } + else if (msg.state == "aborted") + message = isPhase ? + translate("The %(phaseName)s of %(player)s has been aborted.") : + translate("%(player)s has aborted the %(technologyName)s."); } - if (msg.phaseState == "completed") - message = translate("%(player)s has reached the %(phaseName)s."); + + if (msg.state == "completed") + message = isPhase ? + translate("%(player)s has reached the %(phaseName)s.") : + translate("%(player)s has researched the %(technologyName)s."); + + let techName = getEntityNames(GetTechnologyData(msg.name, g_Players[msg.player].civ)); return sprintf(message, { "player": colorizePlayernameByID(msg.player), - "phaseName": getEntityNames(GetTechnologyData(msg.phaseName, g_Players[msg.player].civ)) + "phaseName": techName, + "technologyName": techName }); } Index: binaries/data/mods/public/simulation/components/TechnologyManager.js =================================================================== --- binaries/data/mods/public/simulation/components/TechnologyManager.js +++ binaries/data/mods/public/simulation/components/TechnologyManager.js @@ -119,16 +119,10 @@ } if (template.top && this.IsInProgress(template.top) || - template.bottom && this.IsInProgress(template.bottom)) - return false; - - if (template.pair && !this.CanResearch(template.pair)) - return false; - - if (this.IsInProgress(tech)) - return false; - - if (this.IsTechnologyResearched(tech)) + template.bottom && this.IsInProgress(template.bottom) || + template.pair && !this.CanResearch(template.pair) || + this.IsInProgress(tech) || + this.IsTechnologyResearched(tech)) return false; return this.CheckTechnologyRequirements(DeriveTechnologyRequirements(template, Engine.QueryInterface(this.entity, IID_Player).GetCiv())); @@ -148,10 +142,7 @@ if (!reqs) return false; - if (civonly || !reqs.length) - return true; - - return reqs.some(req => { + return civonly || !reqs.length || reqs.some(req => { return Object.keys(req).every(type => { switch (type) { @@ -343,16 +334,13 @@ Engine.BroadcastMessage(MT_ValueModification, { "entities": ents, "component": component, "valueNames": modifiedComponents[component]}); } - if (tech.startsWith("phase") && !template.autoResearch) - { - let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); - cmpGUIInterface.PushNotification({ - "type": "phase", - "players": [playerID], - "phaseName": tech, - "phaseState": "completed" - }); - } + let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); + cmpGUIInterface.PushNotification({ + "type": "technology", + "players": [playerID], + "name": tech, + "state": "completed" + }); }; // Clears the cached data for an entity from the modifications cache @@ -412,10 +400,10 @@ let cmpPlayer = Engine.QueryInterface(this.entity, IID_Player); let cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); cmpGuiInterface.PushNotification({ - "type": "phase", + "type": "technology", "players": [cmpPlayer.GetPlayerID()], - "phaseName": tech, - "phaseState": "started" + "name": tech, + "state": "started" }); } }; @@ -425,15 +413,15 @@ */ TechnologyManager.prototype.StoppedResearch = function(tech, notification) { - if (notification && tech.startsWith("phase") && this.researchStarted.has(tech)) + if (notification && this.researchStarted.has(tech)) { let cmpPlayer = Engine.QueryInterface(this.entity, IID_Player); let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); cmpGUIInterface.PushNotification({ - "type": "phase", + "type": "technology", "players": [cmpPlayer.GetPlayerID()], - "phaseName": tech, - "phaseState": "aborted" + "name": tech, + "state": "aborted" }); } Index: binaries/data/mods/public/simulation/components/tests/test_VisionSharing.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_VisionSharing.js +++ binaries/data/mods/public/simulation/components/tests/test_VisionSharing.js @@ -51,7 +51,7 @@ cmpVisionSharing.activated = false; cmpVisionSharing.Activate(); TS_ASSERT_EQUALS(cmpVisionSharing.activated, true); -TS_ASSERT_UNEVAL_EQUALS(Array.from(cmpVisionSharing.shared), [1]); +TS_ASSERT_UNEVAL_EQUALS(cmpVisionSharing.shared, new Set([1])); // Test CheckVisionSharings cmpVisionSharing.activated = true;