mirror of
https://github.com/cliffe/BreakEscape.git
synced 2026-02-20 13:50:46 +00:00
- Created `05_EXAMPLE_SCENARIO.md` with a complete Ink script for the Biometric Breach scenario featuring NPCs Alice and Bob. - Added `QUICK_REFERENCE.md` as a cheat sheet for NPC system components, event types, and common patterns. - Introduced `README.md` as an index for NPC integration planning, outlining document structure and key concepts.
5.9 KiB
5.9 KiB
NPC System Quick Reference
One-Page Cheat Sheet
Key Components
Event → NPC Manager → Ink Engine → Phone Chat/Bark
File Locations
| Component | Location |
|---|---|
| Ink Scripts (source) | scenarios/ink/*.ink |
| Compiled Ink JSON | scenarios/compiled/*.json |
| Ink Engine | js/systems/ink/ink-engine.js |
| Event System | js/systems/npc-events.js |
| NPC Manager | js/systems/npc-manager.js |
| Bark System | js/systems/npc-barks.js |
| Phone Chat | js/minigames/phone-chat/phone-chat-minigame.js |
Ink Basics
=== knot_name ===
# speaker: Alice
# type: bark|conversation
# trigger: event_name
Dialogue text here.
~ variable_name = true
+ [Choice 1] -> next_knot
+ [Choice 2] -> other_knot
-> END
Event Emission (in game code)
window.npcEvents.emit('event_type', {
data: 'value',
timestamp: Date.now()
});
Common Event Types
| Event | Format | Example |
|---|---|---|
| Room | room_entered:{roomId} |
room_entered:lab |
| Item | item_picked_up:{itemType} |
item_picked_up:lockpick |
| Door | door_unlocked:{roomTo} |
door_unlocked:server |
| Minigame | minigame_completed:{type}:{result} |
minigame_completed:lockpicking:success |
| Progress | progress:{milestone} |
progress:suspect_found |
Scenario JSON Structure
{
"npcs": {
"alice": {
"id": "alice",
"name": "Alice Chen",
"role": "Security Analyst",
"avatar": "assets/npc/avatars/npc_alice.png",
"inkFile": "scenarios/compiled/scenario_npcs.json",
"initialKnot": "alice_intro",
"eventMappings": {
"room_entered:lab": "alice_room_lab",
"item_picked_up:lockpick": "alice_item_lockpick"
}
}
}
}
Console Commands
// Trigger knot
window.inkEngine.goToKnot('alice', 'alice_hub');
// Open phone
window.MinigameFramework.startMinigame('phone-chat', null, { npcId: 'alice' });
// Show bark
window.npcBarkSystem.showBark('alice', 'Test message', {});
// Emit event
window.npcEvents.emit('room_entered', { roomId: 'lab' });
// Check variable
window.inkEngine.getVariable('alice', 'trust_level');
// Set variable
window.inkEngine.setVariable('alice', 'trust_level', 5);
// Debug mode
window.npcEvents.debug = true;
Ink External Functions
EXTERNAL give_item(item_type)
EXTERNAL unlock_door(door_id)
EXTERNAL show_notification(message)
EXTERNAL get_current_room()
EXTERNAL has_item(item_type)
// Usage
~ give_item("keycard")
~ unlock_door("door_lab")
~ show_notification("New objective!")
Common Patterns
Bark on first room entry:
=== npc_room_lab ===
# speaker: Alice
# type: bark
{player_in_lab:
Still searching the lab?
- else:
You're in the lab! Be careful.
~ player_in_lab = true
}
-> END
Conditional conversation choices:
=== npc_hub ===
+ [General option] -> general_branch
+ {trust >= 5} [High trust option] -> trust_branch
+ {has_item("keycard")} [I have the keycard] -> keycard_branch
-> END
Trust-based responses:
=== npc_greeting ===
{trust >= 7: You've been great. What do you need?}
{trust >= 3 and trust < 7: What's up?}
{trust < 3: What do you want?}
-> END
Compilation
# Compile Ink to JSON
cd scenarios/ink
inklecate script.ink -o ../compiled/script.json
# Verify
ls -lh ../compiled/script.json
CSS Classes
| Element | Class |
|---|---|
| Bark notification | .npc-bark-notification |
| Bark avatar | .npc-bark-avatar |
| Bark name | .npc-bark-name |
| Bark message | .npc-bark-message |
| Contact list | .phone-chat-contacts |
| Contact item | .phone-chat-contact |
| Message thread | .phone-chat-messages |
| Message bubble | .message-bubble |
| Choice buttons | .phone-chat-choice-button |
| Phone button | .phone-access-button |
Troubleshooting
| Problem | Solution |
|---|---|
| Barks not appearing | Check window.npcBarkSystem.init() called |
| Events not firing | Enable debug: window.npcEvents.debug = true |
| Ink errors | Check compiled JSON exists and is valid |
| Phone not opening | Verify minigame registered in framework |
| Wrong dialogue | Check Ink knot name matches event mapping |
| Choices not working | Verify Ink story has choices at current point |
File Size Reference
- Ink source: ~5-10 KB per scenario
- Compiled JSON: ~15-30 KB per scenario
- ink-js library: ~40 KB
- Total overhead: ~50-70 KB per scenario
Performance Tips
- Use cooldowns to limit bark frequency (10-30s)
- Prioritize important events (progress > items > rooms)
- Limit active barks to 3 max
- Auto-dismiss barks after 5s
- Compress avatar images
- Cache Ink story instances
Best Practices
✅ DO:
- Keep barks short (1-2 sentences)
- Provide meaningful dialogue choices
- Track important variables
- Use tags for metadata
- Comment complex logic
- Test all branches
❌ DON'T:
- Spam barks (use cooldowns)
- Create dead-end conversations
- Forget to compile Ink after edits
- Hardcode game state in Ink
- Ignore trust/relationship mechanics
- Skip testing edge cases
Integration Points
Add event emissions at these locations:
| File | Function | Event Type |
|---|---|---|
rooms.js |
updatePlayerRoom() |
room_entered/exited |
inventory.js |
addToInventory() |
item_picked_up |
interactions.js |
handleObjectInteraction() |
object_interacted |
doors.js |
unlockDoor() |
door_unlocked |
base-minigame.js |
complete() |
minigame_completed |
Workflow Summary
- Write
.inkfile - Compile to
.json - Configure NPC in scenario JSON
- Map events to knots
- Test in game
- Iterate
Resources
- Ink Docs: https://github.com/inkle/ink/blob/master/Documentation/WritingWithInk.md
- ink-js: https://github.com/y-lohse/inkjs
- Planning Docs:
planning_notes/npc/
Print this page for quick reference while coding!