563 lines
13 KiB
JavaScript
Executable File
563 lines
13 KiB
JavaScript
Executable File
// ____ _ _
|
|
// / ___| |__ __ _ _ __ __ _ ___| |_ ___ _ __
|
|
// | | | '_ \ / _` | '__/ _` |/ __| __/ _ \ '__|
|
|
// | |___| | | | (_| | | | (_| | (__| || __/ |
|
|
// \____|_| |_|\__,_|_| \__,_|\___|\__\___|_|
|
|
// ____ _
|
|
// / ___| ___ ___ __| | ___ _ __
|
|
// \___ \ / _ \/ _ \/ _` |/ _ \ '__|
|
|
// ___) | __/ __/ (_| | __/ |
|
|
// |____/ \___|\___|\__,_|\___|_|
|
|
// ------------------------------------------------
|
|
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}`);
|
|
}
|
|
}
|
|
}
|