617 lines
17 KiB
Markdown
617 lines
17 KiB
Markdown
# Level Structure Template
|
|
|
|
## Overview
|
|
This document defines the standard structure and components for creating Training Academy campaign levels. Follow this template to ensure consistency across all levels.
|
|
|
|
---
|
|
|
|
## Level Data Structure
|
|
|
|
### Basic Level Properties
|
|
```javascript
|
|
{
|
|
id: 'academy-level-X', // Unique identifier (academy-level-1, academy-level-2, etc.)
|
|
name: 'Level Title', // Display name (e.g., "Edge Training 101")
|
|
arc: 'Arc Name', // Story arc (Foundation, Immersion, Advanced Training, etc.)
|
|
level: X, // Level number (1, 2, 3, etc.)
|
|
duration: 300, // Estimated duration in seconds
|
|
interactiveType: 'scenario-adventure', // Always use this for campaign levels
|
|
interactiveData: {
|
|
// Scenario data here...
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Scenario Structure
|
|
|
|
### Interactive Data Template
|
|
```javascript
|
|
interactiveData: {
|
|
title: 'Level X: Level Title', // Match the level name
|
|
steps: {
|
|
// Steps defined here...
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Step Types
|
|
|
|
### 1. Story Step (Narrative/Dialogue)
|
|
**Purpose**: Display story text without user interaction beyond continuing
|
|
|
|
```javascript
|
|
start: {
|
|
type: 'story',
|
|
mood: 'welcoming', // Options: welcoming, instructional, praising, anticipatory, intense, etc.
|
|
story: 'Your story text here. This displays to the player.',
|
|
nextStep: 'next_step_id'
|
|
}
|
|
```
|
|
|
|
**Common Moods**:
|
|
- `welcoming` - Friendly introduction
|
|
- `instructional` - Teaching/guidance
|
|
- `praising` - Positive reinforcement
|
|
- `anticipatory` - Building excitement
|
|
- `intense` - High energy/challenge
|
|
- `satisfied` - Completion/success
|
|
|
|
---
|
|
|
|
### 2. Action Step (Interactive Task)
|
|
**Purpose**: Execute an interactive task (edge, rhythm, library management, etc.)
|
|
|
|
```javascript
|
|
step_id: {
|
|
type: 'action',
|
|
mood: 'instructional',
|
|
story: 'Explanation of what the player will do.',
|
|
interactiveType: 'edge', // Type of interactive task
|
|
params: {
|
|
// Task-specific parameters
|
|
count: 5,
|
|
instruction: 'Edge 5 times - slowly and deliberately',
|
|
showTimer: true, // ALWAYS include for countdown timer display
|
|
preserveContent: false // Set to true if you want to append to existing content
|
|
},
|
|
nextStep: 'next_step_id'
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 3. Completion Step
|
|
**Purpose**: Mark level as complete and show completion message
|
|
|
|
```javascript
|
|
completion: {
|
|
type: 'completion',
|
|
mood: 'satisfied',
|
|
story: '✅ Level X Complete - Summary of achievements.',
|
|
outcome: 'levelX_complete'
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Standard Interactive Task Types
|
|
|
|
### Edge Task
|
|
**Purpose**: Edge training - stroke to the brink without release
|
|
|
|
```javascript
|
|
{
|
|
type: 'action',
|
|
mood: 'instructional',
|
|
story: 'Edge training instructions.',
|
|
interactiveType: 'edge',
|
|
params: {
|
|
count: 5, // Number of edges (optional)
|
|
duration: 300, // Duration in seconds (optional)
|
|
instruction: 'Edge 5 times - slowly and deliberately',
|
|
showTimer: true, // Show countdown timer in sidebar
|
|
preserveContent: false, // Whether to preserve existing content
|
|
keepVideoPlaying: false // Keep video player active
|
|
},
|
|
nextStep: 'next_step_id'
|
|
}
|
|
```
|
|
|
|
**Components Created**:
|
|
- Edge instruction display
|
|
- Start button
|
|
- Dev skip button (auto-shown in dev mode)
|
|
- Session duration display
|
|
- Sidebar countdown timer (if showTimer: true)
|
|
- Status messages
|
|
|
|
---
|
|
|
|
### Rhythm Task
|
|
**Purpose**: Follow specific stroking rhythm patterns
|
|
|
|
```javascript
|
|
{
|
|
type: 'action',
|
|
mood: 'focused',
|
|
story: 'Follow the rhythm pattern.',
|
|
interactiveType: 'rhythm',
|
|
params: {
|
|
pattern: 'slow-fast-slow', // Pattern name (see patterns below)
|
|
duration: 180, // Duration in seconds
|
|
enableVideo: true, // Enable video playback
|
|
enableMetronomeSound: true, // Play metronome tick sounds
|
|
showTimer: true, // Show countdown timer in sidebar
|
|
multiPattern: [ // Optional: Multiple patterns in sequence
|
|
{ pattern: 'fast-slow-fast', duration: 300 },
|
|
{ pattern: 'varied-medium', duration: 360 }
|
|
]
|
|
},
|
|
nextStep: 'next_step_id'
|
|
}
|
|
```
|
|
|
|
**Available Patterns**:
|
|
- `slow-fast-slow` - [60, 80, 100, 120, 140, 120, 100, 80, 60] BPM
|
|
- `fast-slow-fast` - [140, 120, 100, 80, 60, 80, 100, 120, 140] BPM
|
|
- `steady` - [90, 90, 90, 90, 90, 90] BPM
|
|
- `escalating` - [60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180] BPM
|
|
- `varied-slow` - [70, 80, 90, 100, 0, 80, 90, 110, 100, 0, 70, 85, 95, 80, 100] BPM
|
|
- `varied-medium` - [100, 120, 140, 160, 150, 0, 130, 150, 170, 140, 180, 0, 120, 160, 140, 180, 200] BPM
|
|
- `varied-intense` - [140, 160, 180, 200, 0, 160, 180, 200, 220, 0, 180, 200, 220, 240, 0, 200, 220, 180, 240] BPM
|
|
|
|
**Components Created**:
|
|
- Pattern title display
|
|
- BPM display
|
|
- Phase indicator
|
|
- Metronome visual (pulsing indicator)
|
|
- Video player (if enableVideo: true)
|
|
- Video controls (skip, volume)
|
|
- Metronome volume control
|
|
- Dev skip button
|
|
- Sidebar countdown timer
|
|
|
|
---
|
|
|
|
### Rhythm Training Task (Advanced)
|
|
**Purpose**: Advanced rhythm training with custom tempo sequences
|
|
|
|
```javascript
|
|
{
|
|
type: 'action',
|
|
mood: 'intense',
|
|
story: 'Advanced rhythm training with varying tempo.',
|
|
interactiveType: 'rhythm-training',
|
|
params: {
|
|
duration: 180,
|
|
enableVideo: false,
|
|
showTimer: true,
|
|
tempoSequence: [
|
|
{ tempo: 60, duration: 25.71 }, // Slow warmup
|
|
{ tempo: 120, duration: 25.71 }, // Medium
|
|
{ tempo: 150, duration: 25.71 }, // Fast
|
|
{ tempo: 60, duration: 25.71 }, // Back to slow
|
|
{ tempo: 150, duration: 25.71 }, // Fast again
|
|
{ tempo: 200, duration: 25.71 }, // Intense
|
|
{ tempo: 240, duration: 25.71 } // Extreme finish
|
|
]
|
|
},
|
|
nextStep: 'next_step_id'
|
|
}
|
|
```
|
|
|
|
**Components Created**:
|
|
- Beat timeline visualization (scrolling beats)
|
|
- Current BPM display
|
|
- Tempo label
|
|
- Video player (optional)
|
|
- Volume controls
|
|
- Dev skip button
|
|
- Sidebar countdown timer
|
|
|
|
---
|
|
|
|
### Add Library Directory Task
|
|
**Purpose**: Add media directory to library
|
|
|
|
```javascript
|
|
{
|
|
type: 'action',
|
|
mood: 'practical',
|
|
story: 'Add content to your library.',
|
|
interactiveType: 'add-library-directory',
|
|
params: {
|
|
suggestedTags: ['amateur', 'solo'],
|
|
showTimer: true
|
|
},
|
|
nextStep: 'next_step_id'
|
|
}
|
|
```
|
|
|
|
**Components Created**:
|
|
- Select directory button
|
|
- Suggested tags display
|
|
- Result status area
|
|
- Automatic completion on success
|
|
|
|
---
|
|
|
|
### Tag Files Task
|
|
**Purpose**: Tag files in the library
|
|
|
|
```javascript
|
|
{
|
|
type: 'action',
|
|
mood: 'practical',
|
|
story: 'Tag files in your library.',
|
|
interactiveType: 'tag-files',
|
|
params: {
|
|
minFiles: 10,
|
|
suggestedTags: ['pov', 'blowjob', 'riding', 'amateur'],
|
|
showTimer: true,
|
|
preserveContent: true // Keep existing content visible
|
|
},
|
|
nextStep: 'next_step_id'
|
|
}
|
|
```
|
|
|
|
**Components Created**:
|
|
- Open library button
|
|
- Tag progress tracker
|
|
- Suggested tags display
|
|
- Auto-completion when target reached
|
|
|
|
---
|
|
|
|
### Video Start Task
|
|
**Purpose**: Start video playback
|
|
|
|
```javascript
|
|
{
|
|
type: 'action',
|
|
mood: 'intense',
|
|
story: 'Watch the video.',
|
|
interactiveType: 'video-start',
|
|
params: {
|
|
player: 'focus', // Video player mode
|
|
tags: ['amateur'], // Filter tags
|
|
duration: 120, // Duration in seconds
|
|
showTimer: true // Show countdown timer in sidebar
|
|
},
|
|
nextStep: 'next_step_id'
|
|
}
|
|
```
|
|
|
|
**Components Created**:
|
|
- Video player container
|
|
- Start video button
|
|
- Dev skip button
|
|
- Sidebar countdown timer
|
|
- Auto-completion when duration complete
|
|
|
|
---
|
|
|
|
## Standard UI Components
|
|
|
|
### 1. Sidebar Countdown Timer
|
|
**Always Preserve Game Stats Panel**
|
|
|
|
```javascript
|
|
// ✅ CORRECT - Use specific timer elements
|
|
const countdownEl = document.getElementById('sidebar-countdown-display');
|
|
const countdownWrapper = document.getElementById('sidebar-countdown-timer');
|
|
|
|
// Show timer
|
|
if (countdownWrapper) {
|
|
countdownWrapper.style.display = 'block';
|
|
}
|
|
|
|
// Update timer
|
|
if (countdownEl) {
|
|
const minutes = Math.floor(timeRemaining / 60);
|
|
const seconds = timeRemaining % 60;
|
|
countdownEl.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
|
}
|
|
|
|
// Hide timer
|
|
if (countdownWrapper) {
|
|
countdownWrapper.style.display = 'none';
|
|
}
|
|
|
|
// ❌ WRONG - Never use sidebar.innerHTML
|
|
// This destroys the game stats panel!
|
|
sidebar.innerHTML = '<div>Timer</div>'; // DON'T DO THIS
|
|
```
|
|
|
|
**Required Elements**:
|
|
- `#sidebar-countdown-timer` - Wrapper element (show/hide)
|
|
- `#sidebar-countdown-display` - Text element (update time)
|
|
- `#game-stats-panel` - Stats panel (NEVER destroy this)
|
|
|
|
**See**: `docs/GAME_STATS_PANEL_FIX.md` for complete guide
|
|
|
|
---
|
|
|
|
### 2. Dev Skip Button
|
|
**Standard Implementation**
|
|
|
|
```javascript
|
|
// HTML
|
|
<button class="btn btn-warning skip-task-btn" id="skip-[task]-btn" style="display: none;">
|
|
⏩ Skip Task (Dev)
|
|
</button>
|
|
|
|
// JavaScript
|
|
const skipBtn = container.querySelector('#skip-[task]-btn');
|
|
|
|
// Show if dev mode
|
|
if (window.isDevMode && window.isDevMode()) {
|
|
skipBtn.style.display = 'inline-block';
|
|
}
|
|
|
|
// Handler
|
|
skipBtn.addEventListener('click', () => {
|
|
console.log('⏩ Dev skip - completing task');
|
|
|
|
// Clean up intervals/timers
|
|
if (timerInterval) clearInterval(timerInterval);
|
|
if (beatTimer) clearInterval(beatTimer);
|
|
|
|
// Stop audio
|
|
if (audioContext) audioContext.close();
|
|
if (ambientAudio) ambientAudio.pause();
|
|
|
|
// Hide countdown timer
|
|
if (countdownWrapper) {
|
|
countdownWrapper.style.display = 'none';
|
|
}
|
|
|
|
// Mark complete
|
|
task.completed = true;
|
|
|
|
// Enable continue button
|
|
const completeBtn = document.getElementById('interactive-complete-btn');
|
|
if (completeBtn) {
|
|
completeBtn.disabled = false;
|
|
completeBtn.textContent = 'Continue to Next Step ✓';
|
|
}
|
|
});
|
|
```
|
|
|
|
**Required Cleanup**:
|
|
- Clear all intervals and timers
|
|
- Stop all audio (metronome, ambient, video)
|
|
- Hide countdown timer
|
|
- Mark task as completed
|
|
- Enable continue button
|
|
|
|
---
|
|
|
|
### 3. Task Completion Pattern
|
|
**Standard Completion Flow**
|
|
|
|
```javascript
|
|
// When task naturally completes
|
|
task.completed = true;
|
|
|
|
// Update UI
|
|
statusArea.innerHTML = '<div class="success">✅ Task complete!</div>';
|
|
|
|
// Hide countdown timer
|
|
if (showTimer && countdownWrapper) {
|
|
countdownWrapper.style.display = 'none';
|
|
}
|
|
|
|
// Enable continue button
|
|
const completeBtn = document.getElementById('interactive-complete-btn');
|
|
if (completeBtn) {
|
|
completeBtn.disabled = false;
|
|
completeBtn.textContent = 'Continue to Next Step ✓';
|
|
completeBtn.style.background = 'linear-gradient(135deg, var(--color-success), var(--color-primary))';
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 4. Cleanup Function
|
|
**Every Task Must Have Cleanup**
|
|
|
|
```javascript
|
|
// Store cleanup function on task
|
|
task.cleanup = () => {
|
|
console.log('🧹 Task cleanup called');
|
|
|
|
// Clear intervals
|
|
if (timerInterval) clearInterval(timerInterval);
|
|
if (beatTimer) clearInterval(beatTimer);
|
|
|
|
// Stop audio
|
|
if (audioContext) {
|
|
audioContext.close().catch(err => console.warn('⚠️ Error closing audio:', err));
|
|
}
|
|
if (ambientAudio) {
|
|
ambientAudio.pause();
|
|
ambientAudio = null;
|
|
}
|
|
|
|
// Stop video
|
|
if (videoElement) {
|
|
videoElement.pause();
|
|
videoElement = null;
|
|
}
|
|
|
|
// Hide countdown timer
|
|
const countdownTimer = document.getElementById('sidebar-countdown-timer');
|
|
if (countdownTimer) {
|
|
countdownTimer.style.display = 'none';
|
|
}
|
|
|
|
console.log('✅ Cleanup complete');
|
|
};
|
|
```
|
|
|
|
---
|
|
|
|
## Complete Level Example
|
|
|
|
### Level 1: Edge Training 101
|
|
|
|
```javascript
|
|
level1: {
|
|
id: 'academy-level-1',
|
|
name: 'Edge Training 101',
|
|
arc: 'Foundation',
|
|
level: 1,
|
|
duration: 300,
|
|
interactiveType: 'scenario-adventure',
|
|
interactiveData: {
|
|
title: 'Level 1: Edge Training 101',
|
|
steps: {
|
|
start: {
|
|
type: 'story',
|
|
mood: 'welcoming',
|
|
story: 'Welcome to The Academy, aspiring gooner. I am your instructor, and I will guide your transformation. Today, we begin with the foundation of all gooning: the edge. You will learn to ride the wave of pleasure without release. Are you ready to begin your journey?',
|
|
nextStep: 'intro_complete'
|
|
},
|
|
intro_complete: {
|
|
type: 'action',
|
|
mood: 'instructional',
|
|
story: 'Your first lesson is simple: edge 5 times. Stroke yourself to the very brink, feel that rush of pleasure, then stop. Hold yourself there. Feel it pulsing, demanding release. But you will not give in. This is control. This is the beginning.',
|
|
interactiveType: 'edge',
|
|
params: {
|
|
count: 5,
|
|
instruction: 'Edge 5 times - slowly and deliberately',
|
|
showTimer: true
|
|
},
|
|
nextStep: 'first_edges_done'
|
|
},
|
|
first_edges_done: {
|
|
type: 'story',
|
|
mood: 'praising',
|
|
story: 'Good. Very good. You felt it, didn\'t you? That moment where your body screamed for release, but your mind held firm. That is power. That is what we are building here. You have completed your first training session. Level 2 awaits when you\'re ready.',
|
|
nextStep: 'completion'
|
|
},
|
|
completion: {
|
|
type: 'completion',
|
|
mood: 'satisfied',
|
|
story: '✅ Level 1 Complete - You have taken your first steps into The Academy.',
|
|
outcome: 'level1_complete'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Step Flow Diagram
|
|
|
|
```
|
|
[start] (story)
|
|
↓
|
|
[intro_complete] (action - edge task)
|
|
↓
|
|
[first_edges_done] (story)
|
|
↓
|
|
[completion] (completion)
|
|
```
|
|
|
|
---
|
|
|
|
## Critical Rules
|
|
|
|
### ✅ DO:
|
|
- Always include `showTimer: true` in task params
|
|
- Use specific timer elements (`#sidebar-countdown-display`, `#sidebar-countdown-timer`)
|
|
- Add dev skip buttons to all timed tasks
|
|
- Include cleanup functions for all interactive tasks
|
|
- Clear all intervals/timers in cleanup and skip handlers
|
|
- Hide countdown timer when task completes
|
|
- Enable continue button when task completes
|
|
- Use consistent step naming (start, completion)
|
|
- Include mood indicators for atmosphere
|
|
- Provide clear instructions in story text
|
|
|
|
### ❌ DON'T:
|
|
- Use `sidebar.innerHTML` (destroys game stats panel)
|
|
- Forget to clear intervals in cleanup
|
|
- Forget to hide countdown timer when complete
|
|
- Create tasks without cleanup functions
|
|
- Use generic button IDs that might conflict
|
|
- Forget to check for element existence before using
|
|
- Hardcode values that should be parameters
|
|
- Skip the dev skip button implementation
|
|
- Forget to stop audio in cleanup
|
|
|
|
---
|
|
|
|
## Testing Checklist
|
|
|
|
When creating a new level, verify:
|
|
|
|
- [ ] Game stats panel stays visible throughout all tasks
|
|
- [ ] Countdown timer appears when tasks start
|
|
- [ ] Countdown timer updates every second
|
|
- [ ] Countdown timer hides when task completes
|
|
- [ ] Dev skip button appears in dev mode (`localStorage.setItem('devMode', 'true')`)
|
|
- [ ] Dev skip button completes task immediately
|
|
- [ ] All intervals/timers are cleared on completion
|
|
- [ ] All intervals/timers are cleared on skip
|
|
- [ ] All audio stops on completion
|
|
- [ ] All audio stops on skip
|
|
- [ ] Continue button enables when task completes
|
|
- [ ] Level transitions smoothly to next step
|
|
- [ ] Story text displays correctly
|
|
- [ ] Moods are appropriate for each step
|
|
- [ ] Task parameters work as expected
|
|
- [ ] No console errors during execution
|
|
- [ ] Cleanup function executes without errors
|
|
|
|
---
|
|
|
|
## Quick Reference
|
|
|
|
### Common Parameters
|
|
```javascript
|
|
params: {
|
|
showTimer: true, // Show countdown timer
|
|
preserveContent: false, // Preserve existing content
|
|
duration: 180, // Duration in seconds
|
|
enableVideo: true, // Enable video player
|
|
suggestedTags: [], // Suggested tags array
|
|
instruction: '', // Custom instruction text
|
|
}
|
|
```
|
|
|
|
### Common Element IDs
|
|
- `#sidebar-countdown-timer` - Timer wrapper (show/hide)
|
|
- `#sidebar-countdown-display` - Timer text (update)
|
|
- `#game-stats-panel` - Stats panel (preserve)
|
|
- `#interactive-complete-btn` - Continue button (enable)
|
|
- `.skip-task-btn` - Dev skip button class
|
|
|
|
### Common Event Handlers
|
|
- Start button click → Begin task
|
|
- Skip button click → Complete immediately
|
|
- Timer interval → Update countdown
|
|
- Completion → Clean up and enable continue
|
|
|
|
---
|
|
|
|
## Resources
|
|
|
|
- **Game Stats Panel Fix**: `docs/GAME_STATS_PANEL_FIX.md`
|
|
- **Rhythm Timeline System**: `docs/rhythm-timeline/README.md`
|
|
- **Training Modules**: `docs/TRAINING_MODULES.md`
|
|
- **Level Breakdowns**: `docs/LEVELS_1-15_BREAKDOWN.md`, `docs/LEVELS_16-20_BREAKDOWN.md`
|
|
|
|
---
|
|
|
|
## Version History
|
|
|
|
- **v1.0** (2025-12-06) - Initial template based on Levels 1-3 structure
|