244 lines
16 KiB
JavaScript
244 lines
16 KiB
JavaScript
const rawWeaponData = `
|
|
Angelus Bolter Basic - Bolt Range 50m; S/3/-; 1d10+9 X; Pen 6; Clip 36; Reload 2 Full; Tearing 25 Respected Deathwatch First Founding 97
|
|
Argrax Clawed Hooves Natural - Primitive 1d10 I; Pen 0; 0 Any Deathwatch The Emperor Protects 46
|
|
Armour of the Remorseless Crusader (Forearm Sword) One-Handed Melee - Primitive 1d10+8 R; Pen 6; +10 to hit; Sanctified 70 Hero Deathwatch Deathwatch Core Rulebook 167
|
|
Artificer Omnissian Axe One-Handed Melee - Power 1d10+9 E; Pen 7; Power Field, Unbalanced 25 Distinguished Deathwatch First Founding 99
|
|
Astartes Anti-Plant Grenade Thrown - Grenade 3d10 E; Pen 0; Blast (3) 18 Any Deathwatch Living Errata v1.1 136
|
|
Astartes Armoursbane Missile Launcher Heavy - Launch Range 200m; S/-/-; 0d0 S; Pen 0; Clip 1; Reload 2 Full; Two handed; 15 Any Deathwatch Living Errata v1.1 137
|
|
Astartes Assault Cannon Mounted - Solid Projectile Range 150m; -/-/10; 2d10+12 I; Pen 6; Clip 200; Reload 3 Full; Tearing, Devastating (1) 30 Famed Deathwatch Living Errata v1.1 149
|
|
Astartes Assault Shotgun Basic - Solid Projectile Range 30m; S/3/5; 1d10+10 I; Pen 4; Clip 20; Reload 1 Full; Two handed; Reliable, Scatter 7 Any Deathwatch Living Errata v1.1 136
|
|
Astartes Blind Grenade Thrown - Grenade 0d0 S; Pen 0; Smoke (10) 10 Any Deathwatch Living Errata v1.1 150
|
|
Astartes Bolt Pistol Pistol - Bolt Range 30m; S/2/-; 1d10+9 X; Pen 4; Clip 14; Reload 1 Full; Tearing 5 Any Deathwatch Living Errata v1.1 146
|
|
Astartes Bolter-Godwyn Basic - Bolt Range 100m; S/3/-; 1d10+9 X; Pen 4; Clip 28; Reload 1 Full; Two handed; Tearing 5 Any Deathwatch Living Errata v1.1 146
|
|
Astartes Boltgun-Stalker Basic - Bolt Range 200m; S/-/-; 1d10+9 X; Pen 4; Clip 24; Reload 1 Full; Two handed; Accurate, Tearing 15 Respected Deathwatch Living Errata v1.1 146
|
|
Astartes Chainfist One-Handed Melee - Power 2d10+"2*SB" E; Pen 10; Power Field, Tearing, Unwieldy 40 Famed Deathwatch Living Errata v1.1 154
|
|
Astartes Chainsword One-Handed Melee - Chain 1d10+3 R; Pen 3; Balanced, Tearing 5 Any Deathwatch Living Errata v1.1 153
|
|
Astartes Combat Knife One-Handed Melee - Primitive 1d10 R; Pen 2; 3 Any Deathwatch Living Errata v1.1 155
|
|
Astartes Combat Shield One-Handed Melee - Primitive 1d5+1 I; Pen 0; Balanced 20 Distinguished Deathwatch Living Errata v1.1 166
|
|
Astartes Combi-Weapon Basic - Bolt Range 100m; S/4/-; 1d10+9 X; Pen 4; Clip 28; Reload 1 Full; Two handed; Tearing 15 Respected Deathwatch Living Errata v1.1 146
|
|
Astartes Conversion Beamer Heavy - Exotic Range 100m; S/-/-; 0d0 E; Pen 0; Clip 4; Reload 2 Full; Two handed; 40 Hero Deathwatch Living Errata v1.1 152
|
|
Astartes Cyclone Missile Launcher Mounted - Launch Range 300m; S/2/-; 0d0 S; Pen 0; Clip 12; Reload 3 Full; 25 Famed Deathwatch Living Errata v1.1 152
|
|
Astartes Digital Flamer Pistol - Exotic Range 4m; S/-/-; 1d10+9 E; Pen 4; Clip 1; Reload 1d5 Hours; Flame, Spray 35 Famed Deathwatch Living Errata v1.1 153
|
|
Astartes Digital Laser Pistol - Exotic Range 4m; S/-/-; 1d10+4 E; Pen 7; Clip 1; Reload 1d5 Hours; Reliable 35 Famed Deathwatch Living Errata v1.1 153
|
|
Astartes Digital Melta Pistol - Exotic Range 4m; S/-/-; 2d10+12 E; Pen 10; Clip 1; Reload 1d5 Hours; 35 Famed Deathwatch Living Errata v1.1 153
|
|
Astartes Executioner Axe Two-Handed Melee - Power 1d10+13 E; Pen 8; Two handed; Power Field, Unwieldy, Felling (x1) 25 Famed Deathwatch Living Errata v1.1 139
|
|
Astartes Flamer Basic - Flame Range 20m; S/-/-; 1d10+9 E; Pen 4; Clip 6; Reload 2 Full; Two handed; Flame, Spray 10 Any Deathwatch Living Errata v1.1 148
|
|
Astartes Force Staff One-Handed Melee - Primitive 1d10+"1+PR+SB" S; Pen "PR"; Balanced 25 Respected Deathwatch Living Errata v1.1 155
|
|
Astartes Force Sword One-Handed Melee - Primitive 1d10+"2+PR+SB" S; Pen "2+PR"; Balanced 25 Respected Deathwatch Living Errata v1.1 156
|
|
Astartes Frag Grenade Thrown - Grenade 2d10+2 X; Pen 0; Blast (4) 1 Any Deathwatch Living Errata v1.1 150
|
|
Astartes Hand Flamer Pistol - Flame Range 10m; S/-/-; 1d10+7 E; Pen 4; Clip 4; Reload 2 Full; Flame, Spray 10 Any Deathwatch Living Errata v1.1 149
|
|
Astartes Heavy Flamer Heavy - Flame Range 30m; S/-/-; 1d10+12 E; Pen 6; Clip 10; Reload 2 Full; Two handed; Flame, Spray 15 Any Deathwatch Living Errata v1.1 149
|
|
Astartes Heavy-Bolter Heavy - Bolt Range 150m; -/-/6; 1d10+12 X; Pen 5; Clip 60; Reload 1 Full; Two handed; Tearing 20 Any Deathwatch Living Errata v1.1 147
|
|
Astartes Incendiary Grenade Thrown - Grenade 1d10+4 E; Pen 0; Blast (3) 15 Any Deathwatch Living Errata v1.1 150
|
|
Astartes Infernus Pistol Pistol - Melta Range 10m; S/-/-; 2d10+12 E; Pen 12; Clip 4; Reload 1 Full; Melta 35 Famed Deathwatch Living Errata v1.1 148
|
|
Astartes Krak Grenade Thrown - Grenade 3d10+4 X; Pen 6; 1 Any Deathwatch Living Errata v1.1 150
|
|
Astartes Lascannon Heavy - Las Range 300m; S/-/-; 5d10+10 E; Pen 10; Clip 6; Reload 2 Full; Two handed; Proven (3) 30 Respected Deathwatch Living Errata v1.1 149
|
|
Astartes Lightning Claw One-Handed Melee - Power 1d10+6 E; Pen 8; Power Field, Proven (4) 30 Distinguished Deathwatch Living Errata v1.1 154
|
|
Astartes Meltagun-Vulkan Basic - Melta Range 30m; S/-/-; 2d10+14 E; Pen 12; Clip 6; Reload 2 Full; Two handed; Melta 20 Respected Deathwatch Living Errata v1.1 148
|
|
Astartes Missile Launcher-Soundstrike Heavy - Launch Range 250m; S/-/-; 0d0 S; Pen 0; Clip 8; Reload 1 Full; Two handed; 10 Any Deathwatch Living Errata v1.1 152
|
|
Astartes Multi-Melta - Maxima Heavy - Melta Range 60m; S/-/-; 2d10+16 E; Pen 12; Clip 12; Reload 2 Full; Two handed; Blast (1), Melta 35 Respected Deathwatch Living Errata v1.1 148
|
|
Astartes Nova Grenade Thrown - Grenade 1d10 E; Pen 0; Blast (3) 15 Any Deathwatch Living Errata v1.1 151
|
|
Astartes Photon Flash Grenade Thrown - Grenade 0d0 S; Pen 0; 5 Any Deathwatch Living Errata v1.1 151
|
|
Astartes Plasma Cannon Heavy - Plasma Range 150m; S/-/-; 2d10+12 E; Pen 10; Clip 16; Reload 5 Full; Two handed; Blast (3), Volatile, Maximal 30 Distinguished Deathwatch Living Errata v1.1 147
|
|
Astartes Plasma Grenade Thrown - Grenade 1d10+12 E; Pen 8; Blast (3) 20 Distinguished Deathwatch Living Errata v1.1 151
|
|
Astartes Plasma Gun -Ragefire Basic - Plasma Range 100m; S/2/-; 1d10+12 E; Pen 10; Clip 24; Reload 4 Full; Volatile, Maximal 20 Respected Deathwatch Living Errata v1.1 148
|
|
Astartes Plasma Pistol Pistol - Plasma Range 30m; S/2/-; 1d10+10 E; Pen 8; Clip 12; Reload 3 Full; Volatile, Maximal 25 Respected Deathwatch Living Errata v1.1 148
|
|
Astartes Power Axe One-Handed Melee - Power 1d10+8 E; Pen 7; Power Field, Unbalanced 20 Respected Deathwatch Living Errata v1.1 155
|
|
Astartes Power Claymore Two-Handed Melee - Power 1d10+11 E; Pen 8; Two handed; Power Field, Unwieldy, Devastating (1) 15 Distinguished Deathwatch Living Errata v1.1 139
|
|
Astartes Power Falchion One-Handed Melee - Power 1d10+4 E; Pen 6; Two handed; Power Field, Razor Sharp 25 Distinguished Deathwatch Living Errata v1.1 139
|
|
Astartes Power Fist One-Handed Melee - Power 2d10+"2*SB" E; Pen 9; Power Field, Unwieldy 30 Distinguished Deathwatch Living Errata v1.1 155
|
|
Astartes Power Spear Two-Handed Melee - Power 1d10+6 E; Pen 7; Two handed; Power Field 15 Distinguished Deathwatch Living Errata v1.1 139
|
|
Astartes Power Sword One-Handed Melee - Power 1d10+6 E; Pen 6; Balanced, Power Field 20 Respected Deathwatch Living Errata v1.1 155
|
|
Astartes Servo-Arm Mounted - Primitive 2d10+14 I; Pen 10; 30 Any Deathwatch Living Errata v1.1 177
|
|
`.trim();
|
|
|
|
/** Parse raw weapon data */
|
|
const parseWeaponData = (data) => {
|
|
// Split into lines and filter out empty ones
|
|
const lines = data.split('\n').filter(line => line.trim());
|
|
const weapons = [];
|
|
|
|
// Skip header
|
|
for (let i = 1; i < lines.length; i++) {
|
|
const cols = lines[i].split('\t').map(col => col.trim());
|
|
if (cols.length >= 8) {
|
|
weapons.push({
|
|
name: cols[0],
|
|
class: cols[1],
|
|
damage: cols[2],
|
|
cost: parseInt(cols[3]) || 0,
|
|
availability: cols[4],
|
|
gameSetting: cols[5],
|
|
book: cols[6],
|
|
pageNo: cols[7]
|
|
});
|
|
}
|
|
}
|
|
return weapons;
|
|
};
|
|
|
|
/** Core Deathwatch equipment types */
|
|
const weaponData = `
|
|
Name Class Damage Cost Availability Game Setting Book Page No.
|
|
${rawWeaponData}
|
|
`.trim();
|
|
|
|
const weapons = parseWeaponData(weaponData);
|
|
|
|
// Use Map to deduplicate items, preferring Living Errata versions
|
|
const uniqueWeapons = new Map();
|
|
|
|
weapons.forEach(weapon => {
|
|
const key = weapon.name;
|
|
const existing = uniqueWeapons.get(key);
|
|
|
|
// Prefer Living Errata over Core Rulebook
|
|
if (!existing || weapon.book.includes('Living Errata')) {
|
|
uniqueWeapons.set(key, weapon);
|
|
}
|
|
});
|
|
|
|
const mapAvailabilityToRenown = (availability) => {
|
|
const map = {
|
|
'Any': 'None',
|
|
'Common': 'None',
|
|
'Scarce': 'None',
|
|
'Rare': 'Respected',
|
|
'Very Rare': 'Distinguished',
|
|
'Extremely Rare': 'Hero',
|
|
'Near Unique': 'Hero',
|
|
'Unique': 'Legend',
|
|
'Distinguished': 'Distinguished',
|
|
'Famed': 'Hero',
|
|
'Respected': 'Respected',
|
|
'Hero': 'Hero'
|
|
};
|
|
return map[availability] || 'Distinguished';
|
|
};
|
|
|
|
const mapClassToCategory = (itemClass) => {
|
|
if (itemClass.toLowerCase().includes('melee')) return 'Melee Weapon';
|
|
if (itemClass.toLowerCase().includes('pistol')) return 'Ranged Weapon';
|
|
if (itemClass.toLowerCase().includes('basic') ||
|
|
itemClass.toLowerCase().includes('heavy') ||
|
|
itemClass.toLowerCase().includes('mounted')) return 'Ranged Weapon';
|
|
if (itemClass.toLowerCase().includes('thrown')) return 'Grenade';
|
|
return 'Other';
|
|
};
|
|
|
|
// Group items by category
|
|
const generateShopItems = () => {
|
|
const items = Array.from(uniqueWeapons.values()).map(w => ({
|
|
name: w.name,
|
|
req: w.cost,
|
|
renown: mapAvailabilityToRenown(w.availability),
|
|
category: mapClassToCategory(w.class),
|
|
stats: {
|
|
damage: w.damage,
|
|
class: w.class,
|
|
source: `${w.book} p${w.pageNo}`
|
|
}
|
|
}));
|
|
|
|
return {
|
|
armor: [
|
|
{ name: "Astartes Power Armour", req: 40, renown: "None", category: "Armor" },
|
|
{ name: "Astartes Mk6 Corvus Power Armour", req: 45, renown: "Distinguished", category: "Armor" },
|
|
|
|
// Convert the raw weapons into categorized shop items
|
|
const generateShopItems = () => {
|
|
const items = Array.from(uniqueWeapons.values()).map(w => ({
|
|
name: w.name,
|
|
req: w.cost,
|
|
renown: mapAvailabilityToRenown(w.availability),
|
|
category: mapClassToCategory(w.class),
|
|
stats: {
|
|
damage: w.damage,
|
|
class: w.class,
|
|
source: `${w.book} p${w.pageNo}`
|
|
}
|
|
}));
|
|
|
|
// Group items by category
|
|
const categorized = {
|
|
armor: [
|
|
{ name: "Astartes Power Armour", req: 40, renown: "None", category: "Armor" },
|
|
{ name: "Astartes Mk6 Corvus Power Armour", req: 45, renown: "Distinguished", category: "Armor" },
|
|
{ name: "Astartes Mk7 Aquila Power Armour", req: 45, renown: "Distinguished", category: "Armor" },
|
|
{ name: "Astartes Mk8 Errant Power Armour", req: 50, renown: "Distinguished", category: "Armor" },
|
|
{ name: "Armour of the Remorseless Crusader", req: 70, renown: "Hero", category: "Armor" },
|
|
{ name: "Astartes Scout Armour", req: 30, renown: "None", category: "Armor" },
|
|
{ name: "Astartes Terminator Armour", req: 100, renown: "Hero", category: "Armor" },
|
|
{ name: "Astartes Artificer Armour", req: 60, renown: "Distinguished", category: "Armor" },
|
|
{ name: "Astartes Storm Shield", req: 35, renown: "Distinguished", category: "Armor" },
|
|
{ name: "Astartes Combat Shield", req: 20, renown: "Distinguished", category: "Armor" },
|
|
{ name: "Astartes Iron Halo", req: 45, renown: "Hero", category: "Armor" },
|
|
{ name: "Astartes Sacred Shield", req: 40, renown: "Hero", category: "Armor" }
|
|
],
|
|
rangedWeapons: [
|
|
{ name: "Astartes Bolt Pistol", req: 15, renown: "None", category: "Ranged Weapon" },
|
|
{ name: "Astartes Boltgun", req: 20, renown: "None", category: "Ranged Weapon" },
|
|
{ name: "Astartes Heavy Bolter", req: 30, renown: "None", category: "Ranged Weapon" },
|
|
{ name: "Astartes Storm Bolter", req: 25, renown: "Distinguished", category: "Ranged Weapon" },
|
|
{ name: "Angelus Bolter", req: 25, renown: "Respected", category: "Ranged Weapon" },
|
|
{ name: "Stalker Pattern Boltgun", req: 30, renown: "Distinguished", category: "Ranged Weapon" },
|
|
{ name: "Hellfire Bolter", req: 35, renown: "Distinguished", category: "Ranged Weapon" },
|
|
{ name: "Plasma Pistol", req: 30, renown: "Distinguished", category: "Ranged Weapon" },
|
|
{ name: "Plasma Gun", req: 35, renown: "Distinguished", category: "Ranged Weapon" },
|
|
{ name: "Plasma Cannon", req: 45, renown: "Hero", category: "Ranged Weapon" },
|
|
{ name: "Meltagun", req: 35, renown: "Distinguished", category: "Ranged Weapon" },
|
|
{ name: "Multi-Melta", req: 45, renown: "Hero", category: "Ranged Weapon" },
|
|
{ name: "Flamer", req: 25, renown: "None", category: "Ranged Weapon" },
|
|
{ name: "Heavy Flamer", req: 35, renown: "Distinguished", category: "Ranged Weapon" },
|
|
{ name: "Lascannon", req: 40, renown: "Distinguished", category: "Ranged Weapon" },
|
|
{ name: "Missile Launcher", req: 40, renown: "Distinguished", category: "Ranged Weapon" },
|
|
{ name: "Vengeance Launcher", req: 45, renown: "Hero", category: "Ranged Weapon" },
|
|
{ name: "Astartes Grenade Launcher", req: 30, renown: "Distinguished", category: "Ranged Weapon" }
|
|
],
|
|
meleeWeapons: [
|
|
{ name: "Chainsword", req: 15, renown: "None", category: "Melee Weapon" },
|
|
{ name: "Eviscerator", req: 35, renown: "Distinguished", category: "Melee Weapon" },
|
|
{ name: "Power Sword", req: 25, renown: "Distinguished", category: "Melee Weapon" },
|
|
{ name: "Power Axe", req: 25, renown: "Distinguished", category: "Melee Weapon" },
|
|
{ name: "Power Maul", req: 25, renown: "Distinguished", category: "Melee Weapon" },
|
|
{ name: "Power Lance", req: 30, renown: "Distinguished", category: "Melee Weapon" },
|
|
{ name: "Power Fist", req: 35, renown: "Distinguished", category: "Melee Weapon" },
|
|
{ name: "Lightning Claw", req: 35, renown: "Distinguished", category: "Melee Weapon" },
|
|
{ name: "Thunder Hammer", req: 40, renown: "Hero", category: "Melee Weapon" },
|
|
{ name: "Force Sword", req: 35, renown: "Distinguished", category: "Melee Weapon" },
|
|
{ name: "Force Axe", req: 35, renown: "Distinguished", category: "Melee Weapon" },
|
|
{ name: "Force Halberd", req: 35, renown: "Distinguished", category: "Melee Weapon" },
|
|
{ name: "Force Staff", req: 35, renown: "Distinguished", category: "Melee Weapon" },
|
|
{ name: "Combat Knife", req: 10, renown: "None", category: "Melee Weapon" }
|
|
],
|
|
ammunition: [
|
|
{ name: "Bolt Pistol Magazine", req: 2, renown: "None", category: "Ammunition" },
|
|
{ name: "Boltgun Magazine", req: 2, renown: "None", category: "Ammunition" },
|
|
{ name: "Storm Bolter Magazine", req: 3, renown: "None", category: "Ammunition" },
|
|
{ name: "Heavy Bolter Belt", req: 5, renown: "None", category: "Ammunition" },
|
|
{ name: "Hellfire Rounds", req: 8, renown: "Distinguished", category: "Ammunition" },
|
|
{ name: "Metal Storm Rounds", req: 8, renown: "Distinguished", category: "Ammunition" },
|
|
{ name: "Dragonfire Rounds", req: 8, renown: "Distinguished", category: "Ammunition" },
|
|
{ name: "Vengeance Rounds", req: 8, renown: "Distinguished", category: "Ammunition" },
|
|
{ name: "Kraken Penetrator Rounds", req: 8, renown: "Distinguished", category: "Ammunition" },
|
|
{ name: "Plasma Charge Pack", req: 5, renown: "None", category: "Ammunition" },
|
|
{ name: "Melta Charge", req: 5, renown: "None", category: "Ammunition" },
|
|
{ name: "Promethium Tank", req: 3, renown: "None", category: "Ammunition" },
|
|
{ name: "Missile Pack", req: 5, renown: "None", category: "Ammunition" },
|
|
{ name: "Krak Missiles", req: 8, renown: "None", category: "Ammunition" },
|
|
{ name: "Frag Missiles", req: 6, renown: "None", category: "Ammunition" },
|
|
{ name: "Vengeance Launcher Shells", req: 6, renown: "Distinguished", category: "Ammunition" }
|
|
]
|
|
};
|
|
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
|
|
if (require.main === module) {
|
|
const output = path.resolve('public/deathwatch-armoury.json');
|
|
fs.writeFileSync(output, JSON.stringify(coreItems, null, 2), 'utf8');
|
|
console.log('Wrote core items to:', output);
|
|
}
|
|
|
|
module.exports = coreItems;
|