feat: add weapon type filter (heavy, light, finesse, 2H, bow, crossbow, thrown, caster)
Backend: new weapon_type query parameter on /search/items. Uses skill ID from IntValues[218103840] for melee types (Heavy=44, Light=45, Finesse=46, TwoHanded=41) and name matching for missile sub-types (bow, crossbow, thrown). Caster = ObjectClass 31. Frontend: dropdown appears when "Weapons" radio selected, hidden otherwise. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
35a11d0cf1
commit
9749eafde4
3 changed files with 60 additions and 4 deletions
|
|
@ -2865,6 +2865,10 @@ async def search_items(
|
|||
armor_only: bool = Query(False, description="Show only armor items"),
|
||||
jewelry_only: bool = Query(False, description="Show only jewelry items"),
|
||||
weapon_only: bool = Query(False, description="Show only weapon items"),
|
||||
weapon_type: str = Query(
|
||||
None,
|
||||
description="Weapon sub-type filter: heavy, light, finesse, two_handed, bow, crossbow, thrown, caster",
|
||||
),
|
||||
clothing_only: bool = Query(
|
||||
False, description="Show only clothing items (shirts/pants)"
|
||||
),
|
||||
|
|
@ -3239,9 +3243,30 @@ async def search_items(
|
|||
conditions.append("object_class = 4")
|
||||
elif weapon_only:
|
||||
# Weapons: ObjectClass 1 (MeleeWeapon), 9 (MissileWeapon), 31 (WandStaffOrb)
|
||||
conditions.append(
|
||||
"object_class IN (1, 9, 31)"
|
||||
)
|
||||
if weapon_type:
|
||||
wt = weapon_type.lower()
|
||||
# Skill-based: Heavy=44, Light=45, Finesse=46, TwoHanded=41
|
||||
if wt == 'heavy':
|
||||
conditions.append("(object_class = 1 AND (rd.int_values->>'218103840')::int = 44)")
|
||||
elif wt == 'light':
|
||||
conditions.append("(object_class = 1 AND (rd.int_values->>'218103840')::int = 45)")
|
||||
elif wt == 'finesse':
|
||||
conditions.append("(object_class = 1 AND (rd.int_values->>'218103840')::int = 46)")
|
||||
elif wt == 'two_handed':
|
||||
conditions.append("(object_class = 1 AND (rd.int_values->>'218103840')::int = 41)")
|
||||
# Name-based missile sub-types
|
||||
elif wt == 'bow':
|
||||
conditions.append("(object_class = 9 AND name ILIKE '%bow%' AND name NOT ILIKE '%crossbow%')")
|
||||
elif wt == 'crossbow':
|
||||
conditions.append("(object_class = 9 AND name ILIKE '%crossbow%')")
|
||||
elif wt == 'thrown':
|
||||
conditions.append("(object_class = 9 AND (name ILIKE '%atlatl%' OR name ILIKE '%throwing%' OR name ILIKE '%javelin%' OR name ILIKE '%shuriken%' OR name ILIKE '%dart%' OR name ILIKE '%slingshot%'))")
|
||||
elif wt == 'caster':
|
||||
conditions.append("object_class = 31")
|
||||
else:
|
||||
conditions.append("object_class IN (1, 9, 31)")
|
||||
else:
|
||||
conditions.append("object_class IN (1, 9, 31)")
|
||||
elif clothing_only:
|
||||
# Clothing: ObjectClass 3 (Clothing) - shirts and pants only, exclude cloaks and robes
|
||||
# Focus on underclothes: shirts, pants, breeches, etc.
|
||||
|
|
|
|||
|
|
@ -552,6 +552,20 @@
|
|||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-group" id="weaponTypeGroup" style="display: none;">
|
||||
<label>Weapon Type:</label>
|
||||
<select id="weaponTypeFilter">
|
||||
<option value="">All Weapons</option>
|
||||
<option value="heavy">Heavy Weapons</option>
|
||||
<option value="light">Light Weapons</option>
|
||||
<option value="finesse">Finesse Weapons</option>
|
||||
<option value="two_handed">Two Handed</option>
|
||||
<option value="bow">Bow</option>
|
||||
<option value="crossbow">Crossbow</option>
|
||||
<option value="thrown">Thrown</option>
|
||||
<option value="caster">Wand/Staff/Orb</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label>Slot:</label>
|
||||
<select id="slotFilter">
|
||||
|
|
|
|||
|
|
@ -57,6 +57,17 @@ function initializeEventListeners() {
|
|||
document.getElementById('backToSearch').addEventListener('click', showSearchSection);
|
||||
document.getElementById('runSetAnalysis').addEventListener('click', performSetAnalysis);
|
||||
|
||||
// Show/hide weapon type dropdown when equipment type changes
|
||||
document.querySelectorAll('input[name="equipmentType"]').forEach(radio => {
|
||||
radio.addEventListener('change', (e) => {
|
||||
const weaponGroup = document.getElementById('weaponTypeGroup');
|
||||
weaponGroup.style.display = e.target.value === 'weapon' ? '' : 'none';
|
||||
if (e.target.value !== 'weapon') {
|
||||
document.getElementById('weaponTypeFilter').value = '';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Checkbox visual feedback for cantrips and equipment sets
|
||||
document.querySelectorAll('.checkbox-item input[type="checkbox"]').forEach(checkbox => {
|
||||
checkbox.addEventListener('change', handleCheckboxChange);
|
||||
|
|
@ -168,8 +179,10 @@ function clearAllFields() {
|
|||
// Reset equipment type to armor
|
||||
document.getElementById('armorOnly').checked = true;
|
||||
|
||||
// Reset slot filter
|
||||
// Reset slot filter and weapon type
|
||||
document.getElementById('slotFilter').value = '';
|
||||
document.getElementById('weaponTypeFilter').value = '';
|
||||
document.getElementById('weaponTypeGroup').style.display = 'none';
|
||||
|
||||
// Clear item state checkboxes (not covered by form.reset for standalone checkboxes)
|
||||
['searchBonded', 'searchAttuned', 'searchIsRare'].forEach(id => {
|
||||
|
|
@ -258,6 +271,10 @@ function buildSearchParameters() {
|
|||
params.append('pants_only', 'true');
|
||||
} else if (equipmentType === 'weapon') {
|
||||
params.append('weapon_only', 'true');
|
||||
const weaponType = document.getElementById('weaponTypeFilter')?.value;
|
||||
if (weaponType) {
|
||||
params.append('weapon_type', weaponType);
|
||||
}
|
||||
} else if (equipmentType === 'clothing') {
|
||||
params.append('clothing_only', 'true');
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue