diff --git a/IWantToHeal-Thor-v1.0.34.apk b/IWantToHeal-Thor-v1.0.34.apk new file mode 100644 index 0000000..3b4c6fe Binary files /dev/null and b/IWantToHeal-Thor-v1.0.34.apk differ diff --git a/android/app/build.gradle b/android/app/build.gradle index 3f96380..9bfc59b 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "com.warren.iwanttoheal" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 52 - versionName "1.0.33" + versionCode 53 + versionName "1.0.34" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. diff --git a/db/seed.sql b/db/seed.sql index d319a87..76042f7 100644 --- a/db/seed.sql +++ b/db/seed.sql @@ -561,7 +561,9 @@ SET name = ( SELECT CASE items.item_level WHEN 1 THEN 'Raw ' + WHEN 5 THEN 'Honed ' WHEN 10 THEN 'Green ' + WHEN 15 THEN 'Blue ' WHEN 20 THEN 'Purple ' WHEN 25 THEN 'Orange ' ELSE '' @@ -794,6 +796,7 @@ INSERT INTO generated_loot_tiers (item_level, dungeon_id, raid_id, dungeon_difficulty_id, raid_difficulty_id, recipe_base, craft_quantity) VALUES (10, 3, 2, 2, 101, 1100, 2), + (15, 4, 5, 3, 103, 1200, 3), (20, 6, 7, 4, 104, 1300, 4), (25, 8, 9, 5, 105, 1400, 5); @@ -1347,18 +1350,20 @@ WHERE recipe_id IN ( SELECT crafting_recipes.id FROM crafting_recipes JOIN items ON items.id = crafting_recipes.item_id - WHERE items.item_level NOT IN (1, 10, 20, 25) + WHERE items.item_level NOT IN (1, 5, 10, 15, 20, 25) ); DELETE FROM crafting_recipes WHERE item_id IN ( - SELECT id FROM items WHERE item_level NOT IN (1, 10, 20, 25) + SELECT id FROM items WHERE item_level NOT IN (1, 5, 10, 15, 20, 25) ); UPDATE items SET rarity = CASE item_level WHEN 1 THEN 'common' + WHEN 5 THEN 'uncommon' WHEN 10 THEN 'uncommon' + WHEN 15 THEN 'rare' WHEN 20 THEN 'epic' WHEN 25 THEN 'legendary' ELSE rarity @@ -1370,7 +1375,9 @@ SET name = ( SELECT CASE items.item_level WHEN 1 THEN 'Raw ' + WHEN 5 THEN 'Honed ' WHEN 10 THEN 'Green ' + WHEN 15 THEN 'Blue ' WHEN 20 THEN 'Purple ' WHEN 25 THEN 'Orange ' ELSE '' diff --git a/src/components/CombatScreen.tsx b/src/components/CombatScreen.tsx index 8ace395..d809ac3 100644 --- a/src/components/CombatScreen.tsx +++ b/src/components/CombatScreen.tsx @@ -43,7 +43,7 @@ const TICK_MS = 700 type RoguelikeMode = 'dungeon' | 'raid' type RoguelikeUpgradeTiming = 'boss' | 'encounter' type RoguelikeAbilityLabelMode = 'ability' | 'slot' -type SlotKey = '1' | '2' | '3' | '4' | '5' +type SlotKey = '1' | '2' | '3' | '4' | '5' | '6' type RoguelikeMechanic = | 'party-pulse' | 'searing-mark' @@ -120,11 +120,15 @@ function memberHotEffects(member: PartyMember) { : [] } +function effectId(prefix: string) { + return `${prefix}-${globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random()}`}` +} + function addHotEffect(member: PartyMember, spell: Spell, ticks = 5) { return [ ...memberHotEffects(member), { - id: `${spell.id}-${crypto.randomUUID()}`, + id: effectId(spell.id), label: spell.name, ticks, power: Math.max(1, Math.round(spell.power / 2)), @@ -136,7 +140,7 @@ function addBounceHeal(member: PartyMember, spell: Spell) { return [ ...(member.bounceHeals ?? []), { - id: `${spell.id}-${crypto.randomUUID()}`, + id: effectId(spell.id), label: spell.name, charges: 4, power: spell.power, @@ -164,7 +168,7 @@ function buildRoguelikeUpgrades( spells: Spell[], labelMode: RoguelikeAbilityLabelMode, ): RoguelikeUpgrade[] { - const slotUpgrades = (['1', '2', '3', '4', '5'] as SlotKey[]).flatMap((slot) => { + const slotUpgrades = (['1', '2', '3', '4', '5', '6'] as SlotKey[]).flatMap((slot) => { const label = slotLabel(slot, spells, labelMode) return [ { diff --git a/src/components/CustomizeScreen.tsx b/src/components/CustomizeScreen.tsx index 3b82472..a68d6ae 100644 --- a/src/components/CustomizeScreen.tsx +++ b/src/components/CustomizeScreen.tsx @@ -40,7 +40,7 @@ export function CustomizeScreen({ profile, onBack, onSaved }: Props) { function chooseClass(nextClass: GameClass) { const starterAbilities = nextClass.spells .filter((ability) => ability.unlockLevel <= profile.character.level) - .slice(0, 5) + .slice(0, 6) .map((ability) => ability.id) setClassId(nextClass.id) setSlots([...starterAbilities, ...Array(6 - starterAbilities.length).fill(null)]) diff --git a/src/components/PvpRoguelikeScreen.tsx b/src/components/PvpRoguelikeScreen.tsx index b1827df..c0dd7ad 100644 --- a/src/components/PvpRoguelikeScreen.tsx +++ b/src/components/PvpRoguelikeScreen.tsx @@ -44,7 +44,7 @@ type PvpEncounter = DungeonEncounter & { sourceEncounterId?: number } -type SlotKey = '1' | '2' | '3' | '4' | '5' +type SlotKey = '1' | '2' | '3' | '4' | '5' | '6' type AbilityLabelMode = 'ability' | 'slot' type SelfBuffId = @@ -164,7 +164,7 @@ function slotLabel(slot: SlotKey, spells: Spell[], labelMode: AbilityLabelMode) } function buildSelfBuffChoices(spells: Spell[], labelMode: AbilityLabelMode): Array> { - const slotChoices = (['1', '2', '3', '4', '5'] as SlotKey[]).flatMap((slot) => { + const slotChoices = (['1', '2', '3', '4', '5', '6'] as SlotKey[]).flatMap((slot) => { const label = slotLabel(slot, spells, labelMode) return [ { @@ -193,7 +193,7 @@ function buildSelfBuffChoices(spells: Spell[], labelMode: AbilityLabelMode): Arr } function buildOpponentDebuffChoices(spells: Spell[], labelMode: AbilityLabelMode): Array> { - const slotChoices = (['1', '2', '3', '4', '5'] as SlotKey[]).flatMap((slot) => { + const slotChoices = (['1', '2', '3', '4', '5', '6'] as SlotKey[]).flatMap((slot) => { const label = slotLabel(slot, spells, labelMode) return [ { @@ -334,7 +334,7 @@ function scoreSelfBuff(buff: Choice, spells: Spell[]) { if (buff.id === 'fifth-cast-free') return 8 if (buff.id === 'group-heal-boost') return 8 if (buff.id === 'shield-boost') return 6 - const slot = buff.id.match(/slot([1-5])/i)?.[1] as SlotKey | undefined + const slot = buff.id.match(/slot([1-6])/i)?.[1] as SlotKey | undefined const spell = spells.find((candidate) => candidate.key === slot) if (!spell) return 5 if (buff.id.endsWith('extra-target')) { @@ -408,7 +408,7 @@ export function PvPRoguelikeScreen({ const gameClass = profile.classes.find((candidate) => candidate.id === profile.character.classId)! const starterSpells = useMemo(() => gameClass.spells .filter((spell) => spell.unlockLevel === 1) - .slice(0, 5) + .slice(0, 6) .map((spell, index) => toCombatSpell(spell, String(index + 1))), [gameClass.spells]) const [abilityLabelMode] = useState('ability') const selfBuffChoicesCatalog = useMemo( diff --git a/src/dualScreen.tsx b/src/dualScreen.tsx index 2bd1888..10d1ce6 100644 --- a/src/dualScreen.tsx +++ b/src/dualScreen.tsx @@ -118,6 +118,13 @@ function loadRecentSnapshot() { } } +function memberHotEffects(member: PartyMember) { + if (member.hotEffects?.length) return member.hotEffects + return member.hotTicks > 0 + ? [{ id: 'legacy-renew', label: 'Renew', ticks: member.hotTicks }] + : [] +} + export function DualScreenProvider({ children }: { children: ReactNode }) { const [enabled, setEnabledState] = useState( () => localStorage.getItem(STORAGE_KEY) === 'true', @@ -599,7 +606,9 @@ export function DualScreenTopCombat({ )}
- {member.hotTicks > 0 && Renew} + {memberHotEffects(member).map((effect) => ( + {effect.label} + ))} {member.debuff && {member.debuff}}
diff --git a/src/gameRepository.ts b/src/gameRepository.ts index f72bc11..431f212 100644 --- a/src/gameRepository.ts +++ b/src/gameRepository.ts @@ -103,6 +103,7 @@ const offlineSaveKey = 'chronicle.offlineSave.v1' const onlineCacheKey = 'chronicle.onlineCache.v1' const authTokenKey = 'chronicle.authToken.v1' const offlineAccount = { id: -1, username: 'Offline' } +const ABILITY_SLOT_COUNT = 6 function clone(value: T): T { return structuredClone(value) @@ -147,7 +148,7 @@ function upgradeV1Save(v1: { profile: CharacterProfile; lootRolls: Record & { version: 2 }): OfflineSave { - return { + return normalizeSaveAbilitySlots({ ...v2, version: 3, completedRaidPhases: 0, + }) +} + +function normalizeAbilitySlots(abilitySlots: unknown): Array { + const slots = Array.isArray(abilitySlots) + ? abilitySlots + .slice(0, ABILITY_SLOT_COUNT) + .map((value) => { + if (value === null || value === undefined) return null + const id = Number(value) + return Number.isInteger(id) ? id : null + }) + : [] + while (slots.length < ABILITY_SLOT_COUNT) slots.push(null) + return slots +} + +function normalizeSaveAbilitySlots(save: OfflineSave): OfflineSave { + for (const character of Object.values(save.characters)) { + character.abilitySlots = normalizeAbilitySlots(character.abilitySlots) } + return save } function normalizeOfflineSave(raw: unknown): OfflineSave | null { @@ -178,12 +200,12 @@ function normalizeOfflineSave(raw: unknown): OfflineSave | null { profile?: CharacterProfile lootRolls?: Record } - if (candidate.version === 3) return candidate as OfflineSave + if (candidate.version === 3) return normalizeSaveAbilitySlots(candidate as OfflineSave) if (candidate.version === 2) { return upgradeV2Save(candidate as Omit & { version: 2 }) } if (candidate.version === 1 && candidate.profile) { - return upgradeV1Save(candidate as { profile: CharacterProfile; lootRolls: Record }) + return normalizeSaveAbilitySlots(upgradeV1Save(candidate as { profile: CharacterProfile; lootRolls: Record })) } return null } @@ -448,7 +470,7 @@ function mergeProfileIntoSave(profile: CharacterProfile, existingSave?: OfflineS level: profile.character.level, experience: profile.character.experience, talentPoints: profile.character.talentPoints, - abilitySlots: [...profile.abilitySlots], + abilitySlots: normalizeAbilitySlots(profile.abilitySlots), talentRanks, inventory: clone(profile.inventory), } @@ -787,9 +809,9 @@ function emptyCharacterData(classId: number): CharacterData { const inventory: Item[] = [] const startingAbilitySlots: Array = gc.spells .filter((s) => s.unlockLevel === 1) - .slice(0, 5) + .slice(0, ABILITY_SLOT_COUNT) .map((s) => s.id) - while (startingAbilitySlots.length < 6) startingAbilitySlots.push(null) + while (startingAbilitySlots.length < ABILITY_SLOT_COUNT) startingAbilitySlots.push(null) return { level: 1, experience: 0, @@ -829,31 +851,30 @@ function createLocalRepository(store: LocalSaveStore): GameRepository { }, async saveProfile(classId, abilitySlots) { const save = requireStoredSave(store) - const static_ = clone(starterProfile) as CharacterProfile - const gameClass = static_.classes.find((candidate) => candidate.id === classId) - if (!gameClass) throw new Error('Selected class does not exist.') + const static_ = clone(starterProfile) as CharacterProfile + const gameClass = static_.classes.find((candidate) => candidate.id === classId) + if (!gameClass) throw new Error('Selected class does not exist.') - const slots = abilitySlots.slice(0, 6) - while (slots.length < 6) slots.push(null) - const selectedIds = slots.filter((id): id is number => id !== null) - if (new Set(selectedIds).size !== selectedIds.length) { - throw new Error('The same ability cannot be equipped twice.') - } - const activeChar = save.characters[save.activeClassId] - const validIds = new Set( - gameClass.spells - .filter((spell) => spell.unlockLevel <= activeChar.level) - .map((spell) => spell.id), - ) - if (selectedIds.some((id) => !validIds.has(id))) { - throw new Error('One or more abilities are locked or belong to another class.') - } + const slots = normalizeAbilitySlots(abilitySlots) + const selectedIds = slots.filter((id): id is number => id !== null) + if (new Set(selectedIds).size !== selectedIds.length) { + throw new Error('The same ability cannot be equipped twice.') + } + const activeChar = save.characters[save.activeClassId] + const validIds = new Set( + gameClass.spells + .filter((spell) => spell.unlockLevel <= activeChar.level) + .map((spell) => spell.id), + ) + if (selectedIds.some((id) => !validIds.has(id))) { + throw new Error('One or more abilities are locked or belong to another class.') + } - if (!save.characters[classId]) { - save.characters[classId] = emptyCharacterData(classId) - } - save.characters[classId].abilitySlots = slots - save.activeClassId = classId + if (!save.characters[classId]) { + save.characters[classId] = emptyCharacterData(classId) + } + save.characters[classId].abilitySlots = slots + save.activeClassId = classId store.writeSave(save) return buildProfile(save) }, diff --git a/src/offline-starter-profile.json b/src/offline-starter-profile.json index 4f74932..8b72c34 100644 --- a/src/offline-starter-profile.json +++ b/src/offline-starter-profile.json @@ -1211,6 +1211,366 @@ ], "canCraft": false }, + { + "id": 1004, + "difficultyId": 1, + "sourceDungeonId": 1, + "sourceEncounterId": 12, + "item": { + "id": 4, + "slug": "cinderstep-boots", + "name": "Honed Yian Kut-Ku Boots", + "slot": "boots", + "rarity": "uncommon", + "itemLevel": 5, + "healingPower": 3, + "maxResourceBonus": 0, + "glyph": "b", + "description": "Crafted with Yian Kut-Ku coins.", + "setId": null, + "setSlug": null, + "setName": null + }, + "components": [ + { + "item": { + "id": 281201, + "slug": "yian-kut-ku-coin-ilvl-1", + "name": "Raw Yian Kut-Ku Coin", + "slot": "component", + "rarity": "common", + "itemLevel": 1, + "healingPower": 0, + "maxResourceBonus": 0, + "glyph": "$", + "description": "A boss coin from Yian Kut-Ku used for item level 1 crafting." + }, + "quantity": 5, + "owned": 0 + } + ], + "canCraft": false + }, + { + "id": 1002, + "difficultyId": 1, + "sourceDungeonId": 1, + "sourceEncounterId": 3, + "item": { + "id": 2, + "slug": "wardens-cinderwrap", + "name": "Honed Bulldrome Chest", + "slot": "chest", + "rarity": "uncommon", + "itemLevel": 5, + "healingPower": 3, + "maxResourceBonus": 0, + "glyph": "C", + "description": "Crafted with Bulldrome coins.", + "setId": null, + "setSlug": null, + "setName": null + }, + "components": [ + { + "item": { + "id": 280301, + "slug": "bulldrome-coin-ilvl-1", + "name": "Raw Bulldrome Coin", + "slot": "component", + "rarity": "common", + "itemLevel": 1, + "healingPower": 0, + "maxResourceBonus": 0, + "glyph": "$", + "description": "A boss coin from Bulldrome used for item level 1 crafting." + }, + "quantity": 5, + "owned": 0 + } + ], + "canCraft": false + }, + { + "id": 1003, + "difficultyId": 1, + "sourceDungeonId": 1, + "sourceEncounterId": 3, + "item": { + "id": 6, + "slug": "furnace-tenders-wraps", + "name": "Honed Bulldrome Gloves", + "slot": "gloves", + "rarity": "uncommon", + "itemLevel": 5, + "healingPower": 3, + "maxResourceBonus": 2, + "glyph": "g", + "description": "Crafted with Bulldrome coins.", + "setId": null, + "setSlug": null, + "setName": null + }, + "components": [ + { + "item": { + "id": 280301, + "slug": "bulldrome-coin-ilvl-1", + "name": "Raw Bulldrome Coin", + "slot": "component", + "rarity": "common", + "itemLevel": 1, + "healingPower": 0, + "maxResourceBonus": 0, + "glyph": "$", + "description": "A boss coin from Bulldrome used for item level 1 crafting." + }, + "quantity": 5, + "owned": 0 + } + ], + "canCraft": false + }, + { + "id": 1001, + "difficultyId": 1, + "sourceDungeonId": 1, + "sourceEncounterId": 3, + "item": { + "id": 5, + "slug": "adepts-hood", + "name": "Honed Bulldrome Helmet", + "slot": "helmet", + "rarity": "uncommon", + "itemLevel": 5, + "healingPower": 3, + "maxResourceBonus": 4, + "glyph": "^", + "description": "Crafted with Bulldrome coins.", + "setId": null, + "setSlug": null, + "setName": null + }, + "components": [ + { + "item": { + "id": 280301, + "slug": "bulldrome-coin-ilvl-1", + "name": "Raw Bulldrome Coin", + "slot": "component", + "rarity": "common", + "itemLevel": 1, + "healingPower": 0, + "maxResourceBonus": 0, + "glyph": "$", + "description": "A boss coin from Bulldrome used for item level 1 crafting." + }, + "quantity": 5, + "owned": 0 + } + ], + "canCraft": false + }, + { + "id": 1009, + "difficultyId": 1, + "sourceDungeonId": 1, + "sourceEncounterId": 22, + "item": { + "id": 9, + "slug": "sootglass-pendant", + "name": "Honed Rathian Necklace", + "slot": "necklace", + "rarity": "uncommon", + "itemLevel": 5, + "healingPower": 4, + "maxResourceBonus": 4, + "glyph": "n", + "description": "Crafted with Rathian coins.", + "setId": null, + "setSlug": null, + "setName": null + }, + "components": [ + { + "item": { + "id": 282201, + "slug": "rathian-coin-ilvl-1", + "name": "Raw Rathian Coin", + "slot": "component", + "rarity": "common", + "itemLevel": 1, + "healingPower": 0, + "maxResourceBonus": 0, + "glyph": "$", + "description": "A boss coin from Rathian used for item level 1 crafting." + }, + "quantity": 5, + "owned": 0 + } + ], + "canCraft": false + }, + { + "id": 1008, + "difficultyId": 1, + "sourceDungeonId": 1, + "sourceEncounterId": 22, + "item": { + "id": 8, + "slug": "ashwalker-legwraps", + "name": "Honed Rathian Pants", + "slot": "pants", + "rarity": "uncommon", + "itemLevel": 5, + "healingPower": 3, + "maxResourceBonus": 3, + "glyph": "P", + "description": "Crafted with Rathian coins.", + "setId": null, + "setSlug": null, + "setName": null + }, + "components": [ + { + "item": { + "id": 282201, + "slug": "rathian-coin-ilvl-1", + "name": "Raw Rathian Coin", + "slot": "component", + "rarity": "common", + "itemLevel": 1, + "healingPower": 0, + "maxResourceBonus": 0, + "glyph": "$", + "description": "A boss coin from Rathian used for item level 1 crafting." + }, + "quantity": 5, + "owned": 0 + } + ], + "canCraft": false + }, + { + "id": 1005, + "difficultyId": 1, + "sourceDungeonId": 1, + "sourceEncounterId": 12, + "item": { + "id": 1, + "slug": "emberglass-sigil", + "name": "Honed Yian Kut-Ku Ring", + "slot": "ring", + "rarity": "uncommon", + "itemLevel": 5, + "healingPower": 4, + "maxResourceBonus": 5, + "glyph": "o", + "description": "Crafted with Yian Kut-Ku coins.", + "setId": null, + "setSlug": null, + "setName": null + }, + "components": [ + { + "item": { + "id": 281201, + "slug": "yian-kut-ku-coin-ilvl-1", + "name": "Raw Yian Kut-Ku Coin", + "slot": "component", + "rarity": "common", + "itemLevel": 1, + "healingPower": 0, + "maxResourceBonus": 0, + "glyph": "$", + "description": "A boss coin from Yian Kut-Ku used for item level 1 crafting." + }, + "quantity": 5, + "owned": 0 + } + ], + "canCraft": false + }, + { + "id": 1006, + "difficultyId": 1, + "sourceDungeonId": 1, + "sourceEncounterId": 12, + "item": { + "id": 7, + "slug": "warden-ember", + "name": "Honed Yian Kut-Ku Trinket", + "slot": "trinket", + "rarity": "uncommon", + "itemLevel": 5, + "healingPower": 4, + "maxResourceBonus": 4, + "glyph": "*", + "description": "Crafted with Yian Kut-Ku coins.", + "setId": null, + "setSlug": null, + "setName": null + }, + "components": [ + { + "item": { + "id": 281201, + "slug": "yian-kut-ku-coin-ilvl-1", + "name": "Raw Yian Kut-Ku Coin", + "slot": "component", + "rarity": "common", + "itemLevel": 1, + "healingPower": 0, + "maxResourceBonus": 0, + "glyph": "$", + "description": "A boss coin from Yian Kut-Ku used for item level 1 crafting." + }, + "quantity": 5, + "owned": 0 + } + ], + "canCraft": false + }, + { + "id": 1007, + "difficultyId": 1, + "sourceDungeonId": 1, + "sourceEncounterId": 22, + "item": { + "id": 3, + "slug": "ashwood-crook", + "name": "Honed Rathian Weapon", + "slot": "weapon", + "rarity": "uncommon", + "itemLevel": 5, + "healingPower": 5, + "maxResourceBonus": 0, + "glyph": "/", + "description": "Crafted with Rathian coins.", + "setId": null, + "setSlug": null, + "setName": null + }, + "components": [ + { + "item": { + "id": 282201, + "slug": "rathian-coin-ilvl-1", + "name": "Raw Rathian Coin", + "slot": "component", + "rarity": "common", + "itemLevel": 1, + "healingPower": 0, + "maxResourceBonus": 0, + "glyph": "$", + "description": "A boss coin from Rathian used for item level 1 crafting." + }, + "quantity": 5, + "owned": 0 + } + ], + "canCraft": false + }, { "id": 1104, "difficultyId": 2, @@ -1571,6 +1931,366 @@ ], "canCraft": false }, + { + "id": 1204, + "difficultyId": 2, + "sourceDungeonId": 1, + "sourceEncounterId": 12, + "item": { + "id": 304, + "slug": "runed-cinderstep-boots", + "name": "Blue Yian Kut-Ku Boots", + "slot": "boots", + "rarity": "rare", + "itemLevel": 15, + "healingPower": 9, + "maxResourceBonus": 8, + "glyph": "b", + "description": "Crafted with Yian Kut-Ku coins.", + "setId": null, + "setSlug": null, + "setName": null + }, + "components": [ + { + "item": { + "id": 281210, + "slug": "yian-kut-ku-coin-ilvl-10", + "name": "Green Yian Kut-Ku Coin", + "slot": "component", + "rarity": "uncommon", + "itemLevel": 10, + "healingPower": 0, + "maxResourceBonus": 0, + "glyph": "$", + "description": "A boss coin from Yian Kut-Ku used for item level 10 crafting." + }, + "quantity": 15, + "owned": 0 + } + ], + "canCraft": false + }, + { + "id": 1202, + "difficultyId": 2, + "sourceDungeonId": 1, + "sourceEncounterId": 3, + "item": { + "id": 302, + "slug": "runed-cinderwrap", + "name": "Blue Bulldrome Chest", + "slot": "chest", + "rarity": "rare", + "itemLevel": 15, + "healingPower": 11, + "maxResourceBonus": 3, + "glyph": "C", + "description": "Crafted with Bulldrome coins.", + "setId": null, + "setSlug": null, + "setName": null + }, + "components": [ + { + "item": { + "id": 280310, + "slug": "bulldrome-coin-ilvl-10", + "name": "Green Bulldrome Coin", + "slot": "component", + "rarity": "uncommon", + "itemLevel": 10, + "healingPower": 0, + "maxResourceBonus": 0, + "glyph": "$", + "description": "A boss coin from Bulldrome used for item level 10 crafting." + }, + "quantity": 15, + "owned": 0 + } + ], + "canCraft": false + }, + { + "id": 1203, + "difficultyId": 2, + "sourceDungeonId": 1, + "sourceEncounterId": 3, + "item": { + "id": 306, + "slug": "runed-furnace-wraps", + "name": "Blue Bulldrome Gloves", + "slot": "gloves", + "rarity": "rare", + "itemLevel": 15, + "healingPower": 11, + "maxResourceBonus": 6, + "glyph": "g", + "description": "Crafted with Bulldrome coins.", + "setId": null, + "setSlug": null, + "setName": null + }, + "components": [ + { + "item": { + "id": 280310, + "slug": "bulldrome-coin-ilvl-10", + "name": "Green Bulldrome Coin", + "slot": "component", + "rarity": "uncommon", + "itemLevel": 10, + "healingPower": 0, + "maxResourceBonus": 0, + "glyph": "$", + "description": "A boss coin from Bulldrome used for item level 10 crafting." + }, + "quantity": 15, + "owned": 0 + } + ], + "canCraft": false + }, + { + "id": 1201, + "difficultyId": 2, + "sourceDungeonId": 1, + "sourceEncounterId": 3, + "item": { + "id": 305, + "slug": "runed-adepts-hood", + "name": "Blue Bulldrome Helmet", + "slot": "helmet", + "rarity": "rare", + "itemLevel": 15, + "healingPower": 9, + "maxResourceBonus": 9, + "glyph": "^", + "description": "Crafted with Bulldrome coins.", + "setId": null, + "setSlug": null, + "setName": null + }, + "components": [ + { + "item": { + "id": 280310, + "slug": "bulldrome-coin-ilvl-10", + "name": "Green Bulldrome Coin", + "slot": "component", + "rarity": "uncommon", + "itemLevel": 10, + "healingPower": 0, + "maxResourceBonus": 0, + "glyph": "$", + "description": "A boss coin from Bulldrome used for item level 10 crafting." + }, + "quantity": 15, + "owned": 0 + } + ], + "canCraft": false + }, + { + "id": 1209, + "difficultyId": 2, + "sourceDungeonId": 1, + "sourceEncounterId": 22, + "item": { + "id": 309, + "slug": "runed-sootglass-pendant", + "name": "Blue Rathian Necklace", + "slot": "necklace", + "rarity": "rare", + "itemLevel": 15, + "healingPower": 12, + "maxResourceBonus": 10, + "glyph": "n", + "description": "Crafted with Rathian coins.", + "setId": null, + "setSlug": null, + "setName": null + }, + "components": [ + { + "item": { + "id": 282210, + "slug": "rathian-coin-ilvl-10", + "name": "Green Rathian Coin", + "slot": "component", + "rarity": "uncommon", + "itemLevel": 10, + "healingPower": 0, + "maxResourceBonus": 0, + "glyph": "$", + "description": "A boss coin from Rathian used for item level 10 crafting." + }, + "quantity": 15, + "owned": 0 + } + ], + "canCraft": false + }, + { + "id": 1208, + "difficultyId": 2, + "sourceDungeonId": 1, + "sourceEncounterId": 22, + "item": { + "id": 308, + "slug": "runed-ashwalker-legwraps", + "name": "Blue Rathian Pants", + "slot": "pants", + "rarity": "rare", + "itemLevel": 15, + "healingPower": 9, + "maxResourceBonus": 9, + "glyph": "P", + "description": "Crafted with Rathian coins.", + "setId": null, + "setSlug": null, + "setName": null + }, + "components": [ + { + "item": { + "id": 282210, + "slug": "rathian-coin-ilvl-10", + "name": "Green Rathian Coin", + "slot": "component", + "rarity": "uncommon", + "itemLevel": 10, + "healingPower": 0, + "maxResourceBonus": 0, + "glyph": "$", + "description": "A boss coin from Rathian used for item level 10 crafting." + }, + "quantity": 15, + "owned": 0 + } + ], + "canCraft": false + }, + { + "id": 1205, + "difficultyId": 2, + "sourceDungeonId": 1, + "sourceEncounterId": 12, + "item": { + "id": 301, + "slug": "runed-emberglass-sigil", + "name": "Blue Yian Kut-Ku Ring", + "slot": "ring", + "rarity": "rare", + "itemLevel": 15, + "healingPower": 10, + "maxResourceBonus": 13, + "glyph": "o", + "description": "Crafted with Yian Kut-Ku coins.", + "setId": null, + "setSlug": null, + "setName": null + }, + "components": [ + { + "item": { + "id": 281210, + "slug": "yian-kut-ku-coin-ilvl-10", + "name": "Green Yian Kut-Ku Coin", + "slot": "component", + "rarity": "uncommon", + "itemLevel": 10, + "healingPower": 0, + "maxResourceBonus": 0, + "glyph": "$", + "description": "A boss coin from Yian Kut-Ku used for item level 10 crafting." + }, + "quantity": 15, + "owned": 0 + } + ], + "canCraft": false + }, + { + "id": 1206, + "difficultyId": 2, + "sourceDungeonId": 1, + "sourceEncounterId": 12, + "item": { + "id": 307, + "slug": "runed-warden-ember", + "name": "Blue Yian Kut-Ku Trinket", + "slot": "trinket", + "rarity": "rare", + "itemLevel": 15, + "healingPower": 12, + "maxResourceBonus": 10, + "glyph": "*", + "description": "Crafted with Yian Kut-Ku coins.", + "setId": null, + "setSlug": null, + "setName": null + }, + "components": [ + { + "item": { + "id": 281210, + "slug": "yian-kut-ku-coin-ilvl-10", + "name": "Green Yian Kut-Ku Coin", + "slot": "component", + "rarity": "uncommon", + "itemLevel": 10, + "healingPower": 0, + "maxResourceBonus": 0, + "glyph": "$", + "description": "A boss coin from Yian Kut-Ku used for item level 10 crafting." + }, + "quantity": 15, + "owned": 0 + } + ], + "canCraft": false + }, + { + "id": 1207, + "difficultyId": 2, + "sourceDungeonId": 1, + "sourceEncounterId": 22, + "item": { + "id": 303, + "slug": "runed-ashwood-crook", + "name": "Blue Rathian Weapon", + "slot": "weapon", + "rarity": "rare", + "itemLevel": 15, + "healingPower": 15, + "maxResourceBonus": 3, + "glyph": "/", + "description": "Crafted with Rathian coins.", + "setId": null, + "setSlug": null, + "setName": null + }, + "components": [ + { + "item": { + "id": 282210, + "slug": "rathian-coin-ilvl-10", + "name": "Green Rathian Coin", + "slot": "component", + "rarity": "uncommon", + "itemLevel": 10, + "healingPower": 0, + "maxResourceBonus": 0, + "glyph": "$", + "description": "A boss coin from Rathian used for item level 10 crafting." + }, + "quantity": 15, + "owned": 0 + } + ], + "canCraft": false + }, { "id": 1304, "difficultyId": 4, @@ -3592,7 +4312,152 @@ "description": "A three-boss hunt featuring Nargacuga, Azuros, and Diablos.", "locationName": "The Monster Frontier", "difficulties": [], - "encounters": [], + "encounters": [ + { + "id": 401, + "dungeonId": 4, + "sequence": 1, + "slug": "nargacuga-dungeon-approach", + "enemyName": "Nargacuga Approach", + "encounterType": "trash", + "maxHealth": 1325, + "damage": 18, + "tankDamage": 10, + "partyDamage": 28, + "description": "Hunters clear the path before Nargacuga.", + "imageUrl": "/boss-placeholder.svg", + "isBoss": false, + "lootTables": [] + }, + { + "id": 402, + "dungeonId": 4, + "sequence": 2, + "slug": "nargacuga-dungeon-guardians", + "enemyName": "Nargacuga Guardians", + "encounterType": "trash", + "maxHealth": 1395, + "damage": 19, + "tankDamage": 11, + "partyDamage": 30, + "description": "Hunters clear the path before Nargacuga.", + "imageUrl": "/boss-placeholder.svg", + "isBoss": false, + "lootTables": [] + }, + { + "id": 403, + "dungeonId": 4, + "sequence": 3, + "slug": "nargacuga-dungeon-boss", + "enemyName": "Nargacuga", + "encounterType": "boss", + "maxHealth": 1655, + "damage": 23, + "tankDamage": 15, + "partyDamage": 34, + "description": "Nargacuga drops boss coins for item level 15 crafting.", + "imageUrl": "/boss-placeholder.svg", + "isBoss": true, + "lootTables": [] + }, + { + "id": 404, + "dungeonId": 4, + "sequence": 4, + "slug": "azuros-dungeon-approach", + "enemyName": "Azuros Approach", + "encounterType": "trash", + "maxHealth": 1445, + "damage": 20, + "tankDamage": 12, + "partyDamage": 31, + "description": "Hunters clear the path before Azuros.", + "imageUrl": "/boss-placeholder.svg", + "isBoss": false, + "lootTables": [] + }, + { + "id": 405, + "dungeonId": 4, + "sequence": 5, + "slug": "azuros-dungeon-guardians", + "enemyName": "Azuros Guardians", + "encounterType": "trash", + "maxHealth": 1515, + "damage": 21, + "tankDamage": 13, + "partyDamage": 33, + "description": "Hunters clear the path before Azuros.", + "imageUrl": "/boss-placeholder.svg", + "isBoss": false, + "lootTables": [] + }, + { + "id": 406, + "dungeonId": 4, + "sequence": 6, + "slug": "azuros-dungeon-boss", + "enemyName": "Azuros", + "encounterType": "boss", + "maxHealth": 1775, + "damage": 25, + "tankDamage": 17, + "partyDamage": 37, + "description": "Azuros drops boss coins for item level 15 crafting.", + "imageUrl": "/boss-placeholder.svg", + "isBoss": true, + "lootTables": [] + }, + { + "id": 407, + "dungeonId": 4, + "sequence": 7, + "slug": "diablos-dungeon-approach", + "enemyName": "Diablos Approach", + "encounterType": "trash", + "maxHealth": 1565, + "damage": 22, + "tankDamage": 14, + "partyDamage": 34, + "description": "Hunters clear the path before Diablos.", + "imageUrl": "/boss-placeholder.svg", + "isBoss": false, + "lootTables": [] + }, + { + "id": 408, + "dungeonId": 4, + "sequence": 8, + "slug": "diablos-dungeon-guardians", + "enemyName": "Diablos Guardians", + "encounterType": "trash", + "maxHealth": 1635, + "damage": 23, + "tankDamage": 15, + "partyDamage": 36, + "description": "Hunters clear the path before Diablos.", + "imageUrl": "/boss-placeholder.svg", + "isBoss": false, + "lootTables": [] + }, + { + "id": 409, + "dungeonId": 4, + "sequence": 9, + "slug": "diablos-dungeon-boss", + "enemyName": "Diablos", + "encounterType": "boss", + "maxHealth": 1895, + "damage": 27, + "tankDamage": 19, + "partyDamage": 40, + "description": "Diablos drops boss coins for item level 15 crafting.", + "imageUrl": "/boss-placeholder.svg", + "isBoss": true, + "lootTables": [] + } + ], "completionLoot": [], "leaderboard": [], "leaderboards": { @@ -3614,7 +4479,152 @@ "description": "A raid-scale hunt against Nargacuga, Azuros, and Diablos.", "locationName": "The Monster Frontier", "difficulties": [], - "encounters": [], + "encounters": [ + { + "id": 501, + "dungeonId": 5, + "sequence": 1, + "slug": "nargacuga-raid-approach", + "enemyName": "Nargacuga Approach", + "encounterType": "trash", + "maxHealth": 2225, + "damage": 18, + "tankDamage": 10, + "partyDamage": 52, + "description": "Hunters clear the raid path before Nargacuga.", + "imageUrl": "/boss-placeholder.svg", + "isBoss": false, + "lootTables": [] + }, + { + "id": 502, + "dungeonId": 5, + "sequence": 2, + "slug": "nargacuga-raid-guardians", + "enemyName": "Nargacuga Guardians", + "encounterType": "trash", + "maxHealth": 2295, + "damage": 19, + "tankDamage": 11, + "partyDamage": 54, + "description": "Hunters clear the raid path before Nargacuga.", + "imageUrl": "/boss-placeholder.svg", + "isBoss": false, + "lootTables": [] + }, + { + "id": 503, + "dungeonId": 5, + "sequence": 3, + "slug": "nargacuga-raid-boss", + "enemyName": "Nargacuga", + "encounterType": "boss", + "maxHealth": 2555, + "damage": 23, + "tankDamage": 15, + "partyDamage": 58, + "description": "Nargacuga drops boss coins for item level 15 crafting.", + "imageUrl": "/boss-placeholder.svg", + "isBoss": true, + "lootTables": [] + }, + { + "id": 504, + "dungeonId": 5, + "sequence": 4, + "slug": "azuros-raid-approach", + "enemyName": "Azuros Approach", + "encounterType": "trash", + "maxHealth": 2345, + "damage": 20, + "tankDamage": 12, + "partyDamage": 55, + "description": "Hunters clear the raid path before Azuros.", + "imageUrl": "/boss-placeholder.svg", + "isBoss": false, + "lootTables": [] + }, + { + "id": 505, + "dungeonId": 5, + "sequence": 5, + "slug": "azuros-raid-guardians", + "enemyName": "Azuros Guardians", + "encounterType": "trash", + "maxHealth": 2415, + "damage": 21, + "tankDamage": 13, + "partyDamage": 57, + "description": "Hunters clear the raid path before Azuros.", + "imageUrl": "/boss-placeholder.svg", + "isBoss": false, + "lootTables": [] + }, + { + "id": 506, + "dungeonId": 5, + "sequence": 6, + "slug": "azuros-raid-boss", + "enemyName": "Azuros", + "encounterType": "boss", + "maxHealth": 2675, + "damage": 25, + "tankDamage": 17, + "partyDamage": 61, + "description": "Azuros drops boss coins for item level 15 crafting.", + "imageUrl": "/boss-placeholder.svg", + "isBoss": true, + "lootTables": [] + }, + { + "id": 507, + "dungeonId": 5, + "sequence": 7, + "slug": "diablos-raid-approach", + "enemyName": "Diablos Approach", + "encounterType": "trash", + "maxHealth": 2465, + "damage": 22, + "tankDamage": 14, + "partyDamage": 58, + "description": "Hunters clear the raid path before Diablos.", + "imageUrl": "/boss-placeholder.svg", + "isBoss": false, + "lootTables": [] + }, + { + "id": 508, + "dungeonId": 5, + "sequence": 8, + "slug": "diablos-raid-guardians", + "enemyName": "Diablos Guardians", + "encounterType": "trash", + "maxHealth": 2535, + "damage": 23, + "tankDamage": 15, + "partyDamage": 60, + "description": "Hunters clear the raid path before Diablos.", + "imageUrl": "/boss-placeholder.svg", + "isBoss": false, + "lootTables": [] + }, + { + "id": 509, + "dungeonId": 5, + "sequence": 9, + "slug": "diablos-raid-boss", + "enemyName": "Diablos", + "encounterType": "boss", + "maxHealth": 2795, + "damage": 27, + "tankDamage": 19, + "partyDamage": 64, + "description": "Diablos drops boss coins for item level 15 crafting.", + "imageUrl": "/boss-placeholder.svg", + "isBoss": true, + "lootTables": [] + } + ], "completionLoot": [], "leaderboard": [], "leaderboards": {