mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-09-16 00:08:29 -04:00
d2datadict reading changes (#553)
* Read excel files with csv.Reader * Read LvlWarp from txt file * Fix lint issues in d2datadict * changed ID back to Id
This commit is contained in:
parent
af0fb11a54
commit
04c7ff543a
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Armors stores all of the ArmorRecords
|
||||||
//nolint:gochecknoglobals // Currently global by design, only written once
|
//nolint:gochecknoglobals // Currently global by design, only written once
|
||||||
var Armors map[string]*ItemCommonRecord
|
var Armors map[string]*ItemCommonRecord
|
||||||
|
|
||||||
|
@ -2,18 +2,10 @@ package d2datadict
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
expansion = "Expansion" // blizzard put this in the txt where expansion data starts
|
|
||||||
)
|
|
||||||
|
|
||||||
//nolint:gochecknoglobals // Currently global by design, only written once
|
|
||||||
var frameFields = []string{"Cel1", "Cel2", "Cel3", "Cel4"}
|
|
||||||
|
|
||||||
// AutoMapRecord represents one row from d2data.mpq/AutoMap.txt.
|
// AutoMapRecord represents one row from d2data.mpq/AutoMap.txt.
|
||||||
// Based on the information here https://d2mods.info/forum/kb/viewarticle?a=419
|
// Based on the information here https://d2mods.info/forum/kb/viewarticle?a=419
|
||||||
type AutoMapRecord struct {
|
type AutoMapRecord struct {
|
||||||
@ -67,66 +59,40 @@ var AutoMaps []*AutoMapRecord
|
|||||||
// LoadAutoMaps populates AutoMaps with the data from AutoMap.txt.
|
// LoadAutoMaps populates AutoMaps with the data from AutoMap.txt.
|
||||||
// It also amends a duplicate field (column) name in that data.
|
// It also amends a duplicate field (column) name in that data.
|
||||||
func LoadAutoMaps(file []byte) {
|
func LoadAutoMaps(file []byte) {
|
||||||
// Fix the error in the original file
|
AutoMaps = make([]*AutoMapRecord, 0)
|
||||||
fileString := fixDuplicateFieldName(string(file))
|
|
||||||
|
var frameFields = []string{"Cel1", "Cel2", "Cel3", "Cel4"}
|
||||||
|
|
||||||
// Split file by newlines and tabs
|
// Split file by newlines and tabs
|
||||||
d := d2common.LoadDataDictionary(fileString)
|
d := d2common.LoadDataDictionary(file)
|
||||||
|
for d.Next() {
|
||||||
|
record := &AutoMapRecord{
|
||||||
|
LevelName: d.String("LevelName"),
|
||||||
|
TileName: d.String("TileName"),
|
||||||
|
|
||||||
// Construct records
|
Style: d.Number("Style"),
|
||||||
AutoMaps = make([]*AutoMapRecord, len(d.Data))
|
StartSequence: d.Number("StartSequence"),
|
||||||
|
EndSequence: d.Number("EndSequence"),
|
||||||
|
|
||||||
for idx := range d.Data {
|
//Type1: d.String("Type1"),
|
||||||
if d.GetString("LevelName", idx) == expansion {
|
//Type2: d.String("Type2"),
|
||||||
continue
|
//Type3: d.String("Type3"),
|
||||||
}
|
//Type4: d.String("Type4"),
|
||||||
|
|
||||||
AutoMaps[idx] = &AutoMapRecord{
|
|
||||||
LevelName: d.GetString("LevelName", idx),
|
|
||||||
TileName: d.GetString("TileName", idx),
|
|
||||||
|
|
||||||
Style: d.GetNumber("Style", idx),
|
|
||||||
StartSequence: d.GetNumber("StartSequence", idx),
|
|
||||||
EndSequence: d.GetNumber("EndSequence", idx),
|
|
||||||
|
|
||||||
//Type1: d.GetString("Type1", idx),
|
|
||||||
//Type2: d.GetString("Type2", idx),
|
|
||||||
//Type3: d.GetString("Type3", idx),
|
|
||||||
//Type4: d.GetString("Type4", idx),
|
|
||||||
// Note: I commented these out for now because they supposedly
|
// Note: I commented these out for now because they supposedly
|
||||||
// aren't useful see the AutoMapRecord struct.
|
// aren't useful see the AutoMapRecord struct.
|
||||||
}
|
}
|
||||||
|
record.Frames = make([]int, len(frameFields))
|
||||||
|
|
||||||
AutoMaps[idx].Frames = make([]int, len(frameFields))
|
|
||||||
for i := range frameFields {
|
for i := range frameFields {
|
||||||
AutoMaps[idx].Frames[i] = d.GetNumber(frameFields[i], idx)
|
record.Frames[i] = d.Number(frameFields[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AutoMaps = append(AutoMaps, record)
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.Err != nil {
|
||||||
|
panic(d.Err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Loaded %d AutoMapRecord records", len(AutoMaps))
|
log.Printf("Loaded %d AutoMapRecord records", len(AutoMaps))
|
||||||
}
|
}
|
||||||
|
|
||||||
// fixDuplicateFieldName changes one of the two 'Type2' fields
|
|
||||||
// in AutoMap.txt to 'Type3'. An error in the file can be seen
|
|
||||||
// by looking at the lists of 'Type' and 'Cel' fields:
|
|
||||||
//
|
|
||||||
// Type1 Type2 Type2* Type4
|
|
||||||
// Cel1 Cel2 Cel3 Cel4
|
|
||||||
//
|
|
||||||
// LoadDataDictionary uses a set of field names. The duplicate
|
|
||||||
// is omitted resulting in all rows being skipped because their
|
|
||||||
// counts are different from the field names count.
|
|
||||||
func fixDuplicateFieldName(fileString string) string {
|
|
||||||
// Split rows
|
|
||||||
rows := strings.Split(fileString, "\r\n")
|
|
||||||
|
|
||||||
// Split the field names row and correct the duplicate
|
|
||||||
fieldNames := strings.Split(rows[0], "\t")
|
|
||||||
fieldNames[9] = "Type3"
|
|
||||||
|
|
||||||
// Join the field names back up and assign to the first row
|
|
||||||
rows[0] = strings.Join(fieldNames, "\t")
|
|
||||||
|
|
||||||
// Return the rows, joined back into one string
|
|
||||||
return strings.Join(rows, "\r\n")
|
|
||||||
}
|
|
||||||
|
@ -67,6 +67,8 @@ var weaponTokenMap map[string]d2enum.WeaponClass //nolint:gochecknoglobals // Cu
|
|||||||
//nolint:funlen // Makes no sense to split
|
//nolint:funlen // Makes no sense to split
|
||||||
// LoadCharStats loads charstats.txt file contents into map[d2enum.Hero]*CharStatsRecord
|
// LoadCharStats loads charstats.txt file contents into map[d2enum.Hero]*CharStatsRecord
|
||||||
func LoadCharStats(file []byte) {
|
func LoadCharStats(file []byte) {
|
||||||
|
CharStats = make(map[d2enum.Hero]*CharStatsRecord)
|
||||||
|
|
||||||
charStringMap = map[string]d2enum.Hero{
|
charStringMap = map[string]d2enum.Hero{
|
||||||
"Amazon": d2enum.HeroAmazon,
|
"Amazon": d2enum.HeroAmazon,
|
||||||
"Barbarian": d2enum.HeroBarbarian,
|
"Barbarian": d2enum.HeroBarbarian,
|
||||||
@ -95,103 +97,105 @@ func LoadCharStats(file []byte) {
|
|||||||
"ht2": d2enum.WeaponClassTwoHandToHand,
|
"ht2": d2enum.WeaponClassTwoHandToHand,
|
||||||
}
|
}
|
||||||
|
|
||||||
d := d2common.LoadDataDictionary(string(file))
|
d := d2common.LoadDataDictionary(file)
|
||||||
CharStats = make(map[d2enum.Hero]*CharStatsRecord, len(d.Data))
|
for d.Next() {
|
||||||
|
|
||||||
for idx := range d.Data {
|
|
||||||
record := &CharStatsRecord{
|
record := &CharStatsRecord{
|
||||||
Class: charStringMap[d.GetString("class", idx)],
|
Class: charStringMap[d.String("class")],
|
||||||
|
|
||||||
InitStr: d.GetNumber("str", idx),
|
InitStr: d.Number("str"),
|
||||||
InitDex: d.GetNumber("dex", idx),
|
InitDex: d.Number("dex"),
|
||||||
InitVit: d.GetNumber("vit", idx),
|
InitVit: d.Number("vit"),
|
||||||
InitEne: d.GetNumber("int", idx),
|
InitEne: d.Number("int"),
|
||||||
InitStamina: d.GetNumber("stamina", idx),
|
InitStamina: d.Number("stamina"),
|
||||||
|
|
||||||
ManaRegen: d.GetNumber("ManaRegen", idx),
|
ManaRegen: d.Number("ManaRegen"),
|
||||||
ToHitFactor: d.GetNumber("ToHitFactor", idx),
|
ToHitFactor: d.Number("ToHitFactor"),
|
||||||
|
|
||||||
VelocityWalk: d.GetNumber("WalkVelocity", idx),
|
VelocityWalk: d.Number("WalkVelocity"),
|
||||||
VelocityRun: d.GetNumber("RunVelocity", idx),
|
VelocityRun: d.Number("RunVelocity"),
|
||||||
StaminaRunDrain: d.GetNumber("RunDrain", idx),
|
StaminaRunDrain: d.Number("RunDrain"),
|
||||||
|
|
||||||
LifePerLevel: d.GetNumber("LifePerLevel", idx),
|
LifePerLevel: d.Number("LifePerLevel"),
|
||||||
ManaPerLevel: d.GetNumber("ManaPerLevel", idx),
|
ManaPerLevel: d.Number("ManaPerLevel"),
|
||||||
StaminaPerLevel: d.GetNumber("StaminaPerLevel", idx),
|
StaminaPerLevel: d.Number("StaminaPerLevel"),
|
||||||
|
|
||||||
LifePerVit: d.GetNumber("LifePerVitality", idx),
|
LifePerVit: d.Number("LifePerVitality"),
|
||||||
ManaPerEne: d.GetNumber("ManaPerMagic", idx),
|
ManaPerEne: d.Number("ManaPerMagic"),
|
||||||
StaminaPerVit: d.GetNumber("StaminaPerVitality", idx),
|
StaminaPerVit: d.Number("StaminaPerVitality"),
|
||||||
|
|
||||||
StatPerLevel: d.GetNumber("StatPerLevel", idx),
|
StatPerLevel: d.Number("StatPerLevel"),
|
||||||
BlockFactor: d.GetNumber("BlockFactor", idx),
|
BlockFactor: d.Number("BlockFactor"),
|
||||||
|
|
||||||
StartSkillBonus: d.GetString("StartSkill", idx),
|
StartSkillBonus: d.String("StartSkill"),
|
||||||
SkillStrAll: d.GetString("StrAllSkills", idx),
|
SkillStrAll: d.String("StrAllSkills"),
|
||||||
SkillStrClassOnly: d.GetString("StrClassOnly", idx),
|
SkillStrClassOnly: d.String("StrClassOnly"),
|
||||||
|
|
||||||
BaseSkill: [10]string{
|
BaseSkill: [10]string{
|
||||||
d.GetString("Skill 1", idx),
|
d.String("Skill 1"),
|
||||||
d.GetString("Skill 2", idx),
|
d.String("Skill 2"),
|
||||||
d.GetString("Skill 3", idx),
|
d.String("Skill 3"),
|
||||||
d.GetString("Skill 4", idx),
|
d.String("Skill 4"),
|
||||||
d.GetString("Skill 5", idx),
|
d.String("Skill 5"),
|
||||||
d.GetString("Skill 6", idx),
|
d.String("Skill 6"),
|
||||||
d.GetString("Skill 7", idx),
|
d.String("Skill 7"),
|
||||||
d.GetString("Skill 8", idx),
|
d.String("Skill 8"),
|
||||||
d.GetString("Skill 9", idx),
|
d.String("Skill 9"),
|
||||||
d.GetString("Skill 10", idx),
|
d.String("Skill 10"),
|
||||||
},
|
},
|
||||||
|
|
||||||
SkillStrTab: [3]string{
|
SkillStrTab: [3]string{
|
||||||
d.GetString("StrSkillTab1", idx),
|
d.String("StrSkillTab1"),
|
||||||
d.GetString("StrSkillTab2", idx),
|
d.String("StrSkillTab2"),
|
||||||
d.GetString("StrSkillTab3", idx),
|
d.String("StrSkillTab3"),
|
||||||
},
|
},
|
||||||
|
|
||||||
BaseWeaponClass: weaponTokenMap[d.GetString("baseWClass", idx)],
|
BaseWeaponClass: weaponTokenMap[d.String("baseWClass")],
|
||||||
|
|
||||||
StartItem: [10]string{
|
StartItem: [10]string{
|
||||||
d.GetString("item1", idx),
|
d.String("item1"),
|
||||||
d.GetString("item2", idx),
|
d.String("item2"),
|
||||||
d.GetString("item3", idx),
|
d.String("item3"),
|
||||||
d.GetString("item4", idx),
|
d.String("item4"),
|
||||||
d.GetString("item5", idx),
|
d.String("item5"),
|
||||||
d.GetString("item6", idx),
|
d.String("item6"),
|
||||||
d.GetString("item7", idx),
|
d.String("item7"),
|
||||||
d.GetString("item8", idx),
|
d.String("item8"),
|
||||||
d.GetString("item9", idx),
|
d.String("item9"),
|
||||||
d.GetString("item10", idx),
|
d.String("item10"),
|
||||||
},
|
},
|
||||||
|
|
||||||
StartItemLocation: [10]string{
|
StartItemLocation: [10]string{
|
||||||
d.GetString("item1loc", idx),
|
d.String("item1loc"),
|
||||||
d.GetString("item2loc", idx),
|
d.String("item2loc"),
|
||||||
d.GetString("item3loc", idx),
|
d.String("item3loc"),
|
||||||
d.GetString("item4loc", idx),
|
d.String("item4loc"),
|
||||||
d.GetString("item5loc", idx),
|
d.String("item5loc"),
|
||||||
d.GetString("item6loc", idx),
|
d.String("item6loc"),
|
||||||
d.GetString("item7loc", idx),
|
d.String("item7loc"),
|
||||||
d.GetString("item8loc", idx),
|
d.String("item8loc"),
|
||||||
d.GetString("item9loc", idx),
|
d.String("item9loc"),
|
||||||
d.GetString("item10loc", idx),
|
d.String("item10loc"),
|
||||||
},
|
},
|
||||||
|
|
||||||
StartItemCount: [10]int{
|
StartItemCount: [10]int{
|
||||||
d.GetNumber("item1count", idx),
|
d.Number("item1count"),
|
||||||
d.GetNumber("item2count", idx),
|
d.Number("item2count"),
|
||||||
d.GetNumber("item3count", idx),
|
d.Number("item3count"),
|
||||||
d.GetNumber("item4count", idx),
|
d.Number("item4count"),
|
||||||
d.GetNumber("item5count", idx),
|
d.Number("item5count"),
|
||||||
d.GetNumber("item6count", idx),
|
d.Number("item6count"),
|
||||||
d.GetNumber("item7count", idx),
|
d.Number("item7count"),
|
||||||
d.GetNumber("item8count", idx),
|
d.Number("item8count"),
|
||||||
d.GetNumber("item9count", idx),
|
d.Number("item9count"),
|
||||||
d.GetNumber("item10count", idx),
|
d.Number("item10count"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
CharStats[record.Class] = record
|
CharStats[record.Class] = record
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d.Err != nil {
|
||||||
|
panic(d.Err)
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("Loaded %d CharStats records", len(CharStats))
|
log.Printf("Loaded %d CharStats records", len(CharStats))
|
||||||
}
|
}
|
||||||
|
@ -146,8 +146,7 @@ var CubeRecipes []*CubeRecipeRecord
|
|||||||
// LoadCubeRecipes populates CubeRecipes with
|
// LoadCubeRecipes populates CubeRecipes with
|
||||||
// the data from CubeMain.txt.
|
// the data from CubeMain.txt.
|
||||||
func LoadCubeRecipes(file []byte) {
|
func LoadCubeRecipes(file []byte) {
|
||||||
// Load data
|
CubeRecipes = make([]*CubeRecipeRecord, 0)
|
||||||
d := d2common.LoadDataDictionary(string(file))
|
|
||||||
|
|
||||||
// There are repeated fields and sections in this file, some
|
// There are repeated fields and sections in this file, some
|
||||||
// of which have inconsistent naming conventions. These slices
|
// of which have inconsistent naming conventions. These slices
|
||||||
@ -160,60 +159,65 @@ func LoadCubeRecipes(file []byte) {
|
|||||||
|
|
||||||
var inputFields = []string{"input 1", "input 2", "input 3", "input 4", "input 5", "input 6", "input 7"}
|
var inputFields = []string{"input 1", "input 2", "input 3", "input 4", "input 5", "input 6", "input 7"}
|
||||||
|
|
||||||
// Create records
|
d := d2common.LoadDataDictionary(file)
|
||||||
CubeRecipes = make([]*CubeRecipeRecord, len(d.Data))
|
for d.Next() {
|
||||||
for idx := range d.Data {
|
record := &CubeRecipeRecord{
|
||||||
CubeRecipes[idx] = &CubeRecipeRecord{
|
Description: d.String("description"),
|
||||||
Description: d.GetString("description", idx),
|
|
||||||
|
|
||||||
Enabled: d.GetNumber("enabled", idx) == 1,
|
Enabled: d.Bool("enabled"),
|
||||||
Ladder: d.GetNumber("ladder", idx) == 1,
|
Ladder: d.Bool("ladder"),
|
||||||
|
|
||||||
MinDiff: d.GetNumber("min diff", idx),
|
MinDiff: d.Number("min diff"),
|
||||||
Version: d.GetNumber("version", idx),
|
Version: d.Number("version"),
|
||||||
|
|
||||||
ReqStatID: d.GetNumber("param", idx),
|
ReqStatID: d.Number("param"),
|
||||||
ReqOperation: d.GetNumber("op", idx),
|
ReqOperation: d.Number("op"),
|
||||||
ReqValue: d.GetNumber("value", idx),
|
ReqValue: d.Number("value"),
|
||||||
|
|
||||||
Class: classFieldToEnum(d.GetString("class", idx)),
|
Class: classFieldToEnum(d.String("class")),
|
||||||
|
|
||||||
NumInputs: d.GetNumber("numinputs", idx),
|
NumInputs: d.Number("numinputs"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create inputs - input 1-7
|
// Create inputs - input 1-7
|
||||||
CubeRecipes[idx].Inputs = make([]CubeRecipeItem, 7)
|
record.Inputs = make([]CubeRecipeItem, len(inputFields))
|
||||||
for i := range inputFields {
|
for i := range inputFields {
|
||||||
CubeRecipes[idx].Inputs[i] = newCubeRecipeItem(
|
record.Inputs[i] = newCubeRecipeItem(
|
||||||
d.GetString(inputFields[i], idx))
|
d.String(inputFields[i]))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create outputs - output "", b, c
|
// Create outputs - output "", b, c
|
||||||
CubeRecipes[idx].Outputs = make([]CubeRecipeResult, 3)
|
record.Outputs = make([]CubeRecipeResult, len(outputLabels))
|
||||||
for o, outLabel := range outputLabels {
|
for o, outLabel := range outputLabels {
|
||||||
CubeRecipes[idx].Outputs[o] = CubeRecipeResult{
|
record.Outputs[o] = CubeRecipeResult{
|
||||||
Item: newCubeRecipeItem(
|
Item: newCubeRecipeItem(
|
||||||
d.GetString(outputFields[o], idx)),
|
d.String(outputFields[o])),
|
||||||
|
|
||||||
Level: d.GetNumber(outLabel+"lvl", idx),
|
Level: d.Number(outLabel + "lvl"),
|
||||||
ILevel: d.GetNumber(outLabel+"plvl", idx),
|
ILevel: d.Number(outLabel + "plvl"),
|
||||||
PLevel: d.GetNumber(outLabel+"ilvl", idx),
|
PLevel: d.Number(outLabel + "ilvl"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create properties - mod 1-5
|
// Create properties - mod 1-5
|
||||||
properties := make([]CubeRecipeItemProperty, 5)
|
properties := make([]CubeRecipeItemProperty, len(propLabels))
|
||||||
for p, prop := range propLabels {
|
for p, prop := range propLabels {
|
||||||
properties[p] = CubeRecipeItemProperty{
|
properties[p] = CubeRecipeItemProperty{
|
||||||
Code: d.GetString(outLabel+prop, idx),
|
Code: d.String(outLabel + prop),
|
||||||
Chance: d.GetNumber(outLabel+prop+" chance", idx),
|
Chance: d.Number(outLabel + prop + " chance"),
|
||||||
Param: d.GetNumber(outLabel+prop+" param", idx),
|
Param: d.Number(outLabel + prop + " param"),
|
||||||
Min: d.GetNumber(outLabel+prop+" min", idx),
|
Min: d.Number(outLabel + prop + " min"),
|
||||||
Max: d.GetNumber(outLabel+prop+" max", idx),
|
Max: d.Number(outLabel + prop + " max"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CubeRecipes[idx].Outputs[o].Properties = properties
|
record.Outputs[o].Properties = properties
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CubeRecipes = append(CubeRecipes, record)
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.Err != nil {
|
||||||
|
panic(d.Err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Loaded %d CubeMainRecord records", len(CubeRecipes))
|
log.Printf("Loaded %d CubeMainRecord records", len(CubeRecipes))
|
||||||
|
@ -94,33 +94,35 @@ type DifficultyLevelRecord struct {
|
|||||||
|
|
||||||
// LoadDifficultyLevels is a loader for difficultylevels.txt
|
// LoadDifficultyLevels is a loader for difficultylevels.txt
|
||||||
func LoadDifficultyLevels(file []byte) {
|
func LoadDifficultyLevels(file []byte) {
|
||||||
dict := d2common.LoadDataDictionary(string(file))
|
DifficultyLevels = make(map[string]*DifficultyLevelRecord)
|
||||||
numRows := len(dict.Data)
|
|
||||||
|
|
||||||
DifficultyLevels = make(map[string]*DifficultyLevelRecord, numRows)
|
d := d2common.LoadDataDictionary(file)
|
||||||
|
for d.Next() {
|
||||||
for idx := range dict.Data {
|
|
||||||
record := &DifficultyLevelRecord{
|
record := &DifficultyLevelRecord{
|
||||||
Name: dict.GetString("Name", idx),
|
Name: d.String("Name"),
|
||||||
ResistancePenalty: dict.GetNumber("ResistPenalty", idx),
|
ResistancePenalty: d.Number("ResistPenalty"),
|
||||||
DeathExperiencePenalty: dict.GetNumber("DeathExpPenalty", idx),
|
DeathExperiencePenalty: d.Number("DeathExpPenalty"),
|
||||||
DropChanceLow: dict.GetNumber("UberCodeOddsNormal", idx),
|
DropChanceLow: d.Number("UberCodeOddsNormal"),
|
||||||
DropChanceNormal: dict.GetNumber("UberCodeOddsNormal", idx),
|
DropChanceNormal: d.Number("UberCodeOddsNormal"),
|
||||||
DropChanceSuperior: dict.GetNumber("UberCodeOddsNormal", idx),
|
DropChanceSuperior: d.Number("UberCodeOddsNormal"),
|
||||||
DropChanceExceptional: dict.GetNumber("UberCodeOddsNormal", idx),
|
DropChanceExceptional: d.Number("UberCodeOddsNormal"),
|
||||||
DropChanceMagic: dict.GetNumber("UberCodeOddsGood", idx),
|
DropChanceMagic: d.Number("UberCodeOddsGood"),
|
||||||
DropChanceRare: dict.GetNumber("UberCodeOddsGood", idx),
|
DropChanceRare: d.Number("UberCodeOddsGood"),
|
||||||
DropChanceSet: dict.GetNumber("UberCodeOddsGood", idx),
|
DropChanceSet: d.Number("UberCodeOddsGood"),
|
||||||
DropChanceUnique: dict.GetNumber("UberCodeOddsGood", idx),
|
DropChanceUnique: d.Number("UberCodeOddsGood"),
|
||||||
MonsterSkillBonus: dict.GetNumber("MonsterSkillBonus", idx),
|
MonsterSkillBonus: d.Number("MonsterSkillBonus"),
|
||||||
MonsterColdDivisor: dict.GetNumber("MonsterColdDivisor", idx),
|
MonsterColdDivisor: d.Number("MonsterColdDivisor"),
|
||||||
MonsterFreezeDivisor: dict.GetNumber("MonsterFreezeDivisor", idx),
|
MonsterFreezeDivisor: d.Number("MonsterFreezeDivisor"),
|
||||||
AiCurseDivisor: dict.GetNumber("AiCurseDivisor", idx),
|
AiCurseDivisor: d.Number("AiCurseDivisor"),
|
||||||
LifeStealDivisor: dict.GetNumber("LifeStealDivisor", idx),
|
LifeStealDivisor: d.Number("LifeStealDivisor"),
|
||||||
ManaStealDivisor: dict.GetNumber("ManaStealDivisor", idx),
|
ManaStealDivisor: d.Number("ManaStealDivisor"),
|
||||||
}
|
}
|
||||||
DifficultyLevels[record.Name] = record
|
DifficultyLevels[record.Name] = record
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d.Err != nil {
|
||||||
|
panic(d.Err)
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("Loaded %d DifficultyLevel records", len(DifficultyLevels))
|
log.Printf("Loaded %d DifficultyLevel records", len(DifficultyLevels))
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ type ExperienceBreakpointsRecord struct {
|
|||||||
// ExperienceBreakpoints describes the required experience
|
// ExperienceBreakpoints describes the required experience
|
||||||
// for each level for each character class
|
// for each level for each character class
|
||||||
//nolint:gochecknoglobals // Currently global by design, only written once
|
//nolint:gochecknoglobals // Currently global by design, only written once
|
||||||
var ExperienceBreakpoints []*ExperienceBreakpointsRecord
|
var ExperienceBreakpoints map[int]*ExperienceBreakpointsRecord
|
||||||
|
|
||||||
//nolint:gochecknoglobals // Currently global by design
|
//nolint:gochecknoglobals // Currently global by design
|
||||||
var maxLevels map[d2enum.Hero]int
|
var maxLevels map[d2enum.Hero]int
|
||||||
@ -60,43 +60,42 @@ func GetExperienceBreakpoint(heroType d2enum.Hero, level int) int {
|
|||||||
// LoadExperienceBreakpoints loads experience.txt into a map
|
// LoadExperienceBreakpoints loads experience.txt into a map
|
||||||
// ExperienceBreakpoints []*ExperienceBreakpointsRecord
|
// ExperienceBreakpoints []*ExperienceBreakpointsRecord
|
||||||
func LoadExperienceBreakpoints(file []byte) {
|
func LoadExperienceBreakpoints(file []byte) {
|
||||||
d := d2common.LoadDataDictionary(string(file))
|
ExperienceBreakpoints = make(map[int]*ExperienceBreakpointsRecord)
|
||||||
|
|
||||||
// we skip the second row because that describes max level of char classes
|
d := d2common.LoadDataDictionary(file)
|
||||||
ExperienceBreakpoints = make([]*ExperienceBreakpointsRecord, len(d.Data)-1)
|
d.Next()
|
||||||
|
|
||||||
for idx := range d.Data {
|
// the first row describes the max level of char classes
|
||||||
if idx == 0 {
|
maxLevels = map[d2enum.Hero]int{
|
||||||
// max levels are a special case
|
d2enum.HeroAmazon: d.Number("Amazon"),
|
||||||
maxLevels = map[d2enum.Hero]int{
|
d2enum.HeroBarbarian: d.Number("Barbarian"),
|
||||||
d2enum.HeroAmazon: d.GetNumber("Amazon", idx),
|
d2enum.HeroDruid: d.Number("Druid"),
|
||||||
d2enum.HeroBarbarian: d.GetNumber("Barbarian", idx),
|
d2enum.HeroAssassin: d.Number("Assassin"),
|
||||||
d2enum.HeroDruid: d.GetNumber("Druid", idx),
|
d2enum.HeroNecromancer: d.Number("Necromancer"),
|
||||||
d2enum.HeroAssassin: d.GetNumber("Assassin", idx),
|
d2enum.HeroPaladin: d.Number("Paladin"),
|
||||||
d2enum.HeroNecromancer: d.GetNumber("Necromancer", idx),
|
d2enum.HeroSorceress: d.Number("Sorceress"),
|
||||||
d2enum.HeroPaladin: d.GetNumber("Paladin", idx),
|
}
|
||||||
d2enum.HeroSorceress: d.GetNumber("Sorceress", idx),
|
|
||||||
}
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for d.Next() {
|
||||||
record := &ExperienceBreakpointsRecord{
|
record := &ExperienceBreakpointsRecord{
|
||||||
Level: d.GetNumber("Level", idx),
|
Level: d.Number("Level"),
|
||||||
HeroBreakpoints: map[d2enum.Hero]int{
|
HeroBreakpoints: map[d2enum.Hero]int{
|
||||||
d2enum.HeroAmazon: d.GetNumber("Amazon", idx),
|
d2enum.HeroAmazon: d.Number("Amazon"),
|
||||||
d2enum.HeroBarbarian: d.GetNumber("Barbarian", idx),
|
d2enum.HeroBarbarian: d.Number("Barbarian"),
|
||||||
d2enum.HeroDruid: d.GetNumber("Druid", idx),
|
d2enum.HeroDruid: d.Number("Druid"),
|
||||||
d2enum.HeroAssassin: d.GetNumber("Assassin", idx),
|
d2enum.HeroAssassin: d.Number("Assassin"),
|
||||||
d2enum.HeroNecromancer: d.GetNumber("Necromancer", idx),
|
d2enum.HeroNecromancer: d.Number("Necromancer"),
|
||||||
d2enum.HeroPaladin: d.GetNumber("Paladin", idx),
|
d2enum.HeroPaladin: d.Number("Paladin"),
|
||||||
d2enum.HeroSorceress: d.GetNumber("Sorceress", idx),
|
d2enum.HeroSorceress: d.Number("Sorceress"),
|
||||||
},
|
},
|
||||||
Ratio: d.GetNumber("ExpRatio", idx),
|
Ratio: d.Number("ExpRatio"),
|
||||||
}
|
}
|
||||||
|
|
||||||
ExperienceBreakpoints[record.Level] = record
|
ExperienceBreakpoints[record.Level] = record
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d.Err != nil {
|
||||||
|
panic(d.Err)
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("Loaded %d ExperienceBreakpoint records", len(ExperienceBreakpoints))
|
log.Printf("Loaded %d ExperienceBreakpoint records", len(ExperienceBreakpoints))
|
||||||
}
|
}
|
||||||
|
@ -57,61 +57,58 @@ var Gems map[string]*GemsRecord //nolint:gochecknoglobals // Currently global by
|
|||||||
|
|
||||||
// LoadGems loads gem records into a map[string]*GemsRecord
|
// LoadGems loads gem records into a map[string]*GemsRecord
|
||||||
func LoadGems(file []byte) {
|
func LoadGems(file []byte) {
|
||||||
d := d2common.LoadDataDictionary(string(file))
|
Gems = make(map[string]*GemsRecord)
|
||||||
|
|
||||||
Gems = make(map[string]*GemsRecord, len(d.Data))
|
d := d2common.LoadDataDictionary(file)
|
||||||
|
for d.Next() {
|
||||||
for idx := range d.Data {
|
gem := &GemsRecord{
|
||||||
if d.GetString("name", idx) != expansion {
|
Name: d.String("name"),
|
||||||
/*
|
Letter: d.String("letter"),
|
||||||
"Expansion" is the only field in line 36 of /data/global/excel/gems.txt and is only used to visually
|
Transform: d.Number("transform"),
|
||||||
separate base-game gems and expansion runes.
|
Code: d.String("code"),
|
||||||
*/
|
Nummods: d.Number("nummods"),
|
||||||
gem := &GemsRecord{
|
WeaponMod1Code: d.String("weaponMod1Code"),
|
||||||
Name: d.GetString("name", idx),
|
WeaponMod1Param: d.Number("weaponMod1Param"),
|
||||||
Letter: d.GetString("letter", idx),
|
WeaponMod1Min: d.Number("weaponMod1Min"),
|
||||||
Transform: d.GetNumber("transform", idx),
|
WeaponMod1Max: d.Number("weaponMod1Max"),
|
||||||
Code: d.GetString("code", idx),
|
WeaponMod2Code: d.String("weaponMod2Code"),
|
||||||
Nummods: d.GetNumber("nummods", idx),
|
WeaponMod2Param: d.Number("weaponMod2Param"),
|
||||||
WeaponMod1Code: d.GetString("weaponMod1Code", idx),
|
WeaponMod2Min: d.Number("weaponMod2Min"),
|
||||||
WeaponMod1Param: d.GetNumber("weaponMod1Param", idx),
|
WeaponMod2Max: d.Number("weaponMod2Max"),
|
||||||
WeaponMod1Min: d.GetNumber("weaponMod1Min", idx),
|
WeaponMod3Code: d.String("weaponMod3Code"),
|
||||||
WeaponMod1Max: d.GetNumber("weaponMod1Max", idx),
|
WeaponMod3Param: d.Number("weaponMod3Param"),
|
||||||
WeaponMod2Code: d.GetString("weaponMod2Code", idx),
|
WeaponMod3Min: d.Number("weaponMod3Min"),
|
||||||
WeaponMod2Param: d.GetNumber("weaponMod2Param", idx),
|
WeaponMod3Max: d.Number("weaponMod3Max"),
|
||||||
WeaponMod2Min: d.GetNumber("weaponMod2Min", idx),
|
HelmMod1Code: d.String("helmMod1Code"),
|
||||||
WeaponMod2Max: d.GetNumber("weaponMod2Max", idx),
|
HelmMod1Param: d.Number("helmMod1Param"),
|
||||||
WeaponMod3Code: d.GetString("weaponMod3Code", idx),
|
HelmMod1Min: d.Number("helmMod1Min"),
|
||||||
WeaponMod3Param: d.GetNumber("weaponMod3Param", idx),
|
HelmMod1Max: d.Number("helmMod1Max"),
|
||||||
WeaponMod3Min: d.GetNumber("weaponMod3Min", idx),
|
HelmMod2Code: d.String("helmMod2Code"),
|
||||||
WeaponMod3Max: d.GetNumber("weaponMod3Max", idx),
|
HelmMod2Param: d.Number("helmMod2Param"),
|
||||||
HelmMod1Code: d.GetString("helmMod1Code", idx),
|
HelmMod2Min: d.Number("helmMod2Min"),
|
||||||
HelmMod1Param: d.GetNumber("helmMod1Param", idx),
|
HelmMod2Max: d.Number("helmMod2Max"),
|
||||||
HelmMod1Min: d.GetNumber("helmMod1Min", idx),
|
HelmMod3Code: d.String("helmMod3Code"),
|
||||||
HelmMod1Max: d.GetNumber("helmMod1Max", idx),
|
HelmMod3Param: d.Number("helmMod3Param"),
|
||||||
HelmMod2Code: d.GetString("helmMod2Code", idx),
|
HelmMod3Min: d.Number("helmMod3Min"),
|
||||||
HelmMod2Param: d.GetNumber("helmMod2Param", idx),
|
HelmMod3Max: d.Number("helmMod3Max"),
|
||||||
HelmMod2Min: d.GetNumber("helmMod2Min", idx),
|
ShieldMod1Code: d.String("shieldMod1Code"),
|
||||||
HelmMod2Max: d.GetNumber("helmMod2Max", idx),
|
ShieldMod1Param: d.Number("shieldMod1Param"),
|
||||||
HelmMod3Code: d.GetString("helmMod3Code", idx),
|
ShieldMod1Min: d.Number("shieldMod1Min"),
|
||||||
HelmMod3Param: d.GetNumber("helmMod3Param", idx),
|
ShieldMod1Max: d.Number("shieldMod1Max"),
|
||||||
HelmMod3Min: d.GetNumber("helmMod3Min", idx),
|
ShieldMod2Code: d.String("shieldMod2Code"),
|
||||||
HelmMod3Max: d.GetNumber("helmMod3Max", idx),
|
ShieldMod2Param: d.Number("shieldMod2Param"),
|
||||||
ShieldMod1Code: d.GetString("shieldMod1Code", idx),
|
ShieldMod2Min: d.Number("shieldMod2Min"),
|
||||||
ShieldMod1Param: d.GetNumber("shieldMod1Param", idx),
|
ShieldMod2Max: d.Number("shieldMod2Max"),
|
||||||
ShieldMod1Min: d.GetNumber("shieldMod1Min", idx),
|
ShieldMod3Code: d.String("shieldMod3Code"),
|
||||||
ShieldMod1Max: d.GetNumber("shieldMod1Max", idx),
|
ShieldMod3Param: d.Number("shieldMod3Param"),
|
||||||
ShieldMod2Code: d.GetString("shieldMod2Code", idx),
|
ShieldMod3Min: d.Number("shieldMod3Min"),
|
||||||
ShieldMod2Param: d.GetNumber("shieldMod2Param", idx),
|
ShieldMod3Max: d.Number("shieldMod3Max"),
|
||||||
ShieldMod2Min: d.GetNumber("shieldMod2Min", idx),
|
|
||||||
ShieldMod2Max: d.GetNumber("shieldMod2Max", idx),
|
|
||||||
ShieldMod3Code: d.GetString("shieldMod3Code", idx),
|
|
||||||
ShieldMod3Param: d.GetNumber("shieldMod3Param", idx),
|
|
||||||
ShieldMod3Min: d.GetNumber("shieldMod3Min", idx),
|
|
||||||
ShieldMod3Max: d.GetNumber("shieldMod3Max", idx),
|
|
||||||
}
|
|
||||||
Gems[gem.Name] = gem
|
|
||||||
}
|
}
|
||||||
|
Gems[gem.Name] = gem
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.Err != nil {
|
||||||
|
panic(d.Err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Loaded %d Gems records", len(Gems))
|
log.Printf("Loaded %d Gems records", len(Gems))
|
||||||
|
@ -89,87 +89,90 @@ var Hirelings []*HirelingRecord
|
|||||||
|
|
||||||
// LoadHireling loads hireling data into []*HirelingRecord
|
// LoadHireling loads hireling data into []*HirelingRecord
|
||||||
func LoadHireling(file []byte) {
|
func LoadHireling(file []byte) {
|
||||||
d := d2common.LoadDataDictionary(string(file))
|
Hirelings = make([]*HirelingRecord, 0)
|
||||||
|
|
||||||
Hirelings = make([]*HirelingRecord, len(d.Data))
|
d := d2common.LoadDataDictionary(file)
|
||||||
|
for d.Next() {
|
||||||
for idx := range d.Data {
|
|
||||||
hireling := &HirelingRecord{
|
hireling := &HirelingRecord{
|
||||||
Hireling: d.GetString("Hireling", idx),
|
Hireling: d.String("Hireling"),
|
||||||
SubType: d.GetString("SubType", idx),
|
SubType: d.String("SubType"),
|
||||||
ID: d.GetNumber("Id", idx),
|
ID: d.Number("Id"),
|
||||||
Class: d.GetNumber("Class", idx),
|
Class: d.Number("Class"),
|
||||||
Act: d.GetNumber("Act", idx),
|
Act: d.Number("Act"),
|
||||||
Difficulty: d.GetNumber("Difficulty", idx),
|
Difficulty: d.Number("Difficulty"),
|
||||||
Level: d.GetNumber("Level", idx),
|
Level: d.Number("Level"),
|
||||||
Seller: d.GetNumber("Seller", idx),
|
Seller: d.Number("Seller"),
|
||||||
NameFirst: d.GetString("NameFirst", idx),
|
NameFirst: d.String("NameFirst"),
|
||||||
NameLast: d.GetString("NameLast", idx),
|
NameLast: d.String("NameLast"),
|
||||||
Gold: d.GetNumber("Gold", idx),
|
Gold: d.Number("Gold"),
|
||||||
ExpPerLvl: d.GetNumber("Exp/Lvl", idx),
|
ExpPerLvl: d.Number("Exp/Lvl"),
|
||||||
HP: d.GetNumber("HP", idx),
|
HP: d.Number("HP"),
|
||||||
HPPerLvl: d.GetNumber("HP/Lvl", idx),
|
HPPerLvl: d.Number("HP/Lvl"),
|
||||||
Defense: d.GetNumber("Defense", idx),
|
Defense: d.Number("Defense"),
|
||||||
DefPerLvl: d.GetNumber("Id", idx),
|
DefPerLvl: d.Number("Id"),
|
||||||
Str: d.GetNumber("Str", idx),
|
Str: d.Number("Str"),
|
||||||
StrPerLvl: d.GetNumber("Str/Lvl", idx),
|
StrPerLvl: d.Number("Str/Lvl"),
|
||||||
Dex: d.GetNumber("Dex", idx),
|
Dex: d.Number("Dex"),
|
||||||
DexPerLvl: d.GetNumber("Dex/Lvl", idx),
|
DexPerLvl: d.Number("Dex/Lvl"),
|
||||||
AR: d.GetNumber("AR", idx),
|
AR: d.Number("AR"),
|
||||||
ARPerLvl: d.GetNumber("AR/Lvl", idx),
|
ARPerLvl: d.Number("AR/Lvl"),
|
||||||
Share: d.GetNumber("Share", idx),
|
Share: d.Number("Share"),
|
||||||
DmgMin: d.GetNumber("Dmg-Min", idx),
|
DmgMin: d.Number("Dmg-Min"),
|
||||||
DmgMax: d.GetNumber("Dmg-Max", idx),
|
DmgMax: d.Number("Dmg-Max"),
|
||||||
DmgPerLvl: d.GetNumber("Dmg/Lvl", idx),
|
DmgPerLvl: d.Number("Dmg/Lvl"),
|
||||||
Resist: d.GetNumber("Resist", idx),
|
Resist: d.Number("Resist"),
|
||||||
ResistPerLvl: d.GetNumber("Resist/Lvl", idx),
|
ResistPerLvl: d.Number("Resist/Lvl"),
|
||||||
WType1: d.GetString("WType1", idx),
|
WType1: d.String("WType1"),
|
||||||
WType2: d.GetString("WType2", idx),
|
WType2: d.String("WType2"),
|
||||||
HireDesc: d.GetString("HireDesc", idx),
|
HireDesc: d.String("HireDesc"),
|
||||||
DefaultChance: d.GetNumber("DefaultChance", idx),
|
DefaultChance: d.Number("DefaultChance"),
|
||||||
Skill1: d.GetString("Skill1", idx),
|
Skill1: d.String("Skill1"),
|
||||||
Mode1: d.GetNumber("Mode1", idx),
|
Mode1: d.Number("Mode1"),
|
||||||
Chance1: d.GetNumber("Chance1", idx),
|
Chance1: d.Number("Chance1"),
|
||||||
ChancePerLevel1: d.GetNumber("ChancePerLvl1", idx),
|
ChancePerLevel1: d.Number("ChancePerLvl1"),
|
||||||
Level1: d.GetNumber("Level1", idx),
|
Level1: d.Number("Level1"),
|
||||||
LvlPerLvl1: d.GetNumber("LvlPerLvl1", idx),
|
LvlPerLvl1: d.Number("LvlPerLvl1"),
|
||||||
Skill2: d.GetString("Skill2", idx),
|
Skill2: d.String("Skill2"),
|
||||||
Mode2: d.GetNumber("Mode2", idx),
|
Mode2: d.Number("Mode2"),
|
||||||
Chance2: d.GetNumber("Chance2", idx),
|
Chance2: d.Number("Chance2"),
|
||||||
ChancePerLevel2: d.GetNumber("ChancePerLvl2", idx),
|
ChancePerLevel2: d.Number("ChancePerLvl2"),
|
||||||
Level2: d.GetNumber("Level2", idx),
|
Level2: d.Number("Level2"),
|
||||||
LvlPerLvl2: d.GetNumber("LvlPerLvl2", idx),
|
LvlPerLvl2: d.Number("LvlPerLvl2"),
|
||||||
Skill3: d.GetString("Skill3", idx),
|
Skill3: d.String("Skill3"),
|
||||||
Mode3: d.GetNumber("Mode3", idx),
|
Mode3: d.Number("Mode3"),
|
||||||
Chance3: d.GetNumber("Chance3", idx),
|
Chance3: d.Number("Chance3"),
|
||||||
ChancePerLevel3: d.GetNumber("ChancePerLvl3", idx),
|
ChancePerLevel3: d.Number("ChancePerLvl3"),
|
||||||
Level3: d.GetNumber("Level3", idx),
|
Level3: d.Number("Level3"),
|
||||||
LvlPerLvl3: d.GetNumber("LvlPerLvl3", idx),
|
LvlPerLvl3: d.Number("LvlPerLvl3"),
|
||||||
Skill4: d.GetString("Skill4", idx),
|
Skill4: d.String("Skill4"),
|
||||||
Mode4: d.GetNumber("Mode4", idx),
|
Mode4: d.Number("Mode4"),
|
||||||
Chance4: d.GetNumber("Chance4", idx),
|
Chance4: d.Number("Chance4"),
|
||||||
ChancePerLevel4: d.GetNumber("ChancePerLvl4", idx),
|
ChancePerLevel4: d.Number("ChancePerLvl4"),
|
||||||
Level4: d.GetNumber("Level4", idx),
|
Level4: d.Number("Level4"),
|
||||||
LvlPerLvl4: d.GetNumber("LvlPerLvl4", idx),
|
LvlPerLvl4: d.Number("LvlPerLvl4"),
|
||||||
Skill5: d.GetString("Skill5", idx),
|
Skill5: d.String("Skill5"),
|
||||||
Mode5: d.GetNumber("Mode5", idx),
|
Mode5: d.Number("Mode5"),
|
||||||
Chance5: d.GetNumber("Chance5", idx),
|
Chance5: d.Number("Chance5"),
|
||||||
ChancePerLevel5: d.GetNumber("ChancePerLvl5", idx),
|
ChancePerLevel5: d.Number("ChancePerLvl5"),
|
||||||
Level5: d.GetNumber("Level5", idx),
|
Level5: d.Number("Level5"),
|
||||||
LvlPerLvl5: d.GetNumber("LvlPerLvl5", idx),
|
LvlPerLvl5: d.Number("LvlPerLvl5"),
|
||||||
Skill6: d.GetString("Skill6", idx),
|
Skill6: d.String("Skill6"),
|
||||||
Mode6: d.GetNumber("Mode6", idx),
|
Mode6: d.Number("Mode6"),
|
||||||
Chance6: d.GetNumber("Chance6", idx),
|
Chance6: d.Number("Chance6"),
|
||||||
ChancePerLevel6: d.GetNumber("ChancePerLvl6", idx),
|
ChancePerLevel6: d.Number("ChancePerLvl6"),
|
||||||
Level6: d.GetNumber("Level6", idx),
|
Level6: d.Number("Level6"),
|
||||||
LvlPerLvl6: d.GetNumber("LvlPerLvl6", idx),
|
LvlPerLvl6: d.Number("LvlPerLvl6"),
|
||||||
Head: d.GetNumber("Head", idx),
|
Head: d.Number("Head"),
|
||||||
Torso: d.GetNumber("Torso", idx),
|
Torso: d.Number("Torso"),
|
||||||
Weapon: d.GetNumber("Weapon", idx),
|
Weapon: d.Number("Weapon"),
|
||||||
Shield: d.GetNumber("Shield", idx),
|
Shield: d.Number("Shield"),
|
||||||
}
|
}
|
||||||
Hirelings = append(Hirelings, hireling)
|
Hirelings = append(Hirelings, hireling)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d.Err != nil {
|
||||||
|
panic(d.Err)
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("Loaded %d Hireling records", len(Hirelings))
|
log.Printf("Loaded %d Hireling records", len(Hirelings))
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,9 @@ import (
|
|||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MagicPrefix + MagicSuffix store item affix records
|
// MagicPrefix stores all of the magic prefix records
|
||||||
var MagicPrefix []*ItemAffixCommonRecord //nolint:gochecknoglobals // Currently global by design
|
var MagicPrefix []*ItemAffixCommonRecord //nolint:gochecknoglobals // Currently global by design
|
||||||
|
// MagicSuffix stores all of the magic suffix records
|
||||||
var MagicSuffix []*ItemAffixCommonRecord //nolint:gochecknoglobals // Currently global by design
|
var MagicSuffix []*ItemAffixCommonRecord //nolint:gochecknoglobals // Currently global by design
|
||||||
|
|
||||||
// LoadMagicPrefix loads MagicPrefix.txt
|
// LoadMagicPrefix loads MagicPrefix.txt
|
||||||
@ -47,46 +48,38 @@ func getAffixString(t1 d2enum.ItemAffixSuperType, t2 d2enum.ItemAffixSubType) st
|
|||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadDictionary(
|
func loadDictionary(file []byte, superType d2enum.ItemAffixSuperType, subType d2enum.ItemAffixSubType) []*ItemAffixCommonRecord {
|
||||||
file []byte,
|
d := d2common.LoadDataDictionary(file)
|
||||||
superType d2enum.ItemAffixSuperType,
|
records := createItemAffixRecords(d, superType, subType)
|
||||||
subType d2enum.ItemAffixSubType,
|
|
||||||
) []*ItemAffixCommonRecord {
|
|
||||||
dict := d2common.LoadDataDictionary(string(file))
|
|
||||||
records := createItemAffixRecords(dict, superType, subType)
|
|
||||||
name := getAffixString(superType, subType)
|
name := getAffixString(superType, subType)
|
||||||
log.Printf("Loaded %d %s records", len(dict.Data), name)
|
log.Printf("Loaded %d %s records", len(records), name)
|
||||||
|
|
||||||
return records
|
return records
|
||||||
}
|
}
|
||||||
|
|
||||||
func createItemAffixRecords(
|
func createItemAffixRecords(d *d2common.DataDictionary, superType d2enum.ItemAffixSuperType, subType d2enum.ItemAffixSubType) []*ItemAffixCommonRecord {
|
||||||
d *d2common.DataDictionary,
|
|
||||||
superType d2enum.ItemAffixSuperType,
|
|
||||||
subType d2enum.ItemAffixSubType,
|
|
||||||
) []*ItemAffixCommonRecord {
|
|
||||||
records := make([]*ItemAffixCommonRecord, 0)
|
records := make([]*ItemAffixCommonRecord, 0)
|
||||||
|
|
||||||
for index := range d.Data {
|
for d.Next() {
|
||||||
affix := &ItemAffixCommonRecord{
|
affix := &ItemAffixCommonRecord{
|
||||||
Name: d.GetString("Name", index),
|
Name: d.String("Name"),
|
||||||
Version: d.GetNumber("version", index),
|
Version: d.Number("version"),
|
||||||
Type: subType,
|
Type: subType,
|
||||||
IsPrefix: superType == d2enum.ItemAffixPrefix,
|
IsPrefix: superType == d2enum.ItemAffixPrefix,
|
||||||
IsSuffix: superType == d2enum.ItemAffixSuffix,
|
IsSuffix: superType == d2enum.ItemAffixSuffix,
|
||||||
Spawnable: d.GetNumber("spawnable", index) == 1,
|
Spawnable: d.Bool("spawnable"),
|
||||||
Rare: d.GetNumber("rare", index) == 1,
|
Rare: d.Bool("rare"),
|
||||||
Level: d.GetNumber("level", index),
|
Level: d.Number("level"),
|
||||||
MaxLevel: d.GetNumber("maxlevel", index),
|
MaxLevel: d.Number("maxlevel"),
|
||||||
LevelReq: d.GetNumber("levelreq", index),
|
LevelReq: d.Number("levelreq"),
|
||||||
Class: d.GetString("classspecific", index),
|
Class: d.String("classspecific"),
|
||||||
ClassLevelReq: d.GetNumber("classlevelreq", index),
|
ClassLevelReq: d.Number("classlevelreq"),
|
||||||
Frequency: d.GetNumber("frequency", index),
|
Frequency: d.Number("frequency"),
|
||||||
GroupID: d.GetNumber("group", index),
|
GroupID: d.Number("group"),
|
||||||
Transform: d.GetNumber("transform", index) == 1,
|
Transform: d.Bool("transform"),
|
||||||
TransformColor: d.GetString("transformcolor", index),
|
TransformColor: d.String("transformcolor"),
|
||||||
PriceAdd: d.GetNumber("add", index),
|
PriceAdd: d.Number("add"),
|
||||||
PriceScale: d.GetNumber("multiply", index),
|
PriceScale: d.Number("multiply"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// modifiers (Property references with parameters to be eval'd)
|
// modifiers (Property references with parameters to be eval'd)
|
||||||
@ -96,10 +89,10 @@ func createItemAffixRecords(
|
|||||||
minKey := fmt.Sprintf("mod%dmin", i)
|
minKey := fmt.Sprintf("mod%dmin", i)
|
||||||
maxKey := fmt.Sprintf("mod%dmax", i)
|
maxKey := fmt.Sprintf("mod%dmax", i)
|
||||||
modifier := &ItemAffixCommonModifier{
|
modifier := &ItemAffixCommonModifier{
|
||||||
Code: d.GetString(codeKey, index),
|
Code: d.String(codeKey),
|
||||||
Parameter: d.GetNumber(paramKey, index),
|
Parameter: d.Number(paramKey),
|
||||||
Min: d.GetNumber(minKey, index),
|
Min: d.Number(minKey),
|
||||||
Max: d.GetNumber(maxKey, index),
|
Max: d.Number(maxKey),
|
||||||
}
|
}
|
||||||
affix.Modifiers = append(affix.Modifiers, modifier)
|
affix.Modifiers = append(affix.Modifiers, modifier)
|
||||||
}
|
}
|
||||||
@ -107,14 +100,14 @@ func createItemAffixRecords(
|
|||||||
// items to include for spawning
|
// items to include for spawning
|
||||||
for i := 1; i <= 7; i++ {
|
for i := 1; i <= 7; i++ {
|
||||||
itemKey := fmt.Sprintf("itype%d", i)
|
itemKey := fmt.Sprintf("itype%d", i)
|
||||||
itemToken := d.GetString(itemKey, index)
|
itemToken := d.String(itemKey)
|
||||||
affix.ItemInclude = append(affix.ItemInclude, itemToken)
|
affix.ItemInclude = append(affix.ItemInclude, itemToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
// items to exclude for spawning
|
// items to exclude for spawning
|
||||||
for i := 1; i <= 7; i++ {
|
for i := 1; i <= 7; i++ {
|
||||||
itemKey := fmt.Sprintf("etype%d", i)
|
itemKey := fmt.Sprintf("etype%d", i)
|
||||||
itemToken := d.GetString(itemKey, index)
|
itemToken := d.String(itemKey)
|
||||||
affix.ItemExclude = append(affix.ItemExclude, itemToken)
|
affix.ItemExclude = append(affix.ItemExclude, itemToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,6 +127,9 @@ func createItemAffixRecords(
|
|||||||
|
|
||||||
records = append(records, affix)
|
records = append(records, affix)
|
||||||
}
|
}
|
||||||
|
if d.Err != nil {
|
||||||
|
panic(d.Err)
|
||||||
|
}
|
||||||
|
|
||||||
return records
|
return records
|
||||||
}
|
}
|
||||||
|
@ -109,81 +109,83 @@ var ItemStatCosts map[string]*ItemStatCostRecord
|
|||||||
|
|
||||||
// LoadItemStatCosts loads ItemStatCostRecord's from text
|
// LoadItemStatCosts loads ItemStatCostRecord's from text
|
||||||
func LoadItemStatCosts(file []byte) {
|
func LoadItemStatCosts(file []byte) {
|
||||||
d := d2common.LoadDataDictionary(string(file))
|
ItemStatCosts = make(map[string]*ItemStatCostRecord)
|
||||||
numRecords := len(d.Data)
|
|
||||||
ItemStatCosts = make(map[string]*ItemStatCostRecord, numRecords)
|
|
||||||
|
|
||||||
for idx := range d.Data {
|
d := d2common.LoadDataDictionary(file)
|
||||||
|
for d.Next() {
|
||||||
record := &ItemStatCostRecord{
|
record := &ItemStatCostRecord{
|
||||||
Name: d.GetString("Stat", idx),
|
Name: d.String("Stat"),
|
||||||
Index: d.GetNumber("ID", idx),
|
Index: d.Number("ID"),
|
||||||
|
|
||||||
Signed: d.GetNumber("Signed", idx) > 0,
|
Signed: d.Number("Signed") > 0,
|
||||||
KeepZero: d.GetNumber("keepzero", idx) > 0,
|
KeepZero: d.Number("keepzero") > 0,
|
||||||
|
|
||||||
// Ranged: d.GetNumber("Ranged", idx) > 0,
|
// Ranged: d.Number("Ranged") > 0,
|
||||||
MinAccr: d.GetNumber("MinAccr", idx),
|
MinAccr: d.Number("MinAccr"),
|
||||||
|
|
||||||
UpdateAnimRate: d.GetNumber("UpdateAnimRate", idx) > 0,
|
UpdateAnimRate: d.Number("UpdateAnimRate") > 0,
|
||||||
|
|
||||||
SendOther: d.GetNumber("Send Other", idx) > 0,
|
SendOther: d.Number("Send Other") > 0,
|
||||||
SendBits: d.GetNumber("Send Bits", idx),
|
SendBits: d.Number("Send Bits"),
|
||||||
SendParam: d.GetNumber("Send Param Bits", idx),
|
SendParam: d.Number("Send Param Bits"),
|
||||||
|
|
||||||
Saved: d.GetNumber("CSvBits", idx) > 0,
|
Saved: d.Number("CSvBits") > 0,
|
||||||
SavedSigned: d.GetNumber("CSvSigned", idx) > 0,
|
SavedSigned: d.Number("CSvSigned") > 0,
|
||||||
SavedBits: d.GetNumber("CSvBits", idx),
|
SavedBits: d.Number("CSvBits"),
|
||||||
SaveBits: d.GetNumber("Save Bits", idx),
|
SaveBits: d.Number("Save Bits"),
|
||||||
SaveAdd: d.GetNumber("Save Add", idx),
|
SaveAdd: d.Number("Save Add"),
|
||||||
SaveParamBits: d.GetNumber("Save Param Bits", idx),
|
SaveParamBits: d.Number("Save Param Bits"),
|
||||||
|
|
||||||
Encode: d2enum.EncodingType(d.GetNumber("Encode", idx)),
|
Encode: d2enum.EncodingType(d.Number("Encode")),
|
||||||
|
|
||||||
CallbackEnabled: d.GetNumber("fCallback", idx) > 0,
|
CallbackEnabled: d.Number("fCallback") > 0,
|
||||||
|
|
||||||
CostAdd: d.GetNumber("Add", idx),
|
CostAdd: d.Number("Add"),
|
||||||
CostMultiply: d.GetNumber("Multiply", idx),
|
CostMultiply: d.Number("Multiply"),
|
||||||
ValShift: d.GetNumber("ValShift", idx),
|
ValShift: d.Number("ValShift"),
|
||||||
|
|
||||||
OperatorType: d2enum.OperatorType(d.GetNumber("op", idx)),
|
OperatorType: d2enum.OperatorType(d.Number("op")),
|
||||||
OpParam: d.GetNumber("op param", idx),
|
OpParam: d.Number("op param"),
|
||||||
OpBase: d.GetString("op base", idx),
|
OpBase: d.String("op base"),
|
||||||
OpStat1: d.GetString("op stat1", idx),
|
OpStat1: d.String("op stat1"),
|
||||||
OpStat2: d.GetString("op stat2", idx),
|
OpStat2: d.String("op stat2"),
|
||||||
OpStat3: d.GetString("op stat3", idx),
|
OpStat3: d.String("op stat3"),
|
||||||
|
|
||||||
Direct: d.GetNumber("direct", idx) > 0,
|
Direct: d.Number("direct") > 0,
|
||||||
MaxStat: d.GetString("maxstat", idx),
|
MaxStat: d.String("maxstat"),
|
||||||
|
|
||||||
ItemSpecific: d.GetNumber("itemspecific", idx) > 0,
|
ItemSpecific: d.Number("itemspecific") > 0,
|
||||||
DamageRelated: d.GetNumber("damagerelated", idx) > 0,
|
DamageRelated: d.Number("damagerelated") > 0,
|
||||||
|
|
||||||
EventID1: d2enum.GetItemEventType(d.GetString("itemevent1", idx)),
|
EventID1: d2enum.GetItemEventType(d.String("itemevent1")),
|
||||||
EventID2: d2enum.GetItemEventType(d.GetString("itemevent2", idx)),
|
EventID2: d2enum.GetItemEventType(d.String("itemevent2")),
|
||||||
EventFuncID1: d2enum.GetItemEventFuncID(d.GetNumber("itemeventfunc1", idx)),
|
EventFuncID1: d2enum.GetItemEventFuncID(d.Number("itemeventfunc1")),
|
||||||
EventFuncID2: d2enum.GetItemEventFuncID(d.GetNumber("itemeventfunc2", idx)),
|
EventFuncID2: d2enum.GetItemEventFuncID(d.Number("itemeventfunc2")),
|
||||||
|
|
||||||
DescPriority: d.GetNumber("descpriority", idx),
|
DescPriority: d.Number("descpriority"),
|
||||||
DescFnID: d2enum.DescFuncID(d.GetNumber("descfunc", idx)),
|
DescFnID: d2enum.DescFuncID(d.Number("descfunc")),
|
||||||
DescFn: d2enum.GetDescFunction(d2enum.DescFuncID(d.GetNumber("descfunc", idx))),
|
DescFn: d2enum.GetDescFunction(d2enum.DescFuncID(d.Number("descfunc"))),
|
||||||
DescVal: d.GetNumber("descval", idx),
|
DescVal: d.Number("descval"),
|
||||||
DescStrPos: d.GetString("descstrpos", idx),
|
DescStrPos: d.String("descstrpos"),
|
||||||
DescStrNeg: d.GetString("descstrneg", idx),
|
DescStrNeg: d.String("descstrneg"),
|
||||||
DescStr2: d.GetString("descstr2", idx),
|
DescStr2: d.String("descstr2"),
|
||||||
|
|
||||||
DescGroup: d.GetNumber("dgrp", idx),
|
DescGroup: d.Number("dgrp"),
|
||||||
DescGroupFuncID: d2enum.DescFuncID(d.GetNumber("dgrpfunc", idx)),
|
DescGroupFuncID: d2enum.DescFuncID(d.Number("dgrpfunc")),
|
||||||
DescGroupFn: d2enum.GetDescFunction(d2enum.DescFuncID(d.GetNumber("dgrpfunc", idx))),
|
DescGroupFn: d2enum.GetDescFunction(d2enum.DescFuncID(d.Number("dgrpfunc"))),
|
||||||
DescGroupVal: d.GetNumber("dgrpval", idx),
|
DescGroupVal: d.Number("dgrpval"),
|
||||||
DescGroupStrPos: d.GetString("dgrpstrpos", idx),
|
DescGroupStrPos: d.String("dgrpstrpos"),
|
||||||
DescGroupStrNeg: d.GetString("dgrpstrneg", idx),
|
DescGroupStrNeg: d.String("dgrpstrneg"),
|
||||||
DescGroupStr2: d.GetString("dgrpstr2", idx),
|
DescGroupStr2: d.String("dgrpstr2"),
|
||||||
|
|
||||||
Stuff: d.GetString("stuff", idx),
|
Stuff: d.String("stuff"),
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemStatCosts[record.Name] = record
|
ItemStatCosts[record.Name] = record
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d.Err != nil {
|
||||||
|
panic(d.Err)
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("Loaded %d ItemStatCost records", len(ItemStatCosts))
|
log.Printf("Loaded %d ItemStatCost records", len(ItemStatCosts))
|
||||||
}
|
}
|
||||||
|
@ -41,22 +41,25 @@ var LevelMazeDetails map[int]*LevelMazeDetailsRecord //nolint:gochecknoglobals /
|
|||||||
|
|
||||||
// LoadLevelMazeDetails loads LevelMazeDetailsRecords from text file
|
// LoadLevelMazeDetails loads LevelMazeDetailsRecords from text file
|
||||||
func LoadLevelMazeDetails(file []byte) {
|
func LoadLevelMazeDetails(file []byte) {
|
||||||
dict := d2common.LoadDataDictionary(string(file))
|
LevelMazeDetails = make(map[int]*LevelMazeDetailsRecord)
|
||||||
numRecords := len(dict.Data)
|
|
||||||
LevelMazeDetails = make(map[int]*LevelMazeDetailsRecord, numRecords)
|
|
||||||
|
|
||||||
for idx := range dict.Data {
|
d := d2common.LoadDataDictionary(file)
|
||||||
|
for d.Next() {
|
||||||
record := &LevelMazeDetailsRecord{
|
record := &LevelMazeDetailsRecord{
|
||||||
Name: dict.GetString("Name", idx),
|
Name: d.String("Name"),
|
||||||
LevelID: dict.GetNumber("Level", idx),
|
LevelID: d.Number("Level"),
|
||||||
NumRoomsNormal: dict.GetNumber("Rooms", idx),
|
NumRoomsNormal: d.Number("Rooms"),
|
||||||
NumRoomsNightmare: dict.GetNumber("Rooms(N)", idx),
|
NumRoomsNightmare: d.Number("Rooms(N)"),
|
||||||
NumRoomsHell: dict.GetNumber("Rooms(H)", idx),
|
NumRoomsHell: d.Number("Rooms(H)"),
|
||||||
SizeX: dict.GetNumber("SizeX", idx),
|
SizeX: d.Number("SizeX"),
|
||||||
SizeY: dict.GetNumber("SizeY", idx),
|
SizeY: d.Number("SizeY"),
|
||||||
}
|
}
|
||||||
LevelMazeDetails[record.LevelID] = record
|
LevelMazeDetails[record.LevelID] = record
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d.Err != nil {
|
||||||
|
panic(d.Err)
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("Loaded %d LevelMazeDetails records", len(LevelMazeDetails))
|
log.Printf("Loaded %d LevelMazeDetails records", len(LevelMazeDetails))
|
||||||
}
|
}
|
||||||
|
@ -70,38 +70,40 @@ var LevelSubstitutions map[int]*LevelSubstitutionRecord
|
|||||||
|
|
||||||
// LoadLevelSubstitutions loads lvlsub.txt and parses into records
|
// LoadLevelSubstitutions loads lvlsub.txt and parses into records
|
||||||
func LoadLevelSubstitutions(file []byte) {
|
func LoadLevelSubstitutions(file []byte) {
|
||||||
dict := d2common.LoadDataDictionary(string(file))
|
LevelSubstitutions = make(map[int]*LevelSubstitutionRecord)
|
||||||
numRecords := len(dict.Data)
|
|
||||||
LevelSubstitutions = make(map[int]*LevelSubstitutionRecord, numRecords)
|
|
||||||
|
|
||||||
for idx := range dict.Data {
|
d := d2common.LoadDataDictionary(file)
|
||||||
|
for d.Next() {
|
||||||
record := &LevelSubstitutionRecord{
|
record := &LevelSubstitutionRecord{
|
||||||
Name: dict.GetString("Name", idx),
|
Name: d.String("Name"),
|
||||||
ID: dict.GetNumber("Type", idx),
|
ID: d.Number("Type"),
|
||||||
File: dict.GetString("File", idx),
|
File: d.String("File"),
|
||||||
IsExpansion: dict.GetNumber("Expansion", idx) > 0,
|
IsExpansion: d.Number("Expansion") > 0,
|
||||||
BorderType: dict.GetNumber("BordType", idx),
|
BorderType: d.Number("BordType"),
|
||||||
GridSize: dict.GetNumber("GridSize", idx),
|
GridSize: d.Number("GridSize"),
|
||||||
Mask: dict.GetNumber("Dt1Mask", idx),
|
Mask: d.Number("Dt1Mask"),
|
||||||
ChanceSpawn0: dict.GetNumber("Prob0", idx),
|
ChanceSpawn0: d.Number("Prob0"),
|
||||||
ChanceSpawn1: dict.GetNumber("Prob1", idx),
|
ChanceSpawn1: d.Number("Prob1"),
|
||||||
ChanceSpawn2: dict.GetNumber("Prob2", idx),
|
ChanceSpawn2: d.Number("Prob2"),
|
||||||
ChanceSpawn3: dict.GetNumber("Prob3", idx),
|
ChanceSpawn3: d.Number("Prob3"),
|
||||||
ChanceSpawn4: dict.GetNumber("Prob4", idx),
|
ChanceSpawn4: d.Number("Prob4"),
|
||||||
ChanceFloor0: dict.GetNumber("Trials0", idx),
|
ChanceFloor0: d.Number("Trials0"),
|
||||||
ChanceFloor1: dict.GetNumber("Trials1", idx),
|
ChanceFloor1: d.Number("Trials1"),
|
||||||
ChanceFloor2: dict.GetNumber("Trials2", idx),
|
ChanceFloor2: d.Number("Trials2"),
|
||||||
ChanceFloor3: dict.GetNumber("Trials3", idx),
|
ChanceFloor3: d.Number("Trials3"),
|
||||||
ChanceFloor4: dict.GetNumber("Trials4", idx),
|
ChanceFloor4: d.Number("Trials4"),
|
||||||
GridMax0: dict.GetNumber("Max0", idx),
|
GridMax0: d.Number("Max0"),
|
||||||
GridMax1: dict.GetNumber("Max1", idx),
|
GridMax1: d.Number("Max1"),
|
||||||
GridMax2: dict.GetNumber("Max2", idx),
|
GridMax2: d.Number("Max2"),
|
||||||
GridMax3: dict.GetNumber("Max3", idx),
|
GridMax3: d.Number("Max3"),
|
||||||
GridMax4: dict.GetNumber("Max4", idx),
|
GridMax4: d.Number("Max4"),
|
||||||
}
|
}
|
||||||
|
|
||||||
LevelSubstitutions[record.ID] = record
|
LevelSubstitutions[record.ID] = record
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d.Err != nil {
|
||||||
|
panic(d.Err)
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("Loaded %d LevelSubstitution records", len(LevelSubstitutions))
|
log.Printf("Loaded %d LevelSubstitution records", len(LevelSubstitutions))
|
||||||
}
|
}
|
||||||
|
@ -9,17 +9,18 @@ import (
|
|||||||
// LevelWarpRecord is a representation of a row from lvlwarp.txt
|
// LevelWarpRecord is a representation of a row from lvlwarp.txt
|
||||||
// it describes the warp graphics offsets and dimensions for levels
|
// it describes the warp graphics offsets and dimensions for levels
|
||||||
type LevelWarpRecord struct {
|
type LevelWarpRecord struct {
|
||||||
ID int32
|
Name string
|
||||||
SelectX int32
|
ID int
|
||||||
SelectY int32
|
SelectX int
|
||||||
SelectDX int32
|
SelectY int
|
||||||
SelectDY int32
|
SelectDX int
|
||||||
ExitWalkX int32
|
SelectDY int
|
||||||
ExitWalkY int32
|
ExitWalkX int
|
||||||
OffsetX int32
|
ExitWalkY int
|
||||||
OffsetY int32
|
OffsetX int
|
||||||
|
OffsetY int
|
||||||
LitVersion bool
|
LitVersion bool
|
||||||
Tiles int32
|
Tiles int
|
||||||
Direction string
|
Direction string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,27 +29,27 @@ type LevelWarpRecord struct {
|
|||||||
var LevelWarps map[int]*LevelWarpRecord
|
var LevelWarps map[int]*LevelWarpRecord
|
||||||
|
|
||||||
// LoadLevelWarps loads LevelWarpRecord's from text file data
|
// LoadLevelWarps loads LevelWarpRecord's from text file data
|
||||||
func LoadLevelWarps(levelWarpData []byte) {
|
func LoadLevelWarps(file []byte) {
|
||||||
LevelWarps = make(map[int]*LevelWarpRecord)
|
LevelWarps = make(map[int]*LevelWarpRecord)
|
||||||
streamReader := d2common.CreateStreamReader(levelWarpData)
|
|
||||||
numRecords := int(streamReader.GetInt32())
|
|
||||||
|
|
||||||
for i := 0; i < numRecords; i++ {
|
d := d2common.LoadDataDictionary(file)
|
||||||
id := int(streamReader.GetInt32())
|
for d.Next() {
|
||||||
LevelWarps[id] = &LevelWarpRecord{}
|
record := &LevelWarpRecord{
|
||||||
LevelWarps[id].ID = int32(id)
|
Name: d.String("Name"),
|
||||||
LevelWarps[id].SelectX = streamReader.GetInt32()
|
ID: d.Number("Id"),
|
||||||
LevelWarps[id].SelectY = streamReader.GetInt32()
|
SelectX: d.Number("SelectX"),
|
||||||
LevelWarps[id].SelectDX = streamReader.GetInt32()
|
SelectY: d.Number("SelectY"),
|
||||||
LevelWarps[id].SelectDY = streamReader.GetInt32()
|
SelectDX: d.Number("SelectDX"),
|
||||||
LevelWarps[id].ExitWalkX = streamReader.GetInt32()
|
SelectDY: d.Number("SelectDY"),
|
||||||
LevelWarps[id].ExitWalkY = streamReader.GetInt32()
|
ExitWalkX: d.Number("ExitWalkX"),
|
||||||
LevelWarps[id].OffsetX = streamReader.GetInt32()
|
ExitWalkY: d.Number("ExitWalkY"),
|
||||||
LevelWarps[id].OffsetY = streamReader.GetInt32()
|
OffsetX: d.Number("OffsetX"),
|
||||||
LevelWarps[id].LitVersion = streamReader.GetInt32() == 1
|
OffsetY: d.Number("OffsetY"),
|
||||||
LevelWarps[id].Tiles = streamReader.GetInt32()
|
LitVersion: d.Bool("LitVersion"),
|
||||||
LevelWarps[id].Direction = string(streamReader.GetByte())
|
Tiles: d.Number("Tiles"),
|
||||||
streamReader.SkipBytes(3)
|
Direction: d.String("Direction"),
|
||||||
|
}
|
||||||
|
LevelWarps[record.ID] = record
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Loaded %d level warps", len(LevelWarps))
|
log.Printf("Loaded %d level warps", len(LevelWarps))
|
||||||
|
@ -95,7 +95,7 @@ type LevelDetailsRecord struct {
|
|||||||
|
|
||||||
// Id
|
// Id
|
||||||
// Level ID (used in columns like VIS0-7)
|
// Level ID (used in columns like VIS0-7)
|
||||||
Id int //nolint:golint Id is the right key
|
Id int //nolint:golint,stylecheck // Id is the right key
|
||||||
|
|
||||||
// Palette is the Act Palette . Reference only
|
// Palette is the Act Palette . Reference only
|
||||||
Palette int // Pal
|
Palette int // Pal
|
||||||
@ -381,159 +381,162 @@ func GetLevelDetails(id int) *LevelDetailsRecord {
|
|||||||
// LoadLevelDetails loads level details records from levels.txt
|
// LoadLevelDetails loads level details records from levels.txt
|
||||||
//nolint:funlen // Txt loader, makes no sense to split
|
//nolint:funlen // Txt loader, makes no sense to split
|
||||||
func LoadLevelDetails(file []byte) {
|
func LoadLevelDetails(file []byte) {
|
||||||
dict := d2common.LoadDataDictionary(string(file))
|
LevelDetails = make(map[int]*LevelDetailsRecord)
|
||||||
numRecords := len(dict.Data)
|
|
||||||
LevelDetails = make(map[int]*LevelDetailsRecord, numRecords)
|
|
||||||
|
|
||||||
for idx := range dict.Data {
|
d := d2common.LoadDataDictionary(file)
|
||||||
|
for d.Next() {
|
||||||
record := &LevelDetailsRecord{
|
record := &LevelDetailsRecord{
|
||||||
Name: dict.GetString("Name ", idx),
|
Name: d.String("Name "),
|
||||||
Id: dict.GetNumber("Id", idx),
|
Id: d.Number("Id"),
|
||||||
Palette: dict.GetNumber("Pal", idx),
|
Palette: d.Number("Pal"),
|
||||||
Act: dict.GetNumber("Act", idx),
|
Act: d.Number("Act"),
|
||||||
QuestFlag: dict.GetNumber("QuestFlag", idx),
|
QuestFlag: d.Number("QuestFlag"),
|
||||||
QuestFlagExpansion: dict.GetNumber("QuestFlagEx", idx),
|
QuestFlagExpansion: d.Number("QuestFlagEx"),
|
||||||
AutomapIndex: dict.GetNumber("Layer", idx),
|
AutomapIndex: d.Number("Layer"),
|
||||||
SizeXNormal: dict.GetNumber("SizeX", idx),
|
SizeXNormal: d.Number("SizeX"),
|
||||||
SizeYNormal: dict.GetNumber("SizeY", idx),
|
SizeYNormal: d.Number("SizeY"),
|
||||||
SizeXNightmare: dict.GetNumber("SizeX(N)", idx),
|
SizeXNightmare: d.Number("SizeX(N)"),
|
||||||
SizeYNightmare: dict.GetNumber("SizeY(N)", idx),
|
SizeYNightmare: d.Number("SizeY(N)"),
|
||||||
SizeXHell: dict.GetNumber("SizeX(H)", idx),
|
SizeXHell: d.Number("SizeX(H)"),
|
||||||
SizeYHell: dict.GetNumber("SizeY(H)", idx),
|
SizeYHell: d.Number("SizeY(H)"),
|
||||||
WorldOffsetX: dict.GetNumber("OffsetX", idx),
|
WorldOffsetX: d.Number("OffsetX"),
|
||||||
WorldOffsetY: dict.GetNumber("OffsetY", idx),
|
WorldOffsetY: d.Number("OffsetY"),
|
||||||
DependantLevelID: dict.GetNumber("Depend", idx),
|
DependantLevelID: d.Number("Depend"),
|
||||||
TeleportFlag: d2enum.TeleportFlag(dict.GetNumber("Teleport", idx)),
|
TeleportFlag: d2enum.TeleportFlag(d.Number("Teleport")),
|
||||||
EnableRain: dict.GetNumber("Rain", idx) > 0,
|
EnableRain: d.Number("Rain") > 0,
|
||||||
EnableMud: dict.GetNumber("Mud", idx) > 0,
|
EnableMud: d.Number("Mud") > 0,
|
||||||
EnablePerspective: dict.GetNumber("NoPer", idx) > 0,
|
EnablePerspective: d.Number("NoPer") > 0,
|
||||||
EnableLineOfSightDraw: dict.GetNumber("LOSDraw", idx) > 0,
|
EnableLineOfSightDraw: d.Number("LOSDraw") > 0,
|
||||||
EnableFloorFliter: dict.GetNumber("FloorFilter", idx) > 0,
|
EnableFloorFliter: d.Number("FloorFilter") > 0,
|
||||||
EnableBlankScreen: dict.GetNumber("BlankScreen", idx) > 0,
|
EnableBlankScreen: d.Number("BlankScreen") > 0,
|
||||||
EnableDrawEdges: dict.GetNumber("DrawEdges", idx) > 0,
|
EnableDrawEdges: d.Number("DrawEdges") > 0,
|
||||||
IsInside: dict.GetNumber("IsInside", idx) > 0,
|
IsInside: d.Number("IsInside") > 0,
|
||||||
LevelGenerationType: d2enum.LevelGenerationType(dict.GetNumber("DrlgType", idx)),
|
LevelGenerationType: d2enum.LevelGenerationType(d.Number("DrlgType")),
|
||||||
LevelType: dict.GetNumber("LevelType", idx),
|
LevelType: d.Number("LevelType"),
|
||||||
SubType: dict.GetNumber("SubType", idx),
|
SubType: d.Number("SubType"),
|
||||||
SubTheme: dict.GetNumber("SubTheme", idx),
|
SubTheme: d.Number("SubTheme"),
|
||||||
SubWaypoint: dict.GetNumber("SubWaypoint", idx),
|
SubWaypoint: d.Number("SubWaypoint"),
|
||||||
SubShrine: dict.GetNumber("SubShrine", idx),
|
SubShrine: d.Number("SubShrine"),
|
||||||
LevelLinkID0: dict.GetNumber("Vis0", idx),
|
LevelLinkID0: d.Number("Vis0"),
|
||||||
LevelLinkID1: dict.GetNumber("Vis1", idx),
|
LevelLinkID1: d.Number("Vis1"),
|
||||||
LevelLinkID2: dict.GetNumber("Vis2", idx),
|
LevelLinkID2: d.Number("Vis2"),
|
||||||
LevelLinkID3: dict.GetNumber("Vis3", idx),
|
LevelLinkID3: d.Number("Vis3"),
|
||||||
LevelLinkID4: dict.GetNumber("Vis4", idx),
|
LevelLinkID4: d.Number("Vis4"),
|
||||||
LevelLinkID5: dict.GetNumber("Vis5", idx),
|
LevelLinkID5: d.Number("Vis5"),
|
||||||
LevelLinkID6: dict.GetNumber("Vis6", idx),
|
LevelLinkID6: d.Number("Vis6"),
|
||||||
LevelLinkID7: dict.GetNumber("Vis7", idx),
|
LevelLinkID7: d.Number("Vis7"),
|
||||||
WarpGraphicsID0: dict.GetNumber("Warp0", idx),
|
WarpGraphicsID0: d.Number("Warp0"),
|
||||||
WarpGraphicsID1: dict.GetNumber("Warp1", idx),
|
WarpGraphicsID1: d.Number("Warp1"),
|
||||||
WarpGraphicsID2: dict.GetNumber("Warp2", idx),
|
WarpGraphicsID2: d.Number("Warp2"),
|
||||||
WarpGraphicsID3: dict.GetNumber("Warp3", idx),
|
WarpGraphicsID3: d.Number("Warp3"),
|
||||||
WarpGraphicsID4: dict.GetNumber("Warp4", idx),
|
WarpGraphicsID4: d.Number("Warp4"),
|
||||||
WarpGraphicsID5: dict.GetNumber("Warp5", idx),
|
WarpGraphicsID5: d.Number("Warp5"),
|
||||||
WarpGraphicsID6: dict.GetNumber("Warp6", idx),
|
WarpGraphicsID6: d.Number("Warp6"),
|
||||||
WarpGraphicsID7: dict.GetNumber("Warp7", idx),
|
WarpGraphicsID7: d.Number("Warp7"),
|
||||||
LightIntensity: dict.GetNumber("Intensity", idx),
|
LightIntensity: d.Number("Intensity"),
|
||||||
Red: dict.GetNumber("Red", idx),
|
Red: d.Number("Red"),
|
||||||
Green: dict.GetNumber("Green", idx),
|
Green: d.Number("Green"),
|
||||||
Blue: dict.GetNumber("Blue", idx),
|
Blue: d.Number("Blue"),
|
||||||
PortalEnable: dict.GetNumber("Portal", idx) > 0,
|
PortalEnable: d.Number("Portal") > 0,
|
||||||
PortalRepositionEnable: dict.GetNumber("Position", idx) > 0,
|
PortalRepositionEnable: d.Number("Position") > 0,
|
||||||
SaveMonsterStates: dict.GetNumber("SaveMonsters", idx) > 0,
|
SaveMonsterStates: d.Number("SaveMonsters") > 0,
|
||||||
SaveMerchantStates: dict.GetNumber("SaveMonsters", idx) > 0,
|
SaveMerchantStates: d.Number("SaveMonsters") > 0,
|
||||||
QuestID: dict.GetNumber("Quest", idx),
|
QuestID: d.Number("Quest"),
|
||||||
WarpClearanceDistance: dict.GetNumber("WarpDist", idx),
|
WarpClearanceDistance: d.Number("WarpDist"),
|
||||||
MonsterLevelNormal: dict.GetNumber("MonLvl1", idx),
|
MonsterLevelNormal: d.Number("MonLvl1"),
|
||||||
MonsterLevelNightmare: dict.GetNumber("MonLvl2", idx),
|
MonsterLevelNightmare: d.Number("MonLvl2"),
|
||||||
MonsterLevelHell: dict.GetNumber("MonLvl3", idx),
|
MonsterLevelHell: d.Number("MonLvl3"),
|
||||||
MonsterLevelNormalEx: dict.GetNumber("MonLvl1Ex", idx),
|
MonsterLevelNormalEx: d.Number("MonLvl1Ex"),
|
||||||
MonsterLevelNightmareEx: dict.GetNumber("MonLvl2Ex", idx),
|
MonsterLevelNightmareEx: d.Number("MonLvl2Ex"),
|
||||||
MonsterLevelHellEx: dict.GetNumber("MonLvl3Ex", idx),
|
MonsterLevelHellEx: d.Number("MonLvl3Ex"),
|
||||||
MonsterDensityNormal: dict.GetNumber("MonDen", idx),
|
MonsterDensityNormal: d.Number("MonDen"),
|
||||||
MonsterDensityNightmare: dict.GetNumber("MonDen(N)", idx),
|
MonsterDensityNightmare: d.Number("MonDen(N)"),
|
||||||
MonsterDensityHell: dict.GetNumber("MonDen(H)", idx),
|
MonsterDensityHell: d.Number("MonDen(H)"),
|
||||||
MonsterUniqueMinNormal: dict.GetNumber("MonUMin", idx),
|
MonsterUniqueMinNormal: d.Number("MonUMin"),
|
||||||
MonsterUniqueMinNightmare: dict.GetNumber("MonUMin(N)", idx),
|
MonsterUniqueMinNightmare: d.Number("MonUMin(N)"),
|
||||||
MonsterUniqueMinHell: dict.GetNumber("MonUMin(H)", idx),
|
MonsterUniqueMinHell: d.Number("MonUMin(H)"),
|
||||||
MonsterUniqueMaxNormal: dict.GetNumber("MonUMax", idx),
|
MonsterUniqueMaxNormal: d.Number("MonUMax"),
|
||||||
MonsterUniqueMaxNightmare: dict.GetNumber("MonUMax(N)", idx),
|
MonsterUniqueMaxNightmare: d.Number("MonUMax(N)"),
|
||||||
MonsterUniqueMaxHell: dict.GetNumber("MonUMax(H)", idx),
|
MonsterUniqueMaxHell: d.Number("MonUMax(H)"),
|
||||||
MonsterWanderEnable: dict.GetNumber("MonWndr", idx) > 0,
|
MonsterWanderEnable: d.Number("MonWndr") > 0,
|
||||||
MonsterSpecialWalk: dict.GetNumber("MonSpcWalk", idx) > 0,
|
MonsterSpecialWalk: d.Number("MonSpcWalk") > 0,
|
||||||
NumMonsterTypes: dict.GetNumber("NumMon", idx),
|
NumMonsterTypes: d.Number("NumMon"),
|
||||||
MonsterID1Normal: dict.GetString("mon1", idx),
|
MonsterID1Normal: d.String("mon1"),
|
||||||
MonsterID2Normal: dict.GetString("mon2", idx),
|
MonsterID2Normal: d.String("mon2"),
|
||||||
MonsterID3Normal: dict.GetString("mon3", idx),
|
MonsterID3Normal: d.String("mon3"),
|
||||||
MonsterID4Normal: dict.GetString("mon4", idx),
|
MonsterID4Normal: d.String("mon4"),
|
||||||
MonsterID5Normal: dict.GetString("mon5", idx),
|
MonsterID5Normal: d.String("mon5"),
|
||||||
MonsterID6Normal: dict.GetString("mon6", idx),
|
MonsterID6Normal: d.String("mon6"),
|
||||||
MonsterID7Normal: dict.GetString("mon7", idx),
|
MonsterID7Normal: d.String("mon7"),
|
||||||
MonsterID8Normal: dict.GetString("mon8", idx),
|
MonsterID8Normal: d.String("mon8"),
|
||||||
MonsterID9Normal: dict.GetString("mon9", idx),
|
MonsterID9Normal: d.String("mon9"),
|
||||||
MonsterID10Normal: dict.GetString("mon10", idx),
|
MonsterID10Normal: d.String("mon10"),
|
||||||
MonsterID1Nightmare: dict.GetString("nmon1", idx),
|
MonsterID1Nightmare: d.String("nmon1"),
|
||||||
MonsterID2Nightmare: dict.GetString("nmon2", idx),
|
MonsterID2Nightmare: d.String("nmon2"),
|
||||||
MonsterID3Nightmare: dict.GetString("nmon3", idx),
|
MonsterID3Nightmare: d.String("nmon3"),
|
||||||
MonsterID4Nightmare: dict.GetString("nmon4", idx),
|
MonsterID4Nightmare: d.String("nmon4"),
|
||||||
MonsterID5Nightmare: dict.GetString("nmon5", idx),
|
MonsterID5Nightmare: d.String("nmon5"),
|
||||||
MonsterID6Nightmare: dict.GetString("nmon6", idx),
|
MonsterID6Nightmare: d.String("nmon6"),
|
||||||
MonsterID7Nightmare: dict.GetString("nmon7", idx),
|
MonsterID7Nightmare: d.String("nmon7"),
|
||||||
MonsterID8Nightmare: dict.GetString("nmon8", idx),
|
MonsterID8Nightmare: d.String("nmon8"),
|
||||||
MonsterID9Nightmare: dict.GetString("nmon9", idx),
|
MonsterID9Nightmare: d.String("nmon9"),
|
||||||
MonsterID10Nightmare: dict.GetString("nmon10", idx),
|
MonsterID10Nightmare: d.String("nmon10"),
|
||||||
MonsterID1Hell: dict.GetString("nmon1", idx),
|
MonsterID1Hell: d.String("nmon1"),
|
||||||
MonsterID2Hell: dict.GetString("nmon2", idx),
|
MonsterID2Hell: d.String("nmon2"),
|
||||||
MonsterID3Hell: dict.GetString("nmon3", idx),
|
MonsterID3Hell: d.String("nmon3"),
|
||||||
MonsterID4Hell: dict.GetString("nmon4", idx),
|
MonsterID4Hell: d.String("nmon4"),
|
||||||
MonsterID5Hell: dict.GetString("nmon5", idx),
|
MonsterID5Hell: d.String("nmon5"),
|
||||||
MonsterID6Hell: dict.GetString("nmon6", idx),
|
MonsterID6Hell: d.String("nmon6"),
|
||||||
MonsterID7Hell: dict.GetString("nmon7", idx),
|
MonsterID7Hell: d.String("nmon7"),
|
||||||
MonsterID8Hell: dict.GetString("nmon8", idx),
|
MonsterID8Hell: d.String("nmon8"),
|
||||||
MonsterID9Hell: dict.GetString("nmon9", idx),
|
MonsterID9Hell: d.String("nmon9"),
|
||||||
MonsterID10Hell: dict.GetString("nmon10", idx),
|
MonsterID10Hell: d.String("nmon10"),
|
||||||
MonsterPreferRanged: dict.GetNumber("rangedspawn", idx) > 0,
|
MonsterPreferRanged: d.Number("rangedspawn") > 0,
|
||||||
MonsterUniqueID1: dict.GetString("umon1", idx),
|
MonsterUniqueID1: d.String("umon1"),
|
||||||
MonsterUniqueID2: dict.GetString("umon2", idx),
|
MonsterUniqueID2: d.String("umon2"),
|
||||||
MonsterUniqueID3: dict.GetString("umon3", idx),
|
MonsterUniqueID3: d.String("umon3"),
|
||||||
MonsterUniqueID4: dict.GetString("umon4", idx),
|
MonsterUniqueID4: d.String("umon4"),
|
||||||
MonsterUniqueID5: dict.GetString("umon5", idx),
|
MonsterUniqueID5: d.String("umon5"),
|
||||||
MonsterUniqueID6: dict.GetString("umon6", idx),
|
MonsterUniqueID6: d.String("umon6"),
|
||||||
MonsterUniqueID7: dict.GetString("umon7", idx),
|
MonsterUniqueID7: d.String("umon7"),
|
||||||
MonsterUniqueID8: dict.GetString("umon8", idx),
|
MonsterUniqueID8: d.String("umon8"),
|
||||||
MonsterUniqueID9: dict.GetString("umon9", idx),
|
MonsterUniqueID9: d.String("umon9"),
|
||||||
MonsterUniqueID10: dict.GetString("umon10", idx),
|
MonsterUniqueID10: d.String("umon10"),
|
||||||
MonsterCritterID1: dict.GetString("cmon1", idx),
|
MonsterCritterID1: d.String("cmon1"),
|
||||||
MonsterCritterID2: dict.GetString("cmon2", idx),
|
MonsterCritterID2: d.String("cmon2"),
|
||||||
MonsterCritterID3: dict.GetString("cmon3", idx),
|
MonsterCritterID3: d.String("cmon3"),
|
||||||
MonsterCritterID4: dict.GetString("cmon4", idx),
|
MonsterCritterID4: d.String("cmon4"),
|
||||||
MonsterCritter1SpawnChance: dict.GetNumber("cpct1", idx),
|
MonsterCritter1SpawnChance: d.Number("cpct1"),
|
||||||
MonsterCritter2SpawnChance: dict.GetNumber("cpct2", idx),
|
MonsterCritter2SpawnChance: d.Number("cpct2"),
|
||||||
MonsterCritter3SpawnChance: dict.GetNumber("cpct3", idx),
|
MonsterCritter3SpawnChance: d.Number("cpct3"),
|
||||||
MonsterCritter4SpawnChance: dict.GetNumber("cpct4", idx),
|
MonsterCritter4SpawnChance: d.Number("cpct4"),
|
||||||
SoundEnvironmentID: dict.GetNumber("SoundEnv", idx),
|
SoundEnvironmentID: d.Number("SoundEnv"),
|
||||||
WaypointID: dict.GetNumber("Waypoint", idx),
|
WaypointID: d.Number("Waypoint"),
|
||||||
LevelDisplayName: dict.GetString("LevelName", idx),
|
LevelDisplayName: d.String("LevelName"),
|
||||||
LevelWarpName: dict.GetString("LevelWarp", idx),
|
LevelWarpName: d.String("LevelWarp"),
|
||||||
TitleImageName: dict.GetString("EntryFile", idx),
|
TitleImageName: d.String("EntryFile"),
|
||||||
ObjectGroupID0: dict.GetNumber("ObjGrp0", idx),
|
ObjectGroupID0: d.Number("ObjGrp0"),
|
||||||
ObjectGroupID1: dict.GetNumber("ObjGrp1", idx),
|
ObjectGroupID1: d.Number("ObjGrp1"),
|
||||||
ObjectGroupID2: dict.GetNumber("ObjGrp2", idx),
|
ObjectGroupID2: d.Number("ObjGrp2"),
|
||||||
ObjectGroupID3: dict.GetNumber("ObjGrp3", idx),
|
ObjectGroupID3: d.Number("ObjGrp3"),
|
||||||
ObjectGroupID4: dict.GetNumber("ObjGrp4", idx),
|
ObjectGroupID4: d.Number("ObjGrp4"),
|
||||||
ObjectGroupID5: dict.GetNumber("ObjGrp5", idx),
|
ObjectGroupID5: d.Number("ObjGrp5"),
|
||||||
ObjectGroupID6: dict.GetNumber("ObjGrp6", idx),
|
ObjectGroupID6: d.Number("ObjGrp6"),
|
||||||
ObjectGroupID7: dict.GetNumber("ObjGrp7", idx),
|
ObjectGroupID7: d.Number("ObjGrp7"),
|
||||||
ObjectGroupSpawnChance0: dict.GetNumber("ObjPrb0", idx),
|
ObjectGroupSpawnChance0: d.Number("ObjPrb0"),
|
||||||
ObjectGroupSpawnChance1: dict.GetNumber("ObjPrb1", idx),
|
ObjectGroupSpawnChance1: d.Number("ObjPrb1"),
|
||||||
ObjectGroupSpawnChance2: dict.GetNumber("ObjPrb2", idx),
|
ObjectGroupSpawnChance2: d.Number("ObjPrb2"),
|
||||||
ObjectGroupSpawnChance3: dict.GetNumber("ObjPrb3", idx),
|
ObjectGroupSpawnChance3: d.Number("ObjPrb3"),
|
||||||
ObjectGroupSpawnChance4: dict.GetNumber("ObjPrb4", idx),
|
ObjectGroupSpawnChance4: d.Number("ObjPrb4"),
|
||||||
ObjectGroupSpawnChance5: dict.GetNumber("ObjPrb5", idx),
|
ObjectGroupSpawnChance5: d.Number("ObjPrb5"),
|
||||||
ObjectGroupSpawnChance6: dict.GetNumber("ObjPrb6", idx),
|
ObjectGroupSpawnChance6: d.Number("ObjPrb6"),
|
||||||
ObjectGroupSpawnChance7: dict.GetNumber("ObjPrb7", idx),
|
ObjectGroupSpawnChance7: d.Number("ObjPrb7"),
|
||||||
}
|
}
|
||||||
LevelDetails[idx] = record
|
LevelDetails[record.Id] = record
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.Err != nil {
|
||||||
|
panic(d.Err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Loaded %d LevelDetails records", len(LevelDetails))
|
log.Printf("Loaded %d LevelDetails records", len(LevelDetails))
|
||||||
|
@ -110,7 +110,7 @@ type MissileRecord struct {
|
|||||||
ExplosionMissile string // name of a missile from missiles.txt that is created upon collision
|
ExplosionMissile string // name of a missile from missiles.txt that is created upon collision
|
||||||
// or anytime it is destroyed if AlwaysExplode is true
|
// or anytime it is destroyed if AlwaysExplode is true
|
||||||
|
|
||||||
Id int //nolint:golint Id is the correct key
|
Id int //nolint:golint,stylecheck // Id is the correct key
|
||||||
|
|
||||||
ClientMovementFunc int
|
ClientMovementFunc int
|
||||||
ClientCollisionFunc int
|
ClientCollisionFunc int
|
||||||
|
@ -8,31 +8,24 @@ import (
|
|||||||
|
|
||||||
// MonPresets stores monster presets
|
// MonPresets stores monster presets
|
||||||
//nolint:gochecknoglobals // Currently global by design, only written once
|
//nolint:gochecknoglobals // Currently global by design, only written once
|
||||||
var MonPresets [][]string
|
var MonPresets map[int32][]string
|
||||||
|
|
||||||
// LoadMonPresets loads monster presets from monpresets.txt
|
// LoadMonPresets loads monster presets from monpresets.txt
|
||||||
func LoadMonPresets(file []byte) {
|
func LoadMonPresets(file []byte) {
|
||||||
dict := d2common.LoadDataDictionary(string(file))
|
MonPresets = make(map[int32][]string)
|
||||||
numRecords := len(dict.Data)
|
|
||||||
MonPresets = make([][]string, numRecords)
|
|
||||||
|
|
||||||
for idx := range MonPresets {
|
d := d2common.LoadDataDictionary(file)
|
||||||
MonPresets[idx] = make([]string, numRecords)
|
for d.Next() {
|
||||||
}
|
act := int32(d.Number("Act"))
|
||||||
|
if _, ok := MonPresets[act]; !ok {
|
||||||
lastAct := 0
|
MonPresets[act] = make([]string, 0)
|
||||||
placeIdx := 0
|
|
||||||
|
|
||||||
for dictIdx := range dict.Data {
|
|
||||||
act := dict.GetNumber("Act", dictIdx)
|
|
||||||
if act != lastAct {
|
|
||||||
placeIdx = 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MonPresets[act][placeIdx] = dict.GetString("Place", dictIdx)
|
MonPresets[act] = append(MonPresets[act], d.String("Place"))
|
||||||
lastAct = act
|
}
|
||||||
|
|
||||||
placeIdx++
|
if d.Err != nil {
|
||||||
|
panic(d.Err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Loaded %d MonPreset records", len(MonPresets))
|
log.Printf("Loaded %d MonPreset records", len(MonPresets))
|
||||||
|
@ -28,7 +28,7 @@ type (
|
|||||||
// column also links other hardcoded effects to the units, such as the
|
// column also links other hardcoded effects to the units, such as the
|
||||||
// transparency on necro summons and the name-color change on unique boss
|
// transparency on necro summons and the name-color change on unique boss
|
||||||
// units (thanks to Kingpin for the info)
|
// units (thanks to Kingpin for the info)
|
||||||
Id string // called `hcIdx` in monstats.txt //nolint:golint Id is the right key
|
Id string //nolint:golint,stylecheck // called `hcIdx` in monstats.txt
|
||||||
|
|
||||||
// BaseKey is an ID pointer of the “base” unit for this specific
|
// BaseKey is an ID pointer of the “base” unit for this specific
|
||||||
// monster type (ex. There are five types of “Fallen”; all of them have
|
// monster type (ex. There are five types of “Fallen”; all of them have
|
||||||
@ -81,12 +81,10 @@ type (
|
|||||||
SpawnAnimationKey string // called `spawnmode` in monstats.txt
|
SpawnAnimationKey string // called `spawnmode` in monstats.txt
|
||||||
|
|
||||||
// MinionId1 is an Id of a minion that spawns when this monster is created
|
// MinionId1 is an Id of a minion that spawns when this monster is created
|
||||||
//nolint:golint Id is the right key
|
MinionId1 string //nolint:golint,stylecheck // called `minion1` in monstats.txt
|
||||||
MinionId1 string // called `minion1` in monstats.txt
|
|
||||||
|
|
||||||
// MinionId2 is an Id of a minion that spawns when this monster is created
|
// MinionId2 is an Id of a minion that spawns when this monster is created
|
||||||
//nolint:golint Id is the right key
|
MinionId2 string //nolint:golint,stylecheck // called `minion2` in monstats.txt
|
||||||
MinionId2 string // called `minion2` in monstats.txt
|
|
||||||
|
|
||||||
// SoundKeyNormal, SoundKeySpecial
|
// SoundKeyNormal, SoundKeySpecial
|
||||||
// specifies the ID pointer to this monsters “Sound Bank” in MonSound.txt
|
// specifies the ID pointer to this monsters “Sound Bank” in MonSound.txt
|
||||||
@ -115,14 +113,14 @@ type (
|
|||||||
// the ID Pointer to the skill (from Skills.txt) the monster will cast when
|
// the ID Pointer to the skill (from Skills.txt) the monster will cast when
|
||||||
// this specific slot is accessed by the AI. Which slots are used is
|
// this specific slot is accessed by the AI. Which slots are used is
|
||||||
// determined by the units AI.
|
// determined by the units AI.
|
||||||
SkillId1 string // called `Skill1` in monstats.txt //nolint:golint Id is the right key
|
SkillId1 string //nolint:golint,stylecheck // called `Skill1` in monstats.txt
|
||||||
SkillId2 string // called `Skill2` in monstats.txt //nolint:golint Id is the right key
|
SkillId2 string //nolint:golint,stylecheck // called `Skill2` in monstats.txt
|
||||||
SkillId3 string // called `Skill3` in monstats.txt //nolint:golint Id is the right key
|
SkillId3 string //nolint:golint,stylecheck // called `Skill3` in monstats.txt
|
||||||
SkillId4 string // called `Skill4` in monstats.txt //nolint:golint Id is the right key
|
SkillId4 string //nolint:golint,stylecheck // called `Skill4` in monstats.txt
|
||||||
SkillId5 string // called `Skill5` in monstats.txt //nolint:golint Id is the right key
|
SkillId5 string //nolint:golint,stylecheck // called `Skill5` in monstats.txt
|
||||||
SkillId6 string // called `Skill6` in monstats.txt //nolint:golint Id is the right key
|
SkillId6 string //nolint:golint,stylecheck // called `Skill6` in monstats.txt
|
||||||
SkillId7 string // called `Skill7` in monstats.txt //nolint:golint Id is the right key
|
SkillId7 string //nolint:golint,stylecheck // called `Skill7` in monstats.txt
|
||||||
SkillId8 string // called `Skill8` in monstats.txt //nolint:golint Id is the right key
|
SkillId8 string //nolint:golint,stylecheck // called `Skill8` in monstats.txt
|
||||||
|
|
||||||
// SkillAnimation1 -- SkillAnimation8
|
// SkillAnimation1 -- SkillAnimation8
|
||||||
// the graphical MODE (or SEQUENCE) this unit uses when it uses this skill.
|
// the graphical MODE (or SEQUENCE) this unit uses when it uses this skill.
|
||||||
@ -139,8 +137,7 @@ type (
|
|||||||
// ID Pointer to the skill that controls this units damage. This is used for
|
// ID Pointer to the skill that controls this units damage. This is used for
|
||||||
// the druids summons. IE their damage is specified solely by Skills.txt and
|
// the druids summons. IE their damage is specified solely by Skills.txt and
|
||||||
// not by MonStats.txt.
|
// not by MonStats.txt.
|
||||||
//nolint:golint Id is the right key
|
DamageSkillId string //nolint:golint,stylecheck // called `SkillDamage` in monstats.txt
|
||||||
DamageSkillId string // called `SkillDamage` in monstats.txt
|
|
||||||
|
|
||||||
// ElementAttackMode1 -- ElementAttackMode3
|
// ElementAttackMode1 -- ElementAttackMode3
|
||||||
// the mode to which the elemental damage is appended. The modes to which
|
// the mode to which the elemental damage is appended. The modes to which
|
||||||
@ -190,12 +187,12 @@ type (
|
|||||||
|
|
||||||
// TreasureClassQuestTriggerId
|
// TreasureClassQuestTriggerId
|
||||||
// the ID of the Quest that triggers the Quest Treasureclass drop.
|
// the ID of the Quest that triggers the Quest Treasureclass drop.
|
||||||
TreasureClassQuestTriggerId string // called `TCQuestId` in monstats.txt
|
TreasureClassQuestTriggerId string //nolint:golint,stylecheck // called `TCQuestId` in monstats.txt
|
||||||
|
|
||||||
// TreasureClassQuestCompleteId
|
// TreasureClassQuestCompleteId
|
||||||
// the ID of the Quest State that you need to complete to trigger the Quest
|
// the ID of the Quest State that you need to complete to trigger the Quest
|
||||||
// Treasureclass trop.
|
// Treasureclass trop.
|
||||||
TreasureClassQuestCompleteId string // called `TCQuestCP` in monstats.txt
|
TreasureClassQuestCompleteId string //nolint:golint,stylecheck // called `TCQuestCP` in monstats.txt
|
||||||
|
|
||||||
// PaletteId indicates which palette (color) entry the unit will use, most
|
// PaletteId indicates which palette (color) entry the unit will use, most
|
||||||
// monsters have a palshift.dat file in their COF folder, this file
|
// monsters have a palshift.dat file in their COF folder, this file
|
||||||
@ -208,7 +205,7 @@ type (
|
|||||||
// such as FC do not accept their palettes.
|
// such as FC do not accept their palettes.
|
||||||
// NOTE no 2: some monsters got unused palettes, ZM (zombie) for example
|
// NOTE no 2: some monsters got unused palettes, ZM (zombie) for example
|
||||||
// will turn light-rotten-green with palette nr 5 and pink-creamy with 6.
|
// will turn light-rotten-green with palette nr 5 and pink-creamy with 6.
|
||||||
PaletteId int // called `TransLvl` in monstats.txt
|
PaletteId int //nolint:golint,stylecheck // called `TransLvl` in monstats.txt
|
||||||
|
|
||||||
// SpawnOffsetX, SpawnOffsetY
|
// SpawnOffsetX, SpawnOffsetY
|
||||||
// are the x/y offsets at which spawned monsters are placed. IE this prevents
|
// are the x/y offsets at which spawned monsters are placed. IE this prevents
|
||||||
@ -683,271 +680,275 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var MonStats map[string]*MonStatsRecord
|
// MonStats stores all of the MonStat Records
|
||||||
|
var MonStats map[string]*MonStatsRecord //nolint:gochecknoglobals // Currently global by design, only written once
|
||||||
|
|
||||||
//nolint:funlen // Makes no sense to split
|
// LoadMonStats loads monstats
|
||||||
func LoadMonStats(file []byte) {
|
func LoadMonStats(file []byte) { // nolint:funlen // Makes no sense to split
|
||||||
dict := d2common.LoadDataDictionary(string(file))
|
MonStats = make(map[string]*MonStatsRecord)
|
||||||
numRecords := len(dict.Data)
|
|
||||||
MonStats = make(map[string]*MonStatsRecord, numRecords)
|
|
||||||
|
|
||||||
for idx := range dict.Data {
|
d := d2common.LoadDataDictionary(file)
|
||||||
|
for d.Next() {
|
||||||
record := &MonStatsRecord{
|
record := &MonStatsRecord{
|
||||||
Key: dict.GetString("Id", idx),
|
Key: d.String("Id"),
|
||||||
Id: dict.GetString("hcIdx", idx),
|
Id: d.String("hcIdx"),
|
||||||
BaseKey: dict.GetString("BaseId", idx),
|
BaseKey: d.String("BaseId"),
|
||||||
NextKey: dict.GetString("NextInClass", idx),
|
NextKey: d.String("NextInClass"),
|
||||||
PaletteId: dict.GetNumber("TransLvl", idx),
|
PaletteId: d.Number("TransLvl"),
|
||||||
NameStringTableKey: dict.GetString("NameStr", idx),
|
NameStringTableKey: d.String("NameStr"),
|
||||||
ExtraDataKey: dict.GetString("MonStatsEx", idx),
|
ExtraDataKey: d.String("MonStatsEx"),
|
||||||
PropertiesKey: dict.GetString("MonProp", idx),
|
PropertiesKey: d.String("MonProp"),
|
||||||
MonsterGroup: dict.GetString("MonType", idx),
|
MonsterGroup: d.String("MonType"),
|
||||||
AiKey: dict.GetString("AI", idx),
|
AiKey: d.String("AI"),
|
||||||
DescriptionStringTableKey: dict.GetString("DescStr", idx),
|
DescriptionStringTableKey: d.String("DescStr"),
|
||||||
AnimationDirectoryToken: dict.GetString("Code", idx),
|
AnimationDirectoryToken: d.String("Code"),
|
||||||
Enabled: dict.GetNumber("enabled", idx) > 0,
|
Enabled: d.Number("enabled") > 0,
|
||||||
IsRanged: dict.GetNumber("rangedtype", idx) > 0,
|
IsRanged: d.Number("rangedtype") > 0,
|
||||||
SpawnsMinions: dict.GetNumber("placespawn", idx) > 0,
|
SpawnsMinions: d.Number("placespawn") > 0,
|
||||||
SpawnKey: dict.GetString("spawn", idx),
|
SpawnKey: d.String("spawn"),
|
||||||
SpawnOffsetX: dict.GetNumber("spawnx", idx),
|
SpawnOffsetX: d.Number("spawnx"),
|
||||||
SpawnOffsetY: dict.GetNumber("spawny", idx),
|
SpawnOffsetY: d.Number("spawny"),
|
||||||
SpawnAnimationKey: dict.GetString("spawnmode", idx),
|
SpawnAnimationKey: d.String("spawnmode"),
|
||||||
MinionId1: dict.GetString("minion1", idx),
|
MinionId1: d.String("minion1"),
|
||||||
MinionId2: dict.GetString("minion2", idx),
|
MinionId2: d.String("minion2"),
|
||||||
IsLeader: dict.GetNumber("SetBoss", idx) > 0,
|
IsLeader: d.Number("SetBoss") > 0,
|
||||||
TransferLeadership: dict.GetNumber("BossXfer", idx) > 0,
|
TransferLeadership: d.Number("BossXfer") > 0,
|
||||||
MinionPartyMin: dict.GetNumber("PartyMin", idx),
|
MinionPartyMin: d.Number("PartyMin"),
|
||||||
MinionPartyMax: dict.GetNumber("PartyMax", idx),
|
MinionPartyMax: d.Number("PartyMax"),
|
||||||
MinionGroupMin: dict.GetNumber("MinGrp", idx),
|
MinionGroupMin: d.Number("MinGrp"),
|
||||||
MinionGroupMax: dict.GetNumber("MaxGrp", idx),
|
MinionGroupMax: d.Number("MaxGrp"),
|
||||||
PopulationReductionPercent: dict.GetNumber("sparsePopulate", idx),
|
PopulationReductionPercent: d.Number("sparsePopulate"),
|
||||||
SpeedBase: dict.GetNumber("Velocity", idx),
|
SpeedBase: d.Number("Velocity"),
|
||||||
SpeedRun: dict.GetNumber("Run", idx),
|
SpeedRun: d.Number("Run"),
|
||||||
Rarity: dict.GetNumber("Rarity", idx),
|
Rarity: d.Number("Rarity"),
|
||||||
LevelNormal: dict.GetNumber("Level", idx),
|
LevelNormal: d.Number("Level"),
|
||||||
LevelNightmare: dict.GetNumber("Level(N)", idx),
|
LevelNightmare: d.Number("Level(N)"),
|
||||||
LevelHell: dict.GetNumber("Level(H)", idx),
|
LevelHell: d.Number("Level(H)"),
|
||||||
SoundKeyNormal: dict.GetString("MonSound", idx),
|
SoundKeyNormal: d.String("MonSound"),
|
||||||
SoundKeySpecial: dict.GetString("UMonSound", idx),
|
SoundKeySpecial: d.String("UMonSound"),
|
||||||
ThreatLevel: dict.GetNumber("threat", idx),
|
ThreatLevel: d.Number("threat"),
|
||||||
AiDelayNormal: dict.GetNumber("aidel", idx),
|
AiDelayNormal: d.Number("aidel"),
|
||||||
AiDelayNightmare: dict.GetNumber("aidel(N)", idx),
|
AiDelayNightmare: d.Number("aidel(N)"),
|
||||||
AiDelayHell: dict.GetNumber("aidel(H)", idx),
|
AiDelayHell: d.Number("aidel(H)"),
|
||||||
AiDistanceNormal: dict.GetNumber("aidist", idx),
|
AiDistanceNormal: d.Number("aidist"),
|
||||||
AiDistanceNightmare: dict.GetNumber("aidist(N)", idx),
|
AiDistanceNightmare: d.Number("aidist(N)"),
|
||||||
AiDistanceHell: dict.GetNumber("aidist(H)", idx),
|
AiDistanceHell: d.Number("aidist(H)"),
|
||||||
AiParameterNormal1: dict.GetNumber("aip1", idx),
|
AiParameterNormal1: d.Number("aip1"),
|
||||||
AiParameterNormal2: dict.GetNumber("aip2", idx),
|
AiParameterNormal2: d.Number("aip2"),
|
||||||
AiParameterNormal3: dict.GetNumber("aip3", idx),
|
AiParameterNormal3: d.Number("aip3"),
|
||||||
AiParameterNormal4: dict.GetNumber("aip4", idx),
|
AiParameterNormal4: d.Number("aip4"),
|
||||||
AiParameterNormal5: dict.GetNumber("aip5", idx),
|
AiParameterNormal5: d.Number("aip5"),
|
||||||
AiParameterNormal6: dict.GetNumber("aip6", idx),
|
AiParameterNormal6: d.Number("aip6"),
|
||||||
AiParameterNormal7: dict.GetNumber("aip7", idx),
|
AiParameterNormal7: d.Number("aip7"),
|
||||||
AiParameterNormal8: dict.GetNumber("aip8", idx),
|
AiParameterNormal8: d.Number("aip8"),
|
||||||
AiParameterNightmare1: dict.GetNumber("aip1(N)", idx),
|
AiParameterNightmare1: d.Number("aip1(N)"),
|
||||||
AiParameterNightmare2: dict.GetNumber("aip2(N)", idx),
|
AiParameterNightmare2: d.Number("aip2(N)"),
|
||||||
AiParameterNightmare3: dict.GetNumber("aip3(N)", idx),
|
AiParameterNightmare3: d.Number("aip3(N)"),
|
||||||
AiParameterNightmare4: dict.GetNumber("aip4(N)", idx),
|
AiParameterNightmare4: d.Number("aip4(N)"),
|
||||||
AiParameterNightmare5: dict.GetNumber("aip5(N)", idx),
|
AiParameterNightmare5: d.Number("aip5(N)"),
|
||||||
AiParameterNightmare6: dict.GetNumber("aip6(N)", idx),
|
AiParameterNightmare6: d.Number("aip6(N)"),
|
||||||
AiParameterNightmare7: dict.GetNumber("aip7(N)", idx),
|
AiParameterNightmare7: d.Number("aip7(N)"),
|
||||||
AiParameterNightmare8: dict.GetNumber("aip8(N)", idx),
|
AiParameterNightmare8: d.Number("aip8(N)"),
|
||||||
AiParameterHell1: dict.GetNumber("aip1(H)", idx),
|
AiParameterHell1: d.Number("aip1(H)"),
|
||||||
AiParameterHell2: dict.GetNumber("aip2(H)", idx),
|
AiParameterHell2: d.Number("aip2(H)"),
|
||||||
AiParameterHell3: dict.GetNumber("aip3(H)", idx),
|
AiParameterHell3: d.Number("aip3(H)"),
|
||||||
AiParameterHell4: dict.GetNumber("aip4(H)", idx),
|
AiParameterHell4: d.Number("aip4(H)"),
|
||||||
AiParameterHell5: dict.GetNumber("aip5(H)", idx),
|
AiParameterHell5: d.Number("aip5(H)"),
|
||||||
AiParameterHell6: dict.GetNumber("aip6(H)", idx),
|
AiParameterHell6: d.Number("aip6(H)"),
|
||||||
AiParameterHell7: dict.GetNumber("aip7(H)", idx),
|
AiParameterHell7: d.Number("aip7(H)"),
|
||||||
AiParameterHell8: dict.GetNumber("aip8(H)", idx),
|
AiParameterHell8: d.Number("aip8(H)"),
|
||||||
MissileA1: dict.GetString("MissA1", idx),
|
MissileA1: d.String("MissA1"),
|
||||||
MissileA2: dict.GetString("MissA2", idx),
|
MissileA2: d.String("MissA2"),
|
||||||
MissileS1: dict.GetString("MissS1", idx),
|
MissileS1: d.String("MissS1"),
|
||||||
MissileS2: dict.GetString("MissS2", idx),
|
MissileS2: d.String("MissS2"),
|
||||||
MissileS3: dict.GetString("MissS3", idx),
|
MissileS3: d.String("MissS3"),
|
||||||
MissileS4: dict.GetString("MissS4", idx),
|
MissileS4: d.String("MissS4"),
|
||||||
MissileC: dict.GetString("MissC", idx),
|
MissileC: d.String("MissC"),
|
||||||
MissileSQ: dict.GetString("MissSQ", idx),
|
MissileSQ: d.String("MissSQ"),
|
||||||
Alignment: d2enum.MonsterAlignmentType(dict.GetNumber("Align", idx)),
|
Alignment: d2enum.MonsterAlignmentType(d.Number("Align")),
|
||||||
IsLevelSpawnable: dict.GetNumber("isSpawn", idx) > 0,
|
IsLevelSpawnable: d.Number("isSpawn") > 0,
|
||||||
IsMelee: dict.GetNumber("isMelee", idx) > 0,
|
IsMelee: d.Number("isMelee") > 0,
|
||||||
IsNpc: dict.GetNumber("npc", idx) > 0,
|
IsNpc: d.Number("npc") > 0,
|
||||||
IsInteractable: dict.GetNumber("interact", idx) > 0,
|
IsInteractable: d.Number("interact") > 0,
|
||||||
HasInventory: dict.GetNumber("inventory", idx) > 0,
|
HasInventory: d.Number("inventory") > 0,
|
||||||
CanEnterTown: dict.GetNumber("inTown", idx) > 0,
|
CanEnterTown: d.Number("inTown") > 0,
|
||||||
IsUndeadLow: dict.GetNumber("lUndead", idx) > 0,
|
IsUndeadLow: d.Number("lUndead") > 0,
|
||||||
IsUndeadHigh: dict.GetNumber("hUndead", idx) > 0,
|
IsUndeadHigh: d.Number("hUndead") > 0,
|
||||||
IsDemon: dict.GetNumber("demon", idx) > 0,
|
IsDemon: d.Number("demon") > 0,
|
||||||
IsFlying: dict.GetNumber("flying", idx) > 0,
|
IsFlying: d.Number("flying") > 0,
|
||||||
CanOpenDoors: dict.GetNumber("opendoors", idx) > 0,
|
CanOpenDoors: d.Number("opendoors") > 0,
|
||||||
IsSpecialBoss: dict.GetNumber("boss", idx) > 0,
|
IsSpecialBoss: d.Number("boss") > 0,
|
||||||
IsActBoss: dict.GetNumber("primeevil", idx) > 0,
|
IsActBoss: d.Number("primeevil") > 0,
|
||||||
IsKillable: dict.GetNumber("killable", idx) > 0,
|
IsKillable: d.Number("killable") > 0,
|
||||||
IsAiSwitchable: dict.GetNumber("switchai", idx) > 0,
|
IsAiSwitchable: d.Number("switchai") > 0,
|
||||||
DisableAura: dict.GetNumber("noAura", idx) > 0,
|
DisableAura: d.Number("noAura") > 0,
|
||||||
DisableMultiShot: dict.GetNumber("nomultishot", idx) > 0,
|
DisableMultiShot: d.Number("nomultishot") > 0,
|
||||||
DisableCounting: dict.GetNumber("neverCount", idx) > 0,
|
DisableCounting: d.Number("neverCount") > 0,
|
||||||
IgnorePets: dict.GetNumber("petIgnore", idx) > 0,
|
IgnorePets: d.Number("petIgnore") > 0,
|
||||||
DealsDamageOnDeath: dict.GetNumber("deathDmg", idx) > 0,
|
DealsDamageOnDeath: d.Number("deathDmg") > 0,
|
||||||
GenericSpawn: dict.GetNumber("genericSpawn", idx) > 0,
|
GenericSpawn: d.Number("genericSpawn") > 0,
|
||||||
SkillId1: dict.GetString("Skill1", idx),
|
SkillId1: d.String("Skill1"),
|
||||||
SkillId2: dict.GetString("Skill2", idx),
|
SkillId2: d.String("Skill2"),
|
||||||
SkillId3: dict.GetString("Skill3", idx),
|
SkillId3: d.String("Skill3"),
|
||||||
SkillId4: dict.GetString("Skill4", idx),
|
SkillId4: d.String("Skill4"),
|
||||||
SkillId5: dict.GetString("Skill5", idx),
|
SkillId5: d.String("Skill5"),
|
||||||
SkillId6: dict.GetString("Skill6", idx),
|
SkillId6: d.String("Skill6"),
|
||||||
SkillId7: dict.GetString("Skill7", idx),
|
SkillId7: d.String("Skill7"),
|
||||||
SkillId8: dict.GetString("Skill8", idx),
|
SkillId8: d.String("Skill8"),
|
||||||
SkillAnimation1: dict.GetString("Sk1mode", idx),
|
SkillAnimation1: d.String("Sk1mode"),
|
||||||
SkillAnimation2: dict.GetString("Sk2mode", idx),
|
SkillAnimation2: d.String("Sk2mode"),
|
||||||
SkillAnimation3: dict.GetString("Sk3mode", idx),
|
SkillAnimation3: d.String("Sk3mode"),
|
||||||
SkillAnimation4: dict.GetString("Sk4mode", idx),
|
SkillAnimation4: d.String("Sk4mode"),
|
||||||
SkillAnimation5: dict.GetString("Sk5mode", idx),
|
SkillAnimation5: d.String("Sk5mode"),
|
||||||
SkillAnimation6: dict.GetString("Sk6mode", idx),
|
SkillAnimation6: d.String("Sk6mode"),
|
||||||
SkillAnimation7: dict.GetString("Sk7mode", idx),
|
SkillAnimation7: d.String("Sk7mode"),
|
||||||
SkillAnimation8: dict.GetString("Sk8mode", idx),
|
SkillAnimation8: d.String("Sk8mode"),
|
||||||
SkillLevel1: dict.GetNumber("Sk1lvl", idx),
|
SkillLevel1: d.Number("Sk1lvl"),
|
||||||
SkillLevel2: dict.GetNumber("Sk2lvl", idx),
|
SkillLevel2: d.Number("Sk2lvl"),
|
||||||
SkillLevel3: dict.GetNumber("Sk3lvl", idx),
|
SkillLevel3: d.Number("Sk3lvl"),
|
||||||
SkillLevel4: dict.GetNumber("Sk4lvl", idx),
|
SkillLevel4: d.Number("Sk4lvl"),
|
||||||
SkillLevel5: dict.GetNumber("Sk5lvl", idx),
|
SkillLevel5: d.Number("Sk5lvl"),
|
||||||
SkillLevel6: dict.GetNumber("Sk6lvl", idx),
|
SkillLevel6: d.Number("Sk6lvl"),
|
||||||
SkillLevel7: dict.GetNumber("Sk7lvl", idx),
|
SkillLevel7: d.Number("Sk7lvl"),
|
||||||
SkillLevel8: dict.GetNumber("Sk8lvl", idx),
|
SkillLevel8: d.Number("Sk8lvl"),
|
||||||
LeechSensitivityNormal: dict.GetNumber("Drain", idx),
|
LeechSensitivityNormal: d.Number("Drain"),
|
||||||
LeechSensitivityNightmare: dict.GetNumber("Drain(N)", idx),
|
LeechSensitivityNightmare: d.Number("Drain(N)"),
|
||||||
LeechSensitivityHell: dict.GetNumber("Drain(H)", idx),
|
LeechSensitivityHell: d.Number("Drain(H)"),
|
||||||
ColdSensitivityNormal: dict.GetNumber("coldeffect", idx),
|
ColdSensitivityNormal: d.Number("coldeffect"),
|
||||||
ColdSensitivityNightmare: dict.GetNumber("coldeffect(N)", idx),
|
ColdSensitivityNightmare: d.Number("coldeffect(N)"),
|
||||||
ColdSensitivityHell: dict.GetNumber("coldeffect(H)", idx),
|
ColdSensitivityHell: d.Number("coldeffect(H)"),
|
||||||
ResistancePhysicalNormal: dict.GetNumber("ResDm", idx),
|
ResistancePhysicalNormal: d.Number("ResDm"),
|
||||||
ResistancePhysicalNightmare: dict.GetNumber("ResDm(N)", idx),
|
ResistancePhysicalNightmare: d.Number("ResDm(N)"),
|
||||||
ResistancePhysicalHell: dict.GetNumber("ResDm(H)", idx),
|
ResistancePhysicalHell: d.Number("ResDm(H)"),
|
||||||
ResistanceMagicNormal: dict.GetNumber("ResMa", idx),
|
ResistanceMagicNormal: d.Number("ResMa"),
|
||||||
ResistanceMagicNightmare: dict.GetNumber("ResMa(N)", idx),
|
ResistanceMagicNightmare: d.Number("ResMa(N)"),
|
||||||
ResistanceMagicHell: dict.GetNumber("ResMa(H)", idx),
|
ResistanceMagicHell: d.Number("ResMa(H)"),
|
||||||
ResistanceFireNormal: dict.GetNumber("ResFi", idx),
|
ResistanceFireNormal: d.Number("ResFi"),
|
||||||
ResistanceFireNightmare: dict.GetNumber("ResFi(N)", idx),
|
ResistanceFireNightmare: d.Number("ResFi(N)"),
|
||||||
ResistanceFireHell: dict.GetNumber("ResFi(H)", idx),
|
ResistanceFireHell: d.Number("ResFi(H)"),
|
||||||
ResistanceLightningNormal: dict.GetNumber("ResLi", idx),
|
ResistanceLightningNormal: d.Number("ResLi"),
|
||||||
ResistanceLightningNightmare: dict.GetNumber("ResLi(N)", idx),
|
ResistanceLightningNightmare: d.Number("ResLi(N)"),
|
||||||
ResistanceLightningHell: dict.GetNumber("ResLi(H)", idx),
|
ResistanceLightningHell: d.Number("ResLi(H)"),
|
||||||
ResistanceColdNormal: dict.GetNumber("ResCo", idx),
|
ResistanceColdNormal: d.Number("ResCo"),
|
||||||
ResistanceColdNightmare: dict.GetNumber("ResCo(N)", idx),
|
ResistanceColdNightmare: d.Number("ResCo(N)"),
|
||||||
ResistanceColdHell: dict.GetNumber("ResCo(H)", idx),
|
ResistanceColdHell: d.Number("ResCo(H)"),
|
||||||
ResistancePoisonNormal: dict.GetNumber("ResPo", idx),
|
ResistancePoisonNormal: d.Number("ResPo"),
|
||||||
ResistancePoisonNightmare: dict.GetNumber("ResPo(N)", idx),
|
ResistancePoisonNightmare: d.Number("ResPo(N)"),
|
||||||
ResistancePoisonHell: dict.GetNumber("ResPo(H)", idx),
|
ResistancePoisonHell: d.Number("ResPo(H)"),
|
||||||
HealthRegenPerFrame: dict.GetNumber("DamageRegen", idx),
|
HealthRegenPerFrame: d.Number("DamageRegen"),
|
||||||
DamageSkillId: dict.GetString("SkillDamage", idx),
|
DamageSkillId: d.String("SkillDamage"),
|
||||||
IgnoreMonLevelTxt: dict.GetNumber("noRatio", idx) > 0,
|
IgnoreMonLevelTxt: d.Number("noRatio") > 0,
|
||||||
CanBlockWithoutShield: dict.GetNumber("NoShldBlock", idx) > 0,
|
CanBlockWithoutShield: d.Number("NoShldBlock") > 0,
|
||||||
ChanceToBlockNormal: dict.GetNumber("ToBlock", idx),
|
ChanceToBlockNormal: d.Number("ToBlock"),
|
||||||
ChanceToBlockNightmare: dict.GetNumber("ToBlock(N)", idx),
|
ChanceToBlockNightmare: d.Number("ToBlock(N)"),
|
||||||
ChanceToBlockHell: dict.GetNumber("ToBlock(H)", idx),
|
ChanceToBlockHell: d.Number("ToBlock(H)"),
|
||||||
ChanceDeadlyStrike: dict.GetNumber("Crit", idx),
|
ChanceDeadlyStrike: d.Number("Crit"),
|
||||||
MinHPNormal: dict.GetNumber("minHP", idx),
|
MinHPNormal: d.Number("minHP"),
|
||||||
MinHPNightmare: dict.GetNumber("MinHP(N)", idx),
|
MinHPNightmare: d.Number("MinHP(N)"),
|
||||||
MinHPHell: dict.GetNumber("MinHP(H)", idx),
|
MinHPHell: d.Number("MinHP(H)"),
|
||||||
MaxHPNormal: dict.GetNumber("maxHP", idx),
|
MaxHPNormal: d.Number("maxHP"),
|
||||||
MaxHPNightmare: dict.GetNumber("MaxHP(N)", idx),
|
MaxHPNightmare: d.Number("MaxHP(N)"),
|
||||||
MaxHPHell: dict.GetNumber("MaxHP(H)", idx),
|
MaxHPHell: d.Number("MaxHP(H)"),
|
||||||
ArmorClassNormal: dict.GetNumber("AC", idx),
|
ArmorClassNormal: d.Number("AC"),
|
||||||
ArmorClassNightmare: dict.GetNumber("AC(N)", idx),
|
ArmorClassNightmare: d.Number("AC(N)"),
|
||||||
ArmorClassHell: dict.GetNumber("AC(H)", idx),
|
ArmorClassHell: d.Number("AC(H)"),
|
||||||
ExperienceNormal: dict.GetNumber("Exp", idx),
|
ExperienceNormal: d.Number("Exp"),
|
||||||
ExperienceNightmare: dict.GetNumber("Exp(N)", idx),
|
ExperienceNightmare: d.Number("Exp(N)"),
|
||||||
ExperienceHell: dict.GetNumber("Exp(H)", idx),
|
ExperienceHell: d.Number("Exp(H)"),
|
||||||
DamageMinA1Normal: dict.GetNumber("A1MinD", idx),
|
DamageMinA1Normal: d.Number("A1MinD"),
|
||||||
DamageMinA1Nightmare: dict.GetNumber("A1MinD(N)", idx),
|
DamageMinA1Nightmare: d.Number("A1MinD(N)"),
|
||||||
DamageMinA1Hell: dict.GetNumber("A1MinD(H)", idx),
|
DamageMinA1Hell: d.Number("A1MinD(H)"),
|
||||||
DamageMaxA1Normal: dict.GetNumber("A1MaxD", idx),
|
DamageMaxA1Normal: d.Number("A1MaxD"),
|
||||||
DamageMaxA1Nightmare: dict.GetNumber("A1MaxD(N)", idx),
|
DamageMaxA1Nightmare: d.Number("A1MaxD(N)"),
|
||||||
DamageMaxA1Hell: dict.GetNumber("A1MaxD(H)", idx),
|
DamageMaxA1Hell: d.Number("A1MaxD(H)"),
|
||||||
DamageMinA2Normal: dict.GetNumber("A2MinD", idx),
|
DamageMinA2Normal: d.Number("A2MinD"),
|
||||||
DamageMinA2Nightmare: dict.GetNumber("A2MinD(N)", idx),
|
DamageMinA2Nightmare: d.Number("A2MinD(N)"),
|
||||||
DamageMinA2Hell: dict.GetNumber("A2MinD(H)", idx),
|
DamageMinA2Hell: d.Number("A2MinD(H)"),
|
||||||
DamageMaxA2Normal: dict.GetNumber("A2MaxD", idx),
|
DamageMaxA2Normal: d.Number("A2MaxD"),
|
||||||
DamageMaxA2Nightmare: dict.GetNumber("A2MaxD(N)", idx),
|
DamageMaxA2Nightmare: d.Number("A2MaxD(N)"),
|
||||||
DamageMaxA2Hell: dict.GetNumber("A2MaxD(H)", idx),
|
DamageMaxA2Hell: d.Number("A2MaxD(H)"),
|
||||||
DamageMinS1Normal: dict.GetNumber("S1MinD", idx),
|
DamageMinS1Normal: d.Number("S1MinD"),
|
||||||
DamageMinS1Nightmare: dict.GetNumber("S1MinD(N)", idx),
|
DamageMinS1Nightmare: d.Number("S1MinD(N)"),
|
||||||
DamageMinS1Hell: dict.GetNumber("S1MinD(H)", idx),
|
DamageMinS1Hell: d.Number("S1MinD(H)"),
|
||||||
DamageMaxS1Normal: dict.GetNumber("S1MaxD", idx),
|
DamageMaxS1Normal: d.Number("S1MaxD"),
|
||||||
DamageMaxS1Nightmare: dict.GetNumber("S1MaxD(N)", idx),
|
DamageMaxS1Nightmare: d.Number("S1MaxD(N)"),
|
||||||
DamageMaxS1Hell: dict.GetNumber("S1MaxD(H)", idx),
|
DamageMaxS1Hell: d.Number("S1MaxD(H)"),
|
||||||
AttackRatingA1Normal: dict.GetNumber("A1TH", idx),
|
AttackRatingA1Normal: d.Number("A1TH"),
|
||||||
AttackRatingA1Nightmare: dict.GetNumber("A1TH(N)", idx),
|
AttackRatingA1Nightmare: d.Number("A1TH(N)"),
|
||||||
AttackRatingA1Hell: dict.GetNumber("A1TH(H)", idx),
|
AttackRatingA1Hell: d.Number("A1TH(H)"),
|
||||||
AttackRatingA2Normal: dict.GetNumber("A2TH", idx),
|
AttackRatingA2Normal: d.Number("A2TH"),
|
||||||
AttackRatingA2Nightmare: dict.GetNumber("A2TH(N)", idx),
|
AttackRatingA2Nightmare: d.Number("A2TH(N)"),
|
||||||
AttackRatingA2Hell: dict.GetNumber("A2TH(H)", idx),
|
AttackRatingA2Hell: d.Number("A2TH(H)"),
|
||||||
AttackRatingS1Normal: dict.GetNumber("S1TH", idx),
|
AttackRatingS1Normal: d.Number("S1TH"),
|
||||||
AttackRatingS1Nightmare: dict.GetNumber("S1TH(N)", idx),
|
AttackRatingS1Nightmare: d.Number("S1TH(N)"),
|
||||||
AttackRatingS1Hell: dict.GetNumber("S1TH(H)", idx),
|
AttackRatingS1Hell: d.Number("S1TH(H)"),
|
||||||
ElementAttackMode1: dict.GetString("El1Mode", idx),
|
ElementAttackMode1: d.String("El1Mode"),
|
||||||
ElementAttackMode2: dict.GetString("El2Mode", idx),
|
ElementAttackMode2: d.String("El2Mode"),
|
||||||
ElementAttackMode3: dict.GetString("El3Mode", idx),
|
ElementAttackMode3: d.String("El3Mode"),
|
||||||
ElementType1: dict.GetString("El1Type", idx),
|
ElementType1: d.String("El1Type"),
|
||||||
ElementType2: dict.GetString("El2Type", idx),
|
ElementType2: d.String("El2Type"),
|
||||||
ElementType3: dict.GetString("El3Type", idx),
|
ElementType3: d.String("El3Type"),
|
||||||
ElementChance1Normal: dict.GetNumber("El1Pct", idx),
|
ElementChance1Normal: d.Number("El1Pct"),
|
||||||
ElementChance1Nightmare: dict.GetNumber("El1Pct(N)", idx),
|
ElementChance1Nightmare: d.Number("El1Pct(N)"),
|
||||||
ElementChance1Hell: dict.GetNumber("El1Pct(H)", idx),
|
ElementChance1Hell: d.Number("El1Pct(H)"),
|
||||||
ElementChance2Normal: dict.GetNumber("El2Pct", idx),
|
ElementChance2Normal: d.Number("El2Pct"),
|
||||||
ElementChance2Nightmare: dict.GetNumber("El2Pct(N)", idx),
|
ElementChance2Nightmare: d.Number("El2Pct(N)"),
|
||||||
ElementChance2Hell: dict.GetNumber("El2Pct(H)", idx),
|
ElementChance2Hell: d.Number("El2Pct(H)"),
|
||||||
ElementChance3Normal: dict.GetNumber("El3Pct", idx),
|
ElementChance3Normal: d.Number("El3Pct"),
|
||||||
ElementChance3Nightmare: dict.GetNumber("El3Pct(N)", idx),
|
ElementChance3Nightmare: d.Number("El3Pct(N)"),
|
||||||
ElementChance3Hell: dict.GetNumber("El3Pct(H)", idx),
|
ElementChance3Hell: d.Number("El3Pct(H)"),
|
||||||
ElementDamageMin1Normal: dict.GetNumber("El1MinD", idx),
|
ElementDamageMin1Normal: d.Number("El1MinD"),
|
||||||
ElementDamageMin1Nightmare: dict.GetNumber("El1MinD(N)", idx),
|
ElementDamageMin1Nightmare: d.Number("El1MinD(N)"),
|
||||||
ElementDamageMin1Hell: dict.GetNumber("El1MinD(H)", idx),
|
ElementDamageMin1Hell: d.Number("El1MinD(H)"),
|
||||||
ElementDamageMin2Normal: dict.GetNumber("El2MinD", idx),
|
ElementDamageMin2Normal: d.Number("El2MinD"),
|
||||||
ElementDamageMin2Nightmare: dict.GetNumber("El2MinD(N)", idx),
|
ElementDamageMin2Nightmare: d.Number("El2MinD(N)"),
|
||||||
ElementDamageMin2Hell: dict.GetNumber("El2MinD(H)", idx),
|
ElementDamageMin2Hell: d.Number("El2MinD(H)"),
|
||||||
ElementDamageMin3Normal: dict.GetNumber("El3MinD", idx),
|
ElementDamageMin3Normal: d.Number("El3MinD"),
|
||||||
ElementDamageMin3Nightmare: dict.GetNumber("El3MinD(N)", idx),
|
ElementDamageMin3Nightmare: d.Number("El3MinD(N)"),
|
||||||
ElementDamageMin3Hell: dict.GetNumber("El3MinD(H)", idx),
|
ElementDamageMin3Hell: d.Number("El3MinD(H)"),
|
||||||
ElementDamageMax1Normal: dict.GetNumber("El1MaxD", idx),
|
ElementDamageMax1Normal: d.Number("El1MaxD"),
|
||||||
ElementDamageMax1Nightmare: dict.GetNumber("El1MaxD(N)", idx),
|
ElementDamageMax1Nightmare: d.Number("El1MaxD(N)"),
|
||||||
ElementDamageMax1Hell: dict.GetNumber("El1MaxD(H)", idx),
|
ElementDamageMax1Hell: d.Number("El1MaxD(H)"),
|
||||||
ElementDamageMax2Normal: dict.GetNumber("El2MaxD", idx),
|
ElementDamageMax2Normal: d.Number("El2MaxD"),
|
||||||
ElementDamageMax2Nightmare: dict.GetNumber("El2MaxD(N)", idx),
|
ElementDamageMax2Nightmare: d.Number("El2MaxD(N)"),
|
||||||
ElementDamageMax2Hell: dict.GetNumber("El2MaxD(H)", idx),
|
ElementDamageMax2Hell: d.Number("El2MaxD(H)"),
|
||||||
ElementDamageMax3Normal: dict.GetNumber("El3MaxD", idx),
|
ElementDamageMax3Normal: d.Number("El3MaxD"),
|
||||||
ElementDamageMax3Nightmare: dict.GetNumber("El3MaxD(N)", idx),
|
ElementDamageMax3Nightmare: d.Number("El3MaxD(N)"),
|
||||||
ElementDamageMax3Hell: dict.GetNumber("El3MaxD(H)", idx),
|
ElementDamageMax3Hell: d.Number("El3MaxD(H)"),
|
||||||
ElementDuration1Normal: dict.GetNumber("El1Dur", idx),
|
ElementDuration1Normal: d.Number("El1Dur"),
|
||||||
ElementDuration1Nightmare: dict.GetNumber("El1Dur(N)", idx),
|
ElementDuration1Nightmare: d.Number("El1Dur(N)"),
|
||||||
ElementDuration1Hell: dict.GetNumber("El1Dur(H)", idx),
|
ElementDuration1Hell: d.Number("El1Dur(H)"),
|
||||||
ElementDuration2Normal: dict.GetNumber("El2Dur", idx),
|
ElementDuration2Normal: d.Number("El2Dur"),
|
||||||
ElementDuration2Nightmare: dict.GetNumber("El2Dur(N)", idx),
|
ElementDuration2Nightmare: d.Number("El2Dur(N)"),
|
||||||
ElementDuration2Hell: dict.GetNumber("El2Dur(H)", idx),
|
ElementDuration2Hell: d.Number("El2Dur(H)"),
|
||||||
ElementDuration3Normal: dict.GetNumber("El3Dur", idx),
|
ElementDuration3Normal: d.Number("El3Dur"),
|
||||||
ElementDuration3Nightmare: dict.GetNumber("El3Dur(N)", idx),
|
ElementDuration3Nightmare: d.Number("El3Dur(N)"),
|
||||||
ElementDuration3Hell: dict.GetNumber("El3Dur(H)", idx),
|
ElementDuration3Hell: d.Number("El3Dur(H)"),
|
||||||
TreasureClassNormal: dict.GetString("TreasureClass1", idx),
|
TreasureClassNormal: d.String("TreasureClass1"),
|
||||||
TreasureClassNightmare: dict.GetString("TreasureClass1(N)", idx),
|
TreasureClassNightmare: d.String("TreasureClass1(N)"),
|
||||||
TreasureClassHell: dict.GetString("TreasureClass1(H)", idx),
|
TreasureClassHell: d.String("TreasureClass1(H)"),
|
||||||
TreasureClassChampionNormal: dict.GetString("TreasureClass2", idx),
|
TreasureClassChampionNormal: d.String("TreasureClass2"),
|
||||||
TreasureClassChampionNightmare: dict.GetString("TreasureClass2(N)", idx),
|
TreasureClassChampionNightmare: d.String("TreasureClass2(N)"),
|
||||||
TreasureClassChampionHell: dict.GetString("TreasureClass2(H)", idx),
|
TreasureClassChampionHell: d.String("TreasureClass2(H)"),
|
||||||
TreasureClass3UniqueNormal: dict.GetString("TreasureClass3", idx),
|
TreasureClass3UniqueNormal: d.String("TreasureClass3"),
|
||||||
TreasureClass3UniqueNightmare: dict.GetString("TreasureClass3(N)", idx),
|
TreasureClass3UniqueNightmare: d.String("TreasureClass3(N)"),
|
||||||
TreasureClass3UniqueHell: dict.GetString("TreasureClass3(H)", idx),
|
TreasureClass3UniqueHell: d.String("TreasureClass3(H)"),
|
||||||
TreasureClassQuestNormal: dict.GetString("TreasureClass4", idx),
|
TreasureClassQuestNormal: d.String("TreasureClass4"),
|
||||||
TreasureClassQuestNightmare: dict.GetString("TreasureClass4(N)", idx),
|
TreasureClassQuestNightmare: d.String("TreasureClass4(N)"),
|
||||||
TreasureClassQuestHell: dict.GetString("TreasureClass4(H)", idx),
|
TreasureClassQuestHell: d.String("TreasureClass4(H)"),
|
||||||
TreasureClassQuestTriggerId: dict.GetString("TCQuestId", idx),
|
TreasureClassQuestTriggerId: d.String("TCQuestId"),
|
||||||
TreasureClassQuestCompleteId: dict.GetString("TCQuestCP", idx),
|
TreasureClassQuestCompleteId: d.String("TCQuestCP"),
|
||||||
SpecialEndDeath: dict.GetNumber("SplEndDeath", idx),
|
SpecialEndDeath: d.Number("SplEndDeath"),
|
||||||
SpecialGetModeChart: dict.GetNumber("SplGetModeChart", idx) > 0,
|
SpecialGetModeChart: d.Number("SplGetModeChart") > 0,
|
||||||
SpecialEndGeneric: dict.GetNumber("SplEndGeneric", idx) > 0,
|
SpecialEndGeneric: d.Number("SplEndGeneric") > 0,
|
||||||
SpecialClientEnd: dict.GetNumber("SplClientEnd", idx) > 0,
|
SpecialClientEnd: d.Number("SplClientEnd") > 0,
|
||||||
}
|
}
|
||||||
MonStats[record.Key] = record
|
MonStats[record.Key] = record
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d.Err != nil {
|
||||||
|
panic(d.Err)
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("Loaded %d MonStats records", len(MonStats))
|
log.Printf("Loaded %d MonStats records", len(MonStats))
|
||||||
}
|
}
|
||||||
|
@ -9,37 +9,6 @@ import (
|
|||||||
|
|
||||||
// MonStats2Record is a representation of a row from monstats2.txt
|
// MonStats2Record is a representation of a row from monstats2.txt
|
||||||
type MonStats2Record struct {
|
type MonStats2Record struct {
|
||||||
// Key, the object ID MonStatEx feild from MonStat
|
|
||||||
Key string
|
|
||||||
|
|
||||||
// These follow three are apparently unused
|
|
||||||
Height int
|
|
||||||
OverlayHeight int
|
|
||||||
PixelHeight int
|
|
||||||
|
|
||||||
// Diameter in subtiles
|
|
||||||
SizeX int
|
|
||||||
SizeY int
|
|
||||||
|
|
||||||
// This specifies if the size values get used for collision detection
|
|
||||||
NoGfxHitTest bool
|
|
||||||
|
|
||||||
// Bounding box
|
|
||||||
BoxTop int
|
|
||||||
BoxLeft int
|
|
||||||
BoxWidth int
|
|
||||||
BoxHeight int
|
|
||||||
|
|
||||||
// Spawn method used
|
|
||||||
SpawnMethod int
|
|
||||||
|
|
||||||
// Melee radius
|
|
||||||
MeleeRng int
|
|
||||||
|
|
||||||
// base weaponclass?
|
|
||||||
BaseWeaponClass string
|
|
||||||
HitClass int
|
|
||||||
|
|
||||||
// Available options for equipment
|
// Available options for equipment
|
||||||
// randomly selected from
|
// randomly selected from
|
||||||
HDv []string
|
HDv []string
|
||||||
@ -59,45 +28,40 @@ type MonStats2Record struct {
|
|||||||
S7v []string
|
S7v []string
|
||||||
S8v []string
|
S8v []string
|
||||||
|
|
||||||
// Does the unit have this component
|
Key string // Key, the object ID MonStatEx feild from MonStat
|
||||||
HD bool
|
BaseWeaponClass string
|
||||||
TR bool
|
ResurrectSkill string
|
||||||
LG bool
|
Heart string
|
||||||
RA bool
|
BodyPart string
|
||||||
LA bool
|
|
||||||
RH bool
|
// These follow three are apparently unused
|
||||||
LH bool
|
Height int
|
||||||
SH bool
|
OverlayHeight int
|
||||||
S1 bool
|
PixelHeight int
|
||||||
S2 bool
|
|
||||||
S3 bool
|
// Diameter in subtiles
|
||||||
S4 bool
|
SizeX int
|
||||||
S5 bool
|
SizeY int
|
||||||
S6 bool
|
|
||||||
S7 bool
|
// Bounding box
|
||||||
S8 bool
|
BoxTop int
|
||||||
|
BoxLeft int
|
||||||
|
BoxWidth int
|
||||||
|
BoxHeight int
|
||||||
|
|
||||||
|
// Spawn method used
|
||||||
|
SpawnMethod int
|
||||||
|
|
||||||
|
// Melee radius
|
||||||
|
MeleeRng int
|
||||||
|
|
||||||
|
// base weaponclass?
|
||||||
|
|
||||||
|
HitClass int
|
||||||
|
|
||||||
// Sum of available components
|
// Sum of available components
|
||||||
TotalPieces int
|
TotalPieces int
|
||||||
|
|
||||||
// Available animation modes
|
|
||||||
mDT bool
|
|
||||||
mNU bool
|
|
||||||
mWL bool
|
|
||||||
mGH bool
|
|
||||||
mA1 bool
|
|
||||||
mA2 bool
|
|
||||||
mBL bool
|
|
||||||
mSC bool
|
|
||||||
mS1 bool
|
|
||||||
mS2 bool
|
|
||||||
mS3 bool
|
|
||||||
mS4 bool
|
|
||||||
mDD bool
|
|
||||||
mKB bool
|
|
||||||
mSQ bool
|
|
||||||
mRN bool
|
|
||||||
|
|
||||||
// Number of directions for each mode
|
// Number of directions for each mode
|
||||||
dDT int
|
dDT int
|
||||||
dNU int
|
dNU int
|
||||||
@ -116,6 +80,79 @@ type MonStats2Record struct {
|
|||||||
dSQ int
|
dSQ int
|
||||||
dRN int
|
dRN int
|
||||||
|
|
||||||
|
// If the units is restored on map reload
|
||||||
|
Restore int
|
||||||
|
|
||||||
|
// What maximap index is used for the automap
|
||||||
|
AutomapCel int
|
||||||
|
|
||||||
|
// Blood offset?
|
||||||
|
LocalBlood int
|
||||||
|
|
||||||
|
// 0 = don't bleed, 1 = small blood missile, 2 = small and large, > 3 other missiles?
|
||||||
|
Bleed int
|
||||||
|
|
||||||
|
// If the unit is lights up the area
|
||||||
|
Light int
|
||||||
|
|
||||||
|
// Light color
|
||||||
|
LightR int
|
||||||
|
LightG int
|
||||||
|
lightB int
|
||||||
|
|
||||||
|
// Palettes per difficulty
|
||||||
|
NormalPalette int
|
||||||
|
NightmarePalette int
|
||||||
|
HellPalatte int
|
||||||
|
|
||||||
|
// These two are useless as of 1.07
|
||||||
|
|
||||||
|
// Inferno animation stuff
|
||||||
|
InfernoLen int
|
||||||
|
InfernoAnim int
|
||||||
|
InfernoRollback int
|
||||||
|
// Which mode is used after resurrection
|
||||||
|
ResurrectMode d2enum.MonsterAnimationMode
|
||||||
|
|
||||||
|
// This specifies if the size values get used for collision detection
|
||||||
|
NoGfxHitTest bool
|
||||||
|
|
||||||
|
// Does the unit have this component
|
||||||
|
HD bool
|
||||||
|
TR bool
|
||||||
|
LG bool
|
||||||
|
RA bool
|
||||||
|
LA bool
|
||||||
|
RH bool
|
||||||
|
LH bool
|
||||||
|
SH bool
|
||||||
|
S1 bool
|
||||||
|
S2 bool
|
||||||
|
S3 bool
|
||||||
|
S4 bool
|
||||||
|
S5 bool
|
||||||
|
S6 bool
|
||||||
|
S7 bool
|
||||||
|
S8 bool
|
||||||
|
|
||||||
|
// Available animation modes
|
||||||
|
mDT bool
|
||||||
|
mNU bool
|
||||||
|
mWL bool
|
||||||
|
mGH bool
|
||||||
|
mA1 bool
|
||||||
|
mA2 bool
|
||||||
|
mBL bool
|
||||||
|
mSC bool
|
||||||
|
mS1 bool
|
||||||
|
mS2 bool
|
||||||
|
mS3 bool
|
||||||
|
mS4 bool
|
||||||
|
mDD bool
|
||||||
|
mKB bool
|
||||||
|
mSQ bool
|
||||||
|
mRN bool
|
||||||
|
|
||||||
// Available modes while moving aside from WL and RN
|
// Available modes while moving aside from WL and RN
|
||||||
A1mv bool
|
A1mv bool
|
||||||
A2mv bool
|
A2mv bool
|
||||||
@ -125,12 +162,6 @@ type MonStats2Record struct {
|
|||||||
S3mv bool
|
S3mv bool
|
||||||
S4mv bool
|
S4mv bool
|
||||||
|
|
||||||
// If the units is restored on map reload
|
|
||||||
Restore int
|
|
||||||
|
|
||||||
// What maximap index is used for the automap
|
|
||||||
AutomapCel int
|
|
||||||
|
|
||||||
// true of unit uses an automap entry
|
// true of unit uses an automap entry
|
||||||
NoMap bool
|
NoMap bool
|
||||||
|
|
||||||
@ -191,39 +222,8 @@ type MonStats2Record struct {
|
|||||||
// If multiple layers should be used on death (otherwise only TR)
|
// If multiple layers should be used on death (otherwise only TR)
|
||||||
CompositeDeath bool
|
CompositeDeath bool
|
||||||
|
|
||||||
// Blood offset?
|
|
||||||
LocalBlood int
|
|
||||||
|
|
||||||
// 0 = don't bleed, 1 = small blood missile, 2 = small and large, > 3 other missiles?
|
|
||||||
Bleed int
|
|
||||||
|
|
||||||
// If the unit is lights up the area
|
|
||||||
Light int
|
|
||||||
|
|
||||||
// Light color
|
|
||||||
LightR int
|
|
||||||
LightG int
|
|
||||||
lightB int
|
|
||||||
|
|
||||||
// Palettes per difficulty
|
|
||||||
NormalPalette int
|
|
||||||
NightmarePalette int
|
|
||||||
HellPalatte int
|
|
||||||
|
|
||||||
// These two are useless as of 1.07
|
|
||||||
Heart string
|
|
||||||
BodyPart string
|
|
||||||
|
|
||||||
// Inferno animation stuff
|
|
||||||
InfernoLen int
|
|
||||||
InfernoAnim int
|
|
||||||
InfernoRollback int
|
|
||||||
|
|
||||||
// Which mode is used after resurrection
|
|
||||||
ResurrectMode d2enum.MonsterAnimationMode
|
|
||||||
|
|
||||||
// Which skill is used for resurrection
|
// Which skill is used for resurrection
|
||||||
ResurrectSkill string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MonStats2 stores all of the MonStats2Records
|
// MonStats2 stores all of the MonStats2Records
|
||||||
@ -233,140 +233,143 @@ var MonStats2 map[string]*MonStats2Record
|
|||||||
// LoadMonStats2 loads MonStats2Records from monstats2.txt
|
// LoadMonStats2 loads MonStats2Records from monstats2.txt
|
||||||
//nolint:funlen //just a big data loader
|
//nolint:funlen //just a big data loader
|
||||||
func LoadMonStats2(file []byte) {
|
func LoadMonStats2(file []byte) {
|
||||||
dict := d2common.LoadDataDictionary(string(file))
|
MonStats2 = make(map[string]*MonStats2Record)
|
||||||
numRecords := len(dict.Data)
|
|
||||||
MonStats2 = make(map[string]*MonStats2Record, numRecords)
|
|
||||||
|
|
||||||
for idx := range dict.Data {
|
d := d2common.LoadDataDictionary(file)
|
||||||
|
for d.Next() {
|
||||||
record := &MonStats2Record{
|
record := &MonStats2Record{
|
||||||
Key: dict.GetString("Id", idx),
|
Key: d.String("Id"),
|
||||||
Height: dict.GetNumber("Height", idx),
|
Height: d.Number("Height"),
|
||||||
OverlayHeight: dict.GetNumber("OverlayHeight", idx),
|
OverlayHeight: d.Number("OverlayHeight"),
|
||||||
PixelHeight: dict.GetNumber("pixHeight", idx),
|
PixelHeight: d.Number("pixHeight"),
|
||||||
SizeX: dict.GetNumber("SizeX", idx),
|
SizeX: d.Number("SizeX"),
|
||||||
SizeY: dict.GetNumber("SizeY", idx),
|
SizeY: d.Number("SizeY"),
|
||||||
SpawnMethod: dict.GetNumber("spawnCol", idx),
|
SpawnMethod: d.Number("spawnCol"),
|
||||||
MeleeRng: dict.GetNumber("MeleeRng", idx),
|
MeleeRng: d.Number("MeleeRng"),
|
||||||
BaseWeaponClass: dict.GetString("BaseW", idx),
|
BaseWeaponClass: d.String("BaseW"),
|
||||||
HitClass: dict.GetNumber("HitClass", idx),
|
HitClass: d.Number("HitClass"),
|
||||||
HDv: dict.GetDelimitedList("HDv", idx),
|
HDv: d.List("HDv"),
|
||||||
TRv: dict.GetDelimitedList("TRv", idx),
|
TRv: d.List("TRv"),
|
||||||
LGv: dict.GetDelimitedList("LGv", idx),
|
LGv: d.List("LGv"),
|
||||||
Rav: dict.GetDelimitedList("Rav", idx),
|
Rav: d.List("Rav"),
|
||||||
Lav: dict.GetDelimitedList("Lav", idx),
|
Lav: d.List("Lav"),
|
||||||
RHv: dict.GetDelimitedList("RHv", idx),
|
RHv: d.List("RHv"),
|
||||||
LHv: dict.GetDelimitedList("LHv", idx),
|
LHv: d.List("LHv"),
|
||||||
SHv: dict.GetDelimitedList("SHv", idx),
|
SHv: d.List("SHv"),
|
||||||
S1v: dict.GetDelimitedList("S1v", idx),
|
S1v: d.List("S1v"),
|
||||||
S2v: dict.GetDelimitedList("S2v", idx),
|
S2v: d.List("S2v"),
|
||||||
S3v: dict.GetDelimitedList("S3v", idx),
|
S3v: d.List("S3v"),
|
||||||
S4v: dict.GetDelimitedList("S4v", idx),
|
S4v: d.List("S4v"),
|
||||||
S5v: dict.GetDelimitedList("S5v", idx),
|
S5v: d.List("S5v"),
|
||||||
S6v: dict.GetDelimitedList("S6v", idx),
|
S6v: d.List("S6v"),
|
||||||
S7v: dict.GetDelimitedList("S7v", idx),
|
S7v: d.List("S7v"),
|
||||||
S8v: dict.GetDelimitedList("S8v", idx),
|
S8v: d.List("S8v"),
|
||||||
HD: dict.GetBool("HD", idx),
|
HD: d.Bool("HD"),
|
||||||
TR: dict.GetBool("TR", idx),
|
TR: d.Bool("TR"),
|
||||||
LG: dict.GetBool("LG", idx),
|
LG: d.Bool("LG"),
|
||||||
RA: dict.GetBool("RA", idx),
|
RA: d.Bool("RA"),
|
||||||
LA: dict.GetBool("LA", idx),
|
LA: d.Bool("LA"),
|
||||||
RH: dict.GetBool("RH", idx),
|
RH: d.Bool("RH"),
|
||||||
LH: dict.GetBool("LH", idx),
|
LH: d.Bool("LH"),
|
||||||
SH: dict.GetBool("SH", idx),
|
SH: d.Bool("SH"),
|
||||||
S1: dict.GetBool("S1", idx),
|
S1: d.Bool("S1"),
|
||||||
S2: dict.GetBool("S2", idx),
|
S2: d.Bool("S2"),
|
||||||
S3: dict.GetBool("S3", idx),
|
S3: d.Bool("S3"),
|
||||||
S4: dict.GetBool("S4", idx),
|
S4: d.Bool("S4"),
|
||||||
S5: dict.GetBool("S5", idx),
|
S5: d.Bool("S5"),
|
||||||
S6: dict.GetBool("S6", idx),
|
S6: d.Bool("S6"),
|
||||||
S7: dict.GetBool("S7", idx),
|
S7: d.Bool("S7"),
|
||||||
S8: dict.GetBool("S8", idx),
|
S8: d.Bool("S8"),
|
||||||
TotalPieces: dict.GetNumber("TotalPieces", idx),
|
TotalPieces: d.Number("TotalPieces"),
|
||||||
mDT: dict.GetBool("mDT", idx),
|
mDT: d.Bool("mDT"),
|
||||||
mNU: dict.GetBool("mNU", idx),
|
mNU: d.Bool("mNU"),
|
||||||
mWL: dict.GetBool("mWL", idx),
|
mWL: d.Bool("mWL"),
|
||||||
mGH: dict.GetBool("mGH", idx),
|
mGH: d.Bool("mGH"),
|
||||||
mA1: dict.GetBool("mA1", idx),
|
mA1: d.Bool("mA1"),
|
||||||
mA2: dict.GetBool("mA2", idx),
|
mA2: d.Bool("mA2"),
|
||||||
mBL: dict.GetBool("mBL", idx),
|
mBL: d.Bool("mBL"),
|
||||||
mSC: dict.GetBool("mSC", idx),
|
mSC: d.Bool("mSC"),
|
||||||
mS1: dict.GetBool("mS1", idx),
|
mS1: d.Bool("mS1"),
|
||||||
mS2: dict.GetBool("mS2", idx),
|
mS2: d.Bool("mS2"),
|
||||||
mS3: dict.GetBool("mS3", idx),
|
mS3: d.Bool("mS3"),
|
||||||
mS4: dict.GetBool("mS4", idx),
|
mS4: d.Bool("mS4"),
|
||||||
mDD: dict.GetBool("mDD", idx),
|
mDD: d.Bool("mDD"),
|
||||||
mKB: dict.GetBool("mKB", idx),
|
mKB: d.Bool("mKB"),
|
||||||
mSQ: dict.GetBool("mSQ", idx),
|
mSQ: d.Bool("mSQ"),
|
||||||
mRN: dict.GetBool("mRN", idx),
|
mRN: d.Bool("mRN"),
|
||||||
dDT: dict.GetNumber("mDT", idx),
|
dDT: d.Number("mDT"),
|
||||||
dNU: dict.GetNumber("mNU", idx),
|
dNU: d.Number("mNU"),
|
||||||
dWL: dict.GetNumber("mWL", idx),
|
dWL: d.Number("mWL"),
|
||||||
dGH: dict.GetNumber("mGH", idx),
|
dGH: d.Number("mGH"),
|
||||||
dA1: dict.GetNumber("mA1", idx),
|
dA1: d.Number("mA1"),
|
||||||
dA2: dict.GetNumber("mA2", idx),
|
dA2: d.Number("mA2"),
|
||||||
dBL: dict.GetNumber("mBL", idx),
|
dBL: d.Number("mBL"),
|
||||||
dSC: dict.GetNumber("mSC", idx),
|
dSC: d.Number("mSC"),
|
||||||
dS1: dict.GetNumber("mS1", idx),
|
dS1: d.Number("mS1"),
|
||||||
dS2: dict.GetNumber("mS2", idx),
|
dS2: d.Number("mS2"),
|
||||||
dS3: dict.GetNumber("mS3", idx),
|
dS3: d.Number("mS3"),
|
||||||
dS4: dict.GetNumber("mS4", idx),
|
dS4: d.Number("mS4"),
|
||||||
dDD: dict.GetNumber("mDD", idx),
|
dDD: d.Number("mDD"),
|
||||||
dKB: dict.GetNumber("mKB", idx),
|
dKB: d.Number("mKB"),
|
||||||
dSQ: dict.GetNumber("mSQ", idx),
|
dSQ: d.Number("mSQ"),
|
||||||
dRN: dict.GetNumber("mRN", idx),
|
dRN: d.Number("mRN"),
|
||||||
A1mv: dict.GetBool("A1mv", idx),
|
A1mv: d.Bool("A1mv"),
|
||||||
A2mv: dict.GetBool("A2mv", idx),
|
A2mv: d.Bool("A2mv"),
|
||||||
SCmv: dict.GetBool("SCmv", idx),
|
SCmv: d.Bool("SCmv"),
|
||||||
S1mv: dict.GetBool("S1mv", idx),
|
S1mv: d.Bool("S1mv"),
|
||||||
S2mv: dict.GetBool("S2mv", idx),
|
S2mv: d.Bool("S2mv"),
|
||||||
S3mv: dict.GetBool("S3mv", idx),
|
S3mv: d.Bool("S3mv"),
|
||||||
S4mv: dict.GetBool("S4mv", idx),
|
S4mv: d.Bool("S4mv"),
|
||||||
NoGfxHitTest: dict.GetBool("noGfxHitTest", idx),
|
NoGfxHitTest: d.Bool("noGfxHitTest"),
|
||||||
BoxTop: dict.GetNumber("htTop", idx),
|
BoxTop: d.Number("htTop"),
|
||||||
BoxLeft: dict.GetNumber("htLeft", idx),
|
BoxLeft: d.Number("htLeft"),
|
||||||
BoxWidth: dict.GetNumber("htWidth", idx),
|
BoxWidth: d.Number("htWidth"),
|
||||||
BoxHeight: dict.GetNumber("htHeight", idx),
|
BoxHeight: d.Number("htHeight"),
|
||||||
Restore: dict.GetNumber("restore", idx),
|
Restore: d.Number("restore"),
|
||||||
AutomapCel: dict.GetNumber("automapCel", idx),
|
AutomapCel: d.Number("automapCel"),
|
||||||
NoMap: dict.GetBool("noMap", idx),
|
NoMap: d.Bool("noMap"),
|
||||||
NoOvly: dict.GetBool("noOvly", idx),
|
NoOvly: d.Bool("noOvly"),
|
||||||
IsSelectable: dict.GetBool("isSel", idx),
|
IsSelectable: d.Bool("isSel"),
|
||||||
AllySelectable: dict.GetBool("alSel", idx),
|
AllySelectable: d.Bool("alSel"),
|
||||||
shiftSel: dict.GetBool("shiftSel", idx),
|
shiftSel: d.Bool("shiftSel"),
|
||||||
NotSelectable: dict.GetBool("noSel", idx),
|
NotSelectable: d.Bool("noSel"),
|
||||||
IsCorpseSelectable: dict.GetBool("corpseSel", idx),
|
IsCorpseSelectable: d.Bool("corpseSel"),
|
||||||
IsAttackable: dict.GetBool("isAtt", idx),
|
IsAttackable: d.Bool("isAtt"),
|
||||||
IsRevivable: dict.GetBool("revive", idx),
|
IsRevivable: d.Bool("revive"),
|
||||||
IsCritter: dict.GetBool("critter", idx),
|
IsCritter: d.Bool("critter"),
|
||||||
IsSmall: dict.GetBool("small", idx),
|
IsSmall: d.Bool("small"),
|
||||||
IsLarge: dict.GetBool("large", idx),
|
IsLarge: d.Bool("large"),
|
||||||
IsSoft: dict.GetBool("soft", idx),
|
IsSoft: d.Bool("soft"),
|
||||||
IsInert: dict.GetBool("inert", idx),
|
IsInert: d.Bool("inert"),
|
||||||
objCol: dict.GetBool("objCol", idx),
|
objCol: d.Bool("objCol"),
|
||||||
IsCorpseCollidable: dict.GetBool("deadCol", idx),
|
IsCorpseCollidable: d.Bool("deadCol"),
|
||||||
IsCorpseWalkable: dict.GetBool("unflatDead", idx),
|
IsCorpseWalkable: d.Bool("unflatDead"),
|
||||||
HasShadow: dict.GetBool("Shadow", idx),
|
HasShadow: d.Bool("Shadow"),
|
||||||
NoUniqueShift: dict.GetBool("noUniqueShift", idx),
|
NoUniqueShift: d.Bool("noUniqueShift"),
|
||||||
CompositeDeath: dict.GetBool("compositeDeath", idx),
|
CompositeDeath: d.Bool("compositeDeath"),
|
||||||
LocalBlood: dict.GetNumber("localBlood", idx),
|
LocalBlood: d.Number("localBlood"),
|
||||||
Bleed: dict.GetNumber("Bleed", idx),
|
Bleed: d.Number("Bleed"),
|
||||||
Light: dict.GetNumber("Light", idx),
|
Light: d.Number("Light"),
|
||||||
LightR: dict.GetNumber("light-r", idx),
|
LightR: d.Number("light-r"),
|
||||||
LightG: dict.GetNumber("light-g", idx),
|
LightG: d.Number("light-g"),
|
||||||
lightB: dict.GetNumber("light-b", idx),
|
lightB: d.Number("light-b"),
|
||||||
NormalPalette: dict.GetNumber("Utrans", idx),
|
NormalPalette: d.Number("Utrans"),
|
||||||
NightmarePalette: dict.GetNumber("Utrans(N)", idx),
|
NightmarePalette: d.Number("Utrans(N)"),
|
||||||
HellPalatte: dict.GetNumber("Utrans(H)", idx),
|
HellPalatte: d.Number("Utrans(H)"),
|
||||||
Heart: dict.GetString("Heart", idx),
|
Heart: d.String("Heart"),
|
||||||
BodyPart: dict.GetString("BodyPart", idx),
|
BodyPart: d.String("BodyPart"),
|
||||||
InfernoLen: dict.GetNumber("InfernoLen", idx),
|
InfernoLen: d.Number("InfernoLen"),
|
||||||
InfernoAnim: dict.GetNumber("InfernoAnim", idx),
|
InfernoAnim: d.Number("InfernoAnim"),
|
||||||
InfernoRollback: dict.GetNumber("InfernoRollback", idx),
|
InfernoRollback: d.Number("InfernoRollback"),
|
||||||
ResurrectMode: d2enum.MonsterAnimationModeFromString(dict.GetString("ResurrectMode", idx)),
|
ResurrectMode: d2enum.MonsterAnimationModeFromString(d.String("ResurrectMode")),
|
||||||
ResurrectSkill: dict.GetString("ResurrectSkill", idx),
|
ResurrectSkill: d.String("ResurrectSkill"),
|
||||||
}
|
}
|
||||||
MonStats2[record.Key] = record
|
MonStats2[record.Key] = record
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d.Err != nil {
|
||||||
|
panic(d.Err)
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("Loaded %d MonStats2 records", len(MonStats2))
|
log.Printf("Loaded %d MonStats2 records", len(MonStats2))
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,11 @@ import (
|
|||||||
type ObjectLookupRecord struct {
|
type ObjectLookupRecord struct {
|
||||||
Act int
|
Act int
|
||||||
Type d2enum.ObjectType
|
Type d2enum.ObjectType
|
||||||
Id int //nolint:golint Id is the right key
|
Id int //nolint:golint,stylecheck // Id is the right key
|
||||||
Name string
|
Name string
|
||||||
Description string
|
Description string
|
||||||
ObjectsTxtId int //nolint:golint Id is the right key
|
ObjectsTxtId int //nolint:golint,stylecheck // Id is the right key
|
||||||
MonstatsTxtId int //nolint:golint Id is the right key
|
MonstatsTxtId int //nolint:golint,stylecheck // Id is the right key
|
||||||
Direction int
|
Direction int
|
||||||
Base string
|
Base string
|
||||||
Token string
|
Token string
|
||||||
|
@ -23,9 +23,14 @@ func LoadObjectTypes(objectTypeData []byte) {
|
|||||||
count := streamReader.GetInt32()
|
count := streamReader.GetInt32()
|
||||||
ObjectTypes = make([]ObjectTypeRecord, count)
|
ObjectTypes = make([]ObjectTypeRecord, count)
|
||||||
|
|
||||||
|
const (
|
||||||
|
nameSize = 32
|
||||||
|
tokenSize = 20
|
||||||
|
)
|
||||||
|
|
||||||
for i := range ObjectTypes {
|
for i := range ObjectTypes {
|
||||||
nameBytes := streamReader.ReadBytes(32)
|
nameBytes := streamReader.ReadBytes(nameSize)
|
||||||
tokenBytes := streamReader.ReadBytes(20)
|
tokenBytes := streamReader.ReadBytes(tokenSize)
|
||||||
ObjectTypes[i] = ObjectTypeRecord{
|
ObjectTypes[i] = ObjectTypeRecord{
|
||||||
Name: strings.TrimSpace(strings.ReplaceAll(string(nameBytes), string(0), "")),
|
Name: strings.TrimSpace(strings.ReplaceAll(string(nameBytes), string(0), "")),
|
||||||
Token: strings.TrimSpace(strings.ReplaceAll(string(tokenBytes), string(0), "")),
|
Token: strings.TrimSpace(strings.ReplaceAll(string(tokenBytes), string(0), "")),
|
||||||
|
@ -25,7 +25,7 @@ type ObjectRecord struct {
|
|||||||
token string // refers to what graphics this object uses
|
token string // refers to what graphics this object uses
|
||||||
|
|
||||||
// Don't use, index by line number
|
// Don't use, index by line number
|
||||||
id int //nolint:golint it's ok that it's called Id, unused indexed by line number instead
|
id int //nolint:golint,stylecheck // unused, indexed by line number instead
|
||||||
SpawnMax int // unused?
|
SpawnMax int // unused?
|
||||||
TrapProbability int // unused
|
TrapProbability int // unused
|
||||||
|
|
||||||
|
@ -125,35 +125,39 @@ var SuperUniques map[string]*SuperUniqueRecord
|
|||||||
|
|
||||||
// LoadSuperUniques loads SuperUniqueRecords from superuniques.txt
|
// LoadSuperUniques loads SuperUniqueRecords from superuniques.txt
|
||||||
func LoadSuperUniques(file []byte) {
|
func LoadSuperUniques(file []byte) {
|
||||||
dictionary := d2common.LoadDataDictionary(string(file))
|
SuperUniques = make(map[string]*SuperUniqueRecord)
|
||||||
SuperUniques = make(map[string]*SuperUniqueRecord, len(dictionary.Data))
|
|
||||||
|
|
||||||
for idx := range dictionary.Data {
|
d := d2common.LoadDataDictionary(file)
|
||||||
|
for d.Next() {
|
||||||
record := &SuperUniqueRecord{
|
record := &SuperUniqueRecord{
|
||||||
Key: dictionary.GetString("Superunique", idx),
|
Key: d.String("Superunique"),
|
||||||
Name: dictionary.GetString("Name", idx),
|
Name: d.String("Name"),
|
||||||
Class: dictionary.GetString("Class", idx),
|
Class: d.String("Class"),
|
||||||
HcIdx: dictionary.GetString("hcIdx", idx),
|
HcIdx: d.String("hcIdx"),
|
||||||
MonSound: dictionary.GetString("MonSound", idx),
|
MonSound: d.String("MonSound"),
|
||||||
Mod: [3]int{
|
Mod: [3]int{
|
||||||
dictionary.GetNumber("Mod1", idx),
|
d.Number("Mod1"),
|
||||||
dictionary.GetNumber("Mod2", idx),
|
d.Number("Mod2"),
|
||||||
dictionary.GetNumber("Mod3", idx),
|
d.Number("Mod3"),
|
||||||
},
|
},
|
||||||
MinGrp: dictionary.GetNumber("MinGrp", idx),
|
MinGrp: d.Number("MinGrp"),
|
||||||
MaxGrp: dictionary.GetNumber("MaxGrp", idx),
|
MaxGrp: d.Number("MaxGrp"),
|
||||||
IsExpansion: dictionary.GetNumber("EClass", idx) == 1,
|
IsExpansion: d.Bool("EClass"),
|
||||||
AutoPosition: dictionary.GetNumber("AutoPos", idx) == 1,
|
AutoPosition: d.Bool("AutoPos"),
|
||||||
Stacks: dictionary.GetNumber("Stacks", idx) == 1,
|
Stacks: d.Bool("Stacks"),
|
||||||
TreasureClassNormal: dictionary.GetString("TC", idx),
|
TreasureClassNormal: d.String("TC"),
|
||||||
TreasureClassNightmare: dictionary.GetString("TC(N)", idx),
|
TreasureClassNightmare: d.String("TC(N)"),
|
||||||
TreasureClassHell: dictionary.GetString("TC(H)", idx),
|
TreasureClassHell: d.String("TC(H)"),
|
||||||
UTransNormal: dictionary.GetString("Utrans", idx),
|
UTransNormal: d.String("Utrans"),
|
||||||
UTransNightmare: dictionary.GetString("Utrans(N)", idx),
|
UTransNightmare: d.String("Utrans(N)"),
|
||||||
UTransHell: dictionary.GetString("Utrans(H)", idx),
|
UTransHell: d.String("Utrans(H)"),
|
||||||
}
|
}
|
||||||
SuperUniques[record.Key] = record
|
SuperUniques[record.Key] = record
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d.Err != nil {
|
||||||
|
panic(d.Err)
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("Loaded %d SuperUnique records", len(SuperUniques))
|
log.Printf("Loaded %d SuperUnique records", len(SuperUniques))
|
||||||
}
|
}
|
||||||
|
@ -9,37 +9,35 @@ import (
|
|||||||
|
|
||||||
// UniqueItemRecord is a representation of a row from uniqueitems.txt
|
// UniqueItemRecord is a representation of a row from uniqueitems.txt
|
||||||
type UniqueItemRecord struct {
|
type UniqueItemRecord struct {
|
||||||
Name string
|
Properties [12]UniqueItemProperty
|
||||||
Version int // 0 = classic pre 1.07, 1 = 1.07-1.11, 100 = expansion
|
|
||||||
Enabled bool // if false, this record won't be loaded (should always be true...)
|
|
||||||
Ladder bool // if true, can only be found on ladder and not in single player / tcp/ip
|
|
||||||
Rarity int // 1-255, higher is more common (ironically...)
|
|
||||||
NoLimit bool // if true, can drop more than once per game
|
|
||||||
// (if false, can only drop once per game; if it would drop,
|
|
||||||
// instead a rare item with enhanced durability drops)
|
|
||||||
|
|
||||||
Level int // item's level, can only be dropped by monsters / recipes / vendors / objects of this level or higher
|
|
||||||
// otherwise they would drop a rare item with enhanced durability
|
|
||||||
RequiredLevel int // character must have this level to use this item
|
|
||||||
Code string // three letter code, points to a record in Weapons, Armor, or Misc
|
|
||||||
|
|
||||||
TypeDescription string
|
|
||||||
UberDescription string
|
|
||||||
SingleCopy bool // if true, player can only hold one of these. can't trade it or pick it up
|
|
||||||
CostMultiplier int // base price is multiplied by this when sold, repaired or bought
|
|
||||||
CostAdd int // after multiplied by above, this much is added to the price
|
|
||||||
|
|
||||||
|
Name string
|
||||||
|
Code string // three letter code, points to a record in Weapons, Armor, or Misc
|
||||||
|
TypeDescription string
|
||||||
|
UberDescription string
|
||||||
CharacterGfxTransform string // palette shift applied to this items gfx when held and when
|
CharacterGfxTransform string // palette shift applied to this items gfx when held and when
|
||||||
// on the ground (flippy). Points to a record in Colors.txt
|
// on the ground (flippy). Points to a record in Colors.txt
|
||||||
InventoryGfxTransform string // palette shift applied to the inventory gfx
|
InventoryGfxTransform string // palette shift applied to the inventory gfx
|
||||||
FlippyFile string // if non-empty, overrides the base item's dropped gfx
|
FlippyFile string // if non-empty, overrides the base item's dropped gfx
|
||||||
InventoryFile string // if non-empty, overrides the base item's inventory gfx
|
InventoryFile string // if non-empty, overrides the base item's inventory gfx
|
||||||
|
DropSound string // if non-empty, overrides the base item's drop sound
|
||||||
|
UseSound string // if non-empty, overrides the sound played when item is used
|
||||||
|
|
||||||
DropSound string // if non-empty, overrides the base item's drop sound
|
Version int // 0 = classic pre 1.07, 1 = 1.07-1.11, 100 = expansion
|
||||||
DropSfxFrame int // if non-empty, overrides the base item's frame at which the drop sound plays
|
Rarity int // 1-255, higher is more common (ironically...)
|
||||||
UseSound string // if non-empty, overrides the sound played when item is used
|
Level int // item's level, can only be dropped by monsters / recipes / vendors / objects of this level or higher
|
||||||
|
// otherwise they would drop a rare item with enhanced durability
|
||||||
|
RequiredLevel int // character must have this level to use this item
|
||||||
|
CostMultiplier int // base price is multiplied by this when sold, repaired or bought
|
||||||
|
CostAdd int // after multiplied by above, this much is added to the price
|
||||||
|
DropSfxFrame int // if non-empty, overrides the base item's frame at which the drop sound plays
|
||||||
|
|
||||||
Properties [12]UniqueItemProperty
|
Enabled bool // if false, this record won't be loaded (should always be true...)
|
||||||
|
Ladder bool // if true, can only be found on ladder and not in single player / tcp/ip
|
||||||
|
NoLimit bool // if true, can drop more than once per game
|
||||||
|
// (if false, can only drop once per game; if it would drop,
|
||||||
|
// instead a rare item with enhanced durability drops)
|
||||||
|
SingleCopy bool // if true, player can only hold one of these. can't trade it or pick it up
|
||||||
}
|
}
|
||||||
|
|
||||||
// UniqueItemProperty is describes a property of a unique item
|
// UniqueItemProperty is describes a property of a unique item
|
||||||
|
@ -6,8 +6,10 @@ import (
|
|||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Weapons map[string]*ItemCommonRecord
|
// Weapons stores all of the WeaponRecords
|
||||||
|
var Weapons map[string]*ItemCommonRecord //nolint:gochecknoglobals // Currently global by design, only written once
|
||||||
|
|
||||||
|
// LoadWeapons loads weapon records
|
||||||
func LoadWeapons(file []byte) {
|
func LoadWeapons(file []byte) {
|
||||||
Weapons = LoadCommonItems(file, d2enum.InventoryItemTypeWeapon)
|
Weapons = LoadCommonItems(file, d2enum.InventoryItemTypeWeapon)
|
||||||
log.Printf("Loaded %d weapons", len(Weapons))
|
log.Printf("Loaded %d weapons", len(Weapons))
|
||||||
|
@ -174,7 +174,7 @@ const (
|
|||||||
LevelPreset = "/data/global/excel/LvlPrest.txt"
|
LevelPreset = "/data/global/excel/LvlPrest.txt"
|
||||||
LevelType = "/data/global/excel/LvlTypes.txt"
|
LevelType = "/data/global/excel/LvlTypes.txt"
|
||||||
ObjectType = "/data/global/excel/objtype.bin"
|
ObjectType = "/data/global/excel/objtype.bin"
|
||||||
LevelWarp = "/data/global/excel/LvlWarp.bin"
|
LevelWarp = "/data/global/excel/LvlWarp.txt"
|
||||||
LevelDetails = "/data/global/excel/Levels.txt"
|
LevelDetails = "/data/global/excel/Levels.txt"
|
||||||
LevelMaze = "/data/global/excel/LvlMaze.txt"
|
LevelMaze = "/data/global/excel/LvlMaze.txt"
|
||||||
LevelSubstitutions = "/data/global/excel/LvlSub.txt"
|
LevelSubstitutions = "/data/global/excel/LvlSub.txt"
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package d2common
|
package d2common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/csv"
|
||||||
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -8,74 +11,78 @@ import (
|
|||||||
|
|
||||||
// DataDictionary represents a data file (Excel)
|
// DataDictionary represents a data file (Excel)
|
||||||
type DataDictionary struct {
|
type DataDictionary struct {
|
||||||
FieldNameLookup map[string]int
|
lookup map[string]int
|
||||||
Data [][]string
|
r *csv.Reader
|
||||||
|
record []string
|
||||||
|
Err error
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadDataDictionary loads the contents of a spreadsheet style txt file
|
// LoadDataDictionary loads the contents of a spreadsheet style txt file
|
||||||
func LoadDataDictionary(text string) *DataDictionary {
|
func LoadDataDictionary(buf []byte) *DataDictionary {
|
||||||
result := &DataDictionary{}
|
cr := csv.NewReader(bytes.NewReader(buf))
|
||||||
lines := strings.Split(text, "\r\n")
|
cr.Comma = '\t'
|
||||||
fileNames := strings.Split(lines[0], "\t")
|
cr.ReuseRecord = true
|
||||||
result.FieldNameLookup = make(map[string]int)
|
|
||||||
|
|
||||||
for i, fieldName := range fileNames {
|
fieldNames, err := cr.Read()
|
||||||
result.FieldNameLookup[fieldName] = i
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Data = make([][]string, len(lines)-2)
|
|
||||||
|
|
||||||
for i, line := range lines[1:] {
|
|
||||||
if strings.TrimSpace(line) == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
values := strings.Split(line, "\t")
|
|
||||||
if len(values) != len(result.FieldNameLookup) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Data[i] = values
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetString gets a string from the given column and row
|
|
||||||
func (v *DataDictionary) GetString(fieldName string, index int) string {
|
|
||||||
return v.Data[index][v.FieldNameLookup[fieldName]]
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetNumber gets a number for the given column and row
|
|
||||||
func (v *DataDictionary) GetNumber(fieldName string, index int) int {
|
|
||||||
str := v.GetString(fieldName, index)
|
|
||||||
str = EmptyToZero(AsterToEmpty(str))
|
|
||||||
|
|
||||||
result, err := strconv.Atoi(str)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
data := &DataDictionary{
|
||||||
|
lookup: make(map[string]int, len(fieldNames)),
|
||||||
|
r: cr,
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, name := range fieldNames {
|
||||||
|
data.lookup[name] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDelimitedList splits a delimited list from the given column and row
|
// Next reads the next row, skips Expansion lines or
|
||||||
func (v *DataDictionary) GetDelimitedList(fieldName string, index int) []string {
|
// returns false when the end of a file is reached or an error occured
|
||||||
unsplit := v.GetString(fieldName, index)
|
func (d *DataDictionary) Next() bool {
|
||||||
|
var err error
|
||||||
|
d.record, err = d.r.Read()
|
||||||
|
if err == io.EOF {
|
||||||
|
return false
|
||||||
|
} else if err != nil {
|
||||||
|
d.Err = err
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Comma delimited fields are quoted, not terribly pretty to fix that here but...
|
if d.record[0] == "Expansion" {
|
||||||
unsplit = strings.TrimRight(unsplit, "\"")
|
return d.Next()
|
||||||
unsplit = strings.TrimLeft(unsplit, "\"")
|
}
|
||||||
|
return true
|
||||||
return strings.Split(unsplit, ",")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBool gets a bool value for the given column and row
|
// String gets a string from the given column
|
||||||
func (v *DataDictionary) GetBool(fieldName string, index int) bool {
|
func (d *DataDictionary) String(field string) string {
|
||||||
n := v.GetNumber(fieldName, index)
|
return d.record[d.lookup[field]]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Number gets a number for the given column
|
||||||
|
func (d *DataDictionary) Number(field string) int {
|
||||||
|
n, err := strconv.Atoi(d.String(field))
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
// List splits a delimited list from the given column
|
||||||
|
func (d *DataDictionary) List(field string) []string {
|
||||||
|
str := d.String(field)
|
||||||
|
return strings.Split(str, ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bool gets a bool value for the given column
|
||||||
|
func (d *DataDictionary) Bool(field string) bool {
|
||||||
|
n := d.Number(field)
|
||||||
if n > 1 {
|
if n > 1 {
|
||||||
log.Panic("GetBool on non-bool field")
|
log.Panic("Bool on non-bool field")
|
||||||
}
|
}
|
||||||
|
|
||||||
return n == 1
|
return n == 1
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user