feat: add Equipment tab with slot-type validation
Add a new Equipment tab to manage player gear and stat bonuses. Features: - 19 equipment slots across 8 categories (helmet, necklace, body armor, gloves, pants, shoes, rings, accessories) - Type-to-slot validation: each type has max equipped limits (1 helmet, 10 rings, 3 accessories, etc.) - Auto-slot assignment: equipping a ring fills the first available ring slot - Stat bonuses from equipped items display on RPG attributes (e.g. STR 10 +2) - Create/edit modal with stat checkboxes per RPG attribute - Inventory list for unequipped items Architecture: - Shared constants in src/systems/equipment/constants.js - Category-based types (Ring, Accessory) with auto-slot assignment - v7 migration converts legacy slot-specific types to generic categories - Full i18n support for all UI strings Files: - New: src/systems/equipment/constants.js - New: src/systems/interaction/equipmentActions.js - New: src/systems/rendering/equipment.js - Modified: state.js, persistence.js, template.html, index.js - Modified: userStats.js, desktop.js, mobile.js, layout.js, modals.js - Modified: apiClient.js, sillytavern.js, style.css, en.json
This commit is contained in:
@@ -21,6 +21,7 @@ import {
|
||||
$infoBoxContainer,
|
||||
$thoughtsContainer,
|
||||
$inventoryContainer,
|
||||
$equipmentContainer,
|
||||
$questsContainer,
|
||||
$musicPlayerContainer,
|
||||
setExtensionSettings,
|
||||
@@ -38,6 +39,7 @@ import {
|
||||
setInfoBoxContainer,
|
||||
setThoughtsContainer,
|
||||
setInventoryContainer,
|
||||
setEquipmentContainer,
|
||||
setQuestsContainer,
|
||||
setMusicPlayerContainer,
|
||||
clearSessionAvatarPrompts
|
||||
@@ -69,6 +71,7 @@ import {
|
||||
createThoughtPanel
|
||||
} from './src/systems/rendering/thoughts.js';
|
||||
import { renderInventory } from './src/systems/rendering/inventory.js';
|
||||
import { renderEquipment } from './src/systems/rendering/equipment.js';
|
||||
import { renderQuests } from './src/systems/rendering/quests.js';
|
||||
import { renderMusicPlayer } from './src/systems/rendering/musicPlayer.js';
|
||||
import { toggleSnowflakes, initSnowflakes } from './src/systems/ui/snowflakes.js';
|
||||
@@ -76,6 +79,7 @@ import { toggleDynamicWeather, initWeatherEffects, updateWeatherEffect } from '.
|
||||
|
||||
// Interaction modules
|
||||
import { initInventoryEventListeners } from './src/systems/interaction/inventoryActions.js';
|
||||
import { initEquipmentEventListeners } from './src/systems/interaction/equipmentActions.js';
|
||||
|
||||
// UI Systems modules
|
||||
import {
|
||||
@@ -313,6 +317,7 @@ async function initUI() {
|
||||
setInfoBoxContainer($('#rpg-info-box'));
|
||||
setThoughtsContainer($('#rpg-thoughts'));
|
||||
setInventoryContainer($('#rpg-inventory'));
|
||||
setEquipmentContainer($('#rpg-equipment'));
|
||||
setQuestsContainer($('#rpg-quests'));
|
||||
setMusicPlayerContainer($('#rpg-music-player'));
|
||||
|
||||
@@ -389,6 +394,12 @@ async function initUI() {
|
||||
updateSectionVisibility();
|
||||
});
|
||||
|
||||
$('#rpg-toggle-equipment').on('change', function() {
|
||||
extensionSettings.showEquipment = $(this).prop('checked');
|
||||
saveSettings();
|
||||
updateSectionVisibility();
|
||||
});
|
||||
|
||||
$('#rpg-toggle-quests').on('change', function() {
|
||||
extensionSettings.showQuests = $(this).prop('checked');
|
||||
saveSettings();
|
||||
@@ -403,6 +414,7 @@ async function initUI() {
|
||||
renderInfoBox();
|
||||
renderThoughts();
|
||||
renderInventory();
|
||||
renderEquipment();
|
||||
renderQuests();
|
||||
});
|
||||
|
||||
@@ -862,7 +874,7 @@ async function initUI() {
|
||||
if (lastAssistantIndex !== -1) {
|
||||
commitTrackerDataFromPriorMessage(lastAssistantIndex);
|
||||
}
|
||||
await updateRPGData(renderUserStats, renderInfoBox, renderThoughts, renderInventory);
|
||||
await updateRPGData(renderUserStats, renderInfoBox, renderThoughts, renderInventory, renderEquipment);
|
||||
});
|
||||
|
||||
// Strip widget refresh button - same functionality as main refresh button
|
||||
@@ -881,7 +893,7 @@ async function initUI() {
|
||||
if (lastAssistantIndex !== -1) {
|
||||
commitTrackerDataFromPriorMessage(lastAssistantIndex);
|
||||
}
|
||||
await updateRPGData(renderUserStats, renderInfoBox, renderThoughts, renderInventory);
|
||||
await updateRPGData(renderUserStats, renderInfoBox, renderThoughts, renderInventory, renderEquipment);
|
||||
});
|
||||
|
||||
$('#rpg-stat-bar-color-low').on('change', function() {
|
||||
@@ -1121,6 +1133,7 @@ async function initUI() {
|
||||
$('#rpg-toggle-thought-based-expressions').prop('checked', extensionSettings.enableThoughtBasedExpressions === true);
|
||||
$('#rpg-toggle-hide-default-expressions').prop('checked', extensionSettings.hideDefaultExpressionDisplay === true);
|
||||
$('#rpg-toggle-inventory').prop('checked', extensionSettings.showInventory);
|
||||
$('#rpg-toggle-equipment').prop('checked', extensionSettings.showEquipment);
|
||||
$('#rpg-toggle-quests').prop('checked', extensionSettings.showQuests);
|
||||
$('#rpg-toggle-lock-icons').prop('checked', extensionSettings.showLockIcons ?? true);
|
||||
$('#rpg-toggle-thoughts-in-chat').prop('checked', extensionSettings.showThoughtsInChat);
|
||||
@@ -1271,6 +1284,7 @@ async function initUI() {
|
||||
renderInfoBox();
|
||||
renderThoughts();
|
||||
renderInventory();
|
||||
renderEquipment();
|
||||
renderQuests();
|
||||
renderMusicPlayer($musicPlayerContainer[0]);
|
||||
updateDiceDisplay();
|
||||
@@ -1284,6 +1298,7 @@ async function initUI() {
|
||||
setupMobileKeyboardHandling();
|
||||
setupContentEditableScrolling();
|
||||
initInventoryEventListeners();
|
||||
initEquipmentEventListeners();
|
||||
|
||||
// Initialize chapter checkpoint UI
|
||||
initChapterCheckpointUI();
|
||||
|
||||
Reference in New Issue
Block a user