aboutsummaryrefslogtreecommitdiff
path: root/internal/game/cmd_get.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-10 01:48:28 -0400
committerhistoria <[not public]>2026-06-10 01:48:28 -0400
commita226d72e51eecb768b13600303f73483118d9104 (patch)
tree458d15ef049732c15dacc591a830d3beddbedfde /internal/game/cmd_get.go
parent6a0f3d7a252de4b1741cfe5e1c561412c602becc (diff)
downloadthehouseoficarus-a226d72e51eecb768b13600303f73483118d9104.tar.gz
feat: implemented janky object interaction model
Diffstat (limited to 'internal/game/cmd_get.go')
-rw-r--r--internal/game/cmd_get.go251
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
+}