Add dev seed data: auto-creates campaign with Limpie and Brynn on fresh DB
This commit is contained in:
parent
3e2e43ca95
commit
28e57a77ee
2 changed files with 213 additions and 0 deletions
|
|
@ -8,6 +8,7 @@ import characterRoutes from "./routes/characters.js";
|
||||||
import gameItemRoutes from "./routes/game-items.js";
|
import gameItemRoutes from "./routes/game-items.js";
|
||||||
import gameTalentRoutes from "./routes/game-talents.js";
|
import gameTalentRoutes from "./routes/game-talents.js";
|
||||||
import rollRoutes from "./routes/rolls.js";
|
import rollRoutes from "./routes/rolls.js";
|
||||||
|
import { seedDevData } from "./seed-dev-data.js";
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const httpServer = createServer(app);
|
const httpServer = createServer(app);
|
||||||
|
|
@ -30,6 +31,8 @@ app.use("/api/game-items", gameItemRoutes);
|
||||||
app.use("/api/game-talents", gameTalentRoutes);
|
app.use("/api/game-talents", gameTalentRoutes);
|
||||||
app.use("/api/campaigns/:campaignId/rolls", rollRoutes);
|
app.use("/api/campaigns/:campaignId/rolls", rollRoutes);
|
||||||
|
|
||||||
|
seedDevData();
|
||||||
|
|
||||||
const PORT = process.env.PORT || 3000;
|
const PORT = process.env.PORT || 3000;
|
||||||
httpServer.listen(PORT, () => {
|
httpServer.listen(PORT, () => {
|
||||||
console.log(`Shadowdark server running on http://localhost:${PORT}`);
|
console.log(`Shadowdark server running on http://localhost:${PORT}`);
|
||||||
|
|
|
||||||
210
server/src/seed-dev-data.ts
Normal file
210
server/src/seed-dev-data.ts
Normal file
|
|
@ -0,0 +1,210 @@
|
||||||
|
import db from "./db.js";
|
||||||
|
|
||||||
|
export function seedDevData() {
|
||||||
|
const hasCampaigns = (
|
||||||
|
db.prepare("SELECT COUNT(*) as c FROM campaigns").get() as { c: number }
|
||||||
|
).c;
|
||||||
|
if (hasCampaigns > 0) return;
|
||||||
|
|
||||||
|
// Create campaign
|
||||||
|
db.prepare(
|
||||||
|
"INSERT INTO campaigns (name) VALUES ('Tomb of the Serpent King')",
|
||||||
|
).run();
|
||||||
|
|
||||||
|
const insertChar = db.prepare(`
|
||||||
|
INSERT INTO characters (campaign_id, name, class, ancestry, level, xp, hp_current, hp_max, ac, alignment, title, background, deity, languages, gp, sp, cp, color)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
`);
|
||||||
|
|
||||||
|
const insertStat = db.prepare(
|
||||||
|
"INSERT INTO character_stats (character_id, stat_name, value) VALUES (?, ?, ?)",
|
||||||
|
);
|
||||||
|
|
||||||
|
const insertGear = db.prepare(
|
||||||
|
"INSERT INTO character_gear (character_id, name, type, slot_count, properties, effects, game_item_id) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||||
|
);
|
||||||
|
|
||||||
|
const insertTalent = db.prepare(
|
||||||
|
"INSERT INTO character_talents (character_id, name, description, effect, game_talent_id) VALUES (?, ?, ?, ?, ?)",
|
||||||
|
);
|
||||||
|
|
||||||
|
// --- Limpie ---
|
||||||
|
const limpie = insertChar.run(
|
||||||
|
1,
|
||||||
|
"Limpie",
|
||||||
|
"Thief",
|
||||||
|
"Goblin",
|
||||||
|
1,
|
||||||
|
6,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
10,
|
||||||
|
"Lawful",
|
||||||
|
"Footpad",
|
||||||
|
"Chirurgeo",
|
||||||
|
"Madeera the Covenant",
|
||||||
|
"Common, Goblin",
|
||||||
|
8,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
"hsl(45, 60%, 65%)",
|
||||||
|
);
|
||||||
|
const limpieId = limpie.lastInsertRowid;
|
||||||
|
|
||||||
|
// Limpie stats
|
||||||
|
const limpieStats: [string, number][] = [
|
||||||
|
["STR", 11],
|
||||||
|
["DEX", 11],
|
||||||
|
["CON", 8],
|
||||||
|
["INT", 10],
|
||||||
|
["WIS", 14],
|
||||||
|
["CHA", 10],
|
||||||
|
];
|
||||||
|
for (const [name, value] of limpieStats) {
|
||||||
|
insertStat.run(limpieId, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limpie gear
|
||||||
|
insertGear.run(
|
||||||
|
limpieId,
|
||||||
|
"Shortsword",
|
||||||
|
"weapon",
|
||||||
|
1,
|
||||||
|
"{}",
|
||||||
|
'{"damage":"1d6","melee":true,"stat":"STR"}',
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
insertGear.run(
|
||||||
|
limpieId,
|
||||||
|
"Shortbow",
|
||||||
|
"weapon",
|
||||||
|
1,
|
||||||
|
"{}",
|
||||||
|
'{"damage":"1d4","ranged":true,"stat":"DEX","two_handed":true}',
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
insertGear.run(
|
||||||
|
limpieId,
|
||||||
|
"Leather Armor",
|
||||||
|
"armor",
|
||||||
|
1,
|
||||||
|
"{}",
|
||||||
|
'{"ac_base":11,"ac_dex":true}',
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
insertGear.run(limpieId, "Shield", "armor", 1, "{}", '{"ac_bonus":2}', null);
|
||||||
|
insertGear.run(limpieId, "Arrows (20)", "gear", 1, "{}", "{}", null);
|
||||||
|
insertGear.run(limpieId, "Torch", "gear", 1, "{}", "{}", null);
|
||||||
|
insertGear.run(limpieId, "Rations", "gear", 1, "{}", "{}", null);
|
||||||
|
insertGear.run(limpieId, "Rope (60ft)", "gear", 1, "{}", "{}", null);
|
||||||
|
insertGear.run(limpieId, "Thieves' Tools", "gear", 1, "{}", "{}", null);
|
||||||
|
|
||||||
|
// Limpie talents
|
||||||
|
insertTalent.run(
|
||||||
|
limpieId,
|
||||||
|
"Backstab",
|
||||||
|
"Extra 1 + half level (round down) weapon dice of damage with surprise attacks",
|
||||||
|
'{"damage_bonus_surprise":true}',
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
insertTalent.run(
|
||||||
|
limpieId,
|
||||||
|
"Thievery",
|
||||||
|
"Trained in climbing, sneaking, hiding, disguise, finding & disabling traps, delicate tasks",
|
||||||
|
"{}",
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
insertTalent.run(
|
||||||
|
limpieId,
|
||||||
|
"Keen Senses",
|
||||||
|
"Can't be surprised",
|
||||||
|
'{"immune_surprise":true}',
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
|
||||||
|
// --- Brynn ---
|
||||||
|
const brynn = insertChar.run(
|
||||||
|
1,
|
||||||
|
"Brynn",
|
||||||
|
"Fighter",
|
||||||
|
"Human",
|
||||||
|
2,
|
||||||
|
15,
|
||||||
|
8,
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
"Neutral",
|
||||||
|
"the Bold",
|
||||||
|
"Soldier",
|
||||||
|
"Gede",
|
||||||
|
"Common",
|
||||||
|
25,
|
||||||
|
5,
|
||||||
|
10,
|
||||||
|
"hsl(200, 60%, 65%)",
|
||||||
|
);
|
||||||
|
const brynnId = brynn.lastInsertRowid;
|
||||||
|
|
||||||
|
// Brynn stats
|
||||||
|
const brynnStats: [string, number][] = [
|
||||||
|
["STR", 16],
|
||||||
|
["DEX", 12],
|
||||||
|
["CON", 14],
|
||||||
|
["INT", 8],
|
||||||
|
["WIS", 10],
|
||||||
|
["CHA", 11],
|
||||||
|
];
|
||||||
|
for (const [name, value] of brynnStats) {
|
||||||
|
insertStat.run(brynnId, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Brynn gear
|
||||||
|
insertGear.run(
|
||||||
|
brynnId,
|
||||||
|
"Longsword",
|
||||||
|
"weapon",
|
||||||
|
1,
|
||||||
|
"{}",
|
||||||
|
'{"damage":"1d8","melee":true,"stat":"STR"}',
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
insertGear.run(
|
||||||
|
brynnId,
|
||||||
|
"Chainmail",
|
||||||
|
"armor",
|
||||||
|
1,
|
||||||
|
"{}",
|
||||||
|
'{"ac_base":13,"ac_dex":true}',
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
insertGear.run(brynnId, "Shield", "armor", 1, "{}", '{"ac_bonus":2}', null);
|
||||||
|
insertGear.run(
|
||||||
|
brynnId,
|
||||||
|
"Javelin",
|
||||||
|
"weapon",
|
||||||
|
1,
|
||||||
|
"{}",
|
||||||
|
'{"damage":"1d4","melee":true,"stat":"STR","thrown":true,"range":"far"}',
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
insertGear.run(brynnId, "Torch", "gear", 1, "{}", "{}", null);
|
||||||
|
insertGear.run(brynnId, "Rations", "gear", 1, "{}", "{}", null);
|
||||||
|
|
||||||
|
// Brynn talents
|
||||||
|
insertTalent.run(
|
||||||
|
brynnId,
|
||||||
|
"Weapon Mastery",
|
||||||
|
"+1 to attack and damage with longswords",
|
||||||
|
'{"attack_bonus":1,"damage_bonus":1}',
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
insertTalent.run(
|
||||||
|
brynnId,
|
||||||
|
"Grit",
|
||||||
|
"+2 HP and +1 HP each level",
|
||||||
|
'{"hp_bonus":2}',
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("Dev data seeded: campaign + 2 characters (Limpie & Brynn)");
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue