Files
BreakEscape/planning_notes/npc/progress/VOICE_MESSAGES_SUMMARY.md
Z. Cliffe Schreuders f369b41547 feat: Implement voice messages in phone chat minigame
- Added support for voice messages prefixed with "voice:" in Ink files.
- Updated UI rendering to display voice message UI with play button and transcript.
- Implemented automatic conversion for scenario JSON with voice properties.
- Created test examples for pure voice messages and mixed content.
- Fixed issues with NPC registration and message duplication in test scenarios.
- Documented feature details, use cases, and testing procedures.
2025-10-30 02:45:05 +00:00

8.6 KiB

Voice Messages Feature Summary

Implementation Complete

Voice messages are now fully integrated into the phone-chat minigame system!


What Was Changed

1. UI Rendering (js/minigames/phone-chat/phone-chat-ui.js)

Modified: addMessage() method (lines 277-350)

Before:

  • All messages rendered as simple text bubbles

After:

  • Detects "voice:" prefix in message text
  • Renders voice message UI for voice content
  • Renders regular text bubble for normal messages

Code:

const isVoiceMessage = trimmedText.toLowerCase().startsWith('voice:');

if (isVoiceMessage) {
    // Extract transcript
    const transcript = trimmedText.substring(6).trim();
    
    // Render voice UI with play button + waveform + transcript
} else {
    // Render regular text bubble
}

2. Runtime Conversion (js/utils/phone-message-converter.js)

Modified: toInkJSON() method (lines 7-50)

Added:

  • Automatic "voice: " prefix for phoneObject.voice properties

Code:

let messageText = phoneObject.voice || phoneObject.text || '';

// Add "voice: " prefix if this is a voice message
if (phoneObject.voice) {
    messageText = `voice: ${messageText}`;
}

Result: Old scenario JSON with voice property automatically gets voice message UI!

3. Test Examples

Created:

  • scenarios/ink/voice-message-example.ink - Pure voice message
  • scenarios/ink/mixed-message-example.ink - Mix of text and voice
  • scenarios/compiled/voice-message-example.json - Compiled
  • scenarios/compiled/mixed-message-example.json - Compiled

Updated: test-phone-chat-minigame.html

  • Added IT Team NPC (pure voice)
  • Added David NPC (mixed messages)

How to Use

Method 1: Ink Files (Manual)

Write voice: prefix in your Ink story:

=== start ===
voice: This is a voice message from security.
-> END

Method 2: Scenario JSON (Automatic)

Use voice property in phone objects:

{
  "type": "phone",
  "name": "Security Alert",
  "phoneId": "player_phone",
  "voice": "Security breach detected!",
  "sender": "Security Team"
}

Both methods produce the same voice message UI!


Visual Result

Voice Message UI

┌─────────────────────────────────┐
│  ▶️  ~~~~~~~~~~~~~~~~~~~         │  ← Play button + waveform
│                                  │
│  📄 Transcript:                  │
│  Security breach detected in     │  ← Message text
│  server room. Code: 4829.        │
│                                  │
│                          2:18 PM │  ← Timestamp
└─────────────────────────────────┘

Regular Text UI

┌─────────────────────────────────┐
│  Hey! How's it going?            │  ← Plain text
│                          2:18 PM │  ← Timestamp
└─────────────────────────────────┘

Assets Used

All assets already exist in the project:

  • assets/icons/play.png - Play button icon
  • assets/mini-games/audio.png - Audio waveform sprite
  • css/phone.css - Voice message styling (lines 311-370)

No new assets needed!


Testing

Quick Test

  1. Open test-phone-chat-minigame.html
  2. Click "Register Test NPCs"
  3. Click "📱 Open Phone"
  4. Open "IT Team" contact → See voice message UI
  5. Open "David - Tech Support" → See mixed text + voice

Expected Behavior

  • IT Team: Single voice message with waveform
  • David: First message is text, then voice message after choice
  • Both show appropriate UI for each message type

Backward Compatibility

Old Ink Files

Files without voice: prefix still work:

=== start ===
This is a regular message.
-> END

Result: Regular text bubble (unchanged)

Old Scenario JSON

Phone objects with text property:

{"type": "phone", "text": "Hello"}

Result: Regular text bubble

Phone objects with voice property:

{"type": "phone", "voice": "Hello"}

Result: Voice message UI (automatic!)

Existing NPCs

All registered NPCs continue working:

  • Interactive chats unchanged
  • Simple messages work with both text and voice
  • Mixed content supported

Use Cases

Perfect for Voice Messages

  • 🚨 Security alerts: "Emergency! Evacuate floor 3!"
  • 📞 Voicemail: "Hey, call me back when you get this"
  • 🔑 Sensitive info: "The code is 4-8-2-9"
  • 😰 Dramatic moments: "I think someone is following me..."
  • 📋 Instructions: "Go to server room, enter PIN 4829"

Keep as Text

  • 💬 Casual chat: "Hey! What's up?"
  • Questions: "Did you finish the report?"
  • 👍 Quick replies: "Got it, thanks!"
  • 📝 Typed messages: General conversation

Technical Details

Message Flow

  1. Ink Story outputs: "voice: Message here"
  2. phone-chat-minigame.js calls: ui.addMessage('npc', text)
  3. phone-chat-ui.js detects "voice:" prefix
  4. Rendering: Voice UI or text bubble
  5. Display: Appropriate HTML structure

Detection Logic

// Case-insensitive check
const isVoiceMessage = trimmedText.toLowerCase().startsWith('voice:');

// Extract transcript (remove prefix)
const transcript = trimmedText.substring(6).trim();

HTML Structure

<!-- Voice Message -->
<div class="message-bubble npc">
    <div class="voice-message-display">
        <div class="audio-controls">
            <div class="play-button">
                <img src="assets/icons/play.png">
            </div>
            <img src="assets/mini-games/audio.png" class="audio-sprite">
        </div>
        <div class="transcript">
            <strong>Transcript:</strong><br>
            Extracted message text
        </div>
    </div>
    <div class="message-time">2:18</div>
</div>

Advantages

1. Visual Variety

  • Mix text and voice for engaging conversations
  • Different message types convey different meanings
  • More realistic phone experience

2. Zero Configuration

  • Works with existing Ink files
  • No new assets needed
  • Backward compatible
  • Automatic conversion for scenarios

3. Game Design Flexibility

  • Use voice for important/urgent messages
  • Use text for casual conversation
  • Mix both in same conversation
  • Natural storytelling tool

4. Educational Value

  • Demonstrates different communication types
  • Shows security concepts (voice vs text)
  • Realistic cyber-physical scenarios

Current Limitations

What Works

  • Voice message detection via voice: prefix
  • Visual UI with play button + waveform
  • Transcript display
  • Automatic conversion from scenario JSON
  • Mixed text + voice conversations
  • Backward compatibility

Not Implemented (Future)

  • Actual audio playback (decorative only)
  • Animated waveforms
  • Player voice responses
  • Audio file attachments
  • Recording functionality

These are UI enhancements, not core features


Examples

Example 1: Security Alert (Pure Voice)

=== start ===
voice: Security alert! Unauthorized access detected in server room. Changed access code to 4829.
-> END

Example 2: Mixed Conversation

=== start ===
Hey! Thanks for getting back to me.

+ [No problem!]
    voice: I can't type this safely. The director is listening. Meet me at the server room at midnight.
    + + [Got it]
        Perfect. See you then.
        -> END

Example 3: Voicemail Chain

=== start ===
voice: First voicemail - I need to talk to you urgently.

+ [Listen to next message]
    voice: Second voicemail - It's about the security breach. Call me.
    + + [Listen to final message]
        voice: Final message - I found evidence. It's in locker 42.
        -> END

Documentation

Created comprehensive docs:

  • VOICE_MESSAGES.md - Full feature documentation
  • VOICE_MESSAGES_SUMMARY.md - This summary
  • Code comments in phone-chat-ui.js
  • Examples in scenarios/ink/

Summary

What: Voice message UI in phone-chat system

How: Prefix messages with "voice:" in Ink files

Why: Visual variety, realism, game design flexibility

Status: Fully Implemented & Tested

Integration:

  • Works with Ink files (manual prefix)
  • Works with scenario JSON (automatic conversion)
  • Backward compatible with all existing code
  • Zero breaking changes

It just works! 🎤


Version: 1.0
Date: 2025-10-30
Author: GitHub Copilot
Status: Complete