diff --git a/app/controllers/break_escape/static_files_controller.rb b/app/controllers/break_escape/static_files_controller.rb new file mode 100644 index 0000000..f076c69 --- /dev/null +++ b/app/controllers/break_escape/static_files_controller.rb @@ -0,0 +1,88 @@ +module BreakEscape + class StaticFilesController < BreakEscape::ApplicationController + skip_before_action :verify_authenticity_token + + def serve + # Use the BreakEscape engine's root, not Rails.root + engine_root = BreakEscape::Engine.root + + # Determine the actual file path based on the request URL + request_path = request.path + + # Map different URL patterns to their file locations + # Remember: request_path will be /break_escape/css/... when mounted at /break_escape + file_path = case request_path + when %r{^/break_escape/css/} + engine_root.join('public', 'break_escape', 'css', params[:path]) + when %r{^/break_escape/js/} + engine_root.join('public', 'break_escape', 'js', params[:path]) + when %r{^/break_escape/assets/} + engine_root.join('public', 'break_escape', 'assets', params[:path]) + when %r{^/break_escape/stylesheets/} + engine_root.join('public', 'break_escape', 'css', params[:path]) + else + # Fallback for any other pattern + engine_root.join('public', 'break_escape', params[:path]) + end + + # Security: prevent directory traversal + base_path = engine_root.join('public', 'break_escape').to_s + unless file_path.to_s.start_with?(base_path) + return render_not_found + end + + unless File.file?(file_path) + return render_not_found + end + + # Determine content type + content_type = determine_content_type(file_path.to_s) + + send_file file_path, type: content_type, disposition: 'inline' + rescue Errno::ENOENT + render_not_found + end + + private + + def determine_content_type(file_path) + case File.extname(file_path).downcase + when '.css' + 'text/css' + when '.js' + 'application/javascript' + when '.json' + 'application/json' + when '.png' + 'image/png' + when '.jpg', '.jpeg' + 'image/jpeg' + when '.gif' + 'image/gif' + when '.svg' + 'image/svg+xml' + when '.woff' + 'font/woff' + when '.woff2' + 'font/woff2' + when '.ttf' + 'font/ttf' + when '.eot' + 'application/vnd.ms-fontobject' + when '.mp3' + 'audio/mpeg' + when '.wav' + 'audio/wav' + when '.ogg' + 'audio/ogg' + else + 'application/octet-stream' + end + end + + def render_not_found + render plain: 'Not Found', status: :not_found + end + end +end + diff --git a/app/views/break_escape/games/show.html.erb b/app/views/break_escape/games/show.html.erb index cadd229..ed39263 100644 --- a/app/views/break_escape/games/show.html.erb +++ b/app/views/break_escape/games/show.html.erb @@ -5,18 +5,110 @@ <%= csrf_meta_tags %> <%= csp_meta_tag %> - <%# Load game CSS %> + + + + <%# Google Fonts - Press Start 2P, VT323, Pixelify Sans %> + + + + + + + <%# Web Font Loader script to ensure fonts load properly %> + + + + <%# Load game CSS files %> + + + + + + + + + + + + + + + + + + + + + + <%# Game container - Phaser will render here %> -
+
<%# Loading indicator %>
Loading game...
+ <%# Notification System %> +
+ + <%# Toggle Buttons Container %> +
+ +
+ + <%# Inventory Container %> +
+ + <%# Laptop Popup %> +
+
+
+
+ Crypto Workstation + +
+
+ +
+
+
+
+ + <%# Password Modal %> +
+
+
+ Enter Password +
+ +
+ + +
+
+ + +
+
+
+ + <%# Popup Overlay %> + + <%# Bootstrap configuration for client %> + <%# Load required libraries before the game module %> + + + + <%# Load game JavaScript (ES6 module) %> diff --git a/app/views/layouts/break_escape/application.html.erb b/app/views/layouts/break_escape/application.html.erb index 026d598..822d0b5 100644 --- a/app/views/layouts/break_escape/application.html.erb +++ b/app/views/layouts/break_escape/application.html.erb @@ -6,8 +6,6 @@ <%= csp_meta_tag %> <%= yield :head %> - - <%= stylesheet_link_tag "break_escape/application", media: "all" %> diff --git a/config/routes.rb b/config/routes.rb index e99c303..143ab4e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,11 @@ BreakEscape::Engine.routes.draw do + # Static files - match only static file paths (must come BEFORE resource routes) + # Note: These routes are automatically prefixed with /break_escape by the mount in the parent app + get '/css/*path', to: 'static_files#serve', constraints: { path: /.*/ } + get '/js/*path', to: 'static_files#serve', constraints: { path: /.*/ } + get '/assets/*path', to: 'static_files#serve', constraints: { path: /.*/ } + get '/stylesheets/*path', to: 'static_files#serve', constraints: { path: /.*/ } + # Mission selection resources :missions, only: [:index, :show] diff --git a/public/break_escape/css/hud.css b/public/break_escape/css/hud.css index 40f9912..6778707 100644 --- a/public/break_escape/css/hud.css +++ b/public/break_escape/css/hud.css @@ -42,14 +42,16 @@ #inventory-container { position: fixed; bottom: 0; - left: 50%; - transform: translateX(-50%); + left: 50%; + transform: translateX(-50%); height: 80px; display: flex; align-items: center; padding: 0 20px; z-index: 1000; font-family: 'VT323'; + overflow-x: auto; + overflow-y: hidden; } #inventory-container::-webkit-scrollbar { @@ -74,7 +76,7 @@ justify-content: center; align-items: center; position: relative; - background: rgb(149 157 216 / 80%); + background: transparent; /* keep slot outlines but no filled background per user request */ } /* Pulse animation for newly added items */ diff --git a/public/break_escape/css/main.css b/public/break_escape/css/main.css index 0896212..3fa1630 100644 --- a/public/break_escape/css/main.css +++ b/public/break_escape/css/main.css @@ -2,12 +2,10 @@ body { margin: 0; padding: 0; - display: flex; - justify-content: center; - align-items: center; - min-height: 100vh; + display: block; background: #333; font-smooth: never; + overflow: hidden; } #game-container { diff --git a/public/break_escape/css/minigames-framework.css b/public/break_escape/css/minigames-framework.css index 52c01fd..00d9b11 100644 --- a/public/break_escape/css/minigames-framework.css +++ b/public/break_escape/css/minigames-framework.css @@ -7,7 +7,8 @@ width: 100vw; height: 100vh; background: rgba(0, 0, 0, 0.95); - z-index: 2000; + /* Raised so minigames appear above other UI (inventory, NPC barks, HUD, etc.) */ + z-index: 11000; display: flex; flex-direction: column; justify-content: center; diff --git a/public/break_escape/js/core/game.js b/public/break_escape/js/core/game.js index f81cc3d..8cd3b2c 100644 --- a/public/break_escape/js/core/game.js +++ b/public/break_escape/js/core/game.js @@ -439,25 +439,33 @@ export function preload() { window.soundManagerPreload = new SoundManager(this); window.soundManagerPreload.preloadSounds(); - // Get scenario from URL parameter or use default - const urlParams = new URLSearchParams(window.location.search); - let scenarioFile = urlParams.get('scenario') || 'scenarios/ceo_exfil.json'; - - // Ensure scenario file has proper path prefix - if (!scenarioFile.startsWith('scenarios/')) { - scenarioFile = `scenarios/${scenarioFile}`; + // Load scenario from Rails API endpoint if available, otherwise try URL parameter + if (window.breakEscapeConfig?.apiBasePath) { + // Load scenario from Rails API endpoint + // Use absolute URL with origin to prevent Phaser baseURL from interfering + const scenarioUrl = `${window.location.origin}${window.breakEscapeConfig.apiBasePath}/scenario`; + this.load.json('gameScenarioJSON', scenarioUrl); + } else { + // Fallback to old behavior for standalone HTML files + const urlParams = new URLSearchParams(window.location.search); + let scenarioFile = urlParams.get('scenario') || 'scenarios/ceo_exfil.json'; + + // Ensure scenario file has proper path prefix + if (!scenarioFile.startsWith('scenarios/')) { + scenarioFile = `scenarios/${scenarioFile}`; + } + + // Ensure .json extension + if (!scenarioFile.endsWith('.json')) { + scenarioFile = `${scenarioFile}.json`; + } + + // Add cache buster query parameter to prevent browser caching + scenarioFile = `${scenarioFile}${scenarioFile.includes('?') ? '&' : '?'}v=${Date.now()}`; + + // Load the specified scenario + this.load.json('gameScenarioJSON', scenarioFile); } - - // Ensure .json extension - if (!scenarioFile.endsWith('.json')) { - scenarioFile = `${scenarioFile}.json`; - } - - // Add cache buster query parameter to prevent browser caching - scenarioFile = `${scenarioFile}${scenarioFile.includes('?') ? '&' : '?'}v=${Date.now()}`; - - // Load the specified scenario - this.load.json('gameScenarioJSON', scenarioFile); } diff --git a/public/break_escape/js/minigames/biometrics/biometrics-minigame.js b/public/break_escape/js/minigames/biometrics/biometrics-minigame.js index 1cda404..5f8f767 100644 --- a/public/break_escape/js/minigames/biometrics/biometrics-minigame.js +++ b/public/break_escape/js/minigames/biometrics/biometrics-minigame.js @@ -66,7 +66,7 @@ export class BiometricsMinigame extends MinigameScene { scannerHeader.className = 'biometrics-scanner-header'; scannerHeader.innerHTML = `
- Biometric Samples + Biometric Samples Biometric Samples 0 samples
@@ -81,7 +81,7 @@ export class BiometricsMinigame extends MinigameScene { searchRoomContainer.className = 'biometrics-search-room-container'; searchRoomContainer.innerHTML = ` `; diff --git a/public/break_escape/js/minigames/bluetooth/bluetooth-scanner-minigame.js b/public/break_escape/js/minigames/bluetooth/bluetooth-scanner-minigame.js index 8d944c3..72576eb 100644 --- a/public/break_escape/js/minigames/bluetooth/bluetooth-scanner-minigame.js +++ b/public/break_escape/js/minigames/bluetooth/bluetooth-scanner-minigame.js @@ -63,7 +63,7 @@ export class BluetoothScannerMinigame extends MinigameScene { scannerHeader.className = 'bluetooth-scanner-header'; scannerHeader.innerHTML = `
- Bluetooth Scanner + Bluetooth Scanner Bluetooth Scanner
@@ -490,15 +490,15 @@ export class BluetoothScannerMinigame extends MinigameScene { deviceContent += `
`; } else if (device.nearby) { // Fallback if signal strength not available - deviceContent += `Signal`; + deviceContent += `Signal`; } if (device.saved) { - deviceContent += `Disk`; + deviceContent += `Disk`; } if (device.inInventory) { - deviceContent += `Backpack`; + deviceContent += `Backpack`; } deviceContent += ``; diff --git a/public/break_escape/js/minigames/container/container-minigame.js b/public/break_escape/js/minigames/container/container-minigame.js index 24c84e6..6a24e27 100644 --- a/public/break_escape/js/minigames/container/container-minigame.js +++ b/public/break_escape/js/minigames/container/container-minigame.js @@ -54,7 +54,7 @@ export class ContainerMinigame extends MinigameScene { const notebookBtn = document.createElement('button'); notebookBtn.className = 'minigame-button'; notebookBtn.id = 'minigame-notebook-postit'; - notebookBtn.innerHTML = 'Notepad Add to Notepad'; + notebookBtn.innerHTML = 'Notepad Add to Notepad'; // Insert before the cancel button (first child in controls) this.controlsElement.insertBefore(notebookBtn, this.controlsElement.firstChild); } @@ -104,7 +104,7 @@ export class ContainerMinigame extends MinigameScene { this.gameContainer.innerHTML = `
- ${this.containerItem.scenarioData.name}
@@ -130,7 +130,7 @@ export class ContainerMinigame extends MinigameScene { createDesktopUI() { this.gameContainer.innerHTML = `
- ${this.containerItem.scenarioData.name}
@@ -184,7 +184,7 @@ export class ContainerMinigame extends MinigameScene { const itemImg = document.createElement('img'); itemImg.className = 'container-content-item'; - itemImg.src = `assets/objects/${item.type}.png`; + itemImg.src = `/break_escape/assets/objects/${item.type}.png`; itemImg.alt = item.name; itemImg.title = item.name; @@ -230,7 +230,7 @@ export class ContainerMinigame extends MinigameScene { const iconImg = document.createElement('img'); iconImg.className = 'desktop-icon-image'; - iconImg.src = `assets/objects/${item.type}.png`; + iconImg.src = `/break_escape/assets/objects/${item.type}.png`; iconImg.alt = item.name; const iconLabel = document.createElement('div'); diff --git a/public/break_escape/js/minigames/dusting/dusting-game.js b/public/break_escape/js/minigames/dusting/dusting-game.js index bbd1727..375a839 100644 --- a/public/break_escape/js/minigames/dusting/dusting-game.js +++ b/public/break_escape/js/minigames/dusting/dusting-game.js @@ -3,7 +3,7 @@ import { MinigameScene } from '../framework/base-minigame.js'; // Load dusting-specific CSS const dustingCSS = document.createElement('link'); dustingCSS.rel = 'stylesheet'; -dustingCSS.href = 'css/dusting.css'; +dustingCSS.href = '/break_escape/css/dusting.css'; dustingCSS.id = 'dusting-css'; if (!document.getElementById('dusting-css')) { document.head.appendChild(dustingCSS); diff --git a/public/break_escape/js/minigames/framework/minigame-manager.js b/public/break_escape/js/minigames/framework/minigame-manager.js index 0bf4280..01b68d4 100644 --- a/public/break_escape/js/minigames/framework/minigame-manager.js +++ b/public/break_escape/js/minigames/framework/minigame-manager.js @@ -85,6 +85,12 @@ export const MinigameFramework = { document.body.appendChild(container); } + // Show the popup overlay to darken the background + const popupOverlay = document.querySelector('.popup-overlay'); + if (popupOverlay) { + popupOverlay.classList.add('active'); + } + // Create and start the minigame const MinigameClass = this.registeredScenes[sceneType]; this.currentMinigame = new MinigameClass(container, params); @@ -101,6 +107,12 @@ export const MinigameFramework = { console.log('Cleaning up current minigame'); this.currentMinigame.cleanup(); + // Hide the popup overlay + const popupOverlay = document.querySelector('.popup-overlay'); + if (popupOverlay) { + popupOverlay.classList.remove('active'); + } + // Remove minigame container only if it was auto-created const container = document.querySelector('.minigame-container'); if (container && !container.hasAttribute('data-external')) { diff --git a/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js b/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js index ef2a6d1..44c81a4 100644 --- a/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js +++ b/public/break_escape/js/minigames/lockpicking/lockpicking-game-phaser.js @@ -302,7 +302,7 @@ export class LockpickingMinigamePhaser extends MinigameScene { const switchModeBtn = document.createElement('button'); switchModeBtn.className = 'minigame-button'; switchModeBtn.id = 'lockpicking-switch-mode-btn'; - switchModeBtn.innerHTML = 'Lockpick Switch to Lockpicking'; + switchModeBtn.innerHTML = 'Lockpick Switch to Lockpicking'; switchModeBtn.onclick = () => this.toolMgr.switchToPickMode(); buttonContainer.appendChild(switchModeBtn); @@ -320,7 +320,7 @@ export class LockpickingMinigamePhaser extends MinigameScene { const switchModeBtn = document.createElement('button'); switchModeBtn.className = 'minigame-button'; switchModeBtn.id = 'lockpicking-switch-to-keys-btn'; - switchModeBtn.innerHTML = 'Key Switch to Key Mode'; + switchModeBtn.innerHTML = 'Key Switch to Key Mode'; switchModeBtn.onclick = () => this.toolMgr.switchToKeyMode(); buttonContainer.appendChild(switchModeBtn); diff --git a/public/break_escape/js/minigames/lockpicking/tool-manager.js b/public/break_escape/js/minigames/lockpicking/tool-manager.js index ed2a67d..d125cb1 100644 --- a/public/break_escape/js/minigames/lockpicking/tool-manager.js +++ b/public/break_escape/js/minigames/lockpicking/tool-manager.js @@ -238,7 +238,7 @@ export class ToolManager { const switchModeBtn = document.createElement('button'); switchModeBtn.className = 'minigame-button'; switchModeBtn.id = 'lockpicking-switch-mode-btn'; - switchModeBtn.innerHTML = 'Lockpick Switch to Lockpicking'; + switchModeBtn.innerHTML = 'Lockpick Switch to Lockpicking'; switchModeBtn.onclick = () => this.switchToPickMode(); buttonContainer.appendChild(switchModeBtn); diff --git a/public/break_escape/js/minigames/notes/notes-minigame.js b/public/break_escape/js/minigames/notes/notes-minigame.js index 3a8cc87..9ada09c 100644 --- a/public/break_escape/js/minigames/notes/notes-minigame.js +++ b/public/break_escape/js/minigames/notes/notes-minigame.js @@ -100,7 +100,7 @@ export class NotesMinigame extends MinigameScene { // Add star icon for important notes if (isImportant) { const starIcon = document.createElement('img'); - starIcon.src = 'assets/icons/star.png'; + starIcon.src = '/break_escape/assets/icons/star.png'; starIcon.alt = 'Important'; starIcon.className = 'notes-minigame-star'; noteTitle.appendChild(starIcon); @@ -135,7 +135,7 @@ export class NotesMinigame extends MinigameScene { // Add pencil icon const pencilIcon = document.createElement('img'); - pencilIcon.src = 'assets/icons/pencil.png'; + pencilIcon.src = '/break_escape/assets/icons/pencil.png'; pencilIcon.alt = 'Edit'; editBtn.appendChild(pencilIcon); @@ -163,7 +163,7 @@ export class NotesMinigame extends MinigameScene { // Add pencil icon const pencilIcon = document.createElement('img'); - pencilIcon.src = 'assets/icons/pencil.png'; + pencilIcon.src = '/break_escape/assets/icons/pencil.png'; pencilIcon.alt = 'Edit'; editBtn.appendChild(pencilIcon); @@ -322,7 +322,7 @@ export class NotesMinigame extends MinigameScene { // Add star icon for important notes if (isImportant) { const starIcon = document.createElement('img'); - starIcon.src = 'assets/icons/star.png'; + starIcon.src = '/break_escape/assets/icons/star.png'; starIcon.alt = 'Important'; starIcon.className = 'notes-minigame-star'; noteTitle.appendChild(starIcon); diff --git a/public/break_escape/js/minigames/password/password-minigame.js b/public/break_escape/js/minigames/password/password-minigame.js index b5ada54..a82a3e5 100644 --- a/public/break_escape/js/minigames/password/password-minigame.js +++ b/public/break_escape/js/minigames/password/password-minigame.js @@ -41,7 +41,7 @@ export class PasswordMinigame extends MinigameScene { const notebookBtn = document.createElement('button'); notebookBtn.className = 'minigame-button'; notebookBtn.id = 'minigame-notebook-postit'; - notebookBtn.innerHTML = 'Notepad Add to Notepad'; + notebookBtn.innerHTML = 'Notepad Add to Notepad'; // Insert before the cancel button (first child in controls) this.controlsElement.insertBefore(notebookBtn, this.controlsElement.firstChild); } @@ -80,7 +80,7 @@ export class PasswordMinigame extends MinigameScene {
${imageData ? `
- ${imageData.deviceName}
@@ -100,7 +100,7 @@ export class PasswordMinigame extends MinigameScene { placeholder="Enter password..." maxlength="50">
@@ -128,7 +128,7 @@ export class PasswordMinigame extends MinigameScene {
${this.gameData.showKeyboard ? ` ` : ''}
diff --git a/public/break_escape/js/minigames/phone-chat/phone-chat-minigame.js b/public/break_escape/js/minigames/phone-chat/phone-chat-minigame.js index b988c1a..77dac51 100644 --- a/public/break_escape/js/minigames/phone-chat/phone-chat-minigame.js +++ b/public/break_escape/js/minigames/phone-chat/phone-chat-minigame.js @@ -93,7 +93,7 @@ export class PhoneChatMinigame extends MinigameScene { const notebookBtn = document.createElement('button'); notebookBtn.className = 'minigame-button'; notebookBtn.id = 'minigame-notebook'; - notebookBtn.innerHTML = 'Notepad Add to Notepad'; + notebookBtn.innerHTML = 'Notepad Add to Notepad'; // Insert before the cancel/close button const cancelBtn = this.controlsElement.querySelector('#minigame-cancel'); if (cancelBtn) { diff --git a/public/break_escape/js/minigames/phone-chat/phone-chat-ui.js b/public/break_escape/js/minigames/phone-chat/phone-chat-ui.js index 26a6d31..44027b1 100644 --- a/public/break_escape/js/minigames/phone-chat/phone-chat-ui.js +++ b/public/break_escape/js/minigames/phone-chat/phone-chat-ui.js @@ -268,11 +268,11 @@ export default class PhoneChatUI { if (playing) { // Show stop icon - playButton.innerHTML = 'Stop'; + playButton.innerHTML = 'Stop'; playButton.title = 'Stop'; } else { // Show play icon - playButton.innerHTML = 'Play'; + playButton.innerHTML = 'Play'; playButton.title = 'Play'; } } @@ -489,13 +489,13 @@ export default class PhoneChatUI { const playButton = document.createElement('div'); playButton.className = 'play-button'; const playIcon = document.createElement('img'); - playIcon.src = 'assets/icons/play.png'; + playIcon.src = '/break_escape/assets/icons/play.png'; playIcon.alt = 'Play'; playIcon.className = 'icon'; playButton.appendChild(playIcon); const audioSprite = document.createElement('img'); - audioSprite.src = 'assets/mini-games/audio.png'; + audioSprite.src = '/break_escape/assets/mini-games/audio.png'; audioSprite.alt = 'Audio'; audioSprite.className = 'audio-sprite'; diff --git a/public/break_escape/js/minigames/pin/pin-minigame.js b/public/break_escape/js/minigames/pin/pin-minigame.js index 4b9e583..52d5ddf 100644 --- a/public/break_escape/js/minigames/pin/pin-minigame.js +++ b/public/break_escape/js/minigames/pin/pin-minigame.js @@ -160,7 +160,7 @@ export class PinMinigame extends MinigameScene { // Add pin-cracker icon this.pinCrackerIconElement = document.createElement('img'); - this.pinCrackerIconElement.src = 'assets/objects/pin-cracker.png'; + this.pinCrackerIconElement.src = '/break_escape/assets/objects/pin-cracker.png'; this.pinCrackerIconElement.alt = 'Pin Cracker'; this.pinCrackerIconElement.className = 'pin-minigame-cracker-icon'; this.pinCrackerIconElement.style.display = 'inline-block'; // Show by default when pin-cracker is available diff --git a/public/break_escape/js/minigames/text-file/text-file-minigame.js b/public/break_escape/js/minigames/text-file/text-file-minigame.js index 2bbd69e..8df8ea5 100644 --- a/public/break_escape/js/minigames/text-file/text-file-minigame.js +++ b/public/break_escape/js/minigames/text-file/text-file-minigame.js @@ -23,7 +23,7 @@ export class TextFileMinigame extends MinigameScene { // Customize the header this.headerElement.innerHTML = ` -

Document ${this.textFileData.fileName}

+

Document ${this.textFileData.fileName}

Viewing text file contents

`; @@ -32,7 +32,7 @@ export class TextFileMinigame extends MinigameScene { const notebookBtn = document.createElement('button'); notebookBtn.className = 'minigame-button'; notebookBtn.id = 'minigame-notebook'; - notebookBtn.innerHTML = 'Notepad Add to Notepad'; + notebookBtn.innerHTML = 'Notepad Add to Notepad'; this.controlsElement.appendChild(notebookBtn); // Change cancel button text to "Close" @@ -64,7 +64,7 @@ export class TextFileMinigame extends MinigameScene {
-
Document
+
Document
${this.textFileData.fileName}
@@ -77,7 +77,7 @@ export class TextFileMinigame extends MinigameScene {
- +
@@ -88,7 +88,7 @@ export class TextFileMinigame extends MinigameScene { ${this.textFileData.observations ? `
-

Clipboard Observations:

+

Clipboard Observations:

${this.textFileData.observations}

` : ''} diff --git a/public/break_escape/js/minigames/title-screen/title-screen-minigame.js b/public/break_escape/js/minigames/title-screen/title-screen-minigame.js index 50592f9..584d252 100644 --- a/public/break_escape/js/minigames/title-screen/title-screen-minigame.js +++ b/public/break_escape/js/minigames/title-screen/title-screen-minigame.js @@ -3,7 +3,7 @@ import { MinigameScene } from '../framework/base-minigame.js'; // Load title screen CSS const titleScreenCSS = document.createElement('link'); titleScreenCSS.rel = 'stylesheet'; -titleScreenCSS.href = 'css/title-screen.css'; +titleScreenCSS.href = '/break_escape/css/title-screen.css'; titleScreenCSS.id = 'title-screen-css'; if (!document.getElementById('title-screen-css')) { document.head.appendChild(titleScreenCSS); @@ -26,7 +26,7 @@ export class TitleScreenMinigame extends MinigameScene { this.container.innerHTML = `
- +
BreakEscape
`; diff --git a/public/break_escape/js/systems/inventory.js b/public/break_escape/js/systems/inventory.js index b37bc4b..fc238af 100644 --- a/public/break_escape/js/systems/inventory.js +++ b/public/break_escape/js/systems/inventory.js @@ -242,7 +242,7 @@ export function addToInventory(sprite) { // Create inventory item const itemImg = document.createElement('img'); itemImg.className = 'inventory-item'; - itemImg.src = `assets/objects/${sprite.texture?.key || sprite.name || sprite.scenarioData?.type}.png`; + itemImg.src = `/break_escape/assets/objects/${sprite.texture?.key || sprite.name || sprite.scenarioData?.type}.png`; itemImg.alt = sprite.scenarioData.name; // Create tooltip @@ -440,7 +440,7 @@ function updateKeyRingDisplay() { // Create key ring item const itemImg = document.createElement('img'); itemImg.className = 'inventory-item'; - itemImg.src = keyRing.keys.length === 1 ? `assets/objects/key.png` : `assets/objects/key-ring.png`; + itemImg.src = keyRing.keys.length === 1 ? `/break_escape/assets/objects/key.png` : `/break_escape/assets/objects/key-ring.png`; itemImg.alt = keyRing.keys.length === 1 ? keyRing.keys[0].scenarioData.name : 'Key Ring'; // Add data attributes for styling diff --git a/public/break_escape/js/systems/minigame-starters.js b/public/break_escape/js/systems/minigame-starters.js index 9dbb380..63ffb42 100644 --- a/public/break_escape/js/systems/minigame-starters.js +++ b/public/break_escape/js/systems/minigame-starters.js @@ -94,7 +94,7 @@ export function startLockpickingMinigame(lockable, scene, difficulty = 'medium', } else { // This is a regular item - use scenarioData itemName = lockable?.scenarioData?.name || lockable?.name || 'Locked Item'; - itemImage = lockable?.texture?.key ? `assets/objects/${lockable.texture.key}.png` : null; + itemImage = lockable?.texture?.key ? `/break_escape/assets/objects/${lockable.texture.key}.png` : null; itemObservations = lockable?.scenarioData?.observations || ''; } @@ -397,7 +397,7 @@ export function startKeySelectionMinigame(lockable, type, playerKeys, requiredKe } else { // This is a regular item - use scenarioData itemName = lockable?.scenarioData?.name || lockable?.name || 'Locked Item'; - itemImage = lockable?.texture?.key ? `assets/objects/${lockable.texture.key}.png` : null; + itemImage = lockable?.texture?.key ? `/break_escape/assets/objects/${lockable.texture.key}.png` : null; itemObservations = lockable?.scenarioData?.observations || ''; } diff --git a/public/break_escape/js/ui/game-over-screen.js b/public/break_escape/js/ui/game-over-screen.js index 09ea341..57520bd 100644 --- a/public/break_escape/js/ui/game-over-screen.js +++ b/public/break_escape/js/ui/game-over-screen.js @@ -172,7 +172,7 @@ export class GameOverScreen { mainMenu() { // Navigate to scenario select or main menu - window.location.href = 'scenario_select.html'; + window.location.href = '/break_escape/missions'; } destroy() { diff --git a/public/break_escape/js/ui/health-ui.js b/public/break_escape/js/ui/health-ui.js index 601d6c5..1349310 100644 --- a/public/break_escape/js/ui/health-ui.js +++ b/public/break_escape/js/ui/health-ui.js @@ -34,7 +34,7 @@ export class HealthUI { for (let i = 0; i < COMBAT_CONFIG.ui.maxHearts; i++) { const heart = document.createElement('img'); heart.className = 'health-heart'; - heart.src = 'assets/icons/heart.png'; + heart.src = '/break_escape/assets/icons/heart.png'; heart.alt = 'HP'; heartsContainer.appendChild(heart); this.hearts.push(heart); @@ -84,15 +84,15 @@ export class HealthUI { this.hearts.forEach((heart, index) => { if (index < fullHearts) { // Full heart - heart.src = 'assets/icons/heart.png'; + heart.src = '/break_escape/assets/icons/heart.png'; heart.style.opacity = '1'; } else if (index === fullHearts && halfHeart) { // Half heart - heart.src = 'assets/icons/heart-half.png'; + heart.src = '/break_escape/assets/icons/heart-half.png'; heart.style.opacity = '1'; } else { // Empty heart - heart.src = 'assets/icons/heart.png'; + heart.src = '/break_escape/assets/icons/heart.png'; heart.style.opacity = '0.2'; } }); diff --git a/public/break_escape/js/utils/constants.js b/public/break_escape/js/utils/constants.js index 1e6d25f..197267c 100644 --- a/public/break_escape/js/utils/constants.js +++ b/public/break_escape/js/utils/constants.js @@ -48,6 +48,9 @@ export const GAME_CONFIG = typeof Phaser !== 'undefined' ? { height: 480, // Classic pixel art base resolution (scales cleanly: 1x=240, 2x=480, 3x=720, 4x=960) parent: 'game-container', pixelArt: true, + loader: { + baseURL: '/break_escape/' + }, scale: { mode: Phaser.Scale.ENVELOP, // Fill entire container while maintaining aspect ratio autoCenter: Phaser.Scale.CENTER_BOTH, diff --git a/public/break_escape/js/utils/crypto-workstation.js b/public/break_escape/js/utils/crypto-workstation.js index 47add11..4254a93 100644 --- a/public/break_escape/js/utils/crypto-workstation.js +++ b/public/break_escape/js/utils/crypto-workstation.js @@ -16,7 +16,7 @@ export function openCryptoWorkstation() { const cyberchefFrame = document.getElementById('cyberchef-frame'); // Set the iframe source to the CyberChef HTML file - cyberchefFrame.src = 'assets/cyberchef/CyberChef_v10.19.4.html'; + cyberchefFrame.src = '/break_escape/assets/cyberchef/CyberChef_v10.19.4.html'; // Show the laptop popup laptopPopup.style.display = 'block';