package model import "math/rand" // GearItem represents any equippable item across all slots. type GearItem struct { ID int64 `json:"id"` Slot EquipmentSlot `json:"slot"` FormID string `json:"formId"` Name string `json:"name"` Subtype string `json:"subtype"` Rarity Rarity `json:"rarity"` Ilvl int `json:"ilvl"` BasePrimary int `json:"basePrimary"` PrimaryStat int `json:"primaryStat"` StatType string `json:"statType"` SpeedModifier float64 `json:"speedModifier"` CritChance float64 `json:"critChance"` AgilityBonus int `json:"agilityBonus"` SetName string `json:"setName,omitempty"` SpecialEffect string `json:"specialEffect,omitempty"` } // GearFamily is a template for generating gear drops from the unified catalog. type GearFamily struct { Slot EquipmentSlot FormID string Name string Subtype string // "daggers", "sword", "axe", "light", "medium", "heavy", "" BasePrimary int StatType string SpeedModifier float64 BaseCrit float64 AgilityBonus int SetName string SpecialEffect string } // GearCatalog is the unified catalog of all gear families. var GearCatalog []GearFamily // ArmorSetBonuses maps set names to their bonus description. var GearSetBonuses = map[string]string{ "Assassin's Set": "+crit_chance", "Knight's Set": "+defense", "Berserker's Set": "+attack", "Ancient Guardian's Set": "+all_stats", } func init() { // Weapons -> main_hand for _, w := range legacyWeapons { GearCatalog = append(GearCatalog, GearFamily{ Slot: SlotMainHand, FormID: "gear.form.main_hand." + string(w.Type), Name: w.Name, Subtype: string(w.Type), BasePrimary: w.Damage, StatType: "attack", SpeedModifier: w.Speed, BaseCrit: w.CritChance, SpecialEffect: w.SpecialEffect, }) } // Armors -> chest for _, a := range legacyArmors { GearCatalog = append(GearCatalog, GearFamily{ Slot: SlotChest, FormID: "gear.form.chest." + string(a.Type), Name: a.Name, Subtype: string(a.Type), BasePrimary: a.Defense, StatType: "defense", SpeedModifier: a.SpeedModifier, AgilityBonus: a.AgilityBonus, SetName: a.SetName, SpecialEffect: a.SpecialEffect, }) } // Extended equipment families -> head, feet, neck, hands, legs, cloak, finger, wrist for slot, families := range legacyEquipmentFamilies { for _, f := range families { GearCatalog = append(GearCatalog, GearFamily{ Slot: slot, FormID: f.FormID, Name: f.Name, BasePrimary: f.BasePrimary, StatType: f.StatType, SpeedModifier: 1.0, }) } } // Build the by-slot-and-rarity index. gearBySlot = make(map[EquipmentSlot][]GearFamily) for _, gf := range GearCatalog { gearBySlot[gf.Slot] = append(gearBySlot[gf.Slot], gf) } } var gearBySlot map[EquipmentSlot][]GearFamily // PickGearFamily selects a random gear family for the given slot. // Returns nil if no families exist for the slot. func PickGearFamily(slot EquipmentSlot) *GearFamily { families := gearBySlot[slot] if len(families) == 0 { return nil } f := families[rand.Intn(len(families))] return &f } // NewGearItem creates a GearItem from a family template with ilvl and rarity scaling applied. func NewGearItem(family *GearFamily, ilvl int, rarity Rarity) *GearItem { primary := ScalePrimary(family.BasePrimary, ilvl, rarity) return &GearItem{ Slot: family.Slot, FormID: family.FormID, Name: family.Name, Subtype: family.Subtype, Rarity: rarity, Ilvl: ilvl, BasePrimary: family.BasePrimary, PrimaryStat: primary, StatType: family.StatType, SpeedModifier: family.SpeedModifier, CritChance: family.BaseCrit, AgilityBonus: family.AgilityBonus, SetName: family.SetName, SpecialEffect: family.SpecialEffect, } } // ---------- Legacy data (moved from weapon.go, armor.go, equipment.go) ---------- // legacyWeaponEntry holds weapon catalog data for building the GearCatalog. type legacyWeaponEntry struct { Name string Type string Rarity Rarity Damage int Speed float64 CritChance float64 SpecialEffect string } var legacyWeapons = []legacyWeaponEntry{ // Daggers {Name: "Rusty Dagger", Type: "daggers", Rarity: RarityCommon, Damage: 3, Speed: 1.3, CritChance: 0.05}, {Name: "Iron Dagger", Type: "daggers", Rarity: RarityUncommon, Damage: 5, Speed: 1.3, CritChance: 0.08}, {Name: "Assassin's Blade", Type: "daggers", Rarity: RarityRare, Damage: 8, Speed: 1.35, CritChance: 0.20}, {Name: "Phantom Edge", Type: "daggers", Rarity: RarityEpic, Damage: 12, Speed: 1.4, CritChance: 0.25}, {Name: "Fang of the Void", Type: "daggers", Rarity: RarityLegendary, Damage: 18, Speed: 1.5, CritChance: 0.30}, // Swords {Name: "Iron Sword", Type: "sword", Rarity: RarityCommon, Damage: 7, Speed: 1.0, CritChance: 0.03}, {Name: "Steel Sword", Type: "sword", Rarity: RarityUncommon, Damage: 10, Speed: 1.0, CritChance: 0.05}, {Name: "Longsword", Type: "sword", Rarity: RarityRare, Damage: 15, Speed: 1.0, CritChance: 0.08}, {Name: "Excalibur", Type: "sword", Rarity: RarityEpic, Damage: 22, Speed: 1.05, CritChance: 0.10}, {Name: "Soul Reaver", Type: "sword", Rarity: RarityLegendary, Damage: 30, Speed: 1.1, CritChance: 0.12, SpecialEffect: "lifesteal"}, // Axes {Name: "Rusty Axe", Type: "axe", Rarity: RarityCommon, Damage: 12, Speed: 0.7, CritChance: 0.02}, {Name: "Battle Axe", Type: "axe", Rarity: RarityUncommon, Damage: 18, Speed: 0.7, CritChance: 0.04}, {Name: "War Axe", Type: "axe", Rarity: RarityRare, Damage: 25, Speed: 0.75, CritChance: 0.06}, {Name: "Infernal Axe", Type: "axe", Rarity: RarityEpic, Damage: 35, Speed: 0.75, CritChance: 0.08}, {Name: "Godslayer's Edge", Type: "axe", Rarity: RarityLegendary, Damage: 50, Speed: 0.8, CritChance: 0.10, SpecialEffect: "splash"}, } // legacyArmorEntry holds armor catalog data for building the GearCatalog. type legacyArmorEntry struct { Name string Type string Rarity Rarity Defense int SpeedModifier float64 AgilityBonus int SetName string SpecialEffect string } var legacyArmors = []legacyArmorEntry{ // Light armor {Name: "Leather Armor", Type: "light", Rarity: RarityCommon, Defense: 3, SpeedModifier: 1.05, AgilityBonus: 3}, {Name: "Ranger's Vest", Type: "light", Rarity: RarityUncommon, Defense: 5, SpeedModifier: 1.08, AgilityBonus: 5}, {Name: "Shadow Cloak", Type: "light", Rarity: RarityRare, Defense: 8, SpeedModifier: 1.10, AgilityBonus: 8, SetName: "Assassin's Set", SpecialEffect: "crit_bonus"}, {Name: "Phantom Garb", Type: "light", Rarity: RarityEpic, Defense: 12, SpeedModifier: 1.12, AgilityBonus: 12, SetName: "Assassin's Set", SpecialEffect: "crit_bonus"}, {Name: "Whisper of the Void", Type: "light", Rarity: RarityLegendary, Defense: 16, SpeedModifier: 1.15, AgilityBonus: 18, SetName: "Assassin's Set", SpecialEffect: "crit_bonus"}, // Medium armor {Name: "Chainmail", Type: "medium", Rarity: RarityCommon, Defense: 7, SpeedModifier: 1.0}, {Name: "Reinforced Mail", Type: "medium", Rarity: RarityUncommon, Defense: 10, SpeedModifier: 1.0}, {Name: "Battle Armor", Type: "medium", Rarity: RarityRare, Defense: 15, SpeedModifier: 1.0, SetName: "Knight's Set", SpecialEffect: "def_bonus"}, {Name: "Royal Guard", Type: "medium", Rarity: RarityEpic, Defense: 22, SpeedModifier: 1.0, SetName: "Knight's Set", SpecialEffect: "def_bonus"}, {Name: "Crown of Eternity", Type: "medium", Rarity: RarityLegendary, Defense: 30, SpeedModifier: 1.0, SetName: "Knight's Set", SpecialEffect: "def_bonus"}, // Heavy armor {Name: "Iron Plate", Type: "heavy", Rarity: RarityCommon, Defense: 14, SpeedModifier: 0.7, AgilityBonus: -3}, {Name: "Steel Plate", Type: "heavy", Rarity: RarityUncommon, Defense: 20, SpeedModifier: 0.7, AgilityBonus: -3}, {Name: "Fortress Armor", Type: "heavy", Rarity: RarityRare, Defense: 28, SpeedModifier: 0.7, AgilityBonus: -5, SetName: "Berserker's Set", SpecialEffect: "atk_bonus"}, {Name: "Dragon Scale", Type: "heavy", Rarity: RarityEpic, Defense: 38, SpeedModifier: 0.7, AgilityBonus: -5, SetName: "Berserker's Set", SpecialEffect: "atk_bonus"}, {Name: "Dragon Slayer", Type: "heavy", Rarity: RarityLegendary, Defense: 50, SpeedModifier: 0.7, AgilityBonus: -5, SetName: "Berserker's Set", SpecialEffect: "atk_bonus"}, // Ancient Guardian's Set {Name: "Guardian's Plate", Type: "heavy", Rarity: RarityRare, Defense: 30, SpeedModifier: 0.7, AgilityBonus: 2, SetName: "Ancient Guardian's Set", SpecialEffect: "all_stats"}, {Name: "Guardian's Bastion", Type: "heavy", Rarity: RarityEpic, Defense: 42, SpeedModifier: 0.7, AgilityBonus: 4, SetName: "Ancient Guardian's Set", SpecialEffect: "all_stats"}, {Name: "Ancient Guardian's Aegis", Type: "heavy", Rarity: RarityLegendary, Defense: 55, SpeedModifier: 0.7, AgilityBonus: 6, SetName: "Ancient Guardian's Set", SpecialEffect: "all_stats"}, } // legacyEquipmentFamily is the template used by the old equipment system. type legacyEquipmentFamily struct { Name string FormID string BasePrimary int StatType string } var legacyEquipmentFamilies = map[EquipmentSlot][]legacyEquipmentFamily{ SlotHead: { {Name: "Leather Cap", FormID: "gear.form.head.cap", BasePrimary: 2, StatType: "defense"}, {Name: "Iron Helmet", FormID: "gear.form.head.helmet", BasePrimary: 4, StatType: "defense"}, {Name: "Crown", FormID: "gear.form.head.crown", BasePrimary: 3, StatType: "mixed"}, }, SlotFeet: { {Name: "Sandals", FormID: "gear.form.feet.sandals", BasePrimary: 1, StatType: "speed"}, {Name: "Leather Boots", FormID: "gear.form.feet.boots", BasePrimary: 3, StatType: "defense"}, {Name: "Iron Greaves", FormID: "gear.form.feet.greaves", BasePrimary: 5, StatType: "defense"}, }, SlotNeck: { {Name: "Wooden Pendant", FormID: "gear.form.neck.pendant", BasePrimary: 2, StatType: "mixed"}, {Name: "Silver Amulet", FormID: "gear.form.neck.amulet", BasePrimary: 4, StatType: "attack"}, {Name: "Crystal Necklace", FormID: "gear.form.neck.necklace", BasePrimary: 3, StatType: "defense"}, }, SlotHands: { {Name: "Leather Gloves", FormID: "gear.form.hands.gloves", BasePrimary: 2, StatType: "defense"}, {Name: "Iron Gauntlets", FormID: "gear.form.hands.gauntlets", BasePrimary: 4, StatType: "defense"}, {Name: "Dragonhide Gloves", FormID: "gear.form.hands.gloves", BasePrimary: 3, StatType: "mixed"}, }, SlotLegs: { {Name: "Leather Leggings", FormID: "gear.form.legs.leggings", BasePrimary: 2, StatType: "defense"}, {Name: "Iron Greaves", FormID: "gear.form.legs.greaves", BasePrimary: 4, StatType: "defense"}, }, SlotCloak: { {Name: "Leather Cloak", FormID: "gear.form.cloak.cloak", BasePrimary: 2, StatType: "defense"}, {Name: "Iron Cape", FormID: "gear.form.cloak.cape", BasePrimary: 4, StatType: "defense"}, {Name: "Dragonhide Cloak", FormID: "gear.form.cloak.cloak", BasePrimary: 3, StatType: "mixed"}, }, SlotFinger: { {Name: "Wooden Ring", FormID: "gear.form.finger.ring", BasePrimary: 2, StatType: "mixed"}, {Name: "Silver Ring", FormID: "gear.form.finger.ring", BasePrimary: 4, StatType: "attack"}, {Name: "Crystal Ring", FormID: "gear.form.finger.ring", BasePrimary: 3, StatType: "defense"}, }, SlotWrist: { {Name: "Leather Bracers", FormID: "gear.form.wrist.bracers", BasePrimary: 2, StatType: "defense"}, {Name: "Iron Wristguards", FormID: "gear.form.wrist.wristguards", BasePrimary: 4, StatType: "defense"}, {Name: "Dragonhide Wristguards", FormID: "gear.form.wrist.wristguards", BasePrimary: 3, StatType: "mixed"}, }, }