diff options
| author | historia <[not public]> | 2026-06-19 13:28:06 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-06-19 13:28:06 -0400 |
| commit | 3a58125d14bb307f861b38c6c5b0a63babde7e08 (patch) | |
| tree | bd89e866447d55e6dffd447d8ef5fabf9b8fbe9d /internal/game/cmd_bank.go | |
| parent | 575a71dcfed3b9fa44af244836f638a23df05a9a (diff) | |
| download | thehouseoficarus-3a58125d14bb307f861b38c6c5b0a63babde7e08.tar.gz | |
feat: all skills kind of implemented, random prototype content added
Diffstat (limited to 'internal/game/cmd_bank.go')
| -rw-r--r-- | internal/game/cmd_bank.go | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/internal/game/cmd_bank.go b/internal/game/cmd_bank.go new file mode 100644 index 0000000..ff3a3ac --- /dev/null +++ b/internal/game/cmd_bank.go @@ -0,0 +1,345 @@ +package game + +import ( + "fmt" + "sort" + "strings" + + "thehouseoficarus/internal/net" + "thehouseoficarus/internal/player" + "thehouseoficarus/internal/world" +) + +func (g *Game) handleBankInput(sess *net.Session, input string) { + if sess.Player == nil { + sess.State = net.StateGame + g.writePrompt(sess) + return + } + + input = strings.TrimSpace(input) + parts := strings.Fields(strings.ToLower(input)) + if len(parts) == 0 { + g.showBankBrowse(sess) + return + } + + cmd := parts[0] + + switch cmd { + case "deposit": + if len(parts) < 2 { + sess.WriteLine("Deposit what?") + } else if parts[1] == "all" { + g.doBankDepositAll(sess) + } else { + g.doBankDeposit(sess, strings.Join(parts[1:], " ")) + } + case "withdraw": + if len(parts) < 2 { + sess.WriteLine("Withdraw what?") + } else { + g.doBankWithdraw(sess, strings.Join(parts[1:], " ")) + } + case "browse", "list": + g.showBankBrowse(sess) + case "leave", "bye", "exit", "quit": + g.leaveBank(sess) + return + default: + sess.WriteLine("Commands: deposit <item>, deposit all, withdraw <item>, browse, leave") + } + g.writeBankPrompt(sess) +} + +func (g *Game) writeBankPrompt(sess *net.Session) { + sess.Write(fmt.Sprintf("\n%s", g.colorize(sess, "dialog", "Bank> "))) +} + +func (g *Game) showBankBrowse(sess *net.Session) { + p, _ := sess.Player.(*player.Player) + + unicode := p.OptionBool("unicode") + + t := Table{ + Title: "Bank Contents", + Columns: []string{"#", "Item", "Quantity"}, + } + + type bankEntry struct { + slot int + name string + id string + qty int + } + + var entries []bankEntry + for _, i := range p.BankSlots() { + slot := p.BankSlot(i) + if slot == nil { + continue + } + def, _ := g.ItemStore.Load(slot.ItemID) + itemName := slot.ItemID + if def != nil { + itemName = def.Name + } + entries = append(entries, bankEntry{slot: i, name: itemName, id: slot.ItemID, qty: slot.Quantity}) + } + + if len(entries) == 0 { + sess.WriteLine("\nYour bank is empty.") + return + } + + sort.Slice(entries, func(i, j int) bool { + return entries[i].slot < entries[j].slot + }) + + for _, e := range entries { + t.Rows = append(t.Rows, []string{ + fmt.Sprintf("%d", e.slot+1), + g.colorize(sess, "item", e.name), + fmt.Sprintf("%d", e.qty), + }) + } + + for _, line := range t.Render(unicode) { + sess.WriteLine(line) + } +} + +func (g *Game) doBankDeposit(sess *net.Session, input string) { + p, _ := sess.Player.(*player.Player) + + matches := g.findInventoryMatches(input, p) + if len(matches) == 0 { + sess.WriteLine("You don't have that item.") + return + } + + if len(matches) > 1 { + g.showWhichOne(sess, matches) + return + } + + match := matches[0] + + slot := p.InvSlot(match.Slot) + if slot == nil { + return + } + + itemID := slot.ItemID + qty := slot.Quantity + def, _ := g.ItemStore.Load(itemID) + + p.SetInvSlot(match.Slot, nil) + + bankIdx := p.NextBankSlot() + p.SetBankSlot(bankIdx, &player.InventorySlot{ + ItemID: itemID, + Quantity: qty, + Quality: slot.Quality, + }) + + g.AccountStore.SaveCharacter(p) + + displayName := itemID + if def != nil { + displayName = def.Name + } + itemColor := g.itemColorize(sess, def, displayName) + if qty > 1 { + sess.WriteLine(fmt.Sprintf("You deposit %d %ss.", qty, itemColor)) + } else { + sess.WriteLine(fmt.Sprintf("You deposit a %s.", itemColor)) + } +} + +func (g *Game) doBankDepositAll(sess *net.Session) { + p, _ := sess.Player.(*player.Player) + + var deposited int + for i := 0; i < 28; i++ { + slot := p.InvSlot(i) + if slot == nil { + continue + } + bankIdx := p.NextBankSlot() + p.SetBankSlot(bankIdx, &player.InventorySlot{ + ItemID: slot.ItemID, + Quantity: slot.Quantity, + Quality: slot.Quality, + }) + p.SetInvSlot(i, nil) + deposited++ + } + + if deposited == 0 { + sess.WriteLine("Your inventory is already empty.") + return + } + + g.AccountStore.SaveCharacter(p) + + sess.WriteLine(fmt.Sprintf("You deposit %d item%s.", deposited, plural(deposited))) +} + +func (g *Game) doBankWithdraw(sess *net.Session, input string) { + p, _ := sess.Player.(*player.Player) + + freeSlot := p.FirstFreeSlot() + if freeSlot == -1 { + sess.WriteLine("Your inventory is full.") + return + } + + var entries []struct { + slot int + name string + id string + qty int + } + + for _, i := range p.BankSlots() { + bs := p.BankSlot(i) + if bs == nil { + continue + } + def, _ := g.ItemStore.Load(bs.ItemID) + itemName := bs.ItemID + 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}) + } + + idx, err := parseChoiceIndex(input) + if err == nil && idx > 0 && idx <= len(entries) { + e := entries[idx-1] + g.withdrawBankItem(sess, p, e.slot) + return + } + + var matches []struct { + slot int + name string + id string + qty int + } + lower := strings.ToLower(input) + for _, e := range entries { + if world.WordPrefixMatch(e.name, lower) { + matches = append(matches, e) + } + } + + if len(matches) == 1 { + g.withdrawBankItem(sess, p, matches[0].slot) + return + } + + for _, e := range entries { + def, _ := g.ItemStore.Load(e.id) + if def != nil && def.MatchesName(input) { + matches = append(matches, e) + } + } + + if len(matches) == 0 { + sess.WriteLine("That item isn't in your bank. Use 'browse' to see your bank contents.") + return + } + + if len(matches) > 1 { + var names []string + for _, m := range matches { + names = append(names, m.name) + } + sess.WriteLine("That's ambiguous, which one?") + for _, n := range names { + sess.WriteLine(fmt.Sprintf(" - %s", n)) + } + return + } + + g.withdrawBankItem(sess, p, matches[0].slot) +} + +func (g *Game) withdrawBankItem(sess *net.Session, p *player.Player, bankSlotIdx int) { + bs := p.BankSlot(bankSlotIdx) + if bs == nil { + return + } + + freeSlot := p.FirstFreeSlot() + if freeSlot == -1 { + sess.WriteLine("Your inventory is full.") + return + } + + 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}) + } else { + p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: itemID, Quantity: 1}) + if qty > 1 { + bs.Quantity-- + g.AccountStore.SaveCharacter(p) + displayName := itemID + if def != nil { + displayName = def.Name + } + itemColor := g.itemColorize(sess, def, displayName) + sess.WriteLine(fmt.Sprintf("You withdraw a %s.", itemColor)) + return + } + } + + p.SetBankSlot(bankSlotIdx, nil) + g.AccountStore.SaveCharacter(p) + + displayName := itemID + if def != nil { + displayName = def.Name + } + itemColor := g.itemColorize(sess, def, displayName) + if qty > 1 { + sess.WriteLine(fmt.Sprintf("You withdraw %d %ss.", qty, itemColor)) + } else { + sess.WriteLine(fmt.Sprintf("You withdraw a %s.", itemColor)) + } +} + +func (g *Game) canUseBank(p *player.Player) bool { + instances := g.World.FindObjInstances(p.RoomID, "bank booth") + return len(instances) > 0 +} + +func (g *Game) doBank(sess *net.Session) { + p, _ := sess.Player.(*player.Player) + + if !g.canUseBank(p) { + sess.WriteLine("There is no bank here.") + return + } + + sess.State = net.StateBank + sess.WriteLine(g.colorize(sess, "dialog", "\nYou access the bank terminal.")) + g.showBankBrowse(sess) + g.writeBankPrompt(sess) +} + +func (g *Game) leaveBank(sess *net.Session) { + sess.State = net.StateGame + g.writePrompt(sess) +} |
