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',