mirror of
https://github.com/cliffe/BreakEscape.git
synced 2026-02-22 03:38:03 +00:00
feat: Update minigame controls to use "Notepad" terminology and enhance NPC system initialization
This commit is contained in:
16
js/main.js
16
js/main.js
@@ -13,9 +13,9 @@ import './minigames/index.js';
|
||||
|
||||
// Import NPC systems
|
||||
import './systems/ink/ink-engine.js?v=1';
|
||||
import './systems/npc-events.js?v=1';
|
||||
import './systems/npc-manager.js?v=1';
|
||||
import './systems/npc-barks.js?v=1';
|
||||
import NPCEventDispatcher from './systems/npc-events.js?v=1';
|
||||
import NPCManager from './systems/npc-manager.js?v=1';
|
||||
import NPCBarkSystem from './systems/npc-barks.js?v=1';
|
||||
|
||||
// Global game variables
|
||||
window.game = null;
|
||||
@@ -74,6 +74,16 @@ function initializeGame() {
|
||||
// Bluetooth scanner and biometrics are now handled as minigames
|
||||
|
||||
// Initialize NPC systems
|
||||
console.log('🎭 Initializing NPC systems...');
|
||||
window.eventDispatcher = new NPCEventDispatcher();
|
||||
window.barkSystem = new NPCBarkSystem();
|
||||
window.npcManager = new NPCManager(window.eventDispatcher, window.barkSystem);
|
||||
|
||||
// Start timed message system
|
||||
window.npcManager.startTimedMessages();
|
||||
|
||||
console.log('✅ NPC systems initialized');
|
||||
|
||||
if (window.npcBarkSystem) {
|
||||
window.npcBarkSystem.init();
|
||||
}
|
||||
|
||||
@@ -43,13 +43,14 @@ export class ContainerMinigame extends MinigameScene {
|
||||
`;
|
||||
}
|
||||
|
||||
// Add notebook button to minigame controls if postit note exists
|
||||
// Add notebook button to minigame controls if postit note exists (before cancel button)
|
||||
if (this.controlsElement && this.containerItem.scenarioData.postitNote && this.containerItem.scenarioData.showPostit) {
|
||||
const notebookBtn = document.createElement('button');
|
||||
notebookBtn.className = 'minigame-button';
|
||||
notebookBtn.id = 'minigame-notebook-postit';
|
||||
notebookBtn.innerHTML = '<img src="assets/icons/notes-sm.png" alt="Notebook" class="icon-small"> Add to Notebook';
|
||||
this.controlsElement.appendChild(notebookBtn);
|
||||
notebookBtn.innerHTML = '<img src="assets/icons/notes-sm.png" alt="Notepad" class="icon-small"> Add to Notepad';
|
||||
// Insert before the cancel button (first child in controls)
|
||||
this.controlsElement.insertBefore(notebookBtn, this.controlsElement.firstChild);
|
||||
}
|
||||
|
||||
// Create the container minigame UI
|
||||
@@ -248,7 +249,7 @@ export class ContainerMinigame extends MinigameScene {
|
||||
this.addEventListener(closeBtn, 'click', () => this.complete(false));
|
||||
}
|
||||
|
||||
// Add to Notebook button
|
||||
// Add to Notepad button
|
||||
const addToNotebookBtn = document.getElementById('minigame-notebook-postit');
|
||||
if (addToNotebookBtn) {
|
||||
this.addEventListener(addToNotebookBtn, 'click', () => this.addPostitToNotebook());
|
||||
@@ -424,10 +425,10 @@ export class ContainerMinigame extends MinigameScene {
|
||||
false
|
||||
);
|
||||
|
||||
this.showMessage("Added postit note to notebook", 'success');
|
||||
this.showMessage("Added postit note to notepad", 'success');
|
||||
} else {
|
||||
console.error('Notes minigame not available');
|
||||
this.showMessage('Notebook not available', 'error');
|
||||
this.showMessage('Notepad not available', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,8 +41,9 @@ export class PasswordMinigame extends MinigameScene {
|
||||
const notebookBtn = document.createElement('button');
|
||||
notebookBtn.className = 'minigame-button';
|
||||
notebookBtn.id = 'minigame-notebook-postit';
|
||||
notebookBtn.innerHTML = '<img src="assets/icons/notes-sm.png" alt="Notebook" class="icon-small"> Add to Notebook';
|
||||
this.controlsElement.appendChild(notebookBtn);
|
||||
notebookBtn.innerHTML = '<img src="assets/icons/notes-sm.png" alt="Notepad" class="icon-small"> Add to Notepad';
|
||||
// Insert before the cancel button (first child in controls)
|
||||
this.controlsElement.insertBefore(notebookBtn, this.controlsElement.firstChild);
|
||||
}
|
||||
|
||||
// Set up event listeners
|
||||
@@ -503,9 +504,9 @@ export class PasswordMinigame extends MinigameScene {
|
||||
false
|
||||
);
|
||||
|
||||
this.showSuccess("Added postit note to notebook", false, 2000);
|
||||
this.showSuccess("Added postit note to notepad", false, 2000);
|
||||
} else {
|
||||
this.showFailure("Notebook not available", false, 2000);
|
||||
this.showFailure("Notepad not available", false, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,11 @@ export class PhoneChatMinigame extends MinigameScene {
|
||||
* Initialize the minigame UI and components
|
||||
*/
|
||||
init() {
|
||||
// Set cancelText to "Close" before calling parent init
|
||||
if (!this.params.cancelText) {
|
||||
this.params.cancelText = 'Close';
|
||||
}
|
||||
|
||||
// Call parent init to set up basic structure
|
||||
super.init();
|
||||
|
||||
@@ -80,10 +85,30 @@ export class PhoneChatMinigame extends MinigameScene {
|
||||
this.ui = new PhoneChatUI(this.gameContainer, safeParams, this.npcManager);
|
||||
this.ui.render();
|
||||
|
||||
// Add notebook button to minigame controls (before close button)
|
||||
if (this.controlsElement) {
|
||||
const notebookBtn = document.createElement('button');
|
||||
notebookBtn.className = 'minigame-button';
|
||||
notebookBtn.id = 'minigame-notebook';
|
||||
notebookBtn.innerHTML = '<img src="assets/icons/notes-sm.png" alt="Notepad" class="icon-small"> Add to Notepad';
|
||||
// Insert before the cancel/close button
|
||||
const cancelBtn = this.controlsElement.querySelector('#minigame-cancel');
|
||||
if (cancelBtn) {
|
||||
this.controlsElement.insertBefore(notebookBtn, cancelBtn);
|
||||
} else {
|
||||
this.controlsElement.appendChild(notebookBtn);
|
||||
}
|
||||
}
|
||||
|
||||
// Set up event listeners
|
||||
this.setupEventListeners();
|
||||
|
||||
console.log('✅ PhoneChatMinigame initialized');
|
||||
|
||||
// Call onInit callback if provided (used for returning from notes)
|
||||
if (safeParams.onInit && typeof safeParams.onInit === 'function') {
|
||||
safeParams.onInit(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,6 +129,20 @@ export class PhoneChatMinigame extends MinigameScene {
|
||||
this.closeConversation();
|
||||
});
|
||||
|
||||
// Notepad button (context-aware: saves contact list or conversation)
|
||||
const notebookBtn = document.getElementById('minigame-notebook');
|
||||
if (notebookBtn) {
|
||||
this.addEventListener(notebookBtn, 'click', () => {
|
||||
// Check which view is currently active
|
||||
const currentView = this.ui.getCurrentView();
|
||||
if (currentView === 'conversation' && this.currentNPCId) {
|
||||
this.saveConversationToNotepad();
|
||||
} else {
|
||||
this.saveContactListToNotepad();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Choice button clicks
|
||||
this.addEventListener(this.ui.elements.choicesContainer, 'click', (e) => {
|
||||
const choiceButton = e.target.closest('.choice-button');
|
||||
@@ -478,6 +517,140 @@ export class PhoneChatMinigame extends MinigameScene {
|
||||
this.ui.showContactList(this.phoneId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save contact list to notepad
|
||||
*/
|
||||
saveContactListToNotepad() {
|
||||
console.log('📝 Saving contact list to notepad');
|
||||
|
||||
if (!this.npcManager || !window.startNotesMinigame) {
|
||||
console.warn('Cannot save to notepad: missing dependencies');
|
||||
return;
|
||||
}
|
||||
|
||||
// Get all NPCs for this phone
|
||||
const npcs = this.npcManager.getNPCsByPhone(this.phoneId);
|
||||
|
||||
if (!npcs || npcs.length === 0) {
|
||||
console.warn('No contacts to save');
|
||||
return;
|
||||
}
|
||||
|
||||
// Format contact list
|
||||
let content = `CONTACTS\n`;
|
||||
content += `${'='.repeat(30)}\n\n`;
|
||||
|
||||
npcs.forEach(npc => {
|
||||
const unreadCount = this.history ? this.history.getUnreadCount() : 0;
|
||||
const statusText = unreadCount > 0 ? ` (${unreadCount} unread)` : '';
|
||||
content += `• ${npc.displayName || npc.id}${statusText}\n`;
|
||||
});
|
||||
|
||||
content += `\n${'='.repeat(30)}\n`;
|
||||
content += `Phone: ${this.params.title || 'Phone'}\n`;
|
||||
content += `Date: ${new Date().toLocaleString()}`;
|
||||
|
||||
// Store phone state for return
|
||||
window.pendingPhoneReturn = {
|
||||
phoneId: this.phoneId,
|
||||
title: this.params.title,
|
||||
params: this.params
|
||||
};
|
||||
|
||||
// Create note item
|
||||
const noteItem = {
|
||||
scenarioData: {
|
||||
type: 'note',
|
||||
name: 'Contact List',
|
||||
text: content,
|
||||
observations: `Contact list from ${this.params.title || 'phone'}.`
|
||||
}
|
||||
};
|
||||
|
||||
// Start notes minigame
|
||||
window.startNotesMinigame(
|
||||
noteItem,
|
||||
content,
|
||||
`Contact list from ${this.params.title || 'phone'}.`,
|
||||
null,
|
||||
false,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save current conversation to notepad
|
||||
*/
|
||||
saveConversationToNotepad() {
|
||||
console.log('📝 Saving conversation to notepad');
|
||||
|
||||
if (!this.currentNPCId || !this.history || !window.startNotesMinigame) {
|
||||
console.warn('Cannot save conversation: no active conversation or missing dependencies');
|
||||
return;
|
||||
}
|
||||
|
||||
const npc = this.npcManager.getNPC(this.currentNPCId);
|
||||
if (!npc) {
|
||||
console.warn('Cannot find NPC for conversation');
|
||||
return;
|
||||
}
|
||||
|
||||
// Get conversation history
|
||||
const messages = this.history.loadHistory();
|
||||
|
||||
if (!messages || messages.length === 0) {
|
||||
console.warn('No messages to save');
|
||||
return;
|
||||
}
|
||||
|
||||
// Format conversation
|
||||
const npcName = npc.displayName || npc.id;
|
||||
let content = `CONVERSATION WITH ${npcName.toUpperCase()}\n`;
|
||||
content += `${'='.repeat(30)}\n\n`;
|
||||
|
||||
messages.forEach(message => {
|
||||
if (message.type === 'npc') {
|
||||
content += `${npcName}: ${message.text}\n\n`;
|
||||
} else if (message.type === 'player') {
|
||||
content += `You: ${message.text}\n\n`;
|
||||
} else if (message.type === 'choice') {
|
||||
content += `> ${message.text}\n\n`;
|
||||
}
|
||||
});
|
||||
|
||||
content += `${'='.repeat(30)}\n`;
|
||||
content += `Phone: ${this.params.title || 'Phone'}\n`;
|
||||
content += `Date: ${new Date().toLocaleString()}`;
|
||||
|
||||
// Store phone state for return
|
||||
window.pendingPhoneReturn = {
|
||||
phoneId: this.phoneId,
|
||||
title: this.params.title,
|
||||
params: this.params,
|
||||
returnToNPC: this.currentNPCId // Remember which conversation to return to
|
||||
};
|
||||
|
||||
// Create note item
|
||||
const noteItem = {
|
||||
scenarioData: {
|
||||
type: 'note',
|
||||
name: `Chat: ${npcName}`,
|
||||
text: content,
|
||||
observations: `Conversation history with ${npcName}.`
|
||||
}
|
||||
};
|
||||
|
||||
// Start notes minigame
|
||||
window.startNotesMinigame(
|
||||
noteItem,
|
||||
content,
|
||||
`Conversation history with ${npcName}.`,
|
||||
null,
|
||||
false,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the minigame
|
||||
* @param {boolean} success - Whether minigame was successful
|
||||
@@ -527,10 +700,22 @@ export function returnToPhoneAfterNotes() {
|
||||
|
||||
// Restart the phone-chat minigame with the saved state
|
||||
if (window.MinigameFramework) {
|
||||
window.MinigameFramework.startMinigame('phone-chat', null, phoneState.params || {
|
||||
const params = phoneState.params || {
|
||||
phoneId: phoneState.phoneId || 'default_phone',
|
||||
title: phoneState.title || 'Phone'
|
||||
});
|
||||
};
|
||||
|
||||
// If we need to return to a specific conversation, add callback
|
||||
if (phoneState.returnToNPC) {
|
||||
params.onInit = (minigame) => {
|
||||
// Wait a bit for UI to render, then open the conversation
|
||||
setTimeout(() => {
|
||||
minigame.openConversation(phoneState.returnToNPC);
|
||||
}, 100);
|
||||
};
|
||||
}
|
||||
|
||||
window.MinigameFramework.startMinigame('phone-chat', null, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ export class TextFileMinigame extends MinigameScene {
|
||||
const notebookBtn = document.createElement('button');
|
||||
notebookBtn.className = 'minigame-button';
|
||||
notebookBtn.id = 'minigame-notebook';
|
||||
notebookBtn.innerHTML = '<img src="assets/icons/notes-sm.png" alt="Notebook" class="icon-small"> Add to Notebook';
|
||||
notebookBtn.innerHTML = '<img src="assets/icons/notes-sm.png" alt="Notepad" class="icon-small"> Add to Notepad';
|
||||
this.controlsElement.appendChild(notebookBtn);
|
||||
|
||||
// Change cancel button text to "Close"
|
||||
@@ -284,7 +284,7 @@ export class TextFileMinigame extends MinigameScene {
|
||||
addToNotebook() {
|
||||
// Check if there's content to add
|
||||
if (!this.textFileData.fileContent || this.textFileData.fileContent.trim() === '') {
|
||||
this.showFailure("No content to add to notebook", false, 2000);
|
||||
this.showFailure("No content to add to notepad", false, 2000);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -331,7 +331,7 @@ export class TextFileMinigame extends MinigameScene {
|
||||
|
||||
this.showSuccess("Added file content to notebook", false, 2000);
|
||||
} else {
|
||||
this.showFailure("Notebook not available", false, 2000);
|
||||
this.showFailure("Notepad not available", false, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -527,16 +527,28 @@ export function handleObjectInteraction(sprite) {
|
||||
|
||||
// For phone type objects, use phone-chat with runtime conversion
|
||||
if (data.type === 'phone' && (data.text || data.voice)) {
|
||||
console.log('Phone object detected:', { type: data.type, text: data.text, voice: data.voice });
|
||||
console.log('Phone object detected:', { type: data.type, text: data.text, voice: data.voice, npcIds: data.npcIds });
|
||||
|
||||
// Check if phone-chat system is available
|
||||
if (window.MinigameFramework && window.npcManager) {
|
||||
// Import the converter
|
||||
const phoneId = data.phoneId || 'default_phone';
|
||||
|
||||
// Check if phone has already been converted (has npcIds)
|
||||
if (data.npcIds && data.npcIds.length > 0) {
|
||||
console.log('Phone already converted, opening phone-chat directly');
|
||||
// Phone already has NPCs, open directly
|
||||
window.MinigameFramework.startMinigame('phone-chat', null, {
|
||||
phoneId: phoneId,
|
||||
title: data.name || 'Phone'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Need to convert - import the converter
|
||||
import('../utils/phone-message-converter.js').then(module => {
|
||||
const PhoneMessageConverter = module.default;
|
||||
|
||||
// Convert simple message to virtual NPC
|
||||
const phoneId = data.phoneId || 'default_phone';
|
||||
const npcId = PhoneMessageConverter.convertAndRegister(data, window.npcManager);
|
||||
|
||||
if (npcId) {
|
||||
|
||||
Reference in New Issue
Block a user