mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-11-14 13:16:11 +01:00
feat: armor toggle buttons
This commit is contained in:
1 parent
cddfef1b9f
commit
f86a4022ea
9 files changed
+353
-215
No files matched your search
@@ -1,8 +1,11 @@
|
||||
import { ChevronLeftIcon, MixIcon } from '@radix-ui/react-icons';
|
||||
import { Box, Button, Flex, Heading, Text } from '@radix-ui/themes';
|
||||
import Link from 'next/link';
|
||||
import { Suspense, useEffect, useState } from 'react';
|
||||
import { Suspense, use, useEffect, useMemo, useState } from 'react';
|
||||
import { classIcons } from '../../../../../../components/ClassIcon';
|
||||
import { ThicknessRange } from '../../../../../../components/StaticArmor/components/StaticArmorScene';
|
||||
import { modelDefinitions } from '../../../../../../core/blitzkit/modelDefinitions';
|
||||
import { tankDefinitions } from '../../../../../../core/blitzkit/tankDefinitions';
|
||||
import { TIER_ROMAN_NUMERALS } from '../../../../../../core/blitzkit/tankDefinitions/constants';
|
||||
import { useFullScreen } from '../../../../../../hooks/useFullScreen';
|
||||
import strings from '../../../../../../lang/en-US.json';
|
||||
@@ -11,7 +14,11 @@ import { Options } from './components/Options';
|
||||
import { TankSandbox } from './TankSandbox';
|
||||
import { TankSandboxLoader } from './TankSandboxLoader';
|
||||
|
||||
export function HeroSection({ id }: { id: number }) {
|
||||
interface HeroSectionProps {
|
||||
id: number;
|
||||
}
|
||||
|
||||
export function HeroSection({ id }: HeroSectionProps) {
|
||||
const protagonist = Duel.use((state) => state.protagonist.tank);
|
||||
const antagonist = Duel.use((state) => state.antagonist.tank);
|
||||
const compareTanks =
|
||||
@@ -27,6 +34,50 @@ export function HeroSection({ id }: { id: number }) {
|
||||
: protagonist.treeType === 'premium'
|
||||
? 'amber'
|
||||
: undefined;
|
||||
const awaitedTankDefinitions = use(tankDefinitions);
|
||||
const awaitedModelDefinitions = use(modelDefinitions);
|
||||
const tank = awaitedTankDefinitions[id];
|
||||
const thicknessRange = useMemo(() => {
|
||||
const thicknesses = Object.values(awaitedTankDefinitions)
|
||||
.filter((thisTank) => thisTank.tier === tank.tier)
|
||||
.map((tank) => ({
|
||||
model: awaitedModelDefinitions[tank.id],
|
||||
id: tank.id,
|
||||
}))
|
||||
.filter(Boolean)
|
||||
.map(({ model, id }) => {
|
||||
const tankThicknesses = Object.values(model.armor.thickness);
|
||||
const turretThicknesses = Object.values(model.turrets)
|
||||
.map((turret) => {
|
||||
const turretThicknesses = Object.values(turret.armor.thickness);
|
||||
const gunThicknesses = Object.values(turret.guns)
|
||||
.map((gun) => Object.values(gun.armor.thickness))
|
||||
.flat();
|
||||
|
||||
return [...turretThicknesses, ...gunThicknesses];
|
||||
})
|
||||
.flat();
|
||||
const totalThicknesses = [...tankThicknesses, ...turretThicknesses];
|
||||
|
||||
return totalThicknesses;
|
||||
})
|
||||
.flat();
|
||||
|
||||
const sortedThicknesses = thicknesses.sort((a, b) => a - b);
|
||||
const quartileIndex = (1 - 2 ** -6) * (sortedThicknesses.length + 1) - 1;
|
||||
let quartile: number;
|
||||
|
||||
if (Number.isInteger(quartileIndex)) {
|
||||
quartile = sortedThicknesses[quartileIndex];
|
||||
} else {
|
||||
quartile =
|
||||
(sortedThicknesses[Math.floor(quartileIndex)] +
|
||||
sortedThicknesses[Math.ceil(quartileIndex)]) /
|
||||
2;
|
||||
}
|
||||
|
||||
return { quartile } satisfies ThicknessRange;
|
||||
}, [tank.tier]);
|
||||
|
||||
useEffect(() => {
|
||||
setDummyLoader(false);
|
||||
@@ -129,11 +180,11 @@ export function HeroSection({ id }: { id: number }) {
|
||||
/>
|
||||
}
|
||||
>
|
||||
<TankSandbox />
|
||||
<TankSandbox thicknessRange={thicknessRange} />
|
||||
</Suspense>
|
||||
</Box>
|
||||
|
||||
<Options />
|
||||
<Options thicknessRange={thicknessRange} />
|
||||
</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Armor } from '../../../../../../components/Armor';
|
||||
import { ArmorPlateDisplay } from '../../../../../../components/Armor/components/ArmorPlateDisplay';
|
||||
import { ShotDisplay } from '../../../../../../components/Armor/components/ShotDisplay';
|
||||
import { StaticArmor } from '../../../../../../components/StaticArmor';
|
||||
import { ThicknessRange } from '../../../../../../components/StaticArmor/components/StaticArmorScene';
|
||||
import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits';
|
||||
import { modelDefinitions } from '../../../../../../core/blitzkit/modelDefinitions';
|
||||
import { modelTransformEvent } from '../../../../../../core/blitzkit/modelTransform';
|
||||
@@ -20,7 +21,11 @@ import { SceneProps } from '../SceneProps';
|
||||
import { ModelLoader } from './components/ModelLoader';
|
||||
import { TankModel } from './components/TankModel';
|
||||
|
||||
export function TankSandbox() {
|
||||
interface TankSandboxProps {
|
||||
thicknessRange: ThicknessRange;
|
||||
}
|
||||
|
||||
export function TankSandbox({ thicknessRange }: TankSandboxProps) {
|
||||
const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation();
|
||||
const canvas = useRef<HTMLCanvasElement>(null);
|
||||
const hasImprovedVerticalStabilizer = useEquipment(122);
|
||||
@@ -165,7 +170,7 @@ export function TankSandbox() {
|
||||
<Suspense fallback={<ModelLoader />}>
|
||||
{display === TankopediaDisplay.DynamicArmor && <Armor />}
|
||||
{display === TankopediaDisplay.StaticArmor && (
|
||||
<StaticArmor awaitedTankDefinitions={awaitedTankDefinitions} />
|
||||
<StaticArmor thicknessRange={thicknessRange} />
|
||||
)}
|
||||
<Lighting />
|
||||
</Suspense>
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
import { useEffect, useState } from 'react';
|
||||
import { ModuleButton } from '../../../../../../../components/ModuleButtons/ModuleButton';
|
||||
import { SmallTankIcon } from '../../../../../../../components/SmallTankIcon';
|
||||
import { ThicknessRange } from '../../../../../../../components/StaticArmor/components/StaticArmorScene';
|
||||
import { resolveNearPenetration } from '../../../../../../../core/blitz/resolveNearPenetration';
|
||||
import { resolvePenetrationCoefficient } from '../../../../../../../core/blitz/resolvePenetrationCoefficient';
|
||||
import { asset } from '../../../../../../../core/blitzkit/asset';
|
||||
@@ -42,9 +43,14 @@ import * as TankopediaPersistent from '../../../../../../../stores/tankopediaPer
|
||||
import { TankopediaDisplay } from '../../../../../../../stores/tankopediaPersistent/constants';
|
||||
import { TankSearch } from '../../../../components/TankSearch';
|
||||
import { ENVIRONMENTS } from '../../Lighting';
|
||||
import { RotationInputs } from '../../QuickInputs';
|
||||
import { QuickInputs } from '../../QuickInputs';
|
||||
import { Thicknesses } from '../../Thicknesses';
|
||||
|
||||
export function Options() {
|
||||
interface OptionsProps {
|
||||
thicknessRange: ThicknessRange;
|
||||
}
|
||||
|
||||
export function Options({ thicknessRange }: OptionsProps) {
|
||||
const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation();
|
||||
const mutateTankopediaPersistent = TankopediaPersistent.useMutation();
|
||||
const displayRaw = TankopediaPersistent.use((state) => state.display);
|
||||
@@ -113,7 +119,11 @@ export function Options() {
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<RotationInputs />
|
||||
<QuickInputs />
|
||||
|
||||
{display === TankopediaDisplay.StaticArmor && (
|
||||
<Thicknesses thicknessRange={thicknessRange} />
|
||||
)}
|
||||
|
||||
{display === TankopediaDisplay.DynamicArmor && (
|
||||
<Flex
|
||||
@@ -483,17 +493,17 @@ export function Options() {
|
||||
>
|
||||
<SegmentedControl.Item value={`${TankopediaDisplay.Model}`}>
|
||||
<Flex height="100%" align="center">
|
||||
<img src={imgur('jAdYf0m')} style={{ height: '1.5em' }} />
|
||||
<img src={imgur('jAdYf0m')} style={{ height: '1.25em' }} />
|
||||
</Flex>
|
||||
</SegmentedControl.Item>
|
||||
<SegmentedControl.Item value={`${TankopediaDisplay.DynamicArmor}`}>
|
||||
<Flex height="100%" align="center">
|
||||
<img src={imgur('oe4Cq0g')} style={{ height: '1.5em' }} />
|
||||
<img src={imgur('oe4Cq0g')} style={{ height: '1.25em' }} />
|
||||
</Flex>
|
||||
</SegmentedControl.Item>
|
||||
<SegmentedControl.Item value={`${TankopediaDisplay.StaticArmor}`}>
|
||||
<Flex height="100%" align="center">
|
||||
<img src={imgur('VQ4uDno')} style={{ height: '1.5em' }} />
|
||||
<img src={imgur('VQ4uDno')} style={{ height: '1.25em' }} />
|
||||
</Flex>
|
||||
</SegmentedControl.Item>
|
||||
</SegmentedControl.Root>
|
||||
|
||||
Reference in new issue
Block a user