diff options
Diffstat (limited to 'internal/game/cmd_bank.go')
| -rw-r--r-- | internal/game/cmd_bank.go | 76 |
1 files changed, 47 insertions, 29 deletions
diff --git a/internal/game/cmd_bank.go b/internal/game/cmd_bank.go index 3c4cac3..86057cc 100644 --- a/internal/game/cmd_bank.go +++ b/internal/game/cmd_bank.go @@ -78,6 +78,7 @@ func (g *Game) showBankBrowse(sess *net.Session) { type bankEntry struct { slot int + pos int name string id string qty int @@ -94,7 +95,10 @@ func (g *Game) showBankBrowse(sess *net.Session) { if def != nil { itemName = def.Name } - entries = append(entries, bankEntry{slot: i, name: itemName, id: slot.ItemID, qty: slot.Quantity}) + // pos is the 1-based display position; it is also the number the + // withdraw command accepts, so gaps in bank slot numbering can no + // longer make a displayed number select the wrong item. + entries = append(entries, bankEntry{slot: i, pos: len(entries) + 1, name: itemName, id: slot.ItemID, qty: slot.Quantity}) } if len(entries) == 0 && p.BankedCredits <= 0 { @@ -109,7 +113,7 @@ func (g *Game) showBankBrowse(sess *net.Session) { for _, e := range entries { def, _ := g.ItemStore.Load(e.id) t.Rows = append(t.Rows, []string{ - fmt.Sprintf("%d", e.slot+1), + fmt.Sprintf("%d", e.pos), g.itemColorize(sess, def, e.name), fmt.Sprintf("%d", e.qty), }) @@ -153,9 +157,10 @@ func (g *Game) doBankDeposit(sess *net.Session, input string) { bankIdx := p.NextBankSlot() p.SetBankSlot(bankIdx, &player.InventorySlot{ - ItemID: itemID, - Quantity: qty, - Quality: slot.Quality, + ItemID: itemID, + Quantity: qty, + Quality: slot.Quality, + MaxQuality: slot.MaxQuality, }) g.AccountStore.SaveCharacter(p) @@ -183,9 +188,10 @@ func (g *Game) doBankDepositAll(sess *net.Session) { } bankIdx := p.NextBankSlot() p.SetBankSlot(bankIdx, &player.InventorySlot{ - ItemID: slot.ItemID, - Quantity: slot.Quantity, - Quality: slot.Quality, + ItemID: slot.ItemID, + Quantity: slot.Quantity, + Quality: slot.Quality, + MaxQuality: slot.MaxQuality, }) p.SetInvSlot(i, nil) deposited++ @@ -204,19 +210,18 @@ func (g *Game) doBankDepositAll(sess *net.Session) { func (g *Game) doBankWithdraw(sess *net.Session, input string) { p := sess.Player - freeSlot := p.FirstFreeSlot() - if freeSlot == -1 { - sess.WriteLine("Your inventory is full.") - return - } + // No upfront capacity check here: withdrawBankItem merges stackable items + // into existing stacks first and only needs a free slot otherwise. - var entries []struct { + type entryRef struct { slot int + pos int name string id string qty int } + var entries []entryRef for _, i := range p.BankSlots() { bs := p.BankSlot(i) if bs == nil { @@ -227,12 +232,7 @@ func (g *Game) doBankWithdraw(sess *net.Session, input string) { if def != nil { itemName = def.Name } - entries = append(entries, struct { - slot int - name string - id string - qty int - }{slot: i, name: itemName, id: bs.ItemID, qty: bs.Quantity}) + entries = append(entries, entryRef{slot: i, pos: len(entries) + 1, name: itemName, id: bs.ItemID, qty: bs.Quantity}) } idx, err := parseChoiceIndex(input) @@ -242,12 +242,7 @@ func (g *Game) doBankWithdraw(sess *net.Session, input string) { return } - var matches []struct { - slot int - name string - id string - qty int - } + var matches []entryRef lower := strings.ToLower(input) for _, e := range entries { if behavior.WordPrefixMatch(e.name, lower) { @@ -293,6 +288,30 @@ func (g *Game) withdrawBankItem(sess *net.Session, p *player.Player, bankSlotIdx return } + def, _ := g.ItemStore.Load(bs.ItemID) + + // Stackable withdrawals merge into a compatible stack first; a free slot + // is only required when the player holds none of the item. Compatibility + // means the exact same item instance: merging two different-quality + // stacks would silently destroy the withdrawn stack's properties. + if def != nil && def.Stackable { + for i := 0; i < 28; i++ { + if slot := p.InvSlot(i); slot != nil && slot.ItemID == bs.ItemID && + slot.Quality == bs.Quality && slot.MaxQuality == bs.MaxQuality { + slot.Quantity += bs.Quantity + p.SetBankSlot(bankSlotIdx, nil) + g.AccountStore.SaveCharacter(p) + displayName := bs.ItemID + if def != nil { + displayName = def.Name + } + itemColor := g.itemColorize(sess, def, displayName) + sess.WriteLine(fmt.Sprintf("You withdraw %d %ss.", bs.Quantity, itemColor)) + return + } + } + } + freeSlot := p.FirstFreeSlot() if freeSlot == -1 { sess.WriteLine("Your inventory is full.") @@ -301,12 +320,11 @@ func (g *Game) withdrawBankItem(sess *net.Session, p *player.Player, bankSlotIdx itemID := bs.ItemID qty := bs.Quantity - def, _ := g.ItemStore.Load(itemID) if def != nil && def.Stackable { - p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: itemID, Quantity: qty}) + p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: itemID, Quantity: qty, Quality: bs.Quality, MaxQuality: bs.MaxQuality}) } else { - p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: itemID, Quantity: 1}) + p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: itemID, Quantity: 1, Quality: bs.Quality, MaxQuality: bs.MaxQuality}) if qty > 1 { bs.Quantity-- g.AccountStore.SaveCharacter(p) |
