mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-06-13 13:04:03 +00:00
Ingame achievement viewer
This commit is contained in:
parent
45cef34f02
commit
7499737605
@ -7,7 +7,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "cd gulp && yarn gulp main.serveDev",
|
"dev": "cd gulp && yarn gulp",
|
||||||
"devStandalone": "cd gulp && yarn gulp main.serveStandalone",
|
"devStandalone": "cd gulp && yarn gulp main.serveStandalone",
|
||||||
"tslint": "cd src/js && tsc",
|
"tslint": "cd src/js && tsc",
|
||||||
"lint": "eslint src/js",
|
"lint": "eslint src/js",
|
||||||
|
121
src/css/ingame_hud/achievements.scss
Normal file
121
src/css/ingame_hud/achievements.scss
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
#ingame_HUD_Achievements {
|
||||||
|
.content {
|
||||||
|
@include S(padding-right, 10px);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
@include S(width, 500px);
|
||||||
|
|
||||||
|
.achievement {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr auto;
|
||||||
|
background: #eee;
|
||||||
|
@include S(border-radius, $globalBorderRadius);
|
||||||
|
@include S(margin-bottom, 4px);
|
||||||
|
@include S(padding, 5px, 10px);
|
||||||
|
@include S(grid-row-gap, 1px);
|
||||||
|
@include S(height, 85px);
|
||||||
|
grid-template-rows: #{D(20px)} auto;
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include DarkThemeOverride {
|
||||||
|
background: $darkModeControlsBackground;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
@include S(width, 70px);
|
||||||
|
@include S(height, 70px);
|
||||||
|
background: center center / 80% no-repeat;
|
||||||
|
align-self: center;
|
||||||
|
justify-self: center;
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 1 / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
grid-column: 2;
|
||||||
|
grid-row: 2 / 3;
|
||||||
|
.title {
|
||||||
|
@include PlainText;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
justify-content: flex-end;
|
||||||
|
color: $colorGreenBright;
|
||||||
|
}
|
||||||
|
.description {
|
||||||
|
@include PlainText;
|
||||||
|
color: lighten($colorGreenBright, 20);
|
||||||
|
align-self: start;
|
||||||
|
justify-self: end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button.reset {
|
||||||
|
grid-column: 3;
|
||||||
|
grid-row: 2;
|
||||||
|
align-self: center;
|
||||||
|
justify-self: end;
|
||||||
|
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
transition-property: background-color, opacity;
|
||||||
|
|
||||||
|
background-color: $colorGreenBright;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: lighten($colorGreenBright, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.reset {
|
||||||
|
button.reset {
|
||||||
|
background-color: $colorRedBright;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: darken($colorRedBright, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
.title {
|
||||||
|
font-weight: bold;
|
||||||
|
color: $colorRedBright;
|
||||||
|
}
|
||||||
|
.description {
|
||||||
|
color: lighten($colorRedBright, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.unlocked) {
|
||||||
|
button.reset {
|
||||||
|
background-color: #aaa;
|
||||||
|
cursor: default;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
.info {
|
||||||
|
.title {
|
||||||
|
color: black;
|
||||||
|
@include DarkThemeOverride {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.description {
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,10 @@
|
|||||||
|
|
||||||
backdrop-filter: blur(D(1px));
|
backdrop-filter: blur(D(1px));
|
||||||
|
|
||||||
|
.stats ~ .achievements {
|
||||||
|
grid-column: 1;
|
||||||
|
}
|
||||||
|
|
||||||
> button,
|
> button,
|
||||||
> .button {
|
> .button {
|
||||||
@include PlainText;
|
@include PlainText;
|
||||||
@ -53,12 +57,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.achievements {
|
||||||
|
grid-column: 3;
|
||||||
|
& {
|
||||||
|
/* @load-async */
|
||||||
|
background-image: uiResource("icons/achievements.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.save {
|
&.save {
|
||||||
& {
|
& {
|
||||||
/* @load-async */
|
/* @load-async */
|
||||||
background-image: uiResource("icons/save.png");
|
background-image: uiResource("icons/save.png");
|
||||||
}
|
}
|
||||||
grid-column: 3;
|
grid-column: 4;
|
||||||
@include MakeAnimationWrappedEvenOdd(0.5s ease-in-out) {
|
@include MakeAnimationWrappedEvenOdd(0.5s ease-in-out) {
|
||||||
0% {
|
0% {
|
||||||
transform: scale(1, 1);
|
transform: scale(1, 1);
|
||||||
@ -92,7 +104,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.settings {
|
&.settings {
|
||||||
grid-column: 4;
|
grid-column: 5;
|
||||||
& {
|
& {
|
||||||
/* @load-async */
|
/* @load-async */
|
||||||
background-image: uiResource("icons/settings_menu_settings.png");
|
background-image: uiResource("icons/settings_menu_settings.png");
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
@import "states/puzzle_menu";
|
@import "states/puzzle_menu";
|
||||||
@import "states/mods";
|
@import "states/mods";
|
||||||
|
|
||||||
|
@import "ingame_hud/achievements.scss";
|
||||||
@import "ingame_hud/buildings_toolbar";
|
@import "ingame_hud/buildings_toolbar";
|
||||||
@import "ingame_hud/building_placer";
|
@import "ingame_hud/building_placer";
|
||||||
@import "ingame_hud/beta_overlay";
|
@import "ingame_hud/beta_overlay";
|
||||||
@ -109,6 +110,7 @@ ingame_HUD_SandboxController,
|
|||||||
ingame_HUD_BetaOverlay,
|
ingame_HUD_BetaOverlay,
|
||||||
|
|
||||||
// Dialogs
|
// Dialogs
|
||||||
|
ingame_HUD_Achievements,
|
||||||
ingame_HUD_Shop,
|
ingame_HUD_Shop,
|
||||||
ingame_HUD_Statistics,
|
ingame_HUD_Statistics,
|
||||||
ingame_HUD_ShapeViewer,
|
ingame_HUD_ShapeViewer,
|
||||||
|
@ -62,7 +62,7 @@ $buildingsAndVariants: belt, balancer, underground_belt, underground_belt-tier2,
|
|||||||
}
|
}
|
||||||
|
|
||||||
$icons: notification_saved, notification_success, notification_upgrade, notification_info,
|
$icons: notification_saved, notification_success, notification_upgrade, notification_info,
|
||||||
notification_warning, notification_error;
|
notification_warning, notification_error, notification_achievement;
|
||||||
@each $icon in $icons {
|
@each $icon in $icons {
|
||||||
[data-icon="icons/#{$icon}.png"] {
|
[data-icon="icons/#{$icon}.png"] {
|
||||||
/* @load-async */
|
/* @load-async */
|
||||||
@ -70,6 +70,20 @@ $icons: notification_saved, notification_success, notification_upgrade, notifica
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$achievements: reset, hidden, belt500Tiles, blueprint100k, blueprint1m, completeLvl26, cutShape, darkMode,
|
||||||
|
destroy1000, irrelevantShape, level100, level50, logoBefore18, mam, mapMarkers15, noBeltUpgradesUntilBp,
|
||||||
|
noInverseRotater, oldLevel17, openWires, paintShape, place5000Wires, placeBlueprint, placeBp1000, play1h,
|
||||||
|
play10h, play20h, produceLogo, produceMsLogo, produceRocket, rotateShape, speedrunBp30, speedrunBp60,
|
||||||
|
speedrunBp120, stack4Layers, stackShape, store100Unique, storeShape, throughputBp25, throughputBp50,
|
||||||
|
throughputLogo25, throughputLogo50, throughputRocket10, throughputRocket20, trash1000, unlockWires,
|
||||||
|
upgradesTier5, upgradesTier8;
|
||||||
|
@each $achievement in $achievements {
|
||||||
|
[data-icon="achievements/#{$achievement}.png"] {
|
||||||
|
/* @load-async */
|
||||||
|
background-image: uiResource("res/ui/achievements/#{$achievement}.png") !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$languages: en, de, cs, da, et, es-419, fr, it, pt-BR, sv, tr, el, ru, uk, zh-TW, zh-CN, nb, mt-MT, ar, nl, vi,
|
$languages: en, de, cs, da, et, es-419, fr, it, pt-BR, sv, tr, el, ru, uk, zh-TW, zh-CN, nb, mt-MT, ar, nl, vi,
|
||||||
th, hu, pl, ja, kor, no, pt-PT, fi, ro, he;
|
th, hu, pl, ja, kor, no, pt-PT, fi, ro, he;
|
||||||
|
|
||||||
|
214
src/js/game/hud/parts/achievements.js
Normal file
214
src/js/game/hud/parts/achievements.js
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
import { InputReceiver } from "../../../core/input_receiver";
|
||||||
|
import { makeDiv } from "../../../core/utils";
|
||||||
|
import { ACHIEVEMENTS, HIDDEN_ACHIEVEMENTS } from "../../../platform/achievement_provider";
|
||||||
|
import { T } from "../../../translations";
|
||||||
|
import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper";
|
||||||
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
|
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||||
|
|
||||||
|
export class HUDAchievements extends BaseHUDPart {
|
||||||
|
createElements(parent) {
|
||||||
|
this.background = makeDiv(parent, "ingame_HUD_Achievements", ["ingameDialog"]);
|
||||||
|
|
||||||
|
// DIALOG Inner / Wrapper
|
||||||
|
this.dialogInner = makeDiv(this.background, null, ["dialogInner"]);
|
||||||
|
this.title = makeDiv(this.dialogInner, null, ["title"], T.ingame.achievements.title);
|
||||||
|
this.closeButton = makeDiv(this.title, null, ["closeButton"]);
|
||||||
|
this.trackClicks(this.closeButton, this.close);
|
||||||
|
this.contentDiv = makeDiv(this.dialogInner, null, ["content"]);
|
||||||
|
|
||||||
|
this.resetElement = {};
|
||||||
|
|
||||||
|
// Wrapper
|
||||||
|
this.resetElement.elem = makeDiv(this.contentDiv, null, ["achievement", "reset", "unlocked"]);
|
||||||
|
|
||||||
|
// Icon
|
||||||
|
this.resetElement.icon = makeDiv(this.resetElement.elem, null, ["icon"]);
|
||||||
|
this.resetElement.icon.setAttribute("data-icon", "achievements/reset.png");
|
||||||
|
|
||||||
|
// Info
|
||||||
|
this.resetElement.info = makeDiv(this.resetElement.elem, null, ["info"]);
|
||||||
|
|
||||||
|
// Title
|
||||||
|
this.resetElement.title = makeDiv(
|
||||||
|
this.resetElement.info,
|
||||||
|
null,
|
||||||
|
["title"],
|
||||||
|
T.achievements.reset.title
|
||||||
|
);
|
||||||
|
|
||||||
|
// Description
|
||||||
|
this.resetElement.description = makeDiv(
|
||||||
|
this.resetElement.info,
|
||||||
|
null,
|
||||||
|
["description"],
|
||||||
|
T.achievements.reset.description
|
||||||
|
);
|
||||||
|
|
||||||
|
// Reset button
|
||||||
|
this.resetElement.resetButton = document.createElement("button");
|
||||||
|
this.resetElement.resetButton.classList.add("reset", "styledButton");
|
||||||
|
this.resetElement.resetButton.innerText = T.ingame.achievements.buttonReset;
|
||||||
|
this.resetElement.elem.appendChild(this.resetElement.resetButton);
|
||||||
|
this.trackClicks(this.resetElement.resetButton, () => {
|
||||||
|
const signals = this.root.hud.parts.dialogs.showWarning(
|
||||||
|
T.dialogs.resetAchievements.title,
|
||||||
|
T.dialogs.resetAchievements.description,
|
||||||
|
["cancel:bad:escape", "ok:good:enter"]
|
||||||
|
);
|
||||||
|
signals.ok.add(() => {
|
||||||
|
// TODO: Fix buttons
|
||||||
|
for (const achievementKey in ACHIEVEMENTS) {
|
||||||
|
if (!this.root.achievementProxy.provider.collection.map.has(achievementKey))
|
||||||
|
this.root.achievementProxy.provider.collection.lock(ACHIEVEMENTS[achievementKey]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.achievementToElements = {};
|
||||||
|
|
||||||
|
// ACHIEVEMENTS
|
||||||
|
for (const achievementKey in ACHIEVEMENTS) {
|
||||||
|
const handle = {};
|
||||||
|
|
||||||
|
// Wrapper
|
||||||
|
handle.elem = makeDiv(this.contentDiv, null, ["achievement"]);
|
||||||
|
|
||||||
|
// Icon
|
||||||
|
handle.icon = makeDiv(handle.elem, null, ["icon"]);
|
||||||
|
handle.icon.setAttribute("data-icon", "achievements/" + achievementKey + ".png");
|
||||||
|
|
||||||
|
// Info
|
||||||
|
handle.info = makeDiv(handle.elem, null, ["info"]);
|
||||||
|
|
||||||
|
// Title
|
||||||
|
const title = makeDiv(handle.info, null, ["title"], T.achievements[achievementKey].title);
|
||||||
|
|
||||||
|
// Description
|
||||||
|
handle.elemDescription = makeDiv(
|
||||||
|
handle.info,
|
||||||
|
null,
|
||||||
|
["description"],
|
||||||
|
T.achievements[achievementKey].description
|
||||||
|
);
|
||||||
|
|
||||||
|
// Reset button
|
||||||
|
handle.resetButton = document.createElement("button");
|
||||||
|
handle.resetButton.classList.add("reset", "styledButton");
|
||||||
|
handle.resetButton.innerText = T.ingame.achievements.buttonReset;
|
||||||
|
handle.elem.appendChild(handle.resetButton);
|
||||||
|
|
||||||
|
this.trackClicks(handle.resetButton, () => {
|
||||||
|
// TODO: Fix buttons
|
||||||
|
this.root.achievementProxy.provider.collection.lock(ACHIEVEMENTS[achievementKey]);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assign handle
|
||||||
|
this.achievementToElements[achievementKey] = handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hiddenElement = {};
|
||||||
|
// Wrapper
|
||||||
|
this.hiddenElement.hidden = makeDiv(this.contentDiv, null, ["achievement"]);
|
||||||
|
|
||||||
|
// Icon
|
||||||
|
this.hiddenElement.icon = makeDiv(this.hiddenElement.hidden, null, ["icon"]);
|
||||||
|
this.hiddenElement.icon.setAttribute("data-icon", "achievements/hidden.png");
|
||||||
|
|
||||||
|
// Info
|
||||||
|
this.hiddenElement.info = makeDiv(this.hiddenElement.hidden, null, ["info"]);
|
||||||
|
|
||||||
|
// Title
|
||||||
|
this.hiddenElement.title = makeDiv(
|
||||||
|
this.hiddenElement.info,
|
||||||
|
null,
|
||||||
|
["title"],
|
||||||
|
T.achievements.hidden.title
|
||||||
|
);
|
||||||
|
|
||||||
|
// Description
|
||||||
|
this.hiddenElement.description = makeDiv(
|
||||||
|
this.hiddenElement.info,
|
||||||
|
null,
|
||||||
|
["description"],
|
||||||
|
T.achievements.hidden.description.replace("<amountHidden>", HIDDEN_ACHIEVEMENTS.length + "")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderStatus() {
|
||||||
|
let unlocked = 0;
|
||||||
|
let hidden = 0;
|
||||||
|
for (const achievementKey in this.achievementToElements) {
|
||||||
|
const handle = this.achievementToElements[achievementKey];
|
||||||
|
|
||||||
|
//Check if user has achievement
|
||||||
|
if (!this.root.achievementProxy.provider.collection.map.get(ACHIEVEMENTS[achievementKey])) {
|
||||||
|
if (!handle.elem.classList.contains("unlocked")) handle.elem.classList.add("unlocked");
|
||||||
|
if (handle.elem.classList.contains("hidden")) handle.elem.classList.remove("hidden");
|
||||||
|
unlocked++;
|
||||||
|
} else {
|
||||||
|
if (handle.elem.classList.contains("unlocked")) handle.elem.classList.remove("unlocked");
|
||||||
|
|
||||||
|
if (HIDDEN_ACHIEVEMENTS.includes(ACHIEVEMENTS[achievementKey])) {
|
||||||
|
if (!handle.elem.classList.contains("hidden")) handle.elem.classList.add("hidden");
|
||||||
|
hidden++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hiddenElement.description.innerHTML = T.achievements.hidden.description.replace(
|
||||||
|
"<amountHidden>",
|
||||||
|
hidden + ""
|
||||||
|
);
|
||||||
|
|
||||||
|
if (unlocked > 0) {
|
||||||
|
if (!this.resetElement.elem.classList.contains("unlocked"))
|
||||||
|
this.resetElement.elem.classList.add("unlocked");
|
||||||
|
} else if (this.resetElement.elem.classList.contains("unlocked"))
|
||||||
|
this.resetElement.elem.classList.remove("unlocked");
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
this.domAttach = new DynamicDomAttach(this.root, this.background, {
|
||||||
|
attachClass: "visible",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.inputReciever = new InputReceiver("achievements");
|
||||||
|
this.keyActionMapper = new KeyActionMapper(this.root, this.inputReciever);
|
||||||
|
|
||||||
|
this.keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.close, this);
|
||||||
|
this.keyActionMapper.getBinding(KEYMAPPINGS.ingame.menuClose).add(this.close, this);
|
||||||
|
this.keyActionMapper.getBinding(KEYMAPPINGS.ingame.menuOpenAchievements).add(this.close, this);
|
||||||
|
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
// Cleanup detectors
|
||||||
|
for (const achievementKey in this.achievementToElements) {
|
||||||
|
const handle = this.achievementToElements[achievementKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
show() {
|
||||||
|
this.visible = true;
|
||||||
|
this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever);
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.visible = false;
|
||||||
|
this.root.app.inputMgr.makeSureDetached(this.inputReciever);
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
this.domAttach.update(this.visible);
|
||||||
|
if (this.visible) {
|
||||||
|
this.renderStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isBlockingOverlay() {
|
||||||
|
return this.visible;
|
||||||
|
}
|
||||||
|
}
|
@ -33,6 +33,12 @@ export class HUDGameMenu extends BaseHUDPart {
|
|||||||
visible: () =>
|
visible: () =>
|
||||||
!this.root.app.settings.getAllSettings().offerHints || this.root.hubGoals.level >= 3,
|
!this.root.app.settings.getAllSettings().offerHints || this.root.hubGoals.level >= 3,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "achievements",
|
||||||
|
label: "Achievements",
|
||||||
|
handler: () => this.root.hud.parts.achievements.show(),
|
||||||
|
keybinding: KEYMAPPINGS.ingame.menuOpenAchievements,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
/** @type {Array<{
|
/** @type {Array<{
|
||||||
|
@ -10,6 +10,7 @@ export const enumNotificationType = {
|
|||||||
info: "info",
|
info: "info",
|
||||||
warning: "warning",
|
warning: "warning",
|
||||||
error: "error",
|
error: "error",
|
||||||
|
achievement: "achievement",
|
||||||
};
|
};
|
||||||
|
|
||||||
const notificationDuration = 3;
|
const notificationDuration = 3;
|
||||||
@ -29,6 +30,10 @@ export class HUDNotifications extends BaseHUDPart {
|
|||||||
this.root.signals.gameSaved.add(() =>
|
this.root.signals.gameSaved.add(() =>
|
||||||
this.internalShowNotification(T.ingame.notifications.gameSaved, enumNotificationType.saved)
|
this.internalShowNotification(T.ingame.notifications.gameSaved, enumNotificationType.saved)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.root.signals.achievementCompleted.add(key =>
|
||||||
|
this.internalShowNotification(T.achievements[key].title, enumNotificationType.achievement)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,6 +60,7 @@ export const KEYMAPPINGS = {
|
|||||||
ingame: {
|
ingame: {
|
||||||
menuOpenShop: { keyCode: keyToKeyCode("F") },
|
menuOpenShop: { keyCode: keyToKeyCode("F") },
|
||||||
menuOpenStats: { keyCode: keyToKeyCode("G") },
|
menuOpenStats: { keyCode: keyToKeyCode("G") },
|
||||||
|
menuOpenAchievements: { keyCode: keyToKeyCode("H") },
|
||||||
menuClose: { keyCode: keyToKeyCode("Q") },
|
menuClose: { keyCode: keyToKeyCode("Q") },
|
||||||
|
|
||||||
toggleHud: { keyCode: KEYCODES.F2 },
|
toggleHud: { keyCode: KEYCODES.F2 },
|
||||||
|
@ -38,6 +38,7 @@ import { MetaItemProducerBuilding } from "../buildings/item_producer";
|
|||||||
import { MOD_SIGNALS } from "../../mods/mod_signals";
|
import { MOD_SIGNALS } from "../../mods/mod_signals";
|
||||||
import { finalGameShape, generateLevelsForVariant } from "./levels";
|
import { finalGameShape, generateLevelsForVariant } from "./levels";
|
||||||
import { WEB_STEAM_SSO_AUTHENTICATED } from "../../core/steam_sso";
|
import { WEB_STEAM_SSO_AUTHENTICATED } from "../../core/steam_sso";
|
||||||
|
import { HUDAchievements } from "../hud/parts/achievements";
|
||||||
|
|
||||||
/** @typedef {{
|
/** @typedef {{
|
||||||
* shape: string,
|
* shape: string,
|
||||||
@ -350,6 +351,7 @@ export class RegularGameMode extends GameMode {
|
|||||||
tutorialVideoOffer: HUDTutorialVideoOffer,
|
tutorialVideoOffer: HUDTutorialVideoOffer,
|
||||||
gameMenu: HUDGameMenu,
|
gameMenu: HUDGameMenu,
|
||||||
constantSignalEdit: HUDConstantSignalEdit,
|
constantSignalEdit: HUDConstantSignalEdit,
|
||||||
|
achievements: HUDAchievements,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!IS_MOBILE) {
|
if (!IS_MOBILE) {
|
||||||
|
@ -189,6 +189,7 @@ export class GameRoot {
|
|||||||
// Called with an achievement key and necessary args to validate it can be unlocked.
|
// Called with an achievement key and necessary args to validate it can be unlocked.
|
||||||
achievementCheck: /** @type {TypedSignal<[string, any]>} */ (new Signal()),
|
achievementCheck: /** @type {TypedSignal<[string, any]>} */ (new Signal()),
|
||||||
bulkAchievementCheck: /** @type {TypedSignal<(string|any)[]>} */ (new Signal()),
|
bulkAchievementCheck: /** @type {TypedSignal<(string|any)[]>} */ (new Signal()),
|
||||||
|
achievementCompleted: /** @type {TypedSignal<[string, any]>} */ (new Signal()),
|
||||||
|
|
||||||
// Puzzle mode
|
// Puzzle mode
|
||||||
puzzleComplete: /** @type {TypedSignal<[]>} */ (new Signal()),
|
puzzleComplete: /** @type {TypedSignal<[]>} */ (new Signal()),
|
||||||
|
@ -149,6 +149,13 @@ export class PreloadState extends GameState {
|
|||||||
return this.app.settings.initialize();
|
return this.app.settings.initialize();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
.then(() => this.setStatus("Initializing achievement storage"))
|
||||||
|
.then(() => {
|
||||||
|
if (this.app.achievementProvider.storage)
|
||||||
|
return this.app.achievementProvider.storage.initialize();
|
||||||
|
else return Promise.resolve();
|
||||||
|
})
|
||||||
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Initialize fullscreen
|
// Initialize fullscreen
|
||||||
if (this.app.platformWrapper.getSupportsFullscreen()) {
|
if (this.app.platformWrapper.getSupportsFullscreen()) {
|
||||||
|
Loading…
Reference in New Issue
Block a user