From abac64f01bfcfc3d3e6d298ce3f7edf20287de08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Fri, 28 Jun 2024 20:17:47 -0500 Subject: [PATCH 01/20] fix: enter click no redirect with onselect --- src/app/tools/tankopedia/components/SearchBar.tsx | 10 ++++++++-- .../tools/tankopedia/components/TankSearch/index.tsx | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/app/tools/tankopedia/components/SearchBar.tsx b/src/app/tools/tankopedia/components/SearchBar.tsx index 54490e950..66a47398b 100644 --- a/src/app/tools/tankopedia/components/SearchBar.tsx +++ b/src/app/tools/tankopedia/components/SearchBar.tsx @@ -10,9 +10,10 @@ import { Sort } from './Sort'; interface SearchBarProps { topResult?: TankDefinition; + onSelect?: (tank: TankDefinition) => void; } -export function SearchBar({ topResult }: SearchBarProps) { +export function SearchBar({ topResult, onSelect }: SearchBarProps) { const router = useRouter(); const input = useRef(null); const searching = useTankopediaFilters((state) => state.searching); @@ -42,7 +43,12 @@ export function SearchBar({ topResult }: SearchBarProps) { if (event.key !== 'Enter' || !topResult || searching) return; event.preventDefault(); - router.push(`/tools/tankopedia/${topResult.id}`); + + if (onSelect) { + onSelect(topResult); + } else { + router.push(`/tools/tankopedia/${topResult.id}`); + } }, [topResult], ); diff --git a/src/app/tools/tankopedia/components/TankSearch/index.tsx b/src/app/tools/tankopedia/components/TankSearch/index.tsx index 773a07c19..c5d9f87f9 100644 --- a/src/app/tools/tankopedia/components/TankSearch/index.tsx +++ b/src/app/tools/tankopedia/components/TankSearch/index.tsx @@ -360,7 +360,7 @@ export const TankSearch = memo( return ( - + {!filters.search && !filters.searching && ( From 8d2ec5f5b4fdcc1947da840479eb1de96a542cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Fri, 28 Jun 2024 20:32:19 -0500 Subject: [PATCH 02/20] feat: antagonist penetration preview --- .../components/Model/components/Options.tsx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/app/tools/tankopedia/[id]/components/Model/components/Options.tsx b/src/app/tools/tankopedia/[id]/components/Model/components/Options.tsx index fe3606d10..210ad08e8 100644 --- a/src/app/tools/tankopedia/[id]/components/Model/components/Options.tsx +++ b/src/app/tools/tankopedia/[id]/components/Model/components/Options.tsx @@ -22,6 +22,7 @@ import { useState } from 'react'; import { ModuleButton } from '../../../../../../../components/ModuleButtons/ModuleButton'; import { SmallTankIcon } from '../../../../../../../components/SmallTankIcon'; import { resolveNearPenetration } from '../../../../../../../core/blitz/resolveNearPenetration'; +import { resolvePenetrationCoefficient } from '../../../../../../../core/blitz/resolvePenetrationCoefficient'; import { asset } from '../../../../../../../core/blitzkit/asset'; import { Pose, poseEvent } from '../../../../../../../core/blitzkit/pose'; import { @@ -113,7 +114,23 @@ export function Options() { top: '50%', transform: 'translateY(-50%)', }} + align="end" > + + {( + resolvePenetrationCoefficient( + hasCalibratedShells, + antagonistShell.type, + ) * resolveNearPenetration(antagonistShell.penetration) + ).toFixed(0)} + mm + {antagonistGun.shells.map((thisShell, shellIndex) => ( ))} - Date: Fri, 28 Jun 2024 20:41:24 -0500 Subject: [PATCH 03/20] feat: responsive shot card --- .../components/Model/components/Options.tsx | 8 +- .../[id]/components/ShotDisplaySection.tsx | 16 ++ src/app/tools/tankopedia/[id]/page.tsx | 2 + .../Armor/components/ShotDisplay.tsx | 242 ++---------------- .../Armor/components/ShotDisplayCard.tsx | 242 ++++++++++++++++++ 5 files changed, 276 insertions(+), 234 deletions(-) create mode 100644 src/app/tools/tankopedia/[id]/components/ShotDisplaySection.tsx create mode 100644 src/components/Armor/components/ShotDisplayCard.tsx diff --git a/src/app/tools/tankopedia/[id]/components/Model/components/Options.tsx b/src/app/tools/tankopedia/[id]/components/Model/components/Options.tsx index 210ad08e8..ed9d79b1f 100644 --- a/src/app/tools/tankopedia/[id]/components/Model/components/Options.tsx +++ b/src/app/tools/tankopedia/[id]/components/Model/components/Options.tsx @@ -116,13 +116,7 @@ export function Options() { }} align="end" > - + {( resolvePenetrationCoefficient( hasCalibratedShells, diff --git a/src/app/tools/tankopedia/[id]/components/ShotDisplaySection.tsx b/src/app/tools/tankopedia/[id]/components/ShotDisplaySection.tsx new file mode 100644 index 000000000..a7f1a0b85 --- /dev/null +++ b/src/app/tools/tankopedia/[id]/components/ShotDisplaySection.tsx @@ -0,0 +1,16 @@ +import { Flex } from '@radix-ui/themes'; +import { ShotDisplayCard } from '../../../../../components/Armor/components/ShotDisplayCard'; + +export function ShotDisplaySection() { + return ( + + + + ); +} diff --git a/src/app/tools/tankopedia/[id]/page.tsx b/src/app/tools/tankopedia/[id]/page.tsx index d1b2a9191..7b39f787f 100644 --- a/src/app/tools/tankopedia/[id]/page.tsx +++ b/src/app/tools/tankopedia/[id]/page.tsx @@ -11,6 +11,7 @@ import { HistorySection } from './components/HistorySection'; import { CharacteristicsSection } from './components/Model/CharacteristicsSection'; import { HeroSection } from './components/Model/HeroSection'; import { TechTreeSection } from './components/Model/TechTreeSection'; +import { ShotDisplaySection } from './components/ShotDisplaySection'; import { VideoSection } from './components/VideoSection'; export default function Page({ params }: { params: { id: string } }) { @@ -77,6 +78,7 @@ export default function Page({ params }: { params: { id: string } }) { {assigned && ( <> + {!exempt && } {!exempt && } diff --git a/src/components/Armor/components/ShotDisplay.tsx b/src/components/Armor/components/ShotDisplay.tsx index 2569378b9..877eec688 100644 --- a/src/components/Armor/components/ShotDisplay.tsx +++ b/src/components/Armor/components/ShotDisplay.tsx @@ -1,39 +1,17 @@ -import { Card, Flex, Inset, Separator, Text } from '@radix-ui/themes'; +import { Box, Flex, Text } from '@radix-ui/themes'; import { Html } from '@react-three/drei'; import { useFrame } from '@react-three/fiber'; import { ComponentProps, useRef } from 'react'; import { Euler, Mesh, Quaternion } from 'three'; -import { radToDeg } from 'three/src/math/MathUtils'; import { J_HAT } from '../../../constants/axis'; import { - ShotLayer, ShotLayerNonExternal, ShotStatus, useTankopediaTemporary, } from '../../../stores/tankopedia'; -import { ArmorType } from './SpacedArmorScene'; -import { ExternalModuleVariant } from './SpacedArmorSceneComponent'; +import { ShotDisplayCard } from './ShotDisplayCard'; -const layerTypeNames: Record = { - [ArmorType.Core]: 'Core', - [ArmorType.Spaced]: 'Spaced', - [ArmorType.External]: 'External', - null: 'Gap', -}; - -const externalLayerNames: Record = { - gun: 'Gun', - track: 'Tracks', -}; - -const shotStatusNames: Record = { - blocked: 'Blocked', - ricochet: 'Ricochet', - penetration: 'penetration', - splash: 'splash', -}; - -const shotStatusColors: Record< +export const shotStatusColors: Record< ShotStatus, ComponentProps['color'] > = { @@ -44,93 +22,10 @@ const shotStatusColors: Record< }; const SURFACE_POINT_SIZE = 12; -const LENGTH_INFINITY = 4; +export const SHOT_DISPLAY_LENGTH_INFINITY = 4; const TRACER_THICK = 1 / 32; const TRACER_THIN = TRACER_THICK / 2; -function LayerEntry({ - layerIndex, - shotStatusColor, - layerName, - layer, - angle, -}: { - layerIndex?: string; - shotStatusColor: ComponentProps['color']; - layerName: string; - layer: ShotLayer; - angle?: number; -}) { - return ( - - - {layerIndex} - - - {layerName} - - - {layer.type === null && ( - <> - - {Math.round(layer.distance * 1000).toLocaleString()} - mm - - - - {Math.max(-100, Math.round(-50 * layer.distance))}% penetration - - - )} - - {layer.type === ArmorType.External && ( - - {Math.round(layer.thickness).toLocaleString()} - mm - - )} - - {(layer.type === ArmorType.Core || layer.type === ArmorType.Spaced) && ( - <> - - {Math.round(layer.thicknessAngled).toLocaleString()} - {`mm${angle === undefined ? '' : ` ${Math.round(radToDeg(angle))}°`}`} - - - - {Math.round(layer.thickness).toLocaleString()} - mm nominal - - - )} - - ); -} - export function ShotDisplay() { const shot = useTankopediaTemporary((state) => state.shot); const inTracer = useRef(null); @@ -157,13 +52,13 @@ export function ShotDisplay() { shot.in.layers.reduce((accumulator, layer) => { if (layer.type === null) return accumulator + layer.distance; return accumulator; - }, 0) + LENGTH_INFINITY; + }, 0) + SHOT_DISPLAY_LENGTH_INFINITY; const outLength = shot.out && shot.out.layers.length > 0 ? (shot.in.layers.at(-1) as ShotLayerNonExternal).point.distanceTo( (shot.out.layers.at(-1) as ShotLayerNonExternal).point, ) - : LENGTH_INFINITY; + : SHOT_DISPLAY_LENGTH_INFINITY; const inLast = shot.in.layers.findLast( (layer) => layer.type !== null, ) as ShotLayerNonExternal; @@ -181,122 +76,15 @@ export function ShotDisplay() { transform: 'translateY(-50%)', }} > - - - - - {shot.in.status !== 'blocked' && - shot.in.status !== 'ricochet' && ( - <> - {Math.round(shot.damage).toLocaleString()} - hp - - )} - {` ${shotStatusNames[shot.in.status]} `} - - - - {shot.in.layers.map((layer, index) => { - const layerName = - layer.type === ArmorType.External - ? externalLayerNames[layer.variant] - : layerTypeNames[`${layer.type}`]; - const layerIndex = - layer.type === null - ? undefined - : `${(shot.containsGaps ? index / 2 : index) + 1}.`; - const shotStatusColor = - shot.in.status === 'splash' - ? shotStatusColors.splash - : shotStatusColors[layer.status]; - - return ( - - ); - })} - - - - {shot.out && shot.out.layers.length > 0 && ( - <> - - - - - ricochet (-25% penetration) - - - - - - - {shot.out.status !== 'blocked' && - shot.out.status !== 'ricochet' && ( - <> - {Math.round(shot.damage).toLocaleString()} - hp - - )} - {` ${shotStatusNames[shot.out.status]} `} - - - - {shot.out.layers.map((layer, index) => { - const layerName = - layer.type === ArmorType.External - ? externalLayerNames[layer.variant] - : layerTypeNames[`${layer.type}`]; - const shiftedIndex = index + shot.out!.layers.length; - const layerIndex = - layer.type === null - ? undefined - : `${(shot.containsGaps ? shiftedIndex / 2 : shiftedIndex) + 1}.`; - const shotStatusColor = - shot.out!.status === 'splash' - ? shotStatusColors.splash - : shotStatusColors[layer.status]; - - return ( - - ); - })} - - - )} - - + + + {[...shot.in.layers, ...(shot.out?.layers ?? [])].map((layer, index) => { diff --git a/src/components/Armor/components/ShotDisplayCard.tsx b/src/components/Armor/components/ShotDisplayCard.tsx new file mode 100644 index 000000000..3b67d740a --- /dev/null +++ b/src/components/Armor/components/ShotDisplayCard.tsx @@ -0,0 +1,242 @@ +import { Card, Flex, Inset, Separator, Text } from '@radix-ui/themes'; +import { ComponentProps } from 'react'; +import { radToDeg } from 'three/src/math/MathUtils'; +import { + ShotLayer, + ShotStatus, + useTankopediaTemporary, +} from '../../../stores/tankopedia'; +import { shotStatusColors } from './ShotDisplay'; +import { ArmorType } from './SpacedArmorScene'; +import { ExternalModuleVariant } from './SpacedArmorSceneComponent'; + +const layerTypeNames: Record = { + [ArmorType.Core]: 'Core', + [ArmorType.Spaced]: 'Spaced', + [ArmorType.External]: 'External', + null: 'Gap', +}; + +const externalLayerNames: Record = { + gun: 'Gun', + track: 'Tracks', +}; + +const shotStatusNames: Record = { + blocked: 'Blocked', + ricochet: 'Ricochet', + penetration: 'penetration', + splash: 'splash', +}; + +function LayerEntry({ + layerIndex, + shotStatusColor, + layerName, + layer, + angle, +}: { + layerIndex?: string; + shotStatusColor: ComponentProps['color']; + layerName: string; + layer: ShotLayer; + angle?: number; +}) { + return ( + + + {layerIndex} + + + {layerName} + + + {layer.type === null && ( + <> + + {Math.round(layer.distance * 1000).toLocaleString()} + mm + + + + {Math.max(-100, Math.round(-50 * layer.distance))}% penetration + + + )} + + {layer.type === ArmorType.External && ( + + {Math.round(layer.thickness).toLocaleString()} + mm + + )} + + {(layer.type === ArmorType.Core || layer.type === ArmorType.Spaced) && ( + <> + + {Math.round(layer.thicknessAngled).toLocaleString()} + {`mm${angle === undefined ? '' : ` ${Math.round(radToDeg(angle))}°`}`} + + + + {Math.round(layer.thickness).toLocaleString()} + mm nominal + + + )} + + ); +} + +export function ShotDisplayCard() { + const shot = useTankopediaTemporary((state) => state.shot); + + if (!shot) return null; + + const outTitleColor = shot.out + ? shotStatusColors[shot.out.status] + : undefined; + const inTitleColor = shotStatusColors[shot.in.status]; + + return ( + + + + + {shot.in.status !== 'blocked' && shot.in.status !== 'ricochet' && ( + <> + {Math.round(shot.damage).toLocaleString()} + hp + + )} + {` ${shotStatusNames[shot.in.status]} `} + + + + {shot.in.layers.map((layer, index) => { + const layerName = + layer.type === ArmorType.External + ? externalLayerNames[layer.variant] + : layerTypeNames[`${layer.type}`]; + const layerIndex = + layer.type === null + ? undefined + : `${(shot.containsGaps ? index / 2 : index) + 1}.`; + const shotStatusColor = + shot.in.status === 'splash' + ? shotStatusColors.splash + : shotStatusColors[layer.status]; + + return ( + + ); + })} + + + + {shot.out && shot.out.layers.length > 0 && ( + <> + + + + + ricochet (-25% penetration) + + + + + + + {shot.out.status !== 'blocked' && + shot.out.status !== 'ricochet' && ( + <> + {Math.round(shot.damage).toLocaleString()} + hp + + )} + {` ${shotStatusNames[shot.out.status]} `} + + + + {shot.out.layers.map((layer, index) => { + const layerName = + layer.type === ArmorType.External + ? externalLayerNames[layer.variant] + : layerTypeNames[`${layer.type}`]; + const shiftedIndex = index + shot.out!.layers.length; + const layerIndex = + layer.type === null + ? undefined + : `${(shot.containsGaps ? shiftedIndex / 2 : shiftedIndex) + 1}.`; + const shotStatusColor = + shot.out!.status === 'splash' + ? shotStatusColors.splash + : shotStatusColors[layer.status]; + + return ( + + ); + })} + + + )} + + + ); +} From 4bcd3bffdc844e346abd9950db284e682383909d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 29 Jun 2024 10:37:40 -0500 Subject: [PATCH 04/20] feat: max dispersion --- src/app/tools/compare/page.tsx | 6 ++++++ .../tankopedia/[id]/components/Characteristics/index.tsx | 9 +++++++++ src/core/blitzkit/tankCharacteristics.ts | 9 +++++++++ 3 files changed, 24 insertions(+) diff --git a/src/app/tools/compare/page.tsx b/src/app/tools/compare/page.tsx index 30d002922..6ce7ed92d 100644 --- a/src/app/tools/compare/page.tsx +++ b/src/app/tools/compare/page.tsx @@ -1299,6 +1299,12 @@ export default function Page() { deltaType="lowerIsBetter" decimals={3} /> + diff --git a/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx b/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx index deca9b5df..48fe99abf 100644 --- a/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx +++ b/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx @@ -388,6 +388,15 @@ export function Characteristics() { > {stats.dispersionGunDamaged} + + {stats.maxDispersion} + {stats.gunDepression} diff --git a/src/core/blitzkit/tankCharacteristics.ts b/src/core/blitzkit/tankCharacteristics.ts index dfb22cd42..e8e100213 100644 --- a/src/core/blitzkit/tankCharacteristics.ts +++ b/src/core/blitzkit/tankCharacteristics.ts @@ -364,6 +364,14 @@ export function tankCharacteristics( const shellVelocity = shell.speed * shellVelocityCoefficient; const aimTime = gun.aimTime * aimTimeCoefficient; const dispersion = gun.dispersion.base * dispersionStillCoefficient; + const maxDispersion = + gun.dispersion.base * + Math.sqrt( + ((gun.dispersion.traverse * turret.traverseSpeed) ** 2 + + (track.dispersion.traverse * track.traverseSpeed) ** 2 + + track.dispersion.move * tank.speed.forwards) ** + 2, + ); const dispersionMoving = track.dispersion.move * dispersionMovingCoefficient; const dispersionHullTraversing = track.dispersion.traverse * dispersionHullTraverseCoefficient; @@ -474,6 +482,7 @@ export function tankCharacteristics( shellVelocity, aimTime, dispersion, + maxDispersion, dispersionMoving, dispersionHullTraversing, dispersionTurretTraversing, From 1eddb33380049f8781e23bdbe9038d625acf1f27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 29 Jun 2024 11:41:03 -0500 Subject: [PATCH 05/20] feat: rename fire to firepower --- src/app/tools/compare/page.tsx | 2 +- .../tools/tankopedia/[id]/components/Characteristics/index.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/tools/compare/page.tsx b/src/app/tools/compare/page.tsx index 6ce7ed92d..3e511e3a0 100644 --- a/src/app/tools/compare/page.tsx +++ b/src/app/tools/compare/page.tsx @@ -1211,7 +1211,7 @@ export default function Page() { - Fire + Firepower - Fire + Firepower {gun.shells.map((thisShell, shellIndex) => ( From cf68c9812c78fa6d634e50f28ff19b79165d97e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 29 Jun 2024 11:49:55 -0500 Subject: [PATCH 06/20] feat: move shell selector to firepower header --- src/app/tools/compare/page.tsx | 100 ++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 44 deletions(-) diff --git a/src/app/tools/compare/page.tsx b/src/app/tools/compare/page.tsx index 3e511e3a0..df9b80141 100644 --- a/src/app/tools/compare/page.tsx +++ b/src/app/tools/compare/page.tsx @@ -1160,49 +1160,6 @@ export default function Page() { - - - {gun.shells.map((thisShell, shellIndex) => ( - { - mutateCompareTemporary((draft) => { - draft.members[index].shell = thisShell; - }); - }} - > - {thisShell.name} - - ))} - ); @@ -1211,7 +1168,62 @@ export default function Page() { - Firepower + + + + + Firepower + + + + {members.map(({ gun, shell, key }, index) => ( + + + + {gun.shells.map((thisShell, shellIndex) => ( + { + mutateCompareTemporary((draft) => { + draft.members[index].shell = thisShell; + }); + }} + > + {thisShell.name} + + ))} + + + + ))} + + Date: Sat, 29 Jun 2024 11:57:44 -0500 Subject: [PATCH 07/20] feat: better compare layout --- src/app/tools/compare/page.tsx | 89 ++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 30 deletions(-) diff --git a/src/app/tools/compare/page.tsx b/src/app/tools/compare/page.tsx index df9b80141..ccf01ce94 100644 --- a/src/app/tools/compare/page.tsx +++ b/src/app/tools/compare/page.tsx @@ -178,6 +178,7 @@ export default function Page() { deltaType = 'higherIsBetter', decimals, deltaNominalDisplay, + indent, }: { name: string; value: @@ -191,6 +192,7 @@ export default function Page() { deltaType?: 'higherIsBetter' | 'lowerIsBetter'; decimals?: number; deltaNominalDisplay?: (delta: number) => string | number; + indent?: boolean; }) { const values = stats.map((stat) => typeof value === 'function' ? value(stat)! : (stat[value] as number), @@ -199,7 +201,11 @@ export default function Page() { return ( - + 0 && ( - + - + Maneuverability @@ -1352,17 +1372,19 @@ export default function Page() { decimals={1} /> @@ -1380,19 +1402,21 @@ export default function Page() { /> (stats.camouflageStill * 100).toFixed(0)} deltaNominalDisplay={(delta) => (delta * 100).toFixed(0)} /> (stats.camouflageMoving * 100).toFixed(0)} deltaNominalDisplay={(delta) => (delta * 100).toFixed(0)} /> (stats.camouflageShootingStill * 100).toFixed(0) @@ -1400,7 +1424,8 @@ export default function Page() { deltaNominalDisplay={(delta) => (delta * 100).toFixed(0)} /> (stats.camouflageShootingMoving * 100).toFixed(0) @@ -1408,7 +1433,8 @@ export default function Page() { deltaNominalDisplay={(delta) => (delta * 100).toFixed(0)} /> (stats.camouflageCaughtOnFire * 100).toFixed(0) @@ -1416,29 +1442,32 @@ export default function Page() { deltaNominalDisplay={(delta) => (delta * 100).toFixed(0)} /> + - From 6ef06103318b7664c95a05ef1f7418365368a222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 29 Jun 2024 12:08:42 -0500 Subject: [PATCH 08/20] feat: clipping potential --- src/app/tools/compare/page.tsx | 8 ++++++++ .../tankopedia/[id]/components/Characteristics/index.tsx | 5 +++++ src/core/blitzkit/tankCharacteristics.ts | 2 ++ 3 files changed, 15 insertions(+) diff --git a/src/app/tools/compare/page.tsx b/src/app/tools/compare/page.tsx index ccf01ce94..1d71d1acd 100644 --- a/src/app/tools/compare/page.tsx +++ b/src/app/tools/compare/page.tsx @@ -1261,6 +1261,14 @@ export default function Page() { )} + {hasNonRegularGun && ( + + )} {stats.damage} + {gun.type !== 'regular' && ( + + {stats.clipDamage!} + + )} {stats.moduleDamage} diff --git a/src/core/blitzkit/tankCharacteristics.ts b/src/core/blitzkit/tankCharacteristics.ts index e8e100213..cfe3d0dcd 100644 --- a/src/core/blitzkit/tankCharacteristics.ts +++ b/src/core/blitzkit/tankCharacteristics.ts @@ -359,6 +359,7 @@ export function tankCharacteristics( const penetration = resolveNearPenetration(shell.penetration) * penetrationCoefficient; const damage = shell.damage.armor * damageCoefficient; + const clipDamage = gun.type === 'regular' ? undefined : gun.count * damage; const moduleDamage = shell.damage.module * damageCoefficient; const explosionRadius = shell.explosionRadius; const shellVelocity = shell.speed * shellVelocityCoefficient; @@ -477,6 +478,7 @@ export function tankCharacteristics( caliber, penetration, damage, + clipDamage, moduleDamage, explosionRadius, shellVelocity, From 4bc0a9597373127c50d40ae196cccbb5dc399715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 29 Jun 2024 12:12:10 -0500 Subject: [PATCH 09/20] feat: tank class and icon --- .../[id]/components/Model/HeroSection.tsx | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/app/tools/tankopedia/[id]/components/Model/HeroSection.tsx b/src/app/tools/tankopedia/[id]/components/Model/HeroSection.tsx index bf9f68b85..f2a1482d6 100644 --- a/src/app/tools/tankopedia/[id]/components/Model/HeroSection.tsx +++ b/src/app/tools/tankopedia/[id]/components/Model/HeroSection.tsx @@ -1,6 +1,7 @@ import { ChevronLeftIcon, MixIcon } from '@radix-ui/react-icons'; import { Button, Flex, Heading, Text } from '@radix-ui/themes'; import Link from 'next/link'; +import { classIcons } from '../../../../../../components/ClassIcon'; import { TIER_ROMAN_NUMERALS } from '../../../../../../core/blitzkit/tankDefinitions/constants'; import { useFullScreen } from '../../../../../../hooks/useFullScreen'; import { useWideFormat } from '../../../../../../hooks/useWideFormat'; @@ -11,14 +12,15 @@ import { TankSandbox } from './TankSandbox'; import { Options } from './components/Options'; export function HeroSection() { - const protagonistTank = useDuel((state) => state.protagonist!.tank); - const antagonistTank = useDuel((state) => state.antagonist!.tank); + const protagonist = useDuel((state) => state.protagonist!.tank); + const antagonist = useDuel((state) => state.antagonist!.tank); const wideFormat = useWideFormat(880); const compareTanks = - protagonistTank.id === antagonistTank.id - ? [protagonistTank.id] - : [protagonistTank.id, antagonistTank.id]; + protagonist.id === antagonist.id + ? [protagonist.id] + : [protagonist.id, antagonist.id]; const isFullScreen = useFullScreen(); + const Icon = classIcons[protagonist.class]; return ( - {protagonistTank.nameFull ?? protagonistTank.name} + {' '} + {protagonist.nameFull ?? protagonist.name} - Tier {TIER_ROMAN_NUMERALS[protagonistTank.tier]}{' '} + Tier {TIER_ROMAN_NUMERALS[protagonist.tier]}{' '} { (strings.common.nations_adjectives as Record)[ - protagonistTank.nation + protagonist.nation ] }{' '} - {strings.common.tank_class_short[protagonistTank.class]} + {strings.common.tank_class_short[protagonist.class]} From b032de4a62d6cde3c69821a11a670519f75c0ca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 29 Jun 2024 12:14:34 -0500 Subject: [PATCH 10/20] feat: no default tier --- src/app/tools/tankopedia/components/TankSearch/index.tsx | 3 ++- src/stores/tankopediaFilters.ts | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/tools/tankopedia/components/TankSearch/index.tsx b/src/app/tools/tankopedia/components/TankSearch/index.tsx index c5d9f87f9..fbb7961a9 100644 --- a/src/app/tools/tankopedia/components/TankSearch/index.tsx +++ b/src/app/tools/tankopedia/components/TankSearch/index.tsx @@ -69,7 +69,8 @@ export const TankSearch = memo( (a, b) => awaitedGameDefinitions.nations.indexOf(b.nation) - awaitedGameDefinitions.nations.indexOf(a.nation), - ); + ) + .sort((a, b) => a.tier - b.tier); break; case 'survivability.health': { diff --git a/src/stores/tankopediaFilters.ts b/src/stores/tankopediaFilters.ts index 4d05ace64..0959fb6b8 100644 --- a/src/stores/tankopediaFilters.ts +++ b/src/stores/tankopediaFilters.ts @@ -24,7 +24,6 @@ export const useTankopediaFilters = create()(() => ({ by: 'meta.none', direction: 'descending', }, - tier: 10, searching: false, })); From 5b833bab111f7f113dd099eefbecb850a82654b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 29 Jun 2024 13:15:24 -0500 Subject: [PATCH 11/20] feat: movable tracks --- .vscode/settings.json | 1 + .../tankopedia/[id]/components/Control.tsx | 8 +-- .../components/Model/components/TankModel.tsx | 69 +++++++++++++++---- src/stores/tankopedia.ts | 3 +- 4 files changed, 64 insertions(+), 17 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 923aa3721..110cdf13e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -89,6 +89,7 @@ "lossrate", "mantlets", "metallicness", + "metalness", "minitelrose", "Minotauro", "MIPMAPCOUNT", diff --git a/src/app/tools/tankopedia/[id]/components/Control.tsx b/src/app/tools/tankopedia/[id]/components/Control.tsx index 316d4529d..10ba7cd5a 100644 --- a/src/app/tools/tankopedia/[id]/components/Control.tsx +++ b/src/app/tools/tankopedia/[id]/components/Control.tsx @@ -9,7 +9,7 @@ import { modelDefinitions } from '../../../../../core/blitzkit/modelDefinitions' import { Pose, poseEvent } from '../../../../../core/blitzkit/pose'; import { useAwait } from '../../../../../hooks/useAwait'; import { useDuel } from '../../../../../stores/duel'; -import { useTankopediaPersistent } from '../../../../../stores/tankopedia'; +import { useTankopediaTemporary } from '../../../../../stores/tankopedia'; const poseDistances: Record = { [Pose.HullDown]: 15, @@ -62,8 +62,8 @@ export function Controls() { }, [camera]); useEffect(() => { - const unsubscribeTankopedia = useTankopediaPersistent.subscribe( - (state) => state.model.visual.controlsEnabled, + const unsubscribeTankopedia = useTankopediaTemporary.subscribe( + (state) => state.controlsEnabled, (enabled) => { if (orbitControls.current) orbitControls.current.enabled = enabled; }, @@ -182,7 +182,7 @@ export function Controls() { maxDistance={20} minDistance={5} ref={orbitControls} - enabled={useTankopediaPersistent.getState().model.visual.controlsEnabled} + enabled={useTankopediaTemporary.getState().controlsEnabled} rotateSpeed={0.25} enableDamping={false} autoRotate={autoRotate} diff --git a/src/app/tools/tankopedia/[id]/components/Model/components/TankModel.tsx b/src/app/tools/tankopedia/[id]/components/Model/components/TankModel.tsx index 34928bb07..17e8c53da 100644 --- a/src/app/tools/tankopedia/[id]/components/Model/components/TankModel.tsx +++ b/src/app/tools/tankopedia/[id]/components/Model/components/TankModel.tsx @@ -1,6 +1,13 @@ import { ThreeEvent, useThree } from '@react-three/fiber'; import { memo, useEffect, useRef } from 'react'; -import { Euler, Group, Vector2, Vector3 } from 'three'; +import { + Euler, + Group, + Mesh, + MeshStandardMaterial, + Vector2, + Vector3, +} from 'three'; import { degToRad } from 'three/src/math/MathUtils'; import { I_HAT, J_HAT, K_HAT } from '../../../../../../../constants/axis'; import { applyPitchYawLimits } from '../../../../../../../core/blitz/applyPitchYawLimits'; @@ -15,9 +22,7 @@ import { normalizeAngleRad } from '../../../../../../../core/math/normalizeAngle import { useAwait } from '../../../../../../../hooks/useAwait'; import { useModel } from '../../../../../../../hooks/useModel'; import { mutateDuel, useDuel } from '../../../../../../../stores/duel'; -import mutateTankopediaPersistent, { - mutateTankopediaTemporary, -} from '../../../../../../../stores/tankopedia'; +import { mutateTankopediaTemporary } from '../../../../../../../stores/tankopedia'; export const TankModel = memo(() => { const awaitedModelDefinitions = useAwait(modelDefinitions); @@ -117,11 +122,51 @@ export const TankModel = memo(() => { const isWheel = node.name.startsWith('chassis_wheel_'); const isTrack = node.name.startsWith('chassis_track_'); const isVisible = isHull || isWheel || isTrack; + const position = new Vector2(); + const delta = new Vector2(); if (!isVisible) return null; + function translateTexture(offset: number) { + const mesh = node.children[0] as Mesh; + const material = mesh?.material as MeshStandardMaterial; + + if (!material) return; + + if (material.map) material.map.offset.y += offset; + if (material.aoMap) material.aoMap.offset.y += offset; + if (material.normalMap) material.normalMap.offset.y += offset; + if (material.roughnessMap) material.roughnessMap.offset.y += offset; + if (material.metalnessMap) material.metalnessMap.offset.y += offset; + } + function onPointerDown(event: ThreeEvent) { + if (!isTrack) return; + event.stopPropagation(); + + mutateTankopediaTemporary((draft) => { + draft.controlsEnabled = false; + }); + + window.addEventListener('pointermove', handlePointerMove); + window.addEventListener('pointerup', handlePointerUp); + } + function handlePointerMove(event: PointerEvent) { + delta.set(event.clientX, event.clientY).sub(position); + position.set(event.clientX, event.clientY); + const deltaX = delta.x / window.innerWidth; + const deltaY = delta.y / window.innerHeight; + + translateTexture(deltaX + deltaY); + } + function handlePointerUp() { + mutateTankopediaTemporary((draft) => { + draft.controlsEnabled = true; + }); + + window.removeEventListener('pointermove', handlePointerMove); + window.removeEventListener('pointerup', handlePointerUp); } return jsxTree( @@ -158,8 +203,8 @@ export const TankModel = memo(() => { yaw = protagonist.yaw; pitch = protagonist.pitch; - mutateTankopediaPersistent((draft) => { - draft.model.visual.controlsEnabled = false; + mutateTankopediaTemporary((draft) => { + draft.controlsEnabled = false; }); mutateTankopediaTemporary((draft) => { draft.shot = undefined; @@ -194,8 +239,8 @@ export const TankModel = memo(() => { draft.protagonist!.pitch = normalizeAngleRad(pitch); draft.protagonist!.yaw = normalizeAngleRad(yaw); }); - mutateTankopediaPersistent((draft) => { - draft.model.visual.controlsEnabled = true; + mutateTankopediaTemporary((draft) => { + draft.controlsEnabled = true; }); window.removeEventListener('pointermove', handlePointerMove); window.removeEventListener('pointerup', handlePointerUp); @@ -234,8 +279,8 @@ export const TankModel = memo(() => { function onPointerDown(event: ThreeEvent) { event.stopPropagation(); - mutateTankopediaPersistent((draft) => { - draft.model.visual.controlsEnabled = false; + mutateTankopediaTemporary((draft) => { + draft.controlsEnabled = false; }); mutateTankopediaTemporary((draft) => { draft.shot = undefined; @@ -269,8 +314,8 @@ export const TankModel = memo(() => { modelTransformEvent.emit({ pitch, yaw }); } function handlePointerUp() { - mutateTankopediaPersistent((draft) => { - draft.model.visual.controlsEnabled = true; + mutateTankopediaTemporary((draft) => { + draft.controlsEnabled = true; }); mutateDuel((draft) => { draft.protagonist!.pitch = normalizeAngleRad(pitch); diff --git a/src/stores/tankopedia.ts b/src/stores/tankopedia.ts index 4cdd1da0e..88d746e77 100644 --- a/src/stores/tankopedia.ts +++ b/src/stores/tankopedia.ts @@ -20,7 +20,6 @@ export interface TankopediaPersistent { wireframe: boolean; opaque: boolean; environment: (typeof ENVIRONMENTS)[number]; - controlsEnabled: boolean; showGrid: boolean; greenPenetration: boolean; showEnvironment: boolean; @@ -45,6 +44,7 @@ export interface TankopediaPersistent { interface TankopediaTemporary { shot?: Shot; skills: Record; + controlsEnabled: boolean; } export interface ShotLayerBase { @@ -199,6 +199,7 @@ export const useTankopediaPersistent = create()( export const useTankopediaTemporary = create()( subscribeWithSelector(() => ({ skills: {}, + controlsEnabled: true, })), ); From 5474cc8d9e24d350bc4672a5e5eaf2fbb93dd482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 29 Jun 2024 13:18:10 -0500 Subject: [PATCH 12/20] fix: pointer jump --- .../tankopedia/[id]/components/Model/components/TankModel.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/tools/tankopedia/[id]/components/Model/components/TankModel.tsx b/src/app/tools/tankopedia/[id]/components/Model/components/TankModel.tsx index 17e8c53da..60f5c7531 100644 --- a/src/app/tools/tankopedia/[id]/components/Model/components/TankModel.tsx +++ b/src/app/tools/tankopedia/[id]/components/Model/components/TankModel.tsx @@ -143,6 +143,7 @@ export const TankModel = memo(() => { function onPointerDown(event: ThreeEvent) { if (!isTrack) return; + position.set(event.clientX, event.clientY); event.stopPropagation(); mutateTankopediaTemporary((draft) => { From 11cca03f2c4fbb58003a0063c6a5922c0f73baa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 29 Jun 2024 13:20:36 -0500 Subject: [PATCH 13/20] feat: open in new tab tank compare --- src/app/tools/compare/components/TankControl.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/tools/compare/components/TankControl.tsx b/src/app/tools/compare/components/TankControl.tsx index 423cfe95d..db2fdb73d 100644 --- a/src/app/tools/compare/components/TankControl.tsx +++ b/src/app/tools/compare/components/TankControl.tsx @@ -66,7 +66,7 @@ export function TankControl({ index, id }: TankControlProps) { - + From 1dc85253c908c2be2345ebff6c8c2198c42be455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 29 Jun 2024 13:25:59 -0500 Subject: [PATCH 14/20] feat: terrain coefficients --- src/app/tools/compare/page.tsx | 17 +++++++++++ .../[id]/components/Characteristics/index.tsx | 10 +++++++ src/core/blitzkit/tankCharacteristics.ts | 30 +++++++++---------- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/src/app/tools/compare/page.tsx b/src/app/tools/compare/page.tsx index 1d71d1acd..c77980687 100644 --- a/src/app/tools/compare/page.tsx +++ b/src/app/tools/compare/page.tsx @@ -1357,6 +1357,23 @@ export default function Page() { /> + + + {stats.weight} + + + {stats.hardTerrainCoefficient} + + + {stats.mediumTerrainCoefficient} + + + {stats.softTerrainCoefficient} + {stats.powerToWeightRatioHardTerrain} diff --git a/src/core/blitzkit/tankCharacteristics.ts b/src/core/blitzkit/tankCharacteristics.ts index cfe3d0dcd..db008e97a 100644 --- a/src/core/blitzkit/tankCharacteristics.ts +++ b/src/core/blitzkit/tankCharacteristics.ts @@ -405,40 +405,37 @@ export function tankCharacteristics( const speedForwards = tank.speed.forwards + speedForwardsSum; const speedBackwards = tank.speed.backwards + speedBackwardsSum; const enginePower = resolvedEnginePower; + const hardTerrainCoefficient = + track.resistance.hard * resistanceHardCoefficient; + const mediumTerrainCoefficient = + track.resistance.medium * resistanceMediumCoefficient; + const softTerrainCoefficient = + track.resistance.soft * resistanceSoftCoefficient; const powerToWeightRatioHardTerrain = - resolvedEnginePower / - weightTons / - (track.resistance.hard * resistanceHardCoefficient); + resolvedEnginePower / weightTons / hardTerrainCoefficient; const powerToWeightRatioMediumTerrain = - resolvedEnginePower / - weightTons / - (track.resistance.medium * resistanceMediumCoefficient); + resolvedEnginePower / weightTons / mediumTerrainCoefficient; const powerToWeightRatioSoftTerrain = - resolvedEnginePower / - weightTons / - (track.resistance.soft * resistanceSoftCoefficient); + resolvedEnginePower / weightTons / softTerrainCoefficient; const weight = weightTons; const turretTraverseSpeed = turret.traverseSpeed * turretTraverseCoefficient; const hullTraverseHardTerrain = (resolvedEnginePower / stockEngine.power) * track.traverseSpeed * hullTraverseCoefficient * - (track.resistance.hard / - (track.resistance.hard * resistanceHardCoefficient)) * + (track.resistance.hard / hardTerrainCoefficient) * (stockWeight / weightKg); const hullTraverseMediumTerrain = (resolvedEnginePower / stockEngine.power) * track.traverseSpeed * hullTraverseCoefficient * - (track.resistance.hard / - (track.resistance.medium * resistanceMediumCoefficient)) * + (track.resistance.hard / mediumTerrainCoefficient) * (stockWeight / weightKg); const hullTraverseSoftTerrain = (resolvedEnginePower / stockEngine.power) * track.traverseSpeed * hullTraverseCoefficient * - (track.resistance.hard / - (track.resistance.soft * resistanceSoftCoefficient)) * + (track.resistance.hard / softTerrainCoefficient) * (stockWeight / weightKg); const health = (tank.health + turret.health) * healthCoefficient; const fireChance = engine.fireChance * fireChanceCoefficient; @@ -500,6 +497,9 @@ export function tankCharacteristics( azimuthRight, speedForwards, speedBackwards, + hardTerrainCoefficient, + mediumTerrainCoefficient, + softTerrainCoefficient, enginePower, powerToWeightRatioHardTerrain, powerToWeightRatioMediumTerrain, From bb561847ada740b60872b98d3b73fb18d4f6a63e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 29 Jun 2024 13:29:43 -0500 Subject: [PATCH 15/20] feat: premium dpm --- src/app/tools/tankopedia/components/Sort.tsx | 12 +++++++++++- .../tools/tankopedia/components/TankCard.tsx | 2 ++ .../tankopedia/components/TankSearch/index.tsx | 18 ++++++++++++++++++ src/stores/tankopedia.ts | 4 +++- 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/app/tools/tankopedia/components/Sort.tsx b/src/app/tools/tankopedia/components/Sort.tsx index e0a50f4a8..00727a65f 100644 --- a/src/app/tools/tankopedia/components/Sort.tsx +++ b/src/app/tools/tankopedia/components/Sort.tsx @@ -43,7 +43,17 @@ export function Sort() { }); }} > - DPM + Standard DPM + + { + mutateTankopediaFilters((draft) => { + draft.sort.by = 'fire.dpmPremium'; + }); + }} + > + Premium DPM ( ); break; + case 'fire.dpmPremium': + sorted = filtered.sort( + (a, b) => + (a.turrets.at(-1)!.guns.at(-1)!.shells[1] + ? resolveDpm( + a.turrets.at(-1)!.guns.at(-1)!, + a.turrets.at(-1)!.guns.at(-1)!.shells[1], + ) + : 0) - + (b.turrets.at(-1)!.guns.at(-1)!.shells[1] + ? resolveDpm( + b.turrets.at(-1)!.guns.at(-1)!, + b.turrets.at(-1)!.guns.at(-1)!.shells[1], + ) + : 0), + ); + break; + case 'fire.reload': sorted = filtered.sort( (a, b) => diff --git a/src/stores/tankopedia.ts b/src/stores/tankopedia.ts index 88d746e77..97f4e2af1 100644 --- a/src/stores/tankopedia.ts +++ b/src/stores/tankopedia.ts @@ -114,7 +114,8 @@ export const SORT_NAMES = { 'survivability.camouflageShooting': 'camouflage shooting', 'survivability.volume': 'volume', 'survivability.length': 'length', - 'fire.dpm': 'DPM', + 'fire.dpm': 'standard DPM', + 'fire.dpmPremium': 'premium DPM', 'fire.reload': 'reload', 'fire.caliber': 'caliber', 'fire.standardPenetration': 'standard penetration', @@ -143,6 +144,7 @@ export const SORT_UNITS: Record = { 'fire.dispersionMoving': 'm', 'fire.dispersionStill': 'm', 'fire.dpm': undefined, + 'fire.dpmPremium': undefined, 'fire.gunDepression': '°', 'fire.gunElevation': '°', 'fire.premiumPenetration': 'mm', From f002c23e702b86444c8f5941c6dc70bd3b27ca54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 29 Jun 2024 13:32:57 -0500 Subject: [PATCH 16/20] fix: omit ricochet for explosive shells --- src/core/blitzkit/tankCharacteristics.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/blitzkit/tankCharacteristics.ts b/src/core/blitzkit/tankCharacteristics.ts index db008e97a..9c6dedf50 100644 --- a/src/core/blitzkit/tankCharacteristics.ts +++ b/src/core/blitzkit/tankCharacteristics.ts @@ -1,4 +1,5 @@ import { EquipmentMatrix } from '../../stores/duel'; +import { isExplosive } from '../blitz/isExplosive'; import { resolveNearPenetration } from '../blitz/resolveNearPenetration'; import { resolvePenetrationCoefficient } from '../blitz/resolvePenetrationCoefficient'; import { coefficient } from './coefficient'; @@ -459,7 +460,7 @@ export function tankCharacteristics( const length = size[1]; const volume = width * height * length; const shellNormalization = shell.normalization ?? 0; - const shellRicochet = shell.ricochet; + const shellRicochet = isExplosive(shell.type) ? undefined : shell.ricochet; return { shellNormalization, From 47c3b2de0e723feabc871110e5b10f226a954aea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 29 Jun 2024 13:35:06 -0500 Subject: [PATCH 17/20] fix: mino line depression disparity on live updates --- .../tools/tankopedia/[id]/components/QuickInputs/index.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/tools/tankopedia/[id]/components/QuickInputs/index.tsx b/src/app/tools/tankopedia/[id]/components/QuickInputs/index.tsx index ffeb8e8ef..6983b22e1 100644 --- a/src/app/tools/tankopedia/[id]/components/QuickInputs/index.tsx +++ b/src/app/tools/tankopedia/[id]/components/QuickInputs/index.tsx @@ -38,7 +38,9 @@ export function RotationInputs() { function handleTransformEvent({ pitch, yaw }: ModelTransformEventData) { if (!pitchInput.current || !yawInput.current) return; - pitchInput.current.value = (-radToDeg(pitch)).toFixed(1); + pitchInput.current.value = ( + -radToDeg(pitch) + (tankModelDefinition.turretRotation?.pitch ?? 0) + ).toFixed(1); if (yaw === undefined) return; From 1ad75d8dc54a8b71d8fb2dfeedb0e682242ece67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 29 Jun 2024 13:37:53 -0500 Subject: [PATCH 18/20] fix: remove autofocus in signin popup --- src/components/Navbar/index.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/Navbar/index.tsx b/src/components/Navbar/index.tsx index 7dce4f7c9..50efdd3b5 100644 --- a/src/components/Navbar/index.tsx +++ b/src/components/Navbar/index.tsx @@ -143,7 +143,11 @@ export default function Navbar() { - + event.preventDefault()} + > {(logins.patreon || logins.wargaming) && ( From 63a608b3dfe64c047871fcf7a99158bf4d231ef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 29 Jun 2024 13:40:38 -0500 Subject: [PATCH 19/20] fix: handle non-ok repsoness --- src/hooks/useAdExempt.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hooks/useAdExempt.ts b/src/hooks/useAdExempt.ts index bd3b55299..b1d7bf49e 100644 --- a/src/hooks/useAdExempt.ts +++ b/src/hooks/useAdExempt.ts @@ -15,6 +15,9 @@ export function useAdExempt() { `/api/patreon/membership/${patreon.token}`, { cache: 'force-cache' }, ); + + if (!response.ok) return resolve(false); + const json = await response.json(); const exempt = typeof json === 'boolean' && json; cache[patreon.token] = exempt; From 51da286dc7762f4f5d31f8f5f28dc2f55318ffc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Mon, 1 Jul 2024 20:29:42 -0500 Subject: [PATCH 20/20] feat: logs --- docs/changelogs/1.20.5.md | 28 ++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 docs/changelogs/1.20.5.md diff --git a/docs/changelogs/1.20.5.md b/docs/changelogs/1.20.5.md new file mode 100644 index 000000000..8a6f4ca1f --- /dev/null +++ b/docs/changelogs/1.20.5.md @@ -0,0 +1,28 @@ +# BlitzKit 1.20.5 + +Some QOL changes incoming! + +## Changes + +- The penetration of the shooter is now displayed above the shell switcher +- The shot display card is now shown below the tank instead of to the side on narrow screens +- Added a few more stats to Compare and Tankopedia + - Max dispersion + - Clipping potential for auto-loaders and auto-reloaders + - Raw terrain resistance coefficients +- Renamed the "Fire" section to "Firepower" +- The shell selector for the protagonist tank has been moved to the Firepower section's title +- The table layout of Compare has been compacted and indented in places +- The tank class and type has now displayed in the hero section of the Tankopedia +- Removed the default tier X filter +- Added draggable tracks +- Added the ability to sort by premium shell DPM + +## Fixes + +- Clicking enter no longer changes the tank you're viewing when selecting the shooter tank +- The open in new tab button in Compare now opens in a new tab +- HEAT shells no longer display ricochet angle +- The gun depression is now properly reported for the Minotauro line +- Stopped autofocus of the ghost button in the login card +- Patreon login now handles bad responses diff --git a/package.json b/package.json index a32ba8b2e..e5375c4c9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "blitzkit", - "version": "1.20.4", + "version": "1.20.5", "description": "🎉 Tools for everything World of Tanks Blitz", "main": "src/server.ts", "type": "module",