using Theriapolis.Core.Rules.Reputation; namespace Theriapolis.Core.Rules.Dialogue; /// /// Phase 6 M3 — disposition-driven shop modifiers per the plan §4.6. /// /// NEMESIS → service refused /// HOSTILE → service refused /// ANTAGONISTIC..UNFRIENDLY → +25% prices, +10% sell discount /// NEUTRAL → base prices /// FAVORABLE → -10% buy /// FRIENDLY → -20% buy /// ALLIED → -30% buy /// CHAMPION → -40% buy /// /// Phase 6 M3 ships buy-side adjustment only; sell-side is mirrored at /// 50% of the buy modifier so a friendly merchant pays a small premium /// without dual-tunable knobs. /// public static class ShopPricing { /// True if the player can shop at all given the disposition score. public static bool ServiceAvailable(int dispositionScore) { var label = DispositionLabels.For(dispositionScore); return label != DispositionLabel.Nemesis && label != DispositionLabel.Hostile; } /// /// Multiplier applied to a price the player pays. 1.0 = base; >1 = /// markup; <1 = discount. Caller multiplies the item's listed cost /// and rounds. /// public static float BuyMultiplier(int dispositionScore) { var label = DispositionLabels.For(dispositionScore); return label switch { DispositionLabel.Nemesis => 99f, // shouldn't be called; sentinel DispositionLabel.Hostile => 99f, DispositionLabel.Antagonistic => 1.25f, DispositionLabel.Unfriendly => 1.25f, DispositionLabel.Neutral => 1.00f, DispositionLabel.Favorable => 0.90f, DispositionLabel.Friendly => 0.80f, DispositionLabel.Allied => 0.70f, DispositionLabel.Champion => 0.60f, _ => 1.00f, }; } /// Multiplier applied to a price the merchant pays the player on sell-back. public static float SellMultiplier(int dispositionScore) { // Mirror buy modifier toward 1.0 by 50%: friendly buy = 0.80 → // friendly sell = 0.60 (you still take a haircut), antagonistic // buy = 1.25 → antagonistic sell = 0.30. var label = DispositionLabels.For(dispositionScore); return label switch { DispositionLabel.Antagonistic => 0.35f, DispositionLabel.Unfriendly => 0.40f, DispositionLabel.Neutral => 0.50f, DispositionLabel.Favorable => 0.55f, DispositionLabel.Friendly => 0.60f, DispositionLabel.Allied => 0.65f, DispositionLabel.Champion => 0.70f, _ => 0f, // refused at Hostile / Nemesis }; } /// Buy price for one unit (rounded up). Cost is in the item's "cost_fang" or equivalent unit. public static int BuyPriceFor(int baseCost, int dispositionScore) => System.Math.Max(1, (int)System.Math.Ceiling(baseCost * BuyMultiplier(dispositionScore))); /// Sell price for one unit (rounded down). public static int SellPriceFor(int baseCost, int dispositionScore) => System.Math.Max(0, (int)System.Math.Floor(baseCost * SellMultiplier(dispositionScore))); }