aboutsummaryrefslogtreecommitdiff
path: root/internal/game/cmd_trigger_utility.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_trigger_utility.go
parent153acb7f644d755c45533b7c5311e3ffa47e8973 (diff)
downloadthehouseoficarus-7eab582d8a8ee2af1a6baae7baf0696c7005de2e.tar.gz
fix: harden triggers, economy, casino, world data, and admin/net paths
Diffstat (limited to 'internal/game/cmd_trigger_utility.go')
-rw-r--r--internal/game/cmd_trigger_utility.go62
1 files changed, 38 insertions, 24 deletions
diff --git a/internal/game/cmd_trigger_utility.go b/internal/game/cmd_trigger_utility.go
index b5a168b..f9e3692 100644
--- a/internal/game/cmd_trigger_utility.go
+++ b/internal/game/cmd_trigger_utility.go
@@ -107,12 +107,9 @@ func (g *Game) triggerEmGrab(sess *net.Session, p *player.Player, mod *ModDef, t
return
}
- if p.FirstFreeSlot() < 0 {
- sess.WriteLine("Your inventory is full.")
- return
- }
-
- groundItems := g.World.GroundItems(p.RoomID)
+ // Reservation-aware: only items this player may take are considered, so
+ // em grab cannot magnetize kill loot reserved for another player.
+ groundItems := g.World.AccessibleGround(p.RoomID, p.Name)
var matchedID string
for itemID := range groundItems {
def, _ := g.ItemStore.Load(itemID)
@@ -143,41 +140,58 @@ func (g *Game) triggerEmGrab(sess *net.Session, p *player.Player, mod *ModDef, t
}
// Credits are currency, not an inventory item: collect them the same way
- // the get command does.
+ // the get command does, respecting the balance cap so the excess stays on
+ // the ground instead of being removed and clamped away.
if matchedID == "credits" {
- g.World.RemoveGroundItem(p.RoomID, matchedID, qty)
- g.grantCredits(p, qty)
+ room := creditHeadroom(p)
+ if room <= 0 {
+ sess.WriteLine(g.colorize(sess, "currency_pickup", "Your purse can't hold any more credits."))
+ return
+ }
+ taken := g.World.RemoveAvailableItem(p.RoomID, matchedID, room, p.Name)
+ if taken <= 0 {
+ return
+ }
+ g.grantCredits(p, taken)
+ g.saveCharacter(p)
g.triggerModReward(sess, p, mod, 1.0)
- sess.WriteLine(fmt.Sprintf("You magnetically pull %d credits toward you.", qty))
+ sess.WriteLine(fmt.Sprintf("You magnetically pull %d credits toward you.", taken))
return
}
if def != nil && def.Stackable {
- g.World.RemoveGroundItem(p.RoomID, matchedID, qty)
- if !placeCraftOutput(p, matchedID, def, qty) {
- g.World.AddGroundItem(p.RoomID, matchedID, qty)
+ taken := g.World.RemoveAvailableItem(p.RoomID, matchedID, qty, p.Name)
+ if taken <= 0 {
+ sess.WriteLine("You don't see that here.")
+ return
+ }
+ if !placeCraftOutput(p, matchedID, def, taken) {
+ g.World.AddGroundItem(p.RoomID, matchedID, taken)
sess.WriteLine("Your inventory is full.")
return
}
} else {
// Non-stackable items take one slot each; leave any remainder on the
- // ground instead of cramming N items into a single slot.
- taken := 0
- for taken < qty {
+ // ground instead of cramming N items into a single slot. Remove from
+ // the ground first (reservation-aware) so a placement failure cannot
+ // duplicate stock.
+ taken, ok := g.World.RemoveReservedItem(p.RoomID, matchedID, qty, p.Name)
+ if !ok || taken == 0 {
+ sess.WriteLine("Your inventory is full.")
+ return
+ }
+ placed := 0
+ for placed < taken {
freeSlot := p.FirstFreeSlot()
if freeSlot < 0 {
break
}
p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: matchedID, Quantity: 1})
- taken++
- }
- if taken == 0 {
- sess.WriteLine("Your inventory is full.")
- return
+ placed++
}
- g.World.RemoveGroundItem(p.RoomID, matchedID, taken)
- if taken < qty {
- sess.WriteLine(fmt.Sprintf("Your inventory fills up; %d %s remain on the ground.", qty-taken, name))
+ if placed < taken {
+ g.World.AddGroundItem(p.RoomID, matchedID, taken-placed)
+ sess.WriteLine(fmt.Sprintf("Your inventory fills up; %d %s remain on the ground.", taken-placed, name))
}
}