add attunement requirements tooltip that shows when hovering over 'Special' attunement badge

This commit is contained in:
Thomas 2026-01-24 23:45:38 -05:00
parent 791f8aff8b
commit b32b317be2
2 changed files with 41 additions and 23 deletions

20
app.js
View File

@ -30,6 +30,9 @@ const FACTIONS = {
const MAGIC_ITEM_ATTUNEMENT_MAP = typeof MAGIC_ITEMS_DATA !== 'undefined' const MAGIC_ITEM_ATTUNEMENT_MAP = typeof MAGIC_ITEMS_DATA !== 'undefined'
? new Map(MAGIC_ITEMS_DATA.map(item => [item.name, item.attunementRequired])) ? new Map(MAGIC_ITEMS_DATA.map(item => [item.name, item.attunementRequired]))
: new Map(); : new Map();
const MAGIC_ITEM_ATTUNEMENT_NOTE_MAP = typeof MAGIC_ITEMS_DATA !== 'undefined'
? new Map(MAGIC_ITEMS_DATA.map(item => [item.name, item.attunementNote]).filter(([, note]) => note))
: new Map();
const DNDBEYOND_MAGIC_ITEM_BASE_URL = "https://dndbeyond.com/magic-items/"; const DNDBEYOND_MAGIC_ITEM_BASE_URL = "https://dndbeyond.com/magic-items/";
const MAGIC_ITEM_PAGE_MAP = typeof MAGIC_ITEMS_DATA !== 'undefined' const MAGIC_ITEM_PAGE_MAP = typeof MAGIC_ITEMS_DATA !== 'undefined'
? new Map(MAGIC_ITEMS_DATA.map(item => [item.name, item.dndbeyondPage]).filter(([, page]) => page)) ? new Map(MAGIC_ITEMS_DATA.map(item => [item.name, item.dndbeyondPage]).filter(([, page]) => page))
@ -448,6 +451,9 @@ function renderMarket(marketData, reputationData) {
: normalizedAttunement === 'special' : normalizedAttunement === 'special'
? 'Special' ? 'Special'
: 'No'; : 'No';
const attunementNote = item.attunementNote
|| MAGIC_ITEM_ATTUNEMENT_NOTE_MAP.get(item.name)
|| null;
const dndbeyondPage = item.dndbeyondPage const dndbeyondPage = item.dndbeyondPage
|| MAGIC_ITEM_PAGE_MAP.get(item.name) || MAGIC_ITEM_PAGE_MAP.get(item.name)
|| null; || null;
@ -461,6 +467,7 @@ function renderMarket(marketData, reputationData) {
adjustedPrice, adjustedPrice,
reputation, reputation,
attunementRequired: attunementDisplay, attunementRequired: attunementDisplay,
attunementNote,
dndbeyondUrl dndbeyondUrl
}); });
} }
@ -530,6 +537,9 @@ function renderMarket(marketData, reputationData) {
: attunementRequired === 'Special' : attunementRequired === 'Special'
? 'attunement-special' ? 'attunement-special'
: 'attunement-no'; : 'attunement-no';
const attunementTitle = attunementRequired === 'Special' && item.attunementNote
? ` title="${escapeAttribute(item.attunementNote)}"`
: '';
const nameDisplay = item.dndbeyondUrl const nameDisplay = item.dndbeyondUrl
? `<a class="item-link" href="${item.dndbeyondUrl}" target="_blank" rel="noopener">${item.name}</a>` ? `<a class="item-link" href="${item.dndbeyondUrl}" target="_blank" rel="noopener">${item.name}</a>`
@ -548,7 +558,7 @@ function renderMarket(marketData, reputationData) {
</td> </td>
<td class="item-cost-cell">${priceDisplay}</td> <td class="item-cost-cell">${priceDisplay}</td>
<td class="item-attunement-cell"> <td class="item-attunement-cell">
<span class="attunement-badge ${attunementClass}">${attunementRequired}</span> <span class="attunement-badge ${attunementClass}"${attunementTitle}>${attunementRequired}</span>
</td> </td>
</tr> </tr>
`; `;
@ -633,6 +643,14 @@ function getSortIndicator(column) {
return currentSort.direction === 'asc' ? '↑' : '↓'; return currentSort.direction === 'asc' ? '↑' : '↓';
} }
function escapeAttribute(value) {
return String(value)
.replace(/&/g, '&amp;')
.replace(/\"/g, '&quot;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
}
// ===== END MAGIC ITEM MARKET SYSTEM ===== // ===== END MAGIC ITEM MARKET SYSTEM =====
function getNextQuestForFaction(faction, currentIndex) { function getNextQuestForFaction(faction, currentIndex) {

View File

@ -12,7 +12,7 @@ const MAGIC_ITEMS_DATA = [
{ id: "item_009", name: "Amulet of Proof against Detection and Location", rarity: "Uncommon", faction: "Kundarak", baseCost: 400, attunementRequired: "Required" , dndbeyondPage: "4569-amulet-of-proof-against-detection-and-location" }, { id: "item_009", name: "Amulet of Proof against Detection and Location", rarity: "Uncommon", faction: "Kundarak", baseCost: 400, attunementRequired: "Required" , dndbeyondPage: "4569-amulet-of-proof-against-detection-and-location" },
{ id: "item_010", name: "Amulet of the Planes", rarity: "Very Rare", faction: "Morgrave", baseCost: 43000, attunementRequired: "Required" , dndbeyondPage: "9228345-amulet-of-the-planes" }, { id: "item_010", name: "Amulet of the Planes", rarity: "Very Rare", faction: "Morgrave", baseCost: 43000, attunementRequired: "Required" , dndbeyondPage: "9228345-amulet-of-the-planes" },
{ id: "item_011", name: "Animated Shield", rarity: "Very Rare", faction: "Deneith", baseCost: 6000, attunementRequired: "Required" , dndbeyondPage: "4571-animated-shield" }, { id: "item_011", name: "Animated Shield", rarity: "Very Rare", faction: "Deneith", baseCost: 6000, attunementRequired: "Required" , dndbeyondPage: "4571-animated-shield" },
{ id: "item_012", name: "Arcane Propulsion Arm", rarity: "Very Rare", faction: "Deneith", baseCost: 5100, attunementRequired: "Special" , dndbeyondPage: "976932-arcane-propulsion-arm" }, { id: "item_012", name: "Arcane Propulsion Arm", rarity: "Very Rare", faction: "Deneith", baseCost: 5100, attunementRequired: "Special" , dndbeyondPage: "976932-arcane-propulsion-arm" , attunementNote: "Requires Attunement by a Creature Missing a Hand or an Arm" },
{ id: "item_013", name: "Armor of Resistance", rarity: "Rare", faction: "Kundarak", baseCost: 3000, attunementRequired: "Required" , dndbeyondPage: "5371-armor-of-resistance" }, { id: "item_013", name: "Armor of Resistance", rarity: "Rare", faction: "Kundarak", baseCost: 3000, attunementRequired: "Required" , dndbeyondPage: "5371-armor-of-resistance" },
{ id: "item_014", name: "Armor of Safeguarding", rarity: "Very Rare", faction: "Deneith", baseCost: 10000, attunementRequired: "Required" , dndbeyondPage: "7102410-armor-of-safeguarding" }, { id: "item_014", name: "Armor of Safeguarding", rarity: "Very Rare", faction: "Deneith", baseCost: 10000, attunementRequired: "Required" , dndbeyondPage: "7102410-armor-of-safeguarding" },
{ id: "item_015", name: "Armor of the White Rose", rarity: "Very Rare", faction: "Ashbound", baseCost: 7000, attunementRequired: "No" , dndbeyondPage: "8806813-armor-of-the-white-rose" }, { id: "item_015", name: "Armor of the White Rose", rarity: "Very Rare", faction: "Ashbound", baseCost: 7000, attunementRequired: "No" , dndbeyondPage: "8806813-armor-of-the-white-rose" },
@ -46,7 +46,7 @@ const MAGIC_ITEMS_DATA = [
{ id: "item_043", name: "Cap of Water Breathing", rarity: "Uncommon", faction: "Ashbound", baseCost: 450, attunementRequired: "No" , dndbeyondPage: "9228375-cap-of-water-breathing" }, { id: "item_043", name: "Cap of Water Breathing", rarity: "Uncommon", faction: "Ashbound", baseCost: 450, attunementRequired: "No" , dndbeyondPage: "9228375-cap-of-water-breathing" },
{ id: "item_044", name: "Cape of the Mountebank", rarity: "Rare", faction: "Thuranni", baseCost: 3900, attunementRequired: "No" , dndbeyondPage: "9228376-cape-of-the-mountebank" }, { id: "item_044", name: "Cape of the Mountebank", rarity: "Rare", faction: "Thuranni", baseCost: 3900, attunementRequired: "No" , dndbeyondPage: "9228376-cape-of-the-mountebank" },
{ id: "item_045", name: "Carpet of Flying", rarity: "Very Rare", faction: "Morgrave", baseCost: 44000, attunementRequired: "No" , dndbeyondPage: "9228381-carpet-of-flying" }, { id: "item_045", name: "Carpet of Flying", rarity: "Very Rare", faction: "Morgrave", baseCost: 44000, attunementRequired: "No" , dndbeyondPage: "9228381-carpet-of-flying" },
{ id: "item_046", name: "Cauldron of Rebirth", rarity: "Very Rare", faction: "Ashbound", baseCost: 10000, attunementRequired: "Special" , dndbeyondPage: "9228395-cauldron-of-rebirth" }, { id: "item_046", name: "Cauldron of Rebirth", rarity: "Very Rare", faction: "Ashbound", baseCost: 10000, attunementRequired: "Special" , dndbeyondPage: "9228395-cauldron-of-rebirth" , attunementNote: "Requires Attunement by a Druid or Warlock" },
{ id: "item_047", name: "Censer of Controlling Air Elementals", rarity: "Rare", faction: "Ashbound", baseCost: 4700, attunementRequired: "No" , dndbeyondPage: "9228396-censer-of-controlling-air-elementals" }, { id: "item_047", name: "Censer of Controlling Air Elementals", rarity: "Rare", faction: "Ashbound", baseCost: 4700, attunementRequired: "No" , dndbeyondPage: "9228396-censer-of-controlling-air-elementals" },
{ id: "item_048", name: "Chime of Opening", rarity: "Rare", faction: "Tarkanan", baseCost: 3000, attunementRequired: "No" , dndbeyondPage: "9228405-chime-of-opening" }, { id: "item_048", name: "Chime of Opening", rarity: "Rare", faction: "Tarkanan", baseCost: 3000, attunementRequired: "No" , dndbeyondPage: "9228405-chime-of-opening" },
{ id: "item_049", name: "Circlet of Blasting", rarity: "Uncommon", faction: "Morgrave", baseCost: 350, attunementRequired: "No" , dndbeyondPage: "4603-circlet-of-blasting" }, { id: "item_049", name: "Circlet of Blasting", rarity: "Uncommon", faction: "Morgrave", baseCost: 350, attunementRequired: "No" , dndbeyondPage: "4603-circlet-of-blasting" },
@ -78,7 +78,7 @@ const MAGIC_ITEMS_DATA = [
{ id: "item_075", name: "Dust of Dryness", rarity: "Uncommon", faction: "Ashbound", baseCost: 350, attunementRequired: "No" , dndbeyondPage: "9228523-dust-of-dryness" }, { id: "item_075", name: "Dust of Dryness", rarity: "Uncommon", faction: "Ashbound", baseCost: 350, attunementRequired: "No" , dndbeyondPage: "9228523-dust-of-dryness" },
{ id: "item_076", name: "Dust of Sneezing and Choking", rarity: "Uncommon", faction: "Thuranni", baseCost: 150, attunementRequired: "No" , dndbeyondPage: "9228524-dust-of-sneezing-and-choking" }, { id: "item_076", name: "Dust of Sneezing and Choking", rarity: "Uncommon", faction: "Thuranni", baseCost: 150, attunementRequired: "No" , dndbeyondPage: "9228524-dust-of-sneezing-and-choking" },
{ id: "item_077", name: "Dwarven Plate", rarity: "Very Rare", faction: "Kundarak", baseCost: 25000, attunementRequired: "No" , dndbeyondPage: "9228527-dwarven-plate" }, { id: "item_077", name: "Dwarven Plate", rarity: "Very Rare", faction: "Kundarak", baseCost: 25000, attunementRequired: "No" , dndbeyondPage: "9228527-dwarven-plate" },
{ id: "item_078", name: "Dwarven Thrower", rarity: "Very Rare", faction: "Kundarak", baseCost: 25000, attunementRequired: "Special" , dndbeyondPage: "4627-dwarven-thrower" }, { id: "item_078", name: "Dwarven Thrower", rarity: "Very Rare", faction: "Kundarak", baseCost: 25000, attunementRequired: "Special" , dndbeyondPage: "4627-dwarven-thrower" , attunementNote: "Requires Attunement by a Dwarf or a Creature Attuned to a Belt of Dwarvenkind" },
{ id: "item_079", name: "Dyrrn's Tentacle Whip", rarity: "Very Rare", faction: "Kundarak", baseCost: 17000, attunementRequired: "Required" , dndbeyondPage: "1000370-dyrrns-tentacle-whip" }, { id: "item_079", name: "Dyrrn's Tentacle Whip", rarity: "Very Rare", faction: "Kundarak", baseCost: 17000, attunementRequired: "Required" , dndbeyondPage: "1000370-dyrrns-tentacle-whip" },
{ id: "item_080", name: "Earworm", rarity: "Uncommon", faction: "Kundarak", baseCost: 225, attunementRequired: "Required" , dndbeyondPage: "1000466-earworm" }, { id: "item_080", name: "Earworm", rarity: "Uncommon", faction: "Kundarak", baseCost: 225, attunementRequired: "Required" , dndbeyondPage: "1000466-earworm" },
{ id: "item_081", name: "Efreeti Bottle", rarity: "Very Rare", faction: "Morgrave", baseCost: 45000, attunementRequired: "No" , dndbeyondPage: "9228528-efreeti-bottle" }, { id: "item_081", name: "Efreeti Bottle", rarity: "Very Rare", faction: "Morgrave", baseCost: 45000, attunementRequired: "No" , dndbeyondPage: "9228528-efreeti-bottle" },
@ -99,7 +99,7 @@ const MAGIC_ITEMS_DATA = [
{ id: "item_096", name: "Figurine of Wondrous Power (onyx dog)", rarity: "Rare", faction: "Ashbound", baseCost: 3200, attunementRequired: "No" , dndbeyondPage: "9228621-figurine-of-wondrous-power" }, { id: "item_096", name: "Figurine of Wondrous Power (onyx dog)", rarity: "Rare", faction: "Ashbound", baseCost: 3200, attunementRequired: "No" , dndbeyondPage: "9228621-figurine-of-wondrous-power" },
{ id: "item_097", name: "Figurine of Wondrous Power (serpentine owl)", rarity: "Rare", faction: "Ashbound", baseCost: 3000, attunementRequired: "No" , dndbeyondPage: "9228621-figurine-of-wondrous-power" }, { id: "item_097", name: "Figurine of Wondrous Power (serpentine owl)", rarity: "Rare", faction: "Ashbound", baseCost: 3000, attunementRequired: "No" , dndbeyondPage: "9228621-figurine-of-wondrous-power" },
{ id: "item_098", name: "Figurine of Wondrous Power (silver raven)", rarity: "Uncommon", faction: "Medani", baseCost: 380, attunementRequired: "No" , dndbeyondPage: "9228621-figurine-of-wondrous-power" }, { id: "item_098", name: "Figurine of Wondrous Power (silver raven)", rarity: "Uncommon", faction: "Medani", baseCost: 380, attunementRequired: "No" , dndbeyondPage: "9228621-figurine-of-wondrous-power" },
{ id: "item_099", name: "Finder's Goggles", rarity: "Uncommon", faction: "Tharashk", baseCost: 500, attunementRequired: "Special" , dndbeyondPage: "977633-finders-goggles" }, { id: "item_099", name: "Finder's Goggles", rarity: "Uncommon", faction: "Tharashk", baseCost: 500, attunementRequired: "Special" , dndbeyondPage: "977633-finders-goggles" , attunementNote: "Requires Attunement by a Creature with the Mark of Finding" },
{ id: "item_100", name: "Flame Tongue", rarity: "Rare", faction: "Deneith", baseCost: 5000, attunementRequired: "Required" , dndbeyondPage: "9228647-flame-tongue" }, { id: "item_100", name: "Flame Tongue", rarity: "Rare", faction: "Deneith", baseCost: 5000, attunementRequired: "Required" , dndbeyondPage: "9228647-flame-tongue" },
{ id: "item_101", name: "Folding Boat", rarity: "Rare", faction: "Tharashk", baseCost: 4750, attunementRequired: "No" , dndbeyondPage: "9228649-folding-boat" }, { id: "item_101", name: "Folding Boat", rarity: "Rare", faction: "Tharashk", baseCost: 4750, attunementRequired: "No" , dndbeyondPage: "9228649-folding-boat" },
{ id: "item_102", name: "Frost Brand", rarity: "Very Rare", faction: "Deneith", baseCost: 11000, attunementRequired: "Required" , dndbeyondPage: "9228651-frost-brand" }, { id: "item_102", name: "Frost Brand", rarity: "Very Rare", faction: "Deneith", baseCost: 11000, attunementRequired: "Required" , dndbeyondPage: "9228651-frost-brand" },
@ -169,10 +169,10 @@ const MAGIC_ITEMS_DATA = [
{ id: "item_166", name: "Mindguard Crown", rarity: "Very Rare", faction: "Deneith", baseCost: 11000, attunementRequired: "Required" , dndbeyondPage: "7247083-mindguard-crown" }, { id: "item_166", name: "Mindguard Crown", rarity: "Very Rare", faction: "Deneith", baseCost: 11000, attunementRequired: "Required" , dndbeyondPage: "7247083-mindguard-crown" },
{ id: "item_167", name: "Mirror of Life Trapping", rarity: "Very Rare", faction: "Tharashk", baseCost: 50000, attunementRequired: "No" , dndbeyondPage: "9228851-mirror-of-life-trapping" }, { id: "item_167", name: "Mirror of Life Trapping", rarity: "Very Rare", faction: "Tharashk", baseCost: 50000, attunementRequired: "No" , dndbeyondPage: "9228851-mirror-of-life-trapping" },
{ id: "item_168", name: "Mithral Armor", rarity: "Uncommon", faction: "Kundarak", baseCost: 450, attunementRequired: "No" , dndbeyondPage: "5381-mithral-armor" }, { id: "item_168", name: "Mithral Armor", rarity: "Uncommon", faction: "Kundarak", baseCost: 450, attunementRequired: "No" , dndbeyondPage: "5381-mithral-armor" },
{ id: "item_169", name: "Nature's Mantle", rarity: "Uncommon", faction: "Ashbound", baseCost: 325, attunementRequired: "Special" , dndbeyondPage: "2405507-natures-mantle" }, { id: "item_169", name: "Nature's Mantle", rarity: "Uncommon", faction: "Ashbound", baseCost: 325, attunementRequired: "Special" , dndbeyondPage: "2405507-natures-mantle" , attunementNote: "Requires Attunement by a Druid or Ranger" },
{ id: "item_170", name: "Necklace of Adaptation", rarity: "Uncommon", faction: "Ashbound", baseCost: 450, attunementRequired: "Required" , dndbeyondPage: "4682-necklace-of-adaptation" }, { id: "item_170", name: "Necklace of Adaptation", rarity: "Uncommon", faction: "Ashbound", baseCost: 450, attunementRequired: "Required" , dndbeyondPage: "4682-necklace-of-adaptation" },
{ id: "item_171", name: "Necklace of Fireballs", rarity: "Rare", faction: "Deneith", baseCost: 4350, attunementRequired: "No" , dndbeyondPage: "9228861-necklace-of-fireballs" }, { id: "item_171", name: "Necklace of Fireballs", rarity: "Rare", faction: "Deneith", baseCost: 4350, attunementRequired: "No" , dndbeyondPage: "9228861-necklace-of-fireballs" },
{ id: "item_172", name: "Necklace of Prayer Beads", rarity: "Rare", faction: "Morgrave", baseCost: 5000, attunementRequired: "Special" , dndbeyondPage: "9228862-necklace-of-prayer-beads" }, { id: "item_172", name: "Necklace of Prayer Beads", rarity: "Rare", faction: "Morgrave", baseCost: 5000, attunementRequired: "Special" , dndbeyondPage: "9228862-necklace-of-prayer-beads" , attunementNote: "Requires Attunement by a Cleric, Druid, or Paladin" },
{ id: "item_173", name: "Nimbus Coronet", rarity: "Very Rare", faction: "Tharashk", baseCost: 10500, attunementRequired: "Required" , dndbeyondPage: "7102429-nimbus-coronet" }, { id: "item_173", name: "Nimbus Coronet", rarity: "Very Rare", faction: "Tharashk", baseCost: 10500, attunementRequired: "Required" , dndbeyondPage: "7102429-nimbus-coronet" },
{ id: "item_174", name: "Nine Lives Stealer", rarity: "Very Rare", faction: "Thuranni", baseCost: 36000, attunementRequired: "Required" , dndbeyondPage: "5394-nine-lives-stealer" }, { id: "item_174", name: "Nine Lives Stealer", rarity: "Very Rare", faction: "Thuranni", baseCost: 36000, attunementRequired: "Required" , dndbeyondPage: "5394-nine-lives-stealer" },
{ id: "item_175", name: "Nolzur's Marvelous Pigments", rarity: "Very Rare", faction: "Morgrave", baseCost: 16000, attunementRequired: "No" , dndbeyondPage: "9228905-nolzurs-marvelous-pigments" }, { id: "item_175", name: "Nolzur's Marvelous Pigments", rarity: "Very Rare", faction: "Morgrave", baseCost: 16000, attunementRequired: "No" , dndbeyondPage: "9228905-nolzurs-marvelous-pigments" },
@ -181,7 +181,7 @@ const MAGIC_ITEMS_DATA = [
{ id: "item_178", name: "Oil of Sharpness", rarity: "Very Rare", faction: "Thuranni", baseCost: 2200, attunementRequired: "No" , dndbeyondPage: "9228908-oil-of-sharpness" }, { id: "item_178", name: "Oil of Sharpness", rarity: "Very Rare", faction: "Thuranni", baseCost: 2200, attunementRequired: "No" , dndbeyondPage: "9228908-oil-of-sharpness" },
{ id: "item_179", name: "Oil of Slipperiness", rarity: "Uncommon", faction: "Tarkanan", baseCost: 250, attunementRequired: "No" , dndbeyondPage: "9228909-oil-of-slipperiness" }, { id: "item_179", name: "Oil of Slipperiness", rarity: "Uncommon", faction: "Tarkanan", baseCost: 250, attunementRequired: "No" , dndbeyondPage: "9228909-oil-of-slipperiness" },
{ id: "item_180", name: "Pariah's Shield", rarity: "Rare", faction: "Deneith", baseCost: 1500, attunementRequired: "Required" , dndbeyondPage: "316763-pariahs-shield" }, { id: "item_180", name: "Pariah's Shield", rarity: "Rare", faction: "Deneith", baseCost: 1500, attunementRequired: "Required" , dndbeyondPage: "316763-pariahs-shield" },
{ id: "item_181", name: "Pearl of Power", rarity: "Uncommon", faction: "Morgrave", baseCost: 400, attunementRequired: "Special" , dndbeyondPage: "9228918-pearl-of-power" }, { id: "item_181", name: "Pearl of Power", rarity: "Uncommon", faction: "Morgrave", baseCost: 400, attunementRequired: "Special" , dndbeyondPage: "9228918-pearl-of-power" , attunementNote: "Requires Attunement by a Spellcaster" },
{ id: "item_182", name: "Periapt of Health", rarity: "Uncommon", faction: "Morgrave", baseCost: 250, attunementRequired: "Required" , dndbeyondPage: "9228920-periapt-of-health" }, { id: "item_182", name: "Periapt of Health", rarity: "Uncommon", faction: "Morgrave", baseCost: 250, attunementRequired: "Required" , dndbeyondPage: "9228920-periapt-of-health" },
{ id: "item_183", name: "Periapt of Proof against Poison", rarity: "Rare", faction: "Kundarak", baseCost: 4700, attunementRequired: "Required" , dndbeyondPage: "9276658-periapt-of-proof-against-poison" }, { id: "item_183", name: "Periapt of Proof against Poison", rarity: "Rare", faction: "Kundarak", baseCost: 4700, attunementRequired: "Required" , dndbeyondPage: "9276658-periapt-of-proof-against-poison" },
{ id: "item_184", name: "Periapt of Wound Closure", rarity: "Uncommon", faction: "Morgrave", baseCost: 375, attunementRequired: "Required" , dndbeyondPage: "9228921-periapt-of-wound-closure" }, { id: "item_184", name: "Periapt of Wound Closure", rarity: "Uncommon", faction: "Morgrave", baseCost: 375, attunementRequired: "Required" , dndbeyondPage: "9228921-periapt-of-wound-closure" },
@ -220,7 +220,7 @@ const MAGIC_ITEMS_DATA = [
{ id: "item_217", name: "Repeating Shot", rarity: "Uncommon", faction: "Tarkanan", baseCost: 550, attunementRequired: "Required" , dndbeyondPage: "10886055-repeating-shot" }, { id: "item_217", name: "Repeating Shot", rarity: "Uncommon", faction: "Tarkanan", baseCost: 550, attunementRequired: "Required" , dndbeyondPage: "10886055-repeating-shot" },
{ id: "item_218", name: "Repulsion Shield", rarity: "Uncommon", faction: "Deneith", baseCost: 600, attunementRequired: "No" , dndbeyondPage: "10886056-repulsion-shield" }, { id: "item_218", name: "Repulsion Shield", rarity: "Uncommon", faction: "Deneith", baseCost: 600, attunementRequired: "No" , dndbeyondPage: "10886056-repulsion-shield" },
{ id: "item_219", name: "Returning Weapon", rarity: "Uncommon", faction: "Medani", baseCost: 550, attunementRequired: "No" , dndbeyondPage: "10886064-returning-weapon" }, { id: "item_219", name: "Returning Weapon", rarity: "Uncommon", faction: "Medani", baseCost: 550, attunementRequired: "No" , dndbeyondPage: "10886064-returning-weapon" },
{ id: "item_220", name: "Reveler's Concertina", rarity: "Rare", faction: "Thuranni", baseCost: 4250, attunementRequired: "Special" , dndbeyondPage: "2405691-revelers-concertina" }, { id: "item_220", name: "Reveler's Concertina", rarity: "Rare", faction: "Thuranni", baseCost: 4250, attunementRequired: "Special" , dndbeyondPage: "2405691-revelers-concertina" , attunementNote: "Requires Attunement by a Bard" },
{ id: "item_221", name: "Ring of Animal Influence", rarity: "Rare", faction: "Ashbound", baseCost: 1000, attunementRequired: "No" , dndbeyondPage: "9228958-ring-of-animal-influence" }, { id: "item_221", name: "Ring of Animal Influence", rarity: "Rare", faction: "Ashbound", baseCost: 1000, attunementRequired: "No" , dndbeyondPage: "9228958-ring-of-animal-influence" },
{ id: "item_222", name: "Ring of Evasion", rarity: "Rare", faction: "Thuranni", baseCost: 4900, attunementRequired: "Required" , dndbeyondPage: "4720-ring-of-evasion" }, { id: "item_222", name: "Ring of Evasion", rarity: "Rare", faction: "Thuranni", baseCost: 4900, attunementRequired: "Required" , dndbeyondPage: "4720-ring-of-evasion" },
{ id: "item_223", name: "Ring of Feather Falling", rarity: "Rare", faction: "Tarkanan", baseCost: 2200, attunementRequired: "Required" , dndbeyondPage: "4721-ring-of-feather-falling" }, { id: "item_223", name: "Ring of Feather Falling", rarity: "Rare", faction: "Tarkanan", baseCost: 2200, attunementRequired: "Required" , dndbeyondPage: "4721-ring-of-feather-falling" },
@ -245,7 +245,7 @@ const MAGIC_ITEMS_DATA = [
{ id: "item_242", name: "Robe of Useful Items", rarity: "Uncommon", faction: "Morgrave", baseCost: 400, attunementRequired: "No" , dndbeyondPage: "9228979-robe-of-useful-items" }, { id: "item_242", name: "Robe of Useful Items", rarity: "Uncommon", faction: "Morgrave", baseCost: 400, attunementRequired: "No" , dndbeyondPage: "9228979-robe-of-useful-items" },
{ id: "item_243", name: "Rod of Absorption", rarity: "Very Rare", faction: "Morgrave", baseCost: 48000, attunementRequired: "Required" , dndbeyondPage: "4744-rod-of-absorption" }, { id: "item_243", name: "Rod of Absorption", rarity: "Very Rare", faction: "Morgrave", baseCost: 48000, attunementRequired: "Required" , dndbeyondPage: "4744-rod-of-absorption" },
{ id: "item_244", name: "Rod of Alertness", rarity: "Very Rare", faction: "Kundarak", baseCost: 11000, attunementRequired: "Required" , dndbeyondPage: "9228980-rod-of-alertness" }, { id: "item_244", name: "Rod of Alertness", rarity: "Very Rare", faction: "Kundarak", baseCost: 11000, attunementRequired: "Required" , dndbeyondPage: "9228980-rod-of-alertness" },
{ id: "item_245", name: "Rod of Hellish Flames", rarity: "Very Rare", faction: "Ashbound", baseCost: 10250, attunementRequired: "Special" , dndbeyondPage: "7526749-rod-of-hellish-flames" }, { id: "item_245", name: "Rod of Hellish Flames", rarity: "Very Rare", faction: "Ashbound", baseCost: 10250, attunementRequired: "Special" , dndbeyondPage: "7526749-rod-of-hellish-flames" , attunementNote: "Requires Attunement by a Spellcaster" },
{ id: "item_246", name: "Rod of Rulership", rarity: "Rare", faction: "Tarkanan", baseCost: 3600, attunementRequired: "Required" , dndbeyondPage: "9228982-rod-of-rulership" }, { id: "item_246", name: "Rod of Rulership", rarity: "Rare", faction: "Tarkanan", baseCost: 3600, attunementRequired: "Required" , dndbeyondPage: "9228982-rod-of-rulership" },
{ id: "item_247", name: "Rod of Security", rarity: "Very Rare", faction: "Kundarak", baseCost: 45000, attunementRequired: "No" , dndbeyondPage: "9228983-rod-of-security" }, { id: "item_247", name: "Rod of Security", rarity: "Very Rare", faction: "Kundarak", baseCost: 45000, attunementRequired: "No" , dndbeyondPage: "9228983-rod-of-security" },
{ id: "item_248", name: "Rod of the Pact Keeper (+1)", rarity: "Uncommon", faction: "Morgrave", baseCost: 400, attunementRequired: "Required" , dndbeyondPage: "9228987-rod-of-the-pact-keeper" }, { id: "item_248", name: "Rod of the Pact Keeper (+1)", rarity: "Uncommon", faction: "Morgrave", baseCost: 400, attunementRequired: "Required" , dndbeyondPage: "9228987-rod-of-the-pact-keeper" },
@ -276,18 +276,18 @@ const MAGIC_ITEMS_DATA = [
{ id: "item_273", name: "Spell Scroll (level 8 spell)", rarity: "Very Rare", faction: "Morgrave", baseCost: 5000, attunementRequired: "No" , dndbeyondPage: "9229085-spell-scroll" }, { id: "item_273", name: "Spell Scroll (level 8 spell)", rarity: "Very Rare", faction: "Morgrave", baseCost: 5000, attunementRequired: "No" , dndbeyondPage: "9229085-spell-scroll" },
{ id: "item_274", name: "Spellguard Shield", rarity: "Very Rare", faction: "Kundarak", baseCost: 36000, attunementRequired: "Required" , dndbeyondPage: "4757-spellguard-shield" }, { id: "item_274", name: "Spellguard Shield", rarity: "Very Rare", faction: "Kundarak", baseCost: 36000, attunementRequired: "Required" , dndbeyondPage: "4757-spellguard-shield" },
{ id: "item_275", name: "Spell-refueling Ring", rarity: "Uncommon", faction: "Morgrave", baseCost: 600, attunementRequired: "Required" , dndbeyondPage: "10886065-spell-refueling-ring" }, { id: "item_275", name: "Spell-refueling Ring", rarity: "Uncommon", faction: "Morgrave", baseCost: 600, attunementRequired: "Required" , dndbeyondPage: "10886065-spell-refueling-ring" },
{ id: "item_276", name: "Staff of Charming", rarity: "Rare", faction: "Tarkanan", baseCost: 3750, attunementRequired: "Special" , dndbeyondPage: "9229093-staff-of-charming" }, { id: "item_276", name: "Staff of Charming", rarity: "Rare", faction: "Tarkanan", baseCost: 3750, attunementRequired: "Special" , dndbeyondPage: "9229093-staff-of-charming" , attunementNote: "Requires Attunement by a Bard, Cleric, Druid, Sorcerer, Warlock, or Wizard" },
{ id: "item_277", name: "Staff of Fire", rarity: "Very Rare", faction: "Ashbound", baseCost: 18000, attunementRequired: "Special" , dndbeyondPage: "9229094-staff-of-fire" }, { id: "item_277", name: "Staff of Fire", rarity: "Very Rare", faction: "Ashbound", baseCost: 18000, attunementRequired: "Special" , dndbeyondPage: "9229094-staff-of-fire" , attunementNote: "Requires Attunement by a Druid, Sorcerer, Warlock, or Wizard" },
{ id: "item_278", name: "Staff of Frost", rarity: "Very Rare", faction: "Morgrave", baseCost: 18000, attunementRequired: "Special" , dndbeyondPage: "9229096-staff-of-frost" }, { id: "item_278", name: "Staff of Frost", rarity: "Very Rare", faction: "Morgrave", baseCost: 18000, attunementRequired: "Special" , dndbeyondPage: "9229096-staff-of-frost" , attunementNote: "Requires Attunement by a Druid, Sorcerer, Warlock, or Wizard" },
{ id: "item_279", name: "Staff of Healing", rarity: "Rare", faction: "Morgrave", baseCost: 4800, attunementRequired: "Special" , dndbeyondPage: "9229097-staff-of-healing" }, { id: "item_279", name: "Staff of Healing", rarity: "Rare", faction: "Morgrave", baseCost: 4800, attunementRequired: "Special" , dndbeyondPage: "9229097-staff-of-healing" , attunementNote: "Requires Attunement by a Bard, Cleric, or Druid" },
{ id: "item_280", name: "Staff of Power", rarity: "Very Rare", faction: "Morgrave", baseCost: 46000, attunementRequired: "Special" , dndbeyondPage: "9229098-staff-of-power" }, { id: "item_280", name: "Staff of Power", rarity: "Very Rare", faction: "Morgrave", baseCost: 46000, attunementRequired: "Special" , dndbeyondPage: "9229098-staff-of-power" , attunementNote: "Requires Attunement by a Sorcerer, Warlock, or Wizard" },
{ id: "item_281", name: "Staff of Striking", rarity: "Very Rare", faction: "Morgrave", baseCost: 36000, attunementRequired: "Required" , dndbeyondPage: "4765-staff-of-striking" }, { id: "item_281", name: "Staff of Striking", rarity: "Very Rare", faction: "Morgrave", baseCost: 36000, attunementRequired: "Required" , dndbeyondPage: "4765-staff-of-striking" },
{ id: "item_282", name: "Staff of Swarming Insects", rarity: "Rare", faction: "Ashbound", baseCost: 4500, attunementRequired: "Special" , dndbeyondPage: "9229099-staff-of-swarming-insects" }, { id: "item_282", name: "Staff of Swarming Insects", rarity: "Rare", faction: "Ashbound", baseCost: 4500, attunementRequired: "Special" , dndbeyondPage: "9229099-staff-of-swarming-insects" , attunementNote: "Requires Attunement by a Bard, Cleric, Druid, Sorcerer, Warlock, or Wizard" },
{ id: "item_283", name: "Staff of the Adder", rarity: "Uncommon", faction: "Ashbound", baseCost: 350, attunementRequired: "Required" , dndbeyondPage: "9229100-staff-of-the-adder" }, { id: "item_283", name: "Staff of the Adder", rarity: "Uncommon", faction: "Ashbound", baseCost: 350, attunementRequired: "Required" , dndbeyondPage: "9229100-staff-of-the-adder" },
{ id: "item_284", name: "Staff of the Python", rarity: "Uncommon", faction: "Ashbound", baseCost: 250, attunementRequired: "Required" , dndbeyondPage: "9229102-staff-of-the-python" }, { id: "item_284", name: "Staff of the Python", rarity: "Uncommon", faction: "Ashbound", baseCost: 250, attunementRequired: "Required" , dndbeyondPage: "9229102-staff-of-the-python" },
{ id: "item_285", name: "Staff of the Woodlands", rarity: "Rare", faction: "Ashbound", baseCost: 4500, attunementRequired: "Special" , dndbeyondPage: "9229103-staff-of-the-woodlands" }, { id: "item_285", name: "Staff of the Woodlands", rarity: "Rare", faction: "Ashbound", baseCost: 4500, attunementRequired: "Special" , dndbeyondPage: "9229103-staff-of-the-woodlands" , attunementNote: "Requires Attunement by a Druid" },
{ id: "item_286", name: "Staff of Thunder and Lightning", rarity: "Very Rare", faction: "Morgrave", baseCost: 30000, attunementRequired: "Required" , dndbeyondPage: "9229104-staff-of-thunder-and-lightning" }, { id: "item_286", name: "Staff of Thunder and Lightning", rarity: "Very Rare", faction: "Morgrave", baseCost: 30000, attunementRequired: "Required" , dndbeyondPage: "9229104-staff-of-thunder-and-lightning" },
{ id: "item_287", name: "Staff of Withering", rarity: "Rare", faction: "Ashbound", baseCost: 2100, attunementRequired: "Special" , dndbeyondPage: "4771-staff-of-withering" }, { id: "item_287", name: "Staff of Withering", rarity: "Rare", faction: "Ashbound", baseCost: 2100, attunementRequired: "Special" , dndbeyondPage: "4771-staff-of-withering" , attunementNote: "Requires Attunement by a Cleric, Druid, or Warlock" },
{ id: "item_288", name: "Stone of Controlling Earth Elementals", rarity: "Rare", faction: "Ashbound", baseCost: 4700, attunementRequired: "No" , dndbeyondPage: "9229105-stone-of-controlling-earth-elementals" }, { id: "item_288", name: "Stone of Controlling Earth Elementals", rarity: "Rare", faction: "Ashbound", baseCost: 4700, attunementRequired: "No" , dndbeyondPage: "9229105-stone-of-controlling-earth-elementals" },
{ id: "item_289", name: "Stone of Good Luck", rarity: "Uncommon", faction: "Tharashk", baseCost: 400, attunementRequired: "Required" , dndbeyondPage: "4773-stone-of-good-luck-luckstone" }, { id: "item_289", name: "Stone of Good Luck", rarity: "Uncommon", faction: "Tharashk", baseCost: 400, attunementRequired: "Required" , dndbeyondPage: "4773-stone-of-good-luck-luckstone" },
{ id: "item_290", name: "Sun Blade", rarity: "Rare", faction: "Deneith", baseCost: 2000, attunementRequired: "Required" , dndbeyondPage: "9229110-sun-blade" }, { id: "item_290", name: "Sun Blade", rarity: "Rare", faction: "Deneith", baseCost: 2000, attunementRequired: "Required" , dndbeyondPage: "9229110-sun-blade" },
@ -305,17 +305,17 @@ const MAGIC_ITEMS_DATA = [
{ id: "item_302", name: "Wand of Binding", rarity: "Rare", faction: "Thuranni", baseCost: 2500, attunementRequired: "Required" , dndbeyondPage: "9229182-wand-of-binding" }, { id: "item_302", name: "Wand of Binding", rarity: "Rare", faction: "Thuranni", baseCost: 2500, attunementRequired: "Required" , dndbeyondPage: "9229182-wand-of-binding" },
{ id: "item_303", name: "Wand of Enemy Detection", rarity: "Rare", faction: "Medani", baseCost: 3750, attunementRequired: "Required" , dndbeyondPage: "9229184-wand-of-enemy-detection" }, { id: "item_303", name: "Wand of Enemy Detection", rarity: "Rare", faction: "Medani", baseCost: 3750, attunementRequired: "Required" , dndbeyondPage: "9229184-wand-of-enemy-detection" },
{ id: "item_304", name: "Wand of Fear", rarity: "Rare", faction: "Thuranni", baseCost: 3250, attunementRequired: "Required" , dndbeyondPage: "9229185-wand-of-fear" }, { id: "item_304", name: "Wand of Fear", rarity: "Rare", faction: "Thuranni", baseCost: 3250, attunementRequired: "Required" , dndbeyondPage: "9229185-wand-of-fear" },
{ id: "item_305", name: "Wand of Fireballs", rarity: "Rare", faction: "Ashbound", baseCost: 4800, attunementRequired: "Special" , dndbeyondPage: "9229186-wand-of-fireballs" }, { id: "item_305", name: "Wand of Fireballs", rarity: "Rare", faction: "Ashbound", baseCost: 4800, attunementRequired: "Special" , dndbeyondPage: "9229186-wand-of-fireballs" , attunementNote: "Requires Attunement by a Spellcaster" },
{ id: "item_306", name: "Wand of Lightning Bolts", rarity: "Rare", faction: "Tarkanan", baseCost: 4800, attunementRequired: "Special" , dndbeyondPage: "9229187-wand-of-lightning-bolts" }, { id: "item_306", name: "Wand of Lightning Bolts", rarity: "Rare", faction: "Tarkanan", baseCost: 4800, attunementRequired: "Special" , dndbeyondPage: "9229187-wand-of-lightning-bolts" , attunementNote: "Requires Attunement by a Spellcaster" },
{ id: "item_307", name: "Wand of Magic Detection", rarity: "Uncommon", faction: "Medani", baseCost: 150, attunementRequired: "No" , dndbeyondPage: "9229188-wand-of-magic-detection" }, { id: "item_307", name: "Wand of Magic Detection", rarity: "Uncommon", faction: "Medani", baseCost: 150, attunementRequired: "No" , dndbeyondPage: "9229188-wand-of-magic-detection" },
{ id: "item_308", name: "Wand of Magic Missiles", rarity: "Uncommon", faction: "Tharashk", baseCost: 300, attunementRequired: "No" , dndbeyondPage: "9237129-wand-of-magic-missiles" }, { id: "item_308", name: "Wand of Magic Missiles", rarity: "Uncommon", faction: "Tharashk", baseCost: 300, attunementRequired: "No" , dndbeyondPage: "9237129-wand-of-magic-missiles" },
{ id: "item_309", name: "Wand of Paralysis", rarity: "Rare", faction: "Thuranni", baseCost: 4250, attunementRequired: "Special" , dndbeyondPage: "9229190-wand-of-paralysis" }, { id: "item_309", name: "Wand of Paralysis", rarity: "Rare", faction: "Thuranni", baseCost: 4250, attunementRequired: "Special" , dndbeyondPage: "9229190-wand-of-paralysis" , attunementNote: "Requires Attunement by a Spellcaster" },
{ id: "item_310", name: "Wand of Polymorph", rarity: "Very Rare", faction: "Tharashk", baseCost: 21000, attunementRequired: "Special" , dndbeyondPage: "9229191-wand-of-polymorph" }, { id: "item_310", name: "Wand of Polymorph", rarity: "Very Rare", faction: "Tharashk", baseCost: 21000, attunementRequired: "Special" , dndbeyondPage: "9229191-wand-of-polymorph" , attunementNote: "Requires Attunement by a Spellcaster" },
{ id: "item_311", name: "Wand of Secrets", rarity: "Uncommon", faction: "Medani", baseCost: 125, attunementRequired: "No" , dndbeyondPage: "9229193-wand-of-secrets" }, { id: "item_311", name: "Wand of Secrets", rarity: "Uncommon", faction: "Medani", baseCost: 125, attunementRequired: "No" , dndbeyondPage: "9229193-wand-of-secrets" },
{ id: "item_312", name: "Wand of the War Mage, +1", rarity: "Uncommon", faction: "Morgrave", baseCost: 400, attunementRequired: "Required" , dndbeyondPage: "34712-wand-of-the-war-mage" }, { id: "item_312", name: "Wand of the War Mage, +1", rarity: "Uncommon", faction: "Morgrave", baseCost: 400, attunementRequired: "Required" , dndbeyondPage: "34712-wand-of-the-war-mage" },
{ id: "item_313", name: "Wand of the War Mage, +2", rarity: "Rare", faction: "Morgrave", baseCost: 4000, attunementRequired: "Required" , dndbeyondPage: "34712-wand-of-the-war-mage" }, { id: "item_313", name: "Wand of the War Mage, +2", rarity: "Rare", faction: "Morgrave", baseCost: 4000, attunementRequired: "Required" , dndbeyondPage: "34712-wand-of-the-war-mage" },
{ id: "item_314", name: "Wand of the War Mage, +3", rarity: "Very Rare", faction: "Morgrave", baseCost: 14000, attunementRequired: "Required" , dndbeyondPage: "34712-wand-of-the-war-mage" }, { id: "item_314", name: "Wand of the War Mage, +3", rarity: "Very Rare", faction: "Morgrave", baseCost: 14000, attunementRequired: "Required" , dndbeyondPage: "34712-wand-of-the-war-mage" },
{ id: "item_315", name: "Wand of Web", rarity: "Uncommon", faction: "Thuranni", baseCost: 250, attunementRequired: "Special" , dndbeyondPage: "9229194-wand-of-web" }, { id: "item_315", name: "Wand of Web", rarity: "Uncommon", faction: "Thuranni", baseCost: 250, attunementRequired: "Special" , dndbeyondPage: "9229194-wand-of-web" , attunementNote: "Requires Attunement by a Spellcaster" },
{ id: "item_316", name: "Wand of Wonder", rarity: "Rare", faction: "Morgrave", baseCost: 2250, attunementRequired: "Required" , dndbeyondPage: "9229195-wand-of-wonder" }, { id: "item_316", name: "Wand of Wonder", rarity: "Rare", faction: "Morgrave", baseCost: 2250, attunementRequired: "Required" , dndbeyondPage: "9229195-wand-of-wonder" },
{ id: "item_317", name: "Warrior's Passkey", rarity: "Rare", faction: "Tharashk", baseCost: 5000, attunementRequired: "Required" , dndbeyondPage: "7526784-warriors-passkey" }, { id: "item_317", name: "Warrior's Passkey", rarity: "Rare", faction: "Tharashk", baseCost: 5000, attunementRequired: "Required" , dndbeyondPage: "7526784-warriors-passkey" },
{ id: "item_318", name: "Watchful Helm", rarity: "Very Rare", faction: "Medani", baseCost: 8500, attunementRequired: "Required" , dndbeyondPage: "3001264-watchful-helm" }, { id: "item_318", name: "Watchful Helm", rarity: "Very Rare", faction: "Medani", baseCost: 8500, attunementRequired: "Required" , dndbeyondPage: "3001264-watchful-helm" },