You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

102 lines
4.3 KiB
JavaScript

import React, {useEffect} from 'react'
import ReactMarkdown from 'react-markdown'
import useGameState from '../../hooks/useGameState'
import map from './map.png'
import {ReactComponent as PlayerIcon} from './mapPerson.svg'
import styles from './Map.module.css'
import useSharedState from '../../hooks/useSharedState'
export default function Map() {
const gameState = useGameState()
const playerLocation = gameState?.player?.location
const isOnLower = ['engine', 'docking', 'mainframe', 'stairlower'].includes(playerLocation)
const [currentFloor, setFloor] = useSharedState('mapFloor', isOnLower ? 'lower' : 'upper')
const [roomName, setRoom] = useSharedState('mapRoom')
// On first render, update room
useEffect(() => {
setRoom(playerLocation)
}, []) // eslint-disable-line
const currentRoom = (roomName && gameState.rooms.get(roomName)) || null
const itemsInRoom = Array.from(gameState.items.values()).filter(({lastKnownLocation, location}) => lastKnownLocation === roomName && location !== 'inventory')
return (
<div className={styles.map}>
<img alt="" src={map}/>
<Floor name="upper" currentSelected={currentFloor} setCurrentFloor={setFloor}>
<Room name="bridge" top={15} left={25} width={20} height={15} currentSelected={roomName} setSelected={setRoom}/>
<Room name="comms" top={35} left={25} width={20} height={30} currentSelected={roomName} setSelected={setRoom}/>
<Room name="cabin" top={35} left={50} width={10} height={20} currentSelected={roomName} setSelected={setRoom}/>
<Room name="bathroom" top={60} left={50} width={10} height={10} currentSelected={roomName} setSelected={setRoom}/>
<Room name="medbay" top={35} left={10} width={10} height={20} currentSelected={roomName} setSelected={setRoom}/>
<Room name="stairupper" top={60} left={10} width={10} height={10} currentSelected={roomName} setSelected={setRoom}/>
</Floor>
<Floor name="lower" currentSelected={currentFloor} setCurrentFloor={setFloor}>
<Room name="engine" top={35} left={25} width={20} height={30} currentSelected={roomName} setSelected={setRoom}/>
<Room name="docking" top={35} left={50} width={10} height={35} currentSelected={roomName} setSelected={setRoom}/>
<Room name="mainframe" top={35} left={10} width={10} height={20} currentSelected={roomName} setSelected={setRoom}/>
<Room name="stairlower" top={60} left={10} width={10} height={10} currentSelected={roomName} setSelected={setRoom}/>
</Floor>
<div className={styles.floorSelector}>
<button className={currentFloor === 'upper' ? styles.selectedFloor : ''} onClick={()=>setFloor('upper')}>Upper</button>
<button className={currentFloor === 'lower' ? styles.selectedFloor : ''} onClick={()=>setFloor('lower')}>Lower</button>
</div>
<div className={styles.description}>
{currentRoom ? (
<>
<h3>{currentRoom.printableName}</h3>
{currentRoom.visited
? (<>
<ReactMarkdown escapeHtml={false}>{currentRoom.description}</ReactMarkdown>
{itemsInRoom.length > 0 && (<>
<p>You {(playerLocation === roomName) ? 'see' : 'recall seeing'} the following items here:</p>
<ul>
{itemsInRoom.map(({name, printableName}) => <li><ReactMarkdown escapeHtml={false}>{printableName || name}</ReactMarkdown></li>)}
</ul>
</>)}
</>)
: <p>Visit this room to unlock its description</p>}
</>
) : (
<h3 style={{marginTop: '45%', textAlign: 'center'}}>Select a Room</h3>
)}
</div>
</div>
)
}
function Floor({name, currentSelected, children}) {
// Do not render if not selected
if(name !== currentSelected)
return null;
return (
<div className={styles.rooms}>
{children}
</div>
)
}
function Room({name, top, left, width, height, setSelected, currentSelected}) {
const gameState = useGameState()
const current = gameState?.player?.location === name
return (
<div
onClick={() => setSelected(name)}
className={styles.room + (currentSelected === name ? ' ' + styles.selectedRoom : '')}
style={{top, left, width, height}}
>
{current && <PlayerIcon/>}
</div>
)
}