mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 02:37:05 +02:00
game mode abilities
This commit is contained in:
1 parent
5c482e0bac
commit
53eebc7a43
6 files changed
+164
-122
No files matched your search
Vendored
+1
@@ -96,6 +96,7 @@
|
||||
"fullstats",
|
||||
"fuzzysort",
|
||||
"gamemode",
|
||||
"gamemodes",
|
||||
"gameplay",
|
||||
"glsl",
|
||||
"GLTF",
|
||||
|
||||
@@ -98,6 +98,10 @@
|
||||
}
|
||||
},
|
||||
|
||||
"game_modes": {
|
||||
"title": "Game mode abilities"
|
||||
},
|
||||
|
||||
"navigation": {
|
||||
"tank": "Tank",
|
||||
"characteristics": "Characteristics"
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
.section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: var(--space-5);
|
||||
padding: var(--space-4);
|
||||
|
||||
.cards {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: var(--space-4);
|
||||
width: 100%;
|
||||
|
||||
.card {
|
||||
width: 16rem;
|
||||
height: 20rem;
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
border-radius: var(--space-3);
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
|
||||
.banner {
|
||||
flex: 1;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
min-height: 6.125rem;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: var(--space-2);
|
||||
padding: var(--space-3);
|
||||
backdrop-filter: blur(4rem);
|
||||
-webkit-backdrop-filter: blur(4rem);
|
||||
|
||||
.abilities {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
|
||||
.ability {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-1);
|
||||
white-space: nowrap;
|
||||
|
||||
img {
|
||||
width: 1.5em;
|
||||
height: 1.5em;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
import { alias } from "@blitzkit/core";
|
||||
import { api } from "../../api/dynamic";
|
||||
import { DuelModule, useDuel } from "../../hooks/useDuel";
|
||||
import { useStrings } from "../../hooks/useStrings";
|
||||
import { useUnwrapper } from "../../hooks/useUnwrapper";
|
||||
import { Heading } from "../Heading";
|
||||
import { Text } from "../Text";
|
||||
import styles from "./index.module.css";
|
||||
|
||||
const [gameDefinitions, consumableDefinitions, provisionDefinitions, tanks] =
|
||||
await Promise.all([
|
||||
api.game(),
|
||||
api.consumables(),
|
||||
api.provisions(),
|
||||
api.tanks(),
|
||||
]);
|
||||
|
||||
export function GameModeSection() {
|
||||
const unwrap = useUnwrapper();
|
||||
const strings = useStrings();
|
||||
const tank = useDuel("protagonist", DuelModule.Tank);
|
||||
const roles = Object.entries(tank.roles);
|
||||
|
||||
if (roles.length === 0) return null;
|
||||
|
||||
return (
|
||||
<section className={styles.section}>
|
||||
<Heading size="3">{strings.tanks.game_modes.title}</Heading>
|
||||
|
||||
<div className={styles.cards}>
|
||||
{roles.map(([id, value]) => {
|
||||
const gameMode = gameDefinitions.gameModes[id];
|
||||
const role = gameDefinitions.roles[value];
|
||||
const banner = alias("api", `/gamemodes/${id}/banner.webp`);
|
||||
|
||||
return (
|
||||
<article
|
||||
key={id}
|
||||
className={styles.card}
|
||||
style={{ backgroundImage: `url(${banner})` }}
|
||||
>
|
||||
<div
|
||||
className={styles.banner}
|
||||
style={{ backgroundImage: `url(${banner})` }}
|
||||
/>
|
||||
|
||||
<div className={styles.info}>
|
||||
<Text size="major" weight="bold" align="center">
|
||||
{unwrap(gameMode.name!)}
|
||||
</Text>
|
||||
|
||||
<div className={styles.abilities}>
|
||||
{role.provisions.map((id) => {
|
||||
const provisions = provisionDefinitions.provisions[id];
|
||||
|
||||
return (
|
||||
<Ability
|
||||
key={`provision-${id}`}
|
||||
icon={alias("api", `/icons/provisions/${id}.webp`)}
|
||||
name={unwrap(provisions.name!)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
{role.consumables.map((id) => {
|
||||
const consumable = consumableDefinitions.consumables[id];
|
||||
|
||||
return (
|
||||
<Ability
|
||||
key={`consumable-${id}`}
|
||||
icon={alias("api", `/icons/consumables/${id}.webp`)}
|
||||
name={unwrap(consumable.name!)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function Ability({ icon, name }: { icon: string; name: string }) {
|
||||
return (
|
||||
<Text lowContrast className={styles.ability}>
|
||||
<img src={icon} alt={name} />
|
||||
{name}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
import { alias } from "@blitzkit/core";
|
||||
import { Box, Flex, Heading, Text } from "@radix-ui/themes";
|
||||
import { api } from "../../api/dynamic";
|
||||
import { useLocale } from "../../hooks/useLocale";
|
||||
import { Duel } from "../../stores/duel";
|
||||
|
||||
const [gameDefinitions, consumableDefinitions, provisionDefinitions] =
|
||||
await Promise.all([api.game(), api.consumables(), api.provisions()]);
|
||||
|
||||
export function GameModeSection() {
|
||||
const { unwrap, strings } = useLocale();
|
||||
const tank = Duel.use((state) => state.protagonist.tank);
|
||||
const roles = Object.entries(tank.roles);
|
||||
|
||||
if (roles.length === 0) return null;
|
||||
|
||||
return (
|
||||
<Flex direction="column" gap="4" align="center">
|
||||
<Heading size="6">
|
||||
{strings.website.tools.tankopedia.game_modes.title}
|
||||
</Heading>
|
||||
|
||||
<Flex justify="center" gap="4" wrap="wrap" px="4">
|
||||
{roles.map(([id, value]) => {
|
||||
const gameMode = gameDefinitions.gameModes[id];
|
||||
|
||||
return (
|
||||
<Flex
|
||||
key={id}
|
||||
width="16rem"
|
||||
height="20rem"
|
||||
overflow="hidden"
|
||||
direction="column"
|
||||
style={{
|
||||
borderRadius: "var(--radius-3)",
|
||||
background: `url(${alias(
|
||||
"api",
|
||||
`/gamemodes/${id}/banner.webp`,
|
||||
)})`,
|
||||
backgroundSize: "cover",
|
||||
backgroundPosition: "center",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
flexGrow="1"
|
||||
style={{
|
||||
background: `url(${alias(
|
||||
"api",
|
||||
`/gamemodes/${id}/banner.webp`,
|
||||
)})`,
|
||||
backgroundSize: "cover",
|
||||
backgroundPosition: "center",
|
||||
}}
|
||||
/>
|
||||
|
||||
<Flex
|
||||
p="3"
|
||||
direction="column"
|
||||
height="98px"
|
||||
flexShrink="0"
|
||||
style={{
|
||||
backdropFilter: "blur(4rem)",
|
||||
WebkitBackdropFilter: "blur(4rem)",
|
||||
}}
|
||||
align="center"
|
||||
justify="center"
|
||||
>
|
||||
<Text size="4" weight="bold">
|
||||
{unwrap(gameMode.name!)}
|
||||
</Text>
|
||||
|
||||
<Flex direction="column">
|
||||
{gameDefinitions.roles[value].provisions.map((id) => {
|
||||
const provisions = provisionDefinitions.provisions[id];
|
||||
|
||||
return (
|
||||
<Text color="gray" wrap="nowrap" key={id}>
|
||||
<Flex align="center" gap="1">
|
||||
<img
|
||||
style={{
|
||||
width: "1.5em",
|
||||
height: "1.5em",
|
||||
objectFit: "contain",
|
||||
}}
|
||||
src={alias("api", `/icons/provisions/${id}.webp`)}
|
||||
alt={unwrap(provisions.name!)}
|
||||
/>
|
||||
{unwrap(provisions.name!)}
|
||||
</Flex>
|
||||
</Text>
|
||||
);
|
||||
})}
|
||||
|
||||
{gameDefinitions.roles[value].consumables.map((id) => {
|
||||
const consumable = consumableDefinitions.consumables[id];
|
||||
|
||||
return (
|
||||
<Text color="gray" wrap="nowrap" key={id}>
|
||||
<Flex align="center" gap="1">
|
||||
<img
|
||||
style={{
|
||||
width: "1.5em",
|
||||
height: "1.5em",
|
||||
objectFit: "contain",
|
||||
}}
|
||||
src={alias("api", `/icons/consumables/${id}.webp`)}
|
||||
alt={unwrap(consumable.name!)}
|
||||
/>
|
||||
{unwrap(consumable.name!)}
|
||||
</Flex>
|
||||
</Text>
|
||||
);
|
||||
})}
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
})}
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { api } from "../../../../../api/dynamic";
|
||||
import type { ThicknessRange } from "../../../../../components/StaticArmor";
|
||||
import { TankopediaCharacteristics } from "../../../../../components/TankopediaCharacteristics";
|
||||
import { TankopediaLoadout } from "../../../../../components/TankopediaLoadout";
|
||||
import { GameModeSection } from "../../../../../components/GameModeSection";
|
||||
import { defaultEqualizer } from "../../../../../config/equalizer";
|
||||
import { withErrorWrapper } from "../../../../../hocs/withErrorWrapper";
|
||||
import { withLocale } from "../../../../../hocs/withLocale";
|
||||
@@ -58,6 +59,7 @@ export const Page = withErrorWrapper(
|
||||
<div className={styles.sandbox}>
|
||||
{/* {!skeleton && <TankopediaSandbox thicknessRange={thicknessRange} />} */}
|
||||
<TankopediaCharacteristics characteristics={characteristics} />
|
||||
<GameModeSection />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user