Fetches better item data, adds spec selector
This commit is contained in:
parent
b5ae96870f
commit
181805fcab
@ -7,7 +7,9 @@
|
||||
"dev": "vite",
|
||||
"build": "tsc -b && vite build",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"fetch-items": "node scripts/fetch-item-data.js",
|
||||
"fetch-items-enhanced": "node scripts/fetch-items-enhanced.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@headlessui/react": "^2.2.7",
|
||||
|
||||
117
scripts/README.md
Normal file
117
scripts/README.md
Normal file
@ -0,0 +1,117 @@
|
||||
# WoW Item Data Fetching Scripts
|
||||
|
||||
This directory contains scripts to fetch World of Warcraft item data from various APIs.
|
||||
|
||||
## Scripts
|
||||
|
||||
### `fetch-item-data.js` - Basic Item Fetcher
|
||||
|
||||
A simple script that fetches item information from Wowhead API.
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
# Fetch specific items by ID
|
||||
npm run fetch-items 242494 242495 242481
|
||||
|
||||
# Fetch data for all existing items in drop files
|
||||
npm run fetch-items --existing
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- Fetches item name, slot, icon from Wowhead
|
||||
- Supports both XML and JSON Wowhead APIs
|
||||
- Rate limiting to avoid overwhelming servers
|
||||
- Saves results to JSON file
|
||||
|
||||
### `fetch-items-enhanced.js` - Advanced Item Fetcher
|
||||
|
||||
Enhanced script with multiple API sources and additional features.
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
# Basic usage
|
||||
npm run fetch-items-enhanced 242494 242495 242481
|
||||
|
||||
# Fetch and validate existing items
|
||||
npm run fetch-items-enhanced --existing --validate
|
||||
|
||||
# Generate TypeScript code for new dungeon
|
||||
npm run fetch-items-enhanced --generate "new-dungeon" 123456 123457
|
||||
|
||||
# Use only specific API
|
||||
npm run fetch-items-enhanced --wowhead-only 242494
|
||||
npm run fetch-items-enhanced --blizzard-only 242494
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- Multiple API sources (Wowhead + Blizzard)
|
||||
- Data validation against existing project data
|
||||
- TypeScript code generation
|
||||
- Detailed reporting and analysis
|
||||
- Fallback mechanisms
|
||||
|
||||
### `blizzard-api.js` - Blizzard API Client
|
||||
|
||||
Handles authentication and data fetching from Blizzard's official API.
|
||||
|
||||
**Setup for Blizzard API:**
|
||||
1. Create an application at https://develop.battle.net/
|
||||
2. Get your Client ID and Client Secret
|
||||
3. Set environment variables:
|
||||
```bash
|
||||
export BLIZZARD_CLIENT_ID="your_client_id"
|
||||
export BLIZZARD_CLIENT_SECRET="your_client_secret"
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- OAuth2 token management
|
||||
- Item data and media fetching
|
||||
- Detailed item metadata
|
||||
|
||||
## Data Sources
|
||||
|
||||
### Wowhead API
|
||||
- **Pros:** Reliable, no authentication required, good icon data
|
||||
- **Cons:** Unofficial API, rate limiting needed
|
||||
- **Best for:** Basic item info, icons, quick lookups
|
||||
|
||||
### Blizzard API
|
||||
- **Pros:** Official API, detailed metadata, reliable
|
||||
- **Cons:** Requires authentication setup, more complex
|
||||
- **Best for:** Detailed item data, official information
|
||||
|
||||
## Output Files
|
||||
|
||||
- `fetched-items.json` - Basic fetch results
|
||||
- `fetched-items-detailed-{timestamp}.json` - Enhanced fetch results with all API responses
|
||||
- `{source-name}.ts` - Generated TypeScript code for new item sources
|
||||
|
||||
## Examples
|
||||
|
||||
### Fetch a few specific items
|
||||
```bash
|
||||
npm run fetch-items 242494 242495 242481
|
||||
```
|
||||
|
||||
### Validate all existing project items
|
||||
```bash
|
||||
npm run fetch-items-enhanced --existing --validate
|
||||
```
|
||||
|
||||
### Create a new dungeon data file
|
||||
```bash
|
||||
npm run fetch-items-enhanced --generate "mists-of-tirna-scithe" 178692 178693 178694
|
||||
```
|
||||
|
||||
### Use only Wowhead (no Blizzard setup needed)
|
||||
```bash
|
||||
npm run fetch-items-enhanced --wowhead-only --existing
|
||||
```
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
Both scripts include rate limiting (1 second between requests) to be respectful to the APIs. For large batches of items, expect the process to take some time.
|
||||
|
||||
## Error Handling
|
||||
|
||||
The scripts will continue processing even if individual items fail to fetch. Check the console output and generated files for detailed results and any errors encountered.
|
||||
241
scripts/blizzard-api.js
Normal file
241
scripts/blizzard-api.js
Normal file
@ -0,0 +1,241 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import https from 'https';
|
||||
|
||||
/**
|
||||
* Blizzard API client for fetching item data
|
||||
* To use this, you'll need to:
|
||||
* 1. Create an app at https://develop.battle.net/
|
||||
* 2. Get your client ID and client secret
|
||||
* 3. Set environment variables: BLIZZARD_CLIENT_ID and BLIZZARD_CLIENT_SECRET
|
||||
*/
|
||||
|
||||
let accessToken = null;
|
||||
let tokenExpiry = null;
|
||||
|
||||
/**
|
||||
* Gets an access token from Blizzard API
|
||||
* @returns {Promise<string|null>} Access token or null if failed
|
||||
*/
|
||||
async function getAccessToken() {
|
||||
const clientId = process.env.BLIZZARD_CLIENT_ID;
|
||||
const clientSecret = process.env.BLIZZARD_CLIENT_SECRET;
|
||||
|
||||
if (!clientId || !clientSecret) {
|
||||
console.error('Blizzard API credentials not found. Please set BLIZZARD_CLIENT_ID and BLIZZARD_CLIENT_SECRET environment variables.');
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if we have a valid token
|
||||
if (accessToken && tokenExpiry && Date.now() < tokenExpiry) {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const auth = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
|
||||
const postData = 'grant_type=client_credentials';
|
||||
|
||||
const options = {
|
||||
hostname: 'oauth.battle.net',
|
||||
port: 443,
|
||||
path: '/token',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Basic ${auth}`,
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Content-Length': Buffer.byteLength(postData)
|
||||
}
|
||||
};
|
||||
|
||||
const req = https.request(options, (res) => {
|
||||
let data = '';
|
||||
|
||||
res.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
|
||||
res.on('end', () => {
|
||||
try {
|
||||
const response = JSON.parse(data);
|
||||
if (response.access_token) {
|
||||
accessToken = response.access_token;
|
||||
tokenExpiry = Date.now() + (response.expires_in * 1000);
|
||||
resolve(accessToken);
|
||||
} else {
|
||||
console.error('Failed to get access token:', response);
|
||||
resolve(null);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error parsing token response:', error.message);
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (error) => {
|
||||
console.error('Error getting access token:', error.message);
|
||||
resolve(null);
|
||||
});
|
||||
|
||||
req.write(postData);
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches item data from Blizzard API
|
||||
* @param {number} itemId - The item ID to fetch
|
||||
* @param {string} region - The region (default: 'us')
|
||||
* @returns {Promise<Object|null>} Item data or null if failed
|
||||
*/
|
||||
async function fetchFromBlizzard(itemId, region = 'us') {
|
||||
const token = await getAccessToken();
|
||||
if (!token) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const options = {
|
||||
hostname: `${region}.api.blizzard.com`,
|
||||
port: 443,
|
||||
path: `/data/wow/item/${itemId}?namespace=static-${region}&locale=en_US&access_token=${token}`,
|
||||
method: 'GET'
|
||||
};
|
||||
|
||||
https.get(options, (res) => {
|
||||
let data = '';
|
||||
|
||||
res.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
|
||||
res.on('end', () => {
|
||||
try {
|
||||
const response = JSON.parse(data);
|
||||
|
||||
if (response.name) {
|
||||
const itemData = {
|
||||
id: itemId,
|
||||
name: response.name,
|
||||
slot: mapSlotFromBlizzard(response.inventory_type?.type),
|
||||
quality: response.quality?.name?.toLowerCase(),
|
||||
icon: response.media ? `blizzard-${response.media.id}` : null,
|
||||
source: 'blizzard',
|
||||
blizzardData: {
|
||||
itemClass: response.item_class?.name,
|
||||
itemSubclass: response.item_subclass?.name,
|
||||
inventoryType: response.inventory_type?.name,
|
||||
bindType: response.bind_type?.name,
|
||||
level: response.level,
|
||||
requiredLevel: response.required_level
|
||||
}
|
||||
};
|
||||
resolve(itemData);
|
||||
} else {
|
||||
console.log(`No data found for item ${itemId} on Blizzard API`);
|
||||
resolve(null);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error parsing Blizzard data for item ${itemId}:`, error.message);
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
}).on('error', (error) => {
|
||||
console.error(`Error fetching from Blizzard for item ${itemId}:`, error.message);
|
||||
resolve(null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps Blizzard inventory types to our slot names
|
||||
* @param {string} inventoryType - Blizzard inventory type
|
||||
* @returns {string|null} Our slot name or null
|
||||
*/
|
||||
function mapSlotFromBlizzard(inventoryType) {
|
||||
const typeMap = {
|
||||
'HEAD': 'head',
|
||||
'NECK': 'neck',
|
||||
'SHOULDER': 'shoulders',
|
||||
'BODY': 'chest',
|
||||
'CHEST': 'chest',
|
||||
'WAIST': 'waist',
|
||||
'LEGS': 'legs',
|
||||
'FEET': 'feet',
|
||||
'WRIST': 'wrist',
|
||||
'HAND': 'hands',
|
||||
'FINGER': 'finger',
|
||||
'TRINKET': 'trinket',
|
||||
'WEAPON': '1h-weapon',
|
||||
'SHIELD': 'off-hand',
|
||||
'RANGED': '2h-weapon',
|
||||
'CLOAK': 'back',
|
||||
'WEAPON_2H': '2h-weapon',
|
||||
'WEAPON_MAIN_HAND': '1h-weapon',
|
||||
'WEAPON_OFF_HAND': 'off-hand',
|
||||
'HOLDABLE': 'off-hand',
|
||||
'AMMO': null,
|
||||
'THROWN': '1h-weapon',
|
||||
'RANGED_RIGHT': '2h-weapon',
|
||||
'QUIVER': null,
|
||||
'RELIC': 'trinket'
|
||||
};
|
||||
|
||||
return typeMap[inventoryType] || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches item media (icon) from Blizzard API
|
||||
* @param {number} itemId - The item ID
|
||||
* @param {string} region - The region (default: 'us')
|
||||
* @returns {Promise<string|null>} Icon URL or null if failed
|
||||
*/
|
||||
async function fetchItemMedia(itemId, region = 'us') {
|
||||
const token = await getAccessToken();
|
||||
if (!token) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const options = {
|
||||
hostname: `${region}.api.blizzard.com`,
|
||||
port: 443,
|
||||
path: `/data/wow/media/item/${itemId}?namespace=static-${region}&locale=en_US&access_token=${token}`,
|
||||
method: 'GET'
|
||||
};
|
||||
|
||||
https.get(options, (res) => {
|
||||
let data = '';
|
||||
|
||||
res.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
|
||||
res.on('end', () => {
|
||||
try {
|
||||
const response = JSON.parse(data);
|
||||
|
||||
if (response.assets && response.assets.length > 0) {
|
||||
const iconAsset = response.assets.find(asset => asset.key === 'icon');
|
||||
resolve(iconAsset ? iconAsset.value : null);
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error parsing media data for item ${itemId}:`, error.message);
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
}).on('error', (error) => {
|
||||
console.error(`Error fetching media for item ${itemId}:`, error.message);
|
||||
resolve(null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export {
|
||||
fetchFromBlizzard,
|
||||
fetchItemMedia,
|
||||
getAccessToken,
|
||||
mapSlotFromBlizzard
|
||||
};
|
||||
313
scripts/fetch-item-data.js
Normal file
313
scripts/fetch-item-data.js
Normal file
@ -0,0 +1,313 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import https from "https";
|
||||
import fs from "fs/promises";
|
||||
import path from "path";
|
||||
|
||||
/**
|
||||
* Fetches item data from Wowhead API
|
||||
* @param {number} itemId - The item ID to fetch
|
||||
* @returns {Promise<Object|null>} Item data or null if failed
|
||||
*/
|
||||
async function fetchFromWowhead(itemId, source) {
|
||||
return new Promise((resolve) => {
|
||||
const url = `https://www.wowhead.com/item=${itemId}&xml`;
|
||||
|
||||
https
|
||||
.get(url, (res) => {
|
||||
let data = "";
|
||||
|
||||
res.on("data", (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
|
||||
res.on("end", () => {
|
||||
try {
|
||||
// Weirdly, the JSON in the XML has more data than the XML itself or the JSON API.
|
||||
const jsonString = data.match(/<json><!\[CDATA\[(.*)\]\]><\/json>/);
|
||||
const jsonData = JSON.parse(`{${jsonString[1]}}`);
|
||||
|
||||
// Parse the XML response from Wowhead
|
||||
// const nameMatch = data.match(/<name><!\[CDATA\[(.*?)\]\]><\/name>/);
|
||||
const iconMatch = data.match(
|
||||
/<icon displayId="(\d+)">(.*?)<\/icon>/,
|
||||
);
|
||||
const slotMatch = data.match(
|
||||
/<inventorySlot id="(\d+)">(.*?)<\/inventorySlot>/,
|
||||
);
|
||||
|
||||
const name = jsonData.displayName;
|
||||
|
||||
const itemData = {
|
||||
id: itemId,
|
||||
name,
|
||||
icon: iconMatch ? iconMatch[2] : null,
|
||||
slot: mapSlotFromWowhead(jsonData.slot),
|
||||
specs: jsonData.specs || [],
|
||||
source,
|
||||
};
|
||||
resolve(itemData);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Error parsing Wowhead data for item ${itemId}:`,
|
||||
error.message,
|
||||
);
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
})
|
||||
.on("error", (error) => {
|
||||
console.error(
|
||||
`Error fetching from Wowhead for item ${itemId}:`,
|
||||
error.message,
|
||||
);
|
||||
resolve(null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches item data from Wowhead's JSON API (alternative method)
|
||||
* @param {number} itemId - The item ID to fetch
|
||||
* @returns {Promise<Object|null>} Item data or null if failed
|
||||
*/
|
||||
async function fetchFromWowheadJson(itemId) {
|
||||
return new Promise((resolve) => {
|
||||
const url = `https://nether.wowhead.com/tooltip/item/${itemId}`;
|
||||
|
||||
https
|
||||
.get(url, (res) => {
|
||||
let data = "";
|
||||
|
||||
res.on("data", (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
|
||||
res.on("end", () => {
|
||||
try {
|
||||
const jsonData = JSON.parse(data);
|
||||
|
||||
if (jsonData && jsonData.name) {
|
||||
const itemData = {
|
||||
id: itemId,
|
||||
name: jsonData.name,
|
||||
icon: jsonData.icon || null,
|
||||
slot: mapSlotFromWowhead(jsonData.slot || 0),
|
||||
};
|
||||
resolve(itemData);
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Error parsing Wowhead JSON data for item ${itemId}:`,
|
||||
error.message,
|
||||
);
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
})
|
||||
.on("error", (error) => {
|
||||
console.error(
|
||||
`Error fetching from Wowhead JSON for item ${itemId}:`,
|
||||
error.message,
|
||||
);
|
||||
resolve(null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps Wowhead slot numbers to our slot names
|
||||
* @param {number} slotId - Wowhead slot ID
|
||||
* @returns {string|null} Our slot name or null
|
||||
*/
|
||||
function mapSlotFromWowhead(slotId) {
|
||||
const slotMap = {
|
||||
1: "head",
|
||||
2: "neck",
|
||||
3: "shoulders",
|
||||
5: "chest",
|
||||
6: "waist",
|
||||
7: "legs",
|
||||
8: "feet",
|
||||
9: "wrist",
|
||||
10: "hands",
|
||||
11: "finger",
|
||||
12: "trinket",
|
||||
13: "1h-weapon",
|
||||
14: "off-hand",
|
||||
15: "back",
|
||||
16: "1h-weapon", // Main hand
|
||||
17: "2h-weapon",
|
||||
21: "1h-weapon", // One-handed
|
||||
22: "off-hand",
|
||||
23: "off-hand", // Held in off-hand
|
||||
25: "1h-weapon", // Thrown
|
||||
};
|
||||
|
||||
return slotMap[slotId] || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches multiple items with rate limiting
|
||||
* @param {number[]} itemIds - Array of item IDs to fetch
|
||||
* @param {number} delay - Delay between requests in ms
|
||||
* @returns {Promise<Object[]>} Array of item data
|
||||
*/
|
||||
async function fetchMultipleItems(source, itemIds, delay = 1000) {
|
||||
const results = [];
|
||||
|
||||
console.log(`Fetching data for ${itemIds.length} items...`);
|
||||
|
||||
for (let i = 0; i < itemIds.length; i++) {
|
||||
const itemId = itemIds[i];
|
||||
console.log(`Fetching item ${itemId} (${i + 1}/${itemIds.length})`);
|
||||
|
||||
// Try Wowhead JSON API first, fallback to XML
|
||||
let itemData = await fetchFromWowhead(itemId, source);
|
||||
if (!itemData) {
|
||||
itemData = await fetchFromWowheadJson(itemId, source);
|
||||
}
|
||||
|
||||
if (itemData) {
|
||||
results.push(itemData);
|
||||
console.log(
|
||||
`✓ Found: ${itemData.name} (${itemData.slot || "unknown slot"})`,
|
||||
);
|
||||
} else {
|
||||
console.log(`✗ Failed to fetch data for item ${itemId}`);
|
||||
}
|
||||
|
||||
// Rate limiting
|
||||
if (i < itemIds.length - 1) {
|
||||
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads item IDs from existing drop files
|
||||
* @returns {Promise<number[]>} Array of item IDs
|
||||
*/
|
||||
async function getExistingItemIds() {
|
||||
const dropsDir = path.join(process.cwd(), "src", "lib", "drops");
|
||||
const itemIds = [];
|
||||
|
||||
try {
|
||||
const files = await fs.readdir(dropsDir);
|
||||
|
||||
for (const file of files) {
|
||||
if (file.endsWith(".ts") && file !== "index.ts") {
|
||||
const filePath = path.join(dropsDir, file);
|
||||
const content = await fs.readFile(filePath, "utf-8");
|
||||
|
||||
// Extract item IDs using regex
|
||||
const idMatches = content.match(/id: (\d+) as ItemId/g);
|
||||
if (idMatches) {
|
||||
for (const match of idMatches) {
|
||||
const id = parseInt(match.match(/id: (\d+)/)[1]);
|
||||
itemIds.push(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error reading existing item IDs:", error.message);
|
||||
}
|
||||
|
||||
return [...new Set(itemIds)]; // Remove duplicates
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves fetched data to a JSON file
|
||||
* @param {Object[]} items - Array of item data
|
||||
* @param {string} filename - Output filename
|
||||
*/
|
||||
async function saveToFile(items, filename = "fetched-items.json") {
|
||||
try {
|
||||
const outputPath = path.join(process.cwd(), filename);
|
||||
await fs.writeFile(outputPath, JSON.stringify(items, null, 2));
|
||||
console.log(`\nSaved ${items.length} items to ${filename}`);
|
||||
} catch (error) {
|
||||
console.error("Error saving file:", error.message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function
|
||||
*/
|
||||
async function main() {
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
if (args.length === 0) {
|
||||
console.log(
|
||||
"Usage: npm run fetch-items [item1] [item2] ... or npm run fetch-items --existing",
|
||||
);
|
||||
console.log("Examples:");
|
||||
console.log(" npm run fetch-items 242494 242495 242481");
|
||||
console.log(
|
||||
" npm run fetch-items --existing # Fetch data for all items in drop files",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let itemIds = [];
|
||||
let source = null;
|
||||
|
||||
if (args[0] === "--existing") {
|
||||
console.log("Fetching data for existing items in drop files...");
|
||||
itemIds = await getExistingItemIds();
|
||||
console.log(`Found ${itemIds.length} existing items`);
|
||||
} else {
|
||||
source = args[0];
|
||||
itemIds = args
|
||||
.slice(1)
|
||||
.map((arg) => parseInt(arg))
|
||||
.filter((id) => !isNaN(id));
|
||||
}
|
||||
|
||||
if (itemIds.length === 0) {
|
||||
console.log("No valid item IDs provided");
|
||||
return;
|
||||
}
|
||||
|
||||
const items = await fetchMultipleItems(source, itemIds);
|
||||
|
||||
if (items.length > 0) {
|
||||
await saveToFile(items);
|
||||
|
||||
console.log("\nSummary:");
|
||||
console.log(
|
||||
`Successfully fetched: ${items.length}/${itemIds.length} items`,
|
||||
);
|
||||
|
||||
// Show slot distribution
|
||||
const slotCounts = {};
|
||||
items.forEach((item) => {
|
||||
const slot = item.slot || "unknown";
|
||||
slotCounts[slot] = (slotCounts[slot] || 0) + 1;
|
||||
});
|
||||
|
||||
console.log("\nSlot distribution:");
|
||||
Object.entries(slotCounts).forEach(([slot, count]) => {
|
||||
console.log(` ${slot}: ${count}`);
|
||||
});
|
||||
} else {
|
||||
console.log("No items were successfully fetched");
|
||||
}
|
||||
}
|
||||
|
||||
// Run the script
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
main().catch(console.error);
|
||||
}
|
||||
|
||||
export {
|
||||
fetchFromWowhead,
|
||||
fetchFromWowheadJson,
|
||||
fetchMultipleItems,
|
||||
getExistingItemIds,
|
||||
};
|
||||
343
scripts/fetch-items-enhanced.js
Normal file
343
scripts/fetch-items-enhanced.js
Normal file
@ -0,0 +1,343 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { fetchFromWowhead, fetchFromWowheadJson, getExistingItemIds } from './fetch-item-data.js';
|
||||
import { fetchFromBlizzard } from './blizzard-api.js';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
/**
|
||||
* Enhanced item fetcher with multiple API sources and validation
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetches item data from multiple sources with fallbacks
|
||||
* @param {number} itemId - The item ID to fetch
|
||||
* @returns {Promise<Object|null>} Combined item data or null if failed
|
||||
*/
|
||||
async function fetchItemFromAllSources(itemId) {
|
||||
console.log(`Fetching item ${itemId} from multiple sources...`);
|
||||
|
||||
const results = {
|
||||
wowhead: null,
|
||||
blizzard: null,
|
||||
combined: null
|
||||
};
|
||||
|
||||
// Try Wowhead first (more reliable for icons and basic data)
|
||||
try {
|
||||
results.wowhead = await fetchFromWowheadJson(itemId);
|
||||
if (!results.wowhead) {
|
||||
results.wowhead = await fetchFromWowhead(itemId);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Wowhead fetch failed for ${itemId}:`, error.message);
|
||||
}
|
||||
|
||||
// Try Blizzard API (more detailed data but requires auth)
|
||||
try {
|
||||
results.blizzard = await fetchFromBlizzard(itemId);
|
||||
} catch (error) {
|
||||
console.error(`Blizzard fetch failed for ${itemId}:`, error.message);
|
||||
}
|
||||
|
||||
// Combine the best data from both sources
|
||||
if (results.wowhead || results.blizzard) {
|
||||
results.combined = combineItemData(results.wowhead, results.blizzard, itemId);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines item data from multiple sources, preferring the best available data
|
||||
* @param {Object|null} wowheadData - Data from Wowhead
|
||||
* @param {Object|null} blizzardData - Data from Blizzard
|
||||
* @param {number} itemId - The item ID
|
||||
* @returns {Object} Combined item data
|
||||
*/
|
||||
function combineItemData(wowheadData, blizzardData, itemId) {
|
||||
const combined = {
|
||||
id: itemId,
|
||||
name: null,
|
||||
slot: null,
|
||||
icon: null,
|
||||
quality: null,
|
||||
sources: []
|
||||
};
|
||||
|
||||
// Prefer Wowhead for name and icon (usually more consistent)
|
||||
if (wowheadData) {
|
||||
combined.name = wowheadData.name;
|
||||
combined.icon = wowheadData.icon;
|
||||
combined.slot = wowheadData.slot;
|
||||
combined.quality = wowheadData.quality;
|
||||
combined.sources.push('wowhead');
|
||||
}
|
||||
|
||||
// Use Blizzard data to fill gaps or override with better data
|
||||
if (blizzardData) {
|
||||
if (!combined.name) combined.name = blizzardData.name;
|
||||
if (!combined.slot) combined.slot = blizzardData.slot;
|
||||
if (!combined.quality) combined.quality = blizzardData.quality;
|
||||
|
||||
// Add Blizzard-specific data
|
||||
combined.blizzardData = blizzardData.blizzardData;
|
||||
combined.sources.push('blizzard');
|
||||
}
|
||||
|
||||
return combined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates item data against existing project data
|
||||
* @param {Object[]} fetchedItems - Array of fetched item data
|
||||
* @param {Object[]} existingItems - Array of existing project items
|
||||
* @returns {Object} Validation report
|
||||
*/
|
||||
function validateItemData(fetchedItems, existingItems) {
|
||||
const report = {
|
||||
matches: [],
|
||||
mismatches: [],
|
||||
missing: [],
|
||||
newItems: []
|
||||
};
|
||||
|
||||
const existingById = {};
|
||||
existingItems.forEach(item => {
|
||||
existingById[item.id] = item;
|
||||
});
|
||||
|
||||
fetchedItems.forEach(fetched => {
|
||||
const existing = existingById[fetched.combined.id];
|
||||
|
||||
if (existing) {
|
||||
const issues = [];
|
||||
|
||||
if (existing.name !== fetched.combined.name) {
|
||||
issues.push(`name: "${existing.name}" vs "${fetched.combined.name}"`);
|
||||
}
|
||||
|
||||
if (existing.slot !== fetched.combined.slot) {
|
||||
issues.push(`slot: "${existing.slot}" vs "${fetched.combined.slot}"`);
|
||||
}
|
||||
|
||||
if (existing.icon !== fetched.combined.icon && fetched.combined.icon) {
|
||||
issues.push(`icon: "${existing.icon || 'none'}" vs "${fetched.combined.icon}"`);
|
||||
}
|
||||
|
||||
if (issues.length > 0) {
|
||||
report.mismatches.push({
|
||||
id: fetched.combined.id,
|
||||
issues,
|
||||
existing,
|
||||
fetched: fetched.combined
|
||||
});
|
||||
} else {
|
||||
report.matches.push(fetched.combined.id);
|
||||
}
|
||||
} else {
|
||||
report.newItems.push(fetched.combined);
|
||||
}
|
||||
});
|
||||
|
||||
// Find missing items (in project but not fetched)
|
||||
const fetchedIds = new Set(fetchedItems.map(item => item.combined.id));
|
||||
existingItems.forEach(item => {
|
||||
if (!fetchedIds.has(item.id)) {
|
||||
report.missing.push(item.id);
|
||||
}
|
||||
});
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates TypeScript code for new items
|
||||
* @param {Object[]} items - Array of item data
|
||||
* @param {string} source - Source name for the items
|
||||
* @returns {string} TypeScript code
|
||||
*/
|
||||
function generateTypeScriptCode(items, source) {
|
||||
const lines = [];
|
||||
lines.push(`import type { ItemId } from "../types";`);
|
||||
lines.push('');
|
||||
lines.push(`export const ${source.charAt(0).toUpperCase() + source.slice(1)} = [`);
|
||||
|
||||
items.forEach((item, index) => {
|
||||
lines.push(' {');
|
||||
lines.push(` id: ${item.id} as ItemId,`);
|
||||
lines.push(` slot: "${item.slot}",`);
|
||||
lines.push(` name: "${item.name}",`);
|
||||
lines.push(` source: "${source}" as const,`);
|
||||
if (item.icon) {
|
||||
lines.push(` icon: "${item.icon}",`);
|
||||
}
|
||||
lines.push(' }' + (index < items.length - 1 ? ',' : ''));
|
||||
});
|
||||
|
||||
lines.push('];');
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function with enhanced features
|
||||
*/
|
||||
async function main() {
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
if (args.length === 0) {
|
||||
console.log('Enhanced WoW Item Data Fetcher');
|
||||
console.log('Usage:');
|
||||
console.log(' npm run fetch-items-enhanced [options] [item1] [item2] ...');
|
||||
console.log('');
|
||||
console.log('Options:');
|
||||
console.log(' --existing Fetch data for all items in drop files');
|
||||
console.log(' --validate Compare fetched data with existing project data');
|
||||
console.log(' --generate <name> Generate TypeScript code for new source');
|
||||
console.log(' --blizzard-only Use only Blizzard API');
|
||||
console.log(' --wowhead-only Use only Wowhead API');
|
||||
console.log('');
|
||||
console.log('Examples:');
|
||||
console.log(' npm run fetch-items-enhanced 242494 242495 242481');
|
||||
console.log(' npm run fetch-items-enhanced --existing --validate');
|
||||
console.log(' npm run fetch-items-enhanced --generate "new-dungeon" 123456 123457');
|
||||
return;
|
||||
}
|
||||
|
||||
let itemIds = [];
|
||||
let options = {
|
||||
existing: false,
|
||||
validate: false,
|
||||
generate: null,
|
||||
blizzardOnly: false,
|
||||
wowheadOnly: false
|
||||
};
|
||||
|
||||
// Parse arguments
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i];
|
||||
|
||||
if (arg === '--existing') {
|
||||
options.existing = true;
|
||||
} else if (arg === '--validate') {
|
||||
options.validate = true;
|
||||
} else if (arg === '--generate') {
|
||||
options.generate = args[++i];
|
||||
} else if (arg === '--blizzard-only') {
|
||||
options.blizzardOnly = true;
|
||||
} else if (arg === '--wowhead-only') {
|
||||
options.wowheadOnly = true;
|
||||
} else if (!isNaN(parseInt(arg))) {
|
||||
itemIds.push(parseInt(arg));
|
||||
}
|
||||
}
|
||||
|
||||
// Get item IDs
|
||||
if (options.existing) {
|
||||
console.log('Fetching data for existing items in drop files...');
|
||||
const existingIds = await getExistingItemIds();
|
||||
itemIds = [...new Set([...itemIds, ...existingIds])];
|
||||
console.log(`Found ${existingIds.length} existing items`);
|
||||
}
|
||||
|
||||
if (itemIds.length === 0) {
|
||||
console.log('No valid item IDs provided');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Processing ${itemIds.length} items...`);
|
||||
|
||||
// Fetch items with rate limiting
|
||||
const results = [];
|
||||
for (let i = 0; i < itemIds.length; i++) {
|
||||
const itemId = itemIds[i];
|
||||
console.log(`\nProcessing item ${itemId} (${i + 1}/${itemIds.length})`);
|
||||
|
||||
let result;
|
||||
if (options.blizzardOnly) {
|
||||
const blizzardData = await fetchFromBlizzard(itemId);
|
||||
result = { wowhead: null, blizzard: blizzardData, combined: blizzardData };
|
||||
} else if (options.wowheadOnly) {
|
||||
const wowheadData = await fetchFromWowheadJson(itemId) || await fetchFromWowhead(itemId);
|
||||
result = { wowhead: wowheadData, blizzard: null, combined: wowheadData };
|
||||
} else {
|
||||
result = await fetchItemFromAllSources(itemId);
|
||||
}
|
||||
|
||||
if (result.combined) {
|
||||
results.push(result);
|
||||
console.log(`✓ ${result.combined.name} (${result.combined.slot || 'unknown slot'}) [${result.combined.sources.join(', ')}]`);
|
||||
} else {
|
||||
console.log(`✗ Failed to fetch data for item ${itemId}`);
|
||||
}
|
||||
|
||||
// Rate limiting
|
||||
if (i < itemIds.length - 1) {
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
}
|
||||
}
|
||||
|
||||
// Save detailed results
|
||||
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
||||
await fs.writeFile(
|
||||
`fetched-items-detailed-${timestamp}.json`,
|
||||
JSON.stringify(results, null, 2)
|
||||
);
|
||||
|
||||
// Validation
|
||||
if (options.validate && options.existing) {
|
||||
console.log('\nValidating against existing project data...');
|
||||
const existingItems = [];
|
||||
// This would need to parse the existing TypeScript files
|
||||
// For now, just show what we fetched
|
||||
|
||||
const validation = validateItemData(results, existingItems);
|
||||
console.log(`\nValidation Results:`);
|
||||
console.log(` Matches: ${validation.matches.length}`);
|
||||
console.log(` Mismatches: ${validation.mismatches.length}`);
|
||||
console.log(` New items: ${validation.newItems.length}`);
|
||||
|
||||
if (validation.mismatches.length > 0) {
|
||||
console.log('\nMismatches found:');
|
||||
validation.mismatches.forEach(mismatch => {
|
||||
console.log(` Item ${mismatch.id}: ${mismatch.issues.join(', ')}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Generate TypeScript code
|
||||
if (options.generate) {
|
||||
const validItems = results
|
||||
.map(r => r.combined)
|
||||
.filter(item => item.name && item.slot);
|
||||
|
||||
const tsCode = generateTypeScriptCode(validItems, options.generate);
|
||||
const filename = `${options.generate}.ts`;
|
||||
|
||||
await fs.writeFile(filename, tsCode);
|
||||
console.log(`\nGenerated TypeScript code in ${filename}`);
|
||||
}
|
||||
|
||||
// Summary
|
||||
console.log(`\nSummary:`);
|
||||
console.log(`Successfully fetched: ${results.length}/${itemIds.length} items`);
|
||||
|
||||
const slotCounts = {};
|
||||
results.forEach(result => {
|
||||
const slot = result.combined.slot || 'unknown';
|
||||
slotCounts[slot] = (slotCounts[slot] || 0) + 1;
|
||||
});
|
||||
|
||||
console.log('\nSlot distribution:');
|
||||
Object.entries(slotCounts).forEach(([slot, count]) => {
|
||||
console.log(` ${slot}: ${count}`);
|
||||
});
|
||||
}
|
||||
|
||||
// Run the script
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
main().catch(console.error);
|
||||
}
|
||||
|
||||
export { fetchItemFromAllSources, combineItemData, validateItemData, generateTypeScriptCode };
|
||||
@ -6,6 +6,7 @@ import { StateContext } from "./lib/context/StateContext";
|
||||
import { reducer, withLoadingAction } from "./lib/state";
|
||||
import { WeaponConfig, type ItemId } from "./lib/types";
|
||||
import { WeaponConfigPicker } from "./components/WeaponConfigPicker";
|
||||
import { SpecSelector } from "./components/SpecSelector";
|
||||
|
||||
function App() {
|
||||
const [state, dispatch] = useReducer(withLoadingAction(reducer), "loading");
|
||||
@ -50,6 +51,7 @@ function App() {
|
||||
<h1>WoW Gear Finder</h1>
|
||||
<h2>Config</h2>
|
||||
<WeaponConfigPicker />
|
||||
<SpecSelector />
|
||||
<h2>Equipment</h2>
|
||||
<Equipment
|
||||
state={state}
|
||||
|
||||
@ -41,9 +41,9 @@ const Slot = ({ slot, onUnequip }: SlotProps) => {
|
||||
|
||||
const equipedItems = state.equipedItems
|
||||
.map((item) => ({ ...item, item: ItemsById[item.id] }))
|
||||
.filter((item) => item && item.item.slot === slot);
|
||||
.filter((item) => item && item.item?.slot === slot);
|
||||
|
||||
const allItems = itemsForSlot(slot);
|
||||
const allItems = itemsForSlot(state.spec)(slot);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
35
src/components/SpecSelector.tsx
Normal file
35
src/components/SpecSelector.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import { useAppState } from "../lib/context/StateContext";
|
||||
import { Spec } from "../lib/types";
|
||||
|
||||
const SpecMap = Object.fromEntries(
|
||||
Object.entries(Spec).flatMap(([cls, specs]) =>
|
||||
Object.entries(specs).map(([spec, specId]) => [`${cls} ${spec}`, specId]),
|
||||
),
|
||||
);
|
||||
|
||||
export const SpecSelector = () => {
|
||||
const { state, dispatch } = useAppState();
|
||||
|
||||
const handleOnChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const value = parseInt(event.target.value?.trim(), 10);
|
||||
console.log("Selected spec ID: ", value);
|
||||
if (value) {
|
||||
dispatch({
|
||||
action: "changeSpec",
|
||||
spec: value as Spec,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<select onChange={handleOnChange} value={state.spec}>
|
||||
{Object.entries(SpecMap).map(([spec, id]) => (
|
||||
<option key={id} value={id}>
|
||||
{spec}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
276
src/lib/drops/aldani.json
Normal file
276
src/lib/drops/aldani.json
Normal file
@ -0,0 +1,276 @@
|
||||
[
|
||||
{
|
||||
"id": 242497,
|
||||
"name": "Azhiccaran Parapodia",
|
||||
"icon": "inv_devourersmallmount_light",
|
||||
"slot": "trinket",
|
||||
"specs": [],
|
||||
"source": "Eco-Dome Aldani"
|
||||
},
|
||||
{
|
||||
"id": 242494,
|
||||
"name": "Lily of the Eternal Weave",
|
||||
"icon": "inv_herb_karesh",
|
||||
"slot": "trinket",
|
||||
"specs": [
|
||||
261,
|
||||
254,
|
||||
62,
|
||||
1449,
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
255,
|
||||
577,
|
||||
63,
|
||||
64,
|
||||
270,
|
||||
262,
|
||||
1450,
|
||||
65,
|
||||
1451,
|
||||
256,
|
||||
257,
|
||||
1452,
|
||||
258,
|
||||
264,
|
||||
1444,
|
||||
265,
|
||||
266,
|
||||
267,
|
||||
1454,
|
||||
1465,
|
||||
1467,
|
||||
1468,
|
||||
1473,
|
||||
268,
|
||||
1456,
|
||||
581,
|
||||
103,
|
||||
104,
|
||||
253,
|
||||
260,
|
||||
1448,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
263
|
||||
],
|
||||
"source": "Eco-Dome Aldani"
|
||||
},
|
||||
{
|
||||
"id": 242491,
|
||||
"name": "Whispers of K'aresh",
|
||||
"icon": "inv_112_raidtrinkets_ring01_etherealnontechnologicalstyle_gold",
|
||||
"slot": "finger",
|
||||
"specs": [],
|
||||
"source": "Eco-Dome Aldani"
|
||||
},
|
||||
{
|
||||
"id": 242495,
|
||||
"name": "Incorporeal Warpclaw",
|
||||
"icon": "inv_misc_nightsaberclaw_mana",
|
||||
"slot": "trinket",
|
||||
"specs": [
|
||||
103,
|
||||
255,
|
||||
577,
|
||||
260,
|
||||
1448,
|
||||
581,
|
||||
268,
|
||||
1456,
|
||||
104,
|
||||
1447,
|
||||
253,
|
||||
261,
|
||||
254,
|
||||
1450,
|
||||
70,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
263,
|
||||
1444,
|
||||
250,
|
||||
251,
|
||||
252,
|
||||
1455,
|
||||
1451,
|
||||
66,
|
||||
71,
|
||||
72,
|
||||
1446,
|
||||
73
|
||||
],
|
||||
"source": "Eco-Dome Aldani"
|
||||
},
|
||||
{
|
||||
"id": 242481,
|
||||
"name": "Spellstrike Warplance",
|
||||
"icon": "inv_polearm_2h_outdoorethereal_c_01",
|
||||
"slot": "2h-weapon",
|
||||
"specs": [
|
||||
255,
|
||||
103,
|
||||
104,
|
||||
1447,
|
||||
268,
|
||||
269
|
||||
],
|
||||
"source": "Eco-Dome Aldani"
|
||||
},
|
||||
{
|
||||
"id": 242473,
|
||||
"name": "Spittle-Stained Trousers",
|
||||
"icon": "inv_pants_leather_outdoorethereal_c_01",
|
||||
"slot": "legs",
|
||||
"specs": [
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
270,
|
||||
1450,
|
||||
103,
|
||||
577,
|
||||
581,
|
||||
268,
|
||||
1456,
|
||||
104,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
260,
|
||||
261
|
||||
],
|
||||
"source": "Eco-Dome Aldani"
|
||||
},
|
||||
{
|
||||
"id": 242482,
|
||||
"name": "Reinforced Stalkerhide Vest",
|
||||
"icon": "inv_chest-_leather_outdoorethereal_c_01",
|
||||
"slot": "chest",
|
||||
"specs": [
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
270,
|
||||
1450,
|
||||
103,
|
||||
577,
|
||||
581,
|
||||
268,
|
||||
1456,
|
||||
104,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
260,
|
||||
261
|
||||
],
|
||||
"source": "Eco-Dome Aldani"
|
||||
},
|
||||
{
|
||||
"id": 242477,
|
||||
"name": "Wasteland Devotee's Wrappings",
|
||||
"icon": "inv_helm_cloth_outdoorethereal_c_01",
|
||||
"slot": "head",
|
||||
"specs": [
|
||||
62,
|
||||
1449,
|
||||
1452,
|
||||
256,
|
||||
63,
|
||||
64,
|
||||
265,
|
||||
257,
|
||||
258,
|
||||
266,
|
||||
267,
|
||||
1454
|
||||
],
|
||||
"source": "Eco-Dome Aldani"
|
||||
},
|
||||
{
|
||||
"id": 242470,
|
||||
"name": "Mandibular Bonewhacker",
|
||||
"icon": "inv_mace_1h_outdoorethereal_c_02",
|
||||
"slot": "1h-weapon",
|
||||
"specs": [
|
||||
251,
|
||||
72,
|
||||
1451,
|
||||
66,
|
||||
73,
|
||||
1446
|
||||
],
|
||||
"source": "Eco-Dome Aldani"
|
||||
},
|
||||
{
|
||||
"id": 242468,
|
||||
"name": "Al'dani Attendant's Gauze",
|
||||
"icon": "inv_bracer_cloth_outdoorethereal_c_01",
|
||||
"slot": "wrist",
|
||||
"specs": [
|
||||
62,
|
||||
1449,
|
||||
1452,
|
||||
256,
|
||||
63,
|
||||
64,
|
||||
265,
|
||||
257,
|
||||
258,
|
||||
266,
|
||||
267,
|
||||
1454
|
||||
],
|
||||
"source": "Eco-Dome Aldani"
|
||||
},
|
||||
{
|
||||
"id": 242486,
|
||||
"name": "Mantle of Wounded Fate",
|
||||
"icon": "inv_shoulder_leather_outdoorethereal_c_01",
|
||||
"slot": "shoulders",
|
||||
"specs": [
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
270,
|
||||
1450,
|
||||
103,
|
||||
577,
|
||||
581,
|
||||
268,
|
||||
1456,
|
||||
104,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
260,
|
||||
261
|
||||
],
|
||||
"source": "Eco-Dome Aldani"
|
||||
},
|
||||
{
|
||||
"id": 242490,
|
||||
"name": "Ancient Oracle's Caress",
|
||||
"icon": "inv_glove_cloth_outdoorethereal_c_01",
|
||||
"slot": "hands",
|
||||
"specs": [
|
||||
62,
|
||||
1449,
|
||||
1452,
|
||||
256,
|
||||
63,
|
||||
64,
|
||||
265,
|
||||
257,
|
||||
258,
|
||||
266,
|
||||
267,
|
||||
1454
|
||||
],
|
||||
"source": "Eco-Dome Aldani"
|
||||
}
|
||||
]
|
||||
@ -1,47 +0,0 @@
|
||||
import type { ItemId } from "../types";
|
||||
|
||||
export const Aldani = [
|
||||
{
|
||||
id: 242494 as ItemId,
|
||||
slot: "trinket",
|
||||
name: "Lily of the Eternal Weave",
|
||||
source: "aldani" as const,
|
||||
},
|
||||
{
|
||||
id: 242495 as ItemId,
|
||||
slot: "trinket",
|
||||
name: "Incorporeal Warpclaw",
|
||||
source: "aldani" as const,
|
||||
icon: "inv_misc_nightsaberclaw_mana",
|
||||
},
|
||||
{
|
||||
id: 242481 as ItemId,
|
||||
slot: "2h-weapon",
|
||||
name: "Spellstrike Warplance",
|
||||
source: "aldani" as const,
|
||||
},
|
||||
{
|
||||
id: 242473 as ItemId,
|
||||
slot: "legs",
|
||||
name: "Spittle-Stained Trousers",
|
||||
source: "aldani" as const,
|
||||
},
|
||||
{
|
||||
id: 242470 as ItemId,
|
||||
slot: "1h-weapon",
|
||||
name: "Mandibular Bonewhacker",
|
||||
source: "aldani" as const,
|
||||
},
|
||||
{
|
||||
id: 242486 as ItemId,
|
||||
slot: "shoulders",
|
||||
name: "Mantle of Wounded Fate",
|
||||
source: "aldani" as const,
|
||||
},
|
||||
{
|
||||
id: 242482 as ItemId,
|
||||
slot: "chest",
|
||||
name: "Reinforced Stalkerhide Vest",
|
||||
source: "aldani" as const,
|
||||
},
|
||||
] as const;
|
||||
316
src/lib/drops/ara-kara.json
Normal file
316
src/lib/drops/ara-kara.json
Normal file
@ -0,0 +1,316 @@
|
||||
[
|
||||
{
|
||||
"id": 219314,
|
||||
"name": "Ara-Kara Sacbrood",
|
||||
"icon": "inv_raid_mercurialegg_red",
|
||||
"slot": "trinket",
|
||||
"specs": [],
|
||||
"source": "Ara-Kara, City of Echoes"
|
||||
},
|
||||
{
|
||||
"id": 221159,
|
||||
"name": "Harvester's Interdiction",
|
||||
"icon": "inv_staff_2h_earthendungeon_c_02",
|
||||
"slot": "2h-weapon",
|
||||
"specs": [
|
||||
255,
|
||||
103,
|
||||
104,
|
||||
1447,
|
||||
268,
|
||||
269
|
||||
],
|
||||
"source": "Ara-Kara, City of Echoes"
|
||||
},
|
||||
{
|
||||
"id": 219317,
|
||||
"name": "Harvester's Edict",
|
||||
"icon": "inv_11_0_dungeon_oldgodstatuepiece_purple",
|
||||
"slot": "trinket",
|
||||
"specs": [
|
||||
261,
|
||||
254,
|
||||
62,
|
||||
1449,
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
255,
|
||||
577,
|
||||
63,
|
||||
64,
|
||||
270,
|
||||
262,
|
||||
1450,
|
||||
65,
|
||||
1451,
|
||||
256,
|
||||
257,
|
||||
1452,
|
||||
258,
|
||||
264,
|
||||
1444,
|
||||
265,
|
||||
266,
|
||||
267,
|
||||
1454,
|
||||
1465,
|
||||
1467,
|
||||
1468,
|
||||
1473,
|
||||
268,
|
||||
1456,
|
||||
581,
|
||||
103,
|
||||
104,
|
||||
253,
|
||||
260,
|
||||
1448,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
263
|
||||
],
|
||||
"source": "Ara-Kara, City of Echoes"
|
||||
},
|
||||
{
|
||||
"id": 221150,
|
||||
"name": "Arachnoid Soulcleaver",
|
||||
"icon": "inv_sword_1h_earthendungeon_c_02",
|
||||
"slot": "1h-weapon",
|
||||
"specs": [
|
||||
62,
|
||||
63,
|
||||
1451,
|
||||
64,
|
||||
270,
|
||||
266,
|
||||
65,
|
||||
265,
|
||||
267,
|
||||
1454,
|
||||
1465,
|
||||
1467,
|
||||
1468,
|
||||
1473
|
||||
],
|
||||
"source": "Ara-Kara, City of Echoes"
|
||||
},
|
||||
{
|
||||
"id": 221153,
|
||||
"name": "Gauzewoven Legguards",
|
||||
"icon": "inv_leather_earthendungeon_c_01_pant",
|
||||
"slot": "legs",
|
||||
"specs": [
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
270,
|
||||
1450,
|
||||
103,
|
||||
577,
|
||||
581,
|
||||
268,
|
||||
1456,
|
||||
104,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
260,
|
||||
261
|
||||
],
|
||||
"source": "Ara-Kara, City of Echoes"
|
||||
},
|
||||
{
|
||||
"id": 221157,
|
||||
"name": "Unbreakable Beetlebane Bindings",
|
||||
"icon": "inv_leather_earthendungeon_c_01_bracer",
|
||||
"slot": "wrist",
|
||||
"specs": [
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
270,
|
||||
1450,
|
||||
103,
|
||||
577,
|
||||
581,
|
||||
268,
|
||||
1456,
|
||||
104,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
260,
|
||||
261
|
||||
],
|
||||
"source": "Ara-Kara, City of Echoes"
|
||||
},
|
||||
{
|
||||
"id": 219316,
|
||||
"name": "Ceaseless Swarmgland",
|
||||
"icon": "inv_misc_organmass_color2",
|
||||
"slot": "trinket",
|
||||
"specs": [
|
||||
103,
|
||||
255,
|
||||
577,
|
||||
260,
|
||||
1448,
|
||||
581,
|
||||
268,
|
||||
1456,
|
||||
104,
|
||||
1447,
|
||||
253,
|
||||
261,
|
||||
254,
|
||||
1450,
|
||||
70,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
263,
|
||||
1444,
|
||||
250,
|
||||
251,
|
||||
252,
|
||||
1455,
|
||||
1451,
|
||||
66,
|
||||
71,
|
||||
72,
|
||||
1446,
|
||||
73
|
||||
],
|
||||
"source": "Ara-Kara, City of Echoes"
|
||||
},
|
||||
{
|
||||
"id": 221158,
|
||||
"name": "Burrower's Cinch",
|
||||
"icon": "inv_belt_cloth_earthendungeon_c_01",
|
||||
"slot": "waist",
|
||||
"specs": [
|
||||
62,
|
||||
1449,
|
||||
1452,
|
||||
256,
|
||||
63,
|
||||
64,
|
||||
265,
|
||||
257,
|
||||
258,
|
||||
266,
|
||||
267,
|
||||
1454
|
||||
],
|
||||
"source": "Ara-Kara, City of Echoes"
|
||||
},
|
||||
{
|
||||
"id": 221164,
|
||||
"name": "Archaic Venomancer's Legwraps",
|
||||
"icon": "inv_pant_cloth_earthendungeon_c_01",
|
||||
"slot": "legs",
|
||||
"specs": [
|
||||
62,
|
||||
1449,
|
||||
1452,
|
||||
256,
|
||||
63,
|
||||
64,
|
||||
265,
|
||||
257,
|
||||
258,
|
||||
266,
|
||||
267,
|
||||
1454
|
||||
],
|
||||
"source": "Ara-Kara, City of Echoes"
|
||||
},
|
||||
{
|
||||
"id": 221163,
|
||||
"name": "Whispering Mask",
|
||||
"icon": "inv_leather_earthendungeon_c_01_helm",
|
||||
"slot": "head",
|
||||
"specs": [
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
270,
|
||||
1450,
|
||||
103,
|
||||
577,
|
||||
581,
|
||||
268,
|
||||
1456,
|
||||
104,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
260,
|
||||
261
|
||||
],
|
||||
"source": "Ara-Kara, City of Echoes"
|
||||
},
|
||||
{
|
||||
"id": 221154,
|
||||
"name": "Swarmcaller's Shroud",
|
||||
"icon": "inv_cape_mail_earthendungeon_c_01",
|
||||
"slot": "1h-weapon",
|
||||
"specs": [
|
||||
261,
|
||||
254,
|
||||
62,
|
||||
1449,
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
255,
|
||||
577,
|
||||
63,
|
||||
64,
|
||||
270,
|
||||
262,
|
||||
1450,
|
||||
65,
|
||||
1451,
|
||||
256,
|
||||
250,
|
||||
257,
|
||||
1452,
|
||||
73,
|
||||
258,
|
||||
264,
|
||||
1444,
|
||||
66,
|
||||
265,
|
||||
1446,
|
||||
266,
|
||||
267,
|
||||
1454,
|
||||
1465,
|
||||
1467,
|
||||
1468,
|
||||
1473,
|
||||
268,
|
||||
1456,
|
||||
581,
|
||||
103,
|
||||
104,
|
||||
253,
|
||||
260,
|
||||
1448,
|
||||
70,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
263,
|
||||
251,
|
||||
252,
|
||||
1455,
|
||||
71,
|
||||
72
|
||||
],
|
||||
"source": "Ara-Kara, City of Echoes"
|
||||
}
|
||||
]
|
||||
@ -1,52 +0,0 @@
|
||||
import type { ItemId } from "../types";
|
||||
|
||||
export const AraKara = [
|
||||
{
|
||||
id: 221159 as ItemId,
|
||||
slot: "2h-weapon",
|
||||
name: "Harvester's Interdiction",
|
||||
source: "ara-kara",
|
||||
},
|
||||
{
|
||||
id: 219317 as ItemId,
|
||||
slot: "trinket",
|
||||
name: "Harvester's Edict",
|
||||
source: "ara-kara",
|
||||
},
|
||||
{
|
||||
id: 219316 as ItemId,
|
||||
slot: "trinket",
|
||||
name: "Ceaseless Swarmgland",
|
||||
source: "ara-kara",
|
||||
},
|
||||
{
|
||||
id: 221157 as ItemId,
|
||||
slot: "wrist",
|
||||
name: "Unbreakable Beetlebane Bindings",
|
||||
source: "ara-kara",
|
||||
},
|
||||
{
|
||||
id: 221153 as ItemId,
|
||||
slot: "legs",
|
||||
name: "Gauzewoven Legguards",
|
||||
source: "ara-kara",
|
||||
},
|
||||
{
|
||||
id: 221154 as ItemId,
|
||||
slot: "back",
|
||||
name: "Swarmcaller's Shroud",
|
||||
source: "ara-kara",
|
||||
},
|
||||
{
|
||||
id: 221163 as ItemId,
|
||||
slot: "head",
|
||||
name: "Whispering Mask",
|
||||
source: "ara-kara",
|
||||
},
|
||||
{
|
||||
id: 219315 as ItemId,
|
||||
slot: "trinket",
|
||||
name: "Refracting Aggression Module",
|
||||
source: "ara-kara",
|
||||
},
|
||||
] as const;
|
||||
134
src/lib/drops/dawnbreaker.json
Normal file
134
src/lib/drops/dawnbreaker.json
Normal file
@ -0,0 +1,134 @@
|
||||
[
|
||||
{
|
||||
"id": 219312,
|
||||
"name": "Empowering Crystal of Anub'ikkaj",
|
||||
"icon": "inv_arathordungeon_fragment_color5",
|
||||
"slot": "trinket",
|
||||
"specs": [
|
||||
261, 254, 62, 1449, 102, 1447, 105, 255, 577, 63, 64, 270, 262, 1450, 65,
|
||||
1451, 256, 257, 1452, 258, 264, 1444, 265, 266, 267, 1454, 1465, 1467,
|
||||
1468, 1473, 268, 1456, 581, 103, 104, 253, 260, 1448, 269, 259, 1453, 263
|
||||
],
|
||||
"source": "dawnbreaker"
|
||||
},
|
||||
{
|
||||
"id": 221136,
|
||||
"name": "Devout Zealot's Ring",
|
||||
"icon": "inv_11_0_nerubian_ring_01_color4",
|
||||
"slot": "finger",
|
||||
"specs": [],
|
||||
"source": "dawnbreaker"
|
||||
},
|
||||
{
|
||||
"id": 221141,
|
||||
"name": "High Nerubian Signet",
|
||||
"icon": "inv_11_0_nerubian_ring_02_color5",
|
||||
"slot": "finger",
|
||||
"specs": [],
|
||||
"source": "dawnbreaker"
|
||||
},
|
||||
{
|
||||
"id": 221135,
|
||||
"name": "Fanatic's Blackened Shoulderwraps",
|
||||
"icon": "inv_shoulder_cloth_earthendungeon_c_01",
|
||||
"slot": "shoulders",
|
||||
"specs": [62, 1449, 1452, 256, 63, 64, 265, 257, 258, 266, 267, 1454],
|
||||
"source": "dawnbreaker"
|
||||
},
|
||||
{
|
||||
"id": 219311,
|
||||
"name": "Void Pactstone",
|
||||
"icon": "inv_10_alchemy_alchemystone_color4",
|
||||
"slot": "trinket",
|
||||
"specs": [66, 250, 251, 1455, 252, 72, 1451, 70, 71, 1446, 73],
|
||||
"source": "dawnbreaker"
|
||||
},
|
||||
{
|
||||
"id": 221149,
|
||||
"name": "Membranous Slippers",
|
||||
"icon": "inv_boot_cloth_earthendungeon_c_01",
|
||||
"slot": "feet",
|
||||
"specs": [62, 1449, 1452, 256, 63, 64, 265, 257, 258, 266, 267, 1454],
|
||||
"source": "dawnbreaker"
|
||||
},
|
||||
{
|
||||
"id": 221137,
|
||||
"name": "Black Shepherd's Guisarme",
|
||||
"icon": "inv_polearm_2h_earthendungeon_c_02",
|
||||
"slot": "2h-weapon",
|
||||
"specs": [255, 103, 104, 1447, 268, 269],
|
||||
"source": "dawnbreaker"
|
||||
},
|
||||
{
|
||||
"id": 221144,
|
||||
"name": "Zephyrous Sail Carver",
|
||||
"icon": "inv_sword_1h_earthendungeon_c_02",
|
||||
"slot": "1h-weapon",
|
||||
"specs": [577, 260, 268, 581, 1450, 269],
|
||||
"source": "dawnbreaker"
|
||||
},
|
||||
{
|
||||
"id": 221142,
|
||||
"name": "Scheming Assailer's Bands",
|
||||
"icon": "inv_leather_earthendungeon_c_01_bracer",
|
||||
"slot": "wrist",
|
||||
"specs": [
|
||||
102, 1447, 105, 270, 1450, 103, 577, 581, 268, 1456, 104, 269, 259, 1453,
|
||||
260, 261
|
||||
],
|
||||
"source": "dawnbreaker"
|
||||
},
|
||||
{
|
||||
"id": 221148,
|
||||
"name": "Epaulets of the Clipped Wings",
|
||||
"icon": "inv_leather_earthendungeon_c_01_shoulder",
|
||||
"slot": "shoulders",
|
||||
"specs": [
|
||||
102, 1447, 105, 270, 1450, 103, 577, 581, 268, 1456, 104, 269, 259, 1453,
|
||||
260, 261
|
||||
],
|
||||
"source": "dawnbreaker"
|
||||
},
|
||||
{
|
||||
"id": 219313,
|
||||
"name": "Mereldar's Toll",
|
||||
"icon": "inv_arathordungeon_bell_color1",
|
||||
"slot": "trinket",
|
||||
"specs": [
|
||||
62, 1449, 102, 1447, 105, 63, 64, 270, 262, 1450, 65, 1451, 256, 257,
|
||||
1452, 258, 264, 1444, 265, 266, 267, 1454, 1465, 1467, 1468, 1473
|
||||
],
|
||||
"source": "dawnbreaker"
|
||||
},
|
||||
{
|
||||
"id": 221134,
|
||||
"name": "Shadow Congregant's Belt",
|
||||
"icon": "inv_leather_earthendungeon_c_01_belt",
|
||||
"slot": "waist",
|
||||
"specs": [
|
||||
102, 1447, 105, 270, 1450, 103, 577, 581, 268, 1456, 104, 269, 259, 1453,
|
||||
260, 261
|
||||
],
|
||||
"source": "dawnbreaker"
|
||||
},
|
||||
{
|
||||
"id": 221145,
|
||||
"name": "Shipwrecker's Bludgeon",
|
||||
"icon": "inv_mace_1h_earthendungeon_c_01",
|
||||
"slot": "1h-weapon",
|
||||
"specs": [251, 72, 1451, 66, 73, 1446],
|
||||
"source": "dawnbreaker"
|
||||
},
|
||||
{
|
||||
"id": 221132,
|
||||
"name": "Overflowing Umbral Pail",
|
||||
"icon": "inv_offhand_1h_earthendungeon_c_01",
|
||||
"slot": "off-hand",
|
||||
"specs": [
|
||||
62, 1449, 102, 1447, 105, 63, 64, 270, 262, 1450, 65, 1451, 256, 257,
|
||||
1452, 258, 264, 1444, 265, 266, 267, 1454, 1465, 1467, 1468, 1473
|
||||
],
|
||||
"source": "dawnbreaker"
|
||||
}
|
||||
]
|
||||
|
||||
@ -60,7 +60,7 @@ export const Dawnbreaker = [
|
||||
slot: "waist",
|
||||
name: "Behemoth's Eroded Cinch",
|
||||
source: "dawnbreaker" as const,
|
||||
},
|
||||
|
||||
{
|
||||
id: 212453,
|
||||
slot: "trinket",
|
||||
|
||||
150
src/lib/drops/floodgate.json
Normal file
150
src/lib/drops/floodgate.json
Normal file
@ -0,0 +1,150 @@
|
||||
[
|
||||
{
|
||||
"id": 232541,
|
||||
"name": "Improvised Seaforium Pacemaker",
|
||||
"icon": "ability_blackhand_attachedslagbombs",
|
||||
"slot": "trinket",
|
||||
"specs": [
|
||||
103, 255, 577, 260, 1448, 581, 268, 1456, 104, 1447, 253, 261, 254, 1450,
|
||||
70, 269, 259, 1453, 263, 1444, 250, 251, 252, 1455, 1451, 66, 71, 72,
|
||||
1446, 73
|
||||
],
|
||||
"source": "Operation: Floodgate"
|
||||
},
|
||||
{
|
||||
"id": 251880,
|
||||
"name": "Momma's Mega Medallion",
|
||||
"icon": "inv_112_raidtrinkets_necklace02_etherealribbonorrunestyle_dark",
|
||||
"slot": "neck",
|
||||
"specs": [],
|
||||
"source": "Operation: Floodgate"
|
||||
},
|
||||
{
|
||||
"id": 232543,
|
||||
"name": "Ringing Ritual Mud",
|
||||
"icon": "inv_misc_food_legion_goomolasses_pool",
|
||||
"slot": "trinket",
|
||||
"specs": [],
|
||||
"source": "Operation: Floodgate"
|
||||
},
|
||||
{
|
||||
"id": 234499,
|
||||
"name": "Disturbed Kelp Wraps",
|
||||
"icon": "inv_leather_outdoorundermine_c_01_bracer",
|
||||
"slot": "wrist",
|
||||
"specs": [
|
||||
102, 1447, 105, 270, 1450, 103, 577, 581, 268, 1456, 104, 269, 259, 1453,
|
||||
260, 261
|
||||
],
|
||||
"source": "Operation: Floodgate"
|
||||
},
|
||||
{
|
||||
"id": 232545,
|
||||
"name": "Gigazap's Zap-Cap",
|
||||
"icon": "inv_engineering_90_lightningbox",
|
||||
"slot": "trinket",
|
||||
"specs": [
|
||||
62, 1449, 102, 1447, 105, 63, 64, 270, 262, 1450, 65, 1451, 256, 257,
|
||||
1452, 258, 264, 1444, 265, 266, 267, 1454, 1465, 1467, 1468, 1473
|
||||
],
|
||||
"source": "Operation: Floodgate"
|
||||
},
|
||||
{
|
||||
"id": 246274,
|
||||
"name": "Geezle's Zapstep Boots",
|
||||
"icon": "inv_leather_outdoorundermine_c_01_boot",
|
||||
"slot": "feet",
|
||||
"specs": [
|
||||
102, 1447, 105, 270, 1450, 103, 577, 581, 268, 1456, 104, 269, 259, 1453,
|
||||
260, 261
|
||||
],
|
||||
"source": "Operation: Floodgate"
|
||||
},
|
||||
{
|
||||
"id": 234497,
|
||||
"name": "Nonconductive Kill-o-Socks",
|
||||
"icon": "inv_cloth_outdoorundermine_c_01_boot",
|
||||
"slot": "feet",
|
||||
"specs": [62, 1449, 1452, 256, 63, 64, 265, 257, 258, 266, 267, 1454],
|
||||
"source": "Operation: Floodgate"
|
||||
},
|
||||
{
|
||||
"id": 234494,
|
||||
"name": "Gallytech Turbo-Tiller",
|
||||
"icon": "inv_polearm_2h_outdoorundermine_c_01_purple",
|
||||
"slot": "2h-weapon",
|
||||
"specs": [255, 103, 104, 1447, 268, 269],
|
||||
"source": "Operation: Floodgate"
|
||||
},
|
||||
{
|
||||
"id": 232542,
|
||||
"name": "Darkfuse Medichopper",
|
||||
"icon": "inv_111_healraydrone_blackwater",
|
||||
"slot": "trinket",
|
||||
"specs": [
|
||||
62, 1449, 102, 1447, 105, 63, 64, 270, 262, 1450, 65, 1451, 256, 257,
|
||||
1452, 258, 264, 1444, 265, 266, 267, 1454, 1465, 1467, 1468, 1473
|
||||
],
|
||||
"source": "Operation: Floodgate"
|
||||
},
|
||||
{
|
||||
"id": 234498,
|
||||
"name": "Waterworks Filtration Mask",
|
||||
"icon": "inv_leather_outdoorundermine_c_01_helm",
|
||||
"slot": "head",
|
||||
"specs": [
|
||||
102, 1447, 105, 270, 1450, 103, 577, 581, 268, 1456, 104, 269, 259, 1453,
|
||||
260, 261
|
||||
],
|
||||
"source": "Operation: Floodgate"
|
||||
},
|
||||
{
|
||||
"id": 234495,
|
||||
"name": "Razorchoke Slacks",
|
||||
"icon": "inv_cloth_outdoorundermine_c_01_pant",
|
||||
"slot": "legs",
|
||||
"specs": [62, 1449, 1452, 256, 63, 64, 265, 257, 258, 266, 267, 1454],
|
||||
"source": "Operation: Floodgate"
|
||||
},
|
||||
{
|
||||
"id": 246279,
|
||||
"name": "Fizzlefuse Cuffs",
|
||||
"icon": "inv_cloth_outdoorundermine_c_01_bracer",
|
||||
"slot": "wrist",
|
||||
"specs": [62, 1449, 1452, 256, 63, 64, 265, 257, 258, 266, 267, 1454],
|
||||
"source": "Operation: Floodgate"
|
||||
},
|
||||
{
|
||||
"id": 234496,
|
||||
"name": "Saboteur's Rubber Jacket",
|
||||
"icon": "inv_cloth_outdoorundermine_c_01_chest",
|
||||
"slot": "chest",
|
||||
"specs": [62, 1449, 1452, 256, 63, 64, 265, 257, 258, 266, 267, 1454],
|
||||
"source": "Operation: Floodgate"
|
||||
},
|
||||
{
|
||||
"id": 234500,
|
||||
"name": "Mechanized Junkpads",
|
||||
"icon": "inv_leather_outdoorundermine_c_01_shoulder",
|
||||
"slot": "shoulders",
|
||||
"specs": [
|
||||
102, 1447, 105, 270, 1450, 103, 577, 581, 268, 1456, 104, 269, 259, 1453,
|
||||
260, 261
|
||||
],
|
||||
"source": "Operation: Floodgate"
|
||||
},
|
||||
{
|
||||
"id": 234507,
|
||||
"name": "Electrician's Siphoning Filter",
|
||||
"icon": "inv_mail_outdoorundermine_c_01_cape",
|
||||
"slot": "1h-weapon",
|
||||
"specs": [
|
||||
261, 254, 62, 1449, 102, 1447, 105, 255, 577, 63, 64, 270, 262, 1450, 65,
|
||||
1451, 256, 250, 257, 1452, 73, 258, 264, 1444, 66, 265, 1446, 266, 267,
|
||||
1454, 1465, 1467, 1468, 1473, 268, 1456, 581, 103, 104, 253, 260, 1448,
|
||||
70, 269, 259, 1453, 263, 251, 252, 1455, 71, 72
|
||||
],
|
||||
"source": "Operation: Floodgate"
|
||||
}
|
||||
]
|
||||
|
||||
@ -1,52 +0,0 @@
|
||||
import type { ItemId } from "../types";
|
||||
|
||||
export const Floodgate = [
|
||||
{
|
||||
id: 232541 as ItemId,
|
||||
slot: "trinket",
|
||||
name: "Improvised Seaforium Pacemaker",
|
||||
source: "floodgate" as const,
|
||||
},
|
||||
{
|
||||
id: 232543 as ItemId,
|
||||
slot: "trinket",
|
||||
name: "Ringing Ritual Mud",
|
||||
source: "floodgate" as const,
|
||||
},
|
||||
{
|
||||
id: 234499 as ItemId,
|
||||
slot: "wrist",
|
||||
name: "Disturbed Kelp Wraps",
|
||||
source: "floodgate" as const,
|
||||
},
|
||||
{
|
||||
id: 246274 as ItemId,
|
||||
slot: "feet",
|
||||
name: "Geezle's Zapstep Boots",
|
||||
source: "floodgate" as const,
|
||||
},
|
||||
{
|
||||
id: 234494 as ItemId,
|
||||
slot: "2h-weapon",
|
||||
name: "Gallytech Turbo-Tiller",
|
||||
source: "floodgate" as const,
|
||||
},
|
||||
{
|
||||
id: 234498 as ItemId,
|
||||
slot: "head",
|
||||
name: "Waterworks Filtration Mask",
|
||||
source: "floodgate" as const,
|
||||
},
|
||||
{
|
||||
id: 234507 as ItemId,
|
||||
slot: "back",
|
||||
name: "Electrician's Siphoning Filter",
|
||||
source: "floodgate" as const,
|
||||
},
|
||||
{
|
||||
id: 234500 as ItemId,
|
||||
slot: "shoulders",
|
||||
name: "Mechanized Junkpads",
|
||||
source: "floodgate" as const,
|
||||
},
|
||||
] as const;
|
||||
449
src/lib/drops/halls-of-atonement.json
Normal file
449
src/lib/drops/halls-of-atonement.json
Normal file
@ -0,0 +1,449 @@
|
||||
[
|
||||
{
|
||||
"id": 246344,
|
||||
"name": "Cursed Stone Idol",
|
||||
"icon": "inv_qirajidol_onyx",
|
||||
"slot": "trinket",
|
||||
"specs": [
|
||||
103,
|
||||
255,
|
||||
577,
|
||||
260,
|
||||
1448,
|
||||
581,
|
||||
268,
|
||||
1456,
|
||||
104,
|
||||
1447,
|
||||
253,
|
||||
261,
|
||||
254,
|
||||
1450,
|
||||
70,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
263,
|
||||
1444,
|
||||
250,
|
||||
251,
|
||||
252,
|
||||
1455,
|
||||
1451,
|
||||
66,
|
||||
71,
|
||||
72,
|
||||
1446,
|
||||
73
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 178824,
|
||||
"name": "Signet of the False Accuser",
|
||||
"icon": "inv_ring_revendrethraid_01_gold",
|
||||
"slot": "finger",
|
||||
"specs": [],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 178827,
|
||||
"name": "Sin Stained Pendant",
|
||||
"icon": "inv_7_0raid_necklace_03a",
|
||||
"slot": "neck",
|
||||
"specs": [],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 178829,
|
||||
"name": "Nathrian Ferula",
|
||||
"icon": "inv_staff_2h_oribosdungeon_c_01",
|
||||
"slot": "2h-weapon",
|
||||
"specs": [
|
||||
62,
|
||||
1449,
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
256,
|
||||
63,
|
||||
64,
|
||||
270,
|
||||
257,
|
||||
1452,
|
||||
258,
|
||||
262,
|
||||
264,
|
||||
265,
|
||||
266,
|
||||
267,
|
||||
1454,
|
||||
1465,
|
||||
1467,
|
||||
1468,
|
||||
1473
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 178832,
|
||||
"name": "Gloves of Haunting Fixation",
|
||||
"icon": "inv_glove_leather_oribosdungeon_c_01",
|
||||
"slot": "hands",
|
||||
"specs": [
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
270,
|
||||
1450,
|
||||
103,
|
||||
577,
|
||||
581,
|
||||
268,
|
||||
1456,
|
||||
104,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
260,
|
||||
261
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 178826,
|
||||
"name": "Sunblood Amethyst",
|
||||
"icon": "inv_jewelcrafting_nightseye_01",
|
||||
"slot": "trinket",
|
||||
"specs": [],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 246284,
|
||||
"name": "Nathrian Reliquary",
|
||||
"icon": "inv_offhand_1h_oribosdungeon_c_01",
|
||||
"slot": "off-hand",
|
||||
"specs": [
|
||||
62,
|
||||
1449,
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
63,
|
||||
64,
|
||||
270,
|
||||
262,
|
||||
1450,
|
||||
65,
|
||||
1451,
|
||||
256,
|
||||
257,
|
||||
1452,
|
||||
258,
|
||||
264,
|
||||
1444,
|
||||
265,
|
||||
266,
|
||||
267,
|
||||
1454,
|
||||
1465,
|
||||
1467,
|
||||
1468,
|
||||
1473
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 178822,
|
||||
"name": "Cord of the Dark Word",
|
||||
"icon": "inv_belt_cloth_oribosdungeon_c_01",
|
||||
"slot": "waist",
|
||||
"specs": [
|
||||
62,
|
||||
1449,
|
||||
1452,
|
||||
256,
|
||||
63,
|
||||
64,
|
||||
265,
|
||||
257,
|
||||
258,
|
||||
266,
|
||||
267,
|
||||
1454
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 246276,
|
||||
"name": "Sinlight Shoulderpads",
|
||||
"icon": "inv_shoulder_cloth_oribosdungeon_c_01",
|
||||
"slot": "shoulders",
|
||||
"specs": [
|
||||
62,
|
||||
1449,
|
||||
1452,
|
||||
256,
|
||||
63,
|
||||
64,
|
||||
265,
|
||||
257,
|
||||
258,
|
||||
266,
|
||||
267,
|
||||
1454
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 178819,
|
||||
"name": "Skyterror's Stonehide Leggings",
|
||||
"icon": "inv_pant_leather_oribosdungeon_c_01",
|
||||
"slot": "legs",
|
||||
"specs": [
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
270,
|
||||
1450,
|
||||
103,
|
||||
577,
|
||||
581,
|
||||
268,
|
||||
1456,
|
||||
104,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
260,
|
||||
261
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 246273,
|
||||
"name": "Vest of Refracted Shadows",
|
||||
"icon": "inv_chest_leather_oribosdungeon_c_01",
|
||||
"slot": "chest",
|
||||
"specs": [
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
270,
|
||||
1450,
|
||||
103,
|
||||
577,
|
||||
581,
|
||||
268,
|
||||
1456,
|
||||
104,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
260,
|
||||
261
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 178831,
|
||||
"name": "Slippers of Leavened Station",
|
||||
"icon": "inv_boot_cloth_oribosdungeon_c_01",
|
||||
"slot": "feet",
|
||||
"specs": [
|
||||
62,
|
||||
1449,
|
||||
1452,
|
||||
256,
|
||||
63,
|
||||
64,
|
||||
265,
|
||||
257,
|
||||
258,
|
||||
266,
|
||||
267,
|
||||
1454
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 178833,
|
||||
"name": "Stonefiend Shaper's Mitts",
|
||||
"icon": "inv_glove_cloth_oribosdungeon_c_01",
|
||||
"slot": "hands",
|
||||
"specs": [
|
||||
62,
|
||||
1449,
|
||||
1452,
|
||||
256,
|
||||
63,
|
||||
64,
|
||||
265,
|
||||
257,
|
||||
258,
|
||||
266,
|
||||
267,
|
||||
1454
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 178823,
|
||||
"name": "Waistcord of Dark Devotion",
|
||||
"icon": "inv_belt_leather_oribosdungeon_c_01",
|
||||
"slot": "waist",
|
||||
"specs": [
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
270,
|
||||
1450,
|
||||
103,
|
||||
577,
|
||||
581,
|
||||
268,
|
||||
1456,
|
||||
104,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
260,
|
||||
261
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 178834,
|
||||
"name": "Stoneguardian's Morningstar",
|
||||
"icon": "inv_mace_1h_bastionquest_b_02",
|
||||
"slot": "1h-weapon",
|
||||
"specs": [
|
||||
260,
|
||||
268,
|
||||
1450,
|
||||
269,
|
||||
263
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 178825,
|
||||
"name": "Pulsating Stoneheart",
|
||||
"icon": "inv_misc_gem_bloodstone_01",
|
||||
"slot": "trinket",
|
||||
"specs": [
|
||||
103,
|
||||
255,
|
||||
577,
|
||||
260,
|
||||
1448,
|
||||
581,
|
||||
268,
|
||||
1456,
|
||||
104,
|
||||
1447,
|
||||
253,
|
||||
261,
|
||||
254,
|
||||
1450,
|
||||
70,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
263,
|
||||
1444,
|
||||
250,
|
||||
251,
|
||||
252,
|
||||
1455,
|
||||
1451,
|
||||
66,
|
||||
71,
|
||||
72,
|
||||
1446,
|
||||
73
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 178813,
|
||||
"name": "Sinlight Shroud",
|
||||
"icon": "inv_robe_cloth_oribosdungeon_c_01",
|
||||
"slot": "chest",
|
||||
"specs": [
|
||||
62,
|
||||
1449,
|
||||
1452,
|
||||
256,
|
||||
63,
|
||||
64,
|
||||
265,
|
||||
257,
|
||||
258,
|
||||
266,
|
||||
267,
|
||||
1454
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 178817,
|
||||
"name": "Hood of Refracted Shadows",
|
||||
"icon": "inv_helm_leather_oribosdungeon_c_01",
|
||||
"slot": "head",
|
||||
"specs": [
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
270,
|
||||
1450,
|
||||
103,
|
||||
577,
|
||||
581,
|
||||
268,
|
||||
1456,
|
||||
104,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
260,
|
||||
261
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 178828,
|
||||
"name": "Nathrian Tabernacle",
|
||||
"icon": "inv_offhand_1h_oribosdungeon_c_01",
|
||||
"slot": "off-hand",
|
||||
"specs": [
|
||||
62,
|
||||
1449,
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
63,
|
||||
64,
|
||||
270,
|
||||
262,
|
||||
1450,
|
||||
65,
|
||||
1451,
|
||||
256,
|
||||
257,
|
||||
1452,
|
||||
258,
|
||||
264,
|
||||
1444,
|
||||
265,
|
||||
266,
|
||||
267,
|
||||
1454,
|
||||
1465,
|
||||
1467,
|
||||
1468,
|
||||
1473
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
}
|
||||
]
|
||||
@ -1,52 +0,0 @@
|
||||
import type { ItemId } from "../types";
|
||||
|
||||
export const HallsOfAtonement = [
|
||||
{
|
||||
id: 246344 as ItemId,
|
||||
slot: "trinket",
|
||||
name: "Cursed Stone Idol",
|
||||
source: "halls-of-atonement" as const,
|
||||
},
|
||||
{
|
||||
id: 178832 as ItemId,
|
||||
slot: "hands",
|
||||
name: "Gloves of Haunting Fixation",
|
||||
source: "halls-of-atonement" as const,
|
||||
},
|
||||
{
|
||||
id: 178819 as ItemId,
|
||||
slot: "legs",
|
||||
name: "Skyterror's Stonehide Leggings",
|
||||
source: "halls-of-atonement" as const,
|
||||
},
|
||||
{
|
||||
id: 246273 as ItemId,
|
||||
slot: "chest",
|
||||
name: "Vest of Refracted Shadows",
|
||||
source: "halls-of-atonement" as const,
|
||||
},
|
||||
{
|
||||
id: 178834 as ItemId,
|
||||
slot: "1h-weapon",
|
||||
name: "Stoneguardian's Morningstar",
|
||||
source: "halls-of-atonement" as const,
|
||||
},
|
||||
{
|
||||
id: 178823 as ItemId,
|
||||
slot: "waist",
|
||||
name: "Waistcord of Dark Devotion",
|
||||
source: "halls-of-atonement" as const,
|
||||
},
|
||||
{
|
||||
id: 178825 as ItemId,
|
||||
slot: "trinket",
|
||||
name: "Pulsating Stoneheart",
|
||||
source: "halls-of-atonement" as const,
|
||||
},
|
||||
{
|
||||
id: 178817 as ItemId,
|
||||
slot: "head",
|
||||
name: "Hood of Refracted Shadows",
|
||||
source: "halls-of-atonement" as const,
|
||||
},
|
||||
] as const;
|
||||
@ -1,23 +1,24 @@
|
||||
import type { Item } from "../types";
|
||||
import { Aldani } from "./aldani";
|
||||
import { AraKara } from "./ara-kara";
|
||||
import Aldani from "./aldani.json";
|
||||
import AraKara from "./ara-kara.json";
|
||||
import Dawnbreaker from "./dawnbreaker.json";
|
||||
import Floodgate from "./floodgate.json";
|
||||
import PrioryOfTheSacredFlame from "./priory.json";
|
||||
import Tazavesh from "./tazavesh.json";
|
||||
import { Crafted } from "./crafted";
|
||||
import { Dawnbreaker } from "./dawnbreaker";
|
||||
import { Floodgate } from "./floodgate";
|
||||
import { HallsOfAtonement } from "./halls-of-atonement";
|
||||
import { ManaforgeOmega } from "./manaforge-omega";
|
||||
import { PrioryOfTheSacredFlame } from "./priory";
|
||||
import { Streets, Gambit } from "./tazavesh";
|
||||
import HallsOfAtonement from "./halls-of-atonement.json";
|
||||
import ManaforgeOmega from "./manaforge-omega.json";
|
||||
import Tier from "./tww-s3-tier.json";
|
||||
|
||||
export const AllItems: Item[] = [
|
||||
export const AllItems = [
|
||||
...PrioryOfTheSacredFlame,
|
||||
...Aldani,
|
||||
...AraKara,
|
||||
...Dawnbreaker,
|
||||
...Floodgate,
|
||||
...HallsOfAtonement,
|
||||
...Streets,
|
||||
...Gambit,
|
||||
...Tazavesh,
|
||||
...ManaforgeOmega,
|
||||
...Crafted,
|
||||
];
|
||||
...Tier,
|
||||
] as Item[];
|
||||
|
||||
1158
src/lib/drops/manaforge-omega.json
Normal file
1158
src/lib/drops/manaforge-omega.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,209 +0,0 @@
|
||||
import { Tag, type ItemId } from "../types";
|
||||
|
||||
export const ManaforgeOmega = [
|
||||
{
|
||||
id: 237673 as ItemId,
|
||||
name: "Half-Mask of Fallen Storms",
|
||||
slot: "head",
|
||||
source: "manaforge omega",
|
||||
tags: [Tag.Tier],
|
||||
},
|
||||
{
|
||||
id: 237674 as ItemId,
|
||||
name: "Grasp of Fallen Storms",
|
||||
slot: "hands",
|
||||
source: "manaforge omega",
|
||||
tags: [Tag.Tier],
|
||||
},
|
||||
{
|
||||
id: 237676 as ItemId,
|
||||
name: "Gi of Fallen Storms",
|
||||
slot: "chest",
|
||||
source: "manaforge omega",
|
||||
tags: [Tag.Tier],
|
||||
},
|
||||
{
|
||||
id: 237672 as ItemId,
|
||||
name: "Legwraps of Fallen Storms",
|
||||
slot: "legs",
|
||||
source: "manaforge omega",
|
||||
tags: [Tag.Tier],
|
||||
},
|
||||
{
|
||||
id: 237671 as ItemId,
|
||||
name: "Glyphs of Fallen Storms",
|
||||
slot: "shoulders",
|
||||
source: "manaforge omega",
|
||||
tags: [Tag.Tier],
|
||||
},
|
||||
{
|
||||
id: 235799 as ItemId,
|
||||
name: "Reshii Wraps",
|
||||
slot: "back",
|
||||
source: "manaforge omega",
|
||||
tags: [Tag.Quest],
|
||||
},
|
||||
{
|
||||
id: 242395,
|
||||
name: "Astral Antenna",
|
||||
slot: "trinket",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 243306,
|
||||
name: "Interloper's Reinforced Sandals",
|
||||
slot: "feet",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 242397,
|
||||
name: "Sigil of the Cosmic Hunt",
|
||||
slot: "trinket",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 242394,
|
||||
name: "Eradicating Arcanocore",
|
||||
slot: "trinket",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 237562,
|
||||
name: "Time-Compressed Wristguards",
|
||||
slot: "wrist",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 237739,
|
||||
name: "Obliteration Beamglaive",
|
||||
slot: "2h-weapon",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 242391,
|
||||
name: "Soulbinder's Embrace",
|
||||
slot: "trinket",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 237734,
|
||||
name: "Oath-Breaker's Recompense",
|
||||
slot: "1h-weapon",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 237726,
|
||||
name: "Marvel of Technomancy",
|
||||
slot: "2h-weapon",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 237533,
|
||||
name: "Atomic Phasebelt",
|
||||
slot: "waist",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 237738,
|
||||
name: "Unbound Training Claws",
|
||||
slot: "1h-weapon",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 238027,
|
||||
name: "Harvested Creephide Cord",
|
||||
slot: "waist",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 238031,
|
||||
name: "Veiled Manta Vest",
|
||||
slot: "chest",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 237813,
|
||||
name: "Factory-Issue Plexhammer",
|
||||
slot: "1h-weapon",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 237565,
|
||||
name: "Kinetic Dunerunners",
|
||||
slot: "feet",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 237525,
|
||||
name: "Irradiated Impurity Filter",
|
||||
slot: "head",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 237541,
|
||||
name: "Darksorrow's Corrupted Carapace",
|
||||
slot: "chest",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 237731,
|
||||
name: "Ergospheric Cudgel",
|
||||
slot: "1h-weapon",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 237552,
|
||||
name: "Deathbound Shoulderpads",
|
||||
slot: "shoulders",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 237546,
|
||||
name: "Bindings of Lost Essence",
|
||||
slot: "wrist",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 237540,
|
||||
name: "Winged Gamma Handlers",
|
||||
slot: "hands",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 237557,
|
||||
name: "Reaper's Dreadbelt",
|
||||
slot: "waist",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 237553,
|
||||
name: "Laboratory Test Slippers",
|
||||
slot: "feet",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 237531,
|
||||
name: "Elite Shadowguard Legwraps",
|
||||
slot: "legs",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 230026,
|
||||
name: "Scrapfield 9001",
|
||||
slot: "trinket",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 228854,
|
||||
name: "Bilgerat's Discarded Slacks",
|
||||
slot: "legs",
|
||||
source: "manaforge omega",
|
||||
},
|
||||
{
|
||||
id: 242401,
|
||||
name: "Brand of Ceaseless Ire",
|
||||
slot: "trinket",
|
||||
source: "manaforge omega",
|
||||
icon: "inv_112_raidtrinkets_manaforgetanktrinket3",
|
||||
},
|
||||
] as const;
|
||||
313
src/lib/drops/priory.json
Normal file
313
src/lib/drops/priory.json
Normal file
@ -0,0 +1,313 @@
|
||||
[
|
||||
{
|
||||
"id": 219309,
|
||||
"name": "Tome of Light's Devotion",
|
||||
"icon": "inv_7xp_inscription_talenttome01",
|
||||
"slot": "trinket",
|
||||
"specs": [],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 219308,
|
||||
"name": "Signet of the Priory",
|
||||
"icon": "inv_arathordungeon_signet_color1",
|
||||
"slot": "trinket",
|
||||
"specs": [
|
||||
261,
|
||||
254,
|
||||
62,
|
||||
1449,
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
255,
|
||||
577,
|
||||
63,
|
||||
64,
|
||||
270,
|
||||
262,
|
||||
1450,
|
||||
65,
|
||||
1451,
|
||||
256,
|
||||
250,
|
||||
257,
|
||||
1452,
|
||||
73,
|
||||
258,
|
||||
264,
|
||||
1444,
|
||||
66,
|
||||
265,
|
||||
1446,
|
||||
266,
|
||||
267,
|
||||
1454,
|
||||
1465,
|
||||
1467,
|
||||
1468,
|
||||
1473,
|
||||
268,
|
||||
1456,
|
||||
581,
|
||||
103,
|
||||
104,
|
||||
253,
|
||||
260,
|
||||
1448,
|
||||
70,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
263,
|
||||
251,
|
||||
252,
|
||||
1455,
|
||||
71,
|
||||
72
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 252009,
|
||||
"name": "Bloodstained Memento",
|
||||
"icon": "inv_11_0_arathor_necklace_01_color1",
|
||||
"slot": "neck",
|
||||
"specs": [],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 221200,
|
||||
"name": "Radiant Necromancer's Band",
|
||||
"icon": "inv_11_0_arathor_ring_01_color2",
|
||||
"slot": "finger",
|
||||
"specs": [],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 221125,
|
||||
"name": "Helm of the Righteous Crusade",
|
||||
"icon": "inv_leather_earthendungeon_c_01_helm",
|
||||
"slot": "head",
|
||||
"specs": [
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
270,
|
||||
1450,
|
||||
103,
|
||||
577,
|
||||
581,
|
||||
268,
|
||||
1456,
|
||||
104,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
260,
|
||||
261
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 221126,
|
||||
"name": "Zealous Warden's Raiment",
|
||||
"icon": "inv_chest_cloth_earthendungeon_c_01",
|
||||
"slot": "chest",
|
||||
"specs": [
|
||||
62,
|
||||
1449,
|
||||
1452,
|
||||
256,
|
||||
63,
|
||||
64,
|
||||
265,
|
||||
257,
|
||||
258,
|
||||
266,
|
||||
267,
|
||||
1454
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 221122,
|
||||
"name": "Hand of Beledar",
|
||||
"icon": "inv_mace_1h_earthendungeon_c_01",
|
||||
"slot": "1h-weapon",
|
||||
"specs": [
|
||||
102,
|
||||
258,
|
||||
65,
|
||||
105,
|
||||
262,
|
||||
270,
|
||||
1451,
|
||||
256,
|
||||
257,
|
||||
264,
|
||||
1444,
|
||||
1465,
|
||||
1467,
|
||||
1468,
|
||||
1473
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 219310,
|
||||
"name": "Bursting Lightshard",
|
||||
"icon": "inv_arathordungeon_fragment_color4",
|
||||
"slot": "trinket",
|
||||
"specs": [
|
||||
62,
|
||||
1449,
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
63,
|
||||
64,
|
||||
270,
|
||||
262,
|
||||
1450,
|
||||
65,
|
||||
1451,
|
||||
256,
|
||||
257,
|
||||
1452,
|
||||
258,
|
||||
264,
|
||||
1444,
|
||||
265,
|
||||
266,
|
||||
267,
|
||||
1454,
|
||||
1465,
|
||||
1467,
|
||||
1468,
|
||||
1473
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 221120,
|
||||
"name": "Stalwart Guardian's Boots",
|
||||
"icon": "inv_leather_earthendungeon_c_01_boot",
|
||||
"slot": "feet",
|
||||
"specs": [
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
270,
|
||||
1450,
|
||||
103,
|
||||
577,
|
||||
581,
|
||||
268,
|
||||
1456,
|
||||
104,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
260,
|
||||
261
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 221128,
|
||||
"name": "Starforged Seraph's Mace",
|
||||
"icon": "inv_mace_1h_earthendungeon_c_01",
|
||||
"slot": "1h-weapon",
|
||||
"specs": [
|
||||
260,
|
||||
268,
|
||||
1450,
|
||||
269,
|
||||
263
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 221131,
|
||||
"name": "Elysian Flame Crown",
|
||||
"icon": "inv_helm_cloth_earthendungeon_c_01",
|
||||
"slot": "head",
|
||||
"specs": [
|
||||
62,
|
||||
1449,
|
||||
1452,
|
||||
256,
|
||||
63,
|
||||
64,
|
||||
265,
|
||||
257,
|
||||
258,
|
||||
266,
|
||||
267,
|
||||
1454
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 221121,
|
||||
"name": "Honorbound Retainer's Sash",
|
||||
"icon": "inv_belt_cloth_earthendungeon_c_01",
|
||||
"slot": "waist",
|
||||
"specs": [
|
||||
62,
|
||||
1449,
|
||||
1452,
|
||||
256,
|
||||
63,
|
||||
64,
|
||||
265,
|
||||
257,
|
||||
258,
|
||||
266,
|
||||
267,
|
||||
1454
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 221130,
|
||||
"name": "Seraphic Wraps of the Ordained",
|
||||
"icon": "inv_leather_earthendungeon_c_01_chest",
|
||||
"slot": "chest",
|
||||
"specs": [
|
||||
102,
|
||||
1447,
|
||||
105,
|
||||
270,
|
||||
1450,
|
||||
103,
|
||||
577,
|
||||
581,
|
||||
268,
|
||||
1456,
|
||||
104,
|
||||
269,
|
||||
259,
|
||||
1453,
|
||||
260,
|
||||
261
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
},
|
||||
{
|
||||
"id": 221116,
|
||||
"name": "Glorious Defender's Poleaxe",
|
||||
"icon": "inv_polearm_2h_earthendungeon_c_01",
|
||||
"slot": "2h-weapon",
|
||||
"specs": [
|
||||
255,
|
||||
103,
|
||||
104,
|
||||
1447,
|
||||
268,
|
||||
269
|
||||
],
|
||||
"source": "Priory of the Sacred Flame"
|
||||
}
|
||||
]
|
||||
@ -1,34 +0,0 @@
|
||||
import type { ItemId } from "../types";
|
||||
|
||||
export const PrioryOfTheSacredFlame = [
|
||||
{
|
||||
id: 219309 as ItemId,
|
||||
slot: "trinket",
|
||||
name: "Tome of Light's Devotion",
|
||||
source: "priory" as const,
|
||||
},
|
||||
{
|
||||
id: 219308 as ItemId,
|
||||
slot: "trinket",
|
||||
name: "Signet of the Priory",
|
||||
source: "priory" as const,
|
||||
},
|
||||
{
|
||||
id: 252009 as ItemId,
|
||||
slot: "neck",
|
||||
name: "Bloodstained Memento",
|
||||
source: "priory" as const,
|
||||
},
|
||||
{
|
||||
id: 221200 as ItemId,
|
||||
slot: "finger",
|
||||
name: "Radiant Necromancer's Band",
|
||||
source: "priory" as const,
|
||||
},
|
||||
{
|
||||
id: 221125 as ItemId,
|
||||
slot: "head",
|
||||
name: "Helm of the Righteous Crusade",
|
||||
source: "priory" as const,
|
||||
},
|
||||
] as const;
|
||||
381
src/lib/drops/tazavesh.json
Normal file
381
src/lib/drops/tazavesh.json
Normal file
@ -0,0 +1,381 @@
|
||||
[
|
||||
{
|
||||
"id": 185812,
|
||||
"name": "Acoustically Alluring Censer",
|
||||
"icon": "inv_offhand_1h_broker_c_01",
|
||||
"slot": "off-hand",
|
||||
"specs": [
|
||||
62, 1449, 102, 1447, 105, 63, 64, 270, 262, 1450, 65, 1451, 256, 257,
|
||||
1452, 258, 264, 1444, 265, 266, 267, 1454, 1465, 1467, 1468, 1473
|
||||
],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185801,
|
||||
"name": "Anomalous Starlit Breeches",
|
||||
"icon": "inv_pant_leather_oribosdungeon_c_01",
|
||||
"slot": "legs",
|
||||
"specs": [
|
||||
102, 1447, 105, 270, 1450, 103, 577, 581, 268, 1456, 104, 269, 259, 1453,
|
||||
260, 261
|
||||
],
|
||||
"source": "So'leah's Gambit"
|
||||
},
|
||||
{
|
||||
"id": 185814,
|
||||
"name": "Auctioneer's Counting Bracers",
|
||||
"icon": "inv_bracer_cloth_oribosdungeon_c_01",
|
||||
"slot": "wrist",
|
||||
"specs": [62, 1449, 1452, 256, 63, 64, 265, 257, 258, 266, 267, 1454],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185824,
|
||||
"name": "Blade of Grievous Harm",
|
||||
"icon": "inv_sword_1h_broker2boss_d_01_blue",
|
||||
"slot": "1h-weapon",
|
||||
"specs": [251, 72, 1451, 66, 73, 1446],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 246280,
|
||||
"name": "Boots of Titanic Deconversion",
|
||||
"icon": "inv_boot_leather_oribosdungeon_c_01",
|
||||
"slot": "feet",
|
||||
"specs": [
|
||||
102, 1447, 105, 270, 1450, 103, 577, 581, 268, 1456, 104, 269, 259, 1453,
|
||||
260, 261
|
||||
],
|
||||
"source": "So'leah's Gambit"
|
||||
},
|
||||
{
|
||||
"id": 185817,
|
||||
"name": "Bracers of Autonomous Classification",
|
||||
"icon": "inv_bracer_leather_oribosdungeon_c_01",
|
||||
"slot": "wrist",
|
||||
"specs": [
|
||||
102, 1447, 105, 270, 1450, 103, 577, 581, 268, 1456, 104, 269, 259, 1453,
|
||||
260, 261
|
||||
],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185802,
|
||||
"name": "Breakbeat Shoulderguards",
|
||||
"icon": "inv_shoulder_leather_oribosdungeon_c_01",
|
||||
"slot": "shoulders",
|
||||
"specs": [
|
||||
102, 1447, 105, 270, 1450, 103, 577, 581, 268, 1456, 104, 269, 259, 1453,
|
||||
260, 261
|
||||
],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185820,
|
||||
"name": "Cabochon of the Infinite Flight",
|
||||
"icon": "inv_7_0raid_necklace_02c",
|
||||
"slot": "neck",
|
||||
"specs": [],
|
||||
"source": "So'leah's Gambit"
|
||||
},
|
||||
{
|
||||
"id": 246275,
|
||||
"name": "Codebreaker's Cunning Handwraps",
|
||||
"icon": "inv_glove_cloth_oribosdungeon_c_01",
|
||||
"slot": "hands",
|
||||
"specs": [62, 1449, 1452, 256, 63, 64, 265, 257, 258, 266, 267, 1454],
|
||||
"source": "So'leah's Gambit"
|
||||
},
|
||||
{
|
||||
"id": 185788,
|
||||
"name": "Codebreaker's Cunning Sandals",
|
||||
"icon": "inv_boot_cloth_oribosdungeon_c_01",
|
||||
"slot": "feet",
|
||||
"specs": [62, 1449, 1452, 256, 63, 64, 265, 257, 258, 266, 267, 1454],
|
||||
"source": "So'leah's Gambit"
|
||||
},
|
||||
{
|
||||
"id": 185836,
|
||||
"name": "Codex of the First Technique",
|
||||
"icon": "inv_misc_profession_book_enchanting",
|
||||
"slot": "trinket",
|
||||
"specs": [],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185795,
|
||||
"name": "Cowl of Branching Fate",
|
||||
"icon": "inv_helm_cloth_oribosdungeon_c_01",
|
||||
"slot": "head",
|
||||
"specs": [62, 1449, 1452, 256, 63, 64, 265, 257, 258, 266, 267, 1454],
|
||||
"source": "So'leah's Gambit"
|
||||
},
|
||||
{
|
||||
"id": 185793,
|
||||
"name": "Cyphered Gloves",
|
||||
"icon": "inv_glove_cloth_oribosdungeon_c_01",
|
||||
"slot": "hands",
|
||||
"specs": [62, 1449, 1452, 256, 63, 64, 265, 257, 258, 266, 267, 1454],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185781,
|
||||
"name": "Drape of Titanic Dreams",
|
||||
"icon": "inv_plate_oribosdungeon_c_01_cape",
|
||||
"slot": "1h-weapon",
|
||||
"specs": [
|
||||
261, 254, 62, 1449, 102, 1447, 105, 255, 577, 63, 64, 270, 262, 1450, 65,
|
||||
1451, 256, 250, 257, 1452, 73, 258, 264, 1444, 66, 265, 1446, 266, 267,
|
||||
1454, 1465, 1467, 1468, 1473, 268, 1456, 581, 103, 104, 253, 260, 1448,
|
||||
70, 269, 259, 1453, 263, 251, 252, 1455, 71, 72
|
||||
],
|
||||
"source": "So'leah's Gambit"
|
||||
},
|
||||
{
|
||||
"id": 185843,
|
||||
"name": "Duplicating Drape",
|
||||
"icon": "inv_cape_leather_oribosdungeon_c_01",
|
||||
"slot": "1h-weapon",
|
||||
"specs": [
|
||||
261, 254, 62, 1449, 102, 1447, 105, 255, 577, 63, 64, 270, 262, 1450, 65,
|
||||
1451, 256, 250, 257, 1452, 73, 258, 264, 1444, 66, 265, 1446, 266, 267,
|
||||
1454, 1465, 1467, 1468, 1473, 268, 1456, 581, 103, 104, 253, 260, 1448,
|
||||
70, 269, 259, 1453, 263, 251, 252, 1455, 71, 72
|
||||
],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185823,
|
||||
"name": "Fatebreaker, Destroyer of Futures",
|
||||
"icon": "inv_mace_1h_broker_c_01",
|
||||
"slot": "1h-weapon",
|
||||
"specs": [260, 268, 1450, 269, 263],
|
||||
"source": "So'leah's Gambit"
|
||||
},
|
||||
{
|
||||
"id": 185845,
|
||||
"name": "First Class Healing Distributor",
|
||||
"icon": "inv_7_0raid_trinket_09a",
|
||||
"slot": "trinket",
|
||||
"specs": [
|
||||
62, 1449, 102, 1447, 105, 63, 64, 270, 262, 1450, 65, 1451, 256, 257,
|
||||
1452, 258, 264, 1444, 265, 266, 267, 1454, 1465, 1467, 1468, 1473
|
||||
],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185778,
|
||||
"name": "First Fist of the So Cartel",
|
||||
"icon": "inv_hand_1h_brokerassassin_c_01",
|
||||
"slot": "1h-weapon",
|
||||
"specs": [577, 260, 268, 581, 1456, 1450, 269, 263],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185804,
|
||||
"name": "Harmonious Spaulders",
|
||||
"icon": "inv_shoulder_cloth_oribosdungeon_c_01",
|
||||
"slot": "shoulders",
|
||||
"specs": [62, 1449, 1452, 256, 63, 64, 265, 257, 258, 266, 267, 1454],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185799,
|
||||
"name": "Hyperlight Leggings",
|
||||
"icon": "inv_pant_cloth_oribosdungeon_c_01",
|
||||
"slot": "legs",
|
||||
"specs": [62, 1449, 1452, 256, 63, 64, 265, 257, 258, 266, 267, 1454],
|
||||
"source": "So'leah's Gambit"
|
||||
},
|
||||
{
|
||||
"id": 185780,
|
||||
"name": "Interrogator's Flensing Blade",
|
||||
"icon": "inv_sword_1h_broker2boss_d_01_blue",
|
||||
"slot": "1h-weapon",
|
||||
"specs": [577, 260, 268, 581, 1450, 269],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185791,
|
||||
"name": "Knuckle-Dusting Handwraps",
|
||||
"icon": "inv_glove_leather_oribosdungeon_c_01",
|
||||
"slot": "hands",
|
||||
"specs": [
|
||||
102, 1447, 105, 270, 1450, 103, 577, 581, 268, 1456, 104, 269, 259, 1453,
|
||||
260, 261
|
||||
],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185846,
|
||||
"name": "Miniscule Mailemental in an Envelope",
|
||||
"icon": "inv_misc_paperpackage01b",
|
||||
"slot": "trinket",
|
||||
"specs": [],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185842,
|
||||
"name": "Ornately Engraved Amplifier",
|
||||
"icon": "inv_misc_silverjadenecklace",
|
||||
"slot": "neck",
|
||||
"specs": [],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185807,
|
||||
"name": "Pan-Dimensional Packing Cord",
|
||||
"icon": "inv_belt_cloth_oribosdungeon_c_01",
|
||||
"slot": "waist",
|
||||
"specs": [62, 1449, 1452, 256, 63, 64, 265, 257, 258, 266, 267, 1454],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185797,
|
||||
"name": "Rakishly Tipped Tricorne",
|
||||
"icon": "inv_helm_leather_oribosdungeon_c_01",
|
||||
"slot": "head",
|
||||
"specs": [
|
||||
102, 1447, 105, 270, 1450, 103, 577, 581, 268, 1456, 104, 269, 259, 1453,
|
||||
260, 261
|
||||
],
|
||||
"source": "So'leah's Gambit"
|
||||
},
|
||||
{
|
||||
"id": 246281,
|
||||
"name": "Ring of the Panoply",
|
||||
"icon": "inv_misc_60raid_ring_1b",
|
||||
"slot": "finger",
|
||||
"specs": [],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185782,
|
||||
"name": "Robes of Midnight Bargains",
|
||||
"icon": "inv_robe_cloth_oribosdungeon_c_01",
|
||||
"slot": "chest",
|
||||
"specs": [62, 1449, 1452, 256, 63, 64, 265, 257, 258, 266, 267, 1454],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185840,
|
||||
"name": "Seal of the Panoply",
|
||||
"icon": "inv_misc_60raid_ring_3b",
|
||||
"slot": "finger",
|
||||
"specs": [],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185813,
|
||||
"name": "Signet of Collapsing Stars",
|
||||
"icon": "inv_jewelcrafting_80_maxlvlring_blue",
|
||||
"slot": "finger",
|
||||
"specs": [],
|
||||
"source": "So'leah's Gambit"
|
||||
},
|
||||
{
|
||||
"id": 185786,
|
||||
"name": "So'azmi's Fractal Vest",
|
||||
"icon": "inv_chest_leather_oribosdungeon_c_01",
|
||||
"slot": "chest",
|
||||
"specs": [
|
||||
102, 1447, 105, 270, 1450, 103, 577, 581, 268, 1456, 104, 269, 259, 1453,
|
||||
260, 261
|
||||
],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 190958,
|
||||
"name": "So'leah's Secret Technique",
|
||||
"icon": "inv_60pvp_trinket1d",
|
||||
"slot": "trinket",
|
||||
"specs": [
|
||||
261, 254, 62, 1449, 102, 1447, 105, 255, 577, 63, 64, 270, 262, 1450, 65,
|
||||
1451, 256, 250, 257, 1452, 73, 258, 264, 1444, 66, 265, 1446, 266, 267,
|
||||
1454, 1465, 1467, 1468, 1473, 268, 1456, 581, 103, 104, 253, 260, 1448,
|
||||
70, 269, 259, 1453, 263, 251, 252, 1455, 71, 72
|
||||
],
|
||||
"source": "So'leah's Gambit"
|
||||
},
|
||||
{
|
||||
"id": 185818,
|
||||
"name": "So'leah's Secret Technique",
|
||||
"icon": "inv_60pvp_trinket1d",
|
||||
"slot": "trinket",
|
||||
"specs": [
|
||||
261, 254, 62, 1449, 102, 1447, 105, 255, 577, 63, 64, 270, 262, 1450, 65,
|
||||
1451, 256, 250, 257, 1452, 73, 258, 264, 1444, 66, 265, 1446, 266, 267,
|
||||
1454, 1465, 1467, 1468, 1473, 268, 1456, 581, 103, 104, 253, 260, 1448,
|
||||
70, 269, 259, 1453, 263, 251, 252, 1455, 71, 72
|
||||
],
|
||||
"source": "So'leah's Gambit"
|
||||
},
|
||||
{
|
||||
"id": 185779,
|
||||
"name": "Spire of Expurgation",
|
||||
"icon": "inv_staff_2h_broker_c_01",
|
||||
"slot": "2h-weapon",
|
||||
"specs": [255, 103, 104, 1447, 268, 269],
|
||||
"source": "So'leah's Gambit"
|
||||
},
|
||||
{
|
||||
"id": 185822,
|
||||
"name": "Staff of Fractured Spacetime",
|
||||
"icon": "inv_staff_2h_broker_c_01",
|
||||
"slot": "2h-weapon",
|
||||
"specs": [
|
||||
62, 1449, 102, 1447, 105, 256, 63, 64, 270, 257, 1452, 258, 262, 264, 265,
|
||||
266, 267, 1454, 1465, 1467, 1468, 1473
|
||||
],
|
||||
"source": "So'leah's Gambit"
|
||||
},
|
||||
{
|
||||
"id": 190652,
|
||||
"name": "Ticking Sack of Terror",
|
||||
"icon": "inv_misc_bag_felclothbag",
|
||||
"slot": "trinket",
|
||||
"specs": [],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185844,
|
||||
"name": "Ticking Sack of Terror",
|
||||
"icon": "inv_misc_bag_felclothbag",
|
||||
"slot": "trinket",
|
||||
"specs": [],
|
||||
"source": "Streets of Wonder"
|
||||
},
|
||||
{
|
||||
"id": 185841,
|
||||
"name": "Timetwister Tulwar",
|
||||
"icon": "inv_sword_1h_broker_c_01",
|
||||
"slot": "1h-weapon",
|
||||
"specs": [
|
||||
62, 63, 1451, 64, 270, 266, 65, 265, 267, 1454, 1465, 1467, 1468, 1473
|
||||
],
|
||||
"source": "So'leah's Gambit"
|
||||
},
|
||||
{
|
||||
"id": 185790,
|
||||
"name": "Treads of Titanic Deconversion",
|
||||
"icon": "inv_boot_leather_oribosdungeon_c_01",
|
||||
"slot": "feet",
|
||||
"specs": [
|
||||
102, 1447, 105, 270, 1450, 103, 577, 581, 268, 1456, 104, 269, 259, 1453,
|
||||
260, 261
|
||||
],
|
||||
"source": "So'leah's Gambit"
|
||||
},
|
||||
{
|
||||
"id": 185809,
|
||||
"name": "Venza's Powderbelt",
|
||||
"icon": "inv_belt_leather_oribosdungeon_c_01",
|
||||
"slot": "waist",
|
||||
"specs": [
|
||||
102, 1447, 105, 270, 1450, 103, 577, 581, 268, 1456, 104, 269, 259, 1453,
|
||||
260, 261
|
||||
],
|
||||
"source": "Streets of Wonder"
|
||||
}
|
||||
]
|
||||
|
||||
@ -1,115 +0,0 @@
|
||||
import type { ItemId } from "../types";
|
||||
|
||||
export const Gambit = [
|
||||
{
|
||||
id: 190958 as ItemId,
|
||||
slot: "trinket",
|
||||
name: "So'leah's Secret Technique",
|
||||
source: "gambit" as const,
|
||||
},
|
||||
{
|
||||
id: 185818 as ItemId,
|
||||
slot: "trinket",
|
||||
name: "So'leah's Secret Technique",
|
||||
source: "gambit" as const,
|
||||
},
|
||||
{
|
||||
id: 185823 as ItemId,
|
||||
slot: "1h-weapon",
|
||||
name: "Fatebreaker, Destroyer of Futures",
|
||||
source: "gambit" as const,
|
||||
},
|
||||
{
|
||||
id: 246280 as ItemId,
|
||||
slot: "feet",
|
||||
name: "Boots of Titanic Deconversion",
|
||||
source: "gambit" as const,
|
||||
},
|
||||
{
|
||||
id: 185781 as ItemId,
|
||||
slot: "back",
|
||||
name: "Drape of Titanic Dreams",
|
||||
source: "gambit" as const,
|
||||
},
|
||||
{
|
||||
id: 185790 as ItemId,
|
||||
slot: "feet",
|
||||
name: "Treads of Titanic Deconversion",
|
||||
source: "gambit" as const,
|
||||
},
|
||||
{
|
||||
id: 185797 as ItemId,
|
||||
slot: "head",
|
||||
name: "Rakishly Tipped Tricorne",
|
||||
source: "gambit" as const,
|
||||
},
|
||||
{
|
||||
id: 185801 as ItemId,
|
||||
slot: "legs",
|
||||
name: "Anomalous Starlit Breeches",
|
||||
source: "gambit" as const,
|
||||
},
|
||||
] as const;
|
||||
|
||||
export const Streets = [
|
||||
{
|
||||
id: 185780 as ItemId,
|
||||
slot: "1h-weapon",
|
||||
name: "Interrogator's Flensing Blade",
|
||||
source: "streets" as const,
|
||||
},
|
||||
{
|
||||
id: 185778 as ItemId,
|
||||
slot: "1h-weapon",
|
||||
name: "First Fist of the So Cartel",
|
||||
source: "streets" as const,
|
||||
},
|
||||
{
|
||||
id: 185824 as ItemId,
|
||||
slot: "1h-weapon",
|
||||
name: "Blade of Grievous Harm",
|
||||
source: "streets" as const,
|
||||
},
|
||||
{
|
||||
id: 185809 as ItemId,
|
||||
slot: "waist",
|
||||
name: "Venza's Powderbelt",
|
||||
source: "streets" as const,
|
||||
},
|
||||
{
|
||||
id: 185779 as ItemId,
|
||||
slot: "2h-weapon",
|
||||
name: "Spire of Expurgation",
|
||||
source: "streets" as const,
|
||||
},
|
||||
{
|
||||
id: 185802 as ItemId,
|
||||
slot: "shoulders",
|
||||
name: "Breakbeat Shoulderguards",
|
||||
source: "streets" as const,
|
||||
},
|
||||
{
|
||||
id: 185786 as ItemId,
|
||||
slot: "chest",
|
||||
name: "So'azmi's Fractal Vest",
|
||||
source: "streets" as const,
|
||||
},
|
||||
{
|
||||
id: 185791 as ItemId,
|
||||
slot: "hands",
|
||||
name: "Knuckle-Dusting Handwraps",
|
||||
source: "streets" as const,
|
||||
},
|
||||
{
|
||||
id: 185817 as ItemId,
|
||||
slot: "wrist",
|
||||
name: "Bracers of Autonomous Classification",
|
||||
source: "streets" as const,
|
||||
},
|
||||
{
|
||||
id: 185843 as ItemId,
|
||||
slot: "back",
|
||||
name: "Duplicating Drape",
|
||||
source: "streets" as const,
|
||||
},
|
||||
] as const;
|
||||
523
src/lib/drops/tww-s3-tier.json
Normal file
523
src/lib/drops/tww-s3-tier.json
Normal file
@ -0,0 +1,523 @@
|
||||
[
|
||||
{
|
||||
"id": 237631,
|
||||
"name": "Hollow Sentinel's Breastplate",
|
||||
"icon": "inv_chest_plate_raiddeathknightethereal_d_01",
|
||||
"slot": "chest",
|
||||
"specs": [250, 251, 252, 1455],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237629,
|
||||
"name": "Hollow Sentinel's Gauntlets",
|
||||
"icon": "inv_glove_plate_raiddeathknightethereal_d_01",
|
||||
"slot": "hands",
|
||||
"specs": [250, 251, 252, 1455],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237628,
|
||||
"name": "Hollow Sentinel's Stonemask",
|
||||
"icon": "inv_helm_plate_raiddeathknightethereal_d_01",
|
||||
"slot": "head",
|
||||
"specs": [250, 251, 252, 1455],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237627,
|
||||
"name": "Hollow Sentinel's Stonekilt",
|
||||
"icon": "inv_pant_plate_raiddeathknightethereal_d_01",
|
||||
"slot": "legs",
|
||||
"specs": [250, 251, 252, 1455],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237626,
|
||||
"name": "Hollow Sentinel's Perches",
|
||||
"icon": "inv_shoulder_plate_raiddeathknightethereal_d_01",
|
||||
"slot": "shoulders",
|
||||
"specs": [250, 251, 252, 1455],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237608,
|
||||
"name": "Living Weapon's Ramparts",
|
||||
"icon": "inv_shoulder_plate_raidwarriorethereal_d_01",
|
||||
"slot": "shoulders",
|
||||
"specs": [71, 72, 73, 1446],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237613,
|
||||
"name": "Living Weapon's Bulwark",
|
||||
"icon": "inv_chest_plate_raidwarriorethereal_d_01",
|
||||
"slot": "chest",
|
||||
"specs": [71, 72, 73, 1446],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237611,
|
||||
"name": "Living Weapon's Crushers",
|
||||
"icon": "inv_glove_plate_raidwarriorethereal_d_01",
|
||||
"slot": "hands",
|
||||
"specs": [71, 72, 73, 1446],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237610,
|
||||
"name": "Living Weapon's Faceshield",
|
||||
"icon": "inv_helm_plate_raidwarriorethereal_d_01",
|
||||
"slot": "head",
|
||||
"specs": [71, 72, 73, 1446],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237609,
|
||||
"name": "Living Weapon's Legguards",
|
||||
"icon": "inv_pant_plate_raidwarriorethereal_d_01",
|
||||
"slot": "legs",
|
||||
"specs": [71, 72, 73, 1446],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237701,
|
||||
"name": "Inquisitor's Clutches of Madness",
|
||||
"icon": "inv_glove_cloth_raidwarlockethereal_d_01",
|
||||
"slot": "hands",
|
||||
"specs": [265, 1454, 266, 267],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237700,
|
||||
"name": "Inquisitor's Portal to Madness",
|
||||
"icon": "inv_helm_cloth_raidwarlockethereal_d_01",
|
||||
"slot": "head",
|
||||
"specs": [265, 1454, 266, 267],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237699,
|
||||
"name": "Inquisitor's Leggings of Madness",
|
||||
"icon": "inv_pant_cloth_raidwarlockethereal_d_01",
|
||||
"slot": "legs",
|
||||
"specs": [265, 1454, 266, 267],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237703,
|
||||
"name": "Inquisitor's Robes of Madness",
|
||||
"icon": "inv_robe_cloth_raidwarlockethereal_d_01",
|
||||
"slot": "chest",
|
||||
"specs": [265, 1454, 266, 267],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237698,
|
||||
"name": "Inquisitor's Gaze of Madness",
|
||||
"icon": "inv_shoulder_cloth_raidwarlockethereal_d_01",
|
||||
"slot": "shoulders",
|
||||
"specs": [265, 1454, 266, 267],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237636,
|
||||
"name": "Tassets of Channeled Fury",
|
||||
"icon": "inv_pant_mail_raidshamanethereal_d_01",
|
||||
"slot": "legs",
|
||||
"specs": [262, 264, 1444, 263],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237637,
|
||||
"name": "Aspect of Channeled Fury",
|
||||
"icon": "inv_helm_mail_raidshamanethereal_d_01",
|
||||
"slot": "head",
|
||||
"specs": [262, 264, 1444, 263],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237638,
|
||||
"name": "Claws of Channeled Fury",
|
||||
"icon": "inv_glove_mail_raidshamanethereal_d_01",
|
||||
"slot": "hands",
|
||||
"specs": [262, 264, 1444, 263],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237640,
|
||||
"name": "Furs of Channeled Fury",
|
||||
"icon": "inv_chest_mail_raidshamanethereal_d_01",
|
||||
"slot": "chest",
|
||||
"specs": [262, 264, 1444, 263],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237635,
|
||||
"name": "Fangs of Channeled Fury",
|
||||
"icon": "inv_shoulder_mail_raidshamanethereal_d_01",
|
||||
"slot": "shoulders",
|
||||
"specs": [262, 264, 1444, 263],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237662,
|
||||
"name": "Smokemantle of the Sudden Eclipse",
|
||||
"icon": "inv_shoulder_leather_raidrogueethereal_d_01",
|
||||
"slot": "shoulders",
|
||||
"specs": [259, 1453, 260, 261],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237667,
|
||||
"name": "Tactical Vest of the Sudden Eclipse",
|
||||
"icon": "inv_chest_leather_raidrogueethereal_d_01",
|
||||
"slot": "chest",
|
||||
"specs": [259, 1453, 260, 261],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237665,
|
||||
"name": "Deathgrips of the Sudden Eclipse",
|
||||
"icon": "inv_glove_leather_raidrogueethereal_d_01",
|
||||
"slot": "hands",
|
||||
"specs": [259, 1453, 260, 261],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237664,
|
||||
"name": "Hood of the Sudden Eclipse",
|
||||
"icon": "inv_helm_leather_raidrogueethereal_d_01",
|
||||
"slot": "head",
|
||||
"specs": [259, 1453, 260, 261],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237663,
|
||||
"name": "Pants of the Sudden Eclipse",
|
||||
"icon": "inv_pant_leather_raidrogueethereal_d_01",
|
||||
"slot": "legs",
|
||||
"specs": [259, 1453, 260, 261],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237712,
|
||||
"name": "Dying Star's Cassock",
|
||||
"icon": "inv_robe_cloth_raidpriestethereal_d_01",
|
||||
"slot": "chest",
|
||||
"specs": [1452, 256, 257, 258],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237708,
|
||||
"name": "Dying Star's Leggings",
|
||||
"icon": "inv_pant_cloth_raidpriestethereal_d_01",
|
||||
"slot": "legs",
|
||||
"specs": [1452, 256, 257, 258],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237709,
|
||||
"name": "Dying Star's Veil",
|
||||
"icon": "inv_helm_cloth_raidpriestethereal_d_01",
|
||||
"slot": "head",
|
||||
"specs": [1452, 256, 257, 258],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237710,
|
||||
"name": "Dying Star's Caress",
|
||||
"icon": "inv_glove_cloth_raidpriestethereal_d_01",
|
||||
"slot": "hands",
|
||||
"specs": [1452, 256, 257, 258],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237707,
|
||||
"name": "Dying Star's Pyrelights",
|
||||
"icon": "inv_shoulder_cloth_raidpriestethereal_d_01",
|
||||
"slot": "shoulders",
|
||||
"specs": [1452, 256, 257, 258],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237617,
|
||||
"name": "Chargers of the Lucent Battalion",
|
||||
"icon": "inv_plate_raidpaladinethereal_d_01_shoulder",
|
||||
"slot": "shoulders",
|
||||
"specs": [65, 1451, 66, 70],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237622,
|
||||
"name": "Cuirass of the Lucent Battalion",
|
||||
"icon": "inv_plate_raidpaladinethereal_d_01_chest",
|
||||
"slot": "chest",
|
||||
"specs": [65, 1451, 66, 70],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237620,
|
||||
"name": "Protectors of the Lucent Battalion",
|
||||
"icon": "inv_plate_raidpaladinethereal_d_01_glove",
|
||||
"slot": "hands",
|
||||
"specs": [65, 1451, 66, 70],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237619,
|
||||
"name": "Lightmane of the Lucent Battalion",
|
||||
"icon": "inv_plate_raidpaladinethereal_d_01_helm",
|
||||
"slot": "head",
|
||||
"specs": [65, 1451, 66, 70],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237618,
|
||||
"name": "Cuisses of the Lucent Battalion",
|
||||
"icon": "inv_plate_raidpaladinethereal_d_01_pant",
|
||||
"slot": "legs",
|
||||
"specs": [65, 1451, 66, 70],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237671,
|
||||
"name": "Glyphs of Fallen Storms",
|
||||
"icon": "inv_shoulder_leather_raidmonkethereal_d_01",
|
||||
"slot": "shoulders",
|
||||
"specs": [270, 1450, 268, 269],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237676,
|
||||
"name": "Gi of Fallen Storms",
|
||||
"icon": "inv_chest_leather_raidmonkethereal_d_01",
|
||||
"slot": "chest",
|
||||
"specs": [270, 1450, 268, 269],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237674,
|
||||
"name": "Grasp of Fallen Storms",
|
||||
"icon": "inv_glove_leather_raidmonkethereal_d_01",
|
||||
"slot": "hands",
|
||||
"specs": [270, 1450, 268, 269],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237673,
|
||||
"name": "Half-Mask of Fallen Storms",
|
||||
"icon": "inv_helm_leather_raidmonkethereal_d_01",
|
||||
"slot": "head",
|
||||
"specs": [270, 1450, 268, 269],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237672,
|
||||
"name": "Legwraps of Fallen Storms",
|
||||
"icon": "inv_pant_leather_raidmonkethereal_d_01",
|
||||
"slot": "legs",
|
||||
"specs": [270, 1450, 268, 269],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237716,
|
||||
"name": "Augur's Ephemeral Orbs of Power",
|
||||
"icon": "inv_shoulder_cloth_raidmageethereal_d_01",
|
||||
"slot": "shoulders",
|
||||
"specs": [1449, 62, 63, 64],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237721,
|
||||
"name": "Augur's Ephemeral Habiliments",
|
||||
"icon": "inv_robe_cloth_raidmageethereal_d_01",
|
||||
"slot": "chest",
|
||||
"specs": [1449, 62, 63, 64],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237719,
|
||||
"name": "Augur's Ephemeral Mitts",
|
||||
"icon": "inv_glove_cloth_raidmageethereal_d_01",
|
||||
"slot": "hands",
|
||||
"specs": [1449, 62, 63, 64],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237718,
|
||||
"name": "Augur's Ephemeral Wide-Brim",
|
||||
"icon": "inv_helm_cloth_raidmageethereal_d_01",
|
||||
"slot": "head",
|
||||
"specs": [1449, 62, 63, 64],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237717,
|
||||
"name": "Augur's Ephemeral Trousers",
|
||||
"icon": "inv_pant_cloth_raidmageethereal_d_01",
|
||||
"slot": "legs",
|
||||
"specs": [1449, 62, 63, 64],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237649,
|
||||
"name": "Midnight Herald's Hauberk",
|
||||
"icon": "inv_chest_mail_raidhunterethereal_d_01",
|
||||
"slot": "chest",
|
||||
"specs": [253, 1448, 254, 255],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237647,
|
||||
"name": "Midnight Herald's Gloves",
|
||||
"icon": "inv_glove_mail_raidhunterethereal_d_01",
|
||||
"slot": "hands",
|
||||
"specs": [253, 1448, 254, 255],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237646,
|
||||
"name": "Midnight Herald's Cowl",
|
||||
"icon": "inv_helm_mail_raidhunterethereal_d_01",
|
||||
"slot": "head",
|
||||
"specs": [253, 1448, 254, 255],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237645,
|
||||
"name": "Midnight Herald's Petticoat",
|
||||
"icon": "inv_pant_mail_raidhunterethereal_d_01",
|
||||
"slot": "legs",
|
||||
"specs": [253, 1448, 254, 255],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237644,
|
||||
"name": "Midnight Herald's Shadowguards",
|
||||
"icon": "inv_shoulder_mail_raidhunterethereal_d_01",
|
||||
"slot": "shoulders",
|
||||
"specs": [253, 1448, 254, 255],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237654,
|
||||
"name": "Spellweaver's Immaculate Runeslacks",
|
||||
"icon": "inv_pant_mail_raidevokerethereal_d_01",
|
||||
"slot": "legs",
|
||||
"specs": [1473, 1465, 1467, 1468],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237655,
|
||||
"name": "Spellweaver's Immaculate Focus",
|
||||
"icon": "inv_helm_mail_raidevokerethereal_d_01",
|
||||
"slot": "head",
|
||||
"specs": [1473, 1465, 1467, 1468],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237656,
|
||||
"name": "Spellweaver's Immaculate Scaleguards",
|
||||
"icon": "inv_glove_mail_raidevokerethereal_d_01",
|
||||
"slot": "hands",
|
||||
"specs": [1473, 1465, 1467, 1468],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237658,
|
||||
"name": "Spellweaver's Immaculate Crestward",
|
||||
"icon": "inv_chest_mail_raidevokerethereal_d_01",
|
||||
"slot": "chest",
|
||||
"specs": [1473, 1465, 1467, 1468],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237653,
|
||||
"name": "Spellweaver's Immaculate Pauldrons",
|
||||
"icon": "inv_shoulder_mail_raidevokerethereal_d_01",
|
||||
"slot": "shoulders",
|
||||
"specs": [1473, 1465, 1467, 1468],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237685,
|
||||
"name": "Vest of the Mother Eagle",
|
||||
"icon": "inv_chest_leather_raiddruidethereal_d_01",
|
||||
"slot": "chest",
|
||||
"specs": [102, 1447, 105, 103, 104],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237683,
|
||||
"name": "Wings of the Mother Eagle",
|
||||
"icon": "inv_glove_leather_raiddruidethereal_d_01",
|
||||
"slot": "hands",
|
||||
"specs": [102, 1447, 105, 103, 104],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237682,
|
||||
"name": "Skymane of the Mother Eagle",
|
||||
"icon": "inv_helm_leather_raiddruidethereal_d_01",
|
||||
"slot": "head",
|
||||
"specs": [102, 1447, 105, 103, 104],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237681,
|
||||
"name": "Breeches of the Mother Eagle",
|
||||
"icon": "inv_pant_leather_raiddruidethereal_d_01",
|
||||
"slot": "legs",
|
||||
"specs": [102, 1447, 105, 103, 104],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237680,
|
||||
"name": "Ritual Pauldrons of the Mother Eagle",
|
||||
"icon": "inv_shoulder_leather_raiddruidethereal_d_01",
|
||||
"slot": "shoulders",
|
||||
"specs": [102, 1447, 105, 103, 104],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237690,
|
||||
"name": "Charhound's Vicious Hidecoat",
|
||||
"icon": "inv_pant_leather_raiddemonhunterethereal_d_01",
|
||||
"slot": "legs",
|
||||
"specs": [577, 581, 1456],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237692,
|
||||
"name": "Charhound's Vicious Felclaws",
|
||||
"icon": "inv_glove_leather_raiddemonhunterethereal_d_01",
|
||||
"slot": "hands",
|
||||
"specs": [577, 581, 1456],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237691,
|
||||
"name": "Charhound's Vicious Scalp",
|
||||
"icon": "inv_helm_leather_raiddemonhunterethereal_d_01",
|
||||
"slot": "head",
|
||||
"specs": [577, 581, 1456],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237694,
|
||||
"name": "Charhound's Vicious Bindings",
|
||||
"icon": "inv_chest_leather_raiddemonhunterethereal_d_01",
|
||||
"slot": "chest",
|
||||
"specs": [577, 581, 1456],
|
||||
"source": "Tier"
|
||||
},
|
||||
{
|
||||
"id": 237689,
|
||||
"name": "Charhound's Vicious Hornguards",
|
||||
"icon": "inv_shoulder_leather_raiddemonhunterethereal_d_01",
|
||||
"slot": "shoulders",
|
||||
"specs": [577, 581, 1456],
|
||||
"source": "Tier"
|
||||
}
|
||||
]
|
||||
|
||||
@ -2,6 +2,7 @@ import _ from "lodash";
|
||||
import { AllItems } from "./drops";
|
||||
import type { State } from "./state";
|
||||
import {
|
||||
Spec,
|
||||
UpgradeType,
|
||||
WeaponConfig,
|
||||
type Item,
|
||||
@ -19,12 +20,20 @@ export const ItemsById: Record<string, Item> = AllItems.reduce(
|
||||
{} as Record<ItemId, Item>,
|
||||
);
|
||||
|
||||
const itemHasSpec =
|
||||
(spec: Spec) =>
|
||||
(item: Item): boolean =>
|
||||
item.specs && (item.specs.length === 0 || item.specs?.includes(spec));
|
||||
|
||||
export const ItemsBySlot: Record<Slot, Item[]> = _.groupBy(
|
||||
AllItems,
|
||||
(item: Item) => item.slot,
|
||||
) as Record<Slot, Item[]>;
|
||||
|
||||
export const itemsForSlot = (slot: Slot): Item[] => ItemsBySlot[slot] ?? [];
|
||||
export const itemsForSlot =
|
||||
(spec: Spec) =>
|
||||
(slot: Slot): Item[] =>
|
||||
ItemsBySlot[slot]?.filter(itemHasSpec(spec)) ?? [];
|
||||
|
||||
function qualityToNumber(quality: Quality): number {
|
||||
switch (quality) {
|
||||
@ -70,14 +79,16 @@ export const getUpgrades = ({
|
||||
equipedItems,
|
||||
bisList,
|
||||
weaponConfig,
|
||||
spec,
|
||||
}: State): Upgrade[] => {
|
||||
return Object.entries(ItemsBySlot).flatMap(([slot, items]) => {
|
||||
return Object.entries(ItemsBySlot).flatMap(([slot, allItems]) => {
|
||||
const items = allItems.filter(itemHasSpec(spec)); // Assuming spec 1 for simplicity
|
||||
const equipedItemsHydrated = equipedItems.flatMap(({ id, quality }) => ({
|
||||
item: ItemsById[id],
|
||||
quality,
|
||||
}));
|
||||
const equipedInSlot = equipedItemsHydrated.filter(
|
||||
(item) => item.item.slot === slot,
|
||||
(item) => item.item?.slot === slot,
|
||||
);
|
||||
|
||||
const itemsForSlot = itemsPerSlot(slot as Slot, weaponConfig);
|
||||
|
||||
@ -1,16 +1,18 @@
|
||||
import type { EquipedItem, Item, ItemId, Quality } from "./types";
|
||||
import { WeaponConfig } from "./types";
|
||||
import { Spec, WeaponConfig } from "./types";
|
||||
|
||||
export type State = {
|
||||
equipedItems: EquipedItem[];
|
||||
bisList: ItemId[];
|
||||
weaponConfig: WeaponConfig;
|
||||
spec: Spec;
|
||||
};
|
||||
|
||||
export const emptyState: State = {
|
||||
equipedItems: [],
|
||||
bisList: [],
|
||||
weaponConfig: WeaponConfig.TwoHander, // Default weapon config
|
||||
spec: Spec.Monk.Brewmaster,
|
||||
};
|
||||
|
||||
export type Action =
|
||||
@ -32,6 +34,10 @@ export type Action =
|
||||
itemId: ItemId;
|
||||
isBis: boolean;
|
||||
}
|
||||
| {
|
||||
action: "changeSpec";
|
||||
spec: Spec;
|
||||
}
|
||||
| {
|
||||
action: "changeWeaponConfig";
|
||||
weaponConfig: WeaponConfig;
|
||||
@ -76,6 +82,11 @@ export const reducer = (state: State, action: Action): State => {
|
||||
...(action.isBis ? [action.itemId] : []),
|
||||
],
|
||||
};
|
||||
case "changeSpec":
|
||||
return {
|
||||
...state,
|
||||
spec: action.spec,
|
||||
};
|
||||
case "changeWeaponConfig":
|
||||
return {
|
||||
...state,
|
||||
|
||||
@ -30,17 +30,7 @@ export type Quality = (typeof Quality)[keyof typeof Quality];
|
||||
|
||||
export type ItemId = number & { __type: "ItemId" };
|
||||
|
||||
export type Source =
|
||||
| "aldani"
|
||||
| "ara-kara"
|
||||
| "dawnbreaker"
|
||||
| "floodgate"
|
||||
| "gambit"
|
||||
| "halls-of-atonement"
|
||||
| "priory"
|
||||
| "streets"
|
||||
| "manaforge omega"
|
||||
| "crafted";
|
||||
export type Source = string & { __type: "Source" };
|
||||
|
||||
export type Item = {
|
||||
id: ItemId;
|
||||
@ -49,6 +39,7 @@ export type Item = {
|
||||
source: Source;
|
||||
icon?: string; // Wowhead icon name (not ID)
|
||||
tags?: Tag[];
|
||||
specs: number[];
|
||||
};
|
||||
|
||||
export type EquipedItem = {
|
||||
@ -82,3 +73,69 @@ export const Tag = {
|
||||
};
|
||||
|
||||
export type Tag = (typeof Tag)[keyof typeof Tag];
|
||||
|
||||
export const Spec = {
|
||||
Mage: {
|
||||
Arcane: 62,
|
||||
Fire: 63,
|
||||
Frost: 64,
|
||||
},
|
||||
Paladin: {
|
||||
Holy: 65,
|
||||
Protection: 66,
|
||||
Retribution: 70,
|
||||
},
|
||||
Warrior: {
|
||||
Arms: 71,
|
||||
Fury: 72,
|
||||
Protection: 73,
|
||||
},
|
||||
Druid: {
|
||||
Feral: 103,
|
||||
Balance: 102,
|
||||
Guardian: 104,
|
||||
Restoration: 105,
|
||||
},
|
||||
DeathKnight: {
|
||||
Blood: 250,
|
||||
Frost: 251,
|
||||
Unholy: 252,
|
||||
},
|
||||
Hunter: {
|
||||
Marksmanship: 253,
|
||||
Survival: 254,
|
||||
BeastMastery: 255,
|
||||
},
|
||||
Priest: {
|
||||
Discipline: 256,
|
||||
Holy: 257,
|
||||
Shadow: 258,
|
||||
},
|
||||
Rogue: {
|
||||
Assassination: 259,
|
||||
Subtlety: 260,
|
||||
Outlaw: 261,
|
||||
},
|
||||
Shaman: {
|
||||
Elemental: 262,
|
||||
Enhancement: 263,
|
||||
Restoration: 264,
|
||||
},
|
||||
Warlock: {
|
||||
Affliction: 265,
|
||||
Demonology: 266,
|
||||
Destruction: 267,
|
||||
},
|
||||
Monk: {
|
||||
Brewmaster: 268,
|
||||
Windwalker: 269,
|
||||
Mistweaver: 270,
|
||||
},
|
||||
DemonHunter: {
|
||||
Havoc: 577,
|
||||
Vengeance: 581,
|
||||
},
|
||||
};
|
||||
|
||||
export type Spec =
|
||||
(typeof Spec)[keyof typeof Spec][keyof (typeof Spec)[keyof typeof Spec]];
|
||||
|
||||
Loading…
Reference in New Issue
Block a user