diff --git a/package-lock.json b/package-lock.json
index 9331559..bbd963b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,6 +16,7 @@
"beautiful-react-hooks": "^3.12.2",
"classnames": "^2.3.2",
"cross-env": "^7.0.3",
+ "cyber-dice": "github:blopa/cyber-dice",
"is-mobile": "^3.1.1",
"jest": "^27.5.1",
"phaser": "^3.55.2",
@@ -9422,6 +9423,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/cyber-dice": {
+ "version": "1.0.10",
+ "resolved": "git+ssh://git@github.com/blopa/cyber-dice.git#8809ffc4346c3b9a818a7696b3616dd833e810e0",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ }
+ },
"node_modules/damerau-levenshtein": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
@@ -35739,6 +35749,11 @@
"array-find-index": "^1.0.1"
}
},
+ "cyber-dice": {
+ "version": "git+ssh://git@github.com/blopa/cyber-dice.git#8809ffc4346c3b9a818a7696b3616dd833e810e0",
+ "from": "cyber-dice@github:blopa/cyber-dice",
+ "requires": {}
+ },
"damerau-levenshtein": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
diff --git a/package.json b/package.json
index 39f76ec..38ebe42 100644
--- a/package.json
+++ b/package.json
@@ -38,6 +38,7 @@
"beautiful-react-hooks": "^3.12.2",
"classnames": "^2.3.2",
"cross-env": "^7.0.3",
+ "cyber-dice": "github:blopa/cyber-dice",
"is-mobile": "^3.1.1",
"jest": "^27.5.1",
"phaser": "^3.55.2",
diff --git a/src/components/Battle/Battle.jsx b/src/components/Battle/Battle.jsx
new file mode 100644
index 0000000..ba339d6
--- /dev/null
+++ b/src/components/Battle/Battle.jsx
@@ -0,0 +1,140 @@
+import { useEffect, useRef, useState } from 'react';
+import { FormattedMessage } from 'react-intl';
+import classNames from 'classnames';
+
+// Selectors
+import {
+ selectBattleItems,
+ selectBattleOnHover,
+ selectBattleSetters,
+ selectBattleOnSelect,
+} from '../../zustand/battle/selectBattle';
+
+// Constants
+import {
+ ENTER_KEY,
+ ARROW_UP_KEY,
+ ARROW_DOWN_KEY,
+ ARROW_LEFT_KEY,
+ ARROW_RIGHT_KEY,
+} from '../../constants';
+
+// Utils
+import { getTranslationVariables } from '../../utils/utils';
+
+// Store
+import { useGameStore } from '../../zustand/store';
+
+// Styles
+import styles from './Battle.module.scss';
+
+// Components
+import BattleDiceViewer from '../BattleDiceViewer/BattleDiceViewer';
+
+function Battle() {
+ const battleListRef = useRef();
+
+ // TODO for now only works for four items
+ const battleItems = useGameStore(selectBattleItems);
+
+ const [selectedItemIndex, setSelectedItemIndex] = useState(0);
+ const onSelected = useGameStore(selectBattleOnSelect);
+ const onHover = useGameStore(selectBattleOnHover);
+ const { setBattleItemsListDom } = useGameStore(selectBattleSetters);
+
+ useEffect(() => {
+ setBattleItemsListDom(battleListRef.current);
+ }, [battleListRef, setBattleItemsListDom]);
+
+ useEffect(() => {
+ onHover?.(selectedItemIndex);
+ }, [onHover, selectedItemIndex]);
+
+ useEffect(() => {
+ const handleKeyPressed = (e) => {
+ switch (e.code) {
+ case ENTER_KEY: {
+ onSelected(battleItems[selectedItemIndex], selectedItemIndex);
+ break;
+ }
+
+ case ARROW_UP_KEY: {
+ const increment = selectedItemIndex === 1 ? 1 : -2;
+ setSelectedItemIndex(
+ Math.max(0, selectedItemIndex + increment)
+ );
+
+ break;
+ }
+
+ case ARROW_DOWN_KEY: {
+ const increment = selectedItemIndex === battleItems.length / 2 ? -1 : 2;
+ setSelectedItemIndex(
+ Math.min(3, selectedItemIndex + increment)
+ );
+
+ break;
+ }
+
+ case ARROW_LEFT_KEY: {
+ setSelectedItemIndex(
+ Math.max(0, selectedItemIndex - 1)
+ );
+
+ break;
+ }
+
+ case ARROW_RIGHT_KEY: {
+ setSelectedItemIndex(
+ Math.min(3, selectedItemIndex + 1)
+ );
+
+ break;
+ }
+
+ default: {
+ break;
+ }
+ }
+ };
+
+ window.addEventListener('keydown', handleKeyPressed);
+
+ return () => window.removeEventListener('keydown', handleKeyPressed);
+ }, [battleItems, onSelected, selectedItemIndex]);
+
+ return (
+
+
+
+ {battleItems.map((item, index) => {
+ const [key, variables] = getTranslationVariables(item);
+
+ return (
+ // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
+ - {
+ setSelectedItemIndex(index);
+ }}
+ onClick={() => {
+ onSelected?.(item, index);
+ }}
+ >
+
+
+ );
+ })}
+
+
+ );
+}
+
+export default Battle;
diff --git a/src/components/Battle/Battle.module.scss b/src/components/Battle/Battle.module.scss
new file mode 100644
index 0000000..7c0e29e
--- /dev/null
+++ b/src/components/Battle/Battle.module.scss
@@ -0,0 +1,44 @@
+.battle-wrapper {
+ height: 100%;
+
+ &.paused {
+ background-color: rgb(0 0 0 / 70%);
+ }
+}
+
+.battle-items-wrapper {
+ user-select: none;
+ user-drag: none;
+ position: absolute;
+ font-size: calc(var(--game-zoom) * 10px);
+ list-style: none;
+ image-rendering: pixelated;
+ font-family: "Press Start 2P", serif;
+ text-transform: uppercase;
+ display: flex;
+ flex-wrap: wrap;
+ margin: 0;
+ padding: 0;
+ bottom: 0;
+ background-color: #83a37d;
+ border: calc(var(--game-zoom) * 1px) solid #53814b;
+ outline-offset: calc(var(--game-zoom) * -1px);
+ justify-content: center;
+}
+
+.battle-item {
+ cursor: pointer;
+ padding: 3% 0;
+ margin: 0.22%;
+ text-align: center;
+ border: calc(var(--game-zoom) * 1px) solid #000000;
+ min-width: calc(((var(--game-width) * var(--game-zoom) / 2) - (var(--game-zoom) * 2) - (var(--game-width) * var(--game-zoom) * 0.008)) * 1px);
+
+ &.fewer-items {
+ width: calc(((var(--game-width) * var(--game-zoom)) - (var(--game-zom) * 2)) * 1px);
+ }
+
+ &.selected-battle-item {
+ background-color: #53814b;
+ }
+}
diff --git a/src/components/BattleDice/BattleDice.jsx b/src/components/BattleDice/BattleDice.jsx
new file mode 100644
index 0000000..6098962
--- /dev/null
+++ b/src/components/BattleDice/BattleDice.jsx
@@ -0,0 +1,33 @@
+import { useMemo, useState } from 'react';
+import { DiceWithAnimation } from 'cyber-dice';
+
+// Store
+import { useGameStore } from '../../zustand/store';
+
+// Selectors
+import { selectGameZoom } from '../../zustand/game/selectGameData';
+
+function BattleDice() {
+ const gameZoom = useGameStore(selectGameZoom);
+
+ const [shouldAnimateDice, setShouldAnimateDice] = useState(true);
+ const [randomNumber, setRandomNumber] = useState(Math.floor(Math.random() * 6) + 1);
+ const diceSize = useMemo(() => 80 * gameZoom, [gameZoom]);
+
+ const animationEndHandler = () => {
+ setShouldAnimateDice(false);
+ console.log(randomNumber);
+ };
+
+ return (
+
+ );
+}
+
+export default BattleDice;
diff --git a/src/components/BattleDice/BattleDice.module.scss b/src/components/BattleDice/BattleDice.module.scss
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/BattleDiceViewer/BattleDiceViewer.jsx b/src/components/BattleDiceViewer/BattleDiceViewer.jsx
new file mode 100644
index 0000000..2c98e5b
--- /dev/null
+++ b/src/components/BattleDiceViewer/BattleDiceViewer.jsx
@@ -0,0 +1,80 @@
+import { useMemo } from 'react';
+import { Dice } from 'cyber-dice';
+
+// Styles
+import styles from './BattleDiceViewer.module.scss';
+
+// Store
+import { useGameStore } from '../../zustand/store';
+
+// Selectors
+import { selectGameHeight, selectGameZoom } from '../../zustand/game/selectGameData';
+import { selectHeroEquipedInventoryDice } from '../../zustand/hero/selectHeroData';
+import { selectBattleHoveredItem, selectBattleItemsListDOM } from '../../zustand/battle/selectBattle';
+
+function BattleDiceViewer() {
+ const equipedDice = useGameStore(selectHeroEquipedInventoryDice);
+ const itemsListDOM = useGameStore(selectBattleItemsListDOM);
+ const hoveredItem = useGameStore(selectBattleHoveredItem);
+ const gameHeight = useGameStore(selectGameHeight);
+ const gameZoom = useGameStore(selectGameZoom);
+ const availableScreenHeight = useMemo(
+ // eslint-disable-next-line no-unsafe-optional-chaining
+ () => gameHeight - (itemsListDOM?.offsetHeight || 0) / gameZoom,
+ [gameZoom, gameHeight, itemsListDOM?.offsetHeight]
+ );
+
+ const baseDiceSize = useMemo(
+ () => Math.min((availableScreenHeight / 5), 40), [availableScreenHeight]
+ );
+ const diceSize = useMemo(() => baseDiceSize * gameZoom, [gameZoom, baseDiceSize]);
+ const diceMargin = useMemo(() => (diceSize * 1.25), [diceSize]);
+
+ if (equipedDice.length === 0 || hoveredItem === null || hoveredItem === 3) {
+ return null;
+ }
+
+ const { faces: diceFaces } = equipedDice[hoveredItem];
+ return (
+
+
+ {diceFaces.map((faceNumber, index) => (
+ - 3 && {
+ marginLeft: `${diceMargin * (index - 2)}px`,
+ marginTop: `${diceMargin}px`,
+ },
+ }}
+ >
+
+
+ ))}
+
+
+ );
+}
+
+export default BattleDiceViewer;
diff --git a/src/components/BattleDiceViewer/BattleDiceViewer.module.scss b/src/components/BattleDiceViewer/BattleDiceViewer.module.scss
new file mode 100644
index 0000000..1647b42
--- /dev/null
+++ b/src/components/BattleDiceViewer/BattleDiceViewer.module.scss
@@ -0,0 +1,18 @@
+.dice-faces-list-wrapper {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ padding-inline-start: 0;
+ position: absolute;
+ left: 55%;
+ transform: translateX(-25%);
+ width: 100%;
+}
+
+.dice-faces-wrapper {
+ padding: 0;
+}
+
+.face {
+ position: absolute;
+}
\ No newline at end of file
diff --git a/src/components/ReactWrapper.jsx b/src/components/ReactWrapper.jsx
index afa6d91..77de9b6 100644
--- a/src/components/ReactWrapper.jsx
+++ b/src/components/ReactWrapper.jsx
@@ -14,10 +14,12 @@ import useMutationObserver from '../hooks/useMutationObserver';
import DialogBox from './DialogBox/DialogBox';
import GameMenu from './GameMenu/GameMenu';
import GameText from './GameText/GameText';
+import Battle from './Battle/Battle';
// Selectors
import { selectGameCanvasElement } from '../zustand/game/selectGameData';
import { selectDialogMessages } from '../zustand/dialog/selectDialog';
+import { selectBattleItems } from '../zustand/battle/selectBattle';
import { selectMenuItems } from '../zustand/menu/selectMenu';
import { selectTexts } from '../zustand/text/selectText';
@@ -25,6 +27,7 @@ function ReactWrapper() {
const canvas = useGameStore(selectGameCanvasElement);
const dialogMessages = useGameStore(selectDialogMessages);
const menuItems = useGameStore(selectMenuItems);
+ const battleItems = useGameStore(selectBattleItems);
const gameTexts = useGameStore(selectTexts);
// const s = useGameStore((store) => store);
// console.log(s);
@@ -76,6 +79,9 @@ function ReactWrapper() {
style={inlineStyles}
// onClick={handleWrapperClicked}
>
+ {battleItems.length > 0 && (
+
+ )}
0} />
{menuItems.length > 0 && (
diff --git a/src/constants.js b/src/constants.js
index 90411dc..ff71a5e 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -43,6 +43,24 @@ export const ARROW_UP_KEY = 'ArrowUp';
export const ARROW_RIGHT_KEY = 'ArrowRight';
export const ARROW_DOWN_KEY = 'ArrowDown';
+// Battle
+// export const MELEE_ITEM_INDEX = 0;
+// export const MAGIC_ITEM_INDEX = 1;
+// export const DEFEND_ITEM_INDEX = 2;
+// export const RUN_ITEM_INDEX = 3;
+export const ROCK_BATTLE_ITEM = 'rock';
+export const PAPER_BATTLE_ITEM = 'paper';
+export const SCISSORS_BATTLE_ITEM = 'scissors';
+
+export const ATTACK_BATTLE_ITEM = 'attack';
+export const ITEMS_BATTLE_ITEM = 'items';
+export const DEFENSE_BATTLE_ITEM = 'defense';
+export const RUN_BATTLE_ITEM = 'run';
+export const DICE_1_BATTLE_ITEM = 'dice_1';
+export const DICE_2_BATTLE_ITEM = 'dice_2';
+export const DICE_3_BATTLE_ITEM = 'dice_3';
+export const RETURN_BATTLE_ITEM = 'return';
+
// DOM identifiers
export const GAME_CONTENT_ID = 'game-content';
diff --git a/src/game/scenes/BattleScene.js b/src/game/scenes/BattleScene.js
new file mode 100644
index 0000000..7ec3f8e
--- /dev/null
+++ b/src/game/scenes/BattleScene.js
@@ -0,0 +1,41 @@
+// Utils
+import { getSelectorData } from '../../utils/utils';
+
+// Selectors
+import { selectGameSetters, selectGameWidth } from '../../zustand/game/selectGameData';
+import { selectBattleEnemies } from '../../zustand/battle/selectBattle';
+
+export const scene = {};
+
+export const key = 'BattleScene';
+
+export function create() {
+ const { addGameCameraSizeUpdateCallback } = getSelectorData(selectGameSetters);
+ const backgroundImage = scene.add.image(0, 0, 'background_grass').setOrigin(0, 0);
+ const gameWidth = getSelectorData(selectGameWidth);
+ backgroundImage.setScale(gameWidth / backgroundImage.width);
+
+ addGameCameraSizeUpdateCallback(() => {
+ const gameWidth = getSelectorData(selectGameWidth);
+ backgroundImage.setScale(gameWidth / backgroundImage.width);
+ });
+
+ const enemies = getSelectorData(selectBattleEnemies);
+ enemies.forEach(({ sprite, position }) => {
+ // TODO do this https://medium.com/@junhongwang/sprite-outline-with-phaser-3-9c17190b04bc
+ // const outline = scene.add.image(position.x, position.y, sprite)
+ // .setScale(3.5)
+ // .setTintFill(0x85F9DC)
+ // .setVisible(false);
+ const enemy = scene.add.image(position.x, position.y, sprite).setScale(3);
+ // enemy.outline = outline;
+ // enemy.setInteractive();
+ // enemy.on('pointerover', () => {
+ // enemy.outline.setVisible(true);
+ // });
+ // enemy.on('pointerout', () => {
+ // enemy.outline.setVisible(false);
+ // });
+ enemies.push(enemy);
+ });
+}
diff --git a/src/utils/sceneHelpers.js b/src/utils/sceneHelpers.js
index 26c8b0e..d33b478 100644
--- a/src/utils/sceneHelpers.js
+++ b/src/utils/sceneHelpers.js
@@ -16,11 +16,22 @@ import {
DOWN_DIRECTION,
RIGHT_DIRECTION,
KEY_SPRITE_NAME,
+ RUN_BATTLE_ITEM,
HERO_SPRITE_NAME,
COIN_SPRITE_NAME,
+ ROCK_BATTLE_ITEM,
ENEMY_SPRITE_NAME,
+ PAPER_BATTLE_ITEM,
+ ITEMS_BATTLE_ITEM,
HEART_SPRITE_NAME,
+ RETURN_BATTLE_ITEM,
+ DICE_1_BATTLE_ITEM,
+ DICE_2_BATTLE_ITEM,
+ DICE_3_BATTLE_ITEM,
+ ATTACK_BATTLE_ITEM,
+ DEFENSE_BATTLE_ITEM,
CRYSTAL_SPRITE_NAME,
+ SCISSORS_BATTLE_ITEM,
IDLE_FRAME_POSITION_KEY,
} from '../constants';
@@ -33,6 +44,7 @@ import {
} from './utils';
// Selectors
+import { selectBattleSetters } from '../zustand/battle/selectBattle';
import { selectDialogMessages, selectDialogSetters } from '../zustand/dialog/selectDialog';
import { selectMapKey, selectTilesets, selectMapSetters } from '../zustand/map/selectMapData';
import {
@@ -303,6 +315,122 @@ export const handleObjectsLayer = (scene) => {
}]);
});
+ enemy.on('pointerdown', () => {
+ scene.scene.moveBelow('GameScene', 'BattleScene');
+ scene.scene.pause('GameScene');
+ scene.scene.launch('BattleScene');
+
+ const {
+ setBattleItems,
+ setBattleEnemies,
+ setBattleOnHover,
+ setBattleOnSelect,
+ setBattleHoveredItem,
+ } = getSelectorData(selectBattleSetters);
+
+ const {
+ addHeroInventoryDice,
+ } = getSelectorData(selectHeroSetters);
+
+ setBattleItems([
+ ATTACK_BATTLE_ITEM,
+ ITEMS_BATTLE_ITEM,
+ DEFENSE_BATTLE_ITEM,
+ RUN_BATTLE_ITEM,
+ ]);
+
+ setBattleEnemies([
+ {
+ sprite: 'enemy_01',
+ position: { x: 200, y: 140 },
+ types: [ROCK_BATTLE_ITEM],
+ health: 100,
+ attack: 10,
+ },
+ {
+ sprite: 'enemy_02',
+ position: { x: 300, y: 140 },
+ types: [PAPER_BATTLE_ITEM],
+ health: 100,
+ attack: 10,
+ },
+ {
+ sprite: 'enemy_03',
+ position: { x: 400, y: 160 },
+ types: [SCISSORS_BATTLE_ITEM],
+ health: 100,
+ attack: 10,
+ },
+ ]);
+
+ setBattleOnSelect((item, itemIndex) => {
+ switch (item) {
+ case ATTACK_BATTLE_ITEM: {
+ const items = [
+ DICE_1_BATTLE_ITEM,
+ DICE_2_BATTLE_ITEM,
+ DICE_3_BATTLE_ITEM,
+ RETURN_BATTLE_ITEM,
+ ];
+
+ setBattleItems(items);
+ setBattleOnHover((itemIndex) => {
+ setBattleHoveredItem(itemIndex);
+ });
+
+ [
+ {
+ equiped: true,
+ faces: [1, 2, 3, 4, 5, 6],
+ },
+ {
+ equiped: true,
+ faces: [2, 2, 2, 2, 2, 2],
+ },
+ {
+ equiped: true,
+ faces: [3, 3, 3, 3, 3, 3],
+ },
+ ].forEach((dice) => {
+ addHeroInventoryDice(dice);
+ });
+
+ setBattleOnSelect((item, itemIndex) => {
+ switch (item) {
+ case DICE_1_BATTLE_ITEM: {
+ break;
+ }
+ case DICE_2_BATTLE_ITEM: {
+ break;
+ }
+ case DICE_3_BATTLE_ITEM: {
+ break;
+ }
+ case RETURN_BATTLE_ITEM:
+ default: {
+ break;
+ }
+ }
+ });
+
+ break;
+ }
+ case ITEMS_BATTLE_ITEM: {
+ break;
+ }
+ case DEFENSE_BATTLE_ITEM: {
+ break;
+ }
+ case RUN_BATTLE_ITEM:
+ default: {
+ break;
+ }
+ }
+
+ // setBattleItems([]);
+ });
+ });
+
const enemyActionHeroCollider = scene.physics.add.overlap(
enemy,
scene.heroSprite.actionCollider,
diff --git a/src/zustand/battle/selectBattle.js b/src/zustand/battle/selectBattle.js
new file mode 100644
index 0000000..91c6e34
--- /dev/null
+++ b/src/zustand/battle/selectBattle.js
@@ -0,0 +1,23 @@
+export const selectBattleItems = (state) => state.battle.items;
+
+export const selectBattleEnemies = (state) => state.battle.enemies;
+
+export const selectBattleSkills = (state) => state.battle.skills;
+
+export const selectBattleOnSelect = (state) => state.battle.onSelect;
+
+export const selectBattleOnHover = (state) => state.battle.onHover;
+
+export const selectBattleItemsListDOM = (state) => state.battle.itemsListDOM;
+
+export const selectBattlePickedItem = (state) => state.battle.pickedItem;
+
+export const selectBattleHoveredItem = (state) => state.battle.hoveredItem;
+
+export const selectBattleEnemiesPickedItem = (state) => state.battle.enemiesPickedItem;
+
+export const selectBattleAttackDice = (state) => state.battle.attackDice;
+
+export const selectBattleDefenseDice = (state) => state.battle.defenseDice;
+
+export const selectBattleSetters = (state) => state.battle.setters;
diff --git a/src/zustand/battle/setBattle.js b/src/zustand/battle/setBattle.js
new file mode 100644
index 0000000..646f3e4
--- /dev/null
+++ b/src/zustand/battle/setBattle.js
@@ -0,0 +1,74 @@
+export default (set) => ({
+ setBattleItems: (items) =>
+ set((state) => ({
+ ...state,
+ battle: {
+ ...state.battle,
+ items,
+ },
+ })),
+ setBattlePickedItem: (pickedItem) =>
+ set((state) => ({
+ ...state,
+ battle: {
+ ...state.battle,
+ pickedItem,
+ },
+ })),
+ setBattleHoveredItem: (hoveredItem) =>
+ set((state) => ({
+ ...state,
+ battle: {
+ ...state.battle,
+ hoveredItem,
+ },
+ })),
+ setBattleEnemiesPickedItem: (enemiesPickedItem) =>
+ set((state) => ({
+ ...state,
+ battle: {
+ ...state.battle,
+ enemiesPickedItem,
+ },
+ })),
+ setBattleEnemies: (enemies) =>
+ set((state) => ({
+ ...state,
+ battle: {
+ ...state.battle,
+ enemies,
+ },
+ })),
+ setBattleSkills: (skills) =>
+ set((state) => ({
+ ...state,
+ battle: {
+ ...state.battle,
+ skills,
+ },
+ })),
+ setBattleOnSelect: (onSelect) =>
+ set((state) => ({
+ ...state,
+ battle: {
+ ...state.battle,
+ onSelect,
+ },
+ })),
+ setBattleOnHover: (onHover) =>
+ set((state) => ({
+ ...state,
+ battle: {
+ ...state.battle,
+ onHover,
+ },
+ })),
+ setBattleItemsListDom: (itemsListDOM) =>
+ set((state) => ({
+ ...state,
+ battle: {
+ ...state.battle,
+ itemsListDOM,
+ },
+ })),
+});
diff --git a/src/zustand/store.js b/src/zustand/store.js
index 81b4d2c..b30d549 100644
--- a/src/zustand/store.js
+++ b/src/zustand/store.js
@@ -8,6 +8,7 @@ import setLoadedAssets from './assets/setLoadedAssets';
import setGameData from './game/setGameData';
import setHeroData from './hero/setHeroData';
import setDialog from './dialog/setDialog';
+import setBattle from './battle/setBattle';
import setMapData from './map/setMapData';
import setMenu from './menu/setMenu';
import setText from './text/setText';
@@ -51,6 +52,19 @@ const store = createStore((set) => ({
characterName: '',
setters: setDialog(set),
},
+ battle: {
+ items: [],
+ enemies: [],
+ skills: [],
+ onSelect: null,
+ onHover: null,
+ pickedItem: null,
+ hoveredItem: null,
+ enemiesPickedItem: null,
+ attackDice: [],
+ defenseDice: [],
+ setters: setBattle(set),
+ },
menu: {
items: [],
position: 'center',