diff --git a/manifest.json b/manifest.json index 54cab2e..049c402 100644 --- a/manifest.json +++ b/manifest.json @@ -6,6 +6,6 @@ "js": "index.js", "css": "style.css", "author": "Marysia", - "version": "2.1.1", + "version": "2.1.2", "homePage": "https://github.com/SpicyMarinara/rpg-companion-sillytavern" } diff --git a/src/core/persistence.js b/src/core/persistence.js index 120e933..181c80f 100644 --- a/src/core/persistence.js +++ b/src/core/persistence.js @@ -550,6 +550,21 @@ function migrateToTrackerConfig() { 'Neutral': '⚖️' }; } + + // Migrate to new relationships structure if not already present + if (!pc.relationships) { + pc.relationships = { + enabled: true, // Default to enabled for backward compatibility + relationshipEmojis: pc.relationshipEmojis || { + 'Lover': '❤️', + 'Friend': '⭐', + 'Ally': '🤝', + 'Enemy': '⚔️', + 'Neutral': '⚖️' + } + }; + } + if (!pc.thoughts) { pc.thoughts = { enabled: true, diff --git a/src/core/state.js b/src/core/state.js index c8b58d1..6f0c665 100644 --- a/src/core/state.js +++ b/src/core/state.js @@ -124,9 +124,20 @@ export let extensionSettings = { // Fixed fields (always shown) showEmoji: true, showName: true, - // Relationship fields (shown after name, separated by /) + // Relationship fields configuration + relationships: { + enabled: true, + // Relationship to emoji mapping (shown on character portraits) + relationshipEmojis: { + 'Lover': '❤️', + 'Friend': '⭐', + 'Ally': '🤝', + 'Enemy': '⚔️', + 'Neutral': '⚖️' + } + }, + // Legacy fields kept for backward compatibility relationshipFields: ['Lover', 'Friend', 'Ally', 'Enemy', 'Neutral'], - // Relationship to emoji mapping (shown on character portraits) relationshipEmojis: { 'Lover': '❤️', 'Friend': '⭐', diff --git a/src/i18n/en.json b/src/i18n/en.json index 09cecec..04f9c92 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -121,6 +121,7 @@ "template.trackerEditorModal.infoBoxTab.locationWidget": "Location", "template.trackerEditorModal.infoBoxTab.recentEventsWidget": "Recent Events", "template.trackerEditorModal.presentCharactersTab.relationshipStatusTitle": "Relationship Status Fields", + "template.trackerEditorModal.presentCharactersTab.enableRelationshipStatus": "Enable Relationship Status Fields", "template.trackerEditorModal.presentCharactersTab.relationshipStatusHint": "Define relationship types with corresponding emojis shown on character portraits", "template.trackerEditorModal.presentCharactersTab.newRelationshipButton": "New Relationship", "template.trackerEditorModal.presentCharactersTab.appearanceDemeanorTitle": "Appearance/Demeanor Fields", diff --git a/src/i18n/zh-tw.json b/src/i18n/zh-tw.json index 80a3e14..be8da5a 100644 --- a/src/i18n/zh-tw.json +++ b/src/i18n/zh-tw.json @@ -112,6 +112,7 @@ "template.trackerEditorModal.infoBoxTab.locationWidget": "位置", "template.trackerEditorModal.infoBoxTab.recentEventsWidget": "近期事件", "template.trackerEditorModal.presentCharactersTab.relationshipStatusTitle": "關係狀態", + "template.trackerEditorModal.presentCharactersTab.enableRelationshipStatus": "啟用關係狀態欄位", "template.trackerEditorModal.presentCharactersTab.relationshipStatusHint": "定義關係類型,並在角色頭像上顯示對應的表情符號", "template.trackerEditorModal.presentCharactersTab.newRelationshipButton": "新增關係類型", "template.trackerEditorModal.presentCharactersTab.appearanceDemeanorTitle": "外觀與當前行為舉止", diff --git a/src/systems/generation/promptBuilder.js b/src/systems/generation/promptBuilder.js index 62cfad7..4dc67ca 100644 --- a/src/systems/generation/promptBuilder.js +++ b/src/systems/generation/promptBuilder.js @@ -355,7 +355,11 @@ export function generateTrackerInstructions(includeHtmlPrompt = true, includeCon if (extensionSettings.showCharacterThoughts) { const presentCharsConfig = trackerConfig?.presentCharacters; const enabledFields = presentCharsConfig?.customFields?.filter(f => f && f.enabled && f.name) || []; - const relationshipFields = presentCharsConfig?.relationshipFields || []; + + // Check if relationships are enabled + const relationshipsEnabled = presentCharsConfig?.relationships?.enabled !== false; // Default to true + const relationshipFields = relationshipsEnabled ? (presentCharsConfig?.relationshipFields || []) : []; + const thoughtsConfig = presentCharsConfig?.thoughts; const characterStats = presentCharsConfig?.characterStats; const enabledCharStats = characterStats?.enabled && characterStats?.customStats?.filter(s => s && s.enabled && s.name) || []; @@ -390,7 +394,7 @@ export function generateTrackerInstructions(includeHtmlPrompt = true, includeCon } // Relationship line (only if relationships are enabled) - if (relationshipPlaceholders) { + if (relationshipsEnabled && relationshipPlaceholders) { instructions += `Relationship: [(choose one: ${relationshipPlaceholders})]\n`; } diff --git a/src/systems/rendering/thoughts.js b/src/systems/rendering/thoughts.js index a36e7a3..3e6ee14 100644 --- a/src/systems/rendering/thoughts.js +++ b/src/systems/rendering/thoughts.js @@ -325,8 +325,11 @@ export function renderThoughts() { const enabledFields = config?.customFields?.filter(f => f && f.enabled && f.name) || []; const characterStatsConfig = config?.characterStats; const enabledCharStats = characterStatsConfig?.enabled && characterStatsConfig?.customStats?.filter(s => s && s.enabled && s.name) || []; - const relationshipFields = config?.relationshipFields || []; - const hasRelationshipEnabled = relationshipFields.length > 0; + + // Check if relationships are enabled (new structure with fallback to legacy) + const relationshipsEnabled = config?.relationships?.enabled !== false; // Default to true if not set + const relationshipFields = relationshipsEnabled ? (config?.relationshipFields || []) : []; + const hasRelationshipEnabled = relationshipFields.length > 0 && relationshipsEnabled; // Use committedTrackerData as fallback if lastGeneratedData is empty (e.g., after page refresh) const characterThoughtsData = lastGeneratedData.characterThoughts || committedTrackerData.characterThoughts || ''; @@ -442,7 +445,8 @@ export function renderThoughts() { } // Get relationship emojis from config (with fallback defaults) - const relationshipEmojis = config?.relationshipEmojis || { + // Support both new and legacy structure + const relationshipEmojis = config?.relationships?.relationshipEmojis || config?.relationshipEmojis || { 'Enemy': '⚔️', 'Neutral': '⚖️', 'Friend': '⭐', @@ -876,7 +880,7 @@ export function updateCharacterField(characterName, field, value) { } newCharacterLines.push(`Details: ${detailsParts.join(' | ')}`); - if (presentCharsConfig?.relationshipFields?.length > 0) { + if (presentCharsConfig?.relationships?.enabled !== false && presentCharsConfig?.relationshipFields?.length > 0) { const emojiToRelationship = { '⚔️': 'Enemy', '⚖️': 'Neutral', '⭐': 'Friend', '❤️': 'Lover' }; const relationshipValue = field === 'Relationship' ? (emojiToRelationship[value] || value) : 'Neutral'; newCharacterLines.push(`Relationship: ${relationshipValue}`); diff --git a/src/systems/ui/trackerEditor.js b/src/systems/ui/trackerEditor.js index 8713df9..bfa5c5a 100644 --- a/src/systems/ui/trackerEditor.js +++ b/src/systems/ui/trackerEditor.js @@ -170,6 +170,16 @@ function resetToDefaults() { presentCharacters: { showEmoji: true, showName: true, + relationships: { + enabled: true, + relationshipEmojis: { + 'Lover': '❤️', + 'Friend': '⭐', + 'Ally': '🤝', + 'Enemy': '⚔️', + 'Neutral': '⚖️' + } + }, relationshipFields: ['Lover', 'Friend', 'Ally', 'Enemy', 'Neutral'], relationshipEmojis: { 'Lover': '❤️', @@ -645,11 +655,19 @@ function renderPresentCharactersTab() { // Relationship Fields Section html += `

${i18n.getTranslation('template.trackerEditorModal.presentCharactersTab.relationshipStatusTitle')}

`; + + // Toggle for enabling/disabling relationships + const relationshipsEnabled = config.relationships?.enabled !== false; // Default to true if not set + html += '
'; + html += ``; + html += ``; + html += '
'; + html += `

${i18n.getTranslation('template.trackerEditorModal.presentCharactersTab.relationshipStatusHint')}

`; html += '
'; // Show existing relationships as field → emoji pairs - const relationshipEmojis = config.relationshipEmojis || { + const relationshipEmojis = config.relationships?.relationshipEmojis || config.relationshipEmojis || { 'Lover': '❤️', 'Friend': '⭐', 'Ally': '🤝', @@ -746,16 +764,36 @@ function renderPresentCharactersTab() { * Set up event listeners for Present Characters tab */ function setupPresentCharactersListeners() { + // Relationships enabled toggle + $('#rpg-relationships-enabled').off('change').on('change', function() { + if (!extensionSettings.trackerConfig.presentCharacters.relationships) { + extensionSettings.trackerConfig.presentCharacters.relationships = { enabled: true, relationshipEmojis: {} }; + } + extensionSettings.trackerConfig.presentCharacters.relationships.enabled = $(this).is(':checked'); + }); + // Add new relationship $('#rpg-add-relationship').off('click').on('click', function() { + // Ensure relationships object exists + if (!extensionSettings.trackerConfig.presentCharacters.relationships) { + extensionSettings.trackerConfig.presentCharacters.relationships = { enabled: true, relationshipEmojis: {} }; + } + if (!extensionSettings.trackerConfig.presentCharacters.relationships.relationshipEmojis) { + extensionSettings.trackerConfig.presentCharacters.relationships.relationshipEmojis = {}; + } + + // Add to new structure + extensionSettings.trackerConfig.presentCharacters.relationships.relationshipEmojis['New Relationship'] = '😊'; + + // Also update legacy fields for backward compatibility if (!extensionSettings.trackerConfig.presentCharacters.relationshipEmojis) { extensionSettings.trackerConfig.presentCharacters.relationshipEmojis = {}; } extensionSettings.trackerConfig.presentCharacters.relationshipEmojis['New Relationship'] = '😊'; // Sync relationshipFields - extensionSettings.trackerConfig.presentCharacters.relationshipFields = - Object.keys(extensionSettings.trackerConfig.presentCharacters.relationshipEmojis); + const emojis = extensionSettings.trackerConfig.presentCharacters.relationships.relationshipEmojis; + extensionSettings.trackerConfig.presentCharacters.relationshipFields = Object.keys(emojis); renderPresentCharactersTab(); }); @@ -763,13 +801,20 @@ function setupPresentCharactersListeners() { // Remove relationship $('.rpg-remove-relationship').off('click').on('click', function() { const relationship = $(this).data('relationship'); + + // Remove from new structure + if (extensionSettings.trackerConfig.presentCharacters.relationships?.relationshipEmojis) { + delete extensionSettings.trackerConfig.presentCharacters.relationships.relationshipEmojis[relationship]; + } + + // Remove from legacy structure if (extensionSettings.trackerConfig.presentCharacters.relationshipEmojis) { delete extensionSettings.trackerConfig.presentCharacters.relationshipEmojis[relationship]; } // Sync relationshipFields - extensionSettings.trackerConfig.presentCharacters.relationshipFields = - Object.keys(extensionSettings.trackerConfig.presentCharacters.relationshipEmojis); + const emojis = extensionSettings.trackerConfig.presentCharacters.relationships?.relationshipEmojis || {}; + extensionSettings.trackerConfig.presentCharacters.relationshipFields = Object.keys(emojis); renderPresentCharactersTab(); }); @@ -780,28 +825,48 @@ function setupPresentCharactersListeners() { const $item = $(this).closest('.rpg-relationship-item'); const emoji = $item.find('.rpg-relationship-emoji').val(); - // Find the old name by matching the emoji - const oldName = Object.keys(extensionSettings.trackerConfig.presentCharacters.relationshipEmojis).find( - key => extensionSettings.trackerConfig.presentCharacters.relationshipEmojis[key] === emoji && - key !== newName + // Ensure structures exist + if (!extensionSettings.trackerConfig.presentCharacters.relationships) { + extensionSettings.trackerConfig.presentCharacters.relationships = { enabled: true, relationshipEmojis: {} }; + } + if (!extensionSettings.trackerConfig.presentCharacters.relationshipEmojis) { + extensionSettings.trackerConfig.presentCharacters.relationshipEmojis = {}; + } + + // Find the old name by matching the emoji in new structure + const emojis = extensionSettings.trackerConfig.presentCharacters.relationships.relationshipEmojis; + const oldName = Object.keys(emojis).find( + key => emojis[key] === emoji && key !== newName ); if (oldName && oldName !== newName) { + // Update new structure + delete emojis[oldName]; + emojis[newName] = emoji; + + // Update legacy structure delete extensionSettings.trackerConfig.presentCharacters.relationshipEmojis[oldName]; extensionSettings.trackerConfig.presentCharacters.relationshipEmojis[newName] = emoji; // Sync relationshipFields - extensionSettings.trackerConfig.presentCharacters.relationshipFields = - Object.keys(extensionSettings.trackerConfig.presentCharacters.relationshipEmojis); + extensionSettings.trackerConfig.presentCharacters.relationshipFields = Object.keys(emojis); } }); // Update relationship emoji $('.rpg-relationship-emoji').off('blur').on('blur', function() { const name = $(this).closest('.rpg-relationship-item').find('.rpg-relationship-name').val(); + + // Ensure structures exist + if (!extensionSettings.trackerConfig.presentCharacters.relationships) { + extensionSettings.trackerConfig.presentCharacters.relationships = { enabled: true, relationshipEmojis: {} }; + } if (!extensionSettings.trackerConfig.presentCharacters.relationshipEmojis) { extensionSettings.trackerConfig.presentCharacters.relationshipEmojis = {}; } + + // Update both structures + extensionSettings.trackerConfig.presentCharacters.relationships.relationshipEmojis[name] = $(this).val(); extensionSettings.trackerConfig.presentCharacters.relationshipEmojis[name] = $(this).val(); });