diff options
| author | historia <[not public]> | 2026-06-10 01:48:28 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-06-10 01:48:28 -0400 |
| commit | a226d72e51eecb768b13600303f73483118d9104 (patch) | |
| tree | 458d15ef049732c15dacc591a830d3beddbedfde /internal/game/cmd_get.go | |
| parent | 6a0f3d7a252de4b1741cfe5e1c561412c602becc (diff) | |
| download | thehouseoficarus-a226d72e51eecb768b13600303f73483118d9104.tar.gz | |
feat: implemented janky object interaction model
Diffstat (limited to 'internal/game/cmd_get.go')
| -rw-r--r-- | internal/game/cmd_get.go | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/internal/game/cmd_get.go b/internal/game/cmd_get.go new file mode 100644 index 0000000..bce8ddc --- /dev/null +++ b/internal/game/cmd_get.go @@ -0,0 +1,251 @@ +package game + +import ( + "fmt" + + "thirdcollapse/internal/net" + "thirdcollapse/internal/player" +) + +func (g *Game) doGet(sess *net.Session, input string) { + p := sess.Player.(*player.Player) + ground := g.World.GroundItems(p.RoomID) + if len(ground) == 0 { + sess.WriteLine("There's nothing on the ground to pick up.") + return + } + + matches := g.findGroundMatches(input, p.RoomID) + if len(matches) == 0 { + sess.WriteLine(fmt.Sprintf("There's no '%s' here.", input)) + return + } + + if len(matches) > 1 { + unique := uniqueItemNames(matches) + if len(unique) > 1 { + sess.WriteLine("Which one?") + for _, name := range unique { + sess.WriteLine(fmt.Sprintf(" - %s", name)) + } + return + } + } + + itemID := matches[0].ID + + if itemID == "credits" { + g.pickupCredits(sess, p, itemID) + return + } + + def, _ := g.ItemStore.Load(itemID) + + freeSlot := p.FirstFreeSlot() + if freeSlot == -1 { + sess.WriteLine("Your inventory is full.") + return + } + + qty := 1 + if def != nil && def.Stackable { + ground := g.World.GroundItems(p.RoomID) + if gqty, ok := ground[itemID]; ok && gqty > 0 { + qty = gqty + } + } + + if def != nil && def.Stackable { + for i := 0; i < 28; i++ { + slot := p.InvSlot(i) + if slot != nil && slot.ItemID == itemID { + removed, ok := g.World.RemoveReservedGroundItem(p.RoomID, itemID, qty, p.Name) + if !ok { + sess.WriteLine("That's not yours!") + return + } + _ = removed + slot.Quantity += qty + g.AccountStore.SaveCharacter(p) + sess.WriteLine(fmt.Sprintf("You pick up a %s. (now %d)", def.Name, slot.Quantity)) + return + } + } + } + + removed, ok := g.World.RemoveReservedGroundItem(p.RoomID, itemID, qty, p.Name) + if !ok { + sess.WriteLine("That's not yours!") + return + } + _ = removed + p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: itemID, Quantity: qty}) + g.AccountStore.SaveCharacter(p) + name := itemID + if def != nil { + name = def.Name + } + sess.WriteLine(fmt.Sprintf("You pick up a %s.", name)) +} + +func (g *Game) doGetAll(sess *net.Session) { + p := sess.Player.(*player.Player) + ground := g.World.GroundItems(p.RoomID) + if len(ground) == 0 { + sess.WriteLine("There's nothing on the ground to pick up.") + return + } + + var picked []string + for itemID, qty := range ground { + if qty <= 0 { + continue + } + if itemID == "credits" { + taken, ok := g.World.RemoveReservedGroundItem(p.RoomID, itemID, 999999, p.Name) + if !ok { + continue + } + p.Credits += taken + if taken == 1 { + picked = append(picked, "1 credit") + } else { + picked = append(picked, fmt.Sprintf("%d credits", taken)) + } + continue + } + + def, _ := g.ItemStore.Load(itemID) + for qty > 0 { + if def != nil && def.Stackable { + stacked := false + for i := 0; i < 28; i++ { + slot := p.InvSlot(i) + if slot != nil && slot.ItemID == itemID { + _, ok := g.World.RemoveReservedGroundItem(p.RoomID, itemID, qty, p.Name) + if !ok { + qty = 0 + stacked = true + break + } + slot.Quantity += qty + picked = append(picked, fmt.Sprintf("%s (now %d)", def.Name, slot.Quantity)) + stacked = true + qty = 0 + break + } + } + if stacked { + break + } + freeSlot := p.FirstFreeSlot() + if freeSlot == -1 { + if len(picked) > 0 { + sess.WriteLine("Inventory full. Picked up so far:") + innerPickupReport(sess, picked) + } else { + sess.WriteLine("Your inventory is full.") + } + g.AccountStore.SaveCharacter(p) + return + } + _, ok := g.World.RemoveReservedGroundItem(p.RoomID, itemID, qty, p.Name) + if !ok { + break + } + p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: itemID, Quantity: qty}) + name := itemID + if def != nil { + name = def.Name + } + picked = append(picked, name) + break + } + + freeSlot := p.FirstFreeSlot() + if freeSlot == -1 { + if len(picked) > 0 { + sess.WriteLine("Inventory full. Picked up so far:") + innerPickupReport(sess, picked) + } else { + sess.WriteLine("Your inventory is full.") + } + g.AccountStore.SaveCharacter(p) + return + } + + take := 1 + _, ok := g.World.RemoveReservedGroundItem(p.RoomID, itemID, take, p.Name) + if !ok { + break + } + p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: itemID, Quantity: take}) + name := itemID + if def != nil { + name = def.Name + } + picked = append(picked, name) + qty -= take + } + } + + g.AccountStore.SaveCharacter(p) + + if len(picked) == 0 { + sess.WriteLine("Your inventory is full.") + } else { + sess.Write("You pick up: ") + innerPickupReport(sess, picked) + } +} + +func (g *Game) pickupCredits(sess *net.Session, p *player.Player, itemID string) { + qty, ok := g.World.RemoveReservedGroundItem(p.RoomID, itemID, 999999, p.Name) + if !ok { + sess.WriteLine("That's not yours!") + return + } + if qty <= 0 { + return + } + p.Credits += qty + g.AccountStore.SaveCharacter(p) + if qty == 1 { + sess.WriteLine("You pick up 1 credit.") + } else { + sess.WriteLine(fmt.Sprintf("You pick up %d credits. (total: %d)", qty, p.Credits)) + } +} + +func (g *Game) findGroundMatches(input string, roomID int) []itemMatch { + ground := g.World.GroundItems(roomID) + var matches []itemMatch + for itemID := range ground { + def, err := g.ItemStore.Load(itemID) + if err != nil { + continue + } + if def.MatchesName(input) { + matches = append(matches, itemMatch{ID: itemID, Name: def.Name, Slot: -1}) + } + } + return matches +} + +func (g *Game) findInventoryMatches(input string, p *player.Player) []itemMatch { + var matches []itemMatch + for i := 0; i < 28; i++ { + slot := p.InvSlot(i) + if slot == nil { + continue + } + def, err := g.ItemStore.Load(slot.ItemID) + if err != nil { + continue + } + if def.MatchesName(input) { + matches = append(matches, itemMatch{ID: slot.ItemID, Name: def.Name, Slot: i}) + } + } + return matches +} |
