mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-16 08:52:42 +00:00
D&D: wire the Open5e magic-item registry into live gameplay
Magic items now reach players through three surfaces: zone loot drops, Luigi's "Curios" shelf, and combat effects. Effects are formulaic (Rarity scalar x Kind), mirroring the bestiary tuning pass, with an empty magicItemEffectOverlay as the hand-authored refinement path. - magic_items_gameplay.go: rarity index, magic_item_equipped persistence (new table, DnDSlot-keyed), codified effect formula, applyMagicItemEffects combat hook, potion/scroll -> ConsumableDef bridge, !adventure equip-magic - dropZoneLoot: 15% magic-item substitution roll by tier rarity - Luigi's Curios category: daily UTC-seeded 8-item rotation - combat_bridge / combat_session_build: applyMagicItemEffects after passives - consumableDefByName falls through so loot/shop potions auto-resolve - renderDnDSheet: new Magic Items section Equippable items live entirely in the DnDSlot scheme, separate from the legacy tier-gear. Attunement items equip inert until attuned (3-slot cap).
This commit is contained in:
@@ -64,11 +64,12 @@ func (p *AdventurePlugin) handleDnDSheetCmd(ctx MessageContext) error {
|
||||
treasures, _ := loadAdvTreasureBonuses(ctx.Sender)
|
||||
meta, _ := loadPlayerMeta(ctx.Sender)
|
||||
house, _ := loadHouseState(ctx.Sender)
|
||||
magicEquip, _ := loadEquippedMagicItems(ctx.Sender)
|
||||
|
||||
return p.SendDM(ctx.Sender, renderDnDSheet(c, advChar, meta, house, equip, treasures))
|
||||
return p.SendDM(ctx.Sender, renderDnDSheet(c, advChar, meta, house, equip, treasures, magicEquip))
|
||||
}
|
||||
|
||||
func renderDnDSheet(c *DnDCharacter, adv *AdventureCharacter, meta *PlayerMeta, house HouseState, equip map[EquipmentSlot]*AdvEquipment, treasures []AdvTreasureBonus) string {
|
||||
func renderDnDSheet(c *DnDCharacter, adv *AdventureCharacter, meta *PlayerMeta, house HouseState, equip map[EquipmentSlot]*AdvEquipment, treasures []AdvTreasureBonus, magicEquip map[DnDSlot]EquippedMagicItem) string {
|
||||
ri, _ := raceInfo(c.Race)
|
||||
ci, _ := classInfo(c.Class)
|
||||
mods := c.Modifiers()
|
||||
@@ -137,6 +138,29 @@ func renderDnDSheet(c *DnDCharacter, adv *AdventureCharacter, meta *PlayerMeta,
|
||||
b.WriteString(" _(none equipped)_\n")
|
||||
}
|
||||
|
||||
// Magic items — registry items worn in the D&D slots (separate from the
|
||||
// legacy tier-gear above). Attunement items show whether they're active.
|
||||
if len(magicEquip) > 0 {
|
||||
b.WriteString("\n**Magic Items**\n")
|
||||
for _, ds := range dndSlotOrder {
|
||||
e, ok := magicEquip[ds]
|
||||
if !ok || e.Item.ID == "" {
|
||||
continue
|
||||
}
|
||||
status := ""
|
||||
if e.Item.Attunement {
|
||||
if e.Attuned {
|
||||
status = " — attuned"
|
||||
} else {
|
||||
status = " — _inert (unattuned)_"
|
||||
}
|
||||
}
|
||||
b.WriteString(fmt.Sprintf(" %s %-9s %s _(%s)_%s\n %s\n",
|
||||
rarityIcon(e.Item.Rarity), string(ds), e.Item.Name, e.Item.Rarity,
|
||||
status, magicItemEffectSummary(e.Item)))
|
||||
}
|
||||
}
|
||||
|
||||
// Attunements (re-using adventure_treasures per v1.1 §7.4)
|
||||
if len(treasures) > 0 {
|
||||
b.WriteString("\n**Attunements** (treasures)\n")
|
||||
|
||||
Reference in New Issue
Block a user