Add stat change guidelines, attributes toggle, skills editing, and improved character parsing

- Add temporal awareness and stat decay rules to prompt (0-5% per message)
- Add 'Always Include Attributes' toggle in tracker editor
- Fix skills section editing (was not saving customFields)
- Improve Present Characters parser to handle malformed formats (mid-line chars, extra blank lines)
- All changes work in both together/separate generation modes
This commit is contained in:
Spicy_Marinara
2025-11-18 15:10:24 +01:00
parent ed3eac54fc
commit 2b45dc8fae
4 changed files with 57 additions and 7 deletions
+3 -1
View File
@@ -74,6 +74,7 @@ export let extensionSettings = {
],
// RPG Attributes (customizable D&D-style attributes)
showRPGAttributes: true,
alwaysSendAttributes: false, // If true, always send attributes; if false, only send with dice rolls
rpgAttributes: [
{ id: 'str', name: 'STR', enabled: true },
{ id: 'dex', name: 'DEX', enabled: true },
@@ -91,7 +92,8 @@ export let extensionSettings = {
// Optional skills field
skillsSection: {
enabled: false,
label: 'Skills' // User-editable
label: 'Skills', // User-editable
customFields: [] // Array of skill names
}
},
infoBox: {
+13 -4
View File
@@ -283,12 +283,21 @@ export function generateTrackerInstructions(includeHtmlPrompt = true, includeCon
instructions += `After updating the trackers, continue directly from where the last message in the chat history left off. Ensure the trackers you provide naturally reflect and influence the narrative. Character behavior, dialogue, and story events should acknowledge these conditions when relevant, such as fatigue affecting the protagonist's performance, low hygiene influencing their social interactions, environmental factors shaping the scene, a character's emotional state coloring their responses, and so on. Remember, all bracketed placeholders (e.g., [Location], [Mood Emoji]) MUST be replaced with actual content without the square brackets.\n\n`;
}
// Include attributes and dice roll only if there was a dice roll
if (extensionSettings.lastDiceRoll) {
const roll = extensionSettings.lastDiceRoll;
// Include attributes based on settings
const alwaysSendAttributes = trackerConfig?.userStats?.alwaysSendAttributes;
const shouldSendAttributes = alwaysSendAttributes || extensionSettings.lastDiceRoll;
if (shouldSendAttributes) {
const attributesString = buildAttributesString();
instructions += `${userName}'s attributes: ${attributesString}\n`;
instructions += `${userName} rolled ${roll.total} on the last ${roll.formula} roll. Based on their attributes, decide whether they succeeded or failed the action they attempted.\n\n`;
// Add dice roll context if there was one
if (extensionSettings.lastDiceRoll) {
const roll = extensionSettings.lastDiceRoll;
instructions += `${userName} rolled ${roll.total} on the last ${roll.formula} roll. Based on their attributes, decide whether they succeeded or failed the action they attempted.\n\n`;
} else {
instructions += `\n`;
}
}
}
+17 -1
View File
@@ -151,7 +151,23 @@ export function renderThoughts() {
let lineNumber = 0;
let currentCharacter = null;
for (const line of lines) {
// Pre-process: normalize the format to handle cases where "- char" appears mid-line
// This handles: "Thoughts: ... - char 2" by splitting it into separate lines
const normalizedLines = [];
for (let line of lines) {
// Check if line contains "- [name]" pattern after some content (not at start)
// Match pattern like "some text - CharName" where there's content before the dash
const midLineCharMatch = line.match(/^(.+?)\s+-\s+([A-Z][a-zA-Z\s]+)$/);
if (midLineCharMatch && !line.trim().startsWith('- ')) {
// Split: first part stays as one line, "- Name" becomes new line
normalizedLines.push(midLineCharMatch[1].trim());
normalizedLines.push('- ' + midLineCharMatch[2].trim());
} else {
normalizedLines.push(line);
}
}
for (const line of normalizedLines) {
lineNumber++;
// Skip empty lines, headers, dividers, and code fences
+24 -1
View File
@@ -143,7 +143,8 @@ function resetToDefaults() {
},
skillsSection: {
enabled: false,
label: 'Skills'
label: 'Skills',
customFields: []
}
},
infoBox: {
@@ -230,6 +231,14 @@ function renderUserStatsTab() {
html += '<label for="rpg-show-rpg-attrs">Enable RPG Attributes Section</label>';
html += '</div>';
// Always send attributes toggle
const alwaysSendAttributes = config.alwaysSendAttributes !== undefined ? config.alwaysSendAttributes : false;
html += '<div class="rpg-editor-toggle-row">';
html += `<input type="checkbox" id="rpg-always-send-attrs" ${alwaysSendAttributes ? 'checked' : ''}>`;
html += '<label for="rpg-always-send-attrs">Always Include Attributes in Prompt</label>';
html += '</div>';
html += '<small class="rpg-editor-note">If disabled, attributes are only sent when a dice roll is active.</small>';
html += '<div class="rpg-editor-stats-list" id="rpg-editor-attrs-list">';
// Ensure rpgAttributes exists in the actual config (not just local fallback)
@@ -286,6 +295,10 @@ function renderUserStatsTab() {
html += '<label>Skills Label:</label>';
html += `<input type="text" id="rpg-skills-label" value="${config.skillsSection.label}" class="rpg-text-input" placeholder="Skills">`;
html += '<label>Skills List (comma-separated):</label>';
const skillFields = config.skillsSection.customFields || [];
html += `<input type="text" id="rpg-skills-fields" value="${skillFields.join(', ')}" class="rpg-text-input" placeholder="e.g., Stealth, Persuasion, Combat">`;
html += '</div>';
$('#rpg-editor-tab-userStats').html(html);
@@ -380,6 +393,11 @@ function setupUserStatsListeners() {
extensionSettings.trackerConfig.userStats.showRPGAttributes = $(this).is(':checked');
});
// Always send attributes toggle
$('#rpg-always-send-attrs').off('change').on('change', function() {
extensionSettings.trackerConfig.userStats.alwaysSendAttributes = $(this).is(':checked');
});
// Status section toggles
$('#rpg-status-enabled').off('change').on('change', function() {
extensionSettings.trackerConfig.userStats.statusSection.enabled = $(this).is(':checked');
@@ -402,6 +420,11 @@ function setupUserStatsListeners() {
$('#rpg-skills-label').off('blur').on('blur', function() {
extensionSettings.trackerConfig.userStats.skillsSection.label = $(this).val();
});
$('#rpg-skills-fields').off('blur').on('blur', function() {
const fields = $(this).val().split(',').map(f => f.trim()).filter(f => f);
extensionSettings.trackerConfig.userStats.skillsSection.customFields = fields;
});
}
/**