mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
feat: equipments
This commit is contained in:
1 parent
cc622ef189
commit
31936d6e6c
2 files changed
+207
-49
No files matched your search
@@ -12,6 +12,7 @@ export interface InfoProps {
|
|||||||
delta?: number;
|
delta?: number;
|
||||||
decimals?: number;
|
decimals?: number;
|
||||||
prefix?: string;
|
prefix?: string;
|
||||||
|
deltaType?: 'higherIsBetter' | 'lowerIsBetter';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Info({
|
export function Info({
|
||||||
@@ -23,6 +24,7 @@ export function Info({
|
|||||||
delta,
|
delta,
|
||||||
decimals,
|
decimals,
|
||||||
prefix,
|
prefix,
|
||||||
|
deltaType = 'higherIsBetter',
|
||||||
}: InfoProps) {
|
}: InfoProps) {
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
@@ -58,12 +60,24 @@ export function Info({
|
|||||||
<Flex align="center" gap="1">
|
<Flex align="center" gap="1">
|
||||||
{delta !== undefined && delta !== 0 && (
|
{delta !== undefined && delta !== 0 && (
|
||||||
<>
|
<>
|
||||||
<Text color={delta > 0 ? 'green' : 'tomato'}>
|
<Text
|
||||||
|
color={
|
||||||
|
delta * (deltaType === 'lowerIsBetter' ? -1 : 1) > 0
|
||||||
|
? 'green'
|
||||||
|
: 'tomato'
|
||||||
|
}
|
||||||
|
>
|
||||||
{decimals !== undefined
|
{decimals !== undefined
|
||||||
? Math.abs(delta).toFixed(decimals)
|
? Math.abs(delta).toFixed(decimals)
|
||||||
: Math.abs(delta)}
|
: Math.abs(delta)}
|
||||||
</Text>
|
</Text>
|
||||||
<Text color={delta > 0 ? 'green' : 'tomato'}>
|
<Text
|
||||||
|
color={
|
||||||
|
delta * (deltaType === 'lowerIsBetter' ? -1 : 1) > 0
|
||||||
|
? 'green'
|
||||||
|
: 'tomato'
|
||||||
|
}
|
||||||
|
>
|
||||||
{delta > 0 ? <CaretUpIcon /> : <CaretDownIcon />}
|
{delta > 0 ? <CaretUpIcon /> : <CaretDownIcon />}
|
||||||
</Text>
|
</Text>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Flex, Heading } from '@radix-ui/themes';
|
import { Flex, Heading } from '@radix-ui/themes';
|
||||||
import { use } from 'react';
|
import { use } from 'react';
|
||||||
|
import { isExplosive } from '../../../../../../core/blitz/isExplosive';
|
||||||
import { resolveNearPenetration } from '../../../../../../core/blitz/resolveNearPenetration';
|
import { resolveNearPenetration } from '../../../../../../core/blitz/resolveNearPenetration';
|
||||||
import { modelDefinitions } from '../../../../../../core/blitzkrieg/modelDefinitions';
|
import { modelDefinitions } from '../../../../../../core/blitzkrieg/modelDefinitions';
|
||||||
import { normalizeBoundingBox } from '../../../../../../core/blitzkrieg/normalizeBoundingBox';
|
import { normalizeBoundingBox } from '../../../../../../core/blitzkrieg/normalizeBoundingBox';
|
||||||
@@ -43,34 +44,91 @@ export function Characteristics() {
|
|||||||
stockTurret.weight +
|
stockTurret.weight +
|
||||||
stockGun.weight;
|
stockGun.weight;
|
||||||
const hasRammer = useEquipment(100);
|
const hasRammer = useEquipment(100);
|
||||||
|
const hasCalibratedShells = useEquipment(103);
|
||||||
|
const hasEnhancedGunLayingDrive = useEquipment(104);
|
||||||
|
const hasSupercharger = useEquipment(107);
|
||||||
|
const hasVerticalStabilizer = useEquipment(105);
|
||||||
|
const hasRefinedGun = useEquipment(106);
|
||||||
|
const hasImprovedAssembly = useEquipment(111);
|
||||||
|
const hasImprovedOptics = useEquipment(114);
|
||||||
|
const hasImprovedControl = useEquipment(116);
|
||||||
|
const hasEngineAccelerator = useEquipment(117);
|
||||||
|
const hasCamouflageNet = useEquipment(115);
|
||||||
|
const hasImprovedVerticalStabilizer = useEquipment(122);
|
||||||
|
const hasImprovedSuspension = useEquipment(123);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO:
|
||||||
|
* - Improved Ventilation
|
||||||
|
*/
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex direction="column" gap="4" style={{ width: '100%' }}>
|
<Flex direction="column" gap="4" style={{ width: '100%' }}>
|
||||||
<Flex direction="column" gap="2">
|
<Flex direction="column" gap="2">
|
||||||
<Heading size="5">Survivability</Heading>
|
<Heading size="5">Survivability</Heading>
|
||||||
<InfoWithDelta name="Health" unit="hp">
|
<InfoWithDelta name="Health" unit="hp">
|
||||||
{tank.health + turret.health}
|
{(tank.health + turret.health) * (hasImprovedAssembly ? 1.06 : 1)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta name="Fire chance" unit="%">
|
<InfoWithDelta name="Fire chance" unit="%" deltaType="lowerIsBetter">
|
||||||
{Math.round(engine.fireChance * 100)}
|
{Math.round(engine.fireChance * 100)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta name="View range" unit="m">
|
<InfoWithDelta name="View range" unit="m">
|
||||||
{turret.viewRange}
|
{turret.viewRange *
|
||||||
|
(hasImprovedOptics
|
||||||
|
? tank.type === 'tankDestroyer'
|
||||||
|
? 1.05
|
||||||
|
: tank.type === 'heavy'
|
||||||
|
? 1.07
|
||||||
|
: 1.1
|
||||||
|
: 1)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<Info name="Camouflage" unit="%" />
|
<Info name="Camouflage" unit="%" />
|
||||||
<InfoWithDelta indent name="Still" decimals={2}>
|
<InfoWithDelta
|
||||||
{tank.camouflage.still * 100}
|
indent
|
||||||
|
name="Still"
|
||||||
|
decimals={2}
|
||||||
|
deltaType="lowerIsBetter"
|
||||||
|
>
|
||||||
|
{tank.camouflage.still *
|
||||||
|
100 *
|
||||||
|
(hasCamouflageNet
|
||||||
|
? tank.type === 'heavy'
|
||||||
|
? 1.03
|
||||||
|
: tank.type === 'tankDestroyer'
|
||||||
|
? 1.07
|
||||||
|
: 1.05
|
||||||
|
: 1)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta indent name="Moving" decimals={2}>
|
<InfoWithDelta
|
||||||
|
indent
|
||||||
|
name="Moving"
|
||||||
|
decimals={2}
|
||||||
|
deltaType="lowerIsBetter"
|
||||||
|
>
|
||||||
{tank.camouflage.moving * 100}
|
{tank.camouflage.moving * 100}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta indent name="Shooting still" decimals={2}>
|
<InfoWithDelta
|
||||||
|
indent
|
||||||
|
name="Shooting still"
|
||||||
|
decimals={2}
|
||||||
|
deltaType="lowerIsBetter"
|
||||||
|
>
|
||||||
{tank.camouflage.still * gun.camouflageLoss * 100}
|
{tank.camouflage.still * gun.camouflageLoss * 100}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta indent name="Shooting on move" decimals={2}>
|
<InfoWithDelta
|
||||||
|
indent
|
||||||
|
name="Shooting on move"
|
||||||
|
decimals={2}
|
||||||
|
deltaType="lowerIsBetter"
|
||||||
|
>
|
||||||
{tank.camouflage.moving * gun.camouflageLoss * 100}
|
{tank.camouflage.moving * gun.camouflageLoss * 100}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta indent name="On fire" decimals={2}>
|
<InfoWithDelta
|
||||||
|
indent
|
||||||
|
name="On fire"
|
||||||
|
decimals={2}
|
||||||
|
deltaType="lowerIsBetter"
|
||||||
|
>
|
||||||
{tank.camouflage.onFire * tank.camouflage.still * 100}
|
{tank.camouflage.onFire * tank.camouflage.still * 100}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<Info name="Size" unit="m">
|
<Info name="Size" unit="m">
|
||||||
@@ -124,19 +182,27 @@ export function Characteristics() {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{gun.type === 'autoReloader' ? (
|
{gun.type === 'autoReloader' ? (
|
||||||
gun.reload.map((reload, index) => (
|
<>
|
||||||
<InfoWithDelta
|
<Info name="Reload" unit="s" />
|
||||||
key={index}
|
{gun.reload.map((reload, index) => (
|
||||||
indent={index > 0}
|
<InfoWithDelta
|
||||||
name={index > 0 ? `Shell ${index + 1}` : 'Reload on shell 1'}
|
key={index}
|
||||||
unit="s"
|
indent
|
||||||
decimals={2}
|
name={`Shell ${index + 1}`}
|
||||||
>
|
decimals={2}
|
||||||
{reload}
|
deltaType="lowerIsBetter"
|
||||||
</InfoWithDelta>
|
>
|
||||||
))
|
{reload}
|
||||||
|
</InfoWithDelta>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<InfoWithDelta decimals={2} name="Reload" unit="s">
|
<InfoWithDelta
|
||||||
|
decimals={2}
|
||||||
|
name="Reload"
|
||||||
|
unit="s"
|
||||||
|
deltaType="lowerIsBetter"
|
||||||
|
>
|
||||||
{gun.reload * (hasRammer ? 0.93 : 1)}
|
{gun.reload * (hasRammer ? 0.93 : 1)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
)}
|
)}
|
||||||
@@ -145,14 +211,39 @@ export function Characteristics() {
|
|||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<Info name="Penetration" unit="mm" />
|
<Info name="Penetration" unit="mm" />
|
||||||
{gun.shells.map((shell) => (
|
{gun.shells.map((shell) => (
|
||||||
<InfoWithDelta
|
<>
|
||||||
decimals={0}
|
<InfoWithDelta
|
||||||
key={shell.type}
|
decimals={0}
|
||||||
indent
|
key={shell.type}
|
||||||
name={SHELL_NAMES[shell.type]}
|
indent
|
||||||
>
|
name={SHELL_NAMES[shell.type]}
|
||||||
{resolveNearPenetration(shell.penetration)}
|
>
|
||||||
</InfoWithDelta>
|
{resolveNearPenetration(shell.penetration) *
|
||||||
|
(hasCalibratedShells
|
||||||
|
? isExplosive(shell.type)
|
||||||
|
? 1.1
|
||||||
|
: 1.05
|
||||||
|
: 1)}
|
||||||
|
</InfoWithDelta>
|
||||||
|
{typeof shell.penetration !== 'number' && (
|
||||||
|
<InfoWithDelta
|
||||||
|
decimals={0}
|
||||||
|
key={shell.type}
|
||||||
|
indent
|
||||||
|
name={`${SHELL_NAMES[shell.type]} at 500m`}
|
||||||
|
>
|
||||||
|
{(hasSupercharger
|
||||||
|
? shell.penetration[1] +
|
||||||
|
0.5 * (shell.penetration[0] - shell.penetration[1])
|
||||||
|
: shell.penetration[1]) *
|
||||||
|
(hasCalibratedShells
|
||||||
|
? isExplosive(shell.type)
|
||||||
|
? 1.1
|
||||||
|
: 1.05
|
||||||
|
: 1)}
|
||||||
|
</InfoWithDelta>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
))}
|
))}
|
||||||
<Info name="Damage" unit="hp" />
|
<Info name="Damage" unit="hp" />
|
||||||
{gun.shells.map((shell) => (
|
{gun.shells.map((shell) => (
|
||||||
@@ -184,18 +275,36 @@ export function Characteristics() {
|
|||||||
indent
|
indent
|
||||||
name={SHELL_NAMES[shell.type]}
|
name={SHELL_NAMES[shell.type]}
|
||||||
>
|
>
|
||||||
{shell.speed}
|
{shell.speed * (hasSupercharger ? 1.3 : 1)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
))}
|
))}
|
||||||
<InfoWithDelta decimals={2} name="Aim time" unit="s">
|
<InfoWithDelta
|
||||||
{gun.aimTime}
|
decimals={2}
|
||||||
|
name="Aim time"
|
||||||
|
unit="s"
|
||||||
|
deltaType="lowerIsBetter"
|
||||||
|
>
|
||||||
|
{gun.aimTime * (hasEnhancedGunLayingDrive ? 0.9 : 1)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<Info name="Dispersion at 100m" />
|
<Info name="Dispersion at 100m" />
|
||||||
<InfoWithDelta decimals={3} indent name="Still" unit="m">
|
<InfoWithDelta
|
||||||
{gun.dispersion.base}
|
decimals={3}
|
||||||
|
indent
|
||||||
|
name="Still"
|
||||||
|
unit="m"
|
||||||
|
deltaType="lowerIsBetter"
|
||||||
|
>
|
||||||
|
{gun.dispersion.base * (hasRefinedGun ? 0.9 : 1)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta prefix="+ " decimals={3} indent name="Moving" unit="s">
|
<InfoWithDelta
|
||||||
{track.dispersion.move}
|
prefix="+ "
|
||||||
|
decimals={3}
|
||||||
|
indent
|
||||||
|
name="Moving"
|
||||||
|
unit="s"
|
||||||
|
deltaType="lowerIsBetter"
|
||||||
|
>
|
||||||
|
{track.dispersion.move * (hasVerticalStabilizer ? 0.85 : 1)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta
|
<InfoWithDelta
|
||||||
decimals={3}
|
decimals={3}
|
||||||
@@ -203,8 +312,9 @@ export function Characteristics() {
|
|||||||
indent
|
indent
|
||||||
name="Hull traversing"
|
name="Hull traversing"
|
||||||
unit="°"
|
unit="°"
|
||||||
|
deltaType="lowerIsBetter"
|
||||||
>
|
>
|
||||||
{track.dispersion.traverse}
|
{track.dispersion.traverse * (hasVerticalStabilizer ? 0.85 : 1)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta
|
<InfoWithDelta
|
||||||
decimals={0}
|
decimals={0}
|
||||||
@@ -212,8 +322,9 @@ export function Characteristics() {
|
|||||||
indent
|
indent
|
||||||
name="Turret traversing"
|
name="Turret traversing"
|
||||||
unit="°"
|
unit="°"
|
||||||
|
deltaType="lowerIsBetter"
|
||||||
>
|
>
|
||||||
{gun.dispersion.traverse}
|
{gun.dispersion.traverse * (hasVerticalStabilizer ? 0.85 : 1)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta
|
<InfoWithDelta
|
||||||
decimals={3}
|
decimals={3}
|
||||||
@@ -221,6 +332,7 @@ export function Characteristics() {
|
|||||||
indent
|
indent
|
||||||
name="After shooting"
|
name="After shooting"
|
||||||
unit="m"
|
unit="m"
|
||||||
|
deltaType="lowerIsBetter"
|
||||||
>
|
>
|
||||||
{gun.dispersion.shot}
|
{gun.dispersion.shot}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
@@ -230,15 +342,18 @@ export function Characteristics() {
|
|||||||
indent
|
indent
|
||||||
name="Gun damaged"
|
name="Gun damaged"
|
||||||
unit="scalar"
|
unit="scalar"
|
||||||
|
deltaType="lowerIsBetter"
|
||||||
>
|
>
|
||||||
{gun.dispersion.damaged}
|
{gun.dispersion.damaged}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<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 +
|
||||||
|
(hasImprovedVerticalStabilizer ? 3 : 0)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta decimals={1} indent name="Elevation">
|
<InfoWithDelta decimals={1} indent name="Elevation">
|
||||||
{-gunModelDefinition.pitch.min}
|
{-gunModelDefinition.pitch.min +
|
||||||
|
(hasImprovedVerticalStabilizer ? 3 : 0)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
{gunModelDefinition.pitch.front && (
|
{gunModelDefinition.pitch.front && (
|
||||||
<>
|
<>
|
||||||
@@ -286,15 +401,41 @@ export function Characteristics() {
|
|||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<Info name="Power to weight ratio" unit="hp/mt" />
|
<Info name="Power to weight ratio" unit="hp/mt" />
|
||||||
<InfoWithDelta decimals={1} indent name="On hard terrain">
|
<InfoWithDelta decimals={1} indent name="On hard terrain">
|
||||||
{engine.power / weightMt / track.resistance.hard}
|
{(engine.power /
|
||||||
|
weightMt /
|
||||||
|
(track.resistance.hard * (hasImprovedSuspension ? 0.75 : 1))) *
|
||||||
|
(hasEngineAccelerator
|
||||||
|
? tank.type === 'light' || tank.type === 'medium'
|
||||||
|
? 1.05
|
||||||
|
: 1.07
|
||||||
|
: 1)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta decimals={1} indent name="On medium terrain">
|
<InfoWithDelta decimals={1} indent name="On medium terrain">
|
||||||
{engine.power / weightMt / track.resistance.medium}
|
{(engine.power /
|
||||||
|
weightMt /
|
||||||
|
(track.resistance.medium * (hasImprovedSuspension ? 0.75 : 1))) *
|
||||||
|
(hasEngineAccelerator
|
||||||
|
? tank.type === 'light' || tank.type === 'medium'
|
||||||
|
? 1.05
|
||||||
|
: 1.07
|
||||||
|
: 1)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta decimals={1} indent name="On soft terrain">
|
<InfoWithDelta decimals={1} indent name="On soft terrain">
|
||||||
{engine.power / weightMt / track.resistance.soft}
|
{(engine.power /
|
||||||
|
weightMt /
|
||||||
|
(track.resistance.soft * (hasImprovedSuspension ? 0.75 : 1))) *
|
||||||
|
(hasEngineAccelerator
|
||||||
|
? tank.type === 'light' || tank.type === 'medium'
|
||||||
|
? 1.05
|
||||||
|
: 1.07
|
||||||
|
: 1)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta decimals={1} name="Weight" unit="mt">
|
<InfoWithDelta
|
||||||
|
decimals={1}
|
||||||
|
name="Weight"
|
||||||
|
unit="mt"
|
||||||
|
deltaType="lowerIsBetter"
|
||||||
|
>
|
||||||
{weightMt}
|
{weightMt}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<Info name="Effective traverse speed" unit="°/s" />
|
<Info name="Effective traverse speed" unit="°/s" />
|
||||||
@@ -302,19 +443,22 @@ export function Characteristics() {
|
|||||||
{(engine.power / stockEngine.power) *
|
{(engine.power / stockEngine.power) *
|
||||||
track.traverseSpeed *
|
track.traverseSpeed *
|
||||||
(track.resistance.hard / track.resistance.hard) *
|
(track.resistance.hard / track.resistance.hard) *
|
||||||
(stockWeight / weight)}
|
(stockWeight / weight) *
|
||||||
|
(hasImprovedControl ? 1.1 : 1)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta decimals={1} indent name="On medium terrain">
|
<InfoWithDelta decimals={1} indent name="On medium terrain">
|
||||||
{(engine.power / stockEngine.power) *
|
{(engine.power / stockEngine.power) *
|
||||||
track.traverseSpeed *
|
track.traverseSpeed *
|
||||||
(track.resistance.hard / track.resistance.medium) *
|
(track.resistance.hard / track.resistance.medium) *
|
||||||
(stockWeight / weight)}
|
(stockWeight / weight) *
|
||||||
|
(hasImprovedControl ? 1.1 : 1)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
<InfoWithDelta decimals={1} indent name="On soft terrain">
|
<InfoWithDelta decimals={1} indent name="On soft terrain">
|
||||||
{(engine.power / stockEngine.power) *
|
{(engine.power / stockEngine.power) *
|
||||||
track.traverseSpeed *
|
track.traverseSpeed *
|
||||||
(track.resistance.hard / track.resistance.soft) *
|
(track.resistance.hard / track.resistance.soft) *
|
||||||
(stockWeight / weight)}
|
(stockWeight / weight) *
|
||||||
|
(hasImprovedControl ? 1.1 : 1)}
|
||||||
</InfoWithDelta>
|
</InfoWithDelta>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
Reference in new issue
Block a user