mirror of
https://github.com/cliffe/BreakEscape.git
synced 2026-02-20 13:50:46 +00:00
Add Notes Minigame: Implement interactive note display and inventory integration
Introduce a new Notes Minigame that allows players to view and interact with notes in a notepad-style interface. The minigame supports adding notes to the inventory, displaying observations, and includes navigation features such as previous/next buttons and search functionality. Update relevant files for integration with the existing game systems, including interaction and inventory management. Add test HTML for verifying minigame features and include necessary assets for the notepad background.
This commit is contained in:
113
NOTES_MINIGAME_USAGE.md
Normal file
113
NOTES_MINIGAME_USAGE.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# Notes Minigame Usage
|
||||
|
||||
The Notes Minigame provides an interactive way to display note content with a notepad background and allows players to add notes to their inventory.
|
||||
|
||||
## Features
|
||||
|
||||
- Displays note content on a notepad background (`/assets/mini-games/notepad.png`)
|
||||
- Shows observation text below the main content (if provided)
|
||||
- Provides a "Add to Inventory" button with backpack icon (`/assets/mini-games/backpack.png`)
|
||||
- Integrates with the existing inventory system
|
||||
- Uses the minigame framework for consistent UI
|
||||
|
||||
## Usage in Scenarios
|
||||
|
||||
To use the notes minigame in your scenario files, add the following properties to note objects:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "notes",
|
||||
"name": "Example Note",
|
||||
"takeable": true,
|
||||
"readable": true,
|
||||
"text": "This is the main content of the note.\n\nIt can contain multiple lines and will be displayed on the notepad background.",
|
||||
"observations": "The handwriting appears rushed and there are coffee stains on the paper."
|
||||
}
|
||||
```
|
||||
|
||||
### Required Properties
|
||||
|
||||
- `type`: Must be "notes"
|
||||
- `text`: The main content to display on the notepad
|
||||
- `readable`: Must be true to trigger the minigame
|
||||
|
||||
### Optional Properties
|
||||
|
||||
- `observations`: Additional observation text displayed below the main content
|
||||
- `takeable`: Whether the note can be added to inventory (default: true)
|
||||
|
||||
## Programmatic Usage
|
||||
|
||||
You can also start the notes minigame programmatically:
|
||||
|
||||
```javascript
|
||||
// Basic usage
|
||||
window.startNotesMinigame(item, text, observations);
|
||||
|
||||
// Example
|
||||
const testItem = {
|
||||
scene: null,
|
||||
scenarioData: {
|
||||
type: 'notes',
|
||||
name: 'Test Note',
|
||||
text: 'This is a test note content.',
|
||||
observations: 'The note appears to be written in haste.'
|
||||
}
|
||||
};
|
||||
|
||||
window.startNotesMinigame(testItem, testItem.scenarioData.text, testItem.scenarioData.observations);
|
||||
|
||||
// Show mission brief
|
||||
window.showMissionBrief();
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
### Navigation
|
||||
- **Previous/Next Buttons**: Navigate through collected notes
|
||||
- **Search Functionality**: Search through note titles and content
|
||||
- **Note Counter**: Shows current position (e.g., "2 / 5")
|
||||
|
||||
### Mission Brief Integration
|
||||
- The mission brief is automatically displayed via the notes minigame when starting a new scenario
|
||||
- Uses the same notepad interface for consistency
|
||||
- Automatically added to the notes system as an important note
|
||||
|
||||
### Search
|
||||
- Real-time search through note titles and content
|
||||
- Case-insensitive matching
|
||||
- Filters the note list to show only matching results
|
||||
- Clear search to show all notes again
|
||||
|
||||
### Player Notes
|
||||
- **Edit Observations**: Click the edit button (✏️) to add or modify observations
|
||||
- **Handwritten Style**: Player notes use the same handwritten font as original observations
|
||||
- **Persistent Storage**: Player notes are saved to the notes system and persist between sessions
|
||||
- **Visual Feedback**: Dashed border and background indicate editable areas
|
||||
|
||||
### Visual Effects
|
||||
- **Celotape Effect**: Realistic celotape strip overlapping the top of the text box
|
||||
- **Binder Holes**: Small circular holes on the left side of the text box
|
||||
- **Handwritten Fonts**: Uses Google Fonts 'Kalam' for authentic handwritten appearance
|
||||
|
||||
## Automatic Collection
|
||||
|
||||
- **Auto-Collection**: Notes are automatically added to the notes system when the minigame starts
|
||||
- **Scene Removal**: Notes are automatically removed from the scene after being collected
|
||||
- **No Manual Action**: Players don't need to click "Add to Inventory" - it happens automatically
|
||||
- **Seamless Experience**: Notes are collected and removed from the world in one smooth interaction
|
||||
|
||||
## Integration
|
||||
|
||||
The notes minigame is automatically integrated into the interaction system. When a player interacts with a note object that has `text`, the minigame will be triggered instead of the default text display. The note is automatically collected and removed from the scene.
|
||||
|
||||
## Testing
|
||||
|
||||
A test file is available at `test-notes-minigame.html` to verify the implementation works correctly.
|
||||
|
||||
## Files Modified
|
||||
|
||||
- `js/minigames/notes/notes-minigame.js` - Main minigame implementation
|
||||
- `js/minigames/index.js` - Registration and global export
|
||||
- `js/systems/interactions.js` - Integration with interaction system
|
||||
- `js/systems/inventory.js` - Made addToInventory function globally available
|
||||
BIN
assets/mini-games/notepad.png
Normal file
BIN
assets/mini-games/notepad.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.9 KiB |
@@ -57,7 +57,7 @@
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
"height":10,
|
||||
"id":11,
|
||||
"name":"flat",
|
||||
"name":"props",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"format":"json"
|
||||
"format":"json",
|
||||
"target":"room_closet2.json"
|
||||
}
|
||||
},
|
||||
"height":10,
|
||||
@@ -64,7 +65,7 @@
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
"height":10,
|
||||
"id":11,
|
||||
"name":"flat",
|
||||
"name":"props",
|
||||
"opacity":1,
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
|
||||
@@ -484,6 +484,11 @@ export function create() {
|
||||
// Show introduction
|
||||
introduceScenario();
|
||||
|
||||
// Initialize physics debug display (visual debug off by default)
|
||||
if (window.initializePhysicsDebugDisplay) {
|
||||
window.initializePhysicsDebugDisplay();
|
||||
}
|
||||
|
||||
// Store game reference globally
|
||||
window.game = this;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ export { MinigameScene } from './framework/base-minigame.js';
|
||||
// Export minigame implementations
|
||||
export { LockpickingMinigamePhaser } from './lockpicking/lockpicking-game-phaser.js';
|
||||
export { DustingMinigame } from './dusting/dusting-game.js';
|
||||
export { NotesMinigame, startNotesMinigame, showMissionBrief } from './notes/notes-minigame.js';
|
||||
|
||||
// Initialize the global minigame framework for backward compatibility
|
||||
import { MinigameFramework } from './framework/minigame-manager.js';
|
||||
@@ -16,7 +17,15 @@ window.MinigameFramework = MinigameFramework;
|
||||
// Import the dusting minigame
|
||||
import { DustingMinigame } from './dusting/dusting-game.js';
|
||||
|
||||
// Import the notes minigame
|
||||
import { NotesMinigame, startNotesMinigame, showMissionBrief } from './notes/notes-minigame.js';
|
||||
|
||||
// Register minigames
|
||||
MinigameFramework.registerScene('lockpicking', LockpickingMinigamePhaser); // Use Phaser version as default
|
||||
MinigameFramework.registerScene('lockpicking-phaser', LockpickingMinigamePhaser); // Keep explicit phaser name
|
||||
MinigameFramework.registerScene('dusting', DustingMinigame);
|
||||
MinigameFramework.registerScene('dusting', DustingMinigame);
|
||||
MinigameFramework.registerScene('notes', NotesMinigame);
|
||||
|
||||
// Make notes minigame functions available globally
|
||||
window.startNotesMinigame = startNotesMinigame;
|
||||
window.showMissionBrief = showMissionBrief;
|
||||
800
js/minigames/notes/notes-minigame.js
Normal file
800
js/minigames/notes/notes-minigame.js
Normal file
@@ -0,0 +1,800 @@
|
||||
import { MinigameScene } from '../framework/base-minigame.js';
|
||||
|
||||
// Load handwritten font
|
||||
const fontLink = document.createElement('link');
|
||||
fontLink.href = 'https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&display=swap';
|
||||
fontLink.rel = 'stylesheet';
|
||||
if (!document.querySelector('link[href*="Kalam"]')) {
|
||||
document.head.appendChild(fontLink);
|
||||
}
|
||||
|
||||
// Notes Minigame Scene implementation
|
||||
export class NotesMinigame extends MinigameScene {
|
||||
constructor(container, params) {
|
||||
// Ensure params is defined before calling parent constructor
|
||||
params = params || {};
|
||||
|
||||
// Set default title if not provided
|
||||
if (!params.title) {
|
||||
params.title = 'Reading Notes';
|
||||
}
|
||||
|
||||
super(container, params);
|
||||
|
||||
this.item = params.item;
|
||||
this.noteContent = params.noteContent || this.item?.scenarioData?.noteContent || this.item?.scenarioData?.text || 'No content available';
|
||||
this.observationText = params.observationText || this.item?.scenarioData?.observationText || this.item?.scenarioData?.observations || '';
|
||||
|
||||
// Initialize note navigation
|
||||
this.currentNoteIndex = 0;
|
||||
this.collectedNotes = this.getCollectedNotes();
|
||||
this.autoAddToNotes = true;
|
||||
}
|
||||
|
||||
init() {
|
||||
// Call parent init to set up common components
|
||||
super.init();
|
||||
|
||||
console.log("Notes minigame initializing");
|
||||
|
||||
// Set container dimensions to take up most of the screen
|
||||
this.container.style.width = '90%';
|
||||
this.container.style.height = '85%';
|
||||
this.container.style.padding = '20px';
|
||||
|
||||
// Set up header content
|
||||
this.headerElement.innerHTML = `
|
||||
<h3>Reading Notes</h3>
|
||||
<p>Note automatically added to your collection</p>
|
||||
`;
|
||||
|
||||
// Configure game container with notepad background - scaled to fill most of the screen
|
||||
this.gameContainer.style.cssText = `
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
max-width: 800px;
|
||||
max-height: none;
|
||||
background-image: url('assets/mini-games/notepad.png');
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
position: relative;
|
||||
margin: 20px auto;
|
||||
padding: 10px 140px 50px 150px;
|
||||
box-sizing: border-box;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: -webkit-crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
image-rendering: crisp-edges;
|
||||
`;
|
||||
|
||||
// Create content area
|
||||
const contentArea = document.createElement('div');
|
||||
contentArea.style.cssText = `
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 18px;
|
||||
line-height: 1.5;
|
||||
color: #333;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
`;
|
||||
|
||||
// Create text box container to look like it's stuck in a binder
|
||||
const textBox = document.createElement('div');
|
||||
textBox.style.cssText = `
|
||||
margin: 20px 50px 60px 80px;
|
||||
padding: 40px;
|
||||
background: #fefefe;
|
||||
border: 2px solid #ddd;
|
||||
border-radius: 3px;
|
||||
box-shadow:
|
||||
0 2px 4px rgba(0,0,0,0.1),
|
||||
inset 0 1px 0 rgba(255,255,255,0.8);
|
||||
position: relative;
|
||||
min-height: fit-content;
|
||||
`;
|
||||
|
||||
// Add celotape effect
|
||||
const celotape = document.createElement('div');
|
||||
celotape.className = 'notes-minigame-celotape';
|
||||
celotape.style.cssText = `
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
left: 80px;
|
||||
right: 80px;
|
||||
height: 16px;
|
||||
background: linear-gradient(90deg,
|
||||
rgba(255,255,255,0.9) 0%,
|
||||
rgba(255,255,255,0.7) 20%,
|
||||
rgba(255,255,255,0.9) 40%,
|
||||
rgba(255,255,255,0.7) 60%,
|
||||
rgba(255,255,255,0.9) 80%,
|
||||
rgba(255,255,255,0.7) 100%);
|
||||
border: 1px solid rgba(200,200,200,0.8);
|
||||
border-radius: 2px;
|
||||
box-shadow:
|
||||
0 1px 2px rgba(0,0,0,0.1),
|
||||
inset 0 1px 0 rgba(255,255,255,0.9);
|
||||
z-index: 1;
|
||||
`;
|
||||
textBox.appendChild(celotape);
|
||||
|
||||
// Add binder holes effect
|
||||
const binderHoles = document.createElement('div');
|
||||
binderHoles.style.cssText = `
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 8px;
|
||||
height: 80px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
`;
|
||||
|
||||
|
||||
|
||||
// Add note title/name above the text box
|
||||
const noteTitle = document.createElement('div');
|
||||
noteTitle.className = 'notes-minigame-title';
|
||||
noteTitle.style.cssText = `
|
||||
margin: 0 50px 20px 80px;
|
||||
font-family: 'Kalam', 'Comic Sans MS', cursive;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: #2c3e50;
|
||||
text-decoration: underline;
|
||||
text-decoration-color: #3498db;
|
||||
text-underline-offset: 3px;
|
||||
text-align: center;
|
||||
`;
|
||||
noteTitle.textContent = this.item?.scenarioData?.name || 'Note';
|
||||
contentArea.appendChild(noteTitle);
|
||||
|
||||
// Add note content
|
||||
const noteText = document.createElement('div');
|
||||
noteText.className = 'notes-minigame-text';
|
||||
noteText.style.cssText = `
|
||||
margin-left: 30px;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
color: #333;
|
||||
`;
|
||||
noteText.textContent = this.noteContent;
|
||||
textBox.appendChild(noteText);
|
||||
|
||||
contentArea.appendChild(textBox);
|
||||
|
||||
// Add observation text if available - handwritten directly on the page
|
||||
if (this.observationText) {
|
||||
const observationContainer = document.createElement('div');
|
||||
observationContainer.className = 'notes-minigame-observation-container';
|
||||
observationContainer.style.cssText = `
|
||||
margin: 20px 50px 60px 80px;
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
const observationDiv = document.createElement('div');
|
||||
observationDiv.className = 'notes-minigame-observation';
|
||||
observationDiv.style.cssText = `
|
||||
font-family: 'Kalam', 'Comic Sans MS', cursive;
|
||||
font-style: italic;
|
||||
color: #666;
|
||||
font-size: 18px;
|
||||
line-height: 1.4;
|
||||
text-align: left;
|
||||
min-height: 30px;
|
||||
padding: 10px;
|
||||
border: 1px dashed #ccc;
|
||||
border-radius: 3px;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
`;
|
||||
observationDiv.innerHTML = this.observationText;
|
||||
|
||||
// Add edit button
|
||||
const editBtn = document.createElement('button');
|
||||
editBtn.className = 'notes-minigame-edit-btn';
|
||||
editBtn.style.cssText = `
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
right: -8px;
|
||||
background: #3498db;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.3);
|
||||
transition: background-color 0.3s ease;
|
||||
`;
|
||||
editBtn.innerHTML = '✏️';
|
||||
editBtn.title = 'Edit observations';
|
||||
editBtn.addEventListener('click', () => this.editObservations(observationDiv));
|
||||
|
||||
observationContainer.appendChild(observationDiv);
|
||||
observationContainer.appendChild(editBtn);
|
||||
contentArea.appendChild(observationContainer);
|
||||
} else {
|
||||
// Add empty observation area with edit button
|
||||
const observationContainer = document.createElement('div');
|
||||
observationContainer.className = 'notes-minigame-observation-container';
|
||||
observationContainer.style.cssText = `
|
||||
margin: 20px 50px 60px 80px;
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
const observationDiv = document.createElement('div');
|
||||
observationDiv.className = 'notes-minigame-observation';
|
||||
observationDiv.style.cssText = `
|
||||
font-family: 'Kalam', 'Comic Sans MS', cursive;
|
||||
font-style: italic;
|
||||
color: #999;
|
||||
font-size: 18px;
|
||||
line-height: 1.4;
|
||||
text-align: left;
|
||||
min-height: 30px;
|
||||
padding: 10px;
|
||||
border: 1px dashed #ccc;
|
||||
border-radius: 3px;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
`;
|
||||
observationDiv.innerHTML = '<em>Click edit to add your observations...</em>';
|
||||
|
||||
// Add edit button
|
||||
const editBtn = document.createElement('button');
|
||||
editBtn.className = 'notes-minigame-edit-btn';
|
||||
editBtn.style.cssText = `
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
right: -8px;
|
||||
background: #3498db;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.3);
|
||||
transition: background-color 0.3s ease;
|
||||
`;
|
||||
editBtn.innerHTML = '✏️';
|
||||
editBtn.title = 'Add observations';
|
||||
editBtn.addEventListener('click', () => this.editObservations(observationDiv));
|
||||
|
||||
observationContainer.appendChild(observationDiv);
|
||||
observationContainer.appendChild(editBtn);
|
||||
contentArea.appendChild(observationContainer);
|
||||
}
|
||||
|
||||
this.gameContainer.appendChild(contentArea);
|
||||
|
||||
// Create navigation buttons container
|
||||
const navContainer = document.createElement('div');
|
||||
navContainer.style.cssText = `
|
||||
position: absolute;
|
||||
bottom: 80px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
z-index: 10;
|
||||
`;
|
||||
|
||||
// Add search input if there are multiple notes
|
||||
if (this.collectedNotes.length > 1) {
|
||||
const searchInput = document.createElement('input');
|
||||
searchInput.type = 'text';
|
||||
searchInput.placeholder = 'Search notes...';
|
||||
searchInput.className = 'notes-minigame-search';
|
||||
searchInput.style.cssText = `
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #555;
|
||||
border-radius: 5px;
|
||||
background: rgba(0,0,0,0.7);
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
width: 200px;
|
||||
margin-right: 10px;
|
||||
`;
|
||||
searchInput.addEventListener('input', (e) => this.searchNotes(e.target.value));
|
||||
navContainer.appendChild(searchInput);
|
||||
|
||||
const prevBtn = document.createElement('button');
|
||||
prevBtn.className = 'minigame-button notes-nav-button';
|
||||
prevBtn.style.cssText = `
|
||||
background: #95a5a6;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 8px 15px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
transition: background-color 0.3s ease;
|
||||
`;
|
||||
prevBtn.textContent = '← Previous';
|
||||
prevBtn.addEventListener('click', () => this.navigateToNote(-1));
|
||||
navContainer.appendChild(prevBtn);
|
||||
|
||||
const nextBtn = document.createElement('button');
|
||||
nextBtn.className = 'minigame-button notes-nav-button';
|
||||
nextBtn.style.cssText = `
|
||||
background: #95a5a6;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 8px 15px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
transition: background-color 0.3s ease;
|
||||
`;
|
||||
nextBtn.textContent = 'Next →';
|
||||
nextBtn.addEventListener('click', () => this.navigateToNote(1));
|
||||
navContainer.appendChild(nextBtn);
|
||||
|
||||
// Add note counter
|
||||
const noteCounter = document.createElement('div');
|
||||
noteCounter.className = 'notes-minigame-counter';
|
||||
noteCounter.style.cssText = `
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px 15px;
|
||||
background: rgba(0,0,0,0.5);
|
||||
border-radius: 5px;
|
||||
`;
|
||||
noteCounter.textContent = `${this.currentNoteIndex + 1} / ${this.collectedNotes.length}`;
|
||||
navContainer.appendChild(noteCounter);
|
||||
|
||||
this.container.appendChild(navContainer);
|
||||
}
|
||||
|
||||
// Create action buttons container
|
||||
const buttonsContainer = document.createElement('div');
|
||||
buttonsContainer.style.cssText = `
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
z-index: 10;
|
||||
`;
|
||||
|
||||
|
||||
// Close button
|
||||
const closeBtn = document.createElement('button');
|
||||
closeBtn.className = 'minigame-button notes-close-button';
|
||||
closeBtn.style.cssText = `
|
||||
background: #95a5a6;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
transition: background-color 0.3s ease;
|
||||
`;
|
||||
closeBtn.textContent = 'Close';
|
||||
|
||||
closeBtn.addEventListener('mouseenter', () => {
|
||||
closeBtn.style.backgroundColor = '#7f8c8d';
|
||||
});
|
||||
closeBtn.addEventListener('mouseleave', () => {
|
||||
closeBtn.style.backgroundColor = '#95a5a6';
|
||||
});
|
||||
|
||||
closeBtn.addEventListener('click', () => {
|
||||
this.complete(false);
|
||||
});
|
||||
|
||||
buttonsContainer.appendChild(closeBtn);
|
||||
|
||||
this.container.appendChild(buttonsContainer);
|
||||
}
|
||||
|
||||
|
||||
removeNoteFromScene() {
|
||||
// Remove the note from the scene if it has a sprite
|
||||
if (this.item && this.item.sprite) {
|
||||
console.log('Removing note from scene:', this.item.sprite);
|
||||
|
||||
// Hide the sprite
|
||||
if (this.item.sprite.setVisible) {
|
||||
this.item.sprite.setVisible(false);
|
||||
}
|
||||
|
||||
// Remove from scene if it has a destroy method
|
||||
if (this.item.sprite.destroy) {
|
||||
this.item.sprite.destroy();
|
||||
}
|
||||
|
||||
// Also try to remove from the scene's object list if available
|
||||
if (this.item.scene && this.item.scene.objects) {
|
||||
const objectIndex = this.item.scene.objects.findIndex(obj => obj.sprite === this.item.sprite);
|
||||
if (objectIndex !== -1) {
|
||||
this.item.scene.objects.splice(objectIndex, 1);
|
||||
console.log('Removed note from scene objects list');
|
||||
}
|
||||
}
|
||||
|
||||
// Update the scene's interactive objects if available
|
||||
if (this.item.scene && this.item.scene.interactiveObjects) {
|
||||
const interactiveIndex = this.item.scene.interactiveObjects.findIndex(obj => obj.sprite === this.item.sprite);
|
||||
if (interactiveIndex !== -1) {
|
||||
this.item.scene.interactiveObjects.splice(interactiveIndex, 1);
|
||||
console.log('Removed note from scene interactive objects list');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getCollectedNotes() {
|
||||
// Get all notes from the notes system that are marked as important or have been collected
|
||||
if (!window.gameState || !window.gameState.notes) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Filter for important notes or notes that look like they were collected from objects
|
||||
return window.gameState.notes.filter(note =>
|
||||
note.important ||
|
||||
note.title.includes('Log') ||
|
||||
note.title.includes('Note') ||
|
||||
note.title.includes('Security') ||
|
||||
note.title.includes('Report')
|
||||
);
|
||||
}
|
||||
|
||||
navigateToNote(direction) {
|
||||
if (this.collectedNotes.length <= 1) return;
|
||||
|
||||
this.currentNoteIndex += direction;
|
||||
|
||||
// Wrap around
|
||||
if (this.currentNoteIndex < 0) {
|
||||
this.currentNoteIndex = this.collectedNotes.length - 1;
|
||||
} else if (this.currentNoteIndex >= this.collectedNotes.length) {
|
||||
this.currentNoteIndex = 0;
|
||||
}
|
||||
|
||||
// Update the displayed note
|
||||
this.updateDisplayedNote();
|
||||
|
||||
// Update the counter
|
||||
const noteCounter = this.container.querySelector('.notes-minigame-counter');
|
||||
if (noteCounter) {
|
||||
noteCounter.textContent = `${this.currentNoteIndex + 1} / ${this.collectedNotes.length}`;
|
||||
}
|
||||
}
|
||||
|
||||
updateDisplayedNote() {
|
||||
const currentNote = this.collectedNotes[this.currentNoteIndex];
|
||||
if (!currentNote) return;
|
||||
|
||||
// Parse the note text to extract observations
|
||||
const noteParts = this.parseNoteText(currentNote.text);
|
||||
this.noteContent = noteParts.mainText;
|
||||
this.observationText = noteParts.observationText;
|
||||
|
||||
// Update the displayed content
|
||||
const noteTitle = this.container.querySelector('.notes-minigame-title');
|
||||
const noteText = this.container.querySelector('.notes-minigame-text');
|
||||
const observationDiv = this.container.querySelector('.notes-minigame-observation');
|
||||
|
||||
if (noteTitle) {
|
||||
noteTitle.textContent = currentNote.title;
|
||||
}
|
||||
|
||||
if (noteText) {
|
||||
noteText.textContent = this.noteContent;
|
||||
}
|
||||
|
||||
// Update observation container
|
||||
const observationContainer = this.container.querySelector('.notes-minigame-observation-container');
|
||||
if (observationContainer) {
|
||||
const observationDiv = observationContainer.querySelector('.notes-minigame-observation');
|
||||
const editBtn = observationContainer.querySelector('.notes-minigame-edit-btn');
|
||||
|
||||
if (this.observationText) {
|
||||
observationDiv.innerHTML = this.observationText;
|
||||
observationDiv.style.color = '#666';
|
||||
editBtn.title = 'Edit observations';
|
||||
} else {
|
||||
observationDiv.innerHTML = '<em>Click edit to add your observations...</em>';
|
||||
observationDiv.style.color = '#999';
|
||||
editBtn.title = 'Add observations';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parseNoteText(text) {
|
||||
// Parse note text to separate main content from observations
|
||||
const observationMatch = text.match(/\n\nObservation:\s*(.+)$/s);
|
||||
if (observationMatch) {
|
||||
return {
|
||||
mainText: text.replace(/\n\nObservation:\s*.+$/s, '').trim(),
|
||||
observationText: observationMatch[1].trim()
|
||||
};
|
||||
}
|
||||
return {
|
||||
mainText: text,
|
||||
observationText: ''
|
||||
};
|
||||
}
|
||||
|
||||
searchNotes(searchTerm) {
|
||||
if (!searchTerm || searchTerm.trim() === '') {
|
||||
// Reset to show all notes
|
||||
this.collectedNotes = this.getCollectedNotes();
|
||||
this.currentNoteIndex = 0;
|
||||
this.updateDisplayedNote();
|
||||
this.updateCounter();
|
||||
return;
|
||||
}
|
||||
|
||||
const searchLower = searchTerm.toLowerCase();
|
||||
const matchingNotes = this.collectedNotes.filter(note =>
|
||||
note.title.toLowerCase().includes(searchLower) ||
|
||||
note.text.toLowerCase().includes(searchLower)
|
||||
);
|
||||
|
||||
if (matchingNotes.length > 0) {
|
||||
this.collectedNotes = matchingNotes;
|
||||
this.currentNoteIndex = 0;
|
||||
this.updateDisplayedNote();
|
||||
this.updateCounter();
|
||||
}
|
||||
}
|
||||
|
||||
updateCounter() {
|
||||
const noteCounter = this.container.querySelector('.notes-minigame-counter');
|
||||
if (noteCounter) {
|
||||
noteCounter.textContent = `${this.currentNoteIndex + 1} / ${this.collectedNotes.length}`;
|
||||
}
|
||||
}
|
||||
|
||||
editObservations(observationDiv) {
|
||||
const currentText = observationDiv.textContent.trim();
|
||||
const isPlaceholder = currentText === 'Click edit to add your observations...';
|
||||
const originalText = isPlaceholder ? '' : currentText;
|
||||
|
||||
// Create textarea for editing
|
||||
const textarea = document.createElement('textarea');
|
||||
textarea.value = originalText;
|
||||
textarea.style.cssText = `
|
||||
width: 100%;
|
||||
min-height: 60px;
|
||||
font-family: 'Kalam', 'Comic Sans MS', cursive;
|
||||
font-size: 18px;
|
||||
line-height: 1.4;
|
||||
color: #666;
|
||||
border: 2px solid #3498db;
|
||||
border-radius: 3px;
|
||||
padding: 10px;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
resize: vertical;
|
||||
outline: none;
|
||||
`;
|
||||
textarea.placeholder = 'Add your observations here...';
|
||||
|
||||
// Create button container
|
||||
const buttonContainer = document.createElement('div');
|
||||
buttonContainer.style.cssText = `
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
justify-content: flex-end;
|
||||
`;
|
||||
|
||||
// Save button
|
||||
const saveBtn = document.createElement('button');
|
||||
saveBtn.textContent = 'Save';
|
||||
saveBtn.style.cssText = `
|
||||
background: #2ecc71;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 8px 16px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
`;
|
||||
saveBtn.addEventListener('click', () => {
|
||||
const newText = textarea.value.trim();
|
||||
observationDiv.innerHTML = newText || '<em>Click edit to add your observations...</em>';
|
||||
observationDiv.style.color = newText ? '#666' : '#999';
|
||||
|
||||
// Update the stored observation text
|
||||
this.observationText = newText;
|
||||
|
||||
// Save to the current note in the notes system
|
||||
this.saveObservationToNote(newText);
|
||||
|
||||
// Remove editing elements
|
||||
textarea.remove();
|
||||
buttonContainer.remove();
|
||||
});
|
||||
|
||||
// Cancel button
|
||||
const cancelBtn = document.createElement('button');
|
||||
cancelBtn.textContent = 'Cancel';
|
||||
cancelBtn.style.cssText = `
|
||||
background: #95a5a6;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 8px 16px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
`;
|
||||
cancelBtn.addEventListener('click', () => {
|
||||
// Restore original text
|
||||
if (originalText) {
|
||||
observationDiv.innerHTML = originalText;
|
||||
observationDiv.style.color = '#666';
|
||||
} else {
|
||||
observationDiv.innerHTML = '<em>Click edit to add your observations...</em>';
|
||||
observationDiv.style.color = '#999';
|
||||
}
|
||||
|
||||
// Remove editing elements
|
||||
textarea.remove();
|
||||
buttonContainer.remove();
|
||||
});
|
||||
|
||||
buttonContainer.appendChild(saveBtn);
|
||||
buttonContainer.appendChild(cancelBtn);
|
||||
|
||||
// Replace content with editing interface
|
||||
observationDiv.innerHTML = '';
|
||||
observationDiv.appendChild(textarea);
|
||||
observationDiv.appendChild(buttonContainer);
|
||||
|
||||
// Focus the textarea
|
||||
textarea.focus();
|
||||
textarea.select();
|
||||
}
|
||||
|
||||
saveObservationToNote(newObservationText) {
|
||||
// Update the current note in the notes system
|
||||
const currentNote = this.collectedNotes[this.currentNoteIndex];
|
||||
if (currentNote) {
|
||||
// Parse the existing text to separate main content from observations
|
||||
const noteParts = this.parseNoteText(currentNote.text);
|
||||
|
||||
// Update the observation text
|
||||
noteParts.observationText = newObservationText;
|
||||
|
||||
// Reconstruct the full text
|
||||
let fullText = noteParts.mainText;
|
||||
if (newObservationText) {
|
||||
fullText += `\n\nObservation: ${newObservationText}`;
|
||||
}
|
||||
|
||||
// Update the note in the notes system
|
||||
currentNote.text = fullText;
|
||||
|
||||
// Also update in the global notes system if it exists
|
||||
if (window.gameState && window.gameState.notes) {
|
||||
const globalNote = window.gameState.notes.find(note =>
|
||||
note.title === currentNote.title && note.timestamp === currentNote.timestamp
|
||||
);
|
||||
if (globalNote) {
|
||||
globalNote.text = fullText;
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Observation saved to note:', currentNote.title);
|
||||
}
|
||||
}
|
||||
|
||||
start() {
|
||||
super.start();
|
||||
console.log("Notes minigame started");
|
||||
|
||||
// Automatically add current note to notes system when starting
|
||||
if (this.autoAddToNotes && window.addNote) {
|
||||
const noteTitle = this.item?.scenarioData?.name || 'Note';
|
||||
const noteText = this.noteContent + (this.observationText ? `\n\nObservation: ${this.observationText}` : '');
|
||||
const isImportant = this.item?.scenarioData?.important || false;
|
||||
|
||||
const addedNote = window.addNote(noteTitle, noteText, isImportant);
|
||||
if (addedNote) {
|
||||
console.log('Note automatically added to notes system on start:', addedNote);
|
||||
// Refresh collected notes
|
||||
this.collectedNotes = this.getCollectedNotes();
|
||||
|
||||
// Automatically remove the note from the scene
|
||||
this.removeNoteFromScene();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
complete(success) {
|
||||
// Call parent complete with result
|
||||
super.complete(success, this.gameResult);
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
super.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
// Export the minigame for the framework to register
|
||||
// The registration is handled in the main minigames/index.js file
|
||||
|
||||
// Function to show mission brief via notes minigame
|
||||
export function showMissionBrief() {
|
||||
if (!window.gameScenario || !window.gameScenario.scenario_brief) {
|
||||
console.warn('No mission brief available');
|
||||
return;
|
||||
}
|
||||
|
||||
const missionBriefItem = {
|
||||
scene: null,
|
||||
scenarioData: {
|
||||
type: 'notes',
|
||||
name: 'Mission Brief',
|
||||
text: window.gameScenario.scenario_brief,
|
||||
important: true
|
||||
}
|
||||
};
|
||||
|
||||
startNotesMinigame(missionBriefItem, window.gameScenario.scenario_brief, '');
|
||||
}
|
||||
|
||||
// Function to start the notes minigame
|
||||
export function startNotesMinigame(item, noteContent, observationText) {
|
||||
console.log('Starting notes minigame with:', { item, noteContent, observationText });
|
||||
|
||||
// Make sure the minigame is registered
|
||||
if (window.MinigameFramework && !window.MinigameFramework.registeredScenes['notes']) {
|
||||
window.MinigameFramework.registerScene('notes', NotesMinigame);
|
||||
console.log('Notes minigame registered on demand');
|
||||
}
|
||||
|
||||
// Initialize the framework if not already done
|
||||
if (!window.MinigameFramework.mainGameScene && item && item.scene) {
|
||||
window.MinigameFramework.init(item.scene);
|
||||
}
|
||||
|
||||
// Start the notes minigame with proper parameters
|
||||
const params = {
|
||||
title: item?.scenarioData?.name || 'Reading Notes',
|
||||
item: item,
|
||||
noteContent: noteContent,
|
||||
observationText: observationText,
|
||||
onComplete: (success, result) => {
|
||||
if (success && result && result.addedToInventory) {
|
||||
console.log('NOTES SUCCESS - Added to inventory', result);
|
||||
|
||||
// Show notification
|
||||
if (window.showNotification) {
|
||||
window.showNotification('Note added to inventory', 'success');
|
||||
} else if (window.gameAlert) {
|
||||
window.gameAlert('Note added to inventory', 'success', 'Item Collected', 3000);
|
||||
}
|
||||
} else {
|
||||
console.log('NOTES COMPLETED - Not added to inventory');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
console.log('Starting minigame with params:', params);
|
||||
window.MinigameFramework.startMinigame('notes', null, params);
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
// Debug system variables
|
||||
let debugMode = false;
|
||||
let debugLevel = 1; // 1 = basic, 2 = detailed, 3 = verbose
|
||||
let visualDebugMode = false;
|
||||
let visualDebugMode = false; // Visual debug (collision boxes, movement vectors) - off by default
|
||||
|
||||
// Initialize the debug system
|
||||
export function initializeDebugSystem() {
|
||||
@@ -13,18 +13,10 @@ export function initializeDebugSystem() {
|
||||
// Toggle debug mode with backtick
|
||||
if (event.key === '`') {
|
||||
if (event.shiftKey) {
|
||||
// Toggle visual debug mode with Shift+backtick
|
||||
visualDebugMode = !visualDebugMode;
|
||||
console.log(`%c[DEBUG] === VISUAL DEBUG MODE ${visualDebugMode ? 'ENABLED' : 'DISABLED'} ===`,
|
||||
`color: ${visualDebugMode ? '#00AA00' : '#DD0000'}; font-weight: bold;`);
|
||||
|
||||
// Update physics debug display if game exists
|
||||
if (window.game && window.game.scene && window.game.scene.scenes && window.game.scene.scenes[0]) {
|
||||
const scene = window.game.scene.scenes[0];
|
||||
if (scene.physics && scene.physics.world) {
|
||||
scene.physics.world.drawDebug = debugMode && visualDebugMode;
|
||||
}
|
||||
}
|
||||
// Toggle console debug mode with Shift+backtick
|
||||
debugMode = !debugMode;
|
||||
console.log(`%c[DEBUG] === CONSOLE DEBUG MODE ${debugMode ? 'ENABLED' : 'DISABLED'} ===`,
|
||||
`color: ${debugMode ? '#00AA00' : '#DD0000'}; font-weight: bold;`);
|
||||
} else if (event.ctrlKey) {
|
||||
// Cycle through debug levels with Ctrl+backtick
|
||||
if (debugMode) {
|
||||
@@ -33,18 +25,13 @@ export function initializeDebugSystem() {
|
||||
`color: #0077FF; font-weight: bold;`);
|
||||
}
|
||||
} else {
|
||||
// Regular debug mode toggle
|
||||
debugMode = !debugMode;
|
||||
console.log(`%c[DEBUG] === DEBUG MODE ${debugMode ? 'ENABLED' : 'DISABLED'} ===`,
|
||||
`color: ${debugMode ? '#00AA00' : '#DD0000'}; font-weight: bold;`);
|
||||
// Regular backtick toggles visual debug mode (collision boxes, movement vectors)
|
||||
visualDebugMode = !visualDebugMode;
|
||||
console.log(`%c[DEBUG] === VISUAL DEBUG MODE ${visualDebugMode ? 'ENABLED' : 'DISABLED'} ===`,
|
||||
`color: ${visualDebugMode ? '#00AA00' : '#DD0000'}; font-weight: bold;`);
|
||||
|
||||
// Update physics debug display if game exists
|
||||
if (window.game && window.game.scene && window.game.scene.scenes && window.game.scene.scenes[0]) {
|
||||
const scene = window.game.scene.scenes[0];
|
||||
if (scene.physics && scene.physics.world) {
|
||||
scene.physics.world.drawDebug = debugMode && visualDebugMode;
|
||||
}
|
||||
}
|
||||
updatePhysicsDebugDisplay();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -52,6 +39,17 @@ export function initializeDebugSystem() {
|
||||
console.log('Debug system initialized');
|
||||
}
|
||||
|
||||
// Function to update physics debug display
|
||||
function updatePhysicsDebugDisplay() {
|
||||
if (window.game && window.game.scene && window.game.scene.scenes && window.game.scene.scenes[0]) {
|
||||
const scene = window.game.scene.scenes[0];
|
||||
if (scene.physics && scene.physics.world) {
|
||||
// Visual debug (collision boxes, movement vectors) is controlled by visualDebugMode only
|
||||
scene.physics.world.drawDebug = visualDebugMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Debug logging function that only logs when debug mode is active
|
||||
export function debugLog(message, data = null, level = 1) {
|
||||
if (!debugMode || debugLevel < level) return;
|
||||
@@ -101,5 +99,11 @@ export function debugLog(message, data = null, level = 1) {
|
||||
}
|
||||
}
|
||||
|
||||
// Function to initialize physics debug display (called when game starts)
|
||||
export function initializePhysicsDebugDisplay() {
|
||||
updatePhysicsDebugDisplay();
|
||||
}
|
||||
|
||||
// Export for global access
|
||||
window.debugLog = debugLog;
|
||||
window.debugLog = debugLog;
|
||||
window.initializePhysicsDebugDisplay = initializePhysicsDebugDisplay;
|
||||
@@ -232,7 +232,16 @@ export function handleObjectInteraction(sprite) {
|
||||
if (data.readable && data.text) {
|
||||
message += `Text: ${data.text}\n`;
|
||||
|
||||
// Add readable text as a note
|
||||
// For notes type objects, use the notes minigame
|
||||
if (data.type === 'notes' && data.text) {
|
||||
// Start the notes minigame
|
||||
if (window.startNotesMinigame) {
|
||||
window.startNotesMinigame(sprite, data.text, data.observations);
|
||||
return; // Exit early since minigame handles the interaction
|
||||
}
|
||||
}
|
||||
|
||||
// Add readable text as a note (fallback for other readable objects)
|
||||
if (data.text.trim().length > 0) {
|
||||
const addedNote = window.addNote(data.name, data.text, data.important || false);
|
||||
|
||||
|
||||
@@ -193,4 +193,5 @@ function addToInventory(sprite) {
|
||||
|
||||
// Export for global access
|
||||
window.initializeInventory = initializeInventory;
|
||||
window.processInitialInventoryItems = processInitialInventoryItems;
|
||||
window.processInitialInventoryItems = processInitialInventoryItems;
|
||||
window.addToInventory = addToInventory;
|
||||
@@ -12,8 +12,16 @@ export function introduceScenario() {
|
||||
// Add scenario brief as an important note
|
||||
addNote("Mission Brief", gameScenario.scenario_brief, true);
|
||||
|
||||
// Show notification
|
||||
gameAlert(gameScenario.scenario_brief, 'info', 'Mission Brief', 0);
|
||||
// Show mission brief via notes minigame if available, otherwise fallback to alert
|
||||
if (window.showMissionBrief) {
|
||||
// Delay slightly to ensure the game is fully loaded
|
||||
setTimeout(() => {
|
||||
window.showMissionBrief();
|
||||
}, 500);
|
||||
} else {
|
||||
// Fallback to old alert system
|
||||
gameAlert(gameScenario.scenario_brief, 'info', 'Mission Brief', 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Import crypto workstation functions
|
||||
|
||||
204
test-notes-features.html
Normal file
204
test-notes-features.html
Normal file
@@ -0,0 +1,204 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Notes Minigame Features Test</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 20px;
|
||||
background: #1a1a1a;
|
||||
color: white;
|
||||
}
|
||||
.test-section {
|
||||
margin: 20px 0;
|
||||
padding: 15px;
|
||||
border: 1px solid #444;
|
||||
border-radius: 5px;
|
||||
}
|
||||
button {
|
||||
background: #3498db;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
margin: 5px;
|
||||
}
|
||||
button:hover {
|
||||
background: #2980b9;
|
||||
}
|
||||
.test-notes {
|
||||
background: #2c3e50;
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
border-radius: 3px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Notes Minigame Features Test</h1>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>Test Mission Brief</h2>
|
||||
<p>Test the mission brief functionality:</p>
|
||||
<button onclick="testMissionBrief()">Show Mission Brief</button>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>Test Notes with Observations</h2>
|
||||
<p>Test notes with observations, search functionality, and editing:</p>
|
||||
<button onclick="addTestNotes()">Add Test Notes</button>
|
||||
<button onclick="testNotesMinigame()">Open Notes Minigame</button>
|
||||
<p><small>Features to test: Edit observations, celotape effect, search, navigation</small></p>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>Current Notes</h2>
|
||||
<div id="notes-display"></div>
|
||||
</div>
|
||||
|
||||
<!-- Load the minigame framework -->
|
||||
<script type="module">
|
||||
// Import the minigame framework
|
||||
import { MinigameFramework, showMissionBrief, startNotesMinigame } from './js/minigames/index.js';
|
||||
|
||||
// Make functions available globally for testing
|
||||
window.showMissionBrief = showMissionBrief;
|
||||
window.startNotesMinigame = startNotesMinigame;
|
||||
|
||||
// Initialize game state
|
||||
window.gameState = {
|
||||
notes: []
|
||||
};
|
||||
|
||||
// Mock game scenario
|
||||
window.gameScenario = {
|
||||
scenario_brief: `MISSION BRIEF: CYBER SECURITY BREACH INVESTIGATION
|
||||
|
||||
You are a cybersecurity expert called in to investigate a potential data breach at TechCorp Industries.
|
||||
|
||||
OBJECTIVES:
|
||||
- Investigate suspicious network activity
|
||||
- Identify the source of the breach
|
||||
- Recover any compromised data
|
||||
- Document findings for legal proceedings
|
||||
|
||||
INTEL:
|
||||
- Unusual network traffic detected at 2:47 AM
|
||||
- Multiple failed login attempts from unknown IPs
|
||||
- Employee reports of system slowdowns
|
||||
- CEO's laptop may contain critical evidence
|
||||
|
||||
APPROACH:
|
||||
- Start in the reception area
|
||||
- Gather information from available systems
|
||||
- Look for physical evidence
|
||||
- Document everything you find
|
||||
|
||||
Remember: Time is critical. The longer the breach goes unaddressed, the more data could be compromised.`
|
||||
};
|
||||
|
||||
// Mock addNote function
|
||||
window.addNote = function(title, text, important = false) {
|
||||
const note = {
|
||||
title: title,
|
||||
text: text,
|
||||
important: important,
|
||||
timestamp: new Date().toISOString()
|
||||
};
|
||||
window.gameState.notes.push(note);
|
||||
updateNotesDisplay();
|
||||
return note;
|
||||
};
|
||||
|
||||
// Mock addToInventory function
|
||||
window.addToInventory = function(item) {
|
||||
console.log('Added to inventory:', item);
|
||||
return true;
|
||||
};
|
||||
|
||||
// Mock notification functions
|
||||
window.showNotification = function(message, type) {
|
||||
console.log(`Notification [${type}]: ${message}`);
|
||||
};
|
||||
|
||||
window.gameAlert = function(message, type, title, duration) {
|
||||
console.log(`Alert [${type}] ${title}: ${message}`);
|
||||
};
|
||||
|
||||
function updateNotesDisplay() {
|
||||
const display = document.getElementById('notes-display');
|
||||
display.innerHTML = '';
|
||||
|
||||
window.gameState.notes.forEach((note, index) => {
|
||||
const noteDiv = document.createElement('div');
|
||||
noteDiv.className = 'test-notes';
|
||||
noteDiv.innerHTML = `
|
||||
<strong>${note.title}</strong> ${note.important ? '(Important)' : ''}
|
||||
<br><small>${note.text.substring(0, 100)}...</small>
|
||||
`;
|
||||
display.appendChild(noteDiv);
|
||||
});
|
||||
}
|
||||
|
||||
// Test functions
|
||||
window.testMissionBrief = function() {
|
||||
console.log('Testing mission brief...');
|
||||
window.showMissionBrief();
|
||||
};
|
||||
|
||||
window.addTestNotes = function() {
|
||||
// Add some test notes with observations
|
||||
window.addNote("Security Log Entry #1",
|
||||
"System accessed at 2:47 AM from IP 192.168.1.100\nMultiple failed login attempts detected\nUser: admin\nStatus: BLOCKED\n\nObservation: The handwriting appears rushed and there are coffee stains on the paper.",
|
||||
true);
|
||||
|
||||
window.addNote("Employee Report",
|
||||
"Sarah Johnson reports system slowdowns starting around 2:30 AM\nScreens freezing intermittently\nNetwork connection unstable\n\nObservation: The note is written in neat handwriting with a blue pen.",
|
||||
false);
|
||||
|
||||
window.addNote("Network Analysis",
|
||||
"Traffic analysis shows unusual patterns\nHigh bandwidth usage during off-hours\nMultiple connection attempts to external servers\n\nObservation: This appears to be printed from a system log.",
|
||||
true);
|
||||
|
||||
window.addNote("CEO Laptop Access",
|
||||
"Laptop found in CEO's office\nPassword protected\nContains sensitive financial data\n\nObservation: The laptop shows signs of recent use - warm to the touch.",
|
||||
true);
|
||||
|
||||
// Add a note without observations to test the edit functionality
|
||||
window.addNote("Suspicious Activity",
|
||||
"Found unusual files in the temp directory\nFiles appear to be encrypted\nCreated around 2:45 AM\nNo legitimate user activity at that time",
|
||||
true);
|
||||
|
||||
updateNotesDisplay();
|
||||
};
|
||||
|
||||
window.testNotesMinigame = function() {
|
||||
if (window.gameState.notes.length === 0) {
|
||||
alert('Please add test notes first!');
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a test item for the first note
|
||||
const firstNote = window.gameState.notes[0];
|
||||
const testItem = {
|
||||
scene: null,
|
||||
scenarioData: {
|
||||
type: 'notes',
|
||||
name: firstNote.title,
|
||||
text: firstNote.text,
|
||||
important: firstNote.important
|
||||
}
|
||||
};
|
||||
|
||||
window.startNotesMinigame(testItem, firstNote.text, '');
|
||||
};
|
||||
|
||||
// Initialize
|
||||
updateNotesDisplay();
|
||||
console.log('Notes minigame test page loaded');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user