import { q } from "@thorium/context/AppContext"; import { useCardContext } from "@thorium/context/CardContext"; import useAnimationFrame from "@thorium/hooks/useAnimationFrame"; import { useStation } from "@thorium/routes/station/useStation"; import Button from "@thorium/ui/Button"; import { useLiveQuery } from "@thorium/utils/live-query/client"; import chroma from "chroma-js"; import { useRef } from "react"; const shieldColors = [ "oklch(10.86% 0.045 29.25)", // Black "oklch(66.33% 0.2823 29.25)", // Red "oklch(76.18% 0.207 56.11)", // Orange "oklch(86.52% 0.204 90.38)", // Yellow "oklch(86.18% 0.343 142.58)", // Green "oklch(57.65% 0.249 256.24)", // Blue ]; const shieldColor = (integrity: number) => { return chroma.scale(shieldColors).mode("oklch")(integrity).css("oklch"); }; const shieldStyle = ( shields: { strength: number; maxStrength: number; direction: "fore" | "aft" | "starboard" | "port" | "dorsal" | "ventral"; }[], extra = false, ) => { // Creates the styles for multiple shields const output: string[] = []; shields.forEach((s) => { const integrity = s.strength / s.maxStrength; const color = shieldColor(integrity); if ((s.direction === "starboard" && !extra) || (s.direction === "fore" && extra)) { output.push(`20px 0px 20px -15px ${color}`); output.push(`inset -20px 0px 20px -15px ${color}`); } if ((s.direction === "port" && !extra) || (s.direction === "aft" && extra)) { output.push(`-20px 0px 20px -15px ${color}`); output.push(`inset 20px 0px 20px -15px ${color}`); } if (s.direction === "fore" && !extra) { output.push(`0px -20px 20px -15px ${color}`); output.push(`inset 0px 20px 20px -15px ${color}`); } if (s.direction === "aft" && !extra) { output.push(`0px 20px 20px -15px ${color}`); output.push(`inset 0px -20px 20px -15px ${color}`); } if (s.direction === "ventral" && extra) { output.push(`0px 20px 20px -15px ${color}`); output.push(`inset 0px -20px 20px -15px ${color}`); } if (s.direction === "dorsal" && extra) { output.push(`0px -20px 20px -15px ${color}`); output.push(`inset 0px 20px 20px -15px ${color}`); } }); return output.join(","); }; export function Shields() { const { shipId, ship } = useStation(); const [shields] = q.targeting.shields.get.useNetRequest({ shipId }); if (!ship) return null; if (shields.length === 0) return null; return (
{shields[0].state === "down" ? ( ) : ( )}
); } export function ShieldView() { const { cardLoaded } = useCardContext(); const { shipId, ship } = useStation(); const [shields] = q.targeting.shields.get.useNetRequest({ shipId }); const topViewRef = useRef(null); const sideViewRef = useRef(null); const { interpolate } = useLiveQuery(); useAnimationFrame(() => { const shieldItems: { strength: number; maxStrength: number; direction: "fore" | "aft" | "starboard" | "port" | "dorsal" | "ventral"; }[] = []; for (const shield of shields) { const strength = interpolate(shield.id)?.x || 0; shieldItems.push({ ...shield, strength }); } topViewRef.current?.style.setProperty("box-shadow", shieldStyle(shieldItems)); sideViewRef.current?.style.setProperty("box-shadow", shieldStyle(shieldItems, true)); }, cardLoaded); return ( <>
Top
{shields.length === 6 ? (
Side
) : null} ); }