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/about";
@import "states/mobile_warning";
@import "states/changelog";
@import "ingame_hud/buildings_toolbar";
@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);
}
&.iogLink {
// background: transparenT;
&:not(.boxLink) {
align-self: flex-end;
justify-self: flex-end;
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 {
.logo {
img {

View File

@ -37,6 +37,7 @@ import { AboutState } from "./states/about";
import { PlatformWrapperImplElectron } from "./platform/electron/wrapper";
import { StorageImplElectron } from "./platform/electron/storage";
import { MobileWarningState } from "./states/mobile_warning";
import { ChangelogState } from "./states/changelog";
const logger = createLogger("application");
@ -165,6 +166,7 @@ export class Application {
SettingsState,
KeybindingsState,
AboutState,
ChangelogState,
];
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: {
/* dev:start */
fastGameEnter: true,
noArtificialDelays: true,
// fastGameEnter: true,
// noArtificialDelays: true,
// disableSavegameWrite: true,
// showEntityBounds: true,
// showAcceptorEjectors: true,

View File

@ -62,8 +62,6 @@ export class GameHUD {
notifications: new HUDNotifications(this.root),
settingsMenu: new HUDSettingsMenu(this.root),
tutorialHints: new HUDPartTutorialHints(this.root),
// betaOverlay: new HUDBetaOverlay(this.root),
debugInfo: new HUDDebugInfo(this.root),
@ -87,6 +85,9 @@ export class GameHUD {
if (IS_DEMO) {
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();
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.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) {

View File

@ -116,6 +116,7 @@ export const allApplicationSettings = [
}),
new BoolSetting("alwaysMultiplace", categoryGame, (app, value) => {}),
new BoolSetting("offerHints", categoryGame, (app, value) => {}),
];
export function getApplicationSettingById(id) {
@ -133,6 +134,7 @@ class SettingsStorage {
this.refreshRate = "60";
this.alwaysMultiplace = false;
this.offerHints = true;
/**
* @type {Object.<string, number>}
@ -291,9 +293,10 @@ export class ApplicationSettings extends ReadWriteProxy {
}
getCurrentVersion() {
return 6;
return 7;
}
/** @param {{settings: SettingsStorage, version: number}} data */
migrate(data) {
// Simply reset before
if (data.version < 5) {
@ -307,6 +310,11 @@ export class ApplicationSettings extends ReadWriteProxy {
data.version = 6;
}
if (data.version < 7) {
data.settings.offerHints = true;
data.version = 7;
}
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">
<a class="githubLink" target="_blank">
<a class="githubLink boxLink" target="_blank">
${T.mainMenu.openSourceHint}
<span class="thirdpartyLogo githubLogo"></span>
</a>
<a class="discordLink" target="_blank">
<a class="discordLink boxLink" target="_blank">
${T.mainMenu.discordLink}
<span class="thirdpartyLogo discordLogo"></span>
</a>
<a class="changelog">${T.changelog.title}</a>
${
G_IS_BROWSER &&
this.app.platformWrapper instanceof PlatformWrapperImplBrowser &&
@ -207,6 +209,7 @@ export class MainMenuState extends GameState {
}
this.trackClicks(qs(".settingsButton"), this.onSettingsButtonClicked);
this.trackClicks(qs(".changelog"), this.onChangelogClicked);
if (G_IS_STANDALONE) {
this.trackClicks(qs(".exitAppButton"), this.onExitAppButtonClicked);
@ -251,6 +254,10 @@ export class MainMenuState extends GameState {
this.app.platformWrapper.exitApp();
}
onChangelogClicked() {
this.moveToState("ChangelogState");
}
renderSavegames() {
const oldContainer = this.htmlElement.querySelector(".mainContainer .savegames");
if (oldContainer) {

View File

@ -5,6 +5,7 @@ import { cachebust } from "../core/cachebust";
import { PlatformWrapperImplBrowser } from "../platform/browser/wrapper";
import { T } from "../translations";
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
import { CHANGELOG } from "../changelog";
const logger = createLogger("state/preload");
@ -176,6 +177,52 @@ export class PreloadState extends GameState {
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(
() => {

View File

@ -111,10 +111,6 @@ export class SettingsState extends TextualGameState {
this.moveToStateAddGoBack("AboutState");
}
onChangelogClicked() {
// this.moveToStateAddGoBack("ChangelogState");
}
onKeybindingsClicked() {
this.moveToStateAddGoBack("KeybindingsState");
}

View File

@ -69,6 +69,7 @@ demoBanners:
mainMenu:
play: Play
changelog: Changelog
importSavegame: Import
openSourceHint: This game is open source!
discordLink: Official Discord Server
@ -154,6 +155,16 @@ dialogs:
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!
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:
# This is shown in the top left corner and displays useful keybindings in
# every situation
@ -253,7 +264,7 @@ ingame:
# Bottom left tutorial hints
tutorialHints:
title: No idea what to do?
title: Need help?
showHint: Show hint
hideHint: Close
@ -483,6 +494,11 @@ settings:
description: >-
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:
title: Keybindings
hint: >-
@ -543,6 +559,9 @@ keybindings:
about:
title: About this Game
changelog:
title: Changelog
demo:
features:
restoringGames: Restoring savegames