mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
feat: gamemode abilities
This commit is contained in:
1 parent
98e0f28cd9
commit
55ffe22fd6
2 files changed
+105
-3
No files matched your search
@@ -49,9 +49,18 @@ const consumablesArray = Object.values(consumableDefinitions.consumables)
|
|||||||
consumable.name.locales[locales.default]
|
consumable.name.locales[locales.default]
|
||||||
)
|
)
|
||||||
.map((consumable) => consumable.id);
|
.map((consumable) => consumable.id);
|
||||||
const abilitiesArray = Object.values(consumableDefinitions.consumables)
|
const abilitiesArray = Array.from(
|
||||||
.filter((consumable) => consumable.game_mode_exclusive)
|
Object.values(consumableDefinitions.consumables)
|
||||||
.map((consumable) => consumable.id);
|
.filter((c) => c.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 shellTypeIcons: Record<ShellType, string> = {
|
const shellTypeIcons: Record<ShellType, string> = {
|
||||||
[ShellType.AP]: "ap",
|
[ShellType.AP]: "ap",
|
||||||
@@ -81,6 +90,7 @@ const GUN_TYPES = Object.keys(
|
|||||||
|
|
||||||
const MAX_TIERS = 4;
|
const MAX_TIERS = 4;
|
||||||
const MAX_CONSUMABLES = 4;
|
const MAX_CONSUMABLES = 4;
|
||||||
|
const MAX_ABILITIES = 4;
|
||||||
|
|
||||||
const TIERS = times(10, (i) => 10 - i);
|
const TIERS = times(10, (i) => 10 - i);
|
||||||
|
|
||||||
@@ -98,6 +108,7 @@ export function FilterControl() {
|
|||||||
<GunTypeFilter />
|
<GunTypeFilter />
|
||||||
<ShellFilter />
|
<ShellFilter />
|
||||||
<ConsumablesFilter />
|
<ConsumablesFilter />
|
||||||
|
<AbilitiesFilter />
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -815,3 +826,92 @@ function ConsumablesFilter() {
|
|||||||
</DropdownMenu.Root>
|
</DropdownMenu.Root>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function AbilitiesFilter() {
|
||||||
|
const rawAbilities = TankFilters.use((state) => state.abilities);
|
||||||
|
const abilities = rawAbilities.length === 0 ? abilitiesArray : rawAbilities;
|
||||||
|
const { unwrap } = useLocale();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DropdownMenu.Root>
|
||||||
|
<DropdownMenu.Trigger>
|
||||||
|
<Button color="gray" variant="surface">
|
||||||
|
<Flex>
|
||||||
|
{abilities.slice(0, MAX_ABILITIES).map((ability, index) => (
|
||||||
|
<img
|
||||||
|
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/consumables/${ability}.webp`)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{abilities.length > MAX_ABILITIES && (
|
||||||
|
<Text size="1" ml="1">
|
||||||
|
+{abilities.length - MAX_ABILITIES}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
</Button>
|
||||||
|
</DropdownMenu.Trigger>
|
||||||
|
|
||||||
|
<DropdownMenu.Content>
|
||||||
|
{abilitiesArray.map((ability) => {
|
||||||
|
const selected = rawAbilities.includes(ability);
|
||||||
|
const abilityDefinition = consumableDefinitions.consumables[ability];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DropdownMenu.CheckboxItem
|
||||||
|
onClick={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
TankFilters.mutate((draft) => {
|
||||||
|
if (selected) {
|
||||||
|
draft.abilities = draft.abilities.filter(
|
||||||
|
(n) => n !== ability
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
draft.abilities = [...draft.abilities, ability];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
checked={selected}
|
||||||
|
key={ability}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
style={{
|
||||||
|
width: "1em",
|
||||||
|
height: "1em",
|
||||||
|
objectFit: "contain",
|
||||||
|
}}
|
||||||
|
src={asset(`icons/consumables/${ability}.webp`)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{unwrap(abilityDefinition.name)}
|
||||||
|
</DropdownMenu.CheckboxItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
<DropdownMenu.Separator />
|
||||||
|
|
||||||
|
<DropdownMenu.Item
|
||||||
|
color="red"
|
||||||
|
onClick={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
TankFilters.mutate((draft) => {
|
||||||
|
draft.abilities = [];
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TrashIcon />
|
||||||
|
Clear
|
||||||
|
</DropdownMenu.Item>
|
||||||
|
</DropdownMenu.Content>
|
||||||
|
</DropdownMenu.Root>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ export interface TankFilters {
|
|||||||
gunType: CaseType<GunDefinition>[];
|
gunType: CaseType<GunDefinition>[];
|
||||||
shells: [ShellType | null, ShellType | null, ShellType | null];
|
shells: [ShellType | null, ShellType | null, ShellType | null];
|
||||||
consumables: number[];
|
consumables: number[];
|
||||||
|
abilities: number[];
|
||||||
|
|
||||||
showTesting: boolean;
|
showTesting: boolean;
|
||||||
showNonTesting: boolean;
|
showNonTesting: boolean;
|
||||||
@@ -39,6 +40,7 @@ export const TankFilters = new Varuna<TankFilters>({
|
|||||||
gunType: [],
|
gunType: [],
|
||||||
shells: [null, null, null],
|
shells: [null, null, null],
|
||||||
consumables: [],
|
consumables: [],
|
||||||
|
abilities: [],
|
||||||
|
|
||||||
showTesting: true,
|
showTesting: true,
|
||||||
showNonTesting: true,
|
showNonTesting: true,
|
||||||
|
|||||||
Reference in new issue
Block a user