109 lines
5.4 KiB
JavaScript
109 lines
5.4 KiB
JavaScript
const { missionHelpers, pool } = require('../mariadb');
|
||
|
||
const squadTacticsCheck = {
|
||
name: 'Squad Tactics',
|
||
skill: 'Tactics',
|
||
characteristic: 'Int',
|
||
target: 45,
|
||
modifier: 0,
|
||
rulesNote: 'Core: Tactics is an Advanced Intelligence Skill with groups such as Assault Doctrine, Defensive Doctrine, Orbital Drop Procedures, and Recon and Stealth. It gives tactical reading/positioning; it does not grant free Cohesion or Squad Mode abilities.',
|
||
reward: 'On success, the Kill-team identifies the best tactical approach for this scene; extra Degrees of Success may reveal a safer route, priority threat, ambush vector, or better position.',
|
||
};
|
||
|
||
function withSquadTactics(checks) {
|
||
const list = Array.isArray(checks) ? checks : [];
|
||
if (list.some(check => String(check.name || '').toLowerCase() === 'squad tactics')) return list;
|
||
return [squadTacticsCheck, ...list];
|
||
}
|
||
|
||
function rebalanceScene(scene) {
|
||
if (scene.title === 'The Living Vault') {
|
||
return {
|
||
...scene,
|
||
checks: withSquadTactics([
|
||
{ name: 'Anchor the psychic lock', skill: 'Psyniscience', characteristic: 'Wp', target: 45, modifier: 10, reward: 'Malachiel steadies the vault before the signal tears free.' },
|
||
{ name: 'Read psychic carrier wave', skill: 'Psyniscience', characteristic: 'Per', target: 45, modifier: 10, reward: 'Confirm the signal is warp-amplified.' },
|
||
{ name: 'Copy datapulse checksum', skill: 'Tech-Use', characteristic: 'Int', target: 45, modifier: 0, reward: 'Recover THETA-92 coordinates without needing a perfect decode.' }
|
||
]),
|
||
complications: [
|
||
'2 successes gives full coordinates; 1 success gives partial coordinates with a bad omen.',
|
||
'On 2+ failures, the vault tags one marine with a bio-psychic echo.',
|
||
'Critical failure gives one marine a vision of Bile smiling in a white laboratory.'
|
||
]
|
||
};
|
||
}
|
||
|
||
if (scene.title === 'Prisoner Signal') {
|
||
return {
|
||
...scene,
|
||
checks: withSquadTactics([
|
||
{ name: 'Open stasis cages safely', skill: 'Tech-Use', characteristic: 'Int', target: 45, modifier: 10, reward: 'Release prisoners without killing support systems.' },
|
||
{ name: 'Triage movable prisoners', skill: 'Medicae', characteristic: 'Int', target: 45, modifier: 10, reward: 'Save the prisoners who can survive extraction.' },
|
||
{ name: 'Spot biomorphic trap', skill: 'Awareness', characteristic: 'Per', target: 45, modifier: 10, reward: 'Detect the altered prisoner before it wakes.' }
|
||
]),
|
||
enemies: [
|
||
{ name: 'Gene-Warped Prisoner', type: 'mutant trap', count: 1, wounds: 12, ws: 35, bs: 0, ap: 2, damage: '1d10+4', agBonus: 4 }
|
||
]
|
||
};
|
||
}
|
||
|
||
if (scene.title === 'Engine Shrine Sabotage') {
|
||
return {
|
||
...scene,
|
||
checks: withSquadTactics([
|
||
{ name: 'Place demolition charges', skill: 'Demolitions', characteristic: 'Int', target: 45, modifier: 10, reward: 'Arm the charges in the right sequence.' },
|
||
{ name: 'Sense the living machine-spirit', skill: 'Psyniscience', characteristic: 'Wp', target: 45, modifier: 0, reward: 'Malachiel predicts the reactor pulse before it vents.' },
|
||
{ name: 'Rip open armour panels', skill: 'Strength', characteristic: 'S', target: 45, modifier: 10, reward: 'Expose the core without losing time.' },
|
||
{ name: 'Avoid plasma venting', skill: 'Dodge', characteristic: 'Ag', target: 45, modifier: 10, reward: 'Avoid 1d10+4 Energy Pen 3.' }
|
||
]),
|
||
enemies: [
|
||
{ name: 'Gland Hound', type: 'bio-hound', count: 1, wounds: 14, ws: 40, bs: 0, ap: 2, damage: '1d10+5', agBonus: 5 }
|
||
]
|
||
};
|
||
}
|
||
|
||
if (scene.title === 'The Theta Transmission') {
|
||
return {
|
||
...scene,
|
||
type: 'briefing',
|
||
checks: withSquadTactics([
|
||
{ name: 'Hold the transmission in memory', skill: 'Willpower', characteristic: 'Wp', target: 45, modifier: 10, reward: 'Preserve the coordinates despite Bile’s psychic static.' },
|
||
{ name: 'Lock coordinates', skill: 'Navigation', characteristic: 'Int', target: 45, modifier: 10, reward: '+10 to first infiltration/navigation test next mission.' },
|
||
{ name: 'Frame strategic report', skill: 'Command', characteristic: 'Fel', target: 45, modifier: 10, reward: 'Turn the discovery into actionable Deathwatch orders.' }
|
||
]),
|
||
complications: [
|
||
'Intel priority choices: enemy intel, facility map, sample data, or prisoner testimony.',
|
||
'If Sample extracted, quarantine becomes a next-session pressure.',
|
||
'If Sample destroyed, Mechanicus demands data restitution.',
|
||
'This scene should set the hook, not punish the team with another heavy failure cascade.'
|
||
]
|
||
};
|
||
}
|
||
|
||
return { ...scene, checks: withSquadTactics(scene.checks) };
|
||
}
|
||
|
||
(async function main() {
|
||
const missions = await missionHelpers.getAll();
|
||
const mission = missions.find(m => m.name === 'Vesalius Echo: Theta-92');
|
||
if (!mission) {
|
||
console.error('Mission not found: Vesalius Echo: Theta-92');
|
||
await pool.end();
|
||
process.exit(1);
|
||
}
|
||
|
||
const scenes = (mission.scenes || []).map(rebalanceScene);
|
||
const ok = await missionHelpers.update(mission.id, {
|
||
name: mission.name,
|
||
theme: mission.theme,
|
||
sceneCount: scenes.length,
|
||
enemyCount: 3,
|
||
threatLevel: 'Medium-High',
|
||
playerCount: mission.player_count || 4,
|
||
scenes
|
||
});
|
||
|
||
console.log(JSON.stringify({ status: ok ? 'updated' : 'failed', id: mission.id, name: mission.name }, null, 2));
|
||
await pool.end();
|
||
})();
|