Skip to content

Commit

Permalink
feat: New arena layout. Fixes #996
Browse files Browse the repository at this point in the history
  • Loading branch information
Zenoo committed Nov 11, 2024
1 parent f17ab59 commit 5f5a7fe
Show file tree
Hide file tree
Showing 24 changed files with 1,066 additions and 82 deletions.
Binary file added client/public/images/arena/brute-bg-high.webp
Binary file not shown.
Binary file not shown.
175 changes: 175 additions & 0 deletions client/public/images/pets/bear.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
266 changes: 266 additions & 0 deletions client/public/images/pets/dog.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
275 changes: 275 additions & 0 deletions client/public/images/pets/panther.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions client/src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,7 @@
"rankingPrioritizeAscensions": "The rankings prioritize the amount of ascensions over experience and level !",
"fasterFights": "Faster fights",
"displayVersusPage": "Display versus page",
"displayOpponentDetails": "Display opponent details",
"wiki.howToRankup": "How to rank up?",
"wiki.winDaily": "Win daily tournament(s)",
"wiki.wins_one": "{{count}} win",
Expand Down
14 changes: 9 additions & 5 deletions client/src/components/Brute/Body/BruteRender.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,12 @@ const BruteRender = ({

if (p3 === 0) {
width += 15;
shift.y += 7;

if (looking === 'right') {
shift.x += -20;
}
} else if (p3 === 1) {
width += -10;
shift.y += 10;
} else if (p3 === 3) {
width += 40;

Expand Down Expand Up @@ -87,12 +85,18 @@ const BruteRender = ({
width += 10;
shift.y += 5;
} else if (p3 === 11) {
shift.y += 10;
width -= 5;
} else if (p3 === 5) {
width += 20;
shift.y -= 10;
} else if (p3 === 3) {
shift.y -= 3;
}

if (p7 === 5) {
if (p3 === 9 || p3 === 4 || p3 === 6) {
width += 10;
if (p3 === 9 || p3 === 4 || p3 === 6 || p3 === 3) {
width += 20;
shift.y -= 5;

if (looking === 'right') {
shift.x += -15;
Expand Down
7 changes: 6 additions & 1 deletion client/src/components/Brute/PetTooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next';
import { useBrute } from '../../hooks/useBrute';
import StatColor from '../../utils/StatColor';
import Text from '../Text';
import { Brute } from '@labrute/prisma';

const textShadowBase = '-1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000';
const textProps = {
Expand All @@ -14,19 +15,23 @@ const textProps = {

export interface PetTooltipProps extends Omit<TooltipProps, 'title'> {
pet?: Pet;
brute?: Pick<Brute, 'hp' | 'strengthValue' | 'agilityValue' | 'speedValue'>;
}

const PetTooltip = ({
pet,
brute: specificBrute,
children,
...rest
}: PetTooltipProps) => {
const { t } = useTranslation();
const { brute } = useBrute();
const { brute: authedBrute } = useBrute();
const theme = useTheme();

const textShadow = useMemo(() => (theme.palette.mode === 'dark' ? textShadowBase : undefined), [theme.palette.mode]);

const brute = specificBrute || authedBrute;

return (
<Tooltip
{...rest}
Expand Down
12 changes: 12 additions & 0 deletions client/src/components/StyledButton.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Box, BoxProps, useTheme } from '@mui/material';
import React, { useCallback } from 'react';
import { useNavigate } from 'react-router';

export interface StyledButtonProps extends Omit<BoxProps, 'translate'> {
image?: string;
Expand All @@ -9,6 +10,7 @@ export interface StyledButtonProps extends Omit<BoxProps, 'translate'> {
contrast?: boolean;
shift?: string;
shadowColor?: string;
to?: string;
}

export const StyledButtonWidth = 207;
Expand All @@ -26,10 +28,12 @@ const StyledButton = React.forwardRef<HTMLDivElement, StyledButtonProps>(({
contrast = true,
shift = '4px',
shadowColor = 'rgba(0, 0, 0, 0.2)',
to,
sx,
...rest
}: StyledButtonProps, ref) => {
const { palette: { mode } } = useTheme();
const navigate = useNavigate();

const themedImage = mode === 'dark' ? image.replace('/images/', '/images/dark/') : image;
const themedImageHover = mode === 'dark' ? imageHover.replace('/images/', '/images/dark/') : imageHover;
Expand All @@ -43,10 +47,18 @@ const StyledButton = React.forwardRef<HTMLDivElement, StyledButtonProps>(({
const handleMouseLeave = useCallback(() => {
setHover(false);
}, []);

const handleClick = () => {
if (to) {
navigate(to);
}
};

return (
<Box
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onClick={handleClick}
ref={ref}
sx={{
display: 'flex',
Expand Down
23 changes: 22 additions & 1 deletion client/src/layouts/Main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { getFightsLeft, getGoldNeededForNewBrute, UserUpdateSettingsRequest } from '@labrute/core';
import { Lang } from '@labrute/prisma';
import { Add, AdminPanelSettings, DarkMode, Info, LightMode, Logout, Menu, MilitaryTech, MoreHoriz, MusicNote, NewReleases, Person, Policy, RssFeed, Speed, SportsKabaddi } from '@mui/icons-material';
import { Add, AdminPanelSettings, DarkMode, Info, LightMode, Logout, Menu, MilitaryTech, MoreHoriz, MusicNote, NewReleases, Person, PersonSearch, Policy, RssFeed, Speed, SportsKabaddi } from '@mui/icons-material';
import { Badge, Box, Button, Divider, Drawer, GlobalStyles, IconButton, List, ListItem, ListItemIcon, ListItemText, ListSubheader, Alert as MuiAlert, Switch, ThemeProvider, Tooltip, useTheme } from '@mui/material';
import React, { useCallback, useContext, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
Expand Down Expand Up @@ -34,6 +34,7 @@ const Main = () => {
fightSpeed: 2,
backgroundMusic: false,
displayVersusPage: true,
displayOpponentDetails: true,
});

const favoriteCount = user?.brutes.filter((b) => b.favorite).length || 0;
Expand All @@ -46,6 +47,7 @@ const Main = () => {
fightSpeed: user.fightSpeed,
backgroundMusic: user.backgroundMusic,
displayVersusPage: user.displayVersusPage,
displayOpponentDetails: user.displayOpponentDetails,
});
}, [user]);

Expand Down Expand Up @@ -100,6 +102,7 @@ const Main = () => {
fightSpeed: settings.fightSpeed,
backgroundMusic: settings.backgroundMusic,
displayVersusPage: settings.displayVersusPage,
displayOpponentDetails: settings.displayOpponentDetails,
};

if (key === 'fightSpeed') {
Expand All @@ -116,6 +119,7 @@ const Main = () => {
fightSpeed: newSettings.fightSpeed,
backgroundMusic: newSettings.backgroundMusic,
displayVersusPage: newSettings.displayVersusPage,
displayOpponentDetails: newSettings.displayOpponentDetails,
} : null));
}).catch(catchError(Alert));
};
Expand Down Expand Up @@ -444,6 +448,8 @@ const Main = () => {
</Button>
)}
sx={{
mt: 0,
mb: 1,
'& .MuiAlert-action': {
alignItems: 'center',
}
Expand Down Expand Up @@ -503,6 +509,21 @@ const Main = () => {
}}
/>
</ListItem>
<ListItem>
<ListItemIcon>
<PersonSearch />
</ListItemIcon>
<ListItemText id="switch-displayOpponentDetails" primary={t('displayOpponentDetails')} />
<Switch
edge="end"
size="small"
onChange={toggle('displayOpponentDetails')}
checked={settings.displayOpponentDetails}
inputProps={{
'aria-labelledby': 'switch-displayOpponentDetails',
}}
/>
</ListItem>
</List>
</ThemeProvider>
</>
Expand Down
165 changes: 154 additions & 11 deletions client/src/views/ArenaView.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
import { BrutesGetOpponentsResponse, getFightsLeft, getXPNeeded } from '@labrute/core';
import { Box, Button, Grid, Paper, useMediaQuery, useTheme } from '@mui/material';
import { BrutesGetOpponentsResponse, FightStat, getFightsLeft, getFinalHP, getFinalStat, getXPNeeded, pets, skills, weapons } from '@labrute/core';
import { Box, Button, Divider, Grid, Paper, useMediaQuery, useTheme } from '@mui/material';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate, useParams } from 'react-router';
import ArenaStat from '../components/Arena/ArenaStat';
import BruteRender from '../components/Brute/Body/BruteRender';
import BruteBodyAndStats from '../components/Brute/BruteBodyAndStats';
import BruteButton from '../components/Brute/BruteButton';
import BruteHP from '../components/Brute/BruteHP';
import BruteLevelAndXP from '../components/Brute/BruteLevelAndXP';
import PetTooltip from '../components/Brute/PetTooltip';
import SkillTooltip from '../components/Brute/SkillTooltip';
import WeaponTooltip from '../components/Brute/WeaponTooltip';
import Link from '../components/Link';
import Loader from '../components/Loader';
import Page from '../components/Page';
import StyledInput from '../components/StyledInput';
import Text from '../components/Text';
import { useAlert } from '../hooks/useAlert';
import { useAuth } from '../hooks/useAuth';
import { useBrute } from '../hooks/useBrute';
import Server from '../utils/Server';
import catchError from '../utils/catchError';
import { useAuth } from '../hooks/useAuth';
import Loader from '../components/Loader';

const ArenaView = () => {
const { t } = useTranslation();
Expand Down Expand Up @@ -164,13 +169,151 @@ const ArenaView = () => {
</Grid>
<Grid item xs={12} md={5.6}>
{loading ? <Loader height={346} /> : (
<Grid container spacing={1}>
<Grid container spacing={1} mb={3}>
{opponents.map((opponent) => (
<Grid item key={opponent.name} xs={12} sm={6}>
<BruteButton
brute={opponent}
onClick={goToVersus(opponent.name)}
/>
<Grid item key={opponent.name} xs={12} sm={6} mb={1.5}>
<Box sx={{
width: 185,
height: 1,
p: 1,
pt: 1,
pb: user?.displayOpponentDetails ? 1 : 1.8,
mx: 'auto',
textAlign: 'left',
position: 'relative',
backgroundImage: `url(/images${theme.palette.mode === 'dark' ? '/dark' : ''}/arena/brute-bg${user?.displayOpponentDetails ? '-high' : ''}.webp)`,
backgroundRepeat: 'no-repeat',
backgroundSize: '100% 100%',
}}
>
<Box sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
}}
>
<Box display="flex" alignItems="center">
<Text bold color="secondary" sx={{ display: 'inline' }}>{opponent.name}</Text>
</Box>
</Box>
<Text bold smallCaps color="text.primary">
{t('level')}
<Text component="span" bold color="secondary"> {opponent.level}</Text>
{opponent.eventId ? (
<Box
component="img"
src="/images/event.webp"
sx={{
verticalAlign: 'sub',
height: 18,
ml: 0.5,
}}
/>
) : (
<Box
component="img"
src={`/images/rankings/lvl_${opponent.ranking}.webp`}
sx={{
verticalAlign: 'middle',
height: 16,
ml: 0.5,
}}
/>
)}
</Text>
<Box sx={{ display: 'flex', alignItems: 'center', width: 115 }}>
<BruteHP hp={getFinalHP(opponent, modifiers)} />
<Box flexGrow={1} sx={{ ml: 0.5 }}>
<ArenaStat
stat={FightStat.STRENGTH}
value={getFinalStat(opponent, 'strength', modifiers)}
hideSkillText
/>
<ArenaStat
stat={FightStat.AGILITY}
value={getFinalStat(opponent, 'agility', modifiers)}
hideSkillText
/>
<ArenaStat
stat={FightStat.SPEED}
value={getFinalStat(opponent, 'speed', modifiers)}
hideSkillText
/>
</Box>
</Box>
{user?.displayOpponentDetails && (
<>
<Divider
sx={{
ml: -0.75,
mr: -0.4,
mt: 0.5,
borderColor: 'primary.main',
}}
/>
{/* Weapons */}
<Box pt={1}>
{opponent.weapons.map((weapon) => (
<WeaponTooltip
weapon={weapons.find((w) => w.name === weapon)}
key={weapon}
>
<Box component="img" src={`/images/game/resources/misc/weapons/${weapon}.png`} sx={{ filter: 'drop-shadow(1px 1px 1px black)' }} />
</WeaponTooltip>
))}
</Box>
{/* Skills */}
<Box>
{opponent.skills.map((skill) => (
<SkillTooltip
skill={skills.find((s) => s.name === skill)}
key={skill}
>
<Box
component="img"
src={`/images/skills/${skill}.svg`}
sx={{
width: 16,
mx: 0.25,
my: 0,
filter: 'drop-shadow(1px 1px 1px black)'
}}
/>
</SkillTooltip>
))}
</Box>
{/* Pets */}
<Box>
{opponent.pets.map((pet) => (
<PetTooltip pet={pets.find((p) => p.name === pet)} key={pet}>
<Box component="img" src={`/images/pets/${pet.replace(/\d/g, '')}.svg`} sx={{ width: 16, m: 0.25, mb: 0, filter: 'drop-shadow(1px 1px 1px black)' }} />
</PetTooltip>
))}
</Box>
</>
)}
<Box sx={{
position: 'absolute',
top: 0,
left: 115,
width: 70,
height: user?.displayOpponentDetails ? 94 : 98,
overflow: 'hidden',
}}
>
<BruteRender
brute={opponent}
looking="left"
onClick={goToVersus(opponent.name)}
sx={{
cursor: 'pointer',
'&:hover': {
filter: 'drop-shadow(0px 0px 2px #ff0000)',
},
}}
/>
</Box>
</Box>
</Grid>
))}
</Grid>
Expand Down
1 change: 1 addition & 0 deletions client/src/views/UserAdminView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const UserAdminView = () => {
banReason: u.banReason,
ips: u.ips,
displayVersusPage: u.displayVersusPage,
displayOpponentDetails: u.displayOpponentDetails,
});
setAchievements(u.achievements);
// Map to new array to avoid reference
Expand Down
Loading

0 comments on commit 5f5a7fe

Please sign in to comment.