aboutsummaryrefslogtreecommitdiff
path: root/internal/game/cmd_drop.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-09-18 15:16:44 -0400
committerhistoria <[not public]>2026-09-18 15:16:44 -0400
commit7eab582d8a8ee2af1a6baae7baf0696c7005de2e (patch)
tree902bbc8c6e39c9f62f779ca23267714ec420b9f5 /internal/game/cmd_drop.go
parent153acb7f644d755c45533b7c5311e3ffa47e8973 (diff)
downloadthehouseoficarus-7eab582d8a8ee2af1a6baae7baf0696c7005de2e.tar.gz
fix: harden triggers, economy, casino, world data, and admin/net paths
Diffstat (limited to 'internal/game/cmd_drop.go')
-rw-r--r--internal/game/cmd_drop.go61
1 files changed, 42 insertions, 19 deletions
diff --git a/internal/game/cmd_drop.go b/internal/game/cmd_drop.go
index 5920696..2e27f91 100644
--- a/internal/game/cmd_drop.go
+++ b/internal/game/cmd_drop.go
@@ -51,15 +51,24 @@ func (g *Game) doDropAllNamed(sess *net.Session, input string) {
coloredName := g.itemColorize(sess, def, name)
if def != nil && def.Stackable {
- slot := p.InvSlot(matches[0].Slot)
- qty := slot.Quantity
- p.SetInvSlot(matches[0].Slot, nil)
- g.World.AddGroundItem(p.RoomID, itemID, qty)
+ // Drop every matching stack, not just the first: multiple stacks of
+ // one stackable item are normal (trigger/gather/steal placement does
+ // not always merge), so "drop all <item>" must span them.
+ total := 0
+ for _, match := range matches {
+ slot := p.InvSlot(match.Slot)
+ if slot == nil || slot.ItemID != itemID || slot.Quantity <= 0 {
+ continue
+ }
+ total += slot.Quantity
+ p.SetInvSlot(match.Slot, nil)
+ g.World.AddGroundItem(p.RoomID, itemID, slot.Quantity)
+ }
g.saveCharacter(p)
- if qty == 1 {
+ if total == 1 {
sess.WriteLine(fmt.Sprintf("You drop a %s.", coloredName))
} else {
- sess.WriteLine(fmt.Sprintf("You drop %d x %s.", qty, coloredName))
+ sess.WriteLine(fmt.Sprintf("You drop %d x %s.", total, coloredName))
}
return
}
@@ -110,11 +119,11 @@ func (g *Game) doDrop(sess *net.Session, input string) {
if qty == 0 {
if def != nil && def.Stackable {
+ // "drop <item>" means the whole item: sum every matching stack.
for i := 0; i < 28; i++ {
slot := p.InvSlot(i)
if slot != nil && slot.ItemID == itemID && slot.Quantity > 0 {
- qty = slot.Quantity
- break
+ qty += slot.Quantity
}
}
} else {
@@ -128,21 +137,35 @@ func (g *Game) doDrop(sess *net.Session, input string) {
}
if def != nil && def.Stackable {
- slot := p.InvSlot(matches[0].Slot)
- if qty > slot.Quantity {
- qty = slot.Quantity
- }
- if slot.Quantity > qty {
- slot.Quantity -= qty
- } else {
- p.SetInvSlot(matches[0].Slot, nil)
+ // Consume the requested quantity across every matching stack, not just
+ // the first one.
+ remaining := qty
+ for _, match := range matches {
+ if remaining <= 0 {
+ break
+ }
+ slot := p.InvSlot(match.Slot)
+ if slot == nil || slot.ItemID != itemID || slot.Quantity <= 0 {
+ continue
+ }
+ take := slot.Quantity
+ if take > remaining {
+ take = remaining
+ }
+ if slot.Quantity > take {
+ slot.Quantity -= take
+ } else {
+ p.SetInvSlot(match.Slot, nil)
+ }
+ g.World.AddGroundItem(p.RoomID, itemID, take)
+ remaining -= take
}
- g.World.AddGroundItem(p.RoomID, itemID, qty)
+ dropped := qty - remaining
g.saveCharacter(p)
- if qty == 1 {
+ if dropped == 1 {
sess.WriteLine(fmt.Sprintf("You drop a %s.", g.itemColorize(sess, def, name)))
} else {
- sess.WriteLine(fmt.Sprintf("You drop %d x %s.", qty, g.itemColorize(sess, def, name)))
+ sess.WriteLine(fmt.Sprintf("You drop %d x %s.", dropped, g.itemColorize(sess, def, name)))
}
return
}