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:
@@ -292,16 +292,18 @@ export function setupDesktopTabs() {
|
||||
const $infoBox = $('#rpg-info-box');
|
||||
const $thoughts = $('#rpg-thoughts');
|
||||
const $inventory = $('#rpg-inventory');
|
||||
const $equipment = $('#rpg-equipment');
|
||||
const $quests = $('#rpg-quests');
|
||||
|
||||
// If no sections exist, nothing to organize
|
||||
if ($userStats.length === 0 && $infoBox.length === 0 && $thoughts.length === 0 && $inventory.length === 0 && $quests.length === 0) {
|
||||
if ($userStats.length === 0 && $infoBox.length === 0 && $thoughts.length === 0 && $inventory.length === 0 && $equipment.length === 0 && $quests.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Build tab navigation dynamically based on enabled settings
|
||||
const tabButtons = [];
|
||||
const hasInventory = $inventory.length > 0 && extensionSettings.showInventory;
|
||||
const hasEquipment = $equipment.length > 0 && extensionSettings.showEquipment;
|
||||
const hasQuests = $quests.length > 0 && extensionSettings.showQuests;
|
||||
|
||||
// Status tab (always present if any status content exists)
|
||||
@@ -322,6 +324,16 @@ export function setupDesktopTabs() {
|
||||
`);
|
||||
}
|
||||
|
||||
// Equipment tab (only if enabled in settings)
|
||||
if (hasEquipment) {
|
||||
tabButtons.push(`
|
||||
<button class="rpg-tab-btn" data-tab="equipment">
|
||||
<i class="fa-solid fa-shield-halved"></i>
|
||||
<span data-i18n-key="equipment.title">Equipment</span>
|
||||
</button>
|
||||
`);
|
||||
}
|
||||
|
||||
// Quests tab (only if enabled in settings)
|
||||
if (hasQuests) {
|
||||
tabButtons.push(`
|
||||
@@ -337,6 +349,7 @@ export function setupDesktopTabs() {
|
||||
// Create tab content containers
|
||||
const $statusTab = $('<div class="rpg-tab-content active" data-tab-content="status"></div>');
|
||||
const $inventoryTab = $('<div class="rpg-tab-content" data-tab-content="inventory"></div>');
|
||||
const $equipmentTab = $('<div class="rpg-tab-content" data-tab-content="equipment"></div>');
|
||||
const $questsTab = $('<div class="rpg-tab-content" data-tab-content="quests"></div>');
|
||||
|
||||
// Move sections into their respective tabs (detach to preserve event handlers)
|
||||
@@ -361,6 +374,11 @@ export function setupDesktopTabs() {
|
||||
// Only show if enabled (will be part of tab structure)
|
||||
if (hasInventory) $inventory.show();
|
||||
}
|
||||
if ($equipment.length > 0) {
|
||||
$equipmentTab.append($equipment.detach());
|
||||
// Only show if enabled (will be part of tab structure)
|
||||
if (hasEquipment) $equipment.show();
|
||||
}
|
||||
if ($quests.length > 0) {
|
||||
$questsTab.append($quests.detach());
|
||||
// Only show if enabled (will be part of tab structure)
|
||||
@@ -378,6 +396,7 @@ export function setupDesktopTabs() {
|
||||
// Always append inventory and quests tabs to preserve the elements
|
||||
// But they'll only show if enabled (via tab button visibility)
|
||||
$tabsContainer.append($inventoryTab);
|
||||
$tabsContainer.append($equipmentTab);
|
||||
$tabsContainer.append($questsTab);
|
||||
|
||||
// Replace content box with tabs container
|
||||
@@ -410,6 +429,7 @@ export function removeDesktopTabs() {
|
||||
const $infoBox = $('#rpg-info-box').detach();
|
||||
const $thoughts = $('#rpg-thoughts').detach();
|
||||
const $inventory = $('#rpg-inventory').detach();
|
||||
const $equipment = $('#rpg-equipment').detach();
|
||||
const $quests = $('#rpg-quests').detach();
|
||||
|
||||
// Remove tabs container
|
||||
@@ -419,16 +439,19 @@ export function removeDesktopTabs() {
|
||||
const $dividerStats = $('#rpg-divider-stats');
|
||||
const $dividerInfo = $('#rpg-divider-info');
|
||||
const $dividerThoughts = $('#rpg-divider-thoughts');
|
||||
const $dividerInventory = $('#rpg-divider-inventory');
|
||||
const $dividerEquipment = $('#rpg-divider-equipment');
|
||||
|
||||
// Restore original sections to content box in correct order
|
||||
const $contentBox = $('.rpg-content-box');
|
||||
|
||||
// Re-insert sections in original order: User Stats, Info Box, Thoughts, Inventory, Quests
|
||||
// Re-insert sections in original order: User Stats, Info Box, Thoughts, Inventory, Equipment, Quests
|
||||
if ($dividerStats.length) {
|
||||
$dividerStats.before($userStats);
|
||||
$dividerInfo.before($infoBox);
|
||||
$dividerThoughts.before($thoughts);
|
||||
$contentBox.append($inventory);
|
||||
$dividerInventory.before($inventory);
|
||||
$dividerEquipment.before($equipment);
|
||||
$contentBox.append($quests);
|
||||
} else {
|
||||
// Fallback if dividers don't exist
|
||||
@@ -436,6 +459,7 @@ export function removeDesktopTabs() {
|
||||
$contentBox.append($infoBox);
|
||||
$contentBox.append($thoughts);
|
||||
$contentBox.append($inventory);
|
||||
$contentBox.append($equipment);
|
||||
$contentBox.append($quests);
|
||||
}
|
||||
|
||||
@@ -447,6 +471,7 @@ export function removeDesktopTabs() {
|
||||
}
|
||||
if (extensionSettings.showCharacterThoughts) $thoughts.show();
|
||||
if (extensionSettings.showInventory) $inventory.show();
|
||||
if (extensionSettings.showEquipment) $equipment.show();
|
||||
if (extensionSettings.showQuests) $quests.show();
|
||||
$('.rpg-divider').show();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user