feat(engine): tickGame returns completed action ids for story triggers

This commit is contained in:
ginnoir
2026-06-11 18:48:41 -05:00
parent d2692bcc3c
commit dc7b87eab2
2 changed files with 32 additions and 11 deletions
+19
View File
@@ -299,6 +299,25 @@ describe('completion advances queue', () => {
}); });
}); });
describe('tickGame() completion result', () => {
it('returns the id of each action that completed this tick', () => {
const content = testContent();
const state = createGameState(content);
enqueueAction(state, content, 'forage');
const result = tickGame(state, content, 300);
expect(result.completedActionIds).toEqual(['forage']);
expect(state.activeActionId).toBeNull();
});
it('returns an empty array when nothing completes', () => {
const content = testContent();
const state = createGameState(content);
enqueueAction(state, content, 'forage');
const result = tickGame(state, content, 100);
expect(result.completedActionIds).toEqual([]);
});
});
describe('tickGame()', () => { describe('tickGame()', () => {
it('does nothing when no action is active', () => { it('does nothing when no action is active', () => {
const content = testContent(); const content = testContent();
+13 -11
View File
@@ -115,11 +115,8 @@ function startNextFromQueue(state: GameState, content: Content): void {
state.actionElapsedMs = 0; state.actionElapsedMs = 0;
} }
function completeActiveAction(state: GameState, content: Content): void { export interface TickResult {
const actionId = state.activeActionId; completedActionIds: string[];
if (!actionId) return;
grantYields(state, content, actionId);
startNextFromQueue(state, content);
} }
/** /**
@@ -166,16 +163,21 @@ export function clearQueue(state: GameState): void {
* Advance the active action by `tickMs`. On completion, grants yields and * Advance the active action by `tickMs`. On completion, grants yields and
* advances the queue — actions do not auto-repeat when the queue is empty. * advances the queue — actions do not auto-repeat when the queue is empty.
*/ */
export function tickGame(state: GameState, content: Content, tickMs: number): void { export function tickGame(state: GameState, content: Content, tickMs: number): TickResult {
if (!state.activeActionId) return; const completedActionIds: string[] = [];
if (!state.activeActionId) return { completedActionIds };
state.actionElapsedMs += tickMs; state.actionElapsedMs += tickMs;
while (state.activeActionId) { while (state.activeActionId) {
const action = content.actionsById[state.activeActionId]; const actionId = state.activeActionId;
if (!action) return; const action = content.actionsById[actionId];
if (state.actionElapsedMs < action.durationMs) return; if (!action) return { completedActionIds };
if (state.actionElapsedMs < action.durationMs) return { completedActionIds };
state.actionElapsedMs -= action.durationMs; state.actionElapsedMs -= action.durationMs;
completeActiveAction(state, content); grantYields(state, content, actionId);
completedActionIds.push(actionId);
startNextFromQueue(state, content);
} }
return { completedActionIds };
} }