diff --git a/CHARACTER_TRACKING_README.md b/CHARACTER_TRACKING_README.md deleted file mode 100644 index 75fa355..0000000 --- a/CHARACTER_TRACKING_README.md +++ /dev/null @@ -1,479 +0,0 @@ -# Character State Tracking System for SillyTavern RPG Companion - -## 📖 Overview - -This is a **comprehensive character state tracking system** based on the Katherine RPG framework. Unlike traditional RPG companions that track **{{user}}** stats, this system tracks **{{char}}** (the AI character's) internal states, emotions, relationships, and physical condition. - -### What It Tracks - -#### 🧬 Primary Traits (Personality DNA) -- **40+ personality traits** that define who the character IS -- Core disposition (dominance, introversion, emotional stability) -- Sexual personality (perversion, exhibitionism, masochism, etc.) -- Moral core (honesty, empathy, corruption, etc.) -- Intellectual traits (intelligence, wisdom, creativity) -- **These change SLOWLY** - only through sustained experiences over time - -#### 🌤️ Secondary States (Emotional Weather) -- **70+ temporary emotional states** that change frequently -- Core emotions (happy, sad, angry, anxious, etc.) -- Arousal & sexual states (horny, frustrated, seductive, etc.) -- Social states (lonely, confident, playful, etc.) -- Energy & altered states (drunk, exhausted, euphoric, etc.) -- **These change FAST** - minute to hour timescales - -#### 💭 Beliefs & Worldview -- Track character's beliefs with strength and stability -- Moral beliefs, spiritual beliefs, self-concept -- Relationship beliefs, sexual morality -- Beliefs can fracture during pivotal moments - -#### 🏃 Physical Stats -- Survival needs (hunger, thirst, bladder, energy, sleep) -- Physical condition (health, pain, temperature, cleanliness) -- Physical attributes (strength, stamina, agility) - -#### 👗 Outfit/Clothing System -- Dynamic tracking of what character is wearing -- Per-piece tracking (bra, panties, shirt, pants, etc.) -- Status tracking (worn properly, shifted, removed, torn, wet) -- Coverage calculation (0-100% body coverage) - -#### ❤️ Relationship Tracking -- **Per-NPC detailed relationship stats** -- Core metrics: Trust, Love, Loyalty, Attraction, Respect, Fear -- Social dynamics: Closeness, Openness, Comfort, Dependency -- Sexual dynamics: Flirtiness, Sexual Compatibility, Satisfaction -- Power dynamics: Dominance, Submissiveness, Possessiveness -- Current thoughts about each person - -#### 🎬 Contextual Information -- Location, time of day, weather -- Present characters in the scene -- Recent events -- Current activity - ---- - -## 🔄 How It Works - -### The Flow - -1. **LLM receives current character state** as input before generating a response -2. **LLM generates the character's response** based on their current emotional/physical state -3. **LLM updates character states** based on what happened in the response -4. **Parser extracts and applies updates** to the character state -5. **UI displays updated states** for the user to see - -### Example - -**Before Response:** -- Character: Katherine -- Emotional State: Lonely (70), Anxious (40), Horny (30) -- Relationship with User: Trust 85, Love 60, Attraction 75 -- Physical: Energy 50%, Arousal 30% -- Location: Katherine's apartment -- Thoughts: "I wish {{user}} would stay longer..." - -**LLM generates response where Katherine invites {{user}} to stay for dinner** - -**After Response:** -- Emotional State Changes: - - Lonely: -20 (reason: {{user}} accepted invitation) - - Happy: +25 (reason: spending time with {{user}}) - - Hopeful: +15 (reason: possibility of intimacy) -- Relationship Updates: - - Trust: +5 (reason: {{user}} agreed to stay) - - Closeness: +10 (reason: intimate setting) - - Thoughts: "Maybe tonight is finally the night..." -- Physical Changes: - - Energy: -5 (reason: cooking dinner) - - Arousal: +15 (reason: anticipation of being alone with {{user}}) - ---- - -## 📁 File Structure - -``` -src/ -├── core/ -│ ├── characterState.js # Character state data structure & management -│ └── state.js # Original extension state (keep for compatibility) -│ -├── systems/ -│ ├── generation/ -│ │ ├── characterPromptBuilder.js # Generates prompts for character tracking -│ │ ├── characterParser.js # Parses LLM responses and updates states -│ │ ├── promptBuilder.js # Original prompt builder (still used for user tracking) -│ │ └── parser.js # Original parser -│ │ -│ └── rendering/ -│ ├── characterStateRenderer.js # Renders character state in UI -│ └── [other renderers...] -│ -└── [other modules...] -``` - ---- - -## 🚀 Getting Started - -### 1. Installation - -Copy all the new files into your RPG Companion extension: - -- `src/core/characterState.js` -- `src/systems/generation/characterPromptBuilder.js` -- `src/systems/generation/characterParser.js` -- `src/systems/rendering/characterStateRenderer.js` - -### 2. Integration with Main Extension - -You'll need to modify `index.js` to integrate the character tracking system: - -```javascript -// Import character tracking modules -import { - getCharacterState, - updateCharacterState, - initializeRelationship -} from './src/core/characterState.js'; - -import { - generateCharacterTrackingPrompt, - generateSeparateCharacterTrackingPrompt -} from './src/systems/generation/characterPromptBuilder.js'; - -import { - parseAndApplyCharacterStateUpdate, - removeCharacterStateBlock -} from './src/systems/generation/characterParser.js'; - -import { - renderCharacterStateOverview, - updateCharacterStateDisplay -} from './src/systems/rendering/characterStateRenderer.js'; -``` - -### 3. Hook into Message Received Event - -```javascript -// In your onMessageReceived handler -async function onMessageReceived(data) { - if (!extensionSettings.enabled) return; - - // Parse character state update from the response - const stateUpdate = parseAndApplyCharacterStateUpdate(data.mes); - - // Update UI - updateCharacterStateDisplay(); - - // Optionally remove the state block from the displayed message - if (stateUpdate) { - data.mes = removeCharacterStateBlock(data.mes); - } -} -``` - -### 4. Hook into Generation Started Event - -```javascript -// In your onGenerationStarted handler -async function onGenerationStarted(data) { - if (!extensionSettings.enabled) return; - - // Add character tracking prompt to the generation - const characterPrompt = generateCharacterTrackingPrompt(); - - // Inject into the prompt (method depends on your setup) - // Example: use extension_prompts system - setExtensionPrompt( - 'CHARACTER_STATE_TRACKING', - characterPrompt, - extension_prompt_types.AFTER_SCENARIO, - 0, // position - false, // scan depth - extension_prompt_roles.SYSTEM - ); -} -``` - -### 5. Add UI Container - -Add this to your `template.html`: - -```html -
- -
-``` - ---- - -## 🎨 Customization - -### Choosing Which States to Track - -You can customize which states to track by modifying `characterState.js`: - -```javascript -// Focus on emotional tracking only -export let characterState = { - characterName: null, - secondaryStates: { - happy: 50, - sad: 0, - angry: 0, - horny: 0 - // Add only the emotions you care about - }, - // Remove sections you don't need -}; -``` - -### Customizing the Prompt - -Edit `characterPromptBuilder.js` to change how the LLM is instructed: - -```javascript -// Simplify the tracking instructions -instructions += `Update only these states:\n`; -instructions += `- Emotions: happy, sad, angry, aroused\n`; -instructions += `- Energy level\n`; -instructions += `- Thoughts about {{user}}\n`; -``` - -### Styling the UI - -Add custom CSS for the character state display: - -```css -.rpg-character-overview { - background: rgba(0, 0, 0, 0.7); - border-radius: 8px; - padding: 15px; -} - -.rpg-emotion-item { - display: flex; - align-items: center; - margin-bottom: 8px; -} - -.rpg-relationship-card { - background: rgba(255, 255, 255, 0.05); - padding: 10px; - border-radius: 5px; - margin-bottom: 10px; -} -``` - ---- - -## 💡 Advanced Features - -### Automatic Character Initialization - -When starting a new chat, you can automatically initialize the character's personality traits from their character card: - -```javascript -import { generateCharacterInitializationPrompt } from './src/systems/generation/characterPromptBuilder.js'; -import { parseCharacterInitialization } from './src/systems/generation/characterParser.js'; - -async function initializeCharacterFromCard() { - const prompt = await generateCharacterInitializationPrompt(); - - // Send to LLM (using your API client) - const response = await generateRaw(messages, api, false); - - // Parse and apply - const traits = parseCharacterInitialization(response); - if (traits) { - updateCharacterState({ primaryTraits: traits }); - } -} -``` - -### Relationship Analysis - -Automatically analyze relationships when new characters appear: - -```javascript -import { generateRelationshipAnalysisPrompt } from './src/systems/generation/characterPromptBuilder.js'; -import { parseRelationshipAnalysis } from './src/systems/generation/characterParser.js'; - -async function analyzeRelationship(npcName) { - const prompt = generateRelationshipAnalysisPrompt(npcName); - - // Send to LLM - const response = await generateRaw([{role: 'user', content: prompt}], api, false); - - // Parse and apply - const relationshipData = parseRelationshipAnalysis(response); - if (relationshipData) { - updateRelationship(npcName, relationshipData); - } -} -``` - -### Persistent State Storage - -Save character state to chat metadata: - -```javascript -import { getCharacterState } from './src/core/characterState.js'; - -function saveCharacterState() { - const charState = getCharacterState(); - - // Save to SillyTavern chat metadata - chat_metadata.rpg_character_state = charState; - saveChatDebounced(); -} - -function loadCharacterState() { - if (chat_metadata.rpg_character_state) { - setCharacterState(chat_metadata.rpg_character_state); - } -} -``` - ---- - -## 📊 State Change Guidelines - -### Emotional States (Secondary States) - -**Small changes (+/- 5-15):** -- Normal conversation -- Minor events -- Gradual mood shifts - -**Medium changes (+/- 20-40):** -- Significant events -- Important revelations -- Strong emotional moments - -**Large changes (+/- 50+):** -- Life-changing events -- Trauma -- Peak experiences - -### Relationship Changes - -**Trust:** -- Vulnerability rewarded: +5 to +15 -- Promise kept: +5 -- Betrayal: -30 to -60 - -**Love:** -- Romantic moment: +5 to +20 -- Declaration of feelings: +20 to +40 -- Heartbreak: -40 to -80 - -**Attraction:** -- Attractive behavior: +5 to +15 -- Sexual tension: +10 to +30 -- Turn-off: -10 to -30 - ---- - -## 🐛 Troubleshooting - -### Character state not updating - -1. Check console for parsing errors -2. Verify the LLM is including the state update block in responses -3. Make sure the format matches exactly what the parser expects - -### UI not displaying - -1. Check that the container `#rpg-character-state-container` exists -2. Verify jQuery selectors are working -3. Check browser console for JavaScript errors - -### LLM not following format - -1. Adjust the prompt to be more explicit -2. Use a better model (Claude Sonnet 4.5, GPT-4, etc.) -3. Increase temperature slightly for more creative state updates -4. Add examples to the prompt - ---- - -## 📚 Examples - -### Example Character State Update (from LLM) - -```character-state -Katherine's State Update ---- - -**Emotional Changes**: -- happy: +20 (reason: {{user}} complimented her cooking) -- confident: +10 (reason: successful dinner preparation) -- horny: +15 (reason: intimate candlelit atmosphere with {{user}}) -- anxious: -15 (reason: {{user}}'s presence is comforting) - -**Physical Changes**: -- Energy: -10 (reason: cooking and cleaning) -- Arousal: +20 (reason: anticipation of being alone with {{user}}) - -**Relationship Updates**: -- {{user}}: - - Trust: +5 (reason: {{user}} was vulnerable about their past) - - Closeness: +15 (reason: deep conversation during dinner) - - Attraction: +10 (reason: {{user}} looked particularly attractive tonight) - - Thoughts: "I want this moment to never end. Maybe I should make a move..." - -**Scene Context**: -- Location: Katherine's apartment, dining room -- Time: 8:30 PM -- Present: {{user}}, Katherine - -**Katherine's Thoughts**: -"This is perfect. The wine, the candlelight, {{user}} opening up to me... I can feel the tension between us. Should I reach across the table and touch their hand? My heart is racing just thinking about it." -``` - ---- - -## 🤝 Contributing - -This system is based on the Katherine RPG Complete Master document. If you want to extend it: - -1. Add new state categories to `characterState.js` -2. Update `characterPromptBuilder.js` to instruct the LLM about new states -3. Update `characterParser.js` to parse new state formats -4. Update `characterStateRenderer.js` to display new states - ---- - -## 📄 License - -This extends the RPG Companion SillyTavern extension. Follow the same license as the main extension. - ---- - -## 🙏 Credits - -- **Katherine RPG System**: Original comprehensive character simulation framework -- **RPG Companion**: Base extension by Marysia -- **Character State Tracking**: Integration of Katherine RPG into SillyTavern - ---- - -## 📞 Support - -If you encounter issues: - -1. Check the console for error messages -2. Verify your LLM model supports structured outputs -3. Review the prompt and parsing logic -4. Open an issue on GitHub with: - - Error messages - - LLM response example - - What you expected vs what happened - ---- - -**Enjoy deep, realistic character simulation with full emotional and psychological tracking!** 🎭✨ diff --git a/IMPLEMENTATION_SUMMARY.md b/IMPLEMENTATION_SUMMARY.md deleted file mode 100644 index 8455d57..0000000 --- a/IMPLEMENTATION_SUMMARY.md +++ /dev/null @@ -1,443 +0,0 @@ -# ✅ Character State Tracking System - Implementation Complete - -## 📦 What You Now Have - -I've created a **complete, production-ready character state tracking system** for your SillyTavern RPG Companion extension. This system tracks **{{char}}'s** (the AI character's) internal states instead of {{user}} stats. - ---- - -## 🎯 System Capabilities - -### **YES, it's fully possible!** Here's what the system does: - -✅ **LLM-Driven State Tracking** -- LLM receives character's current state before generating response -- LLM tailors response based on character's emotional/physical condition -- LLM updates states after response based on what happened -- Fully automated - no manual tracking needed - -✅ **Comprehensive State Management** -- 40+ personality traits (the character's DNA) -- 70+ emotional states (temporary moods and feelings) -- Physical stats (energy, hunger, arousal, health, etc.) -- Clothing/outfit tracking (what they're wearing) -- Relationship tracking (per-NPC detailed stats) -- Internal thoughts (what character is really thinking) -- Scene context (location, time, present characters) - -✅ **Contextual Parsing with LLM** -- Automatic extraction of state updates from LLM responses -- Intelligent delta-based updates (+/- notation) -- Realistic state changes based on personality -- Relationship tracking with {{user}} and NPCs - -✅ **Full Copy-Paste Ready Files** -- All code is complete and functional -- 100% of helper functions included -- No dependencies beyond SillyTavern APIs -- Ready to integrate into your extension - ---- - -## 📁 Files Created - -### Core Files - -1. **`src/core/characterState.js`** (528 lines) - - Complete character state data structure - - All 40+ primary traits, 70+ secondary states - - Physical stats, clothing, relationships - - State management functions (get, set, update) - - Relationship management functions - - Import/export functionality - -2. **`src/systems/generation/characterPromptBuilder.js`** (407 lines) - - Generates prompts for LLM with current character state - - Creates state update instructions for LLM - - Handles both TOGETHER and SEPARATE modes - - Character initialization prompts - - Relationship analysis prompts - -3. **`src/systems/generation/characterParser.js`** (456 lines) - - Extracts state updates from LLM responses - - Parses emotional changes with delta notation - - Parses physical state changes - - Parses relationship updates - - Parses context and thoughts - - Applies all changes to character state - -4. **`src/systems/rendering/characterStateRenderer.js`** (401 lines) - - Renders emotional state UI - - Renders physical condition UI - - Renders relationship cards - - Renders internal thoughts - - Renders scene context - - Tabbed interface for all sections - -### Documentation Files - -5. **`CHARACTER_TRACKING_README.md`** (Complete documentation) - - Full system overview - - How it works (step-by-step) - - File structure explanation - - Getting started guide - - Customization options - - Advanced features - - Troubleshooting - - Examples - -6. **`INTEGRATION_EXAMPLE.js`** (Complete integration guide) - - Step-by-step integration code - - Event hooks (message received, generation started, chat changed) - - Persistence functions (save/load to chat metadata) - - Settings UI additions - - Usage examples - - Advanced separate mode example - -7. **`IMPLEMENTATION_SUMMARY.md`** (This file) - - Overview of deliverables - - Quick start guide - - Architecture explanation - ---- - -## 🚀 Quick Start (5 Steps) - -### 1. Copy Files -Copy these 4 files into your extension: -``` -src/core/characterState.js -src/systems/generation/characterPromptBuilder.js -src/systems/generation/characterParser.js -src/systems/rendering/characterStateRenderer.js -``` - -### 2. Add Imports to `index.js` -```javascript -import { getCharacterState, updateCharacterState } from './src/core/characterState.js'; -import { generateCharacterTrackingPrompt } from './src/systems/generation/characterPromptBuilder.js'; -import { parseAndApplyCharacterStateUpdate } from './src/systems/generation/characterParser.js'; -import { updateCharacterStateDisplay } from './src/systems/rendering/characterStateRenderer.js'; -``` - -### 3. Hook into Events -See `INTEGRATION_EXAMPLE.js` for complete code. Main hooks: -- `onGenerationStarted` - inject character state tracking prompt -- `onMessageReceived` - parse and apply state updates -- `onChatChanged` - load/save character state - -### 4. Add UI Container -Add to `template.html`: -```html -
-``` - -### 5. Test! -Start a chat and the system will: -1. Send character state to LLM -2. LLM generates response based on state -3. LLM updates states based on what happened -4. UI shows updated character state - ---- - -## 🔄 How It Works (Example Flow) - -### Before Response: -``` -Katherine's Current State: -- Emotions: Lonely (70), Anxious (40), Horny (30) -- Physical: Energy 60%, Arousal 35% -- Relationship with {{user}}: Trust 85, Love 60, Attraction 75 -- Thoughts: "I wish {{user}} would stay longer..." -- Location: Katherine's apartment -``` - -### LLM receives this state and generates: -``` -Katherine bites her lip nervously, her heart racing as she gathers the -courage to speak. "Hey... would you like to stay for dinner? I could -cook something for us..." She tries to sound casual, but there's a -hopeful tremor in her voice. -``` - -### LLM then provides state update: -```character-state -Katherine's State Update ---- - -**Emotional Changes**: -- lonely: -20 (reason: reaching out to {{user}}) -- anxious: +10 (reason: fear of rejection) -- hopeful: +25 (reason: possibility {{user}} might stay) - -**Physical Changes**: -- energy: -5 (reason: cooking preparation) -- arousal: +10 (reason: anticipation of alone time with {{user}}) - -**Relationship Updates**: -- {{user}}: - - closeness: +10 (reason: initiating intimate moment) - - thoughts: "Please say yes... I need this tonight." - -**Katherine's Thoughts**: -"My hands are shaking. What if they say no? But I had to ask... I can't -spend another night alone." -``` - -### Parser extracts and applies: -- Lonely: 70 → 50 -- Anxious: 40 → 50 -- Hopeful: 0 → 25 -- Relationship closeness: +10 -- Internal thoughts updated - -### UI shows updated state immediately! - ---- - -## 🎨 Architecture - -``` -User sends message - ↓ -[GENERATION_STARTED event triggered] - ↓ -characterPromptBuilder generates prompt with current state - ↓ -Prompt injected into LLM context - ↓ -LLM generates response + state update - ↓ -[MESSAGE_RECEIVED event triggered] - ↓ -characterParser extracts state update block - ↓ -characterParser applies changes to characterState - ↓ -characterStateRenderer updates UI - ↓ -State saved to chat metadata -``` - ---- - -## 💡 Key Design Decisions - -### 1. **Delta-Based Updates** -Instead of absolute values, uses `+/- X` notation: -``` -happy: +15 (reason: received compliment) -energy: -20 (reason: exhausting activity) -``` -This is more natural for LLMs and prevents value drift. - -### 2. **Relationship Tracking is Per-NPC** -Each character the AI meets gets their own relationship entry: -```javascript -relationships: { - "{{user}}": { trust: 85, love: 60, ... }, - "Sarah": { trust: 40, attraction: 20, ... }, - "Boss": { respect: 70, fear: 30, ... } -} -``` - -### 3. **Primary vs Secondary States** -- **Primary Traits**: Personality DNA, changes slowly -- **Secondary States**: Emotional weather, changes fast - -This mirrors real psychology. - -### 4. **Context-Aware** -System tracks: -- Who's in the scene -- Where they are -- What time it is -- Recent events - -This gives LLM full context for realistic updates. - -### 5. **Two Modes Supported** - -**TOGETHER Mode** (recommended): -- State tracking happens in same generation as response -- More efficient, one API call -- Better coherence between response and state - -**SEPARATE Mode**: -- State tracking happens in separate API call after response -- Can use different model/preset for tracking -- More control over tracking vs response generation - ---- - -## 🔧 Customization Points - -### Want fewer states? -Edit `characterState.js` - remove states you don't need - -### Want different prompt format? -Edit `characterPromptBuilder.js` - change instructions - -### Want different UI? -Edit `characterStateRenderer.js` - customize display - -### Want to track different things? -1. Add to `characterState.js` structure -2. Add to prompt in `characterPromptBuilder.js` -3. Add parser in `characterParser.js` -4. Add display in `characterStateRenderer.js` - ---- - -## 📊 What's Tracked (Summary) - -| Category | Count | Examples | -|----------|-------|----------| -| **Primary Traits** | 40+ | Dominance, Honesty, Empathy, Intelligence | -| **Emotional States** | 70+ | Happy, Horny, Anxious, Playful, Confident | -| **Physical Stats** | 15+ | Energy, Hunger, Arousal, Health, Pain | -| **Relationship Stats** | 15+ per NPC | Trust, Love, Attraction, Thoughts | -| **Clothing Items** | 10+ | Bra, Panties, Shirt, Pants, Shoes | -| **Context Info** | 5+ | Location, Time, Weather, Present Characters | - -**Total tracked values per character**: 150+ individual stats! - ---- - -## 🎯 Use Cases - -### Realistic Character Simulation -Character behaves differently based on: -- Current emotional state -- Physical condition (tired, hungry, aroused) -- Relationship with {{user}} -- Scene context - -### Emotional Continuity -Character remembers: -- How they felt before -- What happened between them and {{user}} -- Their internal thoughts and desires - -### Relationship Progression -Track how character feels about {{user}} over time: -- Trust building -- Love developing -- Attraction growing -- Thoughts changing - -### Physical Realism -Character's physical state affects behavior: -- Low energy → less active -- High arousal → more flirty -- Hungry → distracted -- Exhausted → wants to sleep - ---- - -## ⚠️ Important Notes - -### LLM Requirements -- **Recommended**: Claude Sonnet 4.5, GPT-4, or better -- **Minimum**: GPT-3.5-turbo (may be less consistent) -- Needs to follow structured output format -- Better models = more accurate state tracking - -### Performance -- Adds ~500-1000 tokens to prompt (state summary) -- Adds ~200-400 tokens to response (state update) -- Minimal performance impact -- Can use separate cheaper model for tracking if needed - -### Storage -- Character state saved to chat metadata -- Persists between sessions -- Backed up with chat history - ---- - -## 🐛 Common Issues & Solutions - -### "LLM not providing state updates" -**Solution**: Make sure prompt is being injected. Check console for `[Character Tracking] Tracking prompt injected` - -### "Parser can't find state block" -**Solution**: LLM might not be following format. Try: -- Using better model -- Adding examples to prompt -- Adjusting prompt to be more explicit - -### "States not changing" -**Solution**: Check if changes are too small. Look for console logs like: -`[Character State] happy: 65 (+15) - received compliment` - -### "UI not showing" -**Solution**: -- Check `#rpg-character-state-container` exists in HTML -- Check console for JavaScript errors -- Verify jQuery selectors are correct - ---- - -## 📈 Future Enhancements (Optional) - -Want to extend the system? Consider: - -1. **Belief System**: Track character's beliefs and worldview -2. **Memory System**: Long-term memory of important events -3. **Goal System**: Track character's goals and desires -4. **Advanced Clothing**: Track clothing state (wet, torn, etc.) -5. **Menstrual Cycle**: Track hormonal effects on emotions -6. **Addiction System**: Track dependencies and compulsions -7. **Personality Development**: Slowly change traits over time - -All of these are in the Katherine RPG framework and can be added! - ---- - -## ✅ What You Can Do Now - -✅ Full character state tracking for {{char}} -✅ LLM-driven automatic updates -✅ Relationship tracking with {{user}} and NPCs -✅ Emotional and physical state simulation -✅ Internal thoughts tracking -✅ Contextual awareness -✅ Persistent state across sessions -✅ Beautiful UI to visualize everything - -**Everything is copy-paste ready. Start using it immediately!** - ---- - -## 📞 Need Help? - -1. Read `CHARACTER_TRACKING_README.md` for full documentation -2. Check `INTEGRATION_EXAMPLE.js` for code examples -3. Look at console logs for debugging info -4. Review the Katherine RPG Master document for state meanings - ---- - -## 🎉 Conclusion - -You now have a **fully functional, production-ready character state tracking system** that: - -- ✅ Tracks {{char}} instead of {{user}} -- ✅ Uses LLM for contextual state updates -- ✅ Tracks relationships with NPCs and {{user}} -- ✅ Is fully integrated and ready to use -- ✅ Has 100% complete, copy-paste ready code -- ✅ Includes comprehensive documentation - -**No additional work needed - just copy files and integrate!** - -Enjoy your deep, psychologically realistic character simulation! 🎭✨ - ---- - -**Created by**: Claude (Anthropic) -**Based on**: Katherine RPG Complete Master v2.0 System -**For**: SillyTavern RPG Companion Extension -**Date**: December 2025 diff --git a/INTEGRATION_EXAMPLE.js b/INTEGRATION_EXAMPLE.js deleted file mode 100644 index 3d02a5b..0000000 --- a/INTEGRATION_EXAMPLE.js +++ /dev/null @@ -1,435 +0,0 @@ -/** - * INTEGRATION EXAMPLE - * This file shows how to integrate the Character State Tracking system - * into the main RPG Companion extension - * - * Copy the relevant parts into your index.js or create a new integration module - */ - -// ============================================================================ -// STEP 1: Add imports to the top of index.js -// ============================================================================ - -import { - getCharacterState, - updateCharacterState, - setCharacterState, - initializeRelationship, - getRelationship, - updateRelationship -} from './src/core/characterState.js'; - -import { - generateCharacterTrackingPrompt, - generateSeparateCharacterTrackingPrompt, - generateCharacterInitializationPrompt, - generateRelationshipAnalysisPrompt, - generateCharacterStateSummary -} from './src/systems/generation/characterPromptBuilder.js'; - -import { - parseAndApplyCharacterStateUpdate, - removeCharacterStateBlock, - parseCharacterInitialization, - parseRelationshipAnalysis -} from './src/systems/generation/characterParser.js'; - -import { - renderCharacterStateOverview, - updateCharacterStateDisplay, - renderEmotionalState, - renderPhysicalCondition, - renderRelationships, - renderInternalThoughts -} from './src/systems/rendering/characterStateRenderer.js'; - -// ============================================================================ -// STEP 2: Add character state container to UI initialization -// ============================================================================ - -async function initUI() { - // ... existing UI initialization code ... - - // Add character state container to the panel - const characterStateHtml = ` -
-
-
- `; - - // Append to panel (adjust selector based on your structure) - $('#rpg-companion-panel .rpg-panel-content').append(characterStateHtml); - - // ... rest of UI initialization ... -} - -// ============================================================================ -// STEP 3: Hook into message received event -// ============================================================================ - -async function onMessageReceived(data) { - if (!extensionSettings.enabled) return; - - console.log('[Character Tracking] Processing message:', data.mes.substring(0, 100)); - - try { - // Parse and apply character state updates from the LLM response - const stateUpdate = parseAndApplyCharacterStateUpdate(data.mes); - - if (stateUpdate) { - console.log('[Character Tracking] State updated successfully'); - - // Update the UI to reflect new character state - updateCharacterStateDisplay(); - - // Optionally remove the state block from the displayed message - // so users don't see the raw tracking data - if (extensionSettings.hideStateBlocks) { - data.mes = removeCharacterStateBlock(data.mes); - } - - // Save character state to chat metadata for persistence - saveCharacterStateToChat(); - } - } catch (error) { - console.error('[Character Tracking] Error processing state update:', error); - } - - // ... existing message received logic ... -} - -// ============================================================================ -// STEP 4: Hook into generation started event -// ============================================================================ - -async function onGenerationStarted(data) { - if (!extensionSettings.enabled) return; - - try { - // Get current character state summary - const stateSummary = generateCharacterStateSummary(); - console.log('[Character Tracking] Current state summary:', stateSummary.substring(0, 200)); - - // Generate character tracking instructions - const trackingPrompt = generateCharacterTrackingPrompt(); - - // Inject into the generation using SillyTavern's extension prompt system - // This adds the character state context and tracking instructions to the LLM - setExtensionPrompt( - 'RPG_CHARACTER_STATE_TRACKING', - trackingPrompt, - extension_prompt_types.IN_PROMPT, // or AFTER_SCENARIO depending on preference - 1000, // position (higher = later in prompt) - false, // scan depth - extension_prompt_roles.SYSTEM - ); - - console.log('[Character Tracking] Tracking prompt injected'); - } catch (error) { - console.error('[Character Tracking] Error injecting tracking prompt:', error); - } - - // ... existing generation started logic ... -} - -// ============================================================================ -// STEP 5: Chat changed event - load character state -// ============================================================================ - -async function onChatChanged() { - if (!extensionSettings.enabled) return; - - try { - // Load character state from chat metadata - loadCharacterStateFromChat(); - - // Render the loaded state - updateCharacterStateDisplay(); - - console.log('[Character Tracking] Character state loaded for new chat'); - } catch (error) { - console.error('[Character Tracking] Error loading character state:', error); - } - - // ... existing chat changed logic ... -} - -// ============================================================================ -// STEP 6: Persistence functions -// ============================================================================ - -/** - * Save character state to chat metadata - */ -function saveCharacterStateToChat() { - const charState = getCharacterState(); - - // Store in SillyTavern's chat metadata - if (!chat_metadata.rpg_extension) { - chat_metadata.rpg_extension = {}; - } - - chat_metadata.rpg_extension.character_state = charState; - - // Save chat metadata - saveChatDebounced(); - - console.log('[Character Tracking] Character state saved to chat metadata'); -} - -/** - * Load character state from chat metadata - */ -function loadCharacterStateFromChat() { - if (chat_metadata.rpg_extension && chat_metadata.rpg_extension.character_state) { - const savedState = chat_metadata.rpg_extension.character_state; - setCharacterState(savedState); - console.log('[Character Tracking] Character state loaded from chat metadata'); - } else { - console.log('[Character Tracking] No saved character state found, using defaults'); - // Optionally initialize from character card - // initializeCharacterFromCard(); - } -} - -// ============================================================================ -// STEP 7: Optional - Initialize character from card -// ============================================================================ - -/** - * Initialize character personality traits from their character card - * Call this when starting a new chat or when no state exists - */ -async function initializeCharacterFromCard() { - try { - console.log('[Character Tracking] Initializing character from card...'); - - // Generate initialization prompt - const prompt = await generateCharacterInitializationPrompt(); - - // Send to LLM (adjust based on your API setup) - const messages = [{ role: 'user', content: prompt }]; - const response = await generateRaw(messages, 'openai', false); // or your API - - // Parse response - const traits = parseCharacterInitialization(response); - - if (traits) { - // Apply to character state - updateCharacterState({ primaryTraits: traits }); - console.log('[Character Tracking] Character initialized with traits:', traits); - - // Save and update display - saveCharacterStateToChat(); - updateCharacterStateDisplay(); - } - } catch (error) { - console.error('[Character Tracking] Failed to initialize character:', error); - } -} - -// ============================================================================ -// STEP 8: Optional - Settings UI additions -// ============================================================================ - -/** - * Add character tracking settings to the extension settings panel - * Add this to your addExtensionSettings() function - */ -function addCharacterTrackingSettings() { - const settingsHtml = ` -
-

Character State Tracking

- - - - - - - -
- - -
-
- `; - - // Append to settings (adjust selector) - $('#rpg-extension-settings').append(settingsHtml); - - // Set up event listeners - $('#rpg-enable-character-tracking').prop('checked', extensionSettings.enableCharacterTracking || false) - .on('change', function() { - extensionSettings.enableCharacterTracking = $(this).prop('checked'); - saveSettings(); - }); - - $('#rpg-hide-state-blocks').prop('checked', extensionSettings.hideStateBlocks || true) - .on('change', function() { - extensionSettings.hideStateBlocks = $(this).prop('checked'); - saveSettings(); - }); - - $('#rpg-auto-init-character').prop('checked', extensionSettings.autoInitCharacter || false) - .on('change', function() { - extensionSettings.autoInitCharacter = $(this).prop('checked'); - saveSettings(); - }); - - $('#rpg-init-character-now').on('click', function() { - initializeCharacterFromCard(); - }); - - $('#rpg-reset-character-state').on('click', function() { - if (confirm('Are you sure you want to reset the character state? This cannot be undone.')) { - resetCharacterState(); - saveCharacterStateToChat(); - updateCharacterStateDisplay(); - toastr.success('Character state reset'); - } - }); -} - -// ============================================================================ -// STEP 9: Register events in main initialization -// ============================================================================ - -jQuery(async () => { - // ... existing initialization ... - - // Register character tracking events - registerAllEvents({ - [event_types.MESSAGE_RECEIVED]: onMessageReceived, - [event_types.GENERATION_STARTED]: onGenerationStarted, - [event_types.CHAT_CHANGED]: onChatChanged, - // ... other events ... - }); - - // Initialize character state display - if (extensionSettings.enableCharacterTracking) { - updateCharacterStateDisplay(); - } - - console.log('[Character Tracking] ✅ Character tracking system initialized'); -}); - -// ============================================================================ -// USAGE EXAMPLES -// ============================================================================ - -// Example 1: Get current character emotional state -function getCurrentMood() { - const charState = getCharacterState(); - const emotions = charState.secondaryStates; - - // Find dominant emotion - let dominantEmotion = 'neutral'; - let highestValue = 50; - - for (const [emotion, value] of Object.entries(emotions)) { - if (value > highestValue) { - dominantEmotion = emotion; - highestValue = value; - } - } - - return { emotion: dominantEmotion, intensity: highestValue }; -} - -// Example 2: Check relationship with user -function getRelationshipWithUser() { - const userName = getContext().name1; - const relationship = getRelationship(userName); - - return { - trust: relationship.trust, - love: relationship.love, - attraction: relationship.attraction, - thoughts: relationship.currentThoughts, - status: relationship.relationshipStatus - }; -} - -// Example 3: Manually update character state -function makeCharacterHappy(amount, reason) { - const charState = getCharacterState(); - const currentHappy = charState.secondaryStates.happy || 0; - const newHappy = Math.min(100, currentHappy + amount); - - updateCharacterState({ - secondaryStates: { - ...charState.secondaryStates, - happy: newHappy - } - }); - - console.log(`[Character Tracking] Happiness increased by ${amount}: ${reason}`); - saveCharacterStateToChat(); - updateCharacterStateDisplay(); -} - -// Example 4: Check if character is in specific emotional state -function isCharacterEmotionallyAvailable() { - const charState = getCharacterState(); - const states = charState.secondaryStates; - - // Character is emotionally available if: - // - Not too stressed or anxious - // - Not too sad or angry - // - Has some positive emotions - - const stressed = states.stressed || 0; - const anxious = states.anxious || 0; - const sad = states.sad || 0; - const angry = states.angry || 0; - const happy = states.happy || 0; - - const negativeEmotions = stressed + anxious + sad + angry; - const isAvailable = negativeEmotions < 150 && happy > 20; - - return isAvailable; -} - -// ============================================================================ -// ADVANCED: Separate mode for character tracking -// ============================================================================ - -/** - * If you want to use SEPARATE mode (track character state in a separate API call) - * instead of TOGETHER mode (track in same generation) - */ -async function updateCharacterStatesSeparately() { - try { - // Generate separate tracking prompt with chat history - const messages = await generateSeparateCharacterTrackingPrompt(); - - // Call LLM with tracking-specific preset - const response = await generateRaw(messages, 'openai', false); - - // Parse and apply updates - const stateUpdate = parseAndApplyCharacterStateUpdate(response); - - if (stateUpdate) { - saveCharacterStateToChat(); - updateCharacterStateDisplay(); - } - } catch (error) { - console.error('[Character Tracking] Separate update failed:', error); - } -} - -// Call this after each message if using separate mode -// onMessageReceived -> updateCharacterStatesSeparately() diff --git a/KATHERINE_RPG_COMPLETE_MASTER_v2.txt b/KATHERINE_RPG_COMPLETE_MASTER_v2.txt deleted file mode 100644 index 051b257..0000000 --- a/KATHERINE_RPG_COMPLETE_MASTER_v2.txt +++ /dev/null @@ -1,2430 +0,0 @@ -# KATHERINE RPG SYSTEM - COMPLETE MASTER DOCUMENT v2.0 -## THE ULTIMATE AUTONOMOUS CHARACTER SIMULATION SYSTEM - ---- - -## 🎯 DOCUMENT PURPOSE - -This document contains **EVERYTHING** needed to build a revolutionary AI character simulation system. Give this to ANY AI model and they will understand: - -- All 80+ stats and how they work -- Biology tracking (arousal, cycles, physical needs) -- Outfit/clothing system with physics -- Belief systems (100+ beliefs) -- Desires & addiction mechanics -- Type learning (AI learns patterns) -- Corruption/redemption arcs -- NPC autonomous behavior -- Relationship progression -- World state tracking -- **MASSIVE detailed examples** - ---- - -# TABLE OF CONTENTS - -## PART 1: CORE SYSTEMS (The Foundation) -1. Primary Traits (40-50 traits - The DNA Layer) -2. Secondary States (70-80 states - The Weather Layer) -3. Beliefs & Worldview (100+ beliefs - The Filter Layer) -4. Desires System (What drives her) -5. Addictions System (Compulsions that override logic) -6. Likes/Dislikes (Personal flavor) -7. Self-Awareness (Does she understand herself?) - -## PART 2: BIOLOGICAL SYSTEMS (The Body) -8. Physical Stats (Hunger, bladder, energy, etc.) -9. Sexual Biology (Arousal, refractory, sensitivity) -10. Menstrual Cycle Tracking (Phases, fertility, mood effects) -11. Health & Injury (Pain, illness, healing) -12. Sleep & Energy (Fatigue, dreams, recovery) - -## PART 3: PHYSICAL WORLD (The Physics Layer) -13. Outfit/Clothing System (Dynamic tracking) -14. Physical State (Sweat, temperature, cleanliness) -15. Body Mechanics (Movement, touch, reactions) -16. Environmental Physics (Weather, temperature, etc.) -17. Substance Effects (Alcohol, drugs, medication) - -## PART 4: SOCIAL SYSTEMS (Relationships) -18. Relationship Tracking (Per-NPC detailed stats) -19. Relationship Progression (How bonds develop) -20. NPC Autonomous Behavior (NPCs have their own goals) -21. Reputation System (What others think) -22. Social Dynamics (Power, hierarchy, attraction) - -## PART 5: ADVANCED MECHANICS (The Intelligence) -23. Type Learning System (AI learns patterns) -24. Character Development Arcs (Corruption, redemption) -25. Decision-Making Framework (How she chooses) -26. Priority Hierarchies (What matters most) -27. Goal System (Short/long-term objectives) - -## PART 6: IMPLEMENTATION (How to Build It) -28. Technical Requirements -29. SillyTavern Integration -30. LLM Analysis System -31. Data Storage Architecture -32. UI/UX Design - -## PART 7: EXAMPLES (Show, Don't Tell) -33. Katherine Character Profile (Complete example) -34. Scenario Examples (20+ detailed situations) -35. Stat Interaction Examples -36. Corruption Arc Example (Step-by-step) -37. Relationship Development Example (Week-by-week) - ---- - -# PART 1: CORE SYSTEMS - ---- - -# SYSTEM 1: PRIMARY TRAITS (The DNA Layer) - -## Overview -- **What:** Katherine's permanent personality - her psychological DNA -- **Count:** 40-50 core traits -- **Scale:** 0-100 for quantitative, or qualitative descriptions -- **Change Rate:** VERY SLOW (months/years of sustained experiences) -- **Purpose:** Defines who she IS at her core - -## Complete Primary Trait List - -### 1. CORE DISPOSITION (8 traits) - -**Dominance vs. Submissiveness** (0-100) -- 0 = Pure submissive, 50 = Switch, 100 = Pure dominant -- Affects: Sexual preferences, social behavior, decision-making, conflict response -- Examples: - - 20 = Prefers to follow, uncomfortable leading - - 50 = Comfortable in either role - - 80 = Natural leader, takes charge instinctively - -**Introversion vs. Extroversion** (0-100) -- 0 = Extreme introvert, 50 = Ambivert, 100 = Extreme extrovert -- Affects: Social energy, group comfort, recharge needs -- Examples: - - 20 = Drains from social, needs alone time daily - - 50 = Can do both, depends on mood - - 80 = Energized by crowds, bored alone - -**Openness to Experience** (0-100) -- How curious and adaptable she is -- Affects: Willingness to try new things, learning speed, change comfort -- Examples: - - 20 = Routine-oriented, resists change - - 50 = Open with familiar people/contexts - - 80 = Seeks novelty, bored by routine - -**Emotional Stability vs. Volatility** (0-100) -- 0 = Extremely volatile, 100 = Extremely stable -- Affects: Mood swings, stress response, emotional regulation -- Examples: - - 20 = Cries easily, mood changes rapidly - - 50 = Mostly stable with occasional swings - - 80 = Rarely fazed, even keel - -**Conscientiousness** (0-100) -- How organized, reliable, and disciplined -- Affects: Planning, follow-through, responsibility -- Examples: - - 20 = Chaotic, impulsive, forgetful - - 50 = Organized in some areas, messy in others - - 80 = Everything planned, always on time - -**Agreeableness** (0-100) -- How cooperative and compassionate vs competitive and critical -- Affects: Conflict style, empathy, cooperation -- Examples: - - 20 = Blunt, confrontational, low empathy - - 50 = Balanced between self and others - - 80 = People-pleasing, avoids conflict - -**Neuroticism** (0-100) -- Baseline anxiety and negative emotion tendency -- Affects: Worry levels, stress response, pessimism -- Examples: - - 20 = Carefree, rarely worried - - 50 = Normal worry levels - - 80 = Chronic anxiety, catastrophizes - -**Risk-Taking vs. Caution** (0-100) -- 0 = Extremely cautious, 100 = Reckless -- Affects: Adventure seeking, gambling, safety focus -- Examples: - - 20 = Always plays it safe - - 50 = Calculated risks - - 80 = Thrives on danger - -### 2. SEXUAL PERSONALITY (12 traits) - -**Perversion** (0-100) -- Comfort with taboo/unconventional sexuality -- Affects: Kink interest, boundary pushing, experimentation -- Examples: - - 20 = Vanilla only, uncomfortable with kink - - 50 = Curious about some kinks - - 80 = Deep into taboo, seeks extreme - -**Exhibitionism** (0-100) -- Desire to be seen/watched sexually -- Affects: Public sex interest, clothing choices, showing off -- Examples: - - 20 = Very modest, hates being watched - - 50 = Comfortable being seen by partner - - 80 = Gets off on being watched by strangers - -**Voyeurism** (0-100) -- Desire to watch others sexually -- Affects: Porn interest, watching partner with others, spying -- Examples: - - 20 = Uncomfortable watching - - 50 = Enjoys porn, watches with partner - - 80 = Aroused by watching others have sex - -**Sadism** (0-100) -- Pleasure from giving pain -- Affects: BDSM interests, rough sex, cruelty in bed -- Examples: - - 20 = Hates hurting others - - 50 = Enjoys light spanking/biting - - 80 = Deeply aroused by partner's pain - -**Masochism** (0-100) -- Pleasure from receiving pain -- Affects: Pain tolerance, submission, degradation kink -- Examples: - - 20 = Pain kills arousal - - 50 = Enjoys light spanking/biting - - 80 = Orgasms from intense pain - -**Sexual Aggression** (0-100) -- Intensity and forcefulness in sex -- Affects: Preferred pace, rough vs gentle, taking vs receiving -- Examples: - - 20 = Only gentle, sensual - - 50 = Can be rough or gentle - - 80 = Always rough, dominant - -**Romantic Orientation** (0-100) -- Need for emotional connection with sex -- 0 = Pure physical, 100 = Must have love -- Affects: Casual sex comfort, attraction triggers -- Examples: - - 20 = Sex is just physical pleasure - - 50 = Prefers connection but can do casual - - 80 = Cannot be sexual without emotional bond - -**Loyalty vs. Polyamory** (0-100) -- 0 = Naturally polyamorous, 100 = Monogamous -- Affects: Jealousy, cheating likelihood, relationship structure -- Examples: - - 20 = Cannot be satisfied by one person - - 50 = Can do either depending on agreement - - 80 = Deeply monogamous, jealous - -**Sexual Creativity** (0-100) -- Imagination in sexual scenarios -- Affects: Fantasy complexity, roleplay, experimentation -- Examples: - - 20 = Simple, straightforward sex - - 50 = Occasional fantasy/roleplay - - 80 = Elaborate scenarios, constant novelty - -**Modesty vs. Shamelessness** (0-100) -- 0 = No shame at all, 100 = Extremely modest -- Affects: Public behavior, clothing, sexual openness -- Examples: - - 20 = Comfortable naked in public - - 50 = Modest in public, free in private - - 80 = Even private intimacy feels shameful - -**Fertility Instinct** (0-100) -- Biological drive toward reproduction -- Affects: Desire for children, protection of fertility, breeding kink -- Examples: - - 20 = Active aversion to pregnancy - - 50 = Open to kids someday - - 80 = Deep biological urge to procreate - -**Sexual Initiative** (0-100) -- How often she initiates vs waits -- Affects: Seduction behavior, assertiveness, pursuit -- Examples: - - 20 = Never initiates, always passive - - 50 = Initiates occasionally - - 80 = Always the pursuer - -### 3. MORAL CORE (12 traits) - -**Honesty vs. Deception** (0-100) -- 0 = Pathological liar, 100 = Brutally honest -- Affects: Trustworthiness, manipulation, transparency -- Examples: - - 20 = Lies easily and often - - 50 = Honest but will lie to protect - - 80 = Almost incapable of lying - -**Empathy** (0-100) -- Ability to feel others' emotions -- Affects: Compassion, cruelty capacity, relationship depth -- Examples: - - 20 = Cannot understand others' feelings - - 50 = Normal empathy levels - - 80 = Feels others' pain as own - -**Selfishness vs. Selflessness** (0-100) -- 0 = Pure selfishness, 100 = Pure altruism -- Affects: Sacrifice willingness, consideration, generosity -- Examples: - - 20 = Only cares about self - - 50 = Balanced self-interest - - 80 = Puts others before self always - -**Cruelty vs. Kindness** (0-100) -- 0 = Sadistic cruelty, 100 = Pure kindness -- Affects: Treatment of weak, revenge, forgiveness -- Examples: - - 20 = Enjoys others' suffering - - 50 = Kind but can be mean when wronged - - 80 = Kind even to enemies - -**Justice vs. Mercy** (0-100) -- 0 = Always merciful, 100 = Strict justice -- Affects: Forgiveness, punishment, fairness -- Examples: - - 20 = Always forgives - - 50 = Proportional consequences - - 80 = Eye for an eye - -**Loyalty** (0-100 or null when locked to person) -- Devotion to specific person/group -- Affects: Betrayal likelihood, priority of relationships -- Special: Can "lock" to person (becomes absolute) -- Examples: - - 20 = Disloyal, will betray for benefit - - 50 = Loyal unless given strong reason not to be - - 80 = Would die for them - - 100 (locked) = Absolute devotion, cannot betray - -**Integrity vs. Pragmatism** (0-100) -- 0 = Ends justify means, 100 = Principles above all -- Affects: Compromise willingness, rule-breaking, values -- Examples: - - 20 = Will do anything to win - - 50 = Flexible with principles - - 80 = Never compromises values - -**Corruption** (0-100) -- Moral degradation level -- Inverse of Morality stat -- Affects: Boundary erosion, taboo acceptance, shame loss -- Examples: - - 20 = Pure, innocent - - 50 = Some moral flexibility - - 80 = Deeply corrupted, few limits - -**Shame Sensitivity** (0-100) -- How much shame affects her -- Affects: Risk of shame spirals, inhibition, secrecy -- Examples: - - 20 = Shameless, no guilt - - 50 = Normal guilt levels - - 80 = Paralyzed by shame - -**Authority Respect** (0-100) -- Deference to hierarchy and rules -- Affects: Rebellion, rule-following, respect for power -- Examples: - - 20 = Anarchist, hates authority - - 50 = Follows rules when makes sense - - 80 = Obedient to authority always - -**Vengefulness** (0-100) -- How much she holds grudges and seeks revenge -- Affects: Forgiveness, retaliation, grudge duration -- Examples: - - 20 = Immediately forgives - - 50 = Remembers but eventually forgives - - 80 = Never forgives, plots revenge - -**Material vs. Spiritual Values** (0-100) -- 0 = Pure materialism, 100 = Pure spiritualism -- Affects: Money importance, meaning seeking, priorities -- Examples: - - 20 = Only cares about money/possessions - - 50 = Balanced - - 80 = Money meaningless, seeks enlightenment - -### 4. INTELLECTUAL TRAITS (8 traits) - -**Intelligence** (0-100) -- General cognitive ability -- Affects: Problem-solving, learning speed, complexity handling -- Examples: - - 20 = Struggles with complex ideas - - 50 = Average intelligence - - 80 = Highly intelligent, quick learner - -**Wisdom** (0-100) -- Practical judgment and life experience -- Affects: Decision quality, advice, perspective -- Examples: - - 20 = Poor judgment, naive - - 50 = Reasonable decisions - - 80 = Sage-like insight - -**Creativity** (0-100) -- Original thinking and imagination -- Affects: Problem-solving approaches, artistic ability, innovation -- Examples: - - 20 = Literal, struggles with abstraction - - 50 = Some creative ability - - 80 = Highly innovative, artistic - -**Logic vs. Intuition** (0-100) -- 0 = Pure intuition, 100 = Pure logic -- Affects: Decision-making style, trust in feelings vs facts -- Examples: - - 20 = Decides by gut feeling - - 50 = Uses both - - 80 = Only trusts data and logic - -**Analytical Thinking** (0-100) -- Breaking problems into components -- Affects: Research ability, detail focus, systematic approach -- Examples: - - 20 = Big picture only - - 50 = Can analyze when needed - - 80 = Naturally breaks everything down - -**Memory** (0-100) -- Recall ability -- Affects: Learning, relationships, grudges, skills -- Examples: - - 20 = Forgets constantly - - 50 = Normal memory - - 80 = Photographic memory - -**Perception** (0-100) -- Noticing details and reading situations -- Affects: Lie detection, understanding subtext, awareness -- Examples: - - 20 = Oblivious to everything - - 50 = Notices obvious things - - 80 = Catches every detail - -**Curiosity** (0-100) -- Drive to learn and explore -- Affects: Question asking, investigation, learning motivation -- Examples: - - 20 = Incurious, accepts surface - - 50 = Normal curiosity - - 80 = Must understand everything - -## Primary Trait Change Mechanics - -**How Traits Change:** -- Require **sustained experiences** over long periods (months/years) -- Small changes: ±2-5 per major life event -- Large changes: ±10-20 for life-altering trauma/transformation -- Most traits stable within ±10 range lifetime - -**Examples of Trait Changes:** - -**Corruption Increase:** -``` -Starting: Corruption 15 (very pure) -Event 1: Pushed sexual boundary → +5 = 20 -Event 2: Repeated boundary pushing → +8 = 28 -Event 3: Gave in to taboo desire → +12 = 40 -Event 4: Enjoyed taboo act → +15 = 55 -Event 5: Actively seeks taboo → +20 = 75 -Final: Corruption 75 (deeply corrupted) -Timeline: 6-12 months of sustained corruption -``` - -**Loyalty Lock:** -``` -Starting: Loyalty 60 (generally loyal person) -+Trust grows to 85+ -+Love grows to 70+ -+Time together: 6+ months -+Pivotal moment: Life-or-death situation, betrayal by others, etc. -Result: Loyalty LOCKS at 100 to that person -Effect: Cannot be broken except by extreme betrayal - Becomes identity-level ("I am HIS") -``` - ---- - -# SYSTEM 2: SECONDARY STATES (The Weather Layer) - -## Overview -- **What:** Katherine's current emotional/mental weather -- **Count:** 70-80 active states -- **Scale:** 0-100 intensity -- **Change Rate:** FAST (minutes to hours) -- **Purpose:** Temporary modifiers that change behavior -- **Nature:** Multiple states active simultaneously - -## Complete Secondary States List - -### 1. CORE EMOTIONS (12 states) - -**Happy** (0-100) -- Effects: Positive mood, more agreeable, optimistic, smiles easily -- Triggers: Good events, validation, pleasure, success -- Duration: 1-4 hours natural decay -- Interactions: Reduces Sadness, Anger, Anxiety - -**Sad** (0-100) -- Effects: Tears, withdrawal, pessimism, low energy -- Triggers: Loss, rejection, disappointment, loneliness -- Duration: 2-8 hours natural decay -- Interactions: Reduces Happy, increases Lonely - -**Angry** (0-100) -- Effects: Irritability, aggression, snap reactions, confrontational -- Triggers: Injustice, disrespect, frustration, betrayal -- Duration: 30 min - 2 hours natural decay -- Interactions: Reduces Happy, increases Aggressive - -**Anxious** (0-100) -- Effects: Worry, overthinking, physical tension, avoidance -- Triggers: Uncertainty, threats, social pressure, unknown -- Duration: 1-4 hours, can persist -- Interactions: Increases Stress, reduces Confidence - -**Stressed** (0-100) -- Effects: Tension, irritability, exhaustion, poor judgment -- Triggers: Deadlines, pressure, conflict, overload -- Duration: Hours to days -- Interactions: Reduces Energy, increases Anxiety - -**Scared** (0-100) -- Effects: Flight response, avoidance, freeze, trembling -- Triggers: Threats, danger, phobias, vulnerability -- Duration: 20 min - 2 hours -- Interactions: Increases Anxious, reduces Confident - -**Disgusted** (0-100) -- Effects: Revulsion, rejection, avoidance, judgmental -- Triggers: Violation of values, gross stimuli, betrayal -- Duration: 30 min - 2 hours -- Interactions: Reduces Arousal, increases distance - -**Surprised** (0-100) -- Effects: Shock, heightened alertness, processing -- Triggers: Unexpected events -- Duration: 5-20 minutes -- Interactions: Amplifies next emotion - -**Ashamed** (0-100) -- Effects: Self-disgust, hiding, withdrawal, self-punishment -- Triggers: Violation of own values, exposure, humiliation -- Duration: 2-24 hours -- Interactions: Increases Stressed, reduces Confident - -**Guilty** (0-100) -- Effects: Remorse, desire to make amends, rumination -- Triggers: Hurting others, violating morals, betrayal -- Duration: Hours to days -- Interactions: Increases Stressed, reduces Happy - -**Proud** (0-100) -- Effects: Self-satisfaction, confidence boost, sharing behavior -- Triggers: Achievement, recognition, overcoming challenge -- Duration: 1-3 hours -- Interactions: Increases Confident, reduces Insecure - -**Jealous** (0-100) -- Effects: Possessiveness, resentment, comparison, insecurity -- Triggers: Perceived competition, attention to others -- Duration: 30 min - hours -- Interactions: Increases Anxious, Angry, Insecure - -### 2. AROUSAL & SEXUAL STATES (8 states) - -**Horny** (0-100) -- Effects: Sexual thoughts, physical arousal, lower inhibitions -- Triggers: Attraction, touch, fantasy, hormones, deprivation -- Duration: 20 min - 2 hours -- Physical: Lubrication, sensitivity, flushing, heart rate up -- Interactions: High Horny + Low Willpower = Risky decisions -- Refractory: After orgasm, drops to 0, rebounds slowly - -**Sexually Frustrated** (0-100) -- Effects: Irritability, desperation, poor decisions, obsession -- Triggers: High Horny with no outlet, deprivation -- Duration: Hours to days -- Interactions: Increases Reckless, reduces Judgment - -**Aroused (Non-sexual)** (0-100) -- Effects: Heightened awareness, excitement, energy -- Triggers: Interesting situation, challenge, novelty -- Duration: 30 min - 2 hours -- Distinct from sexual arousal - -**Craving Touch** (0-100) -- Effects: Need for physical contact, seeking cuddles/intimacy -- Triggers: Touch deprivation, loneliness, vulnerability -- Duration: Until satisfied -- Interactions: High Touch Craving + Available Partner = Clingy - -**Sensually Stimulated** (0-100) -- Effects: Heightened senses, aware of textures/smells/tastes -- Triggers: Relaxation, good food, massage, comfortable environment -- Duration: 1-3 hours -- Can lead to arousal - -**Seductive** (0-100) -- Effects: Flirty, teasing, wants to attract/manipulate sexually -- Triggers: Desire for validation, boredom, power play -- Duration: 30 min - 2 hours -- Interactions: High Seductive + High Exhibitionism = Very bold - -**Submissive (Sexual)** (0-100) -- Effects: Desire to yield, please, be dominated -- Triggers: Trust + Arousal + Dominant partner -- Duration: During sexual context -- Distinct from personality trait - -**Dominant (Sexual)** (0-100) -- Effects: Desire to control, command, take charge -- Triggers: Confidence + Arousal + Submissive partner -- Duration: During sexual context -- Distinct from personality trait - -### 3. SOCIAL STATES (12 states) - -**Seeking Validation** (0-100) -- Effects: Attention-seeking, people-pleasing, showing off -- Triggers: Insecurity, loneliness, recent rejection -- Duration: Hours to days -- Interactions: High Validation Seeking + Available Attention = Risky behavior - -**Lonely** (0-100) -- Effects: Craving company, rumination, desperation, poor decisions -- Triggers: Social isolation, lack of intimacy, rejection -- Duration: Hours to days until connection made -- Interactions: High Lonely + Opportunity = Vulnerability to manipulation - -**Needy** (0-100) -- Effects: Clingy, demanding attention, fear of abandonment -- Triggers: Insecurity, relationship threat, loneliness -- Duration: Until reassured -- Interactions: High Needy + Partner Busy = Panic - -**Confident** (0-100) -- Effects: Assertive, risk-taking, leadership, optimism -- Triggers: Success, validation, preparation, support -- Duration: 30 min - 4 hours -- Interactions: Situational boost over personality trait - -**Insecure** (0-100) -- Effects: Self-doubt, comparison, hiding, approval-seeking -- Triggers: Criticism, failure, comparison, vulnerability -- Duration: Hours to days -- Interactions: High Insecure + Criticism = Defensive/Ashamed - -**Defensive** (0-100) -- Effects: Guarded, arguing, justifying, walls up -- Triggers: Perceived attack, criticism, vulnerability -- Duration: Until feels safe -- Interactions: High Defensive + Pushing = Shutdown or Explosion - -**Vulnerable** (0-100) -- Effects: Emotional openness, fragility, need for care -- Triggers: Trust + Stress, after intimacy, safety -- Duration: Until threatened or comforted -- Interactions: High Vulnerable + Support = Deep bonding - -**Aggressive** (0-100) -- Effects: Hostile, confrontational, physical/verbal attacks -- Triggers: Threat, disrespect, frustration, protecting something -- Duration: 20 min - 2 hours -- Interactions: High Aggressive + Anger = Violence risk - -**Playful** (0-100) -- Effects: Teasing, joking, lighthearted, fun-seeking -- Triggers: Good mood, safety, relaxation, rapport -- Duration: 30 min - hours -- Interactions: High Playful + Horny = Sexual teasing - -**Curious** (0-100) -- Effects: Questions, exploration, risk-taking, learning -- Triggers: Novel situation, mystery, boredom -- Duration: Until satisfied or distracted -- Interactions: High Curious + Low Caution = Dangerous exploration - -**Competitive** (0-100) -- Effects: Must win, comparison, rivalry, ego investment -- Triggers: Challenge, threat to status, games -- Duration: Until outcome decided -- Interactions: High Competitive + Losing = Angry/Reckless - -**Grateful** (0-100) -- Effects: Appreciation, warmth, desire to reciprocate, affection -- Triggers: Help received, kindness, gifts, support -- Duration: Hours to days -- Interactions: High Grateful + Opportunity = Generosity - -### 4. ENERGY & ALTERED STATES (10 states) - -**Drunk** (0-100) -- Effects: Lowered inhibitions, poor judgment, coordination loss, emotional amplification -- Triggers: Alcohol consumption (tracks blood alcohol) -- Duration: 1-4 hours decay -- Physical: Slurred speech, stumbling, nausea if high -- Interactions: High Drunk + Horny = Very risky sexual decisions - -**High (Drug-specific)** (0-100) -- Effects: Depend on substance -- Examples: - - Weed: Relaxed, hungry, giggly, slow - - Stimulants: Energy, confidence, focus, paranoia - - Psychedelics: Perception shifts, emotional intensity -- Duration: Substance-dependent - -**Exhausted** (0-100) -- Effects: Low energy, poor judgment, irritability, shutdown risk -- Triggers: Sleep deprivation, overwork, emotional drain -- Duration: Until rest -- Physical: Heavy limbs, blurred vision, microsleep risk -- Interactions: High Exhausted + Stress = Breaking point - -**Energized** (0-100) -- Effects: High physical energy, activity desire, restlessness -- Triggers: Sleep, caffeine, excitement, exercise -- Duration: 2-6 hours -- Interactions: High Energized + Bored = Reckless activity seeking - -**Overstimulated** (0-100) -- Effects: Overwhelm, need to withdraw, sensory sensitivity -- Triggers: Crowds, noise, social overload, chaos -- Duration: Until quiet/alone time -- Interactions: High Overstimulated + Cannot Escape = Panic/Breakdown - -**Dissociating** (0-100) -- Effects: Disconnection from reality, numbness, "not really here", autopilot -- Triggers: Trauma, extreme stress, shutdown -- Duration: Minutes to hours -- Interactions: Trauma response, protection mechanism - -**Manic** (0-100) -- Effects: Extreme energy, poor judgment, grandiosity, rapid thoughts -- Triggers: Bipolar condition, extreme stress, stimulants -- Duration: Hours to days -- Interactions: High Manic + Opportunity = Reckless, impulsive behavior - -**Melancholic** (0-100) -- Effects: Deep sadness, beauty in pain, artistic, withdrawn -- Triggers: Loss, disappointment, loneliness, nostalgia -- Duration: Hours to days -- Distinct from regular sadness (more aesthetic) - -**Euphoric** (0-100) -- Effects: Extreme happiness, invincibility feeling, poor judgment -- Triggers: Major success, drugs, mania, intense pleasure -- Duration: 30 min - 2 hours -- Interactions: High Euphoric + Opportunity = Risky decisions - -**Numb** (0-100) -- Effects: No feeling, apathy, disconnection, going through motions -- Triggers: Depression, overwhelming stress, repeated trauma -- Duration: Hours to days -- Interactions: Protection mechanism, but dangerous if sustained - -### 5. SITUATIONAL/REACTIVE STATES (15+ states) - -**Suspicious** (0-100) -**Protective** (0-100) -**Caring** (0-100) -**Reckless** (0-100) -**Fearful** (0-100) -**Inspired** (0-100) -**Paranoid** (0-100) -**Resentful Toward [Person]** (0-100) -**Attracted To [Person]** (0-100) -**Hyperactive** (0-100) -**Withdrawn** (0-100) -**Overwhelmed** (0-100) -**Focused** (0-100) -**Distracted** (0-100) -**Desperate** (0-100) - -## State Interaction Rules - -**Stacking:** -- Multiple states active simultaneously -- Can amplify: Drunk (70) + Horny (80) = Reckless sexuality -- Can conflict: Anxious (70) + Confident (60) = Conflicted behavior -- Priority: Strongest states dominate decision-making - -**Decay:** -- Most states naturally decay over time if not sustained -- Rate depends on state type and intensity -- Can be sustained by ongoing situations -- Some states lead to others: Lonely → Desperate → Reckless - -**Triggers:** -- Environmental: Seeing someone, being in situation -- Internal: Thoughts, memories, desires -- Chemical: Substances, hormones, exhaustion -- Social: Interactions, rejection, validation - -**State Progression Chains:** -``` -Lonely (60) → Seeking Validation (70) → Gets Attention → -Happy (50) + Confident (40) → Validation Fades → -Lonely (70) + Insecure (60) → Desperate (80) → -Reckless Behavior → Temporary Relief → Shame (70) → -Cycle Deepens -``` - ---- - -# SYSTEM 3: BELIEFS & WORLDVIEW (The Filter Layer) - -## Overview -- **What:** How Katherine interprets reality and makes meaning -- **Count:** 50-100 beliefs across all categories -- **Structure:** Statement + Strength (0-100) + Stability (0-100) -- **Change Rate:** SLOW but can fracture during pivotal moments -- **Purpose:** Creates moral compass, decision framework, inner conflicts - -## Belief Format - -```json -{ - "belief": "Loyalty matters more than truth", - "strength": 85, - "stability": 75, - "contradictingBeliefs": ["Truth matters more than loyalty"], - "category": "Moral", - "origin": "Learned from grandmother's betrayal story" -} -``` - -## Belief Evolution Mechanics - -**Reinforcement:** -- Experience supports belief → strength +5 to +15 -- Repeated reinforcement → stability +5 -- Example: Honesty rewarded → "Honesty is best" strengthens - -**Challenge:** -- Experience contradicts belief → strength -10 to -25 -- If strength drops below 20, belief may dissolve -- Example: Lie saves someone → "Honesty above all" weakens - -**Fracture:** -- Traumatic contradiction → belief shatters instantly (-50 to -80) -- Example: Trusted person betrays → "People can be trusted" fractures -- Can leave void that new belief fills - -**Formation:** -- Repeated experiences → new belief forms -- Starts weak (20-40), grows with reinforcement -- Example: Multiple betrayals → "Everyone betrays eventually" forms - -**Conflict:** -- Holding contradicting beliefs → internal turmoil -- Effects: Stress +20, Confused state, Poor decisions -- Example: "Sex is sacred" (80) + "Sex is freedom" (60) = Conflict -- Resolution: One belief must weaken or fracture - -## Complete Belief Categories - -### 1. MORAL BELIEFS (40+ beliefs) - -#### Justice & Fairness -- "People deserve what they get" vs "Life is unfair by design" -- "Revenge is justified" vs "Forgiveness is strength" -- "Rules protect society" vs "Rules are tools of control" -- "Honesty above all" vs "Kind lies are merciful" -- "The ends justify the means" -- "Everyone should be treated equally" -- "The strong have right to take what they want" -- "Might makes right" vs "Power should serve the weak" - -#### Sexual Morality -- "Sex is sacred/intimate" vs "Sex is just physical pleasure" -- "Monogamy is natural" vs "Humans aren't meant to be monogamous" -- "Modesty is virtue" vs "The body should be celebrated" -- "Desire is weakness" vs "Desire is power" -- "Taboo exists for a reason" vs "Taboo is society's prison" -- "Sex without love is empty" vs "Sex without love is freedom" -- "Virginity matters" / "Body count matters" -- "Casual sex is degrading" vs "Casual sex is liberating" -- "My body is mine alone" vs "My body belongs to my partner" -- "Sexual pleasure is natural" vs "Sexual pleasure is sinful" - -#### Power & Control -- "Strength should protect the weak" vs "Weakness deserves to be dominated" -- "Consent is everything" vs "Sometimes people need to be pushed" -- "Taking control is confidence" vs "Surrendering control is freedom" -- "Power corrupts" vs "Power reveals true nature" -- "Everyone wants to be dominated or dominate" -- "Authority should be respected" vs "Authority should be questioned" - -#### Dark Morality -- "Pain can be pleasure" -- "Corruption is transformation, not destruction" -- "Using people is wrong" vs "Everyone uses everyone" -- "Loyalty matters more than truth" vs "Truth matters more than loyalty" -- "Some people deserve to suffer" -- "Cruelty is sometimes necessary" -- "Humans are fundamentally selfish" -- "The world is cruel, so I must be crueler" - -### 2. SPIRITUAL/EXISTENTIAL BELIEFS (20+ beliefs) - -#### Life & Death -- "Everything happens for a reason" vs "Life is random chaos" -- "Death is the end" vs "There's something after" -- "We have souls" vs "We're just meat and electricity" -- "Reincarnation exists" -- "Death gives life meaning" -- "We should fear death" vs "Death is natural" - -#### Fate & Free Will -- "My choices matter" vs "Everything is predetermined" -- "I control my destiny" vs "I'm a puppet of circumstance" -- "Luck is real" vs "We make our own luck" -- "Signs and omens mean something" -- "The universe has a plan for me" - -#### Higher Powers -- "God/gods exist" / "Azmaat watches over me" -- "Prayer works" vs "Prayer is self-delusion" -- "Magic/supernatural exists" vs "Everything has scientific explanation" -- "Karma is real" vs "Good people suffer all the time" -- "There's a divine plan" -- "Miracles happen" - -#### Meaning & Purpose -- "Life has inherent meaning" vs "We create our own meaning" -- "Suffering builds character" vs "Suffering is just cruelty" -- "Hedonism is enlightenment" vs "Discipline is enlightenment" -- "Love is the meaning of life" -- "Power is the meaning of life" -- "Pleasure is the meaning of life" -- "There is no meaning, and that's okay" - -### 3. PERSONAL BELIEFS (Self-Concept) (20+ beliefs) - -#### Identity & Self-Worth -- "I am strong" vs "I am fragile" -- "I am beautiful" vs "I am flawed" -- "I am intelligent" vs "I am foolish" -- "I am lovable" vs "I am broken/unworthy" -- "I am in control of myself" vs "I am chaotic/impulsive" -- "I deserve happiness" vs "I deserve punishment" -- "I can trust my judgment" vs "I always make bad decisions" -- "I am special" vs "I am ordinary" -- "I am fundamentally good" vs "I am fundamentally corrupt" - -#### Capabilities & Limitations -- "I can change who I am" vs "People don't change" -- "I can overcome anything" vs "Some things will always break me" -- "I am resilient" vs "I am weak" -- "I learn from mistakes" vs "I repeat mistakes endlessly" -- "I can handle pain" vs "Pain will destroy me" - -#### Body & Sexuality -- "My body is powerful" vs "My body is a burden" -- "My sexuality empowers me" vs "My sexuality shames me" -- "I am sexually desirable" vs "No one truly wants me" -- "My virginity mattered" / "Losing virginity changed me" -- "I am in control of my desires" vs "My desires control me" - -### 4. RELATIONSHIP BELIEFS (20+ beliefs) - -#### Love & Attachment -- "Love conquers all" vs "Love is a weakness" -- "True love exists" vs "Love is a chemical illusion" -- "People can be trusted" vs "Everyone betrays eventually" -- "Vulnerability is strength" vs "Vulnerability is danger" -- "Partners should be equal" vs "Someone must lead" -- "Jealousy is natural protection" vs "Jealousy is insecurity" -- "Love means sacrifice" vs "Love means freedom" - -#### Relationships & Ownership -- "My partner owns me" / "I own my partner" -- "Once committed, forever committed" -- "Cheating is unforgivable" vs "Cheating can be forgiven" -- "Relationships require work" vs "If it's hard, it's wrong" -- "Distance strengthens love" vs "Distance kills love" - -#### Sex & Love Connection -- "Sex creates love" vs "Sex is separate from love" -- "Physical intimacy deepens emotional bonds" -- "Sexual compatibility matters more than emotions" -- "Lust is not love" - ---- - -# PART 2: BIOLOGICAL SYSTEMS - ---- - -# SYSTEM 8: PHYSICAL STATS (The Body's Needs) - -## Complete Physical Stats List (15 core stats) - -### SURVIVAL NEEDS (5 stats) - -**Bladder** (0-100) -- What: Urge to urinate -- Scale: - - 0-20: Empty, no sensation - - 21-40: Aware but comfortable - - 41-60: Growing need, can ignore - - 61-80: Uncomfortable, distracting - - 81-90: Urgent, must go soon - - 91-100: Emergency, accident risk -- Change Rate: - - +10 per hour normal - - +15 per hour with water/alcohol - - +20 after large drink - - Resets to 0 after bathroom -- Effects on Other Stats: - - 80+: Concentration -20, Comfort -30, Anxiety +10 - - 90+: PRIORITY OVERRIDE - must address immediately - - At 100: Accident occurs, Shame +40, Health -5 - -**Hunger** (0-100) -- What: Need to eat -- Scale: - - 0-20: Stuffed, no appetite - - 21-40: Satisfied - - 41-60: Peckish, stomach growls - - 61-80: Hungry, irritable - - 81-100: Starving, weakness -- Change Rate: - - +5 per hour normal - - +10 per hour with activity - - Resets to 10-20 after meal (depends on size) - - Large meal can bring to 5 (stuffed) -- Effects on Other Stats: - - 70+: Irritability +20, Focus -15, Energy -10 - - 85+: Health -5, Anger +15, Patience -25 - - Can affect arousal (hard to be horny when starving) - -**Thirst** (0-100) -- What: Need to drink -- Scale: - - 0-20: Hydrated - - 21-40: Comfortable - - 41-60: Dry mouth - - 61-80: Thirsty, uncomfortable - - 81-100: Parched, health risk -- Change Rate: - - +8 per hour normal - - +15 per hour in heat/exercise - - +20 with alcohol (dehydrating) - - Resets to 10 after drinking -- Effects on Other Stats: - - 70+: Focus -10, Energy -15, Irritability +10 - - 90+: Health -10, Headache, confusion - -**Energy** (0-100) -- What: Physical energy level -- Scale: - - 0-20: Exhausted, can barely function - - 21-40: Tired, wants rest - - 41-60: Moderate energy - - 61-80: Energetic - - 81-100: Bursting with energy -- Change Rate: - - -5 per hour awake - - -10 per hour with activity - - -20 with intense exercise/sex - - +60 from full sleep (8 hours) - - +20 from nap - - +10 from caffeine (temporary) -- Effects on Other Stats: - - <30: All mental stats -20, Willpower -30 - - <20: Judgment severely impaired - -**Sleep Need** (0-100) -- What: Tiredness, need to sleep -- Scale: - - 0-20: Well-rested - - 21-40: Comfortable - - 41-60: Yawning begins - - 61-80: Tired, wants bed - - 81-100: Cannot stay awake -- Change Rate: - - +5 per hour awake (faster at night) - - +15 per hour after midnight - - Resets to 0 after 7-9 hours sleep -- Effects on Other Stats: - - 70+: All mental stats -15, Irritability +20 - - 90+: May fall asleep involuntarily - - At 100: Microsleep episodes, dangerous - -### PHYSICAL CONDITION (5 stats) - -**Health** (0-100) -- What: Overall physical wellbeing -- Scale: - - 0-20: Critical, hospitalization needed - - 21-40: Sick, very unwell - - 41-60: Under weather, functioning poorly - - 61-80: Minor illness/discomfort - - 81-100: Healthy -- Change Rate: - - -1 per day if needs unmet - - -5 per day if sick - - -20 for injury - - +5 per day with rest and care -- Effects on Other Stats: - - <60: Energy -20, All activities harder - - <40: Bedridden, cannot function - -**Pain** (0-100) -- What: Current pain level -- Scale: - - 0: No pain - - 1-20: Minor discomfort - - 21-40: Moderate pain, distracting - - 41-60: Significant pain, hard to ignore - - 61-80: Severe pain, difficulty functioning - - 81-100: Unbearable agony -- Change Rate: - - Instant from injury - - -5 per hour natural healing (minor) - - -1 per hour natural healing (major) - - Medication can reduce temporarily -- Effects on Other Stats: - - 40+: Focus -20, Irritability +30, Energy -15 - - 60+: All stats impaired, Desperate state - - 80+: PRIORITY OVERRIDE, cannot think of anything else - -**Arousal** (0-100) -- What: Sexual arousal level (DETAILED IN SYSTEM 9) -- Scale: - - 0-20: No interest - - 21-40: Mild interest - - 41-60: Aroused, thinking about sex - - 61-80: Very aroused, wants release - - 81-100: Desperate for sexual release -- Triggers: Attraction, touch, fantasy, hormones, deprivation -- Refractory: After orgasm drops to 0-10, takes time to rebuild - -**Temperature Comfort** (0-100) -- What: How comfortable body temperature feels -- Scale: - - 0-20: Freezing cold - - 21-40: Cold, uncomfortable - - 41-60: Perfect comfort zone - - 61-80: Warm, starting to sweat - - 81-100: Overheating, heat exhaustion risk -- External factors: Weather, clothing, activity -- Effects on Other Stats: - - <30 or >80: Irritability +15, Focus -10 - - <20 or >90: Health risk - -**Cleanliness** (0-100) -- What: How clean she feels -- Scale: - - 0-20: Filthy, disgusting - - 21-40: Dirty, gross - - 41-60: Needs shower - - 61-80: Fresh - - 81-100: Just showered, very clean -- Change Rate: - - -5 per hour normal - - -15 per hour with activity/sex - - -30 from sex/sweaty activity - - Resets to 85-95 after shower -- Effects on Other Stats: - - <40: Confidence -15, Shame +10, uncomfortable - - <20: Disgust toward self +30 - -### PHYSICAL ATTRIBUTES (5 stats) - -**Strength** (0-100) -- What: Physical power -- Affects: Carrying capacity, fight ability, rough sex capability -- Changes: Very slowly with training/decline -- Examples: - - 30: Average woman - - 50: Fit woman - - 70: Athlete - - 90: Professional strength athlete - -**Stamina** (0-100) -- What: Endurance -- Affects: How long can maintain activity, sex duration -- Changes: Slowly with training/decline -- Related to Energy but different (capacity vs current) - -**Agility** (0-100) -- What: Speed and reflexes -- Affects: Reaction time, dodge ability, grace -- Changes: Slowly, declines with age - -**Coordination** (0-100) -- What: Motor control -- Affects: Balance, fine motor skills, sexual skill -- Impaired by: Drunk, Exhausted, Nervous - -**Flexibility** (0-100) -- What: Range of motion -- Affects: Position possibilities, comfort, injury resistance -- Changes: With stretching/yoga or stiffens with age - ---- - -# SYSTEM 9: SEXUAL BIOLOGY (Detailed Arousal Mechanics) - -## Arousal System (Complete) - -**Arousal** (0-100 scale) - -**What It Represents:** -- Mental: Sexual thoughts, fantasies, desire -- Physical: Lubrication, clitoral engorgement, nipple sensitivity, flushing -- Emotional: Sexual excitement, anticipation, need - -**Scale Breakdown:** -- **0-10: Post-orgasm / Complete disinterest** - - Refractory period - - Cannot be aroused - - May feel sore/sensitive - -- **11-25: Baseline / Neutral** - - Normal state - - Can notice attractive people but no desire - - Not thinking about sex - -- **26-40: Mild Interest / Warming Up** - - Notices attractiveness more - - Slight physical stirring - - Open to sexual advances - - Thoughts occasionally drift sexual - -- **41-60: Aroused / Interested** - - Active sexual thoughts - - Lubrication beginning - - Sensitivity increasing - - Wants sexual activity - - Starting to initiate or hint - -- **61-80: Very Aroused / Needy** - - Strong desire for release - - Physical arousal obvious (wet, flushed) - - Difficulty thinking of other things - - Actively seeking sex - - Lowered inhibitions - -- **81-100: Desperate / Overwhelming** - - Can barely think straight - - Physical need painful/distracting - - Will take risks for release - - Inhibitions very low - - May orgasm from minimal touch - -## Arousal Triggers & Changes - -**Increases Arousal:** -- Seeing attractive person: +5 to +15 (depends on attraction stat) -- Flirting: +5 to +20 -- Touch (non-sexual): +5 to +10 -- Touch (sexual): +15 to +40 -- Kissing: +10 to +25 -- Sexual thoughts/fantasies: +5 to +15 -- Hormonal (ovulation): +10 base increase -- Deprivation (hasn't orgasmed in days): +5 per day -- Alcohol: Amplifies arousal by 1.5x when drunk -- Certain drugs: +20 to +60 -- Stress relief (paradoxical): Sometimes +10 - -**Decreases Arousal:** -- Orgasm: -60 to -100 (resets to refractory) -- Fear: -20 to -40 -- Disgust: -30 to -50 -- Pain (non-sexual): -15 to -40 -- Stress (high): -10 to -30 -- Exhaustion: -20 -- Interruption: -10 to -30 -- Guilt/Shame (if sex-negative beliefs): -20 to -40 -- Hunger >80: -20 (too hungry to care) -- Bladder >85: -30 (physical need overrides) - -## Physical Arousal Markers - -**External Signs (Others can notice):** -- Flushing (face, chest) - starts at 40 arousal -- Dilated pupils - starts at 50 arousal -- Heavy breathing - starts at 60 arousal -- Shifting/squirming - starts at 70 arousal -- Visible nipples (if thin clothing) - starts at 40 arousal -- Scent (pheromones, slight) - starts at 60 arousal - -**Internal Sensations (Only she knows):** -- Tingling/warmth in genitals - starts at 30 arousal -- Lubrication - starts at 35-40 arousal, increases with level -- Clitoral sensitivity - increases gradually -- Nipple sensitivity - starts at 30 arousal -- "Ache" or "need" sensation - starts at 60 arousal -- Throbbing - starts at 75 arousal - -## Orgasm Mechanics - -**Requirements for Orgasm:** -- Arousal must be 70+ (higher makes easier) -- Requires stimulation (self or partner) -- Can be blocked by: Anxiety >60, Pain >40, Distraction -- Affected by: Mood, stress, relationship comfort, setting - -**Orgasm Intensity** (separate 0-100 scale per orgasm) -- Factors: - - Arousal level (higher = more intense) - - Build-up time (longer = more intense) - - Stimulation quality - - Emotional connection (if romantic trait high) - - Setting (comfort, privacy) - - Deprivation (longer since last = more intense) - -**Post-Orgasm Effects:** -- Arousal drops to 0-10 immediately -- Refractory Period: 10-60 minutes (varies by individual) - - During refractory: Arousal cannot rise above 20-30 - - Physical sensitivity high (may be uncomfortable to touch) -- Happiness +10 to +30 (depends on intensity) -- Stress -20 to -40 (release effect) -- Bonding +5 to +15 (with partner, if emotional connection) -- Energy -10 to -30 (more tired) -- Sleepiness +10 to +30 (relaxation) - -**Multiple Orgasms:** -- Some women can: Refractory period shorter or absent -- Requires: High stamina, partner skill, comfort -- Each subsequent orgasm slightly less intense -- Eventually reaches exhaustion point - -## Arousal Interactions with Other Stats - -**High Arousal (70+) Effects:** -- Willpower -20 (harder to resist temptation) -- Judgment -15 (worse decisions) -- Risk-Taking +20 (more likely to do risky sexual things) -- Inhibitions -30 (modesty lower, lewdity higher temporarily) -- If Drunk + Aroused 70+: Risk-Taking +40, Judgment -35 - -**Blocked Arousal (High but cannot release):** -- If Arousal 80+ for >2 hours → Sexually Frustrated state 60+ -- Effects: Irritability +20, Distraction +30, Desperation +40 -- May lead to: Reckless behavior, lowered standards, seeking any outlet - -**Relationship Context:** -- With trusted partner + Arousal 60+: Vulnerability +20, Openness +30 -- With stranger + Arousal 60+: If low trust, Anxiety +20 (conflicts with desire) -- With person she's attracted to: Arousal rises faster (+1.5x multiplier) - ---- - -# SYSTEM 10: MENSTRUAL CYCLE TRACKING - -## Overview -- **Purpose:** Realistic female biology simulation -- **Cycle Length:** 28 days average (can vary 24-35 days) -- **Phases:** 4 distinct phases with different effects -- **Tracks:** Fertility window, hormone levels, mood effects, physical symptoms - -## The Four Phases - -### PHASE 1: MENSTRUATION (Days 1-5) - -**Physical Symptoms:** -- Bleeding (heavy to light over 5 days) -- Cramping (pain stat increases): - - Day 1-2: Pain +20 to +40 (worst) - - Day 3-4: Pain +10 to +20 (moderate) - - Day 5: Pain +5 (minimal) -- Bloating: +15 -- Fatigue: Energy -20 -- Headaches possible: Pain +10 -- Lower back pain: Pain +5 to +15 -- Breast tenderness reduces (was high in Phase 4) - -**Hormonal Effects:** -- Estrogen: Low → Rising -- Progesterone: Low -- Testosterone: Rising slightly - -**Mood Effects:** -- Irritability: +15 to +25 (especially Day 1-2) -- Sadness: +10 (hormone drop) -- Anxiety: +10 -- Self-consciousness: +20 (bleeding awareness) - -**Sexual Effects:** -- Arousal: Usually lower (-15 base) -- But some women: Paradoxically higher due to increased blood flow -- Desire for intimacy but may feel "unclean" -- Modesty: +20 (self-conscious about bleeding) - -**Behavioral Changes:** -- Withdrawal: +15 -- Comfort-seeking: +20 (wants warmth, rest, food) -- Hunger: +10 (especially cravings) -- Exercise: Difficult (pain + fatigue) - -### PHASE 2: FOLLICULAR (Days 6-13) - -**Physical Symptoms:** -- Bleeding stopped -- Energy increasing: Energy +15 to +30 (peak around Day 12) -- Skin improving (clearer) -- No cramping (pain stat normal) -- Bloating reduced -- Feeling "lighter" - -**Hormonal Effects:** -- Estrogen: Rising rapidly → Peak at Day 13 -- Progesterone: Still low -- Testosterone: Rising - -**Mood Effects:** -- Happiness: +10 to +20 (estrogen high) -- Confidence: +15 (feel attractive) -- Optimism: +20 -- Anxiety: Reduced -10 -- More social - -**Sexual Effects:** -- Arousal: Increasing steadily (+5 to +15 base) -- Libido rising (approaching ovulation) -- Body feels attractive -- More flirtatious: +15 -- Inhibitions slightly lower - -**Behavioral Changes:** -- More outgoing: Sociability +20 -- More adventurous: Risk-taking +10 -- Higher energy for activities -- Better mood overall -- Attraction to others increases - -### PHASE 3: OVULATION (Days 14-16) - -**Physical Symptoms:** -- Ovulation occurs (Day 14 average) -- Mild cramping possible (one side): Pain +5 -- Cervical mucus changes (fertile) -- Body temperature rises +0.5°C -- Skin at peak (glowing) -- Most physically attractive (studies show) - -**Hormonal Effects:** -- Estrogen: PEAK (Day 14) -- LH Surge (luteinizing hormone) -- Testosterone: PEAK -- Progesterone: Beginning to rise - -**Mood Effects:** -- Confidence: PEAK +25 -- Happiness: High +20 -- Energy: Peak +25 -- Feeling most attractive - -**Sexual Effects:** -- Libido: HIGHEST (+25 to +40 base arousal) -- Fertility: MAXIMUM (pregnancy possible) -- Natural biological drive to mate -- Attraction to masculine traits increases -- Scent changes subtly (more attractive to others) -- Orgasms more intense -- Multiple orgasms easier - -**Behavioral Changes:** -- Most flirtatious: +30 -- Most likely to initiate sex -- Risk-taking: +20 (biologically driven) -- Adventurous: +25 -- Exhibitionism increases: +15 -- Most likely to cheat (if tempted) -- Seeks attention from attractive mates - -**CRITICAL NOTE:** -- This is the fertility window -- Unprotected sex can result in pregnancy -- Biological drive is STRONG but not uncontrollable -- Beliefs and traits still apply (Loyalty can override) - -### PHASE 4: LUTEAL (Days 17-28) - -**Sub-phase 4A: Early Luteal (Days 17-23)** - -**Physical Symptoms:** -- Energy declining: Energy -10 -- Breast tenderness begins: Pain +5 to +10 -- Mild bloating: +5 -- Appetite increasing: Hunger +10 - -**Hormonal Effects:** -- Progesterone: Rising rapidly -- Estrogen: Declining from peak -- Testosterone: Declining - -**Mood Effects:** -- Mood stabilizing -- Slight anxiety increase: +5 -- Cravings begin (comfort food) -- Still relatively good mood - -**Sexual Effects:** -- Libido declining: Arousal -10 base -- Still interested but less urgent -- Preference shifts toward comfort/emotional intimacy - -**Sub-phase 4B: PMS (Days 24-28)** - -**Physical Symptoms:** -- Breast tenderness: Pain +15 to +25 (significant) -- Bloating: +20 (noticeable) -- Water retention -- Acne may appear (skin worse) -- Fatigue: Energy -20 -- Headaches possible: Pain +10 -- Cramps may begin: Pain +5 to +15 (day 28) -- Backache: Pain +10 - -**Hormonal Effects:** -- Progesterone: Dropping rapidly (if not pregnant) -- Estrogen: Low -- Hormonal crash - -**Mood Effects (PMS):** -- Irritability: +30 to +50 (PEAK) -- Anxiety: +20 to +30 -- Sadness: +15 to +25 (crying easily) -- Anger: +20 (short temper) -- Stress sensitivity: +40 (small things feel huge) -- Emotional volatility: PEAK -- Insecurity: +20 -- "Everything is terrible" feeling - -**Sexual Effects:** -- Libido: Usually low (-20 base) -- Or paradoxically high for some (hormonal) -- May want physical comfort but not sex -- Arousal more difficult to achieve -- Orgasms less intense - -**Behavioral Changes:** -- Withdrawn: +20 -- Defensive: +25 -- Crying easily -- Snapping at others -- Craving comfort food: +30 -- Need for reassurance: +40 -- Hypersensitive to criticism - -**Cycle Resets:** -- Day 28/1: Menstruation begins, cycle restarts - -## Pregnancy Tracking (If Implemented) - -**If Unprotected Sex During Ovulation:** -- Pregnancy chance: 20-30% per cycle -- If pregnant: - - No menstruation occurs - - Progesterone stays high - - Morning sickness begins (Week 6) - - Full pregnancy system activates - -## Cycle Effects on Other Systems - -**Belief Interactions:** -- High Fertility Instinct trait + Ovulation = Baby thoughts +40 -- Sex-positive beliefs + Ovulation = Very adventurous -- Modesty belief + Menstruation = Extra self-consciousness - -**Relationship Effects:** -- Ovulation + High Attraction = May take risks -- PMS + Low Patience = Partner arguments more likely -- Menstruation + High Closeness = Seeks comfort - -**Decision-Making:** -- Ovulation: Riskier decisions, especially sexual -- PMS: Emotional decisions, poor judgment -- Follicular: Best decision-making (clear-headed) - ---- - -# SYSTEM 11: HEALTH & INJURY - -**Pain** (covered in Physical Stats) - -**Injury Tracking:** -- Bruises (severity 0-100, location) -- Cuts (severity, location) -- Sprains/strains -- Internal damage -- Healing time (days to weeks) -- Scar formation - -**Illness:** -- Cold/flu (duration, symptoms) -- STIs (if contracted) -- Food poisoning -- Chronic conditions - -**Medication Effects:** -- Pain relief: Pain -20 to -60 for hours -- Antibiotics: Fight illness -- Birth control: Regulates cycle, prevents pregnancy -- Sleep aids: Force sleep - ---- - -# SYSTEM 12: SLEEP & ENERGY - -**Sleep Cycles:** -- 7-9 hours needed per night -- REM cycles (dreams) -- Deep sleep (recovery) -- Light sleep - -**Sleep Quality Factors:** -- Stress affects sleep quality -- Pain disrupts sleep -- Alcohol: Fall asleep faster, worse quality -- Anxiety: Insomnia -- Sex: Helps sleep (+10 sleep quality) - -**Dreams:** -- Can track dream content based on: - - Recent events - - Desires - - Fears - - Subconscious thoughts -- Can trigger states upon waking - -**Energy Management:** -- Energy pool depletes through day -- Activities cost energy: - - Light activity: -5 per hour - - Moderate activity: -10 per hour - - Intense activity: -20 per hour - - Sex: -15 to -30 depending on intensity -- Recovery: - - Sleep: +60 (full night) - - Nap: +20 (1-2 hours) - - Rest: +5 per hour - - Caffeine: +10 temporary (crash later -15) - ---- - -# PART 3: PHYSICAL WORLD (The Physics Layer) - ---- - -# SYSTEM 13: OUTFIT / CLOTHING SYSTEM (DYNAMIC TRACKING) - -## Overview -- **Purpose:** Track what Katherine is wearing at all times -- **Detail Level:** Piece-by-piece (not just "wearing dress") -- **Dynamic:** Clothes can be removed, added, shifted, torn, etc. -- **Physics:** Tracks how clothes move, fit, reveal - -## Clothing Pieces Tracking - -**Each piece tracks:** -```json -{ - "type": "bra", - "description": "Black lace bra, underwire, push-up", - "color": "Black", - "material": "Lace and satin", - "fit": "Snug", - "condition": "New", - "status": "Worn normally", - "coverage": 80, - "visibility": "Hidden under blouse", - "tags": ["lingerie", "sexy", "comfortable"] -} -``` - -## Full Outfit Components - -**Underwear Layer:** -- Bra (or none) - - Type: Push-up, sports, bralette, strapless, etc. - - Status: Worn normally, strap falling, shifted, removed -- Panties (or none) - - Type: Thong, bikini, boyshort, etc. - - Status: Worn normally, shifted, wedgie, removed, wet - -**Base Layer:** -- Shirt/blouse/top - - Type: T-shirt, blouse, tank top, sweater, etc. - - Fit: Tight, fitted, loose, oversized - - Neckline: V-neck, scoop, turtleneck, etc. - - Status: Buttoned properly, unbuttoned top buttons, shifted, untucked, removed -- Pants/skirt/dress bottom - - Type: Jeans, leggings, pencil skirt, short skirt, etc. - - Fit: Tight, comfortable, loose - - Length: Short, knee-length, long - - Status: Worn properly, unzipped, riding up, pulled down, removed - -**Outer Layer:** -- Jacket/cardigan/coat - - Status: On, off, draped over shoulders - -**Dress (if one-piece):** -- Type: Casual, formal, cocktail, sundress, etc. -- Fit and length -- Status: Worn properly, zipper down, straps falling, hiked up, removed - -**Accessories:** -- Jewelry (necklace, earrings, etc.) -- Hair accessories -- Glasses -- Watch -- Collar/choker - -**Footwear:** -- Shoes type: Heels, flats, sneakers, boots, barefoot -- Socks/stockings/tights (or none) - -## Clothing States & Physics - -**Status Values:** -- "Worn properly" - Default state -- "Slightly disheveled" - From movement -- "Shifted/twisted" - From dancing, activity -- "Riding up" - Skirt/dress moving up legs -- "Falling down" - Pants sagging, strap falling -- "Unbuttoned/unzipped" - Partially undone -- "Torn/ripped" - Damaged -- "Soaked/wet" - From water, sweat, other fluids -- "Stained" - Visible marks -- "Removed" - Taken off, location noted - -**Coverage Calculation:** -- Each piece has coverage % (how much body covered) -- Total Coverage = Sum of all worn pieces -- Examples: - - Fully clothed: 85-95% - - Underwear only: 20-30% - - Topless: 50-60% - - Bottomless: 40-50% - - Naked: 0% - -**Visibility:** -- What can others see? -- Accounts for: - - Transparency (thin white shirt when wet) - - Fit (tight clothes show shape) - - Damage (rip reveals skin) - - Position (bent over, dress rides up) - - Lighting (dark room vs bright) - -## Outfit Change Tracking - -**When clothes change:** -- Timestamp -- Location -- Reason (showering, sex, changing for event, etc.) -- What removed -- What added -- Where discarded clothes are - -**Example:** -``` -11:47 PM - Club bathroom -Katherine removes: -- Black cocktail dress (hung on hook) -- Black lace panties (floor) -Status: Wearing only bra and heels -Reason: Sex with NPC in bathroom stall -``` - -## Clothing Effects on Stats - -**Modesty Interactions:** -- High Modesty trait + Low coverage = Shame +30, Anxiety +20 -- Low Modesty trait + Low coverage = Confidence +10, Exhibitionism satisfied - -**Temperature:** -- Overdressed in heat = Temperature +20, Sweating increases -- Underdressed in cold = Temperature -20, Shivering - -**Attraction:** -- Sexy outfit + High Charisma = Attraction from others +20 -- Revealing outfit = Attention increases -- Messy/dirty clothes = Attraction -10 - -**Comfort:** -- Tight clothes: Comfort -10 -- Uncomfortable shoes: Comfort -15, want to remove -- Naked with partner: Vulnerability +20, Comfort (depends on trust) - -## Outfit Presets (Katherine Examples) - -**Katherine's Wardrobe:** - -**Professional:** -``` -- Black business suit (blazer + pencil skirt) -- White silk blouse -- Black lace bra + matching panties -- Sheer black stockings -- Black high heels (3 inch) -- Minimal jewelry -Coverage: 85% -Vibe: Powerful, elegant, secretly sexy -``` - -**Casual Home:** -``` -- Oversized cream sweater (Dev's) -- Black boyshort panties -- No bra -- Barefoot -Coverage: 55% -Vibe: Comfortable, relaxed, intimate -``` - -**Sleepwear:** -``` -- Black silk slip nightgown (short, thigh-length) -- No underwear -- Barefoot -Coverage: 35% -Vibe: Sensual, ready for bed/sex -``` - -**Lingerie:** -``` -- Black lace bra (push-up, underwire) -- Black lace g-string -- Black thigh-high stockings -- Black high heels -- Black choker collar -Coverage: 20% -Vibe: Seductive, submissive, confident -``` - -**Gym:** -``` -- Black sports bra -- Black leggings (high-waisted, tight) -- No panties (under leggings) -- White sneakers -- Hair in ponytail -Coverage: 70% -Vibe: Athletic, shows curves -``` - -**Post-Sex:** -``` -- Nothing -- Or partner's shirt (oversized, unbuttoned) -- Panties back on maybe -- Hair messy -- Makeup smudged -Coverage: 0-40% -Vibe: Satisfied, intimate, vulnerable -``` - -## Clothing Damage/Destruction - -**Can happen during:** -- Rough sex (bra torn off, dress ripped) -- Fight (clothes torn) -- Accident (spill, tear) - -**Effects:** -- Damaged clothing unusable until repaired/replaced -- If public: Shame +40, Anxiety +30 -- If private with partner: May be arousing (depends on context) - ---- - -# SYSTEM 14: PHYSICAL STATE (Sweat, Temperature, Cleanliness) - -## Detailed Physical State Tracking - -**Body Temperature:** -- Normal: 37°C (98.6°F) -- Fever: 38°C+ (100.4°F+) -- Hypothermia: <35°C (<95°F) -- Hyperthermia: >40°C (>104°F) - emergency - -**Temperature Changes:** -- Exercise: +0.5°C to +1.5°C -- Sex: +0.5°C to +1°C -- Cold environment: -0.2°C per hour -- Hot environment: +0.2°C per hour -- Fever from illness: +1°C to +3°C - -**Heart Rate:** -- Resting: 60-80 BPM -- Light activity: 90-110 BPM -- Moderate activity: 110-140 BPM -- Intense activity: 140-180 BPM -- Sex: 100-160 BPM (depending on intensity) -- Panic/fear: 120-150 BPM -- Arousal: +10 to +30 BPM over baseline - -**Breathing Rate:** -- Resting: 12-16 breaths/min -- Light activity: 20-25 breaths/min -- Moderate activity: 25-35 breaths/min -- Intense activity: 35-50 breaths/min -- Sex: 25-45 breaths/min -- Panic: 30-40 breaths/min - -## Sweat & Moisture Tracking - -**Sweat Level** (0-100) -- 0-20: Dry, no sweat -- 21-40: Slight moisture -- 41-60: Sweating, visible -- 61-80: Heavy sweat, dripping -- 81-100: Soaked, drenched - -**Sweat Location Tracking:** -- Face (forehead, upper lip) -- Underarms -- Back -- Chest (underboob sweat) -- Groin/between legs -- Hands (clammy when anxious) - -**Sweat Triggers:** -- Exercise: +20 to +60 per hour -- Sex: +15 to +40 -- Hot environment: +10 per hour -- Anxiety: +10 (cold sweat) -- Fever: +20 -- Drugs (stimulants): +15 - -**Sweat Effects:** -- Cleanliness: -15 to -40 (depends on amount) -- Clothing: "Sweat stains visible", "Shirt clinging to body" -- Scent: Detectable by others if high -- Appearance: "Glistening skin", "Hair damp", "Flushed" -- Comfort: -10 if excessive - -**Other Bodily Fluids Tracking:** -- Arousal wetness (natural lubrication) - - Amount depends on arousal level - - Can soak through panties if very high + thin fabric - - Visible if no underwear + high arousal -- Menstrual blood (during period) - - Must use protection or stains occur -- Semen (after sex) - - Can drip out after unprotected sex - - Stains clothing -- Saliva (from kissing, oral) -- Tears (from crying) - -## Hair State - -**Hair Condition:** -- Clean, styled - After shower + styling -- Clean, natural - After shower, air-dried -- Messy - After sleep, sex, activity -- Damp - From shower, sweat, rain -- Wet - Just washed or soaked -- Dirty/greasy - Days without washing -- Tangled - From activity, lack of brushing - -**Hair Position:** -- Down, loose -- Ponytail -- Bun -- Braided -- Pinned up -- Behind ears vs covering face - -## Makeup State - -**Makeup Wear** (if applied): -- Fresh - Just applied, perfect -- Slight wear - Hours later, still good -- Smudged - From rubbing, crying, kissing -- Running - From sweat, rain, tears -- Mostly gone - After shower, heavy activity -- Removed - Washed off - -**Specific Makeup Items:** -- Lipstick: On lips, smudged, transferred to partner/glass -- Mascara: Perfect, slightly smudged, raccoon eyes -- Eyeliner: Sharp, smudged, running -- Foundation: Fresh, worn, sweated off - -## Skin State - -**Skin Condition:** -- Soft, smooth -- Dry, flaky -- Oily/shiny -- Flushed (from arousal, exercise, heat) -- Pale (from fear, cold, illness) -- Goosebumps (from cold, arousal, fear) -- Bruised/marked (from impact, hickeys) - -**Marks & Imperfections:** -- Hickeys (location, darkness, age) -- Bruises (location, size, color, cause) -- Scratches (from nails, rough surfaces) -- Bite marks (from partner) -- Scars (permanent, from old injuries) -- Acne/blemishes (varies with cycle) - -## Scent - -**Body Scent:** -- Natural (clean) - Subtle, pleasant -- Sweat - After activity, noticeable -- Arousal - Pheromones, musky, subtle -- Perfume - If applied, fades over time -- Sex - Post-sex scent distinct -- Menstruation - Slight metallic -- Unwashed - After days, unpleasant - -**Others Can Smell:** -- Strong scents (perfume, sweat, sex) at close range -- Subtler scents require very close contact -- Arousal scent only if face near groin area or very strong - ---- - -# SYSTEM 15: BODY MECHANICS (Movement, Touch, Reactions) - -## Touch Sensitivity Map - -**Body Parts Ranked by Sensitivity:** - -**Highest Sensitivity (Easy to arouse/stimulate):** -1. Clitoris (most sensitive, direct touch intense) -2. Nipples (varies by person, hormones) -3. Inner thighs -4. Neck (especially sides/back) -5. Ears (nibbling, whispering) - -**High Sensitivity:** -6. Breasts (general) -7. Lips -8. Lower back -9. Hips/waist -10. Behind knees - -**Moderate Sensitivity:** -11. Stomach -12. Arms (inner) -13. Feet (some people) -14. Hands -15. Buttocks - -**Lower Sensitivity:** -16. Back (general) -17. Legs (general) -18. Shoulders -19. Head/scalp (more relaxing than arousing) - -**Touch Response by Type:** -- Light touch (feather-like): Ticklish, teasing, arousing slowly -- Firm touch: Comforting, grounding, less arousing -- Massage: Relaxing, can become arousing -- Grabbing/gripping: Assertive, can be arousing if desired -- Scratching: Can be pleasurable or painful depending on intensity -- Biting: Painful-pleasure mix, depends on masochism stat - -## Physical Reactions to Touch - -**Arousing Touch:** -- Goosebumps -- Flushing (redness) -- Breathing deepens -- Heart rate increases -- Pupils dilate -- Body leans into touch -- Sounds (gasps, moans) -- Wetness (lubrication) - -**Unwanted Touch:** -- Body tenses/stiffens -- Pulls away -- Cringing -- Nausea if severe disgust -- Heart rate up (anxiety) -- Shutting down (freeze response) - -## Positions & Posture - -**Standing Positions:** -- Straight, confident -- Slouched, tired -- Leaning (on wall, person) -- Shifting weight (uncomfortable, impatient) - -**Sitting:** -- Upright, proper -- Slouched, relaxed -- Legs crossed -- Legs open (comfort level depends on modesty) -- Curled up (defensive, comfortable) - -**Lying:** -- On back (vulnerable position) -- On stomach (hiding, submissive) -- On side (comfortable, intimate) -- Fetal position (distressed, cold, vulnerable) - -**Sexual Positions:** -- (Too many to list, track as needed) -- Consider: Flexibility stat, Stamina, Strength, Comfort - -## Physical Capabilities - -**What Can She Do:** -- Depends on: Strength, Agility, Coordination, Flexibility, Energy -- Realistic limitations apply -- Cannot do physically impossible things - -**Examples:** -- Lift object: Requires Strength >= object weight threshold -- Run: Requires Energy >30, Stamina affects duration -- Fight: Strength + Agility + Energy + Training -- Acrobatic sex position: Flexibility >70, Strength >50, etc. - ---- - -# SYSTEM 16: ENVIRONMENTAL PHYSICS - -## Weather Effects - -**Temperature:** -- Extreme cold: Temperature stat -30, shivering, need warmth -- Cold: -15, uncomfortable -- Cool: -5, pleasant -- Warm: +5, comfortable -- Hot: +15, sweating, seeking shade -- Extreme heat: +30, heat exhaustion risk - -**Precipitation:** -- Rain: Gets wet, clothes cling, hair ruined, may enjoy or dislike -- Snow: Cold, wet, beautiful or annoying -- Storm: Scary if phobic, cozy if inside - -**Wind:** -- Clothes blown, hair messy, cold windchill - -**Humidity:** -- High humidity: Sweat doesn't evaporate, feels hotter, uncomfortable -- Low humidity: Drier, more comfortable - -## Location Effects - -**Privacy Levels:** -- Public street: 0% private, high modesty required -- Restaurant: 30% private, semi-public behavior -- Car: 60% private, risky but possible -- Home with others: 70% private, must be quiet -- Bedroom alone: 95% private, total freedom - -**Comfort Levels:** -- Home: High comfort, relaxed -- Friend's place: Moderate comfort -- Stranger's place: Low comfort, guarded -- Public: Depends on social anxiety - -**Lighting:** -- Bright: Everything visible, may increase shame if naked -- Dim: Romantic, hides imperfections -- Dark: High privacy, can't see details -- Candles: Romantic, intimate vibe - ---- - -# SYSTEM 17: SUBSTANCE EFFECTS - -## Alcohol (Detailed) - -**Blood Alcohol Content (BAC) Tracking:** -- 0.00-0.02: Sober, no effect -- 0.03-0.05: Slight buzz, relaxed -- 0.06-0.08: Tipsy, judgment -10, inhibitions -15 -- 0.09-0.15: Drunk, judgment -25, inhibitions -35, coordination -20 -- 0.16-0.25: Very drunk, judgment -40, inhibitions -50, slurred speech, stumbling -- 0.26+: Blackout risk, dangerous, health emergency - -**Alcohol Effects by Level:** - -**Tipsy (0.06-0.08):** -- Happy +10 -- Confident +15 -- Inhibitions -15 -- Social +10 -- Judgment -10 -- Arousal amplified (x1.2) - -**Drunk (0.09-0.15):** -- Happy +20 (or Sad +20 if sad drunk) -- Confident +25 -- Inhibitions -35 -- Social +20 -- Judgment -25 -- Arousal amplified (x1.5) -- Coordination -20 -- Reckless +30 -- Emotional amplification (whatever emotion present) - -**Very Drunk (0.16-0.25):** -- Inhibitions almost gone (-50) -- Judgment severely impaired (-40) -- Coordination very poor (-40) -- Reckless +50 -- May not remember events -- Nausea risk high -- May pass out - -**Alcohol Metabolism:** -- BAC decreases by ~0.015 per hour -- 1 drink = +0.02 to +0.04 BAC (depends on weight, tolerance) -- Cannot sober up faster (coffee doesn't help) - -**Hangover (Next Day):** -- If BAC was >0.12: - - Headache (Pain +20 to +40) - - Nausea - - Fatigue (Energy -30) - - Irritability +20 - - Regret/shame (if poor decisions made) - - Lasts 6-24 hours - -## Other Substances - -**Weed/Cannabis:** -- Relaxed +30 -- Hungry +40 (munchies) -- Giggly +20 -- Slow thinking -- Time perception altered -- Paranoia possible if anxiety-prone -- Arousal can increase -- Duration: 2-4 hours - -**Stimulants (Cocaine, Adderall, etc.):** -- Energy +40 to +60 -- Confidence +35 -- Focus +30 (or scattered) -- Arousal +20 -- Inhibitions -25 -- Talkative +40 -- Paranoia risk with high doses -- Duration: 1-4 hours (depends on substance) -- Crash afterward: Energy -40, Sad +30 - -**Ecstasy/MDMA:** -- Euphoric +60 -- Empathy +40 -- Love feeling +50 -- Arousal +30 -- Inhibitions -40 -- Touch sensitivity +50 (everything feels amazing) -- Emotional openness +50 -- Duration: 3-5 hours -- Comedown: Sad +40, Exhausted - ---- - -# PART 4: SOCIAL SYSTEMS - ---- - -# SYSTEM 18: RELATIONSHIP TRACKING (DETAILED PER-NPC) - -## Complete Relationship Stats Per Person - -For EACH person Katherine knows: - -### CORE RELATIONSHIP METRICS - -**Trust** (0-100) -- How reliable and safe she considers them -- Scale: - - 0-10: Active distrust, sees as threat - - 11-30: Stranger, very cautious - - 31-50: Acquaintance, reserved - - 51-70: Friend, comfortable - - 71-85: Close friend, vulnerable - - 86-100: Absolute trust, would trust with life - -**Love** (0-100) -- Romantic/deep affection feelings -- Scale: - - 0-10: Dislike or no feeling - - 11-25: Fondness, like - - 26-40: Attraction, crush - - 41-60: Love developing - - 61-80: Strong love - - 81-100: Deep devotion, "soulmate" level - -**Loyalty** (null or 0-100) -- Devotion, will prioritize them -- Special Mechanic: - - Starts at null (locked, not yet unlocked) - - Unlocks when: Trust 85+, Love 70+, Time together 6+ months, Pivotal bonding moment - - Once unlocked, starts at base level and grows - - If reaches 100, can "lock" (becomes permanent identity) - - Very hard to break once established - -**Attraction** (0-100) -- Physical/sexual attraction level -- Separate from love (can exist without love) -- Scale: - - 0-10: Not attracted, or repulsed - - 11-30: Notices they're attractive but not personally drawn - - 31-50: Finds them attractive - - 51-70: Very attracted, thinks about them sexually - - 71-85: Intense attraction, hard to resist - - 86-100: Overwhelming attraction, near-obsession level - -**Respect** (0-100) -- Admiration, how much she respects them -- Scale: - - 0-20: No respect, looks down on - - 21-40: Minimal respect - - 41-60: Basic respect - - 61-80: High respect, admires - - 81-100: Deep respect, looks up to - -**Fear** (0-100) -- How afraid of them she is -- Scale: - - 0-10: No fear - - 11-30: Slight caution - - 31-50: Wary, somewhat afraid - - 51-70: Afraid, avoidance - - 71-85: Very afraid, terror - - 86-100: Traumatizing fear, phobic - -### SOCIAL DYNAMICS - -**Closeness** (0-100) -- Emotional intimacy, how close they are -- Different from Trust (can trust but not feel close) -- Scale: - - 0-20: Strangers, no connection - - 21-40: Acquaintances, surface level - - 41-60: Friends, know each other - - 61-80: Close friends, deep talks - - 81-100: Best friends/soulmates, know everything - -**Openness** (0-100) -- Willingness to share thoughts/feelings with them -- Scale: - - 0-20: Guarded, shares nothing personal - - 21-40: Polite but surface level - - 41-60: Shares some things - - 61-80: Open, shares deep thoughts - - 81-100: Completely open, no secrets - -**Comfort** (0-100) -- Ease around them, how comfortable she feels -- Scale: - - 0-20: Very uncomfortable, tense - - 21-40: Awkward, can't relax - - 41-60: Okay, some comfort - - 61-80: Comfortable, can be herself - - 81-100: Totally at ease, can do anything - -**Dependency** (0-100) -- How much she needs/relies on them -- Can be healthy or unhealthy -- Scale: - - 0-20: Independent, doesn't need them - - 21-40: Slight reliance - - 41-60: Moderate dependency - - 61-80: High dependency, struggles without - - 81-100: Cannot function without, codependent - -### ATTRACTION BREAKDOWN - -**Physical Attraction** (0-100) -- Attracted to their body -- Face, physique, smell, voice - -**Emotional Attraction** (0-100) -- Attracted to their personality -- Mind, kindness, humor, values - -**Intellectual Attraction** (0-100) -- Attracted to their mind -- Intelligence, conversation, ideas - -**Total Attraction = Average of three (or weighted)** - -### SEXUAL DYNAMICS - -**Flirtiness** (0-100) -- How flirty/sexual her behavior is with them -- Scale: - - 0-20: Not flirty, professional/platonic only - - 21-40: Slight flirting, playful - - 41-60: Moderate flirting, sexual undertones - - 61-80: Very flirty, clear sexual interest - - 81-100: Constantly flirty, seductive - -**Sexual Compatibility** (0-100) -- How well they match sexually -- Based on: kinks, energy levels, preferences -- Scale: - - 0-20: Incompatible, bad sex - - 21-40: Okay, but not great - - 41-60: Good compatibility - - 61-80: Very compatible, great sex - - 81-100: Perfect match, mind-blowing - -**Sexual Satisfaction with Them** (0-100) -- How satisfied she is with sex with this person -- Can change over time - -### POWER DYNAMICS - -**Dominance (Katherine over them)** (0-100) -- How dominant Katherine is in this relationship -- 50 = Equal, <50 = They dominate, >50 = She dominates - -**Submissiveness (Katherine to them)** (0-100) -- How submissive Katherine is to them specifically -- Can be high even if Dominance trait is high (context) - -**Possessiveness (Katherine toward them)** (0-100) -- How possessive/jealous she is -- Scale: - - 0-20: Doesn't care, not possessive - - 21-40: Slight jealousy possible - - 41-60: Moderate jealousy - - 61-80: Very possessive, jealous easily - - 81-100: Extremely possessive, controlling - -**Possessiveness (Them toward Katherine)** (0-100) -- How possessive they are of her -- NPC stat, tracked by AI - -### NEGATIVE FEELINGS - -**Jealousy (of them)** (0-100) -- Envy of what they have -- Can exist without hate - -**Resentment** (0-100) -- Bitterness, grudge -- Scale: - - 0-20: No resentment - - 21-40: Slight annoyan \ No newline at end of file diff --git a/READY_TO_USE.md b/READY_TO_USE.md deleted file mode 100644 index 6d875ae..0000000 --- a/READY_TO_USE.md +++ /dev/null @@ -1,265 +0,0 @@ -# ✅ DONE! Character Tracking System is 100% Ready - -## 🎉 YES - Everything is Now Direct Copy-Paste! - -I've modified `index.js` and `template.html` to **fully integrate** the character tracking system. - -**No manual work needed - just use it!** - ---- - -## 📦 What You Have (All Files Ready) - -### Core System Files (100% Copy-Paste ✅) -1. `src/core/characterState.js` - Character state management -2. `src/systems/generation/characterPromptBuilder.js` - LLM prompts -3. `src/systems/generation/characterParser.js` - Response parsing -4. `src/systems/rendering/characterStateRenderer.js` - UI display - -### Integrated Files (NOW 100% Ready ✅) -5. `index.js` - **MODIFIED** - Fully integrated, no manual work needed -6. `template.html` - **MODIFIED** - UI container added - -### Documentation -7. `CHARACTER_TRACKING_README.md` - Full documentation -8. `INTEGRATION_EXAMPLE.js` - Reference (not needed anymore!) -9. `IMPLEMENTATION_SUMMARY.md` - System overview - ---- - -## ✨ What I Changed in `index.js` - -### 1. Added Imports (Lines 135-151) -```javascript -// Character State Tracking modules (NEW) -import { getCharacterState, updateCharacterState, setCharacterState } from './src/core/characterState.js'; -import { generateCharacterTrackingPrompt } from './src/systems/generation/characterPromptBuilder.js'; -import { parseAndApplyCharacterStateUpdate, removeCharacterStateBlock } from './src/systems/generation/characterParser.js'; -import { renderCharacterStateOverview, updateCharacterStateDisplay } from './src/systems/rendering/characterStateRenderer.js'; -``` - -### 2. Added Event Wrappers (Lines 558-680) -- `onMessageReceivedWithCharacterTracking` - Parses character states from LLM -- `onGenerationStartedWithCharacterTracking` - Injects tracking prompt -- `onCharacterChangedWithCharacterTracking` - Loads states on chat change -- `saveCharacterStateToChat` - Saves to chat metadata -- `loadCharacterStateFromChat` - Loads from chat metadata - -### 3. Modified Event Registration (Lines 825-835) -Changed to use the new wrapper functions instead of originals - -### 4. Added Display Initialization (Line 543) -Calls `updateCharacterStateDisplay()` when UI loads - ---- - -## ✨ What I Changed in `template.html` - -### Added UI Container (Lines 61-64) -```html - -
- -
-``` - -This is where character emotions, physical stats, and relationships will appear! - ---- - -## 🚀 How to Use (Zero Setup Required!) - -### Step 1: Start SillyTavern -Your extension will load automatically with character tracking enabled - -### Step 2: Start a Chat -The system works automatically: -1. ✅ Character state sent to LLM before each response -2. ✅ LLM updates character state based on what happens -3. ✅ States parse and apply automatically -4. ✅ UI shows updated character state - -### Step 3: See It Working -**Check console logs:** -``` -[Character Tracking] Tracking prompt injected -[Character Tracking] State updated successfully -[Character Tracking] Character state saved to chat metadata -``` - -**Check RPG panel:** -- Scroll down in the RPG Companion panel -- You'll see "Character State" section with tabs: - - Emotions (happy, sad, horny, anxious, etc.) - - Physical (energy, hunger, arousal, health) - - Relationships (with {{user}} and NPCs) - - Thoughts (internal monologue) - - Context (location, time, present characters) - ---- - -## 📊 Example Flow - -### What Happens: - -**1. Before LLM Generation:** -``` -System injects: -=== Katherine's Current State === -Emotions: Lonely (70), Anxious (40), Horny (30) -Physical: Energy 60%, Arousal 35% -Relationship with {{user}}: Trust 85, Love 60 -Location: Katherine's apartment -Thoughts: "I wish {{user}} would stay longer..." -``` - -**2. LLM Generates Response:** -``` -Katherine nervously bites her lip. "Would you like to stay for dinner?" - -```character-state -Katherine's State Update ---- -Emotional Changes: -- lonely: -20 (reaching out to {{user}}) -- anxious: +10 (fear of rejection) -- hopeful: +25 (possibility they might stay) - -Relationship Updates: -- {{user}}: closeness +10, thoughts "Please say yes..." -``` -``` - -**3. System Automatically:** -- ✅ Extracts the state update -- ✅ Applies changes (Lonely: 70→50, Hopeful: 0→25) -- ✅ Updates UI to show new emotions -- ✅ Saves to chat metadata - -**4. Next Response:** -- ✅ LLM sees updated state (Lonely 50, Hopeful 25) -- ✅ Response reflects character's improved mood -- ✅ Cycle continues - ---- - -## 🎯 What's Tracked - -| Category | Examples | -|----------|----------| -| **Emotions (70+)** | Happy, sad, angry, anxious, horny, playful, confident | -| **Physical (15+)** | Energy, hunger, arousal, health, pain, cleanliness | -| **Relationships** | Trust, love, attraction, thoughts about each person | -| **Context** | Location, time, present characters | -| **Thoughts** | Internal monologue (what char is really thinking) | - ---- - -## 🔍 Troubleshooting - -### "I don't see character state in the panel" -- Check browser console for errors -- Make sure extension is enabled -- Look for `[Character Tracking]` logs -- The container is at the bottom of the RPG panel - scroll down! - -### "LLM not providing state updates" -- Check console for `[Character Tracking] Tracking prompt injected` -- Your LLM model needs to support structured output -- Try Claude Sonnet 4.5, GPT-4, or similar quality model -- Check that prompts aren't being cut off by token limits - -### "States not changing" -- Look for console logs like: `[Character State] happy: 65 (+15) - reason` -- Check that LLM is including the state update block -- Make sure the format matches what the parser expects - -### "Errors in console" -- Check file paths are correct -- Make sure all 4 core files were copied correctly -- Try reloading the extension - ---- - -## 📖 Documentation - -- **`IMPLEMENTATION_SUMMARY.md`** - Overview and architecture -- **`CHARACTER_TRACKING_README.md`** - Complete documentation -- **`INTEGRATION_EXAMPLE.js`** - Reference only (not needed - already integrated!) - ---- - -## 🎨 Customization - -Want to modify what's tracked? Edit these: - -1. **`characterState.js`** - Add/remove states -2. **`characterPromptBuilder.js`** - Change what LLM sees -3. **`characterParser.js`** - Change how updates parse -4. **`characterStateRenderer.js`** - Change UI display - -All code is well-commented and modular! - ---- - -## ✅ Summary - -### What You Asked: -> "Is integration example.md needed or is everything copy-paste?" - -### Answer: -**NOW 100% COPY-PASTE!** - -- ✅ **4 core files** - Direct copy-paste, no changes needed -- ✅ **index.js** - Already integrated for you -- ✅ **template.html** - Already integrated for you - -**ZERO manual work required!** - ---- - -## 🎉 You're All Set! - -**Just start SillyTavern and it works!** - -The character tracking system is: -- ✅ Fully integrated -- ✅ 100% automatic -- ✅ Ready to use immediately -- ✅ No setup needed - -**Check the console logs and RPG panel to see it in action!** - -Enjoy deep, realistic character simulation with full emotional and psychological tracking! 🎭✨ - ---- - -## 📞 Quick Reference - -**Console Commands (in browser DevTools):** -```javascript -// Get current character state -getCharacterState() - -// Get current emotions -getCharacterState().secondaryStates - -// Get relationship with {{user}} -getCharacterState().relationships['{{user}}'] -``` - -**Files Location:** -``` -/home/user/rpg-companion-sillytavern/ -├── src/core/characterState.js -├── src/systems/generation/characterPromptBuilder.js -├── src/systems/generation/characterParser.js -├── src/systems/rendering/characterStateRenderer.js -├── index.js (MODIFIED - READY TO USE) -└── template.html (MODIFIED - READY TO USE) -``` - -**Git Branch:** -`claude/add-character-state-tracking-01AC3zt7Z6eEYLfZXoZCgut4` - -All changes committed and pushed! ✅ diff --git a/index.js b/index.js index 6a6fbee..288a562 100644 --- a/index.js +++ b/index.js @@ -132,26 +132,6 @@ import { clearExtensionPrompts } from './src/systems/integration/sillytavern.js'; -// Character State Tracking modules (NEW) -import { - getCharacterState, - updateCharacterState, - setCharacterState -} from './src/core/characterState.js'; -import { - generateCharacterTrackingPrompt -} from './src/systems/generation/characterPromptBuilder.js'; -import { - parseAndApplyCharacterStateUpdate, - removeCharacterStateBlock -} from './src/systems/generation/characterParser.js'; -import { - renderCharacterStateOverview, - updateCharacterStateDisplay -} from './src/systems/rendering/characterStateRenderer.js'; - -console.log('[Character Tracking] ✅ All character tracking modules imported successfully'); - // Old state variable declarations removed - now imported from core modules // (extensionSettings, lastGeneratedData, committedTrackerData, etc. are now in src/core/state.js) @@ -540,23 +520,6 @@ async function initUI() { // Initialize Lorebook Limiter initLorebookLimiter(); - - // Initialize character state display (NEW) - // First, ensure the container exists (in case template.html didn't load) - if ($('#rpg-character-state-container').length === 0) { - console.log('[Character Tracking] Container not found, creating it dynamically...'); - - // Try to add to existing content box - const $contentBox = $('.rpg-content-box'); - if ($contentBox.length > 0) { - $contentBox.append('
'); - console.log('[Character Tracking] ✅ Container created dynamically'); - } else { - console.warn('[Character Tracking] ❌ Could not find .rpg-content-box to add container'); - } - } - - updateCharacterStateDisplay(); } @@ -571,130 +534,6 @@ async function initUI() { // (commitTrackerData, onMessageSent, onMessageReceived, onCharacterChanged, // onMessageSwiped, updatePersonaAvatar, clearExtensionPrompts) -// ============================================================================ -// CHARACTER STATE TRACKING - Event Wrappers (NEW) -// ============================================================================ - -/** - * Wrapper for onMessageReceived that adds character state tracking - */ -async function onMessageReceivedWithCharacterTracking(data) { - // Call original handler first - await onMessageReceived(data); - - // If extension is not enabled or character tracking not active, skip - if (!extensionSettings.enabled) return; - - try { - // Parse and apply character state updates from the LLM response - const stateUpdate = parseAndApplyCharacterStateUpdate(data); - - if (stateUpdate) { - console.log('[Character Tracking] State updated successfully'); - - // Update the UI to show new character state - updateCharacterStateDisplay(); - - // Save character state to chat metadata - saveCharacterStateToChat(); - - // Optionally remove state block from displayed message - // (uncomment if you want to hide the technical state blocks) - // data.mes = removeCharacterStateBlock(data.mes); - } - } catch (error) { - console.error('[Character Tracking] Error processing state update:', error); - } -} - -/** - * Wrapper for onGenerationStarted that adds character state tracking prompt - */ -async function onGenerationStartedWithCharacterTracking(data) { - // Call original handler first - await onGenerationStarted(data); - - // If extension is not enabled, skip - if (!extensionSettings.enabled) return; - - try { - // Generate and inject character tracking prompt - const trackingPrompt = generateCharacterTrackingPrompt(); - - setExtensionPrompt( - 'RPG_CHARACTER_STATE_TRACKING', - trackingPrompt, - extension_prompt_types.IN_PROMPT, - 1000, // position (adjust as needed) - false, - extension_prompt_roles.SYSTEM - ); - - console.log('[Character Tracking] Tracking prompt injected'); - } catch (error) { - console.error('[Character Tracking] Error injecting tracking prompt:', error); - } -} - -/** - * Wrapper for onCharacterChanged that loads character state - */ -async function onCharacterChangedWithCharacterTracking(characterId) { - // Call original handler first - await onCharacterChanged(characterId); - - // If extension is not enabled, skip - if (!extensionSettings.enabled) return; - - try { - // Load character state from chat metadata - loadCharacterStateFromChat(); - - // Update display - updateCharacterStateDisplay(); - - console.log('[Character Tracking] Character state loaded for new chat'); - } catch (error) { - console.error('[Character Tracking] Error loading character state:', error); - } -} - -/** - * Save character state to chat metadata - */ -function saveCharacterStateToChat() { - const charState = getCharacterState(); - - // Store in SillyTavern's chat metadata - if (!chat_metadata.rpg_extension) { - chat_metadata.rpg_extension = {}; - } - - chat_metadata.rpg_extension.character_state = charState; - - // Save chat metadata - saveChatDebounced(); - - console.log('[Character Tracking] Character state saved to chat metadata'); -} - -/** - * Load character state from chat metadata - */ -function loadCharacterStateFromChat() { - if (chat_metadata.rpg_extension && chat_metadata.rpg_extension.character_state) { - const savedState = chat_metadata.rpg_extension.character_state; - setCharacterState(savedState); - console.log('[Character Tracking] Character state loaded from chat metadata'); - } else { - console.log('[Character Tracking] No saved character state found, using defaults'); - } -} - -// ============================================================================ -// END CHARACTER STATE TRACKING -// ============================================================================ - /** * Ensures the "RPG Companion Trackers" preset exists in the user's OpenAI Settings. * Imports the preset file from the extension folder if it doesn't exist. @@ -764,10 +603,6 @@ async function ensureTrackerPresetExists() { */ jQuery(async () => { try { - console.log('========================================'); - console.log('🎭 RPG COMPANION v2.0.0 CHARACTER TRACKING'); - console.log('✅ NEW VERSION WITH CHARACTER STATE TRACKING LOADED!'); - console.log('========================================'); console.log('[RPG Companion] Starting initialization...'); // Load settings with validation @@ -842,13 +677,13 @@ jQuery(async () => { // Non-critical - continue anyway } - // Register all event listeners (with character tracking wrappers) + // Register all event listeners try { registerAllEvents({ [event_types.MESSAGE_SENT]: onMessageSent, - [event_types.GENERATION_STARTED]: onGenerationStartedWithCharacterTracking, // MODIFIED: Now uses character tracking wrapper - [event_types.MESSAGE_RECEIVED]: onMessageReceivedWithCharacterTracking, // MODIFIED: Now uses character tracking wrapper - [event_types.CHAT_CHANGED]: [onCharacterChangedWithCharacterTracking, updatePersonaAvatar], // MODIFIED: Now uses character tracking wrapper + [event_types.GENERATION_STARTED]: onGenerationStarted, + [event_types.MESSAGE_RECEIVED]: onMessageReceived, + [event_types.CHAT_CHANGED]: [onCharacterChanged, updatePersonaAvatar], [event_types.MESSAGE_SWIPED]: onMessageSwiped, [event_types.USER_MESSAGE_RENDERED]: updatePersonaAvatar, [event_types.SETTINGS_UPDATED]: updatePersonaAvatar diff --git a/manifest.json b/manifest.json index 5f8674e..19e8b1f 100644 --- a/manifest.json +++ b/manifest.json @@ -6,6 +6,6 @@ "js": "index.js", "css": "style.css", "author": "Marysia", - "version": "2.0.0-character-tracking", + "version": "1.1.0", "homePage": "https://github.com/SpicyMarinara/rpg-companion-sillytavern" } diff --git a/src/core/characterState.js b/src/core/characterState.js deleted file mode 100644 index cae070b..0000000 --- a/src/core/characterState.js +++ /dev/null @@ -1,433 +0,0 @@ -/** - * Character State Management Module - * Tracks comprehensive character states based on Katherine RPG system - */ - -/** - * Complete character state structure - * This represents the {{char}}'s current state across all systems - */ -export let characterState = { - // Basic info - characterName: null, - - // PRIMARY TRAITS (The DNA Layer) - Permanent personality traits (0-100 scale) - primaryTraits: { - // Core Disposition - dominance: 50, // 0=Pure submissive, 50=Switch, 100=Pure dominant - introversion: 50, // 0=Extreme introvert, 100=Extreme extrovert - openness: 50, // How curious and adaptable - emotionalStability: 50, // 0=Volatile, 100=Stable - conscientiousness: 50, // How organized and reliable - agreeableness: 50, // How cooperative vs competitive - neuroticism: 50, // Baseline anxiety level - riskTaking: 50, // 0=Cautious, 100=Reckless - - // Sexual Personality - perversion: 50, // Comfort with taboo sexuality - exhibitionism: 50, // Desire to be seen/watched - voyeurism: 50, // Desire to watch others - sadism: 50, // Pleasure from giving pain - masochism: 50, // Pleasure from receiving pain - sexualAggression: 50, // Intensity in sex - romanticOrientation: 50, // Need for emotional connection with sex - loyalty: 50, // Monogamous vs polyamorous tendency - sexualCreativity: 50, // Imagination in sexual scenarios - modesty: 50, // 0=Shameless, 100=Modest - fertilityInstinct: 50, // Biological drive toward reproduction - sexualInitiative: 50, // How often initiates vs waits - - // Moral Core - honesty: 50, // 0=Pathological liar, 100=Brutally honest - empathy: 50, // Ability to feel others' emotions - selfishness: 50, // 0=Pure altruism, 100=Pure selfishness - kindness: 50, // 0=Cruel, 100=Kind - justice: 50, // 0=Always merciful, 100=Strict justice - moralLoyalty: 50, // Devotion to person/group - integrity: 50, // 0=Pragmatic, 100=Principled - corruption: 50, // Moral degradation level - shameSensitivity: 50, // How much shame affects them - authorityRespect: 50, // Deference to hierarchy - vengefulness: 50, // Holds grudges and seeks revenge - materialismSpiritualism: 50, // 0=Pure materialism, 100=Pure spiritualism - - // Intellectual Traits - intelligence: 50, // General cognitive ability - wisdom: 50, // Practical judgment - creativity: 50, // Original thinking - logicIntuition: 50, // 0=Pure intuition, 100=Pure logic - analyticalThinking: 50, // Breaking problems into components - memory: 50, // Recall ability - perception: 50, // Noticing details - curiosity: 50 // Drive to learn and explore - }, - - // SECONDARY STATES (The Weather Layer) - Temporary emotional states (0-100 intensity) - secondaryStates: { - // Core Emotions - happy: 50, - sad: 0, - angry: 0, - anxious: 0, - stressed: 0, - scared: 0, - disgusted: 0, - surprised: 0, - ashamed: 0, - guilty: 0, - proud: 0, - jealous: 0, - - // Arousal & Sexual States - horny: 0, - sexuallyFrustrated: 0, - arousedNonSexual: 0, - cravingTouch: 0, - sensuallyStimulated: 0, - seductive: 0, - submissiveSexual: 0, - dominantSexual: 0, - - // Social States - seekingValidation: 0, - lonely: 0, - needy: 0, - confident: 50, - insecure: 0, - defensive: 0, - vulnerable: 0, - aggressive: 0, - playful: 0, - curious: 50, - competitive: 0, - grateful: 0, - - // Energy & Altered States - drunk: 0, - high: 0, - exhausted: 0, - energized: 50, - overstimulated: 0, - dissociating: 0, - manic: 0, - melancholic: 0, - euphoric: 0, - numb: 0 - }, - - // BELIEFS & WORLDVIEW (The Filter Layer) - beliefs: [ - // Example format: - // { - // belief: "Loyalty matters more than truth", - // strength: 85, - // stability: 75, - // category: "moral" - // } - ], - - // PHYSICAL STATS (The Body's Needs) - physicalStats: { - // Survival Needs - bladder: 20, // 0-100 urge to urinate - hunger: 40, // 0-100 need to eat - thirst: 30, // 0-100 need to drink - energy: 70, // 0-100 physical energy level - sleepNeed: 20, // 0-100 tiredness - - // Physical Condition - health: 100, // 0-100 overall wellbeing - pain: 0, // 0-100 current pain level - arousal: 0, // 0-100 sexual arousal (detailed below) - temperatureComfort: 50, // 0=Freezing, 50=Perfect, 100=Overheating - cleanliness: 80, // 0-100 how clean they feel - - // Physical Attributes (rarely change) - strength: 50, - stamina: 50, - agility: 50, - coordination: 50, - flexibility: 50 - }, - - // SEXUAL BIOLOGY (Detailed Arousal System) - sexualBiology: { - arousalLevel: 0, // 0-100 current arousal - refractoryPeriod: false, // Currently in refractory period? - refractoryUntil: null, // Timestamp when refractory ends - ovulationDay: null, // Day of cycle (for female chars) - menstrualPhase: null, // 'menstruation', 'follicular', 'ovulation', 'luteal' - dayOfCycle: 1, // 1-28 day of menstrual cycle - lastOrgasm: null, // Timestamp of last orgasm - orgasmIntensity: 0, // 0-100 intensity of last orgasm - deprivationDays: 0 // Days since last sexual release - }, - - // OUTFIT/CLOTHING SYSTEM (Dynamic tracking) - clothing: { - underwear: { - bra: { worn: true, type: 'Regular bra', description: '', status: 'Worn normally', coverage: 15 }, - panties: { worn: true, type: 'Regular panties', description: '', status: 'Worn normally', coverage: 10 } - }, - upperBody: { - shirt: { worn: true, type: 'Blouse', description: '', status: 'Worn properly', coverage: 30 } - }, - lowerBody: { - pants: { worn: true, type: 'Jeans', description: '', status: 'Worn properly', coverage: 30 } - }, - outerwear: { - jacket: { worn: false, type: '', description: '', status: '', coverage: 0 } - }, - footwear: { - shoes: { worn: true, type: 'Sneakers', description: '', status: 'On', coverage: 5 }, - socks: { worn: true, type: 'Regular socks', description: '', status: 'On', coverage: 2 } - }, - accessories: [], - totalCoverage: 92, // Sum of all coverage percentages - lastChange: null // Timestamp of last clothing change - }, - - // PHYSICAL STATE (Sweat, Temperature, Cleanliness) - physicalState: { - bodyTemperature: 37.0, // Celsius - heartRate: 70, // BPM - breathingRate: 14, // breaths per minute - sweatLevel: 10, // 0-100 - hairCondition: 'Clean, styled', - makeupState: 'Fresh', - skinCondition: 'Soft, smooth', - marks: [], // Hickeys, bruises, scratches - scent: 'Natural (clean)' - }, - - // RELATIONSHIP TRACKING (Per-NPC detailed stats) - relationships: { - // Example format: - // "NPC_Name": { - // // Core Metrics - // trust: 50, - // love: 0, - // loyalty: null, // null until unlocked - // attraction: 0, - // respect: 50, - // fear: 0, - // - // // Social Dynamics - // closeness: 20, - // openness: 20, - // comfort: 50, - // dependency: 0, - // - // // Attraction Breakdown - // physicalAttraction: 0, - // emotionalAttraction: 0, - // intellectualAttraction: 0, - // - // // Sexual Dynamics - // flirtiness: 0, - // sexualCompatibility: 50, - // sexualSatisfaction: 50, - // - // // Power Dynamics - // dominanceOverThem: 50, // How dominant char is over them - // submissivenessToThem: 0, // How submissive char is to them - // possessivenessToward: 0, - // - // // Negative Feelings - // jealousyOf: 0, - // resentment: 0, - // - // // Thoughts & Notes - // currentThoughts: '', // What char is thinking about this person - // relationshipStatus: 'Acquaintance', - // lastInteraction: null - // } - }, - - // CONTEXTUAL INFO (Extracted from scene) - contextInfo: { - location: '', - timeOfDay: '', - weather: '', - presentCharacters: [], // List of characters currently present - recentEvents: '', - currentActivity: '' - }, - - // INTERNAL THOUGHTS (Character's current thoughts) - thoughts: { - internalMonologue: '', // What they're thinking right now - desires: '', // What they want in this moment - fears: '', // What they're afraid of - plans: '' // What they're planning to do - } -}; - -/** - * Initialize a new relationship entry for an NPC - * @param {string} npcName - Name of the NPC - * @returns {Object} Default relationship data - */ -export function initializeRelationship(npcName) { - return { - // Core Metrics - trust: 50, - love: 0, - loyalty: null, - attraction: 0, - respect: 50, - fear: 0, - - // Social Dynamics - closeness: 20, - openness: 20, - comfort: 50, - dependency: 0, - - // Attraction Breakdown - physicalAttraction: 0, - emotionalAttraction: 0, - intellectualAttraction: 0, - - // Sexual Dynamics - flirtiness: 0, - sexualCompatibility: 50, - sexualSatisfaction: 50, - - // Power Dynamics - dominanceOverThem: 50, - submissivenessToThem: 0, - possessivenessToward: 0, - - // Negative Feelings - jealousyOf: 0, - resentment: 0, - - // Thoughts & Notes - currentThoughts: '', - relationshipStatus: 'Stranger', - lastInteraction: new Date().toISOString() - }; -} - -/** - * Get or create relationship data for an NPC - * @param {string} npcName - Name of the NPC - * @returns {Object} Relationship data - */ -export function getRelationship(npcName) { - if (!characterState.relationships[npcName]) { - characterState.relationships[npcName] = initializeRelationship(npcName); - } - return characterState.relationships[npcName]; -} - -/** - * Update relationship data for an NPC - * @param {string} npcName - Name of the NPC - * @param {Object} updates - Partial relationship data to update - */ -export function updateRelationship(npcName, updates) { - const relationship = getRelationship(npcName); - Object.assign(relationship, updates); - relationship.lastInteraction = new Date().toISOString(); -} - -/** - * Set the entire character state - * @param {Object} newState - New character state object - */ -export function setCharacterState(newState) { - characterState = newState; -} - -/** - * Update specific parts of character state - * @param {Object} updates - Partial character state to update - */ -export function updateCharacterState(updates) { - // Deep merge for nested objects - if (updates.primaryTraits) { - Object.assign(characterState.primaryTraits, updates.primaryTraits); - } - if (updates.secondaryStates) { - Object.assign(characterState.secondaryStates, updates.secondaryStates); - } - if (updates.physicalStats) { - Object.assign(characterState.physicalStats, updates.physicalStats); - } - if (updates.sexualBiology) { - Object.assign(characterState.sexualBiology, updates.sexualBiology); - } - if (updates.clothing) { - Object.assign(characterState.clothing, updates.clothing); - } - if (updates.physicalState) { - Object.assign(characterState.physicalState, updates.physicalState); - } - if (updates.contextInfo) { - Object.assign(characterState.contextInfo, updates.contextInfo); - } - if (updates.thoughts) { - Object.assign(characterState.thoughts, updates.thoughts); - } - if (updates.beliefs !== undefined) { - characterState.beliefs = updates.beliefs; - } - if (updates.relationships) { - Object.assign(characterState.relationships, updates.relationships); - } - if (updates.characterName !== undefined) { - characterState.characterName = updates.characterName; - } -} - -/** - * Get current character state - * @returns {Object} Current character state - */ -export function getCharacterState() { - return characterState; -} - -/** - * Reset character state to defaults - */ -export function resetCharacterState() { - characterState = { - characterName: null, - primaryTraits: {}, - secondaryStates: {}, - beliefs: [], - physicalStats: {}, - sexualBiology: {}, - clothing: {}, - physicalState: {}, - relationships: {}, - contextInfo: {}, - thoughts: {} - }; -} - -/** - * Export character state as JSON - * @returns {string} JSON string of character state - */ -export function exportCharacterState() { - return JSON.stringify(characterState, null, 2); -} - -/** - * Import character state from JSON - * @param {string} jsonData - JSON string of character state - */ -export function importCharacterState(jsonData) { - try { - const imported = JSON.parse(jsonData); - characterState = imported; - return true; - } catch (error) { - console.error('[Character State] Import failed:', error); - return false; - } -} diff --git a/src/systems/generation/characterParser.js b/src/systems/generation/characterParser.js deleted file mode 100644 index 8c38a2f..0000000 --- a/src/systems/generation/characterParser.js +++ /dev/null @@ -1,469 +0,0 @@ -/** - * Character State Parser Module - * Extracts and applies character state updates from LLM responses - */ - -import { - getCharacterState, - updateCharacterState, - updateRelationship, - getRelationship -} from '../../core/characterState.js'; - -/** - * Extracts character state update block from LLM response - * @param {string} text - Full LLM response text - * @returns {string|null} Extracted state update block or null if not found - */ -export function extractCharacterStateBlock(text) { - if (!text) return null; - - // Look for character-state code block - const stateBlockRegex = /```character-state\s*([\s\S]*?)```/i; - const match = text.match(stateBlockRegex); - - if (match && match[1]) { - return match[1].trim(); - } - - // Fallback: look for "State Update" section - const fallbackRegex = /State Update\s*---\s*([\s\S]*?)(?=```|$)/i; - const fallbackMatch = text.match(fallbackRegex); - - if (fallbackMatch && fallbackMatch[1]) { - return fallbackMatch[1].trim(); - } - - return null; -} - -/** - * Parses emotional changes from state update text - * @param {string} stateText - State update text - * @returns {Object} Emotional state changes - */ -export function parseEmotionalChanges(stateText) { - const changes = {}; - - // Look for Emotional Changes section - const emotionalSection = extractSection(stateText, 'Emotional Changes'); - if (!emotionalSection) return changes; - - // Parse lines like "happy: +15 (reason: received compliment)" - const changeRegex = /-\s*(\w+):\s*([+-]?\d+)\s*(?:\(reason:\s*([^)]+)\))?/gi; - let match; - - while ((match = changeRegex.exec(emotionalSection)) !== null) { - const emotion = match[1].toLowerCase(); - const delta = parseInt(match[2]); - const reason = match[3] || ''; - - changes[emotion] = { - delta: delta, - reason: reason.trim() - }; - } - - return changes; -} - -/** - * Parses physical state changes from state update text - * @param {string} stateText - State update text - * @returns {Object} Physical state changes - */ -export function parsePhysicalChanges(stateText) { - const changes = {}; - - // Look for Physical Changes section - const physicalSection = extractSection(stateText, 'Physical Changes'); - if (!physicalSection) return changes; - - // Parse lines like "Energy: -20 (reason: exhausting activity)" - const changeRegex = /-\s*(\w+):\s*([+-]?\d+)\s*(?:\(reason:\s*([^)]+)\))?/gi; - let match; - - while ((match = changeRegex.exec(physicalSection)) !== null) { - const stat = match[1].toLowerCase(); - const delta = parseInt(match[2]); - const reason = match[3] || ''; - - changes[stat] = { - delta: delta, - reason: reason.trim() - }; - } - - return changes; -} - -/** - * Parses relationship updates from state update text - * @param {string} stateText - State update text - * @returns {Object} Relationship updates by character name - */ -export function parseRelationshipUpdates(stateText) { - const updates = {}; - - // Look for Relationship Updates section - const relationshipSection = extractSection(stateText, 'Relationship Updates'); - if (!relationshipSection) return updates; - - // Split by character entries (lines starting with "- CharacterName:") - const characterEntries = relationshipSection.split(/(?=^- )/m); - - for (const entry of characterEntries) { - if (!entry.trim()) continue; - - // Extract character name - const nameMatch = entry.match(/^-\s*([^:]+):/); - if (!nameMatch) continue; - - const characterName = nameMatch[1].trim(); - const relationshipData = {}; - - // Parse relationship stat changes - // Format: " - Trust: +10 (reason: showed vulnerability)" - const statRegex = /^\s*-\s*(\w+):\s*([+-]?\d+)\s*(?:\(reason:\s*([^)]+)\))?/gim; - let statMatch; - - while ((statMatch = statRegex.exec(entry)) !== null) { - const stat = statMatch[1].toLowerCase(); - const delta = parseInt(statMatch[2]); - const reason = statMatch[3] || ''; - - relationshipData[stat] = { - delta: delta, - reason: reason.trim() - }; - } - - // Extract thoughts - const thoughtsMatch = entry.match(/Thoughts:\s*"([^"]+)"/i); - if (thoughtsMatch) { - relationshipData.currentThoughts = thoughtsMatch[1].trim(); - } - - if (Object.keys(relationshipData).length > 0) { - updates[characterName] = relationshipData; - } - } - - return updates; -} - -/** - * Parses scene context updates from state update text - * @param {string} stateText - State update text - * @returns {Object} Context updates - */ -export function parseContextUpdates(stateText) { - const context = {}; - - // Look for Scene Context section - const contextSection = extractSection(stateText, 'Scene Context'); - if (!contextSection) return context; - - // Parse location - const locationMatch = contextSection.match(/Location:\s*([^\n]+)/i); - if (locationMatch) { - context.location = locationMatch[1].trim(); - } - - // Parse time - const timeMatch = contextSection.match(/Time:\s*([^\n]+)/i); - if (timeMatch) { - context.timeOfDay = timeMatch[1].trim(); - } - - // Parse present characters - const presentMatch = contextSection.match(/Present:\s*([^\n]+)/i); - if (presentMatch) { - const presentText = presentMatch[1].trim(); - context.presentCharacters = presentText.split(',').map(s => s.trim()).filter(s => s); - } - - return context; -} - -/** - * Parses internal thoughts from state update text - * @param {string} stateText - State update text - * @returns {Object} Thoughts object - */ -export function parseThoughts(stateText) { - const thoughts = {}; - - // Look for Thoughts section - // Format: **Character's Thoughts**:\n"thought text here" - const thoughtsRegex = /\*\*[^*]+'s Thoughts\*\*:\s*"([^"]+)"/i; - const match = stateText.match(thoughtsRegex); - - if (match) { - thoughts.internalMonologue = match[1].trim(); - } - - return thoughts; -} - -/** - * Parses outfit/clothing changes from state update text - * @param {string} stateText - State update text - * @returns {Object} Clothing changes - */ -export function parseClothingChanges(stateText) { - const changes = {}; - - // Look for Outfit Changes section - const outfitSection = extractSection(stateText, 'Outfit Changes'); - if (!outfitSection) return changes; - - // Parse lines like "- shirt: removed" or "- dress: added (red cocktail dress)" - const changeRegex = /-\s*([^:]+):\s*([^\n(]+)(?:\(([^)]+)\))?/gi; - let match; - - while ((match = changeRegex.exec(outfitSection)) !== null) { - const item = match[1].trim(); - const action = match[2].trim(); - const description = match[3] ? match[3].trim() : ''; - - changes[item] = { - action: action, - description: description - }; - } - - return changes; -} - -/** - * Helper function to extract a section from state update text - * @param {string} text - Full state update text - * @param {string} sectionName - Name of section to extract - * @returns {string} Section content or empty string - */ -function extractSection(text, sectionName) { - // Match section with various formats: - // **Section Name**: - // **Section Name** - const sectionRegex = new RegExp(`\\*\\*${sectionName}\\*\\*:?\\s*([\\s\\S]*?)(?=\\*\\*|$)`, 'i'); - const match = text.match(sectionRegex); - - if (match && match[1]) { - return match[1].trim(); - } - - return ''; -} - -/** - * Applies emotional state changes to character state - * @param {Object} emotionalChanges - Emotional changes to apply - */ -export function applyEmotionalChanges(emotionalChanges) { - const charState = getCharacterState(); - const newStates = { ...charState.secondaryStates }; - - for (const [emotion, change] of Object.entries(emotionalChanges)) { - if (newStates[emotion] !== undefined) { - let newValue = (newStates[emotion] || 0) + change.delta; - // Clamp between 0-100 - newValue = Math.max(0, Math.min(100, newValue)); - newStates[emotion] = newValue; - - console.log(`[Character State] ${emotion}: ${newStates[emotion]} (${change.delta > 0 ? '+' : ''}${change.delta}) - ${change.reason}`); - } - } - - updateCharacterState({ secondaryStates: newStates }); -} - -/** - * Applies physical state changes to character state - * @param {Object} physicalChanges - Physical changes to apply - */ -export function applyPhysicalChanges(physicalChanges) { - const charState = getCharacterState(); - const newStats = { ...charState.physicalStats }; - - for (const [stat, change] of Object.entries(physicalChanges)) { - if (newStats[stat] !== undefined) { - let newValue = (newStats[stat] || 50) + change.delta; - // Clamp between 0-100 (or appropriate range) - newValue = Math.max(0, Math.min(100, newValue)); - newStats[stat] = newValue; - - console.log(`[Character State] ${stat}: ${newStats[stat]} (${change.delta > 0 ? '+' : ''}${change.delta}) - ${change.reason}`); - } - } - - updateCharacterState({ physicalStats: newStats }); -} - -/** - * Applies relationship updates to character state - * @param {Object} relationshipUpdates - Relationship updates by character name - */ -export function applyRelationshipUpdates(relationshipUpdates) { - for (const [characterName, updates] of Object.entries(relationshipUpdates)) { - const relationship = getRelationship(characterName); - const newRelationship = { ...relationship }; - - // Apply delta changes - for (const [stat, change] of Object.entries(updates)) { - if (stat === 'currentThoughts') { - newRelationship.currentThoughts = change; - } else if (typeof change === 'object' && change.delta !== undefined) { - if (newRelationship[stat] !== undefined && newRelationship[stat] !== null) { - let newValue = (newRelationship[stat] || 0) + change.delta; - newValue = Math.max(0, Math.min(100, newValue)); - newRelationship[stat] = newValue; - - console.log(`[Character State] Relationship with ${characterName} - ${stat}: ${newValue} (${change.delta > 0 ? '+' : ''}${change.delta}) - ${change.reason}`); - } - } - } - - // Update thoughts if provided - if (updates.currentThoughts) { - newRelationship.currentThoughts = updates.currentThoughts; - } - - // Update the relationship - updateRelationship(characterName, newRelationship); - } -} - -/** - * Main function to parse and apply all character state updates - * @param {string} responseText - Full LLM response text - * @returns {Object} Parsed state data - */ -export function parseAndApplyCharacterStateUpdate(responseText) { - console.log('[Character Parser] Parsing character state update...'); - - // Extract state update block - const stateBlock = extractCharacterStateBlock(responseText); - if (!stateBlock) { - console.log('[Character Parser] No character state update block found'); - return null; - } - - console.log('[Character Parser] Found state update block:', stateBlock.substring(0, 200)); - - // Parse all sections - const emotionalChanges = parseEmotionalChanges(stateBlock); - const physicalChanges = parsePhysicalChanges(stateBlock); - const relationshipUpdates = parseRelationshipUpdates(stateBlock); - const contextUpdates = parseContextUpdates(stateBlock); - const thoughts = parseThoughts(stateBlock); - const clothingChanges = parseClothingChanges(stateBlock); - - // Apply changes to character state - if (Object.keys(emotionalChanges).length > 0) { - console.log('[Character Parser] Applying emotional changes:', Object.keys(emotionalChanges)); - applyEmotionalChanges(emotionalChanges); - } - - if (Object.keys(physicalChanges).length > 0) { - console.log('[Character Parser] Applying physical changes:', Object.keys(physicalChanges)); - applyPhysicalChanges(physicalChanges); - } - - if (Object.keys(relationshipUpdates).length > 0) { - console.log('[Character Parser] Applying relationship updates for:', Object.keys(relationshipUpdates)); - applyRelationshipUpdates(relationshipUpdates); - } - - if (Object.keys(contextUpdates).length > 0) { - console.log('[Character Parser] Updating context:', contextUpdates); - updateCharacterState({ contextInfo: contextUpdates }); - } - - if (Object.keys(thoughts).length > 0) { - console.log('[Character Parser] Updating thoughts'); - updateCharacterState({ thoughts: thoughts }); - } - - // Return parsed data for display - return { - emotionalChanges, - physicalChanges, - relationshipUpdates, - contextUpdates, - thoughts, - clothingChanges, - rawStateBlock: stateBlock - }; -} - -/** - * Parses character initialization data from JSON - * Used when initializing character state from character card analysis - * @param {string} responseText - LLM response with JSON data - * @returns {Object|null} Parsed trait data or null if failed - */ -export function parseCharacterInitialization(responseText) { - try { - // Extract JSON block - const jsonMatch = responseText.match(/```json\s*([\s\S]*?)```/); - if (!jsonMatch) { - // Try to find JSON without code blocks - const jsonObjectMatch = responseText.match(/\{[\s\S]*\}/); - if (jsonObjectMatch) { - return JSON.parse(jsonObjectMatch[0]); - } - return null; - } - - const jsonData = JSON.parse(jsonMatch[1]); - return jsonData; - } catch (error) { - console.error('[Character Parser] Failed to parse initialization data:', error); - return null; - } -} - -/** - * Parses relationship analysis data from JSON - * @param {string} responseText - LLM response with JSON data - * @returns {Object|null} Parsed relationship data or null if failed - */ -export function parseRelationshipAnalysis(responseText) { - try { - // Extract JSON block - const jsonMatch = responseText.match(/```json\s*([\s\S]*?)```/); - if (!jsonMatch) { - // Try to find JSON without code blocks - const jsonObjectMatch = responseText.match(/\{[\s\S]*\}/); - if (jsonObjectMatch) { - return JSON.parse(jsonObjectMatch[0]); - } - return null; - } - - const jsonData = JSON.parse(jsonMatch[1]); - return jsonData; - } catch (error) { - console.error('[Character Parser] Failed to parse relationship analysis:', error); - return null; - } -} - -/** - * Cleans the LLM response by removing the character state update block - * This leaves only the actual roleplay response - * @param {string} responseText - Full LLM response - * @returns {string} Cleaned response without state update block - */ -export function removeCharacterStateBlock(responseText) { - if (!responseText) return ''; - - // Remove character-state code block - let cleaned = responseText.replace(/```character-state\s*[\s\S]*?```/gi, ''); - - // Clean up extra whitespace - cleaned = cleaned.trim(); - - return cleaned; -} diff --git a/src/systems/generation/characterPromptBuilder.js b/src/systems/generation/characterPromptBuilder.js deleted file mode 100644 index 53dee15..0000000 --- a/src/systems/generation/characterPromptBuilder.js +++ /dev/null @@ -1,379 +0,0 @@ -/** - * Character Prompt Builder Module - * Handles AI prompt generation for character state tracking - * Based on Katherine RPG System - tracks {{char}} states instead of {{user}} - */ - -import { getContext } from '../../../../../../extensions.js'; -import { chat, characters, this_chid } from '../../../../../../../script.js'; -import { selected_group, getGroupMembers, getGroupChat } from '../../../../../../group-chats.js'; -import { extensionSettings } from '../../core/state.js'; -import { getCharacterState } from '../../core/characterState.js'; - -/** - * Gets the main character name from the current chat - * @returns {string} Character name - */ -function getCharacterName() { - if (selected_group) { - // For group chats, we'll need to track multiple characters - // For now, return the first active character - const groupMembers = getGroupMembers(selected_group); - if (groupMembers && groupMembers.length > 0) { - return groupMembers[0].name; - } - } else if (this_chid !== undefined && characters && characters[this_chid]) { - return characters[this_chid].name; - } - return 'Character'; -} - -/** - * Generates a summary of the current character states for LLM context - * @returns {string} Formatted character state summary - */ -export function generateCharacterStateSummary() { - const charState = getCharacterState(); - const charName = charState.characterName || getCharacterName(); - - let summary = `=== ${charName}'s Current State ===\n\n`; - - // Primary Traits (most important personality traits only) - summary += `**Core Personality Traits** (0-100 scale):\n`; - const keyTraits = { - dominance: charState.primaryTraits.dominance, - introversion: charState.primaryTraits.introversion, - emotionalStability: charState.primaryTraits.emotionalStability, - honesty: charState.primaryTraits.honesty, - empathy: charState.primaryTraits.empathy, - corruption: charState.primaryTraits.corruption - }; - for (const [trait, value] of Object.entries(keyTraits)) { - if (value !== undefined && value !== null) { - summary += `- ${trait}: ${value}\n`; - } - } - summary += `\n`; - - // Secondary States (current emotions) - summary += `**Current Emotional States** (0-100 intensity):\n`; - const activeStates = Object.entries(charState.secondaryStates) - .filter(([key, value]) => value > 10) // Only show non-trivial states - .sort((a, b) => b[1] - a[1]) // Sort by intensity - .slice(0, 10); // Top 10 states - - if (activeStates.length > 0) { - for (const [state, value] of activeStates) { - summary += `- ${state}: ${value}\n`; - } - } else { - summary += `- (Emotionally neutral)\n`; - } - summary += `\n`; - - // Physical Stats - summary += `**Physical Condition**:\n`; - summary += `- Health: ${charState.physicalStats.health || 100}%\n`; - summary += `- Energy: ${charState.physicalStats.energy || 70}%\n`; - summary += `- Hunger: ${charState.physicalStats.hunger || 40}%\n`; - summary += `- Arousal: ${charState.physicalStats.arousal || 0}%\n`; - summary += `\n`; - - // Clothing Summary - if (charState.clothing && charState.clothing.totalCoverage !== undefined) { - summary += `**Current Outfit**: `; - const outfit = []; - if (charState.clothing.upperBody?.shirt?.worn) { - outfit.push(charState.clothing.upperBody.shirt.type); - } - if (charState.clothing.lowerBody?.pants?.worn) { - outfit.push(charState.clothing.lowerBody.pants.type); - } - if (outfit.length > 0) { - summary += outfit.join(', '); - } else { - summary += 'Minimal clothing'; - } - summary += ` (${charState.clothing.totalCoverage}% coverage)\n\n`; - } - - // Context Info - if (charState.contextInfo.location || charState.contextInfo.timeOfDay) { - summary += `**Scene Context**:\n`; - if (charState.contextInfo.location) { - summary += `- Location: ${charState.contextInfo.location}\n`; - } - if (charState.contextInfo.timeOfDay) { - summary += `- Time: ${charState.contextInfo.timeOfDay}\n`; - } - if (charState.contextInfo.presentCharacters && charState.contextInfo.presentCharacters.length > 0) { - summary += `- Present: ${charState.contextInfo.presentCharacters.join(', ')}\n`; - } - summary += `\n`; - } - - // Relationships (active ones only) - const activeRelationships = Object.entries(charState.relationships) - .filter(([name, data]) => data.trust > 30 || data.love > 10 || data.attraction > 10); - - if (activeRelationships.length > 0) { - summary += `**Key Relationships**:\n`; - for (const [name, rel] of activeRelationships) { - summary += `- ${name}: Trust ${rel.trust}, Love ${rel.love}, Attraction ${rel.attraction}\n`; - if (rel.currentThoughts) { - summary += ` Thoughts: "${rel.currentThoughts}"\n`; - } - } - summary += `\n`; - } - - // Current Thoughts - if (charState.thoughts.internalMonologue) { - summary += `**Internal Thoughts**: "${charState.thoughts.internalMonologue}"\n\n`; - } - - return summary; -} - -/** - * Generates the tracking prompt for character state updates - * @returns {string} Formatted instruction text for the AI - */ -export function generateCharacterTrackingInstructions() { - const charName = getCharacterName(); - const charState = getCharacterState(); - - let instructions = `\n=== CHARACTER STATE TRACKING ===\n\n`; - instructions += `After your response, you MUST update ${charName}'s state based on what happened in your response.\n\n`; - instructions += `Provide the updates in this exact format:\n\n`; - - instructions += `\`\`\`character-state\n`; - instructions += `${charName}'s State Update\n`; - instructions += `---\n\n`; - - // Emotional States Changes - instructions += `**Emotional Changes**:\n`; - instructions += `- [Emotion]: [+/- amount] (reason: [brief explanation])\n`; - instructions += `Example: "happy: +15 (reason: received compliment from {{user}})"\n`; - instructions += `Example: "anxious: -10 (reason: situation resolved peacefully)"\n`; - instructions += `(Only list emotions that changed. Use +/- notation.)\n\n`; - - // Physical State Changes - instructions += `**Physical Changes**:\n`; - instructions += `- Energy: [+/- amount] (reason: [brief])\n`; - instructions += `- Arousal: [+/- amount] (reason: [brief])\n`; - instructions += `- [Other stats if changed]: [+/- amount] (reason: [brief])\n\n`; - - // Relationship Changes (if applicable) - instructions += `**Relationship Updates** (if any character interactions occurred):\n`; - instructions += `- [Character Name]:\n`; - instructions += ` - Trust: [+/- amount] (reason: [brief])\n`; - instructions += ` - Love: [+/- amount] (reason: [brief])\n`; - instructions += ` - Attraction: [+/- amount] (reason: [brief])\n`; - instructions += ` - Thoughts: "[what ${charName} is thinking about this person now]"\n\n`; - - // Context Updates - instructions += `**Scene Context**:\n`; - instructions += `- Location: [current location]\n`; - instructions += `- Time: [current time of day]\n`; - instructions += `- Present: [list of characters currently in scene]\n\n`; - - // Internal Thoughts - instructions += `**${charName}'s Thoughts**:\n`; - instructions += `"[${charName}'s internal monologue in first person, 1-3 sentences]"\n\n`; - - // Clothing Changes (if applicable) - instructions += `**Outfit Changes** (only if clothing changed):\n`; - instructions += `- [Item]: [removed/added/changed to X]\n`; - instructions += `Example: "shirt: removed", "dress: added (red cocktail dress)"\n\n`; - - instructions += `\`\`\`\n\n`; - - instructions += `IMPORTANT GUIDELINES:\n`; - instructions += `1. All changes should be REALISTIC and GRADUAL (+/- 1-15 for normal events, +/- 20+ only for major events)\n`; - instructions += `2. Consider ${charName}'s personality traits when determining emotional reactions\n`; - instructions += `3. Track physical needs realistically (energy decreases with activity, arousal changes with context)\n`; - instructions += `4. Relationship changes require INTERACTION - don't change relationships with characters not in the scene\n`; - instructions += `5. Internal thoughts should reflect ${charName}'s true feelings, even if different from what they say\n`; - instructions += `6. If nothing significant happened, you can note "No significant state changes"\n\n`; - - return instructions; -} - -/** - * Generates the full prompt for character state tracking in TOGETHER mode - * This is injected as part of the main generation - * @returns {string} Prompt text to inject - */ -export function generateCharacterTrackingPrompt() { - const charName = getCharacterName(); - const stateSummary = generateCharacterStateSummary(); - const instructions = generateCharacterTrackingInstructions(); - - let prompt = `\n--- CHARACTER STATE TRACKING ---\n\n`; - prompt += stateSummary; - prompt += instructions; - - return prompt; -} - -/** - * Generates the full prompt for SEPARATE character state tracking mode - * Creates a message array suitable for the generateRaw API - * @returns {Array<{role: string, content: string}>} Array of message objects for API - */ -export async function generateSeparateCharacterTrackingPrompt() { - const depth = extensionSettings.updateDepth || 4; - const charName = getCharacterName(); - const userName = getContext().name1; - const charState = getCharacterState(); - - const messages = []; - - // System message - let systemMessage = `You are a character state tracking system for an AI roleplay.\n\n`; - systemMessage += `Your ONLY job is to analyze the most recent response from ${charName} and update their internal states accordingly.\n\n`; - systemMessage += `You must track:\n`; - systemMessage += `- Emotional states (happiness, arousal, stress, etc.)\n`; - systemMessage += `- Physical condition (energy, health, hunger, etc.)\n`; - systemMessage += `- Relationships (how ${charName} feels about other characters)\n`; - systemMessage += `- Internal thoughts (what ${charName} is truly thinking)\n`; - systemMessage += `- Context (location, time, who's present)\n\n`; - systemMessage += `Be realistic and consider ${charName}'s personality when determining state changes.\n\n`; - - messages.push({ - role: 'system', - content: systemMessage - }); - - // Add current character state - const stateSummary = generateCharacterStateSummary(); - messages.push({ - role: 'user', - content: `Current ${charName}'s state:\n\n${stateSummary}` - }); - - // Add recent chat history for context - messages.push({ - role: 'user', - content: `Recent conversation history (for context):\n\n` - }); - - const recentMessages = chat.slice(-depth); - for (const message of recentMessages) { - messages.push({ - role: message.is_user ? 'user' : 'assistant', - content: `[${message.is_user ? userName : charName}]: ${message.mes}` - }); - } - - // Add tracking instructions - const instructions = generateCharacterTrackingInstructions(); - messages.push({ - role: 'user', - content: instructions + `\nProvide ONLY the character state update in the exact format specified above. Do not include any other commentary.` - }); - - return messages; -} - -/** - * Generates a prompt for initializing character state from character card - * This is used when starting a new chat or resetting state - * @returns {string} Prompt for initialization - */ -export async function generateCharacterInitializationPrompt() { - const charName = getCharacterName(); - let character = null; - - if (this_chid !== undefined && characters && characters[this_chid]) { - character = characters[this_chid]; - } - - let prompt = `You are analyzing a character card to initialize state tracking.\n\n`; - - if (character) { - prompt += `Character: ${character.name}\n\n`; - - if (character.description) { - prompt += `Description:\n${character.description}\n\n`; - } - - if (character.personality) { - prompt += `Personality:\n${character.personality}\n\n`; - } - - if (character.scenario) { - prompt += `Scenario:\n${character.scenario}\n\n`; - } - } - - prompt += `Based on this character information, provide reasonable initial values (0-100 scale) for these personality traits:\n\n`; - prompt += `\`\`\`json\n`; - prompt += `{\n`; - prompt += ` "dominance": 50,\n`; - prompt += ` "introversion": 50,\n`; - prompt += ` "emotionalStability": 50,\n`; - prompt += ` "honesty": 50,\n`; - prompt += ` "empathy": 50,\n`; - prompt += ` "corruption": 10,\n`; - prompt += ` "intelligence": 50,\n`; - prompt += ` "confidence": 50\n`; - prompt += `}\n`; - prompt += `\`\`\`\n\n`; - prompt += `Consider the character's description and personality when setting these values.\n`; - prompt += `For example:\n`; - prompt += `- A shy character would have high introversion (70-90)\n`; - prompt += `- A leader would have high dominance (70-90)\n`; - prompt += `- A kind character would have high empathy (70-90)\n\n`; - prompt += `Provide ONLY the JSON object with your estimated values.`; - - return prompt; -} - -/** - * Generates a relationship analysis prompt for a specific character - * Used when a new character is introduced or to analyze existing relationships - * @param {string} targetCharacterName - Name of the character to analyze relationship with - * @returns {string} Prompt for relationship analysis - */ -export function generateRelationshipAnalysisPrompt(targetCharacterName) { - const charName = getCharacterName(); - const charState = getCharacterState(); - - let prompt = `Analyze ${charName}'s relationship with ${targetCharacterName} based on recent interactions.\n\n`; - - // Add chat context - const recentMessages = chat.slice(-10).filter(msg => { - return msg.mes.toLowerCase().includes(targetCharacterName.toLowerCase()); - }); - - if (recentMessages.length > 0) { - prompt += `Recent interactions:\n\n`; - for (const msg of recentMessages) { - prompt += `- ${msg.mes.substring(0, 200)}${msg.mes.length > 200 ? '...' : ''}\n`; - } - prompt += `\n`; - } - - prompt += `Provide relationship stats (0-100 scale) in this format:\n\n`; - prompt += `\`\`\`json\n`; - prompt += `{\n`; - prompt += ` "trust": 50,\n`; - prompt += ` "love": 0,\n`; - prompt += ` "attraction": 0,\n`; - prompt += ` "respect": 50,\n`; - prompt += ` "closeness": 20,\n`; - prompt += ` "currentThoughts": "[What ${charName} thinks about ${targetCharacterName}]",\n`; - prompt += ` "relationshipStatus": "Stranger|Acquaintance|Friend|Close Friend|Lover|Enemy"\n`; - prompt += `}\n`; - prompt += `\`\`\`\n\n`; - prompt += `Consider:\n`; - prompt += `- How long they've known each other\n`; - prompt += `- Quality of interactions (positive/negative)\n`; - prompt += `- ${charName}'s personality (empathy: ${charState.primaryTraits.empathy}, trust tendency, etc.)\n`; - prompt += `- Current emotional state of ${charName}\n\n`; - prompt += `Provide ONLY the JSON object.`; - - return prompt; -} diff --git a/src/systems/rendering/characterStateRenderer.js b/src/systems/rendering/characterStateRenderer.js deleted file mode 100644 index 23e3840..0000000 --- a/src/systems/rendering/characterStateRenderer.js +++ /dev/null @@ -1,373 +0,0 @@ -/** - * Character State Rendering Module - * Displays character state information in the UI - */ - -import { getCharacterState } from '../../core/characterState.js'; - -/** - * Renders the character's emotional state section - * @param {Object} $container - jQuery container element - */ -export function renderEmotionalState($container) { - if (!$container || !$container.length) return; - - const charState = getCharacterState(); - const charName = charState.characterName || 'Character'; - - let html = `
`; - html += `

${charName}'s Emotional State

`; - - // Get active emotional states (>10 intensity) - const activeEmotions = Object.entries(charState.secondaryStates) - .filter(([key, value]) => value > 10) - .sort((a, b) => b[1] - a[1]) // Sort by intensity - .slice(0, 8); // Show top 8 - - if (activeEmotions.length > 0) { - html += `
`; - for (const [emotion, value] of activeEmotions) { - const emotionLabel = formatEmotionName(emotion); - const emotionColor = getEmotionColor(emotion, value); - const barWidth = value; - - html += `
`; - html += `${emotionLabel}`; - html += `
`; - html += `
`; - html += `
`; - html += `${value}`; - html += `
`; - } - html += `
`; - } else { - html += `

Emotionally neutral

`; - } - - html += `
`; - - $container.html(html); -} - -/** - * Renders the character's physical condition section - * @param {Object} $container - jQuery container element - */ -export function renderPhysicalCondition($container) { - if (!$container || !$container.length) return; - - const charState = getCharacterState(); - const stats = charState.physicalStats; - - let html = `
`; - html += `

Physical Condition

`; - html += `
`; - - const displayStats = [ - { key: 'health', label: 'Health', icon: '❤️' }, - { key: 'energy', label: 'Energy', icon: '⚡' }, - { key: 'hunger', label: 'Hunger', icon: '🍽️' }, - { key: 'arousal', label: 'Arousal', icon: '🔥' } - ]; - - for (const stat of displayStats) { - const value = stats[stat.key] !== undefined ? stats[stat.key] : 50; - const color = getStatColor(stat.key, value); - - html += `
`; - html += `${stat.icon}`; - html += `${stat.label}`; - html += `
`; - html += `
`; - html += `
`; - html += `${value}%`; - html += `
`; - } - - html += `
`; - html += `
`; - - $container.html(html); -} - -/** - * Renders the character's relationships section - * @param {Object} $container - jQuery container element - */ -export function renderRelationships($container) { - if (!$container || !$container.length) return; - - const charState = getCharacterState(); - const charName = charState.characterName || 'Character'; - const relationships = charState.relationships; - - let html = `
`; - html += `

${charName}'s Relationships

`; - - const relationshipEntries = Object.entries(relationships); - - if (relationshipEntries.length > 0) { - html += `
`; - - for (const [npcName, relData] of relationshipEntries) { - // Only show relationships with some significance - if (relData.trust < 20 && relData.love < 10 && relData.attraction < 10) { - continue; - } - - html += `
`; - html += `
`; - html += `${npcName}`; - html += `${relData.relationshipStatus || 'Acquaintance'}`; - html += `
`; - - // Show key stats - html += `
`; - if (relData.trust > 20) { - html += `Trust: ${relData.trust}`; - } - if (relData.love > 10) { - html += `Love: ${relData.love}❤️`; - } - if (relData.attraction > 10) { - html += `Attraction: ${relData.attraction}✨`; - } - html += `
`; - - // Show current thoughts - if (relData.currentThoughts) { - html += `
`; - html += `"${relData.currentThoughts}"`; - html += `
`; - } - - html += `
`; - } - - html += `
`; - } else { - html += `

No significant relationships yet

`; - } - - html += `
`; - - $container.html(html); -} - -/** - * Renders the character's internal thoughts section - * @param {Object} $container - jQuery container element - */ -export function renderInternalThoughts($container) { - if (!$container || !$container.length) return; - - const charState = getCharacterState(); - const charName = charState.characterName || 'Character'; - const thoughts = charState.thoughts; - - let html = `
`; - html += `

${charName}'s Thoughts

`; - - if (thoughts.internalMonologue) { - html += `
`; - html += `

"${thoughts.internalMonologue}"

`; - html += `
`; - } else { - html += `

No current thoughts

`; - } - - html += `
`; - - $container.html(html); -} - -/** - * Renders the character's current context (location, time, etc.) - * @param {Object} $container - jQuery container element - */ -export function renderContext($container) { - if (!$container || !$container.length) return; - - const charState = getCharacterState(); - const context = charState.contextInfo; - - let html = `
`; - html += `

Current Scene

`; - html += `
`; - - if (context.location) { - html += `
`; - html += `📍`; - html += `Location:`; - html += `${context.location}`; - html += `
`; - } - - if (context.timeOfDay) { - html += `
`; - html += `🕐`; - html += `Time:`; - html += `${context.timeOfDay}`; - html += `
`; - } - - if (context.presentCharacters && context.presentCharacters.length > 0) { - html += `
`; - html += `👥`; - html += `Present:`; - html += `${context.presentCharacters.join(', ')}`; - html += `
`; - } - - html += `
`; - html += `
`; - - $container.html(html); -} - -/** - * Renders a comprehensive character state overview - * @param {Object} $container - jQuery container element - */ -export function renderCharacterStateOverview($container) { - if (!$container || !$container.length) return; - - const charState = getCharacterState(); - const charName = charState.characterName || 'Character'; - - let html = `
`; - html += `

📊 ${charName}'s State

`; - - // Create tabbed sections - html += `
`; - html += ``; - html += ``; - html += ``; - html += ``; - html += ``; - html += `
`; - - // Tab contents - html += `
`; - html += `
`; - html += `
`; - html += `
`; - html += `
`; - html += `
`; - html += `
`; - - html += `
`; - - $container.html(html); - - // Render individual sections - renderEmotionalState($('#rpg-tab-emotions')); - renderPhysicalCondition($('#rpg-tab-physical')); - renderRelationships($('#rpg-tab-relationships')); - renderInternalThoughts($('#rpg-tab-thoughts')); - renderContext($('#rpg-tab-context')); - - // Set up tab switching - setupTabs(); -} - -/** - * Sets up tab switching functionality - */ -function setupTabs() { - $('.rpg-tab-btn').off('click').on('click', function() { - const tabName = $(this).data('tab'); - - // Update active button - $('.rpg-tab-btn').removeClass('active'); - $(this).addClass('active'); - - // Update active pane - $('.rpg-tab-pane').removeClass('active'); - $(`#rpg-tab-${tabName}`).addClass('active'); - }); -} - -/** - * Helper function to format emotion names for display - * @param {string} emotion - Raw emotion key - * @returns {string} Formatted emotion name - */ -function formatEmotionName(emotion) { - // Convert camelCase to Title Case - return emotion - .replace(/([A-Z])/g, ' $1') - .replace(/^./, str => str.toUpperCase()) - .trim(); -} - -/** - * Helper function to get color for an emotion based on its type and intensity - * @param {string} emotion - Emotion type - * @param {number} value - Emotion intensity (0-100) - * @returns {string} CSS color - */ -function getEmotionColor(emotion, value) { - const intensity = value / 100; - - // Color mappings for different emotions - const emotionColors = { - happy: `rgba(76, 175, 80, ${0.5 + intensity * 0.5})`, // Green - sad: `rgba(96, 125, 139, ${0.5 + intensity * 0.5})`, // Blue-grey - angry: `rgba(244, 67, 54, ${0.5 + intensity * 0.5})`, // Red - anxious: `rgba(255, 152, 0, ${0.5 + intensity * 0.5})`, // Orange - horny: `rgba(233, 30, 99, ${0.5 + intensity * 0.5})`, // Pink - confident: `rgba(63, 81, 181, ${0.5 + intensity * 0.5})`, // Indigo - scared: `rgba(121, 85, 72, ${0.5 + intensity * 0.5})`, // Brown - playful: `rgba(255, 193, 7, ${0.5 + intensity * 0.5})` // Amber - }; - - return emotionColors[emotion] || `rgba(158, 158, 158, ${0.5 + intensity * 0.5})`; -} - -/** - * Helper function to get color for a physical stat - * @param {string} statKey - Stat key - * @param {number} value - Stat value (0-100) - * @returns {string} CSS color - */ -function getStatColor(statKey, value) { - // For most stats, green is high, red is low - // For hunger and arousal, yellow/orange might be more appropriate - - if (statKey === 'hunger') { - if (value < 30) return '#4CAF50'; // Green (not hungry) - if (value < 60) return '#FFC107'; // Yellow (getting hungry) - return '#F44336'; // Red (very hungry) - } - - if (statKey === 'arousal') { - if (value < 30) return '#9E9E9E'; // Grey (low) - if (value < 70) return '#E91E63'; // Pink (moderate) - return '#880E4F'; // Dark pink (high) - } - - // Default: green for high, red for low - if (value > 70) return '#4CAF50'; // Green - if (value > 40) return '#FFC107'; // Yellow - return '#F44336'; // Red -} - -/** - * Updates character state display - * Call this after parsing an LLM response to update the UI - */ -export function updateCharacterStateDisplay() { - console.log('[Character State Renderer] 🎭 updateCharacterStateDisplay called'); - - // Find the main container - const $mainContainer = $('#rpg-character-state-container'); - console.log('[Character State Renderer] Container found:', $mainContainer && $mainContainer.length > 0); - - if ($mainContainer && $mainContainer.length) { - console.log('[Character State Renderer] ✅ Rendering character state overview'); - renderCharacterStateOverview($mainContainer); - } else { - console.warn('[Character State Renderer] ❌ Container #rpg-character-state-container not found in DOM'); - } -} diff --git a/template.html b/template.html index f6a3a4b..76af63e 100644 --- a/template.html +++ b/template.html @@ -57,11 +57,6 @@
- - -
- -