OpenDiablo2/d2common/d2data/d2datadict/itemstatcost.go

200 lines
6.5 KiB
Go

package d2datadict
import (
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt"
)
// ItemStatCostRecord represents a row from itemstatcost.txt
// these records describe the stat values and costs (in shops) of items
// refer to https://d2mods.info/forum/kb/viewarticle?a=448
type ItemStatCostRecord struct {
Name string
OpBase string
OpStat1 string
OpStat2 string
OpStat3 string
MaxStat string // if Direct true, will not exceed val of MaxStat
DescStrPos string // string used when val is positive
DescStrNeg string
DescStr2 string // additional string used by some string funcs
DescGroupStrPos string // string used when val is positive
DescGroupStrNeg string
DescGroupStr2 string // additional string used by some string funcs
// Stuff
// Stay far away from this column unless you really know what you're
// doing and / or work for Blizzard, this column is used during bin-file
// creation to generate a cache regulating the op-stat stuff and other
// things, changing it can be futile, it works like the constants column
// in MonUMod.txt and has no other relation to ItemStatCost.txt, the first
// stat in the file simply must have this set or else you may break the
// entire op stuff.
Stuff string
Index int
// path_d2.mpq version doesnt have Ranged columne, excluding for now
// Ranged bool // game attempts to keep stat in a range, like strength >-1
MinAccr int // minimum ranged value
SendBits int // #bits to send in stat update
SendParam int // #bits to send in stat update
SavedBits int // #bits allocated to the value in .d2s file
SaveBits int // #bits saved to .d2s files, max == 2^SaveBits-1
SaveAdd int // how large the negative range is (lowers max, as well)
SaveParamBits int // #param bits are saved (safe value is 17)
Encode d2enum.EncodingType // how the stat is encoded in .d2s files
// these two fields control additional cost on items
// cost * (1 + value * multiply / 1024)) + add (...)
CostAdd int
CostMultiply int
// CostDivide // exists in txt, but division hardcoded to 1024
// if divide is used, could we do (?):
// cost * (1 + value * multiply / divide)) + add (...)
ValShift int // controls how stat is stored in .d2s
// so that you can save `+1` instead of `+256`
OperatorType d2enum.OperatorType
OpParam int
EventID1 d2enum.ItemEventType
EventID2 d2enum.ItemEventType
EventFuncID1 d2enum.ItemEventFuncID
EventFuncID2 d2enum.ItemEventFuncID
DescPriority int // determines order when displayed
DescFnID int
// Controls whenever and if so in what way the stat value is shown
// 0 = doesn't show the value of the stat
// 1 = shows the value of the stat infront of the description
// 2 = shows the value of the stat after the description.
DescVal int
// when stats in the same group have the same value they use the
// group func for desc (they need to be in the same affix)
DescGroup int
DescGroupVal int
DescGroupFuncID int
CallbackEnabled bool // whether callback fn is called if value changes
Signed bool // whether the stat is signed
KeepZero bool // prevent from going negative (assume only client side)
UpdateAnimRate bool // when altered, forces speed handler to adjust speed
SendOther bool // whether to send to other clients
Saved bool // whether this stat is saved in .d2s files
SavedSigned bool // whether the stat is saved as signed/unsigned
Direct bool // whether is temporary or permanent
ItemSpecific bool // prevents stacking with an existing stat on item
// like when socketing a jewel
DamageRelated bool // prevents stacking of stats while dual wielding
}
// ItemStatCosts stores all of the ItemStatCostRecords
//nolint:gochecknoglobals // Currently global by design
var ItemStatCosts map[string]*ItemStatCostRecord
// LoadItemStatCosts loads ItemStatCostRecord's from text
func LoadItemStatCosts(file []byte) {
ItemStatCosts = make(map[string]*ItemStatCostRecord)
d := d2txt.LoadDataDictionary(file)
for d.Next() {
record := &ItemStatCostRecord{
Name: d.String("Stat"),
Index: d.Number("ID"),
Signed: d.Number("Signed") > 0,
KeepZero: d.Number("keepzero") > 0,
// Ranged: d.Number("Ranged") > 0,
MinAccr: d.Number("MinAccr"),
UpdateAnimRate: d.Number("UpdateAnimRate") > 0,
SendOther: d.Number("Send Other") > 0,
SendBits: d.Number("Send Bits"),
SendParam: d.Number("Send Param Bits"),
Saved: d.Number("CSvBits") > 0,
SavedSigned: d.Number("CSvSigned") > 0,
SavedBits: d.Number("CSvBits"),
SaveBits: d.Number("Save Bits"),
SaveAdd: d.Number("Save Add"),
SaveParamBits: d.Number("Save Param Bits"),
Encode: d2enum.EncodingType(d.Number("Encode")),
CallbackEnabled: d.Number("fCallback") > 0,
CostAdd: d.Number("Add"),
CostMultiply: d.Number("Multiply"),
ValShift: d.Number("ValShift"),
OperatorType: d2enum.OperatorType(d.Number("op")),
OpParam: d.Number("op param"),
OpBase: d.String("op base"),
OpStat1: d.String("op stat1"),
OpStat2: d.String("op stat2"),
OpStat3: d.String("op stat3"),
Direct: d.Number("direct") > 0,
MaxStat: d.String("maxstat"),
ItemSpecific: d.Number("itemspecific") > 0,
DamageRelated: d.Number("damagerelated") > 0,
EventID1: d2enum.GetItemEventType(d.String("itemevent1")),
EventID2: d2enum.GetItemEventType(d.String("itemevent2")),
EventFuncID1: d2enum.ItemEventFuncID(d.Number("itemeventfunc1")),
EventFuncID2: d2enum.ItemEventFuncID(d.Number("itemeventfunc2")),
DescPriority: d.Number("descpriority"),
DescFnID: d.Number("descfunc"),
// DescVal: d.Number("descval"), // needs special handling
DescStrPos: d.String("descstrpos"),
DescStrNeg: d.String("descstrneg"),
DescStr2: d.String("descstr2"),
DescGroup: d.Number("dgrp"),
DescGroupFuncID: d.Number("dgrpfunc"),
DescGroupVal: d.Number("dgrpval"),
DescGroupStrPos: d.String("dgrpstrpos"),
DescGroupStrNeg: d.String("dgrpstrneg"),
DescGroupStr2: d.String("dgrpstr2"),
Stuff: d.String("stuff"),
}
descValStr := d.String("descval")
switch descValStr {
case "2":
record.DescVal = 2
case "0":
record.DescVal = 0
default:
// handle empty fields, seems like they should have been 1
record.DescVal = 1
}
ItemStatCosts[record.Name] = record
}
if d.Err != nil {
panic(d.Err)
}
log.Printf("Loaded %d ItemStatCost records", len(ItemStatCosts))
}