Files
dsa-ranger/src/lib/rules/modifiers-ranged.ts
T
2026-05-16 21:35:35 +02:00

337 lines
7.0 KiB
TypeScript

import type { Expertise } from '$lib/rules/expertise';
export type RangeId = 'very_near' | 'near' | 'medium' | 'far' | 'very_far';
export type TargetSizeId =
| 'very_large'
| 'large'
| 'medium'
| 'small'
| 'very_small'
| 'tiny';
export type VisibilityId =
| 'clear'
| 'haze'
| 'fog'
| 'dusk'
| 'moonlight'
| 'starlight'
| 'darkness'
| 'invisible';
export type MovementId = 'stationary' | 'standing' | 'slow' | 'fast' | 'very_fast' | 'battle';
export type HitZoneId =
| 'head'
| 'torso'
| 'arms'
| 'stomach'
| 'legs'
| 'hand_foot'
| 'eye_heart'
| 'qrump'
| 'qleg'
| 'weakspot'
| 'qhead'
| 'qtail'
| 'qsensory_organs';
export type ExtraModifierId =
| 'steep_shot_down'
| 'steep_shot_up'
| 'gusty_crosswind'
| 'strong_gusty_crosswind'
| 'fast_shot'
| 'aim';
export type ReloadStateId =
| 'arrow_nocked'
| 'bow_drawn'
| 'regular_shot'
| 'fast_shot_bow'
| 'aimed_shot'
| 'announced'
| 'fast_reload_bow';
export type ModifierRow = {
id: string;
name: string;
modifier: number | string;
modifier_expert?: number | string;
modifier_master?: number | string;
description?: string;
skill?: string;
special?: string;
build?: 'biped' | 'quadruped';
random?: string;
};
export const RANGES: ModifierRow[] = [
{ id: 'very_near', name: 'sehr nah', modifier: -2 },
{ id: 'near', name: 'nah', modifier: 0 },
{ id: 'medium', name: 'mittel', modifier: 4 },
{ id: 'far', name: 'weit', modifier: 8 },
{ id: 'very_far', name: 'extrem weit', modifier: 12 }
];
export const TARGET_SIZES: ModifierRow[] = [
{
id: 'very_large',
name: 'sehr groß',
description: 'Scheunentor, Drache, Elefant, Riese',
modifier: -2
},
{
id: 'large',
name: 'groß',
description: 'Pferd, Steppenrind, Oger, Troll',
modifier: 0
},
{
id: 'medium',
name: 'mittel',
description: 'Mensch, Elf, Ork, Goblin, Zwerg',
modifier: 2
},
{
id: 'small',
name: 'klein',
description: 'Wolf, Reh, Schaf',
modifier: 4
},
{
id: 'very_small',
name: 'sehr klein',
description: 'Schlange, Fasan, Katze, Rabe',
modifier: 6
},
{
id: 'tiny',
name: 'winzig',
description: 'Münze, Drachenauge, Maus, Kröte',
modifier: 8
}
];
export const VISIBILITY: ModifierRow[] = [
{ id: 'clear', name: 'klar', modifier: 0 },
{ id: 'haze', name: 'Dunst', modifier: 2 },
{ id: 'fog', name: 'Nebel', modifier: 4 },
{ id: 'dusk', name: 'Dämmerung', modifier: 2 },
{ id: 'moonlight', name: 'Mondlicht', modifier: 4 },
{ id: 'starlight', name: 'Sternenlicht', modifier: 6 },
{ id: 'darkness', name: 'Finsternis', modifier: 8 },
{ id: 'invisible', name: 'Unsichtbares Ziel', modifier: 8 }
];
export const TARGET_MOVEMENT: ModifierRow[] = [
{ id: 'stationary', name: 'unbewegliches / fest montiertes Ziel', modifier: -4 },
{ id: 'standing', name: 'stillstehendes Ziel', modifier: -2 },
{ id: 'slow', name: 'leichte Bewegung des Ziels', modifier: 0 },
{ id: 'fast', name: 'schnelle Bewegung des Ziels', modifier: 2 },
{
id: 'very_fast',
name: 'sehr schnelle Bewegung des Ziels / Ausweichbewegungen',
modifier: 4
},
{ id: 'battle', name: 'Kampfgetümmel', modifier: 2, special: 'true' }
];
export const HIT_ZONES: ModifierRow[] = [
{
id: 'head',
name: 'Kopf',
modifier: 10,
modifier_expert: 7,
modifier_master: 5,
build: 'biped',
random: '19-20'
},
{
id: 'torso',
name: 'Torso',
modifier: 6,
modifier_expert: 4,
modifier_master: 3,
build: 'biped',
random: '15-18'
},
{
id: 'arms',
name: 'Arme',
modifier: 10,
modifier_expert: 7,
modifier_master: 5,
build: 'biped',
random: '9-14'
},
{
id: 'stomach',
name: 'Bauch',
modifier: 6,
modifier_expert: 4,
modifier_master: 3,
build: 'biped',
random: '7-8'
},
{
id: 'legs',
name: 'Beine',
modifier: 8,
modifier_expert: 5,
modifier_master: 4,
build: 'biped',
random: '1-6'
},
{
id: 'hand_foot',
name: 'Hand/Fuß',
modifier: 16,
modifier_expert: 11,
modifier_master: 8,
build: 'biped'
},
{
id: 'eye_heart',
name: 'Auge/Herz',
modifier: 20,
modifier_expert: 13,
modifier_master: 10,
build: 'biped'
},
{
id: 'qrump',
name: 'Rumpf',
modifier: 4,
modifier_expert: 3,
modifier_master: 2,
build: 'quadruped',
random: '1-8'
},
{
id: 'qleg',
name: 'Bein',
modifier: 10,
modifier_expert: 7,
modifier_master: 5,
build: 'quadruped',
random: '9-16'
},
{
id: 'weakspot',
name: 'verwundbare Stelle',
modifier: 12,
modifier_expert: 8,
modifier_master: 6,
build: 'quadruped',
random: '1-8'
},
{
id: 'qhead',
name: 'Kopf',
modifier: 16,
modifier_expert: 11,
modifier_master: 8,
build: 'quadruped',
random: '17-19'
},
{
id: 'qtail',
name: 'Schwanz',
modifier: 16,
modifier_expert: 11,
modifier_master: 8,
build: 'quadruped',
random: '20'
},
{
id: 'qsensory_organs',
name: 'Sinnesorgane',
modifier: 16,
modifier_expert: 11,
modifier_master: 8,
build: 'quadruped',
random: '20'
}
];
export const OTHER_MODIFIERS: ModifierRow[] = [
{
id: 'steep_shot_down',
name: 'Steilschuss nach unten',
modifier: 2,
skill: 'archery'
},
{
id: 'steep_shot_up',
name: 'Steilschuss nach oben',
modifier: 4,
skill: 'archery'
},
{ id: 'gusty_crosswind', name: 'böiger Seitenwind', modifier: 4 },
{ id: 'strong_gusty_crosswind', name: 'starker, böiger Seitenwind', modifier: 8 },
{
id: 'fast_shot',
name: 'Schnellschuss',
modifier: 2,
modifier_expert: 1,
modifier_master: 0
},
{
id: 'aim',
name: 'Zielen',
modifier: -0.5,
modifier_expert: -1,
modifier_master: -1
}
];
export const RELOAD_STATES: ModifierRow[] = [
{ id: 'arrow_nocked', name: 'Pfeil auf Sehne', modifier: -1 },
{ id: 'bow_drawn', name: 'Bogen bereits gespannt', modifier: -2 },
{ id: 'regular_shot', name: 'Normaler Schuss', modifier: 1 },
{ id: 'fast_shot_bow', name: 'Normaler Schuss (schnell)', modifier: 0 },
{
id: 'aimed_shot',
name: 'Gezielter Schuss',
modifier: '/2',
modifier_expert: '/2 -2',
modifier_master: 1
},
{
id: 'announced',
name: 'Fernkampfangriff mit Ansage',
modifier: '/2',
modifier_expert: '/2 -2',
modifier_master: 1
},
{ id: 'fast_reload_bow', name: 'Schnellladen', modifier: -1, skill: 'archery' }
];
function resolveModifierRaw(
row: ModifierRow,
expertise: Expertise
): number | string {
return expertise === 'master' && row.modifier_master !== undefined
? row.modifier_master
: expertise === 'expert' && row.modifier_expert !== undefined
? row.modifier_expert
: row.modifier;
}
/** Anzeige-Label für Dropdown-Optionen (berücksichtigt Scharfschütze/Meisterschütze). */
export function formatModifierLabel(row: ModifierRow, expertise: Expertise): string {
const m = resolveModifierRaw(row, expertise);
return `${row.name} (${m})`;
}
export function resolveNumericModifier(
row: ModifierRow | undefined,
expertise: Expertise
): number | null {
if (!row) return null;
const raw = resolveModifierRaw(row, expertise);
if (typeof raw === 'number') return raw;
return null;
}
export function isStringModifier(row: ModifierRow | undefined, expertise: Expertise): boolean {
if (!row) return false;
return typeof resolveModifierRaw(row, expertise) === 'string';
}