25 KiB
NPC Implementation Progress
Completed (Phase 1: Core Infrastructure)
✅ Directory Structure
assets/vendor/- Moved ink.js libraryassets/npc/avatars/- Placeholder avatars (npc_alice.png, npc_bob.png)assets/npc/sounds/- Sound directory createdjs/systems/ink/- Ink engine modulejs/minigames/phone-chat/- Phone chat minigame directoryscenarios/ink/- Source Ink scriptsscenarios/compiled/- Compiled Ink JSON files
✅ Core Systems Implemented
-
InkEngine (
js/systems/ink/ink-engine.js) - Enhanced- Load/parse compiled Ink JSON
- Navigate to knots
- Continue dialogue (returns structured result: {text, choices, canContinue})
- Make choices
- Get/set variables with value unwrapping
- Tag parsing support
- Status: Tested and working ✅
-
NPCEventDispatcher (
js/systems/npc-events.js) - Complete- Event emission and listening
- Pattern matching (wildcards supported)
- Cooldown system
- Event queue processing
- Priority-based listener sorting
- Event history tracking
- Debug mode
- Status: Tested and working ✅
-
NPCManager (
js/systems/npc-manager.js) - Enhanced with auto-mapping- NPC registration
- Event → Knot auto-mapping ✅
- Automatic bark triggers on game events
- Support for once-only events
- Configurable cooldowns (default 5s)
- Conditional triggers via functions
- Pattern matching support (e.g.,
item_picked_up:*)
- Conversation state management
- Conversation history tracking
- Current knot tracking
- Event listener cleanup
- Timed Messages System ✅
- Schedule messages to arrive at specific times
- Automatic bark notifications
- Integration with conversation history
- Integration with InkEngine and BarkSystem
- Status: Complete and tested ✅
-
NPCBarkSystem (
js/systems/npc-barks.js) - Enhanced- Bark notification popups
- Auto-dismiss (4s default)
- Click to open phone chat
- Inline fallback phone UI for testing (no Phaser required)
- Modal overlay with phone-shaped container
- Message rendering (NPC left-aligned, player right-aligned)
- Choice buttons with hover states
- Scrollable conversation history
- Close button
- Dynamic import of MinigameFramework when Phaser available
- HTML sanitization
- Status: Tested and working ✅
✅ Example Stories
- alice-chat.ink - Complete branching dialogue example
- Trust level system (0-5+)
- Conditional choices that appear/disappear
- State tracking (knows_about_breach, has_keycard)
- Once-only topics
- Multiple endings
- Realistic security consultant persona
- Status: Tested and working ✅
✅ Test Harness
test-npc-ink.html- Comprehensive test page- ink.js library verification
- InkEngine story loading/continuation
- Event system testing
- Bark display testing
- Phone chat integration testing
- Auto-trigger testing ✅
- Visual console output
- Status: Complete and functional
In Progress (Phase 2: Game Integration)
🔄 Testing & Verification
- Create test HTML page ✅
- Verify ink.js loads correctly ✅
- Test InkEngine with story JSON ✅
- Test event emission ✅
- Test bark display ✅
- Test NPC Manager registration ✅
- Test inline phone UI ✅
- Test branching dialogue ✅
- Test auto-trigger workflow ✅
- Test phone-chat minigame ✅
- Test conversation history persistence ✅
- Test state save/restore ✅
- Test timed messages system ✅
- Test in main game environment
✅ COMPLETED (Phase 2: Phone Chat Minigame)
✅ Phone Chat Modules
-
PhoneChatHistory (
js/minigames/phone-chat/phone-chat-history.js) - ~270 lines- History management and formatting
- Message tracking and unread counts
- Export/import functionality
- Status: Complete ✅
-
PhoneChatConversation (
js/minigames/phone-chat/phone-chat-conversation.js) - ~370 lines- Ink story integration
- Story loading and navigation
- Choice handling
- State management (save/restore)
- Fixed state serialization issues (removed problematic npc_name variable)
- Status: Complete ✅
-
PhoneChatUI (
js/minigames/phone-chat/phone-chat-ui.js) - ~730 lines- Contact list view with unread badges
- Conversation view with message bubbles
- Choice button rendering
- Typing indicator animation
- Auto-scrolling
- Avatar display in conversation header ✅
- Styled scrollbars (8px, black with green border)
- Voice message support (Web Speech API) ✅
- Clickable play/stop button
- Visual feedback (play ↔ stop icon)
- Pixel-art rendering for icons
- Audio waveform visualization
- Transcript display
- Status: Complete ✅
-
PhoneChatMinigame (
js/minigames/phone-chat/phone-chat-minigame.js) - ~515 lines- Main controller extending MinigameScene
- Orchestrates UI, conversation, history
- Event handling and keyboard shortcuts
- Intro message preloading ✅
- State persistence across conversations ✅
- Prevents intro replay on reopen ✅
- Status: Complete ✅
-
CSS Styling (
css/phone-chat-minigame.css) - ~540 lines- Phone UI with pixel-art aesthetic (matches phone-messages)
- Green LCD screen (#5fcf69), gray shell (#a0a0ad)
- Message bubbles (NPC left, player right)
- Choice buttons
- Styled scrollbars (visible on all platforms)
- Avatar styles (32x32px, pixelated rendering)
- Animations (typing, message slide-in)
- Voice message styles ✅
- Audio controls with play/stop button
- Waveform sprite display (32px height)
- Transcript display with borders
- Pixel-art rendering for all icons
- Hover effects
- Status: Complete ✅
-
Registration - Registered with MinigameFramework as 'phone-chat'
- Status: Complete ✅
📋 Phone Access
- Runtime Message Converter (
js/utils/phone-message-converter.js) ✅- Converts simple text/voice phone messages to Ink JSON at runtime
- Zero changes needed to existing scenario files
- Automatic virtual NPC creation and registration
- Backward compatible with existing phone-messages system
- Auto-adds "voice:" prefix for voice messages ✅
- See
RUNTIME_CONVERSION_SUMMARY.mdfor details
- Voice Message Support ✅
- "voice:" prefix detection in Ink text
- Web Speech API integration (browser TTS)
- Clickable audio controls (play/stop)
- Voice selection (prefers Google/Microsoft voices)
- Configurable speech settings (rate, pitch, volume)
- Pixel-art UI rendering
- See
VOICE_MESSAGES.mdandVOICE_PLAYBACK_FEATURE.mdfor details
- Phone type detection and routing (interactions.js) ✅
- Auto-conversion implemented
- Uses phone-chat exclusively
- Phone button in UI (bottom-right corner)
- Shows total unread count from all sources
- Opens phone-unified with player's phone
- Inventory phone item
- Add phone to startItemsInInventory
- Handle phone item clicks in inventory.js
- Old Phone Minigame Removal ✅
- All features migrated to phone-chat ✅
- Voice message playback (Web Speech API)
- Simple text messages
- Interactive conversations (enhanced with Ink)
- Removed
js/minigames/phone/phone-messages-minigame.js✅ - Updated interactions.js to use phone-chat exclusively ✅
- Removed phone-messages registration from MinigameFramework ✅
- Archived
css/phone.css→css/phone.css.old✅
- All features migrated to phone-chat ✅
- Scenario JSON updates (optional - runtime conversion handles this)
- Add phoneId to phone objects (for grouping)
- Define which NPCs are available on which phones
- Optionally add phone to player's starting inventory
- Documentation:
- ✅
RUNTIME_CONVERSION_SUMMARY.md- Complete runtime conversion guide - ✅
PHONE_MIGRATION_GUIDE.md- Manual migration options - ✅
PHONE_INTEGRATION_PLAN.md- Unified phone strategy - ✅
VOICE_MESSAGES.md- Voice message feature guide - ✅
VOICE_PLAYBACK_FEATURE.md- Web Speech API implementation - ✅
MIXED_PHONE_CONTENT.md- Mixed message patterns - ✅
PHONE_CLEANUP_SUMMARY.md- Old minigame removal documentation - ✅
MIXED_PHONE_CONTENT.md- Simple + interactive messages guide
- ✅
TODO (Phase 3: Additional Events)
📋 Event Emissions
- Door events (door_unlocked, door_locked, door_attempt_failed)
- Minigame events (minigame_completed, minigame_started, minigame_failed)
- Interaction events (object_interacted, fingerprint_collected, bluetooth_device_found)
TODO (Phase 5: Polish & Testing)
📋 Enhancements
- Sound effects (message_received.mp3) ✅ COMPLETE
- Better NPC avatars
- Error handling improvements
- Performance optimization
File Statistics
| File | Lines | Status |
|---|---|---|
| ink-engine.js | 360 | ✅ Complete |
| npc-events.js | 230 | ✅ Complete |
| npc-manager.js | 355 | ✅ Complete |
| npc-barks.js | 355 | ✅ Complete (+75 sounds/avatars) |
| npc-barks.css | 70 | ✅ Complete (+18 avatars) |
| test.ink | 40 | ✅ Complete |
| alice-chat.ink | 180 | ✅ Complete |
| helper-npc.ink | 185 | ✅ Complete (with events) |
| game.js | 800 | ✅ Enhanced (+3 audio) |
| ceo_exfil.json | 450 | ✅ Enhanced (avatars) |
| npc_helper.png | 32x32 | ✅ Created |
| npc_adversary.png | 32x32 | ✅ Created |
| npc_neutral.png | 32x32 | ✅ Created |
| generic-npc.ink | 36 | ✅ Complete |
| phone-chat-history.js | 270 | ✅ Complete |
| phone-chat-conversation.js | 370 | ✅ Complete |
| phone-chat-ui.js | 730 | ✅ Complete |
| phone-chat-minigame.js | 739 | ✅ Complete |
| phone-chat-minigame.css | 540 | ✅ Complete |
| phone-message-converter.js | 150 | ✅ Complete |
| inventory.js | 629 | ✅ Enhanced (badge system) |
| inventory.css | 147 | ✅ Enhanced (badge styling) |
| test-npc-ink.html | ~400 | ✅ Complete |
| test-phone-chat-minigame.html | ~557 | ✅ Complete |
Total implemented: ~6,065 lines across 18 files
Next Steps
Phase 3: Testing & Integration
- ✅ Test phone-chat minigame with test harness
- ✅ Verify Alice's complex branching dialogue
- ✅ Verify Bob's generic NPC story
- ✅ Test conversation history persistence
- ✅ Test multiple NPCs on same phone
- ✅ Test event → bark → phone flow
- ✅ Test timed messages system
- ✅ Fix state serialization issues
- ⏳ Test in main game environment
Phase 4: Game Integration
-
Emit game events from core systems ✅ COMPLETE (2024-10-31)
- Doors system:
door_unlocked,door_unlock_attempt - Items system:
item_picked_up:*(already implemented) - Unlock system:
item_unlocked,door_unlocked,door_unlock_attempt - Minigames:
minigame_completed,minigame_failed - Interactions:
object_interacted - Fixed event dispatcher variable naming (window.eventDispatcher)
- Doors system:
-
Implement NPC → Game State Bridge ✅ COMPLETE (2024-10-31)
- Created
js/systems/npc-game-bridge.js(~420 lines) - Implemented 7 methods:
unlockDoor(),giveItem(),setObjective(),revealSecret(),addNote(),triggerEvent(),discoverRoom() - Added action logging system (last 100 actions)
- Exported global convenience functions
- Added tag parsing in phone-chat minigame (~120 lines)
- Created
processGameActionTags()method with notifications - Fixed item display names (spread operator ordering)
- Created comprehensive documentation:
NPC_GAME_BRIDGE_IMPLEMENTATION.md
- Created
-
Add NPC configs to scenario JSON ✅ COMPLETE (2024-10-31)
- Created
scenarios/ink/helper-npc.inkexample (~145 lines with events) - Added helper_npc to
ceo_exfil.jsonnpcs array - Updated phone npcIds to include helper_npc
- Added 7 event mappings for automatic reactions
- Configured cooldowns and once-only triggers
- Added maxTriggers support for limiting bark frequency
- Created
-
Implement Event-Driven NPC Reactions ✅ COMPLETE (2024-10-31)
- Added 8 event-triggered bark knots to helper-npc.ink
- Configured event mappings with patterns, conditions, cooldowns
- Added event emissions to 4 core game systems
- Fixed event mapping array format handling
- Added condition string evaluation support
- Implemented bark-to-conversation flow (barks redirect to main menu)
- Added isBark flag to distinguish barks from conversations
- Fixed conversation history to ignore bark-only messages
- Created comprehensive documentation:
PHASE_4_EVENT_IMPLEMENTATION.md - Created bark improvements documentation:
BARK_IMPROVEMENTS_SUMMARY.md
-
Test in-game NPC interactions ✅ COMPLETE (2024-10-31)
- Helper NPC available in CEO Exfiltration scenario
- Test event-triggered barks ✅ Working!
- Test NPC unlocking doors via conversation ✅ Working!
- Test NPC giving items via conversation ✅ Working!
- Test clicking barks to reply ✅ Working!
- Test conditional responses based on trust level ✅ Working!
- Verify cooldowns work correctly ✅ Working!
- Verify bark frequency limits (maxTriggers) ✅ Implemented!
-
Polish UI/UX 🔄 IN PROGRESS
- Room navigation events (Priority 2) ✅ COMPLETE (2024-10-31)
- Added
room_entered,room_entered:${roomId},room_discovered,room_exitedevents - Created Ink reaction knots (on_room_discovered, on_ceo_office_entered)
- Added event mappings to scenario JSON
- Fixed conversation flow (main_menu vs start)
- Updated unlock messages to be generic (key or lockpick)
- Fixed conditional text in barks (always return text regardless of trust level)
- Added
- Sound effects (Priority 1) ✅ COMPLETE (2024-10-31)
- Added bark notification sound (
message_received.mp3) - Implemented sound preloading in Phaser
- Added volume control (50% default)
- Added sound enable/disable toggle (
setSoundEnabled()) - Sound plays automatically on all bark notifications
- Timed messages automatically trigger sound (via showBark)
- Consolidated through Phaser's Web Audio API
- Added bark notification sound (
- NPC avatars (Priority 3) ✅ COMPLETE (2024-10-31)
- Created 3 default 32x32px pixel-art avatars:
npc_helper.png- Green shirt, friendly smile (helper NPCs)npc_adversary.png- Red shirt, suspicious frown (adversary NPCs)npc_neutral.png- Gray shirt, neutral expression (neutral NPCs)
- Added avatar display in bark notifications
- Updated bark CSS with flexbox layout and avatar styles
- Updated NPCBarkSystem to render avatars
- Updated scenario JSON with avatar paths
- Avatar images use pixel-perfect rendering (
image-rendering: pixelated)
- Created 3 default 32x32px pixel-art avatars:
- More game events (Priority 2 continued)
- objective_completed event
- evidence_collected event
- player_detected event
- Room navigation events (Priority 2) ✅ COMPLETE (2024-10-31)
-
Performance optimization ⏳ NEXT
- Event listener cleanup on scene changes
- Minimize Ink engine instantiation
- Optimize bark rendering for multiple simultaneous barks
Last Updated: 2024-10-31 (Phase 5 NPC Avatars COMPLETE) Status: Phase 5 Complete - Sound effects ✅, room navigation ✅, avatars ✅
Recent Improvements (2024-10-31 - Phase 5)
✅ NPC Avatars (Priority 3)
- Created 3 default pixel-art avatars (32x32px):
npc_helper.png- Green shirt (#5fcf69), friendly smile, helpful characternpc_adversary.png- Red shirt (#dc3232), suspicious frown, warning characternpc_neutral.png- Gray shirt (#a0a0ad), neutral expression, standard NPC
- Implementation:
scripts/create_npc_avatars.py- Python script using PIL to generate avatarscss/npc-barks.css(+18 lines):- Added flexbox layout to bark notifications
.npc-bark-avatar- 32x32px with pixelated rendering and 2px border.npc-bark-text- Flex text container
js/systems/npc-barks.js(~15 lines modified):- Updated
showBark()to acceptavatarparameter - Creates
<img>element for avatar if provided - Wraps text in
<span>for proper layout
- Updated
scenarios/ceo_exfil.json(3 NPCs updated):- helper_npc →
npc_helper.png(green, friendly) - neye_eve →
npc_adversary.png(red, suspicious) - gossip_girl →
npc_neutral.png(gray, neutral)
- helper_npc →
- Display locations:
- Bark notifications (bottom-left corner)
- Already supported in phone-chat conversation header
- Benefits:
- Visual identification of NPCs at a glance
- Color-coded by relationship (helper=green, adversary=red, neutral=gray)
- Consistent pixel-art aesthetic with game
- Easy to add new avatars (just drop PNG files)
- Avatar paths stored in scenario JSON (configurable per NPC)
✅ Sound Effects (Priority 1)
- Bark notification sounds:
- Uses existing
assets/sounds/message_received.mp3 - Loaded through Phaser's audio system (Web Audio API)
- Preloaded in
game.jspreload function - Accessed via
window.game.sound.add('message_received') - Plays automatically when barks appear
- Volume set to 50% by default
- Sound can be disabled via
setSoundEnabled(false)
- Uses existing
- Implementation:
game.js(+3 lines): Added audio loading in preloadnpc-barks.js(~65 lines): Replaced HTML5 Audio with Phaser sound managerloadBarkSound()- Gets sound from Phaser with lazy loading fallbackplayBarkSound()- Uses Phaser's.play()methodsetSoundEnabled(enabled)- Toggle sound on/off- Automatic playback in
showBark()method
- Benefits:
- Consolidated audio system: All game audio through Phaser
- Better performance (Web Audio API vs HTML5 Audio Tag)
- Sound pooling and memory management handled automatically
- No autoplay policy issues (Phaser handles audio context)
- Unified volume control with game's master volume
- Audio feedback for all bark notifications
- Includes event-triggered barks and timed messages
- No breaking changes (sound enabled by default)
✅ Room Navigation Events (Priority 2)
- Conditional text fix:
- Fixed
on_room_enteredandon_room_discoveredknots - Both knots now always return text (required for barks)
- Added trust level 0 fallback messages
- Nested conditionals to handle all trust levels
- Fixed
- Event emissions in rooms.js:
room_entered- General room change eventroom_entered:${roomId}- Specific room entryroom_discovered- First-time room visitsroom_exited- Leaving a room
- Ink reactions in helper-npc.ink:
on_room_discovered- Generic exploration encouragementon_ceo_office_entered- Special CEO office reaction with trust reward
- Event mappings configured:
room_discoveredwith 15s cooldown, max 5 triggersroom_entered:ceoone-time only reaction
- Conversation flow refinements:
- Split
startandmain_menuknots - Barks redirect to
main_menu(notstart) to avoid repeated greeting - "What can I do for you?" only appears in initial greeting
- Split
- Message updates:
- Unlock messages now generic (work for key or lockpick)
- Lockpicking success bark doesn't assume method
- Documentation created:
NPC_INTEGRATION_GUIDE.md- Comprehensive guide for adding NPCs to scenarios- Includes phone setup, Ink structure, event mappings, testing checklist
Recent Improvements (2025-10-30)
✅ UI Enhancements
- Matched phone-messages aesthetic (green LCD screen, pixel-art borders)
- Added styled scrollbars (8px width, visible on all platforms)
- Added avatar display in conversation header
- Fixed all CSS to maintain 2px borders and no border-radius
✅ Conversation Flow Improvements
- Implemented intro message preloading (messages appear before first open)
- Added state persistence system (conversations resume where they left off)
- Fixed intro message replay bug (state now saves after preload)
- Fixed state serialization issues (removed problematic npc_name variable)
✅ Timed Messages System
- NPCManager can schedule messages at specific times
- Messages bark automatically when triggered
- Messages appear in conversation history
- Scenarios can define timed messages in JSON
- Auto-schedules timed messages from NPC registration
- Badge count updates when timed messages arrive
✅ Phone Badge System (NEW - 2025-10-30)
- Unread message indicator on phone inventory items
- Real DOM element badge (not CSS pseudo-element)
- Green background (#5fcf69) matching phone LCD
- Shows total unread NPC message count
- Updates dynamically as messages are read/received
- Intro message preloading when phone added to inventory
- Creates temporary InkEngine to load NPC stories
- Preloads intro messages from all NPCs on phone
- Badge shows correct count immediately on game load
- Badge update hooks:
- When phone added to inventory
- When phone-chat minigame closes
- When timed messages are delivered
- Exported globally as
window.updatePhoneBadge(phoneId)
- Implementation:
inventory.js- Badge creation and update logicinventory.css- Badge styling (absolute positioned on slot)npc-manager.js- getTotalUnreadCount(phoneId) methodphone-chat-minigame.js- Badge update on close
✅ Bark Notification Redesign (NEW - 2025-10-30)
- Styled like phone message bubbles:
- Green background (#5fcf69) matching phone LCD
- Black text and 2px borders
- VT323 monospace font
- No border-radius (pixel-art aesthetic)
- Positioned above inventory:
- Fixed position at bottom: 80px (above inventory bar)
- Left-aligned at 20px from edge
- Stack vertically with newest at bottom
- Slide-up animation on appear
- Behavior:
- Click to open phone-chat with NPC
- Auto-dismiss after 5 seconds
- Fade-out animation on removal
- Updates badge count when delivered
- Implementation:
npc-barks.css- Simplified styling, removed avatar/close buttonnpc-barks.js- Cleaner showBark() method- Container uses flexbox column-reverse for stacking
✅ Voice Messages & Playback
- Voice message detection via
"voice:"prefix in Ink text - Web Speech API integration for text-to-speech playback
- Clickable audio controls:
- Play button (▶) and stop button (■)
- Audio waveform visualization (32px sprite)
- Side-by-side layout with flexbox
- Voice selection (prefers Google/Microsoft natural voices)
- Configurable settings (rate: 0.9, pitch: 1.0, volume: 0.8)
- Pixel-art rendering for all icons (crisp display)
- Runtime conversion auto-adds "voice:" prefix for old phone objects
- Mixed content support (text + voice in same conversation)
- Created comprehensive documentation:
VOICE_MESSAGES.md- Feature guideVOICE_PLAYBACK_FEATURE.md- Technical implementationVOICE_MESSAGES_SUMMARY.md- Quick referenceVOICE_PLAYBACK_TEST_GUIDE.md- Testing instructionsMIXED_PHONE_CONTENT.md- Mixed message patterns
✅ Feature Parity with Old Phone Minigame
phone-chat now has ALL features from phone-messages-minigame:
- ✅ Voice message playback (Web Speech API)
- ✅ Simple text messages
- ✅ Message history and navigation
- ✅ Green LCD phone UI aesthetic
- ✅ Plus NEW features:
- Interactive Ink-based conversations
- Branching dialogue with choices
- State persistence and variables
- NPC relationship tracking
- Automatic runtime conversion
- Contact list with multiple NPCs
- Timed message delivery
✅ Old Phone Minigame Removed
Successfully removed phone-messages-minigame (completed 2025-10-30):
- ✅ Deleted
js/minigames/phone/phone-messages-minigame.js(~934 lines) - ✅ Removed imports/exports from
js/minigames/index.js - ✅ Removed registration from MinigameFramework
- ✅ Updated
js/systems/interactions.jsto use phone-chat exclusively - ✅ Archived
css/phone.css→css/phone.css.old - ✅ All phone interactions now use phone-chat with runtime conversion
- ✅ No breaking changes - backward compatible with existing scenarios
🐛 Bugs Fixed
- State serialization error (InkJS couldn't serialize npc_name variable)
- Intro message replaying on conversation reopen
- Contact list showing "No messages yet" despite preloaded intros
- Voice message JSON files were 0 bytes (compilation issue)
- Simple message conversion creating duplicate NPCs
- Play button and audio sprite on separate lines (layout issue)
- Icons not using pixel-art rendering (blurry display)
- CSS attr() function not working for badge content (switched to DOM elements)
- InkEngine not available during inventory initialization (now imported directly)
- Phone badge not appearing on initial load (added intro message preloading)
- Timed messages arriving instantly (fixed delay vs triggerTime parameter)
- Badge not updating when timed messages arrive (added updatePhoneBadge call)
📚 Documentation Updated
02_PHONE_CHAT_MINIGAME_PLAN.md- Added timed messages documentation01_IMPLEMENTATION_LOG.md- Updated with latest progress- Created 7 new documentation files for voice messages
- Created example scenarios showing all features