commit first major batch of work
parent
561aa08d8a
commit
2c68f44e88
|
@ -0,0 +1,5 @@
|
|||
node_modules
|
||||
.nyc_output
|
||||
pnpm-lock.yaml
|
||||
public/build
|
||||
public/bundle.*
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
stories: [ '../src/**/*stories.js' ]
|
||||
};
|
144
package.json
144
package.json
|
@ -1,12 +1,136 @@
|
|||
{
|
||||
"name": "shipyard",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
"author": "Yanick Champoux <yanick@babyl.ca>",
|
||||
"dependencies": {
|
||||
"@babel/cli": "^7.10.1",
|
||||
"@babel/core": "^7.10.2",
|
||||
"@babel/node": "^7.10.1",
|
||||
"@material/animation": "^7.0.0",
|
||||
"@material/base": "^7.0.0",
|
||||
"@material/density": "^7.0.0",
|
||||
"@material/feature-targeting": "^7.0.0",
|
||||
"@material/floating-label": "^7.0.0",
|
||||
"@material/line-ripple": "^7.0.0",
|
||||
"@material/notched-outline": "^7.0.0",
|
||||
"@material/ripple": "^7.0.0",
|
||||
"@material/rtl": "^7.0.0",
|
||||
"@material/shape": "^7.0.0",
|
||||
"@material/textfield": "^6.0.0",
|
||||
"@material/theme": "^7.0.0",
|
||||
"@material/typography": "^7.0.0",
|
||||
"@smui/floating-label": "^1.0.0-beta.21",
|
||||
"@smui/line-ripple": "^1.0.0-beta.21",
|
||||
"@smui/notched-outline": "^1.0.0-beta.21",
|
||||
"@smui/textfield": "^1.0.0-beta.21",
|
||||
"@storybook/svelte": "^5.3.19",
|
||||
"babel-loader": "^8.1.0",
|
||||
"css-loader": "^3.6.0",
|
||||
"dart-sass": "^1.25.0",
|
||||
"lodash": "^4.17.15",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
"node-sass": "^4.14.1",
|
||||
"prettier": "2.0.5",
|
||||
"prettier-plugin-svelte": "1.1.0",
|
||||
"redux": "^4.0.5",
|
||||
"reselect": "^4.0.0",
|
||||
"rollup-plugin-css-only": "^2.1.0",
|
||||
"rollup-plugin-postcss": "^3.1.2",
|
||||
"rollup-plugin-scss": "^2.5.0",
|
||||
"sass": "^1.26.9",
|
||||
"sass-loader": "^8.0.2",
|
||||
"sirv-cli": "^0.4.4",
|
||||
"style-loader": "^1.2.1",
|
||||
"svelte-loader": "^2.13.6",
|
||||
"svelte3-redux": "^0.3.0",
|
||||
"ts-action": "^11.0.0",
|
||||
"updeep": "^1.2.0",
|
||||
"updux": "^2.1.0",
|
||||
"webpack": "^4.43.0",
|
||||
"webpack-cli": "^3.3.12",
|
||||
"webpack-dev-server": "^3.11.0"
|
||||
},
|
||||
"description": "Full Thrust ship builder",
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-alias": "^3.1.1",
|
||||
"@rollup/plugin-commonjs": "^12.0.0",
|
||||
"@rollup/plugin-node-resolve": "^8.0.0",
|
||||
"eslint": "7.4.0",
|
||||
"eslint-config-prettier": "6.11.0",
|
||||
"eslint-plugin-babel": "5.3.1",
|
||||
"eslint-plugin-lodash": "^7.1.0",
|
||||
"eslint-plugin-prettier": "3.1.4",
|
||||
"eslint-plugin-svelte3": "2.7.3",
|
||||
"eslint-plugin-you-dont-need-lodash-underscore": "^6.10.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"rollup": "^2.3.4",
|
||||
"rollup-plugin-livereload": "^1.0.0",
|
||||
"rollup-plugin-svelte": "^5.0.3",
|
||||
"rollup-plugin-terser": "^5.1.2",
|
||||
"svelte": "^3.0.0",
|
||||
"svelte-material-ui": "^1.0.0-beta.21",
|
||||
"tap": "^14.10.7"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"env": {
|
||||
"amd": true,
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"prettier",
|
||||
"eslint:recommended",
|
||||
"plugin:you-dont-need-lodash-underscore/compatible",
|
||||
"plugin:lodash/recommended"
|
||||
],
|
||||
"ignorePatterns": [
|
||||
"src/node_modules"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"*.svelte"
|
||||
],
|
||||
"processor": "svelte3/svelte3"
|
||||
}
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaFeatures": {
|
||||
"modules": true
|
||||
},
|
||||
"ecmaVersion": "2020",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"svelte3"
|
||||
],
|
||||
"rules": {
|
||||
"lodash/prefer-lodash-method": "off"
|
||||
}
|
||||
},
|
||||
"keywords": [
|
||||
"game"
|
||||
],
|
||||
"license": "ISC",
|
||||
"main": "index.js",
|
||||
"name": "shipyard",
|
||||
"prettier": {
|
||||
"svelteSortOrder": "markup-scripts-styles",
|
||||
"svelteStrictMode": false
|
||||
},
|
||||
"scripts": {
|
||||
"build": "NODE_ENV=production webpack",
|
||||
"lint": "npm-run-all --parallel \"lint:prettier -- {@}\" \"lint:eslint -- {@}\" --",
|
||||
"lint:eslint": "./scripts/eslint",
|
||||
"lint:eslint:fix": "npm run lint:eslint -- --fix",
|
||||
"lint:fix": "npm-run-all \"lint:eslint:fix -- {@}\" \"lint:prettier:fix -- {@}\" --",
|
||||
"lint:prettier": "./scripts/prettier",
|
||||
"lint:prettier:fix": "npm run lint:prettier -- --fix",
|
||||
"package": "./scripts/merge_package.pl",
|
||||
"start": "webpack-dev-server --open --content-base public",
|
||||
"test": "tap 'src/**test.js' --no-coverage"
|
||||
},
|
||||
"tap": {
|
||||
"coverage": false
|
||||
},
|
||||
"version": "0.0.1"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
---
|
||||
_merge:
|
||||
- version
|
||||
- dependencies
|
||||
- devDependencies
|
||||
|
||||
name: shipyard
|
||||
description: Full Thrust ship builder
|
||||
|
||||
author: 'Yanick Champoux <yanick@babyl.ca>'
|
||||
|
||||
scripts:
|
||||
build: NODE_ENV=production webpack
|
||||
start: webpack-dev-server --open --content-base public
|
||||
|
||||
package: ./scripts/merge_package.pl
|
||||
|
||||
test: tap 'src/**test.js' --no-coverage
|
||||
|
||||
"lint:prettier": ./scripts/prettier
|
||||
"lint:eslint": ./scripts/eslint
|
||||
lint: npm-run-all --parallel "lint:prettier -- {@}" "lint:eslint -- {@}" --
|
||||
|
||||
"lint:prettier:fix": npm run lint:prettier -- --fix
|
||||
"lint:eslint:fix": npm run lint:eslint -- --fix
|
||||
"lint:fix": npm-run-all "lint:eslint:fix -- {@}" "lint:prettier:fix -- {@}" --
|
||||
|
||||
eslintConfig:
|
||||
env:
|
||||
amd: true
|
||||
browser: true
|
||||
es6: true
|
||||
node: true
|
||||
extends:
|
||||
- prettier
|
||||
- eslint:recommended
|
||||
- plugin:you-dont-need-lodash-underscore/compatible
|
||||
- plugin:lodash/recommended
|
||||
ignorePatterns:
|
||||
- src/node_modules
|
||||
overrides:
|
||||
- files:
|
||||
- '*.svelte'
|
||||
processor: svelte3/svelte3
|
||||
parserOptions:
|
||||
ecmaFeatures:
|
||||
modules: true
|
||||
ecmaVersion: '2020'
|
||||
sourceType: module
|
||||
plugins:
|
||||
- svelte3
|
||||
rules:
|
||||
lodash/prefer-lodash-method: off
|
||||
keywords: [ game ]
|
||||
license: ISC
|
||||
main: index.js
|
||||
|
||||
prettier:
|
||||
svelteSortOrder: markup-scripts-styles
|
||||
svelteStrictMode: false
|
||||
|
||||
tap:
|
||||
coverage: false
|
|
@ -0,0 +1,76 @@
|
|||
:root {
|
||||
--font-scale-8: calc(1rem/1.125/1.125);
|
||||
--font-scale-9: calc(1rem/1.125);
|
||||
--font-scale-10: 1rem;
|
||||
--font-scale-11: calc(1rem * 1.125);
|
||||
--font-scale-12: calc(1rem * 1.125 * 1.125);
|
||||
}
|
||||
|
||||
|
||||
|
||||
html, body {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: #333;
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: rgb(0,100,200);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: rgb(0,80,160);
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
input, button, select, textarea {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
padding: 0.4em;
|
||||
margin: 0 0 0.5em 0;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
input:disabled {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
input[type="range"] {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
color: #333;
|
||||
background-color: #f4f4f4;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
button:not(:disabled):active {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
button:focus {
|
||||
border-color: #666;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta name='viewport' content='width=device-width,initial-scale=1'>
|
||||
|
||||
<title>Svelte app</title>
|
||||
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,600,700">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto+Mono">
|
||||
|
||||
<link rel='icon' type='image/png' href='/favicon.png'>
|
||||
<link rel='stylesheet' href='/global.css'>
|
||||
<link rel='stylesheet' href='/bundle.css'>
|
||||
|
||||
<!--
|
||||
<link rel='stylesheet' href='/materialize/materialize.css'>
|
||||
<script src="/materialize/materialize.js"></script>
|
||||
-->
|
||||
|
||||
<script>
|
||||
process = { env: { NODE_ENV: 'production' } };
|
||||
</script>
|
||||
<script defer src='/bundle.js'></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version='1.0' encoding='iso-8859-1'?>
|
||||
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512.003 512.003" xmlns:xlink="http://www.w3.org/1999/xlink" enable-background="new 0 0 512.003 512.003">
|
||||
<path d="m510.838,471.439l-80-288c-3.852-13.852-16.461-23.438-30.836-23.438h-112v-6.781c28-12.379 48-40.498 48-73.219 0-44.109-35.891-80-80-80s-80,35.891-80,80c0,32.721 20,60.84 48,73.219v6.781h-112c-14.375,0-26.984,9.586-30.836,23.438l-80,288c-2.672,9.633-0.695,19.969 5.359,27.93 6.055,7.961 15.477,12.633 25.477,12.633h448c10,0 19.422-4.672 25.477-12.633 6.054-7.961 8.03-18.297 5.359-27.93zm-254.836-407.437c8.82-1.42109e-14 16,7.18 16,16s-7.18,16-16,16c-8.82,0-16-7.18-16-16s7.179-16 16-16z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 823 B |
|
@ -0,0 +1,102 @@
|
|||
import svelte from 'rollup-plugin-svelte';
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import alias from '@rollup/plugin-alias';
|
||||
import livereload from 'rollup-plugin-livereload';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
import css from 'rollup-plugin-css-only';
|
||||
import postcss from 'rollup-plugin-postcss';
|
||||
import path from 'path';
|
||||
|
||||
const postcssOptions = () => ({
|
||||
extensions: ['.scss', '.sass'],
|
||||
extract: false,
|
||||
minimize: true,
|
||||
use: [
|
||||
['sass', {
|
||||
includePaths: [
|
||||
'./sass',
|
||||
'./node_modules',
|
||||
// This is only needed because we're using a local module. :-/
|
||||
// Normally, you would not need this line.
|
||||
path.resolve(__dirname, '..', 'node_modules')
|
||||
]
|
||||
}]
|
||||
]
|
||||
});
|
||||
|
||||
const production = !process.env.ROLLUP_WATCH;
|
||||
|
||||
export default {
|
||||
input: 'src/main.js',
|
||||
output: {
|
||||
sourcemap: true,
|
||||
format: 'iife',
|
||||
name: 'app',
|
||||
file: 'public/build/bundle.js'
|
||||
},
|
||||
plugins: [
|
||||
alias({
|
||||
entries: [
|
||||
{ find: '~', replacement: './src' },
|
||||
]
|
||||
}),
|
||||
// scss(),
|
||||
css({ output: 'public/build/import-bundle.css' }),
|
||||
svelte({
|
||||
// enable run-time checks when not in production
|
||||
dev: !production,
|
||||
// we'll extract any component CSS out into
|
||||
// a separate file - better for performance
|
||||
css: css => {
|
||||
css.write('public/build/bundle.css');
|
||||
}
|
||||
}),
|
||||
postcss(postcssOptions()),
|
||||
// If you have external dependencies installed from
|
||||
// npm, you'll most likely need these plugins. In
|
||||
// some cases you'll need additional configuration -
|
||||
// consult the documentation for details:
|
||||
// https://github.com/rollup/plugins/tree/master/packages/commonjs
|
||||
resolve({
|
||||
browser: true,
|
||||
dedupe: ['svelte']
|
||||
}),
|
||||
commonjs(),
|
||||
|
||||
// In dev mode, call `npm run start` once
|
||||
// the bundle has been generated
|
||||
!production && serve(),
|
||||
|
||||
// Watch the `public` directory and refresh the
|
||||
// browser on changes when not in production
|
||||
!production && livereload('public'),
|
||||
|
||||
// If we're building for production (npm run build
|
||||
// instead of npm run dev), minify
|
||||
production && terser()
|
||||
],
|
||||
watch: {
|
||||
clearScreen: false,
|
||||
chokidar: {
|
||||
usePolling: true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function serve() {
|
||||
let started = false;
|
||||
|
||||
return {
|
||||
writeBundle() {
|
||||
if (!started) {
|
||||
started = true;
|
||||
|
||||
require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
|
||||
stdio: ['ignore', 'inherit', 'inherit'],
|
||||
shell: true
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
|
||||
# check by default
|
||||
my @mode;
|
||||
|
||||
my @files = grep {
|
||||
$_ ne '--fix'or not (@mode = ('--fix'));
|
||||
} @ARGV;
|
||||
|
||||
@files = qw/ src / unless @files;
|
||||
|
||||
my @ignore = (
|
||||
qr/\.map$/,
|
||||
qr!^docs/!,
|
||||
qr/\.(css|html|md)$/,
|
||||
qr/package\.(json|yaml)/,
|
||||
qr#^scripts/#,
|
||||
qr#^\.#,
|
||||
qr#\.json$#
|
||||
);
|
||||
|
||||
sub ignored {
|
||||
my $file = shift;
|
||||
|
||||
for my $pattern ( @ignore ) {
|
||||
return 1 if $file =~ $pattern;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
exec 'eslint', @mode, grep {
|
||||
not ignored($_)
|
||||
} @files;
|
|
@ -0,0 +1,59 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
=pod
|
||||
|
||||
I'm slightly fed up with `package.json`, because:
|
||||
|
||||
* the keys are ordering alphabetically, not logically.
|
||||
* no comments.
|
||||
* friggin' no trailing comma. And the quotes, my lord, the bloody
|
||||
quotes...
|
||||
|
||||
Hence this script, which takes a `package.yaml`, and convert it
|
||||
to `package.json`.
|
||||
Sections, like `dependencies`, `devDependencies' and 'version' that we want to preserve can be given `_merge`. All data structures under the keys
|
||||
given in `_merge` will have their `yaml` and `json` values merged,
|
||||
with the `json` having priority.
|
||||
|
||||
By default `package.json` will be updated (like, that's the point isn't?).
|
||||
For a dry run pass in a `-n` argument.
|
||||
|
||||
=cut
|
||||
|
||||
use 5.24.0;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use File::Serialize;
|
||||
use Hash::Merge qw/ merge /;
|
||||
|
||||
use feature qw/ postderef /;
|
||||
use YAML::XS;
|
||||
use Path::Tiny;
|
||||
use JSON::PP qw//;
|
||||
use JSON qw/ to_json /;
|
||||
|
||||
{
|
||||
no warnings;
|
||||
$YAML::XS::Boolean = 'JSON::PP';
|
||||
}
|
||||
|
||||
my $yaml = deserialize_file 'package.yml';
|
||||
my $json = deserialize_file 'package.json';
|
||||
|
||||
my $mergers = delete $yaml->{_merge};
|
||||
|
||||
my $result = merge( { $json->%{@$mergers} }, $yaml );
|
||||
|
||||
my $encoder = JSON->new->pretty->canonical->space_before(0);
|
||||
|
||||
$json = $encoder->encode($result);
|
||||
|
||||
$json =~ s/(^|\G) / /g;
|
||||
|
||||
if( grep { $_ eq '-n' } @ARGV ) {
|
||||
print $json;
|
||||
} else {
|
||||
path('package.json')->spew($json);
|
||||
say "regenerated package.json"
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
|
||||
# check by default
|
||||
my $mode = '-c';
|
||||
|
||||
my @files = grep {
|
||||
$_ ne '--fix'or not ($mode = '--write');
|
||||
} @ARGV;
|
||||
|
||||
@files = qw/ src / unless @files;
|
||||
|
||||
@files = grep { !/\.gitignore/ } @files;
|
||||
|
||||
exec 'prettier', '--plugin-search-dir=.', $mode, @files;
|
|
@ -0,0 +1,41 @@
|
|||
<script>
|
||||
import { setContext } from 'svelte';
|
||||
|
||||
import shipStore from './stores/ship';
|
||||
|
||||
import Ftl from './components/Ftl/index.svelte';
|
||||
import Engine from './components/Engine/index.svelte';
|
||||
import Identification from './components/Identification.svelte';
|
||||
|
||||
const ship = shipStore();
|
||||
|
||||
setContext('ship',ship);
|
||||
|
||||
let ship_name = $ship.ship_type.name;
|
||||
|
||||
const change_name = event => ship.dispatch(
|
||||
ship.actions.set_name( event.target.value) );
|
||||
|
||||
const change_mass = ({target: {value}}) =>
|
||||
ship.dispatch(ship.actions.set_ship_mass(parseInt(value)));
|
||||
|
||||
</script>
|
||||
|
||||
<main>
|
||||
|
||||
Potato?
|
||||
<Identification />
|
||||
|
||||
ship class: <input value={$ship.ship_type.name} on:change={change_name} />
|
||||
|
||||
<input type="number" value={$ship.ship_type.mass} on:change={change_mass} />
|
||||
|
||||
|
||||
<Ftl />
|
||||
|
||||
<Engine />
|
||||
|
||||
</main>
|
||||
|
||||
<style>
|
||||
</style>
|
|
@ -0,0 +1,93 @@
|
|||
<script>
|
||||
import { setContext } from 'svelte';
|
||||
|
||||
import shipStore from './stores/ship';
|
||||
|
||||
import ShipCost from './components/ShipCost.svelte';
|
||||
import Hull from './components/Hull.svelte';
|
||||
import Identification from './components/Identification.svelte';
|
||||
import Firecons from './components/Firecons.svelte';
|
||||
import AddWeapon from './components/Weapons/Add.svelte';
|
||||
import Propulsion from './components/Propulsion/index.svelte';
|
||||
import Section from '~C/Section';
|
||||
import Weapon from '~C/Weapon';
|
||||
|
||||
const ship = shipStore();
|
||||
|
||||
setContext('ship',ship);
|
||||
|
||||
let ship_name = $ship.general.name;
|
||||
|
||||
const change_name = event => ship.dispatch(
|
||||
ship.actions.set_name( event.target.value) );
|
||||
|
||||
const change_mass = ({target: {value}}) => ship.dispatch(ship.actions.set_ship_mass(parseInt(value)));
|
||||
|
||||
const add_weapon = () => ship.dispatch.add_weapon();
|
||||
|
||||
const change_ftl = ({detail}) => ship.dispatch.set_ftl(detail);
|
||||
const change_engine = ({detail}) => ship.dispatch.set_engine(detail);
|
||||
const change_hull = ({detail}) => ship.dispatch.set_hull(detail);
|
||||
const change_firecons = ({detail}) => ship.dispatch.set_firecons(detail);
|
||||
const change_weapon = ({detail}) => ship.dispatch.set_weapon(detail);
|
||||
const remove_weapon = ({detail}) => ship.dispatch.remove_weapon(detail);
|
||||
|
||||
let weapons = [];
|
||||
$: console.log(weapons);
|
||||
$: weapons= $ship.weaponry.weapons;
|
||||
|
||||
const reset = ship.dispatch.reset;
|
||||
|
||||
const add_screen = ({detail}) => ship.dispatch.add_screen(detail);
|
||||
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<input type="button" value="reset" on:click={reset} />
|
||||
|
||||
<Identification />
|
||||
|
||||
<ShipCost />
|
||||
|
||||
<Propulsion
|
||||
ftl={$ship.ftl}
|
||||
engine={$ship.engine}
|
||||
on:change_ftl={change_ftl}
|
||||
on:change_engine={change_engine}
|
||||
/>
|
||||
|
||||
<Hull ship_mass={$ship.general.mass}
|
||||
{ ... $ship.structure.hull }
|
||||
on:change_hull={change_hull}
|
||||
screens={ $ship.structure.screens}
|
||||
on:add_screen={add_screen}
|
||||
/>
|
||||
|
||||
|
||||
<Section label="weaponry">
|
||||
<Firecons { ... $ship.weaponry.firecons }
|
||||
on:change_firecons={ change_firecons }/>
|
||||
|
||||
<input type="button" value="add weapon" on:click={add_weapon}/>
|
||||
|
||||
{#each weapons as weapon (weapon.id)}
|
||||
<Weapon {...weapon} on:change_weapon={change_weapon}
|
||||
on:remove_weapon={remove_weapon} />
|
||||
{/each}
|
||||
|
||||
|
||||
</Section>
|
||||
|
||||
</main>
|
||||
|
||||
<style>
|
||||
main {
|
||||
display: grid;
|
||||
width: 60em;
|
||||
grid-template-columns: 4fr 1fr 1fr;
|
||||
}
|
||||
|
||||
main :global(> *) {
|
||||
grid-column: 1;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,19 @@
|
|||
<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>
|
|
@ -0,0 +1,38 @@
|
|||
<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 Field from '~C/Field';
|
||||
import ShipItem from '~C/ShipItem';
|
||||
import { createEventDispatcher } from '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; }
|
||||
</style>
|
|
@ -0,0 +1,5 @@
|
|||
<Field label="the label" />
|
||||
|
||||
<script>
|
||||
import Field from './index.svelte';
|
||||
</script>
|
|
@ -0,0 +1,20 @@
|
|||
<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>
|
||||
label {
|
||||
font-size: var(--font-scale-8);
|
||||
}
|
||||
</style>
|
|
@ -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,
|
||||
});
|
|
@ -0,0 +1,20 @@
|
|||
<ShipItem {cost} {mass}>
|
||||
<Field label="firecons">
|
||||
<input type="number" bind:value={nbr} />
|
||||
</Field>
|
||||
</ShipItem>
|
||||
|
||||
<script>
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import ShipItem from '~C/ShipItem';
|
||||
import Field from '~C/Field';
|
||||
|
||||
export let nbr, cost, mass = (0,0,0);
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
$: dispatch( 'change_firecons', nbr);
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
|
@ -0,0 +1,35 @@
|
|||
<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>
|
|
@ -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()
|
||||
}
|
||||
});
|
|
@ -0,0 +1,39 @@
|
|||
<Section label="hull">
|
||||
|
||||
<ShipItem {cost} {mass} >
|
||||
<Field label="integrity">
|
||||
<input
|
||||
bind:value={rating}
|
||||
type="number" {min} {max} />
|
||||
</Field>
|
||||
</ShipItem>
|
||||
|
||||
|
||||
<Screens {screens} on:add_screen />
|
||||
|
||||
</Section>
|
||||
|
||||
<script>
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
import Section from '~C/Section';
|
||||
import Field from '~C/Field';
|
||||
import ShipItem from '~C/ShipItem';
|
||||
import Screens from './Screens';
|
||||
|
||||
export let cost, mass, ship_mass, rating, screens = (
|
||||
0, 0, 10, 1, []
|
||||
);
|
||||
|
||||
let min, max;
|
||||
$: min = Math.ceil(ship_mass / 10);
|
||||
$: max = ship_mass;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
$: dispatch( 'change_hull', { rating } );
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
|
@ -0,0 +1,49 @@
|
|||
<div class="identification">
|
||||
|
||||
<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 './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,false).map(
|
||||
({name}) => name
|
||||
);
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.identification {
|
||||
grid-column: span 3;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
<Section label="propulsion">
|
||||
|
||||
<Ftl {...ftl} on:change_ftl />
|
||||
|
||||
<Engine {...engine} on:change_engine />
|
||||
|
||||
</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>
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
<input type="button" value="add screen" on:click={() => add_screen()} />
|
||||
<input type="button" value="add advanced screen"
|
||||
on:click={ () => add_screen(true) }/>
|
||||
|
||||
<ShipItem cost="10" mass="10">
|
||||
{ nbr_regular } { nbr_advanced }
|
||||
</ShipItem>
|
||||
|
||||
<script>
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
import Section from '~C/Section';
|
||||
import Field from '~C/Field';
|
||||
import ShipItem from '~C/ShipItem';
|
||||
|
||||
export let screens = [];
|
||||
|
||||
$: if( !Array.isArray(screens) ) screens = [];
|
||||
|
||||
let nbr_regular, nbr_advanced;
|
||||
$: {
|
||||
nbr_regular = screens.filter( ({advanced}) => !advanced ).length;
|
||||
nbr_advanced = screens.length - nbr_regular;
|
||||
}
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
const add_screen = (advanced) => {
|
||||
console.log(advanced); return dispatch( 'add_screen', advanced ); };
|
||||
|
||||
</script>
|
|
@ -0,0 +1,8 @@
|
|||
<fieldset>
|
||||
<legend>{label}</legend>
|
||||
<slot />
|
||||
</fieldset>
|
||||
|
||||
<script>
|
||||
export let label;
|
||||
</script>
|
|
@ -0,0 +1,58 @@
|
|||
<div class="ship_cost">
|
||||
<div>
|
||||
<label>Ship tonnage</label>
|
||||
<input
|
||||
value={$ship.general.mass}
|
||||
on:change={change_tonnage}
|
||||
type="number" min="10" max="300" />
|
||||
<div>
|
||||
|
||||
<div class="note" class:warning={!within_budget}>
|
||||
{#if within_budget}
|
||||
mass unused: { mass_unused }
|
||||
{:else}
|
||||
excessive mass: { -mass_unused }
|
||||
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>Ship cost</label>
|
||||
<div>{$ship.general.cost}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import { getContext } from 'svelte';
|
||||
|
||||
export let ship = getContext('ship');
|
||||
|
||||
const change_tonnage =
|
||||
({target: {value}}) =>
|
||||
ship.dispatch(ship.actions.set_ship_mass(parseInt(value)));
|
||||
|
||||
let mass_unused;
|
||||
$: mass_unused = $ship.general.mass - $ship.general.used_mass;
|
||||
|
||||
let within_budget = true;
|
||||
|
||||
$: within_budget = mass_unused >= 0;
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.ship_cost {
|
||||
display: flex;
|
||||
grid-column: span 3;
|
||||
justify-content: space-around;
|
||||
}
|
||||
.warning {
|
||||
color: red;
|
||||
}
|
||||
.note {
|
||||
font-size: smaller;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,29 @@
|
|||
<div class="ship-item">
|
||||
<slot />
|
||||
|
||||
<div class="mass">{ mass }</div>
|
||||
<div class="cost">{ cost }</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
export let mass;
|
||||
export let cost;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.ship-item {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.ship-item :global(> *) {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.cost,.mass { width: 4em; flex: inherit; }
|
||||
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>
|
|
@ -0,0 +1,210 @@
|
|||
<ShipItem {cost} {mass}>
|
||||
|
||||
<div class="remove" on:click={remove}>X</div>
|
||||
|
||||
<Field label="weapon type">
|
||||
<select bind:value={weapon_type}>
|
||||
<option>beam</option>
|
||||
</select>
|
||||
</Field>
|
||||
|
||||
<Field label="weapon class">
|
||||
<select bind:value={weapon_class}>
|
||||
<option>1</option>
|
||||
<option>2</option>
|
||||
<option>3</option>
|
||||
<option>4</option>
|
||||
</select>
|
||||
</Field>
|
||||
|
||||
<Field label="arcs">
|
||||
<select bind:value={nbr_arcs}>
|
||||
{#each arc_options[weapon_class]||[] as nbr_arcs (nbr_arcs)}
|
||||
<option>{nbr_arcs}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</Field>
|
||||
|
||||
|
||||
<svg width="60px" height="60px">
|
||||
{#each all_arcs as arc (arc)}
|
||||
<Arc {arc} radius={30}
|
||||
active={arcs.includes(arc)}
|
||||
on:click={()=>click_arc(arc)}
|
||||
/>
|
||||
{/each}
|
||||
<circle cx="30" cy="30" r="15" />
|
||||
|
||||
|
||||
</svg>
|
||||
|
||||
</ShipItem>
|
||||
|
||||
<script>
|
||||
import Arc from '../Weapons/Arc.svelte';
|
||||
import { weapon_cost_mass } from '../../dux/weapons/rules.js';
|
||||
import fp from 'lodash/fp';
|
||||
import _ from 'lodash';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import ShipItem from '~C/ShipItem';
|
||||
import Field from '~C/Field';
|
||||
|
||||
const all_arcs = [ 'FS', 'F', 'FP', 'AP', 'A', 'AS' ];
|
||||
|
||||
export let weapon_type;
|
||||
export let weapon_class;
|
||||
export let id;
|
||||
export let arcs = [];
|
||||
export let cost;
|
||||
export let mass;
|
||||
|
||||
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 nbr_arcs = 6;
|
||||
$: console.log(weapon_class);
|
||||
$: nbr_arcs = arc_options[weapon_class][0];
|
||||
|
||||
$: console.log({arcs,nbr_arcs})
|
||||
|
||||
$: if ( arcs.length !== nbr_arcs ) {
|
||||
if( nbr_arcs === 'broadside' ) {
|
||||
arcs = all_arcs.filter( arc => arc.length === 1 )
|
||||
}
|
||||
else{
|
||||
|
||||
let first_index = all_arcs.findIndex( arc => arcs[0] );
|
||||
if( first_index === -1 ) first_index = 0;
|
||||
|
||||
const new_arcs = [];
|
||||
|
||||
_.range(nbr_arcs).forEach( i => {
|
||||
new_arcs.push( all_arcs[first_index] )
|
||||
first_index = ( first_index + 1 ) % all_arcs.length;
|
||||
});
|
||||
|
||||
arcs = new_arcs;
|
||||
}
|
||||
}
|
||||
|
||||
const click_arc = (first_arc) => {
|
||||
if( nbr_arcs === 'broadside' ) return;
|
||||
|
||||
let first_index = all_arcs.findIndex( arc => arc === first_arc );
|
||||
|
||||
const new_arcs = [];
|
||||
|
||||
_.range(nbr_arcs).forEach( i => {
|
||||
new_arcs.push( all_arcs[first_index] );
|
||||
first_index = ( first_index + 1 ) % all_arcs.length;
|
||||
});
|
||||
|
||||
arcs = new_arcs;
|
||||
|
||||
}
|
||||
|
||||
let i = 1;
|
||||
$: if(weapon_class) i = 1;
|
||||
|
||||
$: console.log( "id", id);
|
||||
$: console.log( "weapon_class", weapon_class);
|
||||
$: console.log( "weapon_type", weapon_type);
|
||||
$: console.log( "arcs", arcs);
|
||||
const dispatch = createEventDispatcher();
|
||||
let cache = '';
|
||||
$: cache = arcs.join(":");
|
||||
$: {
|
||||
//console.log( { id, weapon_class, weapon_type, arcs: cache.split(":") });
|
||||
dispatch( 'change_weapon', { id, weapon_class, weapon_type, arcs:
|
||||
cache.split(":") });
|
||||
}
|
||||
|
||||
|
||||
const remove = () => dispatch( 'remove_weapon', id );
|
||||
|
||||
</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;
|
||||
}
|
||||
|
||||
.remove {
|
||||
width: 1em;
|
||||
flex: 0;
|
||||
color: white;
|
||||
background-color: black;
|
||||
border-radius: 0.5em;
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,203 @@
|
|||
<input class="add-weapon" 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 fp from 'lodash/fp';
|
||||
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>
|
|
@ -0,0 +1,50 @@
|
|||
<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>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
import AddWeapon from './Add.svelte';
|
||||
|
||||
export default {
|
||||
title: "add weapon",
|
||||
};
|
||||
|
||||
export const beam = () => ({
|
||||
Component: AddWeapon,
|
||||
});
|
||||
|