X-Git-Url: https://git.localhorst.tv/?a=blobdiff_plain;f=resources%2Fjs%2Fhelpers%2Ftracker.js;h=c4b685c5b9ced45af45281b71e0728bae7aac022;hb=90922f8595a8d4fd7780a0b137eed66eaf7d6c49;hp=8b210d2632f266c94e629d204ec2715436badfe9;hpb=6a65eac02f94f00fdd2d56ad8feddf5d9476aa1e;p=alttp.git diff --git a/resources/js/helpers/tracker.js b/resources/js/helpers/tracker.js index 8b210d2..c4b685c 100644 --- a/resources/js/helpers/tracker.js +++ b/resources/js/helpers/tracker.js @@ -66,7 +66,7 @@ export const BOTTLE_CONTENTS = [ 'blue-potion', 'fairy', 'bottle-bee', - 'bottle-bee', + 'bottle-good-bee', ]; export const BOSSES = [ @@ -84,7 +84,9 @@ export const BOSSES = [ export const CONFIG = { bossShuffle: false, + checkCalculation: 'room-data', glitches: 'none', + mapLayout: 'horizontal', showMap: 'situational', showCompass: 'situational', showSmall: 'always', @@ -1573,11 +1575,38 @@ export const UNDERWORLD_LOCATIONS = [ }, ]; +export const getConfigValue = (config, name, fallback) => + Object.prototype.hasOwnProperty.call(config, name) ? config[name] : fallback; + +export const configureDungeons = config => DUNGEONS.map(dungeon => { + const newDungeon = JSON.parse(JSON.stringify(dungeon)); + if (config.wildMap && dungeon.map) { + ++newDungeon.items; + } + if (config.wildCompass && dungeon.compass) { + ++newDungeon.items; + } + if (config.wildSmall) { + newDungeon.items += dungeon.sk; + } + if (config.wildBig && dungeon.bk && !dungeon.dropBk) { + ++newDungeon.items; + } + if (dungeon.boss) { + newDungeon.bosses = config.bossShuffle ? BOSSES : [dungeon.boss]; + } + return newDungeon; +}); + export const applyLogic = (config, dungeons, state) => { const logic = Logic[config.worldState]; const map = {}; for (const name in logic) { - map[name] = logic[name](config, dungeons, state); + try { + map[name] = logic[name](config, dungeons, state); + } catch (e) { + console.error('error evaluating', name, e); + } } return map; }; @@ -1590,7 +1619,7 @@ export const shouldShowDungeonItem = (config, which) => { case 'always': return true; case 'situational': - return wild; + return wild || (which === 'Compass' && config.bossShuffle); case 'never': return false; } @@ -1675,9 +1704,9 @@ export const aggregateLocationStatus = (names, logic, state) => { export const countRemainingLocations = (state, locations) => locations.reduce((acc, cur) => state[cur] ? acc : acc + 1, 0); -export const getGanonCrystals = (state) => state['ganon-crystals']; +export const getGanonCrystals = (config) => getConfigValue(config, 'ganon-crystals', 7); -export const getGTCrystals = (state) => state['gt-crystals']; +export const getGTCrystals = (config) => getConfigValue(config, 'gt-crystals', 7); export const getGTBoss = (state, which) => state[`gt-${which}-boss`]; @@ -1685,7 +1714,9 @@ export const hasDungeonBoss = (state, dungeon) => !dungeon.boss || !!state[`${dungeon.id}-boss-defeated`]; export const getDungeonBoss = (state, dungeon) => - state[`${dungeon.id}-boss`] || dungeon.boss || null; + dungeon.bosses.length > 1 + ? state[`${dungeon.id}-boss`] || dungeon.boss || null + : dungeon.bosses[0]; export const hasDungeonPrize = (state, dungeon) => !dungeon.prize || !!state[`${dungeon.id}-prize-acquired`]; @@ -1776,8 +1807,6 @@ export const makeEmptyState = () => { }); state['mm-medallion'] = null; state['tr-medallion'] = null; - state['gt-crystals'] = 7; - state['ganon-crystals'] = 7; return state; }; @@ -1829,10 +1858,26 @@ const collectInventory = (state, data, prizeMap) => { state[`${dungeon.id}-compass`] = !!(compass & dungeon.mask); state[`${dungeon.id}-small-key`] = data[INV_ADDR.RANDO_KEY_START + dungeon.offset]; state[`${dungeon.id}-big-key`] = !!(bigKey & dungeon.mask); + state[`${dungeon.id}-checks-collected`] = + data[INV_ADDR.RANDO_CHECKS_START + dungeon.offset]; if (dungeon.prize) { const isCrystal = prizeMap[dungeon.offset].isCrystal; const prizeFlags = data[isCrystal ? INV_ADDR.CRYSTALS : INV_ADDR.PENDANTS]; - state[`${dungeon.id}-prize-acquired`] = !!(prizeFlags & prizeMap[dungeon.offset].mask); + const prizeAcquired = !!(prizeFlags & prizeMap[dungeon.offset].mask); + state[`${dungeon.id}-prize-acquired`] = prizeAcquired; + if (prizeAcquired) { + if (!isCrystal) { + if (prizeMap[dungeon.offset].mask === 1) { + state[`${dungeon.id}-prize`] = 'red-pendant'; + } else if (prizeMap[dungeon.offset].mask === 2) { + state[`${dungeon.id}-prize`] = 'blue-pendant'; + } else if (prizeMap[dungeon.offset].mask === 4) { + state[`${dungeon.id}-prize`] = 'green-pendant'; + } + } else { + state[`${dungeon.id}-prize`] = 'crystal'; + } + } } }); }; @@ -1852,28 +1897,20 @@ const collectUnderworld = (state, data) => { }); }; -export const computeState = (config, data, prizeMap) => { - const state = {}; - collectInventory(state, data.slice(SRAM_ADDR.INV_START), prizeMap); - collectOverworld(state, data); - collectUnderworld(state, data.slice(SRAM_ADDR.ROOM_DATA_START)); - const amounts = getDungeonAmounts(config, state); - DUNGEONS.forEach(dungeon => { - state[`${dungeon.id}-checks`] = amounts[dungeon.id]; - }); - return state; -}; - const getDungeonAmounts = (config, state) => { const amounts = {}; DUNGEONS.forEach(dungeon => { let amount = 0; let total = dungeon.checks.length; - dungeon.checks.forEach(check => { - if (state[check]) { - ++amount; - } - }); + if (config.checkCalculation === 'inventory') { + amount = state[`${dungeon.id}-checks-collected`]; + } else { + dungeon.checks.forEach(check => { + if (state[check]) { + ++amount; + } + }); + } if (!config.wildMap && state[`${dungeon.id}-map`]) { --amount; --total; @@ -1895,6 +1932,18 @@ const getDungeonAmounts = (config, state) => { return amounts; }; +export const computeState = (config, data, prizeMap) => { + const state = {}; + collectInventory(state, data.slice(SRAM_ADDR.INV_START), prizeMap); + collectOverworld(state, data); + collectUnderworld(state, data.slice(SRAM_ADDR.ROOM_DATA_START)); + const amounts = getDungeonAmounts(config, state); + DUNGEONS.forEach(dungeon => { + state[`${dungeon.id}-checks`] = amounts[dungeon.id]; + }); + return state; +}; + export const mergeStates = (autoState, manualState) => { const next = { ...autoState }; BOOLEAN_STATES.forEach(name => { @@ -1917,6 +1966,9 @@ export const mergeStates = (autoState, manualState) => { if (manualState[`${dungeon.id}-map`]) { next[`${dungeon.id}-map`] = true; } + if (manualState[`${dungeon.id}-boss`]) { + next[`${dungeon.id}-boss`] = manualState[`${dungeon.id}-boss`]; + } if (manualState[`${dungeon.id}-boss-defeated`]) { next[`${dungeon.id}-boss-defeated`] = true; }