- Added core LOS detection module (`js/systems/npc-los.js`) with functions for distance and angle checks, and debug visualization. - Integrated LOS checks into NPC manager (`js/systems/npc-manager.js`) to enhance lockpicking interruption logic based on player visibility. - Updated scenario configurations for NPCs to include LOS properties. - Created comprehensive documentation covering implementation details, configuration options, and testing procedures. - Enhanced debugging capabilities with console commands and visualization options. - Established performance metrics and future enhancement plans for server-side validation and obstacle detection.
7.3 KiB
Scenario JSON Format Audit - Complete Report
Summary
Compared npc-patrol-lockpick.json vs test-npc-patrol.json and identified 4 major structural issues that have been FIXED.
Issues Identified and Fixed
1. ❌ → ✅ Root-Level Properties
| Property | Before | After | Status |
|---|---|---|---|
globalVariables |
Present | Removed | ✅ Fixed |
startItemsInInventory |
Present | Removed | ✅ Fixed |
endGoal |
Missing | Added | ✅ Fixed |
Why it matters: endGoal is a standard scenario property used by the game framework.
2. ❌ → ✅ First NPC Structure (patrol_with_face)
Problem: Event mappings were inside behavior object with trailing comma
Before:
"behavior": {
"facePlayer": true,
"patrol": { ... }
}, // ← Trailing comma (syntax error)
"eventMappings": [ ... ] // ← Incorrectly nested
After:
"behavior": {
"facePlayer": true,
"patrol": {
"enabled": true,
"speed": 100,
"changeDirectionInterval": 4000,
"bounds": { ... }
}
},
"los": { ... },
"eventMappings": [ ... ], // ← At NPC root, correct nesting
"_comment": "..."
Changes:
- ✅ Removed trailing comma
- ✅ Moved
eventMappingsto NPC root - ✅ Added
enabledflag to patrol config - ✅ Reordered properties for clarity
3. ❌ → ✅ Second NPC Structure (security_guard)
Problem: patrol object was at NPC root instead of inside behavior
Before:
{
"los": { ... },
"patrol": { // ← WRONG: At NPC root!
"route": [ ... ],
"speed": 40,
"pauseTime": 10
},
"eventMappings": [ ... ]
}
After:
{
"behavior": { // ← CORRECT: Patrol inside behavior
"patrol": {
"route": [ ... ],
"speed": 40,
"pauseTime": 10
}
},
"los": { ... },
"eventMappings": [ ... ],
"_comment": "..."
}
Changes:
- ✅ Wrapped
patrolinside newbehaviorobject - ✅ Removed trailing comma
- ✅ Moved
eventMappingsto NPC root - ✅ Reordered properties for clarity
4. ❌ → ✅ Property Ordering
Before: Mixed and inconsistent ordering
After: Standardized ordering for all NPCs:
- Basic info:
id,displayName,npcType - Position:
position - Display:
spriteSheet,spriteTalk,spriteConfig - Story:
storyPath,currentKnot - Behavior:
behavior(containspatrolandfacePlayer) - Detection:
los - Events:
eventMappings - Documentation:
_comment
Detailed Format Reference
Correct NPC Structure (Both NPCs Now Follow)
{
"id": "patrol_with_face",
"displayName": "Patrol + Face Player",
"npcType": "person",
"position": { "x": 5, "y": 5 },
"spriteSheet": "hacker",
"spriteConfig": {
"idleFrameStart": 20,
"idleFrameEnd": 23
},
"storyPath": "scenarios/ink/security-guard.json",
"currentKnot": "start",
"behavior": {
"facePlayer": true,
"facePlayerDistance": 96,
"patrol": {
"enabled": true,
"speed": 100,
"changeDirectionInterval": 4000,
"bounds": {
"x": 128,
"y": 128,
"width": 128,
"height": 128
}
}
},
"los": {
"enabled": true,
"range": 250,
"angle": 120,
"visualize": true
},
"eventMappings": [
{
"eventPattern": "lockpick_used_in_view",
"targetKnot": "on_lockpick_used",
"conversationMode": "person-chat",
"cooldown": 0
}
],
"_comment": "Description of NPC behavior"
}
Validation Results
✅ File: npc-patrol-lockpick.json
- Status: FIXED AND VALID
- JSON Syntax: ✅ Valid
- Property Structure: ✅ Correct
- NPC Format: ✅ Matches template
- Ready for Testing: ✅ Yes
Files for Reference
| File | Format | Status |
|---|---|---|
test-npc-patrol.json |
✅ Correct | Reference |
npc-patrol-lockpick.json |
✅ Fixed | Ready to use |
Key Rules Enforced
NPC Structure Rules
-
patrolMUST be insidebehavior✅ npc.behavior.patrol ❌ npc.patrol -
No trailing commas after objects
✅ { "a": 1 } ❌ { "a": 1, } -
eventMappingsat NPC root✅ npc.eventMappings ❌ npc.behavior.eventMappings -
losat NPC root✅ npc.los ❌ npc.behavior.los -
All properties properly ordered
- Basic info first
behaviorcontains patrol/interaction logic- Detection/events after behavior
Documentation Created
Created 3 comprehensive guides:
-
docs/SCENARIO_FORMAT_COMPARISON.md- Before/after examples
- Detailed explanation of each fix
- Template for correct NPC structure
-
docs/JSON_SYNTAX_ERRORS_EXPLAINED.md- Visual error examples
- Why each error is wrong
- JSON validation tips
- Online validators listed
-
SCENARIO_FORMAT_FIXES.md(this directory)- Complete summary of fixes
- Validation checklist
- Reference structure
Testing the Fixed Scenario
To verify the fixes work correctly:
# 1. Validate JSON syntax
python3 -m json.tool scenarios/npc-patrol-lockpick.json
# 2. Load scenario in game
# Open: scenario_select.html
# Select: npc-patrol-lockpick
# Click: Start Scenario
# 3. Test NPC behavior in console
window.enableLOS() # Should show green cones
# 4. Verify patrol and detection
# - Both NPCs should patrol
# - Green cones should appear
# - Lockpicking should trigger person-chat
Before vs After Comparison
Root Level
{
"scenario_brief": "Test scenario for NPC patrol and lockpick detection",
- "globalVariables": {
- "player_caught_lockpicking": false
- },
+ "endGoal": "Test NPC line-of-sight detection and lockpicking interruption",
"startRoom": "patrol_corridor",
- "startItemsInInventory": [],
"player": { ... }
}
First NPC
"storyPath": "scenarios/ink/security-guard.json",
"currentKnot": "start",
+ "behavior": {
"facePlayer": true,
"facePlayerDistance": 96,
"patrol": {
+ "enabled": true,
"speed": 100,
"changeDirectionInterval": 4000,
"bounds": { ... }
}
- },
+ },
"los": { ... },
"eventMappings": [ ... ],
+ "_comment": "..."
Second NPC
"storyPath": "scenarios/ink/security-guard.json",
"currentKnot": "start",
+ "behavior": {
"patrol": {
"route": [ ... ],
"speed": 40,
"pauseTime": 10
}
- },
+ },
"los": { ... },
"eventMappings": [ ... ],
+ "_comment": "..."
Quick Reference Checklist
When creating NPC definitions:
behaviorobject created firstpatrolplaced insidebehavior- No trailing commas anywhere
losat NPC root (not inbehavior)eventMappingsat NPC root- All properties properly quoted
- Brackets/braces properly matched
- Properties in standard order
- Optional
_commentfor documentation
Next Steps
- ✅ Format fixed - JSON is now valid and properly structured
- ✅ Documentation created - Guides for future reference
- 🔄 Ready to test - Scenario can be loaded in game
- 📚 Guidelines established - Format rules documented
The scenario is now in correct format and ready for testing!