This commit is contained in:
Kim Ravn Hansen
2025-09-14 13:04:48 +02:00
parent 8c196bb6a1
commit ed91a7f2f7
43 changed files with 2279 additions and 1727 deletions

View File

@@ -10,16 +10,29 @@
// |____/ \___|\___|\__,_|\___|_|
// ------------------------------------------------
import { Character } from "../models/character.js";
import { Game } from "../models/game.js";
import { gGame } from "../models/globals.js";
import { Player } from "../models/player.js";
import * as roll from "../utils/dice.js";
import { isIdSane } from "../utils/id.js";
// stupid convenience hack that only works if we only have a single Game in the system.
// Which we easily could have.!!
let roll = {};
export class CharacterSeeder {
/** @type {Game} */
constructor(game) {
/** @type {Game} */
this.game = game;
constructor() {
// stupid convenience hack that only works if we only have a single Game in the system.
// Which we easily could have.!!
roll = {
d: (max, min = 1) => {
return gGame.random.within(min, max);
},
d6: () => {
return gGame.random.within(1, 6);
},
d8: () => {
return gGame.random.within(1, 8);
},
};
}
/**
@@ -36,7 +49,7 @@ export class CharacterSeeder {
*/
addItemsToCharacter(character, ...itemBlueprintIds) {
for (const id of itemBlueprintIds) {
const blueprint = this.game.getItemBlueprint(id);
const blueprint = gGame.getItemBlueprint(id);
if (!blueprint) {
throw new Error(`No blueprint found for id: ${id}`);
}
@@ -74,9 +87,9 @@ export class CharacterSeeder {
// Rolling skills
c.name =
this.game.rng.oneOf("sir", "madam", "mister", "miss", "", "", "") +
" random " +
this.game.rng.get().toString();
gGame.random.oneOf("sir ", "madam ", "mister ", "miss ", "", "", "") + // prefix
"random " + // name
gGame.random.get().toString(); // suffix
c.awareness = roll.d6() + 2;
c.grit = roll.d6() + 2;
@@ -86,7 +99,8 @@ export class CharacterSeeder {
c.rangedCombat = roll.d6() + 2;
c.skulduggery = roll.d6() + 2;
switch (roll.d8()) {
let ancestryId = roll.d8();
switch (ancestryId) {
case 1:
c.ancestry = "human";
// Humans get +1 to all skills
@@ -111,7 +125,7 @@ export class CharacterSeeder {
c.meleeCombat = Math.max(c.grit, 10);
break;
case 5:
c.ancestry = "Gnomish";
c.ancestry = "gnomish";
c.meleeCombat = Math.max(c.awareness, 10);
break;
case 6:
@@ -127,12 +141,12 @@ export class CharacterSeeder {
c.meleeCombat = Math.max(c.skulduggery, 10);
break;
default:
throw new Error("Logic error, ancestry d8() roll was out of scope");
throw new Error(`Logic error, ancestry d8() roll of ${ancestryId} was out of scope"`);
}
this.applyFoundation(c);
console.log(c);
console.debug(c);
return c;
}
@@ -163,7 +177,7 @@ export class CharacterSeeder {
applyFoundation(c, foundation = ":random") {
switch (foundation) {
case ":random":
return this.applyFoundation(c, roll.dice(3));
return this.applyFoundation(c, roll.d(3));
break;
//

View File

@@ -1,4 +1,5 @@
import { Game } from "../models/game.js";
import { Config } from "../config.js";
import { gGame } from "../models/globals.js";
import { CharacterSeeder } from "./characerSeeder.js";
import { ItemSeeder } from "./itemSeeder.js";
import { PlayerSeeder } from "./playerSeeder.js";
@@ -11,23 +12,13 @@ import { PlayerSeeder } from "./playerSeeder.js";
* If dev mode, we create some known debug logins. (username = user, password = pass) as well as a few others
*/
export class GameSeeder {
/** @returns {Game} */
createGame(rngSeed) {
/** @protected @constant @readonly @type {Game} */
this.game = new Game(rngSeed);
this.work(); // Seeding may take a bit, so let's defer it so we can return early.
return this.game;
}
work() {
seed() {
console.info("seeding");
//
new PlayerSeeder(this.game).seed(); // Create debug players
new ItemSeeder(this.game).seed(); // Create items, etc.
new CharacterSeeder(this.game).createParty(this.game.getPlayer("user"), 3); // Create debug characters.
gGame.rngSeed = Config.rngSeed;
new PlayerSeeder().seed(); // Create debug players
new ItemSeeder().seed(); // Create items, etc.
new CharacterSeeder().createParty(gGame.getPlayer("user"), 3); // Create debug characters.
//
// Done

View File

@@ -1,5 +1,5 @@
import { Game } from "../models/game.js";
import { ItemBlueprint } from "../models/item.js";
import { gGame } from "../models/globals.js";
//
// ___ _ _____ _ _
@@ -11,11 +11,6 @@ import { ItemBlueprint } from "../models/item.js";
//
// Seed the Game.ItemBlueprint store
export class ItemSeeder {
/** @param {Game} game */
constructor(game) {
this.game = game;
}
seed() {
//
// __ __
@@ -25,7 +20,7 @@ export class ItemSeeder {
// \_/\_/ \___|\__,_| .__/ \___/|_| |_|___/
// |_|
//-------------------------------------------------------
this.game.addItemBlueprint(":weapon.light.dagger", {
gGame.addItemBlueprint(":weapon.light.dagger", {
name: "Dagger",
description: "Small shady blady",
itemSlots: 0.5,
@@ -35,7 +30,7 @@ export class ItemSeeder {
specialEffect: ":effect.weapon.fast",
});
this.game.addItemBlueprint(":weapon.light.sickle", {
gGame.addItemBlueprint(":weapon.light.sickle", {
name: "Sickle",
description: "For cutting nuts, and branches",
itemSlots: 1,
@@ -43,7 +38,7 @@ export class ItemSeeder {
specialEffect: ":effect.weapon.sickle",
});
this.game.addItemBlueprint(":weapon.weird.spiked_gauntlets", {
gGame.addItemBlueprint(":weapon.weird.spiked_gauntlets", {
name: "Spiked Gauntlets",
description: "Spikes with gauntlets on them!",
itemSlots: 1,
@@ -51,7 +46,7 @@ export class ItemSeeder {
specialEffect: "TBD",
});
this.game.addItemBlueprint(":weapon.light.rapier", {
gGame.addItemBlueprint(":weapon.light.rapier", {
name: "Rapier",
description: "Fancy musketeer sword",
itemSlots: 1,
@@ -66,14 +61,14 @@ export class ItemSeeder {
// / ___ \| | | | | | | | (_) | | \__ \
// /_/ \_\_| |_| |_| |_|\___/|_| |___/
// ---------------------------------------
this.game.addItemBlueprint(":armor.light.studded_leather", {
gGame.addItemBlueprint(":armor.light.studded_leather", {
name: "Studded Leather Armor",
description: "Padded and hardened leather with metal stud reinforcement",
itemSlots: 3,
specialEffect: "TBD",
armorHitPoints: 10,
});
this.game.addItemBlueprint(":armor.light.leather", {
gGame.addItemBlueprint(":armor.light.leather", {
name: "Leather Armor",
description: "Padded and hardened leather",
itemSlots: 2,
@@ -81,8 +76,6 @@ export class ItemSeeder {
armorHitPoints: 6,
});
console.log(this.game._itemBlueprints);
//
// _ ___ _
// | |/ (_) |_ ___
@@ -90,7 +83,7 @@ export class ItemSeeder {
// | . \| | |_\__ \
// |_|\_\_|\__|___/
// -------------------
this.game.addItemBlueprint(":kit.poisoners_kit", {
gGame.addItemBlueprint(":kit.poisoners_kit", {
name: "Poisoner's Kit",
description: "Allows you to create poisons that can be applied to weapons",
itemSlots: 2,
@@ -99,7 +92,7 @@ export class ItemSeeder {
maxCount: 20,
});
this.game.addItemBlueprint(":kit.healers_kit", {
gGame.addItemBlueprint(":kit.healers_kit", {
name: "Healer's Kit",
description: "Allows you to heal your teammates outside of combat",
itemSlots: 2,

View File

@@ -1,34 +1,28 @@
import { Game } from "../models/game.js";
import { gGame } from "../models/globals.js";
import { Player } from "../models/player.js";
export class PlayerSeeder {
/** @param {Game} game */
constructor(game) {
/** @type {Game} */
this.game = game;
}
seed() {
// Examples of the word "pass" hashed by the client and then the server:
// Note that the word "pass" has gajillions of hashed representations, all depending on the salts used to hash them.
// "pass" hashed by client: KimsKrappyKryptoV1:userSalt:1000:SHA-256:b106e097f92ff7c288ac5048efb15f1a39a15e5d64261bbbe3f7eacee24b0ef4
// "pass" hashed by server: 1000:15d79316f95ff6c89276308e4b9eb64d:2178d5ded9174c667fe0624690180012f13264a52900fe7067a13f235f4528ef
//
// Since the server-side hashes have random salts, the hashes themselves can change for the same password.
// The client side hash must not have a random salt, otherwise, it must change every time.
//
// The hash below is just one has that represents the password "pass" sent via V1 of the "Kims Krappy Krypto" scheme.
seed() {
// Examples of the word "pass" hashed by the client and then the server:
// Note that the word "pass" has gajillions of hashed representations, all depending on the salts used to hash them.
// "pass" hashed by client: KimsKrappyKryptoV1:userSalt:1000:SHA-256:b106e097f92ff7c288ac5048efb15f1a39a15e5d64261bbbe3f7eacee24b0ef4
// "pass" hashed by server: 1000:15d79316f95ff6c89276308e4b9eb64d:2178d5ded9174c667fe0624690180012f13264a52900fe7067a13f235f4528ef
//
// Since the server-side hashes have random salts, the hashes themselves can change for the same password.
// The client side hash must not have a random salt, otherwise, it must change every time.
//
// The hash below is just one has that represents the password "pass" sent via V1 of the "Kims Krappy Krypto" scheme.
gGame.createPlayer(
"user",
"1000:15d79316f95ff6c89276308e4b9eb64d:2178d5ded9174c667fe0624690180012f13264a52900fe7067a13f235f4528ef",
"userSalt",
);
this.game.createPlayer(
"user",
"1000:15d79316f95ff6c89276308e4b9eb64d:2178d5ded9174c667fe0624690180012f13264a52900fe7067a13f235f4528ef",
"userSalt",
);
this.game.createPlayer(
"admin",
"1000:a84760824d28a9b420ee5f175a04d1e3:a6694e5c9fd41d8ee59f0a6e34c822ee2ce337c187e2d5bb5ba8612d6145aa8e",
"adminSalt",
);
}
gGame.createPlayer(
"admin",
"1000:a84760824d28a9b420ee5f175a04d1e3:a6694e5c9fd41d8ee59f0a6e34c822ee2ce337c187e2d5bb5ba8612d6145aa8e",
"adminSalt",
);
}
}