mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 03:59:50 +02:00
feat: he based gaps
This commit is contained in:
1 parent
8f9306a3db
commit
d89575b25d
3 files changed
+68
-24
No files matched your search
@@ -186,22 +186,18 @@ export function ArmorMesh({
|
|||||||
|
|
||||||
if (mesh.current !== (coreArmorMesh as unknown as Mesh)) return;
|
if (mesh.current !== (coreArmorMesh as unknown as Mesh)) return;
|
||||||
|
|
||||||
let accumulatedThickness = 0;
|
const armorPiercingLayersRaw = intersectionsTillFirstCoreArmor.map(
|
||||||
const armorPiercingLayers = intersectionsTillFirstCoreArmor.map(
|
|
||||||
(event, index) => {
|
(event, index) => {
|
||||||
switch (event.object.userData.type) {
|
switch (event.object.userData.type) {
|
||||||
case 'externalModule': {
|
case 'externalModule': {
|
||||||
accumulatedThickness +=
|
|
||||||
event.object.userData.thickness * thicknessCoefficient;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
nominal:
|
nominal:
|
||||||
event.object.userData.thickness * thicknessCoefficient,
|
event.object.userData.thickness * thicknessCoefficient,
|
||||||
angled:
|
angled:
|
||||||
event.object.userData.thickness * thicknessCoefficient,
|
event.object.userData.thickness * thicknessCoefficient,
|
||||||
ricochet: false,
|
ricochet: false,
|
||||||
block: accumulatedThickness > resolvedPenetration,
|
|
||||||
type: 'external',
|
type: 'external',
|
||||||
|
distance: event.distance,
|
||||||
} satisfies ArmorPiercingLayer;
|
} satisfies ArmorPiercingLayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,28 +231,62 @@ export function ArmorMesh({
|
|||||||
const angled =
|
const angled =
|
||||||
(event.object.userData.thickness * thicknessCoefficient) /
|
(event.object.userData.thickness * thicknessCoefficient) /
|
||||||
Math.cos(angle - degToRad(normalization));
|
Math.cos(angle - degToRad(normalization));
|
||||||
accumulatedThickness += angled;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
nominal:
|
nominal:
|
||||||
event.object.userData.thickness * thicknessCoefficient,
|
event.object.userData.thickness * thicknessCoefficient,
|
||||||
angled,
|
angled,
|
||||||
ricochet,
|
ricochet,
|
||||||
block: accumulatedThickness > resolvedPenetration,
|
|
||||||
type:
|
type:
|
||||||
event.object.userData.type === 'coreArmor'
|
event.object.userData.type === 'coreArmor'
|
||||||
? 'core'
|
? 'core'
|
||||||
: 'spaced',
|
: 'spaced',
|
||||||
|
distance: event.distance,
|
||||||
} satisfies ArmorPiercingLayer;
|
} satisfies ArmorPiercingLayer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
const gaps = armorPiercingLayersRaw.map((layerA, aIndex) => {
|
||||||
|
if (aIndex === armorPiercingLayersRaw.length - 1) return null;
|
||||||
|
const layerB = armorPiercingLayersRaw[aIndex + 1];
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'gap',
|
||||||
|
gap: Math.abs(layerB.distance - layerA.distance),
|
||||||
|
} satisfies ArmorPiercingLayer;
|
||||||
|
});
|
||||||
|
const armorPiercingLayers: ArmorPiercingLayer[] = [];
|
||||||
|
|
||||||
|
armorPiercingLayersRaw.forEach((layer, index) => {
|
||||||
|
const gap = gaps[index];
|
||||||
|
|
||||||
|
armorPiercingLayers.push(layer);
|
||||||
|
if (gap) armorPiercingLayers.push(gap);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(armorPiercingLayers);
|
||||||
|
|
||||||
|
let remainingPenetration = resolvedPenetration;
|
||||||
|
let accumulatedThickness = 0;
|
||||||
|
const explosiveCapable = isExplosive(shell.type);
|
||||||
|
|
||||||
|
armorPiercingLayers.forEach((layer) => {
|
||||||
|
if (layer.type !== 'gap') {
|
||||||
|
remainingPenetration -= layer.angled;
|
||||||
|
accumulatedThickness += layer.angled;
|
||||||
|
} else if (explosiveCapable) {
|
||||||
|
// there is a 50% penetration loss per meter for HE based shells
|
||||||
|
remainingPenetration -= 0.5 * remainingPenetration * layer.gap;
|
||||||
|
}
|
||||||
|
|
||||||
|
remainingPenetration = Math.max(0, remainingPenetration);
|
||||||
|
});
|
||||||
|
|
||||||
const hasRicochet = armorPiercingLayers.some(
|
const hasRicochet = armorPiercingLayers.some(
|
||||||
({ ricochet }) => ricochet,
|
(layer) => layer.type !== 'gap' && layer.ricochet,
|
||||||
);
|
);
|
||||||
const hasPenetrated = resolvedPenetration >= accumulatedThickness;
|
const hasPenetrated = remainingPenetration >= accumulatedThickness;
|
||||||
|
|
||||||
mutateTankopediaTemporary((draft) => {
|
mutateTankopediaTemporary((draft) => {
|
||||||
draft.shot = {
|
draft.shot = {
|
||||||
|
|||||||
@@ -106,23 +106,32 @@ export function ShotDisplay() {
|
|||||||
paddingLeft: shot.thicknesses.length > 1 ? 8 : undefined,
|
paddingLeft: shot.thicknesses.length > 1 ? 8 : undefined,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{shot.thicknesses.map(({ nominal, angled, type }, index) => (
|
{shot.thicknesses.map((layer, index) => (
|
||||||
<Flex gap="2">
|
<Flex gap="2">
|
||||||
{shot.thicknesses.length > 1 && (
|
{shot.thicknesses.length > 1 && (
|
||||||
<Text>
|
<Text>
|
||||||
{index + 1}. {type[0].toUpperCase()}
|
{index + 1}. {layer.type[0].toUpperCase()}
|
||||||
{type.slice(1)}
|
{layer.type.slice(1)}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Flex gap="1">
|
<Flex gap="1">
|
||||||
<NominalPenetration width={24} height={24} />
|
{layer.type !== 'gap' && (
|
||||||
<Text>{nominal}mm</Text>
|
<NominalPenetration width={24} height={24} />
|
||||||
|
)}
|
||||||
|
<Text>
|
||||||
|
{Math.round(
|
||||||
|
layer.type === 'gap'
|
||||||
|
? layer.gap * 1000
|
||||||
|
: layer.nominal,
|
||||||
|
)}
|
||||||
|
mm
|
||||||
|
</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
{type !== 'external' && (
|
{layer.type !== 'external' && layer.type !== 'gap' && (
|
||||||
<Flex gap="1">
|
<Flex gap="1">
|
||||||
<AngledPenetration width={24} height={24} />
|
<AngledPenetration width={24} height={24} />
|
||||||
<Text>{Math.round(angled)}mm</Text>
|
<Text>{Math.round(layer.angled)}mm</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@@ -76,13 +76,18 @@ export type Shot = {
|
|||||||
angle: number;
|
angle: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface ArmorPiercingLayer {
|
export type ArmorPiercingLayer =
|
||||||
nominal: number;
|
| {
|
||||||
angled: number;
|
distance: number;
|
||||||
ricochet: boolean;
|
nominal: number;
|
||||||
block: boolean;
|
angled: number;
|
||||||
type: 'core' | 'spaced' | 'external';
|
ricochet: boolean;
|
||||||
}
|
type: 'core' | 'spaced' | 'external';
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'gap';
|
||||||
|
gap: number;
|
||||||
|
};
|
||||||
|
|
||||||
export const useTankopediaPersistent = create<TankopediaPersistent>()(
|
export const useTankopediaPersistent = create<TankopediaPersistent>()(
|
||||||
persist(
|
persist(
|
||||||
|
|||||||
Reference in new issue
Block a user