Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4787f7a
added monster attacks
MrDeadCe11 Jul 31, 2024
43c9c68
adjusted combat test to test for bob winning or monster winning
MrDeadCe11 Jul 31, 2024
f55842c
missing files
MrDeadCe11 Jul 31, 2024
a2d3de6
trimmed extra calcs
MrDeadCe11 Jul 31, 2024
ef24776
Merge branch 'main' into more-combat-outcomes
ECWireless Aug 1, 2024
54c18c1
fixed respawn and defender action outcome.
MrDeadCe11 Aug 2, 2024
8094e0b
Merge branch 'more-combat-outcomes' of https://github.com/raid-guild/…
MrDeadCe11 Aug 2, 2024
77d852e
trimmed down rng function
MrDeadCe11 Aug 3, 2024
5fd768e
Merge branch 'main' into more-combat-outcomes
ECWireless Aug 5, 2024
bb9a822
New contract out files
ECWireless Aug 5, 2024
e14732e
Increment turn with each action
ECWireless Aug 5, 2024
125e916
some fixes to weapon ids etc
MrDeadCe11 Aug 5, 2024
3c6a4bb
some more combat tweaks
MrDeadCe11 Aug 5, 2024
1c79600
Render monster actions to the ActionsPanel
ECWireless Aug 6, 2024
793fb47
Merge branch 'monster-attacking-tweaks' into feat/add-monster-attack-ui
ECWireless Aug 6, 2024
e79163a
fix to match not ending if monster kills player
MrDeadCe11 Aug 6, 2024
2c77173
New contract out files
ECWireless Aug 6, 2024
ae45c31
Merge branch 'monster-attacking-tweaks' into feat/add-monster-attack-ui
ECWireless Aug 6, 2024
2767166
Merge branch 'main' into feat/add-monster-attack-ui
ECWireless Aug 6, 2024
90f958d
Have user character flicker when hit
ECWireless Aug 7, 2024
07f284d
Fix battle outcome result
ECWireless Aug 7, 2024
5910dea
Only continue to combat outcome after final action
ECWireless Aug 7, 2024
2a54775
Don't show monsters if not spawned
ECWireless Aug 7, 2024
4a7e20d
Deploy to Base Sepolia
ECWireless Aug 7, 2024
2c6b501
Merge pull request #102 from raid-guild/feat/add-monster-attack-ui
ECWireless Aug 7, 2024
464b40e
Merge pull request #100 from raid-guild/monster-attacking-tweaks
ECWireless Aug 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions packages/client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,22 @@ import { BrowserRouter as Router, useLocation } from 'react-router-dom';
import { Footer } from './components/Footer';
import { Header } from './components/Header';
import { WalletDetailsModal } from './components/WalletDetailsModal';
import { MapNavigationProvider } from './contexts/MapNavigationContext';
import { BattleProvider } from './contexts/BattleContext';
import { MapProvider } from './contexts/MapContext';
import { MovementProvider } from './contexts/MovementContext';
import { useMUD } from './contexts/MUDContext';
import AppRoutes, { HOME_PATH } from './Routes';

export const App = (): JSX.Element => {
return (
<Router>
<MapNavigationProvider>
<AppInner />
</MapNavigationProvider>
<MapProvider>
<BattleProvider>
<MovementProvider>
<AppInner />
</MovementProvider>
</BattleProvider>
</MapProvider>
</Router>
);
};
Expand Down
128 changes: 100 additions & 28 deletions packages/client/src/components/ActionsPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,39 @@
import { Box, Button, HStack, Stack, Text, VStack } from '@chakra-ui/react';
import {
Box,
Button,
Divider,
HStack,
Stack,
Text,
VStack,
} from '@chakra-ui/react';
import { useEffect, useMemo, useRef } from 'react';
import { Link } from 'react-router-dom';
// eslint-disable-next-line import/no-named-as-default
import Typist from 'react-typist';

import { useBattle } from '../contexts/BattleContext';
import { useCharacter } from '../contexts/CharacterContext';
import { useMapNavigation } from '../contexts/MapNavigationContext';
import { useMap } from '../contexts/MapContext';
import { useMovement } from '../contexts/MovementContext';

export const ActionsPanel = (): JSX.Element => {
const {
isRefreshing: isRefreshingCharacter,
character,
equippedWeapons,
} = useCharacter();
const { aliveMonsters, isSpawned, position } = useMap();
const {
actionOutcomes,
aliveMonsters,
currentBattle,
isAttacking,
isRefreshing: isRefreshingMap,
isSpawned,
lastestBattleOutcome,
monsterOponent,
onAttack,
position,
} = useMapNavigation();
onContinueToBattleOutcome,
} = useBattle();
const { isRefreshing: isRefreshingMap } = useMovement();

const parentDivRef = useRef<HTMLDivElement>(null);

Expand All @@ -36,6 +46,11 @@ export const ActionsPanel = (): JSX.Element => {
}
}, [actionOutcomes]);

const battleOver = useMemo(
() => currentBattle?.encounterId === lastestBattleOutcome?.encounterId,
[currentBattle, lastestBattleOutcome],
);

const actionText = useMemo(() => {
if (isRefreshingCharacter || isRefreshingMap) return '';

Expand Down Expand Up @@ -80,6 +95,7 @@ export const ActionsPanel = (): JSX.Element => {
<Typist
avgTypingDelay={10}
cursor={{ show: false }}
startDelay={500}
stdTypingDelay={10}
>
<Text size={{ base: 'xs', sm: 'sm', lg: 'md' }}>
Expand Down Expand Up @@ -122,7 +138,7 @@ export const ActionsPanel = (): JSX.Element => {

return (
<Box maxH="100%" overflowY="auto" pb={4} ref={parentDivRef}>
{currentBattle && equippedWeapons && monsterOponent && (
{!battleOver && currentBattle && equippedWeapons && monsterOponent && (
<VStack bgColor="white" position="sticky" spacing={0} top={0} w="100%">
<Text p={{ base: 2, lg: 4 }} size="xs" textAlign="center">
Choose your move:
Expand Down Expand Up @@ -176,19 +192,32 @@ export const ActionsPanel = (): JSX.Element => {
key={`battle-action-${i}`}
stdTypingDelay={10}
>
<Text
key={`battle-action-${i}`}
size={{ base: 'xs', sm: 'sm', lg: 'md' }}
>
You missed{' '}
<Text as="span" color="green">
{monsterOponent.name}
{action.attackerId === character?.characterId ? (
<Text
key={`battle-action-${i}`}
size={{ base: 'xs', sm: 'sm', lg: 'md' }}
>
You missed{' '}
<Text as="span" color="green">
{monsterOponent.name}
</Text>
.
</Text>
.
</Text>
) : (
<Text
key={`battle-action-${i}`}
size={{ base: 'xs', sm: 'sm', lg: 'md' }}
>
<Text as="span" color="green">
{monsterOponent.name}
</Text>{' '}
missed you.
</Text>
)}
</Typist>
);
}

const critText = action.crit ? 'Critical hit! ' : '';

return (
Expand All @@ -198,21 +227,64 @@ export const ActionsPanel = (): JSX.Element => {
key={`battle-action-${i}`}
stdTypingDelay={10}
>
<Text size={{ base: 'xs', sm: 'sm', lg: 'md' }}>
{critText}You attacked{' '}
<Text as="span" color="green">
{monsterOponent?.name}
</Text>{' '}
for{' '}
<Text as="span" color="red">
{action.attackerDamageDelt}
</Text>{' '}
damage.
</Text>
{action.attackerId === character?.characterId ? (
<Text size={{ base: 'xs', sm: 'sm', lg: 'md' }}>
{critText}You attacked{' '}
<Text as="span" color="green">
{monsterOponent?.name}
</Text>{' '}
for{' '}
<Text as="span" color="red">
{action.attackerDamageDelt}
</Text>{' '}
damage.
</Text>
) : (
<Text size={{ base: 'xs', sm: 'sm', lg: 'md' }}>
{critText}
<Text as="span" color="green">
{monsterOponent?.name}
</Text>{' '}
attacked you for{' '}
<Text as="span" color="red">
{action.attackerDamageDelt}
</Text>{' '}
damage.
</Text>
)}
</Typist>
);
})}
</Stack>
{battleOver && currentBattle && (
<Stack my={4} spacing={4}>
<Divider />
<Typist
avgTypingDelay={10}
cursor={{ show: false }}
stdTypingDelay={10}
>
<Text
fontWeight="bold"
size={{ base: 'xs', sm: 'sm', lg: 'md' }}
textAlign="center"
>
{lastestBattleOutcome?.winner === character?.characterId
? 'You won!'
: 'You lost...'}
</Text>
</Typist>
<HStack justifyContent="center">
<Button
onClick={() => onContinueToBattleOutcome(true)}
size="sm"
variant="outline"
>
View Results
</Button>
</HStack>
</Stack>
)}
</Box>
);
};
11 changes: 7 additions & 4 deletions packages/client/src/components/BattleOutcomeModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ import { encodeEntity } from '@latticexyz/store-sync/recs';
import { useCallback, useMemo } from 'react';
import { Link } from 'react-router-dom';

import { useBattle } from '../contexts/BattleContext';
import { useCharacter } from '../contexts/CharacterContext';
import { useMapNavigation } from '../contexts/MapNavigationContext';
import { useMap } from '../contexts/MapContext';
import { useMUD } from '../contexts/MUDContext';
import { BATTLE_OUTCOME_SEEN_KEY } from '../utils/constants';
import { type CombatOutcomeType } from '../utils/types';
Expand All @@ -38,7 +39,8 @@ export const BattleOutcomeModal: React.FC<BattleOutcomeModalProps> = ({
components: { Levels },
} = useMUD();
const { character } = useCharacter();
const { allMonsters, otherCharactersOnTile } = useMapNavigation();
const { allMonsters, otherCharactersOnTile } = useMap();
const { onContinueToBattleOutcome } = useBattle();

const opponent = useMemo(() => {
if (!character) return null;
Expand Down Expand Up @@ -66,8 +68,9 @@ export const BattleOutcomeModal: React.FC<BattleOutcomeModalProps> = ({

const onAcknowledge = useCallback(() => {
localStorage.setItem(BATTLE_OUTCOME_SEEN_KEY, battleOutcome.encounterId);
onContinueToBattleOutcome(false);
onClose();
}, [battleOutcome.encounterId, onClose]);
}, [battleOutcome.encounterId, onContinueToBattleOutcome, onClose]);

const nextLevelXpRequirement =
useComponentValue(
Expand All @@ -90,7 +93,7 @@ export const BattleOutcomeModal: React.FC<BattleOutcomeModalProps> = ({
const { expDropped, goldDropped, itemsDropped, winner } = battleOutcome;

return (
<Modal isOpen={isOpen} onClose={onClose}>
<Modal isOpen={isOpen} onClose={onAcknowledge}>
<ModalOverlay />
<ModalContent>
<ModalHeader textAlign="center">
Expand Down
20 changes: 16 additions & 4 deletions packages/client/src/components/HealthBar.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
import { Box, Flex, StackProps, Text, VStack } from '@chakra-ui/react';

export const HealthBar = ({
currentHp,
baseHp,
currentHp,
level,
...stackProps
}: {
currentHp: string;
baseHp: string;
currentHp: string;
level?: string;
} & StackProps): JSX.Element => {
const health = (parseInt(currentHp) / parseInt(baseHp)) * 100;
const currentHpWithFloor = parseInt(currentHp) < 0 ? 0 : parseInt(currentHp);
const health = (currentHpWithFloor / parseInt(baseHp)) * 100;

const barColor = health > 50 ? 'green' : health > 15 ? 'yellow' : 'red';

return (
<VStack alignItems="end" spacing={0.5} {...stackProps}>
{level && (
<Text
alignSelf="start"
fontWeight="bold"
size={{ base: '3xs', md: '2xs' }}
>
Lvl {level}
</Text>
)}
<Flex
border="2px solid black"
width="100%"
Expand All @@ -38,7 +50,7 @@ export const HealthBar = ({
</Box>
</Flex>
<Text fontWeight={700} size={{ base: '2xs', md: 'xs' }}>
{currentHp} / {baseHp}
{currentHpWithFloor} / {baseHp}
</Text>
</VStack>
);
Expand Down
5 changes: 4 additions & 1 deletion packages/client/src/components/LevelingPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,9 @@ export const LevelingPanel = ({
renderWarning,
]);

const currentHpWithFloor =
parseInt(character.currentHp) < 0 ? 0 : parseInt(character.currentHp);

return (
<VStack>
<HStack justify="space-between" w="100%">
Expand All @@ -223,7 +226,7 @@ export const LevelingPanel = ({
<HStack justify="space-between" w="100%">
<Text>HP - Hit Points</Text>
<Text>
{character.currentHp}/{character.baseHp}
{currentHpWithFloor}/{character.baseHp}
</Text>
</HStack>

Expand Down
18 changes: 7 additions & 11 deletions packages/client/src/components/MapPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,20 @@ import {
} from 'react-icons/io';
import { TbDirectionArrows } from 'react-icons/tb';

import { useMapNavigation } from '../contexts/MapNavigationContext';
import { useBattle } from '../contexts/BattleContext';
import { useMap } from '../contexts/MapContext';
import { useMovement } from '../contexts/MovementContext';

const SAFE_ZONE_AREA = {
topLeft: { x: 0, y: 4 },
bottomRight: { x: 4, y: 0 },
};

export const MapPanel = (): JSX.Element => {
const {
allSpawnedCharacters,
currentBattle,
isRefreshing,
isSpawned,
isSpawning,
onMove,
onSpawn,
position,
} = useMapNavigation();
const { allSpawnedCharacters, isSpawned, isSpawning, onSpawn, position } =
useMap();
const { currentBattle } = useBattle();
const { isRefreshing, onMove } = useMovement();

return (
<Stack
Expand Down
6 changes: 4 additions & 2 deletions packages/client/src/components/StatsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ export const StatsPanel = (): JSX.Element => {
strength,
} = character;

const currentHpWithFloor = parseInt(currentHp) < 0 ? 0 : parseInt(currentHp);

return (
<VStack alignItems="start" h="100%" p={2} spacing={4}>
<HStack
Expand All @@ -117,7 +119,7 @@ export const StatsPanel = (): JSX.Element => {
</GridItem>
<GridItem>
<Text>
{currentHp}/{baseHp}
{currentHpWithFloor}/{baseHp}
</Text>
</GridItem>
<GridItem>
Expand Down Expand Up @@ -165,7 +167,7 @@ export const StatsPanel = (): JSX.Element => {
>
{experience}
</Text>
/{nextLevelXpRequirement.toString()}
/{nextLevelXpRequirement.toString()} XP
</Text>
</HStack>

Expand Down
Loading