Allow to disable hints, add changelog
This commit is contained in:
parent
5a46ba5e31
commit
f03f04caa1
|
@ -27,6 +27,7 @@
|
||||||
@import "states/settings";
|
@import "states/settings";
|
||||||
@import "states/about";
|
@import "states/about";
|
||||||
@import "states/mobile_warning";
|
@import "states/mobile_warning";
|
||||||
|
@import "states/changelog";
|
||||||
|
|
||||||
@import "ingame_hud/buildings_toolbar";
|
@import "ingame_hud/buildings_toolbar";
|
||||||
@import "ingame_hud/building_placer";
|
@import "ingame_hud/building_placer";
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
#state_ChangelogState {
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.entry {
|
||||||
|
padding: 20px;
|
||||||
|
.version {
|
||||||
|
@include Heading;
|
||||||
|
}
|
||||||
|
.date {
|
||||||
|
@include PlainText;
|
||||||
|
&::before {
|
||||||
|
content: " | ";
|
||||||
|
}
|
||||||
|
color: #aaabaf;
|
||||||
|
}
|
||||||
|
|
||||||
|
.changes {
|
||||||
|
@include SuperSmallText;
|
||||||
|
@include S(padding-left, 20px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -322,8 +322,7 @@
|
||||||
transform: scale(1.01);
|
transform: scale(1.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.iogLink {
|
&:not(.boxLink) {
|
||||||
// background: transparenT;
|
|
||||||
align-self: flex-end;
|
align-self: flex-end;
|
||||||
justify-self: flex-end;
|
justify-self: flex-end;
|
||||||
height: unset;
|
height: unset;
|
||||||
|
|
|
@ -6,6 +6,29 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.changelogDialogEntry {
|
||||||
|
width: 100%;
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: left;
|
||||||
|
padding: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
.version {
|
||||||
|
@include Heading;
|
||||||
|
}
|
||||||
|
.date {
|
||||||
|
@include PlainText;
|
||||||
|
&::before {
|
||||||
|
content: " | ";
|
||||||
|
}
|
||||||
|
color: #aaabaf;
|
||||||
|
}
|
||||||
|
|
||||||
|
.changes {
|
||||||
|
@include SuperSmallText;
|
||||||
|
@include S(padding-left, 20px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.failureBox {
|
.failureBox {
|
||||||
.logo {
|
.logo {
|
||||||
img {
|
img {
|
||||||
|
|
|
@ -37,6 +37,7 @@ import { AboutState } from "./states/about";
|
||||||
import { PlatformWrapperImplElectron } from "./platform/electron/wrapper";
|
import { PlatformWrapperImplElectron } from "./platform/electron/wrapper";
|
||||||
import { StorageImplElectron } from "./platform/electron/storage";
|
import { StorageImplElectron } from "./platform/electron/storage";
|
||||||
import { MobileWarningState } from "./states/mobile_warning";
|
import { MobileWarningState } from "./states/mobile_warning";
|
||||||
|
import { ChangelogState } from "./states/changelog";
|
||||||
|
|
||||||
const logger = createLogger("application");
|
const logger = createLogger("application");
|
||||||
|
|
||||||
|
@ -165,6 +166,7 @@ export class Application {
|
||||||
SettingsState,
|
SettingsState,
|
||||||
KeybindingsState,
|
KeybindingsState,
|
||||||
AboutState,
|
AboutState,
|
||||||
|
ChangelogState,
|
||||||
];
|
];
|
||||||
|
|
||||||
for (let i = 0; i < states.length; ++i) {
|
for (let i = 0; i < states.length; ++i) {
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
export const CHANGELOG = [
|
||||||
|
{
|
||||||
|
version: "1.0.2",
|
||||||
|
date: "23.05.2020",
|
||||||
|
entries: [
|
||||||
|
"Introduced changelog",
|
||||||
|
"Removed 'early access' label because the game isn't actually early access - its in a pretty good state already! (No worries, a lot more updates will follow!)",
|
||||||
|
"Added a 'Show hint' button which shows a small video for almost all levels to help out",
|
||||||
|
"Now showing proper descriptions when completing levels, with instructions on what the gained reward does.",
|
||||||
|
"Show a landing page on mobile devices about the game not being ready to be played on mobile yet",
|
||||||
|
"Fix painters and mixers being affected by the shape processors upgrade and not the painter one",
|
||||||
|
"Added 'multiplace' setting which is equivalent to holding SHIFT all the time",
|
||||||
|
"Added keybindings to zoom in / zoom out",
|
||||||
|
"Tunnels now also show connection lines to tunnel exits, instead of just tunnel entries",
|
||||||
|
"Lots of minor fixes and improvements",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "1.0.1",
|
||||||
|
date: "21.05.2020",
|
||||||
|
entries: ["Initial release!"],
|
||||||
|
},
|
||||||
|
];
|
|
@ -83,8 +83,8 @@ export const globalConfig = {
|
||||||
|
|
||||||
debug: {
|
debug: {
|
||||||
/* dev:start */
|
/* dev:start */
|
||||||
fastGameEnter: true,
|
// fastGameEnter: true,
|
||||||
noArtificialDelays: true,
|
// noArtificialDelays: true,
|
||||||
// disableSavegameWrite: true,
|
// disableSavegameWrite: true,
|
||||||
// showEntityBounds: true,
|
// showEntityBounds: true,
|
||||||
// showAcceptorEjectors: true,
|
// showAcceptorEjectors: true,
|
||||||
|
|
|
@ -62,8 +62,6 @@ export class GameHUD {
|
||||||
notifications: new HUDNotifications(this.root),
|
notifications: new HUDNotifications(this.root),
|
||||||
settingsMenu: new HUDSettingsMenu(this.root),
|
settingsMenu: new HUDSettingsMenu(this.root),
|
||||||
|
|
||||||
tutorialHints: new HUDPartTutorialHints(this.root),
|
|
||||||
|
|
||||||
// betaOverlay: new HUDBetaOverlay(this.root),
|
// betaOverlay: new HUDBetaOverlay(this.root),
|
||||||
debugInfo: new HUDDebugInfo(this.root),
|
debugInfo: new HUDDebugInfo(this.root),
|
||||||
|
|
||||||
|
@ -87,6 +85,9 @@ export class GameHUD {
|
||||||
if (IS_DEMO) {
|
if (IS_DEMO) {
|
||||||
this.parts.watermark = new HUDWatermark(this.root);
|
this.parts.watermark = new HUDWatermark(this.root);
|
||||||
}
|
}
|
||||||
|
if (this.root.app.settings.getAllSettings().offerHints) {
|
||||||
|
this.parts.tutorialHints = new HUDPartTutorialHints(this.root);
|
||||||
|
}
|
||||||
|
|
||||||
const frag = document.createDocumentFragment();
|
const frag = document.createDocumentFragment();
|
||||||
for (const key in this.parts) {
|
for (const key in this.parts) {
|
||||||
|
|
|
@ -54,6 +54,15 @@ export class HUDPartTutorialHints extends BaseHUDPart {
|
||||||
this.domAttach = new DynamicDomAttach(this.root, this.element);
|
this.domAttach = new DynamicDomAttach(this.root, this.element);
|
||||||
|
|
||||||
this.currentShownLevel = new TrackedState(this.updateVideoUrl, this);
|
this.currentShownLevel = new TrackedState(this.updateVideoUrl, this);
|
||||||
|
|
||||||
|
this.root.signals.postLoadHook.add(() => {
|
||||||
|
if (this.root.hubGoals.level === 1) {
|
||||||
|
this.root.hud.parts.dialogs.showInfo(
|
||||||
|
T.dialogs.hintDescription.title,
|
||||||
|
T.dialogs.hintDescription.desc
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateVideoUrl(level) {
|
updateVideoUrl(level) {
|
||||||
|
|
|
@ -116,6 +116,7 @@ export const allApplicationSettings = [
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new BoolSetting("alwaysMultiplace", categoryGame, (app, value) => {}),
|
new BoolSetting("alwaysMultiplace", categoryGame, (app, value) => {}),
|
||||||
|
new BoolSetting("offerHints", categoryGame, (app, value) => {}),
|
||||||
];
|
];
|
||||||
|
|
||||||
export function getApplicationSettingById(id) {
|
export function getApplicationSettingById(id) {
|
||||||
|
@ -133,6 +134,7 @@ class SettingsStorage {
|
||||||
this.refreshRate = "60";
|
this.refreshRate = "60";
|
||||||
|
|
||||||
this.alwaysMultiplace = false;
|
this.alwaysMultiplace = false;
|
||||||
|
this.offerHints = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {Object.<string, number>}
|
* @type {Object.<string, number>}
|
||||||
|
@ -291,9 +293,10 @@ export class ApplicationSettings extends ReadWriteProxy {
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentVersion() {
|
getCurrentVersion() {
|
||||||
return 6;
|
return 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param {{settings: SettingsStorage, version: number}} data */
|
||||||
migrate(data) {
|
migrate(data) {
|
||||||
// Simply reset before
|
// Simply reset before
|
||||||
if (data.version < 5) {
|
if (data.version < 5) {
|
||||||
|
@ -307,6 +310,11 @@ export class ApplicationSettings extends ReadWriteProxy {
|
||||||
data.version = 6;
|
data.version = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.version < 7) {
|
||||||
|
data.settings.offerHints = true;
|
||||||
|
data.version = 7;
|
||||||
|
}
|
||||||
|
|
||||||
return ExplainedResult.good();
|
return ExplainedResult.good();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
import { TextualGameState } from "../core/textual_game_state";
|
||||||
|
import { T } from "../translations";
|
||||||
|
import { CHANGELOG } from "../changelog";
|
||||||
|
|
||||||
|
export class ChangelogState extends TextualGameState {
|
||||||
|
constructor() {
|
||||||
|
super("ChangelogState");
|
||||||
|
}
|
||||||
|
|
||||||
|
getStateHeaderTitle() {
|
||||||
|
return T.changelog.title;
|
||||||
|
}
|
||||||
|
|
||||||
|
getMainContentHTML() {
|
||||||
|
const entries = CHANGELOG;
|
||||||
|
|
||||||
|
let html = "";
|
||||||
|
|
||||||
|
for (let i = 0; i < entries.length; ++i) {
|
||||||
|
const entry = entries[i];
|
||||||
|
html += `
|
||||||
|
<div class="entry">
|
||||||
|
<span class="version">${entry.version}</span>
|
||||||
|
<span class="date">${entry.date}</span>
|
||||||
|
<ul class="changes">
|
||||||
|
${entry.entries.map(text => `<li>${text}</li>`).join("")}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
onEnter() {
|
||||||
|
const links = this.htmlElement.querySelectorAll("a[href]");
|
||||||
|
links.forEach(link => {
|
||||||
|
this.trackClicks(
|
||||||
|
link,
|
||||||
|
() => this.app.platformWrapper.openExternalLink(link.getAttribute("href")),
|
||||||
|
{ preventClick: true }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -77,16 +77,18 @@ export class MainMenuState extends GameState {
|
||||||
|
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
|
|
||||||
<a class="githubLink" target="_blank">
|
<a class="githubLink boxLink" target="_blank">
|
||||||
${T.mainMenu.openSourceHint}
|
${T.mainMenu.openSourceHint}
|
||||||
<span class="thirdpartyLogo githubLogo"></span>
|
<span class="thirdpartyLogo githubLogo"></span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a class="discordLink" target="_blank">
|
<a class="discordLink boxLink" target="_blank">
|
||||||
${T.mainMenu.discordLink}
|
${T.mainMenu.discordLink}
|
||||||
<span class="thirdpartyLogo discordLogo"></span>
|
<span class="thirdpartyLogo discordLogo"></span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
<a class="changelog">${T.changelog.title}</a>
|
||||||
|
|
||||||
${
|
${
|
||||||
G_IS_BROWSER &&
|
G_IS_BROWSER &&
|
||||||
this.app.platformWrapper instanceof PlatformWrapperImplBrowser &&
|
this.app.platformWrapper instanceof PlatformWrapperImplBrowser &&
|
||||||
|
@ -207,6 +209,7 @@ export class MainMenuState extends GameState {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.trackClicks(qs(".settingsButton"), this.onSettingsButtonClicked);
|
this.trackClicks(qs(".settingsButton"), this.onSettingsButtonClicked);
|
||||||
|
this.trackClicks(qs(".changelog"), this.onChangelogClicked);
|
||||||
|
|
||||||
if (G_IS_STANDALONE) {
|
if (G_IS_STANDALONE) {
|
||||||
this.trackClicks(qs(".exitAppButton"), this.onExitAppButtonClicked);
|
this.trackClicks(qs(".exitAppButton"), this.onExitAppButtonClicked);
|
||||||
|
@ -251,6 +254,10 @@ export class MainMenuState extends GameState {
|
||||||
this.app.platformWrapper.exitApp();
|
this.app.platformWrapper.exitApp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onChangelogClicked() {
|
||||||
|
this.moveToState("ChangelogState");
|
||||||
|
}
|
||||||
|
|
||||||
renderSavegames() {
|
renderSavegames() {
|
||||||
const oldContainer = this.htmlElement.querySelector(".mainContainer .savegames");
|
const oldContainer = this.htmlElement.querySelector(".mainContainer .savegames");
|
||||||
if (oldContainer) {
|
if (oldContainer) {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { cachebust } from "../core/cachebust";
|
||||||
import { PlatformWrapperImplBrowser } from "../platform/browser/wrapper";
|
import { PlatformWrapperImplBrowser } from "../platform/browser/wrapper";
|
||||||
import { T } from "../translations";
|
import { T } from "../translations";
|
||||||
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
|
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
|
||||||
|
import { CHANGELOG } from "../changelog";
|
||||||
|
|
||||||
const logger = createLogger("state/preload");
|
const logger = createLogger("state/preload");
|
||||||
|
|
||||||
|
@ -176,6 +177,52 @@ export class PreloadState extends GameState {
|
||||||
return this.app.backgroundResourceLoader.getPromiseForBareGame();
|
return this.app.backgroundResourceLoader.getPromiseForBareGame();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
.then(() => this.setStatus("Checking changelog"))
|
||||||
|
.then(() => {
|
||||||
|
return this.app.storage
|
||||||
|
.readFileAsync("lastversion.bin")
|
||||||
|
.catch(err => {
|
||||||
|
logger.warn("Failed to read lastversion:", err);
|
||||||
|
return G_BUILD_VERSION;
|
||||||
|
})
|
||||||
|
.then(version => {
|
||||||
|
this.app.storage.writeFileAsync("lastversion.bin", version);
|
||||||
|
return version;
|
||||||
|
})
|
||||||
|
.then(version => {
|
||||||
|
let changelogEntries = [];
|
||||||
|
logger.log("Last seen version:", version);
|
||||||
|
|
||||||
|
for (let i = 0; i < CHANGELOG.length; ++i) {
|
||||||
|
if (CHANGELOG[i].version === version) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
changelogEntries.push(CHANGELOG[i]);
|
||||||
|
}
|
||||||
|
if (changelogEntries.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let dialogHtml = T.dialogs.updateSummary.desc;
|
||||||
|
for (let i = 0; i < changelogEntries.length; ++i) {
|
||||||
|
const entry = changelogEntries[i];
|
||||||
|
dialogHtml += `
|
||||||
|
<div class="changelogDialogEntry">
|
||||||
|
<span class="version">${entry.version}</span>
|
||||||
|
<span class="date">${entry.date}</span>
|
||||||
|
<ul class="changes">
|
||||||
|
${entry.entries.map(text => `<li>${text}</li>`).join("")}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise(resolve => {
|
||||||
|
this.dialogs.showInfo(T.dialogs.updateSummary.title, dialogHtml).ok.add(resolve);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
.then(() => this.setStatus("Launching"))
|
.then(() => this.setStatus("Launching"))
|
||||||
.then(
|
.then(
|
||||||
() => {
|
() => {
|
||||||
|
|
|
@ -111,10 +111,6 @@ export class SettingsState extends TextualGameState {
|
||||||
this.moveToStateAddGoBack("AboutState");
|
this.moveToStateAddGoBack("AboutState");
|
||||||
}
|
}
|
||||||
|
|
||||||
onChangelogClicked() {
|
|
||||||
// this.moveToStateAddGoBack("ChangelogState");
|
|
||||||
}
|
|
||||||
|
|
||||||
onKeybindingsClicked() {
|
onKeybindingsClicked() {
|
||||||
this.moveToStateAddGoBack("KeybindingsState");
|
this.moveToStateAddGoBack("KeybindingsState");
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,7 @@ demoBanners:
|
||||||
|
|
||||||
mainMenu:
|
mainMenu:
|
||||||
play: Play
|
play: Play
|
||||||
|
changelog: Changelog
|
||||||
importSavegame: Import
|
importSavegame: Import
|
||||||
openSourceHint: This game is open source!
|
openSourceHint: This game is open source!
|
||||||
discordLink: Official Discord Server
|
discordLink: Official Discord Server
|
||||||
|
@ -154,6 +155,16 @@ dialogs:
|
||||||
title: Limited savegames
|
title: Limited savegames
|
||||||
desc: You can only have one savegame at a time in the demo version. Please remove the existing one or get the standalone!
|
desc: You can only have one savegame at a time in the demo version. Please remove the existing one or get the standalone!
|
||||||
|
|
||||||
|
updateSummary:
|
||||||
|
title: New update!
|
||||||
|
desc: >-
|
||||||
|
Here are the changes since you last played:
|
||||||
|
|
||||||
|
hintDescription:
|
||||||
|
title: Tutorial
|
||||||
|
desc: >-
|
||||||
|
Whenever you need help or are stuck, check out the 'Show hint' button in the lower left and I'll give my best to help you!
|
||||||
|
|
||||||
ingame:
|
ingame:
|
||||||
# This is shown in the top left corner and displays useful keybindings in
|
# This is shown in the top left corner and displays useful keybindings in
|
||||||
# every situation
|
# every situation
|
||||||
|
@ -253,7 +264,7 @@ ingame:
|
||||||
|
|
||||||
# Bottom left tutorial hints
|
# Bottom left tutorial hints
|
||||||
tutorialHints:
|
tutorialHints:
|
||||||
title: No idea what to do?
|
title: Need help?
|
||||||
showHint: Show hint
|
showHint: Show hint
|
||||||
hideHint: Close
|
hideHint: Close
|
||||||
|
|
||||||
|
@ -483,6 +494,11 @@ settings:
|
||||||
description: >-
|
description: >-
|
||||||
If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently.
|
If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently.
|
||||||
|
|
||||||
|
offerHints:
|
||||||
|
title: Hints
|
||||||
|
description: >-
|
||||||
|
Whether to show the 'Show hints' button in the lower left.
|
||||||
|
|
||||||
keybindings:
|
keybindings:
|
||||||
title: Keybindings
|
title: Keybindings
|
||||||
hint: >-
|
hint: >-
|
||||||
|
@ -543,6 +559,9 @@ keybindings:
|
||||||
about:
|
about:
|
||||||
title: About this Game
|
title: About this Game
|
||||||
|
|
||||||
|
changelog:
|
||||||
|
title: Changelog
|
||||||
|
|
||||||
demo:
|
demo:
|
||||||
features:
|
features:
|
||||||
restoringGames: Restoring savegames
|
restoringGames: Restoring savegames
|
||||||
|
|
Reference in New Issue