Add Acceleration Segment + Improved Thrust calculation
This commit is contained in:
parent
90085dd87a
commit
986cf8453e
9 changed files with 288 additions and 138 deletions
50
src/lib/cards/Inventories.svelte
Normal file
50
src/lib/cards/Inventories.svelte
Normal file
|
@ -0,0 +1,50 @@
|
|||
<svelte:options runes />
|
||||
|
||||
<script>
|
||||
import {applyUnits, Localization} from "$lib/constants";
|
||||
import {Separator} from "$lib/components/ui/separator";
|
||||
import NewInventory from "$lib/components/NewInventory.svelte";
|
||||
import InventoryList from "$lib/components/InventoryList.svelte";
|
||||
import {Label} from "$lib/components/ui/label";
|
||||
import {Input} from "$lib/components/ui/input";
|
||||
import * as Card from "$lib/components/ui/card";
|
||||
|
||||
let { i18n = new Localization("en-GB"), ship, inventoryMultiplier, onAddInventory, onRemoveInventory } = $props();
|
||||
|
||||
let valid = $derived.by(() => {
|
||||
let valids = [];
|
||||
valids[0] = typeof ship !== "undefined";
|
||||
valids[1] = typeof inventoryMultiplier !== "undefined";
|
||||
valids[2] = typeof onAddInventory !== "undefined";
|
||||
valids[3] = typeof onRemoveInventory !== "undefined";
|
||||
return !valids.includes(false);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
{#if valid}
|
||||
<Card.Root class="flex-1 flex flex-col flex-grow">
|
||||
<Card.Header>
|
||||
<Card.Title>{i18n.localize("inventorySettings")}</Card.Title>
|
||||
</Card.Header>
|
||||
<Card.Content class="flex flex-col flex-grow gap-3">
|
||||
<Separator />
|
||||
<Label for="inventorySize">{i18n.localize("inventory")} {i18n.localize("multiplier")}</Label>
|
||||
<Input id="inventorySize" type="number" bind:value={inventoryMultiplier}/>
|
||||
<Card.Root>
|
||||
<Card.Content class="pt-6 flex flex-col gap-3">
|
||||
<NewInventory i18n={i18n} grid={ship.grid} {onAddInventory} />
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
<Card.Root class="flex flex-col h-60 flex-grow">
|
||||
<Card.Header>
|
||||
<Card.Title>{i18n.localize("inventories")} ({applyUnits(i18n, ship.getTotalVolume(inventoryMultiplier), "l")})</Card.Title>
|
||||
</Card.Header>
|
||||
<Card.Content class="flex flex-col gap-3 overflow-hidden">
|
||||
<Separator />
|
||||
<InventoryList i18n={i18n} inventories={ship.inventories} {onRemoveInventory} grid={ship.grid} multiplier={inventoryMultiplier} />
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
{/if}
|
50
src/lib/cards/Thrusters.svelte
Normal file
50
src/lib/cards/Thrusters.svelte
Normal file
|
@ -0,0 +1,50 @@
|
|||
<svelte:options runes />
|
||||
|
||||
<script>
|
||||
import {applyUnits, Localization} from "$lib/constants";
|
||||
import {Separator} from "$lib/components/ui/separator";
|
||||
import NewInventory from "$lib/components/NewInventory.svelte";
|
||||
import InventoryList from "$lib/components/InventoryList.svelte";
|
||||
import {Label} from "$lib/components/ui/label";
|
||||
import {Input} from "$lib/components/ui/input";
|
||||
import * as Card from "$lib/components/ui/card";
|
||||
import NewThruster from "$lib/components/NewThruster.svelte";
|
||||
import ThrusterList from "$lib/components/ThrusterList.svelte";
|
||||
|
||||
let { i18n = new Localization("en-GB"), ship, atmosphericDensity, onAddThruster, onRemoveThruster } = $props();
|
||||
|
||||
let valid = $derived.by(() => {
|
||||
let valids = [];
|
||||
valids[0] = typeof ship !== "undefined";
|
||||
valids[1] = typeof atmosphericDensity !== "undefined";
|
||||
valids[2] = typeof onAddThruster !== "undefined";
|
||||
valids[3] = typeof onRemoveThruster !== "undefined";
|
||||
return !valids.includes(false);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
{#if valid}
|
||||
<Card.Root class="flex-1 flex flex-col flex-grow">
|
||||
<Card.Header>
|
||||
<Card.Title>{i18n.localize("thrusterSettings")}</Card.Title>
|
||||
</Card.Header>
|
||||
<Card.Content class="flex flex-col flex-grow gap-3">
|
||||
<Separator />
|
||||
<Card.Root>
|
||||
<Card.Content class="flex flex-col gap-3 pt-6">
|
||||
<NewThruster i18n={i18n} {onAddThruster} />
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
<Card.Root class="flex flex-col h-60 flex-grow">
|
||||
<Card.Header>
|
||||
<Card.Title>{i18n.localize("thrusters")} ({applyUnits(i18n, ship.getTotalThrust(atmosphericDensity), "N")})</Card.Title>
|
||||
</Card.Header>
|
||||
<Card.Content class="flex flex-col gap-3 overflow-hidden">
|
||||
<Separator />
|
||||
<ThrusterList i18n={i18n} thrusters={ship.thrusters} {onRemoveThruster} grid={ship.grid} atmosphere={atmosphericDensity}/>
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
{/if}
|
35
src/lib/components/AccelerationOutputSegment.svelte
Normal file
35
src/lib/components/AccelerationOutputSegment.svelte
Normal file
|
@ -0,0 +1,35 @@
|
|||
<svelte:options runes />
|
||||
|
||||
<script lang="ts">
|
||||
import {applyUnits, Localization, weightConversion} from "$lib/constants";
|
||||
|
||||
let { i18n = new Localization("en-GB"), ship, atmosphere, inventoryMultiplier, material } = $props();
|
||||
|
||||
let valid = $derived.by(() => {
|
||||
let valids = [];
|
||||
valids[0] = typeof ship !== "undefined";
|
||||
valids[1] = typeof atmosphere !== "undefined";
|
||||
valids[2] = typeof inventoryMultiplier !== "undefined";
|
||||
valids[3] = typeof material !== "undefined";
|
||||
return !valids.includes(false);
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if valid}
|
||||
<div class="flex gap-2">
|
||||
<p>{i18n.localize("acceleration")} ({i18n.localize("full")}):</p>
|
||||
{#if ship.getAcceleration(atmosphere, inventoryMultiplier, material) <= 0}
|
||||
<p class="text-destructive">{applyUnits(i18n, ship.getAcceleration(atmosphere, inventoryMultiplier, material), "m/s²")}</p>
|
||||
{:else}
|
||||
<p>{applyUnits(i18n, ship.getAcceleration(atmosphere, inventoryMultiplier, material), "m/s²")}</p>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<p>{i18n.localize("acceleration")} ({i18n.localize("empty")}):</p>
|
||||
{#if ship.getMaxAcceleration(atmosphere) < 0}
|
||||
<p class="text-destructive">{applyUnits(i18n, ship.getMaxAcceleration(atmosphere), "m/s²")}</p>
|
||||
{:else}
|
||||
<p>{applyUnits(i18n, ship.getMaxAcceleration(atmosphere), "m/s²")}</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
|
@ -19,7 +19,7 @@
|
|||
<Label for="atmosDensity">{i18n.localize("atmosDensity")} ({(value * 100).toFixed(0)}%)</Label>
|
||||
<div class="flex gap-2">
|
||||
<Label for="atmosDensity">0%</Label>
|
||||
<Slider id="atmosDensity" value={array} onValueChange={handleChange} min={0} max={100} step={1} />
|
||||
<Slider id="atmosDensity" class="fill-primary" value={array} onValueChange={handleChange} min={0} max={100} step={1} />
|
||||
<Label>100%</Label>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
{#if valid}
|
||||
{#each thrusters as thruster, index}
|
||||
<p class="gap-2 flex justify-between">
|
||||
- {i18n.localize(thruster.details.size)} {i18n.localize(thruster.details.type.details.name)}: {applyUnits(i18n, thruster.getThrust(grid, atmosphere), "N")}
|
||||
- {i18n.localize(thruster.details.size)} {i18n.localize(thruster.details.type.details.name)}: {applyUnits(i18n, thruster.getThrust(grid, atmosphere), "N")} ({Math.round(thruster.details.type.details.curve.getEffectiveness(atmosphere).toFixed(2) * 100)}%)
|
||||
<Button variant="destructive" onmousedown={() => onRemoveThruster(index)}>X</Button>
|
||||
</p>
|
||||
{/each}
|
||||
|
|
|
@ -196,6 +196,22 @@ const localization = new Map([
|
|||
["deuterium", new Map([
|
||||
["en-GB", "Deuterium"],
|
||||
["de-DE", "Deuterium"],
|
||||
])],
|
||||
["vehicleWeightInTons", new Map([
|
||||
["en-GB", "Vehicle Weight (in tons)"],
|
||||
["de-DE", "Fahrzeug Gewicht (in Tonnen)"],
|
||||
])],
|
||||
["full", new Map([
|
||||
["en-GB", "full"],
|
||||
["de-DE", "voll"],
|
||||
])],
|
||||
["empty", new Map([
|
||||
["en-GB", "empty"],
|
||||
["de-DE", "leer"],
|
||||
])],
|
||||
["acceleration", new Map([
|
||||
["en-GB", "Acceleration"],
|
||||
["de-DE", "Beschleunigung"],
|
||||
])]
|
||||
])
|
||||
|
||||
|
@ -265,6 +281,6 @@ export function weightConversion(i18n: Localization, weight: number): string {
|
|||
return applyUnits(i18n, weight/1000, "t")
|
||||
}
|
||||
else {
|
||||
return `${weight.toFixed(2)}kg`
|
||||
return `${(weight * 100).toFixed(2) || (weight * 100) / 100}kg`
|
||||
}
|
||||
}
|
|
@ -2,12 +2,13 @@ import {Thruster, THRUSTER_LIST, THRUSTER_TYPE_LIST} from "$lib/thruster.svelte"
|
|||
import {Grid} from "$lib/grid";
|
||||
import {INVENTORIES, Inventory} from "$lib/containers.svelte";
|
||||
import type {Fuel} from "$lib/fuel";
|
||||
import type {CargoMaterial} from "$lib/materials";
|
||||
|
||||
export class Ship {
|
||||
thrusters: Array<Thruster> = $state([]);
|
||||
inventories: Array<Inventory> = $state([]);
|
||||
grid: Grid = $state(Grid.Small);
|
||||
weight: number = $state(0);
|
||||
tons: number = $state(0);
|
||||
|
||||
constructor(grid: Grid = Grid.Small) {
|
||||
this.grid = grid;
|
||||
|
@ -22,7 +23,7 @@ export class Ship {
|
|||
return inventory.details.key;
|
||||
}),
|
||||
grid: this.grid,
|
||||
weight: this.weight,
|
||||
weight: this.tons,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +50,7 @@ export class Ship {
|
|||
}
|
||||
|
||||
if (ship.weight !== undefined) {
|
||||
this.weight = ship.weight;
|
||||
this.tons = ship.weight;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,14 +86,6 @@ export class Ship {
|
|||
return thrust;
|
||||
}
|
||||
|
||||
getTotalMaxThrust(): number {
|
||||
let thrust = 0;
|
||||
this.thrusters.forEach((thruster) => {
|
||||
thrust += thruster.getMaxThrust(this.grid);
|
||||
});
|
||||
return thrust;
|
||||
}
|
||||
|
||||
getFuelTypes(): Array<Fuel> {
|
||||
let fuels: Array<Fuel> = [];
|
||||
this.thrusters.forEach((thruster) => {
|
||||
|
@ -102,4 +95,29 @@ export class Ship {
|
|||
})
|
||||
return fuels;
|
||||
}
|
||||
|
||||
getTotalWeightPossible(gravity: number, atmosphere: number): number {
|
||||
return this.getTotalThrust(atmosphere) / (gravity * 9.81)
|
||||
}
|
||||
|
||||
getVehicleWeightPossible(gravity: number, atmosphere: number, inventoryMultiplier: number, material: CargoMaterial): number {
|
||||
return this.getTotalWeightPossible(gravity, atmosphere) - this.getTotalVolume(inventoryMultiplier) * material.density;
|
||||
}
|
||||
|
||||
getVehicleWeight(): number {
|
||||
return (this.tons * 1000);
|
||||
}
|
||||
|
||||
getTotalWeight(inventoryMultiplier: number, material: CargoMaterial) {
|
||||
return this.getVehicleWeight() + this.getTotalVolume(inventoryMultiplier) * material.density;
|
||||
}
|
||||
|
||||
getAcceleration(atmosphere: number, inventoryMultiplier: number, material: CargoMaterial) {
|
||||
console.log(material)
|
||||
return this.getTotalThrust(atmosphere) / this.getTotalWeight(inventoryMultiplier, material)
|
||||
}
|
||||
|
||||
getMaxAcceleration(atmosphere: number) {
|
||||
return this.getTotalThrust(atmosphere) / this.getVehicleWeight();
|
||||
}
|
||||
}
|
|
@ -8,11 +8,41 @@ export enum ThrusterSize {
|
|||
Huge = "hugeThruster",
|
||||
}
|
||||
|
||||
export type ThrustDensity = {
|
||||
thrust: number;
|
||||
density: number;
|
||||
}
|
||||
|
||||
export class ThrustCurve {
|
||||
private min: ThrustDensity;
|
||||
private max: ThrustDensity;
|
||||
|
||||
constructor(min: ThrustDensity, max: ThrustDensity) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
getEffectiveness(airDensity: number): number {
|
||||
if (airDensity >= this.max.density) {
|
||||
return this.max.thrust;
|
||||
}
|
||||
else if (airDensity <= this.min.density) {
|
||||
return this.min.thrust;
|
||||
}
|
||||
else {
|
||||
return (1 - this.getPointOnCurve(airDensity)) * this.min.thrust + this.getPointOnCurve(airDensity) * this.max.thrust
|
||||
}
|
||||
}
|
||||
|
||||
private getPointOnCurve(airDensity: number): number {
|
||||
return (airDensity-this.min.density)/(this.max.density - this.min.density);
|
||||
}
|
||||
}
|
||||
|
||||
type ThrusterTypeDetails = {
|
||||
key: string,
|
||||
name: string,
|
||||
vacuum: number,
|
||||
atmosphere: number,
|
||||
curve: ThrustCurve,
|
||||
fuel: Fuel,
|
||||
};
|
||||
|
||||
|
@ -20,29 +50,25 @@ export const THRUSTER_TYPE_LIST: { [key: string]: ThrusterTypeDetails } = {
|
|||
Atmospheric: {
|
||||
key: "Atmospheric",
|
||||
name: "atmosphericThruster",
|
||||
vacuum: 0,
|
||||
atmosphere: 1,
|
||||
curve: new ThrustCurve({density: 0.3, thrust: 0}, {density: 1, thrust: 1}),
|
||||
fuel: Fuel.Electricity,
|
||||
},
|
||||
Ion: {
|
||||
key: "Ion",
|
||||
name: "ionThruster",
|
||||
vacuum: 1,
|
||||
atmosphere: 0.2,
|
||||
curve: new ThrustCurve({density: 0, thrust: 1}, {density: 1, thrust: 0.3}),
|
||||
fuel: Fuel.Electricity,
|
||||
},
|
||||
Hydrogen: {
|
||||
key: "Hydrogen",
|
||||
name: "hydrogenThruster",
|
||||
vacuum: 1,
|
||||
atmosphere: 1,
|
||||
curve: new ThrustCurve({density: 0, thrust: 1}, {density: 1, thrust: 1}),
|
||||
fuel: Fuel.Hydrogen,
|
||||
},
|
||||
Fusion: {
|
||||
key: "Fusion",
|
||||
name: "fusionThruster",
|
||||
vacuum: 1,
|
||||
atmosphere: 0.5,
|
||||
curve: new ThrustCurve({density: 0, thrust: 1}, {density: 1, thrust: 0.5}),
|
||||
fuel: Fuel.Deuterium,
|
||||
},
|
||||
}
|
||||
|
@ -61,9 +87,8 @@ export class ThrusterType {
|
|||
let equals: Array<boolean> = [];
|
||||
equals[0] = this.details.key === obj.details.key;
|
||||
equals[1] = this.details.name === obj.details.name;
|
||||
equals[2] = this.details.vacuum === obj.details.vacuum;
|
||||
equals[3] = this.details.atmosphere === obj.details.atmosphere;
|
||||
equals[4] = this.details.fuel === obj.details.fuel;
|
||||
equals[2] = this.details.curve === obj.details.curve;
|
||||
equals[3] = this.details.fuel === obj.details.fuel;
|
||||
return !equals.includes(false);
|
||||
}
|
||||
}
|
||||
|
@ -229,7 +254,7 @@ export class Thruster {
|
|||
}
|
||||
|
||||
getThrust(grid: Grid, atmosphereDensity: number): number {
|
||||
let efficiencyCoefficient: number = (this.details.type.details.vacuum * (1 - atmosphereDensity)) + (this.details.type.details.atmosphere * atmosphereDensity);
|
||||
let efficiencyCoefficient: number = this.details.type.details.curve.getEffectiveness(atmosphereDensity);
|
||||
let thruster: ThrusterDetails | undefined = THRUSTER_LIST[this.details.key];
|
||||
if (thruster === undefined) {
|
||||
throw(`Thruster ${this.details.key} undefined, cannot retrieve thrust values`);
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
import {Slider} from "$lib/components/ui/slider";
|
||||
import Atmosphere from "$lib/components/Atmosphere.svelte";
|
||||
import WeightOutputSegment from "$lib/components/WeightOutputSegment.svelte";
|
||||
import Inventories from "$lib/cards/Inventories.svelte";
|
||||
import Thrusters from "$lib/cards/Thrusters.svelte";
|
||||
import AccelerationOutputSegment from "$lib/components/AccelerationOutputSegment.svelte";
|
||||
|
||||
const STORAGE_VERSION = "2";
|
||||
let i18n = $state(new Localization("en-GB"));
|
||||
|
@ -66,10 +69,6 @@
|
|||
}
|
||||
})
|
||||
|
||||
let maxWeight: number = $derived(ship.getTotalThrust(atmosphericDensity) / (gravity * 9.81))
|
||||
|
||||
let maxVehicleWeight: number = $derived(maxWeight - ship.getTotalVolume(inventoryMultiplier) * material.density)
|
||||
|
||||
function addInventory(newInventory: Inventory) {
|
||||
console.log("triggered")
|
||||
ship.addInventory(newInventory);
|
||||
|
@ -87,12 +86,6 @@
|
|||
ship.removeThruster(index);
|
||||
}
|
||||
|
||||
function handleGravityChange() {
|
||||
if (gravity <= 0) {
|
||||
gravity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
if (navigator) {
|
||||
i18n.language = navigator.language;
|
||||
|
@ -149,6 +142,7 @@
|
|||
<meta name="robots" content="noindex nofollow" />
|
||||
</svelte:head>
|
||||
|
||||
{#if mounted}
|
||||
<div class="gap-4 flex flex-row flex-wrap h-full">
|
||||
<Card.Root class="flex-1">
|
||||
<Card.Header>
|
||||
|
@ -173,7 +167,7 @@
|
|||
{/each}
|
||||
</div>
|
||||
<Label for="gravity">{i18n.localize("gravity")}</Label>
|
||||
<Input type="number" step="0.01" id="gravity" bind:value={gravity} onchange={(change) => {handleGravityChange(change)}}/>
|
||||
<Input type="number" step="0.01" id="gravity" bind:value={gravity} min="0"/>
|
||||
<Label for="density">{i18n.localize("density")}</Label>
|
||||
<div id="density" class="flex gap-2">
|
||||
{#each Object.values(CargoMaterial) as value}
|
||||
|
@ -185,6 +179,9 @@
|
|||
{/each}
|
||||
</div>
|
||||
<Atmosphere bind:value={atmosphericDensity} />
|
||||
<Separator />
|
||||
<Label for="weight">{i18n.localize("vehicleWeightInTons")}</Label>
|
||||
<Input type="number" step="0.01" id="weight" bind:value={ship.tons} min="0" />
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
<Card.Root>
|
||||
|
@ -193,63 +190,22 @@
|
|||
</Card.Header>
|
||||
<Card.Content class="flex flex-col gap-3">
|
||||
<Separator />
|
||||
<WeightOutputSegment {i18n} maxWeight={maxWeight} maxVehicleWeight="{maxVehicleWeight}" />
|
||||
<WeightOutputSegment {i18n} maxWeight={ship.getTotalWeightPossible(gravity, atmosphericDensity)} maxVehicleWeight="{ship.getVehicleWeightPossible(gravity, atmosphericDensity, inventoryMultiplier, material)}" />
|
||||
<Separator />
|
||||
<p>{i18n.localize(ship.getFuelTypes().length > 1 ? "fuels" : "fuel")}:
|
||||
{ship.getFuelTypes().map((fuel) => i18n.localize(fuel.name)).join(", ") }
|
||||
</p>
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
<Card.Root class="flex-1 flex flex-col flex-grow">
|
||||
<Card.Header>
|
||||
<Card.Title>{i18n.localize("thrusterSettings")}</Card.Title>
|
||||
</Card.Header>
|
||||
<Card.Content class="flex flex-col flex-grow gap-3">
|
||||
<Separator />
|
||||
<Card.Root>
|
||||
<Card.Content class="flex flex-col gap-3 pt-6">
|
||||
<NewThruster i18n={i18n} onAddThruster={addThruster} />
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
<Card.Root class="flex flex-col h-60 flex-grow">
|
||||
<Card.Header>
|
||||
<Card.Title>{i18n.localize("thrusters")} ({applyUnits(i18n, ship.getTotalThrust(atmosphericDensity), "N")})</Card.Title>
|
||||
</Card.Header>
|
||||
<Card.Content class="flex flex-col gap-3 overflow-hidden">
|
||||
<Separator />
|
||||
<ThrusterList i18n={i18n} thrusters={ship.thrusters} onRemoveThruster={removeThruster} grid={ship.grid} atmosphere={atmosphericDensity}/>
|
||||
<AccelerationOutputSegment {i18n} {ship} atmosphere={atmosphericDensity} {inventoryMultiplier} {material} />
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
|
||||
<Card.Root class="flex-1 flex flex-col flex-grow">
|
||||
<Card.Header>
|
||||
<Card.Title>{i18n.localize("inventorySettings")}</Card.Title>
|
||||
</Card.Header>
|
||||
<Card.Content class="flex flex-col flex-grow gap-3">
|
||||
<Separator />
|
||||
<Label for="inventorySize">{i18n.localize("inventory")} {i18n.localize("multiplier")}</Label>
|
||||
<Input id="inventorySize" type="number" bind:value={inventoryMultiplier}/>
|
||||
<Card.Root>
|
||||
<Card.Content class="pt-6 flex flex-col gap-3">
|
||||
<NewInventory i18n={i18n} grid={ship.grid} onAddInventory={addInventory} />
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
<Card.Root class="flex flex-col h-60 flex-grow">
|
||||
<Card.Header>
|
||||
<Card.Title>{i18n.localize("inventories")} ({applyUnits(i18n, ship.getTotalVolume(inventoryMultiplier), "l")})</Card.Title>
|
||||
</Card.Header>
|
||||
<Card.Content class="flex flex-col gap-3 overflow-hidden">
|
||||
<Separator />
|
||||
<InventoryList i18n={i18n} inventories={ship.inventories} onRemoveInventory={removeInventory} grid={ship.grid} multiplier={inventoryMultiplier} />
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
<Thrusters {i18n} {ship} {atmosphericDensity} onAddThruster={addThruster} onRemoveThruster={removeThruster} />
|
||||
<Inventories {i18n} {ship} {inventoryMultiplier} onAddInventory={addInventory} onRemoveInventory={removeInventory} />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue