Click a slot to toggle it. Dark slots are disabled for this race.
@@ -215,9 +205,15 @@
Races
// ---- Load ----
async function loadRaces() {
- const res = await AdminAPI.get('/admin/api/v1/races');
+ const [res, slotsRes] = await AdminAPI.all([
+ AdminAPI.get('/admin/api/v1/races'),
+ AdminAPI.get('/admin/api/v1/items/equip-slots'),
+ ]);
if (!res.ok) { console.error('Failed to load races:', res.error); return; }
racesData = (res.data && res.data.data) || {};
+ if (slotsRes.ok) {
+ buildSlotsGrid(slotsRes.data.data || []);
+ }
renderList();
DiceRollHelper.attach(document.getElementById('fDiceRoll'));
const hashId = location.hash.slice(1);
@@ -410,6 +406,20 @@
Races
if (type === 'success') setTimeout(() => { bar.className = 'status-bar'; }, 3000);
}
+function buildSlotsGrid(slots) {
+ const grid = document.getElementById('slotsGrid');
+ if (!grid) return;
+ grid.innerHTML = '';
+ for (const slot of slots) {
+ const label = slot.charAt(0).toUpperCase() + slot.slice(1);
+ const lbl = document.createElement('label');
+ lbl.className = 'slot-item';
+ lbl.setAttribute('onclick', 'toggleSlot(this)');
+ lbl.innerHTML = '
' + escHtml(label);
+ grid.appendChild(lbl);
+ }
+}
+
function toggleSlot(label) {
const cb = label.querySelector('.slot-cb');
cb.checked = !cb.checked;
diff --git a/_datafiles/html/admin/users.html b/_datafiles/html/admin/users.html
index 48cc19382..9e411abd1 100644
--- a/_datafiles/html/admin/users.html
+++ b/_datafiles/html/admin/users.html
@@ -449,46 +449,7 @@
User Editor
Equipment
-
-
Weapon
-
nothing Pick… ×
-
-
-
Offhand
-
nothing Pick… ×
-
-
-
-
-
-
-
Gloves
-
nothing Pick… ×
-
-
-
-
+
Inventory
@@ -576,12 +537,13 @@
User Editor
];
async function init() {
- const [racesRes, buffsRes, itemsRes, questsRes, petsRes] = await AdminAPI.all([
+ const [racesRes, buffsRes, itemsRes, questsRes, petsRes, slotsRes] = await AdminAPI.all([
AdminAPI.get('/admin/api/v1/races'),
AdminAPI.get('/admin/api/v1/buffs'),
AdminAPI.get('/admin/api/v1/items'),
AdminAPI.get('/admin/api/v1/quests'),
AdminAPI.get('/admin/api/v1/pets'),
+ AdminAPI.get('/admin/api/v1/items/equip-slots'),
]);
if (racesRes.ok) {
@@ -602,6 +564,10 @@
User Editor
if (petsRes.ok) {
allPetTypes = petsRes.data.data || {};
}
+ if (slotsRes.ok) {
+ EQ_SLOTS = slotsRes.data.data || [];
+ }
+ buildEquipSlotsGrid();
buildSkillsGrid();
const hashId = parseInt(location.hash.slice(1), 10);
if (hashId) loadUser(hashId);
@@ -724,16 +690,10 @@
User Editor
// Equipment
const eq = ch.Equipment || {};
- setEquipSlot('f-eq-weapon', eqItemId(eq.Weapon));
- setEquipSlot('f-eq-offhand', eqItemId(eq.Offhand));
- setEquipSlot('f-eq-head', eqItemId(eq.Head));
- setEquipSlot('f-eq-neck', eqItemId(eq.Neck));
- setEquipSlot('f-eq-body', eqItemId(eq.Body));
- setEquipSlot('f-eq-belt', eqItemId(eq.Belt));
- setEquipSlot('f-eq-gloves', eqItemId(eq.Gloves));
- setEquipSlot('f-eq-ring', eqItemId(eq.Ring));
- setEquipSlot('f-eq-legs', eqItemId(eq.Legs));
- setEquipSlot('f-eq-feet', eqItemId(eq.Feet));
+ for (const slot of EQ_SLOTS) {
+ const key = slot.charAt(0).toUpperCase() + slot.slice(1);
+ setEquipSlot('f-eq-' + slot, eqItemId(eq[key]));
+ }
// Inventory
renderItemRows(ch.Items || []);
@@ -770,7 +730,28 @@
User Editor
// Equipment slots
// -------------------------------------------------------------------------
- const EQ_SLOTS = ['weapon','offhand','head','neck','body','belt','gloves','ring','legs','feet'];
+ let EQ_SLOTS = [];
+
+ function buildEquipSlotsGrid() {
+ const grid = document.getElementById('equip-slots-grid');
+ if (!grid) return;
+ grid.innerHTML = '';
+ grid.style.display = 'contents';
+ for (const slot of EQ_SLOTS) {
+ const label = slot.charAt(0).toUpperCase() + slot.slice(1);
+ const id = 'f-eq-' + slot;
+ const field = document.createElement('div');
+ field.className = 'field';
+ field.innerHTML =
+ '
' + label + ' ' +
+ '
' +
+ 'nothing ' +
+ 'Pick… ' +
+ '\u00d7 ' +
+ '
';
+ grid.appendChild(field);
+ }
+ }
function applyRaceEquipDisabled(raceId) {
const race = allRaces[String(raceId)];
@@ -1228,18 +1209,14 @@
User Editor
Perception: { Training: parseInt(document.getElementById('f-stat-perception').value, 10) || 0 },
},
Skills: collectSkills(),
- Equipment: {
- Weapon: eqSlot('f-eq-weapon'),
- Offhand: eqSlot('f-eq-offhand'),
- Head: eqSlot('f-eq-head'),
- Neck: eqSlot('f-eq-neck'),
- Body: eqSlot('f-eq-body'),
- Belt: eqSlot('f-eq-belt'),
- Gloves: eqSlot('f-eq-gloves'),
- Ring: eqSlot('f-eq-ring'),
- Legs: eqSlot('f-eq-legs'),
- Feet: eqSlot('f-eq-feet'),
- },
+ Equipment: (function () {
+ const eq = {};
+ for (const slot of EQ_SLOTS) {
+ const key = slot.charAt(0).toUpperCase() + slot.slice(1);
+ eq[key] = eqSlot('f-eq-' + slot);
+ }
+ return eq;
+ }()),
Items: collectItems(),
Shop: collectShop(),
SpellBook: collectSpellBook(),
diff --git a/_datafiles/html/public/static/js/windows/window-gear.js b/_datafiles/html/public/static/js/windows/window-gear.js
index ac1a79050..295ff6b5b 100644
--- a/_datafiles/html/public/static/js/windows/window-gear.js
+++ b/_datafiles/html/public/static/js/windows/window-gear.js
@@ -313,22 +313,6 @@
}
`);
- // -----------------------------------------------------------------------
- // Data
- // -----------------------------------------------------------------------
- const EQUIP_SLOTS = [
- { key: 'head', label: 'Head' },
- { key: 'neck', label: 'Neck' },
- { key: 'body', label: 'Body' },
- { key: 'weapon', label: 'Weapon' },
- { key: 'offhand', label: 'Offhand' },
- { key: 'gloves', label: 'Gloves' },
- { key: 'belt', label: 'Belt' },
- { key: 'ring', label: 'Ring' },
- { key: 'legs', label: 'Legs' },
- { key: 'feet', label: 'Feet' },
- ];
-
// -----------------------------------------------------------------------
// Tooltip
// -----------------------------------------------------------------------
@@ -499,16 +483,6 @@
// -----------------------------------------------------------------------
// DOM factory
// -----------------------------------------------------------------------
- function buildEquipRows() {
- return EQUIP_SLOTS.map(s =>
- '
' +
- '' + s.label + ' ' +
- 'empty ' +
- ' ' +
- '
'
- ).join('');
- }
-
function createDOM() {
const el = document.createElement('div');
el.id = 'gear-window';
@@ -517,32 +491,17 @@
'
Worn ' +
'
Backpack ' +
'
' +
-
- '