namespace Theriapolis.Core.Rules.Character; /// /// Phase 6.5 M4 — universal Hybrid detriments, applied automatically to /// every -bearing character per /// theriapolis-rpg-clades.md HYBRID ORIGIN section. /// /// The four detriments are *invariant rules*, not authored content — /// they don't vary per hybrid character — so they ship as code constants /// rather than a JSON content block. (Plan §3.1's "HybridDetrimentsDef /// loader" is documented as deviation: code constants are simpler and /// match the design's universality.) /// /// 1. — WIS save DC 10 imposed on the /// first NPC interaction; failure → disadvantage on first CHA check. /// 2. — disadvantage on /// nonverbal CHA checks with purebred NPCs. /// 3. — -2 to first CHA check /// with strangers in non-progressive settlements. /// 4. — healing from /// potions / Field Repair / Lay on Paws scaled by 0.75. /// public static class HybridDetriments { /// WIS save DC for Scent Dysphoria detection check. public const int ScentDysphoriaSaveDc = 10; /// Magnitude of the Social Stigma first-CHA-check penalty (negative). public const int SocialStigmaFirstCheckPenalty = -2; /// /// Multiplier applied to healing received by a hybrid character. /// 0.75 = three-quarters effective per clades.md; round down. /// public const float MedicalIncompatibilityMultiplier = 0.75f; /// True if Illegible Body Language imposes disadvantage on the given check. public static bool IllegibleBodyLanguagePenalty => true; /// /// Apply the Medical Incompatibility multiplier to a heal amount when /// the recipient is a hybrid PC. Round down per clades.md. /// Non-hybrid recipients pass through unchanged. /// public static int ScaleHealForHybrid(Character recipient, int rawHeal) { if (recipient.Hybrid is null) return rawHeal; if (rawHeal <= 0) return rawHeal; // Round down — clades.md says "function at 75% effectiveness (round // down)". (int)(0.75 * 7) = 5; (int)(0.75 * 1) = 0 → clamp to 1 // because "no heal" is mechanically harsher than "small heal". int scaled = (int)(rawHeal * MedicalIncompatibilityMultiplier); return System.Math.Max(1, scaled); } }