training-academy/docs/LEVEL_STRUCTURE_TEMPLATE.md

17 KiB

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

{
    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

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

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.)

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

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

{
    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

{
    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

{
    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

{
    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

{
    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

{
    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

// ✅ 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

// 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

// 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

// 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

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

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