mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-10-01 15:46:17 -04:00
DataDictionary loader for ItemStatCost (#333)
* adding rules for swap files to .gitignore * 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 * adding ItemStatCost data dict loader
This commit is contained in:
parent
80877380af
commit
a25e42518d
2
.gitignore
vendored
2
.gitignore
vendored
@ -8,4 +8,6 @@
|
|||||||
/OpenDiablo2.exe
|
/OpenDiablo2.exe
|
||||||
/OpenDiablo2
|
/OpenDiablo2
|
||||||
**/*.pprof
|
**/*.pprof
|
||||||
|
*.swp
|
||||||
|
.*.swp
|
||||||
tags
|
tags
|
320
d2common/d2data/d2datadict/itemstatcost.go
Normal file
320
d2common/d2data/d2datadict/itemstatcost.go
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
package d2datadict
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// refer to https://d2mods.info/forum/kb/viewarticle?a=448
|
||||||
|
type ItemStatCostRecord struct {
|
||||||
|
Name string
|
||||||
|
Index int
|
||||||
|
|
||||||
|
Signed bool // whether the stat is signed
|
||||||
|
KeepZero bool // prevent from going negative (assume only client side)
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
UpdateAnimRate bool // when altered, forces speed handler to adjust speed
|
||||||
|
|
||||||
|
SendOther bool // whether to send to other clients
|
||||||
|
SendBits int // #bits to send in stat update
|
||||||
|
SendParam int // #bits to send in stat update
|
||||||
|
|
||||||
|
Saved bool // whether this stat is saved in .d2s files
|
||||||
|
SavedSigned bool // whether the stat is saved as signed/unsigned
|
||||||
|
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 EncodingType // how the stat is encoded in .d2s files
|
||||||
|
|
||||||
|
CallbackEnabled bool // whether callback fn is called if value changes
|
||||||
|
|
||||||
|
// 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 OperatorType
|
||||||
|
OpParam int
|
||||||
|
OpBase string
|
||||||
|
OpStat1 string
|
||||||
|
OpStat2 string
|
||||||
|
OpStat3 string
|
||||||
|
|
||||||
|
Direct bool // whether is temporary or permanent
|
||||||
|
MaxStat string // if Direct true, will not exceed val of MaxStat
|
||||||
|
|
||||||
|
ItemSpecific bool // prevents stacking with an existing stat on item
|
||||||
|
// like when socketing a jewel
|
||||||
|
|
||||||
|
DamageRelated bool // prevents stacking of stats while dual wielding
|
||||||
|
|
||||||
|
EventID1 d2enum.ItemEventType
|
||||||
|
EventID2 d2enum.ItemEventType
|
||||||
|
EventFuncID1 d2enum.ItemEventFuncID
|
||||||
|
EventFuncID2 d2enum.ItemEventFuncID
|
||||||
|
|
||||||
|
DescPriority int // determines order when displayed
|
||||||
|
DescFnID d2enum.DescFuncID
|
||||||
|
DescFn interface{} // the sprintf func
|
||||||
|
|
||||||
|
// 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
|
||||||
|
DescStrPos string // string used when val is positive
|
||||||
|
DescStrNeg string
|
||||||
|
DescStr2 string // additional string used by some string funcs
|
||||||
|
|
||||||
|
// 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
|
||||||
|
DescGroupFuncID d2enum.DescFuncID
|
||||||
|
DescGroupFn interface{} // group sprintf func
|
||||||
|
DescGroupVal int
|
||||||
|
DescGroupStrPos string // string used when val is positive
|
||||||
|
DescGroupStrNeg string
|
||||||
|
DescGroupStr2 string // additional string used by some string funcs
|
||||||
|
|
||||||
|
// 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 // ? TODO ?
|
||||||
|
}
|
||||||
|
|
||||||
|
type EncodingType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// TODO: determine other encoding types.
|
||||||
|
// didn't see anything about how this stuff is encoded, or the types...
|
||||||
|
EncodeDefault = EncodingType(iota)
|
||||||
|
)
|
||||||
|
|
||||||
|
type OperatorType int // for dynamic properties
|
||||||
|
|
||||||
|
const (
|
||||||
|
// just adds the stat to the unit directly
|
||||||
|
OpDefault = OperatorType(iota)
|
||||||
|
|
||||||
|
// adds opstat.base * statvalue / 100 to the opstat.
|
||||||
|
Op1
|
||||||
|
|
||||||
|
// adds (statvalue * basevalue) / (2 ^ param) to the opstat
|
||||||
|
// this does not work properly with any stat other then level because of the
|
||||||
|
// way this is updated, it is only refreshed when you re-equip the item,
|
||||||
|
// your character is saved or you level up, similar to passive skills, just
|
||||||
|
// because it looks like it works in the item description
|
||||||
|
// does not mean it does, the game just recalculates the information in the
|
||||||
|
// description every frame, while the values remain unchanged serverside.
|
||||||
|
Op2
|
||||||
|
|
||||||
|
// this is a percentage based version of op #2
|
||||||
|
// look at op #2 for information about the formula behind it, just
|
||||||
|
// remember the stat is increased by a percentage rather then by adding
|
||||||
|
// an integer.
|
||||||
|
Op3
|
||||||
|
|
||||||
|
// this works the same way op #2 works, however the stat bonus is
|
||||||
|
// added to the item and not to the player (so that +defense per level
|
||||||
|
// properly adds the defense to the armor and not to the character
|
||||||
|
// directly!)
|
||||||
|
Op4
|
||||||
|
|
||||||
|
// this works like op #4 but is percentage based, it is used for percentage
|
||||||
|
// based increase of stats that are found on the item itself, and not stats
|
||||||
|
// that are found on the character.
|
||||||
|
Op5
|
||||||
|
|
||||||
|
// like for op #7, however this adds a plain bonus to the stat, and just
|
||||||
|
// like #7 it also doesn't work so I won't bother to explain the arithmetic
|
||||||
|
// behind it either.
|
||||||
|
Op6
|
||||||
|
|
||||||
|
// this is used to increase a stat based on the current daytime of the game
|
||||||
|
// world by a percentage, there is no need to explain the arithmetics
|
||||||
|
// behind it because frankly enough it just doesn't work serverside, it
|
||||||
|
// only updates clientside so this op is essentially useless.
|
||||||
|
Op7
|
||||||
|
|
||||||
|
// hardcoded to work only with maxmana, this will apply the proper amount
|
||||||
|
// of mana to your character based on CharStats.txt for the amount of energy
|
||||||
|
// the stat added (doesn't work for non characters)
|
||||||
|
Op8
|
||||||
|
|
||||||
|
// hardcoded to work only with maxhp and maxstamina, this will apply the
|
||||||
|
// proper amount of maxhp and maxstamina to your character based on
|
||||||
|
// CharStats.txt for the amount of vitality the stat added (doesn't work
|
||||||
|
// for non characters)
|
||||||
|
Op9
|
||||||
|
|
||||||
|
// doesn't do anything, this has no switch case in the op function.
|
||||||
|
Op10
|
||||||
|
|
||||||
|
// adds opstat.base * statvalue / 100 similar to 1 and 13, the code just
|
||||||
|
// does a few more checks
|
||||||
|
Op11
|
||||||
|
|
||||||
|
// doesn't do anything, this has no switch case in the op function.
|
||||||
|
Op12
|
||||||
|
|
||||||
|
// adds opstat.base * statvalue / 100 to the value of opstat, this is
|
||||||
|
// useable only on items it will not apply the bonus to other unit types
|
||||||
|
// (this is why it is used for +% durability, +% level requirement,
|
||||||
|
// +% damage, +% defense ).
|
||||||
|
Op13
|
||||||
|
)
|
||||||
|
|
||||||
|
/* column names from path_d2.mpq/data/global/excel/ItemStatCost.txt
|
||||||
|
Stat
|
||||||
|
ID
|
||||||
|
Send Other
|
||||||
|
Signed
|
||||||
|
Send Bits
|
||||||
|
Send Param Bits
|
||||||
|
UpdateAnimRate
|
||||||
|
Saved
|
||||||
|
CSvSigned
|
||||||
|
CSvBits
|
||||||
|
CSvParam
|
||||||
|
fCallback
|
||||||
|
fMin
|
||||||
|
MinAccr
|
||||||
|
Encode
|
||||||
|
Add
|
||||||
|
Multiply
|
||||||
|
Divide
|
||||||
|
ValShift
|
||||||
|
1.09-Save Bits
|
||||||
|
1.09-Save Add
|
||||||
|
Save Bits
|
||||||
|
Save Add
|
||||||
|
Save Param Bits
|
||||||
|
keepzero
|
||||||
|
op
|
||||||
|
op param
|
||||||
|
op base
|
||||||
|
op stat1
|
||||||
|
op stat2
|
||||||
|
op stat3
|
||||||
|
direct
|
||||||
|
maxstat
|
||||||
|
itemspecific
|
||||||
|
damagerelated
|
||||||
|
itemevent1
|
||||||
|
itemeventfunc1
|
||||||
|
itemevent2
|
||||||
|
itemeventfunc2
|
||||||
|
descpriority
|
||||||
|
descfunc
|
||||||
|
descval
|
||||||
|
descstrpos
|
||||||
|
descstrneg
|
||||||
|
descstr2
|
||||||
|
dgrp
|
||||||
|
dgrpfunc
|
||||||
|
dgrpval
|
||||||
|
dgrpstrpos
|
||||||
|
dgrpstrneg
|
||||||
|
dgrpstr2
|
||||||
|
stuff
|
||||||
|
*eol
|
||||||
|
*/
|
||||||
|
|
||||||
|
var ItemStatCosts map[string]*ItemStatCostRecord
|
||||||
|
|
||||||
|
func LoadItemStatCosts(file []byte) {
|
||||||
|
ItemStatCosts = make(map[string]*ItemStatCostRecord, 0)
|
||||||
|
d := d2common.LoadDataDictionary(string(file))
|
||||||
|
r := make([]*ItemStatCostRecord, 0)
|
||||||
|
|
||||||
|
for idx, _ := range d.Data {
|
||||||
|
record := &ItemStatCostRecord{
|
||||||
|
Name: d.GetString("Stat", idx),
|
||||||
|
Index: d.GetNumber("ID", idx),
|
||||||
|
|
||||||
|
Signed: d.GetNumber("Signed", idx) > 0,
|
||||||
|
KeepZero: d.GetNumber("keepzero", idx) > 0,
|
||||||
|
|
||||||
|
// Ranged: d.GetNumber("Ranged", idx) > 0,
|
||||||
|
MinAccr: d.GetNumber("MinAccr", idx),
|
||||||
|
|
||||||
|
UpdateAnimRate: d.GetNumber("UpdateAnimRate", idx) > 0,
|
||||||
|
|
||||||
|
SendOther: d.GetNumber("Send Other", idx) > 0,
|
||||||
|
SendBits: d.GetNumber("Send Bits", idx),
|
||||||
|
SendParam: d.GetNumber("Send Param Bits", idx),
|
||||||
|
|
||||||
|
Saved: d.GetNumber("CSvBits", idx) > 0,
|
||||||
|
SavedSigned: d.GetNumber("CSvSigned", idx) > 0,
|
||||||
|
SavedBits: d.GetNumber("CSvBits", idx),
|
||||||
|
SaveBits: d.GetNumber("Save Bits", idx),
|
||||||
|
SaveAdd: d.GetNumber("Save Add", idx),
|
||||||
|
SaveParamBits: d.GetNumber("Save Param Bits", idx),
|
||||||
|
|
||||||
|
Encode: EncodingType(d.GetNumber("Encode", idx)),
|
||||||
|
|
||||||
|
CallbackEnabled: d.GetNumber("fCallback", idx) > 0,
|
||||||
|
|
||||||
|
CostAdd: d.GetNumber("Add", idx),
|
||||||
|
CostMultiply: d.GetNumber("Multiply", idx),
|
||||||
|
ValShift: d.GetNumber("ValShift", idx),
|
||||||
|
|
||||||
|
OperatorType: OperatorType(d.GetNumber("op", idx)),
|
||||||
|
OpParam: d.GetNumber("op param", idx),
|
||||||
|
OpBase: d.GetString("op base", idx),
|
||||||
|
OpStat1: d.GetString("op stat1", idx),
|
||||||
|
OpStat2: d.GetString("op stat2", idx),
|
||||||
|
OpStat3: d.GetString("op stat3", idx),
|
||||||
|
|
||||||
|
Direct: d.GetNumber("direct", idx) > 0,
|
||||||
|
MaxStat: d.GetString("maxstat", idx),
|
||||||
|
|
||||||
|
ItemSpecific: d.GetNumber("itemspecific", idx) > 0,
|
||||||
|
DamageRelated: d.GetNumber("damagerelated", idx) > 0,
|
||||||
|
|
||||||
|
EventID1: d2enum.GetItemEventType(d.GetString("itemevent1", idx)),
|
||||||
|
EventID2: d2enum.GetItemEventType(d.GetString("itemevent2", idx)),
|
||||||
|
EventFuncID1: d2enum.GetItemEventFuncID(d.GetNumber("itemeventfunc1", idx)),
|
||||||
|
EventFuncID2: d2enum.GetItemEventFuncID(d.GetNumber("itemeventfunc2", idx)),
|
||||||
|
|
||||||
|
DescPriority: d.GetNumber("descpriority", idx),
|
||||||
|
DescFnID: d2enum.DescFuncID(d.GetNumber("descfunc", idx)),
|
||||||
|
DescFn: d2enum.GetDescFunction(d2enum.DescFuncID(d.GetNumber("descfunc", idx))),
|
||||||
|
DescVal: d.GetNumber("descval", idx),
|
||||||
|
DescStrPos: d.GetString("descstrpos", idx),
|
||||||
|
DescStrNeg: d.GetString("descstrneg", idx),
|
||||||
|
DescStr2: d.GetString("descstr2", idx),
|
||||||
|
|
||||||
|
DescGroup: d.GetNumber("dgrp", idx),
|
||||||
|
DescGroupFuncID: d2enum.DescFuncID(d.GetNumber("dgrpfunc", idx)),
|
||||||
|
DescGroupFn: d2enum.GetDescFunction(d2enum.DescFuncID(d.GetNumber("dgrpfunc", idx))),
|
||||||
|
DescGroupVal: d.GetNumber("dgrpval", idx),
|
||||||
|
DescGroupStrPos: d.GetString("dgrpstrpos", idx),
|
||||||
|
DescGroupStrNeg: d.GetString("dgrpstrneg", idx),
|
||||||
|
DescGroupStr2: d.GetString("dgrpstr2", idx),
|
||||||
|
|
||||||
|
Stuff: d.GetString("stuff", idx),
|
||||||
|
}
|
||||||
|
|
||||||
|
r = append(r, record)
|
||||||
|
}
|
||||||
|
log.Printf("Loaded %d ItemStatCost records", len(r))
|
||||||
|
}
|
194
d2common/d2enum/description_functions.go
Normal file
194
d2common/d2enum/description_functions.go
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
package d2enum
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DescFuncID int
|
||||||
|
|
||||||
|
func Format1(value float64, string1 string) string {
|
||||||
|
// +[value] [string1]
|
||||||
|
return fmt.Sprintf("+%f %s", value, string1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format2(value float64, string1 string) string {
|
||||||
|
// [value]% [string1]
|
||||||
|
return fmt.Sprintf("%f%% %s", value, string1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format3(value float64, string1 string) string {
|
||||||
|
// [value] [string1]
|
||||||
|
return fmt.Sprintf("%f %s", value, string1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format4(value float64, string1 string) string {
|
||||||
|
// +[value]% [string1]
|
||||||
|
return fmt.Sprintf("+%f%% %s", value, string1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format5(value float64, string1 string) string {
|
||||||
|
// [value*100/128]% [string1]
|
||||||
|
return fmt.Sprintf("%f%% %s", (value*100.0)/128.0, string1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format6(value float64, string1, string2 string) string {
|
||||||
|
// +[value] [string1] [string2]
|
||||||
|
return fmt.Sprintf("+%f %s %s", value, string1, string2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format7(value float64, string1, string2 string) string {
|
||||||
|
// [value]% [string1] [string2]
|
||||||
|
return fmt.Sprintf("%f%% %s %s", value, string1, string2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format8(value float64, string1, string2 string) string {
|
||||||
|
// +[value]% [string1] [string2]
|
||||||
|
return fmt.Sprintf("+%f%% %s %s", value, string1, string2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format9(value float64, string1, string2 string) string {
|
||||||
|
// [value] [string1] [string2]
|
||||||
|
return fmt.Sprintf("%f %s %s", value, string1, string2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format10(value float64, string1, string2 string) string {
|
||||||
|
// [value*100/128]% [string1] [string2]
|
||||||
|
return fmt.Sprintf("%f%% %s %s", (value*100.0)/128.0, string1, string2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format11(value float64) string {
|
||||||
|
// Repairs 1 Durability In [100 / value] Seconds
|
||||||
|
return fmt.Sprintf("Repairs 1 Durability In %.0f Seconds", 100.0/value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format12(value float64, string1 string) string {
|
||||||
|
// +[value] [string1]
|
||||||
|
return fmt.Sprintf("+%f %s", value, string1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format13(value float64, class string) string {
|
||||||
|
// +[value] to [class] Skill Levels
|
||||||
|
return fmt.Sprintf("+%.0f to %s Skill Levels", value, class)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format14(value float64, skilltab, class string) string {
|
||||||
|
// +[value] to [skilltab] Skill Levels ([class] Only)
|
||||||
|
fmtStr := "+%.0f to %s Skill Levels (%s Only)"
|
||||||
|
return fmt.Sprintf(fmtStr, value, skilltab, class)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format15(value float64, slvl int, skill, event string) string {
|
||||||
|
// [value]% chance to cast [slvl] [skill] on [event]
|
||||||
|
fmtStr := "%.0f%% chance to cast %d %s on %s"
|
||||||
|
return fmt.Sprintf(fmtStr, value, slvl, skill, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format16(slvl int, skill string) string {
|
||||||
|
// Level [sLvl] [skill] Aura When Equipped
|
||||||
|
return fmt.Sprintf("Level %d %s Aura When Equipped", slvl, skill)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format17(value float64, string1 string, time int) string {
|
||||||
|
// [value] [string1] (Increases near [time])
|
||||||
|
return fmt.Sprintf("%f %s (Increases near %d)", value, string1, time)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format18(value float64, string1 string, time int) string {
|
||||||
|
// [value]% [string1] (Increases near [time])
|
||||||
|
return fmt.Sprintf("%f%% %s (Increases near %d)", value, string1, time)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format19(value float64, string1 string) string {
|
||||||
|
// this is used by stats that use Blizzard's sprintf implementation
|
||||||
|
// (if you don't know what that is, it won't be of interest to you
|
||||||
|
// eitherway I guess), look at how prismatic is setup, the string is
|
||||||
|
// the format that gets passed to their sprintf spinoff.
|
||||||
|
return "" // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format20(value float64, string1 string) string {
|
||||||
|
// [value * -1]% [string1]
|
||||||
|
return fmt.Sprintf("%f%% %s", value*-1.0, string1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format21(value float64, string1 string) string {
|
||||||
|
// [value * -1] [string1]
|
||||||
|
return fmt.Sprintf("%f %s", value*-1.0, string1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format22(value float64, string1, montype string) string {
|
||||||
|
// [value]% [string1] [montype]
|
||||||
|
return fmt.Sprintf("%f%% %s %s", value, string1, montype)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format23(value float64, string1 string) string {
|
||||||
|
// (warning: this is bugged in vanilla and doesn't work properly
|
||||||
|
// see CE forum)
|
||||||
|
return "" // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format24(value float64, string1, monster string) string {
|
||||||
|
// [value]% [string1] [monster]
|
||||||
|
return fmt.Sprintf("%f%% %s %s", value, string1, monster)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format25(slvl float64, skill string, charges, maxCharges int) string {
|
||||||
|
// Level [slvl] [skill] ([charges]/[maxCharges] Charges)
|
||||||
|
fmtStr := "Level %.0f %s (%d/%d Charges)"
|
||||||
|
return fmt.Sprintf(fmtStr, slvl, skill, charges, maxCharges)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format26(value float64, string1 string) string {
|
||||||
|
// not used by vanilla, present in the code but I didn't test it yet
|
||||||
|
return "" // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format27(value float64, string1 string) string {
|
||||||
|
// not used by vanilla, present in the code but I didn't test it yet
|
||||||
|
return "" // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format28(value float64, skill, class string) string {
|
||||||
|
// +[value] to [skill] ([class] Only)
|
||||||
|
return fmt.Sprintf("+%f to %s (%s Only)", value, skill, class)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Format29(value float64, skill string) string {
|
||||||
|
// +[value] to [skill]
|
||||||
|
return fmt.Sprintf("+%.0f to %s", value, skill)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDescFunction(n DescFuncID) interface{} {
|
||||||
|
m := map[DescFuncID]interface{}{
|
||||||
|
DescFuncID(0): Format1,
|
||||||
|
DescFuncID(1): Format2,
|
||||||
|
DescFuncID(2): Format3,
|
||||||
|
DescFuncID(3): Format4,
|
||||||
|
DescFuncID(4): Format5,
|
||||||
|
DescFuncID(5): Format6,
|
||||||
|
DescFuncID(6): Format7,
|
||||||
|
DescFuncID(7): Format8,
|
||||||
|
DescFuncID(8): Format9,
|
||||||
|
DescFuncID(9): Format10,
|
||||||
|
DescFuncID(10): Format11,
|
||||||
|
DescFuncID(11): Format12,
|
||||||
|
DescFuncID(12): Format13,
|
||||||
|
DescFuncID(13): Format14,
|
||||||
|
DescFuncID(14): Format15,
|
||||||
|
DescFuncID(15): Format16,
|
||||||
|
DescFuncID(16): Format17,
|
||||||
|
DescFuncID(17): Format18,
|
||||||
|
DescFuncID(18): Format19,
|
||||||
|
DescFuncID(19): Format20,
|
||||||
|
DescFuncID(20): Format21,
|
||||||
|
DescFuncID(21): Format22,
|
||||||
|
DescFuncID(22): Format23,
|
||||||
|
DescFuncID(23): Format24,
|
||||||
|
DescFuncID(24): Format25,
|
||||||
|
DescFuncID(25): Format26,
|
||||||
|
DescFuncID(26): Format27,
|
||||||
|
DescFuncID(27): Format28,
|
||||||
|
DescFuncID(28): Format29,
|
||||||
|
}
|
||||||
|
return m[n]
|
||||||
|
}
|
143
d2common/d2enum/item_event_functions.go
Normal file
143
d2common/d2enum/item_event_functions.go
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
package d2enum
|
||||||
|
|
||||||
|
type ItemEventFuncID int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// shoots a missile at the owner of a missile that has just hit you
|
||||||
|
// (Chilling Armor uses this)
|
||||||
|
ReflectMissile = ItemEventFuncID(iota)
|
||||||
|
|
||||||
|
// freezes the attacker for a set duration the attacker
|
||||||
|
// (Frozen Armor uses this)
|
||||||
|
FreezeAttacker
|
||||||
|
|
||||||
|
// does cold damage to and chills the attacker (Shiver Armor uses this)
|
||||||
|
FreezeChillAttacker
|
||||||
|
|
||||||
|
// % of damage taken is done to the attacker
|
||||||
|
// (Iron Maiden, thorns uses a hardcoded stat)
|
||||||
|
ReflectPercentDamage
|
||||||
|
|
||||||
|
// % of damage done added to life, bypassing the targets resistance
|
||||||
|
// (used by Life Tap)
|
||||||
|
DamageDealtToHealth
|
||||||
|
|
||||||
|
// attacker takes physical damage of #
|
||||||
|
AttackerTakesPhysical
|
||||||
|
|
||||||
|
// knocks the target back
|
||||||
|
Knockback
|
||||||
|
|
||||||
|
// induces fear in the target making it run away
|
||||||
|
InduceFear
|
||||||
|
|
||||||
|
// applies Dim Vision to the target (it casts the actual curse on the
|
||||||
|
// monster)
|
||||||
|
BlindTarget
|
||||||
|
|
||||||
|
// attacker takes lightning damage of #
|
||||||
|
AttackerTakesLightning
|
||||||
|
|
||||||
|
// attacker takes fire damage of #
|
||||||
|
AttackerTakesFire
|
||||||
|
|
||||||
|
// attacker takes cold damage of #
|
||||||
|
AttackerTakesCold
|
||||||
|
|
||||||
|
// % damage taken is added to mana
|
||||||
|
DamageTakenToMana
|
||||||
|
|
||||||
|
// freezes the target
|
||||||
|
FreezeTarget
|
||||||
|
|
||||||
|
// causes the target to bleed and lose life (negative life regen)
|
||||||
|
OpenWounds
|
||||||
|
|
||||||
|
// crushing blow against the target
|
||||||
|
CrushingBlow
|
||||||
|
|
||||||
|
// mana after killing a monster
|
||||||
|
ManaOnKillMonster
|
||||||
|
|
||||||
|
// life after killing a demon
|
||||||
|
LifeOnKillDemon
|
||||||
|
|
||||||
|
// slows the target
|
||||||
|
SlowTarget
|
||||||
|
|
||||||
|
// casts a skill against the defender
|
||||||
|
CastSkillAgainstDefender
|
||||||
|
|
||||||
|
// casts a skill against the attacker
|
||||||
|
CastSkillAgainstAttacker
|
||||||
|
|
||||||
|
// absorbs physical damage taken (used by Bone Armor)
|
||||||
|
AbsorbPhysical
|
||||||
|
|
||||||
|
// transfers damage done from the summon to the owner (used by Blood Golem)
|
||||||
|
TakeSummonDamage
|
||||||
|
|
||||||
|
// used by Energy Shield to absorb damage and shift it from life to mana
|
||||||
|
ManaAbsorbsDamage
|
||||||
|
|
||||||
|
// absorbs elemental damage taken (used by Cyclone Armor)
|
||||||
|
AbsorbElementalDamage
|
||||||
|
|
||||||
|
// transfers damage taken from the summon to the owner (used by Blood Golem)
|
||||||
|
TakeSummonDamage2
|
||||||
|
|
||||||
|
// used to slow the attacker if he hits a unit that has the slow target stat
|
||||||
|
// (used by Clay Golem)
|
||||||
|
TargetSlowsTarget
|
||||||
|
|
||||||
|
// life after killing a monster
|
||||||
|
LifeOnKillMonster
|
||||||
|
|
||||||
|
// destroys the corpse of a killed monster (rest in peace effect)
|
||||||
|
RestInPeace
|
||||||
|
|
||||||
|
// cast a skill when the event occurs, without a target
|
||||||
|
CastSkillWithoutTarget
|
||||||
|
|
||||||
|
// reanimate the target as the specified monster
|
||||||
|
ReanimateTargetAsMonster
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetItemEventFuncID(n int) ItemEventFuncID {
|
||||||
|
m := map[int]ItemEventFuncID{
|
||||||
|
0: ReflectMissile,
|
||||||
|
1: FreezeAttacker,
|
||||||
|
2: FreezeChillAttacker,
|
||||||
|
3: ReflectPercentDamage,
|
||||||
|
4: DamageDealtToHealth,
|
||||||
|
5: AttackerTakesPhysical,
|
||||||
|
6: Knockback,
|
||||||
|
7: InduceFear,
|
||||||
|
8: BlindTarget,
|
||||||
|
9: AttackerTakesLightning,
|
||||||
|
10: AttackerTakesFire,
|
||||||
|
11: AttackerTakesCold,
|
||||||
|
12: DamageTakenToMana,
|
||||||
|
13: FreezeTarget,
|
||||||
|
14: OpenWounds,
|
||||||
|
15: CrushingBlow,
|
||||||
|
16: ManaOnKillMonster,
|
||||||
|
17: LifeOnKillDemon,
|
||||||
|
18: SlowTarget,
|
||||||
|
19: CastSkillAgainstDefender,
|
||||||
|
20: CastSkillAgainstAttacker,
|
||||||
|
21: AbsorbPhysical,
|
||||||
|
22: TakeSummonDamage,
|
||||||
|
23: ManaAbsorbsDamage,
|
||||||
|
24: AbsorbElementalDamage,
|
||||||
|
25: TakeSummonDamage2,
|
||||||
|
26: TargetSlowsTarget,
|
||||||
|
27: LifeOnKillMonster,
|
||||||
|
28: RestInPeace,
|
||||||
|
29: CastSkillWithoutTarget,
|
||||||
|
30: ReanimateTargetAsMonster,
|
||||||
|
}
|
||||||
|
return m[n]
|
||||||
|
}
|
||||||
|
|
||||||
|
//? do i need to do this ? //go:generate stringer -linecomment -type AnimationMode
|
39
d2common/d2enum/item_events.go
Normal file
39
d2common/d2enum/item_events.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package d2enum
|
||||||
|
|
||||||
|
// used in ItemStatCost
|
||||||
|
type ItemEventType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
HitByMissile = ItemEventType(iota) // hit By a Missile
|
||||||
|
DamagedInMelee // Damaged in Melee
|
||||||
|
DamagedByMissile // Damaged By Missile
|
||||||
|
AttackedInMelee // melee Attack atttempt
|
||||||
|
DoActive // do active state skill
|
||||||
|
DoMeleeDamage // do damage in melee
|
||||||
|
DoMissileDamage // do missile damage
|
||||||
|
DoMeleeAttack // do melee attack
|
||||||
|
DoMissileAttack // do missile attack
|
||||||
|
Kill // killed something
|
||||||
|
Killed // killed By something
|
||||||
|
AbsorbDamage // dealt damage
|
||||||
|
LevelUp // gain a level
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetItemEventType(s string) ItemEventType {
|
||||||
|
strLookupTable := map[string]ItemEventType{
|
||||||
|
"HitByMissile": HitByMissile,
|
||||||
|
"DamagedInMelee": DamagedInMelee,
|
||||||
|
"DamagedByMissile": DamagedByMissile,
|
||||||
|
"AttackedInMelee": AttackedInMelee,
|
||||||
|
"DoActive": DoActive,
|
||||||
|
"DoMeleeDamage": DoMeleeDamage,
|
||||||
|
"DoMissileDamage": DoMissileDamage,
|
||||||
|
"DoMeleeAttack": DoMeleeAttack,
|
||||||
|
"DoMissileAttack": DoMissileAttack,
|
||||||
|
"Kill": Kill,
|
||||||
|
"Killed": Killed,
|
||||||
|
"AbsorbDamage": AbsorbDamage,
|
||||||
|
"LevelUp": LevelUp,
|
||||||
|
}
|
||||||
|
return strLookupTable[s]
|
||||||
|
}
|
@ -174,6 +174,7 @@ const (
|
|||||||
LevelDetails = "/data/global/excel/Levels.bin"
|
LevelDetails = "/data/global/excel/Levels.bin"
|
||||||
ObjectDetails = "/data/global/excel/Objects.txt"
|
ObjectDetails = "/data/global/excel/Objects.txt"
|
||||||
SoundSettings = "/data/global/excel/Sounds.txt"
|
SoundSettings = "/data/global/excel/Sounds.txt"
|
||||||
|
ItemStatCost = "/data/global/excel/ItemStatCost.txt"
|
||||||
|
|
||||||
// --- Animations ---
|
// --- Animations ---
|
||||||
|
|
||||||
|
2
main.go
2
main.go
@ -389,6 +389,8 @@ func loadDataDict() error {
|
|||||||
{d2resource.MonStats, d2datadict.LoadMonStats},
|
{d2resource.MonStats, d2datadict.LoadMonStats},
|
||||||
{d2resource.MagicPrefix, d2datadict.LoadMagicPrefix},
|
{d2resource.MagicPrefix, d2datadict.LoadMagicPrefix},
|
||||||
{d2resource.MagicSuffix, d2datadict.LoadMagicSuffix},
|
{d2resource.MagicSuffix, d2datadict.LoadMagicSuffix},
|
||||||
|
{d2resource.ItemStatCost, d2datadict.LoadItemStatCosts},
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
|
Loading…
Reference in New Issue
Block a user