2PlayerGame/detective-game/casegen/motives/serial.js
2026-08-15 14:07:39 +03:00

45 lines
3.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const { pick } = require('../rng');
const N = require('../names');
const { SIGNATURES } = require('../constants');
function generate(ctx) {
const { r, add, addPuzzle, motiveEvs, victim, killer, herring, atScene, citizens } = ctx;
const motiveId = 'Серійний патерн';
if (!killer.tattoo) killer.tattoo = pick(r, N.TATTOOS);
for (const c of citizens) if (c !== killer && c.tattoo === killer.tattoo) c.tattoo = null;
const sign = pick(r, SIGNATURES);
add({
id: 'sf_signature', side: 'field', at: atScene,
title: 'Підпис на тілі', tag: 'патерн',
detail: `Деталь, яка не дає спокою: ${sign.text}. Це не випадковість і не пограбування. Це підпис. Такі речі повторюються.`
});
motiveEvs.push(add({
id: 'mot_arch_serial', side: 'analyst', at: { type: 'sys', sys: 'crim' }, q: { sys: 'crim', kind: 'archive', match: [sign.key, 'підпис'] }, requires: ['sf_signature'],
title: 'Архів: справа 2021 року', tag: 'мотив',
detail: `Пошук за підписом дав збіг: 2021 рік, сусідній район, нерозкрите вбивство — і той самий підпис: ${sign.text}. Тоді вирішили, що це дрібниця, і не внесли в орієнтування. Це не перше його полювання.`,
gives: { motive: true }
}));
motiveEvs.push(add({
id: 'mot_sketch', side: 'analyst', at: { type: 'sys', sys: 'crim' }, q: { sys: 'crim', kind: 'archive', match: [sign.key, 'підпис', '2021'] }, requires: ['mot_arch_serial'],
title: 'Свідок 2021 року: прикмети', tag: 'мотив',
detail: `У справі 2021-го є свідчення: біля місця бачили постать у ${killer.coat}, а на передпліччі — татуювання: ${killer.tattoo}. Свідка тоді не сприйняли серйозно.`,
gives: { filter: { attr: 'coat', val: killer.coat } }
}));
motiveEvs.push(add({
id: 'mot_tattoo_db', side: 'analyst', at: { type: 'sys', sys: 'db' }, q: { sys: 'db', match: killer.tattoo }, requires: ['mot_sketch'],
title: 'Пошук за татуюванням', tag: 'вбивця',
detail: `Запит по базі мешканців: «${killer.tattoo}» — єдиний збіг у районі: ${killer.name}, прож. ${killer.home}.`,
gives: { pointsTo: killer.id }
}));
motiveEvs.push(add({
id: 'mot_trophies', side: 'field', at: { type: 'unit', unit: killer.home, slot: 'шафа' },
title: 'Коробка з трофеями', tag: 'мотив',
detail: 'Взуттєва коробка на антресолі: жіночий годинник із чужим гравіюванням, стара запальничка, окуляри — і чохол від телефона жертви. Кожна річ — чиясь. Кожна річ — трофей.',
gives: { motive: true }
}));
const recapWhy = `Мотиву в людському сенсі не було. Був патерн: підпис (${sign.text}) уже з'являвся у 2021-му, і тоді його не помітили. ${killer.name} ${ctx.g(killer, 'обирав', 'обирала')} тих, хто живе сам і повертається затемна.`;
const herringLead = `«Моторошне питаєте? ${herring.name} ночами гуляє районом і фотографує чужі вікна. Сусіди двічі таке бачили.»`;
return { motiveId, recapWhy, herringLead };
}
module.exports = { generate };