OpenDiablo2/d2common/d2data/d2datadict/item_affix.go

232 lines
5.7 KiB
Go

package d2datadict
import (
"fmt"
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt"
)
// MagicPrefix stores all of the magic prefix records
// nolint:gochecknoglobals // Currently global by design
var MagicPrefix map[string]*ItemAffixCommonRecord
// MagicSuffix stores all of the magic suffix records
// nolint:gochecknoglobals // Currently global by design
var MagicSuffix map[string]*ItemAffixCommonRecord
// LoadMagicPrefix loads MagicPrefix.txt
func LoadMagicPrefix(file []byte) {
superType := d2enum.ItemAffixPrefix
subType := d2enum.ItemAffixMagic
MagicPrefix = loadDictionary(file, superType, subType)
}
// LoadMagicSuffix loads MagicSuffix.txt
func LoadMagicSuffix(file []byte) {
superType := d2enum.ItemAffixSuffix
subType := d2enum.ItemAffixMagic
MagicSuffix = loadDictionary(file, superType, subType)
}
func getAffixString(t1 d2enum.ItemAffixSuperType, t2 d2enum.ItemAffixSubType) string {
var name = ""
if t2 == d2enum.ItemAffixMagic {
name = "Magic"
}
switch t1 {
case d2enum.ItemAffixPrefix:
name += "Prefix"
case d2enum.ItemAffixSuffix:
name += "Suffix"
}
return name
}
func loadDictionary(
file []byte,
superType d2enum.ItemAffixSuperType,
subType d2enum.ItemAffixSubType,
) map[string]*ItemAffixCommonRecord {
d := d2txt.LoadDataDictionary(file)
records := createItemAffixRecords(d, superType, subType)
name := getAffixString(superType, subType)
log.Printf("Loaded %d %s records", len(records), name)
return records
}
func createItemAffixRecords(
d *d2txt.DataDictionary,
superType d2enum.ItemAffixSuperType,
subType d2enum.ItemAffixSubType,
) map[string]*ItemAffixCommonRecord {
records := make(map[string]*ItemAffixCommonRecord)
for d.Next() {
affix := &ItemAffixCommonRecord{
Name: d.String("Name"),
Version: d.Number("version"),
Type: subType,
IsPrefix: superType == d2enum.ItemAffixPrefix,
IsSuffix: superType == d2enum.ItemAffixSuffix,
Spawnable: d.Bool("spawnable"),
Rare: d.Bool("rare"),
Level: d.Number("level"),
MaxLevel: d.Number("maxlevel"),
LevelReq: d.Number("levelreq"),
Class: d.String("classspecific"),
ClassLevelReq: d.Number("classlevelreq"),
Frequency: d.Number("frequency"),
GroupID: d.Number("group"),
Transform: d.Bool("transform"),
TransformColor: d.String("transformcolor"),
PriceAdd: d.Number("add"),
PriceScale: d.Number("multiply"),
}
// modifiers (Code references with parameters to be eval'd)
for i := 1; i <= 3; i++ {
codeKey := fmt.Sprintf("mod%dcode", i)
paramKey := fmt.Sprintf("mod%dparam", i)
minKey := fmt.Sprintf("mod%dmin", i)
maxKey := fmt.Sprintf("mod%dmax", i)
modifier := &ItemAffixCommonModifier{
Code: d.String(codeKey),
Parameter: d.Number(paramKey),
Min: d.Number(minKey),
Max: d.Number(maxKey),
}
affix.Modifiers = append(affix.Modifiers, modifier)
}
// items to include for spawning
for i := 1; i <= 7; i++ {
itemKey := fmt.Sprintf("itype%d", i)
itemToken := d.String(itemKey)
affix.ItemInclude = append(affix.ItemInclude, itemToken)
}
// items to exclude for spawning
for i := 1; i <= 7; i++ {
itemKey := fmt.Sprintf("etype%d", i)
itemToken := d.String(itemKey)
affix.ItemExclude = append(affix.ItemExclude, itemToken)
}
// affix groupis
if ItemAffixGroups == nil {
ItemAffixGroups = make(map[int]*ItemAffixCommonGroup)
}
if _, found := ItemAffixGroups[affix.GroupID]; !found {
ItemAffixGroup := &ItemAffixCommonGroup{}
ItemAffixGroup.ID = affix.GroupID
ItemAffixGroups[affix.GroupID] = ItemAffixGroup
}
group := ItemAffixGroups[affix.GroupID]
group.addMember(affix)
records[affix.Name] = affix
}
if d.Err != nil {
panic(d.Err)
}
return records
}
// ItemAffixGroups are groups of MagicPrefix/Suffixes
var ItemAffixGroups map[int]*ItemAffixCommonGroup //nolint:gochecknoglobals // Currently global by design
// ItemAffixCommonGroup is a grouping that is common between prefix/suffix
type ItemAffixCommonGroup struct {
ID int
Members map[string]*ItemAffixCommonRecord
}
func (g *ItemAffixCommonGroup) addMember(a *ItemAffixCommonRecord) {
if g.Members == nil {
g.Members = make(map[string]*ItemAffixCommonRecord)
}
g.Members[a.Name] = a
}
func (g *ItemAffixCommonGroup) getTotalFrequency() int {
total := 0
for _, affix := range g.Members {
total += affix.Frequency
}
return total
}
// ItemAffixCommonModifier is the generic modifier form that prefix/suffix shares
// modifiers are like dynamic properties, they have a key that points to a property
// a parameter for the property, and a min/max value
type ItemAffixCommonModifier struct {
Code string
Parameter int
Min int
Max int
}
// ItemAffixCommonRecord is a common definition that both prefix and suffix use
type ItemAffixCommonRecord struct {
Group *ItemAffixCommonGroup
Modifiers []*ItemAffixCommonModifier
ItemInclude []string
ItemExclude []string
Name string
Class string
TransformColor string
Version int
Type d2enum.ItemAffixSubType
Level int
MaxLevel int
LevelReq int
ClassLevelReq int
Frequency int
GroupID int
PriceAdd int
PriceScale int
IsPrefix bool
IsSuffix bool
Spawnable bool
Rare bool
Transform bool
}
// ProbabilityToSpawn returns the chance of the affix spawning on an
// item with a given quality level
func (a *ItemAffixCommonRecord) ProbabilityToSpawn(qlvl int) float64 {
if (qlvl > a.MaxLevel) || (qlvl < a.Level) {
return 0
}
p := float64(a.Frequency) / float64(a.Group.getTotalFrequency())
return p
}