wip
This commit is contained in:
parent
0098e899c9
commit
3fb959d9f3
@ -1,4 +1,4 @@
|
|||||||
<div>
|
<div class="field">
|
||||||
{#if label}
|
{#if label}
|
||||||
<label>{label}</label>
|
<label>{label}</label>
|
||||||
{/if}
|
{/if}
|
||||||
|
17
src/lib/components/ShipEdit/Weaponry.story.svelte
Normal file
17
src/lib/components/ShipEdit/Weaponry.story.svelte
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<Hst.Story>
|
||||||
|
<Weaponry {weapons} />
|
||||||
|
</Hst.Story>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export let Hst;
|
||||||
|
import Weaponry from "./Weaponry.svelte";
|
||||||
|
import u from "@yanick/updeep-remeda";
|
||||||
|
import { weaponTypes } from "$lib/store/ship/weaponry/rules";
|
||||||
|
import Changelog from "../Changelog.svelte";
|
||||||
|
|
||||||
|
const weapons = [
|
||||||
|
weaponTypes.find(u.matches({ type: "beam" })).initial,
|
||||||
|
weaponTypes.find(u.matches({ type: "submunition" })).initial,
|
||||||
|
].map((specs, id) => ({ specs, id }));
|
||||||
|
console.log(weapons);
|
||||||
|
</script>
|
@ -2,14 +2,12 @@
|
|||||||
<Firecons {...firecons} />
|
<Firecons {...firecons} />
|
||||||
|
|
||||||
<ADFC {...adfc} />
|
<ADFC {...adfc} />
|
||||||
<!--
|
|
||||||
|
|
||||||
<AddWeapon />
|
<AddWeapon />
|
||||||
|
|
||||||
{#each weapons as weapon (weapon.id)}
|
{#each weapons as weapon (weapon.id)}
|
||||||
<Weapon {weapon} id={weapon.id} />
|
<Weapon {...weapon} />
|
||||||
{/each}
|
{/each}
|
||||||
-->
|
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -22,17 +20,14 @@
|
|||||||
|
|
||||||
import Firecons from "./Weaponry/Firecons.svelte";
|
import Firecons from "./Weaponry/Firecons.svelte";
|
||||||
import ADFC from "./Weaponry/ADFC.svelte";
|
import ADFC from "./Weaponry/ADFC.svelte";
|
||||||
|
import AddWeapon from "./Weaponry/AddWeapon.svelte";
|
||||||
|
|
||||||
export let firecons = {};
|
export let firecons = {};
|
||||||
export let adfc = {};
|
export let adfc = {};
|
||||||
/*
|
|
||||||
|
|
||||||
import AddWeapon from './AddWeapon.svelte';
|
import Weapon from "./Weaponry/Weapon/index.svelte";
|
||||||
import Weapon from './Weapon/index.svelte';
|
|
||||||
|
|
||||||
|
export let weapons = [];
|
||||||
export let weapons = [];
|
|
||||||
*/
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -1,24 +1,25 @@
|
|||||||
<Field label="weapon type">
|
<div>
|
||||||
<select bind:value={type}>
|
<Field label="">
|
||||||
{#each weaponTypes as weapon (weapon.type)}
|
<select bind:value={type}>
|
||||||
<option value={weapon.type}>{weapon.name}</option>
|
{#each weaponTypes as weapon (weapon.type)}
|
||||||
{/each}
|
<option value={weapon.type}>{weapon.name}</option>
|
||||||
</select>
|
{/each}
|
||||||
|
</select>
|
||||||
|
</Field>
|
||||||
<button class="button small primary" on:click={addWeapon}>add weapon</button>
|
<button class="button small primary" on:click={addWeapon}>add weapon</button>
|
||||||
</Field>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getContext } from "svelte";
|
import { getContext } from "svelte";
|
||||||
import Field from "../../Field.svelte";
|
import Field from "../../Field.svelte";
|
||||||
|
|
||||||
import { weaponTypes } from "$lib/shipDux/weaponry/weapons";
|
import { weaponTypes } from "$lib/store/ship/weaponry/rules";
|
||||||
|
|
||||||
export let ship = getContext("ship");
|
export let api = getContext("api");
|
||||||
|
|
||||||
let type = weaponTypes[0].value;
|
let type = weaponTypes[0].type;
|
||||||
|
|
||||||
const addWeapon = () => ship.dispatch.addWeapon(type);
|
const addWeapon = () => api?.dispatch?.addWeapon?.(type);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@ -26,4 +27,17 @@
|
|||||||
width: inherit;
|
width: inherit;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
button {
|
||||||
|
width: inherit;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
div :global(.field) {
|
||||||
|
display: flex;
|
||||||
|
margin-right: 2em;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
display: flex;
|
||||||
|
margin-left: 5em;
|
||||||
|
margin-bottom: 2em;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
<Hst.Story>
|
||||||
|
<Arcs />
|
||||||
|
</Hst.Story>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export let Hst;
|
||||||
|
import Arcs from "./Arcs.svelte";
|
||||||
|
</script>
|
@ -1,10 +1,10 @@
|
|||||||
<svg width="{size}px" height="{size}px">
|
<svg width="{size}px" height="{size}px">
|
||||||
{#each all_arcs as arc (arc)}
|
{#each arcs as arc (arc)}
|
||||||
<Arc
|
<Arc
|
||||||
{arc}
|
{arc}
|
||||||
radius={size / 2}
|
radius={size / 2}
|
||||||
active={selected.includes(arc)}
|
active={selected.includes(arc)}
|
||||||
on:click={() => click_arc(arc)}
|
on:click={() => clickArc(arc)}
|
||||||
/>
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
<circle cx="50%" cy="50%" r={size / 3} />
|
<circle cx="50%" cy="50%" r={size / 3} />
|
||||||
@ -12,17 +12,17 @@
|
|||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Arc from "./Arc.svelte";
|
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
|
|
||||||
const all_arcs = ["FS", "F", "FP", "AP", "A", "AS"];
|
import { arcs } from "$lib/store/ship/weaponry/rules";
|
||||||
|
import Arc from "./Arc.svelte";
|
||||||
|
|
||||||
export let selected = [];
|
export let selected = [];
|
||||||
export let size = 60;
|
export let size = 60;
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
const click_arc = (arc) => dispatch("click_arc", arc);
|
const clickArc = (arc) => dispatch("clickArc", arc);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
Before Width: | Height: | Size: 639 B After Width: | Height: | Size: 634 B |
@ -1,80 +1,93 @@
|
|||||||
<label>beam</label>
|
<label>beam</label>
|
||||||
|
|
||||||
<Field label="beam class">
|
<Field label="beam class">
|
||||||
<select bind:value={weaponClass}>
|
<select bind:value={weaponClass}>
|
||||||
<option value={1}>1</option>
|
<option value={1}>1</option>
|
||||||
<option value={2}>2</option>
|
<option value={2}>2</option>
|
||||||
<option value={3}>3</option>
|
<option value={3}>3</option>
|
||||||
<option value={4}>4</option>
|
<option value={4}>4</option>
|
||||||
</select>
|
</select>
|
||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
<Field label="arcs">
|
<Field label="arcs">
|
||||||
<select bind:value={nbrArcs}>
|
<select bind:value={nbrArcs}>
|
||||||
{#each arc_options[weaponClass] || [] as nbrArcs (nbrArcs)}
|
{#each arc_options[weaponClass] || [] as nbrArcs (nbrArcs)}
|
||||||
<option>{nbrArcs}</option>
|
<option>{nbrArcs}</option>
|
||||||
{/each}
|
{/each}
|
||||||
</select>
|
</select>
|
||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
<Arcs selected={arcs} on:click_arc={({ detail }) => setArcs(detail)} />
|
<Arcs selected={arcs} on:clickArc={({ detail }) => setArcs(detail)} />
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getContext } from "svelte";
|
import { getContext } from "svelte";
|
||||||
|
import * as R from "remeda";
|
||||||
|
|
||||||
import Arcs from "../Arcs.svelte";
|
import Arcs from "../Arcs.svelte";
|
||||||
import ShipItem from "$lib/components/ShipItem.svelte";
|
import ShipItem from "$lib/components/ShipItem.svelte";
|
||||||
import Field from "$lib/components/Field.svelte";
|
import Field from "$lib/components/Field.svelte";
|
||||||
|
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
|
import memoize from "memoize-one";
|
||||||
|
|
||||||
const all_arcs = ["FS", "F", "FP", "AP", "A", "AS"];
|
const all_arcs = ["FS", "F", "FP", "AP", "A", "AS"];
|
||||||
|
|
||||||
export let weaponClass = 1;
|
export let weaponClass = 1;
|
||||||
export let arcs = ["F"];
|
export let arcs = ["F"];
|
||||||
|
|
||||||
let arc_options = {
|
let arc_options = {
|
||||||
1: [6],
|
1: [6],
|
||||||
2: [3, 6],
|
2: [3, 6],
|
||||||
3: [1, 2, 3, 4, 5, 6, "broadside"],
|
3: [1, 2, 3, 4, 5, 6, "broadside"],
|
||||||
4: [1, 2, 3, 4, 5, 6, "broadside"],
|
4: [1, 2, 3, 4, 5, 6, "broadside"],
|
||||||
};
|
};
|
||||||
|
|
||||||
$: arcsCaches = arcs.join(',');
|
let nbrArcs = arcs.length;
|
||||||
|
|
||||||
let nbrArcs = arcs.length;
|
$: if (!arc_options[weaponClass].includes(nbrArcs)) {
|
||||||
|
nbrArcs = arc_options[weaponClass][0];
|
||||||
|
console.log({ nbrArcs, label: "in if" });
|
||||||
|
}
|
||||||
|
|
||||||
$: if (!arc_options[weaponClass].includes(nbrArcs)) {
|
const broadside = ["FS", "FP", "AP", "AS"];
|
||||||
nbrArcs = arc_options[weaponClass][0];
|
|
||||||
console.log({nbrArcs, label:"in if"})
|
function setArcs(firstArc) {
|
||||||
|
console.log(firstArc);
|
||||||
|
let newArcs;
|
||||||
|
if (nbrArcs === "broadside") {
|
||||||
|
newArcs = broadside;
|
||||||
|
} else {
|
||||||
|
let first_index = all_arcs.findIndex((arc) => arc === firstArc);
|
||||||
|
if (first_index === -1) first_index = 0;
|
||||||
|
|
||||||
|
newArcs = Array.from({ length: nbrArcs }).map(
|
||||||
|
(_dummy, i) => all_arcs[(first_index + i) % all_arcs.length]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const broadside = ["FS", "FP", "AP", "AS"];
|
$: console.log({ newArcs, arcs });
|
||||||
|
if (
|
||||||
|
arcs.length !== newArcs.length ||
|
||||||
function setArcs(firstArc) {
|
arcs.length !== R.intersection(arcs, newArcs).length
|
||||||
if (nbrArcs === "broadside") {
|
) {
|
||||||
arcs = broadside;
|
arcs = newArcs;
|
||||||
return;
|
|
||||||
}
|
|
||||||
let first_index = all_arcs.findIndex((arc) => arc === firstArc);
|
|
||||||
if (first_index === -1) first_index = 0;
|
|
||||||
|
|
||||||
arcs = Array.from({length: nbrArcs}).map(
|
|
||||||
(_dummy,i) => all_arcs[(first_index + i) % all_arcs.length]
|
|
||||||
);
|
|
||||||
arcsCaches = arcs.join(',');
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$: if (arcs.length !== nbrArcs) setArcs(arcs[0]);
|
$: if (arcs.length !== nbrArcs) setArcs(arcs[0]);
|
||||||
|
|
||||||
$: console.log("it changed!", arcs)
|
$: console.log("it changed!", arcs);
|
||||||
$: console.log("it changed!", arcsCaches)
|
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
$: dispatch("change", {
|
let i = 5;
|
||||||
weaponClass,
|
|
||||||
arcs: arcsCaches.split(','),
|
const memoChange = memoize((weaponClass, ...arcs) =>
|
||||||
});
|
dispatch("change", {
|
||||||
|
weaponClass,
|
||||||
|
arcs,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
$: memoChange(weaponClass, ...arcs);
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,27 +1,14 @@
|
|||||||
<label>needle weapon</label>
|
<label>needle weapon</label>
|
||||||
|
|
||||||
<Arcs selected={[arc]} on:click_arc={({ detail }) => click_arc(detail)} />
|
<Arcs selected={[arc]} on:clickArc={({ detail }) => clickArc(detail)} />
|
||||||
|
|
||||||
<script>
|
<script lang="ts">
|
||||||
import { getContext } from "svelte";
|
|
||||||
import Arcs from "./Arcs.svelte";
|
import Arcs from "./Arcs.svelte";
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
|
|
||||||
const all_arcs = ["FS", "F", "FP", "AP", "A", "AS"];
|
|
||||||
|
|
||||||
export let arc = "F";
|
export let arc = "F";
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
const click_arc = (arc) => {
|
const clickArc = (arc) => dispatch("change", { arc });
|
||||||
dispatch("change",{arc});
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
.arc {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
margin-right: 1em;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
@ -1,19 +1,16 @@
|
|||||||
<label>submunition pack</label>
|
<label>submunition pack</label>
|
||||||
|
|
||||||
<Arcs selected={[arc]} on:click_arc={({ detail }) => click_arc(detail)} />
|
<Arcs selected={[arc]} on:clickArc={({ detail }) => clickArc(detail)} />
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getContext } from "svelte";
|
|
||||||
import Arcs from "./Arcs.svelte";
|
import Arcs from "./Arcs.svelte";
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
|
|
||||||
const all_arcs = ["FS", "F", "FP", "AP", "A", "AS"];
|
|
||||||
|
|
||||||
export let arc = "F";
|
export let arc = "F";
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
const click_arc = (arc) => {
|
const clickArc = (arc) => {
|
||||||
dispatch("change",{arc});
|
dispatch("change", { arc });
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,15 +1,8 @@
|
|||||||
<ShipItem {...reqs}>
|
<ShipItem {...reqs}>
|
||||||
<div class="weapon_row">
|
<div class="weapon_row">
|
||||||
<button
|
<button class="button small red remove" on:click={remove}>remove </button>
|
||||||
class="button small red remove"
|
|
||||||
on:click={remove}>remove
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<svelte:component
|
<svelte:component this={component[type]} {...specs} on:change={update} />
|
||||||
this={component[type]}
|
|
||||||
{...weapon}
|
|
||||||
on:change={update}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</ShipItem>
|
</ShipItem>
|
||||||
|
|
||||||
@ -19,34 +12,33 @@
|
|||||||
import Arc from "./Arc.svelte";
|
import Arc from "./Arc.svelte";
|
||||||
import ShipItem from "$lib/components/ShipItem.svelte";
|
import ShipItem from "$lib/components/ShipItem.svelte";
|
||||||
import Field from "$lib/components/Field.svelte";
|
import Field from "$lib/components/Field.svelte";
|
||||||
import Beam from "./Beam/index.svelte";
|
import Beam from "./Beam/index.svelte";
|
||||||
import Submunition from "./Submunition.svelte";
|
import Submunition from "./Submunition.svelte";
|
||||||
import PointDefenceSystem from "./PDS.svelte";
|
import PointDefenceSystem from "./PDS.svelte";
|
||||||
import Scattergun from "./Scattergun.svelte";
|
import Scattergun from "./Scattergun.svelte";
|
||||||
import Needle from "./Needle.svelte";
|
import Needle from "./Needle.svelte";
|
||||||
|
|
||||||
const component = {
|
const component = {
|
||||||
beam: Beam,
|
beam: Beam,
|
||||||
submunition: Submunition,
|
submunition: Submunition,
|
||||||
pds: PointDefenceSystem,
|
pds: PointDefenceSystem,
|
||||||
scattergun: Scattergun,
|
scattergun: Scattergun,
|
||||||
needle: Needle,
|
needle: Needle,
|
||||||
};
|
};
|
||||||
|
|
||||||
export let weapon = {};
|
export let reqs = {};
|
||||||
$: reqs = weapon.reqs;
|
export let specs = {};
|
||||||
export let id;
|
export let id;
|
||||||
|
|
||||||
const ship = getContext("ship");
|
const api = getContext("api");
|
||||||
|
|
||||||
$: type = weapon.type;
|
$: type = specs.type;
|
||||||
|
|
||||||
const remove = () => ship.dispatch.removeWeapon(id);
|
const remove = () => api?.dispatch?.removeWeapon?.(id);
|
||||||
|
|
||||||
const update = ({ detail }) => {
|
const update = ({ detail }) => {
|
||||||
console.log({id,type})
|
console.log({ id, type });
|
||||||
ship.dispatch.setWeapon({
|
api?.dispatch?.setWeapon?.(id, {
|
||||||
id,
|
|
||||||
type,
|
type,
|
||||||
...detail,
|
...detail,
|
||||||
});
|
});
|
||||||
@ -54,6 +46,9 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
button {
|
||||||
|
width: inherit;
|
||||||
|
}
|
||||||
.weapon {
|
.weapon {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -47,4 +47,11 @@ test("kicking the tires", () => {
|
|||||||
mass: 6,
|
mass: 6,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
store.dispatch.addWeapon("beam");
|
||||||
|
expect(store.getState().weaponry.weapons[0]).toEqual({
|
||||||
|
id: 1,
|
||||||
|
reqs: { cost: 3, mass: 1 },
|
||||||
|
specs: { arcs: ["F"], type: "beam", weaponClass: 1 },
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -66,28 +66,40 @@ shipDux.addReaction((api) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
shipDux.addReaction((api) => (state) => {
|
shipDux.addReaction((api) => {
|
||||||
let cost = 0;
|
const setShipReqs = memoize((cost, usedMass) =>
|
||||||
let mass = 0;
|
api.dispatch.setShipReqs({ cost, usedMass })
|
||||||
|
);
|
||||||
|
|
||||||
let subsystems = R.values(R.omit(state, ["identification"]));
|
return (state) => {
|
||||||
|
let cost = 0;
|
||||||
|
let mass = 0;
|
||||||
|
|
||||||
while (subsystems.length > 0) {
|
let subsystems = R.values(R.omit(state, ["identification"]));
|
||||||
const subsystem = subsystems.shift();
|
|
||||||
if (typeof subsystem !== "object") continue;
|
|
||||||
|
|
||||||
if (subsystem.reqs) {
|
while (subsystems.length > 0) {
|
||||||
cost += subsystem.reqs.cost;
|
const subsystem = subsystems.shift();
|
||||||
mass += subsystem.reqs.mass;
|
if (typeof subsystem !== "object") continue;
|
||||||
|
|
||||||
|
if (subsystem.reqs) {
|
||||||
|
cost += subsystem.reqs.cost ?? 0;
|
||||||
|
mass += subsystem.reqs.mass ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
subsystems.push(...Object.values(subsystem));
|
||||||
}
|
}
|
||||||
|
|
||||||
subsystems.push(...Object.values(subsystem));
|
if (Number.isNaN(cost)) {
|
||||||
}
|
console.log(state.weaponry.weapons);
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
|
||||||
api.dispatch.setShipReqs({ cost, usedMass: mass });
|
setShipReqs(cost, mass);
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
shipDux.addEffect((api) => (next) => (action) => {
|
shipDux.addEffect((api) => (next) => (action) => {
|
||||||
|
console.log(action);
|
||||||
next(action);
|
next(action);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,58 +1,94 @@
|
|||||||
import type { Reqs } from "$lib/shipDux/reqs";
|
import type { Reqs } from "$lib/shipDux/reqs";
|
||||||
|
|
||||||
|
export const arcs = ["FS", "F", "FP", "AP", "A", "AS"] as const;
|
||||||
|
|
||||||
|
export type Arc = (typeof arcs)[number];
|
||||||
|
|
||||||
|
export type WeaponType = "beam";
|
||||||
|
|
||||||
|
type Beam = {
|
||||||
|
type: "beam";
|
||||||
|
weaponClass: 1 | 2 | 3 | 4;
|
||||||
|
arcs: Arc[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type Submunition = {
|
||||||
|
type: "submunition";
|
||||||
|
arc: Arc;
|
||||||
|
};
|
||||||
|
|
||||||
|
type PDS = {
|
||||||
|
type: "pds";
|
||||||
|
};
|
||||||
|
|
||||||
|
type Scattergun = { type: "scattergun" };
|
||||||
|
|
||||||
|
type Needle = { type: "needle"; arc: Arc };
|
||||||
|
|
||||||
|
export type Weapon = Beam | Submunition | PDS | Scattergun | Needle;
|
||||||
|
|
||||||
export const weaponTypes = [
|
export const weaponTypes = [
|
||||||
{
|
{
|
||||||
name: "beam",
|
|
||||||
type: "beam",
|
type: "beam",
|
||||||
|
name: "beam",
|
||||||
reqs: beamReqs,
|
reqs: beamReqs,
|
||||||
initial: {
|
initial: {
|
||||||
|
type: "beam",
|
||||||
weaponClass: 1,
|
weaponClass: 1,
|
||||||
},
|
arcs,
|
||||||
|
} as any as Beam,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "submunition pack",
|
|
||||||
type: "submunition",
|
type: "submunition",
|
||||||
|
name: "submunition pack",
|
||||||
reqs: { mass: 1, cost: 3 },
|
reqs: { mass: 1, cost: 3 },
|
||||||
initial: { arc: "F" },
|
initial: { type: "submunition", arc: "F" } as Submunition,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "point defence system",
|
name: "point defence system",
|
||||||
type: "pds",
|
type: "pds",
|
||||||
reqs: { mass: 1, cost: 3 },
|
reqs: { mass: 1, cost: 3 },
|
||||||
initial: {},
|
initial: {
|
||||||
|
type: "pds",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "scattergun",
|
name: "scattergun",
|
||||||
type: "scattergun",
|
type: "scattergun",
|
||||||
reqs: { mass: 1, cost: 4 },
|
reqs: { mass: 1, cost: 4 },
|
||||||
initial: {},
|
initial: { type: "scattergun" },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "needle weapon",
|
name: "needle weapon",
|
||||||
type: "needle",
|
type: "needle",
|
||||||
reqs: { mass: 2, cost: 6 },
|
reqs: { mass: 2, cost: 6 },
|
||||||
initial: { arc: "F" },
|
initial: { arc: "F", type: "needle" },
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export function weaponReqs(weapon): Reqs {
|
export function weaponReqs(weapon): Reqs {
|
||||||
const { reqs } = weaponTypes.find((wt) => wt.type === weapon.type) || {};
|
const { reqs } = weaponTypes.find((wt) => wt.type === weapon.type) || {};
|
||||||
|
|
||||||
if (!reqs) return {};
|
if (!reqs)
|
||||||
|
return {
|
||||||
|
cost: 0,
|
||||||
|
mass: 0,
|
||||||
|
};
|
||||||
|
|
||||||
if (typeof reqs === "function") return reqs(weapon);
|
if (typeof reqs === "function") return reqs(weapon);
|
||||||
|
|
||||||
return reqs;
|
return reqs;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isBroadside = (arcs) => {
|
const isBroadside = (arcs: Arc[]) => {
|
||||||
if (arcs.length !== 4) return false;
|
if (arcs.length !== 4) return false;
|
||||||
|
|
||||||
// that'd be A or F
|
// that'd be A or F
|
||||||
return !arcs.some((a) => a.length === 1);
|
return !arcs.some((a) => a.length === 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
function beamReqs({ weaponClass, arcs }) {
|
function beamReqs({ weaponClass, arcs }: Beam) {
|
||||||
|
console.log(weaponClass, arcs);
|
||||||
let mass;
|
let mass;
|
||||||
|
|
||||||
if (weaponClass === 1) {
|
if (weaponClass === 1) {
|
||||||
|
39
src/lib/store/ship/weaponry/weapons.test.ts
Normal file
39
src/lib/store/ship/weaponry/weapons.test.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { weaponsDux } from "./weapons";
|
||||||
|
import Debug from "debug";
|
||||||
|
const debug = Debug("aotds:weapons");
|
||||||
|
import u from "@yanick/updeep-remeda";
|
||||||
|
process.env.UPDEEP_MODE = "dangerously_never_freeze";
|
||||||
|
|
||||||
|
test("setWeapon", () => {
|
||||||
|
const store = weaponsDux.createStore();
|
||||||
|
|
||||||
|
store.dispatch.addWeapon("beam");
|
||||||
|
store.dispatch.addWeapon("submunition");
|
||||||
|
|
||||||
|
expect(store.getState()).toMatchObject([
|
||||||
|
{
|
||||||
|
specs: {
|
||||||
|
type: "beam",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
specs: {
|
||||||
|
type: "submunition",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
store.dispatch.setWeapon(1, {
|
||||||
|
type: "beam",
|
||||||
|
weaponClass: 2,
|
||||||
|
arcs: ["F", "FP", "FS"],
|
||||||
|
});
|
||||||
|
debug(store.getState());
|
||||||
|
expect(store.getState().find(u.matches({ id: 1 }))).toMatchObject({
|
||||||
|
specs: {
|
||||||
|
type: "beam",
|
||||||
|
weaponClass: 2,
|
||||||
|
arcs: ["FS", "F", "FP"],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
@ -2,23 +2,16 @@ import type { Reqs } from "$lib/shipDux/reqs";
|
|||||||
import Updux from "updux";
|
import Updux from "updux";
|
||||||
import u from "@yanick/updeep-remeda";
|
import u from "@yanick/updeep-remeda";
|
||||||
import * as R from "remeda";
|
import * as R from "remeda";
|
||||||
import { weaponReqs } from "./rules";
|
import { weaponReqs, weaponTypes, type WeaponType, type Weapon } from "./rules";
|
||||||
import { nanoid } from "@reduxjs/toolkit";
|
|
||||||
|
|
||||||
type Weapon = {
|
type IndexedWeapon = { id: number; reqs: Reqs; specs: Weapon };
|
||||||
weaponClass: string;
|
|
||||||
arcs?: unknown[];
|
|
||||||
type: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type IndexedWeapon = { id: string; reqs: Reqs; specs: Weapon };
|
|
||||||
|
|
||||||
export const weaponsDux = new Updux({
|
export const weaponsDux = new Updux({
|
||||||
initialState: [] as IndexedWeapon[],
|
initialState: [] as IndexedWeapon[],
|
||||||
actions: {
|
actions: {
|
||||||
removeWeapon: (id: string) => id,
|
removeWeapon: (id: string) => id,
|
||||||
setWeapon: (id: string, specs: Weapon) => ({ id, specs }),
|
setWeapon: (id: string, specs: Weapon) => ({ id, specs }),
|
||||||
addWeapon: (specs: Weapon) => specs,
|
addWeapon: (type: WeaponType) => type,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -26,20 +19,35 @@ weaponsDux.addMutation(weaponsDux.actions.removeWeapon, (id) =>
|
|||||||
R.reject(u.matches({ id }))
|
R.reject(u.matches({ id }))
|
||||||
);
|
);
|
||||||
|
|
||||||
weaponsDux.addMutation(
|
// TODO not needed anymore
|
||||||
weaponsDux.actions.setWeapon,
|
const mergeArcs = (newArcs) => (original) => {
|
||||||
({ id, specs }) =>
|
if (original === undefined) return undefined;
|
||||||
(state) => {
|
|
||||||
const weapon = state.find(u.matches({ id }));
|
let merged = u.filter(original, (a) => newArcs.includes(a));
|
||||||
if (!weapon) return;
|
|
||||||
weapon.specs = specs;
|
let toAdd = newArcs.filter((a) => !merged.includes(a));
|
||||||
weapon.reqs = weaponReqs(specs);
|
if (toAdd.length) return [...merged, ...toAdd];
|
||||||
}
|
|
||||||
|
return merged;
|
||||||
|
};
|
||||||
|
|
||||||
|
weaponsDux.addMutation(weaponsDux.actions.setWeapon, ({ id, specs }) =>
|
||||||
|
u.map(
|
||||||
|
u.if(u.matches({ id }), {
|
||||||
|
specs: {
|
||||||
|
...specs,
|
||||||
|
arcs: mergeArcs((specs as any).arcs),
|
||||||
|
},
|
||||||
|
reqs: weaponReqs(specs),
|
||||||
|
})
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
weaponsDux.addMutation(weaponsDux.actions.addWeapon, (specs) => (state) => {
|
weaponsDux.addMutation(weaponsDux.actions.addWeapon, (type) => (state) => {
|
||||||
|
const specs = weaponTypes.find(u.matches({ type }))?.initial ?? {};
|
||||||
|
const id = 1 + Math.max(0, ...state.map(R.prop("id")));
|
||||||
state.push({
|
state.push({
|
||||||
id: nanoid(),
|
id,
|
||||||
specs,
|
specs,
|
||||||
reqs: weaponReqs(specs),
|
reqs: weaponReqs(specs),
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user