]> git.localhorst.tv Git - alttp.git/blobdiff - resources/js/helpers/tracker.js
simple tracker config dialog
[alttp.git] / resources / js / helpers / tracker.js
index 707e3f708e59f86d2c49cc0f1d622336bd9fa312..e4b0ebe9f765a33d497ff2d994537a64168860ae 100644 (file)
@@ -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;
 };