got all subduxes in
This commit is contained in:
parent
0e76cdd4d3
commit
8bb1955dff
@ -2,44 +2,26 @@ import { combineReducers, createSlice } from "@reduxjs/toolkit";
|
||||
import { reqs } from "../reqs.js";
|
||||
import * as weapons from "./weapons.js";
|
||||
|
||||
const firecons = createSlice({
|
||||
name: "firecons",
|
||||
initialState: {
|
||||
stations: 0,
|
||||
reqs,
|
||||
},
|
||||
reducers: {
|
||||
setFirecons(state, action) {
|
||||
const stations = action.payload;
|
||||
state.stations = action.payload;
|
||||
state.reqs = {
|
||||
cost: 4 * stations,
|
||||
mass: stations,
|
||||
};
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const adfc = createSlice({
|
||||
name: "adfc",
|
||||
initialState: {
|
||||
rating: 0,
|
||||
reqs,
|
||||
},
|
||||
reducers: {
|
||||
setAdfc(state, action) {
|
||||
const rating = action.payload;
|
||||
state.rating = action.payload;
|
||||
state.reqs = {
|
||||
cost: 8 * rating,
|
||||
mass: 2 * rating,
|
||||
};
|
||||
},
|
||||
name: "adfc",
|
||||
initialState: {
|
||||
rating: 0,
|
||||
reqs,
|
||||
},
|
||||
reducers: {
|
||||
setAdfc(state, action) {
|
||||
const rating = action.payload;
|
||||
state.rating = action.payload;
|
||||
state.reqs = {
|
||||
cost: 8 * rating,
|
||||
mass: 2 * rating,
|
||||
};
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const reducer = combineReducers({
|
||||
adfc: adfc.reducer,
|
||||
firecons: firecons.reducer,
|
||||
weapons: weapons.reducer,
|
||||
adfc: adfc.reducer,
|
||||
firecons: firecons.reducer,
|
||||
weapons: weapons.reducer,
|
||||
});
|
||||
|
@ -36,4 +36,15 @@ test("kicking the tires", () => {
|
||||
cost: 0,
|
||||
},
|
||||
});
|
||||
|
||||
store.dispatch.setNbrArmorLayers(1);
|
||||
store.dispatch.setArmorRating(1, 3);
|
||||
|
||||
expect(store.getState().structure.armor).toEqual({
|
||||
layers: [3],
|
||||
reqs: {
|
||||
cost: 6,
|
||||
mass: 6,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
@ -13,27 +13,48 @@ import { calcStreamliningReqs } from "./ship/structure/rules";
|
||||
import { cargoDux } from "./ship/structure/cargo";
|
||||
import { hullDux } from "./ship/structure/hull";
|
||||
import { screensDux, screensReqsReaction } from "./ship/structure/screens";
|
||||
import { armorDux } from "./ship/structure/armor";
|
||||
import { fireconsDux } from "./ship/weaponry/firecons";
|
||||
import { adfcDux } from "./ship/weaponry/adfc";
|
||||
import { weaponsDux } from "./ship/weaponry/weapons";
|
||||
|
||||
process.env.UPDEEP_MODE = "dangerously_never_freeze";
|
||||
|
||||
const structure = new Updux({
|
||||
initialState: {},
|
||||
subduxes: {
|
||||
streamlining,
|
||||
cargo: cargoDux,
|
||||
hull: hullDux,
|
||||
screens: screensDux,
|
||||
armor: armorDux,
|
||||
},
|
||||
});
|
||||
|
||||
const propulsion = new Updux({
|
||||
initialState: {},
|
||||
subduxes: {
|
||||
ftl,
|
||||
drive,
|
||||
},
|
||||
});
|
||||
|
||||
const weaponry = new Updux({
|
||||
initialState: {},
|
||||
subduxes: {
|
||||
adfc: adfcDux,
|
||||
firecons: fireconsDux,
|
||||
weapons: weaponsDux,
|
||||
},
|
||||
});
|
||||
|
||||
const shipDux = new Updux({
|
||||
subduxes: {
|
||||
identification,
|
||||
structure: new Updux({
|
||||
initialState: {},
|
||||
subduxes: {
|
||||
streamlining,
|
||||
cargo: cargoDux,
|
||||
hull: hullDux,
|
||||
screens: screensDux,
|
||||
},
|
||||
}),
|
||||
propulsion: new Updux({
|
||||
initialState: {},
|
||||
subduxes: {
|
||||
ftl,
|
||||
drive,
|
||||
},
|
||||
}),
|
||||
structure,
|
||||
propulsion,
|
||||
carrier: carrierDux,
|
||||
weaponry,
|
||||
},
|
||||
});
|
||||
|
||||
|
52
src/lib/store/ship/structure/armor.ts
Normal file
52
src/lib/store/ship/structure/armor.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import { reqs, type Reqs } from "$lib/shipDux/reqs";
|
||||
import Updux, { createPayloadAction } from "updux";
|
||||
import u from "@yanick/updeep-remeda";
|
||||
import { createSelector } from "reselect";
|
||||
import prepare from "immer";
|
||||
|
||||
type Layer = number;
|
||||
|
||||
const initialState = {
|
||||
reqs,
|
||||
layers: [] as Layer[],
|
||||
};
|
||||
|
||||
const setNbrArmorLayers = createPayloadAction<number>("setNbrArmorLayers");
|
||||
const setArmorRating = createPayloadAction(
|
||||
"setArmorRating",
|
||||
(id: number, rating: number) => ({ index: id - 1, rating })
|
||||
);
|
||||
|
||||
export const armorDux = new Updux({
|
||||
initialState,
|
||||
actions: { setNbrArmorLayers, setArmorRating },
|
||||
});
|
||||
|
||||
armorDux.addMutation(setArmorRating, ({ index, rating }) =>
|
||||
prepare((state) => {
|
||||
state.layers[index] = rating;
|
||||
state.reqs = calcArmorReqs(state.layers);
|
||||
})
|
||||
);
|
||||
|
||||
armorDux.addMutation(setNbrArmorLayers, (nbrLayers) =>
|
||||
prepare((state) => {
|
||||
while (state.layers.length > nbrLayers) {
|
||||
state.layers.pop();
|
||||
}
|
||||
while (state.layers.length < nbrLayers) {
|
||||
state.layers.push(0);
|
||||
}
|
||||
state.reqs = calcArmorReqs(state.layers);
|
||||
})
|
||||
);
|
||||
|
||||
function calcArmorReqs(layers: Layer[]): Reqs {
|
||||
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,
|
||||
};
|
||||
}
|
20
src/lib/store/ship/weaponry/adfc.ts
Normal file
20
src/lib/store/ship/weaponry/adfc.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { reqs } from "$lib/shipDux/reqs";
|
||||
import Updux, { createPayloadAction } from "updux";
|
||||
import u from "@yanick/updeep-remeda";
|
||||
|
||||
export const adfcDux = new Updux({
|
||||
initialState: {
|
||||
rating: 0,
|
||||
reqs,
|
||||
},
|
||||
actions: {
|
||||
setADFC: (rating: number) => rating,
|
||||
},
|
||||
});
|
||||
|
||||
adfcDux.addMutation(adfcDux.actions.setADFC, (rating) =>
|
||||
u({
|
||||
rating,
|
||||
reqs: { cost: 8 * rating, mass: 2 * rating },
|
||||
})
|
||||
);
|
20
src/lib/store/ship/weaponry/firecons.ts
Normal file
20
src/lib/store/ship/weaponry/firecons.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { reqs } from "$lib/shipDux/reqs";
|
||||
import Updux, { createPayloadAction } from "updux";
|
||||
import u from "@yanick/updeep-remeda";
|
||||
|
||||
export const fireconsDux = new Updux({
|
||||
initialState: {
|
||||
stations: 0,
|
||||
reqs,
|
||||
},
|
||||
actions: {
|
||||
setFirecons: (stations: number) => stations,
|
||||
},
|
||||
});
|
||||
|
||||
fireconsDux.addMutation(fireconsDux.actions.setFirecons, (stations) =>
|
||||
u({
|
||||
stations,
|
||||
reqs: { cost: 4 * stations, mass: stations },
|
||||
})
|
||||
);
|
90
src/lib/store/ship/weaponry/rules.ts
Normal file
90
src/lib/store/ship/weaponry/rules.ts
Normal file
@ -0,0 +1,90 @@
|
||||
import type { Reqs } from "$lib/shipDux/reqs";
|
||||
|
||||
export const weaponTypes = [
|
||||
{
|
||||
name: "beam",
|
||||
type: "beam",
|
||||
reqs: beamReqs,
|
||||
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" },
|
||||
},
|
||||
];
|
||||
|
||||
export function weaponReqs(weapon): Reqs {
|
||||
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 beamReqs({ 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,
|
||||
};
|
||||
}
|
46
src/lib/store/ship/weaponry/weapons.ts
Normal file
46
src/lib/store/ship/weaponry/weapons.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import type { Reqs } from "$lib/shipDux/reqs";
|
||||
import Updux from "updux";
|
||||
import u from "@yanick/updeep-remeda";
|
||||
import * as R from "remeda";
|
||||
import { weaponReqs } from "./rules";
|
||||
import { nanoid } from "@reduxjs/toolkit";
|
||||
|
||||
type Weapon = {
|
||||
weaponClass: string;
|
||||
arcs?: unknown[];
|
||||
type: string;
|
||||
};
|
||||
|
||||
type IndexedWeapon = { id: string; reqs: Reqs; specs: Weapon };
|
||||
|
||||
export const weaponsDux = new Updux({
|
||||
initialState: [] as IndexedWeapon[],
|
||||
actions: {
|
||||
removeWeapon: (id: string) => id,
|
||||
setWeapon: (id: string, specs: Weapon) => ({ id, specs }),
|
||||
addWeapon: (specs: Weapon) => specs,
|
||||
},
|
||||
});
|
||||
|
||||
weaponsDux.addMutation(weaponsDux.actions.removeWeapon, (id) =>
|
||||
R.reject(u.matches({ id }))
|
||||
);
|
||||
|
||||
weaponsDux.addMutation(
|
||||
weaponsDux.actions.setWeapon,
|
||||
({ id, specs }) =>
|
||||
(state) => {
|
||||
const weapon = state.find(u.matches({ id }));
|
||||
if (!weapon) return;
|
||||
weapon.specs = specs;
|
||||
weapon.reqs = weaponReqs(specs);
|
||||
}
|
||||
);
|
||||
|
||||
weaponsDux.addMutation(weaponsDux.actions.addWeapon, (specs) => (state) => {
|
||||
state.push({
|
||||
id: nanoid(),
|
||||
specs,
|
||||
reqs: weaponReqs(specs),
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user