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:
+64
-1
@@ -23,7 +23,7 @@ import { validateStoredInventory, cleanItemString } from '../utils/security.js';
|
||||
import { migrateToV3JSON } from '../utils/jsonMigration.js';
|
||||
|
||||
const extensionName = 'third-party/rpg-companion-sillytavern';
|
||||
const CURRENT_SETTINGS_VERSION = 5;
|
||||
const CURRENT_SETTINGS_VERSION = 7;
|
||||
|
||||
const DEFAULT_USER_STATS = {
|
||||
health: 100,
|
||||
@@ -616,6 +616,69 @@ export function loadSettings() {
|
||||
settingsChanged = true;
|
||||
}
|
||||
|
||||
// Migration to version 6: Add equipment data structure
|
||||
if (currentVersion < 6) {
|
||||
// console.log('[RPG Companion] Migrating settings to version 6 (adding equipment)');
|
||||
if (!extensionSettings.userStats.equipment) {
|
||||
extensionSettings.userStats.equipment = {
|
||||
items: [],
|
||||
slots: {
|
||||
helmet: null,
|
||||
ring1: null,
|
||||
ring2: null,
|
||||
ring3: null,
|
||||
ring4: null,
|
||||
ring5: null,
|
||||
ring6: null,
|
||||
ring7: null,
|
||||
ring8: null,
|
||||
ring9: null,
|
||||
ring10: null,
|
||||
necklace: null,
|
||||
bodyArmor: null,
|
||||
pants: null,
|
||||
shoes: null,
|
||||
gloves: null,
|
||||
accessory1: null,
|
||||
accessory2: null,
|
||||
accessory3: null
|
||||
}
|
||||
};
|
||||
}
|
||||
if (extensionSettings.showEquipment === undefined) {
|
||||
extensionSettings.showEquipment = true;
|
||||
}
|
||||
extensionSettings.settingsVersion = 6;
|
||||
settingsChanged = true;
|
||||
}
|
||||
|
||||
// Migration to version 7: Convert equipment types to generic categories + add item.slot
|
||||
if (currentVersion < 7) {
|
||||
const equipment = extensionSettings.userStats?.equipment;
|
||||
if (equipment) {
|
||||
const typeMap = {
|
||||
ring1: 'ring', ring2: 'ring', ring3: 'ring', ring4: 'ring', ring5: 'ring',
|
||||
ring6: 'ring', ring7: 'ring', ring8: 'ring', ring9: 'ring', ring10: 'ring',
|
||||
accessory1: 'accessory', accessory2: 'accessory', accessory3: 'accessory'
|
||||
};
|
||||
for (const item of equipment.items || []) {
|
||||
if (!item.slot && equipment.slots) {
|
||||
for (const [slotId, itemId] of Object.entries(equipment.slots)) {
|
||||
if (itemId === item.id) {
|
||||
item.slot = slotId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (item.type && typeMap[item.type]) {
|
||||
item.type = typeMap[item.type];
|
||||
}
|
||||
}
|
||||
}
|
||||
extensionSettings.settingsVersion = 7;
|
||||
settingsChanged = true;
|
||||
}
|
||||
|
||||
// Normalize additive settings without introducing another schema bump.
|
||||
if (!extensionSettings.thoughtsInChatStyle) {
|
||||
extensionSettings.thoughtsInChatStyle = 'corner';
|
||||
|
||||
Reference in New Issue
Block a user