mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 16:42:41 +00:00
Combines all uncommitted D&D work into one checkpoint: Phases 1-8 (per gogobee_dnd_session_summary.md): - Race/class/stats system, !setup flow, !sheet, !respec - d20-vs-AC combat with race/class passives, auto-migration - XP/level-up, skill checks, NPC refund hooks - Equipment slot mapping, rarity, !rest short/long - Pre-arm active abilities, resource pools - Bestiary, !roll/!stats/!level, onboarding DM - Audit fixes A-I, flavor wiring under internal/flavor/ - Phase 8 weapon dice + armor AC tables (gogobee_equipment_appendix) Phase 9 SP1 — spell system foundations: - 79 SpellDefinitions (76 in-scope + 3 reaction-deferred) - dnd_known_spells, dnd_spell_slots tables - pending_cast / concentration_* columns on dnd_character - Slot tables for Mage/Cleric/Ranger, DC + attack-bonus math - Long-rest refreshes slots; respec wipes spell state - Auto-grant default known list on !setup confirm and auto-migration Phase 9 SP2 — !cast / !spells / !prepare commands: - Out-of-combat HEAL and UTILITY resolve immediately - Damage/control/buff queue as pending_cast for next combat - Audit-style save-then-debit, slot refund on save failure - !cast --drop, concentration supersession, prep-cap enforcement - Reaction spells refused with Phase 11 note SP3 (combat-time resolution of pending_cast) and SP4 (full prep/learn tests) are next. Build clean, full test suite green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
53 lines
1.6 KiB
Go
53 lines
1.6 KiB
Go
package plugin
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestDnDOnboardingText_ContainsLevelMapping(t *testing.T) {
|
|
msg := dndOnboardingText(49, 9)
|
|
if !strings.Contains(msg, "**49**") {
|
|
t.Error("onboarding text doesn't include old level")
|
|
}
|
|
if !strings.Contains(msg, "**9**") {
|
|
t.Error("onboarding text doesn't include new level")
|
|
}
|
|
// Spot-check signature lines from the user's brief.
|
|
for _, snippet := range []string{
|
|
"Welcome to the new Adventure game",
|
|
"Pinkerton agent",
|
|
"dividing your previous level by five",
|
|
"!setup",
|
|
"legally distinct",
|
|
} {
|
|
if !strings.Contains(msg, snippet) {
|
|
t.Errorf("onboarding missing expected snippet: %q", snippet)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestMaybeSendDnDOnboarding_LegacyThreshold: only fires for combat_level >= 2.
|
|
// The DM call itself is no-op in tests (Base.Client is nil and SendDM guards),
|
|
// so we can't assert on send — but we can assert the function doesn't panic
|
|
// or error for either branch.
|
|
func TestMaybeSendDnDOnboarding_DoesNotPanic(t *testing.T) {
|
|
p := &AdventurePlugin{}
|
|
dnd := &DnDCharacter{Level: 4}
|
|
|
|
// Brand-new player (combat_level=1): should be a no-op.
|
|
p.maybeSendDnDOnboarding("@new:x", &AdventureCharacter{CombatLevel: 1}, dnd)
|
|
|
|
// Legacy player (combat_level=20): should attempt to send (no-op'd by nil Client).
|
|
p.maybeSendDnDOnboarding("@legacy:x", &AdventureCharacter{CombatLevel: 20}, dnd)
|
|
|
|
// nil advChar: should be a no-op.
|
|
p.maybeSendDnDOnboarding("@nil:x", nil, dnd)
|
|
}
|
|
|
|
func TestDnDLegacyMinLevel(t *testing.T) {
|
|
if dndLegacyMinLevel < 1 {
|
|
t.Errorf("dndLegacyMinLevel = %d, must be ≥ 1", dndLegacyMinLevel)
|
|
}
|
|
}
|