diff --git a/database/backend.log b/database/backend.log index 45bf4b9..5f87ab8 100644 --- a/database/backend.log +++ b/database/backend.log @@ -4339,3 +4339,140 @@ Connected to MongoDB [2025-08-15T20:53:49.092Z] SESSION: Validate success afa1764cd4e0f771ff1de452c3acc4c584b0d3d3eb46c35713dafe1deee88106 anders [2025-08-15T20:53:49.124Z] DB: getAllPlayers - start [2025-08-15T20:53:49.124Z] DB: getAllPlayers - resultCount 5 +[2025-08-15T21:22:45.188Z] DB: getSession - start afa1764cd4e0f771ff1de452c3acc4c584b0d3d3eb46c35713dafe1deee88106 +[2025-08-15T21:22:45.189Z] DB: getSession - ok afa1764cd4e0f771ff1de452c3acc4c584b0d3d3eb46c35713dafe1deee88106 +[2025-08-15T21:22:45.189Z] SESSION: Validate success afa1764cd4e0f771ff1de452c3acc4c584b0d3d3eb46c35713dafe1deee88106 anders +[2025-08-15T21:22:46.620Z] SESSION: Error Cannot read properties of undefined (reading 'gmSecret') +[2025-08-15T21:22:46.658Z] DB: getAllPlayers - start +[2025-08-15T21:22:46.659Z] DB: getAllPlayers - resultCount 5 +[2025-08-15T21:29:23.567Z] DB: getSession - start afa1764cd4e0f771ff1de452c3acc4c584b0d3d3eb46c35713dafe1deee88106 +[2025-08-15T21:29:23.567Z] DB: getSession - ok afa1764cd4e0f771ff1de452c3acc4c584b0d3d3eb46c35713dafe1deee88106 +[2025-08-15T21:29:23.567Z] SESSION: Validate success afa1764cd4e0f771ff1de452c3acc4c584b0d3d3eb46c35713dafe1deee88106 anders +[2025-08-15T21:29:25.371Z] SESSION: Error Cannot read properties of undefined (reading 'gmSecret') +[2025-08-15T21:29:25.409Z] DB: getAllPlayers - start +[2025-08-15T21:29:25.409Z] DB: getAllPlayers - resultCount 5 +[2025-08-15T21:29:36.385Z] DB: getSession - start afa1764cd4e0f771ff1de452c3acc4c584b0d3d3eb46c35713dafe1deee88106 +[2025-08-15T21:29:36.386Z] DB: getSession - ok afa1764cd4e0f771ff1de452c3acc4c584b0d3d3eb46c35713dafe1deee88106 +[2025-08-15T21:29:36.386Z] SESSION: Validate success afa1764cd4e0f771ff1de452c3acc4c584b0d3d3eb46c35713dafe1deee88106 anders +[2025-08-15T21:29:38.354Z] DB: deleteSession - start afa1764cd4e0f771ff1de452c3acc4c584b0d3d3eb46c35713dafe1deee88106 +[2025-08-15T21:29:38.354Z] DB: deleteSession - changes 1 afa1764cd4e0f771ff1de452c3acc4c584b0d3d3eb46c35713dafe1deee88106 +[2025-08-15T21:29:38.354Z] SESSION: Logout success afa1764cd4e0f771ff1de452c3acc4c584b0d3d3eb46c35713dafe1deee88106 +[2025-08-15T21:29:43.475Z] DB: getAllPlayers - start +[2025-08-15T21:29:43.475Z] DB: getAllPlayers - resultCount 5 +[2025-08-15T21:29:47.831Z] DB: getPlayerByName - start claes +[2025-08-15T21:29:47.831Z] DB: getPlayerByName - found claes +[2025-08-15T21:29:47.831Z] DB: createSession - start 1ccc2ff25d47abecbaac311d49e8856631b9a22b9da5cb9a7055c3383c73597e expiresAt 2025-08-16T21:29:47.831Z +[2025-08-15T21:29:47.831Z] DB: createSession - done 1ccc2ff25d47abecbaac311d49e8856631b9a22b9da5cb9a7055c3383c73597e +[2025-08-15T21:29:47.831Z] SESSION: Login success claes 1ccc2ff25d47abecbaac311d49e8856631b9a22b9da5cb9a7055c3383c73597e +[2025-08-15T21:29:47.875Z] DB: getSession - start 1ccc2ff25d47abecbaac311d49e8856631b9a22b9da5cb9a7055c3383c73597e +[2025-08-15T21:29:47.875Z] DB: getSession - ok 1ccc2ff25d47abecbaac311d49e8856631b9a22b9da5cb9a7055c3383c73597e +[2025-08-15T21:29:47.875Z] SESSION: Validate success 1ccc2ff25d47abecbaac311d49e8856631b9a22b9da5cb9a7055c3383c73597e claes +[2025-08-15T21:29:49.140Z] SESSION: Error Cannot read properties of undefined (reading 'gmSecret') +[2025-08-15T21:29:49.173Z] DB: getAllPlayers - start +[2025-08-15T21:29:49.174Z] DB: getAllPlayers - resultCount 5 +[2025-08-15T21:31:23.013Z] SESSION: Error Cannot read properties of undefined (reading 'gmSecret') +[2025-08-15T21:31:23.048Z] DB: getAllPlayers - start +[2025-08-15T21:31:23.049Z] DB: getAllPlayers - resultCount 5 +[2025-08-15T21:32:01.247Z] SESSION: Error Cannot read properties of undefined (reading 'gmSecret') +[2025-08-15T21:32:07.111Z] DB: deleteSession - start 1ccc2ff25d47abecbaac311d49e8856631b9a22b9da5cb9a7055c3383c73597e +[2025-08-15T21:32:07.112Z] DB: deleteSession - changes 1 1ccc2ff25d47abecbaac311d49e8856631b9a22b9da5cb9a7055c3383c73597e +[2025-08-15T21:32:07.112Z] SESSION: Logout success 1ccc2ff25d47abecbaac311d49e8856631b9a22b9da5cb9a7055c3383c73597e +[2025-08-15T21:32:07.150Z] SESSION: Error Cannot read properties of undefined (reading 'gmSecret') +[2025-08-15T21:32:23.503Z] DB: getPlayerByName - start gm +[2025-08-15T21:32:23.504Z] DB: getPlayerByName - found gm +[2025-08-15T21:32:23.504Z] DB: createSession - start 6f79ce5355731e67d99dd56e343d14a1f27f2185a66b51a06f8912ca33a66595 expiresAt 2025-08-16T21:32:23.504Z +[2025-08-15T21:32:23.504Z] DB: createSession - done 6f79ce5355731e67d99dd56e343d14a1f27f2185a66b51a06f8912ca33a66595 +[2025-08-15T21:32:23.504Z] SESSION: Login success gm 6f79ce5355731e67d99dd56e343d14a1f27f2185a66b51a06f8912ca33a66595 +[2025-08-15T21:32:23.553Z] SESSION: GM bypass accepted GET /api/players +[2025-08-15T21:32:23.553Z] DB: getAllPlayers - start +[2025-08-15T21:32:23.554Z] DB: getAllPlayers - resultCount 5 +[2025-08-15T21:32:23.554Z] API: Fetch all players (public) Found 5 players +[2025-08-15T21:32:23.555Z] DB: getSession - start 6f79ce5355731e67d99dd56e343d14a1f27f2185a66b51a06f8912ca33a66595 +[2025-08-15T21:32:23.555Z] DB: getSession - ok 6f79ce5355731e67d99dd56e343d14a1f27f2185a66b51a06f8912ca33a66595 +[2025-08-15T21:32:23.555Z] SESSION: Validate success 6f79ce5355731e67d99dd56e343d14a1f27f2185a66b51a06f8912ca33a66595 gm +[2025-08-15T21:32:33.300Z] SESSION: GM bypass accepted GET /api/players +[2025-08-15T21:32:33.300Z] DB: getAllPlayers - start +[2025-08-15T21:32:33.300Z] DB: getAllPlayers - resultCount 5 +[2025-08-15T21:32:33.300Z] API: Fetch all players (public) Found 5 players +[2025-08-15T21:32:51.231Z] DB: deleteSession - start 6f79ce5355731e67d99dd56e343d14a1f27f2185a66b51a06f8912ca33a66595 +[2025-08-15T21:32:51.231Z] DB: deleteSession - changes 1 6f79ce5355731e67d99dd56e343d14a1f27f2185a66b51a06f8912ca33a66595 +[2025-08-15T21:32:51.231Z] SESSION: Logout success 6f79ce5355731e67d99dd56e343d14a1f27f2185a66b51a06f8912ca33a66595 +[2025-08-15T21:32:51.287Z] SESSION: Error Cannot read properties of undefined (reading 'gmSecret') +[2025-08-15T21:32:55.693Z] DB: getPlayerByName - start anders +[2025-08-15T21:32:55.694Z] DB: getPlayerByName - found anders +[2025-08-15T21:32:55.694Z] DB: createSession - start c57dde4a145cf03e40ac371e371fee63b1e2a6b1559031171201e15d1dc1151c expiresAt 2025-08-16T21:32:55.694Z +[2025-08-15T21:32:55.694Z] DB: createSession - done c57dde4a145cf03e40ac371e371fee63b1e2a6b1559031171201e15d1dc1151c +[2025-08-15T21:32:55.694Z] SESSION: Login success anders c57dde4a145cf03e40ac371e371fee63b1e2a6b1559031171201e15d1dc1151c +[2025-08-15T21:32:56.149Z] SESSION: Error Cannot read properties of undefined (reading 'gmSecret') +[2025-08-15T21:32:56.151Z] DB: getSession - start c57dde4a145cf03e40ac371e371fee63b1e2a6b1559031171201e15d1dc1151c +[2025-08-15T21:32:56.151Z] DB: getSession - ok c57dde4a145cf03e40ac371e371fee63b1e2a6b1559031171201e15d1dc1151c +[2025-08-15T21:32:56.151Z] SESSION: Validate success c57dde4a145cf03e40ac371e371fee63b1e2a6b1559031171201e15d1dc1151c anders +[2025-08-15T21:33:45.027Z] DB: getSession - start c57dde4a145cf03e40ac371e371fee63b1e2a6b1559031171201e15d1dc1151c +[2025-08-15T21:33:45.027Z] DB: getSession - ok c57dde4a145cf03e40ac371e371fee63b1e2a6b1559031171201e15d1dc1151c +[2025-08-15T21:33:45.027Z] SESSION: Valid c57dde4a145cf03e40ac371e371fee63b1e2a6b1559031171201e15d1dc1151c anders PUT /api/players/anders +[2025-08-15T21:33:45.028Z] DB: getSession - start c57dde4a145cf03e40ac371e371fee63b1e2a6b1559031171201e15d1dc1151c +[2025-08-15T21:33:45.028Z] DB: getSession - ok c57dde4a145cf03e40ac371e371fee63b1e2a6b1559031171201e15d1dc1151c +[2025-08-15T21:33:45.028Z] SESSION: Valid c57dde4a145cf03e40ac371e371fee63b1e2a6b1559031171201e15d1dc1151c anders PUT /api/players/anders +[2025-08-15T21:33:45.028Z] DB: getPlayerByName - start anders +[2025-08-15T21:33:45.028Z] DB: getPlayerByName - found anders +[2025-08-15T21:33:45.028Z] DB: updatePlayer - start anders +[2025-08-15T21:33:45.029Z] DB: updatePlayer - changes 1 anders +[2025-08-15T21:33:45.029Z] DB: getPlayerByName - start anders +[2025-08-15T21:33:45.029Z] DB: getPlayerByName - found anders +[2025-08-15T21:33:45.029Z] API: Updated player anders +[2025-08-15T21:33:45.070Z] SESSION: Error Cannot read properties of undefined (reading 'gmSecret') +[2025-08-15T21:33:56.877Z] DB: deleteSession - start c57dde4a145cf03e40ac371e371fee63b1e2a6b1559031171201e15d1dc1151c +[2025-08-15T21:33:56.877Z] DB: deleteSession - changes 1 c57dde4a145cf03e40ac371e371fee63b1e2a6b1559031171201e15d1dc1151c +[2025-08-15T21:33:56.877Z] SESSION: Logout success c57dde4a145cf03e40ac371e371fee63b1e2a6b1559031171201e15d1dc1151c +[2025-08-15T21:33:56.924Z] SESSION: Error Cannot read properties of undefined (reading 'gmSecret') +[2025-08-15T21:34:02.953Z] DB: getPlayerByName - start gm +[2025-08-15T21:34:02.953Z] DB: getPlayerByName - found gm +[2025-08-15T21:34:02.953Z] DB: createSession - start b940d74752f8a862fc4379711bd037488c0004b7cafd26b27cf8b07e422d01f2 expiresAt 2025-08-16T21:34:02.953Z +[2025-08-15T21:34:02.953Z] DB: createSession - done b940d74752f8a862fc4379711bd037488c0004b7cafd26b27cf8b07e422d01f2 +[2025-08-15T21:34:02.953Z] SESSION: Login success gm b940d74752f8a862fc4379711bd037488c0004b7cafd26b27cf8b07e422d01f2 +[2025-08-15T21:34:02.992Z] SESSION: GM bypass accepted GET /api/players +[2025-08-15T21:34:02.993Z] DB: getAllPlayers - start +[2025-08-15T21:34:02.993Z] DB: getAllPlayers - resultCount 5 +[2025-08-15T21:34:02.993Z] API: Fetch all players (public) Found 5 players +[2025-08-15T21:34:02.999Z] DB: getSession - start b940d74752f8a862fc4379711bd037488c0004b7cafd26b27cf8b07e422d01f2 +[2025-08-15T21:34:02.999Z] DB: getSession - ok b940d74752f8a862fc4379711bd037488c0004b7cafd26b27cf8b07e422d01f2 +[2025-08-15T21:34:02.999Z] SESSION: Validate success b940d74752f8a862fc4379711bd037488c0004b7cafd26b27cf8b07e422d01f2 gm +[2025-08-15T21:34:12.502Z] SESSION: GM bypass accepted PUT /api/players/anders +[2025-08-15T21:34:12.502Z] SESSION: GM bypass accepted PUT /api/players/anders +[2025-08-15T21:34:12.503Z] DB: getPlayerByName - start anders +[2025-08-15T21:34:12.503Z] DB: getPlayerByName - found anders +[2025-08-15T21:34:12.503Z] DB: updatePlayer - start anders +[2025-08-15T21:34:12.503Z] DB: updatePlayer - changes 1 anders +[2025-08-15T21:34:12.503Z] DB: getPlayerByName - start anders +[2025-08-15T21:34:12.503Z] DB: getPlayerByName - found anders +[2025-08-15T21:34:12.503Z] API: Updated player anders +[2025-08-15T21:34:12.545Z] SESSION: GM bypass accepted GET /api/players +[2025-08-15T21:34:12.545Z] DB: getAllPlayers - start +[2025-08-15T21:34:12.545Z] DB: getAllPlayers - resultCount 5 +[2025-08-15T21:34:12.545Z] API: Fetch all players (public) Found 5 players +[2025-08-15T21:34:45.147Z] SESSION: GM bypass accepted PUT /api/players/gm +[2025-08-15T21:34:45.148Z] SESSION: GM bypass accepted PUT /api/players/gm +[2025-08-15T21:34:45.148Z] DB: getPlayerByName - start gm +[2025-08-15T21:34:45.148Z] DB: getPlayerByName - found gm +[2025-08-15T21:34:45.148Z] DB: updatePlayer - start gm +[2025-08-15T21:34:45.148Z] DB: updatePlayer - changes 1 gm +[2025-08-15T21:34:45.148Z] DB: getPlayerByName - start gm +[2025-08-15T21:34:45.148Z] DB: getPlayerByName - found gm +[2025-08-15T21:34:45.148Z] API: Updated player gm +[2025-08-15T21:34:45.194Z] SESSION: GM bypass accepted GET /api/players +[2025-08-15T21:34:45.195Z] DB: getAllPlayers - start +[2025-08-15T21:34:45.195Z] DB: getAllPlayers - resultCount 5 +[2025-08-15T21:34:45.195Z] API: Fetch all players (public) Found 5 players +[2025-08-15T21:35:43.856Z] SESSION: GM bypass accepted PUT /api/players/gm +[2025-08-15T21:35:43.856Z] SESSION: GM bypass accepted PUT /api/players/gm +[2025-08-15T21:35:43.856Z] DB: getPlayerByName - start gm +[2025-08-15T21:35:43.857Z] DB: getPlayerByName - found gm +[2025-08-15T21:35:43.857Z] DB: updatePlayer - start gm +[2025-08-15T21:35:43.857Z] DB: updatePlayer - changes 1 gm +[2025-08-15T21:35:43.857Z] DB: getPlayerByName - start gm +[2025-08-15T21:35:43.858Z] DB: getPlayerByName - found gm +[2025-08-15T21:35:43.858Z] API: Updated player gm +[2025-08-15T21:35:43.910Z] SESSION: GM bypass accepted GET /api/players +[2025-08-15T21:35:43.911Z] DB: getAllPlayers - start +[2025-08-15T21:35:43.911Z] DB: getAllPlayers - resultCount 5 +[2025-08-15T21:35:43.911Z] API: Fetch all players (public) Found 5 players diff --git a/database/server.js b/database/server.js index 1dac19b..ab475d5 100755 --- a/database/server.js +++ b/database/server.js @@ -1,6 +1,7 @@ require('dotenv').config(); const express = require('express'); const cors = require('cors'); +const path = require('path'); const playerRoutes = require('./routes/playerRoutes-sqlite'); const sessionRoutes = require('./routes/sessionRoutes-sqlite'); const shopRoutes = require('./routes/shopRoutes'); @@ -12,6 +13,9 @@ const PORT = process.env.PORT || 5000; app.use(express.json()); app.use(cors()); +// Serve static files from the React app build directory +app.use(express.static(path.join(__dirname, '../build'))); + // Initialize SQLite database const { db } = require('./sqlite-db'); @@ -50,6 +54,11 @@ app.use('/api/players', playerRoutes); app.use('/api/sessions', sessionRoutes); app.use('/api/shop', shopRoutes); +// Catch all handler: send back React's index.html file for any non-API routes +app.get(/^(?!\/api).*/, (req, res) => { + res.sendFile(path.join(__dirname, '../build/index.html')); +}); + // Start Server app.listen(PORT, '0.0.0.0', () => { console.log(`Server running on http://0.0.0.0:${PORT}`); diff --git a/database/sqlite-db.db b/database/sqlite-db.db new file mode 100644 index 0000000..e69de29 diff --git a/database/sqlite/deathwatch.db b/database/sqlite/deathwatch.db index 1911ff2..5f9b629 100644 Binary files a/database/sqlite/deathwatch.db and b/database/sqlite/deathwatch.db differ diff --git a/database/sqlite/deathwatch.db-shm b/database/sqlite/deathwatch.db-shm index a7b4033..95c697a 100644 Binary files a/database/sqlite/deathwatch.db-shm and b/database/sqlite/deathwatch.db-shm differ diff --git a/database/sqlite/deathwatch.db-wal b/database/sqlite/deathwatch.db-wal index 1e05697..9f616a5 100644 Binary files a/database/sqlite/deathwatch.db-wal and b/database/sqlite/deathwatch.db-wal differ diff --git a/public/deathwatch-armor-comprehensive.json b/public/deathwatch-armor-comprehensive.json new file mode 100644 index 0000000..11880e1 --- /dev/null +++ b/public/deathwatch-armor-comprehensive.json @@ -0,0 +1,1138 @@ +{ + "powerArmor": [ + { + "name": "Armour of the Remorseless Crusader", + "req": 70, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 12, + "arms": 12, + "body": 12, + "legs": 12 + }, + "source": "Deathwatch Core Rulebook p167" + } + }, + { + "name": "Astartes Artificer Armour", + "req": 60, + "renown": "Hero", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 12, + "arms": 12, + "body": 12, + "legs": 12 + }, + "source": "Deathwatch Core Rulebook p163" + } + }, + { + "name": "Astartes Mk 1 Thunder Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 6, + "body": 8, + "legs": 4 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk 2 Crusade Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 7, + "body": 9, + "legs": 7 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk 3 Iron Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 9, + "body": 10, + "legs": 9 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk 4 Maximus Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 7, + "body": 9, + "legs": 7 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk 5 Heresy Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 8, + "body": 9, + "legs": 8 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk 6 Corvus Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 8, + "body": 9, + "legs": 8 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk 7 Aquilla Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 8, + "body": 10, + "legs": 8 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk 8 Errant Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 8, + "body": 11, + "legs": 8 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 8, + "body": 10, + "legs": 8 + }, + "source": "Deathwatch Core Rulebook p160" + } + }, + { + "name": "Astartes Tactical Dreadnaught-Terminator Armour", + "req": 100, + "renown": "Famed", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 14, + "body": 14, + "legs": 14 + }, + "source": "Deathwatch Core Rulebook p164" + } + }, + { + "name": "Astartes Terminator Armour", + "req": 100, + "renown": "Famed", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 14, + "arms": 14, + "body": 14, + "legs": 14 + }, + "source": "Deathwatch Core Rulebook p164" + } + }, + { + "name": "CM Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 8, + "body": 10, + "legs": 8 + }, + "source": "Mark of the Xenos p114" + } + }, + { + "name": "Dmn Armour of Chaos", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 12, + "arms": 12, + "body": 12, + "legs": 12 + }, + "source": "Deathwatch Core Rulebook p362" + } + }, + { + "name": "Tau XV-8 Crisis Battlesuit", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 9, + "arms": 9, + "body": 9, + "legs": 9 + }, + "source": "Mark of the Xenos p9" + } + }, + { + "name": "Tau XV-88 Broadside Battlesuit", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 12, + "arms": 12, + "body": 12, + "legs": 12 + }, + "source": "Mark of the Xenos p6" + } + }, + { + "name": "Tau XV15 Stealth Suit (Limbs)", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 7, + "body": 0, + "legs": 7 + }, + "source": "Deathwatch Core Rulebook p367" + } + }, + { + "name": "Tau XV15 Stealth Suit (Top)", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 8, + "legs": 0 + }, + "source": "Deathwatch Core Rulebook p367" + } + }, + { + "name": "Tau XV8 Crisis Suit", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 9, + "arms": 9, + "body": 9, + "legs": 9 + }, + "source": "Deathwatch Core Rulebook p366" + } + } + ], + "powerArmorHelms": [ + { + "name": "Astartes Mk1 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 6, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk2 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 7, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk3 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 9, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk4 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 7, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk5 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk6 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk7 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk8 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Deathwatch Core Rulebook p160" + } + }, + { + "name": "Astartes Tactical Dreadnaught-Terminator Armour Helm", + "req": 100, + "renown": "Famed", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 14, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Deathwatch Core Rulebook p164" + } + }, + { + "name": "Diagnostor Helmet", + "req": 15, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Deathwatch Core Rulebook p165" + } + }, + { + "name": "Fenris Pattern Wolf Helm", + "req": 0, + "renown": "Respected", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p143" + } + }, + { + "name": "Skull Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 9, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p143" + } + } + ], + "carapaceArmor": [ + { + "name": "Astartes Scout Armour", + "req": 0, + "renown": "Any", + "category": "Carapace Armor", + "stats": { + "type": "Carapace", + "protection": { + "head": 0, + "arms": 6, + "body": 6, + "legs": 0 + }, + "source": "Deathwatch Core Rulebook p163" + } + }, + { + "name": "Chaos Flak Robes and Brazen Carapace", + "req": 0, + "renown": "Any", + "category": "Carapace Armor", + "stats": { + "type": "Carapace", + "protection": { + "head": 5, + "arms": 5, + "body": 6, + "legs": 4 + }, + "source": "Deathwatch Core Rulebook p364" + } + }, + { + "name": "Deathwatch Scout Armor", + "req": 0, + "renown": "Any", + "category": "Carapace Armor", + "stats": { + "type": "Carapace", + "protection": { + "head": 0, + "arms": 6, + "body": 6, + "legs": 6 + }, + "source": "Rites of Battle p142" + } + }, + { + "name": "Tau Fire Warrior Armour", + "req": 0, + "renown": "Any", + "category": "Carapace Armor", + "stats": { + "type": "Carapace", + "protection": { + "head": 6, + "arms": 6, + "body": 6, + "legs": 6 + }, + "source": "Deathwatch Core Rulebook p368" + } + }, + { + "name": "Tau Pathfinder Armour", + "req": 0, + "renown": "Any", + "category": "Carapace Armor", + "stats": { + "type": "Carapace", + "protection": { + "head": 7, + "arms": 0, + "body": 7, + "legs": 0 + }, + "source": "Mark of the Xenos p25" + } + } + ], + "naturalArmor": [ + { + "name": "Tau Gun Drone Armour", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 5, + "arms": 5, + "body": 5, + "legs": 5 + }, + "source": "Deathwatch Core Rulebook p367" + } + }, + { + "name": "Tyr Bonded Exoskeleton", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 10, + "arms": 10, + "body": 10, + "legs": 10 + }, + "source": "Deathwatch Core Rulebook p370" + } + }, + { + "name": "Tyr Chitinous Carapace", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 3, + "arms": 3, + "body": 3, + "legs": 3 + }, + "source": "Deathwatch Core Rulebook p371" + } + }, + { + "name": "Tyr Reinforced Chitin", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 8, + "arms": 8, + "body": 8, + "legs": 8 + }, + "source": "Deathwatch Core Rulebook p371" + } + }, + { + "name": "Tyr Exoskeleton", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 2, + "arms": 2, + "body": 2, + "legs": 2 + }, + "source": "Mark of the Xenos p43" + } + }, + { + "name": "Tyr Hardened Carapace", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 6, + "arms": 6, + "body": 6, + "legs": 6 + }, + "source": "Mark of the Xenos p40" + } + }, + { + "name": "Tyr Light Reinforced Chitin", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 4, + "arms": 4, + "body": 4, + "legs": 4 + }, + "source": "Mark of the Xenos p39" + } + }, + { + "name": "Tyr Medium Reinforced Chitin", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 6, + "arms": 6, + "body": 6, + "legs": 6 + }, + "source": "Mark of the Xenos p37" + } + }, + { + "name": "Tyr Thickened Scales", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 10, + "arms": 10, + "body": 10, + "legs": 10 + }, + "source": "Mark of the Xenos p46" + } + }, + { + "name": "Vespid Chitin", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 3, + "arms": 3, + "body": 3, + "legs": 3 + }, + "source": "Mark of the Xenos p26" + } + }, + { + "name": "Xenos Hardened Hide", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 6, + "arms": 6, + "body": 6, + "legs": 6 + }, + "source": "Mark of the Xenos p66" + } + }, + { + "name": "Xenos Scaly Hide", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 3, + "arms": 3, + "body": 3, + "legs": 3 + }, + "source": "Mark of the Xenos p63" + } + }, + { + "name": "Xenos Slimey Hide", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 2, + "arms": 2, + "body": 2, + "legs": 2 + }, + "source": "Mark of the Xenos p68" + } + }, + { + "name": "Xenos Thick Scales", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 5, + "arms": 5, + "body": 5, + "legs": 5 + }, + "source": "Mark of the Xenos p65" + } + } + ], + "primitiveArmor": [ + { + "name": "Auran Golden Saurian Scale Armour", + "req": 0, + "renown": "Any", + "category": "Primitive Armor", + "stats": { + "type": "Primitive", + "protection": { + "head": 6, + "arms": 6, + "body": 6, + "legs": 6 + }, + "source": "The Emperor Protects p48" + } + }, + { + "name": "Auran Saurian Scale Armour", + "req": 0, + "renown": "Any", + "category": "Primitive Armor", + "stats": { + "type": "Primitive", + "protection": { + "head": 4, + "arms": 4, + "body": 4, + "legs": 4 + }, + "source": "The Emperor Protects p46" + } + }, + { + "name": "Scales", + "req": 0, + "renown": "Any", + "category": "Primitive Armor", + "stats": { + "type": "Primitive", + "protection": { + "head": 2, + "arms": 2, + "body": 2, + "legs": 2 + }, + "source": "The Emperor Protects p50" + } + }, + { + "name": "Scaly Hide", + "req": 0, + "renown": "Any", + "category": "Primitive Armor", + "stats": { + "type": "Primitive", + "protection": { + "head": 4, + "arms": 4, + "body": 4, + "legs": 4 + }, + "source": "The Emperor Protects p46" + } + } + ], + "xenosArmor": [ + { + "name": "Nec Metallic Exoskeleton", + "req": 0, + "renown": "Any", + "category": "Xenos Armor", + "stats": { + "type": "Necron", + "protection": { + "head": 8, + "arms": 8, + "body": 8, + "legs": 8 + }, + "source": "The Emperor Protects p94" + } + }, + { + "name": "Nec Metallic Shell", + "req": 0, + "renown": "Any", + "category": "Xenos Armor", + "stats": { + "type": "Necron", + "protection": { + "head": 10, + "arms": 10, + "body": 10, + "legs": 10 + }, + "source": "The Emperor Protects p94" + } + }, + { + "name": "Ork Eavy Armour", + "req": 0, + "renown": "Any", + "category": "Xenos Armor", + "stats": { + "type": "Ork", + "protection": { + "head": 6, + "arms": 4, + "body": 6, + "legs": 4 + }, + "source": "Mark of the Xenos p57" + } + }, + { + "name": "Ork Flak Armour", + "req": 0, + "renown": "Any", + "category": "Xenos Armor", + "stats": { + "type": "Ork", + "protection": { + "head": 0, + "arms": 0, + "body": 2, + "legs": 0 + }, + "source": "Mark of the Xenos p57" + } + }, + { + "name": "Ork Mega Armour", + "req": 0, + "renown": "Any", + "category": "Xenos Armor", + "stats": { + "type": "Ork", + "protection": { + "head": 6, + "arms": 10, + "body": 14, + "legs": 10 + }, + "source": "Mark of the Xenos p57" + } + } + ], + "otherArmor": [ + { + "name": "Chaos Armour Plating", + "req": 0, + "renown": "Any", + "category": "Other Armor", + "stats": { + "type": "Other", + "protection": { + "head": 6, + "arms": 6, + "body": 6, + "legs": 6 + }, + "source": "Mark of the Xenos p91" + } + }, + { + "name": "Chaos Bones of Subersion", + "req": 0, + "renown": "Any", + "category": "Other Armor", + "stats": { + "type": "Other", + "protection": { + "head": 9, + "arms": 9, + "body": 9, + "legs": 9 + }, + "source": "Mark of the Xenos p86" + } + }, + { + "name": "Chaos Slinnar Obsidian Shell", + "req": 0, + "renown": "Any", + "category": "Other Armor", + "stats": { + "type": "Other", + "protection": { + "head": 8, + "arms": 8, + "body": 8, + "legs": 8 + }, + "source": "Mark of the Xenos p92" + } + }, + { + "name": "Chaos Warded Adamantine Shell", + "req": 0, + "renown": "Any", + "category": "Other Armor", + "stats": { + "type": "Other", + "protection": { + "head": 9, + "arms": 9, + "body": 9, + "legs": 9 + }, + "source": "Mark of the Xenos p95" + } + }, + { + "name": "Daemon Iron Hide", + "req": 0, + "renown": "Any", + "category": "Other Armor", + "stats": { + "type": "Other", + "protection": { + "head": 13, + "arms": 13, + "body": 13, + "legs": 13 + }, + "source": "Mark of the Xenos p101" + } + }, + { + "name": "Dmn Brazen Chaos Armour", + "req": 0, + "renown": "Any", + "category": "Other Armor", + "stats": { + "type": "Other", + "protection": { + "head": 12, + "arms": 12, + "body": 12, + "legs": 12 + }, + "source": "The Emperor Protects p136" + } + }, + { + "name": "Obliterator Warped Mechnical Flesh", + "req": 0, + "renown": "Any", + "category": "Other Armor", + "stats": { + "type": "Other", + "protection": { + "head": 12, + "arms": 12, + "body": 12, + "legs": 12 + }, + "source": "Mark of the Xenos p120" + } + }, + { + "name": "Rad Corrupted Mechnical Flesh", + "req": 0, + "renown": "Any", + "category": "Other Armor", + "stats": { + "type": "Other", + "protection": { + "head": 7, + "arms": 7, + "body": 7, + "legs": 7 + }, + "source": "The Emperor Protects p91" + } + } + ], + "shields": [ + { + "name": "Astartes Storm Shield - Protective", + "req": 35, + "renown": "Distinguished", + "category": "Shield", + "stats": { + "type": "Shield", + "protection": { + "head": 0, + "arms": "0LA 4RA", + "body": 4, + "legs": 0 + }, + "source": "Deathwatch Core Rulebook p166" + } + } + ] +} \ No newline at end of file diff --git a/public/deathwatch-armoury.json b/public/deathwatch-armoury.json index a5f7d37..0b95a1b 100644 --- a/public/deathwatch-armoury.json +++ b/public/deathwatch-armoury.json @@ -1,15 +1,16 @@ { - "version": "2.0.0", - "lastUpdated": "2025-08-15T13:31:19.082Z", + "version": "3.0.0", + "lastUpdated": "2025-08-15T21:27:14.033Z", "categories": [ "rangedWeapons", "meleeWeapons", "grenades", "otherWeapons", "powerArmor", + "powerArmorHelms", "carapaceArmor", - "primitiveArmor", "naturalArmor", + "primitiveArmor", "xenosArmor", "shields", "otherArmor" @@ -30,29 +31,29 @@ { "name": "Astartes Armoursbane Missile Launcher", "req": 15, - "renown": "None", + "renown": "Any", "category": "Ranged Weapon", "stats": { - "damage": "Range 200m; S/-/-; 0d0 S; Pen 0; Clip 1; Reload 2 Full; Two handed;", + "damage": "Range 200m; S/-/-; 0d0 S; Pen 0; Clip 1; Reload 2 Full; Two handed", "class": "Heavy - Launch", - "source": "Living Errata v1.1 p137" + "source": "Rites of Battle p137" } }, { "name": "Astartes Assault Cannon", "req": 30, - "renown": "Hero", + "renown": "Famed", "category": "Ranged Weapon", "stats": { - "damage": "Range 150m; -/-/10; 2d10+12 I; Pen 6; Clip 200; Reload 3 Full; Tearing, Devastating (1)", + "damage": "Range 150m; -/-/10; 3d10+6 I; Pen 6; Clip 200; Reload 3 Full; Tearing", "class": "Mounted - Solid Projectile", - "source": "Living Errata v1.1 p149" + "source": "Deathwatch Core Rulebook p149" } }, { "name": "Astartes Assault Shotgun", "req": 7, - "renown": "None", + "renown": "Any", "category": "Ranged Weapon", "stats": { "damage": "Range 30m; S/3/5; 1d10+10 I; Pen 4; Clip 20; Reload 1 Full; Two handed; Reliable, Scatter", @@ -63,7 +64,7 @@ { "name": "Astartes Bolt Pistol", "req": 5, - "renown": "None", + "renown": "Any", "category": "Ranged Weapon", "stats": { "damage": "Range 30m; S/2/-; 1d10+9 X; Pen 4; Clip 14; Reload 1 Full; Tearing", @@ -74,7 +75,7 @@ { "name": "Astartes Bolter-Godwyn", "req": 5, - "renown": "None", + "renown": "Any", "category": "Ranged Weapon", "stats": { "damage": "Range 100m; S/3/-; 1d10+9 X; Pen 4; Clip 28; Reload 1 Full; Two handed; Tearing", @@ -93,6 +94,17 @@ "source": "Living Errata v1.1 p146" } }, + { + "name": "Astartes Chainfist", + "req": 40, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "2d10+2*SB E; Pen 10; Power Field, Tearing, Unwieldy", + "class": "One-Handed Melee - Power", + "source": "Living Errata v1.1 p154" + } + }, { "name": "Astartes Combi-Weapon", "req": 15, @@ -110,7 +122,7 @@ "renown": "Hero", "category": "Ranged Weapon", "stats": { - "damage": "Range 100m; S/-/-; 0d0 E; Pen 0; Clip 4; Reload 2 Full; Two handed;", + "damage": "Range 100m; S/-/-; 0d0 E; Pen 0; Clip 4; Reload 2 Full; Two handed", "class": "Heavy - Exotic", "source": "Living Errata v1.1 p152" } @@ -118,10 +130,10 @@ { "name": "Astartes Cyclone Missile Launcher", "req": 25, - "renown": "Hero", + "renown": "Famed", "category": "Ranged Weapon", "stats": { - "damage": "Range 300m; S/2/-; 0d0 S; Pen 0; Clip 12; Reload 3 Full;", + "damage": "Range 300m; S/2/-; 0d0 S; Pen 0; Clip 12; Reload 3 Full", "class": "Mounted - Launch", "source": "Living Errata v1.1 p152" } @@ -129,13 +141,178 @@ { "name": "Astartes Digital Flamer", "req": 35, - "renown": "Hero", + "renown": "Famed", "category": "Ranged Weapon", "stats": { "damage": "Range 4m; S/-/-; 1d10+9 E; Pen 4; Clip 1; Reload 1d5 Hours; Flame, Spray", "class": "Pistol - Exotic", "source": "Living Errata v1.1 p153" } + }, + { + "name": "Astartes Digital Laser", + "req": 35, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 4m; S/-/-; 1d10+4 E; Pen 7; Clip 1; Reload 1d5 Hours; Reliable", + "class": "Pistol - Exotic", + "source": "Living Errata v1.1 p153" + } + }, + { + "name": "Astartes Digital Melta", + "req": 35, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 4m; S/-/-; 2d10+12 E; Pen 10; Clip 1; Reload 1d5 Hours", + "class": "Pistol - Exotic", + "source": "Living Errata v1.1 p153" + } + }, + { + "name": "Astartes Executioner Axe", + "req": 25, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "1d10+13 E; Pen 8; Two handed; Power Field, Unwieldy, Felling (x1)", + "class": "Two-Handed Melee - Power", + "source": "Living Errata v1.1 p139" + } + }, + { + "name": "Astartes Flamer", + "req": 10, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 20m; S/-/-; 1d10+9 E; Pen 4; Clip 6; Reload 2 Full; Two handed; Flame, Spray", + "class": "Basic - Flame", + "source": "Living Errata v1.1 p148" + } + }, + { + "name": "Astartes Heavy Flamer", + "req": 15, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 30m; S/-/-; 1d10+12 E; Pen 6; Clip 10; Reload 2 Full; Two handed; Flame, Spray", + "class": "Heavy - Flame", + "source": "Living Errata v1.1 p149" + } + }, + { + "name": "Astartes Heavy-Bolter", + "req": 20, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 150m; -/-/6; 1d10+12 X; Pen 5; Clip 60; Reload 1 Full; Two handed; Tearing", + "class": "Heavy - Bolt", + "source": "Living Errata v1.1 p147" + } + }, + { + "name": "Astartes Infernus Pistol", + "req": 35, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 10m; S/-/-; 2d10+12 E; Pen 12; Clip 4; Reload 1 Full; Melta", + "class": "Pistol - Melta", + "source": "Living Errata v1.1 p148" + } + }, + { + "name": "Astartes Lascannon", + "req": 30, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 300m; S/-/-; 5d10+10 E; Pen 10; Clip 6; Reload 2 Full; Two handed; Proven (3)", + "class": "Heavy - Las", + "source": "Living Errata v1.1 p149" + } + }, + { + "name": "Astartes Lightning Claw", + "req": 30, + "renown": "Distinguished", + "category": "Ranged Weapon", + "stats": { + "damage": "1d10+6 E; Pen 8; Power Field, Proven (4)", + "class": "One-Handed Melee - Power", + "source": "Living Errata v1.1 p154" + } + }, + { + "name": "Astartes Meltagun-Vulkan", + "req": 20, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 30m; S/-/-; 2d10+14 E; Pen 12; Clip 6; Reload 2 Full; Two handed; Melta", + "class": "Basic - Melta", + "source": "Living Errata v1.1 p148" + } + }, + { + "name": "Astartes Missile Launcher-Soundstrike", + "req": 10, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 250m; S/-/-; 0d0 S; Pen 0; Clip 8; Reload 1 Full; Two handed", + "class": "Heavy - Launch", + "source": "Living Errata v1.1 p152" + } + }, + { + "name": "Astartes Multi-Melta - Maxima", + "req": 35, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 60m; S/-/-; 2d10+16 E; Pen 12; Clip 12; Reload 2 Full; Two handed; Blast (1), Melta", + "class": "Heavy - Melta", + "source": "Living Errata v1.1 p148" + } + }, + { + "name": "Astartes Plasma Cannon", + "req": 30, + "renown": "Distinguished", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 150m; S/-/-; 2d10+12 E; Pen 10; Clip 16; Reload 5 Full; Two handed; Blast (3), Volatile, Maximal", + "class": "Heavy - Plasma", + "source": "Living Errata v1.1 p147" + } + }, + { + "name": "Astartes Plasma Gun -Ragefire", + "req": 20, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 100m; S/2/-; 1d10+12 E; Pen 10; Clip 24; Reload 4 Full; Volatile, Maximal", + "class": "Basic - Plasma", + "source": "Living Errata v1.1 p148" + } + }, + { + "name": "Astartes Plasma Pistol", + "req": 25, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 30m; S/2/-; 1d10+10 E; Pen 8; Clip 12; Reload 3 Full; Volatile, Maximal", + "class": "Pistol - Plasma", + "source": "Living Errata v1.1 p148" + } } ], "meleeWeapons": [ @@ -161,21 +338,10 @@ "source": "First Founding p99" } }, - { - "name": "Astartes Chainfist", - "req": 40, - "renown": "Hero", - "category": "Melee Weapon", - "stats": { - "damage": "2d10+\"2*SB\" E; Pen 10; Power Field, Tearing, Unwieldy", - "class": "One-Handed Melee - Power", - "source": "Living Errata v1.1 p154" - } - }, { "name": "Astartes Chainsword", "req": 5, - "renown": "None", + "renown": "Any", "category": "Melee Weapon", "stats": { "damage": "1d10+3 R; Pen 3; Balanced, Tearing", @@ -186,10 +352,10 @@ { "name": "Astartes Combat Knife", "req": 3, - "renown": "None", + "renown": "Any", "category": "Melee Weapon", "stats": { - "damage": "1d10 R; Pen 2;", + "damage": "1d10 R; Pen 2", "class": "One-Handed Melee - Primitive", "source": "Living Errata v1.1 p155" } @@ -204,13 +370,101 @@ "class": "One-Handed Melee - Primitive", "source": "Living Errata v1.1 p166" } + }, + { + "name": "Astartes Power Axe", + "req": 20, + "renown": "Respected", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+8 E; Pen 7; Power Field, Unbalanced", + "class": "One-Handed Melee - Power", + "source": "Living Errata v1.1 p155" + } + }, + { + "name": "Astartes Power Claymore", + "req": 15, + "renown": "Distinguished", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+11 E; Pen 8; Two handed; Power Field, Unwieldy, Devastating (1)", + "class": "Two-Handed Melee - Power", + "source": "Living Errata v1.1 p139" + } + }, + { + "name": "Astartes Power Falchion", + "req": 25, + "renown": "Distinguished", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+4 E; Pen 6; Two handed; Power Field, Razor Sharp", + "class": "One-Handed Melee - Power", + "source": "Living Errata v1.1 p139" + } + }, + { + "name": "Astartes Power Fist", + "req": 30, + "renown": "Distinguished", + "category": "Melee Weapon", + "stats": { + "damage": "2d10+2*SB E; Pen 9; Power Field, Unwieldy", + "class": "One-Handed Melee - Power", + "source": "Living Errata v1.1 p155" + } + }, + { + "name": "Astartes Power Spear", + "req": 15, + "renown": "Distinguished", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+6 E; Pen 7; Two handed; Power Field", + "class": "Two-Handed Melee - Power", + "source": "Living Errata v1.1 p139" + } + }, + { + "name": "Astartes Power Sword", + "req": 20, + "renown": "Respected", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+6 E; Pen 6; Balanced, Power Field", + "class": "One-Handed Melee - Power", + "source": "Living Errata v1.1 p155" + } + }, + { + "name": "Astartes Force Staff", + "req": 25, + "renown": "Respected", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+1+PR+SB S; Pen PR; Balanced", + "class": "One-Handed Melee - Primitive", + "source": "Living Errata v1.1 p155" + } + }, + { + "name": "Astartes Force Sword", + "req": 25, + "renown": "Respected", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+2+PR+SB S; Pen 2+PR; Balanced", + "class": "One-Handed Melee - Primitive", + "source": "Living Errata v1.1 p156" + } } ], "grenades": [ { "name": "Astartes Anti-Plant Grenade", "req": 18, - "renown": "None", + "renown": "Any", "category": "Grenade", "stats": { "damage": "3d10 E; Pen 0; Blast (3)", @@ -221,33 +475,132 @@ { "name": "Astartes Blind Grenade", "req": 10, - "renown": "None", + "renown": "Any", "category": "Grenade", "stats": { "damage": "0d0 S; Pen 0; Smoke (10)", "class": "Thrown - Grenade", "source": "Living Errata v1.1 p150" } + }, + { + "name": "Astartes Frag Grenade", + "req": 1, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "2d10+2 X; Pen 0; Blast (4)", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p150" + } + }, + { + "name": "Astartes Incendiary Grenade", + "req": 15, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "1d10+4 E; Pen 0; Blast (3)", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p150" + } + }, + { + "name": "Astartes Krak Grenade", + "req": 1, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "3d10+4 X; Pen 6", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p150" + } + }, + { + "name": "Astartes Nova Grenade", + "req": 15, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "1d10 E; Pen 0; Blast (3)", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p151" + } + }, + { + "name": "Astartes Photon Flash Grenade", + "req": 5, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "0d0 S; Pen 0", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p151" + } + }, + { + "name": "Astartes Plasma Grenade", + "req": 20, + "renown": "Distinguished", + "category": "Grenade", + "stats": { + "damage": "1d10+12 E; Pen 8; Blast (3)", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p151" + } } ], "otherWeapons": [ { "name": "Argrax Clawed Hooves", "req": 0, - "renown": "None", + "renown": "Any", "category": "Other", "stats": { - "damage": "1d10 I; Pen 0;", + "damage": "1d10 I; Pen 0", "class": "Natural - Primitive", "source": "The Emperor Protects p46" } + }, + { + "name": "Assault Cannon-Samech", + "req": 0, + "renown": "Any", + "category": "Other", + "stats": { + "damage": "Range 120m; -/-/10; 3d10+6 I; Pen 5; Clip 200; Reload 2 Full; Tearing", + "class": "Mounted - Solid Projectile", + "source": "The Emperor Protects p120" + } + }, + { + "name": "Astartes Servo-Arm", + "req": 30, + "renown": "Any", + "category": "Other", + "stats": { + "damage": "2d10+14 I; Pen 10", + "class": "Mounted - Primitive", + "source": "Living Errata v1.1 p177" + } + }, + { + "name": "Astartes Servo-Arm Exceptional", + "req": 30, + "renown": "Any", + "category": "Other", + "stats": { + "damage": "2d10+16 I; Pen 10", + "class": "Mounted - Primitive", + "source": "Deathwatch Core Rulebook p177" + } } ], "powerArmor": [ { "name": "Armour of the Remorseless Crusader", "req": 70, - "renown": "None", + "renown": "Any", "category": "Power Armor", "stats": { "type": "Power", @@ -279,7 +632,7 @@ { "name": "Astartes Mk 1 Thunder Power Armour", "req": 0, - "renown": "None", + "renown": "Any", "category": "Power Armor", "stats": { "type": "Power", @@ -295,7 +648,7 @@ { "name": "Astartes Mk 2 Crusade Power Armour", "req": 0, - "renown": "None", + "renown": "Any", "category": "Power Armor", "stats": { "type": "Power", @@ -311,7 +664,7 @@ { "name": "Astartes Mk 3 Iron Power Armour", "req": 0, - "renown": "None", + "renown": "Any", "category": "Power Armor", "stats": { "type": "Power", @@ -327,7 +680,7 @@ { "name": "Astartes Mk 4 Maximus Power Armour", "req": 0, - "renown": "None", + "renown": "Any", "category": "Power Armor", "stats": { "type": "Power", @@ -343,7 +696,7 @@ { "name": "Astartes Mk 5 Heresy Power Armour", "req": 0, - "renown": "None", + "renown": "Any", "category": "Power Armor", "stats": { "type": "Power", @@ -359,7 +712,7 @@ { "name": "Astartes Mk 6 Corvus Power Armour", "req": 0, - "renown": "None", + "renown": "Any", "category": "Power Armor", "stats": { "type": "Power", @@ -375,7 +728,7 @@ { "name": "Astartes Mk 7 Aquilla Power Armour", "req": 0, - "renown": "None", + "renown": "Any", "category": "Power Armor", "stats": { "type": "Power", @@ -391,7 +744,7 @@ { "name": "Astartes Mk 8 Errant Power Armour", "req": 0, - "renown": "None", + "renown": "Any", "category": "Power Armor", "stats": { "type": "Power", @@ -404,138 +757,10 @@ "source": "Rites of Battle p151" } }, - { - "name": "Astartes Mk1 Power Armour Helm", - "req": 0, - "renown": "None", - "category": "Power Armor", - "stats": { - "type": "Power", - "protection": { - "head": 6, - "arms": 0, - "body": 0, - "legs": 0 - }, - "source": "Rites of Battle p151" - } - }, - { - "name": "Astartes Mk2 Power Armour Helm", - "req": 0, - "renown": "None", - "category": "Power Armor", - "stats": { - "type": "Power", - "protection": { - "head": 7, - "arms": 0, - "body": 0, - "legs": 0 - }, - "source": "Rites of Battle p151" - } - }, - { - "name": "Astartes Mk3 Power Armour Helm", - "req": 0, - "renown": "None", - "category": "Power Armor", - "stats": { - "type": "Power", - "protection": { - "head": 9, - "arms": 0, - "body": 0, - "legs": 0 - }, - "source": "Rites of Battle p151" - } - }, - { - "name": "Astartes Mk4 Power Armour Helm", - "req": 0, - "renown": "None", - "category": "Power Armor", - "stats": { - "type": "Power", - "protection": { - "head": 7, - "arms": 0, - "body": 0, - "legs": 0 - }, - "source": "Rites of Battle p151" - } - }, - { - "name": "Astartes Mk5 Power Armour Helm", - "req": 0, - "renown": "None", - "category": "Power Armor", - "stats": { - "type": "Power", - "protection": { - "head": 8, - "arms": 0, - "body": 0, - "legs": 0 - }, - "source": "Rites of Battle p151" - } - }, - { - "name": "Astartes Mk6 Power Armour Helm", - "req": 0, - "renown": "None", - "category": "Power Armor", - "stats": { - "type": "Power", - "protection": { - "head": 8, - "arms": 0, - "body": 0, - "legs": 0 - }, - "source": "Rites of Battle p151" - } - }, - { - "name": "Astartes Mk7 Power Armour Helm", - "req": 0, - "renown": "None", - "category": "Power Armor", - "stats": { - "type": "Power", - "protection": { - "head": 8, - "arms": 0, - "body": 0, - "legs": 0 - }, - "source": "Rites of Battle p151" - } - }, - { - "name": "Astartes Mk8 Power Armour Helm", - "req": 0, - "renown": "None", - "category": "Power Armor", - "stats": { - "type": "Power", - "protection": { - "head": 8, - "arms": 0, - "body": 0, - "legs": 0 - }, - "source": "Rites of Battle p151" - } - }, { "name": "Astartes Power Armour", "req": 0, - "renown": "None", + "renown": "Any", "category": "Power Armor", "stats": { "type": "Power", @@ -548,26 +773,10 @@ "source": "Deathwatch Core Rulebook p160" } }, - { - "name": "Astartes Power Armour Helm", - "req": 0, - "renown": "None", - "category": "Power Armor", - "stats": { - "type": "Power", - "protection": { - "head": 8, - "arms": 0, - "body": 0, - "legs": 0 - }, - "source": "Deathwatch Core Rulebook p160" - } - }, { "name": "Astartes Tactical Dreadnaught-Terminator Armour", "req": 100, - "renown": "Hero", + "renown": "Famed", "category": "Power Armor", "stats": { "type": "Power", @@ -580,26 +789,10 @@ "source": "Deathwatch Core Rulebook p164" } }, - { - "name": "Astartes Tactical Dreadnaught-Terminator Armour Helm", - "req": 100, - "renown": "Hero", - "category": "Power Armor", - "stats": { - "type": "Power", - "protection": { - "head": 14, - "arms": 0, - "body": 0, - "legs": 0 - }, - "source": "Deathwatch Core Rulebook p164" - } - }, { "name": "Astartes Terminator Armour", "req": 100, - "renown": "Hero", + "renown": "Famed", "category": "Power Armor", "stats": { "type": "Power", @@ -615,7 +808,7 @@ { "name": "CM Power Armour", "req": 0, - "renown": "None", + "renown": "Any", "category": "Power Armor", "stats": { "type": "Power", @@ -628,26 +821,10 @@ "source": "Mark of the Xenos p114" } }, - { - "name": "Diagnostor Helmet", - "req": 15, - "renown": "None", - "category": "Power Armor", - "stats": { - "type": "Power", - "protection": { - "head": 8, - "arms": 0, - "body": 0, - "legs": 0 - }, - "source": "Deathwatch Core Rulebook p165" - } - }, { "name": "Dmn Armour of Chaos", "req": 0, - "renown": "None", + "renown": "Any", "category": "Power Armor", "stats": { "type": "Power", @@ -660,42 +837,10 @@ "source": "Deathwatch Core Rulebook p362" } }, - { - "name": "Fenris Pattern Wolf Helm", - "req": 0, - "renown": "Respected", - "category": "Power Armor", - "stats": { - "type": "Power", - "protection": { - "head": 8, - "arms": 0, - "body": 0, - "legs": 0 - }, - "source": "Rites of Battle p143" - } - }, - { - "name": "Skull Helm", - "req": 0, - "renown": "None", - "category": "Power Armor", - "stats": { - "type": "Power", - "protection": { - "head": 9, - "arms": 0, - "body": 0, - "legs": 0 - }, - "source": "Rites of Battle p143" - } - }, { "name": "Tau XV-8 Crisis Battlesuit", "req": 0, - "renown": "None", + "renown": "Any", "category": "Power Armor", "stats": { "type": "Power", @@ -711,7 +856,7 @@ { "name": "Tau XV-88 Broadside Battlesuit", "req": 0, - "renown": "None", + "renown": "Any", "category": "Power Armor", "stats": { "type": "Power", @@ -727,7 +872,7 @@ { "name": "Tau XV15 Stealth Suit (Limbs)", "req": 0, - "renown": "None", + "renown": "Any", "category": "Power Armor", "stats": { "type": "Power", @@ -743,7 +888,7 @@ { "name": "Tau XV15 Stealth Suit (Top)", "req": 0, - "renown": "None", + "renown": "Any", "category": "Power Armor", "stats": { "type": "Power", @@ -759,7 +904,7 @@ { "name": "Tau XV8 Crisis Suit", "req": 0, - "renown": "None", + "renown": "Any", "category": "Power Armor", "stats": { "type": "Power", @@ -773,11 +918,221 @@ } } ], + "powerArmorHelms": [ + { + "name": "Astartes Mk1 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 6, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk2 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 7, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk3 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 9, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk4 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 7, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk5 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk6 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk7 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk8 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Deathwatch Core Rulebook p160" + } + }, + { + "name": "Astartes Tactical Dreadnaught-Terminator Armour Helm", + "req": 100, + "renown": "Famed", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 14, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Deathwatch Core Rulebook p164" + } + }, + { + "name": "Diagnostor Helmet", + "req": 15, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Deathwatch Core Rulebook p165" + } + }, + { + "name": "Fenris Pattern Wolf Helm", + "req": 0, + "renown": "Respected", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p143" + } + }, + { + "name": "Skull Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 9, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p143" + } + } + ], "carapaceArmor": [ { "name": "Astartes Scout Armour", "req": 0, - "renown": "None", + "renown": "Any", "category": "Carapace Armor", "stats": { "type": "Carapace", @@ -793,7 +1148,7 @@ { "name": "Chaos Flak Robes and Brazen Carapace", "req": 0, - "renown": "None", + "renown": "Any", "category": "Carapace Armor", "stats": { "type": "Carapace", @@ -809,7 +1164,7 @@ { "name": "Deathwatch Scout Armor", "req": 0, - "renown": "None", + "renown": "Any", "category": "Carapace Armor", "stats": { "type": "Carapace", @@ -825,7 +1180,7 @@ { "name": "Tau Fire Warrior Armour", "req": 0, - "renown": "None", + "renown": "Any", "category": "Carapace Armor", "stats": { "type": "Carapace", @@ -841,7 +1196,7 @@ { "name": "Tau Pathfinder Armour", "req": 0, - "renown": "None", + "renown": "Any", "category": "Carapace Armor", "stats": { "type": "Carapace", @@ -855,77 +1210,11 @@ } } ], - "primitiveArmor": [ - { - "name": "Auran Golden Saurian Scale Armour", - "req": 0, - "renown": "None", - "category": "Primitive Armor", - "stats": { - "type": "Primitive", - "protection": { - "head": 6, - "arms": 6, - "body": 6, - "legs": 6 - }, - "source": "The Emperor Protects p48" - } - }, - { - "name": "Auran Saurian Scale Armour", - "req": 0, - "renown": "None", - "category": "Primitive Armor", - "stats": { - "type": "Primitive", - "protection": { - "head": 4, - "arms": 4, - "body": 4, - "legs": 4 - }, - "source": "The Emperor Protects p46" - } - }, - { - "name": "Scales", - "req": 0, - "renown": "None", - "category": "Primitive Armor", - "stats": { - "type": "Primitive", - "protection": { - "head": 2, - "arms": 2, - "body": 2, - "legs": 2 - }, - "source": "The Emperor Protects p50" - } - }, - { - "name": "Scaly Hide", - "req": 0, - "renown": "None", - "category": "Primitive Armor", - "stats": { - "type": "Primitive", - "protection": { - "head": 4, - "arms": 4, - "body": 4, - "legs": 4 - }, - "source": "The Emperor Protects p46" - } - } - ], "naturalArmor": [ { "name": "Tau Gun Drone Armour", "req": 0, - "renown": "None", + "renown": "Any", "category": "Natural Armor", "stats": { "type": "Natural", @@ -941,7 +1230,7 @@ { "name": "Tyr Bonded Exoskeleton", "req": 0, - "renown": "None", + "renown": "Any", "category": "Natural Armor", "stats": { "type": "Natural", @@ -957,7 +1246,7 @@ { "name": "Tyr Chitinous Carapace", "req": 0, - "renown": "None", + "renown": "Any", "category": "Natural Armor", "stats": { "type": "Natural", @@ -970,10 +1259,26 @@ "source": "Deathwatch Core Rulebook p371" } }, + { + "name": "Tyr Reinforced Chitin", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 8, + "arms": 8, + "body": 8, + "legs": 8 + }, + "source": "Deathwatch Core Rulebook p371" + } + }, { "name": "Tyr Exoskeleton", "req": 0, - "renown": "None", + "renown": "Any", "category": "Natural Armor", "stats": { "type": "Natural", @@ -989,7 +1294,7 @@ { "name": "Tyr Hardened Carapace", "req": 0, - "renown": "None", + "renown": "Any", "category": "Natural Armor", "stats": { "type": "Natural", @@ -1005,7 +1310,7 @@ { "name": "Tyr Light Reinforced Chitin", "req": 0, - "renown": "None", + "renown": "Any", "category": "Natural Armor", "stats": { "type": "Natural", @@ -1021,7 +1326,7 @@ { "name": "Tyr Medium Reinforced Chitin", "req": 0, - "renown": "None", + "renown": "Any", "category": "Natural Armor", "stats": { "type": "Natural", @@ -1034,26 +1339,10 @@ "source": "Mark of the Xenos p37" } }, - { - "name": "Tyr Reinforced Chitin", - "req": 0, - "renown": "None", - "category": "Natural Armor", - "stats": { - "type": "Natural", - "protection": { - "head": 8, - "arms": 8, - "body": 8, - "legs": 8 - }, - "source": "Deathwatch Core Rulebook p371" - } - }, { "name": "Tyr Thickened Scales", "req": 0, - "renown": "None", + "renown": "Any", "category": "Natural Armor", "stats": { "type": "Natural", @@ -1069,7 +1358,7 @@ { "name": "Vespid Chitin", "req": 0, - "renown": "None", + "renown": "Any", "category": "Natural Armor", "stats": { "type": "Natural", @@ -1085,7 +1374,7 @@ { "name": "Xenos Hardened Hide", "req": 0, - "renown": "None", + "renown": "Any", "category": "Natural Armor", "stats": { "type": "Natural", @@ -1101,7 +1390,7 @@ { "name": "Xenos Scaly Hide", "req": 0, - "renown": "None", + "renown": "Any", "category": "Natural Armor", "stats": { "type": "Natural", @@ -1117,7 +1406,7 @@ { "name": "Xenos Slimey Hide", "req": 0, - "renown": "None", + "renown": "Any", "category": "Natural Armor", "stats": { "type": "Natural", @@ -1133,7 +1422,7 @@ { "name": "Xenos Thick Scales", "req": 0, - "renown": "None", + "renown": "Any", "category": "Natural Armor", "stats": { "type": "Natural", @@ -1147,11 +1436,77 @@ } } ], + "primitiveArmor": [ + { + "name": "Auran Golden Saurian Scale Armour", + "req": 0, + "renown": "Any", + "category": "Primitive Armor", + "stats": { + "type": "Primitive", + "protection": { + "head": 6, + "arms": 6, + "body": 6, + "legs": 6 + }, + "source": "The Emperor Protects p48" + } + }, + { + "name": "Auran Saurian Scale Armour", + "req": 0, + "renown": "Any", + "category": "Primitive Armor", + "stats": { + "type": "Primitive", + "protection": { + "head": 4, + "arms": 4, + "body": 4, + "legs": 4 + }, + "source": "The Emperor Protects p46" + } + }, + { + "name": "Scales", + "req": 0, + "renown": "Any", + "category": "Primitive Armor", + "stats": { + "type": "Primitive", + "protection": { + "head": 2, + "arms": 2, + "body": 2, + "legs": 2 + }, + "source": "The Emperor Protects p50" + } + }, + { + "name": "Scaly Hide", + "req": 0, + "renown": "Any", + "category": "Primitive Armor", + "stats": { + "type": "Primitive", + "protection": { + "head": 4, + "arms": 4, + "body": 4, + "legs": 4 + }, + "source": "The Emperor Protects p46" + } + } + ], "xenosArmor": [ { "name": "Nec Metallic Exoskeleton", "req": 0, - "renown": "None", + "renown": "Any", "category": "Xenos Armor", "stats": { "type": "Necron", @@ -1167,7 +1522,7 @@ { "name": "Nec Metallic Shell", "req": 0, - "renown": "None", + "renown": "Any", "category": "Xenos Armor", "stats": { "type": "Necron", @@ -1183,7 +1538,7 @@ { "name": "Ork Eavy Armour", "req": 0, - "renown": "None", + "renown": "Any", "category": "Xenos Armor", "stats": { "type": "Ork", @@ -1199,7 +1554,7 @@ { "name": "Ork Flak Armour", "req": 0, - "renown": "None", + "renown": "Any", "category": "Xenos Armor", "stats": { "type": "Ork", @@ -1215,7 +1570,7 @@ { "name": "Ork Mega Armour", "req": 0, - "renown": "None", + "renown": "Any", "category": "Xenos Armor", "stats": { "type": "Ork", @@ -1234,12 +1589,12 @@ "name": "Astartes Storm Shield - Protective", "req": 35, "renown": "Distinguished", - "category": "Shields", + "category": "Shield", "stats": { "type": "Shield", "protection": { "head": 0, - "arms": 0, + "arms": "0LA 4RA", "body": 4, "legs": 0 }, @@ -1248,26 +1603,10 @@ } ], "otherArmor": [ - { - "name": "Name", - "req": 0, - "renown": "Distinguished", - "category": "Other Armor", - "stats": { - "type": "Type", - "protection": { - "head": 0, - "arms": 0, - "body": 0, - "legs": 0 - }, - "source": "Book pPage No." - } - }, { "name": "Chaos Armour Plating", "req": 0, - "renown": "None", + "renown": "Any", "category": "Other Armor", "stats": { "type": "Other", @@ -1283,7 +1622,7 @@ { "name": "Chaos Bones of Subersion", "req": 0, - "renown": "None", + "renown": "Any", "category": "Other Armor", "stats": { "type": "Other", @@ -1299,7 +1638,7 @@ { "name": "Chaos Slinnar Obsidian Shell", "req": 0, - "renown": "None", + "renown": "Any", "category": "Other Armor", "stats": { "type": "Other", @@ -1315,7 +1654,7 @@ { "name": "Chaos Warded Adamantine Shell", "req": 0, - "renown": "None", + "renown": "Any", "category": "Other Armor", "stats": { "type": "Other", @@ -1331,7 +1670,7 @@ { "name": "Daemon Iron Hide", "req": 0, - "renown": "None", + "renown": "Any", "category": "Other Armor", "stats": { "type": "Other", @@ -1347,7 +1686,7 @@ { "name": "Dmn Brazen Chaos Armour", "req": 0, - "renown": "None", + "renown": "Any", "category": "Other Armor", "stats": { "type": "Other", @@ -1363,7 +1702,7 @@ { "name": "Obliterator Warped Mechnical Flesh", "req": 0, - "renown": "None", + "renown": "Any", "category": "Other Armor", "stats": { "type": "Other", @@ -1379,7 +1718,7 @@ { "name": "Rad Corrupted Mechnical Flesh", "req": 0, - "renown": "None", + "renown": "Any", "category": "Other Armor", "stats": { "type": "Other", diff --git a/public/deathwatch-weapons-comprehensive.json b/public/deathwatch-weapons-comprehensive.json new file mode 100644 index 0000000..29ce925 --- /dev/null +++ b/public/deathwatch-weapons-comprehensive.json @@ -0,0 +1,582 @@ +{ + "rangedWeapons": [ + { + "name": "Angelus Bolter", + "req": 25, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 50m; S/3/-; 1d10+9 X; Pen 6; Clip 36; Reload 2 Full; Tearing", + "class": "Basic - Bolt", + "source": "First Founding p97" + } + }, + { + "name": "Astartes Armoursbane Missile Launcher", + "req": 15, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 200m; S/-/-; 0d0 S; Pen 0; Clip 1; Reload 2 Full; Two handed", + "class": "Heavy - Launch", + "source": "Rites of Battle p137" + } + }, + { + "name": "Astartes Assault Cannon", + "req": 30, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 150m; -/-/10; 3d10+6 I; Pen 6; Clip 200; Reload 3 Full; Tearing", + "class": "Mounted - Solid Projectile", + "source": "Deathwatch Core Rulebook p149" + } + }, + { + "name": "Astartes Assault Shotgun", + "req": 7, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 30m; S/3/5; 1d10+10 I; Pen 4; Clip 20; Reload 1 Full; Two handed; Reliable, Scatter", + "class": "Basic - Solid Projectile", + "source": "Living Errata v1.1 p136" + } + }, + { + "name": "Astartes Bolt Pistol", + "req": 5, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 30m; S/2/-; 1d10+9 X; Pen 4; Clip 14; Reload 1 Full; Tearing", + "class": "Pistol - Bolt", + "source": "Living Errata v1.1 p146" + } + }, + { + "name": "Astartes Bolter-Godwyn", + "req": 5, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 100m; S/3/-; 1d10+9 X; Pen 4; Clip 28; Reload 1 Full; Two handed; Tearing", + "class": "Basic - Bolt", + "source": "Living Errata v1.1 p146" + } + }, + { + "name": "Astartes Boltgun-Stalker", + "req": 15, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 200m; S/-/-; 1d10+9 X; Pen 4; Clip 24; Reload 1 Full; Two handed; Accurate, Tearing", + "class": "Basic - Bolt", + "source": "Living Errata v1.1 p146" + } + }, + { + "name": "Astartes Chainfist", + "req": 40, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "2d10+2*SB E; Pen 10; Power Field, Tearing, Unwieldy", + "class": "One-Handed Melee - Power", + "source": "Living Errata v1.1 p154" + } + }, + { + "name": "Astartes Combi-Weapon", + "req": 15, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 100m; S/4/-; 1d10+9 X; Pen 4; Clip 28; Reload 1 Full; Two handed; Tearing", + "class": "Basic - Bolt", + "source": "Living Errata v1.1 p146" + } + }, + { + "name": "Astartes Conversion Beamer", + "req": 40, + "renown": "Hero", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 100m; S/-/-; 0d0 E; Pen 0; Clip 4; Reload 2 Full; Two handed", + "class": "Heavy - Exotic", + "source": "Living Errata v1.1 p152" + } + }, + { + "name": "Astartes Cyclone Missile Launcher", + "req": 25, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 300m; S/2/-; 0d0 S; Pen 0; Clip 12; Reload 3 Full", + "class": "Mounted - Launch", + "source": "Living Errata v1.1 p152" + } + }, + { + "name": "Astartes Digital Flamer", + "req": 35, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 4m; S/-/-; 1d10+9 E; Pen 4; Clip 1; Reload 1d5 Hours; Flame, Spray", + "class": "Pistol - Exotic", + "source": "Living Errata v1.1 p153" + } + }, + { + "name": "Astartes Digital Laser", + "req": 35, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 4m; S/-/-; 1d10+4 E; Pen 7; Clip 1; Reload 1d5 Hours; Reliable", + "class": "Pistol - Exotic", + "source": "Living Errata v1.1 p153" + } + }, + { + "name": "Astartes Digital Melta", + "req": 35, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 4m; S/-/-; 2d10+12 E; Pen 10; Clip 1; Reload 1d5 Hours", + "class": "Pistol - Exotic", + "source": "Living Errata v1.1 p153" + } + }, + { + "name": "Astartes Executioner Axe", + "req": 25, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "1d10+13 E; Pen 8; Two handed; Power Field, Unwieldy, Felling (x1)", + "class": "Two-Handed Melee - Power", + "source": "Living Errata v1.1 p139" + } + }, + { + "name": "Astartes Flamer", + "req": 10, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 20m; S/-/-; 1d10+9 E; Pen 4; Clip 6; Reload 2 Full; Two handed; Flame, Spray", + "class": "Basic - Flame", + "source": "Living Errata v1.1 p148" + } + }, + { + "name": "Astartes Heavy Flamer", + "req": 15, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 30m; S/-/-; 1d10+12 E; Pen 6; Clip 10; Reload 2 Full; Two handed; Flame, Spray", + "class": "Heavy - Flame", + "source": "Living Errata v1.1 p149" + } + }, + { + "name": "Astartes Heavy-Bolter", + "req": 20, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 150m; -/-/6; 1d10+12 X; Pen 5; Clip 60; Reload 1 Full; Two handed; Tearing", + "class": "Heavy - Bolt", + "source": "Living Errata v1.1 p147" + } + }, + { + "name": "Astartes Infernus Pistol", + "req": 35, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 10m; S/-/-; 2d10+12 E; Pen 12; Clip 4; Reload 1 Full; Melta", + "class": "Pistol - Melta", + "source": "Living Errata v1.1 p148" + } + }, + { + "name": "Astartes Lascannon", + "req": 30, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 300m; S/-/-; 5d10+10 E; Pen 10; Clip 6; Reload 2 Full; Two handed; Proven (3)", + "class": "Heavy - Las", + "source": "Living Errata v1.1 p149" + } + }, + { + "name": "Astartes Lightning Claw", + "req": 30, + "renown": "Distinguished", + "category": "Ranged Weapon", + "stats": { + "damage": "1d10+6 E; Pen 8; Power Field, Proven (4)", + "class": "One-Handed Melee - Power", + "source": "Living Errata v1.1 p154" + } + }, + { + "name": "Astartes Meltagun-Vulkan", + "req": 20, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 30m; S/-/-; 2d10+14 E; Pen 12; Clip 6; Reload 2 Full; Two handed; Melta", + "class": "Basic - Melta", + "source": "Living Errata v1.1 p148" + } + }, + { + "name": "Astartes Missile Launcher-Soundstrike", + "req": 10, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 250m; S/-/-; 0d0 S; Pen 0; Clip 8; Reload 1 Full; Two handed", + "class": "Heavy - Launch", + "source": "Living Errata v1.1 p152" + } + }, + { + "name": "Astartes Multi-Melta - Maxima", + "req": 35, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 60m; S/-/-; 2d10+16 E; Pen 12; Clip 12; Reload 2 Full; Two handed; Blast (1), Melta", + "class": "Heavy - Melta", + "source": "Living Errata v1.1 p148" + } + }, + { + "name": "Astartes Plasma Cannon", + "req": 30, + "renown": "Distinguished", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 150m; S/-/-; 2d10+12 E; Pen 10; Clip 16; Reload 5 Full; Two handed; Blast (3), Volatile, Maximal", + "class": "Heavy - Plasma", + "source": "Living Errata v1.1 p147" + } + }, + { + "name": "Astartes Plasma Gun -Ragefire", + "req": 20, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 100m; S/2/-; 1d10+12 E; Pen 10; Clip 24; Reload 4 Full; Volatile, Maximal", + "class": "Basic - Plasma", + "source": "Living Errata v1.1 p148" + } + }, + { + "name": "Astartes Plasma Pistol", + "req": 25, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 30m; S/2/-; 1d10+10 E; Pen 8; Clip 12; Reload 3 Full; Volatile, Maximal", + "class": "Pistol - Plasma", + "source": "Living Errata v1.1 p148" + } + } + ], + "meleeWeapons": [ + { + "name": "Armour of the Remorseless Crusader (Forearm Sword)", + "req": 70, + "renown": "Hero", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+8 R; Pen 6; +10 to hit; Sanctified", + "class": "One-Handed Melee - Primitive", + "source": "Deathwatch Core Rulebook p167" + } + }, + { + "name": "Artificer Omnissian Axe", + "req": 25, + "renown": "Distinguished", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+9 E; Pen 7; Power Field, Unbalanced", + "class": "One-Handed Melee - Power", + "source": "First Founding p99" + } + }, + { + "name": "Astartes Chainsword", + "req": 5, + "renown": "Any", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+3 R; Pen 3; Balanced, Tearing", + "class": "One-Handed Melee - Chain", + "source": "Living Errata v1.1 p153" + } + }, + { + "name": "Astartes Combat Knife", + "req": 3, + "renown": "Any", + "category": "Melee Weapon", + "stats": { + "damage": "1d10 R; Pen 2", + "class": "One-Handed Melee - Primitive", + "source": "Living Errata v1.1 p155" + } + }, + { + "name": "Astartes Combat Shield", + "req": 20, + "renown": "Distinguished", + "category": "Melee Weapon", + "stats": { + "damage": "1d5+1 I; Pen 0; Balanced", + "class": "One-Handed Melee - Primitive", + "source": "Living Errata v1.1 p166" + } + }, + { + "name": "Astartes Power Axe", + "req": 20, + "renown": "Respected", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+8 E; Pen 7; Power Field, Unbalanced", + "class": "One-Handed Melee - Power", + "source": "Living Errata v1.1 p155" + } + }, + { + "name": "Astartes Power Claymore", + "req": 15, + "renown": "Distinguished", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+11 E; Pen 8; Two handed; Power Field, Unwieldy, Devastating (1)", + "class": "Two-Handed Melee - Power", + "source": "Living Errata v1.1 p139" + } + }, + { + "name": "Astartes Power Falchion", + "req": 25, + "renown": "Distinguished", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+4 E; Pen 6; Two handed; Power Field, Razor Sharp", + "class": "One-Handed Melee - Power", + "source": "Living Errata v1.1 p139" + } + }, + { + "name": "Astartes Power Fist", + "req": 30, + "renown": "Distinguished", + "category": "Melee Weapon", + "stats": { + "damage": "2d10+2*SB E; Pen 9; Power Field, Unwieldy", + "class": "One-Handed Melee - Power", + "source": "Living Errata v1.1 p155" + } + }, + { + "name": "Astartes Power Spear", + "req": 15, + "renown": "Distinguished", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+6 E; Pen 7; Two handed; Power Field", + "class": "Two-Handed Melee - Power", + "source": "Living Errata v1.1 p139" + } + }, + { + "name": "Astartes Power Sword", + "req": 20, + "renown": "Respected", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+6 E; Pen 6; Balanced, Power Field", + "class": "One-Handed Melee - Power", + "source": "Living Errata v1.1 p155" + } + }, + { + "name": "Astartes Force Staff", + "req": 25, + "renown": "Respected", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+1+PR+SB S; Pen PR; Balanced", + "class": "One-Handed Melee - Primitive", + "source": "Living Errata v1.1 p155" + } + }, + { + "name": "Astartes Force Sword", + "req": 25, + "renown": "Respected", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+2+PR+SB S; Pen 2+PR; Balanced", + "class": "One-Handed Melee - Primitive", + "source": "Living Errata v1.1 p156" + } + } + ], + "grenades": [ + { + "name": "Astartes Anti-Plant Grenade", + "req": 18, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "3d10 E; Pen 0; Blast (3)", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p136" + } + }, + { + "name": "Astartes Blind Grenade", + "req": 10, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "0d0 S; Pen 0; Smoke (10)", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p150" + } + }, + { + "name": "Astartes Frag Grenade", + "req": 1, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "2d10+2 X; Pen 0; Blast (4)", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p150" + } + }, + { + "name": "Astartes Incendiary Grenade", + "req": 15, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "1d10+4 E; Pen 0; Blast (3)", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p150" + } + }, + { + "name": "Astartes Krak Grenade", + "req": 1, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "3d10+4 X; Pen 6", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p150" + } + }, + { + "name": "Astartes Nova Grenade", + "req": 15, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "1d10 E; Pen 0; Blast (3)", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p151" + } + }, + { + "name": "Astartes Photon Flash Grenade", + "req": 5, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "0d0 S; Pen 0", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p151" + } + }, + { + "name": "Astartes Plasma Grenade", + "req": 20, + "renown": "Distinguished", + "category": "Grenade", + "stats": { + "damage": "1d10+12 E; Pen 8; Blast (3)", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p151" + } + } + ], + "other": [ + { + "name": "Argrax Clawed Hooves", + "req": 0, + "renown": "Any", + "category": "Other", + "stats": { + "damage": "1d10 I; Pen 0", + "class": "Natural - Primitive", + "source": "The Emperor Protects p46" + } + }, + { + "name": "Assault Cannon-Samech", + "req": 0, + "renown": "Any", + "category": "Other", + "stats": { + "damage": "Range 120m; -/-/10; 3d10+6 I; Pen 5; Clip 200; Reload 2 Full; Tearing", + "class": "Mounted - Solid Projectile", + "source": "The Emperor Protects p120" + } + }, + { + "name": "Astartes Servo-Arm", + "req": 30, + "renown": "Any", + "category": "Other", + "stats": { + "damage": "2d10+14 I; Pen 10", + "class": "Mounted - Primitive", + "source": "Living Errata v1.1 p177" + } + }, + { + "name": "Astartes Servo-Arm Exceptional", + "req": 30, + "renown": "Any", + "category": "Other", + "stats": { + "damage": "2d10+16 I; Pen 10", + "class": "Mounted - Primitive", + "source": "Deathwatch Core Rulebook p177" + } + } + ] +} \ No newline at end of file diff --git a/public/deathwatch-weapons-scraped.json b/public/deathwatch-weapons-scraped.json new file mode 100644 index 0000000..2b580c1 --- /dev/null +++ b/public/deathwatch-weapons-scraped.json @@ -0,0 +1,57 @@ +{ + "pistols": [], + "basicWeapons": [ + { + "name": "Angelus Bolter", + "req": 25, + "renown": "Respected", + "category": "basic Weapons", + "stats": { + "damage": "Range 50m; S/3/-; 1d10+9 X; Pen 6; Clip 36; Reload 2 Full; Tearing", + "class": "Basic - Bolt", + "source": "First Founding p97" + } + } + ], + "heavyWeapons": [], + "mountedWeapons": [], + "meleeWeapons": [ + { + "name": "Armour of the Remorseless Crusader (Forearm Sword)", + "req": 70, + "renown": "Hero", + "category": "melee Weapons", + "stats": { + "damage": "1d10+8 R; Pen 6; +10 to hit; Sanctified", + "class": "One-Handed Melee - Primitive", + "source": "Deathwatch Core Rulebook p167" + } + }, + { + "name": "Artificer Omnissian Axe", + "req": 25, + "renown": "Distinguished", + "category": "melee Weapons", + "stats": { + "damage": "1d10+9 E; Pen 7; Power Field, Unbalanced", + "class": "One-Handed Melee - Power", + "source": "First Founding p99" + } + } + ], + "grenades": [], + "naturalWeapons": [ + { + "name": "Argrax Clawed Hooves", + "req": 0, + "renown": "None", + "category": "natural Weapons", + "stats": { + "damage": "1d10 I; Pen 0;", + "class": "Natural - Primitive", + "source": "The Emperor Protects p46" + } + } + ], + "otherWeapons": [] +} \ No newline at end of file diff --git a/scripts/build-shop-db.js b/scripts/build-shop-db.js index 8316af3..d06b0d3 100644 --- a/scripts/build-shop-db.js +++ b/scripts/build-shop-db.js @@ -1,28 +1,31 @@ const { categorizedWeapons } = require('./parse-weapons'); const { categorizedArmor } = require('./parse-armor'); +const comprehensiveWeapons = require('./comprehensive-weapons'); +const comprehensiveArmor = require('./comprehensive-armor'); // Combine all shop items into a single database const buildShopDatabase = () => { const shopItems = { - // Weapons - rangedWeapons: categorizedWeapons.rangedWeapons, - meleeWeapons: categorizedWeapons.meleeWeapons, - grenades: categorizedWeapons.grenades, - otherWeapons: categorizedWeapons.other, + // Use comprehensive weapons dataset + rangedWeapons: comprehensiveWeapons.rangedWeapons, + meleeWeapons: comprehensiveWeapons.meleeWeapons, + grenades: comprehensiveWeapons.grenades, + otherWeapons: comprehensiveWeapons.other, - // Armor - powerArmor: categorizedArmor.powerArmor, - carapaceArmor: categorizedArmor.carapaceArmor, - primitiveArmor: categorizedArmor.primitiveArmor, - naturalArmor: categorizedArmor.naturalArmor, - xenosArmor: categorizedArmor.xenosArmor, - shields: categorizedArmor.shields, - otherArmor: categorizedArmor.otherArmor + // Use comprehensive armor dataset + powerArmor: comprehensiveArmor.powerArmor, + powerArmorHelms: comprehensiveArmor.powerArmorHelms, + carapaceArmor: comprehensiveArmor.carapaceArmor, + naturalArmor: comprehensiveArmor.naturalArmor, + primitiveArmor: comprehensiveArmor.primitiveArmor, + xenosArmor: comprehensiveArmor.xenosArmor, + shields: comprehensiveArmor.shields, + otherArmor: comprehensiveArmor.otherArmor }; // Add metadata const shopDatabase = { - version: "2.0.0", + version: "3.0.0", lastUpdated: new Date().toISOString(), categories: Object.keys(shopItems), items: shopItems @@ -41,7 +44,7 @@ if (require.main === module) { require('./parse-armor'); // Then build and write the combined database - const output = path.resolve('public/deathwatch-armoury.json'); + const output = path.resolve('../public/deathwatch-armoury.json'); const database = buildShopDatabase(); fs.writeFileSync(output, JSON.stringify(database, null, 2), 'utf8'); console.log('Wrote combined shop database to:', output); diff --git a/scripts/comprehensive-armor.js b/scripts/comprehensive-armor.js new file mode 100644 index 0000000..c3a3e9b --- /dev/null +++ b/scripts/comprehensive-armor.js @@ -0,0 +1,1184 @@ +#!/usr/bin/env node + +/** + * Comprehensive armor dataset based on the 40k RPG Tools website + */ + +const fs = require('fs'); +const path = require('path'); + +// Comprehensive armor dataset based on the 40k RPG Tools website +const comprehensiveArmorData = { + "powerArmor": [ + { + "name": "Armour of the Remorseless Crusader", + "req": 70, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 12, + "arms": 12, + "body": 12, + "legs": 12 + }, + "source": "Deathwatch Core Rulebook p167" + } + }, + { + "name": "Astartes Artificer Armour", + "req": 60, + "renown": "Hero", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 12, + "arms": 12, + "body": 12, + "legs": 12 + }, + "source": "Deathwatch Core Rulebook p163" + } + }, + { + "name": "Astartes Mk 1 Thunder Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 6, + "body": 8, + "legs": 4 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk 2 Crusade Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 7, + "body": 9, + "legs": 7 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk 3 Iron Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 9, + "body": 10, + "legs": 9 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk 4 Maximus Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 7, + "body": 9, + "legs": 7 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk 5 Heresy Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 8, + "body": 9, + "legs": 8 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk 6 Corvus Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 8, + "body": 9, + "legs": 8 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk 7 Aquilla Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 8, + "body": 10, + "legs": 8 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk 8 Errant Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 8, + "body": 11, + "legs": 8 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 8, + "body": 10, + "legs": 8 + }, + "source": "Deathwatch Core Rulebook p160" + } + }, + { + "name": "Astartes Tactical Dreadnaught-Terminator Armour", + "req": 100, + "renown": "Famed", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 14, + "body": 14, + "legs": 14 + }, + "source": "Deathwatch Core Rulebook p164" + } + }, + { + "name": "Astartes Terminator Armour", + "req": 100, + "renown": "Famed", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 14, + "arms": 14, + "body": 14, + "legs": 14 + }, + "source": "Deathwatch Core Rulebook p164" + } + }, + { + "name": "CM Power Armour", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 8, + "body": 10, + "legs": 8 + }, + "source": "Mark of the Xenos p114" + } + }, + { + "name": "Dmn Armour of Chaos", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 12, + "arms": 12, + "body": 12, + "legs": 12 + }, + "source": "Deathwatch Core Rulebook p362" + } + }, + { + "name": "Tau XV-8 Crisis Battlesuit", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 9, + "arms": 9, + "body": 9, + "legs": 9 + }, + "source": "Mark of the Xenos p9" + } + }, + { + "name": "Tau XV-88 Broadside Battlesuit", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 12, + "arms": 12, + "body": 12, + "legs": 12 + }, + "source": "Mark of the Xenos p6" + } + }, + { + "name": "Tau XV15 Stealth Suit (Limbs)", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 0, + "arms": 7, + "body": 0, + "legs": 7 + }, + "source": "Deathwatch Core Rulebook p367" + } + }, + { + "name": "Tau XV15 Stealth Suit (Top)", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 8, + "legs": 0 + }, + "source": "Deathwatch Core Rulebook p367" + } + }, + { + "name": "Tau XV8 Crisis Suit", + "req": 0, + "renown": "Any", + "category": "Power Armor", + "stats": { + "type": "Power", + "protection": { + "head": 9, + "arms": 9, + "body": 9, + "legs": 9 + }, + "source": "Deathwatch Core Rulebook p366" + } + } + ], + "powerArmorHelms": [ + { + "name": "Astartes Mk1 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 6, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk2 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 7, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk3 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 9, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk4 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 7, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk5 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk6 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk7 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Mk8 Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p151" + } + }, + { + "name": "Astartes Power Armour Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Deathwatch Core Rulebook p160" + } + }, + { + "name": "Astartes Tactical Dreadnaught-Terminator Armour Helm", + "req": 100, + "renown": "Famed", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 14, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Deathwatch Core Rulebook p164" + } + }, + { + "name": "Diagnostor Helmet", + "req": 15, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Deathwatch Core Rulebook p165" + } + }, + { + "name": "Fenris Pattern Wolf Helm", + "req": 0, + "renown": "Respected", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 8, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p143" + } + }, + { + "name": "Skull Helm", + "req": 0, + "renown": "Any", + "category": "Power Armor Helm", + "stats": { + "type": "Power", + "protection": { + "head": 9, + "arms": 0, + "body": 0, + "legs": 0 + }, + "source": "Rites of Battle p143" + } + } + ], + "carapaceArmor": [ + { + "name": "Astartes Scout Armour", + "req": 0, + "renown": "Any", + "category": "Carapace Armor", + "stats": { + "type": "Carapace", + "protection": { + "head": 0, + "arms": 6, + "body": 6, + "legs": 0 + }, + "source": "Deathwatch Core Rulebook p163" + } + }, + { + "name": "Chaos Flak Robes and Brazen Carapace", + "req": 0, + "renown": "Any", + "category": "Carapace Armor", + "stats": { + "type": "Carapace", + "protection": { + "head": 5, + "arms": 5, + "body": 6, + "legs": 4 + }, + "source": "Deathwatch Core Rulebook p364" + } + }, + { + "name": "Deathwatch Scout Armor", + "req": 0, + "renown": "Any", + "category": "Carapace Armor", + "stats": { + "type": "Carapace", + "protection": { + "head": 0, + "arms": 6, + "body": 6, + "legs": 6 + }, + "source": "Rites of Battle p142" + } + }, + { + "name": "Tau Fire Warrior Armour", + "req": 0, + "renown": "Any", + "category": "Carapace Armor", + "stats": { + "type": "Carapace", + "protection": { + "head": 6, + "arms": 6, + "body": 6, + "legs": 6 + }, + "source": "Deathwatch Core Rulebook p368" + } + }, + { + "name": "Tau Pathfinder Armour", + "req": 0, + "renown": "Any", + "category": "Carapace Armor", + "stats": { + "type": "Carapace", + "protection": { + "head": 7, + "arms": 0, + "body": 7, + "legs": 0 + }, + "source": "Mark of the Xenos p25" + } + } + ], + "naturalArmor": [ + { + "name": "Tau Gun Drone Armour", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 5, + "arms": 5, + "body": 5, + "legs": 5 + }, + "source": "Deathwatch Core Rulebook p367" + } + }, + { + "name": "Tyr Bonded Exoskeleton", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 10, + "arms": 10, + "body": 10, + "legs": 10 + }, + "source": "Deathwatch Core Rulebook p370" + } + }, + { + "name": "Tyr Chitinous Carapace", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 3, + "arms": 3, + "body": 3, + "legs": 3 + }, + "source": "Deathwatch Core Rulebook p371" + } + }, + { + "name": "Tyr Reinforced Chitin", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 8, + "arms": 8, + "body": 8, + "legs": 8 + }, + "source": "Deathwatch Core Rulebook p371" + } + }, + { + "name": "Tyr Exoskeleton", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 2, + "arms": 2, + "body": 2, + "legs": 2 + }, + "source": "Mark of the Xenos p43" + } + }, + { + "name": "Tyr Hardened Carapace", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 6, + "arms": 6, + "body": 6, + "legs": 6 + }, + "source": "Mark of the Xenos p40" + } + }, + { + "name": "Tyr Light Reinforced Chitin", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 4, + "arms": 4, + "body": 4, + "legs": 4 + }, + "source": "Mark of the Xenos p39" + } + }, + { + "name": "Tyr Medium Reinforced Chitin", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 6, + "arms": 6, + "body": 6, + "legs": 6 + }, + "source": "Mark of the Xenos p37" + } + }, + { + "name": "Tyr Thickened Scales", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 10, + "arms": 10, + "body": 10, + "legs": 10 + }, + "source": "Mark of the Xenos p46" + } + }, + { + "name": "Vespid Chitin", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 3, + "arms": 3, + "body": 3, + "legs": 3 + }, + "source": "Mark of the Xenos p26" + } + }, + { + "name": "Xenos Hardened Hide", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 6, + "arms": 6, + "body": 6, + "legs": 6 + }, + "source": "Mark of the Xenos p66" + } + }, + { + "name": "Xenos Scaly Hide", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 3, + "arms": 3, + "body": 3, + "legs": 3 + }, + "source": "Mark of the Xenos p63" + } + }, + { + "name": "Xenos Slimey Hide", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 2, + "arms": 2, + "body": 2, + "legs": 2 + }, + "source": "Mark of the Xenos p68" + } + }, + { + "name": "Xenos Thick Scales", + "req": 0, + "renown": "Any", + "category": "Natural Armor", + "stats": { + "type": "Natural", + "protection": { + "head": 5, + "arms": 5, + "body": 5, + "legs": 5 + }, + "source": "Mark of the Xenos p65" + } + } + ], + "primitiveArmor": [ + { + "name": "Auran Golden Saurian Scale Armour", + "req": 0, + "renown": "Any", + "category": "Primitive Armor", + "stats": { + "type": "Primitive", + "protection": { + "head": 6, + "arms": 6, + "body": 6, + "legs": 6 + }, + "source": "The Emperor Protects p48" + } + }, + { + "name": "Auran Saurian Scale Armour", + "req": 0, + "renown": "Any", + "category": "Primitive Armor", + "stats": { + "type": "Primitive", + "protection": { + "head": 4, + "arms": 4, + "body": 4, + "legs": 4 + }, + "source": "The Emperor Protects p46" + } + }, + { + "name": "Scales", + "req": 0, + "renown": "Any", + "category": "Primitive Armor", + "stats": { + "type": "Primitive", + "protection": { + "head": 2, + "arms": 2, + "body": 2, + "legs": 2 + }, + "source": "The Emperor Protects p50" + } + }, + { + "name": "Scaly Hide", + "req": 0, + "renown": "Any", + "category": "Primitive Armor", + "stats": { + "type": "Primitive", + "protection": { + "head": 4, + "arms": 4, + "body": 4, + "legs": 4 + }, + "source": "The Emperor Protects p46" + } + } + ], + "xenosArmor": [ + { + "name": "Nec Metallic Exoskeleton", + "req": 0, + "renown": "Any", + "category": "Xenos Armor", + "stats": { + "type": "Necron", + "protection": { + "head": 8, + "arms": 8, + "body": 8, + "legs": 8 + }, + "source": "The Emperor Protects p94" + } + }, + { + "name": "Nec Metallic Shell", + "req": 0, + "renown": "Any", + "category": "Xenos Armor", + "stats": { + "type": "Necron", + "protection": { + "head": 10, + "arms": 10, + "body": 10, + "legs": 10 + }, + "source": "The Emperor Protects p94" + } + }, + { + "name": "Ork Eavy Armour", + "req": 0, + "renown": "Any", + "category": "Xenos Armor", + "stats": { + "type": "Ork", + "protection": { + "head": 6, + "arms": 4, + "body": 6, + "legs": 4 + }, + "source": "Mark of the Xenos p57" + } + }, + { + "name": "Ork Flak Armour", + "req": 0, + "renown": "Any", + "category": "Xenos Armor", + "stats": { + "type": "Ork", + "protection": { + "head": 0, + "arms": 0, + "body": 2, + "legs": 0 + }, + "source": "Mark of the Xenos p57" + } + }, + { + "name": "Ork Mega Armour", + "req": 0, + "renown": "Any", + "category": "Xenos Armor", + "stats": { + "type": "Ork", + "protection": { + "head": 6, + "arms": 10, + "body": 14, + "legs": 10 + }, + "source": "Mark of the Xenos p57" + } + } + ], + "otherArmor": [ + { + "name": "Chaos Armour Plating", + "req": 0, + "renown": "Any", + "category": "Other Armor", + "stats": { + "type": "Other", + "protection": { + "head": 6, + "arms": 6, + "body": 6, + "legs": 6 + }, + "source": "Mark of the Xenos p91" + } + }, + { + "name": "Chaos Bones of Subersion", + "req": 0, + "renown": "Any", + "category": "Other Armor", + "stats": { + "type": "Other", + "protection": { + "head": 9, + "arms": 9, + "body": 9, + "legs": 9 + }, + "source": "Mark of the Xenos p86" + } + }, + { + "name": "Chaos Slinnar Obsidian Shell", + "req": 0, + "renown": "Any", + "category": "Other Armor", + "stats": { + "type": "Other", + "protection": { + "head": 8, + "arms": 8, + "body": 8, + "legs": 8 + }, + "source": "Mark of the Xenos p92" + } + }, + { + "name": "Chaos Warded Adamantine Shell", + "req": 0, + "renown": "Any", + "category": "Other Armor", + "stats": { + "type": "Other", + "protection": { + "head": 9, + "arms": 9, + "body": 9, + "legs": 9 + }, + "source": "Mark of the Xenos p95" + } + }, + { + "name": "Daemon Iron Hide", + "req": 0, + "renown": "Any", + "category": "Other Armor", + "stats": { + "type": "Other", + "protection": { + "head": 13, + "arms": 13, + "body": 13, + "legs": 13 + }, + "source": "Mark of the Xenos p101" + } + }, + { + "name": "Dmn Brazen Chaos Armour", + "req": 0, + "renown": "Any", + "category": "Other Armor", + "stats": { + "type": "Other", + "protection": { + "head": 12, + "arms": 12, + "body": 12, + "legs": 12 + }, + "source": "The Emperor Protects p136" + } + }, + { + "name": "Obliterator Warped Mechnical Flesh", + "req": 0, + "renown": "Any", + "category": "Other Armor", + "stats": { + "type": "Other", + "protection": { + "head": 12, + "arms": 12, + "body": 12, + "legs": 12 + }, + "source": "Mark of the Xenos p120" + } + }, + { + "name": "Rad Corrupted Mechnical Flesh", + "req": 0, + "renown": "Any", + "category": "Other Armor", + "stats": { + "type": "Other", + "protection": { + "head": 7, + "arms": 7, + "body": 7, + "legs": 7 + }, + "source": "The Emperor Protects p91" + } + } + ], + "shields": [ + { + "name": "Astartes Storm Shield - Protective", + "req": 35, + "renown": "Distinguished", + "category": "Shield", + "stats": { + "type": "Shield", + "protection": { + "head": 0, + "arms": "0LA 4RA", + "body": 4, + "legs": 0 + }, + "source": "Deathwatch Core Rulebook p166" + } + } + ] +}; + +function main() { + try { + console.log('Using comprehensive armor dataset...'); + + // Count items + const totalItems = Object.values(comprehensiveArmorData).reduce((sum, category) => sum + category.length, 0); + console.log(`Total armor pieces: ${totalItems}`); + + // Show breakdown by category + Object.keys(comprehensiveArmorData).forEach(category => { + console.log(`${category}: ${comprehensiveArmorData[category].length} items`); + }); + + // Write to file + const outputPath = path.join(__dirname, '..', 'public', 'deathwatch-armor-comprehensive.json'); + fs.writeFileSync(outputPath, JSON.stringify(comprehensiveArmorData, null, 2)); + console.log(`Comprehensive armor data written to: ${outputPath}`); + + console.log('\nNext steps:'); + console.log('1. Update build-shop-db.js to use comprehensive armor data'); + console.log('2. Run: node scripts/build-shop-db.js to rebuild shop database'); + console.log('3. Run: cd database && node migrations/add-shop-tables.js to update SQLite'); + console.log('4. Restart server to see updated armor selection'); + + } catch (error) { + console.error('Error:', error); + process.exit(1); + } +} + +if (require.main === module) { + main(); +} + +module.exports = comprehensiveArmorData; diff --git a/scripts/comprehensive-weapons.js b/scripts/comprehensive-weapons.js new file mode 100644 index 0000000..8016025 --- /dev/null +++ b/scripts/comprehensive-weapons.js @@ -0,0 +1,629 @@ +#!/usr/bin/env node + +/** + * Enhanced scraper that uses a comprehensive weapons dataset + * This includes a manually curated list of weapons from the 40k RPG Tools website + */ + +const fs = require('fs'); +const path = require('path'); + +// Comprehensive weapon dataset based on the 40k RPG Tools website +const comprehensiveWeaponsData = { + "rangedWeapons": [ + { + "name": "Angelus Bolter", + "req": 25, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 50m; S/3/-; 1d10+9 X; Pen 6; Clip 36; Reload 2 Full; Tearing", + "class": "Basic - Bolt", + "source": "First Founding p97" + } + }, + { + "name": "Astartes Armoursbane Missile Launcher", + "req": 15, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 200m; S/-/-; 0d0 S; Pen 0; Clip 1; Reload 2 Full; Two handed", + "class": "Heavy - Launch", + "source": "Rites of Battle p137" + } + }, + { + "name": "Astartes Assault Cannon", + "req": 30, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 150m; -/-/10; 3d10+6 I; Pen 6; Clip 200; Reload 3 Full; Tearing", + "class": "Mounted - Solid Projectile", + "source": "Deathwatch Core Rulebook p149" + } + }, + { + "name": "Astartes Assault Shotgun", + "req": 7, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 30m; S/3/5; 1d10+10 I; Pen 4; Clip 20; Reload 1 Full; Two handed; Reliable, Scatter", + "class": "Basic - Solid Projectile", + "source": "Living Errata v1.1 p136" + } + }, + { + "name": "Astartes Bolt Pistol", + "req": 5, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 30m; S/2/-; 1d10+9 X; Pen 4; Clip 14; Reload 1 Full; Tearing", + "class": "Pistol - Bolt", + "source": "Living Errata v1.1 p146" + } + }, + { + "name": "Astartes Bolter-Godwyn", + "req": 5, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 100m; S/3/-; 1d10+9 X; Pen 4; Clip 28; Reload 1 Full; Two handed; Tearing", + "class": "Basic - Bolt", + "source": "Living Errata v1.1 p146" + } + }, + { + "name": "Astartes Boltgun-Stalker", + "req": 15, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 200m; S/-/-; 1d10+9 X; Pen 4; Clip 24; Reload 1 Full; Two handed; Accurate, Tearing", + "class": "Basic - Bolt", + "source": "Living Errata v1.1 p146" + } + }, + { + "name": "Astartes Chainfist", + "req": 40, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "2d10+2*SB E; Pen 10; Power Field, Tearing, Unwieldy", + "class": "One-Handed Melee - Power", + "source": "Living Errata v1.1 p154" + } + }, + { + "name": "Astartes Combi-Weapon", + "req": 15, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 100m; S/4/-; 1d10+9 X; Pen 4; Clip 28; Reload 1 Full; Two handed; Tearing", + "class": "Basic - Bolt", + "source": "Living Errata v1.1 p146" + } + }, + { + "name": "Astartes Conversion Beamer", + "req": 40, + "renown": "Hero", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 100m; S/-/-; 0d0 E; Pen 0; Clip 4; Reload 2 Full; Two handed", + "class": "Heavy - Exotic", + "source": "Living Errata v1.1 p152" + } + }, + { + "name": "Astartes Cyclone Missile Launcher", + "req": 25, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 300m; S/2/-; 0d0 S; Pen 0; Clip 12; Reload 3 Full", + "class": "Mounted - Launch", + "source": "Living Errata v1.1 p152" + } + }, + { + "name": "Astartes Digital Flamer", + "req": 35, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 4m; S/-/-; 1d10+9 E; Pen 4; Clip 1; Reload 1d5 Hours; Flame, Spray", + "class": "Pistol - Exotic", + "source": "Living Errata v1.1 p153" + } + }, + { + "name": "Astartes Digital Laser", + "req": 35, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 4m; S/-/-; 1d10+4 E; Pen 7; Clip 1; Reload 1d5 Hours; Reliable", + "class": "Pistol - Exotic", + "source": "Living Errata v1.1 p153" + } + }, + { + "name": "Astartes Digital Melta", + "req": 35, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 4m; S/-/-; 2d10+12 E; Pen 10; Clip 1; Reload 1d5 Hours", + "class": "Pistol - Exotic", + "source": "Living Errata v1.1 p153" + } + }, + { + "name": "Astartes Executioner Axe", + "req": 25, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "1d10+13 E; Pen 8; Two handed; Power Field, Unwieldy, Felling (x1)", + "class": "Two-Handed Melee - Power", + "source": "Living Errata v1.1 p139" + } + }, + { + "name": "Astartes Flamer", + "req": 10, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 20m; S/-/-; 1d10+9 E; Pen 4; Clip 6; Reload 2 Full; Two handed; Flame, Spray", + "class": "Basic - Flame", + "source": "Living Errata v1.1 p148" + } + }, + { + "name": "Astartes Heavy Flamer", + "req": 15, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 30m; S/-/-; 1d10+12 E; Pen 6; Clip 10; Reload 2 Full; Two handed; Flame, Spray", + "class": "Heavy - Flame", + "source": "Living Errata v1.1 p149" + } + }, + { + "name": "Astartes Heavy-Bolter", + "req": 20, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 150m; -/-/6; 1d10+12 X; Pen 5; Clip 60; Reload 1 Full; Two handed; Tearing", + "class": "Heavy - Bolt", + "source": "Living Errata v1.1 p147" + } + }, + { + "name": "Astartes Infernus Pistol", + "req": 35, + "renown": "Famed", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 10m; S/-/-; 2d10+12 E; Pen 12; Clip 4; Reload 1 Full; Melta", + "class": "Pistol - Melta", + "source": "Living Errata v1.1 p148" + } + }, + { + "name": "Astartes Lascannon", + "req": 30, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 300m; S/-/-; 5d10+10 E; Pen 10; Clip 6; Reload 2 Full; Two handed; Proven (3)", + "class": "Heavy - Las", + "source": "Living Errata v1.1 p149" + } + }, + { + "name": "Astartes Lightning Claw", + "req": 30, + "renown": "Distinguished", + "category": "Ranged Weapon", + "stats": { + "damage": "1d10+6 E; Pen 8; Power Field, Proven (4)", + "class": "One-Handed Melee - Power", + "source": "Living Errata v1.1 p154" + } + }, + { + "name": "Astartes Meltagun-Vulkan", + "req": 20, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 30m; S/-/-; 2d10+14 E; Pen 12; Clip 6; Reload 2 Full; Two handed; Melta", + "class": "Basic - Melta", + "source": "Living Errata v1.1 p148" + } + }, + { + "name": "Astartes Missile Launcher-Soundstrike", + "req": 10, + "renown": "Any", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 250m; S/-/-; 0d0 S; Pen 0; Clip 8; Reload 1 Full; Two handed", + "class": "Heavy - Launch", + "source": "Living Errata v1.1 p152" + } + }, + { + "name": "Astartes Multi-Melta - Maxima", + "req": 35, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 60m; S/-/-; 2d10+16 E; Pen 12; Clip 12; Reload 2 Full; Two handed; Blast (1), Melta", + "class": "Heavy - Melta", + "source": "Living Errata v1.1 p148" + } + }, + { + "name": "Astartes Plasma Cannon", + "req": 30, + "renown": "Distinguished", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 150m; S/-/-; 2d10+12 E; Pen 10; Clip 16; Reload 5 Full; Two handed; Blast (3), Volatile, Maximal", + "class": "Heavy - Plasma", + "source": "Living Errata v1.1 p147" + } + }, + { + "name": "Astartes Plasma Gun -Ragefire", + "req": 20, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 100m; S/2/-; 1d10+12 E; Pen 10; Clip 24; Reload 4 Full; Volatile, Maximal", + "class": "Basic - Plasma", + "source": "Living Errata v1.1 p148" + } + }, + { + "name": "Astartes Plasma Pistol", + "req": 25, + "renown": "Respected", + "category": "Ranged Weapon", + "stats": { + "damage": "Range 30m; S/2/-; 1d10+10 E; Pen 8; Clip 12; Reload 3 Full; Volatile, Maximal", + "class": "Pistol - Plasma", + "source": "Living Errata v1.1 p148" + } + } + ], + "meleeWeapons": [ + { + "name": "Armour of the Remorseless Crusader (Forearm Sword)", + "req": 70, + "renown": "Hero", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+8 R; Pen 6; +10 to hit; Sanctified", + "class": "One-Handed Melee - Primitive", + "source": "Deathwatch Core Rulebook p167" + } + }, + { + "name": "Artificer Omnissian Axe", + "req": 25, + "renown": "Distinguished", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+9 E; Pen 7; Power Field, Unbalanced", + "class": "One-Handed Melee - Power", + "source": "First Founding p99" + } + }, + { + "name": "Astartes Chainsword", + "req": 5, + "renown": "Any", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+3 R; Pen 3; Balanced, Tearing", + "class": "One-Handed Melee - Chain", + "source": "Living Errata v1.1 p153" + } + }, + { + "name": "Astartes Combat Knife", + "req": 3, + "renown": "Any", + "category": "Melee Weapon", + "stats": { + "damage": "1d10 R; Pen 2", + "class": "One-Handed Melee - Primitive", + "source": "Living Errata v1.1 p155" + } + }, + { + "name": "Astartes Combat Shield", + "req": 20, + "renown": "Distinguished", + "category": "Melee Weapon", + "stats": { + "damage": "1d5+1 I; Pen 0; Balanced", + "class": "One-Handed Melee - Primitive", + "source": "Living Errata v1.1 p166" + } + }, + { + "name": "Astartes Power Axe", + "req": 20, + "renown": "Respected", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+8 E; Pen 7; Power Field, Unbalanced", + "class": "One-Handed Melee - Power", + "source": "Living Errata v1.1 p155" + } + }, + { + "name": "Astartes Power Claymore", + "req": 15, + "renown": "Distinguished", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+11 E; Pen 8; Two handed; Power Field, Unwieldy, Devastating (1)", + "class": "Two-Handed Melee - Power", + "source": "Living Errata v1.1 p139" + } + }, + { + "name": "Astartes Power Falchion", + "req": 25, + "renown": "Distinguished", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+4 E; Pen 6; Two handed; Power Field, Razor Sharp", + "class": "One-Handed Melee - Power", + "source": "Living Errata v1.1 p139" + } + }, + { + "name": "Astartes Power Fist", + "req": 30, + "renown": "Distinguished", + "category": "Melee Weapon", + "stats": { + "damage": "2d10+2*SB E; Pen 9; Power Field, Unwieldy", + "class": "One-Handed Melee - Power", + "source": "Living Errata v1.1 p155" + } + }, + { + "name": "Astartes Power Spear", + "req": 15, + "renown": "Distinguished", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+6 E; Pen 7; Two handed; Power Field", + "class": "Two-Handed Melee - Power", + "source": "Living Errata v1.1 p139" + } + }, + { + "name": "Astartes Power Sword", + "req": 20, + "renown": "Respected", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+6 E; Pen 6; Balanced, Power Field", + "class": "One-Handed Melee - Power", + "source": "Living Errata v1.1 p155" + } + }, + { + "name": "Astartes Force Staff", + "req": 25, + "renown": "Respected", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+1+PR+SB S; Pen PR; Balanced", + "class": "One-Handed Melee - Primitive", + "source": "Living Errata v1.1 p155" + } + }, + { + "name": "Astartes Force Sword", + "req": 25, + "renown": "Respected", + "category": "Melee Weapon", + "stats": { + "damage": "1d10+2+PR+SB S; Pen 2+PR; Balanced", + "class": "One-Handed Melee - Primitive", + "source": "Living Errata v1.1 p156" + } + } + ], + "grenades": [ + { + "name": "Astartes Anti-Plant Grenade", + "req": 18, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "3d10 E; Pen 0; Blast (3)", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p136" + } + }, + { + "name": "Astartes Blind Grenade", + "req": 10, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "0d0 S; Pen 0; Smoke (10)", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p150" + } + }, + { + "name": "Astartes Frag Grenade", + "req": 1, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "2d10+2 X; Pen 0; Blast (4)", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p150" + } + }, + { + "name": "Astartes Incendiary Grenade", + "req": 15, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "1d10+4 E; Pen 0; Blast (3)", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p150" + } + }, + { + "name": "Astartes Krak Grenade", + "req": 1, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "3d10+4 X; Pen 6", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p150" + } + }, + { + "name": "Astartes Nova Grenade", + "req": 15, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "1d10 E; Pen 0; Blast (3)", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p151" + } + }, + { + "name": "Astartes Photon Flash Grenade", + "req": 5, + "renown": "Any", + "category": "Grenade", + "stats": { + "damage": "0d0 S; Pen 0", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p151" + } + }, + { + "name": "Astartes Plasma Grenade", + "req": 20, + "renown": "Distinguished", + "category": "Grenade", + "stats": { + "damage": "1d10+12 E; Pen 8; Blast (3)", + "class": "Thrown - Grenade", + "source": "Living Errata v1.1 p151" + } + } + ], + "other": [ + { + "name": "Argrax Clawed Hooves", + "req": 0, + "renown": "Any", + "category": "Other", + "stats": { + "damage": "1d10 I; Pen 0", + "class": "Natural - Primitive", + "source": "The Emperor Protects p46" + } + }, + { + "name": "Assault Cannon-Samech", + "req": 0, + "renown": "Any", + "category": "Other", + "stats": { + "damage": "Range 120m; -/-/10; 3d10+6 I; Pen 5; Clip 200; Reload 2 Full; Tearing", + "class": "Mounted - Solid Projectile", + "source": "The Emperor Protects p120" + } + }, + { + "name": "Astartes Servo-Arm", + "req": 30, + "renown": "Any", + "category": "Other", + "stats": { + "damage": "2d10+14 I; Pen 10", + "class": "Mounted - Primitive", + "source": "Living Errata v1.1 p177" + } + }, + { + "name": "Astartes Servo-Arm Exceptional", + "req": 30, + "renown": "Any", + "category": "Other", + "stats": { + "damage": "2d10+16 I; Pen 10", + "class": "Mounted - Primitive", + "source": "Deathwatch Core Rulebook p177" + } + } + ] +}; + +function main() { + try { + console.log('Using comprehensive weapons dataset...'); + + // Count items + const totalItems = Object.values(comprehensiveWeaponsData).reduce((sum, category) => sum + category.length, 0); + console.log(`Total weapons: ${totalItems}`); + + // Show breakdown by category + Object.keys(comprehensiveWeaponsData).forEach(category => { + console.log(`${category}: ${comprehensiveWeaponsData[category].length} items`); + }); + + // Write to file + const outputPath = path.join(__dirname, '..', 'public', 'deathwatch-weapons-comprehensive.json'); + fs.writeFileSync(outputPath, JSON.stringify(comprehensiveWeaponsData, null, 2)); + console.log(`Comprehensive weapon data written to: ${outputPath}`); + + console.log('\nNext steps:'); + console.log('1. Review the data in deathwatch-weapons-comprehensive.json'); + console.log('2. Run: node scripts/build-shop-db.js to rebuild the shop database'); + console.log('3. Run: cd database && node migrations/add-shop-tables.js to update SQLite'); + console.log('4. Restart your server to see the updated shop'); + + } catch (error) { + console.error('Error:', error); + process.exit(1); + } +} + +if (require.main === module) { + main(); +} + +module.exports = comprehensiveWeaponsData; diff --git a/scripts/scrape-40k-tools.js b/scripts/scrape-40k-tools.js new file mode 100644 index 0000000..838335f --- /dev/null +++ b/scripts/scrape-40k-tools.js @@ -0,0 +1,224 @@ +#!/usr/bin/env node + +const https = require('https'); +const fs = require('fs'); +const path = require('path'); + +/** + * Scrape weapon data from 40k RPG Tools website + */ + +function fetchHTML(url) { + return new Promise((resolve, reject) => { + https.get(url, (res) => { + let data = ''; + res.on('data', (chunk) => data += chunk); + res.on('end', () => resolve(data)); + }).on('error', reject); + }); +} + +function parseWeaponTable(html) { + const weapons = []; + + // The data appears to be in the HTML but formatted differently + // Let's look for all table cell patterns and reconstruct the table + const linkRegex = /([^<]+)<\/a>/g; + const weaponNames = []; + + let match; + while ((match = linkRegex.exec(html)) !== null) { + weaponNames.push(match[1]); + } + + console.log(`Found ${weaponNames.length} weapon names`); + + // For now, let's try a different approach - look for the table rows in the HTML you provided + // Parse the specific HTML structure from the user's table + const tableRowRegex = /\s*([^<]+)<\/a><\/td>\s*([^<]*)<\/td>\s*\s*([^<]*?)\s*<\/td>\s*(\d+)<\/td>\s*([^<]*)<\/td>\s*([^<]*)<\/a><\/td>\s*([^<]*)<\/a><\/td>\s*(\d+)<\/td>\s*<\/tr>/gs; + + let rowMatch; + while ((rowMatch = tableRowRegex.exec(html)) !== null) { + const weapon = { + name: rowMatch[1].trim(), + class: rowMatch[2].trim(), + damage: rowMatch[3].replace(/<[^>]*>/g, '').trim(), + cost: parseInt(rowMatch[4]) || 0, + availability: rowMatch[5].trim(), + gameSetting: rowMatch[6].trim(), + book: rowMatch[7].trim(), + page: rowMatch[8].trim() + }; + + weapons.push(weapon); + } + + // If that doesn't work, let's try extracting from the data you provided manually + if (weapons.length === 0) { + console.log('Trying manual extraction from known weapon data...'); + + // Extract weapons from the provided HTML table data + const knownWeapons = [ + { + name: "Angelus Bolter", + class: "Basic - Bolt", + damage: "Range 50m; S/3/-; 1d10+9 X; Pen 6; Clip 36; Reload 2 Full; Tearing", + cost: 25, + availability: "Respected", + gameSetting: "Deathwatch", + book: "First Founding", + page: "97" + }, + { + name: "Argrax Clawed Hooves", + class: "Natural - Primitive", + damage: "1d10 I; Pen 0;", + cost: 0, + availability: "Any", + gameSetting: "Deathwatch", + book: "The Emperor Protects", + page: "46" + }, + { + name: "Armour of the Remorseless Crusader (Forearm Sword)", + class: "One-Handed Melee - Primitive", + damage: "1d10+8 R; Pen 6; +10 to hit; Sanctified", + cost: 70, + availability: "Hero", + gameSetting: "Deathwatch", + book: "Deathwatch Core Rulebook", + page: "167" + }, + { + name: "Artificer Omnissian Axe", + class: "One-Handed Melee - Power", + damage: "1d10+9 E; Pen 7; Power Field, Unbalanced", + cost: 25, + availability: "Distinguished", + gameSetting: "Deathwatch", + book: "First Founding", + page: "99" + } + // Add more weapons from the HTML table data as needed + ]; + + weapons.push(...knownWeapons); + } + + return weapons; +} + +function categorizeWeapon(weapon) { + const className = weapon.class.toLowerCase(); + + if (className.includes('pistol')) { + return 'pistols'; + } else if (className.includes('basic')) { + return 'basicWeapons'; + } else if (className.includes('heavy')) { + return 'heavyWeapons'; + } else if (className.includes('mounted')) { + return 'mountedWeapons'; + } else if (className.includes('melee')) { + return 'meleeWeapons'; + } else if (className.includes('thrown') || className.includes('grenade')) { + return 'grenades'; + } else if (className.includes('natural')) { + return 'naturalWeapons'; + } else { + return 'otherWeapons'; + } +} + +function mapAvailabilityToRenown(availability) { + const availabilityMap = { + 'Any': 'None', + 'Abundant': 'None', + 'Plentiful': 'None', + 'Common': 'None', + 'Average': 'None', + 'Uncommon': 'None', + 'Scarce': 'Respected', + 'Rare': 'Respected', + 'Very Rare': 'Distinguished', + 'Extremely Rare': 'Distinguished', + 'Near Unique': 'Famed', + 'Unique': 'Hero', + 'Respected': 'Respected', + 'Distinguished': 'Distinguished', + 'Famed': 'Famed', + 'Hero': 'Hero' + }; + + return availabilityMap[availability] || 'None'; +} + +function convertToGameFormat(weapons) { + const categorized = { + pistols: [], + basicWeapons: [], + heavyWeapons: [], + mountedWeapons: [], + meleeWeapons: [], + grenades: [], + naturalWeapons: [], + otherWeapons: [] + }; + + weapons.forEach(weapon => { + const category = categorizeWeapon(weapon); + const gameWeapon = { + name: weapon.name, + req: weapon.cost, + renown: mapAvailabilityToRenown(weapon.availability), + category: category.replace(/([A-Z])/g, ' $1').trim(), + stats: { + damage: weapon.damage, + class: weapon.class, + source: `${weapon.book} p${weapon.page}` + } + }; + + categorized[category].push(gameWeapon); + }); + + return categorized; +} + +async function main() { + try { + console.log('Fetching weapon data from 40k RPG Tools...'); + const html = await fetchHTML('https://www.40krpgtools.com/armoury/weapons/'); + + console.log('Parsing weapon table...'); + const weapons = parseWeaponTable(html); + console.log(`Found ${weapons.length} weapons`); + + console.log('Converting to game format...'); + const categorizedWeapons = convertToGameFormat(weapons); + + // Calculate totals per category + Object.keys(categorizedWeapons).forEach(category => { + console.log(`${category}: ${categorizedWeapons[category].length} items`); + }); + + // Write to file + const outputPath = path.join(__dirname, '..', 'public', 'deathwatch-weapons-scraped.json'); + fs.writeFileSync(outputPath, JSON.stringify(categorizedWeapons, null, 2)); + console.log(`Weapon data written to: ${outputPath}`); + + // Create summary + const totalWeapons = Object.values(categorizedWeapons).reduce((sum, cat) => sum + cat.length, 0); + console.log(`\nSummary: ${totalWeapons} total weapons imported`); + + } catch (error) { + console.error('Error scraping weapon data:', error); + process.exit(1); + } +} + +if (require.main === module) { + main(); +} + +module.exports = { fetchHTML, parseWeaponTable, convertToGameFormat };