diff --git a/src/types/Construction.svelte b/src/types/Construction.svelte
index 81cb1d7..6af8c2a 100644
--- a/src/types/Construction.svelte
+++ b/src/types/Construction.svelte
@@ -20,10 +20,14 @@ const _context = "Construction";
interface Props {
construction: Construction;
includeTitle?: boolean;
+ includeRequires?: boolean;
}
-let { construction: sourceConstruction, includeTitle = false }: Props =
- $props();
+let {
+ construction: sourceConstruction,
+ includeTitle = false,
+ includeRequires = true,
+}: Props = $props();
const construction = untrack(() => sourceConstruction);
const using =
@@ -68,9 +72,13 @@ if (construction.pre_flags)
- {t("Required Skills")}
-
- {#each construction.required_skills ?? [] as [id, level], i}
- ({level}){#if i + 2 === construction.required_skills?.length}{" and "}{:else if i + 1 !== construction.required_skills?.length}{", "}{/if}
- {/each}
+ {#if construction.required_skills?.length}
+ {#each construction.required_skills as [id, level], i}
+ ({level}){#if i + 2 === construction.required_skills?.length}{" and "}{:else if i + 1 !== construction.required_skills?.length}{", "}{/if}
+ {/each}
+ {:else}
+ {t("none")}
+ {/if}
- {t("Time", { _context })}
-
@@ -78,7 +86,7 @@ if (construction.pre_flags)
? `${construction.time} m`
: (construction.time ?? "0 m")}
- {#if prerequisites.length}
+ {#if includeRequires && prerequisites.length}
- {t("Requires", { _context })}
-
diff --git a/src/types/Furniture.svelte b/src/types/Furniture.svelte
index 8ed6a26..e9b1c33 100644
--- a/src/types/Furniture.svelte
+++ b/src/types/Furniture.svelte
@@ -46,6 +46,12 @@ const constructions = data
.byType("construction")
.filter((c) => c.post_furniture === item.id);
+const deconstructions = data
+ .byType("construction")
+ .filter(
+ (c) => c.pre_special === "check_deconstruct" && c.pre_furniture === item.id,
+ );
+
const bashedFrom = data
.byType("furniture")
.filter((f) => f.id && f.bash?.furn_set === item.id);
@@ -173,7 +179,14 @@ const pseudo_items: string[] = asArray(item.crafting_pseudo_item);
{#if constructions.length}
{t("Construction", { _context })}
{#each constructions as construction}
-
+
+ {/each}
+{/if}
+
+{#if deconstructions.length}
+ {t("Deconstruction", { _context })}
+ {#each deconstructions as construction}
+
{/each}
{/if}
diff --git a/src/types/Furniture.test.ts b/src/types/Furniture.test.ts
index 78647ec..cd4e2f0 100644
--- a/src/types/Furniture.test.ts
+++ b/src/types/Furniture.test.ts
@@ -1,7 +1,7 @@
/**
* @vitest-environment happy-dom
*/
-import { render } from "@testing-library/svelte";
+import { render, within } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
import WithData from "../WithData.svelte";
import { CBNData } from "../data";
@@ -64,4 +64,87 @@ describe("Furniture", () => {
expect(getByText("Build Sign")).toBeTruthy();
expect(queryByText("Dig Pit")).toBeNull();
});
+
+ it("shows deconstruction methods and required tools for advanced furniture removal", () => {
+ const data = new CBNData([
+ {
+ type: "construction_group",
+ id: "advanced_object_deconstruction",
+ name: "Advanced Object Deconstruction",
+ },
+ {
+ type: "requirement",
+ id: "object_deconstruction_advanced",
+ qualities: [
+ { id: "HAMMER", level: 2 },
+ { id: "CHISEL", level: 2 },
+ { id: "PRY", level: 3 },
+ { id: "SCREW", level: 1 },
+ ],
+ },
+ {
+ type: "tool_quality",
+ id: "HAMMER",
+ name: "hammering",
+ },
+ {
+ type: "tool_quality",
+ id: "CHISEL",
+ name: "chiseling",
+ },
+ {
+ type: "tool_quality",
+ id: "PRY",
+ name: "prying",
+ },
+ {
+ type: "tool_quality",
+ id: "SCREW",
+ name: "screw driving",
+ },
+ {
+ type: "construction",
+ id: "constr_remove_object_fireplace",
+ group: "advanced_object_deconstruction",
+ category: "OTHER",
+ time: "90 m",
+ required_skills: [["fabrication", 2]],
+ using: "object_deconstruction_advanced",
+ pre_furniture: "f_fireplace",
+ pre_special: "check_deconstruct",
+ },
+ {
+ type: "furniture",
+ id: "f_fireplace",
+ name: "fireplace",
+ description: "A warm test fixture.",
+ move_cost_mod: 0,
+ required_str: 0,
+ },
+ ]);
+
+ const { getByText } = render(WithData, {
+ Component: Furniture,
+ data,
+ item: data.byId("furniture", "f_fireplace"),
+ });
+
+ expect(getByText("Deconstruction")).toBeTruthy();
+ expect(getByText("Tools Required")).toBeTruthy();
+ expect(getByText("hammering")).toBeTruthy();
+ expect(getByText("chiseling")).toBeTruthy();
+ expect(getByText("prying")).toBeTruthy();
+ expect(getByText("screw driving")).toBeTruthy();
+
+ const hiddenRequires = render(WithData, {
+ Component: Furniture,
+ data,
+ item: data.byId("furniture", "f_fireplace"),
+ includeRequires: false,
+ });
+
+ const hiddenQueries = within(hiddenRequires.container);
+
+ expect(hiddenQueries.queryByText("Requires")).toBeNull();
+ });
});
diff --git a/src/types/Terrain.svelte b/src/types/Terrain.svelte
index 764dc75..5c71748 100644
--- a/src/types/Terrain.svelte
+++ b/src/types/Terrain.svelte
@@ -50,6 +50,12 @@ const bits = [
const constructions = data
.byType("construction")
.filter((c) => c.post_terrain === item.id);
+
+const deconstructions = data
+ .byType("construction")
+ .filter(
+ (c) => c.pre_special === "check_deconstruct" && c.pre_terrain === item.id,
+ );
@@ -129,4 +135,11 @@ const constructions = data
{/each}
{/if}
+{#if deconstructions.length}
+ {t("Deconstruction", { _context })}
+ {#each deconstructions as construction}
+
+ {/each}
+{/if}
+
diff --git a/src/types/Terrain.test.ts b/src/types/Terrain.test.ts
new file mode 100644
index 0000000..e17eec0
--- /dev/null
+++ b/src/types/Terrain.test.ts
@@ -0,0 +1,61 @@
+/**
+ * @vitest-environment happy-dom
+ */
+import { render } from "@testing-library/svelte";
+import { describe, expect, it } from "vitest";
+import WithData from "../WithData.svelte";
+import { CBNData } from "../data";
+import Terrain from "./Terrain.svelte";
+
+describe("Terrain", () => {
+ it("shows deconstruction methods and required tools for advanced terrain removal", () => {
+ const data = new CBNData([
+ {
+ type: "construction_group",
+ id: "advanced_object_deconstruction",
+ name: "Advanced Object Deconstruction",
+ },
+ {
+ type: "tool_quality",
+ id: "SCREW",
+ name: "screw driving",
+ },
+ {
+ type: "construction",
+ id: "constr_remove_t_console",
+ group: "advanced_object_deconstruction",
+ category: "OTHER",
+ time: "20 m",
+ required_skills: [["electronics", 0]],
+ qualities: [{ id: "SCREW", level: 1 }],
+ pre_terrain: "t_console",
+ pre_special: "check_deconstruct",
+ },
+ {
+ type: "terrain",
+ id: "t_console",
+ name: "console",
+ description: "A test console.",
+ },
+ ]);
+
+ const { getByText } = render(WithData, {
+ Component: Terrain,
+ data,
+ item: data.byId("terrain", "t_console"),
+ });
+
+ expect(getByText("Deconstruction")).toBeTruthy();
+ expect(getByText("Tools Required")).toBeTruthy();
+ expect(getByText("screw driving")).toBeTruthy();
+
+ const { queryByText } = render(WithData, {
+ Component: Terrain,
+ data,
+ item: data.byId("terrain", "t_console"),
+ includeRequires: false,
+ });
+
+ expect(queryByText("Requires")).toBeNull();
+ });
+});