Files
gogobee/gogobee_dnd_design_doc_v1.1.md
prosolis 9e1a1f606c Adv 2.0 D&D layer: Phases 1-8 + Phase 9 SP1+SP2
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>
2026-05-09 14:25:21 -07:00

22 KiB
Raw Blame History

GogoBee — D&D Integration Design Document (v1.1, annotated)

Version: 1.1 — integration revision Status: Draft, supersedes v1.0 for implementation purposes Predecessor: gogobee_dnd_design_doc.md (v1.0) — kept as the vision document Scope: Same as v1.0, reconciled against the existing internal/plugin/adventure_*.go and internal/db/db.go codebase See also: gogobee_equipment_appendix.md


⚠️ Protected Files — DO NOT MODIFY

Unchanged from v1.0. All *_flavor.go / *_flavor.txt files, files containing the DO NOT REWRITE header, and NPC spec files (Thom Krooke, Misty, Arina) are immutable. New D&D flavor lives in new files (dnd_flavor_*.go), never as edits to existing flavor.


0. Why v1.1 exists

v1.0 was written without auditing the live adventure system. A literal implementation would destroy working features and player progress. This revision:

  1. Treats the existing adventure systems as ground truth. The D&D layer is additive, not a replacement. adventure_characters and friends keep their columns and semantics; D&D adds nullable columns and new tables alongside.
  2. Preserves all player progress. Every column in adventure_characters, adventure_equipment, adventure_inventory, adventure_treasures, adventure_buffs, user_archetypes, arena_stats, adventure_rival_records, adventure_babysit_log, holdem_scores, euro_balances, etc. is preserved unchanged. Migrations are column-adds with defaults only — no drops, no renames.
  3. Gates D&D content on opt-in. A pending_setup flag means non-opted-in players continue with the current adventure system unchanged. D&D-flavored output (!sheet, combat resolution narration) is only shown to players who have completed !setup.
  4. Re-uses what already exists rather than reinventing it: combat_level becomes D&D level, adventure_treasures becomes the attunement substrate, adventure_equipment slots map forward, user_archetypes drives class/race inference (already designed for this).

Wherever this revision diverges from v1.0, the divergence is annotated with [REVISED] and a one-line rationale.


1. Overview & Goals

Unchanged from v1.0 except for one added principle:

  • Layered, not replaced. D&D mechanics sit on top of the existing adventure systems. The world layer (skills, encounters, loot, babysit, rivals, housing) keeps running; the character layer (race/class/HP/AC/abilities) is a new lens over it.

2. Existing System Inventory — actual state

[REVISED — v1.0's table was aspirational. This is what's actually in internal/db/db.go and internal/plugin/:]

2.1 Player tables (preserve every column)

Table Key columns Status
adventure_characters user_id (PK), display_name, combat_level, combat_xp, mining_skill/mining_xp, foraging_skill/foraging_xp, fishing_skill/fishing_xp, alive, dead_until, action_taken_today, holiday_action_taken, current_streak, best_streak, arena_wins, arena_losses, invasion_score, pet_*, house_*, babysit_*, auto_babysit, misty_buff_expires, misty_debuff_expires, arina_buff_expires Preserve all. D&D columns added nullable.
adventure_equipment (user_id, slot) PK, tier, condition, name, actions_used, masterwork, skill_source Preserve. Add nullable D&D columns: rarity, stat_bonus_json, attuned.
adventure_inventory id (PK), user_id, name, item_type, tier, value, slot, skill_source Preserve. Add nullable rarity, stat_bonus_json.
adventure_treasures (user_id, treasure_key, bonus_type) UNIQUE, bonus_value (REAL) Preserve and re-use as attunement substrate (Section 7.3).
adventure_buffs user_id, buff_type, buff_name, modifier, expires_at Preserve. Used for D&D conditions.
user_archetypes (user_id, archetype) PK, category, signal_score, flavor, assigned_at Preserve. Drives migration inference (Section 11).
arena_runs, arena_history, arena_stats streaks, win/loss, history Preserve. Combat resolution swaps under the hood; records stay.
adventure_rival_challenges, adventure_rival_records challenge state, head-to-head records Preserve. RPS resolver replaced; tables untouched.
adventure_babysit_log activity, outcome, gold, XP, items_dropped per day Preserve. Babysit stays independent.
euro_balances coin balance Preserve. Coins are euros; no separate D&D gold.
hangman_scores, blackjack_scores, holdem_scores per-game scores Preserve. Independent of D&D layer.

2.2 New tables for D&D layer

Table Purpose
dnd_character Per-player D&D state: race, class, hp_current, hp_max, temp_hp, ac, str/dex/con/int/wis/cha, dnd_level, pending_setup, created_at, updated_at. One row per player after !setup; absent before.
dnd_abilities (user_id, ability_id) — known abilities and uses-remaining of the relevant resource.
dnd_resources (user_id, resource_type) — current Stamina/Focus/Mana/DivineFavor; reset on rest.
dnd_combat_state Active combat encounter (round, turn, conditions JSON, log JSON). Cleared on combat end.
adventure_characters_pre_dnd One-shot mirror of adventure_characters taken at deploy time. Rollback safety net.

2.3 Things that don't yet exist anywhere

  • HP, AC, ability scores, conditions in any persistent form
  • Initiative, attack rolls, saving throws — current arena/rival are RPS or level-comparison
  • Global player XP separate from skill XP

These are genuinely new and require fresh implementation; everything else is layering.


3. Character System

3.1 Races, 3.2 Classes, 3.3 Ability Scores

Tables unchanged from v1.0. The race/class tables and stat-modifier formula stand.

[REVISED] Class ↔ archetype inference is now keyed to the real archetype names from archetype.go, not the abstract categories in v1.0:

Archetype (real) Suggested Class Suggested Race
Arena Champion / Dungeon Crawler Fighter Orc / Human
The Merchant / Whale Rogue Halfling / Human
Novelist / Philosopher / Wordsmith / Linkmaster Mage Elf / Tiefling
Cheerleader / Hype Machine / Patron / Reactor Cleric Dwarf / Half-Elf
The Angler / The Forager / The Adventurer Ranger Human / Elf
Fallback (Regular, Wildcard, no clear signal) Human Fighter (presented as suggestion only)

When a player has multiple archetypes, the highest signal_score wins. Ties broken by archetype priority list defined in code.

3.4 Go data model

[REVISED] Drop the v1.0 CharacterSheet struct in favor of a model that mirrors the actual table layout and keeps adventure_characters as the source of truth for everything that already exists there.

// DnDCharacter is the new persistent layer. Joined with adventure_characters at read time.
type DnDCharacter struct {
    UserID       string
    Race         Race
    Class        Class
    DnDLevel     int       // derived from combat_level at migration; advances independently after
    HP           HPBlock
    AC           int
    Stats        BaseStats // STR/DEX/CON/INT/WIS/CHA
    PendingSetup bool      // true until !setup completes
    CreatedAt    time.Time
    UpdatedAt    time.Time
}

// CharacterView is a read-only join used by !sheet and combat.
// Always construct via repository.LoadCharacterView(userID) — never instantiate directly.
type CharacterView struct {
    Adv  AdventureCharacter // existing struct from adventure_character.go
    DnD  *DnDCharacter      // nil when player hasn't run !setup
    Eq   []EquipmentRow     // existing
    Inv  []InventoryRow     // existing
    Treas []TreasureRow     // existing — surfaces as attunements when DnD != nil
}

Race, Class, BaseStats, HPBlock constants and types follow v1.0 exactly.


4. Leveling System

[REVISED — this is the largest change from v1.0.]

v1.0 specifies a fresh XP curve (300, 900, 2700…) with no relationship to existing skill XP. That throws away hours of player progress. Instead:

4.1 Initial mapping (one-time, at !setup completion)

dnd_level = max(1, combat_level)         // direct adoption — combat_level is literally a combat level
xp_carryover = 0                         // dnd has its own XP track going forward

Skill levels (mining/foraging/fishing) and their XP pools are untouched. They keep advancing on their own from gathering activities.

4.2 New XP sources for D&D level

D&D level advances from:

  • Combat encounters (arena wins, rival duels, monster kills) — primary source
  • Quest/event completions
  • NPC skill-check successes (small amounts)

Not from gathering. Mining XP keeps going to mining; that channel is unchanged.

4.3 XP curve from level N onward

The cumulative table from v1.0 (L2=300, L3=900, L5=2700, L10=14000, L20=85000) applies, but as XP earned past initial level, not from zero. A player migrated in at combat_level=8 starts D&D Level 8 with 0/required-for-9 XP.

4.4 Level-up flow

Same as v1.0 (5 steps, including stat point allocation and subclass prompt at L5). Level-up flavor must be class-specific and lives in a new dnd_flavor_levelup.go (new file, not editing existing flavor).


5. Combat Engine — staged rollout

[REVISED] v1.0 specifies the full D&D combat flow as if combat were greenfield. It isn't — arena and rival have semantics today, plus history. Stage the rollout:

5.1 Stage A — Arena conversion (do first)

  • Replace the level-comparison + 50/50 winner logic with full D&D resolution (initiative → attack rolls vs. AC → damage → conditions).
  • Preserve: arena_stats, arena_history, current_streak, best_streak, arena_wins, arena_losses rows. New combat writes to the same tables.
  • Streak bonuses (+5%/3-streak, etc.) become combat modifiers in the new resolver.
  • Non-opted-in players (no dnd_character row) still hit the legacy resolver. The arena gracefully runs both.

5.2 Stage B — Rival conversion (do second)

  • Replace RPS in adventure_rival.go with D&D combat.
  • adventure_rival_records and adventure_rival_challenges schemas unchanged. New resolver writes the same rows.
  • Stake calculation ((combatLevel/5)*1000 euros) preserved.

5.3 Stage C — Encounter combat (new)

  • New monsters / dungeon encounters use D&D combat from day one. No legacy path.

5.4 Combat resolution flow, AC, conditions, data model

Sections 5.1, 5.2, 5.3, 5.4 of v1.0 stand as the spec for how combat works. Apply at the resolver layer; persist via dnd_combat_state (new table).


6. Abilities & Spells

Unchanged from v1.0. Resources persist in dnd_resources (new table). Reset triggered by !rest short/!rest long (Section 10 below — note the rename).


7. Equipment & Item System

7.1, 7.2 Rarity & Slots

Tables stand from v1.0.

7.3 Slot mapping — additive, not replacement

[REVISED] Existing adventure_equipment has 5 slots. Map them forward instead of orphaning gear:

Existing slot D&D slot
weapon main_hand
armor chest
helmet head
boots feet
tool off_hand (or hands, by item type)

Old gear keeps tier, condition, masterwork. Inferred rarity is computed from tier at migration (e.g., tier 1-2 → Common, 3-4 → Uncommon, 5-6 → Rare, 7+ → Epic). New rarity column is nullable; legacy items render fine without it.

D&D adds the new slots (legs, hands if not already mapped, ring_1, ring_2, amulet) — these start empty for migrated players.

7.4 Attunement = adventure_treasures

[REVISED] v1.0 invents a parallel attunement system. Don't. adventure_treasures already encodes named bonuses with stat modifiers per player — that's exactly an attunement record.

  • The 3-item attunement cap = a row-count constraint on adventure_treasures per user_id.
  • bonus_type and bonus_value (REAL) feed directly into stat resolution.
  • New magic items granted post-D&D-launch insert rows into the same table.
  • Legacy treasures are automatically "attuned" — no migration step required.

7.5 Go data model

Use a thin wrapper that joins adventure_equipment + adventure_inventory + adventure_treasures at read time. Don't introduce a new Inventory/EquipmentSlots struct that duplicates state.


8. Monster Bestiary

Unchanged from v1.0. New tables, new flavor file (dnd_flavor_monsters.go).


9. Skill Check System

Unchanged from v1.0. NPC wiring (Thom Krooke / Misty / Arina) is purely new logic; no schema change.

One nuance: the existing Misty/Arina buff/debuff timestamp columns (misty_buff_expires, misty_debuff_expires, arina_buff_expires) stay as-is and become the persistence layer for skill-check-granted buffs. Don't add parallel buff tracking.


10. Rest System — naming collision resolved

[REVISED]

!adventure rest already exists as a daily-action narrative activity. It's not the same thing as a D&D short/long rest.

Rename and split:

  • !adventure camp — what !adventure rest is today. Daily-action narrative day-skip. (Old command remains as an alias for one release for backwards compat.)
  • !rest short — D&D short rest. No daily-action cost. 1-hour cooldown. Recovers 1d6+CON HP; resets short-rest resources (Fighter Stamina, Rogue/Ranger Focus).
  • !rest long — D&D long rest. Requires housing or paid inn use (Thom Krooke). 24-hour cooldown. Full reset.

Babysit interaction: babysitting is independent of rest. A player on auto-babysit can still !rest short. !rest long while babysitting is allowed and does not interrupt the babysit log.


11. Player Onboarding & Migration

11.1 New user flow

Unchanged from v1.0. A new player runs !setup and gets the 4-step race/class/stats/welcome flow. This creates their adventure_characters row (if absent) and their dnd_character row in one transaction.

11.2 Existing user migration

[REVISED] Migration is opt-in via pending_setup. No data is mutated until the player runs !setup.

At deploy:

  1. Snapshot adventure_charactersadventure_characters_pre_dnd (rollback safety).
  2. No row changes. No dnd_character rows created. Every existing player is implicitly pending_setup = true because the row simply doesn't exist yet.
  3. Bot DMs each active player once with the v1.0 migration message (suggested race/class from archetype, "Yes / No, let me choose / Skip for now"). Reminder cadence per v1.0 (every 7 days, auto-assign at 30 days).

While pending_setup is true:

  • All existing !adventure ... commands work exactly as before.
  • D&D-only commands (!sheet, !stats, !use, !rest short/long, !check) prompt for setup.
  • Arena/rival use the legacy resolver.

After !setup:

  • dnd_character row is created.
  • dnd_level = combat_level (Section 4.1).
  • HP_max computed from class HP die + CON modifier × level. Current HP set to max.
  • AC computed from equipped armor + DEX. (Old armor maps via Section 7.3.)
  • Arena/rival flip to D&D resolver for this user.

11.3 Auto-assign

After 30 days pending_setup and at least one prior interaction, auto-create dnd_character using inferred race/class from archetype. Player notified once: "We started a sheet for you — !setup to change it."

11.4 Data preservation guarantees

Existing data Guarantee
euro_balances Untouched. Coins do not convert.
Skill levels & XP (mining_*, foraging_*, fishing_*) Untouched. Skill grind continues independently.
combat_level Read once at !setup to seed dnd_level. After that, both fields exist and advance independently (combat_level keeps incrementing on legacy paths if any remain; dnd_level is the canonical character level for D&D).
combat_xp Untouched. Used as legacy display.
Pets (pet_*) Untouched. Ranger gets passive bonus on top.
arena_wins/losses/current_streak/best_streak Untouched. New combats append to the same counters.
adventure_inventory Untouched. Items render with inferred rarity until D&D fields populated by new drops.
adventure_equipment Untouched. Slot mapping is read-time, not a migration.
adventure_treasures Untouched. Becomes attunement display source.
adventure_buffs Untouched. Used for new condition tracking too.
user_archetypes Untouched. Drives inference; retained for flavor post-setup.
house_tier, house_loan_* Untouched. Drives long-rest eligibility.
adventure_babysit_log and babysit fields Untouched. Babysit independent of D&D.
holdem_scores, hangman_scores, blackjack_scores Untouched. Out of D&D scope entirely.

Rollback plan: drop the new D&D tables and the nullable D&D columns. adventure_characters_pre_dnd is the integrity check that nothing was clobbered. If anything in adventure_characters differs from the pre-DnD snapshot at rollback time, that's a bug — restore the affected rows from the snapshot.


12. Cross-System Integration

Substantively unchanged from v1.0, with these additions:

  • Babysit is independent of D&D. Stays as-is.
  • Forex / lottery / coop dungeon / holdem are out of D&D scope and unchanged.
  • Skill XP from gathering does not feed D&D level. Two distinct progression tracks (skill grind vs. D&D character level) coexist.

13. Commands Reference

v1.0's table stands, with these additions/clarifications:

Command Note
!adventure camp Renamed from !adventure rest. Old name kept as alias for one release.
!rest short / !rest long New D&D rests, gated on dnd_character existing.
!equip <item> Subsumes !adventure equip. Routes to legacy masterwork-equip path when item is masterwork; otherwise D&D equip.
!inventory Extends !adventure inventory with rarity/attunement display. Legacy !adventure inventory continues to work.
!sheet, !stats, !level, !abilities, !use, !check, !roll, !respec, !attune, !unequip, !setup All new, no current implementation.

14. Implementation Phases — revised

[REVISED — replaces v1.0 Section 14 in full.]

Phase 1 — Layering proof (smallest viable change)

Goal: prove D&D layers cleanly on existing data without changing any behavior for existing players.

  • Schema: add dnd_character, dnd_abilities, dnd_resources, dnd_combat_state tables. Add nullable D&D columns to adventure_equipment / adventure_inventory.
  • One-shot snapshot adventure_characters_pre_dnd at deploy.
  • combat_level → D&D level mapping function (read-only).
  • !setup flow (4-step) with archetype inference.
  • !sheet rendering — read-only join over existing data + dnd_character. No behavior change.
  • pending_setup gating on D&D-only commands.

Exit criteria: opted-in player sees correct !sheet. Non-opted-in player notices nothing different.

Phase 2 — Combat engine + arena conversion (Stage A)

  • Initiative, attack rolls vs. AC, crit/fumble, damage, conditions, saving throws.
  • HP/AC computation on !setup and on level-up.
  • Arena resolver swap for opted-in players. Legacy resolver kept for non-opted-in.
  • dnd_combat_state persistence and combat log.

Phase 3 — Abilities, resources, leveling

  • XP tracking (D&D-level XP separate from skill XP).
  • Level-up flow with class-specific flavor (new dnd_flavor_levelup.go).
  • Starter abilities per class.
  • !use, !abilities commands.
  • Resource tracking and short/long rest reset.

Phase 4 — Equipment expansion + attunement re-use

  • Equipment slot mapping (Section 7.3).
  • Rarity inference for legacy gear at read time.
  • adventure_treasures-as-attunement (Section 7.4).
  • !equip, !unequip, !attune, !inventory subsuming legacy commands.
  • Thom Krooke shop additions (Common/Uncommon equipment, potions).

Phase 5 — Skill checks + NPC integration

  • Skill check resolver, DC table.
  • Wire Thom Krooke (Persuasion), Misty (Insight), Arina (Arcana) using existing buff timestamp columns.
  • !check command.

Phase 6 — Rest system

  • !rest short / !rest long with housing gating.
  • Inn cost at Thom Krooke.
  • Rename !adventure rest!adventure camp with alias.

Phase 7 — Monsters, rival conversion (Stage B), encounter combat (Stage C)

  • Starter bestiary (Section 8.2 minimum) in new files.
  • Rival RPS → D&D combat swap.
  • Encounter-driven combat for new content.
  • Cross-system polish (Ranger pet/fishing bonuses on top of existing bonuses).

15. Configuration Constants

Unchanged from v1.0. Add:

const (
    DnDLevelFromCombatLevel = true // initial mapping at !setup
    PendingSetupReminderDays = 7
    PendingSetupAutoAssignDays = 30
    LegacyArenaResolverEnabled = true // until 100% of active players opted in
)

16. Out of Scope

Same as v1.0. Plus:

  • Forex, lottery, coop dungeon, holdem, blackjack, hangman, tarot, uno — stay out of D&D.
  • Skill grind XP feeding D&D level — explicitly rejected. Two tracks.
  • Coin → gold conversion — euros stay euros.

17. Open questions (must be resolved before Phase 1 ships)

  1. Stat generation method at !setup: point-buy (27 points, standard array) or 4d6-drop-lowest? (v1.0 left TBD.)
  2. Respec cost / cooldown. (v1.0 TBD.)
  3. Inn cost for long rest at Thom Krooke. (v1.0 TBD.)
  4. combat_level post-setup: does it keep advancing on legacy paths, or freeze at setup time and only dnd_level moves forward? Recommend freeze.
  5. Subclass content for L5 prompt. v1.0 defers; need at least placeholder choices to not block the level-up flow.

End of v1.1. Differences from v1.0 are tagged [REVISED]. Where this document is silent, v1.0 is authoritative. Where they conflict, v1.1 wins for implementation purposes.