mirror of https://github.com/aotds/aotds-docks.git
49 changed files with 2152 additions and 10 deletions
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
node_modules |
||||
.nyc_output |
||||
pnpm-lock.yaml |
||||
public/build |
||||
public/bundle.* |
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
module.exports = { |
||||
stories: [ '../src/**/*stories.js' ] |
||||
}; |
@ -1,12 +1,136 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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,102 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -0,0 +1,5 @@
|
||||
<Field label="the label" /> |
||||
|
||||
<script> |
||||
import Field from './index.svelte'; |
||||
</script> |
@ -0,0 +1,20 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -0,0 +1,8 @@
|
||||
<fieldset> |
||||
<legend>{label}</legend> |
||||
<slot /> |
||||
</fieldset> |
||||
|
||||
<script> |
||||
export let label; |
||||
</script> |
@ -0,0 +1,58 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -0,0 +1,10 @@
|
||||
import AddWeapon from './Add.svelte'; |
||||
|
||||
export default { |
||||
title: "add weapon", |
||||
}; |
||||
|
||||
export const beam = () => ({ |
||||
Component: AddWeapon, |
||||
}); |
||||
|