Something went wrong. Try again.
Starship Simulator Controls thoriumsim.com
Something went wrong. Try again.
4.3 kB · 140 lines
TSX
at develop
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141import { 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 ( <div className="shields-container"> <div className="my-4 flex w-full gap-8"> <ShieldView /> </div> {shields[0].state === "down" ? ( <Button className="btn-primary btn-sm w-full" onClick={() => { q.targeting.shields.setState.netSend({ shipId, state: "up" }); }} > Raise Shields </Button> ) : ( <Button className="btn-warning btn-sm w-full" onClick={() => { q.targeting.shields.setState.netSend({ shipId, state: "down" }); }} > Lower Shields </Button> )} </div> );}
export function ShieldView() { const { cardLoaded } = useCardContext();
const { shipId, ship } = useStation(); const [shields] = q.targeting.shields.get.useNetRequest({ shipId });
const topViewRef = useRef<HTMLDivElement>(null); const sideViewRef = useRef<HTMLDivElement>(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 ( <> <div ref={topViewRef} className="aspect-square flex-1 rounded-full p-4" style={{ boxShadow: shieldStyle(shields) }} > <img src={ship.assets?.topView} alt="Top" /> </div> {shields.length === 6 ? ( <div ref={sideViewRef} className="aspect-square flex-1 rounded-full p-4" style={{ boxShadow: shieldStyle(shields, true) }} > <img src={ship.assets?.sideView} alt="Side" /> </div> ) : null} </> );}