add salvo missile racks

This commit is contained in:
Yanick Champoux 2023-05-12 10:48:53 -04:00
parent 11d65b375d
commit e515ce2e74
9 changed files with 237 additions and 3 deletions

View File

@ -4,6 +4,10 @@ project:
with_stats: true with_stats: true
ticket_url: null ticket_url: null
releases: releases:
- version: NEXT
changes:
- desc: add SMRs
type: feat
- version: 3.1.0 - version: 3.1.0
changes: changes:
- desc: add version and changelog to the about section - desc: add version and changelog to the about section

View File

@ -0,0 +1,66 @@
<span>salvo missile rack</span>
<div class="arcs">
<Arcs
size={48}
selected={arcs}
on:clickArc={({ detail }) => setFirstArc(detail)}
/>
</div>
<label class="switch">
<input type="checkbox" bind:checked={extended} />
<span>extended range</span>
</label>
<script lang="ts">
import u from "@yanick/updeep-remeda";
import { createEventDispatcher } from "svelte";
import memoize from "memoize-one";
import Arcs from "./Arcs.svelte";
import {
weaponTypes,
arcs as allArcs,
} from "$lib/store/ship/weaponry/rules.ts";
export let arcs = ["F", "FS", "FP"];
export let extended = false;
const nbrArcs = 3;
let firstArc = allArcs[0];
const setFirstArc = (a) => (firstArc = a);
$: arcs = setArcs(firstArc, nbrArcs);
function setArcs(firstArc, nbrArcs) {
let first_index = allArcs.findIndex((arc) => arc === firstArc);
if (first_index === -1) first_index = 0;
return Array.from({ length: nbrArcs }).map(
(_dummy, i) => allArcs[(first_index + i) % allArcs.length]
);
}
const dispatch = createEventDispatcher();
const memoChange = memoize((extended, ...arcs) =>
dispatch("change", {
extended,
arcs,
})
);
$: memoChange(extended, ...arcs);
</script>
<style>
.arcs {
margin-top: 0.5rem;
}
label span {
padding-left: 1em;
}
</style>

View File

@ -20,6 +20,7 @@
import Graser from "./Graser/index.svelte"; import Graser from "./Graser/index.svelte";
import Torpedo from "./Torpedo/index.svelte"; import Torpedo from "./Torpedo/index.svelte";
import Missile from "./HeavyMissile/index.svelte"; import Missile from "./HeavyMissile/index.svelte";
import SalvoMissileRack from "./SalvoMissileRack.svelte";
const component = { const component = {
beam: Beam, beam: Beam,
@ -30,6 +31,7 @@
graser: Graser, graser: Graser,
torpedo: Torpedo, torpedo: Torpedo,
heavyMissile: Missile, heavyMissile: Missile,
smr: SalvoMissileRack,
}; };
export let reqs = {}; export let reqs = {};

View File

@ -34,6 +34,12 @@ type HeavyMissile = {
multiStage: boolean; multiStage: boolean;
}; };
type SalvoMissileRack = {
type: "salvoMissileRack";
arcs: Arc[];
extended: boolean;
};
type Graser = { type Graser = {
type: "graser"; type: "graser";
weaponClass: 1 | 2 | 3; weaponClass: 1 | 2 | 3;
@ -139,6 +145,16 @@ export const weaponTypes = [
type: "heavyMissile", type: "heavyMissile",
}, },
}, },
{
name: "salvo missile rack",
type: "smr",
reqs: smrReqs,
initial: {
arcs: ["FP", "F", "FS"],
extended: false,
type: "smr",
},
},
]; ];
export function weaponReqs(weapon): Reqs { export function weaponReqs(weapon): Reqs {
@ -247,6 +263,15 @@ function missileReqs({ extended, multiStage }: HeavyMissile): Reqs {
return { cost, mass }; return { cost, mass };
} }
function smrReqs({ extended }: SalvoMissileRack): Reqs {
let mass = 4;
if (extended) mass += 1;
return {
mass,
cost: 3 * mass,
};
}
function torpedoReqs({ weaponClass, arcs }: Torpedo): Reqs { function torpedoReqs({ weaponClass, arcs }: Torpedo): Reqs {
let mass: number = 4; let mass: number = 4;

View File

@ -0,0 +1,36 @@
<div class="smr">
<Arcs selected={arcs} size={40}>
<image href="/icons/missile.svg" width="18" x="12" y="7" />
</Arcs>
<div>
{#if extended}
<div>extended range</div>
{/if}
</div>
</div>
<script>
import Arcs from "$lib/components/ShipEdit/Weaponry/Weapon/Arcs.svelte";
export let arcs = [];
export let extended = false;
</script>
<style>
div {
margin: 0px 0.5rem;
}
div :global(path.arc) {
fill: none;
}
div :global(path.active) {
fill: black;
}
div :global(path.active:hover) {
fill: black;
}
text {
text-anchor: middle;
dominant-baseline: central;
font-size: var(--font-scale-10);
}
</style>

View File

@ -0,0 +1,12 @@
import { render } from "@testing-library/svelte";
import SMR from "./index.svelte";
test("basic", () => {
const { queryByText } = render(SMR, {
props: {
extended: true,
},
});
expect(queryByText("extended range")).toBeTruthy();
});

View File

@ -6,6 +6,7 @@ import Needlebeam from "./Needlebeam.svelte";
import Graser from "./Graser/index.svelte"; import Graser from "./Graser/index.svelte";
import Torpedo from "./Torpedo/index.svelte"; import Torpedo from "./Torpedo/index.svelte";
import HeavyMissile from "./HeavyMissile/index.svelte"; import HeavyMissile from "./HeavyMissile/index.svelte";
import SalvoMissileRack from "./SMR/index.svelte";
export default { export default {
torpedo: Torpedo, torpedo: Torpedo,
@ -16,4 +17,5 @@ export default {
scattergun: Scattergun, scattergun: Scattergun,
needle: Needlebeam, needle: Needlebeam,
heavyMissile: HeavyMissile, heavyMissile: HeavyMissile,
smr: SalvoMissileRack,
}; };

View File

@ -5,7 +5,15 @@
<div class="print-output"> <div class="print-output">
<Identification {...identification} /> <Identification {...identification} />
<HeavyMissiles {heavyMissiles} /> <div class="weapon-group">
{#each smrs as smr (smr.id)}
<SalvoMissileRack {...smr.specs} />
{/each}
</div>
<div class="weapon-group">
<HeavyMissiles {heavyMissiles} />
</div>
<Beams {beams} /> <Beams {beams} />
@ -52,6 +60,7 @@
import PDS from "./Weapons/PDS.svelte"; import PDS from "./Weapons/PDS.svelte";
import Beams from "./Weapons/Beams.svelte"; import Beams from "./Weapons/Beams.svelte";
import HeavyMissiles from "./Weapons/HeavyMissiles.svelte"; import HeavyMissiles from "./Weapons/HeavyMissiles.svelte";
import SalvoMissileRack from "./Weapons/SMR/index.svelte";
export let identification = {}; export let identification = {};
export let propulsion = {}; export let propulsion = {};
@ -66,7 +75,9 @@
$: weapons = u.reject( $: weapons = u.reject(
weapons, weapons,
u.matches({ u.matches({
specs: { type: (t) => ["pds", "beam", "heavyMissiles"].includes(t) }, specs: {
type: (t) => ["smr", "pds", "beam", "heavyMissile"].includes(t),
},
}) })
); );
@ -77,7 +88,10 @@
u.matches({ specs: { type: "beam" } }) u.matches({ specs: { type: "beam" } })
); );
$: heavyMissiles = (weaponry?.weapons ?? []).filter( $: heavyMissiles = (weaponry?.weapons ?? []).filter(
u.matches({ specs: { type: "heavyMissiles" } }) u.matches({ specs: { type: "heavyMissile" } })
);
$: smrs = (weaponry?.weapons ?? []).filter(
u.matches({ specs: { type: "smr" } })
); );
</script> </script>
@ -113,4 +127,9 @@
text-align: center; text-align: center;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.weapon-group {
display: flex;
justify-content: center;
margin-bottom: 1em;
}
</style> </style>

68
static/icons/missile.svg Normal file
View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="90"
height="110"
viewBox="0 0 23.8125 29.104166"
version="1.1"
id="svg876"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
sodipodi:docname="missile.svg">
<defs
id="defs870" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="1138.8867"
inkscape:cy="-549.64407"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
units="px"
inkscape:window-width="1920"
inkscape:window-height="957"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1" />
<metadata
id="metadata873">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(327.78876,55.935586)">
<polygon
style="fill:none;stroke:#000000;stroke-width:6.59100008;stroke-miterlimit:10"
id="polygon30"
points="543,438.6 580.2,462.1 543,378.1 505.8,462.1 "
stroke-miterlimit="10"
transform="matrix(0.26458333,0,0,0.26458333,-459.65684,-151.36374)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB