X-Git-Url: https://git.localhorst.tv/?a=blobdiff_plain;ds=sidebyside;f=resources%2Fjs%2Fhelpers%2Ftracker.js;h=e4b0ebe9f765a33d497ff2d994537a64168860ae;hb=249e06be11d0f7778d99956c87d4f0a8ac7e69f7;hp=707e3f708e59f86d2c49cc0f1d622336bd9fa312;hpb=b5a50d74cf042fa7fc874d8184dc37ae20bb74dd;p=alttp.git diff --git a/resources/js/helpers/tracker.js b/resources/js/helpers/tracker.js index 707e3f7..e4b0ebe 100644 --- a/resources/js/helpers/tracker.js +++ b/resources/js/helpers/tracker.js @@ -68,6 +68,10 @@ export const BOSSES = [ ]; export const CONFIG = { + showMap: 'situational', + showCompass: 'situational', + showSmall: 'always', + showBig: 'always', wildMap: false, wildCompass: false, wildSmall: false, @@ -92,7 +96,7 @@ export const DUNGEONS = [ mask: DUNGEON_MASKS.HC, checks: [ 'dark-cross', - 'hc-map', + 'hc-map-chest', 'hc-boom', 'hc-cell', 'sanc', @@ -905,7 +909,7 @@ export const UNDERWORLD_LOCATIONS = [ chest: 0, }, { - id: 'hc-map', + id: 'hc-map-chest', area: 'hc', room: 0x72, chest: 0, @@ -948,7 +952,7 @@ export const UNDERWORLD_LOCATIONS = [ { id: 'hype-cave-bottom', room: 0x11E, - chest: 4, + chest: 3, }, { id: 'hype-cave-npc', @@ -1140,12 +1144,12 @@ export const UNDERWORLD_LOCATIONS = [ { id: 'paradox-lower-far-right', room: 0xEF, - chest: 4, + chest: 3, }, { id: 'paradox-lower-mid', room: 0xEF, - chest: 5, + chest: 4, }, { id: 'paradox-upper-left', @@ -1543,15 +1547,29 @@ export const UNDERWORLD_LOCATIONS = [ { id: 'waterfall-fairy-left', room: 0x114, - chest: 4, + chest: 0, }, { id: 'waterfall-fairy-right', room: 0x114, - chest: 5, + chest: 1, }, ]; +export const shouldShowDungeonItem = (config, which) => { + const show = config[`show${which}`] || 'always'; + const wild = config[`wild${which}`] || false; + switch (show) { + default: + case 'always': + return true; + case 'situational': + return wild; + case 'never': + return false; + } +}; + export const toggleBoolean = name => state => ({ ...state, [name]: !state[name], @@ -1588,15 +1606,69 @@ export const highestActive = (state, names) => { return null; }; -export const hasDungeonBoss = (state, dungeon) => !!state[`${dungeon.id}-boss-defeated`]; +export const clearAll = names => state => { + const changes = names.reduce((acc, cur) => ({ ...acc, [cur]: true }), {}); + return { ...state, ...changes }; +}; + +export const unclearAll = names => state => { + const changes = names.reduce((acc, cur) => ({ ...acc, [cur]: false }), {}); + return { ...state, ...changes }; +}; + +export const countClearedLocations = (state, locations) => + locations.reduce((acc, cur) => state[cur] ? acc + 1 : acc, 0); + +export const hasClearedLocations = (state, locations) => + countClearedLocations(state, locations) === locations.length; + +export const countRemainingLocations = (state, locations) => + locations.reduce((acc, cur) => state[cur] ? acc : acc + 1, 0); + +export const hasDungeonBoss = (state, dungeon) => + !dungeon.boss || !!state[`${dungeon.id}-boss-defeated`]; export const getDungeonBoss = (state, dungeon) => state[`${dungeon.id}-boss`] || dungeon.boss || null; -export const hasDungeonPrize = (state, dungeon) => !!state[`${dungeon.id}-prize-acquired`]; +export const hasDungeonPrize = (state, dungeon) => + !dungeon.prize || !!state[`${dungeon.id}-prize-acquired`]; export const getDungeonPrize = (state, dungeon) => state[`${dungeon.id}-prize`] || null; +export const getDungeonClearedItems = (state, dungeon) => state[`${dungeon.id}-checks`] || 0; + +export const getDungeonRemainingItems = (state, dungeon) => + Math.max(0, dungeon.items - getDungeonClearedItems(state, dungeon)); + +export const getDungeonAcquiredSKs = (state, dungeon) => state[`${dungeon.id}-small-key`] || 0; + +export const isDungeonCleared = (state, dungeon) => { + const hasItems = !getDungeonRemainingItems(state, dungeon); + const hasBoss = hasDungeonBoss(state, dungeon); + const hasPrize = hasDungeonPrize(state, dungeon); + return hasItems && hasBoss && hasPrize; +}; + +export const toggleBossDefeated = dungeon => toggleBoolean(`${dungeon.id}-boss-defeated`); + +export const setBossDefeated = (dungeon, defeated) => + state => ({ ...state, [`${dungeon.id}-boss-defeated`]: !!defeated }); + +export const togglePrizeAcquired = dungeon => toggleBoolean(`${dungeon.id}-prize-acquired`); + +export const setPrizeAcquired = (dungeon, acquired) => + state => ({ ...state, [`${dungeon.id}-prize-acquired`]: !!acquired }); + +export const addDungeonCheck = dungeon => increment(`${dungeon.id}-checks`, dungeon.items); + +export const removeDungeonCheck = dungeon => decrement(`${dungeon.id}-checks`, dungeon.items); + +export const resetDungeonChecks = dungeon => state => ({ ...state, [`${dungeon.id}-checks`]: 0 }); + +export const completeDungeonChecks = dungeon => + state => ({ ...state, [`${dungeon.id}-checks`]: dungeon.items }); + export const makeEmptyState = () => { const state = {}; BOOLEAN_STATES.forEach(p => { @@ -1620,6 +1692,14 @@ export const makeEmptyState = () => { state[`${dungeon.id}-prize-acquired`] = false; } }); + OVERWORLD_LOCATIONS.forEach(location => { + state[location.id] = false; + }); + UNDERWORLD_LOCATIONS.forEach(location => { + state[location.id] = false; + }); + state['mm-medallion'] = null; + state['tr-medallion'] = null; return state; }; @@ -1703,11 +1783,15 @@ const collectUnderworld = (state, data) => { }); }; -export const computeState = (data, prizeMap) => { +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; }; @@ -1742,12 +1826,54 @@ const getDungeonAmounts = (config, state) => { return amounts; }; -export const mergeStates = (config, cur, inc) => { - const next = { ...cur, ...inc }; - const amounts = getDungeonAmounts(config, inc); +export const mergeStates = (autoState, manualState) => { + const next = { ...autoState }; + BOOLEAN_STATES.forEach(name => { + if (manualState[name]) { + next[name] = true; + } + }); + INTEGER_STATES.forEach(name => { + next[name] = Math.max(autoState[name] || 0, manualState[name] || 0); + }); DUNGEONS.forEach(dungeon => { - next[`${dungeon.id}-checks`] = amounts[dungeon.id]; + next[`${dungeon.id}-small-key`] += manualState[`${dungeon.id}-small-key`] || 0; + next[`${dungeon.id}-checks`] += manualState[`${dungeon.id}-checks`] || 0; + if (manualState[`${dungeon.id}-big-key`]) { + next[`${dungeon.id}-big-key`] = true; + } + if (manualState[`${dungeon.id}-compass`]) { + next[`${dungeon.id}-compass`] = true; + } + if (manualState[`${dungeon.id}-map`]) { + next[`${dungeon.id}-map`] = true; + } + if (manualState[`${dungeon.id}-boss-defeated`]) { + next[`${dungeon.id}-boss-defeated`] = true; + } + if (manualState[`${dungeon.id}-prize`] && + manualState[`${dungeon.id}-prize`] !== 'crystal' + ) { + next[`${dungeon.id}-prize`] = manualState[`${dungeon.id}-prize`]; + } else if (!next[`${dungeon.id}-prize`]) { + next[`${dungeon.id}-prize`] = 'crystal'; + } + if (manualState[`${dungeon.id}-prize-acquired`]) { + next[`${dungeon.id}-prize-acquired`] = true; + } + }); + OVERWORLD_LOCATIONS.forEach(loc => { + if (manualState[loc.id]) { + next[loc.id] = true; + } + }); + UNDERWORLD_LOCATIONS.forEach(loc => { + if (manualState[loc.id]) { + next[loc.id] = true; + } }); + next['mm-medallion'] = manualState['mm-medallion']; + next['tr-medallion'] = manualState['tr-medallion']; //console.log(next); return next; };