Merge branch 'main' into pages
6
.gitignore
vendored
@ -6,3 +6,9 @@ node_modules
|
||||
.vercel_build_output/
|
||||
package-lock.json
|
||||
.svench
|
||||
|
||||
.DS_STORE
|
||||
.cache
|
||||
.temp
|
||||
node_modules/
|
||||
dist/yarn-error.log
|
||||
|
@ -1,12 +1,47 @@
|
||||
const path = require('path');
|
||||
const path = require("path");
|
||||
const preprocess = require("svelte-preprocess");
|
||||
|
||||
module.exports = {
|
||||
addons: ['@storybook/addon-actions/register'],
|
||||
stories: [ '../src/**/*stories.js' ],
|
||||
webpackFinal: (config) => {
|
||||
config.resolve.alias['~'] = path.resolve(__dirname, '../src/');
|
||||
config.resolve.alias['~C'] = path.resolve(__dirname, '../src/components/');
|
||||
core: { builder: "storybook-builder-vite" },
|
||||
staticDirs: ["../static", "../pictures"],
|
||||
stories: [
|
||||
"../src/**/*.stories.mdx",
|
||||
"../src/**/*.stories.svelte",
|
||||
"../src/**/stories.svelte",
|
||||
],
|
||||
addons: [
|
||||
"@storybook/addon-essentials",
|
||||
"@storybook/addon-svelte-csf",
|
||||
],
|
||||
framework: "@storybook/svelte",
|
||||
svelteOptions: {
|
||||
preprocess: preprocess(),
|
||||
},
|
||||
async viteFinal(config, { configType }) {
|
||||
|
||||
if(!config.resolve.alias) config.resolve.alias = {};
|
||||
// customize the Vite config here
|
||||
config.resolve.alias.$lib = path.resolve(__dirname, "../src/lib/");
|
||||
config.resolve.alias.$app = path.resolve(__dirname, "../fake/app/");
|
||||
|
||||
config.resolve.dedupe = ["@storybook/client-api"];
|
||||
|
||||
// return the customized config
|
||||
return config;
|
||||
}
|
||||
},
|
||||
webpackFinal: async (config) => {
|
||||
return {
|
||||
...config,
|
||||
resolve: {
|
||||
...config.resolve,
|
||||
alias: {
|
||||
...config.resolve?.alias,
|
||||
$app: path.resolve("./fake/app"),
|
||||
"\\$lib": path.resolve(__dirname, "../src/lib/"),
|
||||
$lib: path.resolve(__dirname, "../src/lib/"),
|
||||
"\\$app/env": path.resolve(__dirname, "../fake/app/env.js"),
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
|
3
.storybook/package.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "commonjs"
|
||||
}
|
11
.storybook/preview.js
Normal file
@ -0,0 +1,11 @@
|
||||
import "$lib/style/index.js";
|
||||
|
||||
export const parameters = {
|
||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/,
|
||||
},
|
||||
},
|
||||
};
|
6
.vitebook/App.svelte
Normal file
@ -0,0 +1,6 @@
|
||||
<svelte:component this={component} />
|
||||
|
||||
<script>
|
||||
import "$lib/style/index.js";
|
||||
export let component;
|
||||
</script>
|
31
.vitebook/config.js
Normal file
@ -0,0 +1,31 @@
|
||||
import { svelte } from "@sveltejs/vite-plugin-svelte";
|
||||
import { clientPlugin, defineConfig } from "@vitebook/client/node";
|
||||
import { defaultThemePlugin } from "@vitebook/theme-default/node";
|
||||
import preprocess from "svelte-preprocess";
|
||||
|
||||
export default defineConfig({
|
||||
include: ["src/**/*.story.svelte"],
|
||||
alias: {
|
||||
$app: "/node_modules/@sveltejs/kit/assets/app",
|
||||
$lib: "/src/lib",
|
||||
},
|
||||
plugins: [
|
||||
clientPlugin({ appFile: "App.svelte" }),
|
||||
defaultThemePlugin(),
|
||||
svelte({
|
||||
compilerOptions: {
|
||||
hydratable: true,
|
||||
},
|
||||
extensions: [".svelte"],
|
||||
// Consult https://github.com/sveltejs/svelte-preprocess for more information
|
||||
// about preprocessors.
|
||||
preprocess: preprocess(),
|
||||
}),
|
||||
],
|
||||
site: {
|
||||
title: "",
|
||||
description: "",
|
||||
/** @type {(import('@vitebook/theme-default/node').DefaultThemeConfig} */
|
||||
theme: {},
|
||||
},
|
||||
});
|
18
.vitebook/index.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ lang }}">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<meta name="generator" content="vitebook@{{ version }}" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<!--@vitebook/head-->
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="app"><!--@vitebook/app--></div>
|
||||
<!--@vitebook/body-->
|
||||
</body>
|
||||
</html>
|
5
.vitebook/public/404.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg width="400" height="163" viewBox="0 0 400 163" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M192.333 4.56055C159.748 4.56055 136.352 25.4677 136.352 74.2511C136.352 129.539 159.748 144.174 192.333 144.174C224.918 144.174 249.708 128.145 249.708 74.2511C249.708 16.6402 224.918 4.56055 192.333 4.56055ZM192.547 125.822C169.978 125.822 158.187 112.58 158.187 74.2868C158.187 40.4983 170.46 22.6801 193.03 22.6801C215.599 22.6801 227.873 34.3842 227.873 74.2868C227.873 111.615 215.117 125.822 192.547 125.822Z" fill="currentColor"/>
|
||||
<path d="M116.842 105.612H103.369V65.936C103.369 63.8286 102.532 61.8076 101.042 60.3175C99.5523 58.8273 97.5314 57.9902 95.4241 57.9902H92.2672C91.2238 57.9902 90.1906 58.1957 89.2266 58.595C88.2627 58.9943 87.3868 59.5796 86.649 60.3175C85.9112 61.0553 85.3259 61.9312 84.9266 62.8953C84.5274 63.8593 84.3218 64.8925 84.3218 65.936V105.612H46.3199C45.5381 105.612 44.7696 105.41 44.0889 105.025C43.4083 104.641 42.8385 104.087 42.435 103.417C42.0315 102.748 41.8079 101.985 41.7859 101.204C41.7639 100.422 41.9442 99.6481 42.3094 98.9568L82.5303 22.8271C83.0317 21.878 83.3356 20.837 83.4237 19.7672C83.5118 18.6973 83.3822 17.6207 83.0427 16.6023C82.7032 15.5839 82.161 14.6449 81.4486 13.8419C80.7362 13.0389 79.8685 12.3886 78.8979 11.9302L76.5235 10.8089C74.6799 9.93827 72.5722 9.80971 70.6364 10.4498C68.7006 11.09 67.085 12.4498 66.1238 14.248L17.0692 106.019C16.2339 107.582 15.7969 109.327 15.7969 111.099V111.099C15.7969 112.514 16.0755 113.915 16.617 115.222C17.1584 116.529 17.952 117.717 18.9524 118.717C19.9529 119.718 21.1406 120.512 22.4477 121.053C23.7548 121.594 25.1558 121.873 26.5706 121.873H84.3218V146.962C84.3218 148.212 84.5682 149.451 85.0468 150.607C85.5254 151.762 86.2269 152.812 87.1113 153.696C87.9957 154.581 89.0456 155.282 90.201 155.761C91.3565 156.24 92.595 156.486 93.8456 156.486H93.8457C95.0963 156.486 96.3348 156.24 97.4903 155.761C98.6457 155.282 99.6956 154.581 100.58 153.696C101.464 152.812 102.166 151.762 102.644 150.607C103.123 149.451 103.369 148.212 103.369 146.962V121.873H116.842C118.998 121.873 121.066 121.017 122.591 119.492C124.116 117.967 124.972 115.899 124.972 113.743V113.743C124.972 111.586 124.116 109.518 122.591 107.993C121.066 106.469 118.998 105.612 116.842 105.612V105.612Z" fill="currentColor"/>
|
||||
<path d="M366.319 105.612H352.846V65.936C352.846 63.8286 352.009 61.8076 350.519 60.3175C349.029 58.8273 347.008 57.9902 344.901 57.9902H341.744C340.7 57.9902 339.667 58.1957 338.703 58.595C337.739 58.9943 336.863 59.5796 336.126 60.3175C335.388 61.0553 334.802 61.9312 334.403 62.8953C334.004 63.8593 333.798 64.8925 333.798 65.936V105.612H295.796C295.015 105.612 294.246 105.41 293.565 105.025C292.885 104.641 292.315 104.087 291.912 103.417C291.508 102.748 291.284 101.985 291.262 101.204C291.24 100.422 291.421 99.6481 291.786 98.9568L332.007 22.8271C332.508 21.878 332.812 20.8371 332.9 19.7672C332.988 18.6973 332.859 17.6207 332.519 16.6023C332.18 15.5839 331.638 14.6449 330.925 13.8419C330.213 13.0389 329.345 12.3886 328.374 11.9302L326 10.8089C324.156 9.93827 322.049 9.80971 320.113 10.4498C318.177 11.09 316.562 12.4498 315.6 14.248L266.546 106.019C265.71 107.582 265.273 109.327 265.273 111.099V111.099C265.273 113.956 266.409 116.697 268.429 118.717C270.449 120.738 273.19 121.873 276.047 121.873H333.798V146.962C333.798 149.488 334.802 151.91 336.588 153.696C338.374 155.483 340.796 156.486 343.322 156.486V156.486C345.848 156.486 348.27 155.483 350.057 153.696C351.843 151.91 352.846 149.488 352.846 146.962V121.873H366.319C368.475 121.873 370.543 121.017 372.068 119.492C373.592 117.967 374.449 115.899 374.449 113.743V113.743C374.449 111.586 373.592 109.518 372.068 107.993C370.543 106.469 368.475 105.612 366.319 105.612Z" fill="currentColor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
BIN
.vitebook/public/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
.vitebook/public/favicon-16x16.png
Normal file
After Width: | Height: | Size: 338 B |
BIN
.vitebook/public/favicon-32x32.png
Normal file
After Width: | Height: | Size: 492 B |
BIN
.vitebook/public/favicon.ico
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
.vitebook/public/logo-192x192.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
.vitebook/public/logo-512x512.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
4
.vitebook/public/logo.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="32" height="32" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M39.7265 4.50427L39.7265 33.3318H12.3391L28.8049 4.50427H39.7265Z" fill="white" stroke="black" stroke-width="3" stroke-linejoin="bevel"/>
|
||||
<path d="M5.6571 22.6991L17.0572 4.50427H32.2324L25.249 15.1287L38.8616 15.1287L5.6571 44.8828L15.3886 22.6987L5.6571 22.6991Z" fill="currentColor" stroke="black" stroke-width="3" stroke-linejoin="bevel"/>
|
||||
</svg>
|
After Width: | Height: | Size: 456 B |
20
.vitebook/public/manifest.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"short_name": "",
|
||||
"name": " Site",
|
||||
"icons": [
|
||||
{
|
||||
"src": "logo-192x192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo-512x512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#ffc107",
|
||||
"background_color": "#212121"
|
||||
}
|
3
.vitebook/public/robots.txt
Normal file
@ -0,0 +1,3 @@
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
3
.vitebook/theme/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
import Theme from "@vitebook/theme-default";
|
||||
|
||||
export default Theme;
|
5
_templates/generator/help/index.ejs.t
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
message: |
|
||||
hygen {bold generator new} --name [NAME] --action [ACTION]
|
||||
hygen {bold generator with-prompt} --name [NAME] --action [ACTION]
|
||||
---
|
18
_templates/generator/new/hello.ejs.t
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
to: _templates/<%= name %>/<%= action || 'new' %>/hello.ejs.t
|
||||
---
|
||||
---
|
||||
to: app/hello.js
|
||||
---
|
||||
const hello = ```
|
||||
Hello!
|
||||
This is your first hygen template.
|
||||
|
||||
Learn what it can do here:
|
||||
|
||||
https://github.com/jondot/hygen
|
||||
```
|
||||
|
||||
console.log(hello)
|
||||
|
||||
|
18
_templates/generator/with-prompt/hello.ejs.t
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
to: _templates/<%= name %>/<%= action || 'new' %>/hello.ejs.t
|
||||
---
|
||||
---
|
||||
to: app/hello.js
|
||||
---
|
||||
const hello = ```
|
||||
Hello!
|
||||
This is your first prompt based hygen template.
|
||||
|
||||
Learn what it can do here:
|
||||
|
||||
https://github.com/jondot/hygen
|
||||
```
|
||||
|
||||
console.log(hello)
|
||||
|
||||
|
14
_templates/generator/with-prompt/prompt.js
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
to: _templates/<%= name %>/<%= action || 'new' %>/prompt.js
|
||||
---
|
||||
|
||||
// see types of prompts:
|
||||
// https://github.com/enquirer/enquirer/tree/master/examples
|
||||
//
|
||||
module.exports = [
|
||||
{
|
||||
type: 'input',
|
||||
name: 'message',
|
||||
message: "What's your message?"
|
||||
}
|
||||
]
|
3
_templates/package.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "commonjs"
|
||||
}
|
13
_templates/story/new/index.js
Normal file
@ -0,0 +1,13 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
params: ({ args }) => {
|
||||
|
||||
const storypath = args.path.replace( '.svelte', '.stories.svelte' );
|
||||
|
||||
const component = path.basename(args.path.replace('/index.svelte','')).replace('.svelte','');
|
||||
|
||||
const to = path.join(path.dirname(args.path), component + '.stories.svelte' );
|
||||
return { storypath, component, to}
|
||||
}
|
||||
}
|
21
_templates/story/new/stories.svelte.temp
Normal file
@ -0,0 +1,21 @@
|
||||
---
|
||||
to: <%= to %>
|
||||
---
|
||||
<Meta title="<%= component %>" component={<%= component %>} argTypes={{}} />
|
||||
|
||||
<Story name="Primary" args={{}} />
|
||||
|
||||
<Template let:args>
|
||||
<div style="width: 50em">
|
||||
<<%= component %> />
|
||||
</div>
|
||||
</Template>
|
||||
|
||||
<script>
|
||||
import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
|
||||
import <%= component %> from './<%=
|
||||
h.path.basename(path)
|
||||
%>';
|
||||
</script>
|
1
fake/app/env.js
Normal file
@ -0,0 +1 @@
|
||||
export const browser = true;
|
48
package.json
@ -6,32 +6,44 @@
|
||||
"build": "svelte-kit build",
|
||||
"preview": "svelte-kit preview",
|
||||
"lint": "prettier --check . && eslint --ignore-path .gitignore .",
|
||||
"format": "prettier --write ."
|
||||
"format": "prettier --write .",
|
||||
"storybook": "storybook-server",
|
||||
"vitebook:dev": "vitebook dev",
|
||||
"vitebook:build": "vitebook build",
|
||||
"vitebook:preview": "vitebook preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/kit": "^1.0.0-next.115",
|
||||
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.10",
|
||||
"eslint": "^7.22.0",
|
||||
"eslint-config-prettier": "^8.1.0",
|
||||
"eslint-plugin-svelte3": "^3.2.0",
|
||||
"prettier": "~2.2.1",
|
||||
"prettier-plugin-svelte": "^2.2.0",
|
||||
"svelte": "^3.34.0",
|
||||
"svench": "^0.2.0-14",
|
||||
"vite": "^2.3.2"
|
||||
"@sveltejs/adapter-static": "^1.0.0-next.28",
|
||||
"@sveltejs/kit": "^1.0.0-next.288",
|
||||
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.38",
|
||||
"@vitebook/client": "^0.23.2",
|
||||
"@vitebook/core": "^0.23.2",
|
||||
"@vitebook/theme-default": "^0.23.2",
|
||||
"eslint": "^8.10.0",
|
||||
"eslint-config-prettier": "^8.4.0",
|
||||
"eslint-plugin-svelte3": "^3.4.1",
|
||||
"prettier": "~2.5.1",
|
||||
"prettier-plugin-svelte": "^2.6.0",
|
||||
"storybook-builder-vite": "0.1.21",
|
||||
"svelte": "^3.46.4",
|
||||
"vite": "^2.7.0"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@sveltejs/adapter-node": "^1.0.0-next.18",
|
||||
"@sveltejs/adapter-static": "^1.0.0-next.13",
|
||||
"@yanick/updeep": "link:/home/yanick/work/javascript/updeep",
|
||||
"bulma": "^0.9.2",
|
||||
"@storybook/addon-essentials": "^6.4.19",
|
||||
"@storybook/addon-svelte-csf": "^1.1.0",
|
||||
"@storybook/svelte": "^6.4.19",
|
||||
"@sveltejs/adapter-node": "^1.0.0-next.0",
|
||||
"chota": "^0.8.0",
|
||||
"lodash": "^4.17.21",
|
||||
"redux": "^4.1.0",
|
||||
"reselect": "^4.0.0",
|
||||
"redux": "^4.1.2",
|
||||
"reselect": "^4.1.5",
|
||||
"rollup-plugin-analyzer": "^4.0.0",
|
||||
"svelte-chota": "^1.8.6",
|
||||
"svelte-knobby": "^0.3.4",
|
||||
"ts-action": "^11.0.0",
|
||||
"updux": "link:/home/yanick/work/javascript/updux/"
|
||||
"updux": "link:/home/yanick/work/javascript/updux-js/",
|
||||
"webpack": "5"
|
||||
},
|
||||
"prettier": {
|
||||
"svelteSortOrder": "options-markup-scripts-styles",
|
||||
|
@ -1,38 +0,0 @@
|
||||
<ShipItem {cost} {mass} >
|
||||
<Field label={`squadron ${id}`}>
|
||||
<select bind:value={type}>
|
||||
{#each types as type (type)}
|
||||
<option>{type}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</Field>
|
||||
</ShipItem>
|
||||
|
||||
<script>
|
||||
import {getContext } from 'svelte';
|
||||
|
||||
import Section from "$lib/components/Section/index.svelte";
|
||||
import Field from "$lib/components/Field/index.svelte";
|
||||
import ShipItem from "$lib/components/ShipItem/index.svelte";
|
||||
import dux from '$lib/dux/carrier';
|
||||
import squadron_types from '$lib/dux/carrier/squadron_types';
|
||||
|
||||
const types = squadron_types.map( ({type}) => type );
|
||||
|
||||
export let id = 1;
|
||||
export let type = "standard";
|
||||
export let ftl = false;
|
||||
export let cost =0;
|
||||
export let mass = 0;
|
||||
|
||||
export let ship = getContext('ship');
|
||||
|
||||
$: ship?.dispatch_action('set_squadron',{ id, type, });
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div {
|
||||
background-color: red;
|
||||
}
|
||||
</style>
|
@ -1,20 +0,0 @@
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import Carrier from './index.svelte';
|
||||
|
||||
export default {
|
||||
title: 'Carrier',
|
||||
};
|
||||
|
||||
export const basic = () => ({
|
||||
Component: Carrier,
|
||||
props: {
|
||||
bays: 3,
|
||||
squadrons: [
|
||||
{ id: 1, type: "standard", ftl: false, nbr_fighters: 6 },
|
||||
{ id: 2, type: "fast", ftl: false, nbr_fighters: 6 },
|
||||
{ id: 3, type: "none", ftl: false, nbr_fighters: 6 },
|
||||
],
|
||||
ship_change: action('ship_change'),
|
||||
},
|
||||
})
|
@ -1,21 +0,0 @@
|
||||
<div class="mass">{ mass }</div>
|
||||
<div class="cost">{ cost }</div>
|
||||
|
||||
<script>
|
||||
export let mass;
|
||||
export let cost;
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.cost { grid-column: 3; }
|
||||
.mass { grid-column: 2; }
|
||||
img {
|
||||
width: 0.75em;
|
||||
}
|
||||
.cost:after { content: '\00A4'; margin-left: 0.5em; }
|
||||
.mass:after { content: url("/mass.svg"); width: 0.75em; display:
|
||||
inline-block; margin-left: 0.5em; }
|
||||
|
||||
|
||||
</style>
|
@ -1,40 +0,0 @@
|
||||
<ShipItem {cost} {mass}>
|
||||
|
||||
<div>
|
||||
<Field label="thrust rating">
|
||||
<input type="number" bind:value={ rating }
|
||||
min="0" max="20" step="1" />
|
||||
</Field>
|
||||
|
||||
<label><input type="checkbox" bind:checked={advanced} /> advanced</label>
|
||||
</div>
|
||||
|
||||
</ShipItem>
|
||||
|
||||
|
||||
<script>
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
import Field from '$lib/components/Field/index.svelte';
|
||||
import ShipItem from '$lib/components/ShipItem/index.svelte';
|
||||
|
||||
export let cost;
|
||||
export let mass;
|
||||
export let advanced = false;
|
||||
export let rating = 0;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
console.log(advanced);
|
||||
$: dispatch( 'change_engine', { rating, advanced } );
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div {
|
||||
display: flex;
|
||||
align-items: end;
|
||||
}
|
||||
label { margin-left: 2em; }
|
||||
input[type="number"] { width: 5em; }
|
||||
</style>
|
@ -1,29 +0,0 @@
|
||||
<div>
|
||||
{#if label}
|
||||
<label>{label}</label>
|
||||
{/if}
|
||||
<slot>
|
||||
<input type="text" {placeholder} {value} on:change />
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
export let label = "";
|
||||
export let value = "";
|
||||
export let placeholder;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div > :global(*) {
|
||||
margin-left: 1em;
|
||||
}
|
||||
div > label {
|
||||
margin-left: 0em;
|
||||
}
|
||||
label {
|
||||
font-size: var(--font-scale-8);
|
||||
font-weight: lighter;
|
||||
font-family: Dosis;
|
||||
color: var(--indigo-dye);
|
||||
}
|
||||
</style>
|
@ -1,12 +0,0 @@
|
||||
import Component from './index.svelte';
|
||||
import BasicStory from './BasicStory.svelte';
|
||||
|
||||
import '../../../public/global.css';
|
||||
|
||||
export default {
|
||||
title: 'Field'
|
||||
};
|
||||
|
||||
export const basic = () => ({
|
||||
Component: BasicStory,
|
||||
});
|
@ -1,20 +0,0 @@
|
||||
<ShipItem {cost} {mass}>
|
||||
<Field label="firecons">
|
||||
<input type="number" class="short" bind:value={nbr} />
|
||||
</Field>
|
||||
</ShipItem>
|
||||
|
||||
<script>
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import ShipItem from './ShipItem/index.svelte';
|
||||
import Field from './Field/index.svelte';
|
||||
|
||||
export let nbr, cost, mass = (0,0,0);
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
$: dispatch( 'change_firecons', nbr);
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
@ -1,35 +0,0 @@
|
||||
<script>
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
import ShipItem from '../ShipItem/index.svelte';
|
||||
import Field from '../Field/index.svelte';
|
||||
|
||||
export let type = 'none';
|
||||
export let cost = 0;
|
||||
export let mass = 0;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
const change = () => dispatch( 'change_ftl', type );
|
||||
|
||||
const types = [ 'none', 'standard', 'advanced' ];
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<ShipItem {mass} {cost}>
|
||||
<Field label="FTL drive">
|
||||
|
||||
{#each types as t (t)}
|
||||
<label><input type="radio" bind:group={type} value={t}
|
||||
on:change={change} /> {t} </label>
|
||||
{/each}
|
||||
</Field>
|
||||
</ShipItem>
|
||||
|
||||
<style>
|
||||
label {
|
||||
display: inline;
|
||||
margin-right: 1em;
|
||||
}
|
||||
</style>
|
@ -1,13 +0,0 @@
|
||||
export default {
|
||||
title: 'FTL Drive'
|
||||
};
|
||||
|
||||
import Component from '.';
|
||||
import shipStore from '../../stores/ship.js';
|
||||
|
||||
export const basic = () => ({
|
||||
Component,
|
||||
props: {
|
||||
ship: shipStore()
|
||||
}
|
||||
});
|
@ -1,28 +0,0 @@
|
||||
<header>
|
||||
<h1>The Docks</h1>
|
||||
<h2>a <a
|
||||
href="https://shop.groundzerogames.co.uk/rules.html">Full Thrust</a> ship builder</h2>
|
||||
</header>
|
||||
|
||||
<style>
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
width: var(--main-width);
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
h1, h2 {
|
||||
font-family: Faktos;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
text-align: right;
|
||||
flex: 1;
|
||||
padding-left: 2em;
|
||||
font-size: var(--font-scale-12);
|
||||
}
|
||||
</style>
|
@ -1,24 +0,0 @@
|
||||
<Field label={ `layer ${layer}` }>
|
||||
<input type="number" min="0" bind:value={rating} />
|
||||
</Field>
|
||||
|
||||
|
||||
<script>
|
||||
import { getContext} from 'svelte';
|
||||
|
||||
import Field from '$lib/components/Field/index.svelte';
|
||||
|
||||
export let layer = 1;
|
||||
export let rating = 0;
|
||||
|
||||
const ship = getContext('ship');
|
||||
|
||||
$: ship?.dispatch_action( 'set_armour_layer', {layer,rating} );
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
input {
|
||||
width: 5em;
|
||||
}
|
||||
</style>
|
@ -1,56 +0,0 @@
|
||||
<ShipItem {cost} {mass} >
|
||||
|
||||
<div>
|
||||
|
||||
<div class="nbr_layers">
|
||||
<Field label="armour layers">
|
||||
<input type="number" min="0" bind:value={nbr_layers} />
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
<div class="layers">
|
||||
{#each armour as layer ( layer.layer )}
|
||||
<Layer {...layer} on:ship_change/>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</ShipItem>
|
||||
|
||||
<script>
|
||||
import { createEventDispatcher} from 'svelte';
|
||||
|
||||
import ShipItem from '$lib/components/ShipItem/index.svelte';
|
||||
import Field from '$lib/components/Field/index.svelte';
|
||||
import Layer from './Layer/index.svelte';
|
||||
import dux from '$lib/dux/structure/armour';
|
||||
import _ from 'lodash';
|
||||
|
||||
export let armour = [];
|
||||
export let cost = 0;
|
||||
export let mass = 0;
|
||||
|
||||
$: cost = _.sum( _.map( armour, 'cost' ) );
|
||||
$: mass = _.sum( _.map( armour, 'mass' ) );
|
||||
|
||||
let nbr_layers = armour.length;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
$: dispatch( 'ship_change', dux.actions.set_armour_nbr_layers(nbr_layers) );
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.layers {
|
||||
display: flex;
|
||||
|
||||
}
|
||||
|
||||
input {
|
||||
width: 5em;
|
||||
}
|
||||
|
||||
</style>
|
@ -1,18 +0,0 @@
|
||||
import Armour from './index.svelte';
|
||||
|
||||
export default {
|
||||
title: "Armour",
|
||||
};
|
||||
|
||||
export const basic = () => ({
|
||||
Component: Armour,
|
||||
props: {
|
||||
armour: [
|
||||
{ layer: 1, rating: 12, cost: 1, mass: 2 },
|
||||
{ layer: 2, rating: 12, cost: 1, mass: 2 },
|
||||
]
|
||||
},
|
||||
on: {
|
||||
ship_change: ({detail}) => console.log(detail)
|
||||
}
|
||||
});
|
@ -1,42 +0,0 @@
|
||||
<ShipItem { cost } { mass }>
|
||||
<div>
|
||||
|
||||
<Field label="screens">
|
||||
<input type="number" bind:value={standard} min="0" />
|
||||
</Field>
|
||||
|
||||
<Field label="advanced screens">
|
||||
<input type="number" bind:value={advanced} min="0" />
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
</ShipItem>
|
||||
|
||||
<script>
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
import Section from '$lib/components/Section/index.svelte';
|
||||
import Field from '$lib/components/Field/index.svelte';
|
||||
import ShipItem from '../../ShipItem/index.svelte';
|
||||
|
||||
export let cost = 0;
|
||||
export let mass = 0;
|
||||
export let standard = 0;
|
||||
export let advanced = 0;
|
||||
|
||||
let nbr_regular, nbr_advanced;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
$: dispatch( 'set_screens', { standard, advanced } );
|
||||
</script>
|
||||
|
||||
<style>
|
||||
input {
|
||||
width: 3em;
|
||||
}
|
||||
div {
|
||||
display: flex;
|
||||
gap: 2em;
|
||||
}
|
||||
</style>
|
@ -1,38 +0,0 @@
|
||||
<ShipItem {cost} {mass}>
|
||||
<Field label="streamlining">
|
||||
<div>
|
||||
<label>
|
||||
<input type="radio" bind:group={type} value="none" />
|
||||
none</label>
|
||||
<label>
|
||||
|
||||
<input type="radio" bind:group={type} value="partial" />
|
||||
partial</label>
|
||||
<label>
|
||||
<input type="radio" bind:group={type} value="full" />
|
||||
full</label>
|
||||
</div>
|
||||
</Field>
|
||||
</ShipItem>
|
||||
|
||||
<script>
|
||||
import ShipItem from '$lib/components/ShipItem/index.svelte';
|
||||
import Field from '$lib/components/Field/index.svelte';
|
||||
|
||||
import {getContext } from 'svelte';
|
||||
|
||||
export let type = 'none';
|
||||
export let cost = 0;
|
||||
export let mass = 0;
|
||||
export let ship = getContext('ship');
|
||||
|
||||
$: ship?.dispatch_action( 'set_streamlining', type);
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div { display: flex }
|
||||
label {
|
||||
margin-left: 1em;
|
||||
}
|
||||
</style>
|
@ -1,51 +0,0 @@
|
||||
<Section label="hull">
|
||||
|
||||
<ShipItem {cost} {mass} >
|
||||
<Field label="integrity">
|
||||
<input
|
||||
bind:value={rating}
|
||||
type="number" {min} {max} />
|
||||
</Field>
|
||||
</ShipItem>
|
||||
|
||||
|
||||
<Screens {...screens} on:set_screens />
|
||||
|
||||
<Armour {armour} on:ship_change />
|
||||
|
||||
<Cargo {...cargo} on:set_cargo />
|
||||
|
||||
<Streamlining {...streamlining} />
|
||||
</Section>
|
||||
|
||||
<script>
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
import Section from '../Section/index.svelte';
|
||||
import Field from '../Field/index.svelte';
|
||||
import ShipItem from '../ShipItem/index.svelte';
|
||||
import Screens from './Screens/index.svelte';
|
||||
import Armour from './Armour/index.svelte';
|
||||
import Cargo from './Cargo/index.svelte';
|
||||
import Streamlining from './Streamlining/index.svelte';
|
||||
|
||||
export let cost, mass, ship_mass, rating, screens, armour = (
|
||||
0, 0, 10, 1, [], []
|
||||
);
|
||||
|
||||
export let cargo = {};
|
||||
export let streamlining = {};
|
||||
|
||||
let min, max;
|
||||
$: min = Math.ceil(ship_mass / 10);
|
||||
$: max = ship_mass;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
$: dispatch( 'change_hull', { rating } );
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
input { width: 5em; }
|
||||
</style>
|
@ -1,35 +0,0 @@
|
||||
<aside transition:fade>
|
||||
<pre><code>{json}</code></pre>
|
||||
</aside>
|
||||
|
||||
<script>
|
||||
export let ship = {};
|
||||
let json;
|
||||
$: json = JSON.stringify(ship,null,2);
|
||||
|
||||
import { fly, fade } from 'svelte/transition';
|
||||
import {createEventDispatcher} from 'svelte';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
const close = () => dispatch('close');
|
||||
</script>
|
||||
|
||||
<style>
|
||||
pre {
|
||||
font-family: monospace;
|
||||
font-size: var(--font-scale-9);
|
||||
overflow: scroll;
|
||||
height: 90%;
|
||||
|
||||
}
|
||||
div {
|
||||
text-align: right;
|
||||
}
|
||||
aside {
|
||||
|
||||
padding: 1em;
|
||||
border: 3px solid var(--indigo-dye);
|
||||
border-radius: 1em;
|
||||
font-size: var(--font-scale-11);
|
||||
}
|
||||
</style>
|
@ -1,34 +0,0 @@
|
||||
<div class="layers">
|
||||
{#each armour as layer (layer)}
|
||||
<div class="layer">
|
||||
{#each _.range(layer.rating) as i (i) }
|
||||
<div class="cell">
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import _ from 'lodash';
|
||||
|
||||
export let armour = [];
|
||||
|
||||
$: console.log(armour);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.cell {
|
||||
display: inline-block;
|
||||
margin-right: 0.5em;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
border: 1px solid black;
|
||||
border-radius: 0.5em;
|
||||
}
|
||||
.layers {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
</style>
|
@ -1,72 +0,0 @@
|
||||
<div>
|
||||
{#each rows as row,i (i)}
|
||||
<div class="row">
|
||||
{#each row as item,j (j)}
|
||||
<div class="cell">
|
||||
{#if item}
|
||||
<img src="icons/crew-star.svg" alt="crew loss threshold" />
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import { ceil } from '$lib/dux/utils';
|
||||
|
||||
export let ship_mass = 0;
|
||||
export let rating = 0;
|
||||
export let advanced = false;
|
||||
|
||||
let nbr_rows;
|
||||
$: nbr_rows = advanced ? 3 : 4;
|
||||
|
||||
let cells;
|
||||
$: cells = Array(rating).fill(false);
|
||||
|
||||
let dcp;
|
||||
$: dcp= ceil(ship_mass/20);
|
||||
|
||||
$: cells = divide(cells, dcp).map(
|
||||
g => {
|
||||
g[g.length-1] = true;
|
||||
return g;
|
||||
}
|
||||
).flat();
|
||||
|
||||
function divide(list, divider) {
|
||||
if( divider <= 1 ) return [ list ];
|
||||
|
||||
let div = list.length / divider;
|
||||
const mod = list.length % divider;
|
||||
|
||||
if(mod) div++;
|
||||
|
||||
return [
|
||||
list.slice(0,div),
|
||||
...divide( list.slice(div), divider-1 )
|
||||
]
|
||||
}
|
||||
|
||||
let rows = [];
|
||||
$: rows = divide( cells, nbr_rows );
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.row {
|
||||
}
|
||||
.cell {
|
||||
display: inline-block;
|
||||
margin-right: 0.5em;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
border: 1px solid black;
|
||||
}
|
||||
img {
|
||||
width: 1em;
|
||||
}
|
||||
</style>
|
@ -1,23 +0,0 @@
|
||||
import Component from '.';
|
||||
|
||||
export default {
|
||||
title: "printouts/hull/integrity"
|
||||
};
|
||||
|
||||
export const basic = () => ({
|
||||
Component,
|
||||
props: {
|
||||
ship_mass: 50,
|
||||
rating: 14,
|
||||
advanced: false,
|
||||
}
|
||||
});
|
||||
|
||||
export const advanced = () => ({
|
||||
Component,
|
||||
props: {
|
||||
ship_mass: 50,
|
||||
rating: 14,
|
||||
advanced: true,
|
||||
}
|
||||
});
|
@ -1,44 +0,0 @@
|
||||
<h1>ship name: <div class="fill"></div> </h1>
|
||||
|
||||
<div class="details">
|
||||
<h2>{ship_class}-class, {ship_type}</h2>
|
||||
<div class="reqs">
|
||||
<Cost {cost} />
|
||||
|
||||
<Mass {mass} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import Cost from '../../../Cost.svelte';
|
||||
import Mass from '$lib/components/Mass.svelte';
|
||||
|
||||
export let ship_class;
|
||||
export let ship_type;
|
||||
export let cost, mass = ( 0, 0 );
|
||||
</script>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
font-size: var(--font-scale-8);
|
||||
}
|
||||
h2 {
|
||||
font-size: var(--font-scale-7);
|
||||
flex: 1;
|
||||
}
|
||||
.fill {
|
||||
margin-left: 0.5em;
|
||||
display: inline-block;
|
||||
flex: 1;
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
.details {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
.reqs {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
@ -1,13 +0,0 @@
|
||||
import Component from '.';
|
||||
|
||||
export default {
|
||||
title: "printouts/main_systems"
|
||||
};
|
||||
|
||||
export const basic = () => ({
|
||||
Component,
|
||||
props: {
|
||||
ftl: 'standard',
|
||||
engine: 4,
|
||||
}
|
||||
})
|
@ -1,33 +0,0 @@
|
||||
import Component from '.';
|
||||
|
||||
export default {
|
||||
title: "printouts/weapons"
|
||||
};
|
||||
|
||||
export const basic = () => ({
|
||||
Component,
|
||||
props: {
|
||||
"weapons": [
|
||||
{
|
||||
"weapon_type": "submunition",
|
||||
"arcs": [
|
||||
"F"
|
||||
],
|
||||
"mass": 1,
|
||||
"cost": 3,
|
||||
"id": 1
|
||||
},
|
||||
{
|
||||
"weapon_type": "beam",
|
||||
"weapon_class": "2",
|
||||
"arcs": [
|
||||
"A",
|
||||
"AS",
|
||||
"FS"
|
||||
],
|
||||
"mass": 2,
|
||||
"cost": 6,
|
||||
"id": 2
|
||||
}, ]
|
||||
}
|
||||
})
|
@ -1,53 +0,0 @@
|
||||
<aside class="ship-sheet" transition:fade>
|
||||
<Identification {...ship.general} />
|
||||
|
||||
<Weapons weapons={ship.weaponry.weapons} />
|
||||
|
||||
<div class="section-2">
|
||||
<Hull structure={ship.structure}
|
||||
ship_mass={ship.general.mass} />
|
||||
|
||||
<Systems
|
||||
firecons={ship.weaponry.firecons.nbr}
|
||||
screens={ship.structure.screens}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<MainSystems
|
||||
ftl={ship.ftl.type}
|
||||
engine={ship.engine.rating}
|
||||
/>
|
||||
|
||||
</aside>
|
||||
|
||||
<script>
|
||||
import _ from 'lodash';
|
||||
|
||||
import Identification from './Identification/index.svelte';
|
||||
import MainSystems from './MainSystems/index.svelte';
|
||||
import Hull from './Hull/index.svelte';
|
||||
import Weapons from './Weapons/index.svelte';
|
||||
import Systems from './Systems/index.svelte';
|
||||
|
||||
export let ship;
|
||||
|
||||
import { fly, fade } from 'svelte/transition';
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.ship-sheet {
|
||||
width: 4.25in;
|
||||
height: 5.5in;
|
||||
border: 1px solid black;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.section-2 {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
@ -1,114 +0,0 @@
|
||||
export default {
|
||||
"ftl": {
|
||||
"mass": 0,
|
||||
"cost": 0,
|
||||
"type": "standard"
|
||||
},
|
||||
"engine": {
|
||||
"mass": 40,
|
||||
"cost": 80,
|
||||
"rating": 6,
|
||||
"advanced": false
|
||||
},
|
||||
"general": {
|
||||
"ship_class": "Deviant",
|
||||
"name": "",
|
||||
"ship_type": "Battleship",
|
||||
"mass": 132,
|
||||
"used_mass": 131,
|
||||
"cost": 415
|
||||
},
|
||||
"weaponry": {
|
||||
"firecons": {
|
||||
"nbr": 5,
|
||||
"mass": 5,
|
||||
"cost": 20
|
||||
},
|
||||
"weapons": [
|
||||
{
|
||||
"weapon_type": "submunition",
|
||||
"arcs": [
|
||||
"F"
|
||||
],
|
||||
"mass": 1,
|
||||
"cost": 3,
|
||||
"id": 1
|
||||
},
|
||||
{
|
||||
"weapon_type": "beam",
|
||||
"weapon_class": "2",
|
||||
"arcs": [
|
||||
"A",
|
||||
"AS",
|
||||
"FS"
|
||||
],
|
||||
"mass": 2,
|
||||
"cost": 6,
|
||||
"id": 2
|
||||
},
|
||||
{
|
||||
"weapon_type": "pds",
|
||||
"mass": 1,
|
||||
"cost": 3,
|
||||
"id": 3
|
||||
}
|
||||
],
|
||||
"adfc": {
|
||||
"rating": 0,
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
}
|
||||
},
|
||||
"structure": {
|
||||
"mass": 0,
|
||||
"cost": 0,
|
||||
"hull": {
|
||||
"rating": 22,
|
||||
"advanced": false,
|
||||
"cost": 44,
|
||||
"mass": 22
|
||||
},
|
||||
"screens": {
|
||||
"standard": 2,
|
||||
"advanced": 1,
|
||||
"cost": 105,
|
||||
"mass": 35
|
||||
},
|
||||
"armour": [
|
||||
{
|
||||
"layer": 1,
|
||||
"rating": 7,
|
||||
"cost": 14,
|
||||
"mass": 14
|
||||
},
|
||||
{
|
||||
"layer": 2,
|
||||
"rating": 2,
|
||||
"cost": 8,
|
||||
"mass": 4
|
||||
},
|
||||
{
|
||||
"layer": 3,
|
||||
"rating": 0,
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"cargo": {
|
||||
"space": 7,
|
||||
"cost": 0,
|
||||
"mass": 7
|
||||
},
|
||||
"streamlining": {
|
||||
"type": "none",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
"carrier": {
|
||||
"bays": 0,
|
||||
"cost": 0,
|
||||
"mass": 0,
|
||||
"squadrons": []
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
import Print from './index.svelte';
|
||||
import sample from './sample';
|
||||
|
||||
export default {
|
||||
title: "printouts"
|
||||
};
|
||||
|
||||
export const basic = () => ({
|
||||
Component: Print,
|
||||
props: {
|
||||
ship: sample
|
||||
}
|
||||
});
|
@ -1,18 +0,0 @@
|
||||
|
||||
<Section label="propulsion">
|
||||
|
||||
<Engine {...engine} on:change_engine />
|
||||
|
||||
<Ftl {...ftl} on:change_ftl />
|
||||
|
||||
</Section>
|
||||
|
||||
<script>
|
||||
import Ftl from '../Ftl/index.svelte';
|
||||
import Engine from '../Engine/index.svelte';
|
||||
import Section from '../Section/index.svelte';
|
||||
|
||||
export let ftl = {};
|
||||
export let engine = {};
|
||||
|
||||
</script>
|
@ -1,47 +0,0 @@
|
||||
<div>
|
||||
<Field label="ship class" value={general.ship_class}
|
||||
on:change={change_class} />
|
||||
|
||||
<Field label="ship type">
|
||||
<select value={ship_type} on:change={change_ship_type}>
|
||||
{#each ship_types as type (type)}
|
||||
<option>{type}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import { getContext } from 'svelte';
|
||||
|
||||
import Field from '$lib/components/Field/index.svelte';
|
||||
import { candidate_ship_types } from '../../dux/ship_types';
|
||||
|
||||
export let ship = getContext('ship');
|
||||
let general;
|
||||
$: general = $ship.general;
|
||||
|
||||
const change_class = (event) => ship.dispatch(
|
||||
ship.actions.set_ship_class(event.target.value)
|
||||
);
|
||||
|
||||
let ship_type;
|
||||
$: ship_type = $ship.general.ship_type;
|
||||
|
||||
const change_ship_type = ({ target: {value}}) =>
|
||||
ship.dispatch.set_ship_type(value);
|
||||
|
||||
let ship_types;
|
||||
$: ship_types = candidate_ship_types($ship.general.mass,$ship.carrier.bays>0).map(
|
||||
({name}) => name
|
||||
);
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div {
|
||||
display: flex;
|
||||
align-items: end;
|
||||
gap: 2em;
|
||||
}
|
||||
</style>
|
@ -1,32 +0,0 @@
|
||||
|
||||
<svg width="{size}px" height="{size}px">
|
||||
{#each all_arcs as arc (arc)}
|
||||
<Arc {arc} radius={size/2}
|
||||
active={selected.includes(arc)}
|
||||
on:click={()=>click_arc(arc)}
|
||||
/>
|
||||
{/each}
|
||||
<circle cx="50%" cy="50%" r={size /3} />
|
||||
<slot />
|
||||
</svg>
|
||||
|
||||
<script>
|
||||
import Arc from '../../Weapons/Arc.svelte';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
const all_arcs = [ 'FS', 'F', 'FP', 'AP', 'A', 'AS' ];
|
||||
|
||||
export let selected = [];
|
||||
export let size = 60;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
const click_arc = arc => dispatch('click_arc',arc);
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
circle {
|
||||
fill: white;
|
||||
}
|
||||
</style>
|
Before Width: | Height: | Size: 637 B |
@ -1,37 +0,0 @@
|
||||
<label> needle weapon</label>
|
||||
<Arcs selected={arcs} on:click_arc={({detail}) => click_arc(detail)} />
|
||||
|
||||
<script>
|
||||
import {getContext } from 'svelte';
|
||||
import Arcs from '../Arcs/index.svelte';
|
||||
import dux from '$lib/dux';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
const all_arcs = [ 'FS', 'F', 'FP', 'AP', 'A', 'AS' ];
|
||||
|
||||
export let arcs = ['F'];
|
||||
export let ship_change = getContext('ship_change') || ( () => {} );
|
||||
|
||||
const click_arc = (arc) => {
|
||||
if( arcs[0] === arc ) return;
|
||||
arcs = [ arc ];
|
||||
}
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
let cache;
|
||||
$: cache = arcs.join(":");
|
||||
|
||||
$: dispatch( 'change', {
|
||||
arcs: cache.split(":"),
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.arc {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -1,37 +0,0 @@
|
||||
<label> submunition pack</label>
|
||||
<Arcs selected={arcs} on:click_arc={({detail}) => click_arc(detail)} />
|
||||
|
||||
<script>
|
||||
import {getContext } from 'svelte';
|
||||
import Arcs from '../Arcs/index.svelte';
|
||||
import dux from '$lib/dux';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
const all_arcs = [ 'FS', 'F', 'FP', 'AP', 'A', 'AS' ];
|
||||
|
||||
export let arcs = ['F'];
|
||||
export let ship_change = getContext('ship_change') || ( () => {} );
|
||||
|
||||
const click_arc = (arc) => {
|
||||
if( arcs[0] === arc ) return;
|
||||
arcs = [ arc ];
|
||||
}
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
let cache;
|
||||
$: cache = arcs.join(":");
|
||||
|
||||
$: dispatch( 'change', {
|
||||
arcs: cache.split(":"),
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.arc {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -1,202 +0,0 @@
|
||||
<input class="add-weapon button small blue" type="button" value="add"
|
||||
on:click={add} />
|
||||
|
||||
<div class="weapon">
|
||||
|
||||
<select bind:value={weapon_type}>
|
||||
<option>beam</option>
|
||||
</select>
|
||||
|
||||
<select bind:value={weapon_class}>
|
||||
<option>1</option>
|
||||
<option>2</option>
|
||||
<option>3</option>
|
||||
<option>4</option>
|
||||
</select>
|
||||
|
||||
<select bind:value={nbr_arcs}>
|
||||
{#each arc_options[weapon_class] as opt (opt)}
|
||||
<option>{opt}</option>
|
||||
{/each}
|
||||
</select>
|
||||
|
||||
<svg width="60px" height="60px">
|
||||
{#each arcs as arc (arc)}
|
||||
<Arc {arc} radius={30}
|
||||
active={selected_arc[arc]}
|
||||
on:click={()=>click_arc(arc)}
|
||||
/>
|
||||
{/each}
|
||||
<circle cx="30" cy="30" r="15" />
|
||||
|
||||
|
||||
</svg>
|
||||
|
||||
<div>{weapon.cost}</div>
|
||||
<div>{weapon.mass}</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let weapon_type = 'beam';
|
||||
let weapon_class = 1;
|
||||
let nbr_arcs = 6;
|
||||
$: nbr_arcs = arc_options[weapon_class][0];
|
||||
|
||||
import Arc from './Arc.svelte';
|
||||
import { weapon_cost_mass } from '../../dux/weapons/rules.js';
|
||||
|
||||
const arcs = [
|
||||
'FS', 'F', 'FP', 'AP', 'A', 'AS'
|
||||
];
|
||||
|
||||
import _ from 'lodash';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
let arc_options = {
|
||||
1: [ 6],
|
||||
2: [ 3, 6 ],
|
||||
3: [ 1, 2, 3, 4, 5, 6, 'broadside' ],
|
||||
4: [ 1, 2, 3, 4, 5, 6, 'broadside' ]
|
||||
};
|
||||
|
||||
let selected_arc = Object.fromEntries(
|
||||
arcs.map( arc => [ arc, false ] )
|
||||
);
|
||||
|
||||
const nbr_selected_arcs = () => Object.values(selected_arc).filter(
|
||||
x => x ).length;
|
||||
|
||||
$: if ( nbr_selected_arcs() !== nbr_arcs ) {
|
||||
if( nbr_arcs === 'broadside' ) {
|
||||
const new_arcs = {};
|
||||
arcs.forEach( arc => new_arcs[arc] = true );
|
||||
new_arcs.A = false;
|
||||
new_arcs.F = false;
|
||||
selected_arc = new_arcs;
|
||||
}
|
||||
else{
|
||||
|
||||
let first_index = arcs.findIndex( arc => selected_arc[arc] );
|
||||
if( first_index === -1 ) first_index = 0;
|
||||
|
||||
const new_arcs = {};
|
||||
arcs.forEach( arc => new_arcs[arc] = false );
|
||||
|
||||
_.range(nbr_arcs).forEach( i => {
|
||||
new_arcs[ arcs[first_index] ] = true;
|
||||
first_index = ( first_index + 1 ) % arcs.length;
|
||||
});
|
||||
|
||||
selected_arc = new_arcs;
|
||||
}
|
||||
}
|
||||
|
||||
const click_arc = (first_arc) => {
|
||||
if( nbr_arcs === 'broadside' ) return;
|
||||
|
||||
let first_index = arcs.findIndex( arc => arc === first_arc );
|
||||
|
||||
const new_arcs = {};
|
||||
arcs.forEach( arc => new_arcs[arc] = false );
|
||||
|
||||
_.range(nbr_arcs).forEach( i => {
|
||||
console.log(first_index);
|
||||
console.log(selected_arc);
|
||||
new_arcs[ arcs[first_index] ] = true;
|
||||
first_index = ( first_index + 1 ) % arcs.length;
|
||||
});
|
||||
|
||||
selected_arc = new_arcs;
|
||||
|
||||
}
|
||||
|
||||
let weapon = {};
|
||||
$: weapon= {
|
||||
weapon_type,
|
||||
weapon_class,
|
||||
arcs,
|
||||
...weapon_cost_mass({ weapon_type, weapon_class, arcs: arcs.filter(
|
||||
arc => selected_arc[arc]
|
||||
) })
|
||||
};
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
const add = () => {
|
||||
dispatch('add_weapon', weapon);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
.weapon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.weapon > * {
|
||||
margin-right: 2em;
|
||||
}
|
||||
|
||||
.arcs {
|
||||
display: grid;
|
||||
grid-template-rows: 1fr 1fr 1fr 1fr;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
width: 6em;
|
||||
}
|
||||
|
||||
|
||||
.arc input {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
|
||||
.arc.F {
|
||||
grid-column: 2 / span 2;
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
.arc.FS {
|
||||
grid-column: 1;
|
||||
grid-row: 1 / span 2;
|
||||
}
|
||||
|
||||
.arc.FP {
|
||||
grid-column: 4;
|
||||
grid-row: 1 / span 2;
|
||||
}
|
||||
|
||||
.arc.AS {
|
||||
grid-column: 1;
|
||||
grid-row: 3 / span 2;
|
||||
}
|
||||
|
||||
.arc.AP {
|
||||
grid-column: 4;
|
||||
grid-row: 3 / span 2;
|
||||
}
|
||||
|
||||
.arc.A {
|
||||
grid-column: 2 / span 2;
|
||||
grid-row: 4;
|
||||
}
|
||||
|
||||
.arc {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.add-weapon {
|
||||
display: block;
|
||||
}
|
||||
|
||||
circle {
|
||||
fill: white;
|
||||
}
|
||||
|
||||
</style>
|
@ -1,50 +0,0 @@
|
||||
<script>
|
||||
export let arc;
|
||||
export let radius;
|
||||
export let active = false;
|
||||
|
||||
const rotation = {
|
||||
F: 0,
|
||||
FS: 300,
|
||||
AS: 240,
|
||||
A: 180,
|
||||
AP: 120,
|
||||
FP: 60,
|
||||
};
|
||||
|
||||
let y, x_delta;
|
||||
$: y = Math.round( radius * ( 1 - Math.sin(60/180*Math.PI) ) );
|
||||
$: x_delta = Math.round( radius*Math.cos(60/180*Math.PI) );
|
||||
|
||||
let path;
|
||||
$: path = `M ${radius},${radius} L ${radius-x_delta},${y} A ${radius},${radius} 0 0 1 ${radius+x_delta},${y} Z`;
|
||||
|
||||
let transform;
|
||||
$: transform = `rotate(${rotation[arc]},${radius},${radius})`
|
||||
|
||||
</script>
|
||||
|
||||
<g { transform }>
|
||||
<path d={path} class:active on:click />
|
||||
</g>
|
||||
|
||||
<style>
|
||||
path {
|
||||
fill: lightgrey;
|
||||
stroke: white;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
|
||||
path:hover {
|
||||
fill: pink;
|
||||
}
|
||||
|
||||
path.active:hover {
|
||||
fill: pink;
|
||||
}
|
||||
|
||||
path.active {
|
||||
fill: #313131;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,10 +0,0 @@
|
||||
import AddWeapon from './Add.svelte';
|
||||
|
||||
export default {
|
||||
title: "add weapon",
|
||||
};
|
||||
|
||||
export const beam = () => ({
|
||||
Component: AddWeapon,
|
||||
});
|
||||
|
123
src/dux/index.js
@ -5,15 +5,15 @@ import { createSelector } from "reselect";
|
||||
|
||||
import ftl from "./ftl";
|
||||
import engine, { calc_drive_reqs } from "./engine";
|
||||
import weaponry from './weaponry';
|
||||
import weaponry from "./weaponry";
|
||||
import { calc_ftl_reqs } from "./ftl/rules";
|
||||
import { calc_ship_req } from "./utils";
|
||||
import { candidate_ship_types } from './ship_types';
|
||||
import structure from './structure';
|
||||
import cargo from './cargo';
|
||||
import streamlining from './streamlining';
|
||||
import carrier from './carrier';
|
||||
import { ceil } from './utils';
|
||||
import { candidate_ship_types } from "./ship_types";
|
||||
import structure from "./structure";
|
||||
import cargo from "./cargo";
|
||||
import streamlining from "./streamlining";
|
||||
import carrier from "./carrier";
|
||||
import { ceil } from "./utils";
|
||||
|
||||
const set_ship_mass = action("set_ship_mass", payload());
|
||||
const set_name = action("set_name", payload());
|
||||
@ -21,9 +21,9 @@ const set_name = action("set_name", payload());
|
||||
const set_ship_reqs = action("set_ship_reqs", payload());
|
||||
const set_hull = action("set_hull", payload());
|
||||
|
||||
const set_ship_type = action('set_ship_type',payload());
|
||||
const set_ship_type = action("set_ship_type", payload());
|
||||
|
||||
const reset = action('reset' );
|
||||
const reset = action("reset");
|
||||
|
||||
const initial = {
|
||||
general: {
|
||||
@ -34,18 +34,16 @@ const initial = {
|
||||
used_mass: 0,
|
||||
cost: 10,
|
||||
},
|
||||
};
|
||||
|
||||
console.log(Updux);
|
||||
};
|
||||
|
||||
const dux = new Updux({
|
||||
subduxes: { ftl, engine, weaponry, structure, cargo, streamlining, carrier },
|
||||
initial
|
||||
initial,
|
||||
});
|
||||
|
||||
dux.addMutation( reset, () => () => initial );
|
||||
dux.addMutation(reset, () => () => initial);
|
||||
|
||||
dux.addMutation(set_hull, ({rating}) => (state) => {
|
||||
dux.addMutation(set_hull, ({ rating }) => (state) => {
|
||||
return u.updateIn("structure.hull", {
|
||||
cost: 2 * rating,
|
||||
rating,
|
||||
@ -55,8 +53,8 @@ dux.addMutation(set_hull, ({rating}) => (state) => {
|
||||
dux.addMutation(set_ship_mass, (mass) => u.updateIn("general", { mass }));
|
||||
dux.addMutation(set_name, (name) => u.updateIn("general", { name }));
|
||||
|
||||
dux.addMutation( action('set_ship_class',payload() ),
|
||||
ship_class => u.updateIn('general',{ship_class})
|
||||
dux.addMutation(action("set_ship_class", payload()), (ship_class) =>
|
||||
u.updateIn("general", { ship_class })
|
||||
);
|
||||
|
||||
dux.addMutation(set_ship_reqs, ({ cost, mass: used_mass }) =>
|
||||
@ -68,73 +66,54 @@ dux.addSubscription((store) =>
|
||||
createSelector(calc_ship_req, (reqs) => store.dispatch(set_ship_reqs(reqs)))
|
||||
);
|
||||
|
||||
|
||||
dux.addSubscription((store) =>
|
||||
createSelector(
|
||||
store => store.general.mass,
|
||||
store => store.streamlining.type,
|
||||
(ship_mass, streamlining ) => {
|
||||
const mass = ceil( ship_mass * (
|
||||
streamlining === 'none' ? 0
|
||||
: streamlining === 'partial' ? 5 : 10
|
||||
) / 100 );
|
||||
const cost = 2 * mass;
|
||||
(store) => store.general.mass,
|
||||
(store) => store.general.ship_type,
|
||||
(store) => store.carrier.bays,
|
||||
(mass, type, bays) => {
|
||||
console.log({ bays });
|
||||
const candidates = candidate_ship_types(mass, bays > 0);
|
||||
|
||||
store.dispatch( dux.actions.set_streamlining_cost_mass({cost,mass}) );
|
||||
console.log({ candidates });
|
||||
if (candidates.length === 0) return;
|
||||
|
||||
if (candidates.find(({ name }) => name === type)) return;
|
||||
|
||||
store.dispatch(store.actions.set_ship_type(candidates[0].name));
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
dux.addSubscription((store) =>
|
||||
createSelector(
|
||||
store => store.general.mass,
|
||||
store => store.general.ship_type,
|
||||
store => store.carrier.bays,
|
||||
(mass,type,bays) => {
|
||||
console.log({bays});
|
||||
const candidates = candidate_ship_types(mass,bays > 0);
|
||||
|
||||
console.log({candidates});
|
||||
if( candidates.length === 0 ) return;
|
||||
|
||||
if( candidates.find( ({name}) => name === type ) ) return;
|
||||
|
||||
store.dispatch(
|
||||
store.actions.set_ship_type(
|
||||
candidates[0].name
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
dux.addMutation(set_ship_type, type => u.updateIn('general.ship_type',type) );
|
||||
dux.addMutation(set_ship_type, (type) => u.updateIn("general.ship_type", type));
|
||||
|
||||
dux.addSubscription((store) =>
|
||||
createSelector(
|
||||
[(ship) => ship.general.mass, (ship) => ship.ftl.type],
|
||||
(ship_mass, type) =>
|
||||
store.dispatch(ftl.actions.set_ftl_reqs(calc_ftl_reqs(type,ship_mass)))
|
||||
store.dispatch(ftl.actions.set_ftl_reqs(calc_ftl_reqs(type, ship_mass)))
|
||||
)
|
||||
);
|
||||
|
||||
dux.addSubscription( store => createSelector(
|
||||
ship => ship.general.mass,
|
||||
ship => ship.structure.screens.standard,
|
||||
ship => ship.structure.screens.advanced,
|
||||
(mass,standard,advanced) => {
|
||||
console.log({
|
||||
mass, standard, advanced
|
||||
})
|
||||
const standard_mass = standard * Math.max(3,ceil( 0.05 * mass ));
|
||||
const advanced_mass = advanced * Math.max(4,ceil( 0.075 * mass ));
|
||||
dux.addSubscription((store) =>
|
||||
createSelector(
|
||||
(ship) => ship.general.mass,
|
||||
(ship) => ship.structure.screens.standard,
|
||||
(ship) => ship.structure.screens.advanced,
|
||||
(mass, standard, advanced) => {
|
||||
const standard_mass = standard * Math.max(3, ceil(0.05 * mass));
|
||||
const advanced_mass = advanced * Math.max(4, ceil(0.075 * mass));
|
||||
|
||||
store.dispatch( dux.actions.set_screens_reqs({
|
||||
store.dispatch(
|
||||
dux.actions.set_screens_reqs({
|
||||
mass: standard_mass + advanced_mass,
|
||||
cost: 3 * standard_mass + 4 * advanced_mass
|
||||
}));
|
||||
cost: 3 * standard_mass + 4 * advanced_mass,
|
||||
})
|
||||
);
|
||||
}
|
||||
));
|
||||
)
|
||||
);
|
||||
|
||||
dux.addSubscription((store) =>
|
||||
createSelector(
|
||||
@ -150,18 +129,6 @@ dux.addSubscription((store) =>
|
||||
)
|
||||
);
|
||||
|
||||
const calc_firecons_reqs = (nbr) => ({
|
||||
cost: 4 * nbr,
|
||||
mass: nbr,
|
||||
});
|
||||
|
||||
const set_firecons = action("set_firecons", payload());
|
||||
dux.addMutation(set_firecons, (nbr) =>
|
||||
u.updateIn("weaponry.firecons", {
|
||||
nbr,
|
||||
...calc_firecons_reqs(nbr),
|
||||
})
|
||||
);
|
||||
|
||||
export default dux.asDux;
|
||||
|
||||
|
@ -1,18 +0,0 @@
|
||||
import Updux from "updux";
|
||||
import { action, payload } from "ts-action";
|
||||
import u from "@yanick/updeep";
|
||||
import { createSelector } from "reselect";
|
||||
|
||||
const dux = new Updux({
|
||||
initial: {
|
||||
standard: 0, advanced: 0, cost: 0, mass: 0,
|
||||
}
|
||||
});
|
||||
|
||||
const set_screens = action('set_screens', payload() );
|
||||
dux.addMutation(set_screens, payload => u.update(payload) );
|
||||
|
||||
const set_screens_reqs = action('set_screens_reqs', payload() );
|
||||
dux.addMutation(set_screens_reqs, payload => u.update(payload) );
|
||||
|
||||
export default dux.asDux;
|
@ -1,17 +0,0 @@
|
||||
import Updux from "updux";
|
||||
import { action, payload } from "ts-action";
|
||||
import u from "@yanick/updeep";
|
||||
|
||||
const dux = new Updux({
|
||||
initial: {
|
||||
rating: 0,
|
||||
cost: 0,
|
||||
mass: 0,
|
||||
},
|
||||
})
|
||||
|
||||
dux.addMutation( action( 'set_adfc', payload() ), rating =>
|
||||
u.update({ rating, mass: 2 * rating, cost: 8 * rating })
|
||||
);
|
||||
|
||||
export default dux.asDux;
|
@ -1,74 +0,0 @@
|
||||
|
||||
export function weapon_cost_mass(weapon){
|
||||
let cost = 0;
|
||||
let mass = 0;
|
||||
|
||||
if( weapon.weapon_type === 'beam' ) {
|
||||
return beam_cost_mass(weapon);
|
||||
}
|
||||
|
||||
if( weapon.weapon_type == 'submunition' ) {
|
||||
return { mass: 1, cost: 3 };
|
||||
}
|
||||
|
||||
if( weapon.weapon_type === 'pds' ) {
|
||||
return { mass: 1, cost: 3 };
|
||||
}
|
||||
|
||||
if( weapon.weapon_type === 'scattergun' ) {
|
||||
return { mass: 1, cost: 4 };
|
||||
}
|
||||
|
||||
if( weapon.weapon_type === 'needle' ) {
|
||||
return { mass: 2, cost: 6 };
|
||||
}
|
||||
|
||||
return { cost, mass };
|
||||
}
|
||||
|
||||
const is_broadside = arcs => {
|
||||
if( arcs.length !== 4 ) return false;
|
||||
|
||||
// that'd be A or F
|
||||
return !arcs.some( a => a.length === 1 );
|
||||
}
|
||||
|
||||
function beam_cost_mass({weapon_class, arcs}) {
|
||||
let mass;
|
||||
if( weapon_class === 1 ) {
|
||||
mass = 1;
|
||||
}
|
||||
|
||||
if( weapon_class == 2 ) {
|
||||
mass = 2 + (arcs.length > 3 ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
if( weapon_class == 3 ) {
|
||||
mass = 4;
|
||||
|
||||
if( is_broadside(arcs) ) {
|
||||
mass += 2;
|
||||
}
|
||||
else {
|
||||
mass += arcs.length - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if( weapon_class == 4 ) {
|
||||
mass = 8;
|
||||
|
||||
if( is_broadside(arcs) ) {
|
||||
mass += 4;
|
||||
}
|
||||
else {
|
||||
mass += 2*(arcs.length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
mass, cost: 3 * mass
|
||||
}
|
||||
|
||||
|
||||
}
|
3
src/global.d.ts
vendored
@ -1,3 +0,0 @@
|
||||
/// <reference types="@sveltejs/kit" />
|
||||
/// <reference types="svelte" />
|
||||
/// <reference types="vite/client" />
|
@ -1,13 +1,5 @@
|
||||
<aside transition:fly={{ x: -800, opacity: 1 }}>
|
||||
<div>
|
||||
<input
|
||||
type="button"
|
||||
class="button small red"
|
||||
value="close"
|
||||
on:click={close}
|
||||
/>
|
||||
</div>
|
||||
<h3>welcome to the docks</h3>
|
||||
<Card>
|
||||
<h2 slot="header">Welcome to the docks</h2>
|
||||
|
||||
<p>
|
||||
This app is a ship builder for the game
|
||||
@ -16,7 +8,7 @@
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The app, beside any exception mentioned here, is trying to follow the
|
||||
The contruction rules are following the
|
||||
<a href="http://members.ozemail.com.au/~laranzu/fullthrust/rules/">
|
||||
Cross Dimensions rules
|
||||
</a>
|
||||
@ -24,9 +16,9 @@
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The app is mostly developed for Firefox. I also check as much as I can
|
||||
that I don't mess things too badly on Chrome. For the other browsers...
|
||||
caveat emptor.
|
||||
The app is mostly developed for Firefox. I also check as much as I can that
|
||||
I don't mess things too badly on Chrome. For the other browsers... caveat
|
||||
emptor.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -35,17 +27,22 @@
|
||||
. Code available on
|
||||
<a href="https://github.com/aotds/aotds-shipyard">Github</a>
|
||||
</p>
|
||||
</aside>
|
||||
<div slot="footer" />
|
||||
</Card>
|
||||
|
||||
<script>
|
||||
import { fly } from "svelte/transition";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import {
|
||||
Modal, Card
|
||||
} from 'svelte-chota';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
const close = () => dispatch("close");
|
||||
</script>
|
||||
|
||||
<style>
|
||||
h2 {
|
||||
margin-bottom: 1em;
|
||||
font-size: var(--font-scale-14);
|
||||
font-family: Faktos;
|
||||
}
|
||||
aside {
|
||||
background-color: rgb(254, 218, 184);
|
||||
position: absolute;
|
||||
@ -68,7 +65,7 @@
|
||||
text-align: center;
|
||||
margin: 0px;
|
||||
}
|
||||
div {
|
||||
text-align: right;
|
||||
}
|
||||
p {
|
||||
margin-left: 2em;
|
||||
}
|
||||
</style>
|
@ -1,10 +1,5 @@
|
||||
<Ribbon />
|
||||
<Header />
|
||||
|
||||
<nav>
|
||||
<button class="button is-danger" type="button" on:click={reset}
|
||||
>reset</button
|
||||
>
|
||||
<button class="button is-danger" type="button" on:click={reset}>reset</button>
|
||||
|
||||
<div class="spacer" />
|
||||
|
||||
@ -18,9 +13,7 @@
|
||||
<button class="button" on:click={() => set_output("json")}>json</button>
|
||||
</p>
|
||||
<p class="control">
|
||||
<button class="button" on:click={() => set_output("print")}
|
||||
>print</button
|
||||
>
|
||||
<button class="button" on:click={() => set_output("print")}>print</button>
|
||||
</p>
|
||||
</div>
|
||||
</nav>
|
||||
@ -68,12 +61,7 @@
|
||||
<AddWeapon />
|
||||
|
||||
{#each weapons as weapon (weapon.id)}
|
||||
<Weapon
|
||||
{weapon}
|
||||
id={weapon.id}
|
||||
cost={weapon.cost}
|
||||
mass={weapon.mass}
|
||||
/>
|
||||
<Weapon {weapon} id={weapon.id} cost={weapon.cost} mass={weapon.mass} />
|
||||
{/each}
|
||||
</Section>
|
||||
|
||||
@ -89,7 +77,6 @@
|
||||
<script>
|
||||
import { setContext } from "svelte";
|
||||
|
||||
import Header from "./Header.svelte";
|
||||
import Ribbon from "./Ribbon.svelte";
|
||||
import shipStore from "../stores/ship";
|
||||
import OutputJson from "./Output/Json.svelte";
|
53
src/lib/components/App.svelte
Normal file
@ -0,0 +1,53 @@
|
||||
<svelte:head>
|
||||
<meta name="viewport" content="width=960" />
|
||||
</svelte:head>
|
||||
|
||||
<main>
|
||||
|
||||
<Ribbon />
|
||||
<Header on:changeTab={({ detail }) => activeTab = detail}/>
|
||||
|
||||
<div class:hide={activeTab !== 'editor'}>
|
||||
<ShipEdit />
|
||||
</div>
|
||||
<div class:hide={activeTab !== 'json'}>
|
||||
<JsonOutput />
|
||||
</div>
|
||||
<div class:hide={activeTab !== 'print'}>
|
||||
<PrintOutput ship={$state}/>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<script>
|
||||
import { getContext } from 'svelte';
|
||||
import { Modal, Card, Nav } from "svelte-chota";
|
||||
|
||||
import Ribbon from "./Ribbon.svelte";
|
||||
import Header from "./Header.svelte";
|
||||
import ShipEdit from "./ShipEdit/index.svelte";
|
||||
import About from "./About.svelte";
|
||||
import JsonOutput from './Output/Json.svelte';
|
||||
import PrintOutput from './Output/Print/index.svelte';
|
||||
|
||||
let activeTab = 'editor';
|
||||
$: console.log(activeTab);
|
||||
|
||||
const {state} = getContext('ship');
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.nav {
|
||||
width: var(--main-width);
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
main {
|
||||
width: var(--main-width);
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
</style>
|
14
src/lib/components/Carrier/Carrier.story.svelte
Normal file
@ -0,0 +1,14 @@
|
||||
<Carrier />
|
||||
|
||||
<script>
|
||||
import Carrier from "./index.svelte";
|
||||
|
||||
const props = {
|
||||
bays: 3,
|
||||
squadrons: [
|
||||
{ id: 1, type: "standard", ftl: false, nbr_fighters: 6 },
|
||||
{ id: 2, type: "fast", ftl: false, nbr_fighters: 6 },
|
||||
{ id: 3, type: "none", ftl: false, nbr_fighters: 6 },
|
||||
],
|
||||
};
|
||||
</script>
|
@ -1,3 +1,4 @@
|
||||
<!--
|
||||
<Section label="carrier">
|
||||
<ShipItem {cost} {mass}>
|
||||
<Field label="bays">
|
||||
@ -9,15 +10,18 @@
|
||||
<Squadron {...squad} />
|
||||
{/each}
|
||||
</Section>
|
||||
-->
|
||||
|
||||
Hey!
|
||||
|
||||
<script>
|
||||
import { getContext } from "svelte";
|
||||
|
||||
import Section from "../Section/index.svelte";
|
||||
import Field from "../Field/index.svelte";
|
||||
import ShipItem from "../ShipItem/index.svelte";
|
||||
import Squadron from "./Squadron/index.svelte";
|
||||
import dux from "../../dux/carrier";
|
||||
/* import Section from "../Section/index.svelte"; */
|
||||
/* import Field from "../Field/index.svelte"; */
|
||||
/* import ShipItem from "../ShipItem/index.svelte"; */
|
||||
// import Squadron from "./Squadron/index.svelte";
|
||||
// import dux from "../../dux/carrier";
|
||||
|
||||
export let bays = 0;
|
||||
export let squadrons = [];
|
||||
@ -26,6 +30,5 @@
|
||||
|
||||
export let ship = getContext("ship");
|
||||
|
||||
$: ship?.dispatch_action('set_carrier_bays',bays);
|
||||
|
||||
$: ship?.dispatch_action("set_carrier_bays", bays);
|
||||
</script>
|
20
src/lib/components/Carrier/stories.js
Normal file
@ -0,0 +1,20 @@
|
||||
import { action } from "@storybook/addon-actions";
|
||||
|
||||
import Carrier from "./index.svelte";
|
||||
|
||||
export default {
|
||||
title: "Carrier",
|
||||
};
|
||||
|
||||
export const basic = () => ({
|
||||
Component: Carrier,
|
||||
props: {
|
||||
bays: 3,
|
||||
squadrons: [
|
||||
{ id: 1, type: "standard", ftl: false, nbr_fighters: 6 },
|
||||
{ id: 2, type: "fast", ftl: false, nbr_fighters: 6 },
|
||||
{ id: 3, type: "none", ftl: false, nbr_fighters: 6 },
|
||||
],
|
||||
ship_change: action("ship_change"),
|
||||
},
|
||||
});
|
5
src/lib/components/Cost.story.svelte
Normal file
@ -0,0 +1,5 @@
|
||||
<Cost cost={12} />
|
||||
|
||||
<script>
|
||||
import Cost from "./Cost.svelte";
|
||||
</script>
|
@ -5,5 +5,8 @@
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div:after { content: '\00A4'; margin-left: 0.5em; }
|
||||
div:after {
|
||||
content: "\00A4";
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
</style>
|
29
src/lib/components/CostMass.svelte
Normal file
@ -0,0 +1,29 @@
|
||||
<div class="mass">{mass}</div>
|
||||
<div class="cost">{cost}</div>
|
||||
|
||||
<script>
|
||||
export let mass;
|
||||
export let cost;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.cost {
|
||||
grid-column: 3;
|
||||
}
|
||||
.mass {
|
||||
grid-column: 2;
|
||||
}
|
||||
img {
|
||||
width: 0.75em;
|
||||
}
|
||||
.cost:after {
|
||||
content: "\00A4";
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
.mass:after {
|
||||
content: url("/mass.svg");
|
||||
width: 0.75em;
|
||||
display: inline-block;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
</style>
|
@ -1,5 +1,5 @@
|
||||
<Field label="the label" />
|
||||
|
||||
<script>
|
||||
import Field from './index.svelte';
|
||||
import Field from "./index.svelte";
|
||||
</script>
|
32
src/lib/components/Field/index.svelte
Normal file
@ -0,0 +1,32 @@
|
||||
<div>
|
||||
{#if label}
|
||||
<label>{label}</label>
|
||||
{/if}
|
||||
<slot>
|
||||
<input type="text" {placeholder} bind:value on:change />
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
export let label = "";
|
||||
export let value = "";
|
||||
export let placeholder;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div {
|
||||
font-family: var(--main-font-family);
|
||||
}
|
||||
div > :global(*) {
|
||||
margin-left: 1em;
|
||||
}
|
||||
div > label {
|
||||
margin-left: 0em;
|
||||
}
|
||||
label {
|
||||
font-size: var(--font-scale-8);
|
||||
font-weight: lighter;
|
||||
font-family: Dosis;
|
||||
color: var(--indigo-dye);
|
||||
}
|
||||
</style>
|
12
src/lib/components/Field/stories.js
Normal file
@ -0,0 +1,12 @@
|
||||
import Component from "./index.svelte";
|
||||
import BasicStory from "./BasicStory.svelte";
|
||||
|
||||
import "../../../public/global.css";
|
||||
|
||||
export default {
|
||||
title: "Field",
|
||||
};
|
||||
|
||||
export const basic = () => ({
|
||||
Component: BasicStory,
|
||||
});
|
21
src/lib/components/Firecons.svelte
Normal file
@ -0,0 +1,21 @@
|
||||
<ShipItem {cost} {mass}>
|
||||
<Field label="firecons">
|
||||
<input type="number" class="short" bind:value={nbr} />
|
||||
</Field>
|
||||
</ShipItem>
|
||||
|
||||
<script>
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import ShipItem from "./ShipItem/index.svelte";
|
||||
import Field from "./Field/index.svelte";
|
||||
|
||||
export let nbr,
|
||||
cost,
|
||||
mass = (0, 0, 0);
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
$: dispatch("change_firecons", nbr);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
34
src/lib/components/Ftl/index.svelte
Normal file
@ -0,0 +1,34 @@
|
||||
<ShipItem {mass} {cost}>
|
||||
<Field label="FTL drive">
|
||||
{#each types as t (t)}
|
||||
<label
|
||||
><input type="radio" bind:group={type} value={t} />
|
||||
{t}
|
||||
</label>
|
||||
{/each}
|
||||
</Field>
|
||||
</ShipItem>
|
||||
|
||||
<script>
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
import ShipItem from "../ShipItem/index.svelte";
|
||||
import Field from "../Field/index.svelte";
|
||||
|
||||
export let type = "none";
|
||||
export let cost = 0;
|
||||
export let mass = 0;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
const change = () => dispatch("change_ftl", type);
|
||||
|
||||
const types = ["none", "standard", "advanced"];
|
||||
</script>
|
||||
|
||||
<style>
|
||||
label {
|
||||
display: inline;
|
||||
margin-right: 1em;
|
||||
}
|
||||
</style>
|
13
src/lib/components/Ftl/stories.js
Normal file
@ -0,0 +1,13 @@
|
||||
export default {
|
||||
title: "FTL Drive",
|
||||
};
|
||||
|
||||
import Component from ".";
|
||||
import shipStore from "../../stores/ship.js";
|
||||
|
||||
export const basic = () => ({
|
||||
Component,
|
||||
props: {
|
||||
ship: shipStore(),
|
||||
},
|
||||
});
|
76
src/lib/components/Header.svelte
Normal file
@ -0,0 +1,76 @@
|
||||
<header>
|
||||
<h1>The Docks</h1>
|
||||
<h2>
|
||||
a <a href="https://shop.groundzerogames.co.uk/rules.html"
|
||||
>Full Thrust</a
|
||||
> ship builder
|
||||
</h2>
|
||||
<a on:click|preventDefault={() => (showAbout = true)}>about the app</a>
|
||||
</header>
|
||||
|
||||
<div>
|
||||
<Tabs bind:active={activeTab}>
|
||||
<Tab tabid="editor">editor</Tab>
|
||||
<Tab tabid="json">json view</Tab>
|
||||
<Tab tabid="print">print view</Tab>
|
||||
</Tabs>
|
||||
</div>
|
||||
|
||||
<Modal bind:open={showAbout}>
|
||||
<About />
|
||||
</Modal>
|
||||
|
||||
<script>
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { Modal, Card, Nav, Tab, Tabs } from "svelte-chota";
|
||||
|
||||
import About from "./About.svelte";
|
||||
let showAbout = false;
|
||||
let activeTab = 'editor';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
$: dispatch( 'changeTab', activeTab );
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
header {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
width: var(--main-width);
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
h1,
|
||||
h2 {
|
||||
text-align: left;
|
||||
font-family: Faktos;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: var(--font-scale-15);
|
||||
}
|
||||
h2 {
|
||||
flex: 1;
|
||||
padding-left: 1em;
|
||||
font-size: var(--font-scale-13);
|
||||
}
|
||||
header > a {
|
||||
margin: 0px 2em;
|
||||
font-size: var(--font-scale-10);
|
||||
}
|
||||
div :global(nav) {
|
||||
margin-left: 2em;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
div :global(nav span) {
|
||||
font-weight: bold;
|
||||
font-family: var(--main-font-family);
|
||||
font-size: var(--font-scale-12);
|
||||
margin-right: 1em;
|
||||
padding-bottom: 0.125em !important;
|
||||
}
|
||||
</style>
|
49
src/lib/components/Output/Json.svelte
Normal file
@ -0,0 +1,49 @@
|
||||
<div>
|
||||
<button class="button primary" on:click={handleSave}>save</button>
|
||||
|
||||
<pre><code>{json}</code></pre>
|
||||
</div>
|
||||
|
||||
<a style:display="none" {href} {download} bind:this={fileDownload} />
|
||||
|
||||
<script>
|
||||
export let ship = {};
|
||||
let json;
|
||||
$: json = JSON.stringify(ship, null, 2);
|
||||
|
||||
import { fly, fade } from "svelte/transition";
|
||||
import { createEventDispatcher, getContext } from "svelte";
|
||||
|
||||
const { state } = getContext("ship");
|
||||
|
||||
$: json = JSON.stringify($state, null, 2);
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
const close = () => dispatch("close");
|
||||
|
||||
$: href = "data:text/plain;charset=utf-8," + encodeURIComponent(json);
|
||||
$: download = ($state?.identification?.shipClass ?? "ship") + ".json";
|
||||
|
||||
let fileDownload;
|
||||
|
||||
function handleSave() {
|
||||
fileDownload?.click();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div {
|
||||
position: relative;
|
||||
}
|
||||
button {
|
||||
position: absolute;
|
||||
right: 2em;
|
||||
top: 1em;
|
||||
}
|
||||
pre {
|
||||
font-family: monospace;
|
||||
font-size: var(--font-scale-10);
|
||||
overflow: scroll;
|
||||
height: 90%;
|
||||
}
|
||||
</style>
|
32
src/lib/components/Output/Print/Hull/Armor.svelte
Normal file
@ -0,0 +1,32 @@
|
||||
<div class="layers">
|
||||
{#each armor as layer,i (i)}
|
||||
<div class="layer">
|
||||
{#each Array.from({length: layer}) as j}
|
||||
<div class="cell" />
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import _ from "lodash";
|
||||
|
||||
export let armor = [];
|
||||
console.log(armor)
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.cell {
|
||||
display: inline-block;
|
||||
margin-right: 0.5em;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
border: 1px solid black;
|
||||
border-radius: 0.5em;
|
||||
}
|
||||
.layers {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
</style>
|
22
src/lib/components/Output/Print/Hull/Armour.stories.svelte
Normal file
@ -0,0 +1,22 @@
|
||||
<Meta title="Output/Print/Structure/Armor" component={Armor} argTypes={{
|
||||
armor: {
|
||||
type: 'object',
|
||||
defaultValue: [2,4],
|
||||
}
|
||||
}} />
|
||||
|
||||
<Story name="Primary" args={{}} />
|
||||
|
||||
<Template let:args>
|
||||
<div style="width: 50em">
|
||||
<Armor {...args} />
|
||||
</div>
|
||||
</Template>
|
||||
|
||||
<script>
|
||||
import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
|
||||
|
||||
import Armor from './Armor.svelte';
|
||||
|
||||
|
||||
</script>
|
@ -0,0 +1,20 @@
|
||||
<Meta title="Output/Print/Structure/Integrity" component={Integrity} argTypes={{
|
||||
shipMass: {defaultValue:50},
|
||||
rating: {defaultValue:14},
|
||||
advanced: {defaultValue:false},
|
||||
}} />
|
||||
|
||||
<Story name="Primary" args={{}} />
|
||||
<Story name="Advanced" args={{ advanced: true }} />
|
||||
|
||||
<Template let:args>
|
||||
<div style="width: 50em">
|
||||
<Integrity {...args} />
|
||||
</div>
|
||||
</Template>
|
||||
|
||||
<script>
|
||||
import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
|
||||
|
||||
import Integrity from './index.svelte';
|
||||
</script>
|
66
src/lib/components/Output/Print/Hull/Integrity/index.svelte
Normal file
@ -0,0 +1,66 @@
|
||||
<div>
|
||||
{#each rows as row, i (i)}
|
||||
<div class="row">
|
||||
{#each row as threshold, j (j)}
|
||||
<div class="cell">
|
||||
{#if threshold}
|
||||
<img src="icons/crew-star.svg" alt="crew loss threshold" />
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
export let shipMass = 0;
|
||||
export let rating = 0;
|
||||
export let advanced = false;
|
||||
|
||||
let nbr_rows;
|
||||
$: nbr_rows = advanced ? 3 : 4;
|
||||
|
||||
let cells;
|
||||
$: cells = Array(rating).fill(false);
|
||||
|
||||
let dcp;
|
||||
$: dcp = Math.ceil(shipMass / 20);
|
||||
|
||||
$: cells = divide(cells, dcp)
|
||||
.map((g) => {
|
||||
g[g.length - 1] = true;
|
||||
return g;
|
||||
})
|
||||
.flat();
|
||||
|
||||
function divide(list, divider) {
|
||||
if (divider <= 1) return [list];
|
||||
|
||||
let div = list.length / divider;
|
||||
const mod = list.length % divider;
|
||||
|
||||
if (mod) div++;
|
||||
|
||||
return [list.slice(0, div), ...divide(list.slice(div), divider - 1)];
|
||||
}
|
||||
|
||||
let rows = [];
|
||||
$: rows = divide(cells, nbr_rows);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.row {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
.cell {
|
||||
display: inline-block;
|
||||
margin-right: 0.5em;
|
||||
width: 1.5em;
|
||||
height: 1.5em;
|
||||
border: 1px solid black;
|
||||
}
|
||||
img {
|
||||
width: 1em;
|
||||
margin-left: 0.2em;
|
||||
}
|
||||
</style>
|
23
src/lib/components/Output/Print/Hull/Integrity/stories.js
Normal file
@ -0,0 +1,23 @@
|
||||
import Component from ".";
|
||||
|
||||
export default {
|
||||
title: "printouts/hull/integrity",
|
||||
};
|
||||
|
||||
export const basic = () => ({
|
||||
Component,
|
||||
props: {
|
||||
ship_mass: 50,
|
||||
rating: 14,
|
||||
advanced: false,
|
||||
},
|
||||
});
|
||||
|
||||
export const advanced = () => ({
|
||||
Component,
|
||||
props: {
|
||||
ship_mass: 50,
|
||||
rating: 14,
|
||||
advanced: true,
|
||||
},
|
||||
});
|
@ -8,8 +8,8 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import Integrity from './Integrity/index.svelte';
|
||||
import Armour from './Armour/index.svelte';
|
||||
import Integrity from "./Integrity/index.svelte";
|
||||
import Armour from "./Armor.svelte";
|
||||
|
||||
export let structure = {};
|
||||
export let ship_mass = 0;
|
51
src/lib/components/Output/Print/Identification/index.svelte
Normal file
@ -0,0 +1,51 @@
|
||||
<h1>
|
||||
ship name: <div class="fill" />
|
||||
</h1>
|
||||
|
||||
<div class="details">
|
||||
<h2>
|
||||
{#if shipClass}
|
||||
{shipClass}-class,
|
||||
{/if}
|
||||
{shipType}</h2>
|
||||
<div class="reqs">
|
||||
<Cost cost={cost} />
|
||||
|
||||
<Mass mass={mass} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import Cost from "../../../Cost.svelte";
|
||||
import Mass from "$lib/components/Mass.svelte";
|
||||
|
||||
export let shipClass;
|
||||
export let shipType;
|
||||
export let cost = 0;
|
||||
export let mass = 0;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
font-size: var(--font-scale-8);
|
||||
}
|
||||
h2 {
|
||||
font-size: var(--font-scale-7);
|
||||
flex: 1;
|
||||
}
|
||||
.fill {
|
||||
margin-left: 0.5em;
|
||||
display: inline-block;
|
||||
flex: 1;
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
.details {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
.reqs {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
@ -1,6 +1,5 @@
|
||||
<div class="main_systems">
|
||||
|
||||
{#if ftl !== "none" }
|
||||
{#if ftl !== "none"}
|
||||
<img class="ftl" src="icons/ftl-drive.svg" alt="ftl drive" />
|
||||
{/if}
|
||||
|
||||
@ -8,13 +7,16 @@
|
||||
<div class="thrust">{engine}</div>
|
||||
{/if}
|
||||
|
||||
<img class="internal" src="icons/internal-systems.svg" alt="internal systems"/>
|
||||
</div>
|
||||
<img
|
||||
class="internal"
|
||||
src="icons/internal-systems.svg"
|
||||
alt="internal systems"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
export let ftl = 'none';
|
||||
export let ftl = "none";
|
||||
export let engine = 0;
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@ -27,14 +29,16 @@
|
||||
line-height: 2em;
|
||||
text-align: center;
|
||||
}
|
||||
.main_systems {
|
||||
.main_systems {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1em;
|
||||
justify-content: space-evenly;
|
||||
margin-top: 1em;
|
||||
}
|
||||
img.ftl { height: 2em; }
|
||||
}
|
||||
img.ftl {
|
||||
height: 2em;
|
||||
}
|
||||
img.internal {
|
||||
height: 2em;
|
||||
}
|
13
src/lib/components/Output/Print/MainSystems/stories.js
Normal file
@ -0,0 +1,13 @@
|
||||
import Component from ".";
|
||||
|
||||
export default {
|
||||
title: "printouts/main_systems",
|
||||
};
|
||||
|
||||
export const basic = () => ({
|
||||
Component,
|
||||
props: {
|
||||
ftl: "standard",
|
||||
engine: 4,
|
||||
},
|
||||
});
|
23
src/lib/components/Output/Print/Print.stories.svelte
Normal file
@ -0,0 +1,23 @@
|
||||
<Meta title="Output/Print" component={Print} argTypes={{
|
||||
ship: {
|
||||
type: 'object',
|
||||
defaultValue: sample
|
||||
}
|
||||
}} />
|
||||
|
||||
<Story name="Primary" args={{}} />
|
||||
|
||||
<Template let:args>
|
||||
<div style="width: 50em">
|
||||
<Print ship={sample}/>
|
||||
</div>
|
||||
</Template>
|
||||
|
||||
<script>
|
||||
import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
|
||||
import sample from './sample.js';
|
||||
|
||||
import Print from './index.svelte';
|
||||
</script>
|
@ -0,0 +1,17 @@
|
||||
<Meta title="Output/Print/Systems/Firecons" component={Firecons} argTypes={{
|
||||
firecons: { defaultValue: 2, type: 'number' }
|
||||
}} />
|
||||
|
||||
<Story name="Primary" args={{}} />
|
||||
|
||||
<Template let:args>
|
||||
<div style="width: 50em">
|
||||
<Firecons {...args}/>
|
||||
</div>
|
||||
</Template>
|
||||
|
||||
<script>
|
||||
import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
|
||||
|
||||
import Firecons from './index.svelte';
|
||||
</script>
|
@ -1,11 +1,11 @@
|
||||
<div>
|
||||
{#each _.range(firecons) as firecon}
|
||||
{#each range(1,firecons) as firecon}
|
||||
<img class="firecon" src="icons/firecon.svg" alt="firecon" />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import _ from "lodash";
|
||||
import {range} from "$lib/utils.js";
|
||||
|
||||
export let firecons = 0;
|
||||
</script>
|
@ -0,0 +1,18 @@
|
||||
<Meta title="Output/Print/Systems/Screens" component={Screens} argTypes={{
|
||||
standard: { defaultValue: 3 },
|
||||
advanced: { defaultValue: 3 },
|
||||
}} />
|
||||
|
||||
<Story name="Primary" args={{}} />
|
||||
|
||||
<Template let:args>
|
||||
<div style="width: 50em">
|
||||
<Screens {...args}/>
|
||||
</div>
|
||||
</Template>
|
||||
|
||||
<script>
|
||||
import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
|
||||
|
||||
import Screens from './index.svelte';
|
||||
</script>
|
@ -1,15 +1,14 @@
|
||||
<div>
|
||||
{#each _.range(standard) as i }
|
||||
{#each range(1,standard) as i}
|
||||
<img src="icons/screen.svg" alt="screen" />
|
||||
{/each}
|
||||
{#each _.range(advanced) as i }
|
||||
{#each range(1,advanced) as i}
|
||||
<img src="icons/screen-advanced.svg" alt="advanced screen" />
|
||||
{/each}
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import _ from 'lodash';
|
||||
import {range} from "$lib/utils.js";
|
||||
|
||||
export let standard = 0;
|
||||
export let advanced = 0;
|
@ -1,16 +1,15 @@
|
||||
<div>
|
||||
<Firecons {firecons}/>
|
||||
<Firecons {firecons} />
|
||||
|
||||
<Screens {...screens} />
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import Firecons from './Firecons/index.svelte';
|
||||
import Screens from './Screens/index.svelte';
|
||||
import Firecons from "./Firecons/index.svelte";
|
||||
import Screens from "./Screens/index.svelte";
|
||||
|
||||
export let firecons = 0;
|
||||
export let screens = {};
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@ -23,6 +22,5 @@
|
||||
}
|
||||
div > :global(*) {
|
||||
margin-bottom: 1em;
|
||||
|
||||
}
|
||||
</style>
|
||||
</style>
|