You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

257 lines
12 KiB
Go

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"},
},
}