Allow to disable hints, add changelog

This commit is contained in:
tobspr 2020-05-23 15:04:55 +02:00
parent 5a46ba5e31
commit f03f04caa1
15 changed files with 218 additions and 14 deletions

View File

@ -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";

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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 {

View File

@ -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) {

23
src/js/changelog.js Normal file
View File

@ -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!"],
},
];

View File

@ -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,

View File

@ -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) {

View File

@ -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) {

View File

@ -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();
} }
} }

View File

@ -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 }
);
});
}
}

View File

@ -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) {

View File

@ -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(
() => { () => {

View File

@ -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");
} }

View File

@ -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