From: Daniel Karbach Date: Thu, 28 Mar 2024 12:35:36 +0000 (+0100) Subject: restructure map for future X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=6702d0ef2ec2a796a9aa6afdf58604800c4915a0;p=alttp.git restructure map for future --- diff --git a/resources/js/components/tracker/Map.js b/resources/js/components/tracker/Map.js deleted file mode 100644 index 3ee4b2f..0000000 --- a/resources/js/components/tracker/Map.js +++ /dev/null @@ -1,820 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import { useTranslation } from 'react-i18next'; - -import { - addDungeonCheck, - aggregateDungeonStatus, - aggregateLocationStatus, - clearAll, - completeDungeonChecks, - countRemainingLocations, - getDungeonClearedItems, - getDungeonRemainingItems, - hasDungeonBoss, - hasDungeonPrize, - isDungeonCleared, - removeDungeonCheck, - resetDungeonChecks, - setBossDefeated, - setPrizeAcquired, - unclearAll, -} from '../../helpers/tracker'; -import { useTracker } from '../../hooks/tracker'; - -const LW_DUNGEONS = [ - { - id: 'hc', - x: 0.5, - y: 0.5, - }, - { - id: 'ct', - x: 0.5, - y: 0.4, - }, - { - id: 'ep', - x: 0.95, - y: 0.42, - }, - { - id: 'dp', - x: 0.075, - y: 0.8, - }, - { - id: 'th', - x: 0.56, - y: 0.05, - }, -]; - -const LW_LOCATIONS = [ - { - id: 'aginah', - checks: [ - 'aginah', - ], - x: 0.2, - y: 0.83, - }, - { - id: 'blinds-hut', - checks: [ - 'blinds-hut-top', - 'blinds-hut-left', - 'blinds-hut-right', - 'blinds-hut-far-left', - 'blinds-hut-far-right', - ], - x: 0.14, - y: 0.42, - }, - { - id: 'bombos-tablet', - checks: [ - 'bombos-tablet', - ], - x: 0.225, - y: 0.925, - }, - { - id: 'bonk-rocks', - checks: [ - 'bonk-rocks', - ], - x: 0.4, - y: 0.3, - }, - { - id: 'bottle-vendor', - checks: [ - 'bottle-vendor', - ], - x: 0.1, - y: 0.475, - }, - { - id: 'cave-45', - checks: [ - 'cave-45', - ], - x: 0.27, - y: 0.83, - }, - { - id: 'checkerboard', - checks: [ - 'checkerboard', - ], - x: 0.18, - y: 0.78, - }, - { - id: 'chicken-house', - checks: [ - 'chicken-house', - ], - x: 0.1, - y: 0.53, - }, - { - id: 'dam', - checks: [ - 'flooded-chest', - 'sunken-treasure', - ], - x: 0.4675, - y: 0.9375, - }, - { - id: 'desert-ledge', - checks: [ - 'desert-ledge', - ], - x: 0.025, - y: 0.9, - }, - { - id: 'ether-tablet', - checks: [ - 'ether-tablet', - ], - x: 0.425, - y: 0.025, - }, - { - id: 'floating-island', - checks: [ - 'floating-island', - ], - x: 0.8, - y: 0.025, - }, - { - id: 'flute-spot', - checks: [ - 'flute-spot', - ], - x: 0.3, - y: 0.675, - }, - { - id: 'graveyard-ledge', - checks: [ - 'graveyard-ledge', - ], - x: 0.57, - y: 0.28, - }, - { - id: 'hobo', - checks: [ - 'hobo', - ], - x: 0.7, - y: 0.7, - }, - { - id: 'ice-rod-cave', - checks: [ - 'ice-rod-cave', - ], - x: 0.9, - y: 0.76, - }, - { - id: 'kak-well', - checks: [ - 'kak-well-top', - 'kak-well-left', - 'kak-well-mid', - 'kak-well-right', - 'kak-well-bottom', - ], - x: 0.04, - y: 0.425, - }, - { - id: 'kings-tomb', - checks: [ - 'kings-tomb', - ], - x: 0.62, - y: 0.3, - }, - { - id: 'lake-hylia-island', - checks: [ - 'lake-hylia-island', - ], - x: 0.725, - y: 0.8375, - }, - { - id: 'library', - checks: [ - 'library', - ], - x: 0.15, - y: 0.65, - }, - { - id: 'links-house', - checks: [ - 'links-house', - ], - x: 0.55, - y: 0.6875, - }, - { - id: 'lost-woods-hideout', - checks: [ - 'lost-woods-hideout', - ], - x: 0.19, - y: 0.14, - }, - { - id: 'lumberjack', - checks: [ - 'lumberjack', - ], - x: 0.3, - y: 0.07, - }, - { - id: 'magic-bat', - checks: [ - 'magic-bat', - ], - x: 0.325, - y: 0.55, - }, - { - id: 'mimic-cave', - checks: [ - 'mimic-cave', - ], - x: 0.85, - y: 0.1, - }, - { - id: 'mini-moldorm-cave', - checks: [ - 'mini-moldorm-left', - 'mini-moldorm-right', - 'mini-moldorm-far-left', - 'mini-moldorm-far-right', - 'mini-moldorm-npc', - ], - x: 0.65, - y: 0.95, - }, - { - id: 'mushroom-spot', - checks: [ - 'mushroom-spot', - ], - x: 0.125, - y: 0.08, - }, - { - id: 'old-man', - checks: [ - 'old-man', - ], - x: 0.405, - y: 0.195, - }, - { - id: 'paradox-cave', - checks: [ - 'paradox-lower-far-left', - 'paradox-lower-left', - 'paradox-lower-right', - 'paradox-lower-far-right', - 'paradox-lower-mid', - 'paradox-upper-left', - 'paradox-upper-right', - ], - x: 0.85, - y: 0.2, - }, - { - id: 'pedestal', - checks: [ - 'pedestal', - ], - x: 0.03, - y: 0.05, - }, - { - id: 'potion-shop', - checks: [ - 'potion-shop', - ], - x: 0.8, - y: 0.325, - }, - { - id: 'race-game', - checks: [ - 'race-game', - ], - x: 0.025, - y: 0.7, - }, - { - id: 'saha', - checks: [ - 'saha', - ], - x: 0.815, - y: 0.465, - }, - { - id: 'saha-hut', - checks: [ - 'saha-left', - 'saha-mid', - 'saha-right', - ], - x: 0.815, - y: 0.42, - }, - { - id: 'sick-kid', - checks: [ - 'sick-kid', - ], - x: 0.155, - y: 0.525, - }, - { - id: 'uncle', - checks: [ - 'uncle', - 'secret-passage', - ], - x: 0.6, - y: 0.4, - }, - { - id: 'spec-rock', - checks: [ - 'spec-rock', - ], - x: 0.48, - y: 0.09, - }, - { - id: 'spec-rock-cave', - checks: [ - 'spec-rock-cave', - ], - x: 0.48, - y: 0.14, - }, - { - id: 'spiral-cave', - checks: [ - 'spiral-cave', - ], - x: 0.8, - y: 0.1, - }, - { - id: 'tavern', - checks: [ - 'tavern', - ], - x: 0.16, - y: 0.58, - }, - { - id: 'waterfall-fairy', - checks: [ - 'waterfall-fairy-left', - 'waterfall-fairy-right', - ], - x: 0.9, - y: 0.15, - }, - { - id: 'zora', - checks: [ - 'zora', - ], - x: 0.975, - y: 0.12, - }, - { - id: 'zora-ledge', - checks: [ - 'zora-ledge', - ], - x: 0.975, - y: 0.165, - }, -]; - -const DW_DUNGEONS = [ - { - id: 'pd', - x: 0.95, - y: 0.42, - }, - { - id: 'sp', - x: 0.4675, - y: 0.9375, - }, - { - id: 'sw', - x: 0.05, - y: 0.05, - }, - { - id: 'tt', - x: 0.125, - y: 0.475, - }, - { - id: 'ip', - x: 0.7975, - y: 0.86, - }, - { - id: 'mm', - x: 0.12, - y: 0.82, - }, - { - id: 'tr', - x: 0.94, - y: 0.06, - }, - { - id: 'gt', - x: 0.56, - y: 0.05, - }, -]; - -const DW_LOCATIONS = [ - { - id: 'blacksmith', - checks: [ - 'blacksmith', - ], - x: 0.15, - y: 0.65, - }, - { - id: 'brewery', - checks: [ - 'brewery', - ], - x: 0.1, - y: 0.6, - }, - { - id: 'bumper-cave', - checks: [ - 'bumper-cave', - ], - x: 0.325, - y: 0.15, - }, - { - id: 'c-house', - checks: [ - 'c-house', - ], - x: 0.2, - y: 0.5, - }, - { - id: 'catfish', - checks: [ - 'catfish', - ], - x: 0.9, - y: 0.175, - }, - { - id: 'chest-game', - checks: [ - 'chest-game', - ], - x: 0.05, - y: 0.45, - }, - { - id: 'digging-game', - checks: [ - 'digging-game', - ], - x: 0.05, - y: 0.7, - }, - { - id: 'hammer-pegs', - checks: [ - 'hammer-pegs', - ], - x: 0.3125, - y: 0.6, - }, - { - id: 'hookshot-cave', - checks: [ - 'hookshot-cave-tl', - 'hookshot-cave-tr', - 'hookshot-cave-bl', - ], - x: 0.85, - y: 0.02, - }, - { - id: 'hookshot-cave-bonk', - checks: [ - 'hookshot-cave-br', - ], - x: 0.85, - y: 0.065, - }, - { - id: 'hype-cave', - checks: [ - 'hype-cave-top', - 'hype-cave-left', - 'hype-cave-right', - 'hype-cave-bottom', - 'hype-cave-npc', - ], - x: 0.6, - y: 0.75, - }, - { - id: 'mire-shed', - checks: [ - 'mire-shed-left', - 'mire-shed-right', - ], - x: 0.04, - y: 0.8, - }, - { - id: 'purple-chest', - checks: [ - 'purple-chest', - ], - x: 0.3125, - y: 0.525, - }, - { - id: 'pyramid', - checks: [ - 'pyramid', - ], - x: 0.575, - y: 0.45, - }, - { - id: 'pyramid-fairy', - checks: [ - 'pyramid-fairy-left', - 'pyramid-fairy-right', - ], - x: 0.45, - y: 0.5, - }, - { - id: 'spike-cave', - checks: [ - 'spike-cave', - ], - x: 0.575, - y: 0.15, - }, - { - id: 'stumpy', - checks: [ - 'stumpy', - ], - x: 0.3125, - y: 0.6875, - }, - { - id: 'super-bunny', - checks: [ - 'super-bunny-top', - 'super-bunny-bottom', - ], - x: 0.85, - y: 0.15, - }, -]; - -const Location = ({ number, l, size }) => { - const { t } = useTranslation(); - - const classNames = ['location', `status-${l.status}`]; - if (size) { - classNames.push(`size-${size}`); - } - if (l.handlePrimary) { - classNames.push('clickable'); - } - - return { - l.handlePrimary(); - e.preventDefault(); - e.stopPropagation(); - }} - onContextMenu={(e) => { - l.handleSecondary(); - e.preventDefault(); - e.stopPropagation(); - }} - transform={`translate(${l.x} ${l.y})`} - > - {t(`tracker.location.${l.id}`)} - - {number && l.remaining ? - {l.remaining} - : null} - ; -}; - -Location.propTypes = { - number: PropTypes.bool, - l: PropTypes.shape({ - id: PropTypes.string, - x: PropTypes.number, - y: PropTypes.number, - number: PropTypes.number, - remaining: PropTypes.number, - status: PropTypes.string, - handlePrimary: PropTypes.func, - handleSecondary: PropTypes.func, - }), - size: PropTypes.string, -}; - -const makeBackground = (src, level) => { - const amount = Math.pow(2, Math.max(0, level - 8)); - const size = 1 / amount; - const tiles = []; - for (let y = 0; y < amount; ++y) { - for (let x = 0; x < amount; ++x) { - tiles.push(); - } - } - return tiles; -}; - -const Map = () => { - const { dungeons, logic, setManualState, state } = useTracker(); - - const mapDungeon = React.useCallback(dungeon => { - const definition = dungeons.find(d => d.id === dungeon.id); - const remaining = getDungeonRemainingItems(state, definition); - const status = aggregateDungeonStatus(definition, logic, state); - return { - ...dungeon, - status, - remaining, - handlePrimary: () => { - if (getDungeonRemainingItems(state, definition)) { - setManualState(addDungeonCheck(definition)); - } else if ( - !hasDungeonBoss(state, definition) || !hasDungeonPrize(state, definition) - ) { - if (definition.boss) { - setManualState(setBossDefeated(definition, true)); - } - if (definition.prize) { - setManualState(setPrizeAcquired(definition, true)); - } - } else { - setManualState(resetDungeonChecks(definition)); - if (definition.boss) { - setManualState(setBossDefeated(definition, false)); - } - if (definition.prize) { - setManualState(setPrizeAcquired(definition, false)); - } - } - }, - handleSecondary: () => { - if (isDungeonCleared(state, definition)) { - if (definition.items) { - setManualState(removeDungeonCheck(definition)); - } - if (definition.boss) { - setManualState(setBossDefeated(definition, false)); - } - if (definition.prize) { - setManualState(setPrizeAcquired(definition, false)); - } - } else if (getDungeonClearedItems(state, definition)) { - setManualState(removeDungeonCheck(definition)); - } else { - setManualState(completeDungeonChecks(definition)); - if (definition.boss) { - setManualState(setBossDefeated(definition, true)); - } - if (definition.prize) { - setManualState(setPrizeAcquired(definition, true)); - } - } - }, - }; - }, [dungeons, logic, setManualState, state]); - - const mapLocation = React.useCallback(loc => { - const remaining = countRemainingLocations(state, loc.checks); - const status = aggregateLocationStatus(loc.checks, logic, state); - return { - ...loc, - remaining, - status, - handlePrimary: () => { - if (remaining) { - setManualState(clearAll(loc.checks)); - } else { - setManualState(unclearAll(loc.checks)); - } - }, - handleSecondary: () => { - if (remaining) { - setManualState(clearAll(loc.checks)); - } else { - setManualState(unclearAll(loc.checks)); - } - }, - }; - }, [logic, setManualState, state]); - - const lwDungeons = React.useMemo(() => LW_DUNGEONS.map(mapDungeon), [mapDungeon]); - const lwLocations = React.useMemo(() => LW_LOCATIONS.map(mapLocation), [mapLocation]); - - const dwDungeons = React.useMemo(() => DW_DUNGEONS.map(mapDungeon), [mapDungeon]); - const dwLocations = React.useMemo(() => DW_LOCATIONS.map(mapLocation), [mapLocation]); - - return
- { - e.preventDefault(); - e.stopPropagation(); - }} - > - - - {makeBackground('lw_files', 10)} - - - {lwLocations.map(l => - - )} - {lwDungeons.map(l => - - )} - - - - - {makeBackground('dw_files', 10)} - - - {dwLocations.map(l => - - )} - {dwDungeons.map(l => - - )} - - - -
; -}; - -export default Map; diff --git a/resources/js/components/tracker/Map/Overworld.js b/resources/js/components/tracker/Map/Overworld.js new file mode 100644 index 0000000..609dc34 --- /dev/null +++ b/resources/js/components/tracker/Map/Overworld.js @@ -0,0 +1,818 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import { + addDungeonCheck, + aggregateDungeonStatus, + aggregateLocationStatus, + clearAll, + completeDungeonChecks, + countRemainingLocations, + getDungeonClearedItems, + getDungeonRemainingItems, + hasDungeonBoss, + hasDungeonPrize, + isDungeonCleared, + removeDungeonCheck, + resetDungeonChecks, + setBossDefeated, + setPrizeAcquired, + unclearAll, +} from '../../../helpers/tracker'; +import { useTracker } from '../../../hooks/tracker'; + +const LW_DUNGEONS = [ + { + id: 'hc', + x: 0.5, + y: 0.5, + }, + { + id: 'ct', + x: 0.5, + y: 0.4, + }, + { + id: 'ep', + x: 0.95, + y: 0.42, + }, + { + id: 'dp', + x: 0.075, + y: 0.8, + }, + { + id: 'th', + x: 0.56, + y: 0.05, + }, +]; + +const LW_LOCATIONS = [ + { + id: 'aginah', + checks: [ + 'aginah', + ], + x: 0.2, + y: 0.83, + }, + { + id: 'blinds-hut', + checks: [ + 'blinds-hut-top', + 'blinds-hut-left', + 'blinds-hut-right', + 'blinds-hut-far-left', + 'blinds-hut-far-right', + ], + x: 0.14, + y: 0.42, + }, + { + id: 'bombos-tablet', + checks: [ + 'bombos-tablet', + ], + x: 0.225, + y: 0.925, + }, + { + id: 'bonk-rocks', + checks: [ + 'bonk-rocks', + ], + x: 0.4, + y: 0.3, + }, + { + id: 'bottle-vendor', + checks: [ + 'bottle-vendor', + ], + x: 0.1, + y: 0.475, + }, + { + id: 'cave-45', + checks: [ + 'cave-45', + ], + x: 0.27, + y: 0.83, + }, + { + id: 'checkerboard', + checks: [ + 'checkerboard', + ], + x: 0.18, + y: 0.78, + }, + { + id: 'chicken-house', + checks: [ + 'chicken-house', + ], + x: 0.1, + y: 0.53, + }, + { + id: 'dam', + checks: [ + 'flooded-chest', + 'sunken-treasure', + ], + x: 0.4675, + y: 0.9375, + }, + { + id: 'desert-ledge', + checks: [ + 'desert-ledge', + ], + x: 0.025, + y: 0.9, + }, + { + id: 'ether-tablet', + checks: [ + 'ether-tablet', + ], + x: 0.425, + y: 0.025, + }, + { + id: 'floating-island', + checks: [ + 'floating-island', + ], + x: 0.8, + y: 0.025, + }, + { + id: 'flute-spot', + checks: [ + 'flute-spot', + ], + x: 0.3, + y: 0.675, + }, + { + id: 'graveyard-ledge', + checks: [ + 'graveyard-ledge', + ], + x: 0.57, + y: 0.28, + }, + { + id: 'hobo', + checks: [ + 'hobo', + ], + x: 0.7, + y: 0.7, + }, + { + id: 'ice-rod-cave', + checks: [ + 'ice-rod-cave', + ], + x: 0.9, + y: 0.76, + }, + { + id: 'kak-well', + checks: [ + 'kak-well-top', + 'kak-well-left', + 'kak-well-mid', + 'kak-well-right', + 'kak-well-bottom', + ], + x: 0.04, + y: 0.425, + }, + { + id: 'kings-tomb', + checks: [ + 'kings-tomb', + ], + x: 0.62, + y: 0.3, + }, + { + id: 'lake-hylia-island', + checks: [ + 'lake-hylia-island', + ], + x: 0.725, + y: 0.8375, + }, + { + id: 'library', + checks: [ + 'library', + ], + x: 0.15, + y: 0.65, + }, + { + id: 'links-house', + checks: [ + 'links-house', + ], + x: 0.55, + y: 0.6875, + }, + { + id: 'lost-woods-hideout', + checks: [ + 'lost-woods-hideout', + ], + x: 0.19, + y: 0.14, + }, + { + id: 'lumberjack', + checks: [ + 'lumberjack', + ], + x: 0.3, + y: 0.07, + }, + { + id: 'magic-bat', + checks: [ + 'magic-bat', + ], + x: 0.325, + y: 0.55, + }, + { + id: 'mimic-cave', + checks: [ + 'mimic-cave', + ], + x: 0.85, + y: 0.1, + }, + { + id: 'mini-moldorm-cave', + checks: [ + 'mini-moldorm-left', + 'mini-moldorm-right', + 'mini-moldorm-far-left', + 'mini-moldorm-far-right', + 'mini-moldorm-npc', + ], + x: 0.65, + y: 0.95, + }, + { + id: 'mushroom-spot', + checks: [ + 'mushroom-spot', + ], + x: 0.125, + y: 0.08, + }, + { + id: 'old-man', + checks: [ + 'old-man', + ], + x: 0.405, + y: 0.195, + }, + { + id: 'paradox-cave', + checks: [ + 'paradox-lower-far-left', + 'paradox-lower-left', + 'paradox-lower-right', + 'paradox-lower-far-right', + 'paradox-lower-mid', + 'paradox-upper-left', + 'paradox-upper-right', + ], + x: 0.85, + y: 0.2, + }, + { + id: 'pedestal', + checks: [ + 'pedestal', + ], + x: 0.03, + y: 0.05, + }, + { + id: 'potion-shop', + checks: [ + 'potion-shop', + ], + x: 0.8, + y: 0.325, + }, + { + id: 'race-game', + checks: [ + 'race-game', + ], + x: 0.025, + y: 0.7, + }, + { + id: 'saha', + checks: [ + 'saha', + ], + x: 0.815, + y: 0.465, + }, + { + id: 'saha-hut', + checks: [ + 'saha-left', + 'saha-mid', + 'saha-right', + ], + x: 0.815, + y: 0.42, + }, + { + id: 'sick-kid', + checks: [ + 'sick-kid', + ], + x: 0.155, + y: 0.525, + }, + { + id: 'uncle', + checks: [ + 'uncle', + 'secret-passage', + ], + x: 0.6, + y: 0.4, + }, + { + id: 'spec-rock', + checks: [ + 'spec-rock', + ], + x: 0.48, + y: 0.09, + }, + { + id: 'spec-rock-cave', + checks: [ + 'spec-rock-cave', + ], + x: 0.48, + y: 0.14, + }, + { + id: 'spiral-cave', + checks: [ + 'spiral-cave', + ], + x: 0.8, + y: 0.1, + }, + { + id: 'tavern', + checks: [ + 'tavern', + ], + x: 0.16, + y: 0.58, + }, + { + id: 'waterfall-fairy', + checks: [ + 'waterfall-fairy-left', + 'waterfall-fairy-right', + ], + x: 0.9, + y: 0.15, + }, + { + id: 'zora', + checks: [ + 'zora', + ], + x: 0.975, + y: 0.12, + }, + { + id: 'zora-ledge', + checks: [ + 'zora-ledge', + ], + x: 0.975, + y: 0.165, + }, +]; + +const DW_DUNGEONS = [ + { + id: 'pd', + x: 0.95, + y: 0.42, + }, + { + id: 'sp', + x: 0.4675, + y: 0.9375, + }, + { + id: 'sw', + x: 0.05, + y: 0.05, + }, + { + id: 'tt', + x: 0.125, + y: 0.475, + }, + { + id: 'ip', + x: 0.7975, + y: 0.86, + }, + { + id: 'mm', + x: 0.12, + y: 0.82, + }, + { + id: 'tr', + x: 0.94, + y: 0.06, + }, + { + id: 'gt', + x: 0.56, + y: 0.05, + }, +]; + +const DW_LOCATIONS = [ + { + id: 'blacksmith', + checks: [ + 'blacksmith', + ], + x: 0.15, + y: 0.65, + }, + { + id: 'brewery', + checks: [ + 'brewery', + ], + x: 0.1, + y: 0.6, + }, + { + id: 'bumper-cave', + checks: [ + 'bumper-cave', + ], + x: 0.325, + y: 0.15, + }, + { + id: 'c-house', + checks: [ + 'c-house', + ], + x: 0.2, + y: 0.5, + }, + { + id: 'catfish', + checks: [ + 'catfish', + ], + x: 0.9, + y: 0.175, + }, + { + id: 'chest-game', + checks: [ + 'chest-game', + ], + x: 0.05, + y: 0.45, + }, + { + id: 'digging-game', + checks: [ + 'digging-game', + ], + x: 0.05, + y: 0.7, + }, + { + id: 'hammer-pegs', + checks: [ + 'hammer-pegs', + ], + x: 0.3125, + y: 0.6, + }, + { + id: 'hookshot-cave', + checks: [ + 'hookshot-cave-tl', + 'hookshot-cave-tr', + 'hookshot-cave-bl', + ], + x: 0.85, + y: 0.02, + }, + { + id: 'hookshot-cave-bonk', + checks: [ + 'hookshot-cave-br', + ], + x: 0.85, + y: 0.065, + }, + { + id: 'hype-cave', + checks: [ + 'hype-cave-top', + 'hype-cave-left', + 'hype-cave-right', + 'hype-cave-bottom', + 'hype-cave-npc', + ], + x: 0.6, + y: 0.75, + }, + { + id: 'mire-shed', + checks: [ + 'mire-shed-left', + 'mire-shed-right', + ], + x: 0.04, + y: 0.8, + }, + { + id: 'purple-chest', + checks: [ + 'purple-chest', + ], + x: 0.3125, + y: 0.525, + }, + { + id: 'pyramid', + checks: [ + 'pyramid', + ], + x: 0.575, + y: 0.45, + }, + { + id: 'pyramid-fairy', + checks: [ + 'pyramid-fairy-left', + 'pyramid-fairy-right', + ], + x: 0.45, + y: 0.5, + }, + { + id: 'spike-cave', + checks: [ + 'spike-cave', + ], + x: 0.575, + y: 0.15, + }, + { + id: 'stumpy', + checks: [ + 'stumpy', + ], + x: 0.3125, + y: 0.6875, + }, + { + id: 'super-bunny', + checks: [ + 'super-bunny-top', + 'super-bunny-bottom', + ], + x: 0.85, + y: 0.15, + }, +]; + +const Location = ({ number, l, size }) => { + const { t } = useTranslation(); + + const classNames = ['location', `status-${l.status}`]; + if (size) { + classNames.push(`size-${size}`); + } + if (l.handlePrimary) { + classNames.push('clickable'); + } + + return { + l.handlePrimary(); + e.preventDefault(); + e.stopPropagation(); + }} + onContextMenu={(e) => { + l.handleSecondary(); + e.preventDefault(); + e.stopPropagation(); + }} + transform={`translate(${l.x} ${l.y})`} + > + {t(`tracker.location.${l.id}`)} + + {number && l.remaining ? + {l.remaining} + : null} + ; +}; + +Location.propTypes = { + number: PropTypes.bool, + l: PropTypes.shape({ + id: PropTypes.string, + x: PropTypes.number, + y: PropTypes.number, + number: PropTypes.number, + remaining: PropTypes.number, + status: PropTypes.string, + handlePrimary: PropTypes.func, + handleSecondary: PropTypes.func, + }), + size: PropTypes.string, +}; + +const makeBackground = (src, level) => { + const amount = Math.pow(2, Math.max(0, level - 8)); + const size = 1 / amount; + const tiles = []; + for (let y = 0; y < amount; ++y) { + for (let x = 0; x < amount; ++x) { + tiles.push(); + } + } + return tiles; +}; + +const Overworld = () => { + const { dungeons, logic, setManualState, state } = useTracker(); + + const mapDungeon = React.useCallback(dungeon => { + const definition = dungeons.find(d => d.id === dungeon.id); + const remaining = getDungeonRemainingItems(state, definition); + const status = aggregateDungeonStatus(definition, logic, state); + return { + ...dungeon, + status, + remaining, + handlePrimary: () => { + if (getDungeonRemainingItems(state, definition)) { + setManualState(addDungeonCheck(definition)); + } else if ( + !hasDungeonBoss(state, definition) || !hasDungeonPrize(state, definition) + ) { + if (definition.boss) { + setManualState(setBossDefeated(definition, true)); + } + if (definition.prize) { + setManualState(setPrizeAcquired(definition, true)); + } + } else { + setManualState(resetDungeonChecks(definition)); + if (definition.boss) { + setManualState(setBossDefeated(definition, false)); + } + if (definition.prize) { + setManualState(setPrizeAcquired(definition, false)); + } + } + }, + handleSecondary: () => { + if (isDungeonCleared(state, definition)) { + if (definition.items) { + setManualState(removeDungeonCheck(definition)); + } + if (definition.boss) { + setManualState(setBossDefeated(definition, false)); + } + if (definition.prize) { + setManualState(setPrizeAcquired(definition, false)); + } + } else if (getDungeonClearedItems(state, definition)) { + setManualState(removeDungeonCheck(definition)); + } else { + setManualState(completeDungeonChecks(definition)); + if (definition.boss) { + setManualState(setBossDefeated(definition, true)); + } + if (definition.prize) { + setManualState(setPrizeAcquired(definition, true)); + } + } + }, + }; + }, [dungeons, logic, setManualState, state]); + + const mapLocation = React.useCallback(loc => { + const remaining = countRemainingLocations(state, loc.checks); + const status = aggregateLocationStatus(loc.checks, logic, state); + return { + ...loc, + remaining, + status, + handlePrimary: () => { + if (remaining) { + setManualState(clearAll(loc.checks)); + } else { + setManualState(unclearAll(loc.checks)); + } + }, + handleSecondary: () => { + if (remaining) { + setManualState(clearAll(loc.checks)); + } else { + setManualState(unclearAll(loc.checks)); + } + }, + }; + }, [logic, setManualState, state]); + + const lwDungeons = React.useMemo(() => LW_DUNGEONS.map(mapDungeon), [mapDungeon]); + const lwLocations = React.useMemo(() => LW_LOCATIONS.map(mapLocation), [mapLocation]); + + const dwDungeons = React.useMemo(() => DW_DUNGEONS.map(mapDungeon), [mapDungeon]); + const dwLocations = React.useMemo(() => DW_LOCATIONS.map(mapLocation), [mapLocation]); + + return { + e.preventDefault(); + e.stopPropagation(); + }} + > + + + {makeBackground('lw_files', 10)} + + + {lwLocations.map(l => + + )} + {lwDungeons.map(l => + + )} + + + + + {makeBackground('dw_files', 10)} + + + {dwLocations.map(l => + + )} + {dwDungeons.map(l => + + )} + + + ; +}; + +export default Overworld; diff --git a/resources/js/components/tracker/Map/index.js b/resources/js/components/tracker/Map/index.js new file mode 100644 index 0000000..65dcbd3 --- /dev/null +++ b/resources/js/components/tracker/Map/index.js @@ -0,0 +1,11 @@ +import React from 'react'; + +import Overworld from './Overworld'; + +const Map = () => { + return
+ +
; +}; + +export default Map;