import type { MAIN_STATS, ABILITIES, LEVELS, TRAINING_LEVELS, SPELL_TYPES, CATEGORIES, SPELL_ELEMENTS, ALIGNMENTS, RESISTANCES, DAMAGE_TYPES, WEAPON_TYPES } from "#shared/character.util"; import type { Localized } from "../types/general"; export type MainStat = typeof MAIN_STATS[number]; export type Ability = typeof ABILITIES[number]; export type Level = typeof LEVELS[number]; export type TrainingLevel = typeof TRAINING_LEVELS[number]; export type SpellType = typeof SPELL_TYPES[number]; export type Category = typeof CATEGORIES[number]; export type SpellElement = typeof SPELL_ELEMENTS[number]; export type Alignment = typeof ALIGNMENTS[number]; export type Resistance = typeof RESISTANCES[number]; export type DamageType = typeof DAMAGE_TYPES[number]; export type WeaponType = typeof WEAPON_TYPES[number]; export type FeatureID = string; export type i18nID = string; export type RecursiveKeyOf = { [TKey in keyof TObj & (string | number)]: TObj[TKey] extends any[] ? `${TKey}` : TObj[TKey] extends object ? `${TKey}` | `${TKey}/${RecursiveKeyOf}` : `${TKey}`; }[keyof TObj & (string | number)]; export type Character = { id: number; name: string; //Free text people?: string; //People ID level: number; aspect?: number; notes?: { public?: string, private?: string }; //Free text training: Record>>; leveling: Partial>; abilities: Partial>; variables: CharacterVariables; choices: Record; owner: number; username?: string; visibility: "private" | "public"; }; export type CharacterVariables = { health: number; mana: number; exhaustion: number; sickness: Array<{ id: string, state: number | true }>; poisons: Array<{ id: string, state: number | true }>; spells: string[]; //Spell ID items: ItemState[]; }; type ItemState = { id: string; amount: number; enchantments?: []; charges?: number; equipped?: boolean; state?: any; }; export type CharacterConfig = { peoples: Record; training: Record>; spells: SpellConfig[]; aspects: AspectConfig[]; features: Record; enchantments: Record; //TODO items: Record; sickness: Record; action: Record; reaction: Record; freeaction: Record; passive: Record; texts: Record; }; export type EnchantementConfig = { name: string; //TODO -> TextID effect: Array; power: number; } export type ItemConfig = CommonItemConfig & (ArmorConfig | WeaponConfig | WondrousConfig | MundaneConfig); type CommonItemConfig = { id: string; name: string; //TODO -> TextID description: i18nID; rarity: 'common' | 'uncommon' | 'rare' | 'legendary'; weight?: number; //Optionnal but highly recommended price?: number; //Optionnal but highly recommended capacity?: number; //Optionnal as most mundane items should not receive enchantments (potions, herbal heals, etc...) powercost?: number; //Optionnal charge?: number //Max amount of charges enchantments?: string[]; //Enchantment ID effects?: Array; equippable: boolean; consummable: boolean; } type ArmorConfig = { category: 'armor'; health: number; type: 'light' | 'medium' | 'heavy'; absorb: { static: number, percent: number }; }; type WeaponConfig = { category: 'weapon'; type: Array; damage: { value: string; //Dice formula type: DamageType; }; }; type WondrousConfig = { category: 'wondrous'; }; type MundaneConfig = { category: 'mundane'; }; export type SpellConfig = { id: string; name: string; //TODO -> TextID rank: 1 | 2 | 3 | 4; type: SpellType; cost: number; speed: "action" | "reaction" | number; elements: Array; description: string; //TODO -> TextID concentration: boolean; range: 'personnal' | number; tags?: string[]; }; export type RaceConfig = { id: string; name: string; //TODO -> TextID description: string; //TODO -> TextID options: Record; }; export type AspectConfig = { name: string; description: string; //TODO -> TextID stat: MainStat | 'special'; alignment: Alignment; magic: boolean; difficulty: number; physic: { min: number, max: number }; mental: { min: number, max: number }; personality: { min: number, max: number }; options: FeatureItem[]; }; export type FeatureValue = { id: FeatureID; category: "value"; operation: "add" | "set" | "min"; property: RecursiveKeyOf | 'spec' | 'ability' | 'training'; value: number | `modifier/${MainStat}` | false; } export type FeatureEquipment = { id: FeatureID; category: "value"; operation: "add" | "set" | "min"; property: 'weapon/damage/value' | 'armor/health' | 'armor/absorb/flat' | 'armor/absorb/percent'; value: number | `modifier/${MainStat}` | false; } export type FeatureList = { id: FeatureID; category: "list"; list: "spells" | "sickness" | "action" | "reaction" | "freeaction" | "passive"; action: "add" | "remove"; item: string; }; export type FeatureChoice = { id: FeatureID; category: "choice"; text: string; //TODO -> TextID settings?: { //If undefined, amount is 1 by default amount: number; exclusive: boolean; //Disallow to pick the same option twice }; options: Array<{ text: string, effects: Array }>; //TODO -> TextID }; export type FeatureItem = FeatureValue | FeatureList | FeatureChoice; export type Feature = { id: FeatureID; description: string; //TODO -> TextID effect: FeatureItem[]; }; export type CompiledCharacter = { id: number; owner?: number; username?: string; name: string; health: number; //Max mana: number; //Max race: string; spellslots: number; //Max artslots: number; //Max spellranks: Record; aspect: string; //ID speed: number | false; capacity: number | false; initiative: number; exhaust: number; itempower: number; action: number; reaction: number; variables: CharacterVariables, defense: { hardcap: number; static: number; activeparry: number; activedodge: number; passiveparry: number; passivedodge: number; }; mastery: { strength: number; dexterity: number; shield: number; armor: number; multiattack: number; magicpower: number; magicspeed: number; magicelement: number; magicinstinct: number; }; bonus: { defense: Partial>; abilities: Partial>; }; //Any special bonus goes here resistance: Record; modifier: Record; abilities: Partial>; level: number; lists: { [K in FeatureList['list']]?: string[] }; //string => ListItem ID notes: { public: string, private: string }; };