mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 16:42:41 +00:00
Fix arena gear lockout, extend DM window, scrub mining flavor
Arena helmet auto-equip now preserves the existing helmet to inventory
(or stashes the new drop if the existing piece is strictly higher tier),
and arena gear can be re-equipped via !adventure equip. Shop only blocks
swaps that aren't an upgrade over current arena tier. DM response window
bumped from 15m to 3h so NPC/treasure/shop prompts don't expire while
players are AFK. MiningSuccess flavor pools no longer name specific ores
in prose — uses {ore}/{location}/{tool} placeholders so the narration
matches the actual loot.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -333,16 +333,16 @@ func (p *AdventurePlugin) handleEquipCmd(ctx MessageContext) error {
|
||||
return p.SendDM(ctx.Sender, "Failed to load inventory.")
|
||||
}
|
||||
|
||||
// Filter to masterwork items only
|
||||
// Filter to special gear (Masterwork + Arena) items only
|
||||
var mwItems []AdvItem
|
||||
for _, it := range items {
|
||||
if it.Type == "MasterworkGear" {
|
||||
if it.Type == "MasterworkGear" || it.Type == "ArenaGear" {
|
||||
mwItems = append(mwItems, it)
|
||||
}
|
||||
}
|
||||
|
||||
if len(mwItems) == 0 {
|
||||
return p.SendDM(ctx.Sender, "You have no Masterwork gear waiting to be equipped. Go find some.")
|
||||
return p.SendDM(ctx.Sender, "You have no special gear waiting to be equipped. Go find some.")
|
||||
}
|
||||
|
||||
equip, err := loadAdvEquipment(ctx.Sender)
|
||||
@@ -352,7 +352,7 @@ func (p *AdventurePlugin) handleEquipCmd(ctx MessageContext) error {
|
||||
|
||||
// Build listing
|
||||
var sb strings.Builder
|
||||
sb.WriteString("⭐ **Your unequipped Masterwork gear:**\n\n")
|
||||
sb.WriteString("⭐ **Your unequipped special gear:**\n\n")
|
||||
|
||||
for i, it := range mwItems {
|
||||
current := equip[it.Slot]
|
||||
@@ -366,8 +366,12 @@ func (p *AdventurePlugin) handleEquipCmd(ctx MessageContext) error {
|
||||
}
|
||||
currentDesc = fmt.Sprintf("%s (%s)", current.Name, tag)
|
||||
}
|
||||
sb.WriteString(fmt.Sprintf("%d. %s (T%d %s) — currently: %s\n",
|
||||
i+1, it.Name, it.Tier, slotTitle(it.Slot), currentDesc))
|
||||
marker := "⭐"
|
||||
if it.Type == "ArenaGear" {
|
||||
marker = "⚔️"
|
||||
}
|
||||
sb.WriteString(fmt.Sprintf("%d. %s %s (T%d %s) — currently: %s\n",
|
||||
i+1, marker, it.Name, it.Tier, slotTitle(it.Slot), currentDesc))
|
||||
}
|
||||
|
||||
sb.WriteString("\nReply with a number to equip, or \"cancel\".")
|
||||
@@ -375,7 +379,7 @@ func (p *AdventurePlugin) handleEquipCmd(ctx MessageContext) error {
|
||||
p.pending.Store(string(ctx.Sender), &advPendingInteraction{
|
||||
Type: "masterwork_equip",
|
||||
Data: &advPendingMasterworkEquip{Items: mwItems},
|
||||
ExpiresAt: time.Now().Add(5 * time.Minute),
|
||||
ExpiresAt: time.Now().Add(advDMResponseWindow),
|
||||
})
|
||||
|
||||
return p.SendDM(ctx.Sender, sb.String())
|
||||
@@ -430,17 +434,22 @@ func (p *AdventurePlugin) handleMasterworkEquipReply(ctx MessageContext, interac
|
||||
p.pending.Store(string(ctx.Sender), &advPendingInteraction{
|
||||
Type: "masterwork_equip_confirm",
|
||||
Data: &advPendingMasterworkConfirm{Item: selected},
|
||||
ExpiresAt: time.Now().Add(5 * time.Minute),
|
||||
ExpiresAt: time.Now().Add(advDMResponseWindow),
|
||||
})
|
||||
|
||||
def := masterworkDefFor(slotToActivity(selected.Slot), selected.Tier)
|
||||
bonusDesc := ""
|
||||
if def != nil {
|
||||
bonusDesc = fmt.Sprintf("\n%s gives 1.25x %s effectiveness and +5%% %s success.\n", selected.Name, slotTitle(selected.Slot), def.SkillSource)
|
||||
marker := "⭐"
|
||||
if selected.Type == "ArenaGear" {
|
||||
marker = "⚔️"
|
||||
} else {
|
||||
def := masterworkDefFor(slotToActivity(selected.Slot), selected.Tier)
|
||||
if def != nil {
|
||||
bonusDesc = fmt.Sprintf("\n%s gives 1.25x %s effectiveness and +5%% %s success.\n", selected.Name, slotTitle(selected.Slot), def.SkillSource)
|
||||
}
|
||||
}
|
||||
|
||||
return p.SendDM(ctx.Sender, fmt.Sprintf("Equip **%s** (T%d ⭐ %s)?%s\nThis replaces your %s. The old item goes to inventory.%s\nReply \"yes\" to confirm.",
|
||||
selected.Name, selected.Tier, slotTitle(selected.Slot), warning, currentName, bonusDesc))
|
||||
return p.SendDM(ctx.Sender, fmt.Sprintf("Equip **%s** (T%d %s %s)?%s\nThis replaces your %s. The old item goes to inventory.%s\nReply \"yes\" to confirm.",
|
||||
selected.Name, selected.Tier, marker, slotTitle(selected.Slot), warning, currentName, bonusDesc))
|
||||
}
|
||||
|
||||
func (p *AdventurePlugin) handleMasterworkEquipConfirm(ctx MessageContext, interaction *advPendingInteraction) error {
|
||||
@@ -488,10 +497,21 @@ func (p *AdventurePlugin) handleMasterworkEquipConfirm(ctx MessageContext, inter
|
||||
eq.Condition = 100
|
||||
eq.Name = selected.Name
|
||||
eq.ActionsUsed = 0
|
||||
eq.ArenaTier = 0
|
||||
eq.ArenaSet = ""
|
||||
eq.Masterwork = true
|
||||
eq.SkillSource = selected.SkillSource
|
||||
|
||||
if selected.Type == "ArenaGear" {
|
||||
eq.Masterwork = false
|
||||
eq.SkillSource = ""
|
||||
eq.ArenaTier = selected.Tier
|
||||
eq.ArenaSet = ""
|
||||
if gs := arenaGearByName(selected.Name); gs != nil {
|
||||
eq.ArenaSet = gs.SetKey
|
||||
}
|
||||
} else {
|
||||
eq.ArenaTier = 0
|
||||
eq.ArenaSet = ""
|
||||
eq.Masterwork = true
|
||||
eq.SkillSource = selected.SkillSource
|
||||
}
|
||||
|
||||
if err := saveAdvEquipment(ctx.Sender, eq); err != nil {
|
||||
return p.SendDM(ctx.Sender, "Failed to save equipment. Try again.")
|
||||
@@ -502,7 +522,11 @@ func (p *AdventurePlugin) handleMasterworkEquipConfirm(ctx MessageContext, inter
|
||||
slog.Error("adventure: failed to remove equipped item from inventory", "user", ctx.Sender, "err", err)
|
||||
}
|
||||
|
||||
return p.SendDM(ctx.Sender, fmt.Sprintf("**%s** equipped. ⭐ Masterwork %s, Tier %d.", selected.Name, slotTitle(selected.Slot), selected.Tier))
|
||||
kind := "⭐ Masterwork"
|
||||
if selected.Type == "ArenaGear" {
|
||||
kind = "⚔️ Arena"
|
||||
}
|
||||
return p.SendDM(ctx.Sender, fmt.Sprintf("**%s** equipped. %s %s, Tier %d.", selected.Name, kind, slotTitle(selected.Slot), selected.Tier))
|
||||
}
|
||||
|
||||
// slotToActivity converts an EquipmentSlot to the activity that drops masterwork for it.
|
||||
|
||||
Reference in New Issue
Block a user