mirror of
https://github.com/cliffe/BreakEscape.git
synced 2026-02-20 13:50:46 +00:00
286 lines
6.7 KiB
Markdown
286 lines
6.7 KiB
Markdown
|
|
# Lock & Key System - Quick Start Guide
|
||
|
|
|
||
|
|
## Quick Reference: Where Things Are
|
||
|
|
|
||
|
|
### Adding a Locked Door/Room
|
||
|
|
File: `scenario.json`
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"rooms": {
|
||
|
|
"office": {
|
||
|
|
"locked": true,
|
||
|
|
"lockType": "key", // key, pin, password, biometric, bluetooth
|
||
|
|
"requires": "office_key", // ID of key/password/etc.
|
||
|
|
"keyPins": [32, 28, 35, 30] // Optional: for pin tumbler locks
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Adding a Key to Inventory
|
||
|
|
File: `scenario.json`
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"startItemsInInventory": [
|
||
|
|
{
|
||
|
|
"type": "key",
|
||
|
|
"name": "Office Key",
|
||
|
|
"key_id": "office_key", // Must match "requires" in lock
|
||
|
|
"keyPins": [32, 28, 35, 30], // Must match lock's keyPins
|
||
|
|
"observations": "A brass key"
|
||
|
|
}
|
||
|
|
]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Adding a Key in a Container
|
||
|
|
File: `scenario.json`
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"type": "safe",
|
||
|
|
"locked": true,
|
||
|
|
"lockType": "password",
|
||
|
|
"requires": "1234",
|
||
|
|
"contents": [
|
||
|
|
{
|
||
|
|
"type": "key",
|
||
|
|
"name": "CEO Key",
|
||
|
|
"key_id": "ceo_key",
|
||
|
|
"keyPins": [40, 35, 38, 32, 36]
|
||
|
|
}
|
||
|
|
]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## System Entry Points
|
||
|
|
|
||
|
|
### When Player Clicks a Locked Object
|
||
|
|
```
|
||
|
|
interactions.js: handleObjectInteraction(sprite)
|
||
|
|
→ Gets scenario data from sprite
|
||
|
|
→ Calls: handleUnlock(lockable, 'door'|'item')
|
||
|
|
```
|
||
|
|
|
||
|
|
### Unlock System Decision Tree
|
||
|
|
```
|
||
|
|
unlock-system.js: handleUnlock()
|
||
|
|
├─ Lock type: 'key'
|
||
|
|
│ ├─ Has keys in inventory? → Key Selection Minigame
|
||
|
|
│ └─ Has lockpick? → Lockpicking Minigame
|
||
|
|
├─ Lock type: 'pin' → PIN Entry Minigame
|
||
|
|
├─ Lock type: 'password' → Password Entry Minigame
|
||
|
|
├─ Lock type: 'biometric' → Check fingerprint samples
|
||
|
|
└─ Lock type: 'bluetooth' → Check BLE devices
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Key Code Files
|
||
|
|
|
||
|
|
### Primary Lock Logic
|
||
|
|
```
|
||
|
|
js/systems/
|
||
|
|
├─ unlock-system.js [400 lines] Main unlock handler
|
||
|
|
├─ key-lock-system.js [370 lines] Key-lock mappings & cuts
|
||
|
|
├─ inventory.js [630 lines] Item/key management
|
||
|
|
└─ interactions.js [600 lines] Object interaction detector
|
||
|
|
```
|
||
|
|
|
||
|
|
### Lockpicking Minigame (Pin Tumbler)
|
||
|
|
```
|
||
|
|
js/minigames/lockpicking/
|
||
|
|
├─ lockpicking-game-phaser.js [300+ lines] Main controller
|
||
|
|
├─ pin-management.js [150+ lines] Pin creation
|
||
|
|
├─ key-operations.js [100+ lines] Key handling
|
||
|
|
├─ hook-mechanics.js [100+ lines] Tension simulation
|
||
|
|
├─ pin-visuals.js [80+ lines] Rendering
|
||
|
|
└─ lock-configuration.js [60+ lines] State storage
|
||
|
|
```
|
||
|
|
|
||
|
|
### Minigame Framework
|
||
|
|
```
|
||
|
|
js/minigames/framework/
|
||
|
|
├─ minigame-manager.js [180 lines] Framework lifecycle
|
||
|
|
├─ base-minigame.js [150+ lines] Base class
|
||
|
|
└─ index.js [96 lines] Registration
|
||
|
|
```
|
||
|
|
|
||
|
|
### Conversation Integration
|
||
|
|
```
|
||
|
|
js/minigames/helpers/
|
||
|
|
└─ chat-helpers.js [326 lines] Ink tag processing
|
||
|
|
js/minigames/person-chat/
|
||
|
|
└─ person-chat-minigame.js [300+ lines] Conversation UI
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Key Data Structures
|
||
|
|
|
||
|
|
### Pin Tumbler Lock (During Gameplay)
|
||
|
|
```javascript
|
||
|
|
pin = {
|
||
|
|
index: 0,
|
||
|
|
binding: 2, // Which pin sets first (0-3)
|
||
|
|
isSet: false,
|
||
|
|
keyPinLength: 32, // Lock pin height (pixels)
|
||
|
|
driverPinLength: 43, // Spring pin height
|
||
|
|
keyPinHeight: 0, // Current key pin position
|
||
|
|
container: Phaser.Container
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Key Data (In Inventory)
|
||
|
|
```javascript
|
||
|
|
key = {
|
||
|
|
scenarioData: {
|
||
|
|
type: 'key',
|
||
|
|
name: 'Office Key',
|
||
|
|
key_id: 'office_key',
|
||
|
|
keyPins: [32, 28, 35, 30], // Lock pin heights this key opens
|
||
|
|
observations: 'A brass key'
|
||
|
|
},
|
||
|
|
objectId: 'inventory_key_office_key'
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Lock Requirements (From Scenario)
|
||
|
|
```javascript
|
||
|
|
lockRequirements = {
|
||
|
|
lockType: 'key', // Type of lock
|
||
|
|
requires: 'office_key', // Key ID / password / etc.
|
||
|
|
keyPins: [32, 28, 35, 30], // For scenario-defined locks
|
||
|
|
difficulty: 'medium' // For lockpicking
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Common Workflows
|
||
|
|
|
||
|
|
### Scenario Designer: Add New Key-Protected Door
|
||
|
|
|
||
|
|
1. **Define the lock in room:**
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"room_name": {
|
||
|
|
"locked": true,
|
||
|
|
"lockType": "key",
|
||
|
|
"requires": "storage_key",
|
||
|
|
"keyPins": [30, 32, 28, 35] // IMPORTANT: unique pin heights
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **Add key to inventory or container:**
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"type": "key",
|
||
|
|
"name": "Storage Key",
|
||
|
|
"key_id": "storage_key", // Must match "requires"
|
||
|
|
"keyPins": [30, 32, 28, 35] // Must match lock exactly
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **Test: Player should see key icon when near lock**
|
||
|
|
|
||
|
|
### Scenario Designer: Add PIN-Protected Door
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"room_name": {
|
||
|
|
"locked": true,
|
||
|
|
"lockType": "pin",
|
||
|
|
"requires": "4567" // The PIN code
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Scenario Designer: Add Password-Protected Safe
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"type": "safe",
|
||
|
|
"locked": true,
|
||
|
|
"lockType": "password",
|
||
|
|
"requires": "correct_password",
|
||
|
|
"contents": [
|
||
|
|
{ "type": "notes", "name": "Secret Document" }
|
||
|
|
]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Ink Writer: Give Key During Conversation
|
||
|
|
|
||
|
|
In `.ink` file:
|
||
|
|
```ink
|
||
|
|
=== hub ===
|
||
|
|
# speaker:npc
|
||
|
|
Here's the key you'll need!
|
||
|
|
# give_item:key|Storage Key
|
||
|
|
|
||
|
|
What else can I help with?
|
||
|
|
```
|
||
|
|
|
||
|
|
This triggers:
|
||
|
|
1. NPC gives item to player
|
||
|
|
2. Opens container minigame showing the key
|
||
|
|
3. Player can take it to inventory
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Debugging Tips
|
||
|
|
|
||
|
|
### Check Key-Lock Mappings
|
||
|
|
In browser console:
|
||
|
|
```javascript
|
||
|
|
window.showKeyLockMappings() // Shows all key-lock pairs
|
||
|
|
```
|
||
|
|
|
||
|
|
### Check Player Inventory
|
||
|
|
```javascript
|
||
|
|
console.log(window.inventory.items) // All items
|
||
|
|
console.log(window.inventory.keyRing) // Keys specifically
|
||
|
|
```
|
||
|
|
|
||
|
|
### Check Lock Requirements
|
||
|
|
```javascript
|
||
|
|
window.getLockRequirementsForDoor(doorSprite) // Door lock details
|
||
|
|
window.getLockRequirementsForItem(item) // Item lock details
|
||
|
|
```
|
||
|
|
|
||
|
|
### Force Unlock (Testing)
|
||
|
|
```javascript
|
||
|
|
window.DISABLE_LOCKS = true // Disables all locks temporarily
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Common Errors & Solutions
|
||
|
|
|
||
|
|
| Error | Cause | Solution |
|
||
|
|
|-------|-------|----------|
|
||
|
|
| Key doesn't unlock door | `key_id` doesn't match `requires` | Ensure exact match |
|
||
|
|
| Wrong pins in lock | `keyPins` mismatch | Key's keyPins must match lock's keyPins |
|
||
|
|
| Key doesn't appear in inventory | Item not in `startItemsInInventory` | Add it to scenario or container |
|
||
|
|
| Conversation tag not working | Tag format incorrect | Use `# action:param` format |
|
||
|
|
| Minigame won't start | Framework not initialized | Check if MinigameFramework is loaded |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Implementation Checklist
|
||
|
|
|
||
|
|
For adding a new lock type (e.g., RFID/Keycard):
|
||
|
|
|
||
|
|
- [ ] Add case in `unlock-system.js` switch statement
|
||
|
|
- [ ] Check inventory for matching keycard
|
||
|
|
- [ ] Verify access level (if applicable)
|
||
|
|
- [ ] Call `unlockTarget()` on success
|
||
|
|
- [ ] Show appropriate alert messages
|
||
|
|
- [ ] Update scenario schema with examples
|
||
|
|
- [ ] Add documentation with tag examples
|
||
|
|
- [ ] Test with example scenario
|
||
|
|
|