From d47930e4c0816d522de5eac53be477a59dbff486 Mon Sep 17 00:00:00 2001 From: Garrett Vorbeck Date: Fri, 15 Apr 2022 01:36:34 -0400 Subject: [PATCH 01/23] testing bottom drawer --- src/components/arena.js | 18 ++++++++++ src/components/layout.js | 30 ++++++++++++++-- src/components/navigation.js | 68 ++++++++++++++++++++++-------------- src/images/swordwoman.svg | 1 + src/utils/constants.js | 4 +++ src/utils/theme.js | 31 ++++++++++------ 6 files changed, 113 insertions(+), 39 deletions(-) create mode 100644 src/components/arena.js create mode 100644 src/images/swordwoman.svg diff --git a/src/components/arena.js b/src/components/arena.js new file mode 100644 index 0000000..80ed699 --- /dev/null +++ b/src/components/arena.js @@ -0,0 +1,18 @@ +import React from 'react'; +import { Box, Drawer } from '@mui/material'; + +function Arena({ drawerOpen, setDrawerOpen }) { + const txt = 'hello world'; + sessionStorage.setItem('my-key', txt); + console.log(sessionStorage.getItem('my-key')); + + return ( + + setDrawerOpen(false)}> + hiii + + + ); +} + +export default Arena; diff --git a/src/components/layout.js b/src/components/layout.js index 56341f1..6a35e3d 100644 --- a/src/components/layout.js +++ b/src/components/layout.js @@ -10,6 +10,7 @@ import { } from '../utils/constants'; import Navigation from './navigation'; import GmcmBlackBridgeIcon from '../images/black-bridge.svg'; +import Arena from './arena'; // eslint-disable-next-line react/function-component-definition const HeaderContainer = (props) => ; @@ -17,10 +18,29 @@ const HeaderContainer = (props) => ; function Layout({ children, hideNavigation, title, navDirection, }) { + const [drawerOpen, setDrawerOpen] = React.useState(false); + const click = () => { + console.log('hi'); + // const box = document.getElementsByClassName('gmcm-Drawer-paper')[0]; + // console.log(box); + // if (box && !box.contains(event.target)) { + // console.log('yo'); + // setDrawerOpen(false); + // } + }; + React.useEffect(() => { + document.addEventListener('click', click); + return document.removeEventListener('click', click); + }, []); return ( <> { + // console.log(event.target.id); + // event.stopPropagation(); + // drawerOpen && setDrawerOpen(false); + }} sx={{ typography: 'body1', color: 'secondary.main', @@ -34,6 +54,7 @@ function Layout({ '& thead tr': { backgroundColor: 'primary.main', }, + // for '& .SnackbarContainer-root': { gap: 2, }, @@ -44,7 +65,6 @@ function Layout({ sx={{ backgroundColor: 'primary.main', minHeight: '4.25rem', - // display: 'block', position: 'static', }} > @@ -87,7 +107,12 @@ function Layout({ - + + - {NAVIGATION_DATA.map((item) => ( - - - - ))} + {NAVIGATION_DATA.map((item, index) => { + if (!hideDrawerIcon && index === 0) { + return ( + + { + setDrawerOpen(!drawerOpen); + console.log('foo'); + }} + > + + + + + + ); + } + return ( + + + + ); + })} ); diff --git a/src/images/swordwoman.svg b/src/images/swordwoman.svg new file mode 100644 index 0000000..ae70a34 --- /dev/null +++ b/src/images/swordwoman.svg @@ -0,0 +1 @@ + diff --git a/src/utils/constants.js b/src/utils/constants.js index e5a643c..c079ef6 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -44,6 +44,10 @@ export const SITE_NAME = 'Game Master\'s Campaign Manager'; export const SITE_SHORT_NAME = 'GMCM'; export const FOOTER_COPY = `${SITE_NAME} © ${new Date().getFullYear()} J. Garrett Vorbeck`; export const NAVIGATION_DATA = [ + { + title: 'Combat Tracker', + slug: '', + }, { title: 'adventures', slug: '/adventures', diff --git a/src/utils/theme.js b/src/utils/theme.js index 4e1a2ba..146a2e6 100644 --- a/src/utils/theme.js +++ b/src/utils/theme.js @@ -1,6 +1,8 @@ import { createTheme } from '@mui/material/styles'; import { brown, lime } from '@mui/material/colors'; +const height = '100%'; + // A custom theme for this app const theme = createTheme({ palette: { @@ -9,20 +11,27 @@ const theme = createTheme({ main: lime[900], }, secondary: { - // main: brown[900], main: brown[200], }, - // tertiary: { - // light: '#efdcd5', - // main: brown[200], - // dark: '#8c7b75', - // contrastText: '#000000', - // }, }, - // shape: { - // borderRadius: 0, - // }, + components: { + MuiCssBaseline: { + styleOverrides: { + '#gatsby-focus-wrapper': { + height, + }, + '#___gatsby': { + height, + }, + html: { + height, + }, + body: { + height, + }, + }, + }, + }, }); -// theme.palette.background.default = theme.palette.secondary.main; export default theme; From 5cbc5e007c1e48589bbf6e671faaee6b997b2283 Mon Sep 17 00:00:00 2001 From: Garrett Vorbeck Date: Fri, 15 Apr 2022 18:06:42 -0400 Subject: [PATCH 02/23] better drawer behavior --- src/components/arena.js | 89 +++++++++++++++++++++++++++++++++++++--- src/components/layout.js | 18 -------- 2 files changed, 83 insertions(+), 24 deletions(-) diff --git a/src/components/arena.js b/src/components/arena.js index 80ed699..c17c383 100644 --- a/src/components/arena.js +++ b/src/components/arena.js @@ -1,18 +1,95 @@ import React from 'react'; -import { Box, Drawer } from '@mui/material'; +import { + Box, Drawer, List, ListItem, TextField, +} from '@mui/material'; +import { Button, ListItemButton } from 'gatsby-theme-material-ui'; function Arena({ drawerOpen, setDrawerOpen }) { - const txt = 'hello world'; - sessionStorage.setItem('my-key', txt); - console.log(sessionStorage.getItem('my-key')); + const ssCombatData = sessionStorage.getItem('gmcm-combatants') || '[]'; + const [combatantArray, setCombatantArray] = React.useState( + JSON.parse(ssCombatData), + ); + const [playerName, setPlayerName] = React.useState(null); + const [combatantList, setCombatantList] = React.useState(''); + + React.useEffect(() => { + sessionStorage.setItem('gmcm-combatants', JSON.stringify(combatantArray)); + setCombatantList(combatantArray.map((combatant) => ( + {combatant.name} + ))); + }, [combatantArray]); + + const addCombatant = (combatant = null) => { + setCombatantArray([...combatantArray, combatant]); + }; return ( - setDrawerOpen(false)}> - hiii + setDrawerOpen(false)}> + { + setPlayerName(event.target.value); + }} + /> + + {combatantList} ); } +// function Arena({ drawerOpen, setDrawerOpen }) { +// const [playerField, setPlayerField] = React.useState(null); +// const [combatantList, setCombatantList] = React.useState(null); +// const combatants = []; +// // const txt = 'hello world'; +// sessionStorage.setItem('my-key', ['hi', 'how', 'are', 'you']); +// console.log(sessionStorage.getItem('my-key')); + +// const addToCombatants = () => { +// combatants.push(playerField); +// createCombatantList(); +// }; + +// return ( +// +// setDrawerOpen(false)}> +// +// +// add player +// +// +// setPlayerField(event.target.value)} +// /> +// +// {combatantList} +// +// +// ); +// } + export default Arena; diff --git a/src/components/layout.js b/src/components/layout.js index 6a35e3d..87611da 100644 --- a/src/components/layout.js +++ b/src/components/layout.js @@ -19,28 +19,10 @@ function Layout({ children, hideNavigation, title, navDirection, }) { const [drawerOpen, setDrawerOpen] = React.useState(false); - const click = () => { - console.log('hi'); - // const box = document.getElementsByClassName('gmcm-Drawer-paper')[0]; - // console.log(box); - // if (box && !box.contains(event.target)) { - // console.log('yo'); - // setDrawerOpen(false); - // } - }; - React.useEffect(() => { - document.addEventListener('click', click); - return document.removeEventListener('click', click); - }, []); return ( <> { - // console.log(event.target.id); - // event.stopPropagation(); - // drawerOpen && setDrawerOpen(false); - }} sx={{ typography: 'body1', color: 'secondary.main', From 256fe74e2125a3386c20216ce02c275f99423e95 Mon Sep 17 00:00:00 2001 From: Garrett Vorbeck Date: Sat, 16 Apr 2022 13:28:44 -0400 Subject: [PATCH 03/23] fix home nav and add search result add+ button --- src/components/arena.js | 3 --- src/components/navigation.js | 46 ++++++++++++++++++++---------------- src/pages/index.js | 2 +- src/pages/search.js | 22 ++++++++++++++++- 4 files changed, 47 insertions(+), 26 deletions(-) diff --git a/src/components/arena.js b/src/components/arena.js index c17c383..8ed3b32 100644 --- a/src/components/arena.js +++ b/src/components/arena.js @@ -34,9 +34,6 @@ function Arena({ drawerOpen, setDrawerOpen }) { /> - {combatantList} - - + setDrawerOpen(false)}> + { + event.preventDefault(); + if (playerName === '') { + setError(true); + return; + } + addCombatant({ name: playerName }); + setPlayerName(''); + }} + > + + Add to Combat Tracker + { + setError(false); + setPlayerName(event.target.value); + }} + /> + + + + + + {combatantList} + ); } +export { Arena, arenaDrawerState }; + +{ /* // import { +// Box, Drawer, List, ListItem, TextField, +// } from '@mui/material'; +// import { Button, ListItemButton } from 'gatsby-theme-material-ui'; + // function Arena({ drawerOpen, setDrawerOpen }) { -// const [playerField, setPlayerField] = React.useState(null); -// const [combatantList, setCombatantList] = React.useState(null); -// const combatants = []; -// // const txt = 'hello world'; -// sessionStorage.setItem('my-key', ['hi', 'how', 'are', 'you']); -// console.log(sessionStorage.getItem('my-key')); +// const ssCombatData = sessionStorage.getItem('gmcm-combatants') || '[]'; +// const [combatantArray, setCombatantArray] = React.useState( +// JSON.parse(ssCombatData), +// ); +// const [playerName, setPlayerName] = React.useState(null); +// const [combatantList, setCombatantList] = React.useState(''); -// const addToCombatants = () => { -// combatants.push(playerField); -// createCombatantList(); +// React.useEffect(() => { +// sessionStorage.setItem('gmcm-combatants', JSON.stringify(combatantArray)); +// setCombatantList(combatantArray.map((combatant) => ( +// {combatant.name} +// ))); +// }, [combatantArray]); + +// const addCombatant = (combatant = null) => { +// setCombatantArray([...combatantArray, combatant]); // }; // return ( // -// setDrawerOpen(false)}> -// -// -// add player -// -// +// setDrawerOpen(false)}> // setPlayerField(event.target.value)} +// defaultValue={playerName} +// onChange={(event) => { +// setPlayerName(event.target.value); +// }} // /> // // {combatantList} // // // ); -// } - -export default Arena; +// } */ } diff --git a/src/components/layout.js b/src/components/layout.js index 87611da..3d39722 100644 --- a/src/components/layout.js +++ b/src/components/layout.js @@ -10,15 +10,14 @@ import { } from '../utils/constants'; import Navigation from './navigation'; import GmcmBlackBridgeIcon from '../images/black-bridge.svg'; -import Arena from './arena'; +import { Arena } from './arena'; // eslint-disable-next-line react/function-component-definition const HeaderContainer = (props) => ; function Layout({ - children, hideNavigation, title, navDirection, + children, hideNavigation, title, navDirection, drawerOpen = undefined, setDrawerOpen = undefined, }) { - const [drawerOpen, setDrawerOpen] = React.useState(false); return ( <> diff --git a/src/components/location-page-layout.js b/src/components/location-page-layout.js index c215a2a..c0b2648 100644 --- a/src/components/location-page-layout.js +++ b/src/components/location-page-layout.js @@ -49,18 +49,24 @@ import { Boss, Unknown, } from '../images/icons'; +import { arenaDrawerState } from './arena'; const markdownComponentsList = { Link, MonsterLink, SpellLink, Dice, }; function LocationPageLayout({ data, location }) { + const { drawerOpen, setDrawerOpen } = arenaDrawerState(); const [scrollLocation, setScrollLocation] = useState(0); const parentAdventureTitle = location.state ? location.state.parentAdventureTitle : ''; const parentAdventureSlug = location.state ? location.state.parentAdventureSlug : ''; return ( - + {parentAdventureTitle && ( { setDrawerOpen(!drawerOpen); - console.log('foo'); }} > diff --git a/src/components/session-storage.js b/src/components/session-storage.js new file mode 100644 index 0000000..7e261d6 --- /dev/null +++ b/src/components/session-storage.js @@ -0,0 +1,37 @@ +import React from 'react'; +import { ListItem } from '@mui/material'; + +function combatData() { + const ssCombatData = sessionStorage.getItem('gmcm-combatants') || '[]'; + const [combatantArray, setCombatantArray] = React.useState( + JSON.parse(ssCombatData), + ); + const [combatantList, setCombatantList] = React.useState(''); + React.useEffect(() => { + setCombatantList(combatantArray.map((combatant) => ( + {combatant.name} + ))); + sessionStorage.setItem('gmcm-combatants', JSON.stringify(combatantArray)); + console.log('woot'); + }, [combatantArray]); + const addCombatant = (combatant = null) => { + setCombatantArray([...combatantArray, combatant]); + }; + return { + // Either + // A string of unparsed session storage data + // OR an empty array as a string + ssCombatData, + // Parsed session storage data (array of objects) + // Turns the strings of session storage data into usable data + combatantArray, + // Sets the above's value + setCombatantArray, + // Function for adding a new player/monster object to the combatantArray + addCombatant, + // JSX/HTML of the rows for combat tracker + combatantList, + }; +} + +export default combatData; diff --git a/src/pages/adventures.js b/src/pages/adventures.js index 53b20c2..b30169f 100644 --- a/src/pages/adventures.js +++ b/src/pages/adventures.js @@ -7,10 +7,12 @@ import { CardActionArea } from 'gatsby-theme-material-ui'; import Layout from '../components/layout'; import AdventureDetails from '../components/adventure-details'; import { ADVENTURES } from '../utils/constants'; +import { arenaDrawerState } from '../components/arena'; function AdventuresPage({ data }) { + const { drawerOpen, setDrawerOpen } = arenaDrawerState(); return ( - + ); diff --git a/src/pages/reference.js b/src/pages/reference.js index 18b3814..2c0c921 100644 --- a/src/pages/reference.js +++ b/src/pages/reference.js @@ -25,6 +25,7 @@ import Masonry from '@mui/lab/Masonry'; import Layout from '../components/layout'; import Dice from '../components/dice'; import { REFERENCE, SCROLL_BEHAVIOR } from '../utils/constants'; +import { arenaDrawerState } from '../components/arena'; /* Table of Contents */ function TableOfContents({ referenceData }) { @@ -288,8 +289,8 @@ function ReferenceArticlesCategoryBlockItemMarkdown(props) { } /* PAGE FUNCTION */ -function ReferencePage(props) { - const { data } = props; +function ReferencePage({ data }) { + const { drawerOpen, setDrawerOpen } = arenaDrawerState(); const posts = data.allMdx.nodes; const referenceData = []; @@ -327,7 +328,7 @@ function ReferencePage(props) { } return ( - + + - + ); @@ -137,7 +141,7 @@ function SearchForm({ ); } -function SearchResults({ value }) { +function SearchResults({ value, drawerOpen, setDrawerOpen }) { return ( 0 && ( {value.map((item) => ( - + ))} )} @@ -157,17 +166,22 @@ function SearchResults({ value }) { ); } -function SearchResultsItem({ item }) { +function SearchResultsItem({ item, drawerOpen, setDrawerOpen }) { return ( - + ); } -function SearchResultsItemHeader({ item }) { +function SearchResultsItemHeader({ item, drawerOpen, setDrawerOpen }) { + const { addCombatant } = combatData(); let DmcmIcon; let subtitle; let combatIcon = false; @@ -232,9 +246,14 @@ function SearchResultsItemHeader({ item }) { top: '0.25rem', right: '0.25rem', }} + onClick={() => { + setDrawerOpen(!drawerOpen); + addCombatant({ name: item.name }); + }} > - + + {/* */} From 2da007c0af1c81ea243e5d371b0692cba84c3cfe Mon Sep 17 00:00:00 2001 From: Garrett Vorbeck Date: Mon, 18 Apr 2022 14:18:32 -0400 Subject: [PATCH 05/23] finally have a POC that works --- src/components/adventure-page-layout.js | 8 +- src/components/arena.js | 153 +++++++++--------------- src/components/layout.js | 18 ++- src/components/navigation.js | 10 +- src/pages/search.js | 59 ++++++--- 5 files changed, 122 insertions(+), 126 deletions(-) diff --git a/src/components/adventure-page-layout.js b/src/components/adventure-page-layout.js index f9f8404..3dd3397 100644 --- a/src/components/adventure-page-layout.js +++ b/src/components/adventure-page-layout.js @@ -26,16 +26,10 @@ import AdventureDetails from './adventure-details'; import { NPCS, HEADER_CELLS, LOCATIONS, } from '../utils/constants'; -import { arenaDrawerState } from './arena'; function AdventurePageLayout({ data }) { - const { drawerOpen, setDrawerOpen } = arenaDrawerState(); return ( - + { - const [drawerOpen, setDrawerOpen] = React.useState(false); +function useArena() { + // Drawer State. + const [arenaDrawerOpen, setArenaDrawerOpen] = React.useState(false); + // Parsed Session Storage data. + const [arenaSessionStorage, setArenaSessionStorage] = React.useState( + JSON.parse(sessionStorage.getItem('gmcm-combatants') || '[]'), + ); + // Mapping ListItems based on parsed Session Storage data + const combatantListItems = arenaSessionStorage.map((item) => ( + {item.name} + )); + // Set Stringified Session Storage data. React.useEffect(() => { - }, [drawerOpen]); - return { - drawerOpen, setDrawerOpen, - }; -}; + sessionStorage.setItem('gmcm-combatants', JSON.stringify(arenaSessionStorage)); + }, [arenaSessionStorage]); -function Arena({ drawerOpen, setDrawerOpen }) { - const { combatantArray, combatantList, addCombatant } = combatData(); const [playerName, setPlayerName] = React.useState(''); const [error, setError] = React.useState(false); - React.useEffect(() => { - console.log('bar'); - }, [combatantArray]); - return ( - setDrawerOpen(false)}> - { - event.preventDefault(); - if (playerName === '') { - setError(true); - return; - } - addCombatant({ name: playerName }); - setPlayerName(''); - }} - > - - Add to Combat Tracker - { - setError(false); - setPlayerName(event.target.value); - }} - /> - - - - - - {combatantList} - - ); -} - -export { Arena, arenaDrawerState }; -{ /* // import { -// Box, Drawer, List, ListItem, TextField, -// } from '@mui/material'; -// import { Button, ListItemButton } from 'gatsby-theme-material-ui'; - -// function Arena({ drawerOpen, setDrawerOpen }) { -// const ssCombatData = sessionStorage.getItem('gmcm-combatants') || '[]'; -// const [combatantArray, setCombatantArray] = React.useState( -// JSON.parse(ssCombatData), -// ); -// const [playerName, setPlayerName] = React.useState(null); -// const [combatantList, setCombatantList] = React.useState(''); - -// React.useEffect(() => { -// sessionStorage.setItem('gmcm-combatants', JSON.stringify(combatantArray)); -// setCombatantList(combatantArray.map((combatant) => ( -// {combatant.name} -// ))); -// }, [combatantArray]); - -// const addCombatant = (combatant = null) => { -// setCombatantArray([...combatantArray, combatant]); -// }; + return { + arenaSessionStorage, + setArenaSessionStorage, + arenaDrawerOpen, + setArenaDrawerOpen, + arenaRender: ( + setArenaDrawerOpen(false)}> + { + event.preventDefault(); + if (playerName === '') { + setError(true); + return; + } + setArenaSessionStorage([...arenaSessionStorage, { name: playerName }]); + setPlayerName(''); + }} + > + + Add to Combat Tracker + { + setError(false); + setPlayerName(event.target.value); + }} + /> + + + + + + {combatantListItems} + + ), + }; +} -// return ( -// -// setDrawerOpen(false)}> -// { -// setPlayerName(event.target.value); -// }} -// /> -// -// {combatantList} -// -// -// ); -// } */ } +export default useArena; diff --git a/src/components/layout.js b/src/components/layout.js index 3d39722..bd94ab0 100644 --- a/src/components/layout.js +++ b/src/components/layout.js @@ -10,13 +10,20 @@ import { } from '../utils/constants'; import Navigation from './navigation'; import GmcmBlackBridgeIcon from '../images/black-bridge.svg'; -import { Arena } from './arena'; +// import useArena from './arena'; // eslint-disable-next-line react/function-component-definition const HeaderContainer = (props) => ; function Layout({ - children, hideNavigation, title, navDirection, drawerOpen = undefined, setDrawerOpen = undefined, + children, + hideNavigation, + hideDrawerIcon = false, + title, + navDirection, + arenaDrawerOpen = false, + setArenaDrawerOpen = undefined, + arenaRender = undefined, }) { return ( <> @@ -90,9 +97,10 @@ function Layout({ + {arenaRender} {title && title !== 'Home' && ( - { - setDrawerOpen(!drawerOpen); + setArenaDrawerOpen(!arenaDrawerOpen); }} > diff --git a/src/pages/search.js b/src/pages/search.js index 5716b8a..6e425d5 100644 --- a/src/pages/search.js +++ b/src/pages/search.js @@ -46,12 +46,15 @@ import { } from '../utils/constants'; import * as CREATURE_TYPES from '../images/creature-types'; import * as MAGIC_TYPES from '../images/magic-types'; -import { arenaDrawerState } from '../components/arena'; +import useArena from '../components/arena'; import SwordWoman from '../images/swordwoman.svg'; -import combatData from '../components/session-storage'; +// import combatData from '../components/session-storage'; function SearchPage({ data, location }) { - const { drawerOpen, setDrawerOpen } = arenaDrawerState(); + const { + arenaDrawerOpen, setArenaDrawerOpen, arenaRender, arenaSessionStorage, setArenaSessionStorage, + } = useArena(); + const search = new URLSearchParams(location.search.substring(1)); const category = search.get('category'); const searchData = { @@ -91,7 +94,12 @@ function SearchPage({ data, location }) { } const [value, setValue] = React.useState(startingValue || []); return ( - + - + ); @@ -141,7 +155,9 @@ function SearchForm({ ); } -function SearchResults({ value, drawerOpen, setDrawerOpen }) { +function SearchResults({ + value, arenaDrawerOpen, setArenaDrawerOpen, arenaSessionStorage, setArenaSessionStorage, +}) { return ( ))} @@ -166,22 +184,30 @@ function SearchResults({ value, drawerOpen, setDrawerOpen }) { ); } -function SearchResultsItem({ item, drawerOpen, setDrawerOpen }) { +function SearchResultsItem({ + item, arenaDrawerOpen, setArenaDrawerOpen, arenaSessionStorage, setArenaSessionStorage, +}) { return ( ); } -function SearchResultsItemHeader({ item, drawerOpen, setDrawerOpen }) { - const { addCombatant } = combatData(); +function SearchResultsItemHeader({ + item, arenaDrawerOpen, setArenaDrawerOpen, arenaSessionStorage, setArenaSessionStorage, +}) { + // const { + // arenaSessionStorage, setArenaSessionStorage, arenaSessionStorage, setArenaSessionStorage, + // } = useArena(); let DmcmIcon; let subtitle; let combatIcon = false; @@ -247,8 +273,11 @@ function SearchResultsItemHeader({ item, drawerOpen, setDrawerOpen }) { right: '0.25rem', }} onClick={() => { - setDrawerOpen(!drawerOpen); - addCombatant({ name: item.name }); + setArenaDrawerOpen(!arenaDrawerOpen); + // setArenaSessionStorage([...arenaSessionStorage, { name: item.name }]); + setArenaSessionStorage([...arenaSessionStorage, { name: item.name }]); + // test(arenaDrawerOpen); + // console.log(arenaSessionStorage); }} > From 5dacd8c72a98034765c581651a726c45d8777cb8 Mon Sep 17 00:00:00 2001 From: Garrett Vorbeck Date: Mon, 18 Apr 2022 17:34:02 -0400 Subject: [PATCH 06/23] initiative and hp --- src/components/arena.js | 56 ++++++++++++++++++++++++++++++++++------- src/pages/search.js | 18 ++++++++----- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/src/components/arena.js b/src/components/arena.js index adfc7b6..e1283d0 100644 --- a/src/components/arena.js +++ b/src/components/arena.js @@ -1,9 +1,10 @@ import React from 'react'; import { - Box, Drawer, FormControl, Input, InputLabel, List, ListItem, + Box, Drawer, FormControl, Input, InputLabel, List, ListItem, SvgIcon, TextField, } from '@mui/material'; import { IconButton } from 'gatsby-theme-material-ui'; import PersonAddIcon from '@mui/icons-material/PersonAdd'; +import CasinoIcon from '@mui/icons-material/Casino'; function useArena() { // Drawer State. @@ -12,25 +13,62 @@ function useArena() { const [arenaSessionStorage, setArenaSessionStorage] = React.useState( JSON.parse(sessionStorage.getItem('gmcm-combatants') || '[]'), ); + const [playerName, setPlayerName] = React.useState(''); + const [error, setError] = React.useState(false); // Mapping ListItems based on parsed Session Storage data - const combatantListItems = arenaSessionStorage.map((item) => ( - {item.name} - )); + const combatantListItems = arenaSessionStorage + .sort((a, b) => (a.initiative < b.initiative ? 1 : -1)) + .map((item) => { + const initiative = item.initiative || 0; + console.log(initiative); + return ( + + + {initiative === 0 ? ( + + + + ) : initiative} + + {item.name} + { + // setError(false); + // setPlayerName(event.target.value); + }} + /> + + ); + }); // Set Stringified Session Storage data. React.useEffect(() => { sessionStorage.setItem('gmcm-combatants', JSON.stringify(arenaSessionStorage)); }, [arenaSessionStorage]); - const [playerName, setPlayerName] = React.useState(''); - const [error, setError] = React.useState(false); - return { arenaSessionStorage, setArenaSessionStorage, arenaDrawerOpen, setArenaDrawerOpen, arenaRender: ( - setArenaDrawerOpen(false)}> + setArenaDrawerOpen(false)} + sx={{ + p: '1rem', + }} + > { @@ -39,7 +77,7 @@ function useArena() { setError(true); return; } - setArenaSessionStorage([...arenaSessionStorage, { name: playerName }]); + setArenaSessionStorage([...arenaSessionStorage, { name: playerName, initiative: 0 }]); setPlayerName(''); }} > diff --git a/src/pages/search.js b/src/pages/search.js index 6e425d5..fba8a8d 100644 --- a/src/pages/search.js +++ b/src/pages/search.js @@ -29,6 +29,7 @@ import { IconButton } from 'gatsby-theme-material-ui'; // import AddModeratorIcon from '@mui/icons-material/AddModerator'; import Masonry from '@mui/lab/Masonry'; import MarkdownView from 'react-showdown'; +import { DiceRoll } from '@dice-roller/rpg-dice-roller'; import Layout from '../components/layout'; import Dice from '../components/dice'; import { @@ -48,7 +49,6 @@ import * as CREATURE_TYPES from '../images/creature-types'; import * as MAGIC_TYPES from '../images/magic-types'; import useArena from '../components/arena'; import SwordWoman from '../images/swordwoman.svg'; -// import combatData from '../components/session-storage'; function SearchPage({ data, location }) { const { @@ -245,6 +245,10 @@ function SearchResultsItemHeader({ } else { console.error('Searched item not recognized. Make sure your content follows frontmatter guidelines.'); } + const hpRoll = new DiceRoll(item.hp.notes); + const initiativeRoll = new DiceRoll(`d20+${Math.floor((item.abilities.dex - 10) / 2)}`); + + console.log(item); return ( <> { setArenaDrawerOpen(!arenaDrawerOpen); - // setArenaSessionStorage([...arenaSessionStorage, { name: item.name }]); - setArenaSessionStorage([...arenaSessionStorage, { name: item.name }]); - // test(arenaDrawerOpen); - // console.log(arenaSessionStorage); + setArenaSessionStorage([...arenaSessionStorage, + { + name: item.name, + hp: hpRoll.total, + initiative: initiativeRoll.total, + }, + ]); }} > - {/* */} From 4fb768b55c1e2cd36ea5ef2c7019113c8aad9d7b Mon Sep 17 00:00:00 2001 From: Garrett Vorbeck Date: Tue, 19 Apr 2022 11:58:40 -0400 Subject: [PATCH 07/23] auto rolls and initial values --- src/pages/search.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/pages/search.js b/src/pages/search.js index fba8a8d..b5be849 100644 --- a/src/pages/search.js +++ b/src/pages/search.js @@ -166,7 +166,7 @@ function SearchResults({ > {value.length > 0 && ( - + {value.map((item) => ( { if (item.type.toUpperCase().search(c.toUpperCase()) > -1) { @@ -219,6 +221,8 @@ function SearchResultsItemHeader({ }); subtitle = item.type; combatIcon = true; + hpRoll = new DiceRoll(item.hp.notes); + initiativeRoll = new DiceRoll(`d20+${Math.floor((item.abilities.dex - 10) / 2)}`); } else if (item.school) { Object.keys(MAGIC_TYPES).forEach((m) => { if (item.school.toUpperCase().search(m.toUpperCase()) > -1) { @@ -245,8 +249,6 @@ function SearchResultsItemHeader({ } else { console.error('Searched item not recognized. Make sure your content follows frontmatter guidelines.'); } - const hpRoll = new DiceRoll(item.hp.notes); - const initiativeRoll = new DiceRoll(`d20+${Math.floor((item.abilities.dex - 10) / 2)}`); console.log(item); return ( From 7930cfb6cbfaaf72d369b76c924970d6e7b19cb0 Mon Sep 17 00:00:00 2001 From: Garrett Vorbeck Date: Tue, 19 Apr 2022 11:59:29 -0400 Subject: [PATCH 08/23] resorting fields based on initiative/name --- src/components/arena.js | 109 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 99 insertions(+), 10 deletions(-) diff --git a/src/components/arena.js b/src/components/arena.js index e1283d0..5aad3b0 100644 --- a/src/components/arena.js +++ b/src/components/arena.js @@ -1,19 +1,108 @@ import React from 'react'; import { - Box, Drawer, FormControl, Input, InputLabel, List, ListItem, SvgIcon, TextField, + Box, Drawer, FormControl, Input, InputLabel, List, ListItem, ListItemText, SvgIcon, TextField, } from '@mui/material'; import { IconButton } from 'gatsby-theme-material-ui'; import PersonAddIcon from '@mui/icons-material/PersonAdd'; import CasinoIcon from '@mui/icons-material/Casino'; function useArena() { - // Drawer State. + // Prep Session Storage data: + const ssKey = 'gmcm-combatants'; + const parsedSessionData = JSON.parse(sessionStorage.getItem(ssKey) || '[]'); + if (parsedSessionData.length > 0) { + parsedSessionData.sort((a, b) => (a.initiative < b.initiative ? 1 : -1)); + sessionStorage.setItem(ssKey, JSON.stringify(parsedSessionData)); + } + // PARSED data: + const [arenaSessionStorage, setArenaSessionStorage] = React.useState(parsedSessionData); + + // Drawer State: const [arenaDrawerOpen, setArenaDrawerOpen] = React.useState(false); - // Parsed Session Storage data. - const [arenaSessionStorage, setArenaSessionStorage] = React.useState( - JSON.parse(sessionStorage.getItem('gmcm-combatants') || '[]'), - ); + + // For manual entry, Player Name: const [playerName, setPlayerName] = React.useState(''); + + // Create ListItems + const [combatantListItems, setCombatantListItems] = React.useState([]); + // Submit new initiative by making a shallow copy of data, manipulating it, and then + // submiting the new data. + const initiativeSubmit = (value, index) => { + const arenaCopy = [...arenaSessionStorage]; + const arenaCopyItem = { ...arenaCopy[index] }; + arenaCopyItem.initiative = parseInt(value.replace(/\D/g, ''), 10); + arenaCopy[index] = arenaCopyItem; + setArenaSessionStorage(arenaCopy); + }; + const combatantListMaker = (array) => array + // Sort by initiative and then by name. + .sort( + (a, b) => ( + (a.initiative < b.initiative) ? 1 : (a.initiative === b.initiative) ? ( + (a.name.toUpperCase() > b.name.toUpperCase()) ? 1 : -1 + ) : -1 + ), + ) + .map((item, index) => ( + + {/* Initiative value */} + initiativeSubmit(event.target.value, index)} + onKeyDown={(event) => { + if (event.key === 'Enter') { + event.target.blur(); + } + }} + /> + {/* Combatant's name */} + + {/* HP value */} + + + )); + + // IF arenaSessionStorage value is altered, reset the Session Storage data: + React.useEffect(() => { + console.log('arenaSessionStorage useEffect'); + // Resort the data and recreate the list. + setCombatantListItems(combatantListMaker(arenaSessionStorage)); + // Stringify and resend the data to Session Storage. + sessionStorage.setItem(ssKey, JSON.stringify(arenaSessionStorage)); + }, [arenaSessionStorage]); + + return { + arenaSessionStorage, + setArenaSessionStorage, + arenaDrawerOpen, + setArenaDrawerOpen, + arenaRender: ( + setArenaDrawerOpen(false)} + sx={{ + p: '1rem', + }} + > + {combatantListItems} + + ), + }; +} + +{ /* function useArena() { + // Drawer State. + // const [arenaDrawerOpen, setArenaDrawerOpen] = React.useState(false); + // Parsed Session Storage data. + // const [arenaSessionStorage, setArenaSessionStorage] = React.useState( + // JSON.parse(sessionStorage.getItem('gmcm-combatants') || '[]'), + // ); + // const [playerName, setPlayerName] = React.useState(''); const [error, setError] = React.useState(false); // Mapping ListItems based on parsed Session Storage data const combatantListItems = arenaSessionStorage @@ -51,9 +140,9 @@ function useArena() { ); }); // Set Stringified Session Storage data. - React.useEffect(() => { - sessionStorage.setItem('gmcm-combatants', JSON.stringify(arenaSessionStorage)); - }, [arenaSessionStorage]); + // React.useEffect(() => { + // sessionStorage.setItem('gmcm-combatants', JSON.stringify(arenaSessionStorage)); + // }, [arenaSessionStorage]); return { arenaSessionStorage, @@ -101,6 +190,6 @@ function useArena() { ), }; -} +} */ } export default useArena; From 41da08123768798a01951d1bbd389e34308f9856 Mon Sep 17 00:00:00 2001 From: Garrett Vorbeck Date: Tue, 19 Apr 2022 13:21:19 -0400 Subject: [PATCH 09/23] remove console.log --- src/pages/search.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/search.js b/src/pages/search.js index b5be849..e625275 100644 --- a/src/pages/search.js +++ b/src/pages/search.js @@ -250,7 +250,6 @@ function SearchResultsItemHeader({ console.error('Searched item not recognized. Make sure your content follows frontmatter guidelines.'); } - console.log(item); return ( <> Date: Tue, 19 Apr 2022 13:21:50 -0400 Subject: [PATCH 10/23] combat drawer updates --- src/components/arena.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/components/arena.js b/src/components/arena.js index 5aad3b0..36b0556 100644 --- a/src/components/arena.js +++ b/src/components/arena.js @@ -34,6 +34,14 @@ function useArena() { arenaCopy[index] = arenaCopyItem; setArenaSessionStorage(arenaCopy); }; + // Submit new HP value like above. + const hpSubmit = (value, current, index) => { + const arenaCopy = [...arenaSessionStorage]; + const arenaCopyItem = { ...arenaCopy[index] }; + arenaCopyItem.hp = current - parseInt(value.replace(/\D/g, ''), 10); + arenaCopy[index] = arenaCopyItem; + setArenaSessionStorage(arenaCopy); + }; const combatantListMaker = (array) => array // Sort by initiative and then by name. .sort( @@ -61,7 +69,14 @@ function useArena() { {/* HP value */} event.target.select()} + onBlur={(event) => hpSubmit(event.target.value, item.hp, index)} + onKeyDown={(event) => { + if (event.key === 'Enter') { + event.target.blur(); + } + }} /> )); From 3b619e9ad30a57a34f8fdbc67979be1fbb234120 Mon Sep 17 00:00:00 2001 From: Garrett Vorbeck Date: Tue, 19 Apr 2022 21:13:43 -0400 Subject: [PATCH 11/23] remove CombatDrawer icon from nav --- src/pages/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/index.js b/src/pages/index.js index 87a3e24..f038471 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -55,7 +55,7 @@ function IndexPage() { - + From dffd7f7efd52be25f7638af68ef7a7226a0a81fb Mon Sep 17 00:00:00 2001 From: Garrett Vorbeck Date: Tue, 19 Apr 2022 21:14:07 -0400 Subject: [PATCH 12/23] clear button and duplicate checking --- src/components/arena.js | 206 ++++++++++++++++--------------------- src/images/icons/skull.svg | 1 + 2 files changed, 87 insertions(+), 120 deletions(-) create mode 100644 src/images/icons/skull.svg diff --git a/src/components/arena.js b/src/components/arena.js index 36b0556..3bc6921 100644 --- a/src/components/arena.js +++ b/src/components/arena.js @@ -1,10 +1,10 @@ import React from 'react'; import { - Box, Drawer, FormControl, Input, InputLabel, List, ListItem, ListItemText, SvgIcon, TextField, + Box, Drawer, List, ListItem, ListItemText, SvgIcon, TextField, } from '@mui/material'; -import { IconButton } from 'gatsby-theme-material-ui'; -import PersonAddIcon from '@mui/icons-material/PersonAdd'; -import CasinoIcon from '@mui/icons-material/Casino'; +import { Button, IconButton } from 'gatsby-theme-material-ui'; +import SkullIcon from '../images/icons/skull.svg'; +// import PersonAddIcon from '@mui/icons-material/PersonAdd'; function useArena() { // Prep Session Storage data: @@ -25,12 +25,24 @@ function useArena() { // Create ListItems const [combatantListItems, setCombatantListItems] = React.useState([]); + + // State for new player name validation. + const [error, setError] = React.useState(false); + // Skull input adornment. + const deathAdornment = ( + + + + + + ); // Submit new initiative by making a shallow copy of data, manipulating it, and then // submiting the new data. const initiativeSubmit = (value, index) => { const arenaCopy = [...arenaSessionStorage]; const arenaCopyItem = { ...arenaCopy[index] }; - arenaCopyItem.initiative = parseInt(value.replace(/\D/g, ''), 10); + arenaCopyItem.initiative = Number.isNaN(Number(parseInt(value, 10))) + ? 0 : Number(parseInt(value, 10)); arenaCopy[index] = arenaCopyItem; setArenaSessionStorage(arenaCopy); }; @@ -38,10 +50,16 @@ function useArena() { const hpSubmit = (value, current, index) => { const arenaCopy = [...arenaSessionStorage]; const arenaCopyItem = { ...arenaCopy[index] }; - arenaCopyItem.hp = current - parseInt(value.replace(/\D/g, ''), 10); + console.log(`${arenaCopyItem.name} ${value.includes('+') ? 'receives' : 'loses'} ${value} HP`); + const hpSanitized = Number.isNaN(Number(parseInt(value, 10))) ? 0 : Number(parseInt(value, 10)); + const hpDigit = Number.isNaN(hpSanitized) ? 0 : hpSanitized; + arenaCopyItem.hp = value.includes('+') ? (current + hpDigit) : (current - hpDigit); arenaCopy[index] = arenaCopyItem; setArenaSessionStorage(arenaCopy); }; + + // Use this to check for duplicates. + const duplicatesArray = []; const combatantListMaker = (array) => array // Sort by initiative and then by name. .sort( @@ -51,113 +69,57 @@ function useArena() { ) : -1 ), ) - .map((item, index) => ( - - {/* Initiative value */} - initiativeSubmit(event.target.value, index)} - onKeyDown={(event) => { - if (event.key === 'Enter') { - event.target.blur(); - } - }} - /> - {/* Combatant's name */} - - {/* HP value */} - event.target.select()} - onBlur={(event) => hpSubmit(event.target.value, item.hp, index)} - onKeyDown={(event) => { - if (event.key === 'Enter') { - event.target.blur(); - } - }} - /> - - )); - - // IF arenaSessionStorage value is altered, reset the Session Storage data: - React.useEffect(() => { - console.log('arenaSessionStorage useEffect'); - // Resort the data and recreate the list. - setCombatantListItems(combatantListMaker(arenaSessionStorage)); - // Stringify and resend the data to Session Storage. - sessionStorage.setItem(ssKey, JSON.stringify(arenaSessionStorage)); - }, [arenaSessionStorage]); - - return { - arenaSessionStorage, - setArenaSessionStorage, - arenaDrawerOpen, - setArenaDrawerOpen, - arenaRender: ( - setArenaDrawerOpen(false)} - sx={{ - p: '1rem', - }} - > - {combatantListItems} - - ), - }; -} - -{ /* function useArena() { - // Drawer State. - // const [arenaDrawerOpen, setArenaDrawerOpen] = React.useState(false); - // Parsed Session Storage data. - // const [arenaSessionStorage, setArenaSessionStorage] = React.useState( - // JSON.parse(sessionStorage.getItem('gmcm-combatants') || '[]'), - // ); - // const [playerName, setPlayerName] = React.useState(''); - const [error, setError] = React.useState(false); - // Mapping ListItems based on parsed Session Storage data - const combatantListItems = arenaSessionStorage - .sort((a, b) => (a.initiative < b.initiative ? 1 : -1)) - .map((item) => { - const initiative = item.initiative || 0; - console.log(initiative); + .map((item, index) => { + duplicatesArray.push(item.name); + const dupes = (name) => { + let count = 0; + duplicatesArray.forEach((element, i) => { + if (duplicatesArray[i] === name) { + count += 1; + } + }); + return count; + }; return ( - - {initiative === 0 ? ( - - - - ) : initiative} - - {item.name} + {/* Initiative value */} event.target.select()} + onKeyDown={(event) => { + if (event.key === 'Enter') { + initiativeSubmit(event.target.value, index); + } }} - onChange={() => { - // setError(false); - // setPlayerName(event.target.value); + /> + {/* Combatant's name */} + 1 ? `${item.name} #${dupes(item.name)}` : item.name} /> + {/* HP value */} + 0 ? '' : deathAdornment, inputMode: 'numeric', pattern: '[0-9.+-]*' }} + defaultValue={item.hp} + onFocus={(event) => event.target.select()} + onKeyDown={(event) => { + if (event.key === 'Enter') { + hpSubmit(event.target.value, item.hp, index); + } }} /> ); }); - // Set Stringified Session Storage data. - // React.useEffect(() => { - // sessionStorage.setItem('gmcm-combatants', JSON.stringify(arenaSessionStorage)); - // }, [arenaSessionStorage]); + + // IF arenaSessionStorage value is altered, reset the Session Storage data: + React.useEffect(() => { + console.log('arenaSessionStorage useEffect'); + // Resort the data and recreate the list. + setCombatantListItems(combatantListMaker(arenaSessionStorage)); + // Stringify and resend the data to Session Storage. + sessionStorage.setItem(ssKey, JSON.stringify(arenaSessionStorage)); + }, [arenaSessionStorage]); return { arenaSessionStorage, @@ -181,30 +143,34 @@ function useArena() { setError(true); return; } - setArenaSessionStorage([...arenaSessionStorage, { name: playerName, initiative: 0 }]); + setArenaSessionStorage( + [...arenaSessionStorage, { name: playerName, initiative: 0, hp: 0 }], + ); setPlayerName(''); }} > - - Add to Combat Tracker - { - setError(false); - setPlayerName(event.target.value); - }} - /> - - - - + { + setError(false); + setPlayerName(event.target.value); + }} + /> {combatantListItems} + ), }; -} */ } +} export default useArena; diff --git a/src/images/icons/skull.svg b/src/images/icons/skull.svg new file mode 100644 index 0000000..0bae879 --- /dev/null +++ b/src/images/icons/skull.svg @@ -0,0 +1 @@ + From 83ce54af554dce95aad06917dcad34b6f6841ef3 Mon Sep 17 00:00:00 2001 From: Garrett Vorbeck Date: Tue, 19 Apr 2022 21:15:19 -0400 Subject: [PATCH 13/23] no longer needed --- src/components/session-storage.js | 37 ------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 src/components/session-storage.js diff --git a/src/components/session-storage.js b/src/components/session-storage.js deleted file mode 100644 index 7e261d6..0000000 --- a/src/components/session-storage.js +++ /dev/null @@ -1,37 +0,0 @@ -import React from 'react'; -import { ListItem } from '@mui/material'; - -function combatData() { - const ssCombatData = sessionStorage.getItem('gmcm-combatants') || '[]'; - const [combatantArray, setCombatantArray] = React.useState( - JSON.parse(ssCombatData), - ); - const [combatantList, setCombatantList] = React.useState(''); - React.useEffect(() => { - setCombatantList(combatantArray.map((combatant) => ( - {combatant.name} - ))); - sessionStorage.setItem('gmcm-combatants', JSON.stringify(combatantArray)); - console.log('woot'); - }, [combatantArray]); - const addCombatant = (combatant = null) => { - setCombatantArray([...combatantArray, combatant]); - }; - return { - // Either - // A string of unparsed session storage data - // OR an empty array as a string - ssCombatData, - // Parsed session storage data (array of objects) - // Turns the strings of session storage data into usable data - combatantArray, - // Sets the above's value - setCombatantArray, - // Function for adding a new player/monster object to the combatantArray - addCombatant, - // JSX/HTML of the rows for combat tracker - combatantList, - }; -} - -export default combatData; From 799613d0994f3bb23c822af9006b72ff53211406 Mon Sep 17 00:00:00 2001 From: Garrett Vorbeck Date: Wed, 20 Apr 2022 01:15:44 -0400 Subject: [PATCH 14/23] delete button and buggy turn nav --- src/components/arena.js | 63 +++++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 12 deletions(-) diff --git a/src/components/arena.js b/src/components/arena.js index 3bc6921..2ae08ca 100644 --- a/src/components/arena.js +++ b/src/components/arena.js @@ -1,8 +1,16 @@ import React from 'react'; -import { - Box, Drawer, List, ListItem, ListItemText, SvgIcon, TextField, -} from '@mui/material'; +import Box from '@mui/material/Box'; +import Drawer from '@mui/material/Drawer'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +// import SvgIcon from '@mui/material/SvgIcon'; +import TextField from '@mui/material/TextField'; +import ListItemText from '@mui/material/ListItemText'; import { Button, IconButton } from 'gatsby-theme-material-ui'; +import DoubleArrowIcon from '@mui/icons-material/DoubleArrow'; +import PersonOffIcon from '@mui/icons-material/PersonOff'; +import ButtonGroup from '@mui/material/ButtonGroup'; +import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; import SkullIcon from '../images/icons/skull.svg'; // import PersonAddIcon from '@mui/icons-material/PersonAdd'; @@ -30,12 +38,15 @@ function useArena() { const [error, setError] = React.useState(false); // Skull input adornment. const deathAdornment = ( - - - - - + 'hi' + // + // + // + // + // ); + // Turn indicator. + const [turnIndex, setTurnIndex] = React.useState(0); // Submit new initiative by making a shallow copy of data, manipulating it, and then // submiting the new data. const initiativeSubmit = (value, index) => { @@ -52,8 +63,7 @@ function useArena() { const arenaCopyItem = { ...arenaCopy[index] }; console.log(`${arenaCopyItem.name} ${value.includes('+') ? 'receives' : 'loses'} ${value} HP`); const hpSanitized = Number.isNaN(Number(parseInt(value, 10))) ? 0 : Number(parseInt(value, 10)); - const hpDigit = Number.isNaN(hpSanitized) ? 0 : hpSanitized; - arenaCopyItem.hp = value.includes('+') ? (current + hpDigit) : (current - hpDigit); + arenaCopyItem.hp = current + hpSanitized; arenaCopy[index] = arenaCopyItem; setArenaSessionStorage(arenaCopy); }; @@ -82,6 +92,7 @@ function useArena() { }; return ( + {index === turnIndex && } {/* Initiative value */} + { + setArenaSessionStorage( + [...arenaSessionStorage].filter((x) => x !== arenaSessionStorage[index]), + ); + }} + > + + ); }); @@ -115,11 +135,12 @@ function useArena() { // IF arenaSessionStorage value is altered, reset the Session Storage data: React.useEffect(() => { console.log('arenaSessionStorage useEffect'); + console.log(`turnIndex: ${turnIndex}`); // Resort the data and recreate the list. setCombatantListItems(combatantListMaker(arenaSessionStorage)); // Stringify and resend the data to Session Storage. sessionStorage.setItem(ssKey, JSON.stringify(arenaSessionStorage)); - }, [arenaSessionStorage]); + }, [arenaSessionStorage, turnIndex]); return { arenaSessionStorage, @@ -155,10 +176,28 @@ function useArena() { value={playerName} onChange={(event) => { setError(false); - setPlayerName(event.target.value); + setPlayerName( + event.target.value.charAt(0).toUpperCase() + event.target.value.slice(1), + ); }} /> + + + + {combatantListItems} + Turn Direction + + + {/* Combatant List */} + {combatantListItems.length > 0 && ( + + + li + li': { mt: 1 } }}>{combatantListItems} + + + )} + {/* Clear Button Group */} + + - {combatantListItems} - + Press CTRL+C to toggle the Combat Drawer. + ), }; diff --git a/src/pages/search.js b/src/pages/search.js index 8bde937..522c954 100644 --- a/src/pages/search.js +++ b/src/pages/search.js @@ -285,6 +285,7 @@ function SearchResultsItemHeader({ name: item.name, hp: hpRoll.total, initiative: initiativeRoll.total, + type: 'monster', }, ]); }} From b268fbd46ad47a947e518c176f6e0b191ef7d490 Mon Sep 17 00:00:00 2001 From: Garrett Vorbeck Date: Fri, 22 Apr 2022 13:50:58 -0400 Subject: [PATCH 20/23] modify add-on button --- src/components/arena.js | 2 +- src/pages/search.js | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/components/arena.js b/src/components/arena.js index d3e1a70..efae31c 100644 --- a/src/components/arena.js +++ b/src/components/arena.js @@ -2,7 +2,7 @@ // XXX arena: clicking monster's add icon shouldn't open drawer (makes adding multiple monsters tedious). instead it should add the monster to the list (drawer closed) and give a snackbar notification that the monster was added. // XXX arena: add a hotkey for the drawer. add hint text for the key on the drawer. // XXX arena: use split button (https://mui.com/material-ui/react-button-group/#split-button) to have a button that gives option to clear all combatants or clear just npcs. -// arena: give monster add icon a "+" using ::after or something. +// XXX arena: give monster add icon a "+" using ::after or something. // arena: click monster to see its stats // legal: comply with this (https://www.thearcanelibrary.com/blogs/news/how-to-use-the-open-game-license) // Homepage: 'What's new explaining combat drawer. diff --git a/src/pages/search.js b/src/pages/search.js index 522c954..098aa85 100644 --- a/src/pages/search.js +++ b/src/pages/search.js @@ -265,8 +265,9 @@ function SearchResultsItemHeader({ )} - title={{item.name}} + title={{item.name}} subheader={{subtitle}} + sx={{ overflow: 'hidden' }} /> {combatIcon && ( @@ -276,6 +277,20 @@ function SearchResultsItemHeader({ position: 'absolute', top: '0.25rem', right: '0.25rem', + '&::after': { + content: '"+"', + position: 'absolute', + bottom: 0, + left: 0, + borderRadius: '50%', + width: '12px', + height: '12px', + fontSize: '1.25rem', + lineHeight: '12px', + p: '0.25rem', + boxSizing: 'content-box', + backgroundColor: 'grey.800', + }, }} onClick={() => { enqueueSnackbar(`Added ${item.name} to the Combat Tracker.`); From 86688e39b179a969ee4cf8b21271e0dacc197721 Mon Sep 17 00:00:00 2001 From: Garrett Vorbeck Date: Fri, 22 Apr 2022 14:01:41 -0400 Subject: [PATCH 21/23] legal page updates and footer placement --- src/components/layout.js | 2 ++ src/pages/legal.js | 50 ++++++++++++++++++++-------------------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/components/layout.js b/src/components/layout.js index 94f40ac..a6701d5 100644 --- a/src/components/layout.js +++ b/src/components/layout.js @@ -135,6 +135,8 @@ function Layout({ > {FOOTER_COPY} {SITE_AUTHOR} + {', '} + Legal diff --git a/src/pages/legal.js b/src/pages/legal.js index 80bfad8..83eb4a3 100644 --- a/src/pages/legal.js +++ b/src/pages/legal.js @@ -17,79 +17,79 @@ function Legal() { - + Permission to copy, modify and distribute the files collectively known as the System Reference Document 5.1 (“SRD5”) is granted solely through the use of the Open Gaming License, Version 1.0a. - + This material is being released using the Open Gaming License Version 1.0a and you should read and understand the terms of that license before using this material. - + The text of the Open Gaming License itself is not Open Game Content. Instructions on using the License are provided within the License itself. - + The following items are designated Product Identity, as defined in Section 1(e) of the Open Game License Version 1.0a, and are subject to the conditions set forth in Section 7 of the OGL, and are not Open Content: Dungeons & Dragons, D&D, Player’s Handbook, Dungeon Master, Monster Manual, d20 System, Wizards of the Coast, d20 (when used as a trademark), Forgotten Realms, Faerûn, proper names (including those used in the names of spells or items), places, Underdark, Red Wizard of Thay, the City of Union, Heroic Domains of Ysgard, Ever-­‐‑ Changing Chaos of Limbo, Windswept Depths of Pandemonium, Infinite Layers of the Abyss, Tarterian Depths of Carceri, Gray Waste of Hades, Bleak Eternity of Gehenna, Nine Hells of Baator, Infernal Battlefield of Acheron, Clockwork Nirvana of Mechanus, Peaceable Kingdoms of Arcadia, Seven Mounting Heavens of Celestia, Twin Paradises of Bytopia, Blessed Fields of Elysium, Wilderness of the Beastlands, Olympian Glades of Arborea, Concordant Domain of the Outlands, Sigil, Lady of Pain, Book of Exalted Deeds, Book of Vile Darkness, beholder, gauth, carrion crawler, tanar’ri, baatezu, displacer beast, githyanki, githzerai, mind flayer, illithid, umber hulk, yuan-­‐‑ti. - + All of the rest of the SRD5 is Open Game Content as described in Section 1(d) of the License. - + The terms of the Open Gaming License Version 1.0a are as follows: - + OPEN GAME LICENSE Version 1.0a - + The following text is the property of Wizards of the Coast, Inc. and is Copyright 2000 Wizards of the Coast, Inc ("Wizards"). All Rights Reserved. - + 1. Definitions: (a)"Contributors" means the copyright and/or trademark owners who have contributed Open Game Content; (b)"Derivative Material" means copyrighted material including derivative works and translations (including into other computer languages), potation, modification, correction, addition, extension, upgrade, improvement, compilation, abridgment or other form in which an existing work may be recast, transformed or adapted; (c) "Distribute" means to reproduce, license, rent, lease, sell, broadcast, publicly display, transmit or otherwise distribute; (d)"Open Game Content" means the game mechanic and includes the methods, procedures, processes and routines to the extent such content does not embody the Product Identity and is an enhancement over the prior art and any additional content clearly identified as Open Game Content by the Contributor, and means any work covered by this License, including translations and derivative works under copyright law, but specifically excludes Product Identity. (e) "Product Identity" means product and product line names, logos and identifying marks including trade dress; artifacts; creatures characters; stories, storylines, plots, thematic elements, dialogue, incidents, language, artwork, symbols, designs, depictions, likenesses, formats, poses, concepts, themes and graphic, photographic and other visual or audio representations; names and descriptions of characters, spells, enchantments, personalities, teams, personas, likenesses and special abilities; places, locations, environments, creatures, equipment, magical or supernatural abilities or effects, logos, symbols, or graphic designs; and any other trademark or registered trademark clearly identified as Product identity by the owner of the Product Identity, and which specifically excludes the Open Game Content; (f) "Trademark" means the logos, names, mark, sign, motto, designs that are used by a Contributor to identify itself or its products or the associated products contributed to the Open Game License by the Contributor (g) "Use", "Used" or "Using" means to use, Distribute, copy, edit, format, modify, translate and otherwise create Derivative Material of Open Game Content. (h) "You" or "Your" means the licensee in terms of this agreement. - + 2. The License: This License applies to any Open Game Content that contains a notice indicating that the Open Game Content may only be Used under and in terms of this License. You must affix such a notice to any Open Game Content that you Use. No terms may be added to or subtracted from this License except as described by the License itself. No other terms or conditions may be applied to any Open Game Content distributed using this License. 3.Offer and Acceptance: By Using the Open Game Content You indicate Your acceptance of the terms of this License. - + 4. Grant and Consideration: In consideration for agreeing to use this License, the Contributors grant You a perpetual, worldwide, royalty-­‐‑free, non-­‐‑ exclusive license with the exact terms of this License to Use, the Open Game Content. - + 5.Representation of Authority to Contribute: If You are contributing original material as Open Game Content, You represent that Your Contributions are Your original creation and/or You have sufficient rights to grant the rights conveyed by this License. - + 6.Notice of License Copyright: You must update the COPYRIGHT NOTICE portion of this License to include the exact text of the COPYRIGHT NOTICE of any Open Game Content You are copying, modifying or distributing, and You must add the title, the copyright date, and the copyright holder's name to the COPYRIGHT NOTICE of any original Open Game Content you Distribute. - + 7. Use of Product Identity: You agree not to Use any Product Identity, including as an indication as to compatibility, except as expressly licensed in another, independent Agreement with the owner of each element of that Product Identity. You agree not to indicate compatibility or co-­‐‑adaptability with any Trademark or Registered Trademark in conjunction with a work containing Open Game Content except as expressly licensed in another, independent Agreement with the owner of such Trademark or Registered Trademark. The use of any Product Identity in Open Game Content does not constitute a challenge to the ownership of that Product Identity. The owner of any Product Identity used in Open Game Content shall retain all rights, title and interest in and to that Product Identity. - + 8. Identification: If you distribute Open Game Content You must clearly indicate which portions of the work that you are distributing are Open Game Content. - + 9. Updating the License: Wizards or its designated Agents may publish updated versions of this License. You may use any authorized version of this License to copy, modify and distribute any Open Game Content originally distributed under any version of this License. - + 10. Copy of this License: You MUST include a copy of this License with every copy of the Open Game Content You Distribute. - + 11. Use of Contributor Credits: You may not market or advertise the Open Game Content using the name of any Contributor unless You have written permission from the Contributor to do so. - + 12. Inability to Comply: If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Open Game Content due to statute, judicial order, or governmental regulation then You may not Use any Open Game Material so affected. - + 13. Termination: This License will terminate automatically if You fail to comply with all terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses shall survive the termination of this License. - + 14. Reformation: If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. - - 15. COPYRIGHT NOTICE + + 15. COPYRIGHT NOTICE Open Game License v 1.0a Copyright 2000, Wizards of the Coast, LLC. System Reference Document 5.1 Copyright 2016, Wizards of the Coast, LLC.; Authors Mike Mearls, Jeremy Crawford, Chris Perkins, Rodney Thompson, Peter Lee, James Wyatt, Robert J. Schwalb, Bruce R. Cordell, Chris Sims, and Steve Townshend, based on original material by E. Gary Gygax and Dave Arneson. - + Open Game License v 1.0a Copyright 2000, Wizards of the Coast, LLC. - + System Reference Document 5.1 Copyright 2016, Wizards of the Coast, Inc.; Authors Mike Mearls, Jeremy Crawford, Chris Perkins, Rodney Thompson, Peter Lee, James Wyatt, Robert J. Schwalb, Bruce R. Cordell, Chris Sims, and Steve Townshend, based on original material by E. Gary Gygax and Dave Arneson. From 19445a61971a1ea391f297e5e65b9f53a109d573 Mon Sep 17 00:00:00 2001 From: Garrett Vorbeck Date: Fri, 22 Apr 2022 17:47:34 -0400 Subject: [PATCH 22/23] cleanup --- src/components/adventure-page-layout.js | 34 +++++++++++------------ src/components/arena.js | 13 --------- src/components/location-page-layout.js | 36 ++++++++++--------------- src/components/navigation.js | 4 +-- src/pages/adventures.js | 4 +-- src/pages/index.js | 24 ++++++++++++++--- src/pages/reference.js | 4 +-- src/pages/search.js | 5 +--- 8 files changed, 54 insertions(+), 70 deletions(-) diff --git a/src/components/adventure-page-layout.js b/src/components/adventure-page-layout.js index 3dd3397..3fa6f3a 100644 --- a/src/components/adventure-page-layout.js +++ b/src/components/adventure-page-layout.js @@ -1,23 +1,21 @@ import React from 'react'; import { graphql } from 'gatsby'; -import { - Box, - Card, - Divider, - List, - ListItem, - ListItemText, - Paper, - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TablePagination, - TableRow, - TableSortLabel, - Typography, -} from '@mui/material'; +import Box from '@mui/material/Box'; +import Card from '@mui/material/Card'; +import Divider from '@mui/material/Divider'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemText from '@mui/material/ListItemText'; +import Paper from '@mui/material/Paper'; +import Table from '@mui/material/Table'; +import TableBody from '@mui/material/TableBody'; +import TableCell from '@mui/material/TableCell'; +import TableContainer from '@mui/material/TableContainer'; +import TableHead from '@mui/material/TableHead'; +import TablePagination from '@mui/material/TablePagination'; +import TableRow from '@mui/material/TableRow'; +import TableSortLabel from '@mui/material/TableSortLabel'; +import Typography from '@mui/material/Typography'; import { Link, ListItemButton } from 'gatsby-theme-material-ui'; import { visuallyHidden } from '@mui/utils'; import { Feed, LocationOn, EmojiPeople } from '@mui/icons-material/'; diff --git a/src/components/arena.js b/src/components/arena.js index efae31c..46b8d74 100644 --- a/src/components/arena.js +++ b/src/components/arena.js @@ -1,16 +1,3 @@ -// 1.2 Checklist -// XXX arena: clicking monster's add icon shouldn't open drawer (makes adding multiple monsters tedious). instead it should add the monster to the list (drawer closed) and give a snackbar notification that the monster was added. -// XXX arena: add a hotkey for the drawer. add hint text for the key on the drawer. -// XXX arena: use split button (https://mui.com/material-ui/react-button-group/#split-button) to have a button that gives option to clear all combatants or clear just npcs. -// XXX arena: give monster add icon a "+" using ::after or something. -// arena: click monster to see its stats -// legal: comply with this (https://www.thearcanelibrary.com/blogs/news/how-to-use-the-open-game-license) -// Homepage: 'What's new explaining combat drawer. -// Arena: button should be a floating button, not in nav. -// XXX arena: style the drawer. -// general: theme options to exclude default content pieces. -// legal: use Tabs? -// arena: remove strings to constants. import React from 'react'; import Box from '@mui/material/Box'; import Drawer from '@mui/material/Drawer'; diff --git a/src/components/location-page-layout.js b/src/components/location-page-layout.js index c0b2648..73629cb 100644 --- a/src/components/location-page-layout.js +++ b/src/components/location-page-layout.js @@ -1,21 +1,19 @@ import React, { useEffect, useState } from 'react'; import { graphql } from 'gatsby'; import { GatsbyImage, getImage } from 'gatsby-plugin-image'; -import { - Alert, - Box, - ButtonGroup, - Card, - CardContent, - CardHeader, - Divider, - List, - ListItem, - Paper, - Stack, - SvgIcon, - Tooltip, -} from '@mui/material'; +import Alert from '@mui/material/Alert'; +import Box from '@mui/material/Box'; +import ButtonGroup from '@mui/material/ButtonGroup'; +import Card from '@mui/material/Card'; +import CardContent from '@mui/material/CardContent'; +import CardHeader from '@mui/material/CardHeader'; +import Divider from '@mui/material/Divider'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import Paper from '@mui/material/Paper'; +import Stack from '@mui/material/Stack'; +import SvgIcon from '@mui/material/SvgIcon'; +import Tooltip from '@mui/material/Tooltip'; import { MDXRenderer } from 'gatsby-plugin-mdx'; import { Link, @@ -49,24 +47,18 @@ import { Boss, Unknown, } from '../images/icons'; -import { arenaDrawerState } from './arena'; const markdownComponentsList = { Link, MonsterLink, SpellLink, Dice, }; function LocationPageLayout({ data, location }) { - const { drawerOpen, setDrawerOpen } = arenaDrawerState(); const [scrollLocation, setScrollLocation] = useState(0); const parentAdventureTitle = location.state ? location.state.parentAdventureTitle : ''; const parentAdventureSlug = location.state ? location.state.parentAdventureSlug : ''; return ( - + {parentAdventureTitle && ( { - setArenaDrawerOpen(!arenaDrawerOpen); - }} + onClick={() => { setArenaDrawerOpen(!arenaDrawerOpen); }} > diff --git a/src/pages/adventures.js b/src/pages/adventures.js index b30169f..6a4167b 100644 --- a/src/pages/adventures.js +++ b/src/pages/adventures.js @@ -7,12 +7,10 @@ import { CardActionArea } from 'gatsby-theme-material-ui'; import Layout from '../components/layout'; import AdventureDetails from '../components/adventure-details'; import { ADVENTURES } from '../utils/constants'; -import { arenaDrawerState } from '../components/arena'; function AdventuresPage({ data }) { - const { drawerOpen, setDrawerOpen } = arenaDrawerState(); return ( - + ); diff --git a/src/pages/index.js b/src/pages/index.js index f038471..08ca739 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -1,8 +1,14 @@ +/* eslint-disable max-len */ /* eslint-disable react/no-unescaped-entities */ import React from 'react'; -import { - Box, Card, CardContent, List, ListItem, Paper, Typography, -} from '@mui/material'; +import Box from '@mui/material/Box'; +import Card from '@mui/material/Card'; +import CardContent from '@mui/material/CardContent'; +import CardHeader from '@mui/material/CardHeader'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import Paper from '@mui/material/Paper'; +import Typography from '@mui/material/Typography'; import Navigation from '../components/navigation'; import Layout from '../components/layout'; import { GREETING, DESCRIPTION } from '../utils/constants'; @@ -15,7 +21,7 @@ function IndexPage() { sx={{ color: 'secondary.main', display: 'grid', - gridTemplate: 'auto / repeat(2, auto)', + gridTemplate: 'auto / 3fr 1fr', gap: 2, p: 2, mt: 1, @@ -56,6 +62,16 @@ function IndexPage() { + + + + + * Added the Combat Tracker to search pages. You can now add players and monsters to a simple combat simulator that automatically determines the Initiative/HP of monsters added. See plugin documentation for more information. + * Added OGL, SRD documents in a new "Legal" page in the footer. + * Added all SRD monsters to the monster search. + + + diff --git a/src/pages/reference.js b/src/pages/reference.js index 2c0c921..ccb4c03 100644 --- a/src/pages/reference.js +++ b/src/pages/reference.js @@ -25,7 +25,6 @@ import Masonry from '@mui/lab/Masonry'; import Layout from '../components/layout'; import Dice from '../components/dice'; import { REFERENCE, SCROLL_BEHAVIOR } from '../utils/constants'; -import { arenaDrawerState } from '../components/arena'; /* Table of Contents */ function TableOfContents({ referenceData }) { @@ -290,7 +289,6 @@ function ReferenceArticlesCategoryBlockItemMarkdown(props) { /* PAGE FUNCTION */ function ReferencePage({ data }) { - const { drawerOpen, setDrawerOpen } = arenaDrawerState(); const posts = data.allMdx.nodes; const referenceData = []; @@ -328,7 +326,7 @@ function ReferencePage({ data }) { } return ( - + + Date: Fri, 22 Apr 2022 18:15:57 -0400 Subject: [PATCH 23/23] cleanup previous drawer implementations --- src/components/arena.js | 235 ++++++------ src/components/layout.js | 7 - src/components/navigation.js | 56 +-- src/content/monsters/srd-monsters-1.mdx | 456 ++++++++++++------------ src/content/monsters/srd-monsters-2.mdx | 230 ++++++------ src/pages/search.js | 3 - src/utils/constants.js | 4 - 7 files changed, 480 insertions(+), 511 deletions(-) diff --git a/src/components/arena.js b/src/components/arena.js index 46b8d74..f40cc8c 100644 --- a/src/components/arena.js +++ b/src/components/arena.js @@ -9,6 +9,7 @@ import { Button, IconButton } from 'gatsby-theme-material-ui'; import DoubleArrowIcon from '@mui/icons-material/DoubleArrow'; import PersonOffIcon from '@mui/icons-material/PersonOff'; import ButtonGroup from '@mui/material/ButtonGroup'; +import Fab from '@mui/material/Fab'; import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; import Typography from '@mui/material/Typography'; import PersonAddIcon from '@mui/icons-material/PersonAdd'; @@ -24,6 +25,7 @@ import Popper from '@mui/material/Popper'; import MenuItem from '@mui/material/MenuItem'; import MenuList from '@mui/material/MenuList'; import SkullIcon from '../images/icons/skull.svg'; +import SwordWoman from '../images/swordwoman.svg'; function useArena() { // Prep Session Storage data: @@ -267,125 +269,132 @@ function useArena() { arenaDrawerOpen, setArenaDrawerOpen, arenaRender: ( - setArenaDrawerOpen(false)}> - {/* Add player form */} - { - event.preventDefault(); - if (playerName === '') { - setError(true); - return; - } - setArenaSessionStorage( - [...arenaSessionStorage, { - name: playerName, initiative: 0, hp: 0, type: 'player', - }], - ); - setPlayerName(''); - }} - - > - - - - ), + <> + setArenaDrawerOpen(false)}> + {/* Add player form */} + { - setError(false); - setPlayerName( - event.target.value.charAt(0).toUpperCase() + event.target.value.slice(1), + onSubmit={(event) => { + event.preventDefault(); + if (playerName === '') { + setError(true); + return; + } + setArenaSessionStorage( + [...arenaSessionStorage, { + name: playerName, initiative: 0, hp: 0, type: 'player', + }], ); + setPlayerName(''); }} - /> - - {/* Turn advancement */} - - - Turn Direction - - - {/* Combatant List */} - {combatantListItems.length > 0 && ( - - - li + li': { mt: 1 } }}>{combatantListItems} - - - )} - {/* Clear Button Group */} - - - - - - {({ TransitionProps, placement }) => ( - + + + ), }} - > - - - - {options.map((option, index) => ( - handleMenuItemClick(event, index)} - > - {option} - - ))} - - - - + onChange={(event) => { + setError(false); + setPlayerName( + event.target.value.charAt(0).toUpperCase() + event.target.value.slice(1), + ); + }} + /> + + {/* Turn advancement */} + + + Turn Direction + + + {/* Combatant List */} + {combatantListItems.length > 0 && ( + + + li + li': { mt: 1 } }}>{combatantListItems} + + )} - - {/* Hotkey notice */} - - Press CTRL+C to toggle the Combat Drawer. - - + {/* Clear Button Group */} + + + + + + {({ TransitionProps, placement }) => ( + + + + + {options.map((option, index) => ( + handleMenuItemClick(event, index)} + > + {option} + + ))} + + + + + )} + + {/* Hotkey notice */} + + Press CTRL+C to toggle the Combat Drawer. + + + setArenaDrawerOpen(true)}> + + + + + ), }; } diff --git a/src/components/layout.js b/src/components/layout.js index a6701d5..1fa69fb 100644 --- a/src/components/layout.js +++ b/src/components/layout.js @@ -10,7 +10,6 @@ import { } from '../utils/constants'; import Navigation from './navigation'; import GmcmBlackBridgeIcon from '../images/black-bridge.svg'; -// import useArena from './arena'; // eslint-disable-next-line react/function-component-definition const HeaderContainer = (props) => ; @@ -18,11 +17,8 @@ const HeaderContainer = (props) => ; function Layout({ children, hideNavigation, - hideDrawerIcon = false, title, navDirection, - arenaDrawerOpen = false, - setArenaDrawerOpen = undefined, arenaRender = undefined, }) { return ( @@ -97,10 +93,7 @@ function Layout({ - {NAVIGATION_DATA.map((item, index) => { - if (index === 0) { - if (!hideDrawerIcon) { - return ( - - { setArenaDrawerOpen(!arenaDrawerOpen); }} - > - - - - - - ); - } - return ''; - } - return ( - - - - ); - })} + {NAVIGATION_DATA.map((item) => ( + + + + ))} ); diff --git a/src/content/monsters/srd-monsters-1.mdx b/src/content/monsters/srd-monsters-1.mdx index 820cb3c..87b1b6b 100644 --- a/src/content/monsters/srd-monsters-1.mdx +++ b/src/content/monsters/srd-monsters-1.mdx @@ -5,10 +5,10 @@ monsters: type: 'Large aberration, lawful evil' hp: value: '135' - notes: (18d10+36) + notes: '18d10+36' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 10 ft. - swim 40 ft. @@ -104,10 +104,10 @@ monsters: type: 'Medium celestial, lawful good' hp: value: '136' - notes: (16d8+64) + notes: '16d8+64' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - fly 90 ft. @@ -193,10 +193,10 @@ monsters: type: 'Large celestial, lawful good' hp: value: '200' - notes: (16d10+112) + notes: '16d10+112' ac: value: '19' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 120 ft. @@ -274,10 +274,10 @@ monsters: type: 'Large celestial, lawful good' hp: value: '243' - notes: (18d10+144) + notes: '18d10+144' ac: value: '21' - notes: (natural armor) + notes: 'natural armor' speed: - 50 ft. - fly 150 ft. @@ -388,10 +388,10 @@ monsters: type: 'Medium construct, unaligned' hp: value: '33' - notes: (6d8+6) + notes: '6d8+6' ac: value: '18' - notes: (natural armor) + notes: 'natural armor' speed: - 25 ft. abilities: @@ -449,10 +449,10 @@ monsters: type: 'Small construct, unaligned' hp: value: '17' - notes: (5d6) + notes: '5d6' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 0 ft. - fly 50 ft. It can hover. @@ -509,7 +509,7 @@ monsters: type: 'Large construct, unaligned' hp: value: '33' - notes: (6d10) + notes: '6d10' ac: value: '12' notes: null @@ -574,7 +574,7 @@ monsters: type: 'Large monstrosity, unaligned' hp: value: '39' - notes: (6d10+6) + notes: '6d10+6' ac: value: '14' notes: '(natural armor, 11 while prone)' @@ -623,7 +623,7 @@ monsters: type: 'Medium elemental, lawful neutral' hp: value: '39' - notes: (6d8+12) + notes: '6d8+12' ac: value: '17' notes: '(natural armor, shield)' @@ -679,10 +679,10 @@ monsters: type: 'Medium monstrosity, unaligned' hp: value: '52' - notes: (8d8+16) + notes: '8d8+16' ac: value: '12' - notes: (natural armor) + notes: 'natural armor' speed: - 20 ft. abilities: @@ -733,10 +733,10 @@ monsters: type: 'Huge monstrosity, neutral evil' hp: value: '168' - notes: (16d12+64) + notes: '16d12+64' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 50 ft. - climb 40 ft. @@ -807,7 +807,7 @@ monsters: type: 'Medium humanoid (goblinoid), chaotic evil' hp: value: '27' - notes: (5d8+5) + notes: '5d8+5' ac: value: '16' notes: '(hide armor, shield)' @@ -866,10 +866,10 @@ monsters: type: 'Large monstrosity, unaligned' hp: value: '94' - notes: (9d10+45) + notes: '9d10+45' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - burrow 40 ft. @@ -923,7 +923,7 @@ monsters: type: 'Large monstrosity, neutral good' hp: value: '45' - notes: (6d10+12) + notes: '6d10+12' ac: value: '12' notes: null @@ -985,10 +985,10 @@ monsters: type: 'Large monstrosity, chaotic evil' hp: value: '114' - notes: (12d10+48) + notes: '12d10+48' ac: value: '14' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - fly 60 ft. @@ -1045,10 +1045,10 @@ monsters: type: 'Large aberration, chaotic evil' hp: value: '93' - notes: (11d10+33) + notes: '11d10+33' ac: value: '16' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - swim 30 ft. @@ -1107,10 +1107,10 @@ monsters: type: 'Large aberration, chaotic neutral' hp: value: '78' - notes: (12d10+12) + notes: '12d10+12' ac: value: '14' - notes: (natural armor) + notes: 'natural armor' speed: - 10 ft. - fly 40 ft. @@ -1196,7 +1196,7 @@ monsters: type: 'Small monstrosity, unaligned' hp: value: '27' - notes: (6d6+6) + notes: '6d6+6' ac: value: '11' notes: null @@ -1239,10 +1239,10 @@ monsters: type: 'Medium celestial, lawful good' hp: value: '97' - notes: (13d8+39) + notes: '13d8+39' ac: value: '19' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - fly 90 ft. @@ -1325,7 +1325,7 @@ monsters: type: 'Small monstrosity, unaligned' hp: value: '29' - notes: (5d6+5) + notes: '5d6+5' ac: value: '11' notes: null @@ -1391,10 +1391,10 @@ monsters: type: 'Huge fiend (demon), chaotic evil' hp: value: '262' - notes: (21d12+126) + notes: '21d12+126' ac: value: '19' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 80 ft. @@ -1492,10 +1492,10 @@ monsters: type: 'Small fiend (demon), chaotic evil' hp: value: '18' - notes: (4d6+4) + notes: '4d6+4' ac: value: '11' - notes: (natural armor) + notes: 'natural armor' speed: - 20 ft. abilities: @@ -1552,10 +1552,10 @@ monsters: type: 'Large fiend (demon), chaotic evil' hp: value: '157' - notes: (15d10+75) + notes: '15d10+75' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. abilities: @@ -1637,10 +1637,10 @@ monsters: type: 'Large fiend (demon), chaotic evil' hp: value: '136' - notes: (13d10+65) + notes: '13d10+65' ac: value: '16' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -1717,10 +1717,10 @@ monsters: type: 'Large fiend (demon), chaotic evil' hp: value: '189' - notes: (18d10+90) + notes: '18d10+90' ac: value: '18' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. abilities: @@ -1810,10 +1810,10 @@ monsters: type: 'Large fiend (demon), chaotic evil' hp: value: '184' - notes: (16d10+96) + notes: '16d10+96' ac: value: '18' - notes: (natural armor) + notes: 'natural armor' speed: - 20 ft. - fly 30 ft. @@ -1901,7 +1901,7 @@ monsters: type: 'Tiny fiend (demon), chaotic evil' hp: value: '7' - notes: (3d4) + notes: '3d4' ac: value: '13' notes: null @@ -1984,10 +1984,10 @@ monsters: type: 'Large fiend (demon), chaotic evil' hp: value: '104' - notes: (11d10+44) + notes: '11d10+44' ac: value: '15' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 60 ft. @@ -2072,10 +2072,10 @@ monsters: type: 'Medium fiend (devil), lawful evil' hp: value: '110' - notes: (13d8+52) + notes: '13d8+52' ac: value: '15' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -2156,10 +2156,10 @@ monsters: type: 'Medium fiend (devil), lawful evil' hp: value: '52' - notes: (8d8+16) + notes: '8d8+16' ac: value: '13' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -2236,10 +2236,10 @@ monsters: type: 'Large fiend (devil), lawful evil' hp: value: '142' - notes: (15d10+60) + notes: '15d10+60' ac: value: '19' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 40 ft. @@ -2311,10 +2311,10 @@ monsters: type: 'Medium fiend (devil), lawful evil' hp: value: '85' - notes: (10d8+40) + notes: '10d8+40' ac: value: '16' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -2395,10 +2395,10 @@ monsters: type: 'Medium fiend (devil), lawful evil' hp: value: '153' - notes: (18d8+72) + notes: '18d8+72' ac: value: '18' - notes: (plate) + notes: 'plate' speed: - 30 ft. - fly 60 ft. @@ -2479,10 +2479,10 @@ monsters: type: 'Large fiend (devil), lawful evil' hp: value: '178' - notes: (17d10+85) + notes: '17d10+85' ac: value: '18' - notes: (natural armor) + notes: 'natural armor' speed: - 20 ft. - fly 60 ft. @@ -2561,10 +2561,10 @@ monsters: type: 'Large fiend (devil), lawful evil' hp: value: '180' - notes: (19d10+76) + notes: '19d10+76' ac: value: '18' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. abilities: @@ -2654,7 +2654,7 @@ monsters: type: 'Tiny fiend (devil), lawful evil' hp: value: '10' - notes: (3d4+3) + notes: '3d4+3' ac: value: '13' notes: null @@ -2738,7 +2738,7 @@ monsters: type: 'Medium fiend (devil), lawful evil' hp: value: '13' - notes: (3d8) + notes: '3d8' ac: value: '7' notes: null @@ -2791,10 +2791,10 @@ monsters: type: 'Large fiend (devil), lawful evil' hp: value: '300' - notes: (24d10+168) + notes: '24d10+168' ac: value: '19' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - fly 60 ft. @@ -2886,10 +2886,10 @@ monsters: type: 'Large beast, unaligned' hp: value: '68' - notes: (8d10+24) + notes: '8d10+24' ac: value: '13' - notes: (natural armor) + notes: 'natural armor' speed: - 20 ft. - swim 40 ft. @@ -2930,10 +2930,10 @@ monsters: type: 'Huge beast, unaligned' hp: value: '95' - notes: (10d12+30) + notes: '10d12+30' ac: value: '13' - notes: (natural armor) + notes: 'natural armor' speed: - 50 ft. abilities: @@ -2978,10 +2978,10 @@ monsters: type: 'Huge beast, unaligned' hp: value: '136' - notes: (13d12+52) + notes: '13d12+52' ac: value: '13' - notes: (natural armor) + notes: 'natural armor' speed: - 50 ft. abilities: @@ -3027,7 +3027,7 @@ monsters: type: 'Medium monstrosity (shapechanger), unaligned' hp: value: '52' - notes: (8d8+16) + notes: '8d8+16' ac: value: '14' notes: null @@ -3099,10 +3099,10 @@ monsters: type: 'Gargantuan dragon, chaotic evil' hp: value: '367' - notes: (21d20+147) + notes: '21d20+147' ac: value: '22' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 80 ft. @@ -3198,10 +3198,10 @@ monsters: type: 'Huge dragon, chaotic evil' hp: value: '195' - notes: (17d12+85) + notes: '17d12+85' ac: value: '19' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 80 ft. @@ -3295,10 +3295,10 @@ monsters: type: 'Large dragon, chaotic evil' hp: value: '127' - notes: (15d10+45) + notes: '15d10+45' ac: value: '18' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 80 ft. @@ -3367,10 +3367,10 @@ monsters: type: 'Medium dragon, chaotic evil' hp: value: '33' - notes: (6d8+6) + notes: '6d8+6' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - fly 60 ft. @@ -3430,10 +3430,10 @@ monsters: type: 'Gargantuan dragon, lawful evil' hp: value: '481' - notes: (26d20+208) + notes: '26d20+208' ac: value: '22' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - burrow 40 ft. @@ -3523,7 +3523,7 @@ monsters: type: 'Huge dragon, lawful evil' hp: value: '225' - notes: (18d12+108) + notes: '18d12+108' ac: value: '19' notes: null @@ -3618,10 +3618,10 @@ monsters: type: 'Large dragon, lawful evil' hp: value: '152' - notes: (16d10+64) + notes: '16d10+64' ac: value: '18' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - burrow 40 ft. @@ -3688,10 +3688,10 @@ monsters: type: 'Medium dragon, lawful evil' hp: value: '52' - notes: (8d8+16) + notes: '8d8+16' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - burrow 15 ft. @@ -3749,10 +3749,10 @@ monsters: type: 'Gargantuan dragon, lawful evil' hp: value: '385' - notes: (22d20+154) + notes: '22d20+154' ac: value: '21' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 80 ft. @@ -3853,10 +3853,10 @@ monsters: type: 'Huge dragon, lawful evil' hp: value: '207' - notes: (18d12+90) + notes: '18d12+90' ac: value: '19' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 80 ft. @@ -3957,10 +3957,10 @@ monsters: type: 'Large dragon, lawful evil' hp: value: '136' - notes: (16d10+48) + notes: '16d10+48' ac: value: '18' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 80 ft. @@ -4032,10 +4032,10 @@ monsters: type: 'Medium dragon, lawful evil' hp: value: '38' - notes: (7d8+7) + notes: '7d8+7' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - fly 60 ft. @@ -4096,10 +4096,10 @@ monsters: type: 'Gargantuan dragon, chaotic evil' hp: value: '546' - notes: (28d20+252) + notes: '28d20+252' ac: value: '22' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - climb 40 ft. @@ -4190,10 +4190,10 @@ monsters: type: 'Huge dragon, chaotic evil' hp: value: '256' - notes: (19d12+133) + notes: '19d12+133' ac: value: '19' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - climb 40 ft. @@ -4302,10 +4302,10 @@ monsters: type: 'Large dragon, chaotic evil' hp: value: '178' - notes: (17d10+85) + notes: '17d10+85' ac: value: '18' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - climb 40 ft. @@ -4371,10 +4371,10 @@ monsters: type: 'Medium dragon, chaotic evil' hp: value: '75' - notes: (10d8+30) + notes: '10d8+30' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - climb 30 ft. @@ -4431,10 +4431,10 @@ monsters: type: 'Gargantuan dragon, chaotic evil' hp: value: '333' - notes: (18d20+144) + notes: '18d20+144' ac: value: '20' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - burrow 40 ft. @@ -4521,10 +4521,10 @@ monsters: type: 'Huge dragon, chaotic evil' hp: value: '200' - notes: (16d12+96) + notes: '16d12+96' ac: value: '18' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - burrow 30 ft. @@ -4621,10 +4621,10 @@ monsters: type: 'Large dragon, chaotic evil' hp: value: '133' - notes: (14d10+56) + notes: '14d10+56' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - burrow 20 ft. @@ -4696,10 +4696,10 @@ monsters: type: 'Medium dragon, chaotic evil' hp: value: '32' - notes: (5d8+10) + notes: '5d8+10' ac: value: '16' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - burrow 15 ft. @@ -4758,10 +4758,10 @@ monsters: type: 'Gargantuan dragon, chaotic good' hp: value: '297' - notes: (17d20+119) + notes: '17d20+119' ac: value: '20' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - burrow 40 ft. @@ -4873,10 +4873,10 @@ monsters: type: 'Huge dragon, chaotic good' hp: value: '172' - notes: (15d12+75) + notes: '15d12+75' ac: value: '18' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - burrow 40 ft. @@ -4967,10 +4967,10 @@ monsters: type: 'Large dragon, chaotic good' hp: value: '110' - notes: (13d10+39) + notes: '13d10+39' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - burrow 20 ft. @@ -5043,10 +5043,10 @@ monsters: type: 'Medium dragon, chaotic good' hp: value: '16' - notes: (3d8+3) + notes: '3d8+3' ac: value: '16' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - burrow 15 ft. @@ -5109,10 +5109,10 @@ monsters: type: 'Gargantuan dragon, lawful good' hp: value: '444' - notes: (24d20+192) + notes: '24d20+192' ac: value: '22' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 80 ft. @@ -5223,10 +5223,10 @@ monsters: type: 'Huge dragon, lawful good' hp: value: '212' - notes: (17d12+102) + notes: '17d12+102' ac: value: '19' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 80 ft. @@ -5327,10 +5327,10 @@ monsters: type: 'Large dragon, lawful good' hp: value: '142' - notes: (15d10+60) + notes: '15d10+60' ac: value: '18' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 80 ft. @@ -5405,10 +5405,10 @@ monsters: type: 'Medium dragon, lawful good' hp: value: '32' - notes: (5d8+10) + notes: '5d8+10' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - fly 60 ft. @@ -5472,10 +5472,10 @@ monsters: type: 'Gargantuan dragon, chaotic good' hp: value: '350' - notes: (20d20+140) + notes: '20d20+140' ac: value: '21' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - climb 40 ft. @@ -5588,10 +5588,10 @@ monsters: type: 'Huge dragon, chaotic good' hp: value: '184' - notes: (16d12+80) + notes: '16d12+80' ac: value: '18' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - climb 40 ft. @@ -5693,10 +5693,10 @@ monsters: type: 'Large dragon, chaotic good' hp: value: '119' - notes: (14d10+42) + notes: '14d10+42' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - climb 40 ft. @@ -5773,10 +5773,10 @@ monsters: type: 'Medium dragon, chaotic good' hp: value: '22' - notes: (4d8+4) + notes: '4d8+4' ac: value: '16' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - climb 30 ft. @@ -5842,10 +5842,10 @@ monsters: type: 'Gargantuan dragon, lawful good' hp: value: '546' - notes: (28d20+252) + notes: '28d20+252' ac: value: '22' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 80 ft. @@ -5959,10 +5959,10 @@ monsters: type: 'Huge dragon, lawful good' hp: value: '256' - notes: (19d12+133) + notes: '19d12+133' ac: value: '19' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 80 ft. @@ -6065,10 +6065,10 @@ monsters: type: 'Large dragon, lawful good' hp: value: '178' - notes: (17d10+85) + notes: '17d10+85' ac: value: '18' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 80 ft. @@ -6146,10 +6146,10 @@ monsters: type: 'Medium dragon, lawful good' hp: value: '60' - notes: (8d8+24) + notes: '8d8+24' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - fly 60 ft. @@ -6214,10 +6214,10 @@ monsters: type: 'Gargantuan dragon, lawful good' hp: value: '487' - notes: (25d20+225) + notes: '25d20+225' ac: value: '22' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 80 ft. @@ -6328,10 +6328,10 @@ monsters: type: 'Huge dragon, lawful good' hp: value: '243' - notes: (18d12+126) + notes: '18d12+126' ac: value: '19' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 80 ft. @@ -6431,10 +6431,10 @@ monsters: type: 'Large dragon, lawful good' hp: value: '168' - notes: (16d10+80) + notes: '16d10+80' ac: value: '18' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 80 ft. @@ -6509,10 +6509,10 @@ monsters: type: 'Medium dragon, lawful good' hp: value: '45' - notes: (6d8+18) + notes: '6d8+18' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - fly 60 ft. @@ -6574,10 +6574,10 @@ monsters: type: 'Gargantuan dragon, neutral' hp: value: '341' - notes: (22d20+10) + notes: '22d20+10' ac: value: '20' - notes: (natural armor) + notes: 'natural armor' speed: - 20 ft. - swim 40 ft. @@ -6645,10 +6645,10 @@ monsters: type: 'Large monstrosity, chaotic evil' hp: value: '123' - notes: (13d10+52) + notes: '13d10+52' ac: value: '19' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - climb 30 ft. @@ -6722,10 +6722,10 @@ monsters: type: 'Medium fey, neutral' hp: value: '22' - notes: (5d8) + notes: '5d8' ac: value: '11' - notes: (16 with barkskin) + notes: '16 with barkskin' speed: - 30 ft. abilities: @@ -6803,7 +6803,7 @@ monsters: type: 'Medium humanoid (dwarf), lawful evil' hp: value: '26' - notes: (4d8+4) + notes: '4d8+4' ac: value: '16' notes: '(scale mail, shield)' @@ -6907,7 +6907,7 @@ monsters: type: 'Large elemental, neutral' hp: value: '90' - notes: (12d10+24) + notes: '12d10+24' ac: value: '15' notes: null @@ -6977,10 +6977,10 @@ monsters: type: 'Large elemental, neutral' hp: value: '126' - notes: (12d10+60) + notes: '12d10+60' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - burrow 30 ft. @@ -7037,7 +7037,7 @@ monsters: type: 'Large elemental, neutral' hp: value: '102' - notes: (12d10+36) + notes: '12d10+36' ac: value: '13' notes: null @@ -7111,10 +7111,10 @@ monsters: type: 'Large elemental, neutral' hp: value: '114' - notes: (12d10+48) + notes: '12d10+48' ac: value: '14' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - swim 90 ft. @@ -7186,10 +7186,10 @@ monsters: type: 'Medium humanoid (elf), neutral evil' hp: value: '13' - notes: (3d8) + notes: '3d8' ac: value: '15' - notes: (chain shirt) + notes: 'chain shirt' speed: - 30 ft. abilities: @@ -7321,10 +7321,10 @@ monsters: type: 'Medium monstrosity, neutral evil' hp: value: '44' - notes: (8d8+8) + notes: '8d8+8' ac: value: '13' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - climb 30 ft. @@ -7402,10 +7402,10 @@ monsters: type: 'Large giant, chaotic evil' hp: value: '85' - notes: (10d10+30) + notes: '10d10+30' ac: value: '12' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. abilities: @@ -7459,7 +7459,7 @@ monsters: type: 'Medium plant, unaligned' hp: value: '13' - notes: (3d8) + notes: '3d8' ac: value: '5' notes: null @@ -7506,7 +7506,7 @@ monsters: type: 'Medium plant, unaligned' hp: value: '18' - notes: (4d8) + notes: '4d8' ac: value: '5' notes: null @@ -7553,10 +7553,10 @@ monsters: type: 'Medium elemental, chaotic evil' hp: value: '52' - notes: (7d8+21) + notes: '7d8+21' ac: value: '15' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - fly 60 ft. @@ -7612,10 +7612,10 @@ monsters: type: 'Large elemental, chaotic good' hp: value: '161' - notes: (14d10+84) + notes: '14d10+84' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - fly 90 ft. @@ -7713,10 +7713,10 @@ monsters: type: 'Large elemental, lawful evil' hp: value: '200' - notes: (16d10+112) + notes: '16d10+112' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 60 ft. @@ -7803,7 +7803,7 @@ monsters: type: 'Medium undead, any alignment' hp: value: '45' - notes: (10d8) + notes: '10d8' ac: value: '11' notes: null @@ -7905,7 +7905,7 @@ monsters: type: 'Medium undead, chaotic evil' hp: value: '36' - notes: (8d8) + notes: '8d8' ac: value: '13' notes: null @@ -7963,7 +7963,7 @@ monsters: type: 'Medium undead, chaotic evil' hp: value: '22' - notes: (5d8) + notes: '5d8' ac: value: '12' notes: null @@ -8011,10 +8011,10 @@ monsters: type: 'Huge giant, neutral good (50%) or neutral evil (50%)' hp: value: '200' - notes: (16d12+96) + notes: '16d12+96' ac: value: '14' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. abilities: @@ -8090,10 +8090,10 @@ monsters: type: 'Huge giant, lawful evil' hp: value: '162' - notes: (13d12+78) + notes: '13d12+78' ac: value: '18' - notes: (plate) + notes: 'plate' speed: - 30 ft. abilities: @@ -8152,10 +8152,10 @@ monsters: type: 'Huge giant, neutral evil' hp: value: '138' - notes: (12d12+60) + notes: '12d12+60' ac: value: '15' - notes: (patchwork armor) + notes: 'patchwork armor' speed: - 40 ft. abilities: @@ -8215,10 +8215,10 @@ monsters: type: 'Huge giant, chaotic evil' hp: value: '105' - notes: (10d12+40) + notes: '10d12+40' ac: value: '13' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. abilities: @@ -8268,10 +8268,10 @@ monsters: type: 'Huge giant, neutral' hp: value: '126' - notes: (11d12+55) + notes: '11d12+55' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. abilities: @@ -8346,10 +8346,10 @@ monsters: type: 'Huge giant, chaotic good' hp: value: '230' - notes: (20d12+100) + notes: '20d12+100' ac: value: '16' - notes: (scale mail) + notes: 'scale mail' speed: - 50 ft. - swim 50 ft. @@ -8425,7 +8425,7 @@ monsters: type: 'Medium aberration, neutral' hp: value: '67' - notes: (9d8+27) + notes: '9d8+27' ac: value: '9' notes: null @@ -8495,7 +8495,7 @@ monsters: type: 'Medium humanoid (gnoll), chaotic evil' hp: value: '22' - notes: (5d8) + notes: '5d8' ac: value: '15' notes: '(hide armor, shield)' @@ -8548,10 +8548,10 @@ monsters: type: 'Small humanoid (gnome), neutral good' hp: value: '16' - notes: (3d6+6) + notes: '3d6+6' ac: value: '15' - notes: (chain shirt) + notes: 'chain shirt' speed: - 20 ft. abilities: @@ -8670,10 +8670,10 @@ monsters: type: 'Large construct, unaligned' hp: value: '133' - notes: (14d10+56) + notes: '14d10+56' ac: value: '14' - notes: (natural armor) + notes: 'natural armor' speed: - 20 ft. abilities: @@ -8753,7 +8753,7 @@ monsters: type: 'Medium construct, neutral' hp: value: '93' - notes: (11d8+44) + notes: '11d8+44' ac: value: '9' notes: null @@ -8836,10 +8836,10 @@ monsters: type: 'Large construct, unaligned' hp: value: '210' - notes: (20d10+100) + notes: '20d10+100' ac: value: '20' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -8911,10 +8911,10 @@ monsters: type: 'Large construct, unaligned' hp: value: '178' - notes: (17d10+85) + notes: '17d10+85' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -8980,10 +8980,10 @@ monsters: type: 'Large monstrosity, unaligned' hp: value: '114' - notes: (12d10+48) + notes: '12d10+48' ac: value: '19' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. abilities: @@ -9040,10 +9040,10 @@ monsters: type: 'Medium monstrosity, neutral' hp: value: '27' - notes: (6d8) + notes: '6d8' ac: value: '14' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - climb 30 ft. @@ -9094,7 +9094,7 @@ monsters: type: 'Large monstrosity, unaligned' hp: value: '59' - notes: (7d10+21) + notes: '7d10+21' ac: value: '12' notes: null @@ -9145,7 +9145,7 @@ monsters: type: 'Medium humanoid (grimlock), neutral evil' hp: value: '11' - notes: (2d8+2) + notes: '2d8+2' ac: value: '11' notes: null @@ -9203,10 +9203,10 @@ monsters: type: 'Medium fey, neutral evil' hp: value: '82' - notes: (11d8+33) + notes: '11d8+33' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -9322,10 +9322,10 @@ monsters: type: 'Medium fiend, neutral evil' hp: value: '112' - notes: (15d8+45) + notes: '15d8+45' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -9461,10 +9461,10 @@ monsters: type: 'Medium fey, chaotic evil' hp: value: '52' - notes: (7d8+21) + notes: '7d8+21' ac: value: '14' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - swim 40 ft. @@ -9569,10 +9569,10 @@ monsters: type: 'Medium humanoid (human), any alignment' hp: value: '65' - notes: (10d8+20) + notes: '10d8+20' ac: value: '18' - notes: (plate) + notes: 'plate' speed: - 30 ft. abilities: @@ -9636,7 +9636,7 @@ monsters: type: 'Medium monstrosity, chaotic evil' hp: value: '38' - notes: (7d8+7) + notes: '7d8+7' ac: value: '11' notes: null @@ -9698,10 +9698,10 @@ monsters: type: 'Medium fiend, lawful evil' hp: value: '45' - notes: (7d8+14) + notes: '7d8+14' ac: value: '15' - notes: (natural armor) + notes: 'natural armor' speed: - 50 ft. abilities: @@ -9754,7 +9754,7 @@ monsters: type: 'Large monstrosity, unaligned' hp: value: '19' - notes: (3d10+3) + notes: '3d10+3' ac: value: '11' notes: null @@ -9806,7 +9806,7 @@ monsters: type: 'Medium humanoid (goblinoid), lawful evil' hp: value: '97' - notes: (13d8+39) + notes: '13d8+39' ac: value: '20' notes: '(plate, shield)' @@ -9884,10 +9884,10 @@ monsters: type: 'Tiny construct, neutral' hp: value: '5' - notes: (2d4) + notes: '2d4' ac: value: '13' - notes: (natural armor) + notes: 'natural armor' speed: - 20 ft. - fly 40 ft. @@ -9935,10 +9935,10 @@ monsters: type: 'Huge monstrosity, unaligned' hp: value: '172' - notes: (15d12+75) + notes: '15d12+75' ac: value: '15' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - swim 30 ft. diff --git a/src/content/monsters/srd-monsters-2.mdx b/src/content/monsters/srd-monsters-2.mdx index 14c61cd..4d4bc17 100644 --- a/src/content/monsters/srd-monsters-2.mdx +++ b/src/content/monsters/srd-monsters-2.mdx @@ -5,7 +5,7 @@ monsters: type: 'Medium elemental, neutral' hp: value: '104' - notes: (16d8+32) + notes: '16d8+32' ac: value: '14' notes: null @@ -72,7 +72,7 @@ monsters: type: 'Small humanoid (kobold), lawful evil' hp: value: '5' - notes: (2d6-2) + notes: '2d6-2' ac: value: '12' notes: null @@ -125,10 +125,10 @@ monsters: type: 'Gargantuan monstrosity (titan), chaotic evil' hp: value: '472' - notes: (27d20+189) + notes: '27d20+189' ac: value: '18' - notes: (natural armor) + notes: 'natural armor' speed: - 20 ft. - swim 60 ft. @@ -241,10 +241,10 @@ monsters: type: 'Large monstrosity, chaotic evil' hp: value: '97' - notes: (13d10+26) + notes: '13d10+26' ac: value: '13' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -306,10 +306,10 @@ monsters: type: 'Medium undead, any evil alignment' hp: value: '135' - notes: (18d8+54) + notes: '18d8+54' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -419,7 +419,7 @@ monsters: type: 'Medium humanoid (lizardfolk), neutral' hp: value: '22' - notes: (4d8+4) + notes: '4d8+4' ac: value: '15' notes: '(natural armor, shield)' @@ -539,7 +539,7 @@ monsters: type: 'Medium humanoid (human, shapechanger), neutral evil' hp: value: '78' - notes: (12d8+24) + notes: '12d8+24' ac: value: '10' notes: '(in humanoid form, 11 in wolf or hybrid form)' @@ -729,7 +729,7 @@ monsters: type: 'Medium humanoid (human, shapechanger), chaotic evil' hp: value: '58' - notes: (9d8+18) + notes: '9d8+18' ac: value: '11' notes: '(in humanoid form, 12 in wolf or hybrid form)' @@ -797,10 +797,10 @@ monsters: type: 'Small elemental, chaotic neutral' hp: value: '9' - notes: (2d6+2) + notes: '2d6+2' ac: value: '14' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -854,10 +854,10 @@ monsters: type: 'Large monstrosity, lawful evil' hp: value: '68' - notes: (8d10+24) + notes: '8d10+24' ac: value: '14' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - fly 50 ft. @@ -909,10 +909,10 @@ monsters: type: 'Medium monstrosity, lawful evil' hp: value: '127' - notes: (17d8+51) + notes: '17d8+51' ac: value: '15' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -986,7 +986,7 @@ monsters: type: 'Small elemental, neutral evil' hp: value: '17' - notes: (5d6) + notes: '5d6' ac: value: '12' notes: null @@ -1058,7 +1058,7 @@ monsters: type: 'Small elemental, neutral evil' hp: value: '21' - notes: (6d6) + notes: '6d6' ac: value: '11' notes: null @@ -1134,7 +1134,7 @@ monsters: type: 'Small elemental, neutral evil' hp: value: '22' - notes: (5d6+5) + notes: '5d6+5' ac: value: '11' notes: null @@ -1207,7 +1207,7 @@ monsters: type: 'Small elemental, neutral evil' hp: value: '21' - notes: (6d6) + notes: '6d6' ac: value: '10' notes: null @@ -1273,7 +1273,7 @@ monsters: type: 'Medium humanoid (merfolk), neutral' hp: value: '11' - notes: (2d8+2) + notes: '2d8+2' ac: value: '11' notes: null @@ -1318,10 +1318,10 @@ monsters: type: 'Large monstrosity, chaotic evil' hp: value: '45' - notes: (6d10+12) + notes: '6d10+12' ac: value: '13' - notes: (natural armor) + notes: 'natural armor' speed: - 10 ft. - swim 40 ft. @@ -1375,10 +1375,10 @@ monsters: type: 'Medium monstrosity (shapechanger), neutral' hp: value: '58' - notes: (9d8+18) + notes: '9d8+18' ac: value: '12' - notes: (natural armor) + notes: 'natural armor' speed: - 15 ft. abilities: @@ -1441,10 +1441,10 @@ monsters: type: 'Large monstrosity, chaotic evil' hp: value: '76' - notes: (9d10+27) + notes: '9d10+27' ac: value: '14' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. abilities: @@ -1500,10 +1500,10 @@ monsters: type: 'Medium undead, lawful evil' hp: value: '58' - notes: (9d8+18) + notes: '9d8+18' ac: value: '11' - notes: (natural armor) + notes: 'natural armor' speed: - 20 ft. abilities: @@ -1566,10 +1566,10 @@ monsters: type: 'Medium undead, lawful evil' hp: value: '97' - notes: (13d8+39) + notes: '13d8+39' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 20 ft. abilities: @@ -1698,10 +1698,10 @@ monsters: type: 'Large monstrosity, lawful good' hp: value: '127' - notes: (15d10+45) + notes: '15d10+45' ac: value: '18' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. abilities: @@ -1777,10 +1777,10 @@ monsters: type: 'Large monstrosity, chaotic evil' hp: value: '75' - notes: (15d10+45) + notes: '15d10+45' ac: value: '15' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. abilities: @@ -1841,10 +1841,10 @@ monsters: type: 'Large fiend, neutral evil' hp: value: '68' - notes: (8d10+24) + notes: '8d10+24' ac: value: '13' - notes: (natural armor) + notes: 'natural armor' speed: - 60 ft. - fly 90 ft. @@ -1894,10 +1894,10 @@ monsters: type: 'Large giant, chaotic evil' hp: value: '59' - notes: (7d10+21) + notes: '7d10+21' ac: value: '11' - notes: (hide armor) + notes: 'hide armor' speed: - 40 ft. abilities: @@ -1939,10 +1939,10 @@ monsters: type: 'Large giant, lawful evil' hp: value: '110' - notes: (13d10+39) + notes: '13d10+39' ac: value: '16' - notes: (chain mail) + notes: 'chain mail' speed: - 30 ft. - fly 30 ft. @@ -2021,7 +2021,7 @@ monsters: type: 'Large ooze, unaligned' hp: value: '85' - notes: (10d10+30) + notes: '10d10+30' ac: value: '7' notes: null @@ -2098,7 +2098,7 @@ monsters: type: 'Large ooze, unaligned' hp: value: '84' - notes: (8d10+40) + notes: '8d10+40' ac: value: '6' notes: null @@ -2173,7 +2173,7 @@ monsters: type: 'Medium ooze, unaligned' hp: value: '22' - notes: (3d8+9) + notes: '3d8+9' ac: value: '8' notes: null @@ -2242,7 +2242,7 @@ monsters: type: 'Large ooze, unaligned' hp: value: '45' - notes: (6d10+12) + notes: '6d10+12' ac: value: '8' notes: null @@ -2305,10 +2305,10 @@ monsters: type: 'Medium humanoid (orc), chaotic evil' hp: value: '15' - notes: (2d8+6) + notes: '2d8+6' ac: value: '13' - notes: (hide armor) + notes: 'hide armor' speed: - 30 ft. abilities: @@ -2355,10 +2355,10 @@ monsters: type: 'Large aberration, neutral' hp: value: '114' - notes: (12d10+48) + notes: '12d10+48' ac: value: '14' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -2426,10 +2426,10 @@ monsters: type: 'Large monstrosity, unaligned' hp: value: '59' - notes: (7d10+21) + notes: '7d10+21' ac: value: '13' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. abilities: @@ -2477,7 +2477,7 @@ monsters: type: 'Large celestial, chaotic good' hp: value: '59' - notes: (7d10+21) + notes: '7d10+21' ac: value: '12' notes: null @@ -2527,7 +2527,7 @@ monsters: type: 'Tiny dragon, neutral good' hp: value: '7' - notes: (2d4+2) + notes: '2d4+2' ac: value: '13' notes: null @@ -2601,10 +2601,10 @@ monsters: type: 'Gargantuan monstrosity, unaligned' hp: value: '247' - notes: (15d20+90) + notes: '15d20+90' ac: value: '18' - notes: (natural armor) + notes: 'natural armor' speed: - 50 ft. - burrow 30 ft. @@ -2667,10 +2667,10 @@ monsters: type: 'Medium fiend, lawful evil' hp: value: '110' - notes: (13d8+52) + notes: '13d8+52' ac: value: '16' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. abilities: @@ -2734,10 +2734,10 @@ monsters: type: 'Huge monstrosity, unaligned' hp: value: '195' - notes: (17d12+85) + notes: '17d12+85' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - burrow 20 ft. @@ -2796,10 +2796,10 @@ monsters: type: 'Gargantuan monstrosity, unaligned' hp: value: '248' - notes: (16d20+80) + notes: '16d20+80' ac: value: '15' - notes: (natural armor) + notes: 'natural armor' speed: - 20 ft. - fly 120 ft. @@ -2854,10 +2854,10 @@ monsters: type: 'Large monstrosity, neutral evil' hp: value: '93' - notes: (11d10+33) + notes: '11d10+33' ac: value: '20' - notes: (natural armor) + notes: 'natural armor' speed: - 10 ft. - climb 10 ft. @@ -2927,10 +2927,10 @@ monsters: type: 'Medium monstrosity, unaligned' hp: value: '27' - notes: (5d8+5) + notes: '5d8+5' ac: value: '14' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. abilities: @@ -2988,10 +2988,10 @@ monsters: type: 'Medium humanoid (sahuagin), lawful evil' hp: value: '22' - notes: (4d8+4) + notes: '4d8+4' ac: value: '12' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - swim 40 ft. @@ -3055,10 +3055,10 @@ monsters: type: 'Large elemental, neutral evil' hp: value: '90' - notes: (12d10+24) + notes: '12d10+24' ac: value: '15' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -3120,10 +3120,10 @@ monsters: type: 'Medium fey, chaotic neutral' hp: value: '31' - notes: (7d8) + notes: '7d8' ac: value: '14' - notes: (leather armor) + notes: 'leather armor' speed: - 40 ft. abilities: @@ -3183,7 +3183,7 @@ monsters: type: 'Medium undead, chaotic evil' hp: value: '16' - notes: (3d8+3) + notes: '3d8+3' ac: value: '12' notes: null @@ -3259,10 +3259,10 @@ monsters: type: 'Large plant, unaligned' hp: value: '136' - notes: (16d10+48) + notes: '16d10+48' ac: value: '15' - notes: (natural armor) + notes: 'natural armor' speed: - 20 ft. - swim 20 ft. @@ -3324,10 +3324,10 @@ monsters: type: 'Large construct, unaligned' hp: value: '142' - notes: (15d10+60) + notes: '15d10+60' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -3399,10 +3399,10 @@ monsters: type: 'Medium undead, lawful evil' hp: value: '13' - notes: (2d8+4) + notes: '2d8+4' ac: value: '13' - notes: (armor scraps) + notes: 'armor scraps' speed: - 30 ft. abilities: @@ -3444,10 +3444,10 @@ monsters: type: 'Large undead, lawful evil' hp: value: '67' - notes: (9d10+18) + notes: '9d10+18' ac: value: '12' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. abilities: @@ -3498,10 +3498,10 @@ monsters: type: 'Large undead, lawful evil' hp: value: '22' - notes: (3d10+6) + notes: '3d10+6' ac: value: '13' - notes: (barding scraps) + notes: 'barding scraps' speed: - 60 ft. abilities: @@ -3540,7 +3540,7 @@ monsters: type: 'Medium undead, chaotic evil' hp: value: '22' - notes: (5d8) + notes: '5d8' ac: value: '12' notes: null @@ -3611,10 +3611,10 @@ monsters: type: 'Large monstrosity, lawful neutral' hp: value: '199' - notes: (19d10+95) + notes: '19d10+95' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 60 ft. @@ -3722,10 +3722,10 @@ monsters: type: 'Large monstrosity, lawful neutral' hp: value: '136' - notes: (16d10+48) + notes: '16d10+48' ac: value: '17' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. - fly 60 ft. @@ -3810,10 +3810,10 @@ monsters: type: 'Tiny fey, neutral good' hp: value: '2' - notes: (1d4) + notes: '1d4' ac: value: '15' - notes: (leather armor) + notes: 'leather armor' speed: - 10 ft. - fly 40 ft. @@ -3874,10 +3874,10 @@ monsters: type: 'Tiny beast, unaligned' hp: value: '2' - notes: (1d4) + notes: '1d4' ac: value: '14' - notes: (natural armor) + notes: 'natural armor' speed: - 10 ft. - fly 40 ft. @@ -3920,10 +3920,10 @@ monsters: type: 'Medium fiend (shapechanger), neutral evil' hp: value: '66' - notes: (12d8+12) + notes: '12d8+12' ac: value: '15' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. - fly 60 ft. @@ -4024,10 +4024,10 @@ monsters: type: 'Gargantuan monstrosity (titan), unaligned' hp: value: '676' - notes: (33d20+330) + notes: '33d20+330' ac: value: '25' - notes: (natural armor) + notes: 'natural armor' speed: - 40 ft. abilities: @@ -4141,10 +4141,10 @@ monsters: type: 'Huge plant, chaotic good' hp: value: '138' - notes: (12d12+60) + notes: '12d12+60' ac: value: '16' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -4207,10 +4207,10 @@ monsters: type: 'Large giant, chaotic evil' hp: value: '84' - notes: (8d10+40) + notes: '8d10+40' ac: value: '15' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -4288,7 +4288,7 @@ monsters: type: 'Large celestial, lawful good' hp: value: '67' - notes: (9d10+18) + notes: '9d10+18' ac: value: '12' notes: null @@ -4380,10 +4380,10 @@ monsters: type: 'Medium undead (shapechanger), lawful evil' hp: value: '144' - notes: (17d8+68) + notes: '17d8+68' ac: value: '16' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -4525,10 +4525,10 @@ monsters: type: 'Medium undead, neutral evil' hp: value: '82' - notes: (11d8+33) + notes: '11d8+33' ac: value: '15' - notes: (natural armor) + notes: 'natural armor' speed: - 30 ft. abilities: @@ -4609,10 +4609,10 @@ monsters: type: 'Medium undead, neutral evil' hp: value: '45' - notes: (6d8+18) + notes: '6d8+18' ac: value: '14' - notes: (studded leather) + notes: 'studded leather' speed: - 30 ft. abilities: @@ -4681,7 +4681,7 @@ monsters: type: 'Tiny undead, chaotic evil' hp: value: '22' - notes: (9d4) + notes: '9d4' ac: value: '19' notes: null @@ -4761,7 +4761,7 @@ monsters: type: 'Medium undead, neutral evil' hp: value: '67' - notes: (9d8+27) + notes: '9d8+27' ac: value: '13' notes: null @@ -4835,10 +4835,10 @@ monsters: type: 'Large dragon, unaligned' hp: value: '110' - notes: (13d10+39) + notes: '13d10+39' ac: value: '13' - notes: (natural armor) + notes: 'natural armor' speed: - 20 ft. - fly 80 ft. @@ -4891,10 +4891,10 @@ monsters: type: 'Medium elemental, neutral' hp: value: '73' - notes: (7d8+42) + notes: '7d8+42' ac: value: '19' - notes: (natural armor) + notes: 'natural armor' speed: - 20 ft. - burrow 20 ft. @@ -4956,7 +4956,7 @@ monsters: type: 'Medium undead, neutral evil' hp: value: '22' - notes: (3d8+9) + notes: '3d8+9' ac: value: '8' notes: null @@ -5004,7 +5004,7 @@ monsters: type: 'Large undead, neutral evil' hp: value: '85' - notes: (9d10+36) + notes: '9d10+36' ac: value: '8' notes: null diff --git a/src/pages/search.js b/src/pages/search.js index bae6270..b470ac9 100644 --- a/src/pages/search.js +++ b/src/pages/search.js @@ -24,7 +24,6 @@ import TextField from '@mui/material/TextField'; import Tooltip from '@mui/material/Tooltip'; import Typography from '@mui/material/Typography'; import { IconButton } from 'gatsby-theme-material-ui'; -// import AddModeratorIcon from '@mui/icons-material/AddModerator'; import Masonry from '@mui/lab/Masonry'; import MarkdownView from 'react-showdown'; import { DiceRoll } from '@dice-roller/rpg-dice-roller'; @@ -95,8 +94,6 @@ function SearchPage({ data, location }) { return ( diff --git a/src/utils/constants.js b/src/utils/constants.js index 6133578..28508b9 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -46,10 +46,6 @@ export const SITE_SHORT_NAME = 'GMCM'; export const SITE_AUTHOR = gvorbeck; export const FOOTER_COPY = `${SITE_NAME} © ${new Date().getFullYear()} `; export const NAVIGATION_DATA = [ - { - title: 'Combat Tracker', - slug: '', - }, { title: 'adventures', slug: '/adventures',