// ____ _ _ // / ___| |__ __ _ _ __ __ _ ___| |_ ___ _ __ // | | | '_ \ / _` | '__/ _` |/ __| __/ _ \ '__| // | |___| | | | (_| | | | (_| | (__| || __/ | // \____|_| |_|\__,_|_| \__,_|\___|\__\___|_| // ____ _ // / ___| ___ ___ __| | ___ _ __ // \___ \ / _ \/ _ \/ _` |/ _ \ '__| // ___) | __/ __/ (_| | __/ | // |____/ \___|\___|\__,_|\___|_| // ------------------------------------------------ import { Character } from "../models/character.js"; import { Game } from "../models/game.js"; import { Player } from "../models/player.js"; import * as roll from "../utils/dice.js"; import { isIdSane } from "../utils/id.js"; export class CharacterSeeder { /** @type {Game} */ constructor(game) { /** @type {Game} */ this.game = game; } /** * Create an item, using an item blueprint with the given name * * @param {string} itemBlueprintId id of the item blueprint * @returns {Item|undefined} */ item(itemBlueprintId) {} /** * @param {Character} character * @param {...string} itemBlueprintIds */ addItemsToCharacter(character, ...itemBlueprintIds) { for (const id of itemBlueprintIds) { const blueprint = this.game.getItemBlueprint(id); if (!blueprint) { throw new Error(`No blueprint found for id: ${id}`); } const item = blueprint.createItem(); character.addItem(item); } } /** * @param {Character} character * @param {...string} skills */ addSkillsToCharacter(character, ...skills) { for (const skill of skills) { if (!isIdSane(skill)) { throw new Error(`Skill id >>${skill}<< is insane!`); } character.skills.add(skill); } } /** * Foundation function * @name FoundationFunction * @function * @param {Character} The character to which we apply this foundation. */ createCharacter() { const c = new Character(); // // Initializing // // Rolling skills c.awareness = roll.d6() + 2; c.grit = roll.d6() + 2; c.knowledge = roll.d6() + 2; c.magic = roll.d6() + 2; c.meleeCombat = roll.d6() + 2; c.rangedCombat = roll.d6() + 2; c.skulduggery = roll.d6() + 2; switch (roll.d8()) { case 1: c.ancestry = "human"; // Humans get +1 to all skills c.awareness++; c.grit++; c.knowledge++; c.magic++; c.meleeCombat++; c.rangedCombat++; c.skulduggery++; break; case 2: c.ancestry = "dwarven"; c.meleeCombat = Math.max(c.meleeCombat, 10); break; case 3: c.ancestry = "elven"; c.rangedCombat = Math.max(c.rangedCombat, 10); break; case 4: c.ancestry = "giant"; c.meleeCombat = Math.max(c.grit, 10); break; case 5: c.ancestry = "Gnomish"; c.meleeCombat = Math.max(c.awareness, 10); break; case 6: c.ancestry = "primordial"; c.meleeCombat = Math.max(c.magic, 10); break; case 7: c.ancestry = "draconic"; c.meleeCombat = Math.max(c.knowledge, 10); break; case 8: c.ancestry = "demonic"; c.meleeCombat = Math.max(c.skulduggery, 10); break; default: throw new Error("Logic error, ancestry d8() roll was out of scope"); } this.applyFoundation(c); } /** * Create characters for the given player * * The characters are automatically added to the player's party * * @param {Player} player * @param {number} partySize * * @return {Character[]} */ createParty(player, partySize) { // for (let i = 0; i < partySize; i++) { const character = this.createCharacter(player); } } /** * @param {Character} c * @param {string|number} Foundation to add to character */ applyFoundation(c, foundation = "random") { switch (foundation) { case "random": return this.applyFoundation(c, roll.dice(3)); break; // // Brawler // ------ case 1: case ":brawler": c.foundation = "Brawler"; c.skills.add(":armor.light"); c.silver = 40; c.maxHitPoints = c.currentHitPoints = 15; c.itemSlots = 7; c.meleeCombat = Math.max(c.meleeCombat, 10); c.knowledge = Math.min(c.knowledge, 10); this.addItemsToCharacter( c, // ":armor.light.studded_leather", ":weapon.weird.spiked_gauntlets", ); this.addSkillsToCharacter(c, ":weapon.weird.spiked_gauntlets"); break; // // DRUID // ------ case 2: case ":druid": c.foundation = "Druid"; c.silver = 40; c.maxHitPoints = this.currentHitPoints = 15; c.itemSlots = 7; c.meleeCombat = Math.max(this.meleeCombat, 10); c.knowledge = Math.min(this.knowledge, 10); this.addItemsToCharacter( c, // ":armor.light.leather", ":weapon.light.sickle", ":kits.poisoners_kit", ":kits.healers_kit", ); this.addSkillsToCharacter( c, // ":armor.light.leather", ":armor.light.hide", ":weapon.light.sickle", ); break; case 3: case ":fencer": c.foundation = "Fencer"; // // Stats c.maxHitPoints = c.currentHitPoints = 15; c.meleeCombat = Math.max(c.meleeCombat, 10); c.magic = Math.min(c.magic, 10); // // Skills this.addSkillsToCharacter( c, // ":perk.two_weapons", // TODO: perks should be their own thing, and not a part of the skill system? ":armor.light", ); // // Gear c.silver = 40; c.itemSlots = 5; this.addItemsToCharacter( c, // ":armor.light.leather", ":weapon.light.rapier", ":weapon.light.dagger", ); /* // //--------------------------------------------------------------------------------------- //HEADLINE: Fencer //--------------------------------------------------------------------------------------- | {counter:foundation} |Fencer |[unstyled] * Light Armor |[unstyled] * Leather * Rapier * Dagger * 40 Silver Pieces |[unstyled] // //--------------------------------------------------------------------------------------- //HEADLINE: GUARD //--------------------------------------------------------------------------------------- | {counter:foundation} | Guard |[unstyled] * Medium Armor |[unstyled] * Halberd * Bull's Eye Lantern * Signal Whistle * Map of Local Area * 50 Silver Pieces |[unstyled] * 10 Hit Points * 5 Item Slots * Awareness raised to 10 * Melee Combat raised to 10 * Skulduggery limited to 10 // //--------------------------------------------------------------------------------------- //HEADLINE: MAGICIAN //--------------------------------------------------------------------------------------- | {counter:foundation} | Magician |[unstyled] * None |[unstyled] * Tier 2 Wand with random spell. * Tier 1 Wand with random spell. * 10 Silver Pieces |[unstyled] * 10 Hit Points * 6 Item Slots * Melee Combat limited to 10 * Ranged Combat limited to 5 * Magic raised to 10 * Grit limited to 10 // //--------------------------------------------------------------------------------------- //HEADLINE: MEDIC //--------------------------------------------------------------------------------------- | {counter:foundation} |Medic |[unstyled] * Light Armor * Medium Armor |[unstyled] * Club * Sling * 3 Daggers * Healer's Kit * 40 Silver Pieces |[unstyled] * 10 Hit Points * 6 Item Slots // //--------------------------------------------------------------------------------------- //HEADLINE: RECKLESS //--------------------------------------------------------------------------------------- | {counter:foundation} | Reckless |[unstyled] |[unstyled] * Great Axe * 50 Silver Pieces |[unstyled] * 20 Hit Points * 7 Item Slots * Melee Combat raised to 10 * Awareness raised to 10 * Grit raised to 10 * Magic limited to 10 // //--------------------------------------------------------------------------------------- //HEADLINE: ROVER //--------------------------------------------------------------------------------------- | {counter:foundation} | Rover |[unstyled] * Light Armor |[unstyled] * Leather Armor * Short Sword * Longbow * Snare Maker's Kit * 25 Silver Pieces |[unstyled] * 10 Hit Points * 5 Item Slots * Magic Reduced to 10 * Awareness raised to 10 * Ranged Combat raised to 10 // //--------------------------------------------------------------------------------------- //HEADLINE: SKIRMISHER //--------------------------------------------------------------------------------------- | {counter:foundation} | Skirmisher |[unstyled] * Light Armor * Shields |[unstyled] * Spear * Small Shield * 50 Silver Pieces |[unstyled] * 15 Hit Points * 6 Item Slots * Melee Combat raised to 10 * Awareness raised to 10 * Skulduggery raised to 10 * Grit raised to 10 // //--------------------------------------------------------------------------------------- //HEADLINE: SNEAK //--------------------------------------------------------------------------------------- | {counter:foundation} | Sneak |[unstyled] * Light Armor |[unstyled] * 3 daggers * Small Crossbow * Poisoner's Kit * 30 Silver Pieces |[unstyled] * 10 Hit Points * 6 Item Slots * Melee Combat raised to 10 * Awareness raised to 10 * Skulduggery raised to 10 * Grit raised to 10 // //--------------------------------------------------------------------------------------- //HEADLINE: SPELLSWORD //--------------------------------------------------------------------------------------- | {counter:foundation} | Spellsword |[unstyled] |[unstyled] * Tier 1 Wand with random spell. * Longsword * 30 Silver Pieces |[unstyled] * 12 Hit Points * 5 Item Slots * Melee Combat raised to 10 * Ranged Combat limited to 10 * Magic raised to 10 * Skulduggery limited to 10 * Grit raised to 10 // //--------------------------------------------------------------------------------------- //HEADLINE: SPELUNKER //--------------------------------------------------------------------------------------- | {counter:foundation} | Spelunker |[unstyled] * None |[unstyled] * Spear * Caltrops * Bull's Eye Lantern * Map Maker's Kit * Chalk * Caltrops * 5 Silver Pieces |[unstyled] * 10 Hit Points * 4 Item Slots * Awareness raised to 10 * Melee Combat raised to 10 * Skulduggery raised to 10 * Magic limited to 10 // //--------------------------------------------------------------------------------------- //HEADLINE: SPIT'N'POLISH //--------------------------------------------------------------------------------------- | {counter:foundation} | Spit'n' Polish |[unstyled] * Heavy Armor * Shield |[unstyled] * Half-Plate * Large Shield * Long Sword * 10 Silver Pieces |[unstyled] * 10 Hit Points * 2 Item Slots * Melee Combat raised to 10 * Magic Reduced to 6 * Awareness Reduced to 10 // //--------------------------------------------------------------------------------------- //HEADLINE: STILETTO //--------------------------------------------------------------------------------------- | {counter:foundation} | Stiletto |[unstyled] * Light Armor |[unstyled] * Padded Armor * 3 Daggers * Small Crossbow * Poisoner's Kit * 20 Silver Pieces |[unstyled] * 10 Hit Points * 5 Item Slots * Melee Combat raised to 10 * Ranged Combat raised to 10 * Awareness raised to 10 * Magic limited to 6 * Knowledge limited to 10 // //--------------------------------------------------------------------------------------- //HEADLINE: Tinkerer //--------------------------------------------------------------------------------------- | {counter:foundation} |Tinkerer |[unstyled] * Light Armor |[unstyled] * Studded Leather * Wrench (club) * Tinkerer's Kit * 30 Silver Pieces |[unstyled] * 10 Hit Points * 5 Item Slots * Awareness raised to 10 * Knowledge raised to 10 */ // // WTF ?! // ------ default: throw new Error(`Invalid foundation id ${foundation}`); } } }