Files
BreakEscape/planning_notes/npc/progress/VOICE_MESSAGES.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

414 lines
9.6 KiB
Markdown

# Voice Messages in Phone Chat
## Overview
The phone-chat minigame now supports **voice messages** alongside regular text messages. When a message starts with `voice:`, it's automatically rendered with a voice message UI instead of a simple text bubble.
---
## Quick Start
### In Ink Files
Simply prefix any message with `voice:`:
```ink
=== start ===
voice: Hi, this is the IT Team. Security breach detected in server room. Changed access code to 4829.
-> END
```
### In Scenario JSON (Auto-Conversion)
The runtime converter automatically adds `voice:` prefix for phone objects with `voice` property:
```json
{
"type": "phone",
"name": "IT Alert",
"phoneId": "player_phone",
"voice": "Security breach detected in server room. Changed access code to 4829.",
"sender": "IT Team"
}
```
**Result**: Automatically converted to voice message UI! ✅
### Result
Instead of a text bubble, the player sees:
- 🎵 Audio waveform visualization
- ▶️ Play button (decorative)
- 📄 Transcript section with the message text
---
## How It Works
### Detection
The `addMessage()` method in `phone-chat-ui.js` checks if text starts with `"voice:"`:
```javascript
const isVoiceMessage = trimmedText.toLowerCase().startsWith('voice:');
```
### Rendering
**Voice messages** get this HTML structure:
```html
<div class="message-bubble npc">
<div class="voice-message-display">
<div class="audio-controls">
<div class="play-button">
<img src="assets/icons/play.png" alt="Audio" class="icon">
</div>
<img src="assets/mini-games/audio.png" alt="Audio" class="audio-sprite">
</div>
<div class="transcript">
<strong>Transcript:</strong><br>
Message text here
</div>
</div>
<div class="message-time">2:18</div>
</div>
```
**Regular messages** get standard text bubble:
```html
<div class="message-bubble npc">
<div class="message-text">Message text here</div>
<div class="message-time">2:18</div>
</div>
```
---
## Ink Compatibility
### Is "voice:" Compatible with Ink?
**YES!** ✅ It's just text content.
- Ink treats `voice: ...` as plain text content
- No special Ink syntax required
- Works in any knot, stitch, or branch
- Compatible with choices, conditionals, etc.
### Example 1: Simple Voice Message
```ink
=== start ===
voice: This is a voice message from security.
-> END
```
### Example 2: Mixed Content
```ink
=== start ===
Hello! This is a regular text message.
+ [Tell me more]
-> voice_response
=== voice_response ===
voice: Here's a voice message with sensitive information. The code is 4829.
+ [Got it!]
Great, talk soon!
-> END
```
### Example 3: Multiple Voice Messages
```ink
=== start ===
voice: First voice message here.
+ [Continue]
voice: Second voice message follows the first.
+ + [Understood]
Perfect! All done.
-> END
```
---
## Use Cases
### 1. Security Alerts
```ink
voice: Security alert: Unauthorized access detected in server room at 02:15 AM.
```
✅ Makes alerts feel more urgent and official
### 2. Voicemail Messages
```ink
voice: Hey, it's the director. I need you to investigate the breach ASAP. Call me when you find something.
```
✅ Realistic voicemail experience
### 3. Sensitive Information
```ink
voice: The access code is 5-9-2-3. I repeat: five, nine, two, three. Memorize this.
```
✅ Important codes feel more secure
### 4. Emotional Moments
```ink
voice: I'm scared... I think someone is following me. Please come quickly.
```
✅ Voice adds emotional weight
### 5. Technical Instructions
```ink
voice: Navigate to the server room, enter PIN 4829, then disable the firewall using the admin console.
```
✅ Step-by-step instructions feel clearer
---
## Runtime Conversion
### Automatic Voice Detection
The `PhoneMessageConverter` automatically adds `voice:` prefix when converting simple messages:
```javascript
// In phone-message-converter.js
static toInkJSON(phoneObject) {
let messageText = phoneObject.voice || phoneObject.text || '';
// Add "voice: " prefix if this is a voice message
if (phoneObject.voice) {
messageText = `voice: ${messageText}`;
}
// Create Ink JSON with prefixed text...
}
```
### Scenario Integration
Old scenario format:
```json
{
"type": "phone",
"voice": "This is a voicemail",
"sender": "Director"
}
```
Automatically becomes:
```ink
voice: This is a voicemail
```
Which renders as: **Voice Message UI** 🎤
### Text vs Voice
- `phoneObject.voice` → Rendered as voice message
- `phoneObject.text` → Rendered as regular text bubble
```json
// Voice message UI
{"type": "phone", "voice": "Urgent alert!", "sender": "Security"}
// Regular text bubble
{"type": "phone", "text": "Just checking in", "sender": "Alice"}
```
---
## Styling
### CSS Classes
Voice messages use existing CSS from `css/phone.css`:
- `.voice-message-display` - Container with flex column layout
- `.audio-controls` - Play button + waveform sprite
- `.audio-sprite` - Pixelated audio waveform image
- `.play-button` - Decorative play icon
- `.transcript` - Text content with bordered box
### Customization
All voice messages use:
- Pixel-art aesthetic (`image-rendering: pixelated`)
- 2px borders (no rounded corners)
- VT323 monospace font
- Hover effect on audio controls (scale 1.5x)
---
## Testing
### Test Page
Open `test-phone-chat-minigame.html`:
1. Click "Register Test NPCs"
2. Click "📱 Open Phone"
3. Look for "IT Team" contact
4. Click to open voice message
### Expected Behavior
- Contact list shows "IT Team"
- Opening shows voice message UI (play button + waveform)
- Transcript displays below audio controls
- Timestamp shows in bottom-right
### Test NPCs
- **IT Team**: Pure voice message (single message)
- **David - Tech Support**: Mixed text + voice messages (interactive)
---
## Advantages
### 1. Visual Variety
Mix text and voice messages for more engaging conversations:
- Regular messages → casual chat
- Voice messages → important/urgent content
### 2. Game Design Flexibility
Different message types convey different meanings:
- Text = typed message (casual)
- Voice = recorded audio (formal/urgent)
### 3. Realism
Real phones have both SMS and voice messages, making the game feel more authentic.
### 4. Zero Configuration
No special setup needed:
- Works with existing Ink files
- No new assets required
- Backward compatible (old files still work)
---
## Limitations
### Current Implementation
- **No actual audio playback**: The play button is decorative
- **Static visualization**: Audio waveform doesn't animate
- **No recording**: Players can't send voice messages back
### Future Enhancements
Could add:
- Real audio file playback
- Animated waveforms during "playback"
- Player voice message responses (choice branches)
- Audio file attachment support
---
## Best Practices
### When to Use Voice Messages
**DO use voice for**:
- Security alerts/warnings
- Voicemail from NPCs
- Urgent/time-sensitive information
- Emotional/dramatic moments
- Important codes/instructions
- Messages from authority figures
**DON'T use voice for**:
- Every message (loses impact)
- Long paragraphs (hard to read in transcript)
- Back-and-forth conversations (feels unnatural)
- Player responses (currently not supported)
### Writing Style
**Voice messages should sound spoken**:
```ink
// ✅ Good (natural speech)
voice: Hey, it's me. Just wanted to let you know the meeting's at 3.
// ❌ Bad (too formal/written)
voice: This is a message to inform you that the scheduled meeting will commence at 15:00 hours.
```
**Keep them concise**:
```ink
// ✅ Good (clear and brief)
voice: Code changed to 4829.
// ❌ Bad (too long)
voice: I wanted to reach out to you to inform you that the security access code has been modified and the new code that you should use from now on is 4829.
```
---
## Implementation Details
### Code Location
- **Detection & Rendering**: `js/minigames/phone-chat/phone-chat-ui.js` (lines 277-350)
- **CSS Styling**: `css/phone.css` (lines 311-370)
- **Assets**:
- `assets/icons/play.png` (play button icon)
- `assets/mini-games/audio.png` (waveform sprite)
### How Messages Flow
1. Ink story outputs text: `"voice: Message here"`
2. `phone-chat-minigame.js` calls `ui.addMessage('npc', text)`
3. `phone-chat-ui.js` detects `"voice:"` prefix
4. Renders voice UI instead of text bubble
5. Transcript = text after `"voice:"` prefix
### Backward Compatibility
- Old Ink files without `"voice:"` render as regular text
- No breaking changes to existing scenarios
- Works with runtime conversion (simple messages)
- Compatible with timed messages
---
## Examples
### Example 1: Emergency Alert
```ink
=== start ===
voice: Emergency alert! Fire detected on floor 3. Evacuate immediately via stairwell B.
-> END
```
### Example 2: Clue Drop
```ink
=== investigation ===
I found something interesting...
+ [What is it?]
voice: I can't type this. The password is "BlueFalcon2024". Delete this message after reading.
-> END
```
### Example 3: Story Progression
```ink
=== chapter_end ===
Good work today!
+ [Thanks!]
voice: By the way, the director wants to see you tomorrow at 9 AM. Don't be late.
+ + [Got it]
See you then!
-> END
```
---
## Summary
**Question**: How do I add voice messages to NPC conversations?
**Answer**: Just prefix the text with `voice:` in your Ink file!
```ink
voice: Your message here
```
**Result**:
- ✅ Automatic voice message UI
- ✅ Play button + waveform visualization
- ✅ Transcript display
- ✅ Works in any Ink story
- ✅ Mix with regular text messages
**It just works!** 🎤
---
**Document Version**: 1.0
**Date**: 2025-10-30
**Status**: Implemented & Tested