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