package main import ( "fmt" "math/bits" "strings" ) // Port of main.py's sophisticated equipment-slot translation, used to emit the // `slot_name` field. This is load-bearing for the suitbuilder: jewelry items get // an empty computed_slot_name (their EquipMask isn't an armor-coverage value, so // the SQL CONCAT_WS yields ''), and load_items falls back to slot_name // (`computed_slot_name or slot_name`) to bucket them as Left Ring / Neck / etc. // equipMaskEntry is one EquipMask enum row, kept in ascending-mask order so the // bit-flag decode joins parts deterministically (Left before Right). type equipMaskEntry struct { Mask int Name string } // equipFriendly maps technical EquipMask names to display names // (translate_equipment_slot's name_mapping, identical in both branches). var equipFriendly = map[string]string{ "HeadWear": "Head", "ChestWear": "Chest", "ChestArmor": "Chest", "AbdomenWear": "Abdomen", "AbdomenArmor": "Abdomen", "UpperArmWear": "Upper Arms", "UpperArmArmor": "Upper Arms", "LowerArmWear": "Lower Arms", "LowerArmArmor": "Lower Arms", "HandWear": "Hands", "UpperLegWear": "Upper Legs", "UpperLegArmor": "Upper Legs", "LowerLegWear": "Lower Legs", "LowerLegArmor": "Lower Legs", "FootWear": "Feet", "NeckWear": "Neck", "WristWearLeft": "Left Wrist", "WristWearRight": "Right Wrist", "FingerWearLeft": "Left Ring", "FingerWearRight": "Right Ring", "MeleeWeapon": "Melee Weapon", "Shield": "Shield", "MissileWeapon": "Missile Weapon", "MissileAmmo": "Ammo", "Held": "Held", "TwoHanded": "Two-Handed", "TrinketOne": "Trinket", "Cloak": "Cloak", "Robe": "Robe", } var commonSlots = map[int]string{ 30: "Shirt", 786432: "Left Ring, Right Ring", 262144: "Left Ring", 524288: "Right Ring", } func friendlySlot(name string) string { if f, ok := equipFriendly[name]; ok { return f } return name } func isBodyArmorEquipMask(v int) bool { return v&0x00007F21 != 0 } func isBodyArmorCoverageMask(v int) bool { return v&0x0001FF00 != 0 } func totalBitsSet(v int) int { return bits.OnesCount(uint(uint32(v))) } // getCoverageReductionOptions mirrors main.py:658. func getCoverageReductionOptions(coverage int) []int { const ( oUpperArms = 4096 oLowerArms = 8192 oUpperLegs = 256 oLowerLegs = 512 oChest = 1024 oAbdomen = 2048 head = 16384 hands = 32768 feet = 65536 ) if totalBitsSet(coverage) <= 1 || !isBodyArmorCoverageMask(coverage) { return []int{coverage} } switch coverage { case oUpperArms | oLowerArms: return []int{oUpperArms, oLowerArms} case oUpperLegs | oLowerLegs: return []int{oUpperLegs, oLowerLegs} case oLowerLegs | feet: return []int{feet} case oChest | oAbdomen: return []int{oChest} case oChest | oAbdomen | oUpperArms: return []int{oChest} case oChest | oUpperArms | oLowerArms: return []int{oChest} case oChest | oUpperArms: return []int{oChest} case oAbdomen | oUpperLegs | oLowerLegs: return []int{oAbdomen, oUpperLegs, oLowerLegs} case oChest | oAbdomen | oUpperArms | oLowerArms: return []int{oChest} case oAbdomen | oUpperLegs: return []int{oAbdomen} } return []int{coverage} } // coverageToEquipMask mirrors main.py:717. func coverageToEquipMask(coverage int) int { m := map[int]int{ 16384: 1, 1024: 512, 4096: 2048, 8192: 4096, 32768: 32, 2048: 1024, 256: 8192, 512: 16384, 65536: 256, } if v, ok := m[coverage]; ok { return v } return coverage } // getSophisticatedSlotOptions mirrors main.py:734. func getSophisticatedSlotOptions(equippableSlots, coverageValue int, hasMaterial bool) []int { const lowerLegWear, footWear = 128, 256 if equippableSlots == (lowerLegWear | footWear) { return []int{footWear} } if isBodyArmorEquipMask(equippableSlots) && totalBitsSet(equippableSlots) > 1 { if !hasMaterial { return []int{equippableSlots} } var slotOpts []int for _, o := range getCoverageReductionOptions(coverageValue) { slotOpts = append(slotOpts, coverageToEquipMask(o)) } if len(slotOpts) > 0 { return slotOpts } return []int{equippableSlots} } return []int{equippableSlots} } // translateEquipmentSlot mirrors main.py:807. func (s *Server) translateEquipmentSlot(loc int) string { if loc == 0 { return "Inventory" } if name, ok := s.equipMaskMap[loc]; ok { return friendlySlot(name) } if cs, ok := commonSlots[loc]; ok { return cs } var parts []string for _, e := range s.equipMaskOrdered { if e.Mask > 0 && loc&e.Mask == e.Mask { parts = append(parts, friendlySlot(e.Name)) } } if len(parts) > 0 { return strings.Join(parts, ", ") } if loc >= 268435456 { switch loc { case 268435456: return "Aetheria Blue" case 536870912: return "Aetheria Yellow" case 1073741824: return "Aetheria Red" default: return fmt.Sprintf("Special Slot (%d)", loc) } } return "-" } // computeSlotName mirrors the slot_name block in search_items (main.py:3977-4033). func (s *Server) computeSlotName(equippableSlots, coverageValue int, hasMaterial bool) string { if equippableSlots <= 0 { return "-" } opts := getSophisticatedSlotOptions(equippableSlots, coverageValue, hasMaterial) var names []string for _, o := range opts { n := s.translateEquipmentSlot(o) if n != "" && !containsString(names, n) { names = append(names, n) } } if len(names) > 0 { return strings.Join(names, ", ") } return "-" }