rework races

This commit is contained in:
2026-05-16 18:35:55 +02:00
parent 83f2b555f8
commit b0a4bd554e
5 changed files with 63 additions and 34 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ export function newCharacter(partial?: { name?: string; id?: string }): Characte
schemaVersion: CURRENT_SCHEMA_VERSION, schemaVersion: CURRENT_SCHEMA_VERSION,
meta: { meta: {
name, name,
rasse: 'Mensch', rasse: 'mensch01',
kultur: '', kultur: '',
profession: '' profession: ''
}, },
+9 -6
View File
@@ -1,6 +1,6 @@
import type { AttributeKey } from '$lib/rules/attributes'; import type { AttributeKey } from '$lib/rules/attributes';
import type { Character } from '$lib/schema/character'; import type { Character } from '$lib/schema/character';
import { RACE_ASP_MOD, RACE_LEP_MOD } from '$lib/rules/races'; import { getRaceDef } from '$lib/rules/races';
export function effectiveAttr(char: Character, key: AttributeKey): number { export function effectiveAttr(char: Character, key: AttributeKey): number {
const a = char.eigenschaften[key]; const a = char.eigenschaften[key];
@@ -36,11 +36,13 @@ export function iniBasis(char: Character): number {
return Math.round(v); return Math.round(v);
} }
/** MR-Basis = (MU + KL + KO) / 5 + MR-Mod aus Energien */ /** MR-Basis = (MU + KL + KO) / 5 + MR-Mod aus Energien + Rassen-MR */
export function mrBasis(char: Character): number { export function mrBasis(char: Character): number {
const race = getRaceDef(char.meta.rasse);
const v = const v =
(effectiveAttr(char, 'MU') + effectiveAttr(char, 'KL') + effectiveAttr(char, 'KO')) / 5 + (effectiveAttr(char, 'MU') + effectiveAttr(char, 'KL') + effectiveAttr(char, 'KO')) / 5 +
char.energien.mr.mod; char.energien.mr.mod +
(race?.mr_mod ?? 0);
return Math.round(v); return Math.round(v);
} }
@@ -49,20 +51,21 @@ export function lepMax(char: Character): number {
const ko = effectiveAttr(char, 'KO'); const ko = effectiveAttr(char, 'KO');
const kk = effectiveAttr(char, 'KK'); const kk = effectiveAttr(char, 'KK');
const base = Math.floor((2 * ko + kk) / 2); const base = Math.floor((2 * ko + kk) / 2);
const race = RACE_LEP_MOD[char.meta.rasse] ?? 0; const race = getRaceDef(char.meta.rasse)?.lep_mod ?? 0;
return base + race + char.energien.lep.mod; return base + race + char.energien.lep.mod;
} }
export function aspMax(char: Character): number { export function aspMax(char: Character): number {
if (!char.energien.asp) return 0; if (!char.energien.asp) return 0;
const race = RACE_ASP_MOD[char.meta.rasse] ?? 0; const race = getRaceDef(char.meta.rasse)?.asp_mod ?? 0;
const base = effectiveAttr(char, 'IN') + effectiveAttr(char, 'IN') + effectiveAttr(char, 'CH'); const base = effectiveAttr(char, 'IN') + effectiveAttr(char, 'IN') + effectiveAttr(char, 'CH');
return Math.max(0, base + race + char.energien.asp.mod); return Math.max(0, base + race + char.energien.asp.mod);
} }
export function aupMax(char: Character): number { export function aupMax(char: Character): number {
const race = getRaceDef(char.meta.rasse)?.aup_mod ?? 0;
const base = effectiveAttr(char, 'MU') + effectiveAttr(char, 'MU') + effectiveAttr(char, 'IN'); const base = effectiveAttr(char, 'MU') + effectiveAttr(char, 'MU') + effectiveAttr(char, 'IN');
return Math.max(0, base + char.energien.aup.mod); return Math.max(0, base + race + char.energien.aup.mod);
} }
export type DerivedSheet = { export type DerivedSheet = {
+44 -24
View File
@@ -1,26 +1,46 @@
/** LeP-Modifikator je Rasse (typische Werte DSA 4.1, vereinfacht) */ /** Rassen mit LeP-/AuP-/AsP-/MR-Modifikatoren (typische Werte DSA 4.1, vereinfacht) */
export const RACE_LEP_MOD: Record<string, number> = { export type RaceDef = {
Mensch: 5, id: string;
Elf: 2, name: string;
Halbelf: 4, lep_mod: number;
Zwerg: 8, aup_mod: number;
Halbling: 0, asp_mod: number;
Gnom: -4, mr_mod: number;
Halbork: 6,
Ork: 8,
Goblin: -5,
'': 0
}; };
export const RACE_ASP_MOD: Record<string, number> = { export const RACES: RaceDef[] = [
Mensch: 0, { id: 'mensch01', name: 'Mittelländer', lep_mod: 10, aup_mod: 10, asp_mod: 0, mr_mod: -4 },
Elf: 12, { id: 'mensch02', name: 'Tulamide', lep_mod: 10, aup_mod: 10, asp_mod: 0, mr_mod: -4 },
Halbelf: 6, { id: 'mensch03', name: 'Thorwaler', lep_mod: 11, aup_mod: 10, asp_mod: 0, mr_mod: -5 },
Zwerg: 0, { id: 'mensch04', name: 'Nivese', lep_mod: 9, aup_mod: 12, asp_mod: 0, mr_mod: -5 },
Halbling: 0, { id: 'mensch05', name: 'Norbarde', lep_mod: 11, aup_mod: 10, asp_mod: 0, mr_mod: -4 },
Gnom: 0, { id: 'mensch06', name: 'Trollzacker', lep_mod: 11, aup_mod: 18, asp_mod: 0, mr_mod: -5 },
Halbork: 0, { id: 'mensch07', name: 'Rochshaz', lep_mod: 12, aup_mod: 20, asp_mod: 0, mr_mod: -5 },
Ork: 0, { id: 'mensch08', name: 'Waldmensch', lep_mod: 8, aup_mod: 12, asp_mod: 0, mr_mod: -6 },
Goblin: 0, { id: 'mensch09', name: 'Tocamuyac', lep_mod: 8, aup_mod: 12, asp_mod: 0, mr_mod: -6 },
'': 0 { id: 'mensch10', name: 'Utulu', lep_mod: 11, aup_mod: 12, asp_mod: 0, mr_mod: -6 },
}; { id: 'plainelf', name: 'Auelf', lep_mod: 6, aup_mod: 12, asp_mod: 12, mr_mod: -2 },
{ id: 'woodelf', name: 'Waldelf', lep_mod: 6, aup_mod: 10, asp_mod: 12, mr_mod: -2 },
{ id: 'firnelf', name: 'Firnelf', lep_mod: 7, aup_mod: 15, asp_mod: 12, mr_mod: -1 },
{ id: 'halbelf', name: 'Halbelf', lep_mod: 8, aup_mod: 10, asp_mod: -6, mr_mod: -4 },
{ id: 'zwerg01', name: 'Zwerg', lep_mod: 11, aup_mod: 15, asp_mod: 0, mr_mod: -4 },
{ id: 'zwerg02', name: 'Brilliantzwerg', lep_mod: 10, aup_mod: 18, asp_mod: 0, mr_mod: -4 },
{ id: 'zwerg03', name: 'Ambosszwerg', lep_mod: 12, aup_mod: 18, asp_mod: 0, mr_mod: -4 },
{ id: 'ork01', name: 'Ork', lep_mod: 12, aup_mod: 18, asp_mod: 0, mr_mod: -7 },
{ id: 'ork02', name: 'Orkfrau', lep_mod: 10, aup_mod: 15, asp_mod: 0, mr_mod: -7 },
{ id: 'halbork', name: 'Halbork', lep_mod: 11, aup_mod: 15, asp_mod: 0, mr_mod: -6 },
{ id: 'goblin', name: 'Goblin', lep_mod: 4, aup_mod: 12, asp_mod: 0, mr_mod: -5 },
{ id: 'achaz01', name: 'Achaz', lep_mod: 8, aup_mod: 7, asp_mod: 0, mr_mod: -2 },
{ id: 'achaz02', name: 'Orkland-Achaz', lep_mod: 15, aup_mod: 7, asp_mod: 0, mr_mod: -2 },
{ id: 'achaz03', name: 'Maraskan-Achaz', lep_mod: 15, aup_mod: 7, asp_mod: 0, mr_mod: -2 }
];
export function getRaceDef(rasse: string): RaceDef | undefined {
if (!rasse) return undefined;
const byId = RACES.find((r) => r.id === rasse);
if (byId) return byId;
const lower = rasse.toLowerCase();
const byIdLower = RACES.find((r) => r.id === lower);
if (byIdLower) return byIdLower;
return RACES.find((r) => r.name === rasse);
}
@@ -4,6 +4,7 @@
import type { Character } from '$lib/schema/character'; import type { Character } from '$lib/schema/character';
import { ATTRIBUTE_KEYS, ATTRIBUTE_LABELS } from '$lib/rules/attributes'; import { ATTRIBUTE_KEYS, ATTRIBUTE_LABELS } from '$lib/rules/attributes';
import { getCharacter, saveCharacter } from '$lib/storage/repo'; import { getCharacter, saveCharacter } from '$lib/storage/repo';
import { RACES } from '$lib/rules/races';
import { TALENTS } from '$lib/rules/talents'; import { TALENTS } from '$lib/rules/talents';
import { computeDerived } from '$lib/engine/derived'; import { computeDerived } from '$lib/engine/derived';
import { atBasis, paBasis } from '$lib/engine/derived'; import { atBasis, paBasis } from '$lib/engine/derived';
@@ -116,7 +117,12 @@
</div> </div>
<div class="field"> <div class="field">
<label for="rasse">Rasse</label> <label for="rasse">Rasse</label>
<input id="rasse" bind:value={char.meta.rasse} /> <select id="rasse" bind:value={char.meta.rasse}>
<option value=""></option>
{#each RACES as r}
<option value={r.id}>{r.name}</option>
{/each}
</select>
</div> </div>
<div class="field"> <div class="field">
<label for="kultur">Kultur</label> <label for="kultur">Kultur</label>
+2 -2
View File
@@ -12,13 +12,13 @@ describe('derived', () => {
it('includes race LeP bonus for human', () => { it('includes race LeP bonus for human', () => {
const c = newCharacter({ name: 'H', id: '00000000-0000-4000-8000-000000000002' }); const c = newCharacter({ name: 'H', id: '00000000-0000-4000-8000-000000000002' });
c.meta.rasse = 'Mensch'; c.meta.rasse = 'Mittelländer';
const ko = 12; const ko = 12;
const kk = 13; const kk = 13;
c.eigenschaften.KO = { startwert: ko, mod: 0 }; c.eigenschaften.KO = { startwert: ko, mod: 0 };
c.eigenschaften.KK = { startwert: kk, mod: 0 }; c.eigenschaften.KK = { startwert: kk, mod: 0 };
const base = Math.floor((2 * ko + kk) / 2); const base = Math.floor((2 * ko + kk) / 2);
expect(lepMax(c)).toBe(base + 5 + c.energien.lep.mod); expect(lepMax(c)).toBe(base + 10 + c.energien.lep.mod);
}); });
it('computeDerived returns all keys', () => { it('computeDerived returns all keys', () => {