Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
56ca4dcc61 | ||
|
|
d08b537721 | ||
|
|
c1a2edb489 | ||
|
|
164b7fa454 | ||
|
|
428483cf4c | ||
|
|
89f02eb399 | ||
|
|
4ce127516c | ||
|
|
6f4f487dfe | ||
|
|
57dd60e804 | ||
|
|
d24fd2250c | ||
|
|
e00bcdfc06 | ||
|
|
67dd204ee6 | ||
|
|
e130583fa4 | ||
|
|
6ad20a0fcf | ||
|
|
9fad644d7a | ||
|
|
8cb523dd06 | ||
|
|
b50ee23a26 | ||
|
|
a973cf699b | ||
|
|
102abf49c4 | ||
|
|
8929e503ea | ||
|
|
a2a794eb74 | ||
|
|
2e95f5dd95 | ||
|
|
23a42230cb |
No files matched your search
@@ -0,0 +1,66 @@
|
||||
name: Website UE
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
schedule:
|
||||
- cron: "0 4 * * *"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref == 'refs/heads/main' }}
|
||||
|
||||
env:
|
||||
WOTB_SERVER: ${{ secrets.WOTB_SERVER }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: latest
|
||||
|
||||
- uses: arduino/setup-protoc@v3
|
||||
with:
|
||||
repo-token: ${{ secrets.GH_TOKEN }}
|
||||
|
||||
- uses: actions/configure-pages@v5
|
||||
|
||||
- run: bun run setup
|
||||
|
||||
- name: Build website
|
||||
run: bun run build:website
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v4
|
||||
with:
|
||||
path: dist/website
|
||||
|
||||
deploy-github-pages:
|
||||
if: ${{ github.ref == 'refs/heads/ue' }}
|
||||
name: Deploy to GitHub Pages
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
environment:
|
||||
name: Production
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "blitzkit",
|
||||
"version": "1.29.7",
|
||||
"version": "2.0.0-beta.2",
|
||||
"license": "BlitzKit License",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@@ -35,7 +35,7 @@
|
||||
"build:reviews": "cd packages/scripts && bun build:reviews",
|
||||
"build:ids": "cd packages/scripts && bun build:ids",
|
||||
"prunestrings": "cd packages/scripts && bun prunestrings",
|
||||
"setup": "bun install && bun run build:prisma && bun run build:protos && bun run build:proxyclient",
|
||||
"setup": "bun install && bun run build:prisma && bun run build:protos && bun run build:proxyclient && bun run build:catalogitemaccesssor",
|
||||
"patchnotes": "cd packages/scripts && bun run patchnotes"
|
||||
},
|
||||
"type": "module",
|
||||
|
||||
@@ -4,7 +4,6 @@ import { wrapper } from "@blitzkit/i18n";
|
||||
import locales from "@blitzkit/i18n/locales.json";
|
||||
import strings from "@blitzkit/i18n/strings/en.json";
|
||||
import { mauve, mauveDark } from "@radix-ui/colors";
|
||||
import AstroPWA from "@vite-pwa/astro";
|
||||
import favicons from "astro-favicons";
|
||||
import { defineConfig } from "astro/config";
|
||||
import packageJSON from "../../package.json";
|
||||
@@ -21,13 +20,21 @@ if (!target || !POSSIBLE_TARGETS.includes(target)) {
|
||||
export default defineConfig({
|
||||
devToolbar: { enabled: false },
|
||||
|
||||
vite: { server: { allowedHosts: [] } },
|
||||
vite: {
|
||||
server: { allowedHosts: [] },
|
||||
|
||||
esbuild: {
|
||||
minifyIdentifiers: true,
|
||||
minifySyntax: false,
|
||||
minifyWhitespace: true,
|
||||
},
|
||||
},
|
||||
output: target === "web" ? "static" : "server",
|
||||
site: "https://blitzkit.app",
|
||||
outDir: "../../dist/website",
|
||||
prefetch: { defaultStrategy: "hover", prefetchAll: true },
|
||||
|
||||
build: { concurrency: 4 },
|
||||
// build: { concurrency: 4 },
|
||||
adapter: target === "app" ? node({ mode: "standalone" }) : undefined,
|
||||
|
||||
integrations: [
|
||||
@@ -61,7 +68,7 @@ export default defineConfig({
|
||||
(strings) => strings.website.tools[stringId].name
|
||||
),
|
||||
url: `/${tool.id}`,
|
||||
icon: `public/assets/images/tools/${tool.id}.webp`,
|
||||
icon: `public/assets/tools/${tool.id}.webp`,
|
||||
};
|
||||
}),
|
||||
|
||||
@@ -94,21 +101,6 @@ export default defineConfig({
|
||||
},
|
||||
}),
|
||||
|
||||
AstroPWA({
|
||||
manifest: false,
|
||||
devOptions: { enabled: true },
|
||||
workbox: {
|
||||
globPatterns: ["**/*.{html,css,js,png,webp,svg,xml,json}"],
|
||||
runtimeCaching: [
|
||||
{
|
||||
urlPattern: ({ url }) =>
|
||||
url.href.startsWith(import.meta.env.PUBLIC_ASSET_BASE),
|
||||
handler: "NetworkFirst",
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
|
||||
react(),
|
||||
],
|
||||
});
|
||||
@@ -16,9 +16,9 @@
|
||||
"@blitzkit/closed": "workspace:*",
|
||||
"@blitzkit/core": "workspace:*",
|
||||
"@blitzkit/i18n": "workspace:*",
|
||||
"@fontsource-variable/inter": "^5.2.8",
|
||||
"@radix-ui/colors": "^3.0.0",
|
||||
"@radix-ui/react-icons": "^1.3.2",
|
||||
"@radix-ui/themes": "^3.2.1",
|
||||
"@react-three/drei": "^10.7.6",
|
||||
"@react-three/fiber": "^9.4.0",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
|
||||
|
After Width: | Height: | Size: 481 KiB |
|
Before Width: | Height: | Size: 170 KiB After Width: | Height: | Size: 170 KiB |
|
Before Width: | Height: | Size: 443 KiB After Width: | Height: | Size: 443 KiB |
|
Before Width: | Height: | Size: 330 KiB After Width: | Height: | Size: 330 KiB |
|
Before Width: | Height: | Size: 715 KiB After Width: | Height: | Size: 715 KiB |
|
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 676 KiB After Width: | Height: | Size: 676 KiB |
|
Before Width: | Height: | Size: 188 KiB After Width: | Height: | Size: 188 KiB |
|
Before Width: | Height: | Size: 367 KiB After Width: | Height: | Size: 367 KiB |
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 274 KiB After Width: | Height: | Size: 274 KiB |
|
Before Width: | Height: | Size: 346 KiB After Width: | Height: | Size: 346 KiB |
|
Before Width: | Height: | Size: 208 KiB After Width: | Height: | Size: 208 KiB |
|
Before Width: | Height: | Size: 406 KiB After Width: | Height: | Size: 406 KiB |
|
Before Width: | Height: | Size: 360 KiB After Width: | Height: | Size: 360 KiB |
|
Before Width: | Height: | Size: 193 KiB After Width: | Height: | Size: 193 KiB |
|
Before Width: | Height: | Size: 200 KiB After Width: | Height: | Size: 200 KiB |
@@ -0,0 +1,45 @@
|
||||
---
|
||||
import "@fontsource-variable/roboto-flex/wdth.css";
|
||||
import { TextField } from "./TextField";
|
||||
---
|
||||
|
||||
<style is:global>
|
||||
@import "@radix-ui/colors/violet-dark.css";
|
||||
@import "@radix-ui/colors/plum-dark.css";
|
||||
|
||||
.home-hero {
|
||||
background-image: url(/assets/home-hero.webp);
|
||||
background-size: cover;
|
||||
background-position: top;
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
gap: var(--space-7);
|
||||
|
||||
background: linear-gradient(var(--gray-a11), var(--gray-1));
|
||||
padding: var(--space-9);
|
||||
|
||||
h1 {
|
||||
font-weight: 900;
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
@media (max-width: 40rem) {
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="home-hero">
|
||||
<div class="wrapper">
|
||||
<h1>BlitzKit 2.0</h1>
|
||||
|
||||
<TextField placeholder="Search..." className="search" type="search" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,8 @@
|
||||
input {
|
||||
min-width: 0;
|
||||
background-color: var(--gray-1);
|
||||
border: solid 1px var(--gray-4);
|
||||
color: var(--gray-12);
|
||||
padding: var(--space-3) var(--space-4);
|
||||
border-radius: var(--space-3);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import "./index.css";
|
||||
|
||||
export function TextField(props: ComponentProps<"input">) {
|
||||
return <input {...props} />;
|
||||
}
|
||||
@@ -144,7 +144,13 @@ function patch(stage0: StageParameters, stage1: StageParameters) {
|
||||
}
|
||||
|
||||
if (stage1.pump_reload_times.length > 0) {
|
||||
throw new Error("Pump reload times not implemented");
|
||||
stage0.pump_reload_times = [...stage1.pump_reload_times];
|
||||
}
|
||||
|
||||
if (stage1.pump_reload_times.length < stage0.pump_reload_times.length) {
|
||||
throw new Error(
|
||||
`Pump reload times go down???? (${stage0.pump_reload_times.length} -> ${stage1.pump_reload_times.length})`
|
||||
);
|
||||
}
|
||||
|
||||
if (stage1.pitch_limits_up.length > 0 && stage0.pitch_limits_up.length > 0) {
|
||||
@@ -182,12 +188,9 @@ function patch(stage0: StageParameters, stage1: StageParameters) {
|
||||
|
||||
export function aggregateStageParameters(
|
||||
base: StageParameters,
|
||||
stages: StageParameters[],
|
||||
stage: number
|
||||
stages: StageParameters[]
|
||||
) {
|
||||
const stage0 = StageParameters.create();
|
||||
|
||||
patch(stage0, base);
|
||||
const stage0 = StageParameters.create({ ...base, stage_number: 0 });
|
||||
|
||||
/**
|
||||
* Bug in Reforged: base stats are stage 1, so is the first upgrade. Manually
|
||||
@@ -196,14 +199,12 @@ export function aggregateStageParameters(
|
||||
* stage number to -1.
|
||||
*/
|
||||
|
||||
if (stage0.stage_number === 0 && import.meta.env.DEV) {
|
||||
if (base.stage_number === 0 && import.meta.env.DEV) {
|
||||
throw new Error(
|
||||
"Base stats are now stage 0. In-game bug fixed, please remove hack."
|
||||
);
|
||||
}
|
||||
|
||||
stage0.stage_number = 0;
|
||||
|
||||
stages.forEach((stage) => patch(stage0, stage));
|
||||
|
||||
return stage0;
|
||||
|
||||
@@ -28,10 +28,10 @@ export const characteristics = {
|
||||
);
|
||||
},
|
||||
|
||||
gun_type({ attribute, characteristic }) {
|
||||
const isPump = attribute(
|
||||
TankAttributeChange_AttributeName.ATTRIBUTE_NAME_IS_PUMP
|
||||
);
|
||||
gun_type({ attributeSafe, characteristic }) {
|
||||
const isPump =
|
||||
attributeSafe(TankAttributeChange_AttributeName.ATTRIBUTE_NAME_IS_PUMP) ??
|
||||
0;
|
||||
|
||||
if (isPump === 1) return GunType.AutoReloader;
|
||||
|
||||
@@ -104,6 +104,11 @@ export const characteristics = {
|
||||
break;
|
||||
}
|
||||
|
||||
case GunType.AutoReloader: {
|
||||
return -Infinity;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new Error("Unknown gun type");
|
||||
}
|
||||
@@ -128,14 +133,16 @@ export const characteristics = {
|
||||
},
|
||||
|
||||
shell_velocity({ shell }) {
|
||||
return shell(ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_SPEED);
|
||||
return (
|
||||
shell(ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_SPEED) / 100
|
||||
);
|
||||
},
|
||||
|
||||
shell_range({ shellSafe }) {
|
||||
const maxDistance = shellSafe(
|
||||
ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_MAX_DISTANCE
|
||||
);
|
||||
return maxDistance === null ? Infinity : maxDistance;
|
||||
return maxDistance === null ? Infinity : maxDistance / 100;
|
||||
},
|
||||
|
||||
shell_capacity({ shellSafe }) {
|
||||
@@ -244,15 +251,15 @@ export const characteristics = {
|
||||
},
|
||||
|
||||
power_to_weight_hard() {
|
||||
return -1;
|
||||
return -Infinity;
|
||||
},
|
||||
|
||||
power_to_weight_medium() {
|
||||
return -1;
|
||||
return -Infinity;
|
||||
},
|
||||
|
||||
power_to_weight_soft() {
|
||||
return -1;
|
||||
return -Infinity;
|
||||
},
|
||||
|
||||
turret_traverse_speed({ attribute }) {
|
||||
@@ -262,15 +269,15 @@ export const characteristics = {
|
||||
},
|
||||
|
||||
hull_traverse_speed_hard() {
|
||||
return -1;
|
||||
return -Infinity;
|
||||
},
|
||||
|
||||
hull_traverse_speed_medium() {
|
||||
return -1;
|
||||
return -Infinity;
|
||||
},
|
||||
|
||||
hull_traverse_speed_soft() {
|
||||
return -1;
|
||||
return -Infinity;
|
||||
},
|
||||
|
||||
health({ attribute }) {
|
||||
@@ -280,14 +287,18 @@ export const characteristics = {
|
||||
},
|
||||
|
||||
fire_chance({ attribute }) {
|
||||
return attribute(
|
||||
TankAttributeChange_AttributeName.ATTRIBUTE_NAME_FIRE_START_CHANCE
|
||||
return (
|
||||
attribute(
|
||||
TankAttributeChange_AttributeName.ATTRIBUTE_NAME_FIRE_START_CHANCE
|
||||
) * 100
|
||||
);
|
||||
},
|
||||
|
||||
view_range({ attribute }) {
|
||||
return attribute(
|
||||
TankAttributeChange_AttributeName.ATTRIBUTE_NAME_CIRCULAR_VISION_RADIUS
|
||||
return (
|
||||
attribute(
|
||||
TankAttributeChange_AttributeName.ATTRIBUTE_NAME_CIRCULAR_VISION_RADIUS
|
||||
) / 100
|
||||
);
|
||||
},
|
||||
|
||||
@@ -310,7 +321,7 @@ export const characteristics = {
|
||||
},
|
||||
|
||||
camouflage_shooting_moving() {
|
||||
return -1;
|
||||
return -Infinity;
|
||||
},
|
||||
|
||||
camouflage_on_fire({ attributeSafe }) {
|
||||
@@ -322,14 +333,14 @@ export const characteristics = {
|
||||
},
|
||||
|
||||
height() {
|
||||
return -1;
|
||||
return -Infinity;
|
||||
},
|
||||
|
||||
length() {
|
||||
return -1;
|
||||
return -Infinity;
|
||||
},
|
||||
|
||||
volume() {
|
||||
return -1;
|
||||
return -Infinity;
|
||||
},
|
||||
} satisfies Record<string, Characteristic>;
|
||||
@@ -1,110 +0,0 @@
|
||||
import type { CharacteristicName } from "./characteristics";
|
||||
|
||||
export enum BetterDirection {
|
||||
Higher,
|
||||
Lower,
|
||||
}
|
||||
|
||||
type CharacteristicsOrder = {
|
||||
group: string;
|
||||
order: (
|
||||
| {
|
||||
name: CharacteristicName;
|
||||
decimals?: number;
|
||||
}
|
||||
| {
|
||||
toy: string;
|
||||
}
|
||||
)[];
|
||||
}[];
|
||||
|
||||
export const characteristicsGroups: CharacteristicsOrder = [
|
||||
{
|
||||
group: "firepower",
|
||||
order: [
|
||||
{ name: "gun_type" },
|
||||
{ name: "dpm", decimals: 0 },
|
||||
{ name: "damage" },
|
||||
{ name: "module_damage" },
|
||||
{ name: "penetration" },
|
||||
{ name: "clip_size" },
|
||||
{ name: "reload" },
|
||||
{ name: "intra_clip" },
|
||||
|
||||
{ toy: "reload" },
|
||||
|
||||
{ name: "caliber" },
|
||||
{ name: "normalization" },
|
||||
{ name: "ricochet" },
|
||||
|
||||
{ toy: "ricochet" },
|
||||
|
||||
{ name: "shell_velocity" },
|
||||
{ name: "shell_range" },
|
||||
{ name: "shell_capacity" },
|
||||
|
||||
{ name: "aim_time" },
|
||||
|
||||
{ name: "dispersion_still" },
|
||||
{ name: "dispersion_moving" },
|
||||
{ name: "dispersion_hull_traversing" },
|
||||
{ name: "dispersion_turret_traversing" },
|
||||
{ name: "dispersion_shooting" },
|
||||
{ name: "dispersion_gun_damaged" },
|
||||
|
||||
{ name: "gun_depression" },
|
||||
{ name: "gun_elevation" },
|
||||
|
||||
{ toy: "flexibility" },
|
||||
],
|
||||
},
|
||||
{
|
||||
group: "maneuverability",
|
||||
order: [
|
||||
{ name: "speed_forward" },
|
||||
{ name: "speed_backward" },
|
||||
|
||||
{ name: "engine_power" },
|
||||
{ name: "weight" },
|
||||
|
||||
{ name: "terrain_coefficient_hard" },
|
||||
{ name: "terrain_coefficient_medium" },
|
||||
{ name: "terrain_coefficient_soft" },
|
||||
|
||||
{ name: "power_to_weight_hard" },
|
||||
{ name: "power_to_weight_medium" },
|
||||
{ name: "power_to_weight_soft" },
|
||||
|
||||
{ name: "turret_traverse_speed" },
|
||||
{ name: "hull_traverse_speed_hard" },
|
||||
{ name: "hull_traverse_speed_medium" },
|
||||
{ name: "hull_traverse_speed_soft" },
|
||||
|
||||
{ toy: "traverse" },
|
||||
],
|
||||
},
|
||||
{
|
||||
group: "survivability",
|
||||
order: [
|
||||
{ name: "health" },
|
||||
{ name: "fire_chance" },
|
||||
{ name: "view_range" },
|
||||
|
||||
{ toy: "view_range" },
|
||||
|
||||
{ name: "camouflage_still" },
|
||||
{ name: "camouflage_moving" },
|
||||
{ name: "camouflage_shooting_still" },
|
||||
{ name: "camouflage_shooting_moving" },
|
||||
{ name: "camouflage_on_fire" },
|
||||
|
||||
{ name: "height" },
|
||||
{ name: "length" },
|
||||
{ name: "volume" },
|
||||
],
|
||||
},
|
||||
{
|
||||
group: "miscellaneous",
|
||||
order: [],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,109 @@
|
||||
import type { CharacteristicName } from "./characteristics";
|
||||
|
||||
export enum BetterDirection {
|
||||
Higher,
|
||||
Lower,
|
||||
}
|
||||
|
||||
type CharacteristicsOrder = {
|
||||
group: string;
|
||||
order: (
|
||||
| {
|
||||
name: CharacteristicName;
|
||||
decimals?: number;
|
||||
units?: string;
|
||||
}
|
||||
| {
|
||||
toy: string;
|
||||
}
|
||||
)[];
|
||||
}[];
|
||||
|
||||
export const characteristicsOrder: CharacteristicsOrder = [
|
||||
{
|
||||
group: "firepower",
|
||||
order: [
|
||||
{ name: "gun_type" },
|
||||
{ name: "dpm", decimals: 0, units: "hp_min" },
|
||||
{ name: "damage", units: "hp" },
|
||||
{ name: "module_damage", units: "hp" },
|
||||
{ name: "penetration", units: "mm" },
|
||||
{ name: "clip_size" },
|
||||
{ name: "reload", decimals: 2, units: "s" },
|
||||
{ name: "intra_clip", decimals: 2, units: "s" },
|
||||
|
||||
{ toy: "reload" },
|
||||
|
||||
{ name: "caliber", units: "mm" },
|
||||
{ name: "normalization", units: "deg" },
|
||||
{ name: "ricochet", units: "deg" },
|
||||
|
||||
{ toy: "ricochet" },
|
||||
|
||||
{ name: "shell_velocity", units: "m_s" },
|
||||
{ name: "shell_range", units: "m" },
|
||||
{ name: "shell_capacity" },
|
||||
|
||||
{ name: "aim_time", units: "s" },
|
||||
|
||||
{ toy: "aim_time" },
|
||||
|
||||
{ name: "dispersion_still", units: "m" },
|
||||
{ name: "dispersion_moving", units: "m" },
|
||||
{ name: "dispersion_hull_traversing", units: "m" },
|
||||
{ name: "dispersion_turret_traversing", units: "m" },
|
||||
{ name: "dispersion_shooting", units: "m" },
|
||||
{ name: "dispersion_gun_damaged", units: "m" },
|
||||
|
||||
{ name: "gun_depression", units: "deg" },
|
||||
{ name: "gun_elevation", units: "deg" },
|
||||
|
||||
{ toy: "flexibility" },
|
||||
],
|
||||
},
|
||||
{
|
||||
group: "maneuverability",
|
||||
order: [
|
||||
{ name: "speed_forward", units: "km_h" },
|
||||
{ name: "speed_backward", units: "km_h" },
|
||||
|
||||
{ name: "engine_power", units: "bhp" },
|
||||
{ name: "weight", units: "t" },
|
||||
|
||||
{ name: "terrain_coefficient_hard" },
|
||||
{ name: "terrain_coefficient_medium" },
|
||||
{ name: "terrain_coefficient_soft" },
|
||||
|
||||
{ name: "power_to_weight_hard", units: "bhp_t" },
|
||||
{ name: "power_to_weight_medium", units: "bhp_t" },
|
||||
{ name: "power_to_weight_soft", units: "bhp_t" },
|
||||
|
||||
{ name: "turret_traverse_speed", units: "deg_s" },
|
||||
{ name: "hull_traverse_speed_hard", units: "deg_s" },
|
||||
{ name: "hull_traverse_speed_medium", units: "deg_s" },
|
||||
{ name: "hull_traverse_speed_soft", units: "deg_s" },
|
||||
|
||||
{ toy: "traverse" },
|
||||
],
|
||||
},
|
||||
{
|
||||
group: "survivability",
|
||||
order: [
|
||||
{ name: "health", units: "hp" },
|
||||
{ name: "fire_chance", units: "%" },
|
||||
{ name: "view_range", units: "m" },
|
||||
|
||||
{ toy: "view_range" },
|
||||
|
||||
{ name: "camouflage_still", units: "%" },
|
||||
{ name: "camouflage_moving", units: "%" },
|
||||
{ name: "camouflage_shooting_still", units: "%" },
|
||||
{ name: "camouflage_shooting_moving", units: "%" },
|
||||
{ name: "camouflage_on_fire", units: "%" },
|
||||
|
||||
{ name: "height", units: "m" },
|
||||
{ name: "length", units: "m" },
|
||||
{ name: "volume", units: "m" },
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -1,9 +1,115 @@
|
||||
---
|
||||
import "@fontsource-variable/inter";
|
||||
import type { Color } from "../pages/styles/colors/[accent].css";
|
||||
|
||||
interface Props {
|
||||
accent: Color;
|
||||
}
|
||||
|
||||
const { accent } = Astro.props;
|
||||
|
||||
const accentVariables = {
|
||||
"accent-1": `var(--${accent}-1)`,
|
||||
"accent-2": `var(--${accent}-2)`,
|
||||
"accent-3": `var(--${accent}-3)`,
|
||||
"accent-4": `var(--${accent}-4)`,
|
||||
"accent-5": `var(--${accent}-5)`,
|
||||
"accent-6": `var(--${accent}-6)`,
|
||||
"accent-7": `var(--${accent}-7)`,
|
||||
"accent-8": `var(--${accent}-8)`,
|
||||
"accent-9": `var(--${accent}-9)`,
|
||||
"accent-10": `var(--${accent}-10)`,
|
||||
"accent-11": `var(--${accent}-11)`,
|
||||
"accent-12": `var(--${accent}-12)`,
|
||||
};
|
||||
---
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
||||
<style is:global define:vars={accentVariables}>
|
||||
@import "@radix-ui/colors/mauve-dark.css";
|
||||
@import "@radix-ui/colors/mauve-alpha.css";
|
||||
|
||||
:root {
|
||||
--accent-1: var(--amber-1);
|
||||
--accent-2: var(--amber-2);
|
||||
--accent-3: var(--amber-3);
|
||||
--accent-4: var(--amber-4);
|
||||
--accent-5: var(--amber-5);
|
||||
--accent-6: var(--amber-6);
|
||||
--accent-7: var(--amber-7);
|
||||
--accent-8: var(--amber-8);
|
||||
--accent-9: var(--amber-9);
|
||||
--accent-10: var(--amber-10);
|
||||
--accent-11: var(--amber-11);
|
||||
--accent-12: var(--amber-12);
|
||||
}
|
||||
|
||||
body {
|
||||
--gray-1: var(--mauve-1);
|
||||
--gray-2: var(--mauve-2);
|
||||
--gray-3: var(--mauve-3);
|
||||
--gray-4: var(--mauve-4);
|
||||
--gray-5: var(--mauve-5);
|
||||
--gray-6: var(--mauve-6);
|
||||
--gray-7: var(--mauve-7);
|
||||
--gray-8: var(--mauve-8);
|
||||
--gray-9: var(--mauve-9);
|
||||
--gray-10: var(--mauve-10);
|
||||
--gray-11: var(--mauve-11);
|
||||
--gray-12: var(--mauve-12);
|
||||
|
||||
--gray-a1: var(--mauve-a1);
|
||||
--gray-a2: var(--mauve-a2);
|
||||
--gray-a3: var(--mauve-a3);
|
||||
--gray-a4: var(--mauve-a4);
|
||||
--gray-a5: var(--mauve-a5);
|
||||
--gray-a6: var(--mauve-a6);
|
||||
--gray-a7: var(--mauve-a7);
|
||||
--gray-a8: var(--mauve-a8);
|
||||
--gray-a9: var(--mauve-a9);
|
||||
--gray-a10: var(--mauve-a10);
|
||||
--gray-a11: var(--mauve-a11);
|
||||
--gray-a12: var(--mauve-a12);
|
||||
|
||||
--space-1: 0.25rem;
|
||||
--space-2: 0.5rem;
|
||||
--space-3: 0.75rem;
|
||||
--space-4: 1rem;
|
||||
--space-5: 1.5rem;
|
||||
--space-6: 2rem;
|
||||
--space-7: 2.5rem;
|
||||
--space-8: 3rem;
|
||||
--space-9: 4rem;
|
||||
|
||||
background-color: var(--gray-1);
|
||||
color: var(--gray-12);
|
||||
font-family: "Inter Variable", sans-serif;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
body,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--accent-11);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<body class="dark">
|
||||
<slot />
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
import "@radix-ui/colors/amber-dark.css";
|
||||
import {
|
||||
createProgram,
|
||||
displayPartsToString,
|
||||
forEachChild,
|
||||
isFunctionDeclaration,
|
||||
} from "typescript";
|
||||
import BaseLayout from "../../layouts/BaseLayout.astro";
|
||||
|
||||
const root = `/src/pages/api`;
|
||||
const globbed = import.meta.glob("/src/pages/api/**/*.ts", {
|
||||
eager: true,
|
||||
query: "?raw",
|
||||
});
|
||||
const paths: {
|
||||
path: string;
|
||||
documentation: string;
|
||||
}[] = [];
|
||||
|
||||
for (const fullPath in globbed) {
|
||||
const relativePath = `.${fullPath}`;
|
||||
const path = fullPath.slice(root.length + 1, -3);
|
||||
const program = createProgram([relativePath], {});
|
||||
const source = program.getSourceFile(relativePath);
|
||||
if (!source) throw new Error(`Could not find source for ${fullPath}`);
|
||||
|
||||
const checker = program.getTypeChecker();
|
||||
|
||||
const getter = forEachChild(source, (node) => {
|
||||
if (!isFunctionDeclaration(node) || node.name?.text !== "GET") return;
|
||||
return checker.getSymbolAtLocation(node.name);
|
||||
});
|
||||
|
||||
const documentationComment = getter?.getDocumentationComment(checker);
|
||||
if (!documentationComment) continue;
|
||||
|
||||
const documentation = displayPartsToString(documentationComment);
|
||||
if (documentation.length === 0) continue;
|
||||
|
||||
paths.push({ path, documentation });
|
||||
}
|
||||
|
||||
paths.sort((a, b) => a.path.localeCompare(b.path));
|
||||
---
|
||||
|
||||
<BaseLayout accent="amber">
|
||||
<h1>api</h1>
|
||||
|
||||
{
|
||||
paths.map(({ path, documentation }) => (
|
||||
<>
|
||||
<h2>{path}</h2>
|
||||
<p>{documentation}</p>
|
||||
</>
|
||||
))
|
||||
}
|
||||
</BaseLayout>
|
||||
@@ -8,6 +8,9 @@ export const getStaticPaths = (async () => {
|
||||
return tanks.map(({ id }) => ({ params: { id } }));
|
||||
}) satisfies GetStaticPaths;
|
||||
|
||||
/**
|
||||
* Even Noah can't save these animals.
|
||||
*/
|
||||
export async function GET({ params }: APIContext<never, { id: string }>) {
|
||||
const tank = await api.tank(params.id);
|
||||
return new Response(TankCatalogComponent.encode(tank).finish());
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { characteristicsOrder } from "../../../core/tankopedia/characteristicsOrder";
|
||||
|
||||
/**
|
||||
* The naked man fears no pickpocket.
|
||||
*/
|
||||
export function GET() {
|
||||
return Response.json(characteristicsOrder);
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
import { _characteristicsOrder } from "../../../../core/tankopedia/characteristics";
|
||||
|
||||
export function GET() {
|
||||
return Response.json(_characteristicsOrder);
|
||||
}
|
||||
@@ -1 +1,15 @@
|
||||
go to <a href="/tanks">/tanks</a>
|
||||
---
|
||||
import "@radix-ui/colors/amber-dark.css";
|
||||
import packageJson from "../../../../package.json";
|
||||
import BaseLayout from "../layouts/BaseLayout.astro";
|
||||
---
|
||||
|
||||
<BaseLayout accent="amber">
|
||||
<!-- <HomeHero /> -->
|
||||
|
||||
<h1>blitzkit {packageJson.version}</h1>
|
||||
|
||||
<p><a href="/tanks">/tanks</a></p>
|
||||
|
||||
<p><a href="/api">/api</a></p>
|
||||
</BaseLayout>
|
||||
@@ -0,0 +1,35 @@
|
||||
import * as colors from "@radix-ui/colors";
|
||||
import type { APIContext, GetStaticPaths } from "astro";
|
||||
|
||||
const ignoreEndings = ["A", "P3", "Dark", "DarkA", "DarkP3"] as const;
|
||||
|
||||
const filtered = Object.keys(colors).filter(
|
||||
(name) =>
|
||||
!ignoreEndings.some((ending) => name.endsWith(ending)) &&
|
||||
name !== "__esModule"
|
||||
);
|
||||
|
||||
export const getStaticPaths = (() => {
|
||||
return filtered.map((accent) => ({
|
||||
params: { accent },
|
||||
}));
|
||||
}) satisfies GetStaticPaths;
|
||||
|
||||
export type Color = Exclude<
|
||||
keyof typeof colors,
|
||||
`${string}${(typeof ignoreEndings)[number]}` | "__esModule"
|
||||
>;
|
||||
|
||||
export async function GET({ params }: APIContext<{}, { accent: Color }>) {
|
||||
const palette = colors[`${params.accent}Dark`];
|
||||
let content = ":root{";
|
||||
|
||||
for (const key in palette) {
|
||||
const dashedKey = key.replace(/([a-zA-Z])(\d+)/, "$1-$2");
|
||||
content += `--${dashedKey}:${palette[key as keyof typeof palette]};`;
|
||||
}
|
||||
|
||||
content += "}";
|
||||
|
||||
return new Response(content);
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import { times } from "lodash-es";
|
||||
import { Suspense, useMemo } from "react";
|
||||
import { api } from "../../../core/api/dynamic";
|
||||
import { aggregateStageParameters } from "../../../core/tankopedia/aggregateStageParameters";
|
||||
import { characteristicsGroups } from "../../../core/tankopedia/characteristicsGroups";
|
||||
import { characteristicsOrder } from "../../../core/tankopedia/characteristicsOrder";
|
||||
import { computeCharacteristics } from "../../../core/tankopedia/computeCharacteristics";
|
||||
import { useAwait } from "../../../hooks/useAwait";
|
||||
import { Tankopedia } from "../../../stores/tankopedia";
|
||||
@@ -23,8 +23,7 @@ function Content({ id }: { id: string }) {
|
||||
() =>
|
||||
aggregateStageParameters(
|
||||
tank.base_stats!,
|
||||
tank.upgrade_stages.slice(0, protagonist.stage),
|
||||
protagonist.shell
|
||||
tank.upgrade_stages.slice(0, protagonist.stage)
|
||||
),
|
||||
[protagonist]
|
||||
);
|
||||
@@ -70,7 +69,7 @@ function Content({ id }: { id: string }) {
|
||||
))}
|
||||
</div>
|
||||
|
||||
{characteristicsGroups.map(({ group, order }) => (
|
||||
{characteristicsOrder.map(({ group, order }) => (
|
||||
<>
|
||||
<h2 key={group}>{group}</h2>
|
||||
|
||||
@@ -96,7 +95,7 @@ function Content({ id }: { id: string }) {
|
||||
|
||||
return (
|
||||
<p key={entry.name}>
|
||||
{entry.name}: {rendered}
|
||||
{entry.name}: {rendered} {entry.units && `${entry.units}`}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
---
|
||||
import "@radix-ui/colors/violet-dark.css";
|
||||
import type { GetStaticPaths } from "astro";
|
||||
import { api } from "../../../core/api/dynamic";
|
||||
import BaseLayout from "../../../layouts/BaseLayout.astro";
|
||||
@@ -16,6 +17,6 @@ export const getStaticPaths = (async () => {
|
||||
const { id } = Astro.props;
|
||||
---
|
||||
|
||||
<BaseLayout>
|
||||
<BaseLayout accent="violet">
|
||||
<Page {id} client:load />
|
||||
</BaseLayout>
|
||||
@@ -1,19 +1,21 @@
|
||||
---
|
||||
import "@radix-ui/colors/violet-dark.css";
|
||||
import { api } from "../../core/api/dynamic";
|
||||
import BaseLayout from "../../layouts/BaseLayout.astro";
|
||||
|
||||
const tanksList = await api.tanks();
|
||||
---
|
||||
|
||||
<h1>Tanks</h1>
|
||||
<BaseLayout accent="violet">
|
||||
<h1>tanks</h1>
|
||||
|
||||
<ul>
|
||||
{
|
||||
tanksList.tanks.map(({ id, slug }) => (
|
||||
<li>
|
||||
<p>
|
||||
<a href={`/tanks/${slug}`}>
|
||||
{slug} ({id})
|
||||
</a>
|
||||
</li>
|
||||
</p>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
</BaseLayout>
|
||||
@@ -12,7 +12,7 @@ import { tools } from "./src/constants/tools";
|
||||
|
||||
const POSSIBLE_TARGETS = ["app", "web"];
|
||||
|
||||
const target = process.env.PUBLIC_TARGET ;
|
||||
const target = process.env.PUBLIC_TARGET;
|
||||
|
||||
if (!target || !POSSIBLE_TARGETS.includes(target)) {
|
||||
throw new Error("Invalid target");
|
||||
|
||||