Something went wrong. Try again.
Starship Simulator Controls thoriumsim.com
Something went wrong. Try again.
7.4 kB · 286 lines
TSX
at develop
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287import { ObjectImage } from "@thorium/cards/Navigation/ObjectDetails";import { q } from "@thorium/context/AppContext";import { useStation } from "@thorium/routes/station/useStation";import { planetScanTypes, scanTypes, shipScanTypes, starScanTypes,} from "@thorium/utils/flags/scanTypes";import { capitalCase } from "change-case";import type { ReactNode } from "react";import { Button } from "react-aria-components";import type { z } from "zod";
export const ScanComponents = { shields: ShieldsResults, cargo: CargoResults, lifeSupport: null, targeting: TargetingResults, identification: IdentificationResults, crew: CrewResults, weapons: WeaponsResults, engines: null, damage: DamageResults, communications: CommunicationsResults, life: LifeResults, atmosphere: AtmosphereResults, temperature: TemperatureResults,};export function ScanResults({ objectId, type }: { objectId: number; type: string }) { const scans = type === "ship" ? shipScanTypes : type === "planet" ? planetScanTypes : type === "star" ? starScanTypes : scanTypes.options; return ( <div className="flex flex-col gap-1"> {["planet", "star"].includes(type) ? <IdentificationResults objectId={objectId} /> : null} {scans.map((value) => { const ScanComponent = ScanComponents[value]; if (!ScanComponent) return; return ( <ResultsWrapper key={value} scanType={value} objectId={objectId}> <ScanComponent objectId={objectId} /> </ResultsWrapper> ); })} </div> );}function ResultsWrapper({ scanType, children, objectId,}: { scanType: z.infer<typeof scanTypes>; objectId: number; children: ReactNode;}) { const { shipId } = useStation();
const [scans] = q.sensors.scans.useNetRequest({ shipId }); const isScanning = scans.some( (scan) => scan.target === objectId && scan.type === scanType && scan.progress < 1, ); return ( <div> <strong className="flex items-center justify-between font-bold"> <span>{capitalCase(scanType)}</span> {isScanning ? ( <Button className="btn btn-xs btn-info" isDisabled> In Progress... </Button> ) : ( <Button className="btn btn-xs btn-warning" data-testid={`begin-${scanType}`} onPress={() => q.sensors.scanStart.netSend({ shipId, type: scanType, target: objectId, }) } > Begin Scan </Button> )} </strong> <div className="ml-4">{children}</div> </div> );}function IdentificationResults({ objectId }: { objectId: number }) { const { shipId } = useStation();
const [results] = q.sensors.scanResult.useNetRequest({ shipId, objectId });
if (!results.identification) return null;
return ( <div className="flex gap-2"> <div className="aspect-square"> {results.identification.image ? ( <ObjectImage objectImage={results.identification.image} /> ) : null} </div> <div> <div>{results.identification.name}</div> <div>{results.identification.classification}</div> <div>Faction: {results.identification.factionName}</div> </div> </div> );}function CargoResults({ objectId }: { objectId: number }) { const { shipId } = useStation();
const [results] = q.sensors.scanResult.useNetRequest({ shipId, objectId });
if (!results.cargo) return null; const cargoEntries = Object.entries(results.cargo.cargo); return ( <div> {cargoEntries.length === 0 ? "No cargo detected." : cargoEntries.map(([name, amount]) => ( <div key={name}> {name}: {amount} </div> ))} </div> );}function TargetingResults({ objectId }: { objectId: number }) { const { shipId } = useStation();
const [results] = q.sensors.scanResult.useNetRequest({ shipId, objectId });
if (!results.targeting) return null;
return ( <div> <div>Target: {results.targeting.targetName}</div> <div>Targeted System: {results.targeting.targetedSystem}</div> </div> );}function CrewResults({ objectId }: { objectId: number }) { const { shipId } = useStation();
const [results] = q.sensors.scanResult.useNetRequest({ shipId, objectId });
if (!results.crew) return null;
return ( <div> <div>Population: {results.crew.count}</div> </div> );}function WeaponsResults({ objectId }: { objectId: number }) { const { shipId } = useStation();
const [results] = q.sensors.scanResult.useNetRequest({ shipId, objectId });
if (!results.weapons) return null;
return ( <div> {results.weapons.weapons.map((weapon, index) => ( <div key={index} className="flex justify-between"> <span>{capitalCase(weapon.type)}</span> <span> {weapon.type === "phasers" ? `${Math.round(weapon.charge * 100)}%` : `${weapon.loaded}`} </span> </div> ))} </div> );}function DamageResults({ objectId }: { objectId: number }) { const { shipId } = useStation();
const [results] = q.sensors.scanResult.useNetRequest({ shipId, objectId });
if (!results.damage) return null; const damageEntries = Object.entries(results.damage.damage);
return ( <div> {damageEntries.length === 0 ? "No damage detected" : damageEntries.map(([system, efficiency]) => ( <div key={system}> {system}: {Math.round((1 - efficiency) * 100)}% Damaged </div> ))} </div> );}function ShieldsResults({ objectId }: { objectId: number }) { const { shipId } = useStation();
const [results] = q.sensors.scanResult.useNetRequest({ shipId, objectId });
if (!results.shields) return null;
return ( <div> <div>Status: {results.shields.status === "up" ? "Raised" : "Lowered"}</div> <div> Strength:{" "} {typeof results.shields.strength === "number" ? `${Math.round(results.shields.strength * 100)}%` : "0%"} </div> </div> );}function CommunicationsResults({ objectId }: { objectId: number }) { const { shipId } = useStation();
const [results] = q.sensors.scanResult.useNetRequest({ shipId, objectId });
if (!results.communications) return null;
return ( <div className="tabular-nums"> {results.communications.status} — {results.communications.frequency} </div> );}function LifeResults({ objectId }: { objectId: number }) { const { shipId } = useStation();
const [results] = q.sensors.scanResult.useNetRequest({ shipId, objectId });
if (!results.life) return null;
return ( <div> <div>Habitable: {results.life.isHabitable ? "Yes" : "No"}</div> <div>Population: {results.life.population}</div> <div>Lifeforms:</div> <ul className="ml-6 list-disc"> {results.life.lifeforms.map((l) => ( <li key={l}>{l}</li> ))} </ul> </div> );}function AtmosphereResults({ objectId }: { objectId: number }) { const { shipId } = useStation();
const [results] = q.sensors.scanResult.useNetRequest({ shipId, objectId });
if (!results.atmosphere) return null;
return ( <ul className="ml-6 list-disc"> {results.atmosphere.atmosphere.map((a) => ( <li key={a.component}> {a.component}: {a.concentration}% </li> ))} </ul> );}function TemperatureResults({ objectId }: { objectId: number }) { const { shipId } = useStation();
const [results] = q.sensors.scanResult.useNetRequest({ shipId, objectId });
if (!results.temperature) return null;
return ( <div> <div>Temperature: {results.temperature.temperature.toLocaleString()} K</div> </div> );}