feat(content): add action story hints and merge GameContent

This commit is contained in:
ginnoir
2026-06-11 18:50:01 -05:00
parent a66a7db066
commit c7d1f3f51b
4 changed files with 41 additions and 3 deletions
+24
View File
@@ -124,3 +124,27 @@ describe('unlock conditions', () => {
expect(content.actionsById.forage.unlock).toBeUndefined(); expect(content.actionsById.forage.unlock).toBeUndefined();
}); });
}); });
describe('action narrative fields', () => {
it('accepts optional storyHint and storyTooltip', () => {
const actions = [
{
id: 'forage',
name: 'Forage',
durationMs: 3000,
yields: [{ resourceId: 'gold', amount: 1 }],
storyHint: 'Gather what the forest offers.',
storyTooltip: 'Your first step into the wild.',
},
];
const content = buildContent({ resources: validResources, actions });
expect(content.actionsById.forage.storyHint).toBe('Gather what the forest offers.');
expect(content.actionsById.forage.storyTooltip).toBe('Your first step into the wild.');
});
it('defaults storyHint and storyTooltip to undefined when omitted', () => {
const content = buildContent({ resources: validResources, actions: validActions });
expect(content.actionsById.forage.storyHint).toBeUndefined();
expect(content.actionsById.forage.storyTooltip).toBeUndefined();
});
});
+8 -3
View File
@@ -1,7 +1,12 @@
import { actionDefs, resourceDefs } from './definitions'; import { actionDefs, resourceDefs } from './definitions';
import { buildContent } from './schema'; import { buildContent, type Content } from './schema';
import { buildStoryContent, type StoryContent } from './storySchema';
import { storyNodeDefs } from './story';
/** The validated, indexed content the engine and view consume. */ const base = buildContent({ resources: resourceDefs, actions: actionDefs });
export const content = buildContent({ resources: resourceDefs, actions: actionDefs }); const story = buildStoryContent(storyNodeDefs, base.actionsById, base.resourcesById);
export type GameContent = Content & StoryContent;
export const content: GameContent = { ...base, ...story };
export type { ActionDef, Content, ResourceDef } from './schema'; export type { ActionDef, Content, ResourceDef } from './schema';
+2
View File
@@ -32,6 +32,8 @@ export const actionDefSchema = z.object({
costs: z.array(resourceAmountSchema).default([]), costs: z.array(resourceAmountSchema).default([]),
yields: z.array(resourceAmountSchema).min(1), yields: z.array(resourceAmountSchema).min(1),
unlock: unlockDefSchema.optional(), unlock: unlockDefSchema.optional(),
storyHint: z.string().min(1).optional(),
storyTooltip: z.string().min(1).optional(),
}); });
export type ResourceDef = z.infer<typeof resourceDefSchema>; export type ResourceDef = z.infer<typeof resourceDefSchema>;
+7
View File
@@ -0,0 +1,7 @@
export const storyNodeDefs = [
{
id: 'boot_intro',
prose: 'Placeholder boot.',
triggers: [{ type: 'boot', targetNodeId: 'boot_intro' }],
},
];