From 17e7725f252c7f5d3be2e9c37d62751c631f196f Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Thu, 18 Jun 2026 18:50:54 -0400 Subject: feat: fletching added including zero-time bolt feathering, which probably will break lots of things --- internal/game/cmd_wear.go | 106 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 97 insertions(+), 9 deletions(-) (limited to 'internal/game/cmd_wear.go') diff --git a/internal/game/cmd_wear.go b/internal/game/cmd_wear.go index 8910e75..ddc970b 100644 --- a/internal/game/cmd_wear.go +++ b/internal/game/cmd_wear.go @@ -25,9 +25,11 @@ func (g *Game) doWear(sess *net.Session, input string) { g.CancelAction(p) - matches := g.findInventoryMatches(input, p) + qty, itemName := parseQty(input) + + matches := g.findInventoryMatches(itemName, p) if len(matches) == 0 { - sess.WriteLine(fmt.Sprintf("You don't have any '%s'.", input)) + sess.WriteLine(fmt.Sprintf("You don't have any '%s'.", itemName)) return } @@ -52,6 +54,11 @@ func (g *Game) doWear(sess *net.Session, input string) { return } + if def.EquipSlot == object.SlotAmmo && def.Stackable { + g.equipAmmo(sess, p, match.Slot, slot, def, qty) + return + } + existingItemID, slotOccupied := p.Equipment[def.EquipSlot] if slotOccupied { @@ -88,13 +95,64 @@ func (g *Game) doWear(sess *net.Session, input string) { sess.WriteLine(fmt.Sprintf("You %s %s.", verb, g.itemColorize(sess, def, match.Name))) } +func (g *Game) equipAmmo(sess *net.Session, p *player.Player, invIdx int, slot *player.InventorySlot, def *object.ItemDef, qty int) { + transferQty := slot.Quantity + if qty > 0 && qty < transferQty { + transferQty = qty + } + + existingAmmoID, hasAmmo := p.Equipment[object.SlotAmmo] + if hasAmmo && existingAmmoID != slot.ItemID { + g.unequipAmmo(p) + } + + if slot.Quantity <= transferQty { + p.SetInvSlot(invIdx, nil) + } else { + slot.Quantity -= transferQty + } + + if hasAmmo && existingAmmoID == slot.ItemID { + p.AmmoQty += transferQty + } else { + p.Equipment[object.SlotAmmo] = slot.ItemID + p.AmmoQty = transferQty + } + + g.AccountStore.SaveCharacter(p) + displayName := g.itemColorize(sess, def, def.Name) + sess.WriteLine(fmt.Sprintf("You equip %s (x%d).", displayName, p.AmmoQty)) +} + +func (g *Game) unequipAmmo(p *player.Player) { + ammoID, ok := p.Equipment[object.SlotAmmo] + if !ok || p.AmmoQty <= 0 { + return + } + for i := 0; i < 28; i++ { + s := p.InvSlot(i) + if s != nil && s.ItemID == ammoID { + s.Quantity += p.AmmoQty + delete(p.Equipment, object.SlotAmmo) + p.AmmoQty = 0 + return + } + } + freeSlot := p.FirstFreeSlot() + if freeSlot >= 0 { + p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: ammoID, Quantity: p.AmmoQty}) + } + delete(p.Equipment, object.SlotAmmo) + p.AmmoQty = 0 +} + func (g *Game) doWearAll(sess *net.Session) { p := sess.Player.(*player.Player) g.CancelAction(p) bestPerSlot := make(map[object.EquipSlot]struct { - itemID string - value int + itemID string + value int invSlot int }) @@ -108,12 +166,16 @@ func (g *Game) doWearAll(sess *net.Session) { continue } current, exists := bestPerSlot[def.EquipSlot] - if !exists || def.Value > current.value { + val := def.Value + if def.EquipSlot == object.SlotAmmo && def.Stackable { + val = def.Value * slot.Quantity + } + if !exists || val > current.value { bestPerSlot[def.EquipSlot] = struct { - itemID string - value int + itemID string + value int invSlot int - }{slot.ItemID, def.Value, i} + }{slot.ItemID, val, i} } } @@ -125,7 +187,33 @@ func (g *Game) doWearAll(sess *net.Session) { var equipped []string for eqSlot, best := range bestPerSlot { if existing, ok := p.Equipment[eqSlot]; ok && existing == best.itemID { - continue + if eqSlot != object.SlotAmmo { + continue + } + } + + if eqSlot == object.SlotAmmo { + bestDef, _ := g.ItemStore.Load(best.itemID) + if bestDef != nil && bestDef.Stackable { + invSlot := p.InvSlot(best.invSlot) + if invSlot == nil { + continue + } + existingID, hasAmmo := p.Equipment[object.SlotAmmo] + if hasAmmo && existingID != best.itemID { + g.unequipAmmo(p) + } + transferQty := invSlot.Quantity + p.SetInvSlot(best.invSlot, nil) + if hasAmmo && existingID == best.itemID { + p.AmmoQty += transferQty + } else { + p.Equipment[object.SlotAmmo] = best.itemID + p.AmmoQty = transferQty + } + equipped = append(equipped, g.itemColorize(sess, bestDef, bestDef.Name)) + continue + } } if existing, ok := p.Equipment[eqSlot]; ok { -- cgit v1.2.3