Files
dwroller/database/scripts/fill_sheet_rule_descriptions.js
2026-06-29 13:37:02 +02:00

111 lines
6.2 KiB
JavaScript
Raw Permalink 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 { playerHelpers, pool } = require('../mariadb');
const talentDescriptions = {
'Ambidextrous': 'Reduces the penalty for using the off-hand and supports two-weapon fighting.',
'Astartes Weapon Training': 'May use standard Space Marine weapon groups without the normal untrained penalty.',
'Bulging Biceps': 'Can fire heavy weapons more effectively and benefits from massive Astartes strength.',
'Deathwatch Training': 'Against xenos, may confirm Righteous Fury more reliably and apply Deathwatch combat doctrine.',
'Heightened Senses (Hearing, Sight)': '+10 bonus to relevant Awareness tests using hearing or sight.',
'Killing Strike': 'May spend Fate or use focused attack timing to make a melee attack harder to defend against.',
'Nerves of Steel': 'May re-roll failed tests to avoid or recover from Pinning.',
'Psy Rating 3': 'Counts as Psy Rating 3 for psychic power strength, range, and force weapon effects.',
'Quick Draw': 'Can ready a weapon as a Free Action once per round.',
'Resistance (Psychic Powers)': '+10 bonus to resist psychic powers and warp effects.',
'True Grit': 'Reduces incoming Critical Damage, making the Marine much harder to kill outright.',
'Unarmed Master': 'Unarmed attacks are dangerous Astartes attacks rather than weak improvised strikes.',
'Unnatural Strength (x2)': 'Doubles Strength Bonus for lifting, melee damage, and opposed Strength uses.',
'Unnatural Toughness (x2)': 'Doubles Toughness Bonus for resisting damage and physical punishment.',
'Bolter Mastery': 'Improves effectiveness with bolter weapons, often represented as extra damage or reliability.',
'Combat Master': 'Enemies do not gain the normal ganging-up bonus against this character in melee.',
'Melee Weapon Training': 'Can use the listed melee weapon type without the untrained penalty.',
'Pistol Training': 'Can use the listed pistol type without the untrained penalty.',
'Swift Attack': 'Can make multiple melee attacks as a Full Action.',
'Lightning Attack': 'Can make even more rapid melee attacks than Swift Attack.',
'Fearless': 'Immune to Fear and Pinning, but may be unable to retreat from threats.',
'Jaded': 'Immune or resistant to mundane horror and many shocking sights.',
'Hatred': '+10 Weapon Skill against the hated foe and must often pursue them aggressively.',
'Rapid Reload': 'Reduces reload time for ranged weapons.',
'Die Hard': 'Harder to die from blood loss and severe injury.',
'Crushing Blow': 'Adds extra melee damage from brutal force.',
'Two Weapon Wielder': 'Allows more effective fighting with two weapons when prerequisites are met.',
'Unrelenting Devastation': 'Devastator-style heavy fire discipline. When using heavy weapons against massed enemies, the Marine can turn sustained fire into extra Horde pressure or area control.',
'Air of Authority': 'Bonus/effect: On a successful Command Test, affects 1d10 + Fellowship Bonus NPC targets. May Command NPCs not under your authority at -10. No effect on hostile targets.',
'Iron Discipline': 'Followers and allies under the characters command are steadier under fire and less likely to break, panic, or ignore orders.',
'Hatred (Xenos)': '+10 Weapon Skill against xenos enemies; the character is driven to engage hated aliens aggressively.',
'Wings of Angels': 'Assault Marine jump-pack mastery. Improves control and impact when charging, leaping, or striking from above with a jump pack.'
};
const psychicDescriptions = {
'Psy Rating 3': 'Power level 3. Increases psychic effect strength and force weapon impact.',
'Smite': 'Focused psychic attack. Use Willpower/Focus Power; on success it deals direct warp lightning damage.',
'Inspire': 'Sustained support power that strengthens allies against Fear, Pinning, and morale collapse.',
'Reading': 'Reads aura and surface impressions to reveal corruption, psychic traces, wounds, and emotional state.',
'Augury': 'Seeks omens and likely outcomes; useful for mission planning and danger prediction.',
'Avenger': 'Violent psychic flame/force attack for area damage.',
'Short Range Telepathy': 'Silent mind-to-mind communication at short range.'
};
const psychicNoteDescriptions = {
'Using psychic powers risks Psychic Phenomena depending on power level and roll.': 'When a Librarian manifests powers, some rolls can trigger Psychic Phenomena or worse warp side effects. Push powers only when the risk is worth it.',
'Force weapon damage and penetration increase by Psy Rating when wielded by this Librarian.': 'A force weapon channels the Librarians Psy Rating. For Malachiel, add Psy Rating 3 to relevant force weapon damage and penetration when activated as allowed by the rules.'
};
function lines(value) {
return String(value || '').split(/\r?\n/).map(line => line.trim()).filter(Boolean);
}
function nameFromLine(line) {
return String(line || '').replace(/:.*/, '').trim();
}
function descriptionsFor(value, source) {
const out = {};
for (const line of lines(value)) {
const name = nameFromLine(line);
if (source[name]) out[name] = source[name];
}
return out;
}
(async function main() {
const players = await playerHelpers.getAll();
const updated = [];
for (const player of players) {
if (player.name === 'gm') continue;
const tabInfo = player.tabInfo || {};
const nextTabInfo = {
...tabInfo,
talentDescriptions: {
...(tabInfo.talentDescriptions || {}),
...descriptionsFor(tabInfo.talents, talentDescriptions)
},
psychicDescriptions: {
...(tabInfo.psychicDescriptions || {}),
...descriptionsFor(tabInfo.psychic, { ...psychicDescriptions, ...psychicNoteDescriptions })
}
};
await playerHelpers.update(player.name, {
rollerInfo: player.rollerInfo || {},
shopInfo: player.shopInfo || {},
tabInfo: nextTabInfo,
pw: player.pw || '',
pwHash: player.pwHash || ''
});
updated.push({
name: player.name,
talents: Object.keys(nextTabInfo.talentDescriptions).length,
psychic: Object.keys(nextTabInfo.psychicDescriptions).length
});
}
console.log(JSON.stringify({ updated }, null, 2));
await new Promise(resolve => setTimeout(resolve, 250));
await pool.end();
})().catch(async error => {
console.error(error);
try { await pool.end(); } catch {}
process.exit(1);
});