diff --git a/binaries/data/config/default.cfg b/binaries/data/config/default.cfg
index 07107f5f6a..b5e7f21e5a 100644
--- a/binaries/data/config/default.cfg
+++ b/binaries/data/config/default.cfg
@@ -311,6 +311,7 @@ rotate.ccw = LeftBracket ; Rotate building placement preview anticlockwise
toggle = "Alt+G" ; Toggle visibility of session GUI
menu.toggle = "F10" ; Toggle in-game menu
barter.toggle = "Ctrl+B" ; Toggle in-game barter/trade page
+tutorial.toggle = "Ctrl+P" ; Toggle in-game tutorial panel
[hotkey.session.savedgames]
delete = Delete ; Delete the selected saved game asking confirmation
diff --git a/binaries/data/mods/public/gui/manual/intro.txt b/binaries/data/mods/public/gui/manual/intro.txt
index ac0ac4127b..5de382026e 100644
--- a/binaries/data/mods/public/gui/manual/intro.txt
+++ b/binaries/data/mods/public/gui/manual/intro.txt
@@ -90,6 +90,8 @@ PageUp with units selected: Highlights the units/buildings guarded by the select
PageDown with units/buildings selected: Highlights the units guarding the selection.
Tab: See all status bars (which would also show the building progress)
Ctrl + Tab: Toggle summary window.
+Ctrl + B: Toggle in-game barter/trade page.
+Ctrl + P: Toggle in-game tutorial panel.
[font="sans-bold-14"]Modify mouse action
[font="sans-14"]Ctrl + Right Click on building: Garrison
diff --git a/binaries/data/mods/public/gui/session/hotkeys/misc.xml b/binaries/data/mods/public/gui/session/hotkeys/misc.xml
index d8f5ac81ad..79b628d524 100644
--- a/binaries/data/mods/public/gui/session/hotkeys/misc.xml
+++ b/binaries/data/mods/public/gui/session/hotkeys/misc.xml
@@ -28,6 +28,10 @@
toggleTrade();
+
+
diff --git a/binaries/data/mods/public/gui/session/menu.js b/binaries/data/mods/public/gui/session/menu.js
index 9cdccbd595..f2468d27d9 100644
--- a/binaries/data/mods/public/gui/session/menu.js
+++ b/binaries/data/mods/public/gui/session/menu.js
@@ -997,6 +997,13 @@ function toggleTrade()
openTrade();
}
+function toggleTutorial()
+{
+ let tutorialPanel = Engine.GetGUIObjectByName("tutorialPanel");
+ tutorialPanel.hidden = !tutorialPanel.hidden ||
+ !Engine.GetGUIObjectByName("tutorialText").caption;
+}
+
function updateGameSpeedControl()
{
let player = g_Players[Engine.GetPlayerID()];
diff --git a/binaries/data/mods/public/gui/session/messages.js b/binaries/data/mods/public/gui/session/messages.js
index a7e4411981..64e20e4db7 100644
--- a/binaries/data/mods/public/gui/session/messages.js
+++ b/binaries/data/mods/public/gui/session/messages.js
@@ -33,6 +33,16 @@ var g_ChatTimers = [];
*/
var g_LastChatAddressee = "";
+/**
+ * All tutorial messages received so far.
+ */
+var g_TutorialMessages = [];
+
+/**
+ * GUI tags applied to the most recent tutorial message.
+ */
+var g_TutorialNewMessageTags = { "color": "yellow" };
+
/**
* Handle all netmessage types that can occur.
*/
@@ -548,11 +558,29 @@ function updateTutorial(notification)
return;
}
- let tutorialText = Engine.GetGUIObjectByName("tutorialText");
- tutorialText.caption =
- tutorialText.caption.replace('[color="yellow"]', '').replace('[/color]', '') +
- (tutorialText.caption ? "\n" : "") +
- coloredText(notification.instructions.reduce((instructions, item) => instructions + translate(item), ""), "yellow");
+ // TODO temporary should be removed once D1180 is done
+ for (let i = 0; i < notification.instructions.length; ++i)
+ {
+ let item = notification.instructions[i];
+ if (typeof item == "string")
+ continue;
+ if (item.hotkey.length == 1)
+ {
+ let key = Engine.ConfigDB_GetValue("user", "hotkey." + item.hotkey[0]);
+ if (!key || key.toLowerCase() == "unused")
+ notification.instructions[i]= item.text.replace("%(hotkey)s", "{hotkey " + item.hotkey[0] + " undefined}");
+ }
+ else
+ error("Several hotkeys per instruction item is not yet supported, needs D1180.");
+ }
+ // end of temporary
+ let notificationText =
+ notification.instructions.reduce((instructions, item) =>
+ instructions + (typeof item == "string" ? translate(item) : colorizeHotkey(translate(item.text), item.hotkey)),
+ "");
+
+ Engine.GetGUIObjectByName("tutorialText").caption = g_TutorialMessages.concat(setStringTags(notificationText, g_TutorialNewMessageTags)).join("\n");
+ g_TutorialMessages.push(notificationText);
if (notification.readyButton)
{
diff --git a/binaries/data/mods/public/maps/tutorials/starting_economy_walkthrough.js b/binaries/data/mods/public/maps/tutorials/starting_economy_walkthrough.js
index 6eab776e9d..63f7088b29 100644
--- a/binaries/data/mods/public/maps/tutorials/starting_economy_walkthrough.js
+++ b/binaries/data/mods/public/maps/tutorials/starting_economy_walkthrough.js
@@ -2,8 +2,16 @@ Trigger.prototype.tutorialGoals = [
{
"instructions": [
markForTranslation("This tutorial will teach the basics of developing your economy. Typically, you will start with a Civic Center and a couple units in 'Village Phase' and ultimately, your goal will be to develop and expand your empire, often by evolving to 'Town Phase' and 'City Phase' afterward.\n"),
- markForTranslation("\nBefore starting, you can toggle between fullscreen and windowed mode using Alt+Enter. You can also change the level of zoom using the mouse wheel and the camera view using any of your keyboard's arrow keys.\n"),
- markForTranslation("Adjust the game window to your preferences.\n")
+ {
+ "text": markForTranslation("\nBefore starting, you can toggle between fullscreen and windowed mode using %(hotkey)s."),
+ "hotkey": ["togglefullscreen"]
+ },
+ markForTranslation("You can change the level of zoom using the mouse wheel and the camera view using any of your keyboard's arrow keys.\n"),
+ markForTranslation("Adjust the game window to your preferences.\n"),
+ {
+ "text": markForTranslation("\nYou may also toggle between showing and hiding this tutorial panel at any moment using %(hotkey)s.\n"),
+ "hotkey": ["session.gui.tutorial.toggle"]
+ }
]
},
{