docks66-json-schema
Yanick Champoux 2023-05-03 16:39:49 -04:00
parent cf264e4748
commit 666be45472
9 changed files with 209 additions and 6 deletions

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1,5 +1,5 @@
<g {transform}>
<path d={path} class:active on:click />
<path d={path} class="arc" class:active on:click />
</g>
<script>

View File

@ -0,0 +1,98 @@
<span>torpedo</span>
<Field label="torpedo class" suffix>
<select bind:value={weaponClass}>
{#each Array.from({length: maxClass}) as _dummy,i (i)}
<option value={i+1}>{i+1}</option>
{/each}
</select>
<i>arrow_drop_down</i>
</Field>
<Field label="arcs" suffix>
<select bind:value={nbrArcs}>
{#each nbrArcsOptions as value}
<option {value}>{value}</option>
{/each}
</select>
<i>arrow_drop_down</i>
</Field>
<div class="arcs">
<Arcs
size={48}
selected={arcs}
on:clickArc={({ detail }) => setFirstArc(detail)}
/>
</div>
<script lang="ts">
import * as R from "remeda";
import u from "@yanick/updeep-remeda";
import { createEventDispatcher } from "svelte";
import memoize from "memoize-one";
import Arcs from "../Arcs.svelte";
import ShipItem from "$lib/components/ShipItem.svelte";
import Field from "$lib/components/Field.svelte";
import {
weaponTypes,
broadsideArcs,
arcs as allArcs,
isBroadside,
} from "$lib/store/ship/weaponry/rules.ts";
const options = weaponTypes.find(u.matches({ type: "torpedo" }))?.options ??
{};
const maxClass = options.maxClass;
export let weaponClass = 1;
export let arcs = ["F"];
let nbrArcs = isBroadside(arcs) ? "broadside" : arcs.length;
$: nbrArcsOptions = options.nbrArcs;
$: if (!nbrArcsOptions.includes(nbrArcs)) nbrArcs = nbrArcsOptions[0];
function allowedArcs(arcs, options) {
if (options.broadside && isBroadside(arcs)) return true;
return options.nbrArcs.includes(arcs.length);
}
let firstArc = allArcs[0];
const setFirstArc = (a) => (firstArc = a);
$: arcs = setArcs(firstArc, nbrArcs);
function setArcs(firstArc, nbrArcs) {
if (nbrArcs === "broadside") return broadsideArcs;
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((weaponClass, ...arcs) =>
dispatch("change", {
weaponClass,
arcs,
})
);
$: memoChange(weaponClass, ...arcs);
</script>
<style>
.arcs {
margin-top: 0.5rem;
}
</style>

View File

@ -18,6 +18,7 @@
import Scattergun from "./Scattergun.svelte";
import Needle from "./Needle.svelte";
import Graser from "./Graser/index.svelte";
import Torpedo from "./Torpedo/index.svelte";
const component = {
beam: Beam,
@ -26,6 +27,7 @@
scattergun: Scattergun,
needle: Needle,
graser: Graser,
torpedo: Torpedo,
};
export let reqs = {};

View File

@ -33,7 +33,20 @@ type Graser = {
arcs: Arc[];
};
export type Weapon = Beam | Submunition | PDS | Scattergun | Needle | Graser;
type Torpedo = {
type: "torpedo";
weaponClass: 1 | 2 | 3 | 4;
arcs: Arc[];
};
export type Weapon =
| Beam
| Submunition
| PDS
| Scattergun
| Needle
| Graser
| Torpedo;
export const weaponTypes = [
{
@ -67,6 +80,20 @@ export const weaponTypes = [
},
],
},
{
type: "torpedo",
name: "torpedo",
reqs: torpedoReqs,
initial: {
type: "torpedo",
weaponClass: 1,
arcs: ["F"],
} as any as Torpedo,
options: {
maxClass: 4,
nbrArcs: [1, 2, 3, "broadside"],
},
},
{
type: "submunition",
name: "submunition pack",
@ -153,7 +180,7 @@ function beamReqs({ weaponClass, arcs }: Beam) {
};
}
function graserReqs({ weaponClass, arcs }: Beam) {
function graserReqs({ weaponClass, arcs }: Graser) {
let mass: number;
if (weaponClass === 1) {
@ -185,3 +212,20 @@ function graserReqs({ weaponClass, arcs }: Beam) {
cost: 4 * mass,
};
}
function torpedoReqs({ weaponClass, arcs }: Torpedo): Reqs {
let mass: number = 4;
if (isBroadside(arcs)) {
mass += 2;
} else {
mass += arcs.length - 1;
}
mass = mass * Math.pow(2, weaponClass - 1);
return {
mass,
cost: 3 * mass,
};
}

View File

@ -10,15 +10,14 @@
{shipType}
</h2>
<div class="reqs">
{cost} <i>paid</i> &nbsp; {mass} <i>weight</i>
{reqs.cost} <i>paid</i> &nbsp; {reqs.mass} <i>weight</i>
</div>
</div>
<script>
export let shipClass;
export let shipType;
export let cost = 0;
export let mass = 0;
export let reqs = { cost: 0, mass: 0 };
</script>
<style>

View File

@ -0,0 +1,9 @@
<Hst.Story title="Export/PrintShip/Weapons/Torpedo">
<Torpedo arcs={["F", "FS"]} weaponClass={2} />
</Hst.Story>
<script>
import Torpedo from "./index.svelte";
export let Hst;
</script>

View File

@ -0,0 +1,49 @@
<div class="torpedo">
<Arcs selected={arcs} size={40}>
<g transform="scale(0.12) translate(-315,-100)">
<path
d="M480,162.8c-57.2,0-103.5,46.3-103.5,103.5S422.8,369.8,480,369.8c57.2,0,103.5-46.3,103.5-103.5S537.2,162.8,480,162.8z
M534.3,320.6l-38.2-22.8h-32.3l-38.2,22.8l22.8-38.2v-32.3L425.7,212l38.2,22.8h32.3l38.2-22.8l-22.8,38.2v32.3L534.3,320.6z"
/>
</g>
</Arcs>
<div class="weaponClass">2</div>
</div>
<script>
import Arcs from "$lib/components/ShipEdit/Weaponry/Weapon/Arcs.svelte";
export let weaponClass = 1;
export let arcs = [];
</script>
<style>
.torpedo {
display: flex;
flex-direction: column;
align-items: center;
}
.weaponClass {
text-align: center;
background-color: black;
color: white;
border-radius: 50%;
width: 20px;
}
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

@ -4,8 +4,10 @@ import PDS from "./PDS.svelte";
import Scattergun from "./Scattergun.svelte";
import Needlebeam from "./Needlebeam.svelte";
import Graser from "./Graser/index.svelte";
import Torpedo from "./Torpedo/index.svelte";
export default {
torpedo: Torpedo,
graser: Graser,
beam: Beam,
submunition: Submunition,