From e5e2f2505cdbb3a416986987aa614bda7c65304e Mon Sep 17 00:00:00 2001 From: Mark Greene Date: Sun, 4 Oct 2026 14:50:10 +1300 Subject: [PATCH 01/36] Fix: static armor controls peeking in at the screen edge The static armor panel hid itself with a fixed `right: -6rem`. In languages with longer labels (e.g. Spanish) the panel is wider than that, so part of it stayed visible at the edge. Anchor the panel at `right: 0` and slide it out with a transform based on its own width (`translateX(calc(100% + var(--space-4)))`) when static armor isn't active, so it always clears the edge regardless of label length. --- .../HeroSection/components/Options/components/Thicknesses.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/Options/components/Thicknesses.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/Options/components/Thicknesses.tsx index 7fdb09d73..a5621bd97 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/Options/components/Thicknesses.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/Options/components/Thicknesses.tsx @@ -31,11 +31,11 @@ export function Thicknesses({ thicknessRange, skeleton }: ThicknessesProps) { return ( Date: Sun, 4 Oct 2026 15:17:51 +1300 Subject: [PATCH 02/36] Fix: mixer buttons clipping at the screen edges on small phones The mixer's hull/turret/gun row is about 440px wide at its fixed sizes and is centered with `left: 50%` and `translateX(-50%)`, so on phones narrower than that it overflowed past both edges. Use smaller button sizes on phones and scale the tank images with the viewport (`clamp(2rem, 11vw, 4em)`), with smaller separators and gaps. From 520px up the layout is unchanged. --- .../[...locale]/mixer/_index.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/website/src/pages/[...chunk_default]/[...locale]/mixer/_index.tsx b/packages/website/src/pages/[...chunk_default]/[...locale]/mixer/_index.tsx index 2346fc2d9..ebd83ff62 100644 --- a/packages/website/src/pages/[...chunk_default]/[...locale]/mixer/_index.tsx +++ b/packages/website/src/pages/[...chunk_default]/[...locale]/mixer/_index.tsx @@ -94,7 +94,7 @@ function ModuleChooser({ - + Date: Sun, 4 Oct 2026 19:47:20 +1300 Subject: [PATCH 03/36] Fix: restore redirect to the user's preferred locale Users were no longer sent to their preferred locale. `LocaleRedirector` was emptied in `115fa5aca` after its previous versions caused repeated redirects, and nothing replaced it. **Cause** - The earlier logic compared the best locale (a string) against the current locale entry (an object), so the check was always true on non-default locale pages - That made the redirect fire repeatedly, which led to the logic being removed entirely **Changes** - Derive the current locale from the URL, treating the default locale as unprefixed to match how pages are generated - Redirect only when the best locale differs from the current locale, so it stops after one hop - Redirect users with a saved `preferred-locale` from any page - Redirect users without a saved preference from default-locale URLs only, using their browser language, so shared locale links are respected - Preserve the rest of the path when swapping the locale prefix - Skip `/api` paths --- .../src/components/LocaleRedirector.astro | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/packages/website/src/components/LocaleRedirector.astro b/packages/website/src/components/LocaleRedirector.astro index e4ed25333..80c0afeaa 100644 --- a/packages/website/src/components/LocaleRedirector.astro +++ b/packages/website/src/components/LocaleRedirector.astro @@ -1,3 +1,30 @@ From c2c586c2e7e46f47e2481fb8d313d642c0027343 Mon Sep 17 00:00:00 2001 From: Mark Greene Date: Sun, 4 Oct 2026 20:00:51 +1300 Subject: [PATCH 04/36] Fix: scroll track textures at the same rate Dragging a tank's track scrolled its roughness/metalness texture at twice the speed of the base color and normal textures, so highlights drifted off the track links. **Cause** - `translateTexture` added the scroll offset to `roughnessMap` and `metalnessMap` separately - glTF has a single metallic-roughness texture, and the loader assigns that same texture object to both slots, so it received the offset twice **Changes** - Collect the track's maps in a `Set` before scrolling so a texture shared between slots is offset exactly once --- .../TankSandbox/components/TankModel.tsx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/TankModel.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/TankModel.tsx index ded24bba1..c74722bff 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/TankModel.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/TankModel.tsx @@ -51,11 +51,17 @@ export function TankModel() { invalidate(); - 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; + const textures = new Set([ + material.map, + material.aoMap, + material.normalMap, + material.roughnessMap, + material.metalnessMap, + ]); + + for (const texture of textures) { + if (texture) texture.offset.y += offset; + } } function onPointerDown(event: ThreeEvent) { From fbba0bf13bd927d15cc22d2223f28a12432ac5c9 Mon Sep 17 00:00:00 2001 From: Mark Greene Date: Sun, 4 Oct 2026 20:07:52 +1300 Subject: [PATCH 05/36] Fix: constrain playlist filter width The filters on the playlist page stretched into one long strip beside the tank pool, squeezing the pool into the remaining space. **Changes** - Place the filters and the generate button in a fixed-width column (`22rem`) on medium screens and up so the filter buttons wrap compactly - Stretch the generate button to the column width - Let the tank pool take the remaining width - Tighten the gap between the two columns - Keep the existing stacked layout on small screens --- packages/website/src/components/PlaylistGenerator.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/website/src/components/PlaylistGenerator.tsx b/packages/website/src/components/PlaylistGenerator.tsx index c533495ca..b50c74654 100644 --- a/packages/website/src/components/PlaylistGenerator.tsx +++ b/packages/website/src/components/PlaylistGenerator.tsx @@ -25,6 +25,7 @@ import { FilterControl } from "./TankSearch/components/FilterControl"; const tankDefinitions = await api.tankDefinitions(); const POOL_HEIGHT = "16rem"; +const FILTERS_WIDTH = "22rem"; export function PlaylistGenerator({ skeleton }: MaybeSkeletonComponentProps) { const [largeWarningOpen, setLargeWarningOpen] = useState(false); @@ -80,13 +81,19 @@ export function PlaylistGenerator({ skeleton }: MaybeSkeletonComponentProps) { - + + + )} ); } diff --git a/packages/website/src/components/Tankopedia/HeroSection/index.tsx b/packages/website/src/components/Tankopedia/HeroSection/index.tsx index 11f13d58e..51205fb49 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/index.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/index.tsx @@ -1,6 +1,6 @@ import { Box, Flex } from "@radix-ui/themes"; import { times } from "lodash-es"; -import { useEffect, useMemo, useRef } from "react"; +import { Suspense, useEffect, useMemo, useRef } from "react"; import { api } from "../../../core/blitzkit/api"; import { defaultEqualizer } from "../../../core/blitzkit/tankToDuelMember"; import { useFullScreen } from "../../../hooks/useFullScreen"; @@ -20,6 +20,7 @@ export function HeroSection({ skeleton }: MaybeSkeletonComponentProps) { const canvas = useRef(null!); const isFullScreen = useFullScreen(); const protagonist = Duel.use((state) => state.protagonist.tank); + const modelRequested = Tankopedia.use((state) => state.modelRequested); const thicknessRange = useMemo(() => { const entries = Object.values(tankDefinitions.tanks); const filtered = entries.filter( @@ -131,13 +132,15 @@ export function HeroSection({ skeleton }: MaybeSkeletonComponentProps) { top="0" left="0" > - {!skeleton && ( - + {!skeleton && modelRequested && ( + + + )} - + <Title skeleton={skeleton} /> <Options skeleton={skeleton} diff --git a/packages/website/src/hooks/useStableProgress.ts b/packages/website/src/hooks/useStableProgress.ts index 332ded1d0..396136e51 100644 --- a/packages/website/src/hooks/useStableProgress.ts +++ b/packages/website/src/hooks/useStableProgress.ts @@ -3,11 +3,13 @@ import { useRef } from "react"; export function useStableProgress() { const { loaded, total } = useProgress(); + const baseline = useRef(loaded); const progress = useRef(0); + const pending = total - baseline.current; progress.current = Math.max( progress.current, - total === 0 ? 0 : (loaded / total) * 100 + pending <= 0 ? 0 : ((loaded - baseline.current) / pending) * 100 ); return progress.current; diff --git a/packages/website/src/pages/[...chunk_default]/[...locale]/settings/_index.tsx b/packages/website/src/pages/[...chunk_default]/[...locale]/settings/_index.tsx index c5054b676..374d24198 100644 --- a/packages/website/src/pages/[...chunk_default]/[...locale]/settings/_index.tsx +++ b/packages/website/src/pages/[...chunk_default]/[...locale]/settings/_index.tsx @@ -18,6 +18,10 @@ export function Page({ locale }: LocaleAcceptorProps) { function Content({ locale }: LocaleAcceptorProps) { const developerMode = App.useDeferred((state) => state.developerMode, false); + const autoLoadModels = App.useDeferred( + (state) => state.autoLoadModels, + true, + ); const { strings } = useLocale(); return ( @@ -36,6 +40,19 @@ function Content({ locale }: LocaleAcceptorProps) { /> </Flex> + <Flex align="center" gap="2" justify="between"> + <Text>{strings.website.settings.auto_load_models}</Text> + <Switch + variant="classic" + checked={autoLoadModels} + onCheckedChange={(checked) => + App.mutate((draft) => { + draft.autoLoadModels = checked; + }) + } + /> + </Flex> + <Flex align="center" gap="2" justify="between"> <Text>{strings.website.settings.language}</Text> <LocaleSwitcher locale={locale} /> diff --git a/packages/website/src/stores/app/index.ts b/packages/website/src/stores/app/index.ts index 6b15394f2..ba975056c 100644 --- a/packages/website/src/stores/app/index.ts +++ b/packages/website/src/stores/app/index.ts @@ -8,6 +8,7 @@ export interface WargamingLogin { export interface App { developerMode: boolean; + autoLoadModels: boolean; policiesAgreementIndex: number; logins: { wargaming?: WargamingLogin; @@ -17,6 +18,7 @@ export interface App { export const App = new Varuna<App>( { developerMode: false, + autoLoadModels: true, policiesAgreementIndex: -1, logins: {}, }, diff --git a/packages/website/src/stores/tankopedia.ts b/packages/website/src/stores/tankopedia.ts index d2eb8a066..023ab0e87 100644 --- a/packages/website/src/stores/tankopedia.ts +++ b/packages/website/src/stores/tankopedia.ts @@ -9,6 +9,7 @@ import type { ArmorType } from "../components/Armor/components/SpacedArmorScene" import type { ExternalModuleVariant } from "../components/Armor/components/SpacedArmorSceneComponent"; import type { XP_MULTIPLIERS } from "../components/Tankopedia/TechTreeSection"; import { api } from "../core/blitzkit/api"; +import { App } from "./app"; import { TankopediaDisplay } from "./tankopediaPersistent/constants"; export interface ShotLayerBase { @@ -79,6 +80,7 @@ export enum TankopediaRelativeAgainst { interface Tankopedia { disturbed: boolean; revealed: boolean; + modelRequested: boolean; shot?: Shot; skills: Record<string, number>; relativeAgainst: TankopediaRelativeAgainst; @@ -110,6 +112,7 @@ const skillDefinitions = await api.skillDefinitions(); export const Tankopedia = new Varuna<Tankopedia, ModelDefinition>((model) => ({ disturbed: false, revealed: false, + modelRequested: App.state.autoLoadModels, relativeAgainst: TankopediaRelativeAgainst.Class, editStatic: false, skills: createDefaultSkills(skillDefinitions), From 5ce927be4e8748861fa7b5c41a27963c7085501f Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Wed, 7 Oct 2026 10:14:44 -0500 Subject: [PATCH 13/36] force bun even with node installed --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 979a37799..3b4791010 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "license": "BlitzKit License", "private": true, "scripts": { - "dev": "cd packages/website && bun run dev", + "dev": "cd packages/website && bun --bun run dev", "build": "cd packages/website && bun run build", "discover-ids": "cd packages/scripts && bun run discover-ids", "build-protos": "cd packages/scripts && bun run build-protos", From 00149a3d9d8a0d9aad1ebbbfb372d703ff4885bc Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Wed, 7 Oct 2026 16:03:41 -0500 Subject: [PATCH 14/36] simplify strings --- packages/i18n/strings/en.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/i18n/strings/en.json b/packages/i18n/strings/en.json index c610ad57e..04125f138 100644 --- a/packages/i18n/strings/en.json +++ b/packages/i18n/strings/en.json @@ -215,7 +215,7 @@ "title": "Settings", "description": "Change BlitzKit settings", "dev_mode": "Development mode", - "auto_load_models": "Automatically load 3D models", + "auto_load_models": "Auto-load models", "language": "Language" }, @@ -459,7 +459,7 @@ }, "sandbox": { - "load_model": "Load 3D model", + "load_model": "Load model", "poses": { "hull_down": "Hull down", From e1b079ca02c233de57ddbb5047f5e763bd68dc67 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Wed, 7 Oct 2026 16:06:52 -0500 Subject: [PATCH 15/36] high contrast button --- .../HeroSection/components/TankSandbox/Title/index.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/Title/index.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/Title/index.tsx index b3dab3aaf..69f7a0193 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/Title/index.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/Title/index.tsx @@ -81,8 +81,7 @@ export function Title({ skeleton }: MaybeSkeletonComponentProps) { }} > <Button - variant="surface" - color="gray" + variant="solid" highContrast onPointerDown={(event) => event.stopPropagation()} onClick={() => { From 16be5faae6516e4ba1a5bf8adc68b1ff4a5ef615 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Wed, 7 Oct 2026 16:08:56 -0500 Subject: [PATCH 16/36] use UpdateIcon --- .../HeroSection/components/TankSandbox/Title/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/Title/index.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/Title/index.tsx index 69f7a0193..d31db7a1f 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/Title/index.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/Title/index.tsx @@ -1,4 +1,4 @@ -import { DownloadIcon } from "@radix-ui/react-icons"; +import { UpdateIcon } from "@radix-ui/react-icons"; import { Button, Flex, Heading } from "@radix-ui/themes"; import { useLocale } from "../../../../../../hooks/useLocale"; import { Duel } from "../../../../../../stores/duel"; @@ -90,7 +90,7 @@ export function Title({ skeleton }: MaybeSkeletonComponentProps) { }); }} > - <DownloadIcon /> + <UpdateIcon /> {strings.website.tools.tankopedia.sandbox.load_model} </Button> </Flex> From d4e649804e1a35d740fbd791f675c8ba430b387a Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Wed, 7 Oct 2026 16:15:07 -0500 Subject: [PATCH 17/36] add astro cleaning script --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 3b4791010..d9bc165ba 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "discover-ids": "cd packages/scripts && bun run discover-ids", "build-protos": "cd packages/scripts && bun run build-protos", "record-performance": "cd packages/scripts && bun run record-performance", - "download-client": "cd packages/scripts && bun run download-client" + "download-client": "cd packages/scripts && bun run download-client", + "clean-astro": "rm -rf packages/website/.astro packages/website/node_modules/.astro packages/website/node_modules/.vite" }, "type": "module", "workspaces": [ From 3397e7f67bc30260f291f197fc4bce4eea31d45e Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Wed, 7 Oct 2026 16:25:34 -0500 Subject: [PATCH 18/36] truthy array --- .../components/Tankopedia/TechTreeSection/components/Node.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/website/src/components/Tankopedia/TechTreeSection/components/Node.tsx b/packages/website/src/components/Tankopedia/TechTreeSection/components/Node.tsx index 6f575a078..7b743aeaa 100644 --- a/packages/website/src/components/Tankopedia/TechTreeSection/components/Node.tsx +++ b/packages/website/src/components/Tankopedia/TechTreeSection/components/Node.tsx @@ -127,7 +127,7 @@ export function Node({ id, highlight, nextIds, skeleton }: NodeProps) { </Text> </Flex> - {averages && nextTanks && nextTanks.length > 0 && ( + {averages && nextTanks && ( <Text color="gray" size="1" mt="2"> {skeleton && <Skeleton height="1em" width="4em" />} {!skeleton && From 0e119b6ba858db629e9c649670a32e9add880aa2 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Wed, 7 Oct 2026 16:27:38 -0500 Subject: [PATCH 19/36] optimize awaitable tiers --- packages/website/src/core/awaitables/tiers.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/website/src/core/awaitables/tiers.ts b/packages/website/src/core/awaitables/tiers.ts index a83389b73..0729a3d45 100644 --- a/packages/website/src/core/awaitables/tiers.ts +++ b/packages/website/src/core/awaitables/tiers.ts @@ -2,9 +2,11 @@ import { times } from "lodash-es"; import { api } from "../blitzkit/api"; export const awaitableTiers = api.tankDefinitions().then((tankDefinitions) => { - const maxTier = Math.max( - ...Object.values(tankDefinitions.tanks).map((tank) => tank.tier), - ); + let max = 0; - return times(maxTier, (index) => maxTier - index); + for (const tank of Object.values(tankDefinitions.tanks)) { + if (tank.tier > max) max = tank.tier; + } + + return times(max, (index) => max - index); }); From e19d0d5895192f54e538a3e8de9ae559aec3bcfd Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Wed, 7 Oct 2026 16:32:48 -0500 Subject: [PATCH 20/36] revert tank exclusion --- .../website/src/components/Compare/Controls.tsx | 7 ------- .../website/src/components/Compare/TankControl.tsx | 11 +---------- .../website/src/components/TankSearch/index.tsx | 13 +++---------- 3 files changed, 4 insertions(+), 27 deletions(-) diff --git a/packages/website/src/components/Compare/Controls.tsx b/packages/website/src/components/Compare/Controls.tsx index 8614c2c31..1bb45c6cb 100644 --- a/packages/website/src/components/Compare/Controls.tsx +++ b/packages/website/src/components/Compare/Controls.tsx @@ -1,6 +1,5 @@ import { PlusIcon, TrashIcon } from "@radix-ui/react-icons"; import { Button, Dialog, Flex, SegmentedControl } from "@radix-ui/themes"; -import { useMemo } from "react"; import { api } from "../../core/blitzkit/api"; import { tankToCompareMember } from "../../core/blitzkit/tankToCompareMember"; import { useLocale } from "../../hooks/useLocale"; @@ -23,11 +22,6 @@ export function Controls({ onAddTankDialogOpenChange, }: ControlsProps) { const deltaMode = ComparePersistent.use((state) => state.deltaMode); - const members = CompareEphemeral.use((state) => state.members); - const memberIds = useMemo( - () => members.map((member) => member.tank.id), - [members], - ); const { strings } = useLocale(); return ( @@ -59,7 +53,6 @@ export function Controls({ > <TankSearch compact - exclude={memberIds} onSelect={(tank) => { CompareEphemeral.mutate((draft) => { draft.members.push( diff --git a/packages/website/src/components/Compare/TankControl.tsx b/packages/website/src/components/Compare/TankControl.tsx index bf2e6e227..28ab0e129 100644 --- a/packages/website/src/components/Compare/TankControl.tsx +++ b/packages/website/src/components/Compare/TankControl.tsx @@ -1,6 +1,6 @@ import { ExternalLinkIcon, LoopIcon, TrashIcon } from "@radix-ui/react-icons"; import { Dialog, Flex, IconButton } from "@radix-ui/themes"; -import { useMemo, useState } from "react"; +import { useState } from "react"; import { api } from "../../core/blitzkit/api"; import { tankToCompareMember } from "../../core/blitzkit/tankToCompareMember"; import { useLocale } from "../../hooks/useLocale"; @@ -18,14 +18,6 @@ const provisionDefinitions = await api.provisionDefinitions(); export function TankControl({ index, slug }: TankControlProps) { const { locale, strings } = useLocale(); const [switchTankDialogOpen, setSwitchTankDialogOpen] = useState(false); - const members = CompareEphemeral.use((state) => state.members); - const otherMemberIds = useMemo( - () => - members - .filter((_, memberIndex) => memberIndex !== index) - .map((member) => member.tank.id), - [members, index], - ); return ( <Flex gap="3" justify="center" style={{ width: "100%" }}> @@ -65,7 +57,6 @@ export function TankControl({ index, slug }: TankControlProps) { > <TankSearch compact - exclude={otherMemberIds} onSelect={(tank) => { CompareEphemeral.mutate((draft) => { draft.members[index] = tankToCompareMember( diff --git a/packages/website/src/components/TankSearch/index.tsx b/packages/website/src/components/TankSearch/index.tsx index fcc976aed..35321dc2c 100644 --- a/packages/website/src/components/TankSearch/index.tsx +++ b/packages/website/src/components/TankSearch/index.tsx @@ -38,7 +38,6 @@ export type TankSearchProps = MaybeSkeletonComponentProps & compact?: boolean; onSelect?: (tank: TankDefinition) => void; onSelectAll?: (tanks: TankDefinition[]) => void; - exclude?: number[]; }; const PREVIEW_COUNT = 20; @@ -53,14 +52,14 @@ const [gameDefinitions, modelDefinitions, tankDefinitions, tankNames] = ]); export const TankSearch = memo<TankSearchProps>( - ({ compact, onSelect, onSelectAll, exclude, skeleton, ...props }) => { + ({ compact, onSelect, onSelectAll, skeleton, ...props }) => { const { strings, locale } = useLocale(); const wargaming = App.use((state) => state.logins.wargaming); const awaitedTanksDefinitionsArray = Object.values(tankDefinitions.tanks); const tankopediaSort = TankSort.use(); const tankFilters = TankFilters.use(); - const allFiltered = usePromise( + const filtered = usePromise( () => { if (tankFilters.search === null) { return filterTanks( @@ -82,15 +81,9 @@ export const TankSearch = memo<TankSearchProps>( [tankFilters] as any, ); const sorted = useMemo(() => { - const filtered = allFiltered.filter( - (tank) => !exclude?.includes(tank.id), - ); - if (tankFilters.search === null) { let sorted: TankDefinition[]; - filtered.sort((a, b) => a.id - b.id); - switch (tankopediaSort.by) { case "meta.none": sorted = metaSortTank(filtered, gameDefinitions); @@ -424,7 +417,7 @@ export const TankSearch = memo<TankSearchProps>( } else { return filtered; } - }, [tankFilters, tankopediaSort, exclude]); + }, [tankFilters, tankopediaSort]); const [loadedCards, setLoadedCards] = useState(DEFAULT_LOADED_CARDS); const tanks = sorted.slice(0, loadedCards); From 904d50f4c30f84ef611ad09511fc6a296186d9a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Wed, 7 Oct 2026 16:35:15 -0500 Subject: [PATCH 21/36] New Crowdin updates (#379) --- packages/i18n/strings/es.json | 2 ++ packages/i18n/strings/fr.json | 2 ++ packages/i18n/strings/ja.json | 2 ++ packages/i18n/strings/pl.json | 2 ++ packages/i18n/strings/pt.json | 2 ++ packages/i18n/strings/ru.json | 2 ++ packages/i18n/strings/uk.json | 2 ++ packages/i18n/strings/zh.json | 2 ++ 8 files changed, 16 insertions(+) diff --git a/packages/i18n/strings/es.json b/packages/i18n/strings/es.json index 8df0c4a90..e877464d5 100644 --- a/packages/i18n/strings/es.json +++ b/packages/i18n/strings/es.json @@ -194,6 +194,7 @@ "title": "Settings", "description": "Change BlitzKit settings", "dev_mode": "Modo de desarrollador", + "auto_load_models": "Auto-load models", "language": "Idioma" }, "common": { @@ -412,6 +413,7 @@ } }, "sandbox": { + "load_model": "Load model", "poses": { "hull_down": "Hull down", "face_hug": "Cara a cara", diff --git a/packages/i18n/strings/fr.json b/packages/i18n/strings/fr.json index 7e5d2a7c3..ba01e0146 100644 --- a/packages/i18n/strings/fr.json +++ b/packages/i18n/strings/fr.json @@ -194,6 +194,7 @@ "title": "Paramètres", "description": "Modifier les paramètres de BlitzKit", "dev_mode": "Mode développement", + "auto_load_models": "Auto-load models", "language": "Langue" }, "common": { @@ -412,6 +413,7 @@ } }, "sandbox": { + "load_model": "Load model", "poses": { "hull_down": "Hull down", "face_hug": "Face hug", diff --git a/packages/i18n/strings/ja.json b/packages/i18n/strings/ja.json index 18ae1e3f4..f56d1986f 100644 --- a/packages/i18n/strings/ja.json +++ b/packages/i18n/strings/ja.json @@ -194,6 +194,7 @@ "title": "Settings", "description": "Change BlitzKit settings", "dev_mode": "開発者モード", + "auto_load_models": "Auto-load models", "language": "言語 / Language" }, "common": { @@ -412,6 +413,7 @@ } }, "sandbox": { + "load_model": "Load model", "poses": { "hull_down": "ハルダウン", "face_hug": "密着", diff --git a/packages/i18n/strings/pl.json b/packages/i18n/strings/pl.json index cb209b4be..447d389b3 100644 --- a/packages/i18n/strings/pl.json +++ b/packages/i18n/strings/pl.json @@ -194,6 +194,7 @@ "title": "Settings", "description": "Change BlitzKit settings", "dev_mode": "Development mode", + "auto_load_models": "Auto-load models", "language": "Language" }, "common": { @@ -412,6 +413,7 @@ } }, "sandbox": { + "load_model": "Load model", "poses": { "hull_down": "Hull down", "face_hug": "Face hug", diff --git a/packages/i18n/strings/pt.json b/packages/i18n/strings/pt.json index c0591e83c..757530039 100644 --- a/packages/i18n/strings/pt.json +++ b/packages/i18n/strings/pt.json @@ -194,6 +194,7 @@ "title": "Settings", "description": "Change BlitzKit settings", "dev_mode": "Modo de desenvolvimento", + "auto_load_models": "Auto-load models", "language": "Idioma" }, "common": { @@ -412,6 +413,7 @@ } }, "sandbox": { + "load_model": "Load model", "poses": { "hull_down": "Casco para baixo", "face_hug": "Abraço facial", diff --git a/packages/i18n/strings/ru.json b/packages/i18n/strings/ru.json index 3f34d00d4..c887147c7 100644 --- a/packages/i18n/strings/ru.json +++ b/packages/i18n/strings/ru.json @@ -194,6 +194,7 @@ "title": "Настройки", "description": "Изменить настройки BlitzKit", "dev_mode": "Режим разработчика", + "auto_load_models": "Auto-load models", "language": "Язык" }, "common": { @@ -412,6 +413,7 @@ } }, "sandbox": { + "load_model": "Load model", "poses": { "hull_down": "За холмом", "face_hug": "В упор", diff --git a/packages/i18n/strings/uk.json b/packages/i18n/strings/uk.json index 945d41188..1cf6305fe 100644 --- a/packages/i18n/strings/uk.json +++ b/packages/i18n/strings/uk.json @@ -194,6 +194,7 @@ "title": "Налаштування", "description": "Змінити налаштування BlitzKit ", "dev_mode": "Режим розробника", + "auto_load_models": "Auto-load models", "language": "Мова" }, "common": { @@ -412,6 +413,7 @@ } }, "sandbox": { + "load_model": "Load model", "poses": { "hull_down": "Від башти", "face_hug": "Клінч", diff --git a/packages/i18n/strings/zh.json b/packages/i18n/strings/zh.json index eeb75358e..3ab253b45 100644 --- a/packages/i18n/strings/zh.json +++ b/packages/i18n/strings/zh.json @@ -194,6 +194,7 @@ "title": "设置", "description": "更改 BlitzKit 设置", "dev_mode": "开发者模式", + "auto_load_models": "Auto-load models", "language": "语言" }, "common": { @@ -412,6 +413,7 @@ } }, "sandbox": { + "load_model": "Load model", "poses": { "hull_down": "俯角视角", "face_hug": "顶牛视角", From 0e7b020d60baaf4e2d500caff8600474515dba85 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Wed, 7 Oct 2026 16:48:08 -0500 Subject: [PATCH 22/36] fix sliver --- .../CharacteristicsSection/components/Equalizer.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Equalizer.tsx b/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Equalizer.tsx index f9c29e521..8c5b2771b 100644 --- a/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Equalizer.tsx +++ b/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Equalizer.tsx @@ -28,17 +28,17 @@ export function Equalizer() { width="100%" style={{ cursor: "pointer", - borderRadius: "var(--radius-3)", + borderRadius: "var(--radius-3) 0 0 var(--radius-3)", backgroundImage: ` linear-gradient(90deg, var(--black-a3), var(--gray-1)), url(${alias("api", `/gamemodes/Insanity/banner.webp`)}) `, - backgroundSize: "cover", + backgroundSize: "auto, fit", backgroundPosition: "50% 25%", overflow: "hidden", }} > - <Flex align="center" width="100%" justify="between" p="4"> + <Flex align="center" width="100%" justify="between" p="4" style={{}}> <Text style={{ textShadow: "0 0 var(--space-1) var(--black-a12)", From 92c8b90bb3084447eae534da60b6c20676ba4a23 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Wed, 7 Oct 2026 16:56:40 -0500 Subject: [PATCH 23/36] remove api check --- packages/website/src/components/LocaleRedirector.astro | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/website/src/components/LocaleRedirector.astro b/packages/website/src/components/LocaleRedirector.astro index 80c0afeaa..50cd05acb 100644 --- a/packages/website/src/components/LocaleRedirector.astro +++ b/packages/website/src/components/LocaleRedirector.astro @@ -3,7 +3,6 @@ import { getBestLocale } from "../core/i18n/getBestLocale"; const pathname = window.location.pathname; - const isAPI = pathname.startsWith("/api"); const hasPreference = localStorage.getItem("preferred-locale") !== null; const bestLocale = getBestLocale(); const currentLocale = @@ -14,7 +13,6 @@ )?.locale ?? locales.default; if ( - !isAPI && bestLocale !== currentLocale && (hasPreference || currentLocale === locales.default) ) { From 02f5cc0686dd55ca6076e08d890312d0c17fffea Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Wed, 7 Oct 2026 17:00:47 -0500 Subject: [PATCH 24/36] remove redundant logic --- packages/website/src/components/LocaleRedirector.astro | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/website/src/components/LocaleRedirector.astro b/packages/website/src/components/LocaleRedirector.astro index 50cd05acb..3805c19cc 100644 --- a/packages/website/src/components/LocaleRedirector.astro +++ b/packages/website/src/components/LocaleRedirector.astro @@ -8,8 +8,7 @@ const currentLocale = locales.supported.find( ({ locale }) => - locale !== locales.default && - (pathname === `/${locale}` || pathname.startsWith(`/${locale}/`)), + pathname === `/${locale}` || pathname.startsWith(`/${locale}/`), )?.locale ?? locales.default; if ( From 7234c39ad81db68ba6e06349f0fe27331baeb7e9 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Wed, 7 Oct 2026 21:32:38 -0500 Subject: [PATCH 25/36] move credits back --- docs/changelogs/1.29.10.md | 4 ++-- docs/changelogs/1.29.16.md | 2 +- docs/changelogs/1.29.8.md | 2 +- docs/changelogs/1.29.9.md | 4 ++-- docs/changelogs/1.30.0.md | 10 +++++----- docs/changelogs/1.30.1.md | 2 +- docs/changelogs/1.30.2.md | 6 +++--- docs/changelogs/1.30.3.md | 10 +++++----- docs/changelogs/1.30.7.md | 8 ++++---- docs/changelogs/1.31.4.md | 30 +++++++++++++++--------------- 10 files changed, 39 insertions(+), 39 deletions(-) diff --git a/docs/changelogs/1.29.10.md b/docs/changelogs/1.29.10.md index c293c1b4f..d96d78fd8 100644 --- a/docs/changelogs/1.29.10.md +++ b/docs/changelogs/1.29.10.md @@ -5,10 +5,10 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions ## Features - Combined game mode passive and active abilities into a single dropdown -- [Mark Greene] Added tier filters to the Guess game +- Added tier filters to the Guess game [Mark Greene] - Changing tiers will break your streak ## Fixes -- [Mark Greene] module damage is now properly shown when sorting with it in the tank search +- module damage is now properly shown when sorting with it in the tank search [Mark Greene] - Duplicate abilities in the tank filters are now removed diff --git a/docs/changelogs/1.29.16.md b/docs/changelogs/1.29.16.md index c111d385d..9a110001b 100644 --- a/docs/changelogs/1.29.16.md +++ b/docs/changelogs/1.29.16.md @@ -4,7 +4,7 @@ Thank you to [GonnaHetzMe](https://github.com/karelpak1) for your contributions ## Fixes -- [GonnaHetzMe] The turret for Centurion I is no longer offset from the body +- The turret for Centurion I is no longer offset from the body [GonnaHetzMe] - Please allow up to 24 hours for the model to update - Vertical Stabilizers now give the correct 12% buff instead of 15% - Re-ordering tanks in Compare now works once again diff --git a/docs/changelogs/1.29.8.md b/docs/changelogs/1.29.8.md index fa010e23f..a32e7d558 100644 --- a/docs/changelogs/1.29.8.md +++ b/docs/changelogs/1.29.8.md @@ -15,5 +15,5 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions ## Fixes - The Tankopedia now smoothly resizes when enlarging on interaction -- [Mark Greene] Stock turrets now correctly mount the corresponding stock gun +- Stock turrets now correctly mount the corresponding stock gun [Mark Greene] - The consumable and provision buttons in Compare are no longer tiny diff --git a/docs/changelogs/1.29.9.md b/docs/changelogs/1.29.9.md index 5f8d4a78e..c426194e1 100644 --- a/docs/changelogs/1.29.9.md +++ b/docs/changelogs/1.29.9.md @@ -5,10 +5,10 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions ## Features - Reworked tank search filters to be far more compact to make way for new filters -- [Mark Greene] Added the ability to filter tanks by consumables +- Added the ability to filter tanks by consumables [Mark Greene] - Added the ability to filter tanks by provisions and game-mode abilities and powers ## Fixes - Consumable and provision icons in Compare are now properly sized -- [Mark Greene] Provisions now properly affect terrain resistances +- Provisions now properly affect terrain resistances [Mark Greene] diff --git a/docs/changelogs/1.30.0.md b/docs/changelogs/1.30.0.md index cedbf5607..fd009b569 100644 --- a/docs/changelogs/1.30.0.md +++ b/docs/changelogs/1.30.0.md @@ -13,11 +13,11 @@ Thank you to [GonnaHetzMe](https://github.com/karelpak1) for your contributions ## Technical Features -- [GonnaHetzMe] Enabling dev mode now displays the tank's non-numerical id -- [GonnaHetzMe] The dev id and the new dev name are now copyable on click +- Enabling dev mode now displays the tank's non-numerical id [GonnaHetzMe] +- The dev id and the new dev name are now copyable on click [GonnaHetzMe] ## Fixes -- [GonnaHetzMe] Tech trees that start at tiers higher than tier 1 like the Blitz Nation ones now properly render their trees in Tankopedia -- [GonnaHetzMe] The tank pitch/yaw inputs in the Tank Sandbox now initialize with the correct values instead of 0 -- [GonnaHetzMe] Large Repair Kits once again use the correct modern icon +- Tech trees that start at tiers higher than tier 1 like the Blitz Nation ones now properly render their trees in Tankopedia [GonnaHetzMe] +- The tank pitch/yaw inputs in the Tank Sandbox now initialize with the correct values instead of 0 [GonnaHetzMe] +- Large Repair Kits once again use the correct modern icon [GonnaHetzMe] diff --git a/docs/changelogs/1.30.1.md b/docs/changelogs/1.30.1.md index 9491bc53a..8f2fd5c8c 100644 --- a/docs/changelogs/1.30.1.md +++ b/docs/changelogs/1.30.1.md @@ -4,5 +4,5 @@ Thank you to [GonnaHetzMe](https://github.com/karelpak1) for your contributions ## Fixes -- [GonnaHetzMe] Tank hit points in Equalizer mode is now accurate to the game +- Tank hit points in Equalizer mode is now accurate to the game [GonnaHetzMe] - Armor highlighting now reflects the actual thicknesses of tanks in Equalizer mode diff --git a/docs/changelogs/1.30.2.md b/docs/changelogs/1.30.2.md index e6437cad0..db259e391 100644 --- a/docs/changelogs/1.30.2.md +++ b/docs/changelogs/1.30.2.md @@ -4,9 +4,9 @@ Thank you to [GonnaHetzMe](https://github.com/karelpak1) for your contributions ## Fixes -- [GonnaHetzMe] Tungsten shells are now properly cropped +- Tungsten shells are now properly cropped [GonnaHetzMe] - Equalizer no longer gives insanely high penetration values - The tank reveal animation no longer repeats when you scroll away and back to the tank sandbox -- [GonnaHetzMe] The RHM. Pzw.'s turret no longer has the floating plate +- The RHM. Pzw.'s turret no longer has the floating plate [GonnaHetzMe] - Please give BlitzKit up to 1 hour to update the model -- [GonnaHetzMe] Tanks with inclined turret rings like the Minotauro now display the correct pitch in the tank sandbox inputs +- Tanks with inclined turret rings like the Minotauro now display the correct pitch in the tank sandbox inputs [GonnaHetzMe] diff --git a/docs/changelogs/1.30.3.md b/docs/changelogs/1.30.3.md index 69137dcac..74924659b 100644 --- a/docs/changelogs/1.30.3.md +++ b/docs/changelogs/1.30.3.md @@ -4,7 +4,7 @@ Thank you to [GonnaHetzMe](https://github.com/karelpak1) for your contributions ## Features -- [GonnaHetzMe] Added tooltips to the module selector in Tankopedia +- Added tooltips to the module selector in Tankopedia [GonnaHetzMe] ## Fixes @@ -12,7 +12,7 @@ Thank you to [GonnaHetzMe](https://github.com/karelpak1) for your contributions - Removed tank visual and collision model caching - Guesser once again breaks streaks if not all tiers are selected - BlitzKit now properly unloads tank models from memory when visually hidden in Guesser -- [GonnaHetzMe] Tanks with complex transparency like the Herdbreaker once again handle opacity correctly -- [GonnaHetzMe] Pieces of tank models that have transparency now handle culling properly (they're visible from both sides) -- [GonnaHetzMe] Tanks with "cardboard" textures have been fixed, thanks to better PVR file parsing -- [GonnaHetzMe] Tank icons are now scaled correctly so small tanks are now properly zoomed out in contrast to bigger ones +- Tanks with complex transparency like the Herdbreaker once again handle opacity correctly [GonnaHetzMe] +- Pieces of tank models that have transparency now handle culling properly (they're visible from both sides) [GonnaHetzMe] +- Tanks with "cardboard" textures have been fixed, thanks to better PVR file parsing [GonnaHetzMe] +- Tank icons are now scaled correctly so small tanks are now properly zoomed out in contrast to bigger ones [GonnaHetzMe] diff --git a/docs/changelogs/1.30.7.md b/docs/changelogs/1.30.7.md index 2545b4b20..c42589bff 100644 --- a/docs/changelogs/1.30.7.md +++ b/docs/changelogs/1.30.7.md @@ -8,13 +8,13 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions ## Fixes -- [Mark Greene] Clicking on the armor multiple times with HE no longer crashes BlitzKit -- [Mark Greene] Ricochets that later intersect with external modules no longer falsely claim a successful damaging penetration +- Clicking on the armor multiple times with HE no longer crashes BlitzKit [Mark Greene] +- Ricochets that later intersect with external modules no longer falsely claim a successful damaging penetration [Mark Greene] - The lighting animation no longer stops prematurely when BlitzKit is unfocused - The spot light angle has been increased to more evenly light up larger tanks - BlitzKit once again uses soft shadows, reducing the pixelated shadows - Fixed the weird patterns that formed on the tracks of tanks under self-shadows - Increased the floor size and light decay to create the illusion that the floor is infinite -- [Mark Greene] Safari no longer crashes when unloading textures for unloaded tanks +- Safari no longer crashes when unloading textures for unloaded tanks [Mark Greene] - The gun depression transition between two constraints (like often behind tanks) now uses a gentler zoned and can never be 0 -- [Mark Greene] Armor plate names in Static Armor are now properly capitalized in English and translated to other languages +- Armor plate names in Static Armor are now properly capitalized in English and translated to other languages [Mark Greene] diff --git a/docs/changelogs/1.31.4.md b/docs/changelogs/1.31.4.md index ecf232845..462d732f7 100644 --- a/docs/changelogs/1.31.4.md +++ b/docs/changelogs/1.31.4.md @@ -4,27 +4,27 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions ## Features -- [Mark Greene] Added Peekaboo DPM +- Added Peekaboo DPM [Mark Greene] - Your Peekaboo DPM is lower than your normal DPM if your reload is faster than 10s as you'll have to wait for the remaining 10s for you to get unspotted before you can poke and shoot -- [Mark Greene] The test and owned tank filters are now more intuitive as clicking on them now turns the clicked option on instead of off -- [Mark Greene] Added a spall liner button to the Tankopedia beside the other equipment +- The test and owned tank filters are now more intuitive as clicking on them now turns the clicked option on instead of off [Mark Greene] +- Added a spall liner button to the Tankopedia beside the other equipment [Mark Greene] ## Fixes -- [Mark Greene] BlitzKit Session now properly handles tanks removed from the game -- [Mark Greene] Removed the Beta badge from the Equalizer button +- BlitzKit Session now properly handles tanks removed from the game [Mark Greene] +- Removed the Beta badge from the Equalizer button [Mark Greene] - Updated the background image for the Equalizer button to the actual banner of the new game mode -- [Mark Greene] The armor no longer disappears when you turn on Dynamic Armor System -- [Mark Greene] Camouflage values in Tankopedia are now more descriptive when shooting -- [Mark Greene] The contact shadows on the ground no longer grow & darken when switching between tabs +- The armor no longer disappears when you turn on Dynamic Armor System [Mark Greene] +- Camouflage values in Tankopedia are now more descriptive when shooting [Mark Greene] +- The contact shadows on the ground no longer grow & darken when switching between tabs [Mark Greene] - The "Help Translate BlitzKit" text on the home page is now properly centered vertically -- [Mark Greene] The footer now says "Branch" instead of "CDN" -- [Mark Greene] The game version in the footer now displays a shorthand version instead of the entire version number -- [Mark Greene] The reload visualizer now displays just 1 decimal place -- [Mark Greene] The search bar no longer redirects to a seemingly random tank when clicking enter when searching -- [Mark Greene] Tank search now properly handles the full names of tanks like the Super Pershing -- [Mark Greene] The loading bar below the name of the tanks in Tankopedia is now sufficiently spaced below -- [Mark Greene] The gun depression visualizer now properly handles the inherent tilt of tanks like the Minotauro +- The footer now says "Branch" instead of "CDN" [Mark Greene] +- The game version in the footer now displays a shorthand version instead of the entire version number [Mark Greene] +- The reload visualizer now displays just 1 decimal place [Mark Greene] +- The search bar no longer redirects to a seemingly random tank when clicking enter when searching [Mark Greene] +- Tank search now properly handles the full names of tanks like the Super Pershing [Mark Greene] +- The loading bar below the name of the tanks in Tankopedia is now sufficiently spaced below [Mark Greene] +- The gun depression visualizer now properly handles the inherent tilt of tanks like the Minotauro [Mark Greene] ## Technical Features From fbdfa2c0634c0de5e2aa1917b25bc1919db4a7f5 Mon Sep 17 00:00:00 2001 From: Mark Greene <markgreene5833@gmail.com> Date: Thu, 8 Oct 2026 18:00:57 +1300 Subject: [PATCH 26/36] Feature: Penetration chance in the armor shot card MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Shows the chance a shot penetrates in the dynamic armor shot card, right-aligned on the shot's result line. - Penetration varies by ±5% (the same randomisation the armor highlighter shader uses), so the chance is the share of that range where the shot's final outcome is a penetration - Re-runs the existing shot calculation at different penetration values, so spaced armor, HEAT gap losses and ricochets are taken into account - For ricochets the chance is shown on the ricocheted shot's line; HE splashes don't count as penetrations - Adds the `shot_card.stats.penetration_chance` string Fixes #342 --- .../Armor/components/ShotDisplayCard.tsx | 45 ++++++++++++------- .../SpacedArmorSceneComponent/index.tsx | 43 ++++++++++++++++++ packages/website/src/stores/tankopedia.ts | 1 + 3 files changed, 74 insertions(+), 15 deletions(-) diff --git a/packages/website/src/components/Armor/components/ShotDisplayCard.tsx b/packages/website/src/components/Armor/components/ShotDisplayCard.tsx index e27c1de5c..6720458f3 100644 --- a/packages/website/src/components/Armor/components/ShotDisplayCard.tsx +++ b/packages/website/src/components/Armor/components/ShotDisplayCard.tsx @@ -128,19 +128,30 @@ export function ShotDisplayCard({ shot, ...props }: ShotDisplayCardProps) { ? shotStatusColors[shot.out.status] : undefined; const inTitleColor = shotStatusColors[shot.in.status]; + const hasOutLayers = shot.out !== undefined && shot.out.layers.length > 0; + const penetrationChance = shot.penetrationChance !== undefined && ( + <Text color="gray" weight="bold"> + {literals(strings.common.units.percentage, { + value: (shot.penetrationChance * 100).toFixed(0), + })} + </Text> + ); return ( <Card variant="classic" {...props}> <Flex direction="column" gap="2"> <Flex direction="column" gap="1"> - <Text color={inTitleColor} weight="bold"> - {literals( - strings.website.tools.tankopedia.sandbox.dynamic.shot_card.status[ - shot.in.status - ], - { damage: Math.round(shot.damage).toLocaleString(locale) } - )} - </Text> + <Flex justify="between" align="center" gap="4"> + <Text color={inTitleColor} weight="bold"> + {literals( + strings.website.tools.tankopedia.sandbox.dynamic.shot_card + .status[shot.in.status], + { damage: Math.round(shot.damage).toLocaleString(locale) } + )} + </Text> + + {!hasOutLayers && penetrationChance} + </Flex> <table style={{ @@ -204,13 +215,17 @@ export function ShotDisplayCard({ shot, ...props }: ShotDisplayCardProps) { </Flex> </Inset> - <Text color={outTitleColor} weight="bold"> - {literals( - strings.website.tools.tankopedia.sandbox.dynamic.shot_card - .status[shot.out.status], - { damage: Math.round(shot.damage).toLocaleString(locale) } - )} - </Text> + <Flex justify="between" align="center" gap="4"> + <Text color={outTitleColor} weight="bold"> + {literals( + strings.website.tools.tankopedia.sandbox.dynamic.shot_card + .status[shot.out.status], + { damage: Math.round(shot.damage).toLocaleString(locale) } + )} + </Text> + + {penetrationChance} + </Flex> <Flex direction="column"> {shot.out.layers.map((layer, index) => { diff --git a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/index.tsx b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/index.tsx index 784836464..57149cbe4 100644 --- a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/index.tsx +++ b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/index.tsx @@ -63,6 +63,36 @@ export type ArmorUserData = { } ); +const PENETRATION_RANDOMIZATION = 0.05; + +function resolvePenetrationChance(shoot: (scale: number) => Shot | null) { + function penetrates(scale: number) { + const shot = shoot(scale); + + return (shot?.out ?? shot?.in)?.status === "penetration"; + } + + let low = 1 - PENETRATION_RANDOMIZATION; + let high = 1 + PENETRATION_RANDOMIZATION; + + if (penetrates(low)) return 1; + if (!penetrates(high)) return 0; + + for (let iteration = 0; iteration < 16; iteration++) { + const middle = (low + high) / 2; + + if (penetrates(middle)) { + high = middle; + } else { + low = middle; + } + } + + return ( + (1 + PENETRATION_RANDOMIZATION - high) / (2 * PENETRATION_RANDOMIZATION) + ); +} + const omitMaterial = new MeshBasicMaterial({ colorWrite: false, depthWrite: true, @@ -89,6 +119,7 @@ export function SpacedArmorSceneComponent({ intersections: Intersection[], allowRicochet: boolean, remainingPenetrationInput?: number, + penetrationScale = 1, ) => { const { customShell } = Tankopedia.state; const shell = customShell ?? Duel.state.antagonist.shell; @@ -125,6 +156,7 @@ export function SpacedArmorSceneComponent({ Duel.state.protagonist.equipmentMatrix, ); const penetration = + penetrationScale * shell.penetration!.near * resolvePenetrationCoefficient( hasCalibratedShells, @@ -367,6 +399,7 @@ export function SpacedArmorSceneComponent({ ricochetIntersections, false, remainingPenetration, + penetrationScale, ); shot.in.status = "ricochet"; @@ -422,6 +455,16 @@ export function SpacedArmorSceneComponent({ const shot = shoot(event.point, event.intersections, true)!; + shot.penetrationChance = resolvePenetrationChance((scale) => + shoot( + event.point, + event.intersections, + true, + undefined, + scale, + ), + ); + Tankopedia.mutate((draft) => { draft.shot = shot; }); diff --git a/packages/website/src/stores/tankopedia.ts b/packages/website/src/stores/tankopedia.ts index 023ab0e87..d6e374a0a 100644 --- a/packages/website/src/stores/tankopedia.ts +++ b/packages/website/src/stores/tankopedia.ts @@ -43,6 +43,7 @@ export type Shot = { containsGaps: boolean; damage: number; splashRadius?: number; + penetrationChance?: number; in: { surfaceNormal: Vector3; From 940c3c537b89452880246380c3d012a10933da3c Mon Sep 17 00:00:00 2001 From: Mark Greene <markgreene5833@gmail.com> Date: Thu, 8 Oct 2026 18:02:05 +1300 Subject: [PATCH 27/36] Feature: track repair time in Tankopedia Adds track repair time to the Tankopedia survivability stats, matching the value the game lists. - Added a required `repair_time` to track definitions, filled from each chassis's hysteresis health divided by its health regen per second - Applied the toolbox, the repair crew skill and the protective kit as multiplicative repair speed bonuses - Added a Track repair time row under fire chance; it appears once the definitions are regenerated on the next build Fixes #308 --- .../blitzkit/api/server/1_tankDefinitions.ts | 1 + .../core/src/protos/tank_definitions.proto | 1 + packages/core/src/protos/tank_definitions.ts | 18 ++++++++++++++++++ packages/core/src/types/vehicleDefinitions.ts | 2 ++ packages/i18n/strings/en.json | 1 + .../components/Survivability.tsx | 8 ++++++++ .../src/core/blitzkit/tankCharacteristics.ts | 8 ++++++++ 7 files changed, 39 insertions(+) diff --git a/packages/core/src/blitzkit/api/server/1_tankDefinitions.ts b/packages/core/src/blitzkit/api/server/1_tankDefinitions.ts index e7192e140..9e211001b 100644 --- a/packages/core/src/blitzkit/api/server/1_tankDefinitions.ts +++ b/packages/core/src/blitzkit/api/server/1_tankDefinitions.ts @@ -434,6 +434,7 @@ export abstract class ServerBlitzKitAPI1 extends ServerBlitzKitAPI0 { resistance_hard: terrainResistances[0], resistance_medium: terrainResistances[1], resistance_soft: terrainResistances[2], + repair_time: track.hysteresisHealth / track.healthRegenPerSec, tier: track.level, unlocks: resolveUnlocks( this.blitzModuleTypeToBlitzkit, diff --git a/packages/core/src/protos/tank_definitions.proto b/packages/core/src/protos/tank_definitions.proto index 6c9cb1078..9a2713bff 100644 --- a/packages/core/src/protos/tank_definitions.proto +++ b/packages/core/src/protos/tank_definitions.proto @@ -87,6 +87,7 @@ message TrackDefinition { required float resistance_medium = 10; required float resistance_soft = 11; repeated Unlock unlocks = 12; + required float repair_time = 13; } message EngineDefinition { diff --git a/packages/core/src/protos/tank_definitions.ts b/packages/core/src/protos/tank_definitions.ts index be6e2a1f0..52117f6d9 100644 --- a/packages/core/src/protos/tank_definitions.ts +++ b/packages/core/src/protos/tank_definitions.ts @@ -338,6 +338,7 @@ export interface TrackDefinition { resistance_medium: number; resistance_soft: number; unlocks: Unlock[]; + repair_time: number; } export interface EngineDefinition { @@ -1759,6 +1760,7 @@ function createBaseTrackDefinition(): TrackDefinition { resistance_medium: 0, resistance_soft: 0, unlocks: [], + repair_time: 0, }; } @@ -1800,6 +1802,9 @@ export const TrackDefinition: MessageFns<TrackDefinition> = { for (const v of message.unlocks) { Unlock.encode(v!, writer.uint32(98).fork()).join(); } + if (message.repair_time !== 0) { + writer.uint32(109).float(message.repair_time); + } return writer; }, @@ -1906,6 +1911,14 @@ export const TrackDefinition: MessageFns<TrackDefinition> = { message.unlocks.push(Unlock.decode(reader, reader.uint32())); continue; } + case 13: { + if (tag !== 109) { + break; + } + + message.repair_time = reader.float(); + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -1929,6 +1942,7 @@ export const TrackDefinition: MessageFns<TrackDefinition> = { resistance_medium: isSet(object.resistance_medium) ? globalThis.Number(object.resistance_medium) : 0, resistance_soft: isSet(object.resistance_soft) ? globalThis.Number(object.resistance_soft) : 0, unlocks: globalThis.Array.isArray(object?.unlocks) ? object.unlocks.map((e: any) => Unlock.fromJSON(e)) : [], + repair_time: isSet(object.repair_time) ? globalThis.Number(object.repair_time) : 0, }; }, @@ -1970,6 +1984,9 @@ export const TrackDefinition: MessageFns<TrackDefinition> = { if (message.unlocks?.length) { obj.unlocks = message.unlocks.map((e) => Unlock.toJSON(e)); } + if (message.repair_time !== 0) { + obj.repair_time = message.repair_time; + } return obj; }, @@ -1994,6 +2011,7 @@ export const TrackDefinition: MessageFns<TrackDefinition> = { message.resistance_medium = object.resistance_medium ?? 0; message.resistance_soft = object.resistance_soft ?? 0; message.unlocks = object.unlocks?.map((e) => Unlock.fromPartial(e)) || []; + message.repair_time = object.repair_time ?? 0; return message; }, }; diff --git a/packages/core/src/types/vehicleDefinitions.ts b/packages/core/src/types/vehicleDefinitions.ts index e0ff86532..e497c6979 100644 --- a/packages/core/src/types/vehicleDefinitions.ts +++ b/packages/core/src/types/vehicleDefinitions.ts @@ -34,6 +34,8 @@ export interface VehicleDefinitions { }; level: number; hullPosition: string; + hysteresisHealth: number; + healthRegenPerSec: number; armor: { leftTrack: | number diff --git a/packages/i18n/strings/en.json b/packages/i18n/strings/en.json index 04125f138..c55989b8f 100644 --- a/packages/i18n/strings/en.json +++ b/packages/i18n/strings/en.json @@ -683,6 +683,7 @@ "hullTraverseSoftTerrain": "Soft", "health": "Health", "fireChance": "Fire chance", + "trackRepairTime": "Track repair time", "viewRange": "View range", "camouflageStill": "Camouflage still", "camouflageMoving": "Moving", diff --git a/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/Survivability.tsx b/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/Survivability.tsx index edd9c96f7..80d489d8b 100644 --- a/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/Survivability.tsx +++ b/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/Survivability.tsx @@ -24,6 +24,14 @@ export function Survivability({ stats }: StatsAcceptorProps) { decimals={0} value={(stats) => stats.fireChance * 100} /> + {stats.trackRepairTime !== undefined && ( + <InfoWithDelta + value="trackRepairTime" + stats={stats} + deltaType="lowerIsBetter" + decimals={2} + /> + )} <InfoWithDelta value="viewRange" stats={stats} decimals={0} /> <ViewRangeVisualizer stats={stats} /> <Info diff --git a/packages/website/src/core/blitzkit/tankCharacteristics.ts b/packages/website/src/core/blitzkit/tankCharacteristics.ts index 51301190a..67569155a 100644 --- a/packages/website/src/core/blitzkit/tankCharacteristics.ts +++ b/packages/website/src/core/blitzkit/tankCharacteristics.ts @@ -119,6 +119,7 @@ export function tankCharacteristics( const hasImprovedVerticalStabilizer = equipment(122); const hasDownImprovedVerticalStabilizer = equipment(124); const hasImprovedSuspension = equipment(123); + const hasToolbox = equipment(113); const hasTungsten = consumable(45); const hasAdrenaline = consumable(18); @@ -518,6 +519,12 @@ export function tankCharacteristics( } const fireChance = engine.fire_chance * fireChanceCoefficient; + const trackRepairTime = track.repair_time + ? track.repair_time / + ((hasToolbox ? 1.2 : 1) * + (1 + (crewSkills.repair ?? 0) * 0.04) * + (hasProtectiveKit ? 1.1 : 1)) + : undefined; const viewRange = turret.view_range * viewRangeCoefficient; const camouflageStill = tank.camouflage_still * camouflageCoefficientStill; const camouflageMoving = @@ -602,6 +609,7 @@ export function tankCharacteristics( hullTraverseSoftTerrain, health, fireChance, + trackRepairTime, viewRange, camouflageStill, camouflageMoving, From 646d6fa7d5ddd2d63065d1908a087c75a1de50ea Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Fri, 9 Oct 2026 16:54:37 -0500 Subject: [PATCH 28/36] center align and max width 32rem --- packages/website/src/components/PlaylistGenerator.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/website/src/components/PlaylistGenerator.tsx b/packages/website/src/components/PlaylistGenerator.tsx index b50c74654..a64999bc4 100644 --- a/packages/website/src/components/PlaylistGenerator.tsx +++ b/packages/website/src/components/PlaylistGenerator.tsx @@ -25,7 +25,7 @@ import { FilterControl } from "./TankSearch/components/FilterControl"; const tankDefinitions = await api.tankDefinitions(); const POOL_HEIGHT = "16rem"; -const FILTERS_WIDTH = "22rem"; +const FILTERS_WIDTH = "32rem"; export function PlaylistGenerator({ skeleton }: MaybeSkeletonComponentProps) { const [largeWarningOpen, setLargeWarningOpen] = useState(false); @@ -90,7 +90,7 @@ export function PlaylistGenerator({ skeleton }: MaybeSkeletonComponentProps) { <Flex direction="column" gap="4" - align="stretch" + align="center" flexShrink="0" width={{ initial: "100%", md: FILTERS_WIDTH }} > From fbc4355984cf91a6eaf34ab6e92b8d8891f131a5 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Fri, 9 Oct 2026 17:02:54 -0500 Subject: [PATCH 29/36] remove clamped vw --- .../pages/[...chunk_default]/[...locale]/mixer/_index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/website/src/pages/[...chunk_default]/[...locale]/mixer/_index.tsx b/packages/website/src/pages/[...chunk_default]/[...locale]/mixer/_index.tsx index ebd83ff62..7cf3539c4 100644 --- a/packages/website/src/pages/[...chunk_default]/[...locale]/mixer/_index.tsx +++ b/packages/website/src/pages/[...chunk_default]/[...locale]/mixer/_index.tsx @@ -103,12 +103,12 @@ function ModuleChooser({ {...props} > {skeleton ? ( - <Skeleton width="clamp(2rem, 11vw, 4em)" height="2em" /> + <Skeleton width="4em" height="2em" /> ) : ( <img style={{ - width: "clamp(2rem, 11vw, 4em)", - height: "clamp(2rem, 11vw, 4em)", + width: "4em", + height: "4em", objectFit: "contain", }} src={alias("api", `/tanks/${tank}/icons/big.webp`)} From 072174ad45c2641a96d191d39df5fab12de1d351 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Fri, 9 Oct 2026 18:01:10 -0500 Subject: [PATCH 30/36] promote version --- docs/changelogs/{1.31.4.md => 1.32.0.md} | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename docs/changelogs/{1.31.4.md => 1.32.0.md} (99%) diff --git a/docs/changelogs/1.31.4.md b/docs/changelogs/1.32.0.md similarity index 99% rename from docs/changelogs/1.31.4.md rename to docs/changelogs/1.32.0.md index 462d732f7..4cd2f480f 100644 --- a/docs/changelogs/1.31.4.md +++ b/docs/changelogs/1.32.0.md @@ -1,4 +1,4 @@ -# BlitzKit 1.31.4 +# BlitzKit 1.32.0 Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions this update. diff --git a/package.json b/package.json index d9bc165ba..d8dc478c8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "blitzkit", - "version": "1.31.4", + "version": "1.32.0", "license": "BlitzKit License", "private": true, "scripts": { From 78bff2cdd26f6138c76f3ed806c019b23ebba511 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Fri, 9 Oct 2026 18:13:22 -0500 Subject: [PATCH 31/36] logs --- cspell.json | 2 +- docs/changelogs/1.32.0.md | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/cspell.json b/cspell.json index a67dd4960..17d054ca4 100644 --- a/cspell.json +++ b/cspell.json @@ -1,5 +1,5 @@ { - "words": [ + "words": [ "gamemodes", "Tankopedia" ] diff --git a/docs/changelogs/1.32.0.md b/docs/changelogs/1.32.0.md index 4cd2f480f..35c718cbe 100644 --- a/docs/changelogs/1.32.0.md +++ b/docs/changelogs/1.32.0.md @@ -8,6 +8,10 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions - Your Peekaboo DPM is lower than your normal DPM if your reload is faster than 10s as you'll have to wait for the remaining 10s for you to get unspotted before you can poke and shoot - The test and owned tank filters are now more intuitive as clicking on them now turns the clicked option on instead of off [Mark Greene] - Added a spall liner button to the Tankopedia beside the other equipment [Mark Greene] +- Listed track repair times in the Tankopedia [Mark Greene] +- The penetration chance is now displayed when penetration testing armor [Mark Greene] +- Added compatibility for tier XI tanks [Mark Greene] +- Added a new setting to disable automatically loading tanks in Tankopedia [Mark Greene] ## Fixes @@ -17,6 +21,7 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions - The armor no longer disappears when you turn on Dynamic Armor System [Mark Greene] - Camouflage values in Tankopedia are now more descriptive when shooting [Mark Greene] - The contact shadows on the ground no longer grow & darken when switching between tabs [Mark Greene] +- Additionally, the contact shadows stays visible at low angles [Mark Greene] - The "Help Translate BlitzKit" text on the home page is now properly centered vertically - The footer now says "Branch" instead of "CDN" [Mark Greene] - The game version in the footer now displays a shorthand version instead of the entire version number [Mark Greene] @@ -25,6 +30,14 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions - Tank search now properly handles the full names of tanks like the Super Pershing [Mark Greene] - The loading bar below the name of the tanks in Tankopedia is now sufficiently spaced below [Mark Greene] - The gun depression visualizer now properly handles the inherent tilt of tanks like the Minotauro [Mark Greene] +- Plot controls for the Static armor tab no longer pokes in from the right on non-Static armor tabs in some languages [Mark Greene] +- Mixer's controllers now scale better on smaller screens [Mark Greene] +- The flags in the Tankopedia tech tree are no longer offset to the top left [Mark Greene] +- The list of available tanks in the Playlist is no longer excessively wide [Mark Greene] +- When moving the tracks of tanks, the textures no longer move at different rates [Mark Greene] +- Users with a preference on a language are once again redirected to the correct localized pages [Mark Greene] +- Removed the vertical sliver of pixels found to the right of the Equalizer toggle in Tankopedia +- The tank search now remains consistent in order even when an added filter does not add/remove tanks from the list [Mark Greene] ## Technical Features @@ -39,3 +52,5 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions - This was the last bug standing in the way of BlitzKit Previews - Welcome back, BlitzKit Previews! - Removed some dead code from the BlitzKit model mangler +- The player discovery loop now persists for longer than 1 iteration [Mark Greene] +- Bun is now forced to run scripts with the `--bun` flag From d0507766282518b9e0877f43a65bf8bd7b30bc24 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Fri, 9 Oct 2026 18:14:59 -0500 Subject: [PATCH 32/36] format --- docs/changelogs/1.32.0.md | 70 +++++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/docs/changelogs/1.32.0.md b/docs/changelogs/1.32.0.md index 35c718cbe..23b7e2ca6 100644 --- a/docs/changelogs/1.32.0.md +++ b/docs/changelogs/1.32.0.md @@ -4,40 +4,82 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions ## Features -- Added Peekaboo DPM [Mark Greene] - - Your Peekaboo DPM is lower than your normal DPM if your reload is faster than 10s as you'll have to wait for the remaining 10s for you to get unspotted before you can poke and shoot -- The test and owned tank filters are now more intuitive as clicking on them now turns the clicked option on instead of off [Mark Greene] +**Tankopedia & Armor** + - Added a spall liner button to the Tankopedia beside the other equipment [Mark Greene] - Listed track repair times in the Tankopedia [Mark Greene] - The penetration chance is now displayed when penetration testing armor [Mark Greene] -- Added compatibility for tier XI tanks [Mark Greene] - Added a new setting to disable automatically loading tanks in Tankopedia [Mark Greene] +**Tank Performance & Mechanics** + +- Added Peekaboo DPM [Mark Greene] + - Your Peekaboo DPM is lower than your normal DPM if your reload is faster than 10s as you'll have to wait for the remaining 10s for you to get unspotted before you can poke and shoot + +**Tank Filters** + +- The test and owned tank filters are now more intuitive as clicking on them now turns the clicked option on instead of off [Mark Greene] + +**Game Compatibility** + +- Added compatibility for tier XI tanks [Mark Greene] + ## Fixes -- BlitzKit Session now properly handles tanks removed from the game [Mark Greene] -- Removed the Beta badge from the Equalizer button [Mark Greene] -- Updated the background image for the Equalizer button to the actual banner of the new game mode +**Tankopedia & Armor** + - The armor no longer disappears when you turn on Dynamic Armor System [Mark Greene] - Camouflage values in Tankopedia are now more descriptive when shooting [Mark Greene] +- The penetration chance is now displayed when penetration testing armor [Mark Greene] +- Listed track repair times in the Tankopedia [Mark Greene] +- Added a spall liner button to the Tankopedia beside the other equipment [Mark Greene] +- The flags in the Tankopedia tech tree are no longer offset to the top left [Mark Greene] +- The loading bar below the name of the tanks in Tankopedia is now sufficiently spaced below [Mark Greene] +- Removed the vertical sliver of pixels found to the right of the Equalizer toggle in Tankopedia + +**Tank Search & Filters** + +- The search bar no longer redirects to a seemingly random tank when clicking enter when searching [Mark Greene] +- Tank search now properly handles the full names of tanks like the Super Pershing [Mark Greene] +- The tank search now remains consistent in order even when an added filter does not add/remove tanks from the list [Mark Greene] +- The test and owned tank filters are now more intuitive as clicking on them now turns the clicked option on instead of off [Mark Greene] + +**Visuals & UI** + +- Removed the Beta badge from the Equalizer button [Mark Greene] +- Updated the background image for the Equalizer button to the actual banner of the new game mode - The contact shadows on the ground no longer grow & darken when switching between tabs [Mark Greene] - Additionally, the contact shadows stays visible at low angles [Mark Greene] - The "Help Translate BlitzKit" text on the home page is now properly centered vertically - The footer now says "Branch" instead of "CDN" [Mark Greene] - The game version in the footer now displays a shorthand version instead of the entire version number [Mark Greene] - The reload visualizer now displays just 1 decimal place [Mark Greene] -- The search bar no longer redirects to a seemingly random tank when clicking enter when searching [Mark Greene] -- Tank search now properly handles the full names of tanks like the Super Pershing [Mark Greene] -- The loading bar below the name of the tanks in Tankopedia is now sufficiently spaced below [Mark Greene] -- The gun depression visualizer now properly handles the inherent tilt of tanks like the Minotauro [Mark Greene] - Plot controls for the Static armor tab no longer pokes in from the right on non-Static armor tabs in some languages [Mark Greene] - Mixer's controllers now scale better on smaller screens [Mark Greene] -- The flags in the Tankopedia tech tree are no longer offset to the top left [Mark Greene] - The list of available tanks in the Playlist is no longer excessively wide [Mark Greene] + +**Tank Mechanics & Models** + +- The gun depression visualizer now properly handles the inherent tilt of tanks like the Minotauro [Mark Greene] - When moving the tracks of tanks, the textures no longer move at different rates [Mark Greene] + +**Localization** + - Users with a preference on a language are once again redirected to the correct localized pages [Mark Greene] -- Removed the vertical sliver of pixels found to the right of the Equalizer toggle in Tankopedia -- The tank search now remains consistent in order even when an added filter does not add/remove tanks from the list [Mark Greene] + +**Session & Game Compatibility** + +- BlitzKit Session now properly handles tanks removed from the game [Mark Greene] + +**## Technical Fixes** + +- BlitzKit now handles the new ID system for game-modes in WoTB +- The directory which preview versions of the game are downloaded to are now created properly + - This was the last bug standing in the way of BlitzKit Previews + - Welcome back, BlitzKit Previews! +- Removed some dead code from the BlitzKit model mangler +- The player discovery loop now persists for longer than 1 iteration [Mark Greene] +- Bun is now forced to run scripts with the `--bun` flag ## Technical Features From ff03f8ffb2cee027243a0f8a07717ae9c4b018f5 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Fri, 9 Oct 2026 18:17:56 -0500 Subject: [PATCH 33/36] remove bold --- docs/changelogs/1.32.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changelogs/1.32.0.md b/docs/changelogs/1.32.0.md index 23b7e2ca6..441babd95 100644 --- a/docs/changelogs/1.32.0.md +++ b/docs/changelogs/1.32.0.md @@ -71,7 +71,7 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions - BlitzKit Session now properly handles tanks removed from the game [Mark Greene] -**## Technical Fixes** +## Technical Fixes - BlitzKit now handles the new ID system for game-modes in WoTB - The directory which preview versions of the game are downloaded to are now created properly From 1988ecff925f2697e69db6679244659fc26fad73 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Fri, 9 Oct 2026 18:20:11 -0500 Subject: [PATCH 34/36] smaller titles --- docs/changelogs/1.32.0.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/changelogs/1.32.0.md b/docs/changelogs/1.32.0.md index 441babd95..ce86475ee 100644 --- a/docs/changelogs/1.32.0.md +++ b/docs/changelogs/1.32.0.md @@ -4,29 +4,29 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions ## Features -**Tankopedia & Armor** +### Tankopedia & Armor - Added a spall liner button to the Tankopedia beside the other equipment [Mark Greene] - Listed track repair times in the Tankopedia [Mark Greene] - The penetration chance is now displayed when penetration testing armor [Mark Greene] - Added a new setting to disable automatically loading tanks in Tankopedia [Mark Greene] -**Tank Performance & Mechanics** +### Tank Performance & Mechanics - Added Peekaboo DPM [Mark Greene] - Your Peekaboo DPM is lower than your normal DPM if your reload is faster than 10s as you'll have to wait for the remaining 10s for you to get unspotted before you can poke and shoot -**Tank Filters** +### Tank Filters - The test and owned tank filters are now more intuitive as clicking on them now turns the clicked option on instead of off [Mark Greene] -**Game Compatibility** +### Game Compatibility - Added compatibility for tier XI tanks [Mark Greene] ## Fixes -**Tankopedia & Armor** +### Tankopedia & Armor - The armor no longer disappears when you turn on Dynamic Armor System [Mark Greene] - Camouflage values in Tankopedia are now more descriptive when shooting [Mark Greene] @@ -37,14 +37,14 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions - The loading bar below the name of the tanks in Tankopedia is now sufficiently spaced below [Mark Greene] - Removed the vertical sliver of pixels found to the right of the Equalizer toggle in Tankopedia -**Tank Search & Filters** +### Tank Search & Filters - The search bar no longer redirects to a seemingly random tank when clicking enter when searching [Mark Greene] - Tank search now properly handles the full names of tanks like the Super Pershing [Mark Greene] - The tank search now remains consistent in order even when an added filter does not add/remove tanks from the list [Mark Greene] - The test and owned tank filters are now more intuitive as clicking on them now turns the clicked option on instead of off [Mark Greene] -**Visuals & UI** +### Visuals & UI - Removed the Beta badge from the Equalizer button [Mark Greene] - Updated the background image for the Equalizer button to the actual banner of the new game mode @@ -58,16 +58,16 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions - Mixer's controllers now scale better on smaller screens [Mark Greene] - The list of available tanks in the Playlist is no longer excessively wide [Mark Greene] -**Tank Mechanics & Models** +### Tank Mechanics & Models - The gun depression visualizer now properly handles the inherent tilt of tanks like the Minotauro [Mark Greene] - When moving the tracks of tanks, the textures no longer move at different rates [Mark Greene] -**Localization** +### Localization - Users with a preference on a language are once again redirected to the correct localized pages [Mark Greene] -**Session & Game Compatibility** +### Session & Game Compatibility - BlitzKit Session now properly handles tanks removed from the game [Mark Greene] From 0c91ee360031678e329b7758978b5e04bd4e3a06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Fri, 9 Oct 2026 23:33:06 -0500 Subject: [PATCH 35/36] New Crowdin updates (#389) * New translations en.json (Ukrainian) [ci skip] * New translations en.json (Chinese Simplified) [ci skip] * New translations en.json (French) [ci skip] * New translations en.json (Spanish) [ci skip] * New translations en.json (Japanese) [ci skip] * New translations en.json (Polish) [ci skip] * New translations en.json (Portuguese) [ci skip] * New translations en.json (Russian) [ci skip] --- packages/i18n/strings/es.json | 1 + packages/i18n/strings/fr.json | 1 + packages/i18n/strings/ja.json | 1 + packages/i18n/strings/pl.json | 1 + packages/i18n/strings/pt.json | 1 + packages/i18n/strings/ru.json | 1 + packages/i18n/strings/uk.json | 1 + packages/i18n/strings/zh.json | 1 + 8 files changed, 8 insertions(+) diff --git a/packages/i18n/strings/es.json b/packages/i18n/strings/es.json index e877464d5..a4481cde5 100644 --- a/packages/i18n/strings/es.json +++ b/packages/i18n/strings/es.json @@ -623,6 +623,7 @@ "hullTraverseSoftTerrain": "Suave", "health": "Salud", "fireChance": "Probabilidad de incendio", + "trackRepairTime": "Track repair time", "viewRange": "Rango de visión", "camouflageStill": "Quieto", "camouflageMoving": "En movimiento", diff --git a/packages/i18n/strings/fr.json b/packages/i18n/strings/fr.json index ba01e0146..7aeae0160 100644 --- a/packages/i18n/strings/fr.json +++ b/packages/i18n/strings/fr.json @@ -623,6 +623,7 @@ "hullTraverseSoftTerrain": "Soft", "health": "Health", "fireChance": "Fire chance", + "trackRepairTime": "Track repair time", "viewRange": "View range", "camouflageStill": "Still", "camouflageMoving": "Moving", diff --git a/packages/i18n/strings/ja.json b/packages/i18n/strings/ja.json index f56d1986f..11209711e 100644 --- a/packages/i18n/strings/ja.json +++ b/packages/i18n/strings/ja.json @@ -623,6 +623,7 @@ "hullTraverseSoftTerrain": "軟弱地", "health": "耐久値", "fireChance": "火災発生率", + "trackRepairTime": "Track repair time", "viewRange": "視認範囲", "camouflageStill": "静止時", "camouflageMoving": "移動時", diff --git a/packages/i18n/strings/pl.json b/packages/i18n/strings/pl.json index 447d389b3..de8d7a5d0 100644 --- a/packages/i18n/strings/pl.json +++ b/packages/i18n/strings/pl.json @@ -623,6 +623,7 @@ "hullTraverseSoftTerrain": "Soft", "health": "Health", "fireChance": "Fire chance", + "trackRepairTime": "Track repair time", "viewRange": "View range", "camouflageStill": "Still", "camouflageMoving": "Moving", diff --git a/packages/i18n/strings/pt.json b/packages/i18n/strings/pt.json index 757530039..197d34a38 100644 --- a/packages/i18n/strings/pt.json +++ b/packages/i18n/strings/pt.json @@ -623,6 +623,7 @@ "hullTraverseSoftTerrain": "Macio", "health": "Vida", "fireChance": "Chance de incêndio", + "trackRepairTime": "Track repair time", "viewRange": "Alcance de visão", "camouflageStill": "Parado", "camouflageMoving": "Em movimento", diff --git a/packages/i18n/strings/ru.json b/packages/i18n/strings/ru.json index c887147c7..4a75261b4 100644 --- a/packages/i18n/strings/ru.json +++ b/packages/i18n/strings/ru.json @@ -623,6 +623,7 @@ "hullTraverseSoftTerrain": "На мягком грунте", "health": "Прочность", "fireChance": "Вероятность возгорания", + "trackRepairTime": "Track repair time", "viewRange": "Радиус обзора", "camouflageStill": "Когда неподвижен", "camouflageMoving": "В движении", diff --git a/packages/i18n/strings/uk.json b/packages/i18n/strings/uk.json index 1cf6305fe..d09afb611 100644 --- a/packages/i18n/strings/uk.json +++ b/packages/i18n/strings/uk.json @@ -623,6 +623,7 @@ "hullTraverseSoftTerrain": "Soft", "health": "Здоров'я", "fireChance": "Fire chance", + "trackRepairTime": "Track repair time", "viewRange": "View range", "camouflageStill": "Нерухомо", "camouflageMoving": "У русі", diff --git a/packages/i18n/strings/zh.json b/packages/i18n/strings/zh.json index 3ab253b45..6882e04dd 100644 --- a/packages/i18n/strings/zh.json +++ b/packages/i18n/strings/zh.json @@ -623,6 +623,7 @@ "hullTraverseSoftTerrain": "水面上车转速率", "health": "血量", "fireChance": "发动机受击时着火概率", + "trackRepairTime": "Track repair time", "viewRange": "视野范围", "camouflageStill": "静止隐蔽", "camouflageMoving": "移动时", From 7f7d0cc4999923e5a95107a15cc1707e5b538556 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sat, 10 Oct 2026 16:41:57 -0500 Subject: [PATCH 36/36] remove outdated docs --- docs/guides/timezones.md | 9 -- docs/technical/bkrl.md | 45 ---------- docs/technical/dids.md | 18 ---- docs/technical/kitscore.md | 171 +------------------------------------ docs/technical/rts.md | 71 --------------- 5 files changed, 1 insertion(+), 313 deletions(-) delete mode 100644 docs/guides/timezones.md delete mode 100644 docs/technical/bkrl.md delete mode 100644 docs/technical/dids.md delete mode 100644 docs/technical/rts.md diff --git a/docs/guides/timezones.md b/docs/guides/timezones.md deleted file mode 100644 index 631450aaf..000000000 --- a/docs/guides/timezones.md +++ /dev/null @@ -1,9 +0,0 @@ -# Timezones - -What is considered a "day's worth of games" is determined by the reset time. The reset time is generally at midnight everyday after which newer games are counted towards the next day. Reset times vary from region to region: - -- North America: `UTC-5:00` (Central North American Time midnight) -- Europe: `UTC+1:00` (Central European Time midnight) -- Asia: `UTC+7:00` (Central Asia Standard Time midnight) - -**Reset times are different from Blitz Stars** (Blitz Stars resets at 5:00 am locally relative to the user opening their website). Inconsistencies with Blitz Stars only occur with sleep-deprived players and players who play in the wrong region. diff --git a/docs/technical/bkrl.md b/docs/technical/bkrl.md deleted file mode 100644 index b008e11a8..000000000 --- a/docs/technical/bkrl.md +++ /dev/null @@ -1,45 +0,0 @@ -# Blitzkit Rating Leaderboard - -A straightforward way of storing the entire World of Tanks Blitz rating leaderboard to disk. - -```cpp -primary BlitzkitRatingLeaderboard { - utf8"BKRL" magic; - Header header; - primary Body<header> body; -} - -Header { - uint16 version; // always 1 - Format format; - uint32 count; -} - -Format enum<uint8> { - Base, - Superset1, -} - -Body<Header header> match<header.format> { - Base { - primary { - uint32 id; - uint16 score; - }[header.count] entries; - }; - - Superset1 { - primary { - uint32 id; - uint16 score; - - uint32 battles; - uint32 wins; - uint32 survived; - - uint32 damage; - uint32 kills; - }[header.count] entries; - }; -} -``` diff --git a/docs/technical/dids.md b/docs/technical/dids.md deleted file mode 100644 index 6a02cabbf..000000000 --- a/docs/technical/dids.md +++ /dev/null @@ -1,18 +0,0 @@ -# Discovered Ids - -```c -primary DiscoveredIds { - utf8"DIDS" magic; - Header header; - primary Body body; -} - -Header { - uint16 version; // always 1 -} - -Body { - uint32 count; - uint32[count] ids; -} -``` diff --git a/docs/technical/kitscore.md b/docs/technical/kitscore.md index fe8e9dc5a..ab2168005 100644 --- a/docs/technical/kitscore.md +++ b/docs/technical/kitscore.md @@ -1,172 +1,3 @@ # KitScore -## Memo - -KitScore is a performance metric that makes sense. This metric can be applied to any game, virtual or real. Specific pieces of information relating directly to World of Tanks Blitz will be provided within parentheses and with a "WoTB:" prefix. - -## Consumption of Observations - -KitScore is driven solely by the behavior of other players and finding meaning of a new observation within a pool of condensed data based on previously observed data. Generally, we will be provided with a number of statistics (the $x_i$ of an observation) per player (WoTB: $x_\text{frags}$, $x_\text{xp}$, $x_\text{spots}$, etc.) including a target statistic (the $x_j$ of an observation) that all other statistics try to maximize (WoTB: "winrate" which we will defined later as $x_j$). - -If the statistics are cumulative, they will have to be normalized (WoTB: statistics fetched from Wargaming are indeed cumulative even for a single player; $x_\text{frags}=\frac{\Sigma x_\text{frags}}{\Sigma x_\text{battles}}$, $x_\text{spots}=\frac{\Sigma x_\text{spots}}{\Sigma x_\text{battles}}$, $x_j=\frac{\Sigma x_\text{wins}}{\Sigma x_\text{battles}}$, etc.). Each player will have such average statistics, giving us many points of data to work with. If the statistics are not cumulative, then you will be dealing with multiple observations per player which will only help improve accuracy. - -## It's Impossible to "Find What Makes the Metric Tick" - -WN8, a widely adopted metric in the World of Tanks and World of Tanks Blitz communities is plagued with problems. One of them being that people often find and exploit "what makes the metric tick." In other words, people easily exploit the rudimentary nature of WN8 to score undeservedly high. - -In WN8, the gains of some rewarding categories overshadow the losses of others though that may not necessarily be in the best interest in maximizing winrate. KitScore makes this nearly impossible as it punishes a player for scoring well solely high in a certain category. You will never exploit KitScore. Period. - -## Generating Reasonable Values - -TODO: there's like no runaway cases - -## Symbol Interpretation - -| Symbol | Interpretation | -| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -| $A_\text{human}$ | The human readable version of the raw score $A$. | -| $A$ | The raw KitScore. | -| $C$ | An arbitrary coefficient. | -| $I$ | The number of statistics including the target statistic. This means that there are $I-1$ entries for $x_i$ and $1$ entry for $y$ for each observation. | -| $i$ | The statistic index of where there are $I$ entries. | -| $j$ | A discriminator for the target statistic. There may never be more than $1$ entries for $j$. | -| $m$ | The degree of the polynomial regression. | -| $n$ | The number of observations. | -| $a$ | An "atomic" score which is a function of the $i$th statistic. | -| $w$ | The weight of the $i$th atomic statistic. | - -## Computing the Score - -The final metric $A_\text{human}$ is an arbitrarily scaled value of the raw score $A$ where $C$ is any coefficient of your liking. BlitzKit uses $C=10^3$. - -$$ -A_\text{human}=CA -$$ - -The final metric $A$ is the weighted average of individual scores $a$ which are functions of the $i$th statistic excluding the target statistic $j$ itself. - -$$ -A=\frac{\sum_{i \neq j} w_{i}a_{i}}{\sum_{i \neq j} w_{i}} -$$ - -The "atomic" score $a$ is the difference between the predicted target statistic $P_{i \leftrightarrow j}(x_i)$ acquired using a polynomial regression of degree $m$ and the actual newly observed $x_j$. - -$$ -a_i=x_j-P_{i \leftrightarrow j}(x_i) -$$ - -The polynomial regression of $m$th degree can be written as follows: - -$$ -P(x)=\beta_0x^0+\beta_1x^1+\beta_2x^2+\dots+\beta_mx^m -$$ - -Polynomial regression coefficients $\beta$ can be acquired through basic linear algebra where an $m \times m$ of constants is multiplied with $m \times 1$ of unknowns which equals another $m \times 1$ of constants. - -```math -\begin{bmatrix} -\sum_{k=1}^n x_i^0 & \sum_{k=1}^n x_i^1 & \sum_{k=1}^n x_i^2 & \dots & \sum_{k=1}^n x_i^m \\ -\sum_{k=1}^n x_i^1 & \sum_{k=1}^n x_i^2 & \sum_{k=1}^n x_i^3 & \dots & \sum_{k=1}^n x_i^{m+1} \\ -\sum_{k=1}^n x_i^2 & \sum_{k=1}^n x_i^3 & \sum_{k=1}^n x_i^4 & \dots & \sum_{k=1}^n x_i^{m+2} \\ -\vdots & \vdots & \vdots & \ddots & \vdots \\ -\sum_{k=1}^n x_i^m & \sum_{k=1}^n x_i^{m+1} & \sum_{k=1}^n x_i^{m+1} & \dots & \sum_{k=1}^n x_i^{2m} \\ -\end{bmatrix} - -\begin{bmatrix} -\beta_0 \\ -\beta_1 \\ -\beta_2 \\ -\vdots \\ -\beta_m -\end{bmatrix} - -= - -\begin{bmatrix} -\sum_{k=1}^n x_jx_i^0 \\ -\sum_{k=1}^n x_jx_i^1 \\ -\sum_{k=1}^n x_jx_i^2 \\ -\vdots \\ -\sum_{k=1}^n x_jx_i^m -\end{bmatrix} -``` - -The weight $w$ is a slice of the Pearson corelation matrix. The numerator is the corelation between the $i$th statistic and the target statistic $j$ while the denominator the sum of the corelations between the $i$th statistic and all statistics but the target statistic $j$. - -$$ -w_{i}=\frac{r_{i\leftrightarrow j}^2}{\sum_{i_{k}\neq j}r_{i\leftrightarrow i_{k}}^2} -$$ - -## Understanding the Corelation Matrix - -Forming the corelation matrix will create an $I \times I$ matrix where. This matrix is best represented as a table. The example below illustrates a matrix/table for $I=4$ which includes $3$ entries for $i$ statistics and $1$ entry for the $j$ target statistic. - -| | $x_1$ | $x_2$ | $x_3$ | $x_j$ | -| ----- | --------------------------- | --------------------------- | --------------------------- | --------------------------- | -| $x_1$ | $1$ | $r_{1 \leftrightarrow 2}^2$ | $r_{1 \leftrightarrow 3}^2$ | $r_{1 \leftrightarrow j}^2$ | -| $x_2$ | $r_{1 \leftrightarrow 2}^2$ | $1$ | $r_{2 \leftrightarrow 3}^2$ | $r_{2 \leftrightarrow j}^2$ | -| $x_3$ | $r_{1 \leftrightarrow 3}^2$ | $r_{2 \leftrightarrow 3}^2$ | $1$ | $r_{3 \leftrightarrow j}^2$ | -| $x_j$ | $r_{1 \leftrightarrow j}^2$ | $r_{2 \leftrightarrow j}^2$ | $r_{3 \leftrightarrow j}^2$ | $1$ | - -It should not be a surprise to find $r_{i \leftrightarrow i}^2=1$ which forms a neat diagonal across the table. Note that there are many duplicates within the $I^2$ entries. The "bottom-right triangle" can be eliminated to remove redundancies leaving us with only $\frac{I(I+1)}{2}$ fields occupied. - -| | $x_1$ | $x_2$ | $x_3$ | $x_j$ | -| ----- | ----- | --------------------------- | --------------------------- | --------------------------- | -| $x_1$ | $1$ | $r_{1 \leftrightarrow 2}^2$ | $r_{1 \leftrightarrow 3}^2$ | $r_{1 \leftrightarrow j}^2$ | -| $x_2$ | | $1$ | $r_{2 \leftrightarrow 3}^2$ | $r_{2 \leftrightarrow j}^2$ | -| $x_3$ | | | $1$ | $r_{3 \leftrightarrow j}^2$ | -| $x_j$ | | | | $1$ | - -When programming this matrix into an array, $r_{i \leftrightarrow i}^2=1$ will be redundant. I recommend condensing the matrix into an array of size $\frac{I(I+1)}{2}+I=\frac{I(I-1)}{2}$ to avoid all redundant entries. For $I=4$, the array will look something like the one illustrated below (here, $j=4$). - -$$ -[r_{1 \leftrightarrow 2}^2, r_{1 \leftrightarrow 3}^2, r_{1 \leftrightarrow 4}^2, r_{2 \leftrightarrow 3}^2, r_{2 \leftrightarrow 4}^2, r_{3 \leftrightarrow 4}^2] -$$ - -## Understanding the Weights - -Some may find the weight equation arbitrary; it evidently isn't. The goal of $w$ is to eliminate over-rewarding the same behavior represented in multiple statistics. It makes all atomic statistics concurrent by leveraging the Pearson corelation matrix. - -A simplified example will clarify the idea. First, we compute a Pearson corelation matrix for $I=3$ statistics. We have $x_1$ and $x_2$, the statistics that are trying to maximize $x_j$. Reminder: a Pearson corelation matrix finds the $r$ value not only between $x_i$ and $x_j$ but also between all combinations of $x_i$ and themselves. Here, $r^2$ is calculated using polynomial regression corelation analysis to the $m$th degree. - -| | $x_1$ | $x_2$ | $x_3$ | $x_j$ | -| ----- | ----- | ----------- | ----- | ----- | -| $x_1$ | $1$ | $\boxed{0}$ | $0$ | $1$ | -| $x_2$ | | $1$ | $0$ | $1$ | -| $x_3$ | | | $1$ | $1$ | -| $x_j$ | | | | $1$ | - -In the case above, $r^2_{1 \leftrightarrow 2}=0$ meaning that both statistics have absolutely nothing to do with each other. Hence, the player will be awarded for optimizing both individually. And since $r^2_{1 \leftrightarrow j}=r^2_{2 \leftrightarrow j}$, they should both be rewarded equally; in other words, they should have equal weights. - -$$ -w_{1}=\frac{1}{1 + 0 + 0}=1 -$$ - -$$ -w_{2}=\frac{1}{0 + 1 + 0}=1 -$$ - -$$ -w_{3}=\frac{1}{0 + 0 + 1}=1 -$$ - -Now consider a case where $x_1$ and $x_2$ are fully correlated. It would be a bad idea to reward them equally; hence, their weights suffer. - -| | $x_1$ | $x_2$ | $x_3$ | $x_j$ | -| ----- | ----- | ----------- | ----- | ----- | -| $x_1$ | $1$ | $\boxed{1}$ | $0$ | $1$ | -| $x_2$ | | $1$ | $0$ | $1$ | -| $x_3$ | | | $1$ | $1$ | -| $x_j$ | | | | $1$ | - -$$ -w_{1}=\frac{1}{1 + 1 + 0}=0.5 -$$ - -$$ -w_{2}=\frac{1}{1 + 1 + 0}=0.5 -$$ - -$$ -w_{3}=\frac{1}{0 + 0 + 1}=1 -$$ +Remind me to write out the linearized model! diff --git a/docs/technical/rts.md b/docs/technical/rts.md deleted file mode 100644 index 18b814b2e..000000000 --- a/docs/technical/rts.md +++ /dev/null @@ -1,71 +0,0 @@ -# BlitzKit Regular Tank Stats - -A straightforward way of storing the entire World of Tanks Blitz tank statistics for players to disk. - -## Manifest `manifest.rtsm` - -```cpp -primary RegularTankStatisticsManifest { - utf8"RTSM" magic; - Header header; - primary Body body; -} - -Header { - uint16 version; // always 1 -} - -Body { - uint32 time; - uint8 base; -} -``` - -## Chunk `*.rtsc` - -```cpp -primary RegularTankStatisticsChunk { - utf8"RTSC" magic; - Header header; - primary Body body<header.playerCount>; -} - -Header { - uint16 version; // always 1 - uint32 playerCount; -} - -Body<uint32 playerCount> { - Player[playerCount] players; -} - -Player { - uint32 id; - uint16 tankCount; - Tank[tankCount] tanks; -} - -Tank { - uint32 id; - uint32 battleLifeTime; - uint32 lastBattleTime; - uint8 markOfMastery; - uint32 battles; - uint32 capturePoints; - uint32 damageDealt; - uint32 damageReceived; - uint32 droppedCapturePoints; - uint32 frags; - uint32 frags8p; - uint32 hits; - uint32 losses; - uint8 maxFrags; - uint16 maxXp; - uint32 shots; - uint32 spotted; - uint32 survivedBattles; - uint32 winAndSurvived; - uint32 wins; - uint32 xp; -} -```