mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 03:59:50 +02:00
Added ability to filter tanks by available provisions
This commit is contained in:
1 parent
b479c09cf8
commit
b6204b1c2c
3 files changed
+185
-1
No files matched your search
@@ -18,8 +18,10 @@ import {
|
|||||||
type ButtonProps,
|
type ButtonProps,
|
||||||
type FlexProps,
|
type FlexProps,
|
||||||
} from "@radix-ui/themes";
|
} from "@radix-ui/themes";
|
||||||
import { isEqual, times } from "lodash-es";
|
import { isEqual, times, chunk } from "lodash-es";
|
||||||
|
import React from "react";
|
||||||
import { awaitableGameDefinitions } from "../../../core/awaitables/gameDefinitions";
|
import { awaitableGameDefinitions } from "../../../core/awaitables/gameDefinitions";
|
||||||
|
import { awaitableConsumableDefinitions } from "../../../core/awaitables/consumableDefinitions";
|
||||||
import { Var } from "../../../core/radix/var";
|
import { Var } from "../../../core/radix/var";
|
||||||
import { useLocale } from "../../../hooks/useLocale";
|
import { useLocale } from "../../../hooks/useLocale";
|
||||||
import { App } from "../../../stores/app";
|
import { App } from "../../../stores/app";
|
||||||
@@ -35,6 +37,7 @@ import { ScienceIcon } from "../../ScienceIcon";
|
|||||||
import { ScienceOffIcon } from "../../ScienceOffIcon";
|
import { ScienceOffIcon } from "../../ScienceOffIcon";
|
||||||
|
|
||||||
const gameDefinitions = await awaitableGameDefinitions;
|
const gameDefinitions = await awaitableGameDefinitions;
|
||||||
|
const consumableDefinitions = await awaitableConsumableDefinitions;
|
||||||
|
|
||||||
const shellTypeIcons: Record<ShellType, string> = {
|
const shellTypeIcons: Record<ShellType, string> = {
|
||||||
[ShellType.AP]: "ap",
|
[ShellType.AP]: "ap",
|
||||||
@@ -43,6 +46,25 @@ const shellTypeIcons: Record<ShellType, string> = {
|
|||||||
[ShellType.HEAT]: "hc",
|
[ShellType.HEAT]: "hc",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Get consumables
|
||||||
|
const regularConsumables = Object.values(
|
||||||
|
consumableDefinitions.consumables
|
||||||
|
).filter(
|
||||||
|
(consumable) =>
|
||||||
|
!consumable.game_mode_exclusive && consumable.name.locales.en !== ""
|
||||||
|
);
|
||||||
|
|
||||||
|
// Split consumables into chunks of 5 for columns
|
||||||
|
const consumableColumns = chunk(regularConsumables, 5);
|
||||||
|
|
||||||
|
// Get game mode exclusive abilities
|
||||||
|
const gameModeAbilities = Object.values(
|
||||||
|
consumableDefinitions.consumables
|
||||||
|
).filter((consumable) => consumable.game_mode_exclusive);
|
||||||
|
|
||||||
|
// Split abilities into chunks of 5 for columns
|
||||||
|
const abilityColumns = chunk(gameModeAbilities, 5);
|
||||||
|
|
||||||
const size: ButtonProps["size"] = { initial: "1", xs: "2" };
|
const size: ButtonProps["size"] = { initial: "1", xs: "2" };
|
||||||
|
|
||||||
function ShellFilter({ index, premium }: { index: number; premium?: boolean }) {
|
function ShellFilter({ index, premium }: { index: number; premium?: boolean }) {
|
||||||
@@ -337,6 +359,151 @@ export function FilterControl() {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
|
{/* Consumables Filter - RIGHT AFTER NATIONS */}
|
||||||
|
<Flex
|
||||||
|
flexShrink="0"
|
||||||
|
overflow="hidden"
|
||||||
|
style={{ borderRadius: "var(--radius-4)" }}
|
||||||
|
>
|
||||||
|
<Flex direction="column">
|
||||||
|
{consumableColumns[0]?.map((consumable) => {
|
||||||
|
const selected = tankFilters.consumables?.includes(consumable.id);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IconButton
|
||||||
|
size={size}
|
||||||
|
key={consumable.id}
|
||||||
|
variant={selected ? "solid" : "soft"}
|
||||||
|
color={selected ? undefined : "gray"}
|
||||||
|
highContrast
|
||||||
|
radius="none"
|
||||||
|
onClick={() => {
|
||||||
|
TankFilters.mutate((draft) => {
|
||||||
|
if (tankFilters.consumables.includes(consumable.id)) {
|
||||||
|
draft.consumables = draft.consumables.filter(
|
||||||
|
(c) => c !== consumable.id
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
draft.consumables = [
|
||||||
|
...draft.consumables,
|
||||||
|
consumable.id,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
style={{ width: "1em", height: "1em" }}
|
||||||
|
src={asset(`icons/consumables/${consumable.id}.webp`)}
|
||||||
|
/>
|
||||||
|
</IconButton>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
{consumableColumns[1] && (
|
||||||
|
<>
|
||||||
|
<Box
|
||||||
|
display={{ initial: "none", md: "block" }}
|
||||||
|
style={{
|
||||||
|
height: Var("space-1"),
|
||||||
|
backgroundColor: Var("gray-a3"),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Flex direction="column">
|
||||||
|
{consumableColumns[1].map((consumable) => {
|
||||||
|
const selected = tankFilters.consumables?.includes(
|
||||||
|
consumable.id
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IconButton
|
||||||
|
size={size}
|
||||||
|
key={consumable.id}
|
||||||
|
style={{ flex: 1 }}
|
||||||
|
variant={selected ? "solid" : "soft"}
|
||||||
|
color={selected ? undefined : "gray"}
|
||||||
|
highContrast
|
||||||
|
radius="none"
|
||||||
|
onClick={() => {
|
||||||
|
TankFilters.mutate((draft) => {
|
||||||
|
if (tankFilters.consumables.includes(consumable.id)) {
|
||||||
|
draft.consumables = draft.consumables.filter(
|
||||||
|
(c) => c !== consumable.id
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
draft.consumables = [
|
||||||
|
...draft.consumables,
|
||||||
|
consumable.id,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
style={{ width: "1em", height: "1em" }}
|
||||||
|
src={asset(`icons/consumables/${consumable.id}.webp`)}
|
||||||
|
/>
|
||||||
|
</IconButton>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Flex>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{consumableColumns[2] && (
|
||||||
|
<>
|
||||||
|
<Box
|
||||||
|
display={{ initial: "none", md: "block" }}
|
||||||
|
style={{
|
||||||
|
height: Var("space-1"),
|
||||||
|
backgroundColor: Var("gray-a3"),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Flex direction="column">
|
||||||
|
{consumableColumns[2].map((consumable) => {
|
||||||
|
const selected = tankFilters.consumables?.includes(
|
||||||
|
consumable.id
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IconButton
|
||||||
|
size={size}
|
||||||
|
key={consumable.id}
|
||||||
|
style={{ flex: 1 }}
|
||||||
|
variant={selected ? "solid" : "soft"}
|
||||||
|
color={selected ? undefined : "gray"}
|
||||||
|
highContrast
|
||||||
|
radius="none"
|
||||||
|
onClick={() => {
|
||||||
|
TankFilters.mutate((draft) => {
|
||||||
|
if (tankFilters.consumables.includes(consumable.id)) {
|
||||||
|
draft.consumables = draft.consumables.filter(
|
||||||
|
(c) => c !== consumable.id
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
draft.consumables = [
|
||||||
|
...draft.consumables,
|
||||||
|
consumable.id,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
style={{ width: "1em", height: "1em" }}
|
||||||
|
src={asset(`icons/consumables/${consumable.id}.webp`)}
|
||||||
|
/>
|
||||||
|
</IconButton>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Flex>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
|
||||||
<Flex
|
<Flex
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
style={{ borderRadius: "var(--radius-full)" }}
|
style={{ borderRadius: "var(--radius-full)" }}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import type { TankDefinition } from "@blitzkit/core";
|
import type { TankDefinition } from "@blitzkit/core";
|
||||||
|
import { checkConsumableProvisionInclusivity } from "@blitzkit/core/src/blitzkit/checkConsumableProvisionInclusivity";
|
||||||
import { times } from "lodash-es";
|
import { times } from "lodash-es";
|
||||||
|
import { awaitableConsumableDefinitions } from "../../core/awaitables/consumableDefinitions";
|
||||||
import type { TankFilters } from "../../stores/tankFilters";
|
import type { TankFilters } from "../../stores/tankFilters";
|
||||||
|
|
||||||
const SHELLS = times(3, (index) => index);
|
const SHELLS = times(3, (index) => index);
|
||||||
|
const consumableDefinitions = await awaitableConsumableDefinitions;
|
||||||
|
|
||||||
export async function filterTank(
|
export async function filterTank(
|
||||||
filters: TankFilters,
|
filters: TankFilters,
|
||||||
@@ -40,6 +43,18 @@ export async function filterTank(
|
|||||||
gun.shells[index].type === filters.shells[index]
|
gun.shells[index].type === filters.shells[index]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
) &&
|
||||||
|
(filters.consumables.length === 0 ||
|
||||||
|
filters.consumables.every((consumableId) =>
|
||||||
|
tank.turrets.some((turret) =>
|
||||||
|
turret.guns.some((gun) =>
|
||||||
|
checkConsumableProvisionInclusivity(
|
||||||
|
consumableDefinitions.consumables[consumableId],
|
||||||
|
tank,
|
||||||
|
gun
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -21,6 +21,7 @@ export interface TankFilters {
|
|||||||
searching: boolean;
|
searching: boolean;
|
||||||
gunType: CaseType<GunDefinition>[];
|
gunType: CaseType<GunDefinition>[];
|
||||||
shells: [ShellType | null, ShellType | null, ShellType | null];
|
shells: [ShellType | null, ShellType | null, ShellType | null];
|
||||||
|
consumables: number[];
|
||||||
|
|
||||||
showTesting: boolean;
|
showTesting: boolean;
|
||||||
showNonTesting: boolean;
|
showNonTesting: boolean;
|
||||||
@@ -37,6 +38,7 @@ export const TankFilters = new Varuna<TankFilters>({
|
|||||||
searching: false,
|
searching: false,
|
||||||
gunType: [],
|
gunType: [],
|
||||||
shells: [null, null, null],
|
shells: [null, null, null],
|
||||||
|
consumables: [], // Added this line
|
||||||
|
|
||||||
showTesting: true,
|
showTesting: true,
|
||||||
showNonTesting: true,
|
showNonTesting: true,
|
||||||
|
|||||||
Reference in new issue
Block a user