Add chat level perks: XP bonus, shop flavor, rare drop nudge, death pardon (Adventure 2.5 steps 3-6)

- XP bonus: +5% per 10 chat levels (cap +25% at 50+), applies to all
  adventure and arena XP
- Shop flavor: shopkeeper greeting changes at chat levels 10/30/50,
  replacing random flavor for recognized players
- Rare drop nudge: +0.5% per 10 chat levels (cap +2.5%) applied
  additively to treasure and masterwork drop rates
- Death pardon: chat level 20+ gets 33% chance to survive death once
  per 7 days (converts to bad-failure, quiet DM). Does not apply in
  arena. Fires before Sovereign Death's Reprieve check.
- New adventure_chat_perks.go with perk calculation helpers
- LastPardonUsed field + migration on adventure_characters

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
prosolis
2026-04-08 15:50:28 -07:00
parent a44a9d9234
commit 68b2f8b7a5
9 changed files with 120 additions and 31 deletions

View File

@@ -0,0 +1,38 @@
package plugin
// ── Chat Level Perks ────────────────────────────────────────────────────────
// Passive bonuses based on community chat level. All perks are automatic.
// chatLevelXPBonus returns the fractional XP bonus for the given chat level.
// +5% per 10 levels, capped at +25% at level 50+.
func chatLevelXPBonus(chatLevel int) float64 {
tier := chatLevel / 10
if tier > 5 {
tier = 5
}
return float64(tier) * 0.05
}
// chatLevelRareBonus returns the additive rare drop rate bonus.
// +0.5% per 10 levels, capped at +2.5% at level 50+.
func chatLevelRareBonus(chatLevel int) float64 {
tier := chatLevel / 10
if tier > 5 {
tier = 5
}
return float64(tier) * 0.005
}
// shopGreeting returns the shopkeeper's greeting based on chat level.
func shopGreeting(chatLevel int) string {
switch {
case chatLevel >= 50:
return "I saw you coming from down the street. Your usual is already on the counter. The shop is open."
case chatLevel >= 30:
return "Back again. I've started keeping your usual in the back. The shop is open."
case chatLevel >= 10:
return "Ah. You again. The shop is open."
default:
return "The shop is open. What do you need?"
}
}