From 9ed2b79a4b72999ab0854a6420f122f87bb1da88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Thu, 11 Jan 2024 12:04:01 -0600 Subject: [PATCH] feat: ricochet incapable shells --- .../components/Model/components/TankArmor.tsx | 44 ++++++++++++++++--- src/components/ArmorMesh/index.tsx | 20 ++++++--- .../ArmorMesh/shaders/fragment.glsl | 3 +- src/core/blitz/canRicochet.ts | 7 +++ src/core/blitzkrieg/tankDefinitions.ts | 19 ++++---- 5 files changed, 71 insertions(+), 22 deletions(-) create mode 100644 src/core/blitz/canRicochet.ts diff --git a/src/app/tools/tankopedia/[id]/components/Model/components/TankArmor.tsx b/src/app/tools/tankopedia/[id]/components/Model/components/TankArmor.tsx index 36aa52f34..141487eb1 100644 --- a/src/app/tools/tankopedia/[id]/components/Model/components/TankArmor.tsx +++ b/src/app/tools/tankopedia/[id]/components/Model/components/TankArmor.tsx @@ -5,12 +5,14 @@ import { GLTFLoader } from 'three-stdlib'; import { ArmorMesh } from '../../../../../../../components/ArmorMesh'; import { HeadsUpDisplay } from '../../../../../../../components/HeadsUpDisplay'; import { X_AXIS } from '../../../../../../../constants/axis'; +import { canRicochet } from '../../../../../../../core/blitz/canRicochet'; import { numericPenetration } from '../../../../../../../core/blitz/numericPenetration'; import { asset } from '../../../../../../../core/blitzkrieg/asset'; import { ModelDefinitions, modelDefinitions, } from '../../../../../../../core/blitzkrieg/modelDefinitions'; +import { RicochetCapableShell } from '../../../../../../../core/blitzkrieg/tankDefinitions'; import { useTankopedia } from '../../../../../../../stores/tankopedia'; import { Lighting } from '../../Lighting'; @@ -66,6 +68,7 @@ export function TankArmor({ ...props }: TankArmorProps) { .sub(turretOrigin) .applyAxisAngle(new Vector3(0, 0, 1), model.turretYaw); const turretRotation = new Euler(0, 0, model.turretYaw); + const ricochetCapable = canRicochet(antagonist.shell.type); if (tankModelDefinition.turretRotation) { const pitch = -tankModelDefinition.turretRotation.pitch * (Math.PI / 180); @@ -105,6 +108,7 @@ export function TankArmor({ ...props }: TankArmorProps) { (isSpaced && !showSpacedArmor) ) return null; + return ( ); })} @@ -138,6 +151,7 @@ export function TankArmor({ ...props }: TankArmorProps) { (isSpaced && !showSpacedArmor) ) return null; + return ( ); })} @@ -186,9 +209,18 @@ export function TankArmor({ ...props }: TankArmorProps) { geometry={(node as Mesh).geometry} thickness={thickness} penetration={numericPenetration(antagonist.shell.penetration)} - ricochet={antagonist.shell.ricochet} caliber={antagonist.shell.caliber} - normalization={antagonist.shell.normalization} + canRicochet={ricochetCapable} + ricochet={ + ricochetCapable + ? (antagonist.shell as RicochetCapableShell).ricochet + : undefined + } + normalization={ + ricochetCapable + ? (antagonist.shell as RicochetCapableShell).normalization + : undefined + } /> ); })} diff --git a/src/components/ArmorMesh/index.tsx b/src/components/ArmorMesh/index.tsx index 421f1a4e1..0664cc4d5 100644 --- a/src/components/ArmorMesh/index.tsx +++ b/src/components/ArmorMesh/index.tsx @@ -9,10 +9,11 @@ import vertex from './shaders/vertex.glsl'; interface ArmorMeshProps extends MeshProps { thickness: number; penetration: number; - ricochet: number; caliber: number; - normalization: number; spaced?: boolean; + canRicochet: boolean; + ricochet?: number; + normalization?: number; } // shader split: https://github.com/FarazzShaikh/THREE-CustomShaderMaterial/issues/48 @@ -21,6 +22,7 @@ export function ArmorMesh({ thickness, penetration, caliber, + canRicochet, ricochet, normalization, spaced = false, @@ -45,10 +47,18 @@ export function ArmorMesh({ uniforms={{ thickness: { value: thickness }, penetration: { value: penetration }, - ricochet: { value: ricochet * (Math.PI / 180) }, + ricochet: { + value: ricochet === undefined ? 0 : ricochet * (Math.PI / 180), + }, + normalization: { + value: + normalization === undefined + ? 0 + : normalization * (Math.PI / 180), + }, caliber: { value: caliber }, - normalization: { value: normalization * (Math.PI / 180) }, - spaced: { value: spaced }, + spaced: { value: spaced ?? false }, + canRicochet: { value: canRicochet }, }} vertexShader={vertex} fragmentShader={opaqueArmor && !spaced ? fragmentOpaque : fragment} diff --git a/src/components/ArmorMesh/shaders/fragment.glsl b/src/components/ArmorMesh/shaders/fragment.glsl index 3d08e8cc1..54599ffa8 100644 --- a/src/components/ArmorMesh/shaders/fragment.glsl +++ b/src/components/ArmorMesh/shaders/fragment.glsl @@ -7,6 +7,7 @@ uniform float ricochet; uniform float caliber; uniform float normalization; uniform bool spaced; +uniform bool canRichochet; void main() { vec3 normalizedNormal = normalize(vNormal); @@ -17,7 +18,7 @@ void main() { float penetrationChance = -1.0; bool threeCaliberRule = caliber > 3.0 * thickness; - if (!threeCaliberRule && angle >= ricochet) { + if (canRichochet && !threeCaliberRule && angle >= ricochet) { // auto ricochet angle and three caliber rule not met penetrationChance = 0.0; } else { diff --git a/src/core/blitz/canRicochet.ts b/src/core/blitz/canRicochet.ts new file mode 100644 index 000000000..26baf57b5 --- /dev/null +++ b/src/core/blitz/canRicochet.ts @@ -0,0 +1,7 @@ +import { ShellDefinition } from '../blitzkrieg/tankDefinitions'; + +export function canRicochet( + type: ShellDefinition['type'], +): type is 'ap' | 'ap_cr' { + return type === 'ap' || type === 'ap_cr'; +} diff --git a/src/core/blitzkrieg/tankDefinitions.ts b/src/core/blitzkrieg/tankDefinitions.ts index ebfedcf1b..7c7cb816e 100644 --- a/src/core/blitzkrieg/tankDefinitions.ts +++ b/src/core/blitzkrieg/tankDefinitions.ts @@ -58,6 +58,14 @@ interface GunDefinitionAutoReloader { interClip: number; count: number; } +export interface RicochetCapableShell { + type: 'ap' | 'ap_cr'; + normalization: number; + ricochet: number; +} +export interface RicochetIncapableShell { + type: 'hc' | 'he'; +} export type ShellDefinition = { id: number; name: string; @@ -66,16 +74,7 @@ export type ShellDefinition = { caliber: number; icon: string; penetration: number | Vector2Tuple; -} & ( - | { - type: Omit; - normalization: number; - ricochet: number; - } - | { - type: Omit; - } -); +} & (RicochetCapableShell | RicochetIncapableShell); export const tankDefinitions = fetch(asset('definitions/tanks.json'), { cache: 'no-cache',