feat: optimized shell switching

This commit is contained in:
TrèsAbhi committed 2024-01-22 18:14:09 -06:00
1 parent 0b5c2e42fb
commit b8f6394d94
2 files changed
+37 -12

No files matched your search

@@ -25,17 +25,18 @@ export function ArmorMesh({
}: ArmorMeshProps) { }: ArmorMeshProps) {
const initialEquipment = useTankopediaPersistent.getState().model.equipment; const initialEquipment = useTankopediaPersistent.getState().model.equipment;
const camera = useThree((state) => state.camera); const camera = useThree((state) => state.camera);
const shell = useDuel((state) => state.antagonist!.shell); const initialShell = useDuel.getState().antagonist!.shell;
const greenPenetration = useTankopediaPersistent( const greenPenetration = useTankopediaPersistent(
(state) => state.model.visual.greenPenetration, (state) => state.model.visual.greenPenetration,
); );
const material = useRef<ShaderMaterial>(null); const material = useRef<ShaderMaterial>(null);
const resolution = new Vector2(); const resolution = new Vector2();
const explosionCapable = isExplosive(shell.type); const explosionCapable = isExplosive(initialShell.type);
useEffect(() => { useEffect(() => {
function updateQuickEquipments() { function updateQuickEquipments() {
const equipment = useTankopediaPersistent.getState().model.equipment; const equipment = useTankopediaPersistent.getState().model.equipment;
const shell = useDuel.getState().antagonist!.shell;
const nearPenetration = resolveNearPenetration(shell.penetration); const nearPenetration = resolveNearPenetration(shell.penetration);
if (material.current) { if (material.current) {
@@ -47,11 +48,32 @@ export function ArmorMesh({
} }
} }
function updateShellProperties() {
const shell = useDuel.getState().antagonist!.shell;
if (material.current) {
material.current.uniforms.isExplosive.value = isExplosive(shell.type);
material.current.uniforms.canSplash.value = canSplash(shell.type);
material.current.uniforms.caliber.value = shell.caliber;
material.current.uniforms.ricochetAngle.value = degToRad(
shell.ricochet ?? 90,
);
material.current.uniforms.damage.value = shell.damage.armor;
material.current.uniforms.explosionRadius.value =
shell.explosionRadius ?? 0;
}
updateQuickEquipments();
}
const unsubscribes = [ const unsubscribes = [
useTankopediaPersistent.subscribe( useTankopediaPersistent.subscribe(
(state) => state.model.equipment, (state) => state.model.equipment,
updateQuickEquipments, updateQuickEquipments,
), ),
useDuel.subscribe(
(state) => state.antagonist!.shell,
updateShellProperties,
),
]; ];
return () => { return () => {
@@ -102,26 +124,26 @@ export function ArmorMesh({
greenPenetration: { value: greenPenetration }, greenPenetration: { value: greenPenetration },
maxThickness: { value: maxThickness }, maxThickness: { value: maxThickness },
isExplosive: { value: explosionCapable }, isExplosive: { value: explosionCapable },
canSplash: { value: canSplash(shell.type) }, canSplash: { value: canSplash(initialShell.type) },
thickness: { thickness: {
value: thickness * (initialEquipment.enhancedArmor ? 1.04 : 1), value: thickness * (initialEquipment.enhancedArmor ? 1.04 : 1),
}, },
penetration: { penetration: {
value: value:
resolveNearPenetration(shell.penetration) * resolveNearPenetration(initialShell.penetration) *
(initialEquipment.calibratedShells (initialEquipment.calibratedShells
? explosionCapable ? explosionCapable
? 1.1 ? 1.1
: 1.05 : 1.05
: 1), : 1),
}, },
caliber: { value: shell.caliber }, caliber: { value: initialShell.caliber },
ricochetAngle: { value: degToRad(shell.ricochet ?? 90) }, ricochetAngle: { value: degToRad(initialShell.ricochet ?? 90) },
normalization: { normalization: {
value: degToRad(shell.normalization ?? 0), value: degToRad(initialShell.normalization ?? 0),
}, },
damage: { value: shell.damage.armor }, damage: { value: initialShell.damage.armor },
explosionRadius: { value: shell.explosionRadius ?? 0 }, explosionRadius: { value: initialShell.explosionRadius ?? 0 },
}} }}
/> />
</mesh> </mesh>
+6 -3
View File
@@ -1,5 +1,6 @@
import { produce } from 'immer'; import { produce } from 'immer';
import { create } from 'zustand'; import { create } from 'zustand';
import { subscribeWithSelector } from 'zustand/middleware';
import { DuelMember } from './tankopedia'; import { DuelMember } from './tankopedia';
export interface Duel { export interface Duel {
@@ -8,9 +9,11 @@ export interface Duel {
antagonist?: DuelMember; antagonist?: DuelMember;
} }
export const useDuel = create<Duel>()(() => ({ export const useDuel = create<Duel>()(
assigned: false, subscribeWithSelector<Duel>(() => ({
})); assigned: false,
})),
);
export function mutateDuel(recipe: (draft: Duel) => void) { export function mutateDuel(recipe: (draft: Duel) => void) {
useDuel.setState(produce(recipe)); useDuel.setState(produce(recipe));