Merge branch 'cumulative-cost' into version-2
This commit is contained in:
commit
e2560d6e16
@ -2,6 +2,7 @@ const path = require("path");
|
|||||||
const preprocess = require("svelte-preprocess");
|
const preprocess = require("svelte-preprocess");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
// core: { builder: "storybook-builder-vite" },
|
||||||
staticDirs: ["../static", "../pictures"],
|
staticDirs: ["../static", "../pictures"],
|
||||||
stories: [
|
stories: [
|
||||||
"../src/**/*.stories.mdx",
|
"../src/**/*.stories.mdx",
|
||||||
@ -9,13 +10,20 @@ module.exports = {
|
|||||||
"../src/**/stories.svelte",
|
"../src/**/stories.svelte",
|
||||||
],
|
],
|
||||||
addons: [
|
addons: [
|
||||||
"@storybook/addon-links",
|
|
||||||
"@storybook/addon-essentials",
|
"@storybook/addon-essentials",
|
||||||
"@storybook/addon-svelte-csf",
|
"@storybook/addon-svelte-csf",
|
||||||
],
|
],
|
||||||
framework: "@storybook/svelte",
|
framework: "@storybook/svelte",
|
||||||
svelteOptions: {
|
svelteOptions: {
|
||||||
preprocess: preprocess(),
|
preprocess: preprocess(),
|
||||||
|
},
|
||||||
|
async viteFinal(config, { configType }) {
|
||||||
|
// customize the Vite config here
|
||||||
|
config.resolve.alias.$lib = path.resolve(__dirname, "../src/lib/");
|
||||||
|
config.resolve.alias.$app = path.resolve(__dirname, "../fake/app/");
|
||||||
|
|
||||||
|
// return the customized config
|
||||||
|
return config;
|
||||||
},
|
},
|
||||||
webpackFinal: async (config) => {
|
webpackFinal: async (config) => {
|
||||||
return {
|
return {
|
||||||
|
@ -24,14 +24,13 @@
|
|||||||
"eslint-plugin-svelte3": "^3.4.1",
|
"eslint-plugin-svelte3": "^3.4.1",
|
||||||
"prettier": "~2.5.1",
|
"prettier": "~2.5.1",
|
||||||
"prettier-plugin-svelte": "^2.6.0",
|
"prettier-plugin-svelte": "^2.6.0",
|
||||||
|
"storybook-builder-vite": "0.1.17",
|
||||||
"svelte": "^3.46.4",
|
"svelte": "^3.46.4",
|
||||||
"vite": "^2.7.0"
|
"vite": "^2.7.0"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@storybook/addon-actions": "^6.4.19",
|
|
||||||
"@storybook/addon-essentials": "^6.4.19",
|
"@storybook/addon-essentials": "^6.4.19",
|
||||||
"@storybook/addon-links": "6.4.19",
|
|
||||||
"@storybook/addon-svelte-csf": "^1.1.0",
|
"@storybook/addon-svelte-csf": "^1.1.0",
|
||||||
"@storybook/svelte": "^6.4.19",
|
"@storybook/svelte": "^6.4.19",
|
||||||
"@sveltejs/adapter-node": "^1.0.0-next.0",
|
"@sveltejs/adapter-node": "^1.0.0-next.0",
|
||||||
|
@ -66,22 +66,6 @@ dux.addSubscription((store) =>
|
|||||||
createSelector(calc_ship_req, (reqs) => store.dispatch(set_ship_reqs(reqs)))
|
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.dispatch(dux.actions.set_streamlining_cost_mass({ cost, mass }));
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
dux.addSubscription((store) =>
|
dux.addSubscription((store) =>
|
||||||
createSelector(
|
createSelector(
|
||||||
@ -145,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;
|
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
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
33
src/lib/components/ShipEdit/Carrier/Carrier.stories.svelte
Normal file
33
src/lib/components/ShipEdit/Carrier/Carrier.stories.svelte
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<Meta title="ShipEdit/Carrier" component={Carrier} argTypes={{}} />
|
||||||
|
|
||||||
|
<Story name="Primary" args={{}} />
|
||||||
|
|
||||||
|
<Template let:args>
|
||||||
|
<div style="width: 50em">
|
||||||
|
<Carrier {...args} {...$state}/>
|
||||||
|
</div>
|
||||||
|
</Template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
|
||||||
|
import { action } from "@storybook/addon-actions";
|
||||||
|
|
||||||
|
import { setContext } from "svelte";
|
||||||
|
import { readable, get, derived } from "svelte/store";
|
||||||
|
|
||||||
|
import Carrier from "./index.svelte";
|
||||||
|
import carrierDux from '$lib/shipDux/carrier.js'
|
||||||
|
|
||||||
|
const carrierStore = carrierDux.createStore();
|
||||||
|
const state = readable(carrierStore.getState(), (set) => {
|
||||||
|
carrierStore.subscribe(() => {
|
||||||
|
set(carrierStore.getState());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
setContext("ship", {
|
||||||
|
dispatch: carrierStore.dispatch,
|
||||||
|
shipMass: readable(50),
|
||||||
|
state,
|
||||||
|
});
|
||||||
|
</script>
|
@ -1,4 +1,4 @@
|
|||||||
<ShipItem {cost} {mass}>
|
<ShipItem {...reqs}>
|
||||||
<Field label={`squadron ${id}`}>
|
<Field label={`squadron ${id}`}>
|
||||||
<select bind:value={type}>
|
<select bind:value={type}>
|
||||||
{#each types as type (type)}
|
{#each types as type (type)}
|
||||||
@ -14,24 +14,20 @@
|
|||||||
import Section from "$lib/components/Section/index.svelte";
|
import Section from "$lib/components/Section/index.svelte";
|
||||||
import Field from "$lib/components/Field/index.svelte";
|
import Field from "$lib/components/Field/index.svelte";
|
||||||
import ShipItem from "$lib/components/ShipItem/index.svelte";
|
import ShipItem from "$lib/components/ShipItem/index.svelte";
|
||||||
import dux from "$lib/dux/carrier";
|
import { squadronTypes } from "$lib/shipDux/carrier.js";
|
||||||
import squadron_types from "$lib/dux/carrier/squadron_types";
|
|
||||||
|
|
||||||
const types = squadron_types.map(({ type }) => type);
|
const types = squadronTypes.map(({ type }) => type);
|
||||||
|
|
||||||
export let id = 1;
|
export let id = 1;
|
||||||
export let type = "standard";
|
export let type = types[0].type;
|
||||||
export let ftl = false;
|
export let reqs= {};
|
||||||
export let cost = 0;
|
|
||||||
export let mass = 0;
|
|
||||||
|
|
||||||
export let ship = getContext("ship");
|
export let { dispatch } = getContext("ship");
|
||||||
|
|
||||||
|
$: console.log(type)
|
||||||
|
$: dispatch.setSquadronType({type, id});
|
||||||
|
|
||||||
$: ship?.dispatch_action("set_squadron", { id, type });
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
div {
|
|
||||||
background-color: red;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
34
src/lib/components/ShipEdit/Carrier/index.svelte
Normal file
34
src/lib/components/ShipEdit/Carrier/index.svelte
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<Section label="carrier">
|
||||||
|
<ShipItem {...reqs}>
|
||||||
|
<Field label="bays">
|
||||||
|
<input type="number" min="0" bind:value={bays} />
|
||||||
|
</Field>
|
||||||
|
</ShipItem>
|
||||||
|
|
||||||
|
{#each squadrons as squadron,id (id)}
|
||||||
|
<Squadron {...squadron} id={id+1} />
|
||||||
|
{/each}
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getContext } from 'svelte';
|
||||||
|
import Field from '$lib/components/Field/index.svelte';
|
||||||
|
import ShipItem from '$lib/components/ShipItem/index.svelte';
|
||||||
|
import Section from '$lib/components/Section/index.svelte';
|
||||||
|
import Squadron from './Squadron.svelte';
|
||||||
|
|
||||||
|
export let bays = 0;
|
||||||
|
export let reqs = {};
|
||||||
|
export let squadrons = [];
|
||||||
|
|
||||||
|
const { dispatch } = getContext('ship');
|
||||||
|
|
||||||
|
$: dispatch.setCarrierBays(bays);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
input {
|
||||||
|
width: 5em;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,4 +1,4 @@
|
|||||||
<Meta title="Identification" component={Identification} argTypes={{}} />
|
<Meta title="ShipEdit/Identification" component={Identification} argTypes={{}} />
|
||||||
|
|
||||||
<Story name="Primary" args={{}} />
|
<Story name="Primary" args={{}} />
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
const ship_types = [
|
const ship_types = [
|
||||||
{ name: "Scout", mass: [4, 10], abbrev: "SC" },
|
{ name: "Scout", mass: [0, 10], abbrev: "SC" },
|
||||||
{ name: "Courier", mass: [4, 10], abbrev: "SC" },
|
{ name: "Courier", mass: [4, 10], abbrev: "SC" },
|
||||||
{ name: "Corvette", mass: [8, 16], abbrev: "CT" },
|
{ name: "Corvette", mass: [8, 16], abbrev: "CT" },
|
||||||
{ name: "Frigate", mass: [14, 28], abbrev: "FF" },
|
{ name: "Frigate", mass: [14, 28], abbrev: "FF" },
|
||||||
@ -14,7 +14,7 @@ const ship_types = [
|
|||||||
{ name: "Heavy Battleship", mass: [120, 160], abbrev: "BDN" },
|
{ name: "Heavy Battleship", mass: [120, 160], abbrev: "BDN" },
|
||||||
{ name: "Dreadnought", mass: [140, 180], abbrev: "DN" },
|
{ name: "Dreadnought", mass: [140, 180], abbrev: "DN" },
|
||||||
{ name: "Superdreadnought", mass: [160, 300], abbrev: "SDN" },
|
{ name: "Superdreadnought", mass: [160, 300], abbrev: "SDN" },
|
||||||
{ name: "Escort Carrier", mass: [60, 140], abbrev: "CVE", carrier: true },
|
{ name: "Escort Carrier", mass: [0, 140], abbrev: "CVE", carrier: true },
|
||||||
{ name: "Light Carrier", mass: [120, 180], abbrev: "CVL", carrier: true },
|
{ name: "Light Carrier", mass: [120, 180], abbrev: "CVL", carrier: true },
|
||||||
{ name: "Heavy Carrier", mass: [160, 300], abbrev: "CVH", carrier: true },
|
{ name: "Heavy Carrier", mass: [160, 300], abbrev: "CVH", carrier: true },
|
||||||
{ name: "Attack Carrier", mass: [150, 300], abbrev: "CVA", carrier: true },
|
{ name: "Attack Carrier", mass: [150, 300], abbrev: "CVA", carrier: true },
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
const ship = getContext("ship");
|
const ship = getContext("ship");
|
||||||
|
|
||||||
console.log( ship.dispatch )
|
|
||||||
$: ship.dispatch.setDrive({ rating, advanced });
|
$: ship.dispatch.setDrive({ rating, advanced });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
41
src/lib/components/ShipEdit/Structure/Armor.svelte
Normal file
41
src/lib/components/ShipEdit/Structure/Armor.svelte
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<ShipItem {...reqs}>
|
||||||
|
<div>
|
||||||
|
<div class="nbr_layers">
|
||||||
|
<Field label="armour layers">
|
||||||
|
<input type="number" min="0" bind:value={nbr_layers} />
|
||||||
|
</Field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="layers">
|
||||||
|
{#each layers as rating,i (i)}
|
||||||
|
<Layer {rating} layer={i+1} />
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ShipItem>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getContext } from 'svelte';
|
||||||
|
import ShipItem from "$lib/components/ShipItem/index.svelte";
|
||||||
|
import Field from "$lib/components/Field/index.svelte";
|
||||||
|
import Layer from "./Armor/Layer.svelte";
|
||||||
|
|
||||||
|
export let layers = [];
|
||||||
|
export let reqs = {};
|
||||||
|
|
||||||
|
let nbr_layers = layers.length;
|
||||||
|
|
||||||
|
const { dispatch } = getContext('ship');
|
||||||
|
|
||||||
|
$: dispatch.setArmorLayers(nbr_layers);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.layers {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 5em;
|
||||||
|
}
|
||||||
|
</style>
|
22
src/lib/components/ShipEdit/Structure/Armor/Layer.svelte
Normal file
22
src/lib/components/ShipEdit/Structure/Armor/Layer.svelte
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<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.setArmorRating({ layer, rating });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
input {
|
||||||
|
width: 5em;
|
||||||
|
}
|
||||||
|
</style>
|
25
src/lib/components/ShipEdit/Structure/Cargo.svelte
Normal file
25
src/lib/components/ShipEdit/Structure/Cargo.svelte
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<ShipItem {...reqs}>
|
||||||
|
<Field label="cargo">
|
||||||
|
<input type="number" min="0" bind:value={space} />
|
||||||
|
</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 ship = getContext("ship");
|
||||||
|
|
||||||
|
export let space = 0;
|
||||||
|
export let reqs = {};
|
||||||
|
|
||||||
|
$: ship.dispatch.setCargo(space);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
input {
|
||||||
|
width: 5em;
|
||||||
|
}
|
||||||
|
</style>
|
41
src/lib/components/ShipEdit/Structure/Streamlining.svelte
Normal file
41
src/lib/components/ShipEdit/Structure/Streamlining.svelte
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<ShipItem {...reqs}>
|
||||||
|
<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 reqs = {};
|
||||||
|
|
||||||
|
export let {dispatch, shipMass} = getContext("ship");
|
||||||
|
|
||||||
|
$: dispatch.setStreamlining({type, shipMass: $shipMass});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,15 +1,24 @@
|
|||||||
<Section label="structure">
|
<Section label="structure">
|
||||||
<Hull {...hull}/>
|
<Hull {...hull}/>
|
||||||
<Screens {...screens} />
|
<Screens {...screens} />
|
||||||
|
<Armor {...armor} />
|
||||||
|
<Cargo {...cargo} />
|
||||||
|
<Streamlining {...streamlining} />
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Section from "$lib/components/Section/index.svelte";
|
import Section from "$lib/components/Section/index.svelte";
|
||||||
import Hull from './Hull.svelte';
|
import Hull from './Hull.svelte';
|
||||||
import Screens from './Screens.svelte';
|
import Screens from './Screens.svelte';
|
||||||
|
import Cargo from './Cargo.svelte';
|
||||||
|
import Armor from './Armor.svelte';
|
||||||
|
import Streamlining from './Streamlining.svelte';
|
||||||
|
|
||||||
export let hull = {};
|
export let hull = {};
|
||||||
export let screens = {};
|
export let screens = {};
|
||||||
|
export let cargo = {};
|
||||||
|
export let streamlining = {};
|
||||||
|
export let armor = {};
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
18
src/lib/components/ShipEdit/Weaponry/ADFC.svelte
Normal file
18
src/lib/components/ShipEdit/Weaponry/ADFC.svelte
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<ShipItem {...reqs}>
|
||||||
|
<Field label="ADFC">
|
||||||
|
<input type="number" class="short" bind:value={rating} />
|
||||||
|
</Field>
|
||||||
|
</ShipItem>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getContext } from 'svelte';
|
||||||
|
import ShipItem from "$lib/components/ShipItem/index.svelte";
|
||||||
|
import Field from "$lib/components/Field/index.svelte";
|
||||||
|
|
||||||
|
export let rating = 0;
|
||||||
|
export let reqs = {};
|
||||||
|
|
||||||
|
const { dispatch } = getContext('ship');
|
||||||
|
|
||||||
|
$: dispatch.setADFC(rating);
|
||||||
|
</script>
|
22
src/lib/components/ShipEdit/Weaponry/AddWeapon.svelte
Normal file
22
src/lib/components/ShipEdit/Weaponry/AddWeapon.svelte
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<Field label="weapon type">
|
||||||
|
<select bind:value={type}>
|
||||||
|
{#each weaponTypes as weapon (weapon.type)}
|
||||||
|
<option value={weapon.type}>{weapon.name}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<button class="button small blue" on:click={addWeapon} >add weapon</button>
|
||||||
|
</Field>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getContext } from "svelte";
|
||||||
|
import Field from "../../Field/index.svelte";
|
||||||
|
|
||||||
|
import { weaponTypes } from '$lib/shipDux/weaponry/weapons.js';
|
||||||
|
|
||||||
|
export let ship = getContext("ship");
|
||||||
|
|
||||||
|
let type = weaponTypes[0].value;
|
||||||
|
|
||||||
|
const addWeapon = () => ship.dispatch.addWeapon(type);
|
||||||
|
</script>
|
21
src/lib/components/ShipEdit/Weaponry/Firecons.svelte
Normal file
21
src/lib/components/ShipEdit/Weaponry/Firecons.svelte
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<ShipItem {...reqs}>
|
||||||
|
<Field label="firecons">
|
||||||
|
<input type="number" class="short" bind:value={stations} />
|
||||||
|
</Field>
|
||||||
|
</ShipItem>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getContext } from 'svelte';
|
||||||
|
import ShipItem from "$lib/components/ShipItem/index.svelte";
|
||||||
|
import Field from "$lib/components/Field/index.svelte";
|
||||||
|
|
||||||
|
export let stations = 0;
|
||||||
|
export let reqs = {};
|
||||||
|
|
||||||
|
const { dispatch } = getContext('ship');
|
||||||
|
|
||||||
|
$: dispatch.setFirecons(stations);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
@ -12,7 +12,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Arc from "../../Weapons/Arc.svelte";
|
import Arc from "./Arc.svelte";
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
|
|
||||||
const all_arcs = ["FS", "F", "FP", "AP", "A", "AS"];
|
const all_arcs = ["FS", "F", "FP", "AP", "A", "AS"];
|
Before Width: | Height: | Size: 651 B After Width: | Height: | Size: 639 B |
@ -0,0 +1,83 @@
|
|||||||
|
<label>beam</label>
|
||||||
|
|
||||||
|
<Field label="beam class">
|
||||||
|
<select bind:value={weaponClass}>
|
||||||
|
<option value={1}>1</option>
|
||||||
|
<option value={2}>2</option>
|
||||||
|
<option value={3}>3</option>
|
||||||
|
<option value={4}>4</option>
|
||||||
|
</select>
|
||||||
|
</Field>
|
||||||
|
|
||||||
|
<Field label="arcs">
|
||||||
|
<select bind:value={nbrArcs}>
|
||||||
|
{#each arc_options[weaponClass] || [] as nbrArcs (nbrArcs)}
|
||||||
|
<option>{nbrArcs}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
</Field>
|
||||||
|
|
||||||
|
<Arcs selected={arcs} on:click_arc={({ detail }) => setArcs(detail)} />
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getContext } from "svelte";
|
||||||
|
|
||||||
|
import Arcs from "../Arcs.svelte";
|
||||||
|
import ShipItem from "$lib/components/ShipItem/index.svelte";
|
||||||
|
import Field from "$lib/components/Field/index.svelte";
|
||||||
|
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
|
|
||||||
|
const all_arcs = ["FS", "F", "FP", "AP", "A", "AS"];
|
||||||
|
|
||||||
|
export let weaponClass = 1;
|
||||||
|
export let arcs = ["F"];
|
||||||
|
|
||||||
|
let arc_options = {
|
||||||
|
1: [6],
|
||||||
|
2: [3, 6],
|
||||||
|
3: [1, 2, 3, 4, 5, 6, "broadside"],
|
||||||
|
4: [1, 2, 3, 4, 5, 6, "broadside"],
|
||||||
|
};
|
||||||
|
|
||||||
|
$: arcsCaches = arcs.join(',');
|
||||||
|
|
||||||
|
let nbrArcs = arcs.length;
|
||||||
|
|
||||||
|
$: if (!arc_options[weaponClass].includes(nbrArcs)) {
|
||||||
|
nbrArcs = arc_options[weaponClass][0];
|
||||||
|
console.log({nbrArcs, label:"in if"})
|
||||||
|
}
|
||||||
|
|
||||||
|
const broadside = ["FS", "FP", "AP", "AS"];
|
||||||
|
|
||||||
|
|
||||||
|
function setArcs(firstArc) {
|
||||||
|
console.log(firstArc);
|
||||||
|
if (nbrArcs === "broadside") {
|
||||||
|
arcs = broadside;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let first_index = all_arcs.findIndex((arc) => arc === firstArc);
|
||||||
|
if (first_index === -1) first_index = 0;
|
||||||
|
|
||||||
|
console.log({arcs, label:"before"});
|
||||||
|
arcs = _.range(nbrArcs).map(
|
||||||
|
(i) => all_arcs[(first_index + i) % all_arcs.length]
|
||||||
|
);
|
||||||
|
arcsCaches = arcs.join(',');
|
||||||
|
console.log({arcs, label:"after"});
|
||||||
|
}
|
||||||
|
|
||||||
|
$: if (arcs.length !== nbrArcs) setArcs(arcs[0]);
|
||||||
|
|
||||||
|
$: console.log("it changed!", arcs)
|
||||||
|
$: console.log("it changed!", arcsCaches)
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
$: dispatch("change", {
|
||||||
|
weaponClass,
|
||||||
|
arcs: arcsCaches.split(','),
|
||||||
|
});
|
||||||
|
</script>
|
27
src/lib/components/ShipEdit/Weaponry/Weapon/Needle.svelte
Normal file
27
src/lib/components/ShipEdit/Weaponry/Weapon/Needle.svelte
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<label>needle weapon</label>
|
||||||
|
|
||||||
|
<Arcs selected={[arc]} on:click_arc={({ detail }) => click_arc(detail)} />
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getContext } from "svelte";
|
||||||
|
import Arcs from "./Arcs.svelte";
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
|
|
||||||
|
const all_arcs = ["FS", "F", "FP", "AP", "A", "AS"];
|
||||||
|
|
||||||
|
export let arc = "F";
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
const click_arc = (arc) => {
|
||||||
|
dispatch("change",{arc});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.arc {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
1
src/lib/components/ShipEdit/Weaponry/Weapon/PDS.svelte
Normal file
1
src/lib/components/ShipEdit/Weaponry/Weapon/PDS.svelte
Normal file
@ -0,0 +1 @@
|
|||||||
|
<label>point defence system</label>
|
@ -0,0 +1,19 @@
|
|||||||
|
<label>submunition pack</label>
|
||||||
|
|
||||||
|
<Arcs selected={[arc]} on:click_arc={({ detail }) => click_arc(detail)} />
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getContext } from "svelte";
|
||||||
|
import Arcs from "./Arcs.svelte";
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
|
|
||||||
|
const all_arcs = ["FS", "F", "FP", "AP", "A", "AS"];
|
||||||
|
|
||||||
|
export let arc = "F";
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
const click_arc = (arc) => {
|
||||||
|
dispatch("change",{arc});
|
||||||
|
};
|
||||||
|
</script>
|
121
src/lib/components/ShipEdit/Weaponry/Weapon/index.svelte
Normal file
121
src/lib/components/ShipEdit/Weaponry/Weapon/index.svelte
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
<ShipItem {...reqs}>
|
||||||
|
<div class="weapon_row">
|
||||||
|
<button
|
||||||
|
class="button small red remove"
|
||||||
|
on:click={remove}>remove
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<svelte:component
|
||||||
|
this={component[type]}
|
||||||
|
{...weapon}
|
||||||
|
on:change={update}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</ShipItem>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getContext } from "svelte";
|
||||||
|
|
||||||
|
import Arc from "./Arc.svelte";
|
||||||
|
import ShipItem from "$lib/components/ShipItem/index.svelte";
|
||||||
|
import Field from "$lib/components/Field/index.svelte";
|
||||||
|
import Beam from "./Beam/index.svelte";
|
||||||
|
import Submunition from "./Submunition.svelte";
|
||||||
|
import PointDefenceSystem from "./PDS.svelte";
|
||||||
|
import Scattergun from "./Scattergun.svelte";
|
||||||
|
import Needle from "./Needle.svelte";
|
||||||
|
|
||||||
|
const component = {
|
||||||
|
beam: Beam,
|
||||||
|
submunition: Submunition,
|
||||||
|
pds: PointDefenceSystem,
|
||||||
|
scattergun: Scattergun,
|
||||||
|
needle: Needle,
|
||||||
|
};
|
||||||
|
|
||||||
|
export let weapon = {};
|
||||||
|
$: reqs = weapon.reqs;
|
||||||
|
export let id;
|
||||||
|
|
||||||
|
const ship = getContext("ship");
|
||||||
|
|
||||||
|
$: type = weapon.type;
|
||||||
|
|
||||||
|
const remove = () => ship.dispatch.removeWeapon(id);
|
||||||
|
|
||||||
|
const update = ({ detail }) => {
|
||||||
|
console.log({id,type})
|
||||||
|
ship.dispatch.setWeapon({
|
||||||
|
id,
|
||||||
|
type,
|
||||||
|
...detail,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-weapon {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weapon_row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weapon_row > :global(*) {
|
||||||
|
margin-right: 2em;
|
||||||
|
}
|
||||||
|
</style>
|
34
src/lib/components/ShipEdit/Weaponry/Weaponry.stories.svelte
Normal file
34
src/lib/components/ShipEdit/Weaponry/Weaponry.stories.svelte
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<Meta title="ShipEdit/Weaponry" component={Weaponry} argTypes={{}} />
|
||||||
|
|
||||||
|
<Story name="Primary" args={{}} />
|
||||||
|
|
||||||
|
<Template let:args>
|
||||||
|
<div style="width: 50em">
|
||||||
|
<Weaponry {...args} {...$state}/>
|
||||||
|
</div>
|
||||||
|
</Template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
|
||||||
|
import { action } from "@storybook/addon-actions";
|
||||||
|
|
||||||
|
import { setContext } from "svelte";
|
||||||
|
import { readable, get, derived } from "svelte/store";
|
||||||
|
|
||||||
|
import Weaponry from "./index.svelte";
|
||||||
|
import weaponryDux from '$lib/shipDux/weaponry/index.js';
|
||||||
|
|
||||||
|
const store = weaponryDux.createStore();
|
||||||
|
const state = readable(store.getState(), (set) => {
|
||||||
|
store.subscribe(() => {
|
||||||
|
console.log(store.getState());
|
||||||
|
set(store.getState());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
setContext("ship", {
|
||||||
|
dispatch: store.dispatch,
|
||||||
|
shipMass: readable(50),
|
||||||
|
state,
|
||||||
|
});
|
||||||
|
</script>
|
34
src/lib/components/ShipEdit/Weaponry/index.svelte
Normal file
34
src/lib/components/ShipEdit/Weaponry/index.svelte
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<Section label="weaponry">
|
||||||
|
<Firecons {...firecons} />
|
||||||
|
|
||||||
|
<ADFC {...adfc} />
|
||||||
|
|
||||||
|
<AddWeapon />
|
||||||
|
|
||||||
|
{#each weapons as weapon (weapon.id)}
|
||||||
|
<Weapon {weapon} id={weapon.id} />
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getContext } from 'svelte';
|
||||||
|
|
||||||
|
import Section from "$lib/components/Section/index.svelte";
|
||||||
|
import ShipItem from '$lib/components/ShipItem/index.svelte';
|
||||||
|
import Field from '$lib/components/Field/index.svelte';
|
||||||
|
|
||||||
|
import Firecons from './Firecons.svelte';
|
||||||
|
import ADFC from './ADFC.svelte';
|
||||||
|
import AddWeapon from './AddWeapon.svelte';
|
||||||
|
import Weapon from './Weapon/index.svelte';
|
||||||
|
|
||||||
|
export let firecons = {};
|
||||||
|
export let adfc = {};
|
||||||
|
|
||||||
|
export let weapons = [];
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
@ -8,6 +8,10 @@
|
|||||||
|
|
||||||
<Structure {...$shipState.structure} />
|
<Structure {...$shipState.structure} />
|
||||||
|
|
||||||
|
<Weaponry {...$shipState.weaponry}/>
|
||||||
|
|
||||||
|
<Carrier {...$shipState.carrier} />
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getContext } from "svelte";
|
import { getContext } from "svelte";
|
||||||
|
|
||||||
@ -15,6 +19,8 @@
|
|||||||
import ShipCost from "./ShipCost.svelte";
|
import ShipCost from "./ShipCost.svelte";
|
||||||
import Propulsion from "./Propulsion/index.svelte";
|
import Propulsion from "./Propulsion/index.svelte";
|
||||||
import Structure from "./Structure/index.svelte";
|
import Structure from "./Structure/index.svelte";
|
||||||
|
import Carrier from "./Carrier/index.svelte";
|
||||||
|
import Weaponry from "./Weaponry/index.svelte";
|
||||||
|
|
||||||
const { state: shipState } = getContext("ship");
|
const { state: shipState } = getContext("ship");
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,35 +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>
|
|
76
src/lib/shipDux/carrier.js
Normal file
76
src/lib/shipDux/carrier.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import { Updux } from "updux";
|
||||||
|
import u from "updeep";
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
import reqs from "./reqs.js";
|
||||||
|
|
||||||
|
const dux = new Updux({
|
||||||
|
subduxes: { reqs },
|
||||||
|
initial: {
|
||||||
|
bays: 0,
|
||||||
|
squadrons: [],
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
setCarrierBays: null,
|
||||||
|
setSquadronType: null,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dux.setMutation( 'setCarrierBays', bays => u({bays, reqs:
|
||||||
|
calcBaysReqs(bays),
|
||||||
|
squadrons: adjustSquadrons(bays),
|
||||||
|
}) );
|
||||||
|
|
||||||
|
dux.setMutation('setSquadronType', ({type, id}) => state => {
|
||||||
|
|
||||||
|
return u.updateIn(['squadrons', id-1], {
|
||||||
|
type,
|
||||||
|
reqs: squadronReqs(type)
|
||||||
|
}, state )
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
export const squadronTypes= [
|
||||||
|
{ type: "standard", cost: 3 },
|
||||||
|
{ type: "fast", cost: 4 },
|
||||||
|
{ type: "heavy", cost: 5 },
|
||||||
|
{ type: "interceptor", cost: 3 },
|
||||||
|
{ type: "attack", cost: 4 },
|
||||||
|
{ type: "long range", cost: 4 },
|
||||||
|
{ type: "torpedo", cost: 6 },
|
||||||
|
];
|
||||||
|
|
||||||
|
function squadronReqs(type) {
|
||||||
|
return { mass: 6, cost: 6 * squadronTypes.find( s => s.type === type )?.cost }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const adjustSquadrons = bays => squadrons => {
|
||||||
|
if( squadrons.length > bays ) {
|
||||||
|
squadrons = squadrons.slice(0,bays);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( squadrons.length < bays ) {
|
||||||
|
squadrons = [ ...squadrons, ..._.times(
|
||||||
|
bays - squadrons.length, () => ({
|
||||||
|
type: squadronTypes[0].type,
|
||||||
|
reqs: {
|
||||||
|
cost: 6 * squadronTypes[0].cost,
|
||||||
|
mass: 6,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return squadrons;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function calcBaysReqs(bays) {
|
||||||
|
return {
|
||||||
|
mass: 9 * bays,
|
||||||
|
cost: 18 * bays,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default dux;
|
@ -1,10 +1,13 @@
|
|||||||
import { Updux } from "updux";
|
import { Updux } from "updux";
|
||||||
import u from "updeep";
|
import u from "updeep";
|
||||||
|
|
||||||
|
import carrier from './carrier.js';
|
||||||
|
|
||||||
const dux = new Updux({
|
const dux = new Updux({
|
||||||
actions: {
|
actions: {
|
||||||
setShipType: null,
|
setShipType: null,
|
||||||
setShipClass: null,
|
setShipClass: null,
|
||||||
|
setCarrierBays: carrier.actions.setCarrierBays,
|
||||||
},
|
},
|
||||||
initial: {
|
initial: {
|
||||||
shipType: "",
|
shipType: "",
|
||||||
@ -16,5 +19,8 @@ const dux = new Updux({
|
|||||||
|
|
||||||
dux.setMutation("setShipType", (shipType) => u({ shipType }));
|
dux.setMutation("setShipType", (shipType) => u({ shipType }));
|
||||||
dux.setMutation("setShipClass", (shipClass) => u({ shipClass }));
|
dux.setMutation("setShipClass", (shipClass) => u({ shipClass }));
|
||||||
|
dux.setMutation('setCarrierBays', (bays) => u({
|
||||||
|
isCarrier: bays > 0,
|
||||||
|
}))
|
||||||
|
|
||||||
export default dux;
|
export default dux;
|
||||||
|
@ -1,30 +1,59 @@
|
|||||||
import { Updux } from "updux";
|
import { Updux } from "updux";
|
||||||
import u from 'updeep';
|
import u from "updeep";
|
||||||
|
|
||||||
import propulsion from "./propulsion/index.js";
|
import propulsion from "./propulsion/index.js";
|
||||||
import identification from "./identification.js";
|
import identification from "./identification.js";
|
||||||
import { calculateDriveReqs } from './propulsion/drive.js';
|
import { calculateDriveReqs } from "./propulsion/drive.js";
|
||||||
import { ftlReqsReaction } from './propulsion/ftl.js';
|
import { ftlReqsReaction } from "./propulsion/ftl.js";
|
||||||
import structure from './structure/index.js';
|
import structure from "./structure/index.js";
|
||||||
import { screenReqsReaction, screensReqsReaction } from './structure/screens.js'
|
import carrier from "./carrier.js";
|
||||||
|
import weaponry from "./weaponry/index.js";
|
||||||
|
import { screensReqsReaction } from "./structure/screens.js";
|
||||||
|
|
||||||
const dux = new Updux({
|
const dux = new Updux({
|
||||||
subduxes: {
|
subduxes: {
|
||||||
identification,
|
identification,
|
||||||
propulsion,
|
propulsion,
|
||||||
structure
|
structure,
|
||||||
},
|
carrier,
|
||||||
initial: {
|
weaponry,
|
||||||
reqs: { cost: 0, mass: 10, usedMass: 0 },
|
},
|
||||||
},
|
initial: {
|
||||||
|
reqs: { cost: 0, mass: 10, usedMass: 0 },
|
||||||
|
},
|
||||||
actions: {
|
actions: {
|
||||||
}
|
setShipReqs: null,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
dux.setMutation( 'setShipMass', mass => u({reqs: {mass}}) );
|
dux.setMutation("setShipMass", (mass) => u({ reqs: { mass } }));
|
||||||
|
dux.setMutation('setShipReqs', reqs => u({reqs}));
|
||||||
|
|
||||||
|
dux.addReaction(calculateDriveReqs);
|
||||||
|
dux.addReaction(ftlReqsReaction);
|
||||||
|
dux.addReaction(screensReqsReaction);
|
||||||
|
|
||||||
|
dux.addReaction( (store) => (state) => {
|
||||||
|
let cost = 0;
|
||||||
|
let mass = 0;
|
||||||
|
|
||||||
|
let subsystems = Object.values(state);
|
||||||
|
|
||||||
|
while(subsystems.length>0) {
|
||||||
|
const subsystem = subsystems.shift();
|
||||||
|
if( typeof subsystem !== 'object' ) continue;
|
||||||
|
|
||||||
|
if( subsystem.reqs ) {
|
||||||
|
cost += subsystem.reqs.cost;
|
||||||
|
mass += subsystem.reqs.mass;
|
||||||
|
}
|
||||||
|
|
||||||
|
subsystems.push( ...Object.values(subsystem));
|
||||||
|
}
|
||||||
|
|
||||||
|
store.dispatch.setShipReqs({cost,usedMass: mass});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
dux.addReaction( calculateDriveReqs );
|
|
||||||
dux.addReaction( ftlReqsReaction );
|
|
||||||
dux.addReaction( screenReqsReaction );
|
|
||||||
|
|
||||||
export default dux;
|
export default dux;
|
||||||
|
50
src/lib/shipDux/structure/armor.js
Normal file
50
src/lib/shipDux/structure/armor.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { Updux } from "updux";
|
||||||
|
import u from "updeep";
|
||||||
|
|
||||||
|
import reqs from "../reqs.js";
|
||||||
|
|
||||||
|
const dux = new Updux({
|
||||||
|
subduxes: {
|
||||||
|
reqs,
|
||||||
|
},
|
||||||
|
initial: {
|
||||||
|
layers: [],
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
setArmorLayers: null,
|
||||||
|
setArmorRating: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
export default dux;
|
||||||
|
|
||||||
|
dux.setMutation('setArmorRating', ({layer, rating}) => state => {
|
||||||
|
let layers = [ ...state.layers ].map( (v,k) => k === layer-1 ? rating : v );
|
||||||
|
|
||||||
|
return { layers, reqs: calcArmorReqs(layers) }
|
||||||
|
} );
|
||||||
|
|
||||||
|
dux.setMutation( 'setArmorLayers', nbrLayers => state => {
|
||||||
|
|
||||||
|
let layers = [...state.layers];
|
||||||
|
|
||||||
|
if( nbrLayers < state.layers.length )
|
||||||
|
layers = [ ...state.layers ].slice(0,nbrLayers);
|
||||||
|
|
||||||
|
while( layers.length < nbrLayers ) {
|
||||||
|
layers.push(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
layers,
|
||||||
|
reqs: calcArmorReqs(layers),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function calcArmorReqs(layers) {
|
||||||
|
const mass = 2* layers.reduce( (a,b) => a+ b,0 );
|
||||||
|
const cost = 2* layers.map( (v,k) => v * (k+1) ).reduce( (a,b) => a+ b,0 );
|
||||||
|
|
||||||
|
return {
|
||||||
|
mass, cost
|
||||||
|
}
|
||||||
|
}
|
24
src/lib/shipDux/structure/cargo.js
Normal file
24
src/lib/shipDux/structure/cargo.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { Updux } from "updux";
|
||||||
|
import u from 'updeep';
|
||||||
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
|
import reqs from '../reqs.js';
|
||||||
|
|
||||||
|
const dux = new Updux({
|
||||||
|
subduxes: {
|
||||||
|
reqs
|
||||||
|
},
|
||||||
|
initial: {
|
||||||
|
space: 0,
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
setCargo: null,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
export default dux;
|
||||||
|
|
||||||
|
dux.setMutation('setCargo', space => u({
|
||||||
|
space,
|
||||||
|
reqs: { mass: space }
|
||||||
|
}));
|
||||||
|
|
@ -2,8 +2,12 @@ import { Updux } from 'updux';
|
|||||||
|
|
||||||
import hull from './hull.js';
|
import hull from './hull.js';
|
||||||
import screens from './screens.js';
|
import screens from './screens.js';
|
||||||
|
import cargo from './cargo.js';
|
||||||
|
import armor from './armor.js';
|
||||||
|
import streamlining from './streamlining.js';
|
||||||
|
|
||||||
const dux = new Updux({
|
const dux = new Updux({
|
||||||
subduxes: { hull, screens }
|
subduxes: { hull, screens, cargo, streamlining, armor }
|
||||||
});
|
});
|
||||||
export default dux;
|
export default dux;
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ export default dux;
|
|||||||
dux.setMutation('setScreens', payload => u(payload));
|
dux.setMutation('setScreens', payload => u(payload));
|
||||||
dux.setMutation('setScreensReqs', reqs => u({reqs}));
|
dux.setMutation('setScreensReqs', reqs => u({reqs}));
|
||||||
|
|
||||||
export const screenReqsReaction = store => createSelector(
|
export const screensReqsReaction = store => createSelector(
|
||||||
(ship) => ship.reqs.mass,
|
(ship) => ship.reqs.mass,
|
||||||
(ship) => ship.structure.screens.standard,
|
(ship) => ship.structure.screens.standard,
|
||||||
(ship) => ship.structure.screens.advanced,
|
(ship) => ship.structure.screens.advanced,
|
||||||
|
32
src/lib/shipDux/structure/streamlining.js
Normal file
32
src/lib/shipDux/structure/streamlining.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { Updux } from "updux";
|
||||||
|
import u from "updeep";
|
||||||
|
|
||||||
|
import reqs from "../reqs.js";
|
||||||
|
|
||||||
|
const dux = new Updux({
|
||||||
|
subduxes: {
|
||||||
|
reqs,
|
||||||
|
},
|
||||||
|
initial: {
|
||||||
|
type: "none",
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
setStreamlining: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
export default dux;
|
||||||
|
|
||||||
|
dux.setMutation("setStreamlining", ({ shipMass, type }) =>
|
||||||
|
u({
|
||||||
|
type,
|
||||||
|
reqs: calcStreamliningReqs({ shipMass, type }),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
function calcStreamliningReqs({ shipMass, type }) {
|
||||||
|
const mass = Math.ceil(
|
||||||
|
(shipMass * (type === "none" ? 0 : type === "partial" ? 5 : 10)) / 100
|
||||||
|
);
|
||||||
|
|
||||||
|
return { mass, cost: 2 * mass };
|
||||||
|
}
|
46
src/lib/shipDux/weaponry/index.js
Normal file
46
src/lib/shipDux/weaponry/index.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { Updux } from "updux";
|
||||||
|
import u from "updeep";
|
||||||
|
|
||||||
|
import weapons from './weapons.js';
|
||||||
|
|
||||||
|
const reqs = { cost: 0, mass: 0 };
|
||||||
|
|
||||||
|
const dux = new Updux({
|
||||||
|
subduxes: { weapons },
|
||||||
|
initial: {
|
||||||
|
firecons: {
|
||||||
|
stations: 0,
|
||||||
|
reqs,
|
||||||
|
},
|
||||||
|
adfc: { rating: 0, reqs },
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
setADFC: null,
|
||||||
|
setFirecons: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
dux.setMutation("setFirecons", (stations) =>
|
||||||
|
u({
|
||||||
|
firecons: {
|
||||||
|
stations,
|
||||||
|
reqs: {
|
||||||
|
cost: 4 * stations,
|
||||||
|
mass: stations,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
dux.setMutation("setADFC", (rating) =>
|
||||||
|
u({
|
||||||
|
adfc: {
|
||||||
|
rating,
|
||||||
|
reqs: {
|
||||||
|
cost: 8 * rating,
|
||||||
|
mass: 2 * rating,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
export default dux;
|
122
src/lib/shipDux/weaponry/weapons.js
Normal file
122
src/lib/shipDux/weaponry/weapons.js
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
import { Updux } from "updux";
|
||||||
|
import u from "updeep";
|
||||||
|
|
||||||
|
const reqs = { cost: 0, mass: 0 };
|
||||||
|
|
||||||
|
export const weaponTypes = [
|
||||||
|
{ name: 'beam', type: 'beam', reqs: beam_cost_mass, initial: {
|
||||||
|
weaponClass: 1
|
||||||
|
}},
|
||||||
|
{ name: 'submunition pack', type: 'submunition', reqs: { mass:1, cost:3 },
|
||||||
|
initial: { arc: 'F' }
|
||||||
|
},
|
||||||
|
{ name: 'point defence system', type: 'pds', reqs: {mass:1,cost:3}, initial: {}},
|
||||||
|
{ name: 'scattergun', type: 'scattergun', reqs: { mass:1,cost:4 }, initial: {}},
|
||||||
|
{ name: 'needle weapon', type: 'needle', reqs: { mass: 2, cost: 6 },
|
||||||
|
initial: { arc: 'F' }},
|
||||||
|
];
|
||||||
|
|
||||||
|
const dux = new Updux({
|
||||||
|
initial: [],
|
||||||
|
actions: {
|
||||||
|
addWeapon: null,
|
||||||
|
removeWeapon: null,
|
||||||
|
setWeapon: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
dux.setMutation('setWeapon', ({id,...rest}) => state => {
|
||||||
|
console.log(id,rest,state);
|
||||||
|
state = u.map( u.if( (w) => w.id === id,
|
||||||
|
weapon => {
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
...rest,
|
||||||
|
reqs: weaponReqs(rest),
|
||||||
|
}
|
||||||
|
} ), state );
|
||||||
|
console.log(state);
|
||||||
|
return state;
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
dux.setMutation('removeWeapon', id => state => [
|
||||||
|
...state.filter( (w) => w.id !== id )
|
||||||
|
]);
|
||||||
|
|
||||||
|
dux.setMutation('addWeapon', type => state => {
|
||||||
|
const initial = weaponTypes.find(w => w.type === type ).initial;
|
||||||
|
return [
|
||||||
|
...state,
|
||||||
|
{
|
||||||
|
id: state.length === 0 ? 1 : state[state.length -1]+1,
|
||||||
|
type,
|
||||||
|
reqs: weaponReqs({type,...initial}),
|
||||||
|
...initial,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
function weaponReqs(weapon) {
|
||||||
|
|
||||||
|
const {reqs} = weaponTypes.find( wt => wt.type === weapon.type ) ||{};
|
||||||
|
|
||||||
|
if(!reqs) return {};
|
||||||
|
|
||||||
|
if( typeof reqs === 'function' ) return reqs(weapon);
|
||||||
|
|
||||||
|
return reqs;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isBroadside = arcs => {
|
||||||
|
if( arcs.length !== 4 ) return false;
|
||||||
|
|
||||||
|
// that'd be A or F
|
||||||
|
return !arcs.some( a => a.length === 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
function beam_cost_mass({weaponClass, arcs}) {
|
||||||
|
console.log({weaponClass,arcs})
|
||||||
|
let mass;
|
||||||
|
|
||||||
|
if( weaponClass === 1 ) {
|
||||||
|
mass = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( weaponClass === 2 ) {
|
||||||
|
mass = 2 + (arcs.length > 3 ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( weaponClass == 3 ) {
|
||||||
|
mass = 4;
|
||||||
|
|
||||||
|
if( isBroadside(arcs) ) {
|
||||||
|
mass += 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mass += arcs.length - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( weaponClass == 4 ) {
|
||||||
|
mass = 8;
|
||||||
|
|
||||||
|
if( isBroadside(arcs) ) {
|
||||||
|
mass += 4;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mass += 2*(arcs.length - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
mass, cost: 3 * mass
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default dux;
|
@ -1,5 +1,5 @@
|
|||||||
import { browser } from "$app/env";
|
import { browser } from "$app/env";
|
||||||
import { readable, get } from "svelte/store";
|
import { readable, get, derived } from "svelte/store";
|
||||||
import { compose, applyMiddleware } from "redux";
|
import { compose, applyMiddleware } from "redux";
|
||||||
|
|
||||||
import shipDux from "../shipDux/index.js";
|
import shipDux from "../shipDux/index.js";
|
||||||
@ -20,7 +20,6 @@ export default () => {
|
|||||||
duxStore.subscribe(() => {
|
duxStore.subscribe(() => {
|
||||||
if (previous === duxStore.getState()) return;
|
if (previous === duxStore.getState()) return;
|
||||||
previous = duxStore.getState();
|
previous = duxStore.getState();
|
||||||
console.log("Setting!", previous);
|
|
||||||
set(previous);
|
set(previous);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -28,5 +27,6 @@ export default () => {
|
|||||||
return {
|
return {
|
||||||
dispatch: duxStore.dispatch,
|
dispatch: duxStore.dispatch,
|
||||||
state,
|
state,
|
||||||
|
shipMass: derived( state, state => state.reqs.mass )
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user