diff --git a/binaries/data/mods/public/gui/pregame/BackgroundHandler.js b/binaries/data/mods/public/gui/pregame/BackgroundHandler.js index a379453be1..2844ab8bae 100644 --- a/binaries/data/mods/public/gui/pregame/BackgroundHandler.js +++ b/binaries/data/mods/public/gui/pregame/BackgroundHandler.js @@ -1,32 +1,3 @@ -class BackgroundHandler -{ - constructor(layers) - { - this.backgroundLayers = layers.map((layer, i) => - new BackgroundLayer(layer, i)); - - this.initTime = Date.now(); - - this.backgrounds = Engine.GetGUIObjectByName("backgrounds"); - this.backgrounds.onTick = this.onTick.bind(this); - this.backgrounds.onWindowResized = this.onWindowResized.bind(this); - this.onWindowResized(); - } - - onWindowResized() - { - const size = this.backgrounds.getComputedSize(); - this.backgroundsSize = deepfreeze(new GUISize(size.top, size.left, size.right, size.bottom)); - } - - onTick() - { - const time = Date.now() - this.initTime; - for (const background of this.backgroundLayers) - background.update(time, this.backgroundsSize); - } -} - class BackgroundLayer { constructor(layer, i) @@ -69,4 +40,33 @@ class BackgroundLayer } } +class BackgroundHandler +{ + constructor(layers) + { + this.backgroundLayers = layers.map((layer, i) => + new BackgroundLayer(layer, i)); + + this.initTime = Date.now(); + + this.backgrounds = Engine.GetGUIObjectByName("backgrounds"); + this.backgrounds.onTick = this.onTick.bind(this); + this.backgrounds.onWindowResized = this.onWindowResized.bind(this); + this.onWindowResized(); + } + + onWindowResized() + { + const size = this.backgrounds.getComputedSize(); + this.backgroundsSize = deepfreeze(new GUISize(size.top, size.left, size.right, size.bottom)); + } + + onTick() + { + const time = Date.now() - this.initTime; + for (const background of this.backgroundLayers) + background.update(time, this.backgroundsSize); + } +} + BackgroundLayer.prototype.AspectRatio = 16 / 9; diff --git a/binaries/data/mods/public/gui/pregame/MainMenuPage.js b/binaries/data/mods/public/gui/pregame/MainMenuPage.js index 1c1501f20d..59887d8172 100644 --- a/binaries/data/mods/public/gui/pregame/MainMenuPage.js +++ b/binaries/data/mods/public/gui/pregame/MainMenuPage.js @@ -1,28 +1,3 @@ -/** - * This is the handler that coordinates all other handlers on this GUI page. - */ -class MainMenuPage -{ - constructor(closePageCallback, data, hotloadData, mainMenuItems, backgroundLayerData, - projectInformation, communityButtons) - { - this.backgroundHandler = new BackgroundHandler(pickRandom(backgroundLayerData)); - this.menuHandler = new MainMenuItemHandler(closePageCallback, mainMenuItems); - this.splashScreenHandler = new SplashScreenHandler(data, hotloadData && hotloadData.splashScreenHandler); - - new MusicHandler(); - new ProjectInformationHandler(projectInformation); - new CommunityButtonHandler(communityButtons); - } - - getHotloadData() - { - return { - "splashScreenHandler": this.splashScreenHandler.getHotloadData() - }; - } -} - class MusicHandler { constructor() @@ -59,3 +34,28 @@ class CommunityButtonHandler error("GUI page has space for " + buttons.length + " community buttons, but " + menuItems.length + " items are provided!"); } } + +/** + * This is the handler that coordinates all other handlers on this GUI page. + */ +class MainMenuPage +{ + constructor(closePageCallback, data, hotloadData, mainMenuItems, backgroundLayerData, + projectInformation, communityButtons) + { + this.backgroundHandler = new BackgroundHandler(pickRandom(backgroundLayerData)); + this.menuHandler = new MainMenuItemHandler(closePageCallback, mainMenuItems); + this.splashScreenHandler = new SplashScreenHandler(data, hotloadData && hotloadData.splashScreenHandler); + + new MusicHandler(); + new ProjectInformationHandler(projectInformation); + new CommunityButtonHandler(communityButtons); + } + + getHotloadData() + { + return { + "splashScreenHandler": this.splashScreenHandler.getHotloadData() + }; + } +} diff --git a/binaries/data/mods/public/gui/session/ResearchProgress.js b/binaries/data/mods/public/gui/session/ResearchProgress.js index 67f0986b06..e20e2725ee 100644 --- a/binaries/data/mods/public/gui/session/ResearchProgress.js +++ b/binaries/data/mods/public/gui/session/ResearchProgress.js @@ -1,48 +1,3 @@ -/** - * This class is responsible for displaying the currently researched technologies in an overlay. - */ -class ResearchProgress -{ - constructor(playerViewControl, selection) - { - this.buttons = Engine.GetGUIObjectByName("researchStartedButtons").children; - this.buttonHandlers = this.buttons.map((button, i) => new ResearchProgressButton(selection, i)); - - /** - * Top coordinate of the research list. - * Changes depending on the number of displayed counters. - */ - this.topOffset = g_OverlayCounterManager.lastHeight; - - const updater = this.updateResearchProgress.bind(this); - registerSimulationUpdateHandler(updater); - playerViewControl.registerViewedPlayerChangeHandler(updater); - g_OverlayCounterManager.registerResizeHandler(this.setTopOffset.bind(this)); - } - - setTopOffset(offset) - { - this.topOffset = offset; - } - - updateResearchProgress() - { - const researchStarted = Engine.GuiInterfaceCall("GetStartedResearch", g_ViewedPlayer); - - let i = 0; - for (const techName in researchStarted) - { - if (i == this.buttons.length) - break; - - this.buttonHandlers[i++].onResearchedProgress(this.topOffset, techName, researchStarted[techName]); - } - - while (i < this.buttons.length) - this.buttons[i++].hidden = true; - } -} - /** * This is an individual button displaying a tech currently researched by the currently viewed player. */ @@ -101,6 +56,51 @@ class ResearchProgressButton } } +/** + * This class is responsible for displaying the currently researched technologies in an overlay. + */ +class ResearchProgress +{ + constructor(playerViewControl, selection) + { + this.buttons = Engine.GetGUIObjectByName("researchStartedButtons").children; + this.buttonHandlers = this.buttons.map((button, i) => new ResearchProgressButton(selection, i)); + + /** + * Top coordinate of the research list. + * Changes depending on the number of displayed counters. + */ + this.topOffset = g_OverlayCounterManager.lastHeight; + + const updater = this.updateResearchProgress.bind(this); + registerSimulationUpdateHandler(updater); + playerViewControl.registerViewedPlayerChangeHandler(updater); + g_OverlayCounterManager.registerResizeHandler(this.setTopOffset.bind(this)); + } + + setTopOffset(offset) + { + this.topOffset = offset; + } + + updateResearchProgress() + { + const researchStarted = Engine.GuiInterfaceCall("GetStartedResearch", g_ViewedPlayer); + + let i = 0; + for (const techName in researchStarted) + { + if (i == this.buttons.length) + break; + + this.buttonHandlers[i++].onResearchedProgress(this.topOffset, techName, researchStarted[techName]); + } + + while (i < this.buttons.length) + this.buttons[i++].hidden = true; + } +} + /** * Distance between consecutive buttons. */ diff --git a/binaries/data/mods/public/gui/session/developer_overlay/TimeWarp.js b/binaries/data/mods/public/gui/session/developer_overlay/TimeWarp.js index c33250142a..f063e6b451 100644 --- a/binaries/data/mods/public/gui/session/developer_overlay/TimeWarp.js +++ b/binaries/data/mods/public/gui/session/developer_overlay/TimeWarp.js @@ -1,3 +1,12 @@ +class TimeWarpMessageBox extends SessionMessageBox +{ +} +TimeWarpMessageBox.prototype.Width = 500; +TimeWarpMessageBox.prototype.Height = 250; +TimeWarpMessageBox.prototype.Title = translate("Time warp mode"); +TimeWarpMessageBox.prototype.Caption = translate( + "Note: time warp mode is a developer option, and not intended for use over long periods of time. Using it incorrectly may cause the game to run out of memory or crash."); + /** * This class manages the timewarp hotkeys that allow jumping back in time and fast forwarding the game. */ @@ -56,12 +65,3 @@ TimeWarp.prototype.NumberTurns = 10; * Gamespeed used while pressing the fast forward hotkey. */ TimeWarp.prototype.FastForwardSpeed = 20; - -class TimeWarpMessageBox extends SessionMessageBox -{ -} -TimeWarpMessageBox.prototype.Width = 500; -TimeWarpMessageBox.prototype.Height = 250; -TimeWarpMessageBox.prototype.Title = translate("Time warp mode"); -TimeWarpMessageBox.prototype.Caption = translate( - "Note: time warp mode is a developer option, and not intended for use over long periods of time. Using it incorrectly may cause the game to run out of memory or crash."); diff --git a/binaries/data/mods/public/gui/session/message_box/QuitConfirmationMenu.js b/binaries/data/mods/public/gui/session/message_box/QuitConfirmationMenu.js index 24894667d0..d0390cfa02 100644 --- a/binaries/data/mods/public/gui/session/message_box/QuitConfirmationMenu.js +++ b/binaries/data/mods/public/gui/session/message_box/QuitConfirmationMenu.js @@ -1,3 +1,23 @@ +class ReturnQuestion extends SessionMessageBox +{ +} +ReturnQuestion.prototype.Title = translate("Confirmation"); +ReturnQuestion.prototype.Caption = translate("Do you want to resign or will you return soon?"); +ReturnQuestion.prototype.Buttons = [ + { + "caption": translate("I will return"), + "onPress": () => { endGame(false); } + }, + { + "caption": translate("I resign"), + "onPress": () => { + Engine.PostNetworkCommand({ + "type": "resign" + }); + } + } +]; + /** * The class that is enabled() will be triggered when the user clicks on the Exit menu button. */ @@ -58,24 +78,3 @@ QuitConfirmationMenu.prototype.MultiplayerClient.prototype.Buttons = } } ]; - -class ReturnQuestion extends SessionMessageBox -{ -} - -ReturnQuestion.prototype.Title = translate("Confirmation"); -ReturnQuestion.prototype.Caption = translate("Do you want to resign or will you return soon?"); -ReturnQuestion.prototype.Buttons = [ - { - "caption": translate("I will return"), - "onPress": () => { endGame(false); } - }, - { - "caption": translate("I resign"), - "onPress": () => { - Engine.PostNetworkCommand({ - "type": "resign" - }); - } - } -]; diff --git a/binaries/data/mods/public/simulation/ai/common-api/class.js b/binaries/data/mods/public/simulation/ai/common-api/class.js index 79c51c23d7..6a17b9cfde 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/class.js +++ b/binaries/data/mods/public/simulation/ai/common-api/class.js @@ -1,4 +1,4 @@ -var API3 = function(m) +API3 = function(m) { /** * Provides a nicer syntax for defining classes, diff --git a/binaries/data/mods/public/simulation/ai/common-api/entity.js b/binaries/data/mods/public/simulation/ai/common-api/entity.js index f8e5cb81ef..90167aaad2 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/entity.js +++ b/binaries/data/mods/public/simulation/ai/common-api/entity.js @@ -1,4 +1,4 @@ -var API3 = function(m) +API3 = function(m) { // defines a template. diff --git a/binaries/data/mods/public/simulation/ai/common-api/entitycollection.js b/binaries/data/mods/public/simulation/ai/common-api/entitycollection.js index e34bf15e44..6cb8cb19ad 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/entitycollection.js +++ b/binaries/data/mods/public/simulation/ai/common-api/entitycollection.js @@ -1,4 +1,4 @@ -var API3 = function(m) +API3 = function(m) { m.EntityCollection = function(sharedAI, entities = new Map(), filters = []) diff --git a/binaries/data/mods/public/simulation/ai/common-api/filters.js b/binaries/data/mods/public/simulation/ai/common-api/filters.js index d2c7809348..7affafb6a6 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/filters.js +++ b/binaries/data/mods/public/simulation/ai/common-api/filters.js @@ -1,4 +1,4 @@ -var API3 = function(m) +API3 = function(m) { m.Filters = { diff --git a/binaries/data/mods/public/simulation/ai/common-api/gamestate.js b/binaries/data/mods/public/simulation/ai/common-api/gamestate.js index c435441f96..1eb920838e 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/gamestate.js +++ b/binaries/data/mods/public/simulation/ai/common-api/gamestate.js @@ -1,4 +1,4 @@ -var API3 = function(m) +API3 = function(m) { /** diff --git a/binaries/data/mods/public/simulation/ai/common-api/map-module.js b/binaries/data/mods/public/simulation/ai/common-api/map-module.js index 1a99c29fc8..dc81c60eea 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/map-module.js +++ b/binaries/data/mods/public/simulation/ai/common-api/map-module.js @@ -1,4 +1,4 @@ -var API3 = function(m) +API3 = function(m) { /** diff --git a/binaries/data/mods/public/simulation/ai/common-api/resources.js b/binaries/data/mods/public/simulation/ai/common-api/resources.js index d88d6c5b51..3d716abb51 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/resources.js +++ b/binaries/data/mods/public/simulation/ai/common-api/resources.js @@ -1,6 +1,6 @@ Resources = new Resources(); -var API3 = function(m) +API3 = function(m) { m.Resources = function(amounts = {}, population = 0) diff --git a/binaries/data/mods/public/simulation/ai/common-api/shared.js b/binaries/data/mods/public/simulation/ai/common-api/shared.js index 497894de77..df74be2537 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/shared.js +++ b/binaries/data/mods/public/simulation/ai/common-api/shared.js @@ -1,4 +1,4 @@ -var API3 = function(m) +API3 = function(m) { /** Shared script handling templates and basic terrain analysis */ diff --git a/binaries/data/mods/public/simulation/ai/common-api/technology.js b/binaries/data/mods/public/simulation/ai/common-api/technology.js index 0def4981ee..2cba43e6c6 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/technology.js +++ b/binaries/data/mods/public/simulation/ai/common-api/technology.js @@ -1,6 +1,6 @@ LoadModificationTemplates(); -var API3 = function(m) +API3 = function(m) { /** Wrapper around a technology template */ diff --git a/binaries/data/mods/public/simulation/ai/common-api/terrain-analysis.js b/binaries/data/mods/public/simulation/ai/common-api/terrain-analysis.js index 4cb25f4185..6d1a02b499 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/terrain-analysis.js +++ b/binaries/data/mods/public/simulation/ai/common-api/terrain-analysis.js @@ -1,4 +1,4 @@ -var API3 = function(m) +API3 = function(m) { /** diff --git a/binaries/data/mods/public/simulation/ai/common-api/utils.js b/binaries/data/mods/public/simulation/ai/common-api/utils.js index 2243098b18..dcc42f6450 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/utils.js +++ b/binaries/data/mods/public/simulation/ai/common-api/utils.js @@ -1,4 +1,4 @@ -var API3 = function(m) +API3 = function(m) { m.warn = function(output) diff --git a/binaries/data/mods/public/simulation/helpers/Commands.js b/binaries/data/mods/public/simulation/helpers/Commands.js index 6fad8cb50e..9666d48360 100644 --- a/binaries/data/mods/public/simulation/helpers/Commands.js +++ b/binaries/data/mods/public/simulation/helpers/Commands.js @@ -2,60 +2,6 @@ // are likely to fail, which may be useful for debugging AIs var g_DebugCommands = false; -function ProcessCommand(player, cmd) -{ - const cmpPlayer = QueryPlayerIDInterface(player); - if (!cmpPlayer) - return; - - const data = { - "cmpPlayer": cmpPlayer, - "controlAllUnits": cmpPlayer.CanControlAllUnits() - }; - - if (cmd.entities) - data.entities = FilterEntityList(cmd.entities, player, data.controlAllUnits); - - // TODO: queuing order and forcing formations doesn't really work. - // To play nice, we'll still no-formation queued order if units are in formation - // but the opposite perhaps ought to be implemented. - if (!cmd.queued || cmd.formation == NULL_FORMATION) - data.formation = cmd.formation || undefined; - - // Allow focusing the camera on recent commands - const commandData = { - "type": "playercommand", - "players": [player], - "cmd": cmd - }; - - // Save the position, since the GUI event is received after the unit died - if (cmd.type == "delete-entities") - { - const cmpPosition = cmd.entities[0] && Engine.QueryInterface(cmd.entities[0], IID_Position); - commandData.position = cmpPosition && cmpPosition.IsInWorld() && cmpPosition.GetPosition2D(); - } - - const cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); - cmpGuiInterface.PushNotification(commandData); - - // Note: checks of UnitAI targets are not robust enough here, as ownership - // can change after the order is issued, they should be checked by UnitAI - // when the specific behavior (e.g. attack, garrison) is performed. - // (Also it's not ideal if a command silently fails, it's nicer if UnitAI - // moves the entities closer to the target before giving up.) - - // Now handle various commands - if (g_Commands[cmd.type]) - { - var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger); - cmpTrigger.CallEvent("OnPlayerCommand", { "player": player, "cmd": cmd }); - g_Commands[cmd.type](player, cmd, data); - } - else - error("Invalid command: unknown command type: "+uneval(cmd)); -} - var g_Commands = { "aichat": function(player, cmd, data) @@ -905,6 +851,60 @@ var g_Commands = { }; +function ProcessCommand(player, cmd) +{ + const cmpPlayer = QueryPlayerIDInterface(player); + if (!cmpPlayer) + return; + + const data = { + "cmpPlayer": cmpPlayer, + "controlAllUnits": cmpPlayer.CanControlAllUnits() + }; + + if (cmd.entities) + data.entities = FilterEntityList(cmd.entities, player, data.controlAllUnits); + + // TODO: queuing order and forcing formations doesn't really work. + // To play nice, we'll still no-formation queued order if units are in formation + // but the opposite perhaps ought to be implemented. + if (!cmd.queued || cmd.formation == NULL_FORMATION) + data.formation = cmd.formation || undefined; + + // Allow focusing the camera on recent commands + const commandData = { + "type": "playercommand", + "players": [player], + "cmd": cmd + }; + + // Save the position, since the GUI event is received after the unit died + if (cmd.type == "delete-entities") + { + const cmpPosition = cmd.entities[0] && Engine.QueryInterface(cmd.entities[0], IID_Position); + commandData.position = cmpPosition && cmpPosition.IsInWorld() && cmpPosition.GetPosition2D(); + } + + const cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); + cmpGuiInterface.PushNotification(commandData); + + // Note: checks of UnitAI targets are not robust enough here, as ownership + // can change after the order is issued, they should be checked by UnitAI + // when the specific behavior (e.g. attack, garrison) is performed. + // (Also it's not ideal if a command silently fails, it's nicer if UnitAI + // moves the entities closer to the target before giving up.) + + // Now handle various commands + if (g_Commands[cmd.type]) + { + var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger); + cmpTrigger.CallEvent("OnPlayerCommand", { "player": player, "cmd": cmd }); + g_Commands[cmd.type](player, cmd, data); + } + else + error("Invalid command: unknown command type: "+uneval(cmd)); +} + /** * Sends a GUI notification about unit(s) that failed to ungarrison. */