Item Affixes (#328)

* main, d2common: load Magic/Rare/Unique Affix

* d2common: item affixes only

removed Rare/Unique Prefix/Suffix as those are related to monsters, not items.

* removed debug print from item_affix.go

* changed item affix type names for clarity, removed debug print from data_dictionary

* d2common: item affix datadict and records

Item Affixes are defined in `/data/global/excel/Magic{Prefix,Suffix}.txt`
Rare and Unique Pre/Suffixes seem to be for monsters, not items.

d2common: item affixes only

removed Rare/Unique Prefix/Suffix as those are related to monsters, not items.

removed debug print from item_affix.go

changed item affix type names for clarity, removed debug print from data_dictionary

* reverting to pre-allocating memory for parsing txt lines

* removing the rest of the rare/unique definitions

* removing the rest of the rare/unique definitions
This commit is contained in:
dk 2020-05-08 09:33:37 -07:00 committed by GitHub
parent ff4f0b0bfa
commit 515b66736d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 286 additions and 2 deletions

View File

@ -0,0 +1,255 @@
package d2datadict
import (
"fmt"
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
)
var MagicPrefixDictionary *d2common.DataDictionary
var MagicSuffixDictionary *d2common.DataDictionary
var MagicPrefixRecords []*ItemAffixCommonRecord
var MagicSuffixRecords []*ItemAffixCommonRecord
var AffixMagicGroups []*ItemAffixCommonGroup
var superType d2enum.ItemAffixSuperType
var subType d2enum.ItemAffixSubType
func LoadMagicPrefix(file []byte) {
superType = d2enum.ItemAffixPrefix
subType = d2enum.ItemAffixMagic
loadDictionary(file, MagicPrefixDictionary, superType, subType)
}
func LoadMagicSuffix(file []byte) {
superType = d2enum.ItemAffixSuffix
subType = d2enum.ItemAffixMagic
loadDictionary(file, MagicSuffixDictionary, superType, subType)
}
func getAffixString(t1 d2enum.ItemAffixSuperType, t2 d2enum.ItemAffixSubType) string {
var name string = ""
switch t2 {
case d2enum.ItemAffixMagic:
name = "Magic"
}
switch t1 {
case d2enum.ItemAffixPrefix:
name += "Prefix"
case d2enum.ItemAffixSuffix:
name += "Suffix"
}
return name
}
func loadDictionary(
file []byte,
dict *d2common.DataDictionary,
superType d2enum.ItemAffixSuperType,
subType d2enum.ItemAffixSubType,
) {
dict = d2common.LoadDataDictionary(string(file))
records := make([]*ItemAffixCommonRecord, 0)
createItemAffixRecords(dict, records, superType, subType)
name := getAffixString(superType, subType)
log.Printf("Loaded %d %s records", len(dict.Data), name)
}
// --- column names from d2exp.mpq:/data/globa/excel/MagicPrefix.txt
// Name
// version
// spawnable
// rare
// level
// maxlevel
// levelreq
// classspecific
// class
// classlevelreq
// frequency
// group
// mod1code
// mod1param
// mod1min
// mod1max
// mod2code
// mod2param
// mod2min
// mod2max
// mod3code
// mod3param
// mod3min
// mod3max
// transform
// transformcolor
// itype1
// itype2
// itype3
// itype4
// itype5
// itype6
// itype7
// etype1
// etype2
// etype3
// etype4
// etype5
// divide
// multiply
// add
func createItemAffixRecords(
d *d2common.DataDictionary,
r []*ItemAffixCommonRecord,
superType d2enum.ItemAffixSuperType,
subType d2enum.ItemAffixSubType,
) {
for index, _ := range d.Data {
affix := &ItemAffixCommonRecord{
Name: d.GetString("Name", index),
Version: d.GetNumber("version", index),
Type: subType,
IsPrefix: superType == d2enum.ItemAffixPrefix,
IsSuffix: superType == d2enum.ItemAffixSuffix,
Spawnable: d.GetNumber("spawnable", index) == 1,
Rare: d.GetNumber("rare", index) == 1,
Level: d.GetNumber("level", index),
MaxLevel: d.GetNumber("maxlevel", index),
LevelReq: d.GetNumber("levelreq", index),
Class: d.GetString("classspecific", index),
ClassLevelReq: d.GetNumber("classlevelreq", index),
Frequency: d.GetNumber("frequency", index),
GroupID: d.GetNumber("group", index),
Transform: d.GetNumber("transform", index) == 1,
TransformColor: d.GetString("transformcolor", index),
PriceAdd: d.GetNumber("add", index),
PriceScale: d.GetNumber("multiply", index),
}
// modifiers (Property 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.GetString(codeKey, index),
Parameter: d.GetNumber(paramKey, index),
Min: d.GetNumber(minKey, index),
Max: d.GetNumber(maxKey, index),
}
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.GetString(itemKey, index)
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.GetString(itemKey, index)
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)
r = append(r, affix)
}
}
var ItemAffixGroups map[int]*ItemAffixCommonGroup
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
}
type ItemAffixCommonModifier struct {
Code string
Parameter int
Min int
Max int
}
type ItemAffixCommonRecord struct {
Name string
Version int
Type d2enum.ItemAffixSubType
IsPrefix bool
IsSuffix bool
Spawnable bool
Rare bool
Level int
MaxLevel int
LevelReq int
Class string
ClassLevelReq int
Frequency int
GroupID int
Group *ItemAffixCommonGroup
Modifiers []*ItemAffixCommonModifier
Transform bool
TransformColor string
ItemInclude []string
ItemExclude []string
PriceAdd int
PriceScale int
}
func (a *ItemAffixCommonRecord) ProbabilityToSpawn(qlvl int) float64 {
if (qlvl > a.MaxLevel) || (qlvl < a.Level) {
return 0.0
}
p := (float64)(a.Frequency) / (float64)(a.Group.GetTotalFrequency())
return p
}

View File

@ -0,0 +1,14 @@
package d2enum
type ItemAffixSuperType int
type ItemAffixSubType int
const (
ItemAffixPrefix ItemAffixSuperType = iota
ItemAffixSuffix
)
const (
ItemAffixCommon ItemAffixSubType = iota
ItemAffixMagic
)

View File

@ -189,6 +189,17 @@ const (
Misc = "/data/global/excel/misc.txt"
UniqueItems = "/data/global/excel/UniqueItems.txt"
// --- Affixes ---
MagicPrefix = "/data/global/excel/MagicPrefix.txt"
MagicSuffix = "/data/global/excel/MagicSuffix.txt"
// --- Monster Prefix/Suffixes (?) ---
RarePrefix = "/data/global/excel/RarePrefix.txt"
RareSuffix = "/data/global/excel/RareSuffix.txt"
UniquePrefix = "/data/global/excel/UniquePrefix.txt"
UniqueSuffix = "/data/global/excel/UniqueSuffix.txt"
// --- Character Data ---
Experience = "/data/global/excel/experience.txt"

View File

@ -20,7 +20,7 @@ func LoadDataDictionary(text string) *DataDictionary {
for i, fieldName := range fileNames {
result.FieldNameLookup[fieldName] = i
}
result.Data = make([][]string, len(lines)-1)
result.Data = make([][]string, len(lines)-2)
for i, line := range lines[1:] {
if len(strings.TrimSpace(line)) == 0 {
continue
@ -39,7 +39,9 @@ func (v *DataDictionary) GetString(fieldName string, index int) string {
}
func (v *DataDictionary) GetNumber(fieldName string, index int) int {
result, err := strconv.Atoi(v.GetString(fieldName, index))
str := v.GetString(fieldName, index)
str = EmptyToZero(AsterToEmpty(str))
result, err := strconv.Atoi(str)
if err != nil {
log.Panic(err)
}

View File

@ -383,6 +383,8 @@ func loadDataDict() error {
{d2resource.SoundSettings, d2datadict.LoadSounds},
{d2resource.AnimationData, d2data.LoadAnimationData},
{d2resource.MonStats, d2datadict.LoadMonStats},
{d2resource.MagicPrefix, d2datadict.LoadMagicPrefix},
{d2resource.MagicSuffix, d2datadict.LoadMagicSuffix},
}
for _, entry := range entries {