mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
somewhat through PrimaryArmorSceneComponent
This commit is contained in:
1 parent
488451d71f
commit
e18d6f58f9
13 files changed
+110
-66
No files matched your search
+11
-10
@@ -17,9 +17,9 @@ import {
|
|||||||
Vector2,
|
Vector2,
|
||||||
} from "three";
|
} from "three";
|
||||||
import { degToRad } from "three/src/math/MathUtils.js";
|
import { degToRad } from "three/src/math/MathUtils.js";
|
||||||
import { hasEquipment } from "../../../../core/blitzkit/hasEquipment";
|
|
||||||
import { jsxTree } from "../../../../core/blitzkit/jsxTree";
|
import { jsxTree } from "../../../../core/blitzkit/jsxTree";
|
||||||
import { Duel } from "../../../../stores/duel";
|
import { DuelModule, getDuel } from "../../../../hooks/useDuel";
|
||||||
|
import { hasEquipment } from "../../../../hooks/useEquipment";
|
||||||
import { Tankopedia } from "../../../../stores/tankopedia";
|
import { Tankopedia } from "../../../../stores/tankopedia";
|
||||||
import { TankopediaPersistent } from "../../../../stores/tankopediaPersistent";
|
import { TankopediaPersistent } from "../../../../stores/tankopediaPersistent";
|
||||||
import { transitionEvent } from "../../../Lighting";
|
import { transitionEvent } from "../../../Lighting";
|
||||||
@@ -82,9 +82,8 @@ export function PrimaryArmorSceneComponent({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function handleShellChange() {
|
function handleShellChange() {
|
||||||
const tankopediaEphemeral = Tankopedia.state;
|
|
||||||
const shell =
|
const shell =
|
||||||
tankopediaEphemeral.customShell ?? Duel.state.antagonist.shell;
|
Tankopedia.state.customShell ?? getDuel("antagonist", DuelModule.Shell);
|
||||||
|
|
||||||
material.uniforms.caliber.value = shell.caliber;
|
material.uniforms.caliber.value = shell.caliber;
|
||||||
material.uniforms.ricochet.value = degToRad(
|
material.uniforms.ricochet.value = degToRad(
|
||||||
@@ -117,15 +116,16 @@ export function PrimaryArmorSceneComponent({
|
|||||||
material.wireframe = wireframe;
|
material.wireframe = wireframe;
|
||||||
}
|
}
|
||||||
function handleProtagonistEquipmentChange(noInvalidate = false) {
|
function handleProtagonistEquipmentChange(noInvalidate = false) {
|
||||||
const equipment = Duel.state.protagonist.equipmentMatrix;
|
const equipment = Tankopedia.state.protagonist.equipment;
|
||||||
|
const protagonist = getDuel("protagonist", DuelModule.Tank);
|
||||||
const hasEnhancedArmor = hasEquipment(
|
const hasEnhancedArmor = hasEquipment(
|
||||||
110,
|
110,
|
||||||
Duel.state.protagonist.tank.equipment_preset,
|
protagonist.equipment_preset,
|
||||||
equipment,
|
equipment,
|
||||||
);
|
);
|
||||||
const equalizer =
|
const equalizer =
|
||||||
(Duel.state.equalize
|
(Tankopedia.state.equalize
|
||||||
? Duel.state.protagonist.tank.equalizer?.armor
|
? protagonist.equalizer?.armor
|
||||||
: undefined) ?? 1;
|
: undefined) ?? 1;
|
||||||
|
|
||||||
material.uniforms.thickness.value =
|
material.uniforms.thickness.value =
|
||||||
@@ -134,10 +134,11 @@ export function PrimaryArmorSceneComponent({
|
|||||||
if (!noInvalidate) invalidate();
|
if (!noInvalidate) invalidate();
|
||||||
}
|
}
|
||||||
function handleAntagonistEquipmentChange(noInvalidate = false) {
|
function handleAntagonistEquipmentChange(noInvalidate = false) {
|
||||||
const equipment = Duel.state.antagonist.equipmentMatrix;
|
const equipment = Tankopedia.state.antagonist.equipment;
|
||||||
const tankopediaEphemeral = Tankopedia.state;
|
const tankopediaEphemeral = Tankopedia.state;
|
||||||
const shell =
|
const shell =
|
||||||
tankopediaEphemeral.customShell ?? Duel.state.antagonist.shell;
|
tankopediaEphemeral.customShell ??
|
||||||
|
getDuel("antagonist", DuelModule.Shell);
|
||||||
const penetration = shell.penetration!.near;
|
const penetration = shell.penetration!.near;
|
||||||
const hasCalibratedShells = hasEquipment(
|
const hasCalibratedShells = hasEquipment(
|
||||||
103,
|
103,
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ export function StaticArmorSceneComponent({
|
|||||||
...props
|
...props
|
||||||
}: StaticArmorSceneComponentProps) {
|
}: StaticArmorSceneComponentProps) {
|
||||||
const camera = useThree((state) => state.camera);
|
const camera = useThree((state) => state.camera);
|
||||||
const hasEnhancedArmor = useEquipment(110);
|
const hasEnhancedArmor = useEquipment("protagonist", 110);
|
||||||
const tank = Duel.use((state) => state.protagonist.tank);
|
const tank = Duel.use((state) => state.protagonist.tank);
|
||||||
const equalize = Duel.use((state) => state.equalize);
|
const equalize = Duel.use((state) => state.equalize);
|
||||||
const equalizer = (equalize ? tank.equalizer : undefined) ?? defaultEqualizer;
|
const equalizer = (equalize ? tank.equalizer : undefined) ?? defaultEqualizer;
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@ export function Crew({ stats }: StatsAcceptorProps) {
|
|||||||
const tank = Duel.use((state) => state.protagonist.tank);
|
const tank = Duel.use((state) => state.protagonist.tank);
|
||||||
const { strings } = useLocale();
|
const { strings } = useLocale();
|
||||||
const provisions = Duel.use((state) => state.protagonist.provisions);
|
const provisions = Duel.use((state) => state.protagonist.provisions);
|
||||||
const hasImprovedVentilation = useEquipment(102);
|
const hasImprovedVentilation = useEquipment("protagonist", 102);
|
||||||
const provisionCrewBonus =
|
const provisionCrewBonus =
|
||||||
provisions.reduce(
|
provisions.reduce(
|
||||||
(total, provision) =>
|
(total, provision) =>
|
||||||
|
|||||||
+2
-2
@@ -71,8 +71,8 @@ export function Characteristics({ skeleton }: MaybeSkeletonComponentProps) {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const hasImprovedVerticalStabilizer = useEquipment(122);
|
const hasImprovedVerticalStabilizer = useEquipment("protagonist", 122);
|
||||||
const hasDownImprovedVerticalStabilizer = useEquipment(124);
|
const hasDownImprovedVerticalStabilizer = useEquipment("protagonist", 124);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const [pitch, yaw] = applyPitchYawLimits(
|
const [pitch, yaw] = applyPitchYawLimits(
|
||||||
|
|||||||
+2
-2
@@ -32,8 +32,8 @@ export function Consumables() {
|
|||||||
const cooldownBooster = Duel.use(
|
const cooldownBooster = Duel.use(
|
||||||
(state) => state.protagonist.cooldownBooster,
|
(state) => state.protagonist.cooldownBooster,
|
||||||
);
|
);
|
||||||
const hasConsumableDeliverySystem = useEquipment(118);
|
const hasConsumableDeliverySystem = useEquipment("protagonist", 118);
|
||||||
const hasHighEndConsumables = useEquipment(101);
|
const hasHighEndConsumables = useEquipment("protagonist", 101);
|
||||||
const { strings } = useLocale();
|
const { strings } = useLocale();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
+2
-2
@@ -23,8 +23,8 @@ export function QuickInputs() {
|
|||||||
const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id];
|
const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id];
|
||||||
const initialTurretPitch =
|
const initialTurretPitch =
|
||||||
tankModelDefinition.initial_turret_rotation?.pitch ?? 0;
|
tankModelDefinition.initial_turret_rotation?.pitch ?? 0;
|
||||||
const hasImprovedVerticalStabilizer = useEquipment(122);
|
const hasImprovedVerticalStabilizer = useEquipment("protagonist", 122);
|
||||||
const hasDownImprovedVerticalStabilizer = useEquipment(124);
|
const hasDownImprovedVerticalStabilizer = useEquipment("protagonist", 124);
|
||||||
|
|
||||||
function displayPitch(pitch: number) {
|
function displayPitch(pitch: number) {
|
||||||
return radToDeg(pitch) - initialTurretPitch;
|
return radToDeg(pitch) - initialTurretPitch;
|
||||||
|
|||||||
@@ -68,9 +68,9 @@ export function Options({ thicknessRange, canvas, skeleton }: OptionsProps) {
|
|||||||
const antagonistShell = Duel.use((state) => state.antagonist.shell);
|
const antagonistShell = Duel.use((state) => state.antagonist.shell);
|
||||||
const [antagonistSelectorOpen, setAntagonistSelectorOpen] = useState(false);
|
const [antagonistSelectorOpen, setAntagonistSelectorOpen] = useState(false);
|
||||||
const antagonistTank = Duel.use((state) => state.antagonist.tank);
|
const antagonistTank = Duel.use((state) => state.antagonist.tank);
|
||||||
const hasCalibratedShells = useEquipment(103, true);
|
const hasCalibratedShells = useEquipment("protagonist", 103, true);
|
||||||
const [tab, setTab] = useState("search");
|
const [tab, setTab] = useState("search");
|
||||||
const hasEnhancedArmor = useEquipment(110);
|
const hasEnhancedArmor = useEquipment("protagonist", 110);
|
||||||
const antagonistUniqueGuns = uniqueGuns(antagonistTank.turrets);
|
const antagonistUniqueGuns = uniqueGuns(antagonistTank.turrets);
|
||||||
const { strings, unwrap } = useLocale();
|
const { strings, unwrap } = useLocale();
|
||||||
const revealed = Tankopedia.use((state) => state.revealed);
|
const revealed = Tankopedia.use((state) => state.revealed);
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import {
|
|||||||
import { applyPitchYawLimits } from "../../core/blitz/applyPitchYawLimits";
|
import { applyPitchYawLimits } from "../../core/blitz/applyPitchYawLimits";
|
||||||
import { modelTransformEvent } from "../../core/blitzkit/modelTransform";
|
import { modelTransformEvent } from "../../core/blitzkit/modelTransform";
|
||||||
import { Pose, poseEvent } from "../../core/blitzkit/pose";
|
import { Pose, poseEvent } from "../../core/blitzkit/pose";
|
||||||
|
import { DuelModule, useDuel } from "../../hooks/useDuel";
|
||||||
import { useEquipment } from "../../hooks/useEquipment";
|
import { useEquipment } from "../../hooks/useEquipment";
|
||||||
import { useModel } from "../../hooks/useModel";
|
import { useModel } from "../../hooks/useModel";
|
||||||
import { useProtagonistTurret } from "../../hooks/useProtagonistTurret";
|
|
||||||
import { Tankopedia } from "../../stores/tankopedia";
|
import { Tankopedia } from "../../stores/tankopedia";
|
||||||
import { TankopediaPersistent } from "../../stores/tankopediaPersistent";
|
import { TankopediaPersistent } from "../../stores/tankopediaPersistent";
|
||||||
import { TankopediaDisplay } from "../../stores/tankopediaPersistent/constants";
|
import { TankopediaDisplay } from "../../stores/tankopediaPersistent/constants";
|
||||||
@@ -39,12 +39,12 @@ export const TankopediaSandbox = forwardRef<
|
|||||||
TankSandboxProps
|
TankSandboxProps
|
||||||
>(({ thicknessRange }, ref) => {
|
>(({ thicknessRange }, ref) => {
|
||||||
const canvas = useRef<HTMLCanvasElement>(null);
|
const canvas = useRef<HTMLCanvasElement>(null);
|
||||||
const hasImprovedVerticalStabilizer = useEquipment(122);
|
const hasImprovedVerticalStabilizer = useEquipment("protagonist", 122);
|
||||||
const hasDownImprovedVerticalStabilizer = useEquipment(124);
|
const hasDownImprovedVerticalStabilizer = useEquipment("protagonist", 124);
|
||||||
|
|
||||||
const tank = useDuel("protagonist", DuelModule.Tank);
|
const tank = useDuel("protagonist", DuelModule.Tank);
|
||||||
const gun = useDuel("protagonist", DuelModule.Gun);
|
const gun = useDuel("protagonist", DuelModule.Gun);
|
||||||
const turret = useProtagonistTurret();
|
const turret = useDuel("protagonist", DuelModule.Turret);
|
||||||
|
|
||||||
const model = Tankopedia.use((state) => state.protagonist.model);
|
const model = Tankopedia.use((state) => state.protagonist.model);
|
||||||
const turretModelDefinition = model.turrets[turret.id];
|
const turretModelDefinition = model.turrets[turret.id];
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
import { api } from "../../api/dynamic";
|
|
||||||
import type { EquipmentMatrix } from "../../stores/duel";
|
|
||||||
|
|
||||||
const equipmentDefinitions = await api.equipment();
|
|
||||||
|
|
||||||
export function hasEquipment(
|
|
||||||
id: number,
|
|
||||||
equipmentPreset: string,
|
|
||||||
equipmentMatrix: EquipmentMatrix,
|
|
||||||
) {
|
|
||||||
const preset = equipmentDefinitions.presets[equipmentPreset];
|
|
||||||
return preset.slots.some((slot, index) => {
|
|
||||||
const row = Math.floor(index / 3);
|
|
||||||
const column = index % 3;
|
|
||||||
const choice = equipmentMatrix[row][column];
|
|
||||||
|
|
||||||
if (choice === 0) return false;
|
|
||||||
|
|
||||||
const equipped = slot[choice === -1 ? "left" : "right"];
|
|
||||||
|
|
||||||
return equipped === id;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -72,3 +72,55 @@ export function useDuel(side: DuelSide, module: DuelModule) {
|
|||||||
const shellId = Tankopedia.use((state) => state[side].shell);
|
const shellId = Tankopedia.use((state) => state[side].shell);
|
||||||
return gun.shells.find((shell) => shell.id === shellId)!;
|
return gun.shells.find((shell) => shell.id === shellId)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getDuel(
|
||||||
|
side: DuelSide,
|
||||||
|
module: DuelModule.Tank,
|
||||||
|
): TankDefinition;
|
||||||
|
export function getDuel(
|
||||||
|
side: DuelSide,
|
||||||
|
module: DuelModule.Track,
|
||||||
|
): TrackDefinition;
|
||||||
|
export function getDuel(
|
||||||
|
side: DuelSide,
|
||||||
|
module: DuelModule.Engine,
|
||||||
|
): EngineDefinition;
|
||||||
|
export function getDuel(
|
||||||
|
side: DuelSide,
|
||||||
|
module: DuelModule.Turret,
|
||||||
|
): TurretDefinition;
|
||||||
|
export function getDuel(side: DuelSide, module: DuelModule.Gun): GunDefinition;
|
||||||
|
export function getDuel(
|
||||||
|
side: DuelSide,
|
||||||
|
module: DuelModule.Shell,
|
||||||
|
): ShellDefinition;
|
||||||
|
|
||||||
|
export function getDuel(side: DuelSide, module: DuelModule) {
|
||||||
|
const tank = tanks.tanks[Tankopedia.state[side].tank];
|
||||||
|
|
||||||
|
if (module === DuelModule.Tank) return tank;
|
||||||
|
|
||||||
|
if (module === DuelModule.Track) {
|
||||||
|
return tank.tracks.find(
|
||||||
|
(track) => track.id === Tankopedia.state[side].track,
|
||||||
|
)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (module === DuelModule.Engine) {
|
||||||
|
return tank.engines.find(
|
||||||
|
(engine) => engine.id === Tankopedia.state[side].engine,
|
||||||
|
)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
const turret = tank.turrets.find(
|
||||||
|
(turret) => turret.id === Tankopedia.state[side].turret,
|
||||||
|
)!;
|
||||||
|
|
||||||
|
if (module === DuelModule.Turret) return turret;
|
||||||
|
|
||||||
|
const gun = turret.guns.find((gun) => gun.id === Tankopedia.state[side].gun)!;
|
||||||
|
|
||||||
|
if (module === DuelModule.Gun) return gun;
|
||||||
|
|
||||||
|
return gun.shells.find((shell) => shell.id === Tankopedia.state[side].shell)!;
|
||||||
|
}
|
||||||
@@ -9,25 +9,30 @@ export type DuelSide = "protagonist" | "antagonist";
|
|||||||
|
|
||||||
export function useEquipment(side: DuelSide, id: number) {
|
export function useEquipment(side: DuelSide, id: number) {
|
||||||
const member = Tankopedia.use((state) => state[side]);
|
const member = Tankopedia.use((state) => state[side]);
|
||||||
|
const appliedEquipment = Tankopedia.use((state) => state[side].equipment);
|
||||||
|
|
||||||
const tank = tanks.tanks[member.tank];
|
const tank = tanks.tanks[member.tank];
|
||||||
const preset = equipment.presets[tank.equipment_preset];
|
|
||||||
const equipmentMatrix = Tankopedia.use(
|
const value = useMemo(
|
||||||
(state) => state[side].equipment_matrix,
|
() => hasEquipment(id, tank.equipment_preset, appliedEquipment),
|
||||||
|
[appliedEquipment, member.tank],
|
||||||
);
|
);
|
||||||
|
|
||||||
const value = useMemo(() => {
|
|
||||||
return preset.slots.some((slot, index) => {
|
|
||||||
const row = Math.floor(index / 3);
|
|
||||||
const column = index % 3;
|
|
||||||
const choice = equipmentMatrix[row][column];
|
|
||||||
|
|
||||||
if (choice === 0) return false;
|
|
||||||
|
|
||||||
const equipped = slot[choice === -1 ? "left" : "right"];
|
|
||||||
|
|
||||||
return equipped === id;
|
|
||||||
});
|
|
||||||
}, [equipmentMatrix, member.tank]);
|
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function hasEquipment(
|
||||||
|
id: number,
|
||||||
|
_preset: string,
|
||||||
|
applied: Record<number, number>,
|
||||||
|
) {
|
||||||
|
const preset = equipment.presets[_preset];
|
||||||
|
|
||||||
|
return preset.slots.some((slot, index) => {
|
||||||
|
if (!(index in applied)) return false;
|
||||||
|
|
||||||
|
const choice = applied[index];
|
||||||
|
|
||||||
|
return slot.options[choice] === id;
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@ export const Page = withErrorWrapper(
|
|||||||
Tankopedia.useInitialization(protagonistTank);
|
Tankopedia.useInitialization(protagonistTank);
|
||||||
|
|
||||||
const protagonist = Tankopedia.use((state) => state.protagonist);
|
const protagonist = Tankopedia.use((state) => state.protagonist);
|
||||||
// const protagonistEquipment = useEquipment(protagonistTank.tank!);
|
// const protagonistEquipment = useEquipment("protagonist", protagonistTank.tank!);
|
||||||
|
|
||||||
const characteristics = useMemo(
|
const characteristics = useMemo(
|
||||||
() => computeCharacteristics(),
|
() => computeCharacteristics(),
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { createDefaultSkills } from "@blitzkit/core";
|
import { createDefaultSkills } from "@blitzkit/core";
|
||||||
import type { ShellDefinition, TankDefinition } from "@blitzkit/protos";
|
import type {
|
||||||
|
ModelDefinition,
|
||||||
|
ShellDefinition,
|
||||||
|
TankDefinition,
|
||||||
|
} from "@blitzkit/protos";
|
||||||
import type { Vector3 } from "three";
|
import type { Vector3 } from "three";
|
||||||
import { Varuna } from "varuna";
|
import { Varuna } from "varuna";
|
||||||
import { api } from "../api/dynamic";
|
import { api } from "../api/dynamic";
|
||||||
@@ -81,6 +85,9 @@ interface Tankopedia {
|
|||||||
|
|
||||||
protagonist: TankState;
|
protagonist: TankState;
|
||||||
antagonist: TankState;
|
antagonist: TankState;
|
||||||
|
model: ModelDefinition;
|
||||||
|
|
||||||
|
equalize: boolean;
|
||||||
|
|
||||||
shot?: Shot;
|
shot?: Shot;
|
||||||
skills: Record<string, number>;
|
skills: Record<string, number>;
|
||||||
@@ -118,6 +125,8 @@ export const Tankopedia = new Varuna<Tankopedia, TankDefinition>((tank) => ({
|
|||||||
antagonist: createTankState(tank),
|
antagonist: createTankState(tank),
|
||||||
model: models.models[tank.id],
|
model: models.models[tank.id],
|
||||||
|
|
||||||
|
equalize: false,
|
||||||
|
|
||||||
relativeAgainst: TankopediaRelativeAgainst.Class,
|
relativeAgainst: TankopediaRelativeAgainst.Class,
|
||||||
editStatic: false,
|
editStatic: false,
|
||||||
skills: createDefaultSkills(skills),
|
skills: createDefaultSkills(skills),
|
||||||
|
|||||||
Reference in new issue
Block a user