Skip to content
53 changes: 36 additions & 17 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -792,20 +792,38 @@ export type ActivityDataCommon = {
item: string; // item_id
count?: number | [number, number];
}[];
prying_data?: {
prying_nails?: boolean;
difficulty?: integer;
prying_level?: integer;
noisy?: boolean;
alarm?: boolean;
breakable?: boolean;
failure?: Translation;
};

result?: string;
message?: Translation;
sound?: Translation;
};

export type PryDataCommon = {
pry_quality?: integer; // default: -1
pry_bonus_mult?: integer; // default: 1
difficulty?: integer; // default: 1
noise?: integer; // default: 0
break_noise?: integer; // default: noise
alarm?: boolean; // default: false
breakable?: boolean; // default: false
pry_items?: ItemGroupEntry[];
break_items?: ItemGroupEntry[];
sound?: Translation;
break_sound?: Translation;
success_message?: Translation;
fail_message?: Translation;
break_message?: Translation;
};

export type TerrainPryData = PryDataCommon & {
new_ter_type?: string; // terrain_id, default: t_null
break_ter_type?: string; // terrain_id, default: t_null
};

export type FurniturePryData = PryDataCommon & {
new_furn_type?: string; // furniture_id, default: f_null
break_furn_type?: string; // furniture_id, default: f_null
};

export type MapDataCommon = {
color?: string | [string] | [string, string, string, string];
bgcolor?: string | [string] | [string, string, string, string];
Expand Down Expand Up @@ -849,10 +867,10 @@ export type Terrain = MapDataCommon & {
| { type: "cardreader" }
| { type: "effect_on_condition" };

oxytorch?: ActivityDataCommon & { result: string };
boltcut?: ActivityDataCommon & { result: string };
hacksaw?: ActivityDataCommon & { result: string };
prying?: ActivityDataCommon & { result: string };
oxytorch?: ActivityDataCommon;
boltcut?: ActivityDataCommon;
hacksaw?: ActivityDataCommon;
pry?: TerrainPryData;
};

export type Furniture = MapDataCommon & {
Expand Down Expand Up @@ -880,9 +898,10 @@ export type Furniture = MapDataCommon & {
bash?: MapBashInfo;
deconstruct?: MapDeconstructInfo;

oxytorch?: ActivityDataCommon & { result?: string };
boltcut?: ActivityDataCommon & { result?: string };
hacksaw?: ActivityDataCommon & { result?: string };
oxytorch?: ActivityDataCommon;
boltcut?: ActivityDataCommon;
hacksaw?: ActivityDataCommon;
pry?: FurniturePryData;

// TODO:
// open
Expand Down
7 changes: 7 additions & 0 deletions src/types/Furniture.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import FurnitureSpawnedIn from "./item/FurnitureSpawnedIn.svelte";
import LimitedList from "../LimitedList.svelte";
import HarvestedTo from "./item/HarvestedTo.svelte";
import { gameSingular } from "../i18n/game-locale";
import TerFurnPry from "./TerFurnPry.svelte";

const data = getContext<CBNData>("data");
const _context = "Terrain / Furniture";
Expand Down Expand Up @@ -111,6 +112,12 @@ const pseudo_items: string[] = asArray(item.crafting_pseudo_item);
<TerFurnActivity act={item.oxytorch} resultType="furniture" />
</dd>
{/if}
{#if item.pry}
<dt><ThingLink type="item_action" id="CROWBAR" showIcon={false} /></dt>
<dd>
<TerFurnPry act={item.pry} resultType="furniture" />
</dd>
{/if}
{#if deconstruct.length}
<dt>{t("Deconstruct", { _context })}</dt>
<dd>
Expand Down
56 changes: 56 additions & 0 deletions src/types/Furniture.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,62 @@ import { makeTestCBNData } from "../data.test-helpers";
import Furniture from "./Furniture.svelte";

describe("Furniture", () => {
it("shows pry details from the real furniture pry data", () => {
const data = makeTestCBNData([
{
type: "tool_quality",
id: "PRY",
name: "prying",
},
{
type: "furniture",
id: "f_coffin_c",
name: "closed coffin",
description: "A sealed test coffin.",
move_cost_mod: 0,
required_str: 0,
pry: {
pry_quality: 1,
noise: 12,
difficulty: 7,
new_furn_type: "f_coffin_o",
},
},
{
type: "furniture",
id: "f_coffin_o",
name: "open coffin",
description: "The lid has yielded.",
move_cost_mod: 0,
required_str: 0,
},
]);

const { getByText, queryByText } = render(WithData, {
Component: Furniture,
data,
item: data.byId("furniture", "f_coffin_c"),
});

const requiresDefinition = getByText("Requires").nextElementSibling;
const difficultyDefinition = getByText("Difficulty").nextElementSibling;
const becomesDefinition = getByText("Becomes").nextElementSibling;

expect(requiresDefinition).toBeTruthy();
expect(
within(requiresDefinition as HTMLElement).getByText("prying"),
).toBeTruthy();
expect(difficultyDefinition).toBeTruthy();
expect(
within(difficultyDefinition as HTMLElement).getByText("7"),
).toBeTruthy();
expect(becomesDefinition).toBeTruthy();
expect(
within(becomesDefinition as HTMLElement).getByText("open coffin"),
).toBeTruthy();
expect(queryByText("Duration")).toBeNull();
});

it("shows furniture constructions from post_furniture", () => {
const data = makeTestCBNData([
{
Expand Down
62 changes: 28 additions & 34 deletions src/types/TerFurnActivity.svelte
Original file line number Diff line number Diff line change
@@ -1,58 +1,52 @@
<script lang="ts">
import { t } from "@transifex/native";
import type { CBNData } from "src/data";
import type { ActivityDataCommon } from "src/types";
import { getContext } from "svelte";
import ThingLink from "./ThingLink.svelte";
import { untrack } from "svelte";

interface Props {
act: ActivityDataCommon & { result?: string };
act: ActivityDataCommon;
resultType: "terrain" | "furniture";
}

let { act, resultType }: Props = $props();

const data = getContext<CBNData>("data");
function visibleResult(
value: ActivityDataCommon,
resultType: "terrain" | "furniture",
): string | undefined {
if (value.result === (resultType === "terrain" ? "t_null" : "f_null")) {
return undefined;
}
return value.result;
}

const activity = untrack(() => act);
const result = untrack(() => visibleResult(act, resultType));

const _context = "Terrain / Furniture";
const _comment = "activity (prying, hacksawing, etc.)";
const _comment = "activity (oxytorch, hacksaw, boltcut, etc.)";
</script>

<ul class="comma-separated">
{#each act.byproducts ?? [] as { item: i, count }}
<li>
<ThingLink
id={i}
type="item"
showIcon={false} />{#if typeof count === "number"}&nbsp;({count}){:else if Array.isArray(count)}&nbsp;({count[0]}–{count[1]}){/if}
</li>
{/each}
</ul>
<dl>
<dt>{t("Duration", { _context, _comment })}</dt>
<dd>{act.duration ?? "1 s"}</dd>
{#if act.prying_data}
<dt>{t("Difficulty", { _context, _comment })}</dt>
<dd>{act.prying_data.difficulty ?? 0}</dd>
<dt>{t("Requires", { _context, _comment })}</dt>
<dd>{activity.duration ?? "1 s"}</dd>
{#if result}
<dt>{t("Becomes", { _context, _comment })}</dt>
<dd>
<ThingLink id="PRY" type="tool_quality" showIcon={false} />
{act.prying_data.prying_level ?? 0}{#if act.prying_data.prying_nails}, <ThingLink
id="PRYING_NAIL"
type="tool_quality"
showIcon={false} />&nbsp;1{/if}
<ThingLink id={result} type={resultType} showIcon={false} />
</dd>
<dt>{t("Noisy", { _context, _comment })}</dt>
<dd>{act.prying_data.noisy ? t("Yes") : t("No")}</dd>
<dt>{t("Alarm", { _context, _comment })}</dt>
<dd>{act.prying_data.alarm ? t("Yes") : t("No")}</dd>
<dt>{t("Breakable", { _context, _comment })}</dt>
<dd>{act.prying_data.breakable ? t("Yes") : t("No")}</dd>
{/if}
{#if act.result && act.result !== "t_null"}
<dt>{t("Result", { _context, _comment })}</dt>
{#if activity.byproducts}
<dt>{t("Byproducts", { _context, _comment })}</dt>
<dd>
<ThingLink id={act.result} type={resultType} />
<ul class="comma-separated">
{#each activity.byproducts ?? [] as { item: i, count }}
<li>
<ThingLink id={i} type="item" showIcon={false} {count} />
</li>
{/each}
</ul>
</dd>
{/if}
</dl>
109 changes: 109 additions & 0 deletions src/types/TerFurnPry.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<script lang="ts">
import { t } from "@transifex/native";
import { CBNData } from "../data";
import type { FurniturePryData, TerrainPryData } from "src/types";
import { getContext, untrack } from "svelte";
import ThingLink from "./ThingLink.svelte";

type PryData = TerrainPryData | FurniturePryData;

interface Props {
act: PryData;
resultType: "terrain" | "furniture";
}

let { act, resultType }: Props = $props();
const data = getContext<CBNData>("data");

const pry = untrack(() => act);
const result = untrack(() => visibleResult(act, resultType));
const pryItems = untrack(() =>
data.flattenItemGroup({
subtype: "collection",
entries: act.pry_items ?? [],
}),
);
const breakItems = untrack(() =>
data.flattenItemGroup({
subtype: "collection",
entries: act.break_items ?? [],
}),
);

function visibleResult(
value: PryData,
resultType: "terrain" | "furniture",
): string | undefined {
let result = undefined;
if (resultType === "terrain") {
result = "new_ter_type" in value ? value.new_ter_type : undefined;
} else if (resultType === "furniture") {
result = "new_furn_type" in value ? value.new_furn_type : undefined;
}
if (result === (resultType === "terrain" ? "t_null" : "f_null")) {
return undefined;
}
return result;
}

const _context = "Terrain / Furniture";
const _comment = "prying";
</script>

<dl>
<dt>{t("Difficulty", { _context, _comment })}</dt>
<dd>{pry.difficulty ?? 1}</dd>
<dt>{t("Requires", { _context, _comment })}</dt>
<dd>
<ThingLink id="PRY" type="tool_quality" showIcon={false} />
{pry.pry_quality ?? 0}
</dd>
<dt>{t("Alarm", { _context, _comment })}</dt>
<dd>{pry.alarm ? t("Yes") : t("No")}</dd>
<dt>{t("Noise", { _context, _comment })}</dt>
<dd>{pry.noise ?? 0}</dd>
<dt>{t("Breakable", { _context, _comment })}</dt>
<dd>{pry.breakable ? t("Yes") : t("No")}</dd>
Comment thread
ushkinaz marked this conversation as resolved.
{#if pry.breakable}
<dt>{t("Break noise", { _context, _comment })}</dt>
<dd>{pry.break_noise ?? 0}</dd>
{#if breakItems.length}
<dt>{t("Break Items", { _context, _comment })}</dt>
<dd>
<ul class="comma-separated">
{#each breakItems as entry}
<li>
<ThingLink
id={entry.id}
type="item"
showIcon={false}
count={entry.count} />
</li>
{/each}
</ul>
</dd>
{/if}
{/if}
Comment thread
ushkinaz marked this conversation as resolved.
{#if pryItems.length}
<dt>{t("Pry Items", { _context, _comment })}</dt>
<dd>
<ul class="comma-separated">
{#each pryItems as entry}
<li>
<ThingLink
id={entry.id}
type="item"
showIcon={false}
count={entry.count} />
</li>
{/each}
</ul>
</dd>
{/if}
{#if result}
<dt>{t("Becomes", { _context, _comment })}</dt>
<dd>
<ThingLink id={result} type={resultType} showIcon={false} />
</dd>
{/if}
Comment thread
ushkinaz marked this conversation as resolved.
</dl>
5 changes: 3 additions & 2 deletions src/types/Terrain.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import TerFurnActivity from "./TerFurnActivity.svelte";
import TerrainSpawnedIn from "./item/TerrainSpawnedIn.svelte";
import HarvestedTo from "./item/HarvestedTo.svelte";
import { gameSingular } from "../i18n/game-locale";
import TerFurnPry from "./TerFurnPry.svelte";

const data = getContext<CBNData>("data");
const _context = "Terrain / Furniture";
Expand Down Expand Up @@ -87,10 +88,10 @@ const deconstructions = data
<TerFurnActivity act={item.oxytorch} resultType="terrain" />
</dd>
{/if}
{#if item.prying}
{#if item.pry}
<dt><ThingLink type="item_action" id="CROWBAR" showIcon={false} /></dt>
<dd>
<TerFurnActivity act={item.prying} resultType="terrain" />
<TerFurnPry act={item.pry} resultType="terrain" />
</dd>
{/if}
{#if deconstruct.length || item.deconstruct?.ter_set}
Expand Down
Loading
Loading