OpenDiablo2/d2core/d2records/item_types_loader.go

166 lines
4.2 KiB
Go

package d2records
import (
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt"
)
// LoadItemTypes loads ItemType records
func itemTypesLoader(r *RecordManager, d *d2txt.DataDictionary) error {
records := make(ItemTypes)
charCodeMap := map[string]d2enum.Hero{
"ama": d2enum.HeroAmazon,
"ass": d2enum.HeroAssassin,
"bar": d2enum.HeroBarbarian,
"dru": d2enum.HeroDruid,
"nec": d2enum.HeroNecromancer,
"pal": d2enum.HeroPaladin,
"sor": d2enum.HeroSorceress,
}
for d.Next() {
if d.String("*eol") == "" {
continue
}
itemType := &ItemTypeRecord{
Name: d.String("ItemType"),
Code: d.String("Code"),
Equiv1: d.String("Equiv1"),
Equiv2: d.String("Equiv2"),
Repair: d.Number("Repair") > 0,
Body: d.Number("Body") > 0,
BodyLoc1: d.Number("BodyLoc1"),
BodyLoc2: d.Number("BodyLoc2"),
Shoots: d.String("Shoots"),
Quiver: d.String("Quiver"),
Throwable: d.Number("Throwable") > 0,
Reload: d.Number("Reload") > 0,
ReEquip: d.Number("ReEquip") > 0,
AutoStack: d.Number("AutoStack") > 0,
Magic: d.Number("Magic") > 0,
Rare: d.Number("Rare") > 0,
Normal: d.Number("Normal") > 0,
Charm: d.Number("Charm") > 0,
Gem: d.Number("Gem") > 0,
Beltable: d.Number("Beltable") > 0,
MaxSock1: d.Number("MaxSock1"),
MaxSock25: d.Number("MaxSock25"),
MaxSock40: d.Number("MaxSock40"),
TreasureClass: d.Number("TreasureClass"),
Rarity: d.Number("Rarity"),
StaffMods: charCodeMap[d.String("StaffMods")],
CostFormula: d.Number("CostFormula"),
Class: charCodeMap[d.String("Class")],
VarInvGfx: d.Number("VarInvGfx"),
InvGfx1: d.String("InvGfx1"),
InvGfx2: d.String("InvGfx2"),
InvGfx3: d.String("InvGfx3"),
InvGfx4: d.String("InvGfx4"),
InvGfx5: d.String("InvGfx5"),
InvGfx6: d.String("InvGfx6"),
StorePage: d.String("StorePage"),
}
records[itemType.Code] = itemType
}
equivMap := LoadItemEquivalencies(r.Item.All, records)
for idx := range records {
records[idx].EquivalentItems = equivMap[records[idx].Code]
}
if d.Err != nil {
return d.Err
}
r.Debugf("Loaded %d ItemType records", len(records))
r.Item.Types = records
r.Item.Equivalency = equivMap
return nil
}
// LoadItemEquivalencies loads a map of ItemType string codes to slices of ItemCommonRecord pointers
func LoadItemEquivalencies(allItems CommonItems, allTypes ItemTypes) ItemEquivalenceMap {
equivMap := make(ItemEquivalenceMap)
for typeCode := range allTypes {
code := []string{
typeCode,
allTypes[typeCode].Equiv1,
allTypes[typeCode].Equiv2,
}
for _, str := range code {
if str == "" {
continue
}
if equivMap[str] == nil {
equivMap[str] = make([]*ItemCommonRecord, 0)
}
}
}
for icrCode := range allItems {
commonItem := allItems[icrCode]
updateEquivalencies(allTypes, equivMap, commonItem, allTypes[commonItem.Type], nil)
if commonItem.Type2 != "" { // some items (like gems) have a secondary type
updateEquivalencies(allTypes, equivMap, commonItem, allTypes[commonItem.Type2], nil)
}
}
return equivMap
}
func updateEquivalencies(
allTypes ItemTypes,
equivMap ItemEquivalenceMap,
icr *ItemCommonRecord,
itemType *ItemTypeRecord,
checked []string,
) {
if itemType == nil {
log.Fatal("invalid data file. Please ensure, you're using the newest patch_d2.mpq file!")
}
if itemType.Code == "" {
return
}
if checked == nil {
checked = make([]string, 0)
}
checked = append(checked, itemType.Code)
if !itemEquivPresent(icr, equivMap[itemType.Code]) {
equivMap[itemType.Code] = append(equivMap[itemType.Code], icr)
}
if itemType.Equiv1 != "" {
updateEquivalencies(allTypes, equivMap, icr, allTypes[itemType.Equiv1], checked)
}
if itemType.Equiv2 != "" {
updateEquivalencies(allTypes, equivMap, icr, allTypes[itemType.Equiv2], checked)
}
}
func itemEquivPresent(icr *ItemCommonRecord, list []*ItemCommonRecord) bool {
for idx := range list {
if list[idx] == icr {
return true
}
}
return false
}