mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-21 03:12:41 +00:00
adventure: ask 7 — apply web equipment management (poll half)
Mirror of Pete's ask 7. gogobee polls the equip queue and applies the new
actions against the five standard gear slots:
- equip: routes MasterworkGear/ArenaGear to applyMasterworkEquip (evicts
any special occupant back to the pack; downgrade-blocked), else the
existing applyMagicEquip.
- unequip: EquipmentSlot vocabulary -> applyMasterworkUnequip (resets the
slot to its tier-0 default, keeps the row), else applyMagicUnequip.
- upgrade: purchaseEquipmentTier, euro-idempotent (DebitIdem keyed on the
order GUID), downgrade + max-tier guarded.
- repair: repair(), euro-idempotent, recomputes blacksmithRepairCost.
Detail push now carries Slots (EquipSlotView x5) + Balance; itemViews gives
masterwork/arena backpack rows an equip id; the compare decorator is guarded
to magic-only. buildDetailSnapshot is a method so it can read the euro balance.
Retry-safety: no CreditIdem refund on a later save fault (would double-pay a
guid-guarded retry) — we return retry=true and let the next poll re-run, since
the debit is guid-idempotent and the slot write is idempotent. Matches the
casino escrow precedent. Unit tests cover downgrade block, max-tier,
insufficient funds, idempotent replay, eviction, and take-off reset.
Deploy AFTER Pete: Pete's ingest must accept the new verdict strings before
this side emits them.
This commit is contained in:
@@ -142,6 +142,21 @@ func (p *AdventurePlugin) applyEquipOrder(owner id.UserID, order peteclient.Equi
|
||||
// a different item — this is a clean miss, not a wrong hit.
|
||||
return "rejected_not_owned", "That item wasn't in your pack anymore.", false
|
||||
}
|
||||
// Masterwork/arena pieces equip into a standard slot; everything else takes
|
||||
// the magic-item path. Type alone routes it — the id resolved the same row.
|
||||
if it.Type == "MasterworkGear" || it.Type == "ArenaGear" {
|
||||
out, err := applyMasterworkEquip(owner, it)
|
||||
if errors.Is(err, errItemNotEquippable) {
|
||||
return "rejected_not_equippable", "That item can't be worn.", false
|
||||
}
|
||||
if errors.Is(err, errEquipDowngrade) {
|
||||
return "rejected_downgrade", "That isn't an upgrade over what you're wearing.", false
|
||||
}
|
||||
if err != nil {
|
||||
return "", "", true // transient DB fault
|
||||
}
|
||||
return "applied", masterworkEquipDetail(out), false
|
||||
}
|
||||
out, err := applyMagicEquip(owner, it)
|
||||
if errors.Is(err, errItemNotEquippable) {
|
||||
return "rejected_not_equippable", "That item can't be worn.", false
|
||||
@@ -152,6 +167,19 @@ func (p *AdventurePlugin) applyEquipOrder(owner id.UserID, order peteclient.Equi
|
||||
return "applied", equipAppliedDetail(out), false
|
||||
|
||||
case "unequip":
|
||||
// A standard slot (weapon/armor/…) takes a masterwork/arena piece off; a DnD
|
||||
// slot takes a magic item off. The vocabularies are disjoint, so the slot
|
||||
// string alone tells the two apart.
|
||||
if isEquipmentSlot(order.Slot) {
|
||||
out, err := applyMasterworkUnequip(owner, EquipmentSlot(order.Slot))
|
||||
if errors.Is(err, errSlotEmpty) {
|
||||
return "rejected_not_worn", "There was nothing to take off there.", false
|
||||
}
|
||||
if err != nil {
|
||||
return "", "", true
|
||||
}
|
||||
return "applied", fmt.Sprintf("Took %s off, back in your pack.", out.Name), false
|
||||
}
|
||||
out, err := applyMagicUnequip(owner, DnDSlot(order.Slot))
|
||||
if errors.Is(err, errSlotEmpty) {
|
||||
return "rejected_not_worn", "That slot was already empty.", false
|
||||
@@ -165,6 +193,12 @@ func (p *AdventurePlugin) applyEquipOrder(owner id.UserID, order peteclient.Equi
|
||||
}
|
||||
return "applied", note, false
|
||||
|
||||
case "upgrade":
|
||||
return p.purchaseEquipmentTier(owner, EquipmentSlot(order.Slot), order.Tier, order.GUID)
|
||||
|
||||
case "repair":
|
||||
return p.repairSlot(owner, EquipmentSlot(order.Slot), order.GUID)
|
||||
|
||||
default:
|
||||
// Pete validates the action before it ever queues an order, so this is a
|
||||
// contract breach, not a user mistake. Reject permanently rather than spin.
|
||||
|
||||
Reference in New Issue
Block a user