/* Data loader + helpers */ const ABILITIES = ["STR", "DEX", "CON", "INT", "WIS", "CHA"]; const ABILITY_LABELS = { STR: "Strength", DEX: "Dexterity", CON: "Constitution", INT: "Intellect", WIS: "Wisdom", CHA: "Charisma", }; const STANDARD_ARRAY = [15, 14, 13, 12, 10, 8]; const SKILL_ABILITY = { acrobatics: "DEX", animal_handling: "WIS", arcana: "INT", athletics: "STR", deception: "CHA", history: "INT", insight: "WIS", intimidation: "CHA", investigation: "INT", medicine: "WIS", nature: "INT", perception: "WIS", performance: "CHA", persuasion: "CHA", religion: "INT", sleight_of_hand: "DEX", stealth: "DEX", survival: "WIS", }; const SKILL_LABEL = { acrobatics: "Acrobatics", animal_handling: "Animal Handling", arcana: "Arcana", athletics: "Athletics", deception: "Deception", history: "History", insight: "Insight", intimidation: "Intimidation", investigation: "Investigation", medicine: "Medicine", nature: "Nature", perception: "Perception", performance: "Performance", persuasion: "Persuasion", religion: "Religion", sleight_of_hand: "Sleight of Hand", stealth: "Stealth", survival: "Survival", }; // Skill descriptions, framed in Theriapolis's clade-vocabulary so hover hints // match the rest of the codex's tone. const SKILL_DESC = { acrobatics: "Tumbling, balance, and the kind of footwork that keeps you upright on a coliseum sand-floor or a warren-rope. Body-cunning under pressure.", animal_handling: "Reading and steering non-sentient beasts — feral hounds, draft-kine, the wild cousins of your own clade. Calming, herding, riding.", arcana: "Knowledge of the older magics: scent-sorcery, blood-sigil, the half-forgotten rites that pre-date the Covenant of Claws.", athletics: "Raw physical effort. Climbing scaffold, swimming the foul canal, hauling a packmate from the pit, breaking a hold.", deception: "Speaking convincingly past your scent. The art of the false posture, the planted rumor, the answer that is technically true.", history: "The long memory of Theriapolis — the Imperium's fall, the Compact's ratification, which clade owes which other a centuries-old debt.", insight: "Reading another's true posture beneath their words. Catching the off-note in a snarl, the held breath, the lie in a friendly tail.", intimidation: "Bared-teeth diplomacy. The threat made plain enough that violence is not required to extract compliance.", investigation: "Methodical search and inference: scene-reading, document-sifting, the patient accumulation of small facts into a verdict.", medicine: "Field surgery, poultice-craft, knowing which clade tolerates which tincture. Stabilizing the dying without finishing them.", nature: "Knowledge of the wild outside the city wall — terrain, weather, plant-lore, and the unsigned beasts that observe no Covenant.", perception: "Awareness through every sense your clade gives you: ear-cock, scent-prickle, the half-glimpsed shape at the edge of vision.", performance: "Holding an audience — coliseum crowd, courtroom gallery, market square. Song, oratory, the body that compels watching.", persuasion: "Open-handed argument. The case made on its merits, the appeal to mutual benefit, the patient construction of agreement.", religion: "The hymn-cycles of the Cervid liturgy, the Compact's sacred clauses, the small household rites your clade keeps without thinking.", sleight_of_hand: "Quiet fingers — pickpocketing, palmed coins, the swap performed under another's nose. Useful in markets and courtrooms alike.", stealth: "Movement unseen and unsmelled. Wind-checking, scent-suppression, the slow weight-shift on a creaking floor.", survival: "Field-craft beyond the wall: tracking, foraging, fire-making, knowing which run-off is safe to drink and which carries the upstream butcher's leavings.", }; const SIZE_LABEL = { small: "Small", medium: "Medium", medium_large: "Medium-Large", large: "Large", }; // Class → recommended clades (informational, per design intent) const CLASS_CLADE_REC = { fangsworn: ["canidae", "felidae", "ursidae"], bulwark: ["bovidae", "ursidae"], feral: ["ursidae", "mustelidae", "bovidae"], shadow_pelt: ["felidae", "mustelidae", "leporidae"], scent_broker: ["canidae", "mustelidae"], covenant_keeper: ["canidae", "bovidae", "cervidae"], muzzle_speaker: ["felidae", "leporidae"], claw_wright: ["mustelidae", "leporidae"], }; // Language metadata — name + description for hover hints const LANGUAGES = { common: { name: "Common", description: "The market-and-courthouse trade tongue of Theriapolis. Spoken by every clade; the language of contracts, guard-watches, and most of the city's signage." }, canid: { name: "Canid", description: "Pack-tongue of the Canidae. Heavy with subsonic registers and scent-words — Canid sentences carry pheromonal undertones non-Canid speakers cannot fully parse." }, felid: { name: "Felid", description: "Sinuous and tonal, with a parallel tail-and-ear pidgin. Felid speakers trade in implication and pause; lying in Felid is a high art." }, mustelid: { name: "Mustelid", description: "Quick, percussive trade-speech of the Mustelidae. Famous for its dense vocabulary of musks, debts, and small grievances." }, ursid: { name: "Ursid", description: "Slow, low-register growl-speech. Ursid grammar prefers final emphasis — the important word always comes last." }, cervid: { name: "Cervid", description: "Old, hymn-shaped tongue of the Cervidae. Most speakers know Cervid as a song-language for funerals, treaties, and the long calendar." }, bovid: { name: "Bovid", description: "Patient, formal speech of the herd-clades. Bovid is the language of guild-councils and oaths; lying in formal Bovid is itself a punishable act." }, leporid: { name: "Leporid", description: "Rapid, twitch-paced chatter of the Leporidae. Leporid uses tense markers for danger and runs faster than most non-Leporidae can follow." }, }; // Pretty item names from item ids const ITEM_NAME = { rend_sword: "Rend-sword", chain_shirt: "Chain Shirt", buckler: "Buckler", healers_kit: "Healer's Kit", rations_predator: "Rations (predator)", rations_prey: "Rations (prey)", hoof_club: "Hoof Club", chain_mail: "Chain Mail", standard_shield: "Shield", paw_axe: "Paw Axe", hide_vest: "Hide Vest", thorn_blade: "Thorn-blade", studded_leather: "Studded Leather", claw_bow: "Claw-bow", poultice_universal: "Universal Poultice", scent_mask_basic: "Scent-mask", fang_knife: "Fang Knife", leather_harness: "Leather Harness", pheromone_vial_calm: "Pheromone Vial (calm)", pheromone_vial_fear: "Pheromone Vial (fear)", rope_claw_braid: "Claw-braid Rope", }; // Plain-language readings for traits/detriments — author-curated const TRAIT_READING = { pack_instinct: "When a friend nearby gets attacked, you can throw your shoulder in front of them to ward off the blow.", superior_scent: "Your nose tells you what eyes can't — feelings, lies, fear in a room.", subsonic_communication: "You can talk silently with other Canid-folk over short distances.", pack_dependent: "Alone, your nerves fray. Crowds steady you.", scent_overload: "Strong smells make a noisy room.", retractable_claws: "Sheath them for fine work, draw them for a fight.", darkvision: "Dim light reads as bright; pitch dark reads as dim grey.", feline_grace: "You shrug off most falls and find your feet on any ledge.", tail_speak: "Your tail says what your mouth won't — visible to anyone who reads Felid.", solitary_instinct: "Help from non-Felidae mostly bounces off — you work alone or you work with kin.", prides_cost: "A public fumble costs you the next charm check; the room is watching.", sinuous_frame: "Bend through gaps the size of a saucer; slip a grapple like water.", burning_metabolism: "Cold doesn't stick. Hunger does.", ferocity: "Wounded, you bite harder for one turn.", high_metabolism: "Two days of rations a day — or you crash.", scent_marker: "Mustelid musk is unmistakable. Stealth costs extra.", powerful_build: "You count as one size larger for hauling and grappling.", thick_hide: "Your skin is armor. Blunt damage barely lands.", bone_crushing_jaws: "A clean bite ends fights.", lumbering: "You don't sneak. You arrive.", heat_intolerance: "Heat saps you — long hot days demand rest.", fleet_footed: "You're faster, and dashing past enemies is safer.", antlers: "A natural weapon, growing back each year.", wide_field_of_view: "Hard to flank — you see what's at the corners.", flight_response: "Sudden danger triggers a save-or-flee reflex.", delicate_frame: "Less HP per level. You feel hits.", horns: "Permanent natural weapon — bone, not bone-spurs.", herd_wall: "Allies at your shoulder give you AC.", unshakeable: "Fear and charm slide off you.", ponderous_gait: "Slower base speed; quick pivots aren't your thing.", stubborn: "Feints fool you because you commit.", leaping_strides: "No run-up needed for big jumps.", burrow_savvy: "Underground is home. You see and survive there.", twitch_reflexes: "First in initiative; ranged shots flinch off.", fragile_body: "Less HP. Easier to knock down.", constant_vigilance: "New places keep you wired — short rests don't take.", }; async function loadData() { const fetchJson = async (p) => { const r = await fetch(p); if (!r.ok) throw new Error("Failed to load " + p); return r.json(); }; const [clades, species, classes, backgrounds] = await Promise.all([ fetchJson("data/clades.json"), fetchJson("data/species.json"), fetchJson("data/classes.json"), fetchJson("data/backgrounds.json"), ]); return { clades, species, classes, backgrounds }; } function abilityMod(score) { return Math.floor((score - 10) / 2); } function signed(n) { return n >= 0 ? `+${n}` : `${n}`; } window.ABILITIES = ABILITIES; window.ABILITY_LABELS = ABILITY_LABELS; window.STANDARD_ARRAY = STANDARD_ARRAY; window.SKILL_ABILITY = SKILL_ABILITY; window.SKILL_LABEL = SKILL_LABEL; window.SKILL_DESC = SKILL_DESC; window.SIZE_LABEL = SIZE_LABEL; window.CLASS_CLADE_REC = CLASS_CLADE_REC; window.ITEM_NAME = ITEM_NAME; window.LANGUAGES = LANGUAGES; window.TRAIT_READING = TRAIT_READING; window.loadData = loadData; window.abilityMod = abilityMod; window.signed = signed;