diff --git a/res/ui/achievements/reset.png b/res/ui/achievements/reset.png new file mode 100644 index 00000000..510875ef Binary files /dev/null and b/res/ui/achievements/reset.png differ diff --git a/src/css/ingame_hud/achievements.scss b/src/css/ingame_hud/achievements.scss index 5d2c6b99..3979d0a0 100644 --- a/src/css/ingame_hud/achievements.scss +++ b/src/css/ingame_hud/achievements.scss @@ -39,6 +39,9 @@ } .info { + display: flex; + flex-direction: column; + justify-content: center; grid-column: 2; grid-row: 2 / 3; .title { @@ -74,6 +77,26 @@ } } + &.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; diff --git a/src/css/resources.scss b/src/css/resources.scss index 37842c80..7a636a6e 100644 --- a/src/css/resources.scss +++ b/src/css/resources.scss @@ -66,7 +66,7 @@ $icons: notification_saved, notification_success, notification_upgrade, notifica } } -$achievements: hidden, belt500Tiles, blueprint100k, blueprint1m, completeLvl26, cutShape, darkMode, +$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, diff --git a/src/js/game/hud/parts/achievements.js b/src/js/game/hud/parts/achievements.js index 9d7506ee..91ed5b39 100644 --- a/src/js/game/hud/parts/achievements.js +++ b/src/js/game/hud/parts/achievements.js @@ -65,38 +65,95 @@ export class HUDAchievements extends BaseHUDPart { this.achievementToElements[achievementKey] = handle; } - const handle = {}; + this.hiddenElement = {}; // Wrapper - handle.hidden = makeDiv(this.contentDiv, null, ["achievement"]); + this.hiddenElement.hidden = makeDiv(this.contentDiv, null, ["achievement"]); // Icon - handle.icon = makeDiv(handle.hidden, null, ["icon"]); - handle.icon.setAttribute("data-icon", "achievements/hidden.png"); + this.hiddenElement.icon = makeDiv(this.hiddenElement.hidden, null, ["icon"]); + this.hiddenElement.icon.setAttribute("data-icon", "achievements/hidden.png"); // Info - handle.info = makeDiv(handle.hidden, null, ["info"]); + this.hiddenElement.info = makeDiv(this.hiddenElement.hidden, null, ["info"]); // Title - handle.title = makeDiv(handle.info, null, ["title"], T.achievements.hidden.title); + this.hiddenElement.title = makeDiv( + this.hiddenElement.info, + null, + ["title"], + T.achievements.hidden.title + ); // Description - handle.description = makeDiv( - handle.info, + this.hiddenElement.description = makeDiv( + this.hiddenElement.info, null, ["description"], T.achievements.hidden.description.replace("", HIDDEN_ACHIEVEMENTS.length + "") ); - this.hiddenElement = handle; + + 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(() => { + for (const achievementKey in ACHIEVEMENTS) { + if (!this.root.achievementProxy.provider.collection.map.has(achievementKey)) + this.root.achievementProxy.provider.collection.lock( + achievementKey, + enum_achievement_mappings[ACHIEVEMENTS[achievementKey]] + ); + } + }); + }); } 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"); @@ -111,6 +168,12 @@ export class HUDAchievements extends BaseHUDPart { "", 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() { diff --git a/src/js/platform/achievement_provider.js b/src/js/platform/achievement_provider.js index d9b7d67d..01151995 100644 --- a/src/js/platform/achievement_provider.js +++ b/src/js/platform/achievement_provider.js @@ -472,8 +472,8 @@ export class AchievementCollection { achievement .unlock() .then(() => { + if (this.map.has(key)) this.root.signals.achievementCompleted.dispatch(key, data); this.onActivate(null, key); - this.root.signals.achievementCompleted.dispatch(key, data); }) .catch(err => { this.onActivate(err, key); diff --git a/translations/base-en.yaml b/translations/base-en.yaml index 99508410..e3842cdb 100644 --- a/translations/base-en.yaml +++ b/translations/base-en.yaml @@ -253,6 +253,10 @@ dialogs: title: Tutorial Available desc: There is a tutorial video available for this level, but it is only available in English. Would you like to watch it? + resetAchievements: + title: Reset Achievements + description: Are you sure you want to reset all your achievements? + ingame: # This is shown in the top left corner and displays useful keybindings in # every situation @@ -499,6 +503,9 @@ shopUpgrades: # All achievements achievements: + reset: + title: Reset achievements + description: Resets all your achievements! hidden: title: Hidden achievements description: You have hidden achievement(s)