From b38c732983dbbbe1102461cb560534989d735f6e Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sat, 14 Dec 2024 15:46:47 -0600 Subject: [PATCH 01/19] fix: missing image backup --- packages/bot/src/commands/rating.tsx | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/bot/src/commands/rating.tsx b/packages/bot/src/commands/rating.tsx index 29ddaf439..1188c3706 100644 --- a/packages/bot/src/commands/rating.tsx +++ b/packages/bot/src/commands/rating.tsx @@ -7,6 +7,7 @@ import { getLeagueFromScore, getRatingInfo, getRatingNeighbors, + imgur, } from '@blitzkit/core'; import { SlashCommandSubcommandBuilder } from 'discord.js'; import markdownEscape from 'markdown-escape'; @@ -119,6 +120,19 @@ export const ratingCommand = new Promise((resolve) => { statsB2, ); const leagueTheme = LEAGUE_ACCENT[league.index]; + let rewardImage = reward + ? reward.type === 'vehicle' + ? reward.vehicle.preview_image_url + : reward.stuff.image_url + : undefined; + + if (rewardImage) { + const { ok } = await fetch(rewardImage); + + if (!ok) { + rewardImage = imgur('kP88vqr'); + } + } return ( @@ -325,11 +339,7 @@ export const ratingCommand = new Promise((resolve) => { height: 64, objectFit: 'cover', }} - src={await iconPng( - reward.type === 'vehicle' - ? reward.vehicle.preview_image_url - : reward.stuff.image_url, - )} + src={await iconPng(rewardImage!)} /> )} From bc9c9ad4e7086dd6a1ddec3180f75e8fd380aca5 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sat, 14 Dec 2024 22:32:28 -0600 Subject: [PATCH 02/19] feat: start of custom renders --- .../TankSandbox/components/Control.tsx | 8 +++- .../components/TankSandbox/index.tsx | 14 +++++-- .../api/tankopedia/tank-icon/[id]/_index.tsx | 40 +++++++++++++++++++ .../api/tankopedia/tank-icon/[id]/index.astro | 30 ++++++++++++++ 4 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 packages/website/src/pages/api/tankopedia/tank-icon/[id]/_index.tsx create mode 100644 packages/website/src/pages/api/tankopedia/tank-icon/[id]/index.astro diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/Control.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/Control.tsx index 75e173ea4..0b6403752 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/Control.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/Control.tsx @@ -35,7 +35,11 @@ const ARCADE_MODE_DISTANCE = 19; const ARCADE_MODE_ANGLE = degToRad(10); const ARCADE_MODE_FOV = 54; -export function Controls() { +interface ControlsProps { + naked?: boolean; +} + +export function Controls({ naked }: ControlsProps) { const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation(); const display = TankopediaEphemeral.use((state) => state.display); const duelStore = Duel.useStore(); @@ -82,7 +86,7 @@ export function Controls() { antagonistModelDefinition.turret_origin.y + antagonistTurretModelDefinition.gun_origin.y; const [autoRotate, setAutoRotate] = useState( - display !== TankopediaDisplay.ShootingRange, + display !== TankopediaDisplay.ShootingRange && !naked, ); const gunHeight = protagonistHullOrigin.y + diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/index.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/index.tsx index 0c920375c..511d3c09c 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/index.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/index.tsx @@ -31,10 +31,11 @@ import { TankModel } from './components/TankModel'; interface TankSandboxProps { thicknessRange: ThicknessRange; + naked?: boolean; } export const TankSandbox = forwardRef( - ({ thicknessRange }, ref) => { + ({ thicknessRange, naked }, ref) => { const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation(); const canvas = useRef(null); const hasImprovedVerticalStabilizer = useEquipment(122); @@ -179,10 +180,15 @@ export const TankSandbox = forwardRef( draft.highlightArmor = undefined; }); }} - style={{ userSelect: 'none' }} + style={{ + userSelect: 'none', + width: naked ? 640 : '100%', + height: naked ? 480 : '100%', + outline: naked ? '1rem red solid' : undefined, + }} > - - + + {!naked && } {display !== TankopediaDisplay.StaticArmor && } diff --git a/packages/website/src/pages/api/tankopedia/tank-icon/[id]/_index.tsx b/packages/website/src/pages/api/tankopedia/tank-icon/[id]/_index.tsx new file mode 100644 index 000000000..213149ea1 --- /dev/null +++ b/packages/website/src/pages/api/tankopedia/tank-icon/[id]/_index.tsx @@ -0,0 +1,40 @@ +import { TankSandbox } from '../../../../../components/Tankopedia/HeroSection/components/TankSandbox'; +import { awaitableModelDefinitions } from '../../../../../core/awaitables/modelDefinitions'; +import { awaitableProvisionDefinitions } from '../../../../../core/awaitables/provisionDefinitions'; +import { awaitableTankDefinitions } from '../../../../../core/awaitables/tankDefinitions'; +import { App } from '../../../../../stores/app'; +import { Duel } from '../../../../../stores/duel'; +import { TankopediaEphemeral } from '../../../../../stores/tankopediaEphemeral'; +import { TankopediaPersistent } from '../../../../../stores/tankopediaPersistent'; + +const [provisionDefinitions, tankDefinitions, modelDefinitions] = + await Promise.all([ + awaitableProvisionDefinitions, + awaitableTankDefinitions, + awaitableModelDefinitions, + ]); + +interface PageProps { + id: number; +} + +export function Page({ id }: PageProps) { + const tank = tankDefinitions.tanks[id]; + const model = modelDefinitions.models[id]; + + return ( + + + + + + + + + + ); +} + +function Content() { + return ; +} diff --git a/packages/website/src/pages/api/tankopedia/tank-icon/[id]/index.astro b/packages/website/src/pages/api/tankopedia/tank-icon/[id]/index.astro new file mode 100644 index 000000000..7aa817f2b --- /dev/null +++ b/packages/website/src/pages/api/tankopedia/tank-icon/[id]/index.astro @@ -0,0 +1,30 @@ +--- +import { assertSecret } from '@blitzkit/core'; +import type { GetStaticPaths } from 'astro'; +import { getStaticPaths as tankopediaGetStaticPaths } from '../../../../tools/tankopedia/[id]/index.astro'; +import { Page } from './_index'; + +export const getStaticPaths = (async () => { + if (assertSecret(import.meta.env.MODE) === 'development') { + return await tankopediaGetStaticPaths(); + } else { + return []; + } +}) satisfies GetStaticPaths; + +const { id } = Astro.params; +--- + + + + + + + + + + From 318a71bd32d1ad3e077d0a2f1ee0bc979a42ecd2 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sun, 15 Dec 2024 18:13:23 -0600 Subject: [PATCH 03/19] feat: advanced mode --- .../PrimaryArmorSceneComponent/index.tsx | 19 ++- .../shaders/fragment.glsl | 20 +++- .../HeroSection/components/Options/index.tsx | 108 +++++++++++------- .../TankSandbox/components/Control.tsx | 1 - .../src/stores/tankopediaPersistent/index.ts | 2 + 5 files changed, 98 insertions(+), 52 deletions(-) diff --git a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx index 519646c10..462288558 100644 --- a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx +++ b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx @@ -49,6 +49,7 @@ export function PrimaryArmorSceneComponent({ damage: { value: null }, explosionRadius: { value: null }, greenPenetration: { value: null }, + advancedHighlighting: { value: null }, opaque: { value: null }, inverseProjectionMatrix: { value: null }, @@ -90,6 +91,9 @@ export function PrimaryArmorSceneComponent({ function handleGreenPenetrationChange(greenPenetration: boolean) { material.uniforms.greenPenetration.value = greenPenetration; } + function handleAdvancedHighlightingChange(advancedHighlighting: boolean) { + material.uniforms.advancedHighlighting.value = advancedHighlighting; + } function handleOpaqueChange(opaque: boolean) { material.uniforms.opaque.value = opaque; } @@ -133,12 +137,13 @@ export function PrimaryArmorSceneComponent({ if (!noInvalidate) invalidate(); } + const initialState = tankopediaPersistentStore.getState(); + handleShellChange(); - handleGreenPenetrationChange( - tankopediaPersistentStore.getState().greenPenetration, - ); - handleOpaqueChange(tankopediaPersistentStore.getState().opaque); - handleWireframeChange(tankopediaPersistentStore.getState().wireframe); + handleGreenPenetrationChange(initialState.greenPenetration); + handleAdvancedHighlightingChange(initialState.advancedHighlighting); + handleOpaqueChange(initialState.opaque); + handleWireframeChange(initialState.wireframe); handleProtagonistEquipmentChange( duelStore.getState().protagonist.equipmentMatrix, ); @@ -156,6 +161,10 @@ export function PrimaryArmorSceneComponent({ (state) => state.greenPenetration, handleGreenPenetrationChange, ), + tankopediaPersistentStore.subscribe( + (state) => state.advancedHighlighting, + handleAdvancedHighlightingChange, + ), tankopediaPersistentStore.subscribe( (state) => state.opaque, handleOpaqueChange, diff --git a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl index 045d49a80..76bc4520f 100644 --- a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl +++ b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl @@ -12,6 +12,7 @@ uniform bool canSplash; uniform float damage; uniform float explosionRadius; uniform bool greenPenetration; +uniform bool advancedHighlighting; uniform bool opaque; uniform mat4 inverseProjectionMatrix; @@ -27,16 +28,18 @@ float depthToDistance(float depth) { void main() { float penetrationChance = -1.0; float splashChance = -1.0; + bool didRicochet = false; vec2 screenCoordinates = gl_FragCoord.xy / resolution; float angle = acos(dot(vNormal, -vViewPosition) / length(vViewPosition)); vec4 spacedArmorBufferFragment = texture2D(spacedArmorBuffer, screenCoordinates); bool isUnderSpacedArmor = spacedArmorBufferFragment.a != 0.0; - bool threeCalibersRule = caliber > thickness * 3.0 || isUnderSpacedArmor; + if (!threeCalibersRule && angle >= ricochet) { penetrationChance = 0.0; + didRicochet = true; } else { bool twoCalibersRule = caliber > thickness * 2.0 && thickness > 0.0; float finalNormalization = twoCalibersRule ? ((1.4 * normalization * caliber) / (2.0 * thickness)) : normalization; @@ -82,11 +85,22 @@ void main() { float alpha = opaque ? 1.0 : 0.5; vec3 color = vec3(1.0, splashChance * 0.392, 0.0); - if (greenPenetration) { + + if (advancedHighlighting && didRicochet) { + color = vec3(1.0, color.g, 1.0); + } + + if (greenPenetration || advancedHighlighting) { // non-trigonometric red-green mixing: https://www.desmos.com/calculator/ceo1oq7l67 float falling = -pow(penetrationChance, 2.0) + 1.0; float gaining = -pow(penetrationChance - 1.0, 2.0) + 1.0; - gl_FragColor = vec4(falling * color + gaining * vec3(0.0, 1.0, 0.0), alpha); + vec3 penetrationColor = vec3(0.0, 1.0, 0.0); + + if (advancedHighlighting && threeCalibersRule) { + penetrationColor = vec3(0.0, 1.0, 1.0); + } + + gl_FragColor = vec4(falling * color + gaining * penetrationColor, alpha); } else { gl_FragColor = vec4(color, (1.0 - penetrationChance) * alpha); } diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx index 20dad8563..1e4baa024 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx @@ -17,6 +17,7 @@ import { import { Box, Button, + Checkbox, Dialog, DropdownMenu, Flex, @@ -68,6 +69,9 @@ export function Options({ thicknessRange, canvas }: OptionsProps) { const greenPenetration = TankopediaPersistent.use( (state) => state.greenPenetration, ); + const advancedHighlighting = TankopediaPersistent.use( + (state) => state.advancedHighlighting, + ); const wireframe = TankopediaPersistent.use((state) => state.wireframe); const opaque = TankopediaPersistent.use((state) => state.opaque); const fullScreenAvailable = useFullscreenAvailability(); @@ -325,53 +329,71 @@ export function Options({ thicknessRange, canvas }: OptionsProps) { style={{ transform: 'translateX(-50%)' }} > {display === TankopediaDisplay.DynamicArmor && ( - - - Shooter: - - + { + mutateTankopediaPersistent((draft) => { + draft.advancedHighlighting = !draft.advancedHighlighting; + }); + }} > - - - + + + Advanced highlighting + + - - Select tank + + + Shooter: + + + + + - - { - mutateDuel((draft) => { - draft.antagonist.tank = tank; - draft.antagonist.engine = tank.engines.at(-1)!; - draft.antagonist.track = tank.tracks.at(-1)!; - draft.antagonist.turret = tank.turrets.at(-1)!; - draft.antagonist.gun = - draft.antagonist.turret.guns.at(-1)!; - draft.antagonist.shell = - draft.antagonist.gun.gun_type!.value.base.shells[0]; - }); - setAntagonistSelectorOpen(false); - }} - /> - - - - + + Select tank + + + { + mutateDuel((draft) => { + draft.antagonist.tank = tank; + draft.antagonist.engine = tank.engines.at(-1)!; + draft.antagonist.track = tank.tracks.at(-1)!; + draft.antagonist.turret = tank.turrets.at(-1)!; + draft.antagonist.gun = + draft.antagonist.turret.guns.at(-1)!; + draft.antagonist.shell = + draft.antagonist.gun.gun_type!.value.base.shells[0]; + }); + setAntagonistSelectorOpen(false); + }} + /> + + + + + )} - diff --git a/packages/website/src/stores/tankopediaPersistent/index.ts b/packages/website/src/stores/tankopediaPersistent/index.ts index c70dd4607..d8054b75a 100644 --- a/packages/website/src/stores/tankopediaPersistent/index.ts +++ b/packages/website/src/stores/tankopediaPersistent/index.ts @@ -12,6 +12,7 @@ export type TankopediaTestTankDisplay = 'include' | 'exclude' | 'only'; export interface TankopediaPersistentStore { wireframe: boolean; opaque: boolean; + advancedHighlighting: boolean; environment: (typeof ENVIRONMENTS)[number]; showGrid: boolean; greenPenetration: boolean; @@ -33,6 +34,7 @@ export const TankopediaPersistent = createContextualStore(() => subscribeWithSelector(() => ({ wireframe: false, opaque: false, + advancedHighlighting: false, environment: ENVIRONMENTS[0], showGrid: true, greenPenetration: false, From d78f8c6ec4c9516c708a81869175b7d98bc14897 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sun, 15 Dec 2024 18:21:03 -0600 Subject: [PATCH 04/19] feat: optimize constants --- .../shaders/fragment.glsl | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl index 76bc4520f..c280336f4 100644 --- a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl +++ b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl @@ -19,6 +19,11 @@ uniform mat4 inverseProjectionMatrix; uniform highp sampler2D spacedArmorBuffer; uniform highp sampler2D spacedArmorDepth; +const float HALF = 0.5; +const float EXPLOSION_DAMAGE_FACTOR = 1.1; +const float RANDOMIZATION_FACTOR = 0.05; +const float GREEN_VALUE = 0.392; + float depthToDistance(float depth) { vec4 clipPosition = vec4(gl_FragCoord.xy / resolution * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0); vec4 eyePosition = inverseProjectionMatrix * clipPosition; @@ -53,7 +58,7 @@ void main() { if (canSplash && isUnderSpacedArmor) { float spacedArmorThickness = spacedArmorBufferFragment.r * penetration; - float finalDamage = 0.5 * damage * (1.0 - distanceFromSpacedArmor / explosionRadius) - 1.1 * (finalThickness + spacedArmorThickness); + float finalDamage = HALF * damage * (1.0 - distanceFromSpacedArmor / explosionRadius) - EXPLOSION_DAMAGE_FACTOR * (finalThickness + spacedArmorThickness); penetrationChance = 0.0; splashChance = finalDamage > 0.0 ? 1.0 : 0.0; @@ -65,17 +70,17 @@ void main() { remainingPenetration -= spacedArmorThickness; if (isExplosive && remainingPenetration > 0.0) { - remainingPenetration -= 0.5 * remainingPenetration * distanceFromSpacedArmor; + remainingPenetration -= HALF * remainingPenetration * distanceFromSpacedArmor; } } remainingPenetration = max(0.0, remainingPenetration); float delta = finalThickness - remainingPenetration; - float randomization = remainingPenetration * 0.05; + float randomization = remainingPenetration * RANDOMIZATION_FACTOR; penetrationChance = clamp(1.0 - (delta + randomization) / (2.0 * randomization), 0.0, 1.0); if (canSplash) { - float splashDamage = 0.5 * damage - 1.1 * finalThickness; + float splashDamage = HALF * damage - EXPLOSION_DAMAGE_FACTOR * finalThickness; splashChance = splashDamage > 0.0 ? 1.0 : 0.0; } else { splashChance = 0.0; @@ -83,8 +88,8 @@ void main() { } } - float alpha = opaque ? 1.0 : 0.5; - vec3 color = vec3(1.0, splashChance * 0.392, 0.0); + float alpha = opaque ? 1.0 : HALF; + vec3 color = vec3(1.0, splashChance * GREEN_VALUE, 0.0); if (advancedHighlighting && didRicochet) { color = vec3(1.0, color.g, 1.0); From 853c520d8a4c58351e2913964f716443fc82a44d Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sun, 15 Dec 2024 18:26:34 -0600 Subject: [PATCH 05/19] feat: optimize depth sampling --- .../PrimaryArmorSceneComponent/shaders/fragment.glsl | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl index c280336f4..0275503e5 100644 --- a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl +++ b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl @@ -30,6 +30,12 @@ float depthToDistance(float depth) { return length(eyePosition.xyz / eyePosition.w); } +float getDistance(vec2 coord, float depth) { + vec4 clipPos = vec4(coord * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0); + vec4 eyePos = inverseProjectionMatrix * clipPos; + return length(eyePos.xyz / eyePos.w); +} + void main() { float penetrationChance = -1.0; float splashChance = -1.0; @@ -51,9 +57,8 @@ void main() { float finalThickness = thickness / cos(max(0.0, angle - finalNormalization)); // world space in meters - vec4 spacedArmorDepthFragment = texture2D(spacedArmorDepth, screenCoordinates); - float spacedArmorDistance = depthToDistance(spacedArmorDepthFragment.r); - float primaryArmorDistance = depthToDistance(gl_FragCoord.z); + float spacedArmorDistance = getDistance(screenCoordinates, texture2D(spacedArmorDepth, screenCoordinates).r); + float primaryArmorDistance = getDistance(screenCoordinates, gl_FragCoord.z); float distanceFromSpacedArmor = primaryArmorDistance - spacedArmorDistance; if (canSplash && isUnderSpacedArmor) { From a4080f21b9aa43885a2e890c354336224455796a Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sun, 15 Dec 2024 18:33:15 -0600 Subject: [PATCH 06/19] feat: optimize using claude lol --- .../shaders/fragment.glsl | 98 +++++++++---------- 1 file changed, 47 insertions(+), 51 deletions(-) diff --git a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl index 0275503e5..97f0f6a39 100644 --- a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl +++ b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl @@ -24,94 +24,90 @@ const float EXPLOSION_DAMAGE_FACTOR = 1.1; const float RANDOMIZATION_FACTOR = 0.05; const float GREEN_VALUE = 0.392; -float depthToDistance(float depth) { - vec4 clipPosition = vec4(gl_FragCoord.xy / resolution * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0); - vec4 eyePosition = inverseProjectionMatrix * clipPosition; - return length(eyePosition.xyz / eyePosition.w); -} - float getDistance(vec2 coord, float depth) { vec4 clipPos = vec4(coord * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0); vec4 eyePos = inverseProjectionMatrix * clipPos; return length(eyePos.xyz / eyePos.w); } +vec3 getPenetrationColor(bool isThreeCalibersRule) { + if (advancedHighlighting) { + return vec3(0.0, 1.0, isThreeCalibersRule ? 1.0 : 0.0); + } + + return vec3(0.0, 1.0, 0.0); +} + void main() { - float penetrationChance = -1.0; - float splashChance = -1.0; - bool didRicochet = false; + vec2 screenCoord = gl_FragCoord.xy / resolution; + vec4 spacedArmorData = texture2D(spacedArmorBuffer, screenCoord); + bool isUnderSpacedArmor = spacedArmorData.a != 0.0; - vec2 screenCoordinates = gl_FragCoord.xy / resolution; - float angle = acos(dot(vNormal, -vViewPosition) / length(vViewPosition)); + float viewDistance = length(vViewPosition); + float angle = acos(dot(vNormal, -vViewPosition) / viewDistance); - vec4 spacedArmorBufferFragment = texture2D(spacedArmorBuffer, screenCoordinates); - bool isUnderSpacedArmor = spacedArmorBufferFragment.a != 0.0; bool threeCalibersRule = caliber > thickness * 3.0 || isUnderSpacedArmor; + float penetrationChance = -1.0; + float splashChance = 0.0; + bool didRicochet = false; if (!threeCalibersRule && angle >= ricochet) { penetrationChance = 0.0; didRicochet = true; } else { - bool twoCalibersRule = caliber > thickness * 2.0 && thickness > 0.0; - float finalNormalization = twoCalibersRule ? ((1.4 * normalization * caliber) / (2.0 * thickness)) : normalization; - float finalThickness = thickness / cos(max(0.0, angle - finalNormalization)); + float thicknessRatio = thickness > 0.0 ? caliber / thickness : 0.0; + bool twoCalibersRule = thicknessRatio > 2.0; + float finalNorm = twoCalibersRule ? ((1.4 * normalization * caliber) / (2.0 * thickness)) : normalization; + float finalThickness = thickness / cos(max(0.0, angle - finalNorm)); - // world space in meters - float spacedArmorDistance = getDistance(screenCoordinates, texture2D(spacedArmorDepth, screenCoordinates).r); - float primaryArmorDistance = getDistance(screenCoordinates, gl_FragCoord.z); - float distanceFromSpacedArmor = primaryArmorDistance - spacedArmorDistance; + float remainingPen = penetration; - if (canSplash && isUnderSpacedArmor) { - float spacedArmorThickness = spacedArmorBufferFragment.r * penetration; - float finalDamage = HALF * damage * (1.0 - distanceFromSpacedArmor / explosionRadius) - EXPLOSION_DAMAGE_FACTOR * (finalThickness + spacedArmorThickness); + if (isUnderSpacedArmor) { + float spacedArmorThickness = spacedArmorData.r * penetration; + remainingPen -= spacedArmorThickness; - penetrationChance = 0.0; - splashChance = finalDamage > 0.0 ? 1.0 : 0.0; - } else { - float remainingPenetration = penetration; + if (isExplosive && remainingPen > 0.0) { + float spacedDist = getDistance(screenCoord, texture2D(spacedArmorDepth, screenCoord).r); + float primaryDist = getDistance(screenCoord, gl_FragCoord.z); + float distFromArmor = primaryDist - spacedDist; - if (isUnderSpacedArmor) { - float spacedArmorThickness = spacedArmorBufferFragment.r * penetration; - remainingPenetration -= spacedArmorThickness; + if (canSplash) { + float finalDamage = HALF * damage * (1.0 - distFromArmor / explosionRadius) - EXPLOSION_DAMAGE_FACTOR * (finalThickness + spacedArmorThickness); + splashChance = step(0.0, finalDamage); + penetrationChance = 0.0; - if (isExplosive && remainingPenetration > 0.0) { - remainingPenetration -= HALF * remainingPenetration * distanceFromSpacedArmor; + } else { + remainingPen -= HALF * remainingPen * distFromArmor; } } + } - remainingPenetration = max(0.0, remainingPenetration); - float delta = finalThickness - remainingPenetration; - float randomization = remainingPenetration * RANDOMIZATION_FACTOR; + if (penetrationChance < 0.0) { + remainingPen = max(0.0, remainingPen); + float delta = finalThickness - remainingPen; + float randomization = remainingPen * RANDOMIZATION_FACTOR; penetrationChance = clamp(1.0 - (delta + randomization) / (2.0 * randomization), 0.0, 1.0); if (canSplash) { float splashDamage = HALF * damage - EXPLOSION_DAMAGE_FACTOR * finalThickness; - splashChance = splashDamage > 0.0 ? 1.0 : 0.0; - } else { - splashChance = 0.0; + splashChance = step(0.0, splashDamage); } } } float alpha = opaque ? 1.0 : HALF; - vec3 color = vec3(1.0, splashChance * GREEN_VALUE, 0.0); + vec3 baseColor = vec3(1.0, splashChance * GREEN_VALUE, 0.0); if (advancedHighlighting && didRicochet) { - color = vec3(1.0, color.g, 1.0); + baseColor = vec3(1.0, baseColor.g, 1.0); } if (greenPenetration || advancedHighlighting) { - // non-trigonometric red-green mixing: https://www.desmos.com/calculator/ceo1oq7l67 - float falling = -pow(penetrationChance, 2.0) + 1.0; - float gaining = -pow(penetrationChance - 1.0, 2.0) + 1.0; - vec3 penetrationColor = vec3(0.0, 1.0, 0.0); - - if (advancedHighlighting && threeCalibersRule) { - penetrationColor = vec3(0.0, 1.0, 1.0); - } - - gl_FragColor = vec4(falling * color + gaining * penetrationColor, alpha); + float falling = -penetrationChance * penetrationChance + 1.0; + float gaining = -(penetrationChance - 1.0) * (penetrationChance - 1.0) + 1.0; + vec3 penColor = getPenetrationColor(threeCalibersRule); + gl_FragColor = vec4(falling * baseColor + gaining * penColor, alpha); } else { - gl_FragColor = vec4(color, (1.0 - penetrationChance) * alpha); + gl_FragColor = vec4(baseColor, (1.0 - penetrationChance) * alpha); } } \ No newline at end of file From d865043b34bb0bd1510fbcd5ca198c1f0cb5eb81 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sun, 15 Dec 2024 18:39:24 -0600 Subject: [PATCH 07/19] fix: invalidate on advanced highlighting change --- .../Armor/components/PrimaryArmorSceneComponent/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx index 462288558..45a326318 100644 --- a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx +++ b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx @@ -93,6 +93,7 @@ export function PrimaryArmorSceneComponent({ } function handleAdvancedHighlightingChange(advancedHighlighting: boolean) { material.uniforms.advancedHighlighting.value = advancedHighlighting; + invalidate(); } function handleOpaqueChange(opaque: boolean) { material.uniforms.opaque.value = opaque; From f9c4cee30c020da60a3fd3d6c73550a80b973a15 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sun, 15 Dec 2024 18:46:59 -0600 Subject: [PATCH 08/19] feat: disable vercel deployments --- vercel.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 vercel.json diff --git a/vercel.json b/vercel.json new file mode 100644 index 000000000..540ffc64e --- /dev/null +++ b/vercel.json @@ -0,0 +1,7 @@ +{ + "git": { + "deploymentEnabled": { + "main": false + } + } +} From 4f6b41e264b891b386b94d48d6c4c17b2e475838 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sun, 15 Dec 2024 18:59:20 -0600 Subject: [PATCH 09/19] feat: start work on website deployment --- .../{build-website.yml => website.yml} | 38 +++++++++++++++---- .vscode/settings.json | 1 + 2 files changed, 31 insertions(+), 8 deletions(-) rename .github/workflows/{build-website.yml => website.yml} (70%) diff --git a/.github/workflows/build-website.yml b/.github/workflows/website.yml similarity index 70% rename from .github/workflows/build-website.yml rename to .github/workflows/website.yml index cfa126071..c09345069 100644 --- a/.github/workflows/build-website.yml +++ b/.github/workflows/website.yml @@ -1,8 +1,7 @@ -name: Build Website +name: Website on: push: - branches: main workflow_dispatch: schedule: @@ -52,14 +51,37 @@ jobs: with: path: dist/website - deploy: - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - needs: build - runs-on: ubuntu-latest + deploy-github-pages: + if: github.ref == 'refs/heads/main' + name: Deploy + 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 + + deploy-vercel: + name: Deploy + needs: build + runs-on: ubuntu-latest + environment: + name: Preview + url: ${{ steps.deployment.outputs.page_url }} + + steps: + - uses: oven-sh/setup-bun@v1 + + - name: Install Vercel CLI + run: bun install --global vercel@latest + + - name: Pull Vercel environment information + run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} + + - name: Deploy project artifacts to vercel + run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} diff --git a/.vscode/settings.json b/.vscode/settings.json index a263f4dd4..6be5a5ada 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -189,6 +189,7 @@ "unpickled", "Unregistering", "unrotate", + "vercel", "vickers", "vitepress", "Vovko", From bb99220497e6e04f3fc3616cb3c3c60930b3d2bf Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sun, 15 Dec 2024 19:06:05 -0600 Subject: [PATCH 10/19] feat: /auction strikethrough and warning --- packages/bot/src/commands/auction.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/bot/src/commands/auction.ts b/packages/bot/src/commands/auction.ts index d9c97a330..ed5a85285 100644 --- a/packages/bot/src/commands/auction.ts +++ b/packages/bot/src/commands/auction.ts @@ -68,6 +68,8 @@ interface Currency { type: 'currency'; } +const WARNING_COUNT = 500; + export const auctionCommand = new Promise((resolve) => { resolve({ command: createLocalizedCommand('auction'), @@ -116,12 +118,16 @@ export const auctionCommand = new Promise((resolve) => { data.current_count.toLocaleString(interaction.locale), data.initial_count.toLocaleString(interaction.locale), ]); + const nextLine = `\n-# ${next}`; + const isOut = data.current_count === 0; + const outString = isOut ? '~~' : ''; + const isLow = data.current_count <= WARNING_COUNT; - return `${ - index + 1 - }. ${name} <:gold:1317173197082333244> ${data.price!.value.toLocaleString( + return `${index + 1}. ${ + outString + }${name} <:gold:1317173197082333244> ${data.price!.value.toLocaleString( interaction.locale, - )}\n-# ${available}\n-# ${next}`; + )}${outString}\n-# ${available}${isLow ? ' ⚠️' : ''}${isOut ? '' : nextLine}`; }); const header = `${title}\n${subtitle}`; const lines = [header, ...body]; From 55927258ca3dbbe6aea40d1b890eb551c2f36d22 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sun, 15 Dec 2024 19:08:31 -0600 Subject: [PATCH 11/19] feat: use better emoji --- packages/bot/src/commands/auction.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bot/src/commands/auction.ts b/packages/bot/src/commands/auction.ts index ed5a85285..d9d8de6b6 100644 --- a/packages/bot/src/commands/auction.ts +++ b/packages/bot/src/commands/auction.ts @@ -127,7 +127,7 @@ export const auctionCommand = new Promise((resolve) => { outString }${name} <:gold:1317173197082333244> ${data.price!.value.toLocaleString( interaction.locale, - )}${outString}\n-# ${available}${isLow ? ' ⚠️' : ''}${isOut ? '' : nextLine}`; + )}${outString}\n-#${isLow ? ' ‼️ ' : ' '}${available}${isOut ? '' : nextLine}`; }); const header = `${title}\n${subtitle}`; const lines = [header, ...body]; From 374d6c22f92ffd6ef3b8c875d389ba76c61dbc5d Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sun, 15 Dec 2024 19:25:13 -0600 Subject: [PATCH 12/19] feat: use artifact --- .github/workflows/website.yml | 21 +++++++++++---------- .gitignore | 1 + vercel.json | 6 ++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index c09345069..c81909adb 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -72,16 +72,17 @@ jobs: runs-on: ubuntu-latest environment: name: Preview - url: ${{ steps.deployment.outputs.page_url }} steps: - - uses: oven-sh/setup-bun@v1 + - name: Download artifact + uses: actions/download-artifact@v4 + with: + path: ./dist/website - - name: Install Vercel CLI - run: bun install --global vercel@latest - - - name: Pull Vercel environment information - run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} - - - name: Deploy project artifacts to vercel - run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} + - uses: amondnet/vercel-action@v25 + with: + vercel-token: ${{ secrets.VERCEL_TOKEN }} + github-token: ${{ secrets.GITHUB_TOKEN }} + vercel-org-id: ${{ secrets.VERCEL_ORG_ID}} + vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }} + working-directory: ./dist/website diff --git a/.gitignore b/.gitignore index 7cb0c5661..8834744dc 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ target # !packages/core/src/protos/*.proto /.vercel /.astro +.vercel diff --git a/vercel.json b/vercel.json index 540ffc64e..80e57248a 100644 --- a/vercel.json +++ b/vercel.json @@ -1,7 +1,5 @@ { - "git": { - "deploymentEnabled": { - "main": false - } + "github": { + "enabled": false } } From 066f17a2f3797ef425f132a84d6a3049d10feb74 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sun, 15 Dec 2024 19:26:36 -0600 Subject: [PATCH 13/19] fix: concurrent only on main --- .github/workflows/website.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index c81909adb..bf4eab4b5 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -14,7 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true + cancel-in-progress: ${{ github.ref == 'refs/heads/main' }} env: PUBLIC_WARGAMING_APPLICATION_ID: ${{ secrets.PUBLIC_WARGAMING_APPLICATION_ID }} From 6bcaf685f83d5f71d2097e23e24ec052d2b6616f Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sun, 15 Dec 2024 19:26:58 -0600 Subject: [PATCH 14/19] fix: names --- .github/workflows/website.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index bf4eab4b5..68d2a0377 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -54,7 +54,7 @@ jobs: deploy-github-pages: if: github.ref == 'refs/heads/main' - name: Deploy + name: Deploy to GitHub Pages runs-on: ubuntu-latest needs: build environment: @@ -67,7 +67,7 @@ jobs: uses: actions/deploy-pages@v4 deploy-vercel: - name: Deploy + name: Deploy to Vercel needs: build runs-on: ubuntu-latest environment: From d07a6e954e2fd5626d6e4275d4ac432c34eed05f Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sun, 15 Dec 2024 19:30:22 -0600 Subject: [PATCH 15/19] fix: remove dead code --- .../TankSandbox/components/Control.tsx | 16 ---------------- .../SceneProps/components/TargetCircle.tsx | 2 +- .../website/src/components/TierList/Tile.tsx | 2 +- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/Control.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/Control.tsx index 7bd3fdb37..4b87c69b5 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/Control.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/Control.tsx @@ -8,10 +8,6 @@ import { degToRad } from 'three/src/math/MathUtils.js'; import { awaitableModelDefinitions } from '../../../../../../core/awaitables/modelDefinitions'; import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits'; import { hasEquipment } from '../../../../../../core/blitzkit/hasEquipment'; -import { - modelTransformEvent, - type ModelTransformEventData, -} from '../../../../../../core/blitzkit/modelTransform'; import { Pose, poseEvent } from '../../../../../../core/blitzkit/pose'; import { Duel } from '../../../../../../stores/duel'; import { @@ -253,10 +249,6 @@ export function Controls({ naked }: ControlsProps) { canvas.addEventListener('wheel', handleWheel); document.body.addEventListener('scroll', handleScroll); - const sniperModeCameraOffset = new Vector3(); - let pitch = 0; - let yaw = 0; - function updateCamera() { if (!orbitControls.current) return; @@ -311,13 +303,6 @@ export function Controls({ naked }: ControlsProps) { camera.updateProjectionMatrix(); } - function handleModelTransform(event: ModelTransformEventData) { - pitch = event.pitch; - yaw = event.yaw ?? yaw; - } - - modelTransformEvent.on(handleModelTransform); - updateCamera(); const unsubscribeDisplay = tankopediaEphemeralStore.subscribe( @@ -341,7 +326,6 @@ export function Controls({ naked }: ControlsProps) { window.removeEventListener('keydown', handleKeyDown); canvas.removeEventListener('wheel', handleWheel); document.body.removeEventListener('scroll', handleScroll); - modelTransformEvent.off(handleModelTransform); }; }, [display === TankopediaDisplay.ShootingRange]); diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/SceneProps/components/TargetCircle.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/SceneProps/components/TargetCircle.tsx index dfdc6589a..151045d70 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/SceneProps/components/TargetCircle.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/SceneProps/components/TargetCircle.tsx @@ -3,7 +3,7 @@ import { Box, type BoxProps } from '@radix-ui/themes'; import { forwardRef } from 'react'; import { Var } from '../../../../../../../../core/radix/var'; -const DOTS = 32; +// const DOTS = 32; type TargetCircleProps = BoxProps & { variant: 'client' | 'server'; diff --git a/packages/website/src/components/TierList/Tile.tsx b/packages/website/src/components/TierList/Tile.tsx index 6e3ef7736..c569f19b6 100644 --- a/packages/website/src/components/TierList/Tile.tsx +++ b/packages/website/src/components/TierList/Tile.tsx @@ -68,7 +68,7 @@ export function TierListTile(props: TierListTileProps) { lastPosition.current = { x: event.clientX, y: event.clientY }; }, []); - const handlePointerUp = useCallback((event: PointerEvent) => { + const handlePointerUp = useCallback(() => { if (!card.current) return; const cardRect = card.current.getBoundingClientRect(); From d9aca6a3edc50e43192ae9e59ec715ef27eee9e5 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sun, 15 Dec 2024 19:35:25 -0600 Subject: [PATCH 16/19] fix: include .git --- .github/workflows/website.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index 68d2a0377..9d1915491 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -74,6 +74,9 @@ jobs: name: Preview steps: + # vercel begs for the .git dir so here it is my guy + - uses: actions/checkout@v4 + - name: Download artifact uses: actions/download-artifact@v4 with: From e296267ccd1840f9943c0f2b2d9f2815f381878a Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Mon, 16 Dec 2024 10:30:05 -0600 Subject: [PATCH 17/19] feat: add cpr --- packages/bot/src/main.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/bot/src/main.ts b/packages/bot/src/main.ts index c6ccd605b..6857c5b32 100644 --- a/packages/bot/src/main.ts +++ b/packages/bot/src/main.ts @@ -7,8 +7,19 @@ import { manager } from './core/discord/manager'; console.log('pre manager event listeners and spawn'); +let isFirst = true; +const interval = setInterval(() => { + if (!isFirst) { + console.warn('respawning all shards because manager died'); + manager.respawnAll(); + } + + isFirst = false; +}, 5000); + const shards = await manager .on('shardCreate', (shard) => { + clearInterval(interval); console.log(`🟡 Launching shard ${shard.id}`); shard.on('ready', () => console.log(`🟢 Launched shard ${shard.id}`)); }) From 50a3d1e922e4e26eef6c1bdfdbfbe32470a43bb0 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Mon, 16 Dec 2024 10:34:14 -0600 Subject: [PATCH 18/19] feat: logs --- docs/changelogs/1.26.4.md | 15 +++++++++++++++ package.json | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 docs/changelogs/1.26.4.md diff --git a/docs/changelogs/1.26.4.md b/docs/changelogs/1.26.4.md new file mode 100644 index 000000000..f79137bcd --- /dev/null +++ b/docs/changelogs/1.26.4.md @@ -0,0 +1,15 @@ +# BlitzKit 1.26.4 + +## Features + +- `/auction` now warns if a tank stock is at or below 500 and now strikes through the tank name if its out +- Added advanced armor highlighting mode + - Green: penetration + - Red: blocked + - Pink: ricochet + - Cyan: penetration with 3 calibers rule +- Optimized the armor highlighting for about a 15% increase in frame rate + +## Fixes + +- Added 5000 doses of adrenaline, incase the BOT DECIDES TO DIE AGAIN FOR NO REASON diff --git a/package.json b/package.json index de13f3b0a..6ea76e4e5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "blitzkit", "private": true, - "version": "1.26.3", + "version": "1.26.4", "description": "🎉 Tools for everything World of Tanks Blitz", "type": "module", "types": "./types.d.ts", From e7f47fd2fd06e81511a91f6abcc04d7c32e746d2 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Mon, 16 Dec 2024 10:41:10 -0600 Subject: [PATCH 19/19] feat: handle no next price --- packages/bot/src/commands/auction.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/bot/src/commands/auction.ts b/packages/bot/src/commands/auction.ts index d9d8de6b6..cc8da1920 100644 --- a/packages/bot/src/commands/auction.ts +++ b/packages/bot/src/commands/auction.ts @@ -27,7 +27,7 @@ type Result = available_from?: Date; available_before?: Date; price?: Price; - next_price?: Price | null; + next_price: Price | null; available: true; display?: boolean; next_price_datetime: Date; @@ -109,16 +109,18 @@ export const auctionCommand = new Promise((resolve) => { const name = `[${tank.name}]()`; - const next = translate('bot.commands.auction.body.next', [ - `<:gold:1317173197082333244> ${data.next_price!.value.toLocaleString( - interaction.locale, - )}`, - ]); + const next = + data.next_price === null + ? '' + : `\n-# ${translate('bot.commands.auction.body.next', [ + `<:gold:1317173197082333244> ${data.next_price.value.toLocaleString( + interaction.locale, + )}`, + ])}`; const available = translate('bot.commands.auction.body.available', [ data.current_count.toLocaleString(interaction.locale), data.initial_count.toLocaleString(interaction.locale), ]); - const nextLine = `\n-# ${next}`; const isOut = data.current_count === 0; const outString = isOut ? '~~' : ''; const isLow = data.current_count <= WARNING_COUNT; @@ -127,7 +129,7 @@ export const auctionCommand = new Promise((resolve) => { outString }${name} <:gold:1317173197082333244> ${data.price!.value.toLocaleString( interaction.locale, - )}${outString}\n-#${isLow ? ' ‼️ ' : ' '}${available}${isOut ? '' : nextLine}`; + )}${outString}\n-#${isLow ? ' ‼️ ' : ' '}${available}${isOut ? '' : next}`; }); const header = `${title}\n${subtitle}`; const lines = [header, ...body];