aboutsummaryrefslogtreecommitdiff
path: root/internal/game/production_index.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-09-18 05:31:09 -0400
committerhistoria <[not public]>2026-09-18 05:31:09 -0400
commit153acb7f644d755c45533b7c5311e3ffa47e8973 (patch)
tree7645e6f7b65bc3830b078e3b9336d2e6b199d584 /internal/game/production_index.go
parent87d08f0151e643951769e323995f1c5ed89ee200 (diff)
downloadthehouseoficarus-153acb7f644d755c45533b7c5311e3ffa47e8973.tar.gz
fix: harden engine across casino, economy, concurrency, security, and content
Diffstat (limited to 'internal/game/production_index.go')
-rw-r--r--internal/game/production_index.go23
1 files changed, 20 insertions, 3 deletions
diff --git a/internal/game/production_index.go b/internal/game/production_index.go
index ffacd8a..35466a7 100644
--- a/internal/game/production_index.go
+++ b/internal/game/production_index.go
@@ -272,6 +272,19 @@ func consumeIngredients(c *item.CraftDef, countItem func(string) int, removeItem
return true
}
+// stackProps returns the Quality and MaxQuality a NEW inventory stack of def
+// receives, mirroring newInventorySlot (core_utils.go): a quality-bearing
+// definition is stamped at its full quality. Every stack-creation and
+// stack-merge site must agree on these values, or a stack produced by one
+// path (craft, harvest, ammo removal, shop) stops merging with the same item
+// picked up from the ground while the inventory is full.
+func stackProps(def *item.ItemDef) (quality, maxQuality int) {
+ if def != nil && def.MaxQuality > 0 {
+ return def.MaxQuality, def.MaxQuality
+ }
+ return 0, 0
+}
+
// craftOutputFits reports whether outputQty of an item can be placed into
// the inventory right now: merged into an existing stack for stackable
// definitions, otherwise a free slot. Crafters must check BEFORE consuming
@@ -279,8 +292,10 @@ func consumeIngredients(c *item.CraftDef, countItem func(string) int, removeItem
// producing the output.
func craftOutputFits(p *player.Player, itemID string, outDef *item.ItemDef) bool {
if outDef != nil && outDef.Stackable {
+ quality, maxQuality := stackProps(outDef)
for i := 0; i < 28; i++ {
- if slot := p.InvSlot(i); slot != nil && slot.ItemID == itemID {
+ slot := p.InvSlot(i)
+ if slot != nil && slot.ItemID == itemID && slot.Quality == quality && slot.MaxQuality == maxQuality {
return true
}
}
@@ -294,9 +309,11 @@ func craftOutputFits(p *player.Player, itemID string, outDef *item.ItemDef) bool
// (consumption cannot free fewer slots than the check saw on the owner
// goroutine, so a false return is defensive).
func placeCraftOutput(p *player.Player, itemID string, outDef *item.ItemDef, outputQty int) bool {
+ quality, maxQuality := stackProps(outDef)
if outDef != nil && outDef.Stackable {
for i := 0; i < 28; i++ {
- if slot := p.InvSlot(i); slot != nil && slot.ItemID == itemID {
+ slot := p.InvSlot(i)
+ if slot != nil && slot.ItemID == itemID && slot.Quality == quality && slot.MaxQuality == maxQuality {
slot.Quantity += outputQty
return true
}
@@ -306,6 +323,6 @@ func placeCraftOutput(p *player.Player, itemID string, outDef *item.ItemDef, out
if freeSlot == -1 {
return false
}
- p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: itemID, Quantity: outputQty})
+ p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: itemID, Quantity: outputQty, Quality: quality, MaxQuality: maxQuality})
return true
}