package game import ( "fmt" "strings" "thehouseoficarus/internal/item" "thehouseoficarus/internal/net" "thehouseoficarus/internal/player" ) func (g *Game) executeWear(sess *net.Session, args []string, rawInput string) { g.doWear(sess, strings.Join(args, " ")) } func (g *Game) checkRequirements(sess *net.Session, p *player.Player, def *item.ItemDef) string { if len(def.Requirements) == 0 { return "" } var unmet []string for skill, level := range def.Requirements { if p.Level(player.SkillName(skill)) < level { unmet = append(unmet, fmt.Sprintf("%d %s", level, skill)) } } if len(unmet) == 0 { return "" } return fmt.Sprintf("You need %s to wear %s.", strings.Join(unmet, ", "), g.itemColorize(sess, def, def.Name)) } func (g *Game) doWear(sess *net.Session, input string) { p := sess.Player lower := strings.ToLower(strings.TrimSpace(input)) if lower == "all" { g.doWearAll(sess) return } if lower == "" { sess.WriteLine("Wear what?") return } g.cancelAction(p) qty, itemName := parseQty(input) matches := g.findInventoryMatches(itemName, p) if len(matches) == 0 { sess.WriteLine(fmt.Sprintf("You don't have any '%s'.", itemName)) return } unique := uniqueItemNames(matches) if len(unique) > 1 { sess.WriteLine("Equip what?") seen := make(map[string]bool) for _, m := range matches { if seen[m.Name] { continue } seen[m.Name] = true def, _ := g.ItemStore.Load(m.ID) sess.WriteLine(fmt.Sprintf(" - %s", g.itemColorize(sess, def, m.Name))) } return } match := matches[0] slot := p.InvSlot(match.Slot) if slot == nil { return } def, err := g.ItemStore.Load(slot.ItemID) if err != nil || def.EquipSlot() == "" { sess.WriteLine(fmt.Sprintf("You can't wear %s.", g.itemColorize(sess, def, match.Name))) return } if msg := g.checkRequirements(sess, p, def); msg != "" { sess.WriteLine(msg) return } if def.EquipSlot() == item.SlotAmmo && def.Stackable { g.equipAmmo(sess, p, match.Slot, slot, def, qty) return } existingItemID, slotOccupied := p.Equipment[def.EquipSlot()] if slotOccupied { freeSlot := p.FirstFreeSlot() if freeSlot == -1 && existingItemID != slot.ItemID { sess.WriteLine("Your inventory is full.") return } if freeSlot >= 0 { p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: existingItemID, Quantity: 1}) } } if slot.Quantity > 1 { slot.Quantity-- } else { p.SetInvSlot(match.Slot, nil) } if slot.Quality > 0 && slot.MaxQuality > 0 { if p.EquipQuality == nil { p.EquipQuality = make(map[string]int) } p.EquipQuality[slot.ItemID] = slot.Quality } p.Equipment[def.EquipSlot()] = slot.ItemID g.AccountStore.SaveCharacter(p) verb := "wear" if def.EquipmentType() != "" { verb = "wield" } 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 *item.ItemDef, qty int) { transferQty := slot.Quantity if qty > 0 && qty < transferQty { transferQty = qty } existingAmmoID, hasAmmo := p.Equipment[item.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[item.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[item.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, item.SlotAmmo) p.AmmoQty = 0 return } } freeSlot := p.FirstFreeSlot() if freeSlot >= 0 { p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: ammoID, Quantity: p.AmmoQty}) } delete(p.Equipment, item.SlotAmmo) p.AmmoQty = 0 } func (g *Game) doWearAll(sess *net.Session) { p := sess.Player g.cancelAction(p) bestPerSlot := make(map[item.EquipSlot]struct { itemID string value int invSlot int }) for i := 0; i < 28; i++ { slot := p.InvSlot(i) if slot == nil { continue } def, err := g.ItemStore.Load(slot.ItemID) if err != nil || def.EquipSlot() == "" { continue } if g.checkRequirements(sess, p, def) != "" { continue } current, exists := bestPerSlot[def.EquipSlot()] val := def.Value if def.EquipSlot() == item.SlotAmmo && def.Stackable { val = def.Value * slot.Quantity } if !exists || val > current.value { bestPerSlot[def.EquipSlot()] = struct { itemID string value int invSlot int }{slot.ItemID, val, i} } } if len(bestPerSlot) == 0 { sess.WriteLine("You have nothing to wear.") return } var equipped []string for eqSlot, best := range bestPerSlot { if existing, ok := p.Equipment[eqSlot]; ok && existing == best.itemID { if eqSlot != item.SlotAmmo { continue } } if eqSlot == item.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[item.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[item.SlotAmmo] = best.itemID p.AmmoQty = transferQty } equipped = append(equipped, g.itemColorize(sess, bestDef, bestDef.Name)) continue } } if existing, ok := p.Equipment[eqSlot]; ok { freeSlot := p.FirstFreeSlot() if freeSlot == -1 { continue } p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: existing, Quantity: 1}) } invSlot := p.InvSlot(best.invSlot) if invSlot != nil && invSlot.Quantity > 1 { invSlot.Quantity-- } else { p.SetInvSlot(best.invSlot, nil) } if invSlot != nil && invSlot.Quality > 0 && invSlot.MaxQuality > 0 { if p.EquipQuality == nil { p.EquipQuality = make(map[string]int) } p.EquipQuality[best.itemID] = invSlot.Quality } p.Equipment[eqSlot] = best.itemID def, _ := g.ItemStore.Load(best.itemID) name := best.itemID if def != nil { name = def.Name } equipped = append(equipped, g.itemColorize(sess, def, name)) } if len(equipped) == 0 { sess.WriteLine("Nothing new to wear.") } else { g.AccountStore.SaveCharacter(p) sess.Write("You wear: ") formatPickupList(sess, equipped) } }