feat: more accurate HE

This commit is contained in:
TrèsAbhi committed 2024-02-29 12:42:15 -06:00
1 parent f5578ee788
commit 199e156e53
5 files changed
+61 -20

No files matched your search

@@ -53,8 +53,8 @@ void main() {
float spacedArmorThickness = spacedArmorBufferFragment.r * penetration;
remainingPenetration -= spacedArmorThickness;
if (isExplosive && remainingPenetration > 0.0) {
// there is a 50% penetration loss per meter for HE based shells
if (isExplosive && !canSplash && remainingPenetration > 0.0) {
// there is a 50% penetration loss per meter for HEAT shells
remainingPenetration -= 0.5 * remainingPenetration * distanceFromSpacedArmor;
}
}
@@ -68,7 +68,7 @@ void main() {
// only allow splashing if the damage equation deals more than 0 damage
float nominalArmorThickness = finalThickness - remainingPenetration;
float finalDamage = 0.5 * damage * (1.0 - distanceFromSpacedArmor / explosionRadius) - 1.1 * nominalArmorThickness;
splashChance = finalDamage > 0.0 ? 1.0 : 0.0;
splashChance = finalDamage > 0.0 ? 1.0 : 0.0; // TODO: add randomization here?
} else {
splashChance = 0.0;
}
+47 -11
View File
@@ -4,13 +4,17 @@ import { Euler, Quaternion, Vector3 } from 'three';
import { radToDeg } from 'three/src/math/MathUtils';
import { J_HAT } from '../../../constants/axis';
import { isExplosive } from '../../../core/blitz/isExplosive';
import { NaNFallback } from '../../../core/math/NaNFallback';
import { AngledPenetration } from '../../../icons/AngledPenetration';
import { Block } from '../../../icons/Block';
import { NominalPenetration } from '../../../icons/NominalPenetration';
import { Ricochet } from '../../../icons/Ricochet';
import { useDuel } from '../../../stores/duel';
import {
ShotLayer,
ShotLayerBase,
ShotLayerGap,
ShotLayerNonExternal,
useTankopediaTemporary,
} from '../../../stores/tankopedia';
import { ArmorType } from './SpacedArmorScene';
@@ -79,10 +83,10 @@ export function ShotDisplay() {
style={{
backgroundColor:
trueStatus === 'penetration'
? '#00ff0080'
? '#00ff00c0'
: trueStatus === 'blocked'
? '#ff000080'
: '#ffff0080',
? '#ff0000c0'
: '#ffff00c0',
border: 'none',
}}
>
@@ -93,9 +97,11 @@ export function ShotDisplay() {
width: '100%',
display: 'block',
textAlign: 'center',
color:
trueStatus === 'ricochet' ? 'black' : undefined,
}}
>
{layer.index + 1}
<b>{layer.index + 1}</b>
</Text>
)}
</Inset>
@@ -155,25 +161,54 @@ export function ShotDisplay() {
{shot &&
(() => {
const firstLayer = shot.layers[0] as Exclude<ShotLayer, ShotLayerGap>;
const lastLayer = shot.layers.at(-1)!;
const lastStatus = lastLayer.status;
const midPointLayer = (shot.layers.findLast(
(layer) => layer.type !== null && layer.status === 'ricochet',
) ??
shot.layers.findLast(
(layer) => layer.type !== null,
)) as ShotLayerBase;
const distanceFromSpacedArmor = firstLayer.point.distanceTo(
shot.point,
);
console.log(distanceFromSpacedArmor);
return (
<Html
position={shot.point}
position={midPointLayer.point}
style={{
transform: 'translateY(-50%)',
marginLeft: 16,
marginLeft: 32,
pointerEvents: 'none',
}}
>
<Card style={{ width: 256 + 32 }}>
<Flex direction="column">
<Text>
{lastStatus[0].toUpperCase()}
{lastStatus.slice(1)}
{lastStatus === 'penetration' &&
`: ${shell.damage.module}hp`}
{lastLayer.status[0].toUpperCase()}
{lastLayer.status.slice(1)}
{lastLayer.status === 'penetration' &&
`: ${Math.round(shell.damage.armor)}hp`}
{lastLayer.status === 'blocked' &&
shell.type === 'he' &&
`: ${NaNFallback(
Math.max(
0,
Math.round(
0.5 *
shell.damage.armor *
(1 -
distanceFromSpacedArmor /
shell.explosionRadius!) -
1.1 *
(midPointLayer as ShotLayerNonExternal)
.thicknessAngled,
),
),
0,
)}hp`}
</Text>
{shot.layers.map((layer) => {
@@ -223,6 +258,7 @@ export function ShotDisplay() {
{layer.type === null && (
<Text size="2">
{/* why is it x50? i can't pretend to understand this shit */}
{Math.round(layer.distance * 1000)}mm (-
{Math.round(Math.min(100, layer.distance * 50))}%
penetration)
@@ -9,6 +9,7 @@ import {
Vector3,
} from 'three';
import { degToRad } from 'three/src/math/MathUtils';
import { canSplash } from '../../../../core/blitz/canSplash';
import { isExplosive } from '../../../../core/blitz/isExplosive';
import { resolveNearPenetration } from '../../../../core/blitz/resolveNearPenetration';
import { hasEquipment } from '../../../../core/blitzkrieg/hasEquipment';
@@ -93,6 +94,7 @@ export function SpacedArmorSceneComponent({
const thicknessCoefficient = hasEnhancedArmor ? 1.04 : 1;
const shell = useDuel.getState().antagonist!.shell;
const explosive = isExplosive(shell.type);
const splashing = canSplash(shell.type);
const penetration =
resolveNearPenetration(shell.penetration) *
(hasCalibratedShells
@@ -171,17 +173,17 @@ export function SpacedArmorSceneComponent({
const distance = (
shot.layers.at(-1) as ShotLayerBase
).point.distanceTo(intersections[0].point);
if (explosive)
if (explosive && !splashing)
remainingPenetration -= 0.5 * remainingPenetration * distance;
const wasted = remainingPenetration < 0;
const blocked = remainingPenetration < 0;
shot.layers.push({
type: null,
status: wasted ? 'blocked' : 'penetration',
status: blocked ? 'blocked' : 'penetration',
distance,
});
if (wasted) return;
if (blocked) return;
}
for (const intersection of intersections) {
@@ -197,7 +199,7 @@ export function SpacedArmorSceneComponent({
const previousIntersection = intersections[layerIndex - 1];
const distance =
intersection.distance - previousIntersection.distance;
if (explosive)
if (explosive && !splashing)
remainingPenetration -=
0.5 * remainingPenetration * distance;
const wasted = remainingPenetration < 0;
+3
View File
@@ -0,0 +1,3 @@
export function NaNFallback(value: number, fallback: number) {
return isNaN(value) ? fallback : value;
}
+1 -1
View File
@@ -57,7 +57,7 @@ interface ShotLayerExternal extends ShotLayerBase {
type: ArmorType.External;
}
interface ShotLayerNonExternal extends ShotLayerBase {
export interface ShotLayerNonExternal extends ShotLayerBase {
type: Exclude<ArmorType, ArmorType.External>;
angle: number;
thicknessAngled: number;