mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 18:57:03 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c54ceb944e | ||
|
|
37a2ba3566 | ||
|
|
caff7bb6d0 | ||
|
|
01c491aee0 | ||
|
|
fd408d6777 | ||
|
|
6d1ed1e56e | ||
|
|
46f9d605f7 | ||
|
|
a65ea42b81 | ||
|
|
40f8c6a915 | ||
|
|
4678359f36 | ||
|
|
f91bd63646 | ||
|
|
c1872262f5 | ||
|
|
082e112758 | ||
|
|
4cb7d50eb5 | ||
|
|
8c050add23 | ||
|
|
2610697d86 | ||
|
|
64f1de37ad | ||
|
|
58f6862279 | ||
|
|
b47f6fdb32 | ||
|
|
ce5a53d0ff | ||
|
|
6ee1fa13d3 |
No files matched your search
@@ -2,10 +2,10 @@ name: CD Build Assets
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: dev
|
branches: [dev, main]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
# schedule:
|
schedule:
|
||||||
# - cron: '0 0 * * *'
|
- cron: '0 0 * * *'
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
@@ -44,10 +44,11 @@ jobs:
|
|||||||
run: yarn setup:depotdownloader
|
run: yarn setup:depotdownloader
|
||||||
|
|
||||||
- name: Run DepotDownloader
|
- name: Run DepotDownloader
|
||||||
run: ./temp/depotDownloader/DepotDownloader.exe -app 444202 -username ${{ secrets.DEPOT_DOWNLOADER_USERNAME }} -password "${{ secrets.DEPOT_DOWNLOADER_PASSWORD }}"
|
run: ./temp/depotDownloader/DepotDownloader.exe -app 444200 -username ${{ secrets.DEPOT_DOWNLOADER_USERNAME }} -password "${{ secrets.DEPOT_DOWNLOADER_PASSWORD }}"
|
||||||
|
|
||||||
- name: Build assets
|
- name: Build assets
|
||||||
run: |
|
run: |
|
||||||
$env:GH_TOKEN = "${{ secrets.GH_TOKEN }}"
|
$env:GH_TOKEN = "${{ secrets.GH_TOKEN }}"
|
||||||
$env:DISCORD_TOKEN = "${{ secrets.DISCORD_TOKEN }}"
|
$env:DISCORD_TOKEN = "${{ secrets.DISCORD_TOKEN }}"
|
||||||
|
$env:DISCORD_BLITZ_DB = "${{ secrets.DISCORD_BLITZ_DB }}"
|
||||||
yarn build:assets --all-targets --depot ${{ github.ref == 'refs/heads/main' && '--production' || '' }}
|
yarn build:assets --all-targets --depot ${{ github.ref == 'refs/heads/main' && '--production' || '' }}
|
||||||
@@ -35,4 +35,4 @@ jobs:
|
|||||||
run: yarn
|
run: yarn
|
||||||
|
|
||||||
- name: Generate leaderboard
|
- name: Generate leaderboard
|
||||||
run: GH_TOKEN=${{ secrets.GH_TOKEN }} DISCORD_TOKEN=${{ secrets.DISCORD_TOKEN }} yarn publish:ratingsleaderboard --region=asia --target=${{ github.event.schedule == '0 0 * * *' && 'latest' || 'midnight' }}
|
run: GH_TOKEN=${{ secrets.GH_TOKEN }} DISCORD_TOKEN=${{ secrets.DISCORD_TOKEN }} DISCORD_BLITZ_DB=${{ secrets.DISCORD_BLITZ_DB }} yarn publish:ratingsleaderboard --region=asia --target=${{ github.event.schedule == '0 0 * * *' && 'latest' || 'midnight' }}
|
||||||
@@ -35,4 +35,4 @@ jobs:
|
|||||||
run: yarn
|
run: yarn
|
||||||
|
|
||||||
- name: Generate leaderboard
|
- name: Generate leaderboard
|
||||||
run: GH_TOKEN=${{ secrets.GH_TOKEN }} DISCORD_TOKEN=${{ secrets.DISCORD_TOKEN }} yarn publish:ratingsleaderboard --region=eu --target=${{ github.event.schedule == '0 0 * * *' && 'latest' || 'midnight' }}
|
run: GH_TOKEN=${{ secrets.GH_TOKEN }} DISCORD_TOKEN=${{ secrets.DISCORD_TOKEN }} DISCORD_BLITZ_DB=${{ secrets.DISCORD_BLITZ_DB }} yarn publish:ratingsleaderboard --region=eu --target=${{ github.event.schedule == '0 0 * * *' && 'latest' || 'midnight' }}
|
||||||
@@ -35,4 +35,4 @@ jobs:
|
|||||||
run: yarn
|
run: yarn
|
||||||
|
|
||||||
- name: Generate leaderboard
|
- name: Generate leaderboard
|
||||||
run: GH_TOKEN=${{ secrets.GH_TOKEN }} DISCORD_TOKEN=${{ secrets.DISCORD_TOKEN }} yarn publish:ratingsleaderboard --region=na --target=${{ github.event.schedule == '0 0 * * *' && 'latest' || 'midnight' }}
|
run: GH_TOKEN=${{ secrets.GH_TOKEN }} DISCORD_TOKEN=${{ secrets.DISCORD_TOKEN }} DISCORD_BLITZ_DB=${{ secrets.DISCORD_BLITZ_DB }} yarn publish:ratingsleaderboard --region=na --target=${{ github.event.schedule == '0 0 * * *' && 'latest' || 'midnight' }}
|
||||||
Vendored
+1
@@ -73,6 +73,7 @@
|
|||||||
"lods",
|
"lods",
|
||||||
"metallicness",
|
"metallicness",
|
||||||
"minitelrose",
|
"minitelrose",
|
||||||
|
"Minotauro",
|
||||||
"MIPMAPCOUNT",
|
"MIPMAPCOUNT",
|
||||||
"modeltransform",
|
"modeltransform",
|
||||||
"MURICA",
|
"MURICA",
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# Blitzkrieg 1.16.2
|
||||||
|
|
||||||
|
¡Hola desde el mundo del español!
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Added translations for Spanish to the bot
|
||||||
|
- Your language will be inferred automatically from your Discord settings
|
||||||
|
- Any untranslated languages and words we forgot to translate will be left in English
|
||||||
|
- If you have your language set to Spanish and see English in any places, please let us know on [the official Discord server](https://discord.gg/nDt7AjGJQH)
|
||||||
|
- All `/about` commands except for `commands` remain in English
|
||||||
|
- Tank names are still in English
|
||||||
|
- The website remains unchanged
|
||||||
|
- The title bar (featured as the big text on top of most commands) has now been made more compact
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
- "Tank type" is now called "tank class"
|
||||||
|
- Removed `/player-achievements` and `search-tanks`
|
||||||
|
- They will be reintroduced in the future in a far better way
|
||||||
|
- Also removed a `SKLLD` server exclusive `/eligible` command
|
||||||
|
- This will be generalized for all clans in the future
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- Fixed the red glowing floor underneath the tank sandbox
|
||||||
|
- This has been replaced with a static image
|
||||||
|
- The refresh button is now properly removed when lacking permissions
|
||||||
|
- Tank names that start with a number are now properly inferred from command inputs
|
||||||
|
|
||||||
|
## Technical Changes
|
||||||
|
|
||||||
|
- Command registration is now error tolerant meaning that if a single command fails to initiate, it will be discarded until the next restart
|
||||||
|
- We are currently looking into how we can allow the command to retry registration after a fixed amount of time
|
||||||
|
- Due to the implications of the code added which can be very easily exploited by hackers, a single file has been added to the repository as a closed source submodule and will remain closed unless a third party open-source implementation is made public
|
||||||
|
- Removed preview commands
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# Blitzkrieg 1.16.3
|
||||||
|
|
||||||
|
Further polishing and corrections for the Tankopedia.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Added a few more stats to view for the Tankopedia
|
||||||
|
- Added the count of shells in the magazine for auto-reloaders
|
||||||
|
- The optimal shell index was moved below this stats
|
||||||
|
- Shell reloads for auto-reloaders now abide crew stats
|
||||||
|
- Intra-clip is now also shown for auto-reloaders
|
||||||
|
- Added 1 more decimal place worth of precision when viewing and changing gun pitch and yaw
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- "Inter-clip" is now correctly spelled as "intra-clip"
|
||||||
|
- Tanks with initial gun pitches (like the Minotauro) are now handled correctly
|
||||||
|
- The stats now reflect the fact that the gun is naturally pitched downwards
|
||||||
|
- The view model now compensates for the natural pitch
|
||||||
|
- Tanks with the improved vertical stabilizer equipment are now handled correctly
|
||||||
|
- The view model now allows you to pitch the gun further as intended when the equipment is on
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
|
import { readdir } from 'fs/promises';
|
||||||
import { argv } from 'process';
|
import { argv } from 'process';
|
||||||
|
|
||||||
const isDepot = argv.includes('--depot');
|
const isDepot = argv.includes('--depot');
|
||||||
export const WOTB_WIN32_DEPOT = 444202;
|
export const WOTB_WIN32_DEPOT = 444202;
|
||||||
export const DATA = isDepot
|
export const DATA = isDepot
|
||||||
? // ? await (async () => {
|
? await (async () => {
|
||||||
// const [installationVersion] = await readdir(`depots/${WOTB_WIN32_DEPOT}`);
|
const [installationVersion] = await readdir(`depots/${WOTB_WIN32_DEPOT}`);
|
||||||
// return `depots/${WOTB_WIN32_DEPOT}/${installationVersion}/Data`;
|
return `depots/${WOTB_WIN32_DEPOT}/${installationVersion}/Data`;
|
||||||
// })()
|
})()
|
||||||
`depots/${WOTB_WIN32_DEPOT}/Data`
|
|
||||||
: 'C:/Program Files (x86)/Steam/steamapps/common/World of Tanks Blitz/Data';
|
: 'C:/Program Files (x86)/Steam/steamapps/common/World of Tanks Blitz/Data';
|
||||||
|
|
||||||
export const POI = {
|
export const POI = {
|
||||||
|
|||||||
@@ -674,7 +674,7 @@ export async function definitions(production: boolean) {
|
|||||||
: turretGunEntry.reloadTime;
|
: turretGunEntry.reloadTime;
|
||||||
const gunClipCount =
|
const gunClipCount =
|
||||||
gunType === 'regular' ? undefined : turretGunEntry.clip!.count;
|
gunType === 'regular' ? undefined : turretGunEntry.clip!.count;
|
||||||
const gunInterClip =
|
const gunIntraClip =
|
||||||
gunType === 'regular'
|
gunType === 'regular'
|
||||||
? undefined
|
? undefined
|
||||||
: 60 / turretGunEntry.clip!.rate;
|
: 60 / turretGunEntry.clip!.rate;
|
||||||
@@ -722,7 +722,7 @@ export async function definitions(production: boolean) {
|
|||||||
type: gunType,
|
type: gunType,
|
||||||
reload: gunReload,
|
reload: gunReload,
|
||||||
count: gunClipCount,
|
count: gunClipCount,
|
||||||
interClip: gunInterClip,
|
intraClip: gunIntraClip,
|
||||||
camouflageLoss:
|
camouflageLoss:
|
||||||
typeof turretGunEntry.invisibilityFactorAtShot === 'number'
|
typeof turretGunEntry.invisibilityFactorAtShot === 'number'
|
||||||
? turretGunEntry.invisibilityFactorAtShot
|
? turretGunEntry.invisibilityFactorAtShot
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { debounce } from 'lodash';
|
|||||||
import { use, useEffect, useRef, useState } from 'react';
|
import { use, useEffect, useRef, useState } from 'react';
|
||||||
import { lerp } from 'three/src/math/MathUtils';
|
import { lerp } from 'three/src/math/MathUtils';
|
||||||
import { ShellButton } from '../../../../../../components/ModuleButtons/ShellButton';
|
import { ShellButton } from '../../../../../../components/ModuleButtons/ShellButton';
|
||||||
|
import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits';
|
||||||
import { isExplosive } from '../../../../../../core/blitz/isExplosive';
|
import { isExplosive } from '../../../../../../core/blitz/isExplosive';
|
||||||
import { resolveNearPenetration } from '../../../../../../core/blitz/resolveNearPenetration';
|
import { resolveNearPenetration } from '../../../../../../core/blitz/resolveNearPenetration';
|
||||||
import { coefficient } from '../../../../../../core/blitzkrieg/coefficient';
|
import { coefficient } from '../../../../../../core/blitzkrieg/coefficient';
|
||||||
@@ -56,6 +57,7 @@ export function Characteristics() {
|
|||||||
turretModelDefinition.boundingBox,
|
turretModelDefinition.boundingBox,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
const gunDefaultPitch = tankModelDefinition.turretRotation?.pitch ?? 0;
|
||||||
const weight =
|
const weight =
|
||||||
tank.weight + engine.weight + track.weight + turret.weight + gun.weight;
|
tank.weight + engine.weight + track.weight + turret.weight + gun.weight;
|
||||||
const weightTons = weight / 1000;
|
const weightTons = weight / 1000;
|
||||||
@@ -113,7 +115,7 @@ export function Characteristics() {
|
|||||||
// TODO: add max rolls
|
// TODO: add max rolls
|
||||||
[hasTungsten, 0.15],
|
[hasTungsten, 0.15],
|
||||||
);
|
);
|
||||||
const interClipCoefficient = coefficient([hasShellReloadBoost, -0.3]);
|
const intraClipCoefficient = coefficient([hasShellReloadBoost, -0.3]);
|
||||||
const shellVelocityCoefficient = coefficient(
|
const shellVelocityCoefficient = coefficient(
|
||||||
[hasSupercharger, 0.3],
|
[hasSupercharger, 0.3],
|
||||||
[hasImprovedGunPowder, 0.3],
|
[hasImprovedGunPowder, 0.3],
|
||||||
@@ -210,7 +212,7 @@ export function Characteristics() {
|
|||||||
shell,
|
shell,
|
||||||
damageCoefficient,
|
damageCoefficient,
|
||||||
reloadCoefficient,
|
reloadCoefficient,
|
||||||
interClipCoefficient,
|
intraClipCoefficient,
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -218,6 +220,17 @@ export function Characteristics() {
|
|||||||
penetrationDistanceInput.current.value = `${penetrationDistance}`;
|
penetrationDistanceInput.current.value = `${penetrationDistance}`;
|
||||||
}
|
}
|
||||||
}, [penetrationDistance]);
|
}, [penetrationDistance]);
|
||||||
|
useEffect(() => {
|
||||||
|
mutateDuel((draft) => {
|
||||||
|
[draft.protagonist!.pitch, draft.protagonist!.yaw] = applyPitchYawLimits(
|
||||||
|
draft.protagonist!.pitch,
|
||||||
|
draft.protagonist!.yaw,
|
||||||
|
gunModelDefinition.pitch,
|
||||||
|
turretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}, [hasImprovedVerticalStabilizer]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex direction="column" gap="8" style={{ width: '100%' }}>
|
<Flex direction="column" gap="8" style={{ width: '100%' }}>
|
||||||
@@ -255,7 +268,7 @@ export function Characteristics() {
|
|||||||
<>
|
<>
|
||||||
<InfoWithDelta decimals={0} indent name="Maximum" unit="hp / min">
|
<InfoWithDelta decimals={0} indent name="Maximum" unit="hp / min">
|
||||||
{gun.reload.at(-1)! < gun.reload.at(-2)!
|
{gun.reload.at(-1)! < gun.reload.at(-2)!
|
||||||
? (shell.damage.armor / (gun.reload.at(-1)! + gun.interClip)) *
|
? (shell.damage.armor / (gun.reload.at(-1)! + gun.intraClip)) *
|
||||||
60
|
60
|
||||||
: (shell.damage.armor / gun.reload[0]) * 60}
|
: (shell.damage.armor / gun.reload[0]) * 60}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
@@ -266,12 +279,12 @@ export function Characteristics() {
|
|||||||
unit="hp / min"
|
unit="hp / min"
|
||||||
>
|
>
|
||||||
{gun.reload.at(-1)! < gun.reload.at(-2)!
|
{gun.reload.at(-1)! < gun.reload.at(-2)!
|
||||||
? (shell.damage.armor / (gun.reload.at(-1)! + gun.interClip)) *
|
? (shell.damage.armor / (gun.reload.at(-1)! + gun.intraClip)) *
|
||||||
(60 -
|
(60 -
|
||||||
(gun.reload.slice(0, -1).length - 1) * gun.interClip) +
|
(gun.reload.slice(0, -1).length - 1) * gun.intraClip) +
|
||||||
shell.damage.armor * gun.reload.slice(0, -1).length
|
shell.damage.armor * gun.reload.slice(0, -1).length
|
||||||
: (shell.damage.armor / (gun.reload[0] + gun.interClip)) *
|
: (shell.damage.armor / (gun.reload[0] + gun.intraClip)) *
|
||||||
(60 - (gun.reload.slice(1).length - 1) * gun.interClip) +
|
(60 - (gun.reload.slice(1).length - 1) * gun.intraClip) +
|
||||||
shell.damage.armor * gun.reload.slice(1).length}
|
shell.damage.armor * gun.reload.slice(1).length}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<Info
|
<Info
|
||||||
@@ -285,14 +298,15 @@ export function Characteristics() {
|
|||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Info indent name="Optimal shell index">
|
|
||||||
{gun.reload.at(-1)! < gun.reload.at(-2)! ? gun.reload.length : 1}
|
|
||||||
</Info>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{gun.type === 'autoReloader' ? (
|
{gun.type === 'autoReloader' ? (
|
||||||
<>
|
<>
|
||||||
<Info name="Reload" unit="s" />
|
<InfoWithDelta name="Shells">{gun.reload.length}</InfoWithDelta>
|
||||||
|
<Info indent name="Most optimal">
|
||||||
|
{gun.reload.at(-1)! < gun.reload.at(-2)! ? gun.reload.length : 1}
|
||||||
|
</Info>
|
||||||
|
<Info name="Shell reloads" unit="s" />
|
||||||
{gun.reload.map((reload, index) => (
|
{gun.reload.map((reload, index) => (
|
||||||
<InfoWithDelta
|
<InfoWithDelta
|
||||||
key={index}
|
key={index}
|
||||||
@@ -301,7 +315,7 @@ export function Characteristics() {
|
|||||||
decimals={2}
|
decimals={2}
|
||||||
deltaType="lowerIsBetter"
|
deltaType="lowerIsBetter"
|
||||||
>
|
>
|
||||||
{reload}
|
{reload * reloadCoefficient}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
@@ -315,17 +329,18 @@ export function Characteristics() {
|
|||||||
{gun.reload * reloadCoefficient}
|
{gun.reload * reloadCoefficient}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
)}
|
)}
|
||||||
{gun.type === 'autoLoader' && (
|
{gun.type === 'autoLoader' ||
|
||||||
<InfoWithDelta
|
(gun.type === 'autoReloader' && (
|
||||||
indent
|
<InfoWithDelta
|
||||||
decimals={2}
|
indent
|
||||||
name="Inter-clip reload"
|
decimals={2}
|
||||||
unit="s"
|
name="Intra-clip"
|
||||||
deltaType="lowerIsBetter"
|
unit="s"
|
||||||
>
|
deltaType="lowerIsBetter"
|
||||||
{gun.interClip * interClipCoefficient}
|
>
|
||||||
</InfoWithDelta>
|
{gun.intraClip * intraClipCoefficient}
|
||||||
)}
|
</InfoWithDelta>
|
||||||
|
))}
|
||||||
<InfoWithDelta name="Caliber" decimals={0} unit="mm">
|
<InfoWithDelta name="Caliber" decimals={0} unit="mm">
|
||||||
{shell.caliber}
|
{shell.caliber}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
@@ -457,10 +472,12 @@ export function Characteristics() {
|
|||||||
<Info name="Gun flexibility" unit="°" />
|
<Info name="Gun flexibility" unit="°" />
|
||||||
<InfoWithDelta decimals={1} indent name="Depression">
|
<InfoWithDelta decimals={1} indent name="Depression">
|
||||||
{gunModelDefinition.pitch.max +
|
{gunModelDefinition.pitch.max +
|
||||||
|
gunDefaultPitch +
|
||||||
(hasImprovedVerticalStabilizer ? 3 : 0)}
|
(hasImprovedVerticalStabilizer ? 3 : 0)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta decimals={1} indent name="Elevation">
|
<InfoWithDelta decimals={1} indent name="Elevation">
|
||||||
{-gunModelDefinition.pitch.min +
|
{-gunModelDefinition.pitch.min -
|
||||||
|
gunDefaultPitch +
|
||||||
(hasImprovedVerticalStabilizer ? 3 : 0)}
|
(hasImprovedVerticalStabilizer ? 3 : 0)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
{gunModelDefinition.pitch.front && (
|
{gunModelDefinition.pitch.front && (
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useEffect, useRef } from 'react';
|
|||||||
import { Vector3 } from 'three';
|
import { Vector3 } from 'three';
|
||||||
import { OrbitControls as OrbitControlsClass } from 'three-stdlib';
|
import { OrbitControls as OrbitControlsClass } from 'three-stdlib';
|
||||||
import { applyPitchYawLimits } from '../../../../../core/blitz/applyPitchYawLimits';
|
import { applyPitchYawLimits } from '../../../../../core/blitz/applyPitchYawLimits';
|
||||||
|
import { hasEquipment } from '../../../../../core/blitzkrieg/hasEquipment';
|
||||||
import { modelDefinitions } from '../../../../../core/blitzkrieg/modelDefinitions';
|
import { modelDefinitions } from '../../../../../core/blitzkrieg/modelDefinitions';
|
||||||
import { Pose, poseEvent } from '../../../../../core/blitzkrieg/pose';
|
import { Pose, poseEvent } from '../../../../../core/blitzkrieg/pose';
|
||||||
import { useAwait } from '../../../../../hooks/useAwait';
|
import { useAwait } from '../../../../../hooks/useAwait';
|
||||||
@@ -67,7 +68,9 @@ export function Controls() {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
function handlePoseEvent(event: Pose) {
|
async function handlePoseEvent(event: Pose) {
|
||||||
|
const hasImprovedVerticalStabilizer = await hasEquipment(122);
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case Pose.HullDown: {
|
case Pose.HullDown: {
|
||||||
const [pitch] = applyPitchYawLimits(
|
const [pitch] = applyPitchYawLimits(
|
||||||
@@ -75,6 +78,7 @@ export function Controls() {
|
|||||||
0,
|
0,
|
||||||
protagonistGunModelDefinition.pitch,
|
protagonistGunModelDefinition.pitch,
|
||||||
protagonistTurretModelDefinition.yaw,
|
protagonistTurretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
|
|
||||||
camera.position
|
camera.position
|
||||||
@@ -106,6 +110,7 @@ export function Controls() {
|
|||||||
0,
|
0,
|
||||||
protagonistGunModelDefinition.pitch,
|
protagonistGunModelDefinition.pitch,
|
||||||
protagonistTurretModelDefinition.yaw,
|
protagonistTurretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
|
|
||||||
camera.position
|
camera.position
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { modelDefinitions } from '../../../../../../core/blitzkrieg/modelDefinit
|
|||||||
import { modelTransformEvent } from '../../../../../../core/blitzkrieg/modelTransform';
|
import { modelTransformEvent } from '../../../../../../core/blitzkrieg/modelTransform';
|
||||||
import { Pose, poseEvent } from '../../../../../../core/blitzkrieg/pose';
|
import { Pose, poseEvent } from '../../../../../../core/blitzkrieg/pose';
|
||||||
import { tankIcon } from '../../../../../../core/blitzkrieg/tankIcon';
|
import { tankIcon } from '../../../../../../core/blitzkrieg/tankIcon';
|
||||||
|
import { useEquipment } from '../../../../../../hooks/useEquipment';
|
||||||
import { useWideFormat } from '../../../../../../hooks/useWideFormat';
|
import { useWideFormat } from '../../../../../../hooks/useWideFormat';
|
||||||
import { mutateDuel, useDuel } from '../../../../../../stores/duel';
|
import { mutateDuel, useDuel } from '../../../../../../stores/duel';
|
||||||
import mutateTankopediaPersistent, {
|
import mutateTankopediaPersistent, {
|
||||||
@@ -29,6 +30,7 @@ import { TankModel } from './components/TankModel';
|
|||||||
|
|
||||||
export function TankSandbox() {
|
export function TankSandbox() {
|
||||||
const canvas = useRef<HTMLCanvasElement>(null);
|
const canvas = useRef<HTMLCanvasElement>(null);
|
||||||
|
const hasImprovedVerticalStabilizer = useEquipment(122);
|
||||||
const awaitedModelDefinitions = use(modelDefinitions);
|
const awaitedModelDefinitions = use(modelDefinitions);
|
||||||
const canvasWrapper = useRef<HTMLDivElement>(null);
|
const canvasWrapper = useRef<HTMLDivElement>(null);
|
||||||
const [isFullScreen, setIsFullScreen] = useState(false);
|
const [isFullScreen, setIsFullScreen] = useState(false);
|
||||||
@@ -70,6 +72,7 @@ export function TankSandbox() {
|
|||||||
0,
|
0,
|
||||||
gunModelDefinition.pitch,
|
gunModelDefinition.pitch,
|
||||||
turretModelDefinition.yaw,
|
turretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
|
|
||||||
modelTransformEvent.emit({ pitch, yaw });
|
modelTransformEvent.emit({ pitch, yaw });
|
||||||
@@ -87,6 +90,7 @@ export function TankSandbox() {
|
|||||||
0,
|
0,
|
||||||
gunModelDefinition.pitch,
|
gunModelDefinition.pitch,
|
||||||
turretModelDefinition.yaw,
|
turretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
|
|
||||||
modelTransformEvent.emit({ pitch, yaw });
|
modelTransformEvent.emit({ pitch, yaw });
|
||||||
@@ -104,6 +108,7 @@ export function TankSandbox() {
|
|||||||
0,
|
0,
|
||||||
gunModelDefinition.pitch,
|
gunModelDefinition.pitch,
|
||||||
turretModelDefinition.yaw,
|
turretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
|
|
||||||
modelTransformEvent.emit({ pitch, yaw });
|
modelTransformEvent.emit({ pitch, yaw });
|
||||||
@@ -131,6 +136,7 @@ export function TankSandbox() {
|
|||||||
draft.protagonist!.yaw,
|
draft.protagonist!.yaw,
|
||||||
gunModelDefinition.pitch,
|
gunModelDefinition.pitch,
|
||||||
turretModelDefinition.yaw,
|
turretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}, [protagonist.gun, protagonist.turret]);
|
}, [protagonist.gun, protagonist.turret]);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Euler, Group, Vector3 } from 'three';
|
|||||||
import { degToRad } from 'three/src/math/MathUtils';
|
import { degToRad } from 'three/src/math/MathUtils';
|
||||||
import { I_HAT, J_HAT, K_HAT } from '../../../../../../../constants/axis';
|
import { I_HAT, J_HAT, K_HAT } from '../../../../../../../constants/axis';
|
||||||
import { applyPitchYawLimits } from '../../../../../../../core/blitz/applyPitchYawLimits';
|
import { applyPitchYawLimits } from '../../../../../../../core/blitz/applyPitchYawLimits';
|
||||||
|
import { hasEquipment } from '../../../../../../../core/blitzkrieg/hasEquipment';
|
||||||
import { jsxTree } from '../../../../../../../core/blitzkrieg/jsxTree';
|
import { jsxTree } from '../../../../../../../core/blitzkrieg/jsxTree';
|
||||||
import { modelDefinitions } from '../../../../../../../core/blitzkrieg/modelDefinitions';
|
import { modelDefinitions } from '../../../../../../../core/blitzkrieg/modelDefinitions';
|
||||||
import {
|
import {
|
||||||
@@ -106,7 +107,6 @@ export const TankModel = memo(() => {
|
|||||||
const turretModelDefinition =
|
const turretModelDefinition =
|
||||||
tankModelDefinition.turrets[protagonist.turret.id];
|
tankModelDefinition.turrets[protagonist.turret.id];
|
||||||
const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id];
|
const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id];
|
||||||
|
|
||||||
const { gltf } = useModel(protagonist.tank.id);
|
const { gltf } = useModel(protagonist.tank.id);
|
||||||
const nodes = Object.values(gltf.nodes);
|
const nodes = Object.values(gltf.nodes);
|
||||||
|
|
||||||
@@ -161,12 +161,14 @@ export const TankModel = memo(() => {
|
|||||||
window.addEventListener('pointerup', handlePointerUp);
|
window.addEventListener('pointerup', handlePointerUp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function handlePointerMove(event: PointerEvent) {
|
async function handlePointerMove(event: PointerEvent) {
|
||||||
|
const hasImprovedVerticalStabilizer = await hasEquipment(122);
|
||||||
[pitch, yaw] = applyPitchYawLimits(
|
[pitch, yaw] = applyPitchYawLimits(
|
||||||
pitch,
|
pitch,
|
||||||
yaw + event.movementX * (Math.PI / canvas.width),
|
yaw + event.movementX * (Math.PI / canvas.width),
|
||||||
gunModelDefinition.pitch,
|
gunModelDefinition.pitch,
|
||||||
turretModelDefinition.yaw,
|
turretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
modelTransformEvent.emit({ pitch, yaw });
|
modelTransformEvent.emit({ pitch, yaw });
|
||||||
}
|
}
|
||||||
@@ -220,12 +222,14 @@ export const TankModel = memo(() => {
|
|||||||
window.addEventListener('pointermove', handlePointerMove);
|
window.addEventListener('pointermove', handlePointerMove);
|
||||||
window.addEventListener('pointerup', handlePointerUp);
|
window.addEventListener('pointerup', handlePointerUp);
|
||||||
}
|
}
|
||||||
function handlePointerMove(event: PointerEvent) {
|
async function handlePointerMove(event: PointerEvent) {
|
||||||
|
const hasImprovedVerticalStabilizer = await hasEquipment(122);
|
||||||
[pitch, yaw] = applyPitchYawLimits(
|
[pitch, yaw] = applyPitchYawLimits(
|
||||||
pitch - event.movementY * (Math.PI / canvas.height),
|
pitch - event.movementY * (Math.PI / canvas.height),
|
||||||
yaw + event.movementX * (Math.PI / canvas.width),
|
yaw + event.movementX * (Math.PI / canvas.width),
|
||||||
gunModelDefinition.pitch,
|
gunModelDefinition.pitch,
|
||||||
turretModelDefinition.yaw,
|
turretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
modelTransformEvent.emit({ pitch, yaw });
|
modelTransformEvent.emit({ pitch, yaw });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Flex, TextField } from '@radix-ui/themes';
|
import { Flex, TextField } from '@radix-ui/themes';
|
||||||
import { use, useEffect, useRef } from 'react';
|
import { use, useEffect, useRef } from 'react';
|
||||||
|
import { degToRad, radToDeg } from 'three/src/math/MathUtils';
|
||||||
import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits';
|
import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits';
|
||||||
import { modelDefinitions } from '../../../../../../core/blitzkrieg/modelDefinitions';
|
import { modelDefinitions } from '../../../../../../core/blitzkrieg/modelDefinitions';
|
||||||
import { modelTransformEvent } from '../../../../../../core/blitzkrieg/modelTransform';
|
import { modelTransformEvent } from '../../../../../../core/blitzkrieg/modelTransform';
|
||||||
@@ -20,22 +21,21 @@ export function RotationInputs({ isFullScreen }: RotationInputsProps) {
|
|||||||
const mode = useTankopediaPersistent((state) => state.mode);
|
const mode = useTankopediaPersistent((state) => state.mode);
|
||||||
const hasCalibratedShells = useEquipment(103, true);
|
const hasCalibratedShells = useEquipment(103, true);
|
||||||
const hasEnhancedArmor = useEquipment(110);
|
const hasEnhancedArmor = useEquipment(110);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
turretYawInput.current!.value = `${-Math.round(
|
|
||||||
protagonist.yaw * (180 / Math.PI),
|
|
||||||
)}`;
|
|
||||||
}, [protagonist.yaw]);
|
|
||||||
useEffect(() => {
|
|
||||||
gunPitchInput.current!.value = `${-Math.round(
|
|
||||||
protagonist.pitch * (180 / Math.PI),
|
|
||||||
)}`;
|
|
||||||
}, [protagonist.pitch]);
|
|
||||||
|
|
||||||
const tankModelDefinition = awaitedModelDefinitions[protagonist.tank.id];
|
const tankModelDefinition = awaitedModelDefinitions[protagonist.tank.id];
|
||||||
const turretModelDefinition =
|
const turretModelDefinition =
|
||||||
tankModelDefinition.turrets[protagonist.turret.id];
|
tankModelDefinition.turrets[protagonist.turret.id];
|
||||||
const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id];
|
const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id];
|
||||||
|
const initialGunPitch = tankModelDefinition.turretRotation?.pitch ?? 0;
|
||||||
|
const hasImprovedVerticalStabilizer = useEquipment(122);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
turretYawInput.current!.value = radToDeg(protagonist.yaw).toFixed(1);
|
||||||
|
}, [protagonist.yaw]);
|
||||||
|
useEffect(() => {
|
||||||
|
gunPitchInput.current!.value = (
|
||||||
|
-radToDeg(protagonist.pitch) + initialGunPitch
|
||||||
|
).toFixed(1);
|
||||||
|
}, [protagonist.pitch]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
@@ -68,22 +68,22 @@ export function RotationInputs({ isFullScreen }: RotationInputsProps) {
|
|||||||
Yaw
|
Yaw
|
||||||
</TextField.Slot>
|
</TextField.Slot>
|
||||||
<TextField.Input
|
<TextField.Input
|
||||||
defaultValue={Math.round(protagonist.yaw * (180 / Math.PI))}
|
|
||||||
onBlur={() => {
|
onBlur={() => {
|
||||||
const [pitch, yaw] = applyPitchYawLimits(
|
const [pitch, yaw] = applyPitchYawLimits(
|
||||||
protagonist.pitch,
|
protagonist.pitch,
|
||||||
-Number(turretYawInput.current?.value) * (Math.PI / 180),
|
degToRad(Number(turretYawInput.current!.value)),
|
||||||
gunModelDefinition.pitch,
|
gunModelDefinition.pitch,
|
||||||
turretModelDefinition.yaw,
|
turretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
modelTransformEvent.emit({ pitch, yaw });
|
modelTransformEvent.emit({ pitch, yaw });
|
||||||
mutateDuel((state) => {
|
mutateDuel((state) => {
|
||||||
state.protagonist!.pitch = pitch;
|
state.protagonist!.pitch = pitch;
|
||||||
state.protagonist!.yaw = yaw;
|
state.protagonist!.yaw = yaw;
|
||||||
});
|
});
|
||||||
turretYawInput.current!.value = `${Math.round(
|
turretYawInput.current!.value = radToDeg(protagonist.yaw).toFixed(
|
||||||
yaw * (180 / Math.PI),
|
1,
|
||||||
)}`;
|
);
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
if (event.key === 'Enter') {
|
if (event.key === 'Enter') {
|
||||||
@@ -116,22 +116,24 @@ export function RotationInputs({ isFullScreen }: RotationInputsProps) {
|
|||||||
Pitch
|
Pitch
|
||||||
</TextField.Slot>
|
</TextField.Slot>
|
||||||
<TextField.Input
|
<TextField.Input
|
||||||
defaultValue={-Math.round(protagonist.pitch * (180 / Math.PI))}
|
|
||||||
onBlur={() => {
|
onBlur={() => {
|
||||||
const [pitch, yaw] = applyPitchYawLimits(
|
const [pitch, yaw] = applyPitchYawLimits(
|
||||||
-Number(gunPitchInput.current?.value) * (Math.PI / 180),
|
degToRad(
|
||||||
|
-Number(gunPitchInput.current!.value) + initialGunPitch,
|
||||||
|
),
|
||||||
protagonist.yaw,
|
protagonist.yaw,
|
||||||
gunModelDefinition.pitch,
|
gunModelDefinition.pitch,
|
||||||
turretModelDefinition.yaw,
|
turretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
modelTransformEvent.emit({ pitch, yaw });
|
modelTransformEvent.emit({ pitch, yaw });
|
||||||
mutateDuel((state) => {
|
mutateDuel((state) => {
|
||||||
state.protagonist!.pitch = pitch;
|
state.protagonist!.pitch = pitch;
|
||||||
state.protagonist!.yaw = yaw;
|
state.protagonist!.yaw = yaw;
|
||||||
});
|
});
|
||||||
gunPitchInput.current!.value = `${Math.round(
|
gunPitchInput.current!.value = (
|
||||||
pitch * (180 / Math.PI),
|
-radToDeg(protagonist.pitch) + initialGunPitch
|
||||||
)}`;
|
).toFixed(1);
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
if (event.key === 'Enter') {
|
if (event.key === 'Enter') {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export function WN8SurroundingStat({
|
|||||||
style={{
|
style={{
|
||||||
color: theme.colors.textHighContrast,
|
color: theme.colors.textHighContrast,
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
fontWeight: 'bold',
|
fontWeight: 700,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{value}
|
{value}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export function RowStat({
|
|||||||
<span
|
<span
|
||||||
style={{
|
style={{
|
||||||
color: theme.textHighContrast,
|
color: theme.textHighContrast,
|
||||||
fontWeight: 'bold',
|
fontWeight: 700,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export default function GenericStatsRow({ stat }: GenericStatsRowProps) {
|
|||||||
<span
|
<span
|
||||||
style={{
|
style={{
|
||||||
color: theme.colors.textHighContrast,
|
color: theme.colors.textHighContrast,
|
||||||
fontWeight: 'bold',
|
fontWeight: 700,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { clamp } from 'lodash';
|
import { clamp } from 'lodash';
|
||||||
|
import { degToRad } from 'three/src/math/MathUtils';
|
||||||
import { PitchLimits, YawLimits } from '../blitzkrieg/modelDefinitions';
|
import { PitchLimits, YawLimits } from '../blitzkrieg/modelDefinitions';
|
||||||
import { normalizeAngleRad } from '../math/normalizeAngleRad';
|
import { normalizeAngleRad } from '../math/normalizeAngleRad';
|
||||||
|
|
||||||
@@ -7,33 +8,31 @@ export function applyPitchYawLimits(
|
|||||||
yaw: number, // rad
|
yaw: number, // rad
|
||||||
pitchLimits: PitchLimits, // deg
|
pitchLimits: PitchLimits, // deg
|
||||||
yawLimits?: YawLimits, // deg
|
yawLimits?: YawLimits, // deg
|
||||||
|
verticalStabilizer = false,
|
||||||
) {
|
) {
|
||||||
let newPitch = pitch;
|
let newPitch = pitch;
|
||||||
let newYaw = yaw;
|
let newYaw = yaw;
|
||||||
|
|
||||||
if (yawLimits) {
|
if (yawLimits) {
|
||||||
newYaw = normalizeAngleRad(
|
newYaw = normalizeAngleRad(
|
||||||
clamp(
|
clamp(newYaw, -degToRad(yawLimits.max), -degToRad(yawLimits.min)),
|
||||||
newYaw,
|
|
||||||
-yawLimits.max * (Math.PI / 180),
|
|
||||||
-yawLimits.min * (Math.PI / 180),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let lowerPitch = -pitchLimits.max * (Math.PI / 180);
|
const pitchBuff = verticalStabilizer ? degToRad(3) : 0;
|
||||||
let upperPitch = -pitchLimits.min * (Math.PI / 180);
|
let lowerPitch = -degToRad(pitchLimits.max) - pitchBuff;
|
||||||
const transition = (pitchLimits.transition ?? 10) * (Math.PI / 180);
|
let upperPitch = -degToRad(pitchLimits.min) + pitchBuff;
|
||||||
|
const transition = degToRad(pitchLimits.transition ?? 10);
|
||||||
|
|
||||||
if (pitchLimits.back) {
|
if (pitchLimits.back) {
|
||||||
const range = pitchLimits.back.range * (Math.PI / 180);
|
const range = degToRad(pitchLimits.back.range);
|
||||||
const yawRotatedAbs = Math.abs(normalizeAngleRad(newYaw - Math.PI));
|
const yawRotatedAbs = Math.abs(normalizeAngleRad(newYaw - Math.PI));
|
||||||
|
|
||||||
if (yawRotatedAbs <= range + transition) {
|
if (yawRotatedAbs <= range + transition) {
|
||||||
if (yawRotatedAbs <= range) {
|
if (yawRotatedAbs <= range) {
|
||||||
// inside range
|
// inside range
|
||||||
lowerPitch = -pitchLimits.back.max * (Math.PI / 180);
|
lowerPitch = -degToRad(pitchLimits.back.max);
|
||||||
upperPitch = -pitchLimits.back.min * (Math.PI / 180);
|
upperPitch = -degToRad(pitchLimits.back.min);
|
||||||
} else {
|
} else {
|
||||||
// inside transition
|
// inside transition
|
||||||
const transitionProgress = (yawRotatedAbs - range) / transition;
|
const transitionProgress = (yawRotatedAbs - range) / transition;
|
||||||
@@ -44,21 +43,21 @@ export function applyPitchYawLimits(
|
|||||||
(1 - transitionProgress) * pitchLimits.back.min +
|
(1 - transitionProgress) * pitchLimits.back.min +
|
||||||
transitionProgress * pitchLimits.min;
|
transitionProgress * pitchLimits.min;
|
||||||
|
|
||||||
lowerPitch = -maxInterpolatedPitch * (Math.PI / 180);
|
lowerPitch = -degToRad(maxInterpolatedPitch);
|
||||||
upperPitch = -minInterpolatedPitch * (Math.PI / 180);
|
upperPitch = -degToRad(minInterpolatedPitch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pitchLimits.front) {
|
if (pitchLimits.front) {
|
||||||
const range = pitchLimits.front.range * (Math.PI / 180);
|
const range = degToRad(pitchLimits.front.range);
|
||||||
const yawAbs = Math.abs(normalizeAngleRad(newYaw));
|
const yawAbs = Math.abs(normalizeAngleRad(newYaw));
|
||||||
|
|
||||||
if (yawAbs <= range + transition) {
|
if (yawAbs <= range + transition) {
|
||||||
if (yawAbs <= range) {
|
if (yawAbs <= range) {
|
||||||
// inside range
|
// inside range
|
||||||
lowerPitch = -pitchLimits.front.max * (Math.PI / 180);
|
lowerPitch = -degToRad(pitchLimits.front.max);
|
||||||
upperPitch = -pitchLimits.front.min * (Math.PI / 180);
|
upperPitch = -degToRad(pitchLimits.front.min);
|
||||||
} else {
|
} else {
|
||||||
// inside transition
|
// inside transition
|
||||||
const transitionProgress = (yawAbs - range) / transition;
|
const transitionProgress = (yawAbs - range) / transition;
|
||||||
@@ -69,8 +68,8 @@ export function applyPitchYawLimits(
|
|||||||
(1 - transitionProgress) * pitchLimits.front.min +
|
(1 - transitionProgress) * pitchLimits.front.min +
|
||||||
transitionProgress * pitchLimits.min;
|
transitionProgress * pitchLimits.min;
|
||||||
|
|
||||||
lowerPitch = -maxInterpolatedPitch * (Math.PI / 180);
|
lowerPitch = -degToRad(maxInterpolatedPitch);
|
||||||
upperPitch = -minInterpolatedPitch * (Math.PI / 180);
|
upperPitch = -degToRad(minInterpolatedPitch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
import { degToRad } from 'three/src/math/MathUtils';
|
||||||
import {
|
import {
|
||||||
DuelMember,
|
DuelMember,
|
||||||
genericDefaultEquipmentMatrix,
|
genericDefaultEquipmentMatrix,
|
||||||
mutateDuel,
|
mutateDuel,
|
||||||
} from '../../stores/duel';
|
} from '../../stores/duel';
|
||||||
import { availableProvisions } from './availableProvisions';
|
import { availableProvisions } from './availableProvisions';
|
||||||
|
import { modelDefinitions } from './modelDefinitions';
|
||||||
import { provisionDefinitions } from './provisionDefinitions';
|
import { provisionDefinitions } from './provisionDefinitions';
|
||||||
import { tankDefinitions } from './tankDefinitions';
|
import { tankDefinitions } from './tankDefinitions';
|
||||||
|
|
||||||
@@ -13,6 +15,8 @@ export async function assignDuelMember(
|
|||||||
) {
|
) {
|
||||||
const awaitedTankDefinitions = await tankDefinitions;
|
const awaitedTankDefinitions = await tankDefinitions;
|
||||||
const awaitedProvisionDefinitions = await provisionDefinitions;
|
const awaitedProvisionDefinitions = await provisionDefinitions;
|
||||||
|
const awaitedModelDefinitions = await modelDefinitions;
|
||||||
|
const tankModelDefinition = awaitedModelDefinitions[id];
|
||||||
const tank = awaitedTankDefinitions[id];
|
const tank = awaitedTankDefinitions[id];
|
||||||
const turret = tank.turrets.at(-1)!;
|
const turret = tank.turrets.at(-1)!;
|
||||||
const gun = turret.guns.at(-1)!;
|
const gun = turret.guns.at(-1)!;
|
||||||
@@ -32,7 +36,7 @@ export async function assignDuelMember(
|
|||||||
shell,
|
shell,
|
||||||
track,
|
track,
|
||||||
equipment: genericDefaultEquipmentMatrix,
|
equipment: genericDefaultEquipmentMatrix,
|
||||||
pitch: 0,
|
pitch: degToRad(tankModelDefinition.turretRotation?.pitch ?? 0),
|
||||||
yaw: 0,
|
yaw: 0,
|
||||||
camouflage: true,
|
camouflage: true,
|
||||||
consumables: [],
|
consumables: [],
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
import { readFile } from 'fs/promises';
|
|
||||||
import satori from 'satori';
|
|
||||||
|
|
||||||
const FONT_NAME = 'Roboto';
|
|
||||||
const FONT_FILES = [
|
|
||||||
{ weight: 400 as const, path: 'src/assets/fonts/Roboto.ttf' },
|
|
||||||
{ weight: 700 as const, path: 'src/assets/fonts/Roboto-Bold.ttf' },
|
|
||||||
{ weight: 900 as const, path: 'src/assets/fonts/Roboto-Black.ttf' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const fonts = Promise.all(
|
|
||||||
FONT_FILES.map(({ path, weight }) =>
|
|
||||||
readFile(path).then((data) => ({
|
|
||||||
data: Buffer.from(data.buffer),
|
|
||||||
name: FONT_NAME,
|
|
||||||
weight,
|
|
||||||
})),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
export default async function jsxToSvg(jsx: JSX.Element) {
|
|
||||||
return await satori(jsx, {
|
|
||||||
width: 480,
|
|
||||||
fonts: await fonts,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,28 @@
|
|||||||
|
import { readFileSync } from 'fs';
|
||||||
|
import satori from 'satori';
|
||||||
|
|
||||||
|
const fonts = [
|
||||||
|
{
|
||||||
|
file: require('./Roboto.ttf') as string,
|
||||||
|
weight: 400 as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: require('./Roboto-Bold.ttf') as string,
|
||||||
|
weight: 700 as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: require('./Roboto-Black.ttf') as string,
|
||||||
|
weight: 900 as const,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default async function jsxToSvg(jsx: JSX.Element) {
|
||||||
|
return await satori(jsx, {
|
||||||
|
width: 480,
|
||||||
|
fonts: fonts.map(({ file, weight }) => ({
|
||||||
|
weight,
|
||||||
|
name: 'Roboto',
|
||||||
|
data: readFileSync(`${__dirname}/${file}`),
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ export function resolveDpm(
|
|||||||
shell: ShellDefinition,
|
shell: ShellDefinition,
|
||||||
damageCoefficient = 1,
|
damageCoefficient = 1,
|
||||||
reloadCoefficient = 1,
|
reloadCoefficient = 1,
|
||||||
interClipCoefficient = 1,
|
intraClipCoefficient = 1,
|
||||||
) {
|
) {
|
||||||
const alpha = shell.damage.armor * damageCoefficient;
|
const alpha = shell.damage.armor * damageCoefficient;
|
||||||
|
|
||||||
@@ -14,14 +14,14 @@ export function resolveDpm(
|
|||||||
} else if (gun.type === 'autoLoader') {
|
} else if (gun.type === 'autoLoader') {
|
||||||
return (
|
return (
|
||||||
((alpha * gun.count) /
|
((alpha * gun.count) /
|
||||||
(gun.reload + (gun.count - 1) * gun.interClip * interClipCoefficient)) *
|
(gun.reload + (gun.count - 1) * gun.intraClip * intraClipCoefficient)) *
|
||||||
60
|
60
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
((alpha * gun.count) /
|
((alpha * gun.count) /
|
||||||
(gun.reload.reduce((a, b) => a + b, 0) +
|
(gun.reload.reduce((a, b) => a + b, 0) +
|
||||||
(gun.count - 1) * gun.interClip)) *
|
(gun.count - 1) * gun.intraClip)) *
|
||||||
60
|
60
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ export function resolveReload(gun: GunDefinition) {
|
|||||||
if (gun.type === 'regular') {
|
if (gun.type === 'regular') {
|
||||||
return gun.reload;
|
return gun.reload;
|
||||||
} else if (gun.type === 'autoLoader') {
|
} else if (gun.type === 'autoLoader') {
|
||||||
return gun.reload + (gun.count - 1) * gun.interClip;
|
return gun.reload + (gun.count - 1) * gun.intraClip;
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
gun.reload.reduce((a, b) => a + b, 0) + (gun.count - 1) * gun.interClip
|
gun.reload.reduce((a, b) => a + b, 0) + (gun.count - 1) * gun.intraClip
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,13 +125,13 @@ interface GunDefinitionRegular extends GunDefinitionBase {
|
|||||||
interface GunDefinitionAutoLoader extends GunDefinitionBase {
|
interface GunDefinitionAutoLoader extends GunDefinitionBase {
|
||||||
type: 'autoLoader';
|
type: 'autoLoader';
|
||||||
reload: number;
|
reload: number;
|
||||||
interClip: number;
|
intraClip: number;
|
||||||
count: number;
|
count: number;
|
||||||
}
|
}
|
||||||
interface GunDefinitionAutoReloader extends GunDefinitionBase {
|
interface GunDefinitionAutoReloader extends GunDefinitionBase {
|
||||||
type: 'autoReloader';
|
type: 'autoReloader';
|
||||||
reload: number[];
|
reload: number[];
|
||||||
interClip: number;
|
intraClip: number;
|
||||||
count: number;
|
count: number;
|
||||||
}
|
}
|
||||||
export type ShellDefinition = {
|
export type ShellDefinition = {
|
||||||
|
|||||||
Reference in new issue
Block a user