mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
feat: provisions
This commit is contained in:
1 parent
f885fba4bd
commit
718576d5a9
3 files changed
+135
-2
No files matched your search
@@ -4,7 +4,8 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions
|
||||
|
||||
## Features
|
||||
|
||||
- [Mark Greene] Added the ability to filter tanks by Consumables and game-mode Abilities
|
||||
- [Mark Greene] Added the ability to filter tanks by consumables
|
||||
- Also added the ability to filter tanks by game-mode abilities and provisions
|
||||
|
||||
## Fixes
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import { times } from "lodash-es";
|
||||
import type { ComponentProps, ReactNode } from "react";
|
||||
import { awaitableConsumableDefinitions } from "../../../core/awaitables/consumableDefinitions";
|
||||
import { awaitableGameDefinitions } from "../../../core/awaitables/gameDefinitions";
|
||||
import { awaitableProvisionDefinitions } from "../../../core/awaitables/provisionDefinitions";
|
||||
import { useLocale } from "../../../hooks/useLocale";
|
||||
import { App } from "../../../stores/app";
|
||||
import { TankFilters, type CaseType } from "../../../stores/tankFilters";
|
||||
@@ -42,6 +43,7 @@ import { ScienceOffIcon } from "../../ScienceOffIcon";
|
||||
|
||||
const gameDefinitions = await awaitableGameDefinitions;
|
||||
const consumableDefinitions = await awaitableConsumableDefinitions;
|
||||
const provisionDefinitions = await awaitableProvisionDefinitions;
|
||||
|
||||
const consumablesArray = Object.values(consumableDefinitions.consumables)
|
||||
.filter(
|
||||
@@ -52,7 +54,38 @@ const consumablesArray = Object.values(consumableDefinitions.consumables)
|
||||
.map((consumable) => consumable.id);
|
||||
const abilitiesArray = Array.from(
|
||||
Object.values(consumableDefinitions.consumables)
|
||||
.filter((c) => c.game_mode_exclusive)
|
||||
.filter((ability) => ability.game_mode_exclusive)
|
||||
.reduce((uniqueMap, consumable) => {
|
||||
if (!uniqueMap.has(consumable.name.locales[locales.default])) {
|
||||
uniqueMap.set(consumable.name.locales[locales.default], consumable.id);
|
||||
}
|
||||
|
||||
return uniqueMap;
|
||||
}, new Map<string, number>())
|
||||
.values()
|
||||
);
|
||||
const provisionsArray = Array.from(
|
||||
Object.values(provisionDefinitions.provisions)
|
||||
.filter(
|
||||
(provision) =>
|
||||
!provision.game_mode_exclusive &&
|
||||
provision.name.locales[locales.default]
|
||||
)
|
||||
.reduce((uniqueMap, consumable) => {
|
||||
if (!uniqueMap.has(consumable.name.locales[locales.default])) {
|
||||
uniqueMap.set(consumable.name.locales[locales.default], consumable.id);
|
||||
}
|
||||
|
||||
return uniqueMap;
|
||||
}, new Map<string, number>())
|
||||
.values()
|
||||
);
|
||||
const powersArray = Array.from(
|
||||
Object.values(provisionDefinitions.provisions)
|
||||
.filter(
|
||||
(provision) =>
|
||||
provision.game_mode_exclusive && provision.name.locales[locales.default]
|
||||
)
|
||||
.reduce((uniqueMap, consumable) => {
|
||||
if (!uniqueMap.has(consumable.name.locales[locales.default])) {
|
||||
uniqueMap.set(consumable.name.locales[locales.default], consumable.id);
|
||||
@@ -91,6 +124,7 @@ const GUN_TYPES = Object.keys(
|
||||
|
||||
const MAX_TIERS = 4;
|
||||
const MAX_CONSUMABLES = 4;
|
||||
const MAX_PROVISIONS = 4;
|
||||
const MAX_ABILITIES = 4;
|
||||
|
||||
const TIERS = times(10, (i) => 10 - i);
|
||||
@@ -109,7 +143,9 @@ export function FilterControl() {
|
||||
<GunTypeFilter />
|
||||
<ShellFilter />
|
||||
<ConsumablesFilter />
|
||||
<ProvisionsFilter />
|
||||
<AbilitiesFilter />
|
||||
<PowersFilter />
|
||||
|
||||
<ClearButton />
|
||||
</Flex>
|
||||
@@ -881,6 +917,100 @@ function ConsumablesFilter() {
|
||||
);
|
||||
}
|
||||
|
||||
function ProvisionsFilter() {
|
||||
const { unwrap, strings } = useLocale();
|
||||
const rawProvisions = TankFilters.use((state) => state.provisions);
|
||||
const provisions =
|
||||
rawProvisions.length === 0 ? provisionsArray : rawProvisions;
|
||||
|
||||
return (
|
||||
<DropdownMenu.Root modal={false}>
|
||||
<DropdownMenu.Trigger>
|
||||
<Button color="gray" variant="surface">
|
||||
<Flex>
|
||||
{provisions.slice(0, MAX_PROVISIONS).map((provision, index) => (
|
||||
<img
|
||||
key={provision}
|
||||
style={{
|
||||
filter: "drop-shadow(0 0 var(--space-1) var(--black-a11))",
|
||||
marginLeft: index > 0 ? "-0.5em" : undefined,
|
||||
width: "1.25em",
|
||||
height: "1.25em",
|
||||
objectFit: "contain",
|
||||
}}
|
||||
src={asset(`icons/provisions/${provision}.webp`)}
|
||||
/>
|
||||
))}
|
||||
|
||||
{provisions.length > MAX_CONSUMABLES && (
|
||||
<Text size="1" ml="1">
|
||||
{literals(strings.common.units.plus, {
|
||||
value: provisions.length - MAX_CONSUMABLES,
|
||||
})}
|
||||
</Text>
|
||||
)}
|
||||
</Flex>
|
||||
</Button>
|
||||
</DropdownMenu.Trigger>
|
||||
|
||||
<DropdownMenu.Content>
|
||||
{provisionsArray.map((provision) => {
|
||||
const selected = rawProvisions.includes(provision);
|
||||
const provisionDefinition =
|
||||
provisionDefinitions.provisions[provision];
|
||||
|
||||
return (
|
||||
<DropdownMenu.CheckboxItem
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
|
||||
TankFilters.mutate((draft) => {
|
||||
if (selected) {
|
||||
draft.provisions = draft.provisions.filter(
|
||||
(n) => n !== provision
|
||||
);
|
||||
} else {
|
||||
draft.provisions = [...draft.provisions, provision];
|
||||
}
|
||||
});
|
||||
}}
|
||||
checked={selected}
|
||||
key={provision}
|
||||
>
|
||||
<img
|
||||
style={{
|
||||
width: "1.25em",
|
||||
height: "1.25em",
|
||||
objectFit: "contain",
|
||||
}}
|
||||
src={asset(`icons/provisions/${provision}.webp`)}
|
||||
/>
|
||||
|
||||
{unwrap(provisionDefinition.name)}
|
||||
</DropdownMenu.CheckboxItem>
|
||||
);
|
||||
})}
|
||||
|
||||
<DropdownMenu.Separator />
|
||||
|
||||
<DropdownMenu.Item
|
||||
color="red"
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
|
||||
TankFilters.mutate((draft) => {
|
||||
draft.provisions = [];
|
||||
});
|
||||
}}
|
||||
>
|
||||
<TrashIcon />
|
||||
{strings.website.common.tank_search.clear}
|
||||
</DropdownMenu.Item>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Root>
|
||||
);
|
||||
}
|
||||
|
||||
function AbilitiesFilter() {
|
||||
const { unwrap, strings } = useLocale();
|
||||
const rawAbilities = TankFilters.use((state) => state.abilities);
|
||||
|
||||
@@ -22,6 +22,7 @@ export interface TankFilters {
|
||||
gunType: CaseType<GunDefinition>[];
|
||||
shells: [ShellType | null, ShellType | null, ShellType | null];
|
||||
consumables: number[];
|
||||
provisions: number[];
|
||||
abilities: number[];
|
||||
|
||||
showTesting: boolean;
|
||||
@@ -40,6 +41,7 @@ export const TankFilters = new Varuna<TankFilters>({
|
||||
gunType: [],
|
||||
shells: [null, null, null],
|
||||
consumables: [],
|
||||
provisions: [],
|
||||
abilities: [],
|
||||
|
||||
showTesting: true,
|
||||
|
||||
Reference in new issue
Block a user