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