Add editable stat names, fix clear cache for quests, update tracker text to use custom stat names
This commit is contained in:
@@ -53,6 +53,13 @@ export let extensionSettings = {
|
|||||||
assets: "None"
|
assets: "None"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
statNames: {
|
||||||
|
health: 'Health',
|
||||||
|
satiety: 'Satiety',
|
||||||
|
energy: 'Energy',
|
||||||
|
hygiene: 'Hygiene',
|
||||||
|
arousal: 'Arousal'
|
||||||
|
},
|
||||||
quests: {
|
quests: {
|
||||||
main: "None", // Current main quest title
|
main: "None", // Current main quest title
|
||||||
optional: [] // Array of optional quest titles
|
optional: [] // Array of optional quest titles
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
import { extensionSettings, lastGeneratedData, committedTrackerData } from '../../core/state.js';
|
import { extensionSettings, lastGeneratedData, committedTrackerData } from '../../core/state.js';
|
||||||
import { saveSettings, saveChatData, updateMessageSwipeData } from '../../core/persistence.js';
|
import { saveSettings, saveChatData, updateMessageSwipeData } from '../../core/persistence.js';
|
||||||
import { buildInventorySummary } from '../generation/promptBuilder.js';
|
import { buildInventorySummary } from '../generation/promptBuilder.js';
|
||||||
|
import { buildUserStatsText } from '../rendering/userStats.js';
|
||||||
import { renderInventory, getLocationId } from '../rendering/inventory.js';
|
import { renderInventory, getLocationId } from '../rendering/inventory.js';
|
||||||
import { parseItems, serializeItems } from '../../utils/itemParser.js';
|
import { parseItems, serializeItems } from '../../utils/itemParser.js';
|
||||||
import { sanitizeLocationName, sanitizeItemName } from '../../utils/security.js';
|
import { sanitizeLocationName, sanitizeItemName } from '../../utils/security.js';
|
||||||
@@ -42,18 +43,8 @@ let openForms = {
|
|||||||
* This ensures manual edits are immediately visible to AI in next generation.
|
* This ensures manual edits are immediately visible to AI in next generation.
|
||||||
*/
|
*/
|
||||||
function updateLastGeneratedDataInventory() {
|
function updateLastGeneratedDataInventory() {
|
||||||
const stats = extensionSettings.userStats;
|
// Rebuild the userStats text format using custom stat names
|
||||||
const inventorySummary = buildInventorySummary(stats.inventory);
|
const statsText = buildUserStatsText();
|
||||||
|
|
||||||
// Rebuild the userStats text format
|
|
||||||
const statsText =
|
|
||||||
`Health: ${stats.health}%\n` +
|
|
||||||
`Satiety: ${stats.satiety}%\n` +
|
|
||||||
`Energy: ${stats.energy}%\n` +
|
|
||||||
`Hygiene: ${stats.hygiene}%\n` +
|
|
||||||
`Arousal: ${stats.arousal}%\n` +
|
|
||||||
`${stats.mood}: ${stats.conditions}\n` +
|
|
||||||
`${inventorySummary}`;
|
|
||||||
|
|
||||||
// Update BOTH lastGeneratedData AND committedTrackerData
|
// Update BOTH lastGeneratedData AND committedTrackerData
|
||||||
// This makes manual edits immediately visible to AI
|
// This makes manual edits immediately visible to AI
|
||||||
|
|||||||
@@ -20,9 +20,28 @@ import {
|
|||||||
import { getSafeThumbnailUrl } from '../../utils/avatars.js';
|
import { getSafeThumbnailUrl } from '../../utils/avatars.js';
|
||||||
import { buildInventorySummary } from '../generation/promptBuilder.js';
|
import { buildInventorySummary } from '../generation/promptBuilder.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the user stats text string using custom stat names
|
||||||
|
* @returns {string} Formatted stats text for tracker
|
||||||
|
*/
|
||||||
|
export function buildUserStatsText() {
|
||||||
|
const stats = extensionSettings.userStats;
|
||||||
|
const statNames = extensionSettings.statNames || {
|
||||||
|
health: 'Health',
|
||||||
|
satiety: 'Satiety',
|
||||||
|
energy: 'Energy',
|
||||||
|
hygiene: 'Hygiene',
|
||||||
|
arousal: 'Arousal'
|
||||||
|
};
|
||||||
|
const inventorySummary = buildInventorySummary(stats.inventory);
|
||||||
|
|
||||||
|
return `${statNames.health}: ${stats.health}%\n${statNames.satiety}: ${stats.satiety}%\n${statNames.energy}: ${stats.energy}%\n${statNames.hygiene}: ${stats.hygiene}%\n${statNames.arousal}: ${stats.arousal}%\n${stats.mood}: ${stats.conditions}\n${inventorySummary}`;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the user stats panel with health bars, mood, inventory, and classic stats.
|
* Renders the user stats panel with health bars, mood, inventory, and classic stats.
|
||||||
* Includes event listeners for editable fields.
|
* Includes event listeners for editable fields.
|
||||||
|
```
|
||||||
*/
|
*/
|
||||||
export function renderUserStats() {
|
export function renderUserStats() {
|
||||||
if (!extensionSettings.showUserStats || !$userStatsContainer) {
|
if (!extensionSettings.showUserStats || !$userStatsContainer) {
|
||||||
@@ -30,11 +49,18 @@ export function renderUserStats() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const stats = extensionSettings.userStats;
|
const stats = extensionSettings.userStats;
|
||||||
|
const statNames = extensionSettings.statNames || {
|
||||||
|
health: 'Health',
|
||||||
|
satiety: 'Satiety',
|
||||||
|
energy: 'Energy',
|
||||||
|
hygiene: 'Hygiene',
|
||||||
|
arousal: 'Arousal'
|
||||||
|
};
|
||||||
const userName = getContext().name1;
|
const userName = getContext().name1;
|
||||||
|
|
||||||
// Initialize lastGeneratedData.userStats if it doesn't exist
|
// Initialize lastGeneratedData.userStats if it doesn't exist
|
||||||
if (!lastGeneratedData.userStats) {
|
if (!lastGeneratedData.userStats) {
|
||||||
lastGeneratedData.userStats = `Health: ${stats.health}%\nSatiety: ${stats.satiety}%\nEnergy: ${stats.energy}%\nHygiene: ${stats.hygiene}%\nArousal: ${stats.arousal}%\n${stats.mood}: ${stats.conditions}\nInventory: ${stats.inventory}`;
|
lastGeneratedData.userStats = buildUserStatsText();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get user portrait - handle both default-user and custom persona folders
|
// Get user portrait - handle both default-user and custom persona folders
|
||||||
@@ -64,7 +90,7 @@ export function renderUserStats() {
|
|||||||
</div>
|
</div>
|
||||||
<div class="rpg-stats-grid">
|
<div class="rpg-stats-grid">
|
||||||
<div class="rpg-stat-row">
|
<div class="rpg-stat-row">
|
||||||
<span class="rpg-stat-label">Health:</span>
|
<span class="rpg-stat-label rpg-editable-stat-name" contenteditable="true" data-field="health" title="Click to edit stat name">${statNames.health}:</span>
|
||||||
<div class="rpg-stat-bar" style="background: ${gradient}">
|
<div class="rpg-stat-bar" style="background: ${gradient}">
|
||||||
<div class="rpg-stat-fill" style="width: ${100 - stats.health}%"></div>
|
<div class="rpg-stat-fill" style="width: ${100 - stats.health}%"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -72,7 +98,7 @@ export function renderUserStats() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="rpg-stat-row">
|
<div class="rpg-stat-row">
|
||||||
<span class="rpg-stat-label">Satiety:</span>
|
<span class="rpg-stat-label rpg-editable-stat-name" contenteditable="true" data-field="satiety" title="Click to edit stat name">${statNames.satiety}:</span>
|
||||||
<div class="rpg-stat-bar" style="background: ${gradient}">
|
<div class="rpg-stat-bar" style="background: ${gradient}">
|
||||||
<div class="rpg-stat-fill" style="width: ${100 - stats.satiety}%"></div>
|
<div class="rpg-stat-fill" style="width: ${100 - stats.satiety}%"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -80,7 +106,7 @@ export function renderUserStats() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="rpg-stat-row">
|
<div class="rpg-stat-row">
|
||||||
<span class="rpg-stat-label">Energy:</span>
|
<span class="rpg-stat-label rpg-editable-stat-name" contenteditable="true" data-field="energy" title="Click to edit stat name">${statNames.energy}:</span>
|
||||||
<div class="rpg-stat-bar" style="background: ${gradient}">
|
<div class="rpg-stat-bar" style="background: ${gradient}">
|
||||||
<div class="rpg-stat-fill" style="width: ${100 - stats.energy}%"></div>
|
<div class="rpg-stat-fill" style="width: ${100 - stats.energy}%"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -88,7 +114,7 @@ export function renderUserStats() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="rpg-stat-row">
|
<div class="rpg-stat-row">
|
||||||
<span class="rpg-stat-label">Hygiene:</span>
|
<span class="rpg-stat-label rpg-editable-stat-name" contenteditable="true" data-field="hygiene" title="Click to edit stat name">${statNames.hygiene}:</span>
|
||||||
<div class="rpg-stat-bar" style="background: ${gradient}">
|
<div class="rpg-stat-bar" style="background: ${gradient}">
|
||||||
<div class="rpg-stat-fill" style="width: ${100 - stats.hygiene}%"></div>
|
<div class="rpg-stat-fill" style="width: ${100 - stats.hygiene}%"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -96,7 +122,7 @@ export function renderUserStats() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="rpg-stat-row">
|
<div class="rpg-stat-row">
|
||||||
<span class="rpg-stat-label">Arousal:</span>
|
<span class="rpg-stat-label rpg-editable-stat-name" contenteditable="true" data-field="arousal" title="Click to edit stat name">${statNames.arousal}:</span>
|
||||||
<div class="rpg-stat-bar" style="background: ${gradient}">
|
<div class="rpg-stat-bar" style="background: ${gradient}">
|
||||||
<div class="rpg-stat-fill" style="width: ${100 - stats.arousal}%"></div>
|
<div class="rpg-stat-fill" style="width: ${100 - stats.arousal}%"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -184,10 +210,8 @@ export function renderUserStats() {
|
|||||||
// Update the setting
|
// Update the setting
|
||||||
extensionSettings.userStats[field] = value;
|
extensionSettings.userStats[field] = value;
|
||||||
|
|
||||||
// Rebuild userStats text with proper inventory format
|
// Rebuild userStats text with custom stat names
|
||||||
const stats = extensionSettings.userStats;
|
const statsText = buildUserStatsText();
|
||||||
const inventorySummary = buildInventorySummary(stats.inventory);
|
|
||||||
const statsText = `Health: ${stats.health}%\nSatiety: ${stats.satiety}%\nEnergy: ${stats.energy}%\nHygiene: ${stats.hygiene}%\nArousal: ${stats.arousal}%\n${stats.mood}: ${stats.conditions}\n${inventorySummary}`;
|
|
||||||
|
|
||||||
// Update BOTH lastGeneratedData AND committedTrackerData
|
// Update BOTH lastGeneratedData AND committedTrackerData
|
||||||
// This makes manual edits immediately visible to AI
|
// This makes manual edits immediately visible to AI
|
||||||
@@ -207,10 +231,8 @@ export function renderUserStats() {
|
|||||||
const value = $(this).text().trim();
|
const value = $(this).text().trim();
|
||||||
extensionSettings.userStats.mood = value || '😐';
|
extensionSettings.userStats.mood = value || '😐';
|
||||||
|
|
||||||
// Rebuild userStats text with proper inventory format
|
// Rebuild userStats text with custom stat names
|
||||||
const stats = extensionSettings.userStats;
|
const statsText = buildUserStatsText();
|
||||||
const inventorySummary = buildInventorySummary(stats.inventory);
|
|
||||||
const statsText = `Health: ${stats.health}%\nSatiety: ${stats.satiety}%\nEnergy: ${stats.energy}%\nHygiene: ${stats.hygiene}%\nArousal: ${stats.arousal}%\n${stats.mood}: ${stats.conditions}\n${inventorySummary}`;
|
|
||||||
|
|
||||||
// Update BOTH lastGeneratedData AND committedTrackerData
|
// Update BOTH lastGeneratedData AND committedTrackerData
|
||||||
// This makes manual edits immediately visible to AI
|
// This makes manual edits immediately visible to AI
|
||||||
@@ -226,10 +248,8 @@ export function renderUserStats() {
|
|||||||
const value = $(this).text().trim();
|
const value = $(this).text().trim();
|
||||||
extensionSettings.userStats.conditions = value || 'None';
|
extensionSettings.userStats.conditions = value || 'None';
|
||||||
|
|
||||||
// Rebuild userStats text with proper inventory format
|
// Rebuild userStats text with custom stat names
|
||||||
const stats = extensionSettings.userStats;
|
const statsText = buildUserStatsText();
|
||||||
const inventorySummary = buildInventorySummary(stats.inventory);
|
|
||||||
const statsText = `Health: ${stats.health}%\nSatiety: ${stats.satiety}%\nEnergy: ${stats.energy}%\nHygiene: ${stats.hygiene}%\nArousal: ${stats.arousal}%\n${stats.mood}: ${stats.conditions}\n${inventorySummary}`;
|
|
||||||
|
|
||||||
// Update BOTH lastGeneratedData AND committedTrackerData
|
// Update BOTH lastGeneratedData AND committedTrackerData
|
||||||
// This makes manual edits immediately visible to AI
|
// This makes manual edits immediately visible to AI
|
||||||
@@ -241,6 +261,30 @@ export function renderUserStats() {
|
|||||||
updateMessageSwipeData();
|
updateMessageSwipeData();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add event listeners for stat name editing
|
||||||
|
$('.rpg-editable-stat-name').on('blur', function() {
|
||||||
|
const field = $(this).data('field');
|
||||||
|
const value = $(this).text().trim().replace(':', '');
|
||||||
|
|
||||||
|
if (!extensionSettings.statNames) {
|
||||||
|
extensionSettings.statNames = {
|
||||||
|
health: 'Health',
|
||||||
|
satiety: 'Satiety',
|
||||||
|
energy: 'Energy',
|
||||||
|
hygiene: 'Hygiene',
|
||||||
|
arousal: 'Arousal'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
extensionSettings.statNames[field] = value || extensionSettings.statNames[field];
|
||||||
|
|
||||||
|
saveSettings();
|
||||||
|
saveChatData();
|
||||||
|
|
||||||
|
// Re-render to update the display
|
||||||
|
renderUserStats();
|
||||||
|
});
|
||||||
|
|
||||||
// Add event listener for level editing
|
// Add event listener for level editing
|
||||||
$('.rpg-level-value.rpg-editable').on('blur', function() {
|
$('.rpg-level-value.rpg-editable').on('blur', function() {
|
||||||
let value = parseInt($(this).text().trim());
|
let value = parseInt($(this).text().trim());
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
import { saveSettings, saveChatData } from '../../core/persistence.js';
|
import { saveSettings, saveChatData } from '../../core/persistence.js';
|
||||||
import { renderUserStats } from '../rendering/userStats.js';
|
import { renderUserStats } from '../rendering/userStats.js';
|
||||||
import { updateChatThoughts } from '../rendering/thoughts.js';
|
import { updateChatThoughts } from '../rendering/thoughts.js';
|
||||||
|
import { renderQuests } from '../rendering/quests.js';
|
||||||
import {
|
import {
|
||||||
rollDice as rollDiceCore,
|
rollDice as rollDiceCore,
|
||||||
clearDiceRoll as clearDiceRollCore,
|
clearDiceRoll as clearDiceRollCore,
|
||||||
@@ -403,6 +404,12 @@ export function setupSettingsPopup() {
|
|||||||
// Clear dice roll
|
// Clear dice roll
|
||||||
extensionSettings.lastDiceRoll = null;
|
extensionSettings.lastDiceRoll = null;
|
||||||
|
|
||||||
|
// Clear quests
|
||||||
|
extensionSettings.quests = {
|
||||||
|
main: "None",
|
||||||
|
optional: []
|
||||||
|
};
|
||||||
|
|
||||||
// Save everything
|
// Save everything
|
||||||
saveChatData();
|
saveChatData();
|
||||||
saveSettings();
|
saveSettings();
|
||||||
@@ -411,6 +418,7 @@ export function setupSettingsPopup() {
|
|||||||
renderUserStats();
|
renderUserStats();
|
||||||
updateDiceDisplayCore();
|
updateDiceDisplayCore();
|
||||||
updateChatThoughts(); // Clear the thought bubble in chat
|
updateChatThoughts(); // Clear the thought bubble in chat
|
||||||
|
renderQuests(); // Clear and re-render quests UI
|
||||||
|
|
||||||
// console.log('[RPG Companion] Chat cache cleared');
|
// console.log('[RPG Companion] Chat cache cleared');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1896,7 +1896,8 @@ body:has(.rpg-panel.rpg-position-left) #sheld {
|
|||||||
|
|
||||||
/* Editable field styles */
|
/* Editable field styles */
|
||||||
.rpg-editable,
|
.rpg-editable,
|
||||||
.rpg-editable-stat {
|
.rpg-editable-stat,
|
||||||
|
.rpg-editable-stat-name {
|
||||||
cursor: text;
|
cursor: text;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
@@ -1904,13 +1905,15 @@ body:has(.rpg-panel.rpg-position-left) #sheld {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.rpg-editable:hover,
|
.rpg-editable:hover,
|
||||||
.rpg-editable-stat:hover {
|
.rpg-editable-stat:hover,
|
||||||
|
.rpg-editable-stat-name:hover {
|
||||||
background: var(--rpg-accent);
|
background: var(--rpg-accent);
|
||||||
outline: 1px solid var(--rpg-highlight);
|
outline: 1px solid var(--rpg-highlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
.rpg-editable:focus,
|
.rpg-editable:focus,
|
||||||
.rpg-editable-stat:focus {
|
.rpg-editable-stat:focus,
|
||||||
|
.rpg-editable-stat-name:focus {
|
||||||
background: var(--rpg-bg);
|
background: var(--rpg-bg);
|
||||||
outline: 2px solid var(--rpg-highlight);
|
outline: 2px solid var(--rpg-highlight);
|
||||||
box-shadow: 0 0 8px var(--rpg-highlight);
|
box-shadow: 0 0 8px var(--rpg-highlight);
|
||||||
|
|||||||
Reference in New Issue
Block a user