1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-06-13 13:04:03 +00:00

Achievements accessable in main menu

This commit is contained in:
DJ1TJOO 2021-03-13 16:13:42 +01:00
parent 9ef35a2b1c
commit db8cd2cd77
8 changed files with 249 additions and 0 deletions

View File

@ -119,3 +119,19 @@
}
}
}
#state_AchievementsState {
#ingame_HUD_Achievements {
z-index: unset;
overflow-y: scroll;
position: relative;
background-color: unset;
max-height: 100%;
align-items: unset;
.content {
width: 100%;
display: block;
}
}
}

View File

@ -15,6 +15,7 @@
grid-auto-flow: column;
@include S(grid-gap, 15px);
.achievementsButton,
.settingsButton,
.exitAppButton,
.languageChoose {
@ -34,6 +35,11 @@
}
}
.achievementsButton {
/* @load-async */
background-image: uiResource("icons/achievements.png");
}
.exitAppButton {
/* @load-async */
background-image: uiResource("icons/main_menu_exit.png");

View File

@ -31,6 +31,7 @@ import { PreloadState } from "./states/preload";
import { SettingsState } from "./states/settings";
import { ShapezGameAnalytics } from "./platform/browser/game_analytics";
import { RestrictionManager } from "./core/restriction_manager";
import { AchievementsState } from "./states/achievements";
/**
* @typedef {import("./platform/achievement_provider").AchievementProviderInterface} AchievementProviderInterface
@ -159,6 +160,7 @@ export class Application {
KeybindingsState,
AboutState,
ChangelogState,
AchievementsState,
];
for (let i = 0; i < states.length; ++i) {

View File

@ -318,6 +318,15 @@ export class AchievementProviderInterface {
return Promise.reject();
}
/**
* Unlocks already unlocked achievements.
* @returns {Promise<void>}
*/
unlockUnlocked() {
abstract;
return Promise.reject();
}
/**
* Opportunity to do additional initialization work with the GameRoot.
* @param {GameRoot} root

View File

@ -115,6 +115,20 @@ export class BrowserAchievementProvider extends AchievementProviderInterface {
}
}
unlockUnlocked() {
let promise = Promise.resolve();
//Unlock already unlocked
for (let i = 0; i < this.storage.currentData.unlocked.length; i++) {
promise.then(() => {
const achievement = this.storage.currentData.unlocked[i];
this.collection.unlock(achievement, null, true);
});
}
return promise;
}
/** @returns {Promise<void>} */
initialize() {
return Promise.resolve();

View File

@ -132,6 +132,22 @@ export class SteamAchievementProvider extends AchievementProviderInterface {
});
}
unlockUnlocked() {
let promise = Promise.resolve();
//Unlock already unlocked
for (const id in ACHIEVEMENT_IDS) {
promise.then(() =>
this.ipc.invoke("steam:get-achievement", ACHIEVEMENT_IDS[id]).then(is_achieved => {
if (is_achieved) this.collection.unlock(id, null, true);
return Promise.resolve();
})
);
}
return promise;
}
/**
* @param {string} key
* @returns {Promise<void>}

View File

@ -0,0 +1,180 @@
import { TextualGameState } from "../core/textual_game_state";
import { makeDiv } from "../core/utils";
import {
ACHIEVEMENTS,
enum_achievement_mappings,
HIDDEN_ACHIEVEMENTS,
} from "../platform/achievement_provider";
import { T } from "../translations";
export class AchievementsState extends TextualGameState {
constructor() {
super("AchievementsState");
}
getStateHeaderTitle() {
return T.ingame.achievements.title;
}
onEnter(payload) {
this.app.achievementProvider.unlockUnlocked();
this.parent = makeDiv(document.querySelector(".content.mainContent"), "ingame_HUD_Achievements", [
"ingameDialog",
]);
this.contentDiv = makeDiv(this.parent, null, ["content"]);
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, () => {
this.app.achievementProvider.collection.lock(
achievementKey,
enum_achievement_mappings[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 + "")
);
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.dialogs.showWarning(
T.dialogs.resetAchievements.title,
T.dialogs.resetAchievements.description,
["cancel:bad:escape", "ok:good:enter"]
);
signals.ok.add(() => {
for (const achievementKey in ACHIEVEMENTS) {
if (!this.app.achievementProvider.collection.map.has(achievementKey))
this.app.achievementProvider.collection.lock(
achievementKey,
enum_achievement_mappings[ACHIEVEMENTS[achievementKey]]
);
}
});
});
}
onRender(dt) {
let unlocked = 0;
let hidden = 0;
for (const achievementKey in this.achievementToElements) {
const handle = this.achievementToElements[achievementKey];
//Check if user has achievement
if (!this.app.achievementProvider.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");
}
}

View File

@ -48,6 +48,7 @@ export class MainMenuState extends GameState {
: `<button class="languageChoose" data-languageicon="${this.app.settings.getLanguage()}"></button>`
}
<button class="achievementsButton"></button>
<button class="settingsButton"></button>
${
G_IS_STANDALONE || G_IS_DEV
@ -232,6 +233,7 @@ export class MainMenuState extends GameState {
});
this.trackClicks(qs(".settingsButton"), this.onSettingsButtonClicked);
this.trackClicks(qs(".achievementsButton"), this.onAchievementsButtonClicked);
if (!G_CHINA_VERSION) {
this.trackClicks(qs(".languageChoose"), this.onLanguageChooseClicked);
@ -569,6 +571,10 @@ export class MainMenuState extends GameState {
this.moveToState("SettingsState");
}
onAchievementsButtonClicked() {
this.moveToState("AchievementsState");
}
onTranslationHelpLinkClicked() {
this.app.analytics.trackUiClick("translation_help_link");
this.app.platformWrapper.openExternalLink(