From b9d4dcd93f25c8f3cae3a91983ec7b03faa68a31 Mon Sep 17 00:00:00 2001 From: "Z. Cliffe Schreuders" Date: Fri, 8 Aug 2025 16:54:46 +0100 Subject: [PATCH] Enhance locksmith-forge gameplay: Add progress tracking and achievement notifications in the locksmith-forge.html file, including localStorage integration for saving progress. Update styles for the progress bar and achievement messages. Refactor ProgressiveLockpicking class to improve level management and user feedback. Adjust text positioning in lockpicking-game-phaser.js for better visibility of game elements. --- .../lockpicking/lockpicking-game-phaser.js | 6 +- locksmith-forge.html | 165 +++++++++++++++--- 2 files changed, 140 insertions(+), 31 deletions(-) diff --git a/js/minigames/lockpicking/lockpicking-game-phaser.js b/js/minigames/lockpicking/lockpicking-game-phaser.js index d68b16b..1f4b665 100644 --- a/js/minigames/lockpicking/lockpicking-game-phaser.js +++ b/js/minigames/lockpicking/lockpicking-game-phaser.js @@ -261,7 +261,7 @@ export class LockpickingMinigamePhaser extends MinigameScene { this.tensionWrench.setInteractive(new Phaser.Geom.Rectangle(-12.5, -138.75, 60, 176.25), Phaser.Geom.Rectangle.Contains); // Add text - const wrenchText = this.scene.add.text(-10, 50, 'Tension Wrench', { + const wrenchText = this.scene.add.text(-10, 58, 'Tension Wrench', { fontSize: '14px', fill: '#00ff00', fontWeight: 'bold' @@ -471,7 +471,7 @@ export class LockpickingMinigamePhaser extends MinigameScene { this.hookGroup.add(hookPickGraphics); // Add hook pick label - const hookPickLabel = this.scene.add.text(-10, 80, 'Hook Pick', { + const hookPickLabel = this.scene.add.text(-10, 85, 'Hook Pick', { fontSize: '14px', fill: '#00ff00', fontWeight: 'bold' @@ -892,7 +892,7 @@ export class LockpickingMinigamePhaser extends MinigameScene { springLabel.setDepth(100); // Bring to front // Driver pin label - positioned below the shear line - const driverPinLabel = this.scene.add.text(pinX, pinY - 30, 'Driver Pin', { + const driverPinLabel = this.scene.add.text(pinX, pinY - 35, 'Driver Pin', { fontSize: '14px', fill: '#00ff00', fontWeight: 'bold' diff --git a/locksmith-forge.html b/locksmith-forge.html index 3e9e5bc..81f1b69 100644 --- a/locksmith-forge.html +++ b/locksmith-forge.html @@ -38,7 +38,7 @@ min-height: 100vh; } - .minigame-close-button, #minigame-cancel { + .minigame-close-button, #minigame-cancel, .minigame-header { display: none; } @@ -220,6 +220,22 @@ from { box-shadow: 0 0 5px #ffaa00; } to { box-shadow: 0 0 20px #ffaa00, 0 0 30px #ffaa00; } } + + .progress-achievement { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: white; + font-size: 16px; + font-weight: bold; + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 90%; + z-index: 10; + } @@ -270,14 +286,13 @@
- +
- -
Ready to start Level 1
- +
+
@@ -288,18 +303,54 @@ class ProgressiveLockpicking { constructor() { - this.currentLevel = 1; this.maxLevel = 50; - this.successCount = 0; - this.failureCount = 0; - this.currentGame = null; this.levelConfig = this.generateLevelConfig(); + // Load saved progress from localStorage + this.loadProgress(); + + this.currentGame = null; + this.initializeUI(); this.bindEvents(); this.updateDisplay(); } + loadProgress() { + try { + const savedProgress = localStorage.getItem('lockpickingProgress'); + if (savedProgress) { + const progress = JSON.parse(savedProgress); + this.currentLevel = Math.max(1, Math.min(this.maxLevel, progress.currentLevel || 1)); + this.successCount = progress.successCount || 0; + this.failureCount = progress.failureCount || 0; + } else { + this.currentLevel = 1; + this.successCount = 0; + this.failureCount = 0; + } + } catch (error) { + console.warn('Failed to load progress from localStorage:', error); + this.currentLevel = 1; + this.successCount = 0; + this.failureCount = 0; + } + } + + saveProgress() { + try { + const progress = { + currentLevel: this.currentLevel, + successCount: this.successCount, + failureCount: this.failureCount, + lastSaved: new Date().toISOString() + }; + localStorage.setItem('lockpickingProgress', JSON.stringify(progress)); + } catch (error) { + console.warn('Failed to save progress to localStorage:', error); + } + } + generateLevelConfig() { const config = {}; @@ -308,7 +359,7 @@ let pinCount = Math.min(3 + Math.floor((level - 1) / 5), 8); // 3-8 pins let difficulty = this.getDifficulty(level); let sensitivity = Math.max(1, Math.min(10, 5 + Math.floor((level - 1) / 3))); // 1-10 - let liftSpeed = Math.max(0.5, Math.min(3.0, 1.0 + (level - 1) * 0.1)); // 0.5-3.0 + let liftSpeed = Math.max(0.5, Math.min(3.0, 0.8 + (level - 1) * 0.04)); // 0.5-3.0 (starts slower, progresses slower) // Add some randomness and complexity if (level > 10) { @@ -321,7 +372,7 @@ if (level > 20) { // Increase difficulty more aggressively - liftSpeed = Math.min(3.0, liftSpeed + 0.2); + liftSpeed = Math.min(3.0, liftSpeed + 0.1); } if (level > 30) { @@ -379,9 +430,7 @@ this.resetLevel(); }); - document.getElementById('skipButton').addEventListener('click', () => { - this.skipLevel(); - }); + } updateRangeValue(id) { @@ -458,15 +507,62 @@ handleChallengeComplete(success) { if (success) { this.successCount++; - this.updateStatus(`Level ${this.currentLevel} completed successfully!`); - this.showAchievement(`Level ${this.currentLevel} Complete!`); + this.saveProgress(); + + // Check if this was the final level + if (this.currentLevel === this.maxLevel) { + this.updateStatus(`🎊 INCREDIBLE! You've completed ALL ${this.maxLevel} levels! You are a TRUE MASTER LOCKPICKER! 🎊`); + this.showAchievement(`👑 LEGENDARY LOCKPICKER - ALL LEVELS COMPLETE! 👑`); + } else { + // Check for milestone levels + const milestoneMessages = { + 1: { + status: `🎯 Great start! Level 1 complete! You're on your way to becoming a lockpicking master! 🎯`, + achievement: `🌟 First Steps - Level 1 Complete! 🌟` + }, + 10: { + status: `🔥 Excellent progress! Level 10 conquered! You're getting the hang of this! 🔥`, + achievement: `⚡ Rising Star - Level 10 Complete! ⚡` + }, + 20: { + status: `💪 Impressive! Level 20 mastered! Your skills are really developing! 💪`, + achievement: `🏅 Skillful Picker - Level 20 Complete! 🏅` + }, + 30: { + status: `🚀 Outstanding! Level 30 achieved! You're becoming a true expert! 🚀`, + achievement: `🎖️ Expert Level - Level 30 Complete! 🎖️` + }, + 40: { + status: `⚔️ Phenomenal! Level 40 conquered! You're almost at the ultimate challenge! ⚔️`, + achievement: `🏆 Elite Picker - Level 40 Complete! 🏆` + } + }; + + const milestone = milestoneMessages[this.currentLevel]; + if (milestone) { + this.updateStatus(milestone.status); + this.showAchievement(milestone.achievement); + } else { + this.updateStatus(`Level ${this.currentLevel} completed successfully!`); + this.showAchievement(`Level ${this.currentLevel} Complete!`); + } + } // Progress to next level after a delay setTimeout(() => { - this.currentLevel = Math.min(this.currentLevel + 1, this.maxLevel); + const nextLevel = Math.min(this.currentLevel + 1, this.maxLevel); + this.currentLevel = nextLevel; + this.saveProgress(); this.updateDisplay(); this.updateControlsFromLevel(); - this.updateStatus(`Starting Level ${this.currentLevel}...`); + + // Check if player has reached the final level + if (this.currentLevel === this.maxLevel) { + this.updateStatus(`🎉 CONGRATULATIONS! You've reached the ultimate challenge - Level ${this.currentLevel}! 🎉`); + this.showAchievement(`🏆 MASTER LOCKPICKER - Level ${this.currentLevel} Unlocked! 🏆`); + } else { + this.updateStatus(`Starting Level ${this.currentLevel}...`); + } // Auto-start the next level setTimeout(() => { @@ -475,6 +571,7 @@ }, 2000); } else { this.failureCount++; + this.saveProgress(); this.updateStatus(`Level ${this.currentLevel} failed. Retrying...`); // Auto-retry after a delay @@ -490,6 +587,7 @@ this.currentLevel = 1; this.successCount = 0; this.failureCount = 0; + this.saveProgress(); this.updateDisplay(); this.updateControlsFromLevel(); this.updateStatus(`Progress reset. Ready for Level ${this.currentLevel}`); @@ -501,13 +599,7 @@ }, 500); } - skipLevel() { - this.currentLevel = Math.min(this.currentLevel + 1, this.maxLevel); - this.updateDisplay(); - this.updateControlsFromLevel(); - this.updateStatus(`Skipped to Level ${this.currentLevel}`); - this.updateProgress(); - } + updateDisplay() { document.getElementById('currentLevel').textContent = this.currentLevel; @@ -519,10 +611,16 @@ document.getElementById('sensitivity').textContent = config.sensitivity; document.getElementById('liftSpeed').textContent = config.liftSpeed; } + + // Update progress bar to reflect current level + this.updateProgress(); } updateStatus(message) { - document.getElementById('status').textContent = message; + const feedbackElement = document.querySelector('.lockpick-feedback'); + if (feedbackElement) { + feedbackElement.textContent = message; + } } updateProgress() { @@ -538,7 +636,18 @@ achievements.appendChild(achievement); - // Remove after 5 seconds + // Display achievement message in progress bar + const progressAchievement = document.getElementById('progressAchievement'); + if (progressAchievement) { + progressAchievement.textContent = message; + + // Clear the progress bar message after 5 seconds + setTimeout(() => { + progressAchievement.textContent = ''; + }, 5000); + } + + // Remove achievement popup after 5 seconds setTimeout(() => { if (achievement.parentNode) { achievement.parentNode.removeChild(achievement); @@ -550,7 +659,7 @@ // Initialize the progressive lockpicking system document.addEventListener('DOMContentLoaded', () => { const progressiveSystem = new ProgressiveLockpicking(); - // Auto-start the first level + // Auto-start the current level (could be loaded from saved progress) setTimeout(() => { progressiveSystem.startChallenge(); }, 500);