diff --git a/src/components/Armor/components/CoreArmor/index.tsx b/src/components/Armor/components/CoreArmor/index.tsx index 8ddb62118..5c81454eb 100644 --- a/src/components/Armor/components/CoreArmor/index.tsx +++ b/src/components/Armor/components/CoreArmor/index.tsx @@ -11,9 +11,10 @@ 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'; import { jsxTree } from '../../../../core/blitzkrieg/jsxTree'; import { ShellDefinition } from '../../../../core/blitzkrieg/tankDefinitions'; -import { useDuel } from '../../../../stores/duel'; +import { EquipmentMatrix, useDuel } from '../../../../stores/duel'; import { TankopediaPersistent, useTankopediaPersistent, @@ -40,7 +41,7 @@ export function CoreArmor({ node, thickness }: CoreArmorProps) { transparent: true, uniforms: { - thickness: { value: thickness }, + thickness: { value: null }, penetration: { value: null }, caliber: { value: null }, ricochet: { value: null }, @@ -82,9 +83,16 @@ export function CoreArmor({ node, thickness }: CoreArmorProps) { material.uniforms.opaque.value = visual.opaque || visual.wireframe; material.wireframe = visual.wireframe; } + async function handleEquipmentChange(equipment: EquipmentMatrix) { + const hasEnhancedArmor = await hasEquipment(110, false, equipment); + material.uniforms.thickness.value = hasEnhancedArmor + ? thickness * 1.04 + : thickness; + } handleShellChange(useDuel.getState().antagonist!.shell); handleVisualChange(useTankopediaPersistent.getState().model.visual); + handleEquipmentChange(useDuel.getState().protagonist!.equipment); const unsubscribes = [ useDuel.subscribe((state) => state.antagonist!.shell, handleShellChange), @@ -92,6 +100,10 @@ export function CoreArmor({ node, thickness }: CoreArmorProps) { (state) => state.model.visual, handleVisualChange, ), + useDuel.subscribe( + (state) => state.protagonist!.equipment, + handleEquipmentChange, + ), ]; return () => { diff --git a/src/components/Armor/components/SpacedArmor/components/SpacedArmorSubExternal/index.tsx b/src/components/Armor/components/SpacedArmor/components/SpacedArmorSubExternal/index.tsx index ddff80d45..8641cc63f 100644 --- a/src/components/Armor/components/SpacedArmor/components/SpacedArmorSubExternal/index.tsx +++ b/src/components/Armor/components/SpacedArmor/components/SpacedArmorSubExternal/index.tsx @@ -6,9 +6,10 @@ import { ShaderMaterial, } from 'three'; import { resolveNearPenetration } from '../../../../../../core/blitz/resolveNearPenetration'; +import { hasEquipment } from '../../../../../../core/blitzkrieg/hasEquipment'; import { jsxTree } from '../../../../../../core/blitzkrieg/jsxTree'; import { ShellDefinition } from '../../../../../../core/blitzkrieg/tankDefinitions'; -import { useDuel } from '../../../../../../stores/duel'; +import { EquipmentMatrix, useDuel } from '../../../../../../stores/duel'; import fragmentShader from './shaders/fragment.glsl'; import vertexShader from './shaders/vertex.glsl'; @@ -30,20 +31,38 @@ export function SpacedArmorSubExternal({ blending: AdditiveBlending, uniforms: { - thickness: { value: thickness }, + thickness: { value: null }, penetration: { value: null }, }, }); useEffect(() => { - function handleChange(shell: ShellDefinition) { + function handleShellChange(shell: ShellDefinition) { material.uniforms.penetration.value = resolveNearPenetration( shell.penetration, ); } + async function handleEquipmentChange(equipment: EquipmentMatrix) { + const hasEnhancedArmor = await hasEquipment(110, false, equipment); + material.uniforms.thickness.value = hasEnhancedArmor + ? thickness * 1.04 + : thickness; + } - handleChange(useDuel.getState().antagonist!.shell); - return useDuel.subscribe((state) => state.antagonist!.shell, handleChange); + handleShellChange(useDuel.getState().antagonist!.shell); + handleEquipmentChange(useDuel.getState().protagonist!.equipment); + + const unsubscribes = [ + useDuel.subscribe((state) => state.antagonist!.shell, handleShellChange), + useDuel.subscribe( + (state) => state.protagonist!.equipment, + handleEquipmentChange, + ), + ]; + + return () => { + unsubscribes.forEach((unsubscribe) => unsubscribe()); + }; }, []); return ( diff --git a/src/components/Armor/components/SpacedArmor/components/SpacedArmorSubSpaced/index.tsx b/src/components/Armor/components/SpacedArmor/components/SpacedArmorSubSpaced/index.tsx index dd0906145..ac264e31d 100644 --- a/src/components/Armor/components/SpacedArmor/components/SpacedArmorSubSpaced/index.tsx +++ b/src/components/Armor/components/SpacedArmor/components/SpacedArmorSubSpaced/index.tsx @@ -7,9 +7,10 @@ import { } from 'three'; import { degToRad } from 'three/src/math/MathUtils'; import { resolveNearPenetration } from '../../../../../../core/blitz/resolveNearPenetration'; +import { hasEquipment } from '../../../../../../core/blitzkrieg/hasEquipment'; import { jsxTree } from '../../../../../../core/blitzkrieg/jsxTree'; import { ShellDefinition } from '../../../../../../core/blitzkrieg/tankDefinitions'; -import { useDuel } from '../../../../../../stores/duel'; +import { EquipmentMatrix, useDuel } from '../../../../../../stores/duel'; import fragmentShader from './shaders/fragment.glsl'; import vertexShader from './shaders/vertex.glsl'; @@ -36,7 +37,7 @@ export function SpacedArmorSubSpaced({ blending: AdditiveBlending, uniforms: { - thickness: { value: thickness }, + thickness: { value: null }, penetration: { value: null }, caliber: { value: null }, ricochet: { value: null }, @@ -45,7 +46,7 @@ export function SpacedArmorSubSpaced({ }); useEffect(() => { - function handleChange(shell: ShellDefinition) { + function handleShellChange(shell: ShellDefinition) { material.uniforms.penetration.value = resolveNearPenetration( shell.penetration, ); @@ -55,9 +56,27 @@ export function SpacedArmorSubSpaced({ shell.normalization ?? 0, ); } + async function handleEquipmentChange(equipment: EquipmentMatrix) { + const hasEnhancedArmor = await hasEquipment(110, false, equipment); + material.uniforms.thickness.value = hasEnhancedArmor + ? thickness * 1.04 + : thickness; + } - handleChange(useDuel.getState().antagonist!.shell); - return useDuel.subscribe((state) => state.antagonist!.shell, handleChange); + handleShellChange(useDuel.getState().antagonist!.shell); + handleEquipmentChange(useDuel.getState().protagonist!.equipment); + + const unsubscribes = [ + useDuel.subscribe((state) => state.antagonist!.shell, handleShellChange), + useDuel.subscribe( + (state) => state.protagonist!.equipment, + handleEquipmentChange, + ), + ]; + + return () => { + unsubscribes.forEach((unsubscribe) => unsubscribe()); + }; }, []); return ( diff --git a/src/core/blitzkrieg/hasEquipment.ts b/src/core/blitzkrieg/hasEquipment.ts index 396153b31..d0ddf713f 100644 --- a/src/core/blitzkrieg/hasEquipment.ts +++ b/src/core/blitzkrieg/hasEquipment.ts @@ -1,15 +1,17 @@ import { useDuel } from '../../stores/duel'; import { equipmentDefinitions } from './equipmentDefinitions'; -export async function hasEquipment(id: number, antagonist = false) { +export async function hasEquipment( + id: number, + antagonist = false, + equipmentMatrix = useDuel.getState()[ + antagonist ? 'antagonist' : 'protagonist' + ]!.equipment, +) { const awaitedEquipmentDefinitions = await equipmentDefinitions; const member = useDuel.getState()[antagonist ? 'antagonist' : 'protagonist']!; - const equipmentRows = - awaitedEquipmentDefinitions.presets[member.tank.equipment]; - const equipmentMatrix = - useDuel.getState()[antagonist ? 'antagonist' : 'protagonist']!.equipment; - - return equipmentRows.some((equipmentRow, rowIndex) => { + const presetRows = awaitedEquipmentDefinitions.presets[member.tank.equipment]; + return presetRows.some((equipmentRow, rowIndex) => { return equipmentRow.some((equipment, columnIndex) => { const choice = equipmentMatrix[rowIndex][columnIndex]; if (choice === 0) return false;